@intutic/sync-daemon 1.10.0 → 2.0.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/README.md +2 -2
- package/dist/agentReporter.d.ts +205 -0
- package/dist/agentReporter.d.ts.map +1 -0
- package/dist/agentReporter.js +394 -0
- package/dist/agentReporter.js.map +1 -0
- package/dist/configReader.d.ts +39 -2
- package/dist/configReader.d.ts.map +1 -1
- package/dist/configReader.js +56 -2
- package/dist/configReader.js.map +1 -1
- package/dist/configWriter.d.ts +51 -1
- package/dist/configWriter.d.ts.map +1 -1
- package/dist/configWriter.js +490 -63
- package/dist/configWriter.js.map +1 -1
- package/dist/harness/antigravityHooks.d.ts.map +1 -1
- package/dist/harness/antigravityHooks.js +33 -55
- package/dist/harness/antigravityHooks.js.map +1 -1
- package/dist/harness/claudeCodeHooks.d.ts +47 -13
- package/dist/harness/claudeCodeHooks.d.ts.map +1 -1
- package/dist/harness/claudeCodeHooks.js +316 -54
- package/dist/harness/claudeCodeHooks.js.map +1 -1
- package/dist/harness/claudeDesktopHooks.d.ts.map +1 -1
- package/dist/harness/claudeDesktopHooks.js +35 -48
- package/dist/harness/claudeDesktopHooks.js.map +1 -1
- package/dist/harness/clineHooks.d.ts.map +1 -1
- package/dist/harness/clineHooks.js +42 -34
- package/dist/harness/clineHooks.js.map +1 -1
- package/dist/harness/codexHooks.d.ts +36 -0
- package/dist/harness/codexHooks.d.ts.map +1 -0
- package/dist/harness/codexHooks.js +227 -0
- package/dist/harness/codexHooks.js.map +1 -0
- package/dist/harness/continueHooks.d.ts +45 -5
- package/dist/harness/continueHooks.d.ts.map +1 -1
- package/dist/harness/continueHooks.js +225 -5
- package/dist/harness/continueHooks.js.map +1 -1
- package/dist/harness/cursorHooks.d.ts +31 -0
- package/dist/harness/cursorHooks.d.ts.map +1 -1
- package/dist/harness/cursorHooks.js +78 -49
- package/dist/harness/cursorHooks.js.map +1 -1
- package/dist/harness/dshHooks.d.ts +198 -0
- package/dist/harness/dshHooks.d.ts.map +1 -0
- package/dist/harness/dshHooks.js +569 -0
- package/dist/harness/dshHooks.js.map +1 -0
- package/dist/harness/gateBody.d.ts +422 -0
- package/dist/harness/gateBody.d.ts.map +1 -0
- package/dist/harness/gateBody.js +1816 -0
- package/dist/harness/gateBody.js.map +1 -0
- package/dist/harness/gateKind.d.ts +164 -0
- package/dist/harness/gateKind.d.ts.map +1 -0
- package/dist/harness/gateKind.js +143 -0
- package/dist/harness/gateKind.js.map +1 -0
- package/dist/harness/githubCopilotHooks.d.ts +54 -0
- package/dist/harness/githubCopilotHooks.d.ts.map +1 -0
- package/dist/harness/githubCopilotHooks.js +218 -0
- package/dist/harness/githubCopilotHooks.js.map +1 -0
- package/dist/harness/gooseHooks.d.ts.map +1 -1
- package/dist/harness/gooseHooks.js +67 -37
- package/dist/harness/gooseHooks.js.map +1 -1
- package/dist/harness/grokHooks.d.ts +77 -0
- package/dist/harness/grokHooks.d.ts.map +1 -0
- package/dist/harness/grokHooks.js +350 -0
- package/dist/harness/grokHooks.js.map +1 -0
- package/dist/harness/hermesHooks.d.ts.map +1 -1
- package/dist/harness/hermesHooks.js +26 -55
- package/dist/harness/hermesHooks.js.map +1 -1
- package/dist/harness/holdRedaction.d.ts +69 -0
- package/dist/harness/holdRedaction.d.ts.map +1 -0
- package/dist/harness/holdRedaction.js +211 -0
- package/dist/harness/holdRedaction.js.map +1 -0
- package/dist/harness/jetbrainsXmlConfig.d.ts +51 -0
- package/dist/harness/jetbrainsXmlConfig.d.ts.map +1 -0
- package/dist/harness/jetbrainsXmlConfig.js +151 -0
- package/dist/harness/jetbrainsXmlConfig.js.map +1 -0
- package/dist/harness/mcpAutoWrite.d.ts +100 -3
- package/dist/harness/mcpAutoWrite.d.ts.map +1 -1
- package/dist/harness/mcpAutoWrite.js +712 -90
- package/dist/harness/mcpAutoWrite.js.map +1 -1
- package/dist/harness/museHooks.d.ts +53 -0
- package/dist/harness/museHooks.d.ts.map +1 -0
- package/dist/harness/museHooks.js +273 -0
- package/dist/harness/museHooks.js.map +1 -0
- package/dist/harness/n8nHooks.d.ts +25 -9
- package/dist/harness/n8nHooks.d.ts.map +1 -1
- package/dist/harness/n8nHooks.js +174 -9
- package/dist/harness/n8nHooks.js.map +1 -1
- package/dist/harness/openCodeHooks.d.ts +93 -0
- package/dist/harness/openCodeHooks.d.ts.map +1 -0
- package/dist/harness/openCodeHooks.js +248 -0
- package/dist/harness/openCodeHooks.js.map +1 -0
- package/dist/harness/openWebuiHooks.d.ts.map +1 -1
- package/dist/harness/openWebuiHooks.js +56 -11
- package/dist/harness/openWebuiHooks.js.map +1 -1
- package/dist/harness/openclawHooks.d.ts.map +1 -1
- package/dist/harness/openclawHooks.js +30 -54
- package/dist/harness/openclawHooks.js.map +1 -1
- package/dist/harness/openhandsHooks.d.ts.map +1 -1
- package/dist/harness/openhandsHooks.js +35 -41
- package/dist/harness/openhandsHooks.js.map +1 -1
- package/dist/harness/piHooks.d.ts.map +1 -1
- package/dist/harness/piHooks.js +31 -58
- package/dist/harness/piHooks.js.map +1 -1
- package/dist/harness/protectedPaths.d.ts +353 -0
- package/dist/harness/protectedPaths.d.ts.map +1 -0
- package/dist/harness/protectedPaths.js +805 -0
- package/dist/harness/protectedPaths.js.map +1 -0
- package/dist/harness/rooCodeHooks.d.ts.map +1 -1
- package/dist/harness/rooCodeHooks.js +34 -48
- package/dist/harness/rooCodeHooks.js.map +1 -1
- package/dist/harness/windsurfHooks.d.ts +72 -0
- package/dist/harness/windsurfHooks.d.ts.map +1 -1
- package/dist/harness/windsurfHooks.js +172 -58
- package/dist/harness/windsurfHooks.js.map +1 -1
- package/dist/harness/windsurfJetBrainsProxy.d.ts +78 -0
- package/dist/harness/windsurfJetBrainsProxy.d.ts.map +1 -0
- package/dist/harness/windsurfJetBrainsProxy.js +159 -0
- package/dist/harness/windsurfJetBrainsProxy.js.map +1 -0
- package/dist/hashReporter.js +1 -1
- package/dist/hashReporter.js.map +1 -1
- package/dist/index.d.ts +12 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -6
- package/dist/index.js.map +1 -1
- package/dist/integrityStore.d.ts +0 -8
- package/dist/integrityStore.d.ts.map +1 -1
- package/dist/integrityStore.js +6 -29
- package/dist/integrityStore.js.map +1 -1
- package/dist/lib/approvedBypasses.d.ts +76 -0
- package/dist/lib/approvedBypasses.d.ts.map +1 -0
- package/dist/lib/approvedBypasses.js +140 -0
- package/dist/lib/approvedBypasses.js.map +1 -0
- package/dist/lib/complianceProbes.d.ts.map +1 -1
- package/dist/lib/complianceProbes.js +5 -0
- package/dist/lib/complianceProbes.js.map +1 -1
- package/dist/lib/decisionsDigest.d.ts +99 -0
- package/dist/lib/decisionsDigest.d.ts.map +1 -0
- package/dist/lib/decisionsDigest.js +199 -0
- package/dist/lib/decisionsDigest.js.map +1 -0
- package/dist/lib/egressPolicy.d.ts +69 -0
- package/dist/lib/egressPolicy.d.ts.map +1 -0
- package/dist/lib/egressPolicy.js +126 -0
- package/dist/lib/egressPolicy.js.map +1 -0
- package/dist/lib/gitWorktrees.d.ts +140 -0
- package/dist/lib/gitWorktrees.d.ts.map +1 -0
- package/dist/lib/gitWorktrees.js +191 -0
- package/dist/lib/gitWorktrees.js.map +1 -0
- package/dist/lib/policySnapshot.d.ts +224 -0
- package/dist/lib/policySnapshot.d.ts.map +1 -0
- package/dist/lib/policySnapshot.js +637 -0
- package/dist/lib/policySnapshot.js.map +1 -0
- package/dist/lib/processPoller.d.ts +44 -0
- package/dist/lib/processPoller.d.ts.map +1 -1
- package/dist/lib/processPoller.js +176 -1
- package/dist/lib/processPoller.js.map +1 -1
- package/dist/lib/runtimeEnv.d.ts +8 -0
- package/dist/lib/runtimeEnv.d.ts.map +1 -1
- package/dist/lib/runtimeEnv.js +3 -0
- package/dist/lib/runtimeEnv.js.map +1 -1
- package/dist/localTrajectoryHeuristics.d.ts +51 -0
- package/dist/localTrajectoryHeuristics.d.ts.map +1 -0
- package/dist/localTrajectoryHeuristics.js +90 -0
- package/dist/localTrajectoryHeuristics.js.map +1 -0
- package/dist/sessionReporter.d.ts +70 -0
- package/dist/sessionReporter.d.ts.map +1 -0
- package/dist/sessionReporter.js +140 -0
- package/dist/sessionReporter.js.map +1 -0
- package/dist/skillWriter.d.ts +1 -1
- package/dist/skillWriter.d.ts.map +1 -1
- package/dist/skillWriter.js +5 -2
- package/dist/skillWriter.js.map +1 -1
- package/dist/syncLoop.d.ts +105 -3
- package/dist/syncLoop.d.ts.map +1 -1
- package/dist/syncLoop.js +397 -65
- package/dist/syncLoop.js.map +1 -1
- package/dist/trajectoryMonitor.d.ts +2 -0
- package/dist/trajectoryMonitor.d.ts.map +1 -1
- package/dist/trajectoryMonitor.js +57 -0
- package/dist/trajectoryMonitor.js.map +1 -1
- package/dist/watcher/driftWatcher.d.ts.map +1 -1
- package/dist/watcher/driftWatcher.js +12 -3
- package/dist/watcher/driftWatcher.js.map +1 -1
- package/dist/watcher/settingsGuard.d.ts +23 -0
- package/dist/watcher/settingsGuard.d.ts.map +1 -1
- package/dist/watcher/settingsGuard.js +202 -17
- package/dist/watcher/settingsGuard.js.map +1 -1
- package/package.json +37 -6
- package/dist/brainIndexer.d.ts +0 -51
- package/dist/brainIndexer.d.ts.map +0 -1
- package/dist/brainIndexer.js +0 -148
- package/dist/brainIndexer.js.map +0 -1
- package/dist/harness/cursorHooksJson.d.ts +0 -29
- package/dist/harness/cursorHooksJson.d.ts.map +0 -1
- package/dist/harness/cursorHooksJson.js +0 -130
- package/dist/harness/cursorHooksJson.js.map +0 -1
- package/dist/harness/gooseHooksWriter.d.ts +0 -27
- package/dist/harness/gooseHooksWriter.d.ts.map +0 -1
- package/dist/harness/gooseHooksWriter.js +0 -147
- package/dist/harness/gooseHooksWriter.js.map +0 -1
- package/dist/harness/openhandsHooksWriter.d.ts +0 -23
- package/dist/harness/openhandsHooksWriter.d.ts.map +0 -1
- package/dist/harness/openhandsHooksWriter.js +0 -146
- package/dist/harness/openhandsHooksWriter.js.map +0 -1
|
@@ -19,18 +19,10 @@ import * as os from 'node:os';
|
|
|
19
19
|
import { createLogger } from '@intutic/logger';
|
|
20
20
|
import { newIso } from '@intutic/id';
|
|
21
21
|
import { hardenGoosePlugin, unharden } from './gooseHardener.js';
|
|
22
|
+
import { emitShellGate, SHELL_EXTRACT, SHELL_FAIL_CLOSED, REVIEW_REQUESTS_BASENAME } from './gateBody.js';
|
|
22
23
|
const log = createLogger('sync-goose-hooks');
|
|
23
24
|
const PLUGIN_DIR = path.join(os.homedir(), '.agents', 'plugins', 'intutic-governance');
|
|
24
25
|
const GOOSE_CONFIG = path.join(os.homedir(), '.config', 'goose', 'config.yaml');
|
|
25
|
-
const PROTECTED_PATHS = [
|
|
26
|
-
'.agents/plugins/intutic-governance',
|
|
27
|
-
'.intutic/hooks',
|
|
28
|
-
'.intutic/integrity.json',
|
|
29
|
-
'.claude/settings.json',
|
|
30
|
-
'.cursor/hooks.json',
|
|
31
|
-
'.cline/hooks',
|
|
32
|
-
'.openhands/hooks.json',
|
|
33
|
-
];
|
|
34
26
|
/**
|
|
35
27
|
* Write Goose governance plugin and harden it.
|
|
36
28
|
*
|
|
@@ -78,26 +70,48 @@ export async function writeGooseHooks(proxyUrl, workspaceRoot = os.homedir(), wo
|
|
|
78
70
|
# Proxy: ${proxyUrl}
|
|
79
71
|
# Generated: ${newIso()}
|
|
80
72
|
set -euo pipefail
|
|
81
|
-
|
|
73
|
+
${SHELL_FAIL_CLOSED}
|
|
82
74
|
EVENT="\${1:-pre}"
|
|
83
75
|
INPUT="\$(cat)"
|
|
84
|
-
|
|
85
|
-
TARGET="$(echo "$INPUT" | python3 -c "import sys,json; d=json.load(sys.stdin); i=d.get('tool_input',{}); print(i.get('path',i.get('file_path','')))" 2>/dev/null || true)"
|
|
76
|
+
${SHELL_EXTRACT}
|
|
86
77
|
|
|
87
78
|
HOOK_EVENTS_LOG=${JSON.stringify(hookEventsLog)}
|
|
88
79
|
|
|
89
80
|
# ── Runtime credentials (sourced from ~/.intutic/env/runtime.env) ────────────────────────
|
|
81
|
+
# These are defaults, and they are also the only thing standing between
|
|
82
|
+
# \`set -u\` and a fatal unbound-variable error: log_event reads all three, so on
|
|
83
|
+
# a machine with no runtime.env to source, an unset name kills the gate before
|
|
84
|
+
# it can exit 2. Spelling matters — INTUTIC_, never INTUITIC_.
|
|
90
85
|
RUNTIME_ENV="$HOME/.intutic/env/runtime.env"
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
86
|
+
INTUTIC_HOST="https://api.intutic.ai"
|
|
87
|
+
INTUTIC_API_KEY=""
|
|
88
|
+
INTUTIC_WORKSPACE_ID=${JSON.stringify(workspaceId)}
|
|
94
89
|
[ -f "$RUNTIME_ENV" ] && source "$RUNTIME_ENV" 2>/dev/null || true
|
|
95
90
|
|
|
96
91
|
log_event() {
|
|
97
92
|
local verdict="\$1" tool="\$2" reason="\$3"
|
|
93
|
+
# \`tool\` and \`reason\` carry agent-controlled text — the tool name, and the
|
|
94
|
+
# target path quoted into the block reason — and both are spliced into the
|
|
95
|
+
# JSON string below. Escape first: one unescaped quote yields a line
|
|
96
|
+
# JSON.parse rejects, and drainHookEvents drops malformed lines then wipes the
|
|
97
|
+
# log on a successful drain, so the record of a block is destroyed rather than
|
|
98
|
+
# delayed. A crafted path could otherwise close the string and forge fields.
|
|
99
|
+
tool="\${tool//\\\\/\\\\\\\\}"; tool="\${tool//\\"/\\\\\\"}"
|
|
100
|
+
reason="\${reason//\\\\/\\\\\\\\}"; reason="\${reason//\\"/\\\\\\"}"
|
|
101
|
+
# Every C0 control character, not just newline and carriage return. JSON
|
|
102
|
+
# forbids all of U+0000-U+001F unescaped, so a plain TAB in a filename — no
|
|
103
|
+
# adversary required — was still enough to produce a line JSON.parse rejects.
|
|
104
|
+
# (NUL cannot appear in a bash variable, so the range starts at \\x01.)
|
|
105
|
+
tool="\${tool//[\$'\\x01'-\$'\\x1f']/ }"; reason="\${reason//[\$'\\x01'-\$'\\x1f']/ }"
|
|
106
|
+
# The workspace id is spliced into the same JSON string. It comes from
|
|
107
|
+
# runtime.env on disk rather than from the agent, so it is lower risk — but a
|
|
108
|
+
# value with a quote in it breaks every audit line the same way, and "lower
|
|
109
|
+
# risk" is not "cannot happen" for a file the operator edits by hand.
|
|
110
|
+
local ws="\${INTUTIC_WORKSPACE_ID}"
|
|
111
|
+
ws="\${ws//\\\\/\\\\\\\\}"; ws="\${ws//\\"/\\\\\\"}"; ws="\${ws//[\$'\\x01'-\$'\\x1f']/ }"
|
|
98
112
|
local ts; ts="\$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
99
113
|
local incident_id; incident_id="\$(printf '%s' "\${ts}\${tool}\${INTUTIC_WORKSPACE_ID}" | sha1sum 2>/dev/null | cut -c1-16 || echo \"\$(date +%s)\")"
|
|
100
|
-
local entry="{
|
|
114
|
+
local entry="{\\"event\\":\\"\${verdict}\\",\\"toolName\\":\\"\${tool}\\",\\"reason\\":\\"\${reason}\\",\\"workspaceId\\":\\"\${ws}\\",\\"harnessType\\":\\"goose\\",\\"timestamp\\":\\"\${ts}\\",\\"incidentId\\":\\"\${incident_id}\\"}"
|
|
101
115
|
# Path B: reliable file append
|
|
102
116
|
printf '%s\\n' "\$entry" >> "\$HOOK_EVENTS_LOG" 2>/dev/null || true
|
|
103
117
|
# Path A: fire-and-forget HTTP (non-blocking, near-real-time)
|
|
@@ -105,29 +119,12 @@ log_event() {
|
|
|
105
119
|
curl -s -o /dev/null --max-time 3 -X POST \\
|
|
106
120
|
-H "Content-Type: application/json" \\
|
|
107
121
|
-H "Authorization: Bearer \$INTUTIC_API_KEY" \\
|
|
108
|
-
-d "{
|
|
122
|
+
-d "{\\"events\\":[\$entry]}" \\
|
|
109
123
|
"\${INTUTIC_HOST}/api/v1/hook-events" & disown 2>/dev/null || true
|
|
110
124
|
fi
|
|
111
125
|
}
|
|
112
126
|
|
|
113
|
-
|
|
114
|
-
".agents/plugins/intutic-governance"
|
|
115
|
-
".intutic/hooks"
|
|
116
|
-
".intutic/integrity.json"
|
|
117
|
-
".claude/settings.json"
|
|
118
|
-
".cursor/hooks.json"
|
|
119
|
-
".cline/hooks"
|
|
120
|
-
".openhands/hooks.json"
|
|
121
|
-
)
|
|
122
|
-
|
|
123
|
-
for p in "\${PROTECTED_PATHS[@]}"; do
|
|
124
|
-
if echo "$TARGET" | grep -qF "$p"; then
|
|
125
|
-
REASON="Attempt to modify governance-protected path \\"$TARGET\\""
|
|
126
|
-
echo "[Intutic Governance] BLOCKED: $REASON" >&2
|
|
127
|
-
log_event "tool_blocked" "\$TOOL" "\$REASON"
|
|
128
|
-
exit 2
|
|
129
|
-
fi
|
|
130
|
-
done
|
|
127
|
+
${emitShellGate({ harness: 'goose', reviewRequestFile: path.join(workspaceRoot, '.intutic', 'events', REVIEW_REQUESTS_BASENAME) })}
|
|
131
128
|
|
|
132
129
|
log_event "tool_allowed" "\$TOOL" ""
|
|
133
130
|
exit 0
|
|
@@ -143,7 +140,20 @@ exit 0
|
|
|
143
140
|
await mergeGooseConfig(proxyUrl);
|
|
144
141
|
}
|
|
145
142
|
/**
|
|
146
|
-
* Merge provider host
|
|
143
|
+
* Merge the provider host **and** the `hooks.pre_tool_use` registration into
|
|
144
|
+
* `~/.config/goose/config.yaml`.
|
|
145
|
+
*
|
|
146
|
+
* The hook registration used to live in a second module, `gooseHooksWriter.ts`,
|
|
147
|
+
* which wrote its own gate script and registered *that* one here — so goose had
|
|
148
|
+
* two co-installed gates with contradictory models: this one, which enforces
|
|
149
|
+
* locally and fails closed, and that one, which POSTed to the control plane and
|
|
150
|
+
* failed open. Which of them actually ran depended on whether goose honours the
|
|
151
|
+
* plugin `hooks.json` or this config key, and nothing in the tree established
|
|
152
|
+
* which.
|
|
153
|
+
*
|
|
154
|
+
* Absorbing the registration here settles it without needing to know: both
|
|
155
|
+
* mechanisms now name the same script. That is why the answer to "which one does
|
|
156
|
+
* goose read" stopped mattering, rather than being looked up.
|
|
147
157
|
*/
|
|
148
158
|
async function mergeGooseConfig(proxyUrl) {
|
|
149
159
|
let existing = '';
|
|
@@ -151,7 +161,9 @@ async function mergeGooseConfig(proxyUrl) {
|
|
|
151
161
|
existing = await fs.readFile(GOOSE_CONFIG, 'utf-8');
|
|
152
162
|
}
|
|
153
163
|
catch {
|
|
154
|
-
|
|
164
|
+
// Deliberate fail-open: no config.yaml yet (first run) or it is unreadable.
|
|
165
|
+
// Fall through with `existing` at its '' initialiser so the block below
|
|
166
|
+
// writes a fresh provider stanza rather than aborting the whole sync.
|
|
155
167
|
}
|
|
156
168
|
// Inject or update provider.host
|
|
157
169
|
// Goose config.yaml format: provider.host or OPENAI_HOST env var
|
|
@@ -166,6 +178,24 @@ async function mergeGooseConfig(proxyUrl) {
|
|
|
166
178
|
else {
|
|
167
179
|
existing += `\nprovider:\n host: "${proxyUrl}"\n`;
|
|
168
180
|
}
|
|
181
|
+
// Register the gate under `hooks.pre_tool_use`, pointing at the script this
|
|
182
|
+
// module writes.
|
|
183
|
+
const hookScript = path.join(PLUGIN_DIR, 'scripts', 'intutic-check.sh');
|
|
184
|
+
const hookLine = ` pre_tool_use: ${hookScript}`;
|
|
185
|
+
if (!(existing.includes('pre_tool_use:') && existing.includes(hookScript))) {
|
|
186
|
+
// Replace any stale pre_tool_use line rather than adding a second one — an
|
|
187
|
+
// earlier install pointed this at gooseHooksWriter's script, and two
|
|
188
|
+
// registrations under one key is how the double gate started.
|
|
189
|
+
if (/^\s*pre_tool_use:.*$/m.test(existing)) {
|
|
190
|
+
existing = existing.replace(/^\s*pre_tool_use:.*$/m, hookLine);
|
|
191
|
+
}
|
|
192
|
+
else if (/^hooks:/m.test(existing)) {
|
|
193
|
+
existing = existing.replace(/^hooks:/m, `hooks:\n${hookLine}`);
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
existing = existing.trimEnd() + `\nhooks:\n${hookLine}\n`;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
169
199
|
const tmpConfig = GOOSE_CONFIG + '.intutic-tmp';
|
|
170
200
|
await fs.mkdir(path.dirname(GOOSE_CONFIG), { recursive: true });
|
|
171
201
|
await fs.writeFile(tmpConfig, existing, 'utf-8');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gooseHooks.js","sourceRoot":"","sources":["../../src/harness/gooseHooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAA;AACtC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAA;AACjC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAA;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"gooseHooks.js","sourceRoot":"","sources":["../../src/harness/gooseHooks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* grokHooks.ts — xAI Grok Build (`grok`, GA 2026-05, open-sourced 2026-07-15)
|
|
3
|
+
* governance hook injection.
|
|
4
|
+
*
|
|
5
|
+
* Writes the Intutic PreToolUse gate script and registers it at project and
|
|
6
|
+
* user level:
|
|
7
|
+
* - `<workspaceRoot>/.grok/hooks/intutic-governance.json`
|
|
8
|
+
* - `~/.grok/hooks/intutic-governance.json`
|
|
9
|
+
*
|
|
10
|
+
* Also merges the Intutic proxy `base_url` into `config.toml`'s `[model.*]`
|
|
11
|
+
* tables at both `<workspaceRoot>/.grok/config.toml` and
|
|
12
|
+
* `~/.grok/config.toml` — the LLM-egress half of coverage, same split every
|
|
13
|
+
* other harness in this file uses (the gate refuses tool calls; the config
|
|
14
|
+
* merge routes the model traffic itself).
|
|
15
|
+
*
|
|
16
|
+
* # Blocking contract — CONFIRMED, not assumed
|
|
17
|
+
*
|
|
18
|
+
* Grok Build's `PreToolUse` hook carries no `matcher` (it fires for every
|
|
19
|
+
* tool call), has a default `timeout` of 5s (ample for a local
|
|
20
|
+
* policy-snapshot evaluation), and — this is the part that is independently
|
|
21
|
+
* confirmed, unlike Muse Code's — signals a block by writing
|
|
22
|
+
* `{"decision":"deny","reason":"..."}` as JSON on **stdout** and exiting 0.
|
|
23
|
+
* That is a *different* stdout shape from Cline/Roo Code's `{"cancel":true}`
|
|
24
|
+
* — Grok Build does not recognise `cancel`, and Cline/Roo Code do not
|
|
25
|
+
* recognise `decision` — so this writer uses its own `BlockContract` value,
|
|
26
|
+
* `'stdout-decision-deny'` (see gateBody.ts's module doc for why the two
|
|
27
|
+
* stdout shapes are not folded into one contract), rather than reusing
|
|
28
|
+
* `'stdout-cancel'` and silently going inert.
|
|
29
|
+
*
|
|
30
|
+
* # Double-gating with the Claude Code / Cursor compat paths
|
|
31
|
+
*
|
|
32
|
+
* Grok Build ALSO natively reads and executes `.claude/settings.json` hooks
|
|
33
|
+
* and `.cursor/hooks.json` hooks if present (a compatibility feature) — so
|
|
34
|
+
* if a workspace already has Intutic's Claude Code or Cursor gate installed,
|
|
35
|
+
* BOTH that gate and this native one fire for the same Grok Build tool call.
|
|
36
|
+
* This is the same "both layers firing is expected, not a bug" posture this
|
|
37
|
+
* codebase already documents for the mcp-proxy + PreToolUse gate combination
|
|
38
|
+
* (see apps/docs/guide/mcp-governance.md, "Both layers firing on the same
|
|
39
|
+
* blocked call is expected, not a bug"): a block wins if EITHER gate blocks,
|
|
40
|
+
* neither gate knows about the other's decision, and an operator may see a
|
|
41
|
+
* `tool_blocked` event recorded twice for what was, from the developer's
|
|
42
|
+
* point of view, one refused action. That is redundancy, not a discrepancy
|
|
43
|
+
* to reconcile — see `grokHooks.test.ts` for a test pinning that a
|
|
44
|
+
* double-fired block does not corrupt the audit log or the exit/stdout
|
|
45
|
+
* contract of either gate.
|
|
46
|
+
*
|
|
47
|
+
* # `[model.*]` table naming — CONFIRMED against the real open-sourced parser
|
|
48
|
+
*
|
|
49
|
+
* The shape is `[model."<id>"]` with a per-model `base_url` (and many other
|
|
50
|
+
* override fields — `xai_grok_shell::agent::config::ConfigModelOverride`),
|
|
51
|
+
* keyed by model id and consulted only for the model whose id equals `<id>`;
|
|
52
|
+
* it does not fall back to any other key. `xai-grok-models/default_models.json`
|
|
53
|
+
* (embedded at compile time) pins the operative default id, CONFIRMED live by
|
|
54
|
+
* cloning `github.com/xai-org/grok-build` (open-sourced 2026-07-15) and
|
|
55
|
+
* reading it directly: `"default": "grok-4.6"` — NOT the literal string
|
|
56
|
+
* `"default"`. This writer therefore overrides `base_url` on every EXISTING
|
|
57
|
+
* `[model.*]` table (never invents one if the user already configured
|
|
58
|
+
* models), and — only when no `[model.*]` table exists at all — seeds
|
|
59
|
+
* `[model."grok-4.6"]`, the confirmed compiled-in default id, not a guess.
|
|
60
|
+
* A future Grok Build release that changes its compiled default would make
|
|
61
|
+
* this seeded table inert again until re-synced against a newer clone —
|
|
62
|
+
* the same residual risk `windsurfHooks.ts`'s "confirmed, not evergreen"
|
|
63
|
+
* caveat already documents for a versioned upstream default.
|
|
64
|
+
*
|
|
65
|
+
* HLD §3.14 — Harness Onboarding Matrix
|
|
66
|
+
* @module
|
|
67
|
+
*/
|
|
68
|
+
/**
|
|
69
|
+
* Write Grok Build hooks at project and user level, and merge the Intutic
|
|
70
|
+
* proxy into `config.toml`'s `[model.*]` tables at both levels.
|
|
71
|
+
*
|
|
72
|
+
* @param workspaceRoot - Absolute workspace root.
|
|
73
|
+
* @param proxyUrl - Intutic proxy URL (also merged into config.toml).
|
|
74
|
+
* @param workspaceId - Workspace ID embedded in hook event payloads.
|
|
75
|
+
*/
|
|
76
|
+
export declare function writeGrokHooks(workspaceRoot: string, proxyUrl: string, workspaceId?: string): Promise<void>;
|
|
77
|
+
//# sourceMappingURL=grokHooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grokHooks.d.ts","sourceRoot":"","sources":["../../src/harness/grokHooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkEG;AA+RH;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAClC,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,EAChB,WAAW,SAAK,GACf,OAAO,CAAC,IAAI,CAAC,CA0Bf"}
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* grokHooks.ts — xAI Grok Build (`grok`, GA 2026-05, open-sourced 2026-07-15)
|
|
3
|
+
* governance hook injection.
|
|
4
|
+
*
|
|
5
|
+
* Writes the Intutic PreToolUse gate script and registers it at project and
|
|
6
|
+
* user level:
|
|
7
|
+
* - `<workspaceRoot>/.grok/hooks/intutic-governance.json`
|
|
8
|
+
* - `~/.grok/hooks/intutic-governance.json`
|
|
9
|
+
*
|
|
10
|
+
* Also merges the Intutic proxy `base_url` into `config.toml`'s `[model.*]`
|
|
11
|
+
* tables at both `<workspaceRoot>/.grok/config.toml` and
|
|
12
|
+
* `~/.grok/config.toml` — the LLM-egress half of coverage, same split every
|
|
13
|
+
* other harness in this file uses (the gate refuses tool calls; the config
|
|
14
|
+
* merge routes the model traffic itself).
|
|
15
|
+
*
|
|
16
|
+
* # Blocking contract — CONFIRMED, not assumed
|
|
17
|
+
*
|
|
18
|
+
* Grok Build's `PreToolUse` hook carries no `matcher` (it fires for every
|
|
19
|
+
* tool call), has a default `timeout` of 5s (ample for a local
|
|
20
|
+
* policy-snapshot evaluation), and — this is the part that is independently
|
|
21
|
+
* confirmed, unlike Muse Code's — signals a block by writing
|
|
22
|
+
* `{"decision":"deny","reason":"..."}` as JSON on **stdout** and exiting 0.
|
|
23
|
+
* That is a *different* stdout shape from Cline/Roo Code's `{"cancel":true}`
|
|
24
|
+
* — Grok Build does not recognise `cancel`, and Cline/Roo Code do not
|
|
25
|
+
* recognise `decision` — so this writer uses its own `BlockContract` value,
|
|
26
|
+
* `'stdout-decision-deny'` (see gateBody.ts's module doc for why the two
|
|
27
|
+
* stdout shapes are not folded into one contract), rather than reusing
|
|
28
|
+
* `'stdout-cancel'` and silently going inert.
|
|
29
|
+
*
|
|
30
|
+
* # Double-gating with the Claude Code / Cursor compat paths
|
|
31
|
+
*
|
|
32
|
+
* Grok Build ALSO natively reads and executes `.claude/settings.json` hooks
|
|
33
|
+
* and `.cursor/hooks.json` hooks if present (a compatibility feature) — so
|
|
34
|
+
* if a workspace already has Intutic's Claude Code or Cursor gate installed,
|
|
35
|
+
* BOTH that gate and this native one fire for the same Grok Build tool call.
|
|
36
|
+
* This is the same "both layers firing is expected, not a bug" posture this
|
|
37
|
+
* codebase already documents for the mcp-proxy + PreToolUse gate combination
|
|
38
|
+
* (see apps/docs/guide/mcp-governance.md, "Both layers firing on the same
|
|
39
|
+
* blocked call is expected, not a bug"): a block wins if EITHER gate blocks,
|
|
40
|
+
* neither gate knows about the other's decision, and an operator may see a
|
|
41
|
+
* `tool_blocked` event recorded twice for what was, from the developer's
|
|
42
|
+
* point of view, one refused action. That is redundancy, not a discrepancy
|
|
43
|
+
* to reconcile — see `grokHooks.test.ts` for a test pinning that a
|
|
44
|
+
* double-fired block does not corrupt the audit log or the exit/stdout
|
|
45
|
+
* contract of either gate.
|
|
46
|
+
*
|
|
47
|
+
* # `[model.*]` table naming — CONFIRMED against the real open-sourced parser
|
|
48
|
+
*
|
|
49
|
+
* The shape is `[model."<id>"]` with a per-model `base_url` (and many other
|
|
50
|
+
* override fields — `xai_grok_shell::agent::config::ConfigModelOverride`),
|
|
51
|
+
* keyed by model id and consulted only for the model whose id equals `<id>`;
|
|
52
|
+
* it does not fall back to any other key. `xai-grok-models/default_models.json`
|
|
53
|
+
* (embedded at compile time) pins the operative default id, CONFIRMED live by
|
|
54
|
+
* cloning `github.com/xai-org/grok-build` (open-sourced 2026-07-15) and
|
|
55
|
+
* reading it directly: `"default": "grok-4.6"` — NOT the literal string
|
|
56
|
+
* `"default"`. This writer therefore overrides `base_url` on every EXISTING
|
|
57
|
+
* `[model.*]` table (never invents one if the user already configured
|
|
58
|
+
* models), and — only when no `[model.*]` table exists at all — seeds
|
|
59
|
+
* `[model."grok-4.6"]`, the confirmed compiled-in default id, not a guess.
|
|
60
|
+
* A future Grok Build release that changes its compiled default would make
|
|
61
|
+
* this seeded table inert again until re-synced against a newer clone —
|
|
62
|
+
* the same residual risk `windsurfHooks.ts`'s "confirmed, not evergreen"
|
|
63
|
+
* caveat already documents for a versioned upstream default.
|
|
64
|
+
*
|
|
65
|
+
* HLD §3.14 — Harness Onboarding Matrix
|
|
66
|
+
* @module
|
|
67
|
+
*/
|
|
68
|
+
import * as fs from 'node:fs/promises';
|
|
69
|
+
import * as path from 'node:path';
|
|
70
|
+
import * as os from 'node:os';
|
|
71
|
+
import { parse as parseToml, stringify as stringifyToml } from 'smol-toml';
|
|
72
|
+
import { createLogger } from '@intutic/logger';
|
|
73
|
+
import { newIso } from '@intutic/id';
|
|
74
|
+
import { emitJsGate, emitJsFailClosedPrelude } from './gateBody.js';
|
|
75
|
+
const log = createLogger('sync-grok-hooks');
|
|
76
|
+
const GROK_USER_DIR = path.join(os.homedir(), '.grok');
|
|
77
|
+
/** The single self-contained hook file this writer owns. Grok Build's hook
|
|
78
|
+
* directory is a glob of independent files (`.grok/hooks/*.json`), unlike
|
|
79
|
+
* Codex/Windsurf's one shared `hooks.json` — so, unlike those writers, this
|
|
80
|
+
* one never needs to merge into or preserve anything else in the
|
|
81
|
+
* directory: dropping its own uniquely-named file cannot clobber a hook the
|
|
82
|
+
* user registered themselves. */
|
|
83
|
+
const HOOK_FILENAME = 'intutic-governance.json';
|
|
84
|
+
/**
|
|
85
|
+
* Builds the per-file registration this writer drops at
|
|
86
|
+
* `.grok/hooks/intutic-governance.json` (project) and `~/.grok/hooks/intutic-governance.json`
|
|
87
|
+
* (user).
|
|
88
|
+
*
|
|
89
|
+
* **Shape CONFIRMED against the real, now-open-source parser** (xAI open-sourced
|
|
90
|
+
* `grok-build` 2026-07-15 — `github.com/xai-org/grok-build`, `crates/codegen/xai-grok-hooks`):
|
|
91
|
+
* `xai_grok_hooks::config::parse_hook_file` (called identically for both a
|
|
92
|
+
* settings-file source and a `.grok/hooks/*.json` directory entry — the SAME
|
|
93
|
+
* function, see `discovery.rs`'s `load_hooks_from_settings_file`/
|
|
94
|
+
* `load_hooks_from_directory`) requires a TOP-LEVEL `"hooks"` key; a file
|
|
95
|
+
* without one returns an EMPTY spec set, silently — no error, no warning. The
|
|
96
|
+
* value under `"hooks"` is keyed by event name to an ARRAY of `MatcherGroup`s
|
|
97
|
+
* (`{matcher?: string, hooks: [{type, command, timeout?, ...}]}`), each entry
|
|
98
|
+
* of which becomes one `HookSpec` — the exact shape Claude Code's own
|
|
99
|
+
* `settings.json` `hooks` block uses, not the flat `{event, command, timeout}`
|
|
100
|
+
* record this writer emitted before this fix (which the real parser silently
|
|
101
|
+
* ignored — ZERO hooks ever registered, confirmed by having no top-level
|
|
102
|
+
* `"hooks"` key at all). No `matcher` field on the group means "fires for
|
|
103
|
+
* every tool call" (`MatcherGroup.matcher: Option<String>`, `#[serde(default)]`).
|
|
104
|
+
*/
|
|
105
|
+
function buildHookRegistration(hookScriptPath) {
|
|
106
|
+
return {
|
|
107
|
+
_comment: 'Intutic governance hook — auto-generated. DO NOT EDIT.',
|
|
108
|
+
_lastSync: newIso(),
|
|
109
|
+
hooks: {
|
|
110
|
+
// No matcher — CONFIRMED to apply to every tool call.
|
|
111
|
+
PreToolUse: [
|
|
112
|
+
{
|
|
113
|
+
hooks: [
|
|
114
|
+
{
|
|
115
|
+
type: 'command',
|
|
116
|
+
command: `node "${hookScriptPath}"`,
|
|
117
|
+
// Grok Build's documented default; stated explicitly rather than
|
|
118
|
+
// left to fall back, since a local policy-snapshot evaluation is
|
|
119
|
+
// cheap but a future default change upstream should not silently
|
|
120
|
+
// starve this hook.
|
|
121
|
+
timeout: 5,
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
},
|
|
125
|
+
],
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function buildHookScript(proxyUrl, workspaceRoot, workspaceId) {
|
|
130
|
+
const hookEventsLog = path.join(workspaceRoot, '.intutic', 'events', 'hook-events.jsonl');
|
|
131
|
+
return `#!/usr/bin/env node
|
|
132
|
+
/**
|
|
133
|
+
* Intutic Grok Build governance gate.
|
|
134
|
+
* Auto-generated by intutic sync-daemon. DO NOT EDIT.
|
|
135
|
+
* Proxy: ${proxyUrl}
|
|
136
|
+
* Generated: ${newIso()}
|
|
137
|
+
*/
|
|
138
|
+
${emitJsFailClosedPrelude({ harness: 'grok', contract: 'stdout-decision-deny' })}
|
|
139
|
+
const fs = require('fs');
|
|
140
|
+
const crypto = require('crypto');
|
|
141
|
+
const https = require('https');
|
|
142
|
+
|
|
143
|
+
// Runtime credentials
|
|
144
|
+
const _runtimeEnvPath = require('path').join(require('os').homedir(), '.intutic', 'env', 'runtime.env');
|
|
145
|
+
let _intuticHost = 'https://api.intutic.ai', _intuticKey = '', _intuticWsId = ${JSON.stringify(workspaceId)};
|
|
146
|
+
try {
|
|
147
|
+
fs.readFileSync(_runtimeEnvPath, 'utf-8').split('\\n').forEach(line => {
|
|
148
|
+
const eq = line.indexOf('='); if (eq < 0) return;
|
|
149
|
+
const k = line.slice(0, eq).trim(), v = line.slice(eq + 1).trim();
|
|
150
|
+
if (k === 'INTUTIC_HOST' && v) _intuticHost = v;
|
|
151
|
+
if (k === 'INTUTIC_API_KEY' && v) _intuticKey = v;
|
|
152
|
+
if (k === 'INTUTIC_WORKSPACE_ID' && v) _intuticWsId = v;
|
|
153
|
+
});
|
|
154
|
+
} catch {}
|
|
155
|
+
|
|
156
|
+
${emitJsGate({ harness: 'grok', contract: 'stdout-decision-deny' })}
|
|
157
|
+
|
|
158
|
+
let _intuticSessionId = '';
|
|
159
|
+
function logEvent(verdict, toolName, reason) {
|
|
160
|
+
try {
|
|
161
|
+
const ts = new Date().toISOString();
|
|
162
|
+
const incidentId = crypto.createHash('sha1').update(ts + toolName + _intuticWsId).digest('hex').slice(0, 16);
|
|
163
|
+
const entry = JSON.stringify({
|
|
164
|
+
// Passed through, not collapsed to two values: the advisory tier emits
|
|
165
|
+
// 'tool_flagged', and a ternary here silently recorded it as an allow.
|
|
166
|
+
event: verdict,
|
|
167
|
+
toolName, reason: reason || '',
|
|
168
|
+
workspaceId: _intuticWsId,
|
|
169
|
+
harnessType: 'grok',
|
|
170
|
+
timestamp: ts,
|
|
171
|
+
incidentId,
|
|
172
|
+
...(_intuticSessionId ? { sessionId: _intuticSessionId } : {}),
|
|
173
|
+
}) + '\\n';
|
|
174
|
+
fs.appendFileSync(${JSON.stringify(hookEventsLog)}, entry, { flag: 'a' });
|
|
175
|
+
if (_intuticKey) {
|
|
176
|
+
try {
|
|
177
|
+
const body = JSON.stringify({ events: [JSON.parse(entry)] });
|
|
178
|
+
const urlObj = new URL('/api/v1/hook-events', _intuticHost);
|
|
179
|
+
const mod = urlObj.protocol === 'https:' ? https : require('http');
|
|
180
|
+
const req = mod.request({ hostname: urlObj.hostname, port: urlObj.port || 443, path: urlObj.pathname, method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body), 'Authorization': 'Bearer ' + _intuticKey } });
|
|
181
|
+
req.on('error', () => { /* fire-and-forget */ });
|
|
182
|
+
req.write(body); req.end();
|
|
183
|
+
} catch { /* never crash the hook */ }
|
|
184
|
+
}
|
|
185
|
+
} catch { /* never crash the hook */ }
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
let raw = '';
|
|
189
|
+
process.stdin.on('data', (c) => { raw += c; });
|
|
190
|
+
process.stdin.on('end', () => {
|
|
191
|
+
try {
|
|
192
|
+
const ctx = JSON.parse(raw);
|
|
193
|
+
_intuticSessionId = ctx.session_id || ctx.sessionId || '';
|
|
194
|
+
intuticGuardEnvelope(ctx, ['tool_name', 'toolName', 'tool_input', 'toolInput'], logEvent);
|
|
195
|
+
const input = ctx.tool_input || ctx.toolInput || {};
|
|
196
|
+
const toolName = ctx.tool_name || ctx.toolName || 'tool';
|
|
197
|
+
|
|
198
|
+
const targetPath = input.path || input.file_path || input.filePath || input.file ||
|
|
199
|
+
input.target || input.notebook_path || '';
|
|
200
|
+
const command = input.command || input.cmd || input.script || '';
|
|
201
|
+
|
|
202
|
+
intuticGate(toolName, targetPath, command, logEvent, _intuticWsId, input);
|
|
203
|
+
|
|
204
|
+
// Allow — no stdout object at all, which Grok Build reads as "not denied".
|
|
205
|
+
logEvent('tool_allowed', toolName, '');
|
|
206
|
+
process.exit(0);
|
|
207
|
+
} catch (err) {
|
|
208
|
+
// Fail CLOSED — the stdout-decision-deny contract, even on a crash inside
|
|
209
|
+
// this handler (the module-level prelude above covers crashes outside it).
|
|
210
|
+
const errMsg = String(err);
|
|
211
|
+
process.stderr.write('[Intutic Governance] Hook error (fail-closed): ' + errMsg + '\\n');
|
|
212
|
+
logEvent('tool_blocked', 'unknown', errMsg);
|
|
213
|
+
process.stdout.write(JSON.stringify({ decision: 'deny', reason: '[Intutic Governance] Hook error (fail-closed): ' + errMsg }) + '\\n');
|
|
214
|
+
process.exit(0);
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
`;
|
|
218
|
+
}
|
|
219
|
+
async function atomicWriteJson(filePath, data) {
|
|
220
|
+
const tmp = filePath + '.intutic-tmp';
|
|
221
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
222
|
+
await fs.writeFile(tmp, JSON.stringify(data, null, 2) + '\n', 'utf-8');
|
|
223
|
+
await fs.rename(tmp, filePath);
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Grok Build's compiled-in default model id — CONFIRMED live (2026-08-20)
|
|
227
|
+
* against `github.com/xai-org/grok-build`'s `crates/codegen/xai-grok-models/default_models.json`
|
|
228
|
+
* `"default"` key, NOT a guess. See this module's `[model.*]` doc comment.
|
|
229
|
+
* A future upstream release may change this; re-verify against a fresh
|
|
230
|
+
* clone if this writer's seeded table stops being honoured.
|
|
231
|
+
*/
|
|
232
|
+
const GROK_DEFAULT_MODEL_ID = 'grok-4.6';
|
|
233
|
+
/**
|
|
234
|
+
* The pre-parser fallback: append a `[model."<default id>"]` block only,
|
|
235
|
+
* never touching (or even parsing) anything else in the file — mirroring
|
|
236
|
+
* `injectGooseAppendOnly`'s reasoning exactly: a parser that cannot safely
|
|
237
|
+
* represent a malformed file cannot safely round-trip it either, so the safe
|
|
238
|
+
* degrade is "never touch anything but the block we control".
|
|
239
|
+
*/
|
|
240
|
+
async function mergeGrokConfigTomlAppendOnly(configPath, existingRaw, proxyUrl) {
|
|
241
|
+
let text = existingRaw;
|
|
242
|
+
const tableHeader = `[model."${GROK_DEFAULT_MODEL_ID}"]`;
|
|
243
|
+
if (!text.includes(tableHeader) && !text.includes(`[model.${GROK_DEFAULT_MODEL_ID}]`)) {
|
|
244
|
+
text = text.trimEnd() + `\n\n${tableHeader}\nbase_url = ${JSON.stringify(proxyUrl)}\n`;
|
|
245
|
+
}
|
|
246
|
+
if (text === existingRaw)
|
|
247
|
+
return;
|
|
248
|
+
await fs.mkdir(path.dirname(configPath), { recursive: true });
|
|
249
|
+
const tmp = configPath + '.intutic-tmp';
|
|
250
|
+
await fs.writeFile(tmp, text, 'utf-8');
|
|
251
|
+
await fs.rename(tmp, configPath);
|
|
252
|
+
log.info({ action: 'grok_config_written', path: configPath, mode: 'append_only_fallback' }, 'Grok config.toml updated (append-only fallback — did not parse as TOML)');
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Structurally merges the Intutic proxy `base_url` into every `[model.*]`
|
|
256
|
+
* table in `config.toml`, via `smol-toml` — the same "parse structurally,
|
|
257
|
+
* write-if-changed, fall back to append-only on a parse failure" shape
|
|
258
|
+
* `injectGoose` established for YAML, applied to TOML since no TOML-parsing
|
|
259
|
+
* dependency existed anywhere in this monorepo before this writer (checked:
|
|
260
|
+
* `openhandsHooks.ts`'s own `config.toml` edits are regex text-surgery, not
|
|
261
|
+
* a real parse — the OpenHands precedent that predates this one).
|
|
262
|
+
*
|
|
263
|
+
* Never invents a model id if the user already configured one or more —
|
|
264
|
+
* only overrides `base_url` on each existing `[model.*]` table. Only when
|
|
265
|
+
* NO `[model.*]` table exists at all does it seed a `[model."<default id>"]`
|
|
266
|
+
* table (`GROK_DEFAULT_MODEL_ID` below) — see this module's doc comment for
|
|
267
|
+
* why that id is CONFIRMED against the real open-sourced default, not a guess.
|
|
268
|
+
*/
|
|
269
|
+
async function mergeGrokConfigToml(configPath, proxyUrl) {
|
|
270
|
+
let existing = '';
|
|
271
|
+
try {
|
|
272
|
+
existing = await fs.readFile(configPath, 'utf-8');
|
|
273
|
+
}
|
|
274
|
+
catch {
|
|
275
|
+
// Deliberate fail-open: no config.toml yet (first run) or unreadable.
|
|
276
|
+
// Falls through with `existing` at '' so a fresh file is written below.
|
|
277
|
+
}
|
|
278
|
+
let doc;
|
|
279
|
+
try {
|
|
280
|
+
doc = existing.trim() ? parseToml(existing) : {};
|
|
281
|
+
}
|
|
282
|
+
catch (err) {
|
|
283
|
+
log.warn({ action: 'grok_toml_unparseable', path: configPath, err: err.message }, 'Grok config.toml did not parse as TOML — falling back to append-only text injection');
|
|
284
|
+
await mergeGrokConfigTomlAppendOnly(configPath, existing, proxyUrl);
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
const model = doc.model && typeof doc.model === 'object' ? doc.model : {};
|
|
288
|
+
const modelNames = Object.keys(model);
|
|
289
|
+
let changed = false;
|
|
290
|
+
if (modelNames.length === 0) {
|
|
291
|
+
// No [model.*] table exists yet — GROK_DEFAULT_MODEL_ID is CONFIRMED
|
|
292
|
+
// against the real open-sourced compiled default (see module doc), not
|
|
293
|
+
// a guess.
|
|
294
|
+
model[GROK_DEFAULT_MODEL_ID] = { ...(model[GROK_DEFAULT_MODEL_ID] ?? {}), base_url: proxyUrl };
|
|
295
|
+
changed = true;
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
for (const name of modelNames) {
|
|
299
|
+
const entry = model[name] && typeof model[name] === 'object' ? model[name] : {};
|
|
300
|
+
if (entry.base_url !== proxyUrl) {
|
|
301
|
+
model[name] = { ...entry, base_url: proxyUrl };
|
|
302
|
+
changed = true;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
if (!changed) {
|
|
307
|
+
// Already present and unchanged — write-if-changed, same reasoning
|
|
308
|
+
// mcpAutoWrite.ts's writeJsonFile/injectGoose document: this runs every
|
|
309
|
+
// sync cycle, so a no-op merge must not churn the file's mtime.
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
doc.model = model;
|
|
313
|
+
await fs.mkdir(path.dirname(configPath), { recursive: true });
|
|
314
|
+
const tmp = configPath + '.intutic-tmp';
|
|
315
|
+
await fs.writeFile(tmp, stringifyToml(doc), 'utf-8');
|
|
316
|
+
await fs.rename(tmp, configPath);
|
|
317
|
+
log.info({ action: 'grok_config_written', path: configPath, mode: 'toml' }, 'Grok config.toml updated (structural TOML edit)');
|
|
318
|
+
}
|
|
319
|
+
// ─── Public API ─────────────────────────────────────────────────────────
|
|
320
|
+
/**
|
|
321
|
+
* Write Grok Build hooks at project and user level, and merge the Intutic
|
|
322
|
+
* proxy into `config.toml`'s `[model.*]` tables at both levels.
|
|
323
|
+
*
|
|
324
|
+
* @param workspaceRoot - Absolute workspace root.
|
|
325
|
+
* @param proxyUrl - Intutic proxy URL (also merged into config.toml).
|
|
326
|
+
* @param workspaceId - Workspace ID embedded in hook event payloads.
|
|
327
|
+
*/
|
|
328
|
+
export async function writeGrokHooks(workspaceRoot, proxyUrl, workspaceId = '') {
|
|
329
|
+
const hookScriptDir = path.join(workspaceRoot, '.intutic', 'hooks');
|
|
330
|
+
await fs.mkdir(hookScriptDir, { recursive: true });
|
|
331
|
+
await fs.mkdir(path.join(workspaceRoot, '.intutic', 'events'), { recursive: true });
|
|
332
|
+
const hookScriptPath = path.join(hookScriptDir, 'grok-check.js');
|
|
333
|
+
const tmpScript = hookScriptPath + '.intutic-tmp';
|
|
334
|
+
await fs.writeFile(tmpScript, buildHookScript(proxyUrl, workspaceRoot, workspaceId), 'utf-8');
|
|
335
|
+
await fs.rename(tmpScript, hookScriptPath);
|
|
336
|
+
await fs.chmod(hookScriptPath, 0o755);
|
|
337
|
+
const registration = buildHookRegistration(hookScriptPath);
|
|
338
|
+
// 1. Project-level: <root>/.grok/hooks/intutic-governance.json
|
|
339
|
+
const projectHooksDir = path.join(workspaceRoot, '.grok', 'hooks');
|
|
340
|
+
await atomicWriteJson(path.join(projectHooksDir, HOOK_FILENAME), registration);
|
|
341
|
+
log.info({ action: 'grok_hooks_written', level: 'project', path: projectHooksDir }, 'Grok project-level hooks written');
|
|
342
|
+
// 2. User-level: ~/.grok/hooks/intutic-governance.json
|
|
343
|
+
const userHooksDir = path.join(GROK_USER_DIR, 'hooks');
|
|
344
|
+
await atomicWriteJson(path.join(userHooksDir, HOOK_FILENAME), registration);
|
|
345
|
+
log.info({ action: 'grok_hooks_written', level: 'user', path: userHooksDir }, 'Grok user-level hooks written');
|
|
346
|
+
// 3. config.toml model base_url — project and user level.
|
|
347
|
+
await mergeGrokConfigToml(path.join(workspaceRoot, '.grok', 'config.toml'), proxyUrl);
|
|
348
|
+
await mergeGrokConfigToml(path.join(GROK_USER_DIR, 'config.toml'), proxyUrl);
|
|
349
|
+
}
|
|
350
|
+
//# sourceMappingURL=grokHooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grokHooks.js","sourceRoot":"","sources":["../../src/harness/grokHooks.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hermesHooks.d.ts","sourceRoot":"","sources":["../../src/harness/hermesHooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;
|
|
1
|
+
{"version":3,"file":"hermesHooks.d.ts","sourceRoot":"","sources":["../../src/harness/hermesHooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAmKH;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CACpC,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,EAChB,WAAW,SAAK,GACf,OAAO,CAAC,IAAI,CAAC,CAiEf"}
|