@fantasticit/sumi 0.7.5 → 0.7.6

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.
Files changed (76) hide show
  1. package/README.md +27 -25
  2. package/dist/adapters.d.ts +24 -3
  3. package/dist/adapters.js +100 -14
  4. package/dist/adapters.js.map +1 -1
  5. package/dist/agent-hooks.d.ts +3 -0
  6. package/dist/agent-hooks.js +54 -3
  7. package/dist/agent-hooks.js.map +1 -1
  8. package/dist/agents.js +36 -3
  9. package/dist/agents.js.map +1 -1
  10. package/dist/cli.d.ts +3 -1
  11. package/dist/cli.js +4 -4
  12. package/dist/cli.js.map +1 -1
  13. package/dist/context.d.ts +27 -0
  14. package/dist/context.js +28 -10
  15. package/dist/context.js.map +1 -1
  16. package/dist/index.d.ts +1 -0
  17. package/dist/index.js +1 -0
  18. package/dist/index.js.map +1 -1
  19. package/dist/instructions.js +4 -4
  20. package/dist/instructions.js.map +1 -1
  21. package/dist/task.d.ts +1 -0
  22. package/dist/task.js +170 -0
  23. package/dist/task.js.map +1 -0
  24. package/node_modules/@sumi/create/dist/bin.d.ts +2 -0
  25. package/node_modules/@sumi/create/dist/bin.js +52 -0
  26. package/node_modules/@sumi/create/dist/bin.js.map +1 -0
  27. package/node_modules/@sumi/create/package.json +1 -1
  28. package/node_modules/@sumi/kernel/package.json +2 -2
  29. package/node_modules/@sumi/plugin-sdk/README.md +39 -20
  30. package/node_modules/@sumi/plugin-sdk/dist/index.d.ts +1 -0
  31. package/node_modules/@sumi/plugin-sdk/dist/index.js +1 -0
  32. package/node_modules/@sumi/plugin-sdk/dist/index.js.map +1 -1
  33. package/node_modules/@sumi/plugin-sdk/dist/protocol.d.ts +55 -1
  34. package/node_modules/@sumi/plugin-sdk/dist/protocol.js.map +1 -1
  35. package/node_modules/@sumi/plugin-sdk/dist/rules.d.ts +1 -4
  36. package/node_modules/@sumi/plugin-sdk/dist/rules.js.map +1 -1
  37. package/node_modules/@sumi/plugin-sdk/dist/session-context.d.ts +7 -0
  38. package/node_modules/@sumi/plugin-sdk/dist/session-context.js +62 -0
  39. package/node_modules/@sumi/plugin-sdk/dist/session-context.js.map +1 -0
  40. package/node_modules/@sumi/plugin-sdk/dist/validate.js +51 -2
  41. package/node_modules/@sumi/plugin-sdk/dist/validate.js.map +1 -1
  42. package/node_modules/@sumi/plugin-sdk/package.json +1 -1
  43. package/node_modules/@sumi/plugins-core/dist/tool-batches.d.ts +11 -0
  44. package/node_modules/@sumi/plugins-core/dist/tool-batches.js +41 -0
  45. package/node_modules/@sumi/plugins-core/dist/tool-batches.js.map +1 -0
  46. package/node_modules/@sumi/plugins-core/instructions/bugfix.md +9 -0
  47. package/node_modules/@sumi/plugins-core/instructions/feature.md +9 -0
  48. package/node_modules/@sumi/plugins-core/package.json +2 -2
  49. package/node_modules/@sumi/plugins-core/sumi-plugins.yaml +2 -1
  50. package/node_modules/@sumi/plugins-governance/dist/hooks.d.ts +2 -0
  51. package/node_modules/@sumi/plugins-governance/dist/hooks.js +4 -0
  52. package/node_modules/@sumi/plugins-governance/dist/hooks.js.map +1 -0
  53. package/node_modules/@sumi/plugins-governance/package.json +2 -2
  54. package/node_modules/@sumi/plugins-openspec/package.json +2 -2
  55. package/node_modules/@sumi/plugins-precedent/README.md +6 -0
  56. package/node_modules/@sumi/plugins-precedent/dist/after-edit-context.d.ts +2 -0
  57. package/node_modules/@sumi/plugins-precedent/dist/after-edit-context.js +89 -77
  58. package/node_modules/@sumi/plugins-precedent/dist/after-edit-context.js.map +1 -1
  59. package/node_modules/@sumi/plugins-precedent/dist/commands/before-edit-context.d.ts +1 -0
  60. package/node_modules/@sumi/plugins-precedent/dist/commands/before-edit-context.js +10 -0
  61. package/node_modules/@sumi/plugins-precedent/dist/commands/before-edit-context.js.map +1 -0
  62. package/node_modules/@sumi/plugins-precedent/dist/commands/context.js +15 -5
  63. package/node_modules/@sumi/plugins-precedent/dist/commands/context.js.map +1 -1
  64. package/node_modules/@sumi/plugins-precedent/dist/commands/on-prompt-context.d.ts +1 -0
  65. package/node_modules/@sumi/plugins-precedent/dist/commands/on-prompt-context.js +55 -0
  66. package/node_modules/@sumi/plugins-precedent/dist/commands/on-prompt-context.js.map +1 -0
  67. package/node_modules/@sumi/plugins-precedent/dist/model.d.ts +2 -0
  68. package/node_modules/@sumi/plugins-precedent/dist/model.js.map +1 -1
  69. package/node_modules/@sumi/plugins-precedent/package.json +3 -3
  70. package/node_modules/@sumi/plugins-precedent/sumi-plugins.yaml +25 -1
  71. package/node_modules/@sumi/plugins-review/dist/commands/context.js +18 -3
  72. package/node_modules/@sumi/plugins-review/dist/commands/context.js.map +1 -1
  73. package/node_modules/@sumi/plugins-review/dist/review.d.ts +1 -0
  74. package/node_modules/@sumi/plugins-review/dist/review.js.map +1 -1
  75. package/node_modules/@sumi/plugins-review/package.json +3 -3
  76. package/package.json +10 -10
