@cybedefend/vibedefend 1.1.2 → 1.2.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.
@@ -17,6 +17,7 @@
17
17
  import { copyFileSync, existsSync, rmSync } from 'node:fs';
18
18
  import { dirname, join } from 'node:path';
19
19
  import { fileURLToPath } from 'node:url';
20
+ import { detectInstallMode, resolveScriptPath, GLOBAL_MODES, } from '../self-update.js';
20
21
  import { ensureDirFor, home, log, writeJson } from '../utils.js';
21
22
  /** Top-level directory we own. */
22
23
  export const VIBEDEFEND_DIR = home('.cybedefend');
@@ -48,6 +49,23 @@ function locateBundledRunner() {
48
49
  }
49
50
  return null;
50
51
  }
52
+ /**
53
+ * Resolve the bundled `shim.js` shipped alongside `hook-runner.js`.
54
+ * Same search strategy as `locateBundledRunner`. Returns null if absent.
55
+ */
56
+ function locateBundledShim() {
57
+ const here = dirname(fileURLToPath(import.meta.url));
58
+ const candidates = [
59
+ join(here, 'shim.js'),
60
+ join(here, '..', 'dist', 'shim.js'),
61
+ join(here, '..', '..', 'dist', 'shim.js'),
62
+ ];
63
+ for (const c of candidates) {
64
+ if (existsSync(c))
65
+ return c;
66
+ }
67
+ return null;
68
+ }
51
69
  /**
52
70
  * Drop any legacy `~/.cybedefend/hooks/` directory (V1 bash scripts).
53
71
  * Idempotent — silent no-op if the directory doesn't exist.
@@ -68,21 +86,36 @@ function removeLegacyHooks() {
68
86
  *
69
87
  * Steps:
70
88
  * 1. Sweep legacy `~/.cybedefend/hooks/` if present.
71
- * 2. Copy `dist/hook-runner.js` → `~/.cybedefend/hook-runner.js`.
89
+ * 2. For global installs: copy `dist/shim.js` → `~/.cybedefend/hook-runner.js`
90
+ * and stamp `runnerSource` in the config so updates are live immediately.
91
+ * For non-global installs: copy the full runner (legacy behaviour) and
92
+ * force `autoUpdate: false`.
72
93
  * 3. Write `~/.cybedefend/runtime-config.json` with the user's
73
94
  * region + hook settings.
74
95
  *
75
96
  * Returns the destination paths so the caller can `log.hint(...)` them.
76
97
  */
