@solongate/proxy 0.83.55 → 0.83.57

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.
@@ -0,0 +1,26 @@
1
+ export interface HookStart {
2
+ ok: boolean;
3
+ /** The node the launcher resolved, when it resolved one. */
4
+ node?: string;
5
+ detail: string;
6
+ }
7
+ /**
8
+ * Run the launcher's own resolution and report what it found.
9
+ *
10
+ * It runs the INSTALLED launcher rather than reimplementing its search here.
11
+ * A second copy of the candidate list would drift from the first, and the drift
12
+ * would be invisible: the check would pass while the thing it stands for
13
+ * failed.
14
+ */
15
+ export declare function hookCanStart(): HookStart;
16
+ export interface HookBeat {
17
+ hook: string;
18
+ at: Date;
19
+ /** What the launcher resolved that time, or `no-node` when it resolved nothing. */
20
+ node: string;
21
+ }
22
+ /** Every hook that has ever been invoked on this machine, newest first. */
23
+ export declare function hookBeats(): HookBeat[];
24
+ /** The guard's own beat, which is the one that means enforcement happened. */
25
+ export declare function guardBeat(): HookBeat | null;
26
+ export declare function agoLabel(d: Date): string;
@@ -0,0 +1,57 @@
1
+ /**
2
+ * The launcher that stands between an agent client and a hook script.
3
+ *
4
+ * WHY THIS EXISTS
5
+ *
6
+ * A hook is registered as a command string in somebody else's config file, and
7
+ * that string used to name a node binary by absolute path — `process.execPath`
8
+ * at install time. The absolute path was deliberate and is still right: Claude
9
+ * Code runs hooks in a non-interactive environment whose PATH frequently has no
10
+ * `node` on it, and bare `node` there fails with "command not found" while the
11
+ * client reports nothing at all.
12
+ *
13
+ * What was wrong is that `process.execPath` RESOLVES SYMLINKS. On the machines
14
+ * where this bit, that is the whole story:
15
+ *
16
+ * Homebrew /opt/homebrew/bin/node is a symlink into
17
+ * /opt/homebrew/Cellar/node/<version>/bin/node, so execPath records
18
+ * the VERSIONED path — and `brew upgrade` moves it and `brew
19
+ * cleanup` deletes it. The stable symlink was right there and we
20
+ * wrote down the thing it pointed at.
21
+ * nvm/fnm ~/.nvm/versions/node/v22.11.0/bin/node, and the version directory
22
+ * /volta goes away the moment that version is uninstalled or pruned.
23
+ *
24
+ * Linux distro node is /usr/bin/node and Windows node is under Program Files;
25
+ * neither moves. macOS is where node is nearly always under a version manager,
26
+ * which is why "it works everywhere except on the Mac" is the shape this took.
27
+ *
28
+ * When the recorded path is gone, the client spawns a command that cannot start.
29
+ * Nothing enforces, nothing is logged, and every status this CLI printed still
30
+ * said "guard registered" — because it was registered. It just could not run.
31
+ *
32
+ * WHAT THIS DOES
33
+ *
34
+ * Resolve node at RUN time, from a list that starts with the recorded path and
35
+ * falls through every place a Mac actually keeps one. Then exec the hook, so no
36
+ * extra process is left behind.
37
+ *
38
+ * And leave a mark. The launcher touches a beat file before it does anything
39
+ * else, which is the one fact nothing else in this product could establish: that
40
+ * the client invoked the hook at all. "Registered but never fired" and "fired
41
+ * but enforcing nothing" are different faults with different fixes and they
42
+ * looked identical from the outside.
43
+ */
44
+ /** Where the launcher lives, relative to the hooks directory. */
45
+ export declare const LAUNCHER_NAME = "sg-run.sh";
46
+ /** Where the beat files live, relative to ~/.solongate. */
47
+ export declare const BEAT_DIR = ".beat";
48
+ /**
49
+ * The launcher, with the install-time node baked in.
50
+ *
51
+ * POSIX sh, because /bin/sh is the one interpreter every macOS and Linux has at
52
+ * a fixed path. It runs before every single tool call, so it forks nothing on
53
+ * the happy path: the candidate tests are builtins, the beat file is written by
54
+ * a redirect whose MTIME is the timestamp, and the hook is `exec`d rather than
55
+ * spawned.
56
+ */
57
+ export declare function launcherScript(pinnedNode: string): string;