@spikedpunch/mast 0.3.0 → 0.4.0
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 +180 -9
- package/assets/prime.md +18 -0
- package/assets/signals.md +51 -0
- package/assets/skill.md +6 -47
- package/dist/cli/docs-cmd.d.ts +1 -0
- package/dist/cli/docs-cmd.d.ts.map +1 -1
- package/dist/cli/docs-cmd.js +2 -1
- package/dist/cli/docs-cmd.js.map +1 -1
- package/dist/cli/hook-cmd.d.ts +3 -0
- package/dist/cli/hook-cmd.d.ts.map +1 -0
- package/dist/cli/hook-cmd.js +13 -0
- package/dist/cli/hook-cmd.js.map +1 -0
- package/dist/cli/hook-state-dir.d.ts +24 -0
- package/dist/cli/hook-state-dir.d.ts.map +1 -0
- package/dist/cli/hook-state-dir.js +57 -0
- package/dist/cli/hook-state-dir.js.map +1 -0
- package/dist/cli/hook.d.ts +44 -0
- package/dist/cli/hook.d.ts.map +1 -0
- package/dist/cli/hook.js +200 -0
- package/dist/cli/hook.js.map +1 -0
- package/dist/cli/index.js +12 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/installed-artifacts.d.ts +23 -0
- package/dist/cli/installed-artifacts.d.ts.map +1 -0
- package/dist/cli/installed-artifacts.js +39 -0
- package/dist/cli/installed-artifacts.js.map +1 -0
- package/dist/cli/prime-cmd.d.ts +17 -0
- package/dist/cli/prime-cmd.d.ts.map +1 -0
- package/dist/cli/prime-cmd.js +70 -0
- package/dist/cli/prime-cmd.js.map +1 -0
- package/dist/cli/program.d.ts.map +1 -1
- package/dist/cli/program.js +6 -0
- package/dist/cli/program.js.map +1 -1
- package/dist/cli/setup-cmd.d.ts +34 -0
- package/dist/cli/setup-cmd.d.ts.map +1 -0
- package/dist/cli/setup-cmd.js +205 -0
- package/dist/cli/setup-cmd.js.map +1 -0
- package/dist/cli/setup-command.d.ts +32 -0
- package/dist/cli/setup-command.d.ts.map +1 -0
- package/dist/cli/setup-command.js +43 -0
- package/dist/cli/setup-command.js.map +1 -0
- package/dist/cli/setup-plan.d.ts +52 -0
- package/dist/cli/setup-plan.d.ts.map +1 -0
- package/dist/cli/setup-plan.js +221 -0
- package/dist/cli/setup-plan.js.map +1 -0
- package/dist/cli/setup-rules.d.ts +41 -0
- package/dist/cli/setup-rules.d.ts.map +1 -0
- package/dist/cli/setup-rules.js +76 -0
- package/dist/cli/setup-rules.js.map +1 -0
- package/dist/cli/setup-static.d.ts +13 -0
- package/dist/cli/setup-static.d.ts.map +1 -0
- package/dist/cli/setup-static.js +116 -0
- package/dist/cli/setup-static.js.map +1 -0
- package/dist/cli/skill-install.d.ts +2 -0
- package/dist/cli/skill-install.d.ts.map +1 -1
- package/dist/cli/skill-install.js +2 -0
- package/dist/cli/skill-install.js.map +1 -1
- package/dist/cli/upgrade-cmd.d.ts +5 -1
- package/dist/cli/upgrade-cmd.d.ts.map +1 -1
- package/dist/cli/upgrade-cmd.js +28 -3
- package/dist/cli/upgrade-cmd.js.map +1 -1
- package/dist/indexer/watcher.d.ts +80 -2
- package/dist/indexer/watcher.d.ts.map +1 -1
- package/dist/indexer/watcher.js +172 -27
- package/dist/indexer/watcher.js.map +1 -1
- package/dist/mcp/instructions.d.ts +7 -0
- package/dist/mcp/instructions.d.ts.map +1 -0
- package/dist/mcp/instructions.js +10 -0
- package/dist/mcp/instructions.js.map +1 -0
- package/dist/mcp/server.d.ts +8 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +17 -4
- package/dist/mcp/server.js.map +1 -1
- package/dist/store/config.d.ts.map +1 -1
- package/dist/store/config.js +4 -5
- package/dist/store/config.js.map +1 -1
- package/dist/store/defaults.d.ts +9 -0
- package/dist/store/defaults.d.ts.map +1 -0
- package/dist/store/defaults.js +12 -0
- package/dist/store/defaults.js.map +1 -0
- package/package.json +2 -1
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { chmodSync, existsSync, mkdirSync, readFileSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { basename, dirname, join, resolve } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { readDoc } from './docs-cmd.js';
|
|
6
|
+
import { buildHookCommand, hookFilePath } from './setup-command.js';
|
|
7
|
+
import { HOOK_DEFS, planFor } from './setup-plan.js';
|
|
8
|
+
import { runCursorRules, runStaticSetup, STATIC_HARNESSES } from './setup-static.js';
|
|
9
|
+
import { detectInstallKind } from './upgrade-cmd.js';
|
|
10
|
+
import { PACKAGE_NAME } from './version.js';
|
|
11
|
+
/**
|
|
12
|
+
* `mast setup <harness>` writes hook configuration and, for harnesses with a rules file
|
|
13
|
+
* mast can own (or Zed's, via a marked block), that file too. It follows the rules
|
|
14
|
+
* `skill-install.ts` states: touch nothing it does not own, and be a byte-level no-op on
|
|
15
|
+
* re-run. Unlike `skill --install` it creates its file when absent, because a hook file
|
|
16
|
+
* is tool configuration and not a hand-curated prompt (ADR 017 section 3).
|
|
17
|
+
*/
|
|
18
|
+
const HOOK_HARNESSES = ['claude', 'cursor', 'vscode'];
|
|
19
|
+
const ALL_HARNESSES = [...HOOK_HARNESSES, ...STATIC_HARNESSES];
|
|
20
|
+
/** Re-emits `value` in the file's own indentation, line endings and trailing-newline state. */
|
|
21
|
+
function serialize(value, previous) {
|
|
22
|
+
const indent = previous === null ? ' ' : (/^([ \t]+)\S/m.exec(previous)?.[1] ?? ' ');
|
|
23
|
+
const trailingNewline = previous === null || previous.endsWith('\n');
|
|
24
|
+
let text = JSON.stringify(value, null, indent) + (trailingNewline ? '\n' : '');
|
|
25
|
+
if (previous?.includes('\r\n'))
|
|
26
|
+
text = text.replace(/\n/g, '\r\n');
|
|
27
|
+
return text;
|
|
28
|
+
}
|
|
29
|
+
function parseJson(raw) {
|
|
30
|
+
try {
|
|
31
|
+
return { ok: true, value: JSON.parse(raw) };
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
return { ok: false, problem: `not valid JSON (${error instanceof Error ? error.message : String(error)})` };
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function buildCommands(harness, scope, env) {
|
|
38
|
+
const commands = {};
|
|
39
|
+
for (const def of HOOK_DEFS[harness]) {
|
|
40
|
+
const built = buildHookCommand({ harness, event: def.event, installKind: env.installKind, scope, cliEntry: env.cliEntry });
|
|
41
|
+
if (!built.ok)
|
|
42
|
+
return built;
|
|
43
|
+
commands[def.event] = built.command;
|
|
44
|
+
}
|
|
45
|
+
return { ok: true, commands };
|
|
46
|
+
}
|
|
47
|
+
function notesFor(harness, scope, env) {
|
|
48
|
+
const notes = [];
|
|
49
|
+
if (harness === 'vscode') {
|
|
50
|
+
notes.push('Only the session primer is installed for VS Code. A search reminder is not: VS Code ignores hook matchers, ' +
|
|
51
|
+
'so it would run on every tool call, and the name of its search tool is not documented.');
|
|
52
|
+
}
|
|
53
|
+
if (env.installKind === 'source') {
|
|
54
|
+
notes.push('The hook command contains a path specific to this machine; do not commit this file.');
|
|
55
|
+
}
|
|
56
|
+
if (env.installKind === 'local' && scope === 'project' && harness === 'vscode') {
|
|
57
|
+
notes.push('The relative command node_modules/.bin/mast is unverified in VS Code: its docs do not say what directory hooks run in.');
|
|
58
|
+
}
|
|
59
|
+
return notes;
|
|
60
|
+
}
|
|
61
|
+
function describePlan(plan, existed, remove) {
|
|
62
|
+
if (remove)
|
|
63
|
+
return plan.removedCount > 0 ? 'removed' : 'not installed';
|
|
64
|
+
if (!plan.changed)
|
|
65
|
+
return 'already up to date';
|
|
66
|
+
return !existed || plan.items.every((i) => i.state === 'missing') ? 'installed' : 'updated';
|
|
67
|
+
}
|
|
68
|
+
function reportProblem(io, path, problem) {
|
|
69
|
+
io.err(`mast setup: cannot update ${path}: ${problem}.`);
|
|
70
|
+
io.err('The file was left unchanged. Fix or delete it, then run the command again.');
|
|
71
|
+
}
|
|
72
|
+
/** Returns the process exit code: 0 done, 1 refused or failed, 2 usage error. */
|
|
73
|
+
export function runSetup(opts, env, io) {
|
|
74
|
+
const hookHarness = HOOK_HARNESSES.find((h) => h === opts.harness);
|
|
75
|
+
const staticHarness = STATIC_HARNESSES.find((h) => h === opts.harness);
|
|
76
|
+
if (hookHarness === undefined && staticHarness === undefined) {
|
|
77
|
+
io.err(`mast setup: unknown harness "${opts.harness}". Supported: ${ALL_HARNESSES.join(', ')}.`);
|
|
78
|
+
return 2;
|
|
79
|
+
}
|
|
80
|
+
if (opts.check && (opts.remove || opts.dryRun)) {
|
|
81
|
+
io.err('mast setup: --check cannot be combined with --remove or --dry-run.');
|
|
82
|
+
return 2;
|
|
83
|
+
}
|
|
84
|
+
if (staticHarness !== undefined)
|
|
85
|
+
return runStaticSetup(staticHarness, opts, env, io);
|
|
86
|
+
if (hookHarness === undefined)
|
|
87
|
+
return 2;
|
|
88
|
+
const hookCode = runHookSetup(hookHarness, opts, env, io);
|
|
89
|
+
if (hookHarness !== 'cursor')
|
|
90
|
+
return hookCode;
|
|
91
|
+
// A failed hooks step stops the rules step, except under --check, which reports both.
|
|
92
|
+
if (hookCode !== 0 && !opts.check)
|
|
93
|
+
return hookCode;
|
|
94
|
+
const rulesCode = runCursorRules(opts, env, io);
|
|
95
|
+
return hookCode !== 0 ? hookCode : rulesCode;
|
|
96
|
+
}
|
|
97
|
+
function runHookSetup(harness, opts, env, io) {
|
|
98
|
+
const scope = opts.global ? 'global' : 'project';
|
|
99
|
+
const path = hookFilePath(harness, scope, opts.projectRoot, env.home);
|
|
100
|
+
let mode = { kind: 'remove' };
|
|
101
|
+
if (!opts.remove) {
|
|
102
|
+
const built = buildCommands(harness, scope, env);
|
|
103
|
+
if (!built.ok) {
|
|
104
|
+
io.err(`mast setup: ${built.problem}`);
|
|
105
|
+
return 1;
|
|
106
|
+
}
|
|
107
|
+
if (env.installKind === 'local' && scope === 'project' && !io.fileExists(join(opts.projectRoot, 'node_modules', '.bin', 'mast'))) {
|
|
108
|
+
io.err(`mast setup: ${join(opts.projectRoot, 'node_modules', '.bin', 'mast')} does not exist, so the hook command would not run. Install mast in this project (pnpm add -D ${PACKAGE_NAME}) or install it globally.`);
|
|
109
|
+
return 1;
|
|
110
|
+
}
|
|
111
|
+
mode = { kind: 'install', commands: built.commands };
|
|
112
|
+
}
|
|
113
|
+
try {
|
|
114
|
+
const raw = io.readFile(path);
|
|
115
|
+
let existing = null;
|
|
116
|
+
if (raw !== null) {
|
|
117
|
+
const parsed = parseJson(raw);
|
|
118
|
+
if (!parsed.ok) {
|
|
119
|
+
reportProblem(io, path, parsed.problem);
|
|
120
|
+
return 1;
|
|
121
|
+
}
|
|
122
|
+
existing = parsed.value;
|
|
123
|
+
}
|
|
124
|
+
const plan = planFor(harness, existing, mode);
|
|
125
|
+
if (!plan.ok) {
|
|
126
|
+
reportProblem(io, path, plan.problem);
|
|
127
|
+
return 1;
|
|
128
|
+
}
|
|
129
|
+
if (opts.check) {
|
|
130
|
+
const stale = plan.items.filter((i) => i.state !== 'current');
|
|
131
|
+
if (stale.length === 0) {
|
|
132
|
+
io.out(`${path}: already up to date`);
|
|
133
|
+
return 0;
|
|
134
|
+
}
|
|
135
|
+
// A settings file that exists but holds none of mast's hooks is "not installed",
|
|
136
|
+
// the same as no file: "out of date" would send someone looking for a stale entry.
|
|
137
|
+
io.out(`${path}: ${stale.length === plan.items.length && stale.every((i) => i.state === 'missing') ? 'not installed' : 'out of date'}`);
|
|
138
|
+
for (const item of stale)
|
|
139
|
+
io.out(` ${item.state === 'missing' ? 'missing' : 'out of date'}: ${item.label}`);
|
|
140
|
+
return 1;
|
|
141
|
+
}
|
|
142
|
+
const status = describePlan(plan, raw !== null, opts.remove);
|
|
143
|
+
const willWrite = plan.changed;
|
|
144
|
+
if (opts.dryRun) {
|
|
145
|
+
io.out(`${path}: ${status} (dry run, nothing written)`);
|
|
146
|
+
if (willWrite)
|
|
147
|
+
io.out(plan.next === null ? '(the file would be deleted)' : serialize(plan.next, raw).trimEnd());
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
if (willWrite) {
|
|
151
|
+
if (plan.next === null)
|
|
152
|
+
io.removeFile(path);
|
|
153
|
+
else
|
|
154
|
+
io.writeFileAtomic(path, serialize(plan.next, raw));
|
|
155
|
+
}
|
|
156
|
+
io.out(`${path}: ${status}`);
|
|
157
|
+
}
|
|
158
|
+
if (!opts.remove)
|
|
159
|
+
for (const note of notesFor(harness, scope, env))
|
|
160
|
+
io.out(`Note: ${note}`);
|
|
161
|
+
return 0;
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
io.err(`mast setup: ${path}: ${error instanceof Error ? error.message : String(error)}`);
|
|
165
|
+
return 1;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
export function createNodeSetupIo() {
|
|
169
|
+
return {
|
|
170
|
+
readFile: (path) => (existsSync(path) ? readFileSync(path, 'utf8') : null),
|
|
171
|
+
writeFileAtomic: (path, content) => {
|
|
172
|
+
// Resolve a symlinked settings file first, or the rename would replace the link
|
|
173
|
+
// (a dotfiles checkout, say) with a regular file.
|
|
174
|
+
const target = existsSync(path) ? realpathSync(path) : path;
|
|
175
|
+
mkdirSync(dirname(target), { recursive: true });
|
|
176
|
+
// Same directory, so the rename cannot cross a filesystem and stays atomic.
|
|
177
|
+
const temp = join(dirname(target), `.${basename(target)}.${process.pid}.tmp`);
|
|
178
|
+
writeFileSync(temp, content);
|
|
179
|
+
if (existsSync(target))
|
|
180
|
+
chmodSync(temp, statSync(target).mode & 0o777);
|
|
181
|
+
renameSync(temp, target);
|
|
182
|
+
},
|
|
183
|
+
removeFile: (path) => { rmSync(path); },
|
|
184
|
+
fileExists: existsSync,
|
|
185
|
+
directoryExists: (path) => existsSync(path) && statSync(path).isDirectory(),
|
|
186
|
+
out: (line) => { process.stdout.write(`${line}\n`); },
|
|
187
|
+
err: (line) => { process.stderr.write(`${line}\n`); },
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
export function registerSetupCommand(program) {
|
|
191
|
+
program
|
|
192
|
+
.command('setup <harness> [path]')
|
|
193
|
+
.description('Install the hooks and rules files that tell an agent to use mast (claude|cursor|vscode|windsurf|zed|desktop)')
|
|
194
|
+
.option('--global', 'Write the user-level file instead of the project one')
|
|
195
|
+
.option('--check', 'Write nothing; exit 0 only if everything is installed and current')
|
|
196
|
+
.option('--remove', 'Remove what mast installed')
|
|
197
|
+
.option('--dry-run', 'Print the file that would be written, and write nothing')
|
|
198
|
+
.action((harness, path, opts) => {
|
|
199
|
+
const projectRoot = resolve(path ?? '.');
|
|
200
|
+
const moduleDir = dirname(fileURLToPath(import.meta.url));
|
|
201
|
+
// The home directory is resolved here, at the edge, and nowhere below.
|
|
202
|
+
process.exitCode = runSetup({ harness, projectRoot, global: opts.global === true, check: opts.check === true, remove: opts.remove === true, dryRun: opts.dryRun === true }, { installKind: detectInstallKind(moduleDir, projectRoot), home: homedir(), cliEntry: join(moduleDir, 'index.js'), skillText: readDoc('skill') }, createNodeSetupIo());
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=setup-cmd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup-cmd.js","sourceRoot":"","sources":["../../src/cli/setup-cmd.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Harness, HookEvent } from './hook.js';
|
|
2
|
+
import type { InstallKind } from './upgrade-cmd.js';
|
|
3
|
+
export type SetupScope = 'project' | 'global';
|
|
4
|
+
export interface HookCommandInput {
|
|
5
|
+
readonly harness: Harness;
|
|
6
|
+
readonly event: HookEvent;
|
|
7
|
+
readonly installKind: InstallKind;
|
|
8
|
+
readonly scope: SetupScope;
|
|
9
|
+
/** Absolute path of this build's `cli/index.js`; used only for a source checkout. */
|
|
10
|
+
readonly cliEntry: string;
|
|
11
|
+
}
|
|
12
|
+
export type HookCommandResult = {
|
|
13
|
+
readonly ok: true;
|
|
14
|
+
readonly command: string;
|
|
15
|
+
} | {
|
|
16
|
+
readonly ok: false;
|
|
17
|
+
readonly problem: string;
|
|
18
|
+
};
|
|
19
|
+
/** The hook file `setup` writes for a harness: project-level, or under the user's home. */
|
|
20
|
+
export declare function hookFilePath(harness: Harness, scope: SetupScope, projectRoot: string, home: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* The command line a harness runs for one hook. Every spelling ends in
|
|
23
|
+
* ` hook <harness> <event>`: `setup` finds its own entries by that suffix, so the part
|
|
24
|
+
* before it can change between installs without orphaning the old entry.
|
|
25
|
+
*
|
|
26
|
+
* A project-dependency install cannot be written into user-level settings: the path
|
|
27
|
+
* points into one project's node_modules and fails in every other project.
|
|
28
|
+
*/
|
|
29
|
+
export declare function buildHookCommand(input: HookCommandInput): HookCommandResult;
|
|
30
|
+
/** True when `command` is the one `setup` installs for this harness and event, in any spelling. */
|
|
31
|
+
export declare function isMastCommand(command: string | undefined, harness: Harness, event: HookEvent): boolean;
|
|
32
|
+
//# sourceMappingURL=setup-command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup-command.d.ts","sourceRoot":"","sources":["../../src/cli/setup-command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE9C,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,qFAAqF;IACrF,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,MAAM,iBAAiB,GACzB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC/C;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAErD,2FAA2F;AAC3F,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAK3G;AAOD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,gBAAgB,GAAG,iBAAiB,CAc3E;AAED,mGAAmG;AACnG,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,GAAG,OAAO,CAEtG"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
/** The hook file `setup` writes for a harness: project-level, or under the user's home. */
|
|
3
|
+
export function hookFilePath(harness, scope, projectRoot, home) {
|
|
4
|
+
const base = scope === 'global' ? home : projectRoot;
|
|
5
|
+
if (harness === 'claude')
|
|
6
|
+
return join(base, '.claude', 'settings.json');
|
|
7
|
+
if (harness === 'cursor')
|
|
8
|
+
return join(base, '.cursor', 'hooks.json');
|
|
9
|
+
return scope === 'global' ? join(home, '.copilot', 'hooks', 'mast.json') : join(projectRoot, '.github', 'hooks', 'mast.json');
|
|
10
|
+
}
|
|
11
|
+
// Claude Code expands this variable itself when it runs a project hook, so the spelling
|
|
12
|
+
// holds wherever the project is checked out. A template literal would interpolate it.
|
|
13
|
+
const CLAUDE_LOCAL_BIN = '"$' + '{CLAUDE_PROJECT_DIR}"/node_modules/.bin/mast';
|
|
14
|
+
const RELATIVE_LOCAL_BIN = 'node_modules/.bin/mast';
|
|
15
|
+
/**
|
|
16
|
+
* The command line a harness runs for one hook. Every spelling ends in
|
|
17
|
+
* ` hook <harness> <event>`: `setup` finds its own entries by that suffix, so the part
|
|
18
|
+
* before it can change between installs without orphaning the old entry.
|
|
19
|
+
*
|
|
20
|
+
* A project-dependency install cannot be written into user-level settings: the path
|
|
21
|
+
* points into one project's node_modules and fails in every other project.
|
|
22
|
+
*/
|
|
23
|
+
export function buildHookCommand(input) {
|
|
24
|
+
const tail = ` hook ${input.harness} ${input.event}`;
|
|
25
|
+
if (input.installKind === 'global')
|
|
26
|
+
return { ok: true, command: `mast${tail}` };
|
|
27
|
+
if (input.installKind === 'source')
|
|
28
|
+
return { ok: true, command: `node "${input.cliEntry}"${tail}` };
|
|
29
|
+
if (input.scope === 'global') {
|
|
30
|
+
return {
|
|
31
|
+
ok: false,
|
|
32
|
+
problem: 'this mast is a project dependency, and a user-level hook that points into one project\'s node_modules ' +
|
|
33
|
+
'breaks in every other project. Install mast globally, or run without --global.',
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
const bin = input.harness === 'claude' ? CLAUDE_LOCAL_BIN : RELATIVE_LOCAL_BIN;
|
|
37
|
+
return { ok: true, command: `${bin}${tail}` };
|
|
38
|
+
}
|
|
39
|
+
/** True when `command` is the one `setup` installs for this harness and event, in any spelling. */
|
|
40
|
+
export function isMastCommand(command, harness, event) {
|
|
41
|
+
return command !== undefined && command.endsWith(` hook ${harness} ${event}`);
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=setup-command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup-command.js","sourceRoot":"","sources":["../../src/cli/setup-command.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAkBjC,2FAA2F;AAC3F,MAAM,UAAU,YAAY,CAAC,OAAgB,EAAE,KAAiB,EAAE,WAAmB,EAAE,IAAY;IACjG,MAAM,IAAI,GAAG,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC;IACrD,IAAI,OAAO,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC;IACxE,IAAI,OAAO,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;IACrE,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;AAChI,CAAC;AAED,wFAAwF;AACxF,sFAAsF;AACtF,MAAM,gBAAgB,GAAG,IAAI,GAAG,8CAA8C,CAAC;AAC/E,MAAM,kBAAkB,GAAG,wBAAwB,CAAC;AAEpD;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAuB;IACtD,MAAM,IAAI,GAAG,SAAS,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;IACrD,IAAI,KAAK,CAAC,WAAW,KAAK,QAAQ;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,IAAI,EAAE,EAAE,CAAC;IAChF,IAAI,KAAK,CAAC,WAAW,KAAK,QAAQ;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,KAAK,CAAC,QAAQ,IAAI,IAAI,EAAE,EAAE,CAAC;IACpG,IAAI,KAAK,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC7B,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EACL,wGAAwG;gBACxG,gFAAgF;SACnF,CAAC;IACJ,CAAC;IACD,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,kBAAkB,CAAC;IAC/E,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,GAAG,GAAG,IAAI,EAAE,EAAE,CAAC;AAChD,CAAC;AAED,mGAAmG;AACnG,MAAM,UAAU,aAAa,CAAC,OAA2B,EAAE,OAAgB,EAAE,KAAgB;IAC3F,OAAO,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,QAAQ,CAAC,SAAS,OAAO,IAAI,KAAK,EAAE,CAAC,CAAC;AAChF,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Harness, HookEvent } from './hook.js';
|
|
2
|
+
interface HookDef {
|
|
3
|
+
readonly event: HookEvent;
|
|
4
|
+
/** The harness's own name for the event, which is also the key in its hooks object. */
|
|
5
|
+
readonly nativeEvent: string;
|
|
6
|
+
readonly matcher?: string;
|
|
7
|
+
readonly timeout: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* The hooks each harness gets. The Claude session-start group has no matcher on purpose:
|
|
11
|
+
* that matches every source, including `compact`. VS Code has no search hook because its
|
|
12
|
+
* docs say matchers are ignored (it would run on every tool call) and the search tool's
|
|
13
|
+
* name is undocumented.
|
|
14
|
+
*/
|
|
15
|
+
export declare const HOOK_DEFS: Readonly<Record<Harness, readonly HookDef[]>>;
|
|
16
|
+
export type Commands = Readonly<Partial<Record<HookEvent, string>>>;
|
|
17
|
+
export type PlanMode = {
|
|
18
|
+
readonly kind: 'install';
|
|
19
|
+
readonly commands: Commands;
|
|
20
|
+
} | {
|
|
21
|
+
readonly kind: 'remove';
|
|
22
|
+
};
|
|
23
|
+
export type ItemState = 'missing' | 'outdated' | 'current';
|
|
24
|
+
export interface PlanItem {
|
|
25
|
+
readonly label: string;
|
|
26
|
+
readonly state: ItemState;
|
|
27
|
+
}
|
|
28
|
+
export type PlanResult = {
|
|
29
|
+
readonly ok: true;
|
|
30
|
+
/** The whole file's next value, or null when the file should be deleted. */
|
|
31
|
+
readonly next: object | null;
|
|
32
|
+
/** False means the file must not be written at all. */
|
|
33
|
+
readonly changed: boolean;
|
|
34
|
+
/** Install mode: the state of each hook found. */
|
|
35
|
+
readonly items: readonly PlanItem[];
|
|
36
|
+
/** Remove mode: how many of mast's entries were taken out. */
|
|
37
|
+
readonly removedCount: number;
|
|
38
|
+
} | {
|
|
39
|
+
readonly ok: false;
|
|
40
|
+
readonly problem: string;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Claude Code: `hooks.<Event>` is a list of groups, each `{matcher?, hooks: [handler]}`.
|
|
44
|
+
* Within a group only mast's handler is touched; a group mast empties is removed, a group
|
|
45
|
+
* with other handlers keeps them.
|
|
46
|
+
*/
|
|
47
|
+
export declare function planClaude(existing: unknown, mode: PlanMode): PlanResult;
|
|
48
|
+
export declare const planCursor: (existing: unknown, mode: PlanMode) => PlanResult;
|
|
49
|
+
export declare const planVscode: (existing: unknown, mode: PlanMode) => PlanResult;
|
|
50
|
+
export declare function planFor(harness: Harness, existing: unknown, mode: PlanMode): PlanResult;
|
|
51
|
+
export {};
|
|
52
|
+
//# sourceMappingURL=setup-plan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup-plan.d.ts","sourceRoot":"","sources":["../../src/cli/setup-plan.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAOpD,UAAU,OAAO;IACf,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,uFAAuF;IACvF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;GAKG;AACH,eAAO,MAAM,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,OAAO,EAAE,SAAS,OAAO,EAAE,CAAC,CAUnE,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;AACpE,MAAM,MAAM,QAAQ,GAChB;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,GACzD;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC;AAEhC,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;AAC3D,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;CAC3B;AAED,MAAM,MAAM,UAAU,GAClB;IACE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,4EAA4E;IAC5E,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,uDAAuD;IACvD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,kDAAkD;IAClD,QAAQ,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAC;IACpC,8DAA8D;IAC9D,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B,GACD;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AA2CrD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,GAAG,UAAU,CA6ExE;AA2ED,eAAO,MAAM,UAAU,GAAI,UAAU,OAAO,EAAE,MAAM,QAAQ,KAAG,UAAgD,CAAC;AAChH,eAAO,MAAM,UAAU,GAAI,UAAU,OAAO,EAAE,MAAM,QAAQ,KAAG,UAAgD,CAAC;AAEhH,wBAAgB,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,GAAG,UAAU,CAGvF"}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { isMastCommand } from './setup-command.js';
|
|
3
|
+
/** Seconds, in all three harnesses. Session start builds the primer; search must stay cheap. */
|
|
4
|
+
const SESSION_START_TIMEOUT = 30;
|
|
5
|
+
const SEARCH_TIMEOUT = 5;
|
|
6
|
+
/**
|
|
7
|
+
* The hooks each harness gets. The Claude session-start group has no matcher on purpose:
|
|
8
|
+
* that matches every source, including `compact`. VS Code has no search hook because its
|
|
9
|
+
* docs say matchers are ignored (it would run on every tool call) and the search tool's
|
|
10
|
+
* name is undocumented.
|
|
11
|
+
*/
|
|
12
|
+
export const HOOK_DEFS = {
|
|
13
|
+
claude: [
|
|
14
|
+
{ event: 'session-start', nativeEvent: 'SessionStart', timeout: SESSION_START_TIMEOUT },
|
|
15
|
+
{ event: 'search', nativeEvent: 'PreToolUse', matcher: 'Grep|Glob', timeout: SEARCH_TIMEOUT },
|
|
16
|
+
],
|
|
17
|
+
cursor: [
|
|
18
|
+
{ event: 'session-start', nativeEvent: 'sessionStart', timeout: SESSION_START_TIMEOUT },
|
|
19
|
+
{ event: 'search', nativeEvent: 'postToolUse', matcher: 'Grep', timeout: SEARCH_TIMEOUT },
|
|
20
|
+
],
|
|
21
|
+
vscode: [{ event: 'session-start', nativeEvent: 'SessionStart', timeout: SESSION_START_TIMEOUT }],
|
|
22
|
+
};
|
|
23
|
+
// Zod is used to validate, not to rebuild: a parsed loose object puts its known keys
|
|
24
|
+
// first, which would reorder a user's file. `passThrough` validates and hands back the
|
|
25
|
+
// original value, so key order survives and only mast's entries are edited.
|
|
26
|
+
const rootShape = z.looseObject({ hooks: z.looseObject({}).optional() });
|
|
27
|
+
const handlerShape = z.looseObject({ command: z.string().optional() });
|
|
28
|
+
const groupShape = z.looseObject({ matcher: z.string().optional(), hooks: z.array(handlerShape) });
|
|
29
|
+
const flatEntryShape = z.looseObject({ command: z.string().optional() });
|
|
30
|
+
function passThrough(schema) {
|
|
31
|
+
return z.custom((value) => schema.safeParse(value).success);
|
|
32
|
+
}
|
|
33
|
+
function readTyped(schema, value, where) {
|
|
34
|
+
const result = schema.safeParse(value);
|
|
35
|
+
if (!result.success) {
|
|
36
|
+
const found = result.error.issues
|
|
37
|
+
.slice(0, 3)
|
|
38
|
+
.map((issue) => `${[where, ...issue.path.map(String)].join('.')}: ${issue.message}`);
|
|
39
|
+
return { ok: false, problem: `unexpected structure (${found.join('; ')})` };
|
|
40
|
+
}
|
|
41
|
+
return { ok: true, data: structuredClone(passThrough(schema).parse(value)) };
|
|
42
|
+
}
|
|
43
|
+
function readRoot(existing) {
|
|
44
|
+
return existing === null ? { ok: true, data: {} } : readTyped(rootShape, existing, 'file');
|
|
45
|
+
}
|
|
46
|
+
const fail = (problem) => ({ ok: false, problem });
|
|
47
|
+
function hooksOf(root) {
|
|
48
|
+
const hooks = root.hooks ?? {};
|
|
49
|
+
root.hooks = hooks;
|
|
50
|
+
return hooks;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Claude Code: `hooks.<Event>` is a list of groups, each `{matcher?, hooks: [handler]}`.
|
|
54
|
+
* Within a group only mast's handler is touched; a group mast empties is removed, a group
|
|
55
|
+
* with other handlers keeps them.
|
|
56
|
+
*/
|
|
57
|
+
export function planClaude(existing, mode) {
|
|
58
|
+
const rootRead = readRoot(existing);
|
|
59
|
+
if (!rootRead.ok)
|
|
60
|
+
return fail(rootRead.problem);
|
|
61
|
+
const root = rootRead.data;
|
|
62
|
+
const items = [];
|
|
63
|
+
let removedCount = 0;
|
|
64
|
+
let changed = false;
|
|
65
|
+
for (const def of HOOK_DEFS.claude) {
|
|
66
|
+
const rawGroups = root.hooks?.[def.nativeEvent];
|
|
67
|
+
const read = rawGroups === undefined ? null : readTyped(z.array(groupShape), rawGroups, `hooks.${def.nativeEvent}`);
|
|
68
|
+
if (read !== null && !read.ok)
|
|
69
|
+
return fail(read.problem);
|
|
70
|
+
let groups = read === null ? [] : read.data;
|
|
71
|
+
const isMast = (command) => isMastCommand(command, 'claude', def.event);
|
|
72
|
+
const touched = new Set();
|
|
73
|
+
if (mode.kind === 'remove') {
|
|
74
|
+
for (const group of groups) {
|
|
75
|
+
const kept = group.hooks.filter((h) => !isMast(h.command));
|
|
76
|
+
if (kept.length === group.hooks.length)
|
|
77
|
+
continue;
|
|
78
|
+
removedCount += group.hooks.length - kept.length;
|
|
79
|
+
group.hooks = kept;
|
|
80
|
+
touched.add(group);
|
|
81
|
+
}
|
|
82
|
+
if (touched.size === 0)
|
|
83
|
+
continue;
|
|
84
|
+
groups = groups.filter((g) => !touched.has(g) || g.hooks.length > 0);
|
|
85
|
+
changed = true;
|
|
86
|
+
if (groups.length === 0)
|
|
87
|
+
delete hooksOf(root)[def.nativeEvent];
|
|
88
|
+
else
|
|
89
|
+
hooksOf(root)[def.nativeEvent] = groups;
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
const command = mode.commands[def.event];
|
|
93
|
+
if (command === undefined)
|
|
94
|
+
continue;
|
|
95
|
+
const handler = { type: 'command', command, timeout: def.timeout };
|
|
96
|
+
const found = groups.flatMap((group) => group.hooks.filter((h) => isMast(h.command)).map((h) => ({ group, h })));
|
|
97
|
+
const first = found[0];
|
|
98
|
+
const duplicates = found.slice(1);
|
|
99
|
+
const fresh = () => ({ ...(def.matcher === undefined ? {} : { matcher: def.matcher }), hooks: [{ ...handler }] });
|
|
100
|
+
let state = 'current';
|
|
101
|
+
if (first === undefined) {
|
|
102
|
+
groups.push(fresh());
|
|
103
|
+
state = 'missing';
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
const sameHandler = first.h['type'] === handler.type && first.h.command === command && first.h['timeout'] === handler.timeout;
|
|
107
|
+
if (!sameHandler || first.group.matcher !== def.matcher) {
|
|
108
|
+
state = 'outdated';
|
|
109
|
+
const ownsGroup = first.group.hooks.every((h) => isMast(h.command));
|
|
110
|
+
if (ownsGroup || first.group.matcher === def.matcher) {
|
|
111
|
+
Object.assign(first.h, handler);
|
|
112
|
+
if (ownsGroup) {
|
|
113
|
+
if (def.matcher === undefined)
|
|
114
|
+
delete first.group.matcher;
|
|
115
|
+
else
|
|
116
|
+
first.group.matcher = def.matcher;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
// The group's matcher also scopes someone else's handler, so it cannot be edited.
|
|
121
|
+
first.group.hooks = first.group.hooks.filter((h) => h !== first.h);
|
|
122
|
+
touched.add(first.group);
|
|
123
|
+
groups.push(fresh());
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
for (const dup of duplicates) {
|
|
128
|
+
dup.group.hooks = dup.group.hooks.filter((h) => h !== dup.h);
|
|
129
|
+
touched.add(dup.group);
|
|
130
|
+
state = 'outdated';
|
|
131
|
+
}
|
|
132
|
+
groups = groups.filter((g) => !touched.has(g) || g.hooks.length > 0);
|
|
133
|
+
items.push({ label: def.nativeEvent, state });
|
|
134
|
+
if (state !== 'current') {
|
|
135
|
+
changed = true;
|
|
136
|
+
hooksOf(root)[def.nativeEvent] = groups;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return { ok: true, next: root, changed, items, removedCount };
|
|
140
|
+
}
|
|
141
|
+
/** Cursor (`hooks.json`) and VS Code (`mast.json`): `hooks.<event>` is a flat list of entries. */
|
|
142
|
+
function planFlat(harness, existing, mode) {
|
|
143
|
+
const rootRead = readRoot(existing);
|
|
144
|
+
if (!rootRead.ok)
|
|
145
|
+
return fail(rootRead.problem);
|
|
146
|
+
const root = rootRead.data;
|
|
147
|
+
const items = [];
|
|
148
|
+
let removedCount = 0;
|
|
149
|
+
let changed = false;
|
|
150
|
+
if (mode.kind === 'install' && harness === 'cursor' && !('version' in root)) {
|
|
151
|
+
root['version'] = 1;
|
|
152
|
+
items.push({ label: 'version', state: 'missing' });
|
|
153
|
+
changed = true;
|
|
154
|
+
}
|
|
155
|
+
for (const def of HOOK_DEFS[harness]) {
|
|
156
|
+
const rawEntries = root.hooks?.[def.nativeEvent];
|
|
157
|
+
const read = rawEntries === undefined ? null : readTyped(z.array(flatEntryShape), rawEntries, `hooks.${def.nativeEvent}`);
|
|
158
|
+
if (read !== null && !read.ok)
|
|
159
|
+
return fail(read.problem);
|
|
160
|
+
const entries = read === null ? [] : read.data;
|
|
161
|
+
const isMast = (e) => isMastCommand(e.command, harness, def.event);
|
|
162
|
+
if (mode.kind === 'remove') {
|
|
163
|
+
const kept = entries.filter((e) => !isMast(e));
|
|
164
|
+
if (kept.length === entries.length)
|
|
165
|
+
continue;
|
|
166
|
+
removedCount += entries.length - kept.length;
|
|
167
|
+
changed = true;
|
|
168
|
+
if (kept.length === 0)
|
|
169
|
+
delete hooksOf(root)[def.nativeEvent];
|
|
170
|
+
else
|
|
171
|
+
hooksOf(root)[def.nativeEvent] = kept;
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
const command = mode.commands[def.event];
|
|
175
|
+
if (command === undefined)
|
|
176
|
+
continue;
|
|
177
|
+
const wanted = harness === 'cursor'
|
|
178
|
+
? { command, type: 'command', ...(def.matcher === undefined ? {} : { matcher: def.matcher }), timeout: def.timeout }
|
|
179
|
+
: { type: 'command', command, timeout: def.timeout };
|
|
180
|
+
const found = entries.filter(isMast);
|
|
181
|
+
const first = found[0];
|
|
182
|
+
let state = 'current';
|
|
183
|
+
let next = entries;
|
|
184
|
+
if (first === undefined) {
|
|
185
|
+
next = [...entries, wanted];
|
|
186
|
+
state = 'missing';
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
const same = Object.entries(wanted).every(([key, value]) => first[key] === value) && 'matcher' in first === 'matcher' in wanted;
|
|
190
|
+
if (!same) {
|
|
191
|
+
Object.assign(first, wanted);
|
|
192
|
+
if (!('matcher' in wanted))
|
|
193
|
+
delete first['matcher'];
|
|
194
|
+
state = 'outdated';
|
|
195
|
+
}
|
|
196
|
+
if (found.length > 1) {
|
|
197
|
+
next = entries.filter((e) => e === first || !isMast(e));
|
|
198
|
+
state = 'outdated';
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
items.push({ label: def.nativeEvent, state });
|
|
202
|
+
if (state !== 'current') {
|
|
203
|
+
changed = true;
|
|
204
|
+
hooksOf(root)[def.nativeEvent] = next;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
// mast.json belongs to mast outright: once its last entry goes, so does the file.
|
|
208
|
+
const hooksLeft = root.hooks === undefined ? 0 : Object.keys(root.hooks).length;
|
|
209
|
+
if (harness === 'vscode' && removedCount > 0 && Object.keys(root).length === 1 && hooksLeft === 0) {
|
|
210
|
+
return { ok: true, next: null, changed, items, removedCount };
|
|
211
|
+
}
|
|
212
|
+
return { ok: true, next: root, changed, items, removedCount };
|
|
213
|
+
}
|
|
214
|
+
export const planCursor = (existing, mode) => planFlat('cursor', existing, mode);
|
|
215
|
+
export const planVscode = (existing, mode) => planFlat('vscode', existing, mode);
|
|
216
|
+
export function planFor(harness, existing, mode) {
|
|
217
|
+
if (harness === 'claude')
|
|
218
|
+
return planClaude(existing, mode);
|
|
219
|
+
return harness === 'cursor' ? planCursor(existing, mode) : planVscode(existing, mode);
|
|
220
|
+
}
|
|
221
|
+
//# sourceMappingURL=setup-plan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup-plan.js","sourceRoot":"","sources":["../../src/cli/setup-plan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,gGAAgG;AAChG,MAAM,qBAAqB,GAAG,EAAE,CAAC;AACjC,MAAM,cAAc,GAAG,CAAC,CAAC;AAUzB;;;;;GAKG;AACH,MAAM,CAAC,MAAM,SAAS,GAAkD;IACtE,MAAM,EAAE;QACN,EAAE,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,cAAc,EAAE,OAAO,EAAE,qBAAqB,EAAE;QACvF,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,cAAc,EAAE;KAC9F;IACD,MAAM,EAAE;QACN,EAAE,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,cAAc,EAAE,OAAO,EAAE,qBAAqB,EAAE;QACvF,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE;KAC1F;IACD,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,cAAc,EAAE,OAAO,EAAE,qBAAqB,EAAE,CAAC;CAClG,CAAC;AA2BF,qFAAqF;AACrF,uFAAuF;AACvF,4EAA4E;AAC5E,MAAM,SAAS,GAAG,CAAC,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;AACzE,MAAM,YAAY,GAAG,CAAC,CAAC,WAAW,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;AACvE,MAAM,UAAU,GAAG,CAAC,CAAC,WAAW,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;AACnG,MAAM,cAAc,GAAG,CAAC,CAAC,WAAW,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;AAMzE,SAAS,WAAW,CAAsB,MAAS;IACjD,OAAO,CAAC,CAAC,MAAM,CAAa,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC;AAC1E,CAAC;AAID,SAAS,SAAS,CAAsB,MAAS,EAAE,KAAc,EAAE,KAAa;IAC9E,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACvC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM;aAC9B,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;aACX,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACvF,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,yBAAyB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;IAC9E,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,eAAe,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;AAC/E,CAAC;AAED,SAAS,QAAQ,CAAC,QAAiB;IACjC,OAAO,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;AAC7F,CAAC;AAED,MAAM,IAAI,GAAG,CAAC,OAAe,EAAc,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;AAEvE,SAAS,OAAO,CAAC,IAAU;IACzB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;IAC/B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACnB,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,QAAiB,EAAE,IAAc;IAC1D,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACpC,IAAI,CAAC,QAAQ,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;IAC3B,MAAM,KAAK,GAAe,EAAE,CAAC;IAC7B,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,KAAK,MAAM,GAAG,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC;QACnC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAChD,MAAM,IAAI,GAAG,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,SAAS,EAAE,SAAS,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;QACpH,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzD,IAAI,MAAM,GAAY,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QACrD,MAAM,MAAM,GAAG,CAAC,OAA2B,EAAW,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;QACrG,MAAM,OAAO,GAAG,IAAI,GAAG,EAAS,CAAC;QAEjC,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC3B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;gBAC3D,IAAI,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC,KAAK,CAAC,MAAM;oBAAE,SAAS;gBACjD,YAAY,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;gBACjD,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;gBACnB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACrB,CAAC;YACD,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC;gBAAE,SAAS;YACjC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACrE,OAAO,GAAG,IAAI,CAAC;YACf,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;;gBAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,MAAM,CAAC;YAC7C,SAAS;QACX,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACzC,IAAI,OAAO,KAAK,SAAS;YAAE,SAAS;QACpC,MAAM,OAAO,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;QACnE,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACjH,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACvB,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAClC,MAAM,KAAK,GAAG,GAAU,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;QAEzH,IAAI,KAAK,GAAc,SAAS,CAAC;QACjC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;YACrB,KAAK,GAAG,SAAS,CAAC;QACpB,CAAC;aAAM,CAAC;YACN,MAAM,WAAW,GACf,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,OAAO,CAAC,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,IAAI,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC;YAC5G,IAAI,CAAC,WAAW,IAAI,KAAK,CAAC,KAAK,CAAC,OAAO,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC;gBACxD,KAAK,GAAG,UAAU,CAAC;gBACnB,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;gBACpE,IAAI,SAAS,IAAI,KAAK,CAAC,KAAK,CAAC,OAAO,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC;oBACrD,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;oBAChC,IAAI,SAAS,EAAE,CAAC;wBACd,IAAI,GAAG,CAAC,OAAO,KAAK,SAAS;4BAAE,OAAO,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC;;4BACrD,KAAK,CAAC,KAAK,CAAC,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;oBACzC,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,kFAAkF;oBAClF,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC;oBACnE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;oBACzB,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;gBACvB,CAAC;YACH,CAAC;QACH,CAAC;QACD,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;YAC7B,GAAG,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;YAC7D,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACvB,KAAK,GAAG,UAAU,CAAC;QACrB,CAAC;QACD,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACrE,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC;QAC9C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,GAAG,IAAI,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,MAAM,CAAC;QAC1C,CAAC;IACH,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC;AAChE,CAAC;AAED,kGAAkG;AAClG,SAAS,QAAQ,CAAC,OAA4B,EAAE,QAAiB,EAAE,IAAc;IAC/E,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACpC,IAAI,CAAC,QAAQ,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;IAC3B,MAAM,KAAK,GAAe,EAAE,CAAC;IAC7B,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,KAAK,QAAQ,IAAI,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC,EAAE,CAAC;QAC5E,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACpB,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QACnD,OAAO,GAAG,IAAI,CAAC;IACjB,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;QACrC,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACjD,MAAM,IAAI,GAAG,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,UAAU,EAAE,SAAS,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;QAC1H,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzD,MAAM,OAAO,GAAgB,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QAC5D,MAAM,MAAM,GAAG,CAAC,CAAY,EAAW,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;QAEvF,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC3B,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YAC/C,IAAI,IAAI,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM;gBAAE,SAAS;YAC7C,YAAY,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;YAC7C,OAAO,GAAG,IAAI,CAAC;YACf,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;;gBACxD,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC;YAC3C,SAAS;QACX,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACzC,IAAI,OAAO,KAAK,SAAS;YAAE,SAAS;QACpC,MAAM,MAAM,GACV,OAAO,KAAK,QAAQ;YAClB,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,CAAC,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE;YACpH,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;QACzD,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACrC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACvB,IAAI,KAAK,GAAc,SAAS,CAAC;QACjC,IAAI,IAAI,GAAG,OAAO,CAAC;QACnB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,IAAI,GAAG,CAAC,GAAG,OAAO,EAAE,MAAM,CAAC,CAAC;YAC5B,KAAK,GAAG,SAAS,CAAC;QACpB,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,GACR,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,SAAS,IAAI,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC;YACrH,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;gBAC7B,IAAI,CAAC,CAAC,SAAS,IAAI,MAAM,CAAC;oBAAE,OAAO,KAAK,CAAC,SAAS,CAAC,CAAC;gBACpD,KAAK,GAAG,UAAU,CAAC;YACrB,CAAC;YACD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACrB,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;gBACxD,KAAK,GAAG,UAAU,CAAC;YACrB,CAAC;QACH,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC;QAC9C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,GAAG,IAAI,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC;QACxC,CAAC;IACH,CAAC;IAED,kFAAkF;IAClF,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;IAChF,IAAI,OAAO,KAAK,QAAQ,IAAI,YAAY,GAAG,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,IAAI,SAAS,KAAK,CAAC,EAAE,CAAC;QAClG,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC;IAChE,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC;AAChE,CAAC;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,QAAiB,EAAE,IAAc,EAAc,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;AAChH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,QAAiB,EAAE,IAAc,EAAc,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;AAEhH,MAAM,UAAU,OAAO,CAAC,OAAgB,EAAE,QAAiB,EAAE,IAAc;IACzE,IAAI,OAAO,KAAK,QAAQ;QAAE,OAAO,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC5D,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;AACxF,CAAC"}
|