package/dist/task.js ADDED
@@ -0,0 +1,170 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
3
+ import { loadConfig, loadRegistry, KernelError } from '@sumi/kernel';
4
+ import { PROJECT_SUMI, readContextSession, saveContextSession } from '@sumi/plugin-sdk';
5
+ import { ruleRefs } from '@sumi/plugin-sdk';
6
+ import { emit, registerCommand, requireRoot } from './cli.js';
7
+ import { collectContext, expand } from './context.js';
8
+ import { projectInstruction, topicContext, topics } from './instructions.js';
9
+ const LIMIT = 2300; // JSON 包装仍留出空间,整个 hook 输出不超过约 2500 字符。
10
+ function bounded(header, rows, footer) {
11
+ let text = header;
12
+ const keys = [];
13
+ for (const row of rows) {
14
+ const line = `\n${row.text.slice(0, 300)}`;
15
+ if (text.length + line.length + footer.length + 30 > LIMIT)
16
+ break;
17
+ text += line;
18
+ keys.push(row.key);
19
+ }
20
+ if (keys.length < rows.length)
21
+ text += '\n其余目录或条目已截断;';
22
+ return { text: `${text}${footer}`.slice(0, LIMIT), keys };
23
+ }
24
+ registerCommand('task', '按任务获取目录、精确上下文或评测:sumi task ["<意图>"] [--select <id,...>] [--eval <golden.jsonl>] [--bug|--feature] [--issue N] [--change id] [路径...] [--json]', { flags: ['select', 'eval', 'bug', 'feature', 'issue', 'change', 'session', 'no-record'], booleanFlags: ['bug', 'feature', 'no-record'] }, async (args, io, root) => {
25
+ const repo = requireRoot(root);
26
+ if (args.flags.bug && args.flags.feature)
27
+ throw new KernelError('--bug 与 --feature 不能同时使用');
28
+ const selected = typeof args.flags.select === 'string'
29
+ ? [
30
+ ...new Set(args.flags.select
31
+ .split(',')
32
+ .map((s) => s.trim())
33
+ .filter(Boolean)),
34
+ ]
35
+ : [];
36
+ if (args.flags.select && !selected.length)
37
+ throw new KernelError('--select 需要至少一个 ID');
38
+ if (selected.join(',').length > 400)
39
+ throw new KernelError('--select ID 列表过长,请分批查询');
40
+ const rawPaths = selected.length ? args.positionals : args.positionals.slice(1);
41
+ const config = loadConfig(repo);
42
+ const paths = expand(repo, io.cwd, rawPaths, config.exclude);
43
+ const session = typeof args.flags.session === 'string' ? args.flags.session : process.env.SUMI_SESSION_ID;
44
+ if (session && session.length > 200)
45
+ throw new KernelError('--session 过长');
46
+ const input = {
47
+ repoRoot: repo,
48
+ paths,
49
+ kind: args.flags.bug ? 'bug' : args.flags.feature ? 'feature' : 'other',
50
+ ...(typeof args.flags.issue === 'string' ? { issue: args.flags.issue } : {}),
51
+ ...(typeof args.flags.change === 'string' ? { change: args.flags.change } : {}),
52
+ };
53
+ // 目录先于选择查询。CLI 从不根据 intent 文本判断哪个 ID 相关。
54
+ const index = collectContext(repo, { ...input, catalog: true, select: [] });
55
+ const entries = [...new Map(index.catalog.map((entry) => [entry.id, entry])).values()].sort((a, b) => a.id.localeCompare(b.id));
56
+ if (args.flags.eval !== undefined) {
57
+ if (typeof args.flags.eval !== 'string')
58
+ throw new KernelError('--eval 需要 JSONL 文件路径');
59
+ const lines = readFileSync(resolve(io.cwd, args.flags.eval), 'utf8')
60
+ .split(/\r?\n/)
61
+ .filter((line) => line.trim());
62
+ if (!lines.length)
63
+ throw new KernelError('--eval 样本文件不能为空');
64
+ const knownIds = new Set(entries.map((entry) => entry.id));
65
+ let hits = 0;
66
+ let predicted = 0;
67
+ let expected = 0;
68
+ let sampleHits = 0;
69
+ for (const [i, line] of lines.entries()) {
70
+ let row;
71
+ try {
72
+ row = JSON.parse(line);
73
+ }
74
+ catch {
75
+ throw new KernelError(`--eval 第 ${i + 1} 行不是 JSON`);
76
+ }
77
+ const sample = row;
78
+ if (!sample ||
79
+ typeof sample.intent !== 'string' ||
80
+ !Array.isArray(sample.expected) ||
81
+ !Array.isArray(sample.selected) ||
82
+ !sample.expected.every((id) => typeof id === 'string') ||
83
+ !sample.selected.every((id) => typeof id === 'string'))
84
+ throw new KernelError(`--eval 第 ${i + 1} 行必须包含 intent、expected 与宿主代理给出的 selected ID 数组`);
85
+ const want = new Set(sample.expected);
86
+ const got = new Set(sample.selected);
87
+ const unknownIds = [...want, ...got].filter((id) => !knownIds.has(id));
88
+ if (unknownIds.length)
89
+ throw new KernelError(`--eval 第 ${i + 1} 行有未知目录 ID:${[...new Set(unknownIds)].join('、')}`);
90
+ const matched = [...got].filter((id) => want.has(id)).length;
91
+ hits += matched;
92
+ predicted += got.size;
93
+ expected += want.size;
94
+ if (matched || (!want.size && !got.size))
95
+ sampleHits++;
96
+ }
97
+ const metrics = {
98
+ samples: lines.length,
99
+ hitRate: sampleHits / lines.length,
100
+ precision: predicted ? hits / predicted : 0,
101
+ recall: expected ? hits / expected : 0,
102
+ };
103
+ emit(io, args, metrics, `样本 ${metrics.samples};命中率 ${metrics.hitRate.toFixed(3)};精确率 ${metrics.precision.toFixed(3)};召回率 ${metrics.recall.toFixed(3)}。selected 须来自宿主代理的独立选择,Sumi 不调用模型自评。`);
104
+ return 0;
105
+ }
106
+ if (!selected.length) {
107
+ if (!entries.length) {
108
+ const fallback = `当前项目没有任务上下文目录;请运行 ${PROJECT_SUMI} instructions develop,并在定位路径后运行 ${PROJECT_SUMI} context <路径...>。`;
109
+ emit(io, args, { phase: 'catalog', count: 0, text: fallback }, fallback);
110
+ return 0;
111
+ }
112
+ const seen = session ? new Set(readContextSession(repo, session)?.keys ?? []) : new Set();
113
+ const rows = entries
114
+ .filter((e) => !seen.has(`catalog:${e.id}`))
115
+ .map((e) => ({
116
+ key: `catalog:${e.id}`,
117
+ text: `- ${e.id}:${e.description}${e.symptoms ? `;现象:${e.symptoms}` : ''}`,
118
+ }));
119
+ const suffix = `\n由你判断相关 ID,然后运行 ${PROJECT_SUMI} task --select <id,...>${session ? ` --session ${JSON.stringify(session)}` : ''};Sumi 不做关键词分类。`;
120
+ const result = bounded('任务上下文目录(请选择相关 ID):', rows, suffix);
121
+ const deliveryKeys = result.keys.length === rows.length ? [...result.keys, 'catalog:complete'] : result.keys;
122
+ if (rows.length || !session) {
123
+ emit(io, args, { phase: 'catalog', count: result.keys.length, text: result.text, deliveryKeys }, result.text);
124
+ if (session && !args.flags['no-record'])
125
+ saveContextSession(repo, session, deliveryKeys);
126
+ }
127
+ else if (args.flags.json)
128
+ emit(io, args, { phase: 'catalog', count: 0, text: '' }, '');
129
+ return 0;
130
+ }
131
+ const known = new Set(entries.map((e) => e.id));
132
+ const unknown = selected.filter((id) => !known.has(id));
133
+ if (unknown.length)
134
+ throw new KernelError(`未知任务上下文 ID:${unknown.join('、')};先运行 ${PROJECT_SUMI} task "<意图>" 查看目录`);
135
+ const data = collectContext(repo, { ...input, select: selected });
136
+ const selectedItems = data.items.filter((i) => selected.some((id) => i.ref === id || i.aliases?.includes(id)));
137
+ const empty = selected.filter((id) => !selectedItems.some((item) => item.ref === id || item.aliases?.includes(id)));
138
+ if (empty.length)
139
+ throw new KernelError(`任务上下文 ID 没有可读取的条目:${empty.join('、')};请检查提供者的 select 实现`);
140
+ const selectedRefs = new Set(selectedItems.flatMap((item) => [item.ref, ...(item.aliases ?? [])]));
141
+ const selectedRules = [...data.rules, ...data.generalRules].filter((rule) => ruleRefs(rule.text).some((ref) => selectedRefs.has(`${ref.kind}:${ref.target}`)));
142
+ const rows = [
143
+ ...selectedItems.map((i) => ({
144
+ key: `item:${i.ref}`,
145
+ text: `- ${i.category ? `${i.category} ` : ''}[${i.ref}] ${i.text}${i.source ? `(来源:${i.source})` : ''}`,
146
+ })),
147
+ ...selectedRules.map((r) => ({ key: `rule:${r.file}:${r.line}`, text: `- ${r.file}:${r.line} ${r.text}` })),
148
+ ...data.plugins.filter((p) => !p.global).map((p) => ({ key: `plugin:${p.id}`, text: `- 机械门 ${p.id}:${p.description}` })),
149
+ ];
150
+ const seen = session ? new Set(readContextSession(repo, session)?.keys ?? []) : new Set();
151
+ const fresh = rows.filter((r) => !seen.has(r.key));
152
+ const footer = `\n原文:${PROJECT_SUMI} task --select ${selected.join(',')}${paths.length ? `;路径:${PROJECT_SUMI} context <路径...>` : ''}`;
153
+ const declared = [...loadRegistry(repo, config).plugins.values()].flatMap(({ decl }) => decl.taskTopics?.[input.kind] ? [decl.taskTopics[input.kind]] : []);
154
+ if (new Set(declared).size > 1)
155
+ throw new KernelError(`任务类型 ${input.kind} 的指令主题声明冲突:${declared.join('、')}`);
156
+ const topicName = declared[0] ?? 'develop';
157
+ const topic = topics(repo).get(topicName);
158
+ const workflow = topic
159
+ ? `\n流程(${topicName}):${projectInstruction(topic.text(topicContext(repo)))
160
+ .replace(/\s+/g, ' ')
161
+ .slice(0, 300)};完整:${PROJECT_SUMI} instructions ${topicName}`
162
+ : `\n流程:${PROJECT_SUMI} instructions develop`;
163
+ const text = [`已选择:${selected.join('、')}。${workflow}`, ...fresh.map((row) => row.text), footer].join('\n');
164
+ const deliveryKeys = fresh.map((row) => row.key);
165
+ emit(io, args, { phase: 'selected', count: deliveryKeys.length, text, deliveryKeys }, text);
166
+ if (session && deliveryKeys.length && !args.flags['no-record'])
167
+ saveContextSession(repo, session, deliveryKeys);
168
+ return 0;
169
+ });
170
+ //# sourceMappingURL=task.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task.js","sourceRoot":"","sources":["../src/task.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env node
2
+ import { execFileSync, spawnSync } from 'node:child_process';
3
+ import { existsSync, symlinkSync } from 'node:fs';
4
+ import { join, resolve } from 'node:path';
5
+ import { scaffold } from './scaffold.js';
6
+ /**
7
+ * create-ai-coding <目录> [--agents claude,codex,cursor] [--link <node_modules 路径>] [--no-install]
8
+ * 创建遵循三层结构的新项目:复制模板、初始化 git、安装依赖、生成 AI 工具适配与 git hook。
9
+ */
10
+ const args = process.argv.slice(2);
11
+ const flag = (name) => {
12
+ const i = args.indexOf(`--${name}`);
13
+ return i >= 0 ? args[i + 1] : undefined;
14
+ };
15
+ const target = args.find((a, i) => !a.startsWith('--') && !['--agents', '--link'].includes(args[i - 1] ?? ''));
16
+ if (!target) {
17
+ process.stderr.write('用法:create-ai-coding <目录> [--agents claude,codex,cursor] [--link <node_modules>] [--no-install]\n');
18
+ process.exit(3);
19
+ }
20
+ const dir = resolve(target);
21
+ try {
22
+ scaffold(dir, {
23
+ agents: flag('agents')
24
+ ?.split(',')
25
+ .map((a) => a.trim())
26
+ .filter(Boolean),
27
+ });
28
+ }
29
+ catch (error) {
30
+ process.stderr.write(`${error.message}\n`);
31
+ process.exit(1);
32
+ }
33
+ execFileSync('git', ['init', '-q', '-b', 'main'], { cwd: dir });
34
+ const link = flag('link');
35
+ if (link)
36
+ symlinkSync(resolve(link), join(dir, 'node_modules'));
37
+ else if (!args.includes('--no-install')) {
38
+ const r = spawnSync('pnpm', ['install'], { cwd: dir, stdio: 'inherit' });
39
+ if (r.status !== 0)
40
+ process.stderr.write('依赖安装失败,请稍后在项目中手动运行 pnpm install\n');
41
+ }
42
+ const ctl = join(dir, 'node_modules', '.bin', 'ctl');
43
+ if (existsSync(ctl))
44
+ spawnSync(ctl, ['sync-agents'], { cwd: dir, stdio: 'inherit' });
45
+ process.stdout.write([
46
+ `已创建 ${dir}`,
47
+ '下一步:',
48
+ ' npx ctl run check --all # 新项目应直接通过',
49
+ ' 首次推送时,门禁会要求确认全部 control 内容:由人在自己的终端运行它给出的 npx ctl approve <请求 id>',
50
+ '',
51
+ ].join('\n'));
52
+ //# sourceMappingURL=bin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sumi/create",
3
- "version": "0.7.5",
3
+ "version": "0.7.6",
4
4
  "description": "Sumi 脚手架与项目模板(由 sumi init 调用)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sumi/kernel",