77
- export function installHookRuntime(opts) {
98
+ export function installHookRuntime(opts, deps = {}) {
78
99
  removeLegacyHooks();
79
- const source = locateBundledRunner();
80
- if (source === null) {
100
+ const installMode = deps.installMode ?? detectInstallMode(resolveScriptPath());
101
+ const locateRunner = deps.locateRunner ?? locateBundledRunner;
102
+ const locateShim = deps.locateShim ?? locateBundledShim;
103
+ const runnerSource = locateRunner();
104
+ if (runnerSource === null) {
81
105
  throw new Error('Could not locate the bundled hook-runner.js. Did `pnpm run build` finish? ' +
82
106
  'Expected to find it under <package>/dist/.');
83
107
  }
84
- ensureDirFor(HOOK_RUNNER_PATH);
85
- copyFileSync(source, HOOK_RUNNER_PATH);
108
+ const dir = deps.cybeDir ?? VIBEDEFEND_DIR;
109
+ const hookRunnerDest = join(dir, 'hook-runner.js');
110
+ const configDest = join(dir, 'runtime-config.json');
111
+ // Global installs get the stable shim + a stamped runnerSource so a later
112
+ // `npm i -g` is immediately live with no recopy. Non-global installs have
113
+ // no stable package path, so we keep the legacy full-copy behaviour and
114
+ // disable background auto-update.
115
+ const shimPath = locateShim();
116
+ const useShim = GLOBAL_MODES.has(installMode) && shimPath !== null;
117
+ ensureDirFor(hookRunnerDest);
118
+ copyFileSync(useShim ? shimPath : runnerSource, hookRunnerDest);
86
119
  const runtimeConfig = {
87
120
  region: {
88
121
  id: opts.region.id,
@@ -95,11 +128,23 @@ export function installHookRuntime(opts) {
95
128
  enableSessionReview: opts.hooks.enableSessionReview,
96
129
  reviewThreshold: opts.hooks.reviewThreshold,
97
130
  autoProposeMode: opts.hooks.autoProposeMode,
131
+ autoUpdate: useShim ? opts.hooks.autoUpdate : false,
98
132
  },
99
133
  installedVersion: opts.installedVersion,
134
+ ...(useShim ? { runnerSource } : {}),
100
135
  };
101
- writeJson(RUNTIME_CONFIG_PATH, runtimeConfig);
102
- return { runnerPath: HOOK_RUNNER_PATH, configPath: RUNTIME_CONFIG_PATH };
136
+ writeJson(configDest, runtimeConfig);
137
+ return { runnerPath: hookRunnerDest, configPath: configDest };
138
+ }
139
+ /**
140
+ * Quote a path for embedding in a hook `command` string, but ONLY when it
141
+ * contains whitespace. Both POSIX `sh` and Windows `cmd.exe` (which run the
142
+ * hook command) accept a double-quoted path, so a home directory with a
143
+ * space (e.g. `C:\\Users\\First Last\\...`) no longer splits mid-argument.
144
+ * Space-free paths are left untouched so the common command is unchanged.
145
+ */
146
+ export function quoteCommandPath(p) {
147
+ return /\s/.test(p) ? `"${p}"` : p;
103
148
  }
104
149
  /**
105
150
  * Compose the `command` field for a settings.json hook entry, targeting
@@ -107,7 +152,7 @@ export function installHookRuntime(opts) {
107
152
  * touching the filesystem.
108
153
  */
109
154
  export function hookCommand(subcommand) {
110
- return `node ${HOOK_RUNNER_PATH} ${subcommand}`;
155
+ return `node ${quoteCommandPath(HOOK_RUNNER_PATH)} ${subcommand}`;
111
156
  }
112
157
  /**
113
158
  * Marker used by every adapter's `dropOurs` to identify legacy AND new
@@ -1 +1 @@
1
- {"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/hooks/install.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/hooks/install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC3D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAIzC,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,GAEb,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGjE,kCAAkC;AAClC,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC;AAElD,0EAA0E;AAC1E,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC;AAEtE,iEAAiE;AACjE,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,CACrC,aAAa,EACb,qBAAqB,CACtB,CAAC;AAEF,kEAAkE;AAClE,MAAM,gBAAgB,GAAG,IAAI,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;AAEtD;;;;;;;GAOG;AACH,SAAS,mBAAmB;IAC1B,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACrD,iEAAiE;IACjE,MAAM,UAAU,GAAG;QACjB,IAAI,CAAC,IAAI,EAAE,gBAAgB,CAAC;QAC5B,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,gBAAgB,CAAC;QAC1C,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,gBAAgB,CAAC;KACjD,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,UAAU,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,SAAS,iBAAiB;IACxB,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACrD,MAAM,UAAU,GAAG;QACjB,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC;QACrB,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC;QACnC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC;KAC1C,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,UAAU,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,SAAS,iBAAiB;IACxB,IAAI,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACjC,IAAI,CAAC;YACH,MAAM,CAAC,gBAAgB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAC3D,GAAG,CAAC,IAAI,CAAC,kCAAkC,gBAAgB,EAAE,CAAC,CAAC;QACjE,CAAC;QAAC,MAAM,CAAC;YACP,kCAAkC;QACpC,CAAC;IACH,CAAC;AACH,CAAC;AAaD;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,kBAAkB,CAChC,IAIC,EACD,OAA+B,EAAE;IAEjC,iBAAiB,EAAE,CAAC;IAEpB,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,iBAAiB,CAAC,iBAAiB,EAAE,CAAC,CAAC;IAC/E,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,mBAAmB,CAAC;IAC9D,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,iBAAiB,CAAC;IAExD,MAAM,YAAY,GAAG,YAAY,EAAE,CAAC;IACpC,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CACb,4EAA4E;YAC1E,4CAA4C,CAC/C,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,IAAI,cAAc,CAAC;IAC3C,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;IACnD,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,qBAAqB,CAAC,CAAC;IAEpD,0EAA0E;IAC1E,0EAA0E;IAC1E,wEAAwE;IACxE,kCAAkC;IAClC,MAAM,QAAQ,GAAG,UAAU,EAAE,CAAC;IAC9B,MAAM,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,QAAQ,KAAK,IAAI,CAAC;IAEnE,YAAY,CAAC,cAAc,CAAC,CAAC;IAC7B,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,QAAS,CAAC,CAAC,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;IAEjE,MAAM,aAAa,GAAkB;QACnC,MAAM,EAAE;YACN,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE;YAClB,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK;YACxB,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO;YAC5B,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM;YAC1B,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO;SAC7B;QACD,KAAK,EAAE;YACL,mBAAmB,EAAE,IAAI,CAAC,KAAK,CAAC,mBAAmB;YACnD,eAAe,EAAE,IAAI,CAAC,KAAK,CAAC,eAAe;YAC3C,eAAe,EAAE,IAAI,CAAC,KAAK,CAAC,eAAe;YAC3C,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK;SACpD;QACD,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;QACvC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACrC,CAAC;IACF,SAAS,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;IAErC,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC;AAChE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,CAAS;IACxC,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACrC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW,CACzB,UAMiB;IAEjB,OAAO,QAAQ,gBAAgB,CAAC,gBAAgB,CAAC,IAAI,UAAU,EAAE,CAAC;AACpE,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,cAAc,CAAC;AAErD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,mBAAmB,GAAsB;IAC7C,yBAAyB;CAC1B,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,UAAU,4BAA4B,CAAC,OAAe;IAC1D,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACtE,IAAI,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1D,KAAK,MAAM,MAAM,IAAI,mBAAmB,EAAE,CAAC;QACzC,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,OAAO,IAAI,CAAC;IAC5C,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,196 @@
1
+ /**
2
+ * Throttled, opt-out background self-update check. Runs once per session
3
+ * from the SessionStart hook. RETURNS a one-line notice to fold into the
4
+ * bootstrap body (or null) — it never writes to stdout itself (the caller
5
+ * emits once, so Codex's JSON envelope stays intact). Side effects: writes
6
+ * the throttle stamp and, when an update is due + enabled for a global
7
+ * install, spawns a DETACHED wrapper that runs the package-manager update
8
+ * and records the outcome to last-update.log.
9
+ *
10
+ * Source of truth: the npm registry (`/<pkg>/latest`). No gateway call.
11
+ */
12
+ import { spawn } from 'node:child_process';
13
+ import { existsSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
14
+ import { homedir } from 'node:os';
15
+ import { join } from 'node:path';
16
+ import { ensureDirFor } from '../../utils.js';
17
+ import { isNewer } from './semver.js';
18
+ import { detectInstallMode, resolveScriptPath, GLOBAL_MODES, } from '../../self-update.js';
19
+ const PACKAGE_NAME = '@cybedefend/vibedefend';
20
+ const REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`;
21
+ const THROTTLE_MS = 24 * 60 * 60 * 1000;
22
+ const FETCH_TIMEOUT_MS = 3000;
23
+ export async function selfUpdateCheck(deps) {
24
+ const now = deps.now ?? (() => Date.now());
25
+ const dir = deps.cybeDir ?? join(process.env.CYBEDEFEND_HOME ?? homedir(), '.cybedefend');
26
+ const throttlePath = join(dir, 'update-check.json');
27
+ const logPath = join(dir, 'last-update.log');
28
+ // Derive the install mode from the stable global runner path
29
+ // (`runnerSource`) when available — NOT from `resolveScriptPath()`, which at
30
+ // runtime returns the shim (`~/.cybedefend/hook-runner.js` → `'unknown'`,
31
+ // never a global mode, so the background update would never spawn).
32
+ const installMode = deps.installMode ??
33
+ (deps.runnerSource
34
+ ? detectInstallMode(deps.runnerSource)
35
+ : detectInstallMode(resolveScriptPath()));
36
+ // Read + consume last-update.log (a prior background update's outcome),
37
+ // regardless of throttle — surface a failure as soon as possible.
38
+ const priorFailure = takeUpdateLogNotice(logPath);
39
+ const throttle = readThrottle(throttlePath);
40
+ if (throttle && now() - throttle.lastCheckedAt < THROTTLE_MS) {
41
+ return priorFailure;
42
+ }
43
+ const fetchLatest = deps.fetchLatest ?? defaultFetchLatest;
44
+ const latest = await fetchLatest();
45
+ // Stamp the check time regardless of fetch outcome so a flaky registry
46
+ // doesn't make every session hammer npm.
47
+ writeThrottle(throttlePath, { lastCheckedAt: now() });
48
+ if (!latest || !isNewer(latest, deps.installedVersion)) {
49
+ return priorFailure;
50
+ }
51
+ const updateNotice = applyOrNotify(deps, installMode, latest, logPath);
52
+ // Surface BOTH signals when present: a prior failure (its log was already
53
+ // consumed on read) AND the new pending update. They're independent.
54
+ return [priorFailure, updateNotice].filter(Boolean).join('\n') || null;
55
+ }
56
+ function applyOrNotify(deps, installMode, latest, logPath) {
57
+ const from = deps.installedVersion;
58
+ if (!deps.autoUpdate || !GLOBAL_MODES.has(installMode)) {
59
+ return `\u{1F6E1}️ vibedefend ${from} → ${latest} available — run \`vibedefend update --self\` to upgrade.`;
60
+ }
61
+ const spawnUpdate = deps.spawnUpdate ?? defaultSpawnUpdate;
62
+ spawnUpdate({
63
+ mode: installMode,
64
+ spec: `${PACKAGE_NAME}@${latest}`,
65
+ logPath,
66
+ from,
67
+ to: latest,
68
+ });
69
+ return `\u{1F6E1}️ vibedefend: updating in background ${from} → ${latest} (active next session).`;
70
+ }
71
+ function readThrottle(path) {
72
+ try {
73
+ if (!existsSync(path))
74
+ return null;
75
+ const data = JSON.parse(readFileSync(path, 'utf8'));
76
+ if (typeof data.lastCheckedAt !== 'number')
77
+ return null;
78
+ return { lastCheckedAt: data.lastCheckedAt };
79
+ }
80
+ catch {
81
+ return null;
82
+ }
83
+ }
84
+ function writeThrottle(path, throttle) {
85
+ try {
86
+ ensureDirFor(path);
87
+ writeFileSync(path, JSON.stringify(throttle) + '\n');
88
+ }
89
+ catch {
90
+ /* best-effort */
91
+ }
92
+ }
93
+ /**
94
+ * Read and CONSUME last-update.log (the prior background update's outcome).
95
+ * The log is always deleted on read — a failure is surfaced once, a stale
96
+ * success (or garbage) is simply dropped so it can't accumulate or re-nag.
97
+ * Returns a one-line notice only when the prior update failed.
98
+ */
99
+ function takeUpdateLogNotice(logPath) {
100
+ try {
101
+ if (!existsSync(logPath))
102
+ return null;
103
+ let parsed = {};
104
+ try {
105
+ parsed = JSON.parse(readFileSync(logPath, 'utf8'));
106
+ }
107
+ catch {
108
+ parsed = {};
109
+ }
110
+ rmSync(logPath, { force: true }); // consume once, whatever the content
111
+ if (typeof parsed.exitCode === 'number' && parsed.exitCode !== 0) {
112
+ return `⚠ vibedefend: last auto-update to ${parsed.to ?? 'latest'} failed (exit ${parsed.exitCode}) — run \`vibedefend update --self\`.`;
113
+ }
114
+ return null;
115
+ }
116
+ catch {
117
+ return null;
118
+ }
119
+ }
120
+ async function defaultFetchLatest() {
121
+ try {
122
+ const res = await fetch(REGISTRY_URL, {
123
+ signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
124
+ });
125
+ if (!res.ok)
126
+ return null;
127
+ const body = (await res.json());
128
+ return typeof body.version === 'string' ? body.version : null;
129
+ }
130
+ catch {
131
+ return null;
132
+ }
133
+ }
134
+ /**
135
+ * Build the `node -e` wrapper script that runs the package-manager update and
136
+ * records the outcome (`{ from, to, exitCode, finishedAt }`) to last-update.log.
137
+ * Exported for tests. `shell: process.platform === 'win32'` so the
138
+ * `npm`/`pnpm`/`yarn` `.cmd` shims resolve on Windows; POSIX resolves the
139
+ * binaries directly (no shell layer). `node -e` runs as CommonJS, so `require`
140
+ * is available.
141
+ */
142
+ export function buildUpdateWrapperScript(args) {
143
+ return `
144
+ const { spawnSync } = require('node:child_process');
145
+ const { writeFileSync } = require('node:fs');
146
+ const r = spawnSync(${JSON.stringify(args.pm)}, ${JSON.stringify(args.pmArgs)}, {
147
+ stdio: 'ignore',
148
+ shell: process.platform === 'win32',
149
+ });
150
+ try {
151
+ writeFileSync(${JSON.stringify(args.logPath)}, JSON.stringify({
152
+ from: ${JSON.stringify(args.from)},
153
+ to: ${JSON.stringify(args.to)},
154
+ exitCode: r.status == null ? 1 : r.status,
155
+ finishedAt: Date.now(),
156
+ }) + "\\n");
157
+ } catch {}
158
+ `;
159
+ }
160
+ /**
161
+ * Spawn a DETACHED, unref'd wrapper that runs the package-manager update and
162
+ * records its outcome. `windowsHide` prevents a console window flashing on
163
+ * Windows.
164
+ */
165
+ function defaultSpawnUpdate(args) {
166
+ const { pm, pmArgs } = pmCommand(args.mode, args.spec);
167
+ const script = buildUpdateWrapperScript({
168
+ pm,
169
+ pmArgs,
170
+ logPath: args.logPath,
171
+ from: args.from,
172
+ to: args.to,
173
+ });
174
+ try {
175
+ const child = spawn(process.execPath, ['-e', script], {
176
+ detached: true,
177
+ stdio: 'ignore',
178
+ windowsHide: true,
179
+ });
180
+ child.unref();
181
+ }
182
+ catch {
183
+ /* best-effort — failure is invisible; the 24h retry covers it */
184
+ }
185
+ }
186
+ function pmCommand(mode, spec) {
187
+ switch (mode) {
188
+ case 'pnpm-global':
189
+ return { pm: 'pnpm', pmArgs: ['add', '-g', spec] };
190
+ case 'yarn-global':
191
+ return { pm: 'yarn', pmArgs: ['global', 'add', spec] };
192
+ default:
193
+ return { pm: 'npm', pmArgs: ['install', '-g', spec] };
194
+ }
195
+ }
196
+ //# sourceMappingURL=self-update-check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"self-update-check.js","sourceRoot":"","sources":["../../../src/hooks/runtime/self-update-check.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Minimal semver comparison for `x.y.z` version strings — no dependency,
3
+ * the CLI ships only what it needs. Tolerant: a leading `v` is stripped,
4
+ * prerelease/build suffixes are ignored, and any missing or non-numeric
5
+ * segment counts as 0, so a malformed input never throws (it simply
6
+ * compares as a low version).
7
+ */
8
+ export function parseVersion(input) {
9
+ const cleaned = input.trim().replace(/^v/i, '');
10
+ const core = cleaned.split('-')[0].split('+')[0];
11
+ const parts = core.split('.');
12
+ const seg = (i) => {
13
+ const v = Number.parseInt(parts[i] ?? '0', 10);
14
+ return Number.isFinite(v) && v >= 0 ? v : 0;
15
+ };
16
+ return [seg(0), seg(1), seg(2)];
17
+ }
18
+ /** -1 if a<b, 0 if equal, 1 if a>b — by major, then minor, then patch. */
19
+ export function compareVersions(a, b) {
20
+ const pa = parseVersion(a);
21
+ const pb = parseVersion(b);
22
+ for (let i = 0; i < 3; i++) {
23
+ if (pa[i] < pb[i])
24
+ return -1;
25
+ if (pa[i] > pb[i])
26
+ return 1;
27
+ }
28
+ return 0;
29
+ }
30
+ /** True iff `latest` is strictly newer than `current`. */
31
+ export function isNewer(latest, current) {
32
+ return compareVersions(latest, current) > 0;
33
+ }
34
+ //# sourceMappingURL=semver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semver.js","sourceRoot":"","sources":["../../../src/hooks/runtime/semver.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,GAAG,GAAG,CAAC,CAAS,EAAU,EAAE;QAChC,MAAM,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;QAC/C,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9C,CAAC,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAClC,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,eAAe,CAAC,CAAS,EAAE,CAAS;IAClD,MAAM,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAC,CAAC;QAC7B,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,OAAO,CAAC,MAAc,EAAE,OAAe;IACrD,OAAO,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;AAC9C,CAAC"}
@@ -99,61 +99,143 @@ function defaultReadTranscript(path) {
99
99
  return null;
100
100
  }
101
101
  }
102
+ /** Field names the various agents use to carry a tool name. */
103
+ function toolNameOf(obj) {
104
+ return ((typeof obj.name === 'string' && obj.name) ||
105
+ (typeof obj.tool_name === 'string' && obj.tool_name) ||
106
+ (typeof obj.toolName === 'string' && obj.toolName) ||
107
+ '');
108
+ }
109
+ /**
110
+ * Recursively count objects whose tool-name field is in COUNTED_TOOLS.
111
+ *
112
+ * Handles every transcript shape we've seen:
113
+ * - flat: `{ tool_uses: [{ name: 'Edit' }] }` (synthetic / some agents)
114
+ * - nested: `{ message: { content: [{ type: 'tool_use', name: 'Edit',
115
+ * input: {...} }] } }` — the REAL Claude Code / JSONL shape,
116
+ * where the tool call lives inside `message.content[]`. The old
117
+ * flat reader never descended here, so `countEdits` returned 0
118
+ * for every Claude Code session and the Stop hook never fired.
119
+ *
120
+ * When a node IS a counted invocation we count it and STOP descending: its
121
+ * remaining fields are the tool's `input` args (which may themselves carry
122
+ * a `name`), not further tool calls. Depth-bounded so a pathological
123
+ * transcript can't blow the stack.
124
+ */
125
+ function countToolUsesDeep(node, depth) {
126
+ if (depth > 8 || node === null || typeof node !== 'object')
127
+ return 0;
128
+ if (Array.isArray(node)) {
129
+ let n = 0;
130
+ for (const item of node)
131
+ n += countToolUsesDeep(item, depth + 1);
132
+ return n;
133
+ }
134
+ const obj = node;
135
+ if (COUNTED_TOOLS.has(toolNameOf(obj)))
136
+ return 1;
137
+ let n = 0;
138
+ for (const value of Object.values(obj)) {
139
+ if (value && typeof value === 'object') {
140
+ n += countToolUsesDeep(value, depth + 1);
141
+ }
142
+ }
143
+ return n;
144
+ }
102
145
  /**
103
146
  * Walk every event in the transcript and count tool invocations whose
104
- * name is in COUNTED_TOOLS. Tolerant to the multiple field-name
105
- * conventions different agents use (`tool_uses` / `toolCalls` / `tools`,
106
- * and inside each `name` / `tool_name` / `toolName`).
147
+ * name is in COUNTED_TOOLS. See `countToolUsesDeep` for the shapes covered.
107
148
  */
108
149
  export function countEdits(transcript) {
109
150
  let n = 0;
110
151
  for (const event of transcript) {
111
- if (!event || typeof event !== 'object')
112
- continue;
113
- const rec = event;
114
- const candidates = [];
115
- for (const key of ['tool_uses', 'toolCalls', 'tools', 'message']) {
116
- const v = rec[key];
117
- if (Array.isArray(v))
118
- candidates.push(...v);
119
- else if (v && typeof v === 'object')
120
- candidates.push(v);
121
- }
122
- // Some transcripts inline a `name` / `tool_name` directly on the event.
123
- candidates.push(rec);
124
- for (const c of candidates) {
125
- if (!c || typeof c !== 'object')
126
- continue;
127
- const obj = c;
128
- const name = (typeof obj.name === 'string' && obj.name) ||
129
- (typeof obj.tool_name === 'string' && obj.tool_name) ||
130
- (typeof obj.toolName === 'string' && obj.toolName) ||
131
- '';
132
- if (COUNTED_TOOLS.has(name))
133
- n += 1;
134
- }
152
+ n += countToolUsesDeep(event, 0);
135
153
  }
136
154
  return n;
137
155
  }
138
156
  /**
139
- * Pull the first user-role message text from the transcript. Truncated
140
- * to 600 chars enough context for the agent to do the gap analysis
141
- * without bloating the output.
157
+ * Prefixes Claude Code uses to wrap NON-human user turns: slash-command
158
+ * invocations (`/effort`, `/clear`, …), the caveat banner injected before
159
+ * local-command output, and the command's captured stdout. They are
160
+ * recorded with role=user but are not the human's request, so the gap
161
+ * analysis skips them to find the real prompt.
162
+ */
163
+ const COMMAND_WRAPPER_PREFIXES = [
164
+ '<local-command-',
165
+ '<command-name>',
166
+ '<command-message>',
167
+ '<command-args>',
168
+ '<command-stdout>',
169
+ '<bash-input>',
170
+ '<bash-stdout>',
171
+ '<bash-stderr>',
172
+ ];
173
+ function isCommandWrapper(text) {
174
+ const t = text.trimStart();
175
+ return COMMAND_WRAPPER_PREFIXES.some((p) => t.startsWith(p));
176
+ }
177
+ /**
178
+ * Pull human-readable text out of the many user-message shapes:
179
+ * - flat string: `{ content: '...' }` / `{ text }` / `{ message: '...' }`
180
+ * (synthetic tests + some agents)
181
+ * - Anthropic message: `{ message: { content: '...' } }` (Claude Code) or
182
+ * `{ message: { content: [ { type: 'text', text } … ] } }`
183
+ *
184
+ * Returns '' for tool_result-only turns (no human text to surface).
185
+ */
186
+ function userText(rec) {
187
+ if (typeof rec.content === 'string' && rec.content)
188
+ return rec.content;
189
+ if (typeof rec.text === 'string' && rec.text)
190
+ return rec.text;
191
+ if (typeof rec.message === 'string' && rec.message)
192
+ return rec.message;
193
+ const msg = rec.message;
194
+ if (msg && typeof msg === 'object') {
195
+ const content = msg.content;
196
+ if (typeof content === 'string' && content)
197
+ return content;
198
+ if (Array.isArray(content)) {
199
+ const parts = [];
200
+ for (const block of content) {
201
+ if (!block || typeof block !== 'object')
202
+ continue;
203
+ const b = block;
204
+ // Only `text` blocks are human prompt content — skip tool_result,
205
+ // image, etc. that also appear inside a user turn.
206
+ if (typeof b.text === 'string' &&
207
+ (b.type === 'text' || b.type === undefined)) {
208
+ parts.push(b.text);
209
+ }
210
+ }
211
+ const joined = parts.join('\n').trim();
212
+ if (joined)
213
+ return joined;
214
+ }
215
+ }
216
+ return '';
217
+ }
218
+ /**
219
+ * Pull the first REAL user prompt from the transcript — the first
220
+ * human-authored turn, skipping subagent sidechains, synthetic meta
221
+ * events, and Claude Code's slash-command / local-command wrapper turns.
222
+ * Truncated to 600 chars — enough context for the agent to do the gap
223
+ * analysis without bloating the output.
142
224
  */
143
225
  export function extractFirstUserPrompt(transcript) {
144
226
  for (const event of transcript) {
145
227
  if (!event || typeof event !== 'object')
146
228
  continue;
147
229
  const rec = event;
230
+ if (rec.isSidechain === true || rec.isMeta === true)
231
+ continue;
148
232
  const isUser = rec.role === 'user' || rec.type === 'user' || rec.from === 'user';
149
233
  if (!isUser)
150
234
  continue;
151
- const text = (typeof rec.content === 'string' && rec.content) ||
152
- (typeof rec.text === 'string' && rec.text) ||
153
- (typeof rec.message === 'string' && rec.message) ||
154
- '';
155
- if (text)
156
- return text.slice(0, 600);
235
+ const text = userText(rec);
236
+ if (!text || isCommandWrapper(text))
237
+ continue;
238
+ return text.slice(0, 600);
157
239
  }
158
240
  return '';
159
241
  }
@@ -164,8 +246,8 @@ function composeReviewBody(editCount, client, userPrompt, autoPropose) {
164
246
  ' **Auto-propose mode is ON** (configured at install). Without asking the user,',
165
247
  ' call `cybe_rules_report_missing(projectId, { rule_text, evidence_files,',
166
248
  ' rationale: "<quote user prompt>", confirmed_by_user: true })` for each',
167
- ' uncovered concern. The user will validate them at the next session start',
168
- ' via the Accept/Reject picker.',
249
+ ' selected concern (1–2 max). The user will validate them at the next',
250
+ ' session start via the Accept/Reject picker.',
169
251
  ].join('\n')
170
252
  : [
171
253
  ' Ask the user via AskUserQuestion:',
@@ -187,9 +269,13 @@ function composeReviewBody(editCount, client, userPrompt, autoPropose) {
187
269
  '### Required next-turn action',
188
270
  '1. Extract security/business concerns the prompt mentions.',
189
271
  '2. List CybeDefend rules returned during the session.',
190
- '3. For each concern WITHOUT a matching rule:',
272
+ '3. Identify concerns WITHOUT a matching rule, then select **AT MOST the',
273
+ ' 1–2 most important** (prefer security-critical / data-handling). Ignore',
274
+ ' the rest — over-proposing causes proposal fatigue and users end up',
275
+ ' rejecting everything. Propose nothing if no gap is worth a standing rule.',
276
+ '4. For each selected concern (1–2 max):',
191
277
  proposalLine,
192
- '4. If every concern is covered, say so:',
278
+ '5. If every concern is covered (or none warrants a rule), say so:',
193
279
  ' "🛡️ CybeDefend gap analysis: every concern in your request was covered',
194
280
  ' by an existing rule. No new proposals."',
195
281
  '',
@@ -1 +1 @@
1
- {"version":3,"file":"session-review.js","sourceRoot":"","sources":["../../../src/hooks/runtime/session-review.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session-review.js","sourceRoot":"","sources":["../../../src/hooks/runtime/session-review.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEnD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE/D,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC;IAC5B,MAAM;IACN,OAAO;IACP,WAAW;IACX,aAAa;IACb,gBAAgB;CACjB,CAAC,CAAC;AAUH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,OAA0B,EAAE;IAE5B,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,aAAa,CAAC;IAClD,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,iBAAiB,CAAC;IACxD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC;IACnC,MAAM,kBAAkB,GAAG,IAAI,CAAC,kBAAkB,IAAI,qBAAqB,CAAC;IAE5E,MAAM,KAAK,GAAG,MAAM,SAAS,EAAE,CAAC;IAChC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IAE3B,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,IAAI,CAAC,MAAM;QAAE,OAAO;IACpB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB;QAAE,OAAO;IAE9C,MAAM,UAAU,GAAG,cAAc,CAAC,KAAK,EAAE,kBAAkB,CAAC,CAAC;IAC7D,IAAI,SAAS,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;IAEvC,qEAAqE;IACrE,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,KAAK,GAAG,EAAE,CAAC;QAC3C,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,wBAAwB,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,IAAI,SAAS,KAAK,CAAC;QAAE,OAAO;IAC5B,IAAI,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,eAAe;QAAE,OAAO;IAErD,MAAM,UAAU,GAAG,sBAAsB,CAAC,UAAU,CAAC,CAAC;IACtD,MAAM,IAAI,GAAG,iBAAiB,CAC5B,SAAS,EACT,KAAK,CAAC,MAAM,EACZ,UAAU,EACV,MAAM,CAAC,KAAK,CAAC,eAAe,CAC7B,CAAC;IACF,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;AAC7B,CAAC;AAED;;;;;GAKG;AACH,SAAS,cAAc,CACrB,KAA8B,EAC9B,QAAyC;IAEzC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC;QAAE,OAAO,KAAK,CAAC,UAAU,CAAC;IAE7D,MAAM,IAAI,GACR,OAAO,KAAK,CAAC,eAAe,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;IACzE,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IAErB,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC3B,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC;IAEpB,wEAAwE;IACxE,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3B,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5B,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAChC,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QACvC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IACD,MAAM,GAAG,GAAc,EAAE,CAAC;IAC1B,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACvC,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACtB,IAAI,CAAC,CAAC;YAAE,SAAS;QACjB,IAAI,CAAC;YACH,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1B,CAAC;QAAC,MAAM,CAAC;YACP,6DAA6D;YAC7D,gEAAgE;QAClE,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,qBAAqB,CAAC,IAAY;IACzC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,+DAA+D;AAC/D,SAAS,UAAU,CAAC,GAA4B;IAC9C,OAAO,CACL,CAAC,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,CAAC;QAC1C,CAAC,OAAO,GAAG,CAAC,SAAS,KAAK,QAAQ,IAAI,GAAG,CAAC,SAAS,CAAC;QACpD,CAAC,OAAO,GAAG,CAAC,QAAQ,KAAK,QAAQ,IAAI,GAAG,CAAC,QAAQ,CAAC;QAClD,EAAE,CACH,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,SAAS,iBAAiB,CAAC,IAAa,EAAE,KAAa;IACrD,IAAI,KAAK,GAAG,CAAC,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,CAAC,CAAC;IACrE,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,IAAI,CAAC,GAAG,CAAC,CAAC;QACV,KAAK,MAAM,IAAI,IAAI,IAAI;YAAE,CAAC,IAAI,iBAAiB,CAAC,IAAI,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;QACjE,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,GAAG,GAAG,IAA+B,CAAC;IAC5C,IAAI,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QAAE,OAAO,CAAC,CAAC;IACjD,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;QACvC,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YACvC,CAAC,IAAI,iBAAiB,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,UAAqB;IAC9C,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;QAC/B,CAAC,IAAI,iBAAiB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;;;;GAMG;AACH,MAAM,wBAAwB,GAAG;IAC/B,iBAAiB;IACjB,gBAAgB;IAChB,mBAAmB;IACnB,gBAAgB;IAChB,kBAAkB;IAClB,cAAc;IACd,eAAe;IACf,eAAe;CAChB,CAAC;AAEF,SAAS,gBAAgB,CAAC,IAAY;IACpC,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;IAC3B,OAAO,wBAAwB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,QAAQ,CAAC,GAA4B;IAC5C,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,IAAI,GAAG,CAAC,OAAO;QAAE,OAAO,GAAG,CAAC,OAAO,CAAC;IACvE,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI;QAAE,OAAO,GAAG,CAAC,IAAI,CAAC;IAC9D,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,IAAI,GAAG,CAAC,OAAO;QAAE,OAAO,GAAG,CAAC,OAAO,CAAC;IAEvE,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC;IACxB,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QACnC,MAAM,OAAO,GAAI,GAA+B,CAAC,OAAO,CAAC;QACzD,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO;YAAE,OAAO,OAAO,CAAC;QAC3D,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3B,MAAM,KAAK,GAAa,EAAE,CAAC;YAC3B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;gBAC5B,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;oBAAE,SAAS;gBAClD,MAAM,CAAC,GAAG,KAAgC,CAAC;gBAC3C,kEAAkE;gBAClE,mDAAmD;gBACnD,IACE,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ;oBAC1B,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,EAC3C,CAAC;oBACD,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;gBACrB,CAAC;YACH,CAAC;YACD,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;YACvC,IAAI,MAAM;gBAAE,OAAO,MAAM,CAAC;QAC5B,CAAC;IACH,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CAAC,UAAqB;IAC1D,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;QAC/B,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,SAAS;QAClD,MAAM,GAAG,GAAG,KAAgC,CAAC;QAC7C,IAAI,GAAG,CAAC,WAAW,KAAK,IAAI,IAAI,GAAG,CAAC,MAAM,KAAK,IAAI;YAAE,SAAS;QAC9D,MAAM,MAAM,GACV,GAAG,CAAC,IAAI,KAAK,MAAM,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,CAAC;QACpE,IAAI,CAAC,MAAM;YAAE,SAAS;QACtB,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC3B,IAAI,CAAC,IAAI,IAAI,gBAAgB,CAAC,IAAI,CAAC;YAAE,SAAS;QAC9C,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,SAAS,iBAAiB,CACxB,SAAiB,EACjB,MAAc,EACd,UAAkB,EAClB,WAAoB;IAEpB,MAAM,UAAU,GAAG,UAAU,IAAI,0CAA0C,CAAC;IAC5E,MAAM,YAAY,GAAG,WAAW;QAC9B,CAAC,CAAC;YACE,kFAAkF;YAClF,4EAA4E;YAC5E,2EAA2E;YAC3E,wEAAwE;YACxE,gDAAgD;SACjD,CAAC,IAAI,CAAC,IAAI,CAAC;QACd,CAAC,CAAC;YACE,sCAAsC;YACtC,wEAAwE;YACxE,+EAA+E;YAC/E,uEAAuE;YACvE,mEAAmE;YACnE,iCAAiC;SAClC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEjB,OAAO;QACL,+CAA+C,SAAS,+BAA+B,MAAM,GAAG;QAChG,EAAE;QACF,iEAAiE;QACjE,uDAAuD;QACvD,EAAE;QACF,6CAA6C;QAC7C,KAAK,UAAU,EAAE;QACjB,EAAE;QACF,+BAA+B;QAC/B,4DAA4D;QAC5D,uDAAuD;QACvD,yEAAyE;QACzE,4EAA4E;QAC5E,uEAAuE;QACvE,8EAA8E;QAC9E,yCAAyC;QACzC,YAAY;QACZ,mEAAmE;QACnE,4EAA4E;QAC5E,6CAA6C;QAC7C,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}