@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.
- package/README.md +27 -25
- package/dist/adapters.d.ts +24 -3
- package/dist/adapters.js +100 -14
- package/dist/adapters.js.map +1 -1
- package/dist/agent-hooks.d.ts +3 -0
- package/dist/agent-hooks.js +54 -3
- package/dist/agent-hooks.js.map +1 -1
- package/dist/agents.js +36 -3
- package/dist/agents.js.map +1 -1
- package/dist/cli.d.ts +3 -1
- package/dist/cli.js +4 -4
- package/dist/cli.js.map +1 -1
- package/dist/context.d.ts +27 -0
- package/dist/context.js +28 -10
- package/dist/context.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/instructions.js +4 -4
- package/dist/instructions.js.map +1 -1
- package/dist/task.d.ts +1 -0
- package/dist/task.js +170 -0
- package/dist/task.js.map +1 -0
- package/node_modules/@sumi/create/dist/bin.d.ts +2 -0
- package/node_modules/@sumi/create/dist/bin.js +52 -0
- package/node_modules/@sumi/create/dist/bin.js.map +1 -0
- package/node_modules/@sumi/create/package.json +1 -1
- package/node_modules/@sumi/kernel/package.json +2 -2
- package/node_modules/@sumi/plugin-sdk/README.md +39 -20
- package/node_modules/@sumi/plugin-sdk/dist/index.d.ts +1 -0
- package/node_modules/@sumi/plugin-sdk/dist/index.js +1 -0
- package/node_modules/@sumi/plugin-sdk/dist/index.js.map +1 -1
- package/node_modules/@sumi/plugin-sdk/dist/protocol.d.ts +55 -1
- package/node_modules/@sumi/plugin-sdk/dist/protocol.js.map +1 -1
- package/node_modules/@sumi/plugin-sdk/dist/rules.d.ts +1 -4
- package/node_modules/@sumi/plugin-sdk/dist/rules.js.map +1 -1
- package/node_modules/@sumi/plugin-sdk/dist/session-context.d.ts +7 -0
- package/node_modules/@sumi/plugin-sdk/dist/session-context.js +62 -0
- package/node_modules/@sumi/plugin-sdk/dist/session-context.js.map +1 -0
- package/node_modules/@sumi/plugin-sdk/dist/validate.js +51 -2
- package/node_modules/@sumi/plugin-sdk/dist/validate.js.map +1 -1
- package/node_modules/@sumi/plugin-sdk/package.json +1 -1
- package/node_modules/@sumi/plugins-core/dist/tool-batches.d.ts +11 -0
- package/node_modules/@sumi/plugins-core/dist/tool-batches.js +41 -0
- package/node_modules/@sumi/plugins-core/dist/tool-batches.js.map +1 -0
- package/node_modules/@sumi/plugins-core/instructions/bugfix.md +9 -0
- package/node_modules/@sumi/plugins-core/instructions/feature.md +9 -0
- package/node_modules/@sumi/plugins-core/package.json +2 -2
- package/node_modules/@sumi/plugins-core/sumi-plugins.yaml +2 -1
- package/node_modules/@sumi/plugins-governance/dist/hooks.d.ts +2 -0
- package/node_modules/@sumi/plugins-governance/dist/hooks.js +4 -0
- package/node_modules/@sumi/plugins-governance/dist/hooks.js.map +1 -0
- package/node_modules/@sumi/plugins-governance/package.json +2 -2
- package/node_modules/@sumi/plugins-openspec/package.json +2 -2
- package/node_modules/@sumi/plugins-precedent/README.md +6 -0
- package/node_modules/@sumi/plugins-precedent/dist/after-edit-context.d.ts +2 -0
- package/node_modules/@sumi/plugins-precedent/dist/after-edit-context.js +89 -77
- package/node_modules/@sumi/plugins-precedent/dist/after-edit-context.js.map +1 -1
- package/node_modules/@sumi/plugins-precedent/dist/commands/before-edit-context.d.ts +1 -0
- package/node_modules/@sumi/plugins-precedent/dist/commands/before-edit-context.js +10 -0
- package/node_modules/@sumi/plugins-precedent/dist/commands/before-edit-context.js.map +1 -0
- package/node_modules/@sumi/plugins-precedent/dist/commands/context.js +15 -5
- package/node_modules/@sumi/plugins-precedent/dist/commands/context.js.map +1 -1
- package/node_modules/@sumi/plugins-precedent/dist/commands/on-prompt-context.d.ts +1 -0
- package/node_modules/@sumi/plugins-precedent/dist/commands/on-prompt-context.js +55 -0
- package/node_modules/@sumi/plugins-precedent/dist/commands/on-prompt-context.js.map +1 -0
- package/node_modules/@sumi/plugins-precedent/dist/model.d.ts +2 -0
- package/node_modules/@sumi/plugins-precedent/dist/model.js.map +1 -1
- package/node_modules/@sumi/plugins-precedent/package.json +3 -3
- package/node_modules/@sumi/plugins-precedent/sumi-plugins.yaml +25 -1
- package/node_modules/@sumi/plugins-review/dist/commands/context.js +18 -3
- package/node_modules/@sumi/plugins-review/dist/commands/context.js.map +1 -1
- package/node_modules/@sumi/plugins-review/dist/review.d.ts +1 -0
- package/node_modules/@sumi/plugins-review/dist/review.js.map +1 -1
- package/node_modules/@sumi/plugins-review/package.json +3 -3
- 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
|
package/dist/task.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task.js","sourceRoot":"","sources":["../src/task.ts"],"names":[],"mappings":"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"}
|
|
@@ -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/kernel",
|
|
3
|
-
"version": "0.7.
|
|
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.
|
|
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
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
|
82
|
-
|
|
|
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
|
|
|
@@ -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":"AAAA,yBAAyB;AAUzB,MAAM,CAAC,MAAM,QAAQ,GAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;AAC7F,MAAM,CAAC,MAAM,OAAO,GAAsB,CAAC,MAAM,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;AAC9G,MAAM,CAAC,MAAM,gBAAgB,GAA8B,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC;AAE3G,qCAAqC;AACrC,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,IAAI,MAAM,KAAK,MAAM;QAAE,OAAO,CAAC,CAAC;IAChC,IAAI,MAAM,KAAK,MAAM;QAAE,OAAO,CAAC,CAAC;IAChC,OAAO,CAAC,CAAC;AACX,CAAC;AASD,4CAA4C;AAC5C,MAAM,UAAU,aAAa,CAAC,IAAuB,EAAE,KAAa,EAAE,IAAY;IAChF,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,IAAI,CAAC,CAAC;IAChC,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,KAAK,iBAAiB,CAAC,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC;IACjF,OAAO,EAAE,KAAK,EAAE,KAAK,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,GAAG,GAAG,EAAE,CAAC;AACtD,CAAC;
|
|
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,
|
|
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":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAChH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAOjC,SAAS,SAAS,CAAC,IAAY,EAAE,OAAe;IAC9C,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC/D,OAAO,IAAI,CAAC,IAAI,EAAE,0BAA0B,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC;AAC/D,CAAC;AAED,qCAAqC;AACrC,MAAM,UAAU,kBAAkB,CAAC,IAAY,EAAE,OAAe;IAC9D,IAAI,CAAC;QACH,MAAM,KAAK,GAAY,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;QAClF,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,GAAG,KAAK,QAAQ,CAAC;YAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;QACpH,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAC7E,MAAM,KAAK,GAAG,KAAgC,CAAC;QAC/C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,GAAG,KAAK,QAAQ,CAAC;YAAE,OAAO,IAAI,CAAC;QACnG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,GAAG,KAAK,QAAQ,CAAC;YAAE,OAAO,IAAI,CAAC;QACnH,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAgB,EAAE,YAAY,EAAE,KAAK,CAAC,YAAwB,EAAE,CAAC;IACxF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAQ,KAA+B,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IACpG,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,IAAY,EACZ,OAAe,EACf,IAAc,EACd,WAA+B,EAC/B,cAAc,GAAG,KAAK;IAEtB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,kBAAkB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC9C,IAAI,CAAC,GAAG,IAAI,CAAC,cAAc;YAAE,OAAO,KAAK,CAAC;QAC1C,MAAM,KAAK,GAAG,GAAG,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;QACpD,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,EAAE,0BAA0B,CAAC,CAAC;QACnD,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;QACpD,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;YACpC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAAE,SAAS;YACtC,IAAI,CAAC;gBACH,IAAI,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,GAAG,MAAM;oBAAE,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;YAC9E,CAAC;YAAC,MAAM,CAAC;gBACP,UAAU;YACZ,CAAC;QACH,CAAC;QACD,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACtC,MAAM,SAAS,GAAG,GAAG,IAAI,IAAI,UAAU,EAAE,MAAM,CAAC;QAChD,aAAa,CACX,SAAS,EACT,IAAI,CAAC,SAAS,CAAC;YACb,IAAI,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;YAC5C,YAAY,EAAE;gBACZ,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,YAAY,EAAE,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;aACtH;SAC4B,CAAC,CACjC,CAAC;QACF,UAAU,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAC5B,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|