3
- "version": "0.7.5",
3
+ "version": "0.7.6",
4
4
  "description": "策略中立的编排内核",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -13,7 +13,7 @@
13
13
  "./package.json": "./package.json"
14
14
  },
15
15
  "dependencies": {
16
- "@sumi/plugin-sdk": "0.7.5",
16
+ "@sumi/plugin-sdk": "0.7.6",
17
17
  "yaml": "2.9.1",
18
18
  "picomatch": "4.0.7"
19
19
  }
@@ -60,26 +60,45 @@
60
60
 
61
61
  声明 `hooks.agent.afterEdit` 的命令从 stdin 读取工具原始负载;返回成功时可向 stdout 写 `{ "additionalContext": "...", "deliveryKeys": ["规则键"] }`。入口在 Claude Code / Codex 的 PostToolUse 补充上下文确实交给模型后,才用相同命令发送回执:环境变量 `SUMI_AFTER_EDIT_DELIVERED=1`,stdin 为 `{ "originalInput": "原始负载", "keys": ["规则键"] }`。仅退出码 0 且 stdout 有模型可见上下文,或退出码 2 且 stderr 有阻断反馈时回执;普通失败或信号终止不会回执,下次编辑可重试。命令必须在任何业务逻辑之前识别回执变量;回执分支只记录 `keys`,必须幂等、无校验/修改文件等业务副作用,否则二次调用会重复执行这些动作。不需要去重的插件不要返回 `deliveryKeys`。
