glimmervoid 0.0.0-stage → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +48 -0
- package/README.md +195 -2
- package/dist/bin/glimmervoid.js +275 -0
- package/dist/chunks/adapters-Dho1VSY5.js +2 -0
- package/dist/chunks/adapters-zPDx1Xox.js +575 -0
- package/dist/chunks/agent-api-cli-D0MmtEdz.js +71 -0
- package/dist/chunks/agent-api-core-Dz0r21y9.js +103 -0
- package/dist/chunks/agent-setup-cli-B5Atxr3F.js +139 -0
- package/dist/chunks/ascii-figure-core-pDAwtlKO.js +45 -0
- package/dist/chunks/child-process-safe-DRGsp0TE.js +69 -0
- package/dist/chunks/child-process-safe-DvQjXsgz.js +2 -0
- package/dist/chunks/config-path-core-DFt-TemS.js +38 -0
- package/dist/chunks/config-store-CC8T3okC.js +2 -0
- package/dist/chunks/config-store-mm7MgzoL.js +1412 -0
- package/dist/chunks/contracts-DGkKNh9W.js +3020 -0
- package/dist/chunks/grok-DuU8xVLZ.js +436 -0
- package/dist/chunks/hook-command-core-DclEoE9e.js +14 -0
- package/dist/chunks/hook-relay-core-BHfYFnYV.js +88 -0
- package/dist/chunks/hook-tools-pSJia7ks.js +74 -0
- package/dist/chunks/ingest-core-DWI1Mbu4.js +342 -0
- package/dist/chunks/ingest-editor-core-BuI1gMF_.js +445 -0
- package/dist/chunks/loopback-post-C7C22eYi.js +79 -0
- package/dist/chunks/main-CuIZQPhZ.js +43559 -0
- package/dist/chunks/node-pty-preflight-CK1knGIR.js +162 -0
- package/dist/chunks/pair-cli-w-gCAF-1.js +110 -0
- package/dist/chunks/path-doctor-C23VAqeu.js +63 -0
- package/dist/chunks/refocus-core-BKQKllq7.js +38 -0
- package/dist/chunks/relay-stdin-CpHvLu6M.js +20 -0
- package/dist/chunks/remote-config-C2ytQwrs.js +525 -0
- package/dist/chunks/rtk-hook-core-Bl6gYHPN.js +133 -0
- package/dist/chunks/rtk-resolver-CLo-gZzw.js +21 -0
- package/dist/chunks/rtk-resolver-CMQAidlI.js +2 -0
- package/dist/chunks/runtime-paths-Ci_ksSkj.js +75 -0
- package/dist/chunks/runtime-paths-JLrZ3wyi.js +2 -0
- package/dist/chunks/sandbox-deps-Dd5-kZnf.js +67 -0
- package/dist/chunks/session-Cez8aIWg.js +164 -0
- package/dist/chunks/spawn-command-Cc40FiZI.js +134 -0
- package/dist/chunks/visions-cli-BXQFIBCX.js +98 -0
- package/dist/chunks/visions-setup-CvVnOe1r.js +1753 -0
- package/dist/client/assets/favicon-CKygeLwW.svg +7 -0
- package/dist/client/assets/index-B1MFijjb.css +1 -0
- package/dist/client/assets/index-CU1iPPdn.js +249 -0
- package/dist/client/index.html +108 -0
- package/dist/package.json +3 -0
- package/dist/scripts/postinstall-path-check.js +36 -0
- package/dist/server/index.js +92 -0
- package/dist/session/command-hook-relay.js +16 -0
- package/dist/session/hook-relay.js +24 -0
- package/dist/session/hook-tool-relay.js +107 -0
- package/dist/session/statusline-relay.js +82 -0
- package/dist/session/visions-relay.js +627 -0
- package/dist/tools/vscode-visions/extension.js +289 -0
- package/dist/tools/vscode-visions/lsp-convert.js +80 -0
- package/dist/tools/vscode-visions/package.json +32 -0
- package/dist/tools/vscode-visions/visions-lsp-core.js +112 -0
- package/package.json +96 -4
- package/scripts/postinstall.mjs +4 -0
- package/scripts/prepare-build.js +38 -0
- package/scripts/recover-handoff.mjs +82 -0
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
import { o as relayPath } from "./runtime-paths-Ci_ksSkj.js";
|
|
2
|
+
import { n as AGENT_URL_ENV } from "./session-Cez8aIWg.js";
|
|
3
|
+
import { t as HOOK_URL_ENV } from "./hook-relay-core-BHfYFnYV.js";
|
|
4
|
+
import { a as SANE_YOLO_PATH_ENV, n as RTK_PATH_ENV, o as saneYoloEnv } from "./rtk-hook-core-Bl6gYHPN.js";
|
|
5
|
+
import { t as buildHookCommand } from "./hook-command-core-DclEoE9e.js";
|
|
6
|
+
import fs from "node:fs";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import os from "node:os";
|
|
9
|
+
//#region session/core/spawn-env.ts
|
|
10
|
+
var GLIMMERVOID_SCRUB_KEYS = [
|
|
11
|
+
"GLIMMERVOID_PORT",
|
|
12
|
+
"GLIMMERVOID_CONFIG",
|
|
13
|
+
HOOK_URL_ENV,
|
|
14
|
+
AGENT_URL_ENV,
|
|
15
|
+
RTK_PATH_ENV,
|
|
16
|
+
SANE_YOLO_PATH_ENV,
|
|
17
|
+
...[
|
|
18
|
+
"GLIMMERVOID_POSTHOG_API_KEY",
|
|
19
|
+
"GLIMMERVOID_TELEGRAM_BOT_TOKEN",
|
|
20
|
+
"GLIMMERVOID_CLAUDE_OAUTH_TOKEN"
|
|
21
|
+
]
|
|
22
|
+
];
|
|
23
|
+
var SANE_YOLO_GUARD_KEYS = [SANE_YOLO_PATH_ENV, ...Object.keys(saneYoloEnv(""))];
|
|
24
|
+
var SAFETY_NET_ENV_PREFIXES = ["CC_SAFETY_NET_", "SAFETY_NET_"];
|
|
25
|
+
var LAUNCHING_TERMINAL_IDENTITY_KEYS = ["TERM_PROGRAM", "TERM_PROGRAM_VERSION"];
|
|
26
|
+
function normalizePathEntry(entry) {
|
|
27
|
+
return entry.replace(/\\/g, "/").toLowerCase();
|
|
28
|
+
}
|
|
29
|
+
function isWindowsDriveColon(value, index, entryStart) {
|
|
30
|
+
if (path.delimiter !== ":") return false;
|
|
31
|
+
if (index !== entryStart + 1) return false;
|
|
32
|
+
if (!/[A-Za-z]/.test(value[index - 1] || "")) return false;
|
|
33
|
+
return value[index + 1] === "\\" || value[index + 1] === "/";
|
|
34
|
+
}
|
|
35
|
+
function splitPathEntries(value) {
|
|
36
|
+
const entries = [];
|
|
37
|
+
let entryStart = 0;
|
|
38
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
39
|
+
if (value[index] !== path.delimiter) continue;
|
|
40
|
+
if (isWindowsDriveColon(value, index, entryStart)) continue;
|
|
41
|
+
entries.push(value.slice(entryStart, index));
|
|
42
|
+
entryStart = index + 1;
|
|
43
|
+
}
|
|
44
|
+
entries.push(value.slice(entryStart));
|
|
45
|
+
return entries.filter(Boolean);
|
|
46
|
+
}
|
|
47
|
+
function prependPathDir(env, prependPathDirValue) {
|
|
48
|
+
if (!prependPathDirValue) return;
|
|
49
|
+
const pathKey = Object.keys(env).find((key) => key.toLowerCase() === "path") || "PATH";
|
|
50
|
+
const existingPath = env[pathKey] || "";
|
|
51
|
+
const pathEntries = splitPathEntries(existingPath);
|
|
52
|
+
const normalizedPrependDir = normalizePathEntry(prependPathDirValue);
|
|
53
|
+
if (pathEntries.some((entry) => normalizePathEntry(entry) === normalizedPrependDir)) return;
|
|
54
|
+
if (!existingPath) {
|
|
55
|
+
env[pathKey] = prependPathDirValue;
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
env[pathKey] = `${prependPathDirValue}${path.delimiter}${existingPath}`;
|
|
59
|
+
}
|
|
60
|
+
function isSafetyNetKey(key) {
|
|
61
|
+
const upperKey = key.toUpperCase();
|
|
62
|
+
return SAFETY_NET_ENV_PREFIXES.some((prefix) => upperKey.startsWith(prefix));
|
|
63
|
+
}
|
|
64
|
+
function isSaneYoloGuarded(extraEnv) {
|
|
65
|
+
if (!extraEnv) return false;
|
|
66
|
+
return SANE_YOLO_GUARD_KEYS.some((key) => extraEnv[key] !== void 0);
|
|
67
|
+
}
|
|
68
|
+
function scrubInheritedSafetyNetEnv(env) {
|
|
69
|
+
for (const key of Object.keys(env)) if (isSafetyNetKey(key)) delete env[key];
|
|
70
|
+
}
|
|
71
|
+
function buildAgentEnv(baseEnv, extraEnv, profile, { prependPathDir: pathDir = null } = {}) {
|
|
72
|
+
const env = { ...baseEnv };
|
|
73
|
+
for (const key of profile.scrub || []) delete env[key];
|
|
74
|
+
for (const key of GLIMMERVOID_SCRUB_KEYS) delete env[key];
|
|
75
|
+
for (const key of LAUNCHING_TERMINAL_IDENTITY_KEYS) delete env[key];
|
|
76
|
+
if (isSaneYoloGuarded(extraEnv)) scrubInheritedSafetyNetEnv(env);
|
|
77
|
+
Object.assign(env, extraEnv || {});
|
|
78
|
+
Object.assign(env, profile.set || {});
|
|
79
|
+
prependPathDir(env, pathDir);
|
|
80
|
+
return env;
|
|
81
|
+
}
|
|
82
|
+
//#endregion
|
|
83
|
+
//#region session/core/grok-hooks-file-core.ts
|
|
84
|
+
function hookGroup(command) {
|
|
85
|
+
return [{ hooks: [{
|
|
86
|
+
type: "command",
|
|
87
|
+
command
|
|
88
|
+
}] }];
|
|
89
|
+
}
|
|
90
|
+
function renderGrokHooksFile({ relayPath, events, hookToolRelayPath }) {
|
|
91
|
+
const hooks = {};
|
|
92
|
+
for (const event of events) {
|
|
93
|
+
const command = buildHookCommand(relayPath, event);
|
|
94
|
+
if (!command) return null;
|
|
95
|
+
hooks[event] = hookGroup(command);
|
|
96
|
+
}
|
|
97
|
+
if (hookToolRelayPath) {
|
|
98
|
+
const command = buildHookCommand(hookToolRelayPath, "saneYolo");
|
|
99
|
+
if (!command) return null;
|
|
100
|
+
hooks.PreToolUse = hookGroup(command);
|
|
101
|
+
}
|
|
102
|
+
return `${JSON.stringify({ hooks }, null, 2)}\n`;
|
|
103
|
+
}
|
|
104
|
+
function hasOnlyKeys(value, expectedKeys) {
|
|
105
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
106
|
+
const actualKeys = Object.keys(value).sort();
|
|
107
|
+
const sortedExpectedKeys = [...expectedKeys].sort();
|
|
108
|
+
return actualKeys.length === sortedExpectedKeys.length && actualKeys.every((key, index) => key === sortedExpectedKeys[index]);
|
|
109
|
+
}
|
|
110
|
+
var MANAGED_RELAY_RE = /(?:^|\/)(hook-relay|hook-tool-relay)\.(?:js|ts)$/;
|
|
111
|
+
function isManagedCommand(command, event) {
|
|
112
|
+
if (typeof command !== "string") return false;
|
|
113
|
+
const match = command.match(/^node (?:(?:"([^"\r\n]+)")|([^\s"']+)) ([A-Za-z][A-Za-z0-9_-]{0,63})$/);
|
|
114
|
+
if (!match) return false;
|
|
115
|
+
const relayPath = match[1] || match[2];
|
|
116
|
+
const relayMatch = relayPath.match(MANAGED_RELAY_RE);
|
|
117
|
+
if (!relayMatch) return false;
|
|
118
|
+
const expectedRelay = event === "PreToolUse" ? "hook-tool-relay" : "hook-relay";
|
|
119
|
+
const expectedToken = event === "PreToolUse" ? "saneYolo" : event;
|
|
120
|
+
if (relayMatch[1] !== expectedRelay || match[3] !== expectedToken) return false;
|
|
121
|
+
return buildHookCommand(relayPath, expectedToken) === command;
|
|
122
|
+
}
|
|
123
|
+
function isManagedHookGroup(group, event) {
|
|
124
|
+
if (!Array.isArray(group) || group.length !== 1) return false;
|
|
125
|
+
const matcherGroup = group[0];
|
|
126
|
+
if (!hasOnlyKeys(matcherGroup, ["hooks"])) return false;
|
|
127
|
+
if (!Array.isArray(matcherGroup.hooks) || matcherGroup.hooks.length !== 1) return false;
|
|
128
|
+
const handler = matcherGroup.hooks[0];
|
|
129
|
+
if (!hasOnlyKeys(handler, ["type", "command"])) return false;
|
|
130
|
+
if (handler.type !== "command") return false;
|
|
131
|
+
return isManagedCommand(handler.command, event);
|
|
132
|
+
}
|
|
133
|
+
function classifyGrokHooksFile(contents, { relayPath, events, managedEventSets = [], hookToolRelayPath }) {
|
|
134
|
+
if (contents == null) return "absent";
|
|
135
|
+
if (contents === renderGrokHooksFile({
|
|
136
|
+
relayPath,
|
|
137
|
+
events,
|
|
138
|
+
hookToolRelayPath
|
|
139
|
+
})) return "current";
|
|
140
|
+
if (contents === renderGrokHooksFile({
|
|
141
|
+
relayPath,
|
|
142
|
+
events
|
|
143
|
+
})) return "current";
|
|
144
|
+
let parsed = null;
|
|
145
|
+
try {
|
|
146
|
+
parsed = JSON.parse(contents);
|
|
147
|
+
} catch {
|
|
148
|
+
return "foreign";
|
|
149
|
+
}
|
|
150
|
+
if (!hasOnlyKeys(parsed, ["hooks"])) return "foreign";
|
|
151
|
+
const hooksValue = parsed.hooks;
|
|
152
|
+
if (hooksValue === null || hooksValue === void 0) throw new TypeError("hooks must be an object");
|
|
153
|
+
if (typeof hooksValue !== "object" || Array.isArray(hooksValue)) return "foreign";
|
|
154
|
+
const actualEvents = Object.keys(hooksValue);
|
|
155
|
+
if (!hasOnlyKeys(hooksValue, actualEvents)) return "foreign";
|
|
156
|
+
const hooks = hooksValue;
|
|
157
|
+
if (![events, ...managedEventSets].some((managedEvents) => hasOnlyKeys(hooks, managedEvents) || hasOnlyKeys(hooks, [...managedEvents, "PreToolUse"]))) return "foreign";
|
|
158
|
+
for (const event of actualEvents) if (!isManagedHookGroup(hooks[event], event)) return "foreign";
|
|
159
|
+
return "managed-stale";
|
|
160
|
+
}
|
|
161
|
+
var CIRCLE_HALVES_SPINNER_CODEPOINTS = /* @__PURE__ */ new Set([
|
|
162
|
+
9680,
|
|
163
|
+
9681,
|
|
164
|
+
9682,
|
|
165
|
+
9683
|
|
166
|
+
]);
|
|
167
|
+
function isBrailleChar(char) {
|
|
168
|
+
if (!char) return false;
|
|
169
|
+
const codePoint = char.codePointAt(0) ?? 0;
|
|
170
|
+
return codePoint >= 10240 && codePoint <= 10495;
|
|
171
|
+
}
|
|
172
|
+
function isSpinnerChar(char) {
|
|
173
|
+
if (!char) return false;
|
|
174
|
+
if (isBrailleChar(char)) return true;
|
|
175
|
+
return CIRCLE_HALVES_SPINNER_CODEPOINTS.has(char.codePointAt(0) ?? 0);
|
|
176
|
+
}
|
|
177
|
+
function isPathLikeTitle(title) {
|
|
178
|
+
return title.includes("/") || title.includes("\\");
|
|
179
|
+
}
|
|
180
|
+
function firstCharOfTitle(title) {
|
|
181
|
+
if (title.length === 0) return "";
|
|
182
|
+
return String.fromCodePoint(title.codePointAt(0) ?? 0);
|
|
183
|
+
}
|
|
184
|
+
function classifyAgentTitle(title, { cwdBasename = null }, vocabulary) {
|
|
185
|
+
const trimmedTitle = title.trim();
|
|
186
|
+
if (vocabulary.busyTitle && trimmedTitle === vocabulary.busyTitle) return "working";
|
|
187
|
+
if (vocabulary.idleTitle && trimmedTitle === vocabulary.idleTitle) return "ready";
|
|
188
|
+
if (isPathLikeTitle(title)) return "ignore";
|
|
189
|
+
if (vocabulary.isSpinnerChar(firstCharOfTitle(title))) return "working";
|
|
190
|
+
if (!cwdBasename) return "ignore";
|
|
191
|
+
const cwdAwareClassification = vocabulary.classifyAgainstCwdBasename?.(title, cwdBasename) ?? null;
|
|
192
|
+
if (cwdAwareClassification) return cwdAwareClassification;
|
|
193
|
+
if (trimmedTitle === cwdBasename) return "ready";
|
|
194
|
+
return "unknown";
|
|
195
|
+
}
|
|
196
|
+
//#endregion
|
|
197
|
+
//#region session/adapters/grok.ts
|
|
198
|
+
var ID = "grok";
|
|
199
|
+
var COMMAND_NAME = "grok";
|
|
200
|
+
var RELAY_PATH = relayPath("hook-relay");
|
|
201
|
+
var HOOK_TOOL_RELAY_PATH = relayPath("hook-tool-relay");
|
|
202
|
+
var HOOK_EVENTS = [
|
|
203
|
+
"UserPromptSubmit",
|
|
204
|
+
"Stop",
|
|
205
|
+
"StopFailure",
|
|
206
|
+
"StopCancelled",
|
|
207
|
+
"Notification",
|
|
208
|
+
"SubagentStart",
|
|
209
|
+
"SubagentStop"
|
|
210
|
+
];
|
|
211
|
+
var MANAGED_HOOK_EVENT_SETS = [[
|
|
212
|
+
"UserPromptSubmit",
|
|
213
|
+
"Stop",
|
|
214
|
+
"StopFailure",
|
|
215
|
+
"StopCancelled",
|
|
216
|
+
"Notification"
|
|
217
|
+
]];
|
|
218
|
+
var ACTION_REQUIRED_MARKER = String.fromCodePoint(9888);
|
|
219
|
+
var CLAUDE_COMPAT_HOOKS_ENV = "GROK_CLAUDE_HOOKS_ENABLED";
|
|
220
|
+
var PROJECT_CONFIG_CANDIDATES = Object.freeze([Object.freeze({
|
|
221
|
+
relPath: ".claude/settings.json",
|
|
222
|
+
presenceIsHit: false
|
|
223
|
+
}), Object.freeze({
|
|
224
|
+
relPath: ".claude/settings.local.json",
|
|
225
|
+
presenceIsHit: false
|
|
226
|
+
})]);
|
|
227
|
+
var envProfile = {
|
|
228
|
+
scrub: [],
|
|
229
|
+
set: { [CLAUDE_COMPAT_HOOKS_ENV]: "false" }
|
|
230
|
+
};
|
|
231
|
+
function notificationType(payload) {
|
|
232
|
+
return String(payload?.notificationType || payload?.notification_type || "").toLowerCase();
|
|
233
|
+
}
|
|
234
|
+
function isMainSessionPayload(payload) {
|
|
235
|
+
return !payload?.subagentType && !payload?.subagent_type;
|
|
236
|
+
}
|
|
237
|
+
function mapBackgroundTask(task) {
|
|
238
|
+
if (!task || typeof task !== "object" || Array.isArray(task)) return task;
|
|
239
|
+
const entry = task;
|
|
240
|
+
return {
|
|
241
|
+
...entry,
|
|
242
|
+
...typeof entry.agentType === "string" ? { agent_type: entry.agentType } : {}
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
function mapHookPayload(_event, payload) {
|
|
246
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload)) return payload;
|
|
247
|
+
return {
|
|
248
|
+
...payload,
|
|
249
|
+
...typeof payload.subagentId === "string" ? { agent_id: payload.subagentId } : {},
|
|
250
|
+
...typeof payload.subagentType === "string" ? { agent_type: payload.subagentType } : {},
|
|
251
|
+
...Array.isArray(payload.backgroundTasks) ? { background_tasks: payload.backgroundTasks.map(mapBackgroundTask) } : {}
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
function mayContributeHooks(configText) {
|
|
255
|
+
if (typeof configText !== "string") return false;
|
|
256
|
+
let settings;
|
|
257
|
+
try {
|
|
258
|
+
settings = JSON.parse(configText);
|
|
259
|
+
} catch {
|
|
260
|
+
return true;
|
|
261
|
+
}
|
|
262
|
+
if (!settings || typeof settings !== "object" || Array.isArray(settings)) return false;
|
|
263
|
+
return Object.hasOwn(settings, "hooks");
|
|
264
|
+
}
|
|
265
|
+
function mapHookToSignal(event, payload) {
|
|
266
|
+
const normalizedEvent = String(event || "").toLowerCase();
|
|
267
|
+
if (normalizedEvent === "subagentstart") return "subagent-start";
|
|
268
|
+
if (normalizedEvent === "subagentstop") return "subagent-stop";
|
|
269
|
+
if (!isMainSessionPayload(payload)) return null;
|
|
270
|
+
switch (normalizedEvent) {
|
|
271
|
+
case "sessionstart": return "session-start";
|
|
272
|
+
case "sessionend": return "session-end";
|
|
273
|
+
case "userpromptsubmit": return "resume";
|
|
274
|
+
case "stop": return payload?.reason === "end_turn" ? "ready" : null;
|
|
275
|
+
case "stopfailure":
|
|
276
|
+
case "stopcancelled": return "ready";
|
|
277
|
+
case "notification": {
|
|
278
|
+
const type = notificationType(payload);
|
|
279
|
+
if (type === "idle_prompt") return "ready";
|
|
280
|
+
if (type === "permission_prompt" || type === "approval_required") return "awaiting-input";
|
|
281
|
+
return null;
|
|
282
|
+
}
|
|
283
|
+
default: return null;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
function mapHookConfidence(event, payload) {
|
|
287
|
+
if (String(event || "").toLowerCase() === "notification" && notificationType(payload) === "idle_prompt") return "low";
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
function mapHookPromptKind(event, payload) {
|
|
291
|
+
if (String(event || "").toLowerCase() !== "notification") return null;
|
|
292
|
+
const type = notificationType(payload);
|
|
293
|
+
if (type === "permission_prompt" || type === "approval_required") return "permission";
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
function sessionIdOf(payload) {
|
|
297
|
+
return payload?.sessionId;
|
|
298
|
+
}
|
|
299
|
+
function classifyTitle(title) {
|
|
300
|
+
const normalizedTitle = String(title || "");
|
|
301
|
+
if (isPathLikeTitle(normalizedTitle)) return "ignore";
|
|
302
|
+
if (isBrailleChar(firstCharOfTitle(normalizedTitle))) return "working";
|
|
303
|
+
if (normalizedTitle.startsWith(ACTION_REQUIRED_MARKER)) return "awaiting-input";
|
|
304
|
+
return "unknown";
|
|
305
|
+
}
|
|
306
|
+
var titleProfile = {
|
|
307
|
+
classifyTitle,
|
|
308
|
+
taskTitle: {
|
|
309
|
+
readsTranscriptTitle: false,
|
|
310
|
+
genericTitles: [ID],
|
|
311
|
+
agentSuffix: ` - ${ID}`
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
function grokHome(env = process.env, homedir = os.homedir(), platform = process.platform) {
|
|
315
|
+
const pathApi = platform === "win32" ? path.win32 : path;
|
|
316
|
+
const configuredHome = typeof env.GROK_HOME === "string" ? env.GROK_HOME.trim() : "";
|
|
317
|
+
if (configuredHome) return pathApi.resolve(configuredHome);
|
|
318
|
+
return pathApi.join(homedir, ".grok");
|
|
319
|
+
}
|
|
320
|
+
function hooksFilePath(env = process.env, homedir = os.homedir()) {
|
|
321
|
+
return path.join(grokHome(env, homedir), "hooks", "glimmervoid.json");
|
|
322
|
+
}
|
|
323
|
+
function nativeBinaryPath({ platform = process.platform, env = process.env, homedir = os.homedir() } = {}) {
|
|
324
|
+
const pathApi = platform === "win32" ? path.win32 : path;
|
|
325
|
+
const binaryName = platform === "win32" ? "grok.exe" : "grok";
|
|
326
|
+
return pathApi.join(grokHome(env, homedir, platform), "bin", binaryName);
|
|
327
|
+
}
|
|
328
|
+
function resolveCommand({ platform = process.platform, env = process.env, homedir = os.homedir(), existsSync = fs.existsSync, realpathSync = fs.realpathSync, warn = console.warn } = {}) {
|
|
329
|
+
const candidate = nativeBinaryPath({
|
|
330
|
+
platform,
|
|
331
|
+
env,
|
|
332
|
+
homedir
|
|
333
|
+
});
|
|
334
|
+
try {
|
|
335
|
+
if (existsSync(candidate)) return {
|
|
336
|
+
path: realpathSync(candidate),
|
|
337
|
+
kind: "exe"
|
|
338
|
+
};
|
|
339
|
+
} catch (error) {
|
|
340
|
+
warn(`[glimmervoid] could not resolve the native 'grok' binary at ${candidate}: ${error instanceof Error ? error.message : String(error)}`);
|
|
341
|
+
return {
|
|
342
|
+
path: null,
|
|
343
|
+
kind: "unresolved"
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
warn(`[glimmervoid] could not resolve the native 'grok' binary at ${candidate}`);
|
|
347
|
+
return {
|
|
348
|
+
path: null,
|
|
349
|
+
kind: "unresolved"
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
function buildSpawnCommand({ resolved, settingsArgs = [], agentArgs = [] }) {
|
|
353
|
+
if (!resolved?.path) throw new Error("the native grok binary is not resolved");
|
|
354
|
+
return {
|
|
355
|
+
file: resolved.path,
|
|
356
|
+
args: [...settingsArgs, ...agentArgs]
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
function buildEnv(baseEnv, extraEnv, options) {
|
|
360
|
+
return buildAgentEnv(baseEnv, extraEnv, envProfile, options);
|
|
361
|
+
}
|
|
362
|
+
function buildArgs({ dangerouslySkipPermissions = false, resumeSessionId = null, extraArgs = [], initialPrompt = null } = {}) {
|
|
363
|
+
const args = ["--no-auto-update"];
|
|
364
|
+
if (dangerouslySkipPermissions) args.push("--always-approve");
|
|
365
|
+
if (resumeSessionId) args.push("-r", resumeSessionId);
|
|
366
|
+
if (extraArgs.length > 0) args.push(...extraArgs);
|
|
367
|
+
if (initialPrompt != null) args.push(initialPrompt);
|
|
368
|
+
return args;
|
|
369
|
+
}
|
|
370
|
+
var grok = {
|
|
371
|
+
id: ID,
|
|
372
|
+
label: "Grok Build",
|
|
373
|
+
usageVendor: "grok",
|
|
374
|
+
commandName: COMMAND_NAME,
|
|
375
|
+
envProfile,
|
|
376
|
+
titleProfile,
|
|
377
|
+
hooks: {
|
|
378
|
+
mapSignal: mapHookToSignal,
|
|
379
|
+
mapConfidence: mapHookConfidence,
|
|
380
|
+
mapPromptKind: mapHookPromptKind,
|
|
381
|
+
mapPayload: mapHookPayload,
|
|
382
|
+
injection: {
|
|
383
|
+
kind: "home-hooks-file",
|
|
384
|
+
filePath: hooksFilePath,
|
|
385
|
+
expectedContents: () => renderGrokHooksFile({
|
|
386
|
+
relayPath: RELAY_PATH,
|
|
387
|
+
events: HOOK_EVENTS,
|
|
388
|
+
hookToolRelayPath: HOOK_TOOL_RELAY_PATH
|
|
389
|
+
}),
|
|
390
|
+
classifyContents: (contents) => classifyGrokHooksFile(contents, {
|
|
391
|
+
relayPath: RELAY_PATH,
|
|
392
|
+
events: HOOK_EVENTS,
|
|
393
|
+
managedEventSets: MANAGED_HOOK_EVENT_SETS,
|
|
394
|
+
hookToolRelayPath: HOOK_TOOL_RELAY_PATH
|
|
395
|
+
}),
|
|
396
|
+
projectConfigCandidates: PROJECT_CONFIG_CANDIDATES,
|
|
397
|
+
mayContributeHooks
|
|
398
|
+
}
|
|
399
|
+
},
|
|
400
|
+
resolveCommand,
|
|
401
|
+
buildSpawnCommand,
|
|
402
|
+
buildEnv,
|
|
403
|
+
buildArgs,
|
|
404
|
+
sessionIdOf,
|
|
405
|
+
mapHookPayload,
|
|
406
|
+
mapHookToSignal,
|
|
407
|
+
mapHookConfidence,
|
|
408
|
+
mapHookPromptKind,
|
|
409
|
+
classifyTitle,
|
|
410
|
+
grokHome,
|
|
411
|
+
hooksFilePath,
|
|
412
|
+
nativeBinaryPath,
|
|
413
|
+
mayContributeHooks,
|
|
414
|
+
PROJECT_CONFIG_CANDIDATES,
|
|
415
|
+
CLAUDE_COMPAT_HOOKS_ENV,
|
|
416
|
+
HOOK_TOOL_RELAY_PATH,
|
|
417
|
+
HOOK_EVENTS,
|
|
418
|
+
MANAGED_HOOK_EVENT_SETS,
|
|
419
|
+
RELAY_PATH,
|
|
420
|
+
ACTION_REQUIRED_MARKER,
|
|
421
|
+
capabilities: {
|
|
422
|
+
hooks: true,
|
|
423
|
+
awaitingInput: true,
|
|
424
|
+
backgroundAgents: true,
|
|
425
|
+
resume: true,
|
|
426
|
+
statusLine: false,
|
|
427
|
+
rtk: false,
|
|
428
|
+
saneYolo: true,
|
|
429
|
+
antiSlop: false,
|
|
430
|
+
compactQuiet: false,
|
|
431
|
+
skipPermissionsFlag: true,
|
|
432
|
+
headless: true
|
|
433
|
+
}
|
|
434
|
+
};
|
|
435
|
+
//#endregion
|
|
436
|
+
export { classifyGrokHooksFile as a, isSpinnerChar as i, classifyAgentTitle as n, renderGrokHooksFile as o, isBrailleChar as r, buildAgentEnv as s, grok as t };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region session/core/hook-command-core.ts
|
|
2
|
+
var SAFE_PATH_RE = /^[A-Za-z0-9_.:/\\ -]+$/;
|
|
3
|
+
var SAFE_EVENT_RE = /^[A-Za-z][A-Za-z0-9_-]{0,63}$/;
|
|
4
|
+
function buildHookCommand(relayPath, event, argvTail = []) {
|
|
5
|
+
const rawPath = String(relayPath);
|
|
6
|
+
const rawEvent = String(event);
|
|
7
|
+
if (!SAFE_PATH_RE.test(rawPath)) return null;
|
|
8
|
+
if (!SAFE_EVENT_RE.test(rawEvent)) return null;
|
|
9
|
+
if (argvTail.some((argument) => !/^[A-Za-z0-9_-]+$/.test(argument))) return null;
|
|
10
|
+
const forwardSlashedPath = rawPath.replace(/\\/g, "/");
|
|
11
|
+
return `node ${/\s/.test(forwardSlashedPath) ? `"${forwardSlashedPath}"` : forwardSlashedPath} ${rawEvent}${argvTail.length ? ` ${argvTail.join(" ")}` : ""}`;
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
export { buildHookCommand as t };
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
//#region session/core/hook-relay-core.ts
|
|
2
|
+
var HOOK_URL_ENV = "GLIMMERVOID_HOOK_URL";
|
|
3
|
+
var MAX_RESPONSE_BYTES = 65536;
|
|
4
|
+
var LOOPBACK_HOSTS = /* @__PURE__ */ new Set([
|
|
5
|
+
"127.0.0.1",
|
|
6
|
+
"::1",
|
|
7
|
+
"[::1]",
|
|
8
|
+
"localhost"
|
|
9
|
+
]);
|
|
10
|
+
var EVENT_RE = /^[a-zA-Z][a-zA-Z0-9_-]{0,63}$/;
|
|
11
|
+
var HOOK_PATH_PREFIX = "/hook/";
|
|
12
|
+
function readHookUrl(env) {
|
|
13
|
+
const raw = env ? env[HOOK_URL_ENV] : null;
|
|
14
|
+
if (typeof raw !== "string") return null;
|
|
15
|
+
return raw.trim() || null;
|
|
16
|
+
}
|
|
17
|
+
function normalizeEvent(event) {
|
|
18
|
+
if (typeof event !== "string") return null;
|
|
19
|
+
const trimmed = event.trim();
|
|
20
|
+
if (!EVENT_RE.test(trimmed)) return null;
|
|
21
|
+
return trimmed.toLowerCase();
|
|
22
|
+
}
|
|
23
|
+
function resolveHookTarget(baseUrl, event, pathPrefix = HOOK_PATH_PREFIX) {
|
|
24
|
+
let target;
|
|
25
|
+
try {
|
|
26
|
+
target = new URL(baseUrl);
|
|
27
|
+
} catch {
|
|
28
|
+
return {
|
|
29
|
+
url: null,
|
|
30
|
+
reason: "bad-url"
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
if (target.protocol !== "http:") return {
|
|
34
|
+
url: null,
|
|
35
|
+
reason: "not-http"
|
|
36
|
+
};
|
|
37
|
+
if (!LOOPBACK_HOSTS.has(target.hostname)) return {
|
|
38
|
+
url: null,
|
|
39
|
+
reason: "not-loopback"
|
|
40
|
+
};
|
|
41
|
+
if (!target.pathname.startsWith(pathPrefix)) return {
|
|
42
|
+
url: null,
|
|
43
|
+
reason: "not-hook-path"
|
|
44
|
+
};
|
|
45
|
+
const base = target.pathname.replace(/\/+$/, "");
|
|
46
|
+
target.pathname = `${base}/${event}`;
|
|
47
|
+
return {
|
|
48
|
+
url: target.toString(),
|
|
49
|
+
reason: "ok"
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function decideRelayPost({ env = {}, event = null, payloadBytes = 0 } = {}) {
|
|
53
|
+
const baseUrl = readHookUrl(env);
|
|
54
|
+
if (!baseUrl) return {
|
|
55
|
+
post: false,
|
|
56
|
+
url: null,
|
|
57
|
+
reason: "no-hook-url"
|
|
58
|
+
};
|
|
59
|
+
const name = normalizeEvent(event);
|
|
60
|
+
if (!name) return {
|
|
61
|
+
post: false,
|
|
62
|
+
url: null,
|
|
63
|
+
reason: "bad-event"
|
|
64
|
+
};
|
|
65
|
+
if (!Number.isFinite(payloadBytes) || payloadBytes < 0) return {
|
|
66
|
+
post: false,
|
|
67
|
+
url: null,
|
|
68
|
+
reason: "bad-payload"
|
|
69
|
+
};
|
|
70
|
+
if (payloadBytes > 65536) return {
|
|
71
|
+
post: false,
|
|
72
|
+
url: null,
|
|
73
|
+
reason: "payload-too-large"
|
|
74
|
+
};
|
|
75
|
+
const target = resolveHookTarget(baseUrl, name);
|
|
76
|
+
if (!target.url) return {
|
|
77
|
+
post: false,
|
|
78
|
+
url: null,
|
|
79
|
+
reason: target.reason
|
|
80
|
+
};
|
|
81
|
+
return {
|
|
82
|
+
post: true,
|
|
83
|
+
url: target.url,
|
|
84
|
+
reason: "ok"
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
//#endregion
|
|
88
|
+
export { resolveHookTarget as i, MAX_RESPONSE_BYTES as n, decideRelayPost as r, HOOK_URL_ENV as t };
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { r as resolvePathCommandMatches } from "./spawn-command-Cc40FiZI.js";
|
|
2
|
+
import { a as SANE_YOLO_PATH_ENV, n as RTK_PATH_ENV, o as saneYoloEnv } from "./rtk-hook-core-Bl6gYHPN.js";
|
|
3
|
+
import { t as buildHookCommand } from "./hook-command-core-DclEoE9e.js";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
//#region session/core/hook-tools.ts
|
|
6
|
+
function firstExistingFile(candidates, fsApi) {
|
|
7
|
+
for (const candidate of candidates) try {
|
|
8
|
+
if (fsApi.statSync(candidate).isFile()) return path.resolve(candidate);
|
|
9
|
+
} catch {}
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
function resolveRtkPath({ glimmervoidHome, platform, exec, fsApi }) {
|
|
13
|
+
const bundled = firstExistingFile([path.join(glimmervoidHome, "bin", "rtk.exe"), path.join(glimmervoidHome, "bin", "rtk")], fsApi);
|
|
14
|
+
if (bundled) return bundled;
|
|
15
|
+
const matches = resolvePathCommandMatches("rtk", {
|
|
16
|
+
platform,
|
|
17
|
+
exec
|
|
18
|
+
});
|
|
19
|
+
if (matches.length === 0) return null;
|
|
20
|
+
const firstMatch = matches[0];
|
|
21
|
+
if (!firstMatch) return null;
|
|
22
|
+
return path.resolve(firstMatch);
|
|
23
|
+
}
|
|
24
|
+
function quoteCommandPath(commandPath) {
|
|
25
|
+
if (!/\s/.test(commandPath)) return commandPath;
|
|
26
|
+
return `"${commandPath}"`;
|
|
27
|
+
}
|
|
28
|
+
function toForwardSlashes(commandPath) {
|
|
29
|
+
return commandPath.replace(/\\/g, "/");
|
|
30
|
+
}
|
|
31
|
+
function buildRtkHookEntry(rtkPath) {
|
|
32
|
+
return {
|
|
33
|
+
matcher: "Bash",
|
|
34
|
+
hooks: [{
|
|
35
|
+
type: "command",
|
|
36
|
+
command: `${quoteCommandPath(toForwardSlashes(rtkPath))} hook claude`
|
|
37
|
+
}]
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function codexGroup(command) {
|
|
41
|
+
if (!command) return null;
|
|
42
|
+
return `{matcher='Bash',hooks=[{type='command',command='${command}'}]}`;
|
|
43
|
+
}
|
|
44
|
+
var HOOK_TOOLS = {
|
|
45
|
+
rtk: {
|
|
46
|
+
capability: "rtk",
|
|
47
|
+
purpose: "rtk command rewriting",
|
|
48
|
+
env: (tool) => ({ [RTK_PATH_ENV]: tool.binPath }),
|
|
49
|
+
claudeEntry: (tool) => buildRtkHookEntry(tool.binPath),
|
|
50
|
+
codexGroup: (_tool, relayPath) => codexGroup(buildHookCommand(relayPath, "rtk"))
|
|
51
|
+
},
|
|
52
|
+
saneYolo: {
|
|
53
|
+
capability: "saneYolo",
|
|
54
|
+
purpose: "Sane YOLO catastrophic command protection",
|
|
55
|
+
env: (tool, homeDir) => ({
|
|
56
|
+
[SANE_YOLO_PATH_ENV]: tool.binPath,
|
|
57
|
+
...saneYoloEnv(homeDir)
|
|
58
|
+
}),
|
|
59
|
+
claudeEntry: (tool) => ({
|
|
60
|
+
matcher: "Bash|PowerShell|Monitor",
|
|
61
|
+
hooks: [{
|
|
62
|
+
type: "command",
|
|
63
|
+
command: `node "${toForwardSlashes(tool.binPath)}" hook --coding-cli`
|
|
64
|
+
}]
|
|
65
|
+
}),
|
|
66
|
+
codexGroup: (tool) => codexGroup(buildHookCommand(tool.binPath, "hook", ["--codex"]))
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
function mergeCodexPreToolUse(groups) {
|
|
70
|
+
if (groups.length === 0) return [];
|
|
71
|
+
return ["-c", `hooks.PreToolUse=[${groups.join(",")}]`];
|
|
72
|
+
}
|
|
73
|
+
//#endregion
|
|
74
|
+
export { mergeCodexPreToolUse as n, resolveRtkPath as r, HOOK_TOOLS as t };
|