sessionpipe-conformance 0.1.0 → 0.1.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 +1 -1
- package/dist/cli.js +189 -48
- package/dist/cli.js.map +3 -3
- package/dist/index.js +189 -48
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
|
-
// sessionpipe-conformance 0.1.
|
|
1
|
+
// sessionpipe-conformance 0.1.1 · Apache-2.0 · https://sessionpipe.org
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import { readFileSync as readFileSync6 } from "node:fs";
|
|
5
5
|
|
|
6
6
|
// ../core/src/adapters/antigravity.ts
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
existsSync as existsSync2,
|
|
9
|
+
mkdirSync as mkdirSync2,
|
|
10
|
+
readdirSync as readdirSync2,
|
|
11
|
+
readFileSync as readFileSync2,
|
|
12
|
+
realpathSync,
|
|
13
|
+
statSync as statSync2,
|
|
14
|
+
unlinkSync as unlinkSync2,
|
|
15
|
+
writeFileSync as writeFileSync2
|
|
16
|
+
} from "node:fs";
|
|
8
17
|
import path3 from "node:path";
|
|
9
18
|
|
|
10
19
|
// ../core/src/paths.ts
|
|
@@ -212,16 +221,42 @@ function readAntigravity(lines, from) {
|
|
|
212
221
|
}
|
|
213
222
|
|
|
214
223
|
// ../core/src/adapters/claude-shaped.ts
|
|
215
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
224
|
+
import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
216
225
|
import path2 from "node:path";
|
|
217
226
|
var OURS = /sessionpipe[^"\n]*[\\/]hook\.js"?\s+[a-z][a-z-]*\s+[A-Za-z]+\s*$/;
|
|
218
227
|
var isOurs = (h) => Array.isArray(h?.hooks) && h.hooks.some((x) => typeof x.command === "string" && OURS.test(x.command));
|
|
219
|
-
function
|
|
228
|
+
function readJsonFile(file) {
|
|
229
|
+
let raw;
|
|
220
230
|
try {
|
|
221
|
-
|
|
231
|
+
raw = readFileSync(file, "utf8");
|
|
222
232
|
} catch {
|
|
223
|
-
return {};
|
|
233
|
+
return { ok: true, existed: false, value: {}, raw: "", indent: " ", eol: "\n", finalNewline: true };
|
|
224
234
|
}
|
|
235
|
+
let value;
|
|
236
|
+
try {
|
|
237
|
+
value = JSON.parse(raw);
|
|
238
|
+
} catch {
|
|
239
|
+
const hint = /^\s*\/\/|\/\*/m.test(raw) ? "not plain JSON (it has comments)" : "not plain JSON";
|
|
240
|
+
return { ok: false, existed: true, reason: hint };
|
|
241
|
+
}
|
|
242
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
243
|
+
return { ok: false, existed: true, reason: "not a JSON object" };
|
|
244
|
+
const eol = raw.includes("\r\n") ? "\r\n" : "\n";
|
|
245
|
+
const m = /^( +|\t+)\S/m.exec(raw);
|
|
246
|
+
const indent = m?.[1] ?? " ";
|
|
247
|
+
return {
|
|
248
|
+
ok: true,
|
|
249
|
+
existed: true,
|
|
250
|
+
value,
|
|
251
|
+
raw,
|
|
252
|
+
indent,
|
|
253
|
+
eol,
|
|
254
|
+
finalNewline: /\r?\n$/.test(raw)
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
function formatJson(value, f) {
|
|
258
|
+
const text = JSON.stringify(value, null, f.indent).replace(/\n/g, f.eol);
|
|
259
|
+
return f.finalNewline ? text + f.eol : text;
|
|
225
260
|
}
|
|
226
261
|
function entryFor(event, harness, cmd, o) {
|
|
227
262
|
const matcher = o.matcherFor(event);
|
|
@@ -231,9 +266,22 @@ function entryFor(event, harness, cmd, o) {
|
|
|
231
266
|
};
|
|
232
267
|
}
|
|
233
268
|
function installClaudeShaped(file, harness, events, cmd, o) {
|
|
234
|
-
const
|
|
269
|
+
const f = readJsonFile(file);
|
|
270
|
+
if (!f.ok) return { file, changed: false, skipped: true, note: `${f.reason}; not touched` };
|
|
271
|
+
const settings2 = f.value;
|
|
235
272
|
const hooks = settings2.hooks && typeof settings2.hooks === "object" ? settings2.hooks : {};
|
|
236
273
|
let changed = false;
|
|
274
|
+
const want = new Set(events);
|
|
275
|
+
for (const ev of Object.keys(hooks)) {
|
|
276
|
+
if (want.has(ev)) continue;
|
|
277
|
+
const list = Array.isArray(hooks[ev]) ? hooks[ev] : [];
|
|
278
|
+
const kept = list.filter((h) => !isOurs(h));
|
|
279
|
+
if (kept.length !== list.length) {
|
|
280
|
+
changed = true;
|
|
281
|
+
if (kept.length) hooks[ev] = kept;
|
|
282
|
+
else delete hooks[ev];
|
|
283
|
+
}
|
|
284
|
+
}
|
|
237
285
|
for (const ev of events) {
|
|
238
286
|
const list = Array.isArray(hooks[ev]) ? hooks[ev] : [];
|
|
239
287
|
const entry2 = entryFor(ev, harness, cmd, o);
|
|
@@ -252,19 +300,19 @@ function installClaudeShaped(file, harness, events, cmd, o) {
|
|
|
252
300
|
if (changed) {
|
|
253
301
|
settings2.hooks = hooks;
|
|
254
302
|
mkdirSync(path2.dirname(file), { recursive: true });
|
|
255
|
-
writeFileSync(file,
|
|
256
|
-
`);
|
|
303
|
+
writeFileSync(file, formatJson(settings2, f));
|
|
257
304
|
}
|
|
258
|
-
return { file, changed };
|
|
305
|
+
return { file, changed, created: !f.existed && changed };
|
|
259
306
|
}
|
|
260
|
-
function uninstallClaudeShaped(file, events) {
|
|
307
|
+
function uninstallClaudeShaped(file, events, opts = {}) {
|
|
261
308
|
if (!existsSync(file)) return { file, changed: false };
|
|
262
|
-
const
|
|
263
|
-
|
|
309
|
+
const f = readJsonFile(file);
|
|
310
|
+
if (!f.ok) return { file, changed: false, skipped: true, note: `${f.reason}; not touched` };
|
|
311
|
+
const settings2 = f.value;
|
|
264
312
|
const hooks = settings2.hooks;
|
|
265
313
|
if (!hooks || typeof hooks !== "object") return { file, changed: false };
|
|
266
314
|
let changed = false;
|
|
267
|
-
for (const ev of events) {
|
|
315
|
+
for (const ev of [...events, ...Object.keys(hooks)]) {
|
|
268
316
|
const list = Array.isArray(hooks[ev]) ? hooks[ev] : [];
|
|
269
317
|
const kept = list.filter((h) => !isOurs(h));
|
|
270
318
|
if (kept.length !== list.length) {
|
|
@@ -275,13 +323,17 @@ function uninstallClaudeShaped(file, events) {
|
|
|
275
323
|
}
|
|
276
324
|
if (!changed) return { file, changed: false };
|
|
277
325
|
if (!Object.keys(hooks).length) delete settings2.hooks;
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
326
|
+
if (opts.created && !Object.keys(settings2).length) {
|
|
327
|
+
unlinkSync(file);
|
|
328
|
+
return { file, changed: true, note: "removed (sessionpipe created it)" };
|
|
329
|
+
}
|
|
330
|
+
const next = formatJson(settings2, f);
|
|
331
|
+
if (next !== f.raw) writeFileSync(file, next);
|
|
281
332
|
return { file, changed: true };
|
|
282
333
|
}
|
|
283
334
|
function installedClaudeShaped(file, harness, events, cmd, o) {
|
|
284
|
-
const
|
|
335
|
+
const f = readJsonFile(file);
|
|
336
|
+
const hooks = f.ok ? f.value.hooks ?? {} : {};
|
|
285
337
|
let present = 0;
|
|
286
338
|
let current = 0;
|
|
287
339
|
for (const ev of events) {
|
|
@@ -290,6 +342,9 @@ function installedClaudeShaped(file, harness, events, cmd, o) {
|
|
|
290
342
|
if (mine.length) present++;
|
|
291
343
|
if (mine.length === 1 && JSON.stringify(mine[0]) === JSON.stringify(entryFor(ev, harness, cmd, o))) current++;
|
|
292
344
|
}
|
|
345
|
+
for (const ev of Object.keys(hooks))
|
|
346
|
+
if (!events.includes(ev) && (Array.isArray(hooks[ev]) ? hooks[ev] : []).some((h) => isOurs(h)))
|
|
347
|
+
return "stale";
|
|
293
348
|
if (!present) return "missing";
|
|
294
349
|
return current === events.length ? "current" : "stale";
|
|
295
350
|
}
|
|
@@ -304,10 +359,13 @@ var projectsDir = (env) => path3.join(gemini(env), "config", "projects");
|
|
|
304
359
|
var dataDirs = (env) => ["antigravity", "antigravity-cli", "antigravity-ide"].map((d) => path3.join(gemini(env), d));
|
|
305
360
|
var ID_RE = /^[A-Za-z0-9_-]{1,128}$/;
|
|
306
361
|
var validTool = (n) => typeof n === "string" && /^[A-Za-z0-9_.:-]{1,120}$/.test(n);
|
|
307
|
-
function entry(cmd) {
|
|
362
|
+
function entry(cmd, lean) {
|
|
308
363
|
const handler = (e) => ({ type: "command", command: cmd([NAME, e]).command, timeout: 5 });
|
|
309
364
|
const out = { enabled: true };
|
|
310
|
-
for (const e of AG_EVENTS)
|
|
365
|
+
for (const e of AG_EVENTS) {
|
|
366
|
+
if (lean && e === "PreToolUse") continue;
|
|
367
|
+
out[e] = /Tool/.test(e) ? [{ matcher: "*", hooks: [handler(e)] }] : [handler(e)];
|
|
368
|
+
}
|
|
311
369
|
return out;
|
|
312
370
|
}
|
|
313
371
|
var antigravity = {
|
|
@@ -315,34 +373,49 @@ var antigravity = {
|
|
|
315
373
|
events: AG_EVENTS,
|
|
316
374
|
detect: (env = process.env) => existsSync2(path3.join(gemini(env), "config")) || dataDirs(env).some((d) => existsSync2(d)),
|
|
317
375
|
configFiles: (env = process.env) => [hooksFile(env)],
|
|
318
|
-
install(cmd, env = process.env) {
|
|
376
|
+
install(cmd, env = process.env, opts = {}) {
|
|
319
377
|
const file = hooksFile(env);
|
|
320
|
-
const
|
|
321
|
-
|
|
378
|
+
const f = readJsonFile(file);
|
|
379
|
+
if (!f.ok) return [{ file, changed: false, skipped: true, note: `${f.reason}; not touched` }];
|
|
380
|
+
const hooks = f.value;
|
|
381
|
+
const e = entry(cmd, opts.lean);
|
|
322
382
|
if (JSON.stringify(hooks[HOOK_NAME]) === JSON.stringify(e)) return [{ file, changed: false }];
|
|
323
383
|
hooks[HOOK_NAME] = e;
|
|
324
384
|
mkdirSync2(path3.dirname(file), { recursive: true });
|
|
325
|
-
writeFileSync2(file,
|
|
326
|
-
`);
|
|
385
|
+
writeFileSync2(file, formatJson(hooks, f));
|
|
327
386
|
return [
|
|
328
|
-
{
|
|
387
|
+
{
|
|
388
|
+
file,
|
|
389
|
+
changed: true,
|
|
390
|
+
created: !f.existed,
|
|
391
|
+
note: "hooks.json is read when a conversation starts; open ones report after a restart"
|
|
392
|
+
}
|
|
329
393
|
];
|
|
330
394
|
},
|
|
331
|
-
uninstall(env = process.env) {
|
|
395
|
+
uninstall(env = process.env, opts = {}) {
|
|
332
396
|
const file = hooksFile(env);
|
|
333
397
|
if (!existsSync2(file)) return [{ file, changed: false }];
|
|
334
|
-
const
|
|
398
|
+
const f = readJsonFile(file);
|
|
399
|
+
if (!f.ok) return [{ file, changed: false, skipped: true, note: `${f.reason}; not touched` }];
|
|
400
|
+
const hooks = f.value;
|
|
335
401
|
if (!(HOOK_NAME in hooks)) return [{ file, changed: false }];
|
|
336
402
|
delete hooks[HOOK_NAME];
|
|
337
|
-
|
|
338
|
-
|
|
403
|
+
if (opts.created?.includes(file) && !Object.keys(hooks).length) {
|
|
404
|
+
unlinkSync2(file);
|
|
405
|
+
return [{ file, changed: true, note: "removed (sessionpipe created it)" }];
|
|
406
|
+
}
|
|
407
|
+
writeFileSync2(file, formatJson(hooks, f));
|
|
339
408
|
return [{ file, changed: true }];
|
|
340
409
|
},
|
|
341
|
-
installed(cmd, env = process.env) {
|
|
410
|
+
installed(cmd, env = process.env, opts = {}) {
|
|
342
411
|
const file = hooksFile(env);
|
|
343
|
-
const
|
|
412
|
+
const f = readJsonFile(file);
|
|
413
|
+
const have = f.ok ? f.value[HOOK_NAME] : void 0;
|
|
344
414
|
return [
|
|
345
|
-
{
|
|
415
|
+
{
|
|
416
|
+
file,
|
|
417
|
+
state: !have ? "missing" : JSON.stringify(have) === JSON.stringify(entry(cmd, opts.lean)) ? "current" : "stale"
|
|
418
|
+
}
|
|
346
419
|
];
|
|
347
420
|
},
|
|
348
421
|
fromHook(input) {
|
|
@@ -608,8 +681,11 @@ var CLAUDE_EVENTS = [
|
|
|
608
681
|
"SubagentStop",
|
|
609
682
|
"PreCompact",
|
|
610
683
|
"PostCompact",
|
|
611
|
-
"SessionEnd"
|
|
684
|
+
"SessionEnd",
|
|
685
|
+
"StopFailure"
|
|
612
686
|
];
|
|
687
|
+
var LEAN_SKIP = /* @__PURE__ */ new Set(["PreToolUse", "PostToolUseFailure"]);
|
|
688
|
+
var eventsFor = (lean) => lean ? CLAUDE_EVENTS.filter((e) => !LEAN_SKIP.has(e)) : [...CLAUDE_EVENTS];
|
|
613
689
|
var OPTS = { matcherFor: (e) => /Tool|Permission/.test(e) ? "" : void 0, timeout: 5 };
|
|
614
690
|
var DESKTOP_ID = /^local_[A-Za-z0-9-]{1,64}$/;
|
|
615
691
|
function claudeDirs(env = process.env, home = HOME) {
|
|
@@ -641,11 +717,13 @@ var claudeCode = {
|
|
|
641
717
|
events: CLAUDE_EVENTS,
|
|
642
718
|
detect: (env = process.env) => claudeDirs(env).some((d) => existsSync3(d)),
|
|
643
719
|
configFiles: (env = process.env) => claudeDirs(env).map(settingsIn),
|
|
644
|
-
install: (cmd, env = process.env) => claudeDirs(env).map((d) => installClaudeShaped(settingsIn(d), NAME2,
|
|
645
|
-
uninstall: (env = process.env) => claudeDirs(env).map(
|
|
646
|
-
|
|
720
|
+
install: (cmd, env = process.env, opts = {}) => claudeDirs(env).map((d) => installClaudeShaped(settingsIn(d), NAME2, eventsFor(opts.lean), cmd, OPTS)),
|
|
721
|
+
uninstall: (env = process.env, opts = {}) => claudeDirs(env).map(
|
|
722
|
+
(d) => uninstallClaudeShaped(settingsIn(d), CLAUDE_EVENTS, { created: opts.created?.includes(settingsIn(d)) })
|
|
723
|
+
),
|
|
724
|
+
installed: (cmd, env = process.env, opts = {}) => claudeDirs(env).map((d) => ({
|
|
647
725
|
file: settingsIn(d),
|
|
648
|
-
state: installedClaudeShaped(settingsIn(d), NAME2,
|
|
726
|
+
state: installedClaudeShaped(settingsIn(d), NAME2, eventsFor(opts.lean), cmd, OPTS)
|
|
649
727
|
})),
|
|
650
728
|
fromHook(input) {
|
|
651
729
|
const event = input.argv[1] ?? "";
|
|
@@ -736,6 +814,15 @@ var claudeCode = {
|
|
|
736
814
|
case "Stop":
|
|
737
815
|
events.push(ev("turn.ended", { turn_id, reason: "stop" }));
|
|
738
816
|
break;
|
|
817
|
+
case "StopFailure":
|
|
818
|
+
events.push(
|
|
819
|
+
ev("turn.ended", {
|
|
820
|
+
turn_id,
|
|
821
|
+
reason: "error",
|
|
822
|
+
error: typeof s.error === "string" ? s.error.slice(0, 200) : void 0
|
|
823
|
+
})
|
|
824
|
+
);
|
|
825
|
+
break;
|
|
739
826
|
case "SubagentStart":
|
|
740
827
|
events.push(
|
|
741
828
|
ev("subagent.started", {
|
|
@@ -1247,6 +1334,7 @@ var CODEX_EVENTS = [
|
|
|
1247
1334
|
"SessionEnd"
|
|
1248
1335
|
];
|
|
1249
1336
|
var OPTS2 = { matcherFor: (e) => /Tool|Permission/.test(e) ? "" : void 0, timeout: 5 };
|
|
1337
|
+
var eventsFor2 = (lean) => lean ? CODEX_EVENTS.filter((e) => e !== "PreToolUse") : [...CODEX_EVENTS];
|
|
1250
1338
|
var codexHome = (env) => env.CODEX_HOME || path5.join(HOME, ".codex");
|
|
1251
1339
|
var hooksFile2 = (env) => path5.join(codexHome(env), "hooks.json");
|
|
1252
1340
|
var configFile = (env) => path5.join(codexHome(env), "config.toml");
|
|
@@ -1295,7 +1383,8 @@ function installNotify(cmd, env) {
|
|
|
1295
1383
|
return {
|
|
1296
1384
|
file,
|
|
1297
1385
|
changed: false,
|
|
1298
|
-
|
|
1386
|
+
skipped: true,
|
|
1387
|
+
note: `notify belongs to ${(n.argv?.[0] ?? n.raw).replace(/^.*\//, "").slice(0, 40)}; left alone. Codex will report nothing until you approve the hooks: start \`codex\` and accept the hook review`
|
|
1299
1388
|
};
|
|
1300
1389
|
}
|
|
1301
1390
|
write(withNotify(text, line));
|
|
@@ -1352,14 +1441,21 @@ var codex = {
|
|
|
1352
1441
|
events: CODEX_EVENTS,
|
|
1353
1442
|
detect: (env = process.env) => existsSync4(codexHome(env)),
|
|
1354
1443
|
configFiles: (env = process.env) => [hooksFile2(env), configFile(env)],
|
|
1355
|
-
install: (cmd, env = process.env) => [
|
|
1356
|
-
installClaudeShaped(hooksFile2(env), NAME3,
|
|
1444
|
+
install: (cmd, env = process.env, opts = {}) => [
|
|
1445
|
+
installClaudeShaped(hooksFile2(env), NAME3, eventsFor2(opts.lean), cmd, OPTS2),
|
|
1357
1446
|
installNotify(cmd, env)
|
|
1358
1447
|
],
|
|
1359
|
-
uninstall: (env = process.env) => [
|
|
1360
|
-
|
|
1448
|
+
uninstall: (env = process.env, opts = {}) => [
|
|
1449
|
+
uninstallClaudeShaped(hooksFile2(env), CODEX_EVENTS, { created: opts.created?.includes(hooksFile2(env)) }),
|
|
1450
|
+
uninstallNotify(env)
|
|
1451
|
+
],
|
|
1452
|
+
installed: (cmd, env = process.env, opts = {}) => {
|
|
1361
1453
|
const out = [
|
|
1362
|
-
{
|
|
1454
|
+
{
|
|
1455
|
+
file: hooksFile2(env),
|
|
1456
|
+
state: installedClaudeShaped(hooksFile2(env), NAME3, eventsFor2(opts.lean), cmd, OPTS2),
|
|
1457
|
+
note: "Codex runs non-managed hooks only after the review in `codex` (/hooks); until then nothing is reported unless the notify fallback is ours"
|
|
1458
|
+
}
|
|
1363
1459
|
];
|
|
1364
1460
|
let text = "";
|
|
1365
1461
|
try {
|
|
@@ -1547,6 +1643,7 @@ function codexFacts(file) {
|
|
|
1547
1643
|
}
|
|
1548
1644
|
|
|
1549
1645
|
// ../core/src/adapters/gemini-cli.ts
|
|
1646
|
+
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
1550
1647
|
import { existsSync as existsSync5, readFileSync as readFileSync5 } from "node:fs";
|
|
1551
1648
|
import path6 from "node:path";
|
|
1552
1649
|
var NAME4 = "gemini-cli";
|
|
@@ -1564,17 +1661,61 @@ var OPTS3 = { matcherFor: (e) => /Tool/.test(e) ? ".*" : void 0, timeout: 5e3 };
|
|
|
1564
1661
|
var geminiDir = (env) => env.GEMINI_CLI_HOME || path6.join(HOME, ".gemini");
|
|
1565
1662
|
var settings = (env) => path6.join(geminiDir(env), "settings.json");
|
|
1566
1663
|
var validTool4 = (n) => typeof n === "string" && /^[A-Za-z0-9_.:-]{1,120}$/.test(n);
|
|
1664
|
+
var eventsFor3 = (lean) => lean ? GEMINI_EVENTS.filter((e) => e !== "BeforeTool") : [...GEMINI_EVENTS];
|
|
1665
|
+
function geminiHooksActive(settingsFile) {
|
|
1666
|
+
let tools;
|
|
1667
|
+
try {
|
|
1668
|
+
tools = JSON.parse(readFileSync5(settingsFile, "utf8")).tools;
|
|
1669
|
+
} catch {
|
|
1670
|
+
}
|
|
1671
|
+
if (tools?.enableHooks === true) return { active: true };
|
|
1672
|
+
if (tools?.enableHooks === false)
|
|
1673
|
+
return { active: false, note: "inactive: tools.enableHooks is false in settings.json" };
|
|
1674
|
+
let version = "";
|
|
1675
|
+
try {
|
|
1676
|
+
version = execFileSync3("gemini", ["--version"], {
|
|
1677
|
+
encoding: "utf8",
|
|
1678
|
+
timeout: 4e3,
|
|
1679
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
1680
|
+
}).trim();
|
|
1681
|
+
} catch {
|
|
1682
|
+
return {
|
|
1683
|
+
active: true,
|
|
1684
|
+
note: "could not run `gemini --version`; hooks need tools.enableHooks on versions before 0.46"
|
|
1685
|
+
};
|
|
1686
|
+
}
|
|
1687
|
+
const m = /(\d+)\.(\d+)/.exec(version);
|
|
1688
|
+
if (m && (Number(m[1]) > 0 || Number(m[2]) >= 46)) return { active: true };
|
|
1689
|
+
return {
|
|
1690
|
+
active: false,
|
|
1691
|
+
note: `inactive: Gemini CLI ${version || "?"} runs hooks only with "tools": {"enableHooks": true} in settings.json`
|
|
1692
|
+
};
|
|
1693
|
+
}
|
|
1567
1694
|
var geminiCli = {
|
|
1568
1695
|
name: NAME4,
|
|
1569
1696
|
events: GEMINI_EVENTS,
|
|
1570
1697
|
// ~/.gemini also belongs to Antigravity; Gemini CLI is here when its settings or its chat logs exist.
|
|
1571
1698
|
detect: (env = process.env) => existsSync5(settings(env)) || existsSync5(path6.join(geminiDir(env), "tmp")),
|
|
1572
1699
|
configFiles: (env = process.env) => [settings(env)],
|
|
1573
|
-
install: (cmd, env = process.env
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1700
|
+
install: (cmd, env = process.env, opts = {}) => {
|
|
1701
|
+
const r = installClaudeShaped(settings(env), NAME4, eventsFor3(opts.lean), cmd, OPTS3);
|
|
1702
|
+
const a = geminiHooksActive(settings(env));
|
|
1703
|
+
return [a.note && !r.skipped ? { ...r, note: [r.note, a.note].filter(Boolean).join("; ") } : r];
|
|
1704
|
+
},
|
|
1705
|
+
uninstall: (env = process.env, opts = {}) => [
|
|
1706
|
+
uninstallClaudeShaped(settings(env), GEMINI_EVENTS, { created: opts.created?.includes(settings(env)) })
|
|
1577
1707
|
],
|
|
1708
|
+
installed: (cmd, env = process.env, opts = {}) => {
|
|
1709
|
+
const state = installedClaudeShaped(settings(env), NAME4, eventsFor3(opts.lean), cmd, OPTS3);
|
|
1710
|
+
const a = geminiHooksActive(settings(env));
|
|
1711
|
+
return [
|
|
1712
|
+
{
|
|
1713
|
+
file: settings(env),
|
|
1714
|
+
state: state === "current" && !a.active ? "inactive" : state,
|
|
1715
|
+
...a.note ? { note: a.note } : {}
|
|
1716
|
+
}
|
|
1717
|
+
];
|
|
1718
|
+
},
|
|
1578
1719
|
fromHook(input) {
|
|
1579
1720
|
const event = input.argv[1] ?? "";
|
|
1580
1721
|
let s = {};
|