62
62
 
63
- | 字段 | 说明 |
64
- | --------------- | --------------------------------------------------------------------------------------------------------------------------------- |
65
- | `id`、`version` | 必需 |
66
- | `kind` | `check` 或 `planner`;可执行插件必需 |
67
- | `command` | argv 数组;`./`、`../` 开头的参数相对声明目录解析。派生插件不能声明 |
68
- | `timeout` | 超时秒数(正数);可执行插件必需 |
69
- | `base` | 派生插件:沿用该插件的 `command`;未声明 `kind`、`timeout` 时取它的值 |
70
- | `with` | 默认步骤配置,流程步骤的 `with` 逐键覆盖 |
71
- | `description` | 一句话说明,供 `sumi context` 与诊断展示 |
72
- | `triggers` | glob 数组;声明后只接收命中的文件,未命中时步骤为 `not-applicable` |
73
- | `minTier` | 低于该档位时不运行 |
74
- | `fix` | 修复命令 argv(非空),由 `sumi fix <step-id>` 以上次检查范围的文件为参数执行 |
75
- | `metrics` | `{ name, direction: lower-is-better \| higher-is-better, tolerance? }` |
76
- | `commands` | 注册到 `sumi` 的命令:`{ name, argv, description }` |
77
- | `requires` | 依赖的插件包名,必须已在项目配置 `packages` 中启用 |
78
- | `needs` | 运行前提 `{ bin?, files? }`:`node_modules/.bin` 下的可执行文件与相对仓库根的文件;`sumi init` 接入已有仓库时据此去掉不满足的步骤 |
79
- | `hooks` | `git`:git hook 名称 → 命令名;`agent.beforeTool` / `agent.afterEdit`:AI 工具调用工具前、编辑文件后运行的命令名 |
80
- | `afterInit` | 接入已有仓库后运行的 `sumi` 命令参数,例如 `[snapshot, save]` |
81
- | `instructions` | 指令主题名 → 插件包内的 Markdown 文件 |
82
- | `context` | 约束查询命令名:标准输入 `{ repoRoot, paths }`,标准输出 `{ items: [{ ref, text, source?, global?, aliases? }] }` |
63
+ 声明 `hooks.agent.onPrompt` 的命令也可返回同一结果形状。统一入口只在 Claude Code / Codex 的 `UserPromptSubmit` 补充上下文已输出后回执,回执环境变量为 `SUMI_PROMPT_DELIVERED=1`,stdin 同样包含 `originalInput` 与 `keys`;插件应在回执分支只记录送达键,故障与空输出保持静默。
64
+
65
+ ### 编辑前 hook
66
+
67
+ `hooks.agent.beforeTool` 的原有字符串形式继续匹配所有受支持工具,命令执行异常时保持拒绝。需要仅匹配编辑工具且失败时放行的插件可声明对象形式:
68
+
69
+ ```yaml
70
+ hooks:
71
+ agent:
72
+ beforeTool:
73
+ command: context-before-edit
74
+ tools: edit
75
+ failure: open
76
+ when: { path: agentContext.beforeEdit, notEquals: off }
77
+ ```
78
+
79
+ `when` 按项目配置判断,未启用时不生成 hook。Claude Code 和 Codex 的 `PreToolUse` 中,命令退出码 2 且 stderr 非空才将反馈作为拒绝交给模型;成功、超时、异常或没有明确反馈均放行。命令应在确认可送达具体约束后才返回拒绝,并自行保证同会话的重试可通过。Cursor 不支持这一能力,启用时会由 `doctor` 报告。
80
+
81
+ | 字段 | 说明 |
82
+ | --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
83
+ | `id`、`version` | 必需 |
84
+ | `kind` | `check` 或 `planner`;可执行插件必需 |
85
+ | `command` | argv 数组;`./`、`../` 开头的参数相对声明目录解析。派生插件不能声明 |
86
+ | `timeout` | 超时秒数(正数);可执行插件必需 |
87
+ | `base` | 派生插件:沿用该插件的 `command`;未声明 `kind`、`timeout` 时取它的值 |
88
+ | `with` | 默认步骤配置,流程步骤的 `with` 逐键覆盖 |
89
+ | `description` | 一句话说明,供 `sumi context` 与诊断展示 |
90
+ | `triggers` | glob 数组;声明后只接收命中的文件,未命中时步骤为 `not-applicable` |
91
+ | `minTier` | 低于该档位时不运行 |
92
+ | `fix` | 修复命令 argv(非空),由 `sumi fix <step-id>` 以上次检查范围的文件为参数执行 |
93
+ | `metrics` | `{ name, direction: lower-is-better \| higher-is-better, tolerance? }` |
94
+ | `commands` | 注册到 `sumi` 的命令:`{ name, argv, description }` |
95
+ | `requires` | 依赖的插件包名,必须已在项目配置 `packages` 中启用 |
96
+ | `needs` | 运行前提 `{ bin?, files? }`:`node_modules/.bin` 下的可执行文件与相对仓库根的文件;`sumi init` 接入已有仓库时据此去掉不满足的步骤 |
97
+ | `hooks` | `git`:git hook 名称 → 命令名;`agent.beforeTool`:命令名或带 `tools`、`failure`、`when` 的声明;`agent.afterEdit`:编辑后命令名;`agent.onPrompt`:提示词命令名或带 `when` 的声明 |
98
+ | `afterInit` | 接入已有仓库后运行的 `sumi` 命令参数,例如 `[snapshot, save]` |
99
+ | `instructions` | 指令主题名 → 插件包内的 Markdown 文件 |
100
+ | `taskTopics` | 可选的任务类型 `bug` / `feature` / `other` → 指令主题名映射;由插件决定任务流程,CLI 只按声明取用。 |
101
+ | `context` | 约束查询命令名:标准输入 `{ repoRoot, paths, intent?, kind?, issue?, change?, select?, catalog? }`,标准输出 `{ items: [{ ref, text, source?, global?, aliases?, category? }], catalog?: [{ id, description, symptoms?, source?, warning? }] }`。`catalog` 仅供宿主模型选择,`select` 由插件按 ID 精确取回;旧插件仅处理 paths 仍兼容。目录阶段不传用户提示词原文;`warning` 由 doctor 展示。 |
83
102
 
