@cybedefend/vibedefend 1.1.2 → 1.2.1
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 +25 -4
- package/dist/clients/claude-code.js +6 -8
- package/dist/clients/claude-code.js.map +1 -1
- package/dist/clients/codex.js +6 -1
- package/dist/clients/codex.js.map +1 -1
- package/dist/clients/detect.js +5 -1
- package/dist/clients/detect.js.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/diagnostics.js +5 -0
- package/dist/diagnostics.js.map +1 -1
- package/dist/doctor.js +13 -0
- package/dist/doctor.js.map +1 -1
- package/dist/hook-runner.js +458 -75
- package/dist/hooks/install.js +54 -9
- package/dist/hooks/install.js.map +1 -1
- package/dist/hooks/runtime/self-update-check.js +196 -0
- package/dist/hooks/runtime/self-update-check.js.map +1 -0
- package/dist/hooks/runtime/semver.js +34 -0
- package/dist/hooks/runtime/semver.js.map +1 -0
- package/dist/hooks/runtime/session-review.js +126 -40
- package/dist/hooks/runtime/session-review.js.map +1 -1
- package/dist/hooks/runtime/session-start.js +24 -0
- package/dist/hooks/runtime/session-start.js.map +1 -1
- package/dist/hooks/shim-entry.js +10 -0
- package/dist/hooks/shim-entry.js.map +1 -0
- package/dist/hooks/shim.js +66 -0
- package/dist/hooks/shim.js.map +1 -0
- package/dist/index.js +46 -31
- package/dist/index.js.map +1 -1
- package/dist/login.js +25 -5
- package/dist/login.js.map +1 -1
- package/dist/prompts.js +14 -2
- package/dist/prompts.js.map +1 -1
- package/dist/self-update.js +64 -21
- package/dist/self-update.js.map +1 -1
- package/dist/shim.js +40 -0
- package/dist/update.js +51 -0
- package/dist/update.js.map +1 -0
- package/dist/utils.js +5 -1
- package/dist/utils.js.map +1 -1
- package/package.json +1 -1
package/dist/hooks/install.js
CHANGED
|
@@ -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.
|
|
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
|
|
80
|
-
|
|
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
|
-
|
|
85
|
-
|
|
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(
|
|
102
|
-
return { runnerPath:
|
|
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":"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,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,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;
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/hooks/install.ts"],"names":[],"mappings":"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"}
|
|
@@ -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.
|
|
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
|
-
|
|
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
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
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 = (
|
|
152
|
-
|
|
153
|
-
|
|
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
|
-
'
|
|
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.
|
|
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
|
-
'
|
|
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"}
|