84
103
  `hooks` 与 `context` 引用的命令名必须在本插件的 `commands` 中注册。
85
104
 
@@ -8,3 +8,4 @@ export * from './process.js';
8
8
  export * from './git.js';
9
9
  export * from './tool-batches.js';
10
10
  export * from './command-args.js';
11
+ export * from './session-context.js';
@@ -8,4 +8,5 @@ export * from './process.js';
8
8
  export * from './git.js';
9
9
  export * from './tool-batches.js';
10
10
  export * from './command-args.js';
11
+ export * from './session-context.js';
11
12
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC"}
@@ -27,6 +27,35 @@ export interface CommandDeclaration {
27
27
  argv: string[];
28
28
  description: string;
29
29
  }
30
+ /** 工具前置命令的通用接线元数据;字符串旧格式等价于 all/closed。 */
31
+ export interface BeforeToolHook {
32
+ command: string;
33
+ tools?: 'all' | 'edit';
34
+ failure?: 'closed' | 'open';
35
+ when?: {
36
+ path: string;
37
+ equals?: string;
38
+ notEquals?: string;
39
+ };
40
+ }
41
+ export interface PromptHook {
42
+ command: string;
43
+ when?: {
44
+ path: string;
45
+ equals?: string;
46
+ notEquals?: string;
47
+ };
48
+ }
49
+ /** 插件拥有的项目配置模式;适配器只负责通用校验、诊断和首次接线提示。 */
50
+ export interface AgentSetting {
51
+ path: string;
52
+ values: string[];
53
+ default: string;
54
+ event: 'beforeTool' | 'onPrompt';
55
+ group: string;
56
+ label: string;
57
+ upgradeNotice?: string;
58
+ }
30
59
  export interface PluginDeclaration {
31
60
  id: string;
32
61
  version: string;
@@ -57,15 +86,19 @@ export interface PluginDeclaration {
57
86
  git?: Record<string, string>;
58
87
  /** AI 工具调用工具前、编辑文件后与准备结束回合时运行的命令。工具原始负载经标准输入传入。 */
59
88
  agent?: {
60
- beforeTool?: string;
89
+ beforeTool?: string | BeforeToolHook;
61
90
  afterEdit?: string;
91
+ onPrompt?: string | PromptHook;
62
92
  stop?: string;
63
93
  };
64
94
  };
95
+ agentSettings?: AgentSetting[];
65
96
  /** 接入已有仓库后运行的 sumi 命令参数,例如 [snapshot, save]。 */
66
97
  afterInit?: string[];
67
98
  /** 本插件提供的动态指令:主题名 → 插件包内的指令文件(Markdown)。 */
68
99
  instructions?: Record<string, string>;
100
+ /** 任务类型到指令主题的映射;CLI 不内置具体任务流程。 */
101
+ taskTopics?: Partial<Record<'bug' | 'feature' | 'other', string>>;
69
102
  /** 一句话说明,供 sumi context 与诊断展示。 */
70
103
  description?: string;
71
104
  /** 约束查询命令(本插件注册的命令名):标准输入为 { repoRoot, paths },标准输出为 ContextResult。 */
@@ -80,9 +113,30 @@ export interface ContextItem {
80
113
  global?: boolean;
81
114
  /** 同样指向本条目的其他引用写法(例如条目所属集合的引用),规则引用其中任一即视为关联。 */
82
115
  aliases?: string[];
116
+ /** 非约束类型由提供者定义,CLI 仅分组展示。 */
117
+ category?: 'scenario' | 'known-issue' | 'workflow';
118
+ }
119
+ export interface ContextCatalogEntry {
120
+ id: string;
121
+ description: string;
122
+ symptoms?: string;
123
+ source?: string;
124
+ /** 目录提供者维护质量诊断,由 doctor 原样报告;CLI 不解释策略。 */
125
+ warning?: string;
126
+ }
127
+ export interface ContextInput {
128
+ repoRoot: string;
129
+ paths: string[];
130
+ intent?: string;
131
+ kind?: 'bug' | 'feature' | 'other';
132
+ issue?: string;
133
+ change?: string;
134
+ select?: string[];
135
+ catalog?: boolean;
83
136
  }
84
137
  export interface ContextResult {
85
138
  items: ContextItem[];
139
+ catalog?: ContextCatalogEntry[];
86
140
  }
87
141
  /** 编辑后命令的可选成功结果;不含工具专属包装。 */
88
142
  export interface AfterEditResult {
@@ -1 +1 @@
1
- {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"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"}
@@ -11,7 +11,4 @@ export declare function ruleRefPattern(): RegExp;
11
11
  /** 一行文本中的全部执行者引用。 */
12
12
  export declare function ruleRefs(text: string): RuleRef[];
13
13
  /** 读取约束查询命令的输入:标准输入上的 { repoRoot, paths }。 */
14
- export declare function readContextInput(): Promise<{
15
- repoRoot: string;
16
- paths: string[];
17
- }>;
14
+ export declare function readContextInput(): Promise<import('./protocol.js').ContextInput>;
@@ -1 +1 @@
1
- {"version":3,"file":"rules.js","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"AASA,iCAAiC;AACjC,MAAM,UAAU,cAAc;IAC5B,OAAO,gCAAgC,CAAC;AAC1C,CAAC;AAED,qBAAqB;AACrB,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,OAAO,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAE,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAE,EAAE,CAAC,CAAC,CAAC;AAC3F,CAAC;AAED,8CAA8C;AAC9C,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,OAAO,CAAC,KAAK;QAAE,IAAI,IAAI,KAAK,CAAC;IACvD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAA0C,CAAC;AACnE,CAAC"}
1
+ {"version":3,"file":"rules.js","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"AASA,iCAAiC;AACjC,MAAM,UAAU,cAAc;IAC5B,OAAO,gCAAgC,CAAC;AAC1C,CAAC;AAED,qBAAqB;AACrB,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,OAAO,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAE,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAE,EAAE,CAAC,CAAC,CAAC;AAC3F,CAAC;AAED,8CAA8C;AAC9C,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,OAAO,CAAC,KAAK;QAAE,IAAI,IAAI,KAAK,CAAC;IACvD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAyC,CAAC;AAClE,CAAC"}
@@ -0,0 +1,7 @@
1
+ export interface ContextSessionState {
2
+ keys: string[];
3
+ deniedScopes: string[];
4
+ }
5
+ /** 兼容旧版数组状态;损坏状态返回 null,由调用方故障开放。 */
6
+ export declare function readContextSession(root: string, session: string): ContextSessionState | null;
7
+ export declare function saveContextSession(root: string, session: string, keys: string[], deniedScope?: string | string[], recoverCorrupt?: boolean): boolean;
@@ -0,0 +1,62 @@
1
+ import { createHash, randomUUID } from 'node:crypto';
2
+ import { mkdirSync, readFileSync, readdirSync, renameSync, statSync, unlinkSync, writeFileSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ function stateFile(root, session) {
5
+ const key = createHash('sha256').update(session).digest('hex');
6
+ return join(root, '.sumi/after-edit-context', `${key}.json`);
7
+ }
8
+ /** 兼容旧版数组状态;损坏状态返回 null,由调用方故障开放。 */
9
+ export function readContextSession(root, session) {
10
+ try {
11
+ const value = JSON.parse(readFileSync(stateFile(root, session), 'utf8'));
12
+ if (Array.isArray(value) && value.every((key) => typeof key === 'string'))
13
+ return { keys: value, deniedScopes: [] };
14
+ if (!value || typeof value !== 'object' || Array.isArray(value))
15
+ return null;
16
+ const state = value;
17
+ if (!Array.isArray(state.keys) || !state.keys.every((key) => typeof key === 'string'))
18
+ return null;
19
+ if (!Array.isArray(state.deniedScopes) || !state.deniedScopes.every((key) => typeof key === 'string'))
20
+ return null;
21
+ return { keys: state.keys, deniedScopes: state.deniedScopes };
22
+ }
23
+ catch (error) {
24
+ return error.code === 'ENOENT' ? { keys: [], deniedScopes: [] } : null;
25
+ }
26
+ }
27
+ export function saveContextSession(root, session, keys, deniedScope, recoverCorrupt = false) {
28
+ try {
29
+ const old = readContextSession(root, session);
30
+ if (!old && !recoverCorrupt)
31
+ return false;
32
+ const prior = old ?? { keys: [], deniedScopes: [] };
33
+ const dir = join(root, '.sumi/after-edit-context');
34
+ mkdirSync(dir, { recursive: true });
35
+ const cutoff = Date.now() - 7 * 24 * 60 * 60 * 1000;
36
+ for (const name of readdirSync(dir)) {
37
+ if (!name.endsWith('.json'))
38
+ continue;
39
+ try {
40
+ if (statSync(join(dir, name)).mtimeMs < cutoff)
41
+ unlinkSync(join(dir, name));
42
+ }
43
+ catch {
44
+ /* 尽力清理 */
45
+ }
46
+ }
47
+ const file = stateFile(root, session);
48
+ const temporary = `${file}.${randomUUID()}.tmp`;
49
+ writeFileSync(temporary, JSON.stringify({
50
+ keys: [...new Set([...prior.keys, ...keys])],
51
+ deniedScopes: [
52
+ ...new Set([...prior.deniedScopes, ...(Array.isArray(deniedScope) ? deniedScope : deniedScope ? [deniedScope] : [])]),
53
+ ],
54
+ }));
55
+ renameSync(temporary, file);
56
+ return true;
57
+ }
58
+ catch {
59
+ return false;
60
+ }
61
+ }
62
+ //# sourceMappingURL=session-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-context.js","sourceRoot":"","sources":["../src/session-context.ts"],"names":[],"mappings":"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"}