@ken-jo/agent-connector 0.5.0 → 0.6.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 +3 -3
- package/dist/{action-LEYTHNIU.js → action-EKK6FMPY.js} +8 -8
- package/dist/{audit-HPKCUCES.js → audit-H7PQWIVH.js} +5 -5
- package/dist/{chunk-BXPSDNIB.js → chunk-34RRWEWU.js} +2 -2
- package/dist/{chunk-SFY6YLVK.js → chunk-4YOYR3T5.js} +5 -6
- package/dist/{chunk-SFY6YLVK.js.map → chunk-4YOYR3T5.js.map} +1 -1
- package/dist/{chunk-6WN37NVN.js → chunk-6FRAVOVF.js} +2 -2
- package/dist/{chunk-2Y2MZRLP.js → chunk-CWUPIT72.js} +2 -2
- package/dist/{chunk-6XMV2OOA.js → chunk-CZOXXS77.js} +3 -3
- package/dist/{chunk-IRUYJD23.js → chunk-IVJUPNLD.js} +2 -8
- package/dist/chunk-IVJUPNLD.js.map +1 -0
- package/dist/{chunk-FKW5A6HE.js → chunk-IY3SSCNK.js} +4 -4
- package/dist/{chunk-U2XJWG7N.js → chunk-JUBEM3OR.js} +2 -2
- package/dist/{chunk-UM5S7DKK.js → chunk-KOFCNA5T.js} +11 -2
- package/dist/{chunk-UM5S7DKK.js.map → chunk-KOFCNA5T.js.map} +1 -1
- package/dist/{chunk-4KIXXJ7B.js → chunk-KY2VQGD7.js} +2 -2
- package/dist/{chunk-M6OS4OLU.js → chunk-R4FABNAL.js} +2 -2
- package/dist/{chunk-T5AI3AW3.js → chunk-SA6CSOH5.js} +19 -19
- package/dist/{chunk-G5HAIYRM.js → chunk-XJSVJD5T.js} +37 -29
- package/dist/chunk-XJSVJD5T.js.map +1 -0
- package/dist/{chunk-WZMSSIDN.js → chunk-XSR3GF55.js} +14 -6
- package/dist/chunk-XSR3GF55.js.map +1 -0
- package/dist/{claude-code-LJ6DVXWQ.js → claude-code-VEERATN5.js} +4 -4
- package/dist/cli/sdk.js +4 -4
- package/dist/cli.js +1 -1
- package/dist/{cline-JAPJNOZQ.js → cline-UW6WCQRK.js} +2 -2
- package/dist/cline-UW6WCQRK.js.map +1 -0
- package/dist/{codebuff-3VODFPD4.js → codebuff-R7QBLCSJ.js} +11 -11
- package/dist/codebuff-R7QBLCSJ.js.map +1 -0
- package/dist/{codex-RXIS5BHM.js → codex-S2RADR5K.js} +2 -2
- package/dist/{crush-YB3SK6NK.js → crush-AJNQRFVE.js} +2 -2
- package/dist/{define-connector-odRHEC4H.d.ts → define-connector-iosc34CA.d.ts} +1 -1
- package/dist/{detect-USP5JMWM.js → detect-ZC344YOJ.js} +4 -4
- package/dist/{doctor-VSW5KHBM.js → doctor-ABYQF2YX.js} +13 -13
- package/dist/{goose-3X7ID7YW.js → goose-SXFRT7UF.js} +2 -2
- package/dist/grok-build-EP2ZUFXZ.js +682 -0
- package/dist/grok-build-EP2ZUFXZ.js.map +1 -0
- package/dist/{grok-cli-4VFVF2CQ.js → grok-cli-UUNPOUYY.js} +4 -3
- package/dist/grok-cli-UUNPOUYY.js.map +1 -0
- package/dist/{hook-QRW3ON6C.js → hook-M3KQSEO3.js} +8 -8
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/{install-ASTAUZKB.js → install-4X4JDKGY.js} +10 -10
- package/dist/{introspect-gTx6GzpW.d.ts → introspect-z3eKVWHN.d.ts} +1 -1
- package/dist/{kilo-SW7BH6EG.js → kilo-FVBFSS4Y.js} +1 -1
- package/dist/kilo-FVBFSS4Y.js.map +1 -0
- package/dist/{kilo-T4OXNUYY.js → kilo-N5T6KXAG.js} +2 -2
- package/dist/{kilo-cli-I2S3W245.js → kilo-cli-JOAEWYI4.js} +2 -2
- package/dist/{leaderboard-3XSVSGAJ.js → leaderboard-Q4YZ3LI7.js} +3 -3
- package/dist/{mux-BO2L5CTW.js → mux-WSZWWZOX.js} +27 -21
- package/dist/mux-WSZWWZOX.js.map +1 -0
- package/dist/{package-VWBPHCLA.js → package-FY2QZWRM.js} +6 -6
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.js +6 -6
- package/dist/sdk/index.d.ts +4 -4
- package/dist/sdk/index.js +3 -3
- package/dist/sdk/test.d.ts +2 -2
- package/dist/sdk/test.js +6 -6
- package/dist/{serve-IQGHE4SJ.js → serve-XT76DWUN.js} +8 -8
- package/dist/{status-BVLY6XDL.js → status-DHVWBRLI.js} +8 -8
- package/dist/{statusline-PRODZV2J.js → statusline-SY5UBQOJ.js} +7 -7
- package/dist/{telemetry-UU4SHJ23.js → telemetry-TJIFAKWX.js} +5 -5
- package/dist/{types-DWXnnx-N.d.ts → types-CAKApZpX.d.ts} +4 -4
- package/dist/{uninstall-WI5YLDCT.js → uninstall-VQO36IQ4.js} +10 -10
- package/dist/{upgrade-L45BTG6X.js → upgrade-QEYZOA7S.js} +10 -10
- package/dist/{usage-K3NQTAJP.js → usage-LV7UGO64.js} +3 -3
- package/dist/{usage-event-J5CQ6LNT.js → usage-event-MQMKMK2R.js} +7 -7
- package/dist/{windsurf-R6D2JUTN.js → windsurf-ZWVFNJ73.js} +1 -1
- package/dist/windsurf-ZWVFNJ73.js.map +1 -0
- package/dist/{zed-DQV3ZUCU.js → zed-JCOKXOLA.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-G5HAIYRM.js.map +0 -1
- package/dist/chunk-IRUYJD23.js.map +0 -1
- package/dist/chunk-WZMSSIDN.js.map +0 -1
- package/dist/cline-JAPJNOZQ.js.map +0 -1
- package/dist/codebuff-3VODFPD4.js.map +0 -1
- package/dist/grok-cli-4VFVF2CQ.js.map +0 -1
- package/dist/kilo-SW7BH6EG.js.map +0 -1
- package/dist/mux-BO2L5CTW.js.map +0 -1
- package/dist/roo-code-SUWI4BBN.js +0 -229
- package/dist/roo-code-SUWI4BBN.js.map +0 -1
- package/dist/roo-code-VI2ZKTZC.js +0 -361
- package/dist/roo-code-VI2ZKTZC.js.map +0 -1
- package/dist/windsurf-R6D2JUTN.js.map +0 -1
- /package/dist/{action-LEYTHNIU.js.map → action-EKK6FMPY.js.map} +0 -0
- /package/dist/{audit-HPKCUCES.js.map → audit-H7PQWIVH.js.map} +0 -0
- /package/dist/{chunk-BXPSDNIB.js.map → chunk-34RRWEWU.js.map} +0 -0
- /package/dist/{chunk-6WN37NVN.js.map → chunk-6FRAVOVF.js.map} +0 -0
- /package/dist/{chunk-2Y2MZRLP.js.map → chunk-CWUPIT72.js.map} +0 -0
- /package/dist/{chunk-6XMV2OOA.js.map → chunk-CZOXXS77.js.map} +0 -0
- /package/dist/{chunk-FKW5A6HE.js.map → chunk-IY3SSCNK.js.map} +0 -0
- /package/dist/{chunk-U2XJWG7N.js.map → chunk-JUBEM3OR.js.map} +0 -0
- /package/dist/{chunk-4KIXXJ7B.js.map → chunk-KY2VQGD7.js.map} +0 -0
- /package/dist/{chunk-M6OS4OLU.js.map → chunk-R4FABNAL.js.map} +0 -0
- /package/dist/{chunk-T5AI3AW3.js.map → chunk-SA6CSOH5.js.map} +0 -0
- /package/dist/{claude-code-LJ6DVXWQ.js.map → claude-code-VEERATN5.js.map} +0 -0
- /package/dist/{codex-RXIS5BHM.js.map → codex-S2RADR5K.js.map} +0 -0
- /package/dist/{crush-YB3SK6NK.js.map → crush-AJNQRFVE.js.map} +0 -0
- /package/dist/{detect-USP5JMWM.js.map → detect-ZC344YOJ.js.map} +0 -0
- /package/dist/{doctor-VSW5KHBM.js.map → doctor-ABYQF2YX.js.map} +0 -0
- /package/dist/{goose-3X7ID7YW.js.map → goose-SXFRT7UF.js.map} +0 -0
- /package/dist/{hook-QRW3ON6C.js.map → hook-M3KQSEO3.js.map} +0 -0
- /package/dist/{install-ASTAUZKB.js.map → install-4X4JDKGY.js.map} +0 -0
- /package/dist/{kilo-T4OXNUYY.js.map → kilo-N5T6KXAG.js.map} +0 -0
- /package/dist/{kilo-cli-I2S3W245.js.map → kilo-cli-JOAEWYI4.js.map} +0 -0
- /package/dist/{leaderboard-3XSVSGAJ.js.map → leaderboard-Q4YZ3LI7.js.map} +0 -0
- /package/dist/{package-VWBPHCLA.js.map → package-FY2QZWRM.js.map} +0 -0
- /package/dist/{serve-IQGHE4SJ.js.map → serve-XT76DWUN.js.map} +0 -0
- /package/dist/{status-BVLY6XDL.js.map → status-DHVWBRLI.js.map} +0 -0
- /package/dist/{statusline-PRODZV2J.js.map → statusline-SY5UBQOJ.js.map} +0 -0
- /package/dist/{telemetry-UU4SHJ23.js.map → telemetry-TJIFAKWX.js.map} +0 -0
- /package/dist/{uninstall-WI5YLDCT.js.map → uninstall-VQO36IQ4.js.map} +0 -0
- /package/dist/{upgrade-L45BTG6X.js.map → upgrade-QEYZOA7S.js.map} +0 -0
- /package/dist/{usage-K3NQTAJP.js.map → usage-LV7UGO64.js.map} +0 -0
- /package/dist/{usage-event-J5CQ6LNT.js.map → usage-event-MQMKMK2R.js.map} +0 -0
- /package/dist/{zed-DQV3ZUCU.js.map → zed-JCOKXOLA.js.map} +0 -0
|
@@ -0,0 +1,682 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
grokBuildConfigHome
|
|
4
|
+
} from "./chunk-KOFCNA5T.js";
|
|
5
|
+
import {
|
|
6
|
+
normalizeSessionSource
|
|
7
|
+
} from "./chunk-H53QZQJI.js";
|
|
8
|
+
import {
|
|
9
|
+
resolveEnvRefsDeep
|
|
10
|
+
} from "./chunk-BEFVJ2OE.js";
|
|
11
|
+
import {
|
|
12
|
+
BaseAdapter,
|
|
13
|
+
removeFromObjectMap,
|
|
14
|
+
renderCommandMd,
|
|
15
|
+
renderSkillMd,
|
|
16
|
+
renderSubagentMd,
|
|
17
|
+
upsertInObjectMap
|
|
18
|
+
} from "./chunk-JTN3AKZO.js";
|
|
19
|
+
import {
|
|
20
|
+
buildHomeBinHookCommand,
|
|
21
|
+
buildWrappedStdio
|
|
22
|
+
} from "./chunk-QSY74NAP.js";
|
|
23
|
+
import "./chunk-UMQ6NBQR.js";
|
|
24
|
+
import {
|
|
25
|
+
ensureDir
|
|
26
|
+
} from "./chunk-GZGLCCEE.js";
|
|
27
|
+
|
|
28
|
+
// src/adapters/grok-build/index.ts
|
|
29
|
+
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
30
|
+
import { dirname, join } from "path";
|
|
31
|
+
import TOML from "@iarna/toml";
|
|
32
|
+
var GROK_BUILD_HOOK_EVENTS = [
|
|
33
|
+
"SessionStart",
|
|
34
|
+
"SessionEnd",
|
|
35
|
+
"UserPromptSubmit",
|
|
36
|
+
"PreToolUse",
|
|
37
|
+
"PostToolUse",
|
|
38
|
+
"PostToolUseFailure",
|
|
39
|
+
"Stop",
|
|
40
|
+
"Notification",
|
|
41
|
+
"SubagentStart",
|
|
42
|
+
"SubagentStop",
|
|
43
|
+
"PreCompact",
|
|
44
|
+
"PostCompact"
|
|
45
|
+
];
|
|
46
|
+
var PRE_TOOL_USE_MATCHER = "run_terminal_command|Bash|search_replace|Edit|Write|MultiEdit|apply_patch|spawn_subagent|Task";
|
|
47
|
+
var WARN_SKIP_EVENTS = /* @__PURE__ */ new Set(["PermissionRequest"]);
|
|
48
|
+
var HOOKS_FILENAME = "agent-connector.json";
|
|
49
|
+
function coerceToolResult(value) {
|
|
50
|
+
if (value === void 0 || value === null) return void 0;
|
|
51
|
+
if (typeof value === "string") return value;
|
|
52
|
+
try {
|
|
53
|
+
return JSON.stringify(value);
|
|
54
|
+
} catch {
|
|
55
|
+
return String(value);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
var GrokBuildAdapter = class extends BaseAdapter {
|
|
59
|
+
id = "grok-build";
|
|
60
|
+
name = "Grok Build";
|
|
61
|
+
paradigm = "json-stdio";
|
|
62
|
+
capabilities = {
|
|
63
|
+
preToolUse: true,
|
|
64
|
+
postToolUse: true,
|
|
65
|
+
preCompact: true,
|
|
66
|
+
sessionStart: true,
|
|
67
|
+
sessionEnd: true,
|
|
68
|
+
userPromptSubmit: true,
|
|
69
|
+
stop: true,
|
|
70
|
+
notification: true,
|
|
71
|
+
// PostToolUseFailure is a first-class Grok event (a dispatch failure or an
|
|
72
|
+
// MCP error result fires it INSTEAD of PostToolUse); SubagentStart/Stop and
|
|
73
|
+
// PostCompact are all native. permissionRequest stays UNSET — see the header.
|
|
74
|
+
postToolUseFailure: true,
|
|
75
|
+
subagentStart: true,
|
|
76
|
+
subagentStop: true,
|
|
77
|
+
postCompact: true,
|
|
78
|
+
// PreToolUse `updatedInput` rewrites the call before it runs, and every
|
|
79
|
+
// downstream consumer (plan-mode gate, permission prompt, the tool, the later
|
|
80
|
+
// PostToolUse payload) sees the rewritten input.
|
|
81
|
+
canModifyArgs: true,
|
|
82
|
+
// PostToolUse `updatedToolOutput` replaces the model's copy of the result —
|
|
83
|
+
// "Universal key; works for every tool".
|
|
84
|
+
canModifyOutput: true,
|
|
85
|
+
// FALSE: Grok ignores stdout on SessionStart ("For events like SessionStart
|
|
86
|
+
// or Notification, stdout is ignored. Just exit 0.") and on an allowing
|
|
87
|
+
// UserPromptSubmit ("stdout of an allowing hook is discarded (no
|
|
88
|
+
// additionalContext)"). Context injection exists only on the tool events,
|
|
89
|
+
// which this flag does not describe.
|
|
90
|
+
canInjectSessionContext: false,
|
|
91
|
+
// `grok mcp add` documents stdio (default), --transport http and
|
|
92
|
+
// --transport sse; the TOML carries `url` for both remote forms.
|
|
93
|
+
transports: ["stdio", "http", "sse"],
|
|
94
|
+
// Content surfaces, all under <scope>/.grok:
|
|
95
|
+
// command → commands/<name>.md (flat md, stem = slash name)
|
|
96
|
+
// skill → skills/<name>/SKILL.md (Anthropic frontmatter)
|
|
97
|
+
// subagent → agents/<name>.md (name/description/tools/model)
|
|
98
|
+
supportsCommands: true,
|
|
99
|
+
supportsSkills: true,
|
|
100
|
+
supportsSubagents: true,
|
|
101
|
+
// Memory: AGENTS.md (project) / $GROK_HOME/rules (user).
|
|
102
|
+
supportsMemory: true
|
|
103
|
+
};
|
|
104
|
+
// ── Detection ──────────────────────────────────────────────────────────
|
|
105
|
+
/**
|
|
106
|
+
* Grok Build is installed when its OWN marker file exists, or when a config
|
|
107
|
+
* dir exists that is not merely the community Grok CLI's `~/.grok`. The
|
|
108
|
+
* sibling bow-out is what keeps the two products' shared default directory
|
|
109
|
+
* from cross-reporting (see the header).
|
|
110
|
+
*/
|
|
111
|
+
detectInstalled(projectDir) {
|
|
112
|
+
const userDir = this.userConfigDir();
|
|
113
|
+
const projDir = join(projectDir, ".grok");
|
|
114
|
+
const userCfg = join(userDir, "config.toml");
|
|
115
|
+
const projCfg = join(projDir, "config.toml");
|
|
116
|
+
const siblingOnly = existsSync(join(userDir, "user-settings.json")) && !existsSync(userCfg);
|
|
117
|
+
const userInstalled = existsSync(userCfg) || existsSync(userDir) && !siblingOnly;
|
|
118
|
+
const projInstalled = existsSync(projCfg) || existsSync(projDir);
|
|
119
|
+
const installed = userInstalled || projInstalled;
|
|
120
|
+
const scope = projInstalled && !userInstalled ? "project" : "user";
|
|
121
|
+
const configPath = scope === "project" ? projCfg : userCfg;
|
|
122
|
+
return {
|
|
123
|
+
id: this.id,
|
|
124
|
+
name: this.name,
|
|
125
|
+
installed,
|
|
126
|
+
paradigm: this.paradigm,
|
|
127
|
+
capabilities: this.capabilities,
|
|
128
|
+
configPath,
|
|
129
|
+
scope,
|
|
130
|
+
reason: installed ? `found Grok Build config dir (${scope})` : siblingOnly ? `${userDir} holds only the community Grok CLI's user-settings.json` : `no .grok config dir at ${userDir} or ${projDir}`,
|
|
131
|
+
confidence: installed ? "high" : "low"
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
// ── Native paths ───────────────────────────────────────────────────────
|
|
135
|
+
getConfigDir(ctx) {
|
|
136
|
+
if (ctx.scope === "project") return join(ctx.projectDir, ".grok");
|
|
137
|
+
return this.userConfigDir();
|
|
138
|
+
}
|
|
139
|
+
getServerConfigPath(ctx) {
|
|
140
|
+
return join(this.getConfigDir(ctx), "config.toml");
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Hooks live in their OWN directory, one JSON file per author —
|
|
144
|
+
* `$GROK_HOME/hooks/*.json` (user) or `<project>/.grok/hooks/*.json`. We own
|
|
145
|
+
* exactly one file there, so an install never rewrites a hand-authored config.
|
|
146
|
+
*/
|
|
147
|
+
getHookConfigPath(ctx) {
|
|
148
|
+
return join(this.getConfigDir(ctx), "hooks", HOOKS_FILENAME);
|
|
149
|
+
}
|
|
150
|
+
/** `$GROK_HOME` (tilde-expanded, then resolved) || `~/.grok`. */
|
|
151
|
+
userConfigDir() {
|
|
152
|
+
return grokBuildConfigHome();
|
|
153
|
+
}
|
|
154
|
+
// ── Memory surface: AGENTS.md (project) / $GROK_HOME/rules (user) ────────
|
|
155
|
+
// 12-project-rules.md is titled "Project Rules (AGENTS.md)" and documents
|
|
156
|
+
// AGENTS.md discovery from the repo root down to the cwd. The USER tier has no
|
|
157
|
+
// AGENTS.md equivalent: home-level guidance is `*.md` under
|
|
158
|
+
// `$GROK_HOME/rules/` ("Always scanned; applies to all projects").
|
|
159
|
+
memoryTargets(ctx) {
|
|
160
|
+
if (this.memoryOverride(ctx)?.path) return super.memoryTargets(ctx);
|
|
161
|
+
if (ctx.scope === "project") {
|
|
162
|
+
return [
|
|
163
|
+
{
|
|
164
|
+
path: join(ctx.projectDir, "AGENTS.md"),
|
|
165
|
+
reason: "AGENTS.md standard (project root; Grok Build loads it root \u2192 cwd)"
|
|
166
|
+
}
|
|
167
|
+
];
|
|
168
|
+
}
|
|
169
|
+
if (ctx.scope === "user") {
|
|
170
|
+
return [
|
|
171
|
+
{
|
|
172
|
+
path: join(this.userConfigDir(), "rules", "agent-connector.md"),
|
|
173
|
+
reason: "$GROK_HOME/rules/*.md global rules (always scanned, all projects)"
|
|
174
|
+
}
|
|
175
|
+
];
|
|
176
|
+
}
|
|
177
|
+
return [];
|
|
178
|
+
}
|
|
179
|
+
// ── TOML config IO (config.toml is TOML, not JSON) ───────────────────────
|
|
180
|
+
readToml(path) {
|
|
181
|
+
if (!existsSync(path)) return {};
|
|
182
|
+
try {
|
|
183
|
+
return TOML.parse(readFileSync(path, "utf8"));
|
|
184
|
+
} catch {
|
|
185
|
+
return {};
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
writeToml(path, data, dryRun) {
|
|
189
|
+
if (dryRun) return;
|
|
190
|
+
ensureDir(dirname(path));
|
|
191
|
+
writeFileSync(path, TOML.stringify(data), "utf8");
|
|
192
|
+
}
|
|
193
|
+
/** ObjectMapCodec over config.toml, mirroring codex: readToml fail-softs to
|
|
194
|
+
* {} so a corrupt file coerces rather than warn-skipping. */
|
|
195
|
+
tomlObjectMapCodec() {
|
|
196
|
+
return {
|
|
197
|
+
parse: (path) => this.readToml(path),
|
|
198
|
+
serialize: (path, data, dryRun) => this.writeToml(path, data, dryRun),
|
|
199
|
+
isPresentButUnparseable: () => false
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
// ── Install server (config.toml → [mcp_servers.<id>]) ────────────────────
|
|
203
|
+
installServer(ctx) {
|
|
204
|
+
const { connector, dryRun } = ctx;
|
|
205
|
+
const server = this.effectiveServer(ctx);
|
|
206
|
+
const path = this.getServerConfigPath(ctx);
|
|
207
|
+
if (!server) {
|
|
208
|
+
return [{ platform: this.id, action: "skip", path, detail: "no server declared" }];
|
|
209
|
+
}
|
|
210
|
+
const isStdio = server.transport === "stdio" && !!server.command;
|
|
211
|
+
const isRemote = (server.transport === "http" || server.transport === "sse") && !!server.url;
|
|
212
|
+
if (!isStdio && !isRemote) {
|
|
213
|
+
return [
|
|
214
|
+
{
|
|
215
|
+
platform: this.id,
|
|
216
|
+
action: "skip",
|
|
217
|
+
path,
|
|
218
|
+
detail: `transport "${server.transport}" not registrable in config.toml (stdio + http/sse url only)`
|
|
219
|
+
}
|
|
220
|
+
];
|
|
221
|
+
}
|
|
222
|
+
const symlink = this.symlinkPathWarning(path);
|
|
223
|
+
if (symlink) return [symlink];
|
|
224
|
+
return [
|
|
225
|
+
upsertInObjectMap({
|
|
226
|
+
codec: this.tomlObjectMapCodec(),
|
|
227
|
+
rootKey: "mcp_servers",
|
|
228
|
+
policy: "coerce",
|
|
229
|
+
platform: this.id,
|
|
230
|
+
configPath: path,
|
|
231
|
+
entryId: connector.id,
|
|
232
|
+
entry: this.renderMcpEntry(ctx, server),
|
|
233
|
+
dryRun
|
|
234
|
+
})
|
|
235
|
+
];
|
|
236
|
+
}
|
|
237
|
+
uninstallServer(ctx) {
|
|
238
|
+
const { connector, dryRun } = ctx;
|
|
239
|
+
const path = this.getServerConfigPath(ctx);
|
|
240
|
+
const symlink = this.symlinkPathWarning(path);
|
|
241
|
+
if (symlink) return [symlink];
|
|
242
|
+
return [
|
|
243
|
+
removeFromObjectMap({
|
|
244
|
+
codec: this.tomlObjectMapCodec(),
|
|
245
|
+
rootKey: "mcp_servers",
|
|
246
|
+
policy: "coerce",
|
|
247
|
+
platform: this.id,
|
|
248
|
+
configPath: path,
|
|
249
|
+
entryId: connector.id,
|
|
250
|
+
dryRun
|
|
251
|
+
})
|
|
252
|
+
];
|
|
253
|
+
}
|
|
254
|
+
// ── Install hooks (hooks/agent-connector.json) ───────────────────────────
|
|
255
|
+
installHooks(ctx) {
|
|
256
|
+
const path = this.getHookConfigPath(ctx);
|
|
257
|
+
const hooksOff = ctx.connector.platforms[this.id]?.hooks === false;
|
|
258
|
+
const declared = hooksOff ? [] : ctx.connector.hookEvents;
|
|
259
|
+
if (declared.length === 0) {
|
|
260
|
+
return [{ platform: this.id, action: "skip", path, detail: "no hooks declared" }];
|
|
261
|
+
}
|
|
262
|
+
const supported = (e) => GROK_BUILD_HOOK_EVENTS.includes(e);
|
|
263
|
+
const pending = [
|
|
264
|
+
...declared.filter((e) => !supported(e)).map((event) => ({ event, matcher: "" })),
|
|
265
|
+
...declared.filter(supported).map((event) => ({ event, matcher: "" }))
|
|
266
|
+
];
|
|
267
|
+
return this.upsertHookEntries(ctx, path, pending, this.hookDescriptor(ctx));
|
|
268
|
+
}
|
|
269
|
+
uninstallHooks(ctx) {
|
|
270
|
+
return this.removeHookEntries(ctx, this.getHookConfigPath(ctx), this.hookDescriptor(ctx));
|
|
271
|
+
}
|
|
272
|
+
/** Hook-merge policy for the shared object-map engine (Claude-compatible file). */
|
|
273
|
+
hookDescriptor(_ctx) {
|
|
274
|
+
return {
|
|
275
|
+
malformedPolicy: "coerce",
|
|
276
|
+
mapEvent: (e) => GROK_BUILD_HOOK_EVENTS.includes(e) ? e : void 0,
|
|
277
|
+
unmappedWarnDetail: (e) => `${e} has no Grok Build hook equivalent \u2014 skipped`,
|
|
278
|
+
unmappedAction: (e) => WARN_SKIP_EVENTS.has(e) ? "warn" : "skip",
|
|
279
|
+
renderEntry: (event, _matcher, command) => {
|
|
280
|
+
const entry = { hooks: [{ type: "command", command }] };
|
|
281
|
+
entry.matcher = event === "PreToolUse" ? PRE_TOOL_USE_MATCHER : "";
|
|
282
|
+
return entry;
|
|
283
|
+
},
|
|
284
|
+
entryOwnsCommand: (entry, command) => Array.isArray(entry.hooks) && entry.hooks.some(
|
|
285
|
+
(h) => (h.command ?? "").replace(/\\/g, "/") === command.replace(/\\/g, "/")
|
|
286
|
+
),
|
|
287
|
+
ownsEntryForRemove: (c, event) => (entry) => this.isOurEntry(c, event, entry),
|
|
288
|
+
skipDetail: (e) => `hooks.${e}`,
|
|
289
|
+
removeDetail: (e, _n) => `hooks.${e}`,
|
|
290
|
+
absentDetail: `no ${HOOKS_FILENAME}`,
|
|
291
|
+
noMatchDetail: "no agent-connector hooks present",
|
|
292
|
+
removeEventKeys: GROK_BUILD_HOOK_EVENTS
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
// ── Health checks ────────────────────────────────────────────────────────
|
|
296
|
+
getHealthChecks(ctx) {
|
|
297
|
+
const path = this.getServerConfigPath(ctx);
|
|
298
|
+
const id = ctx.connector.id;
|
|
299
|
+
const checks = [
|
|
300
|
+
{
|
|
301
|
+
name: `${this.name}: config.toml exists`,
|
|
302
|
+
check: () => existsSync(path) ? { status: "OK", detail: path } : { status: "FAIL", detail: `not found: ${path}` }
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
name: `${this.name}: mcp_servers.${id} registered`,
|
|
306
|
+
check: () => {
|
|
307
|
+
if (!ctx.connector.server) {
|
|
308
|
+
return { status: "OK", detail: "no MCP server declared" };
|
|
309
|
+
}
|
|
310
|
+
const bucket = this.readToml(path)["mcp_servers"];
|
|
311
|
+
const present = typeof bucket === "object" && bucket !== null && id in bucket;
|
|
312
|
+
return present ? { status: "OK", detail: `mcp_servers.${id}` } : { status: "FAIL", detail: `mcp_servers.${id} not found in ${path}` };
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
];
|
|
316
|
+
for (const cmd of ctx.connector.commands) {
|
|
317
|
+
const p = this.commandPath(ctx, cmd.name);
|
|
318
|
+
checks.push({
|
|
319
|
+
name: `${this.name}: command ${cmd.name} present`,
|
|
320
|
+
check: () => existsSync(p) ? { status: "OK", detail: p } : { status: "FAIL", detail: `not found: ${p}` }
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
for (const skill of ctx.connector.skills) {
|
|
324
|
+
const p = join(this.skillDir(ctx, skill.name), "SKILL.md");
|
|
325
|
+
checks.push({
|
|
326
|
+
name: `${this.name}: skill ${skill.name} present`,
|
|
327
|
+
check: () => existsSync(p) ? { status: "OK", detail: p } : { status: "FAIL", detail: `not found: ${p}` }
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
for (const agent of ctx.connector.subagents) {
|
|
331
|
+
const p = this.subagentPath(ctx, agent.name);
|
|
332
|
+
checks.push({
|
|
333
|
+
name: `${this.name}: subagent ${agent.name} present`,
|
|
334
|
+
check: () => existsSync(p) ? { status: "OK", detail: p } : { status: "FAIL", detail: `not found: ${p}` }
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
return checks;
|
|
338
|
+
}
|
|
339
|
+
// ── Content surfaces: commands / skills / subagents ──────────────────────
|
|
340
|
+
// Pure native-file writers under <scope>/.grok — idempotent via
|
|
341
|
+
// writeContentFile, reversible via removeContentFile. All three roots are
|
|
342
|
+
// scope-symmetric (Grok scans the same layout at user, repo and cwd tiers).
|
|
343
|
+
commandPath(ctx, name) {
|
|
344
|
+
return join(this.getConfigDir(ctx), "commands", `${name}.md`);
|
|
345
|
+
}
|
|
346
|
+
skillDir(ctx, name) {
|
|
347
|
+
return join(this.getConfigDir(ctx), "skills", name);
|
|
348
|
+
}
|
|
349
|
+
subagentPath(ctx, name) {
|
|
350
|
+
return join(this.getConfigDir(ctx), "agents", `${name}.md`);
|
|
351
|
+
}
|
|
352
|
+
// ── Commands (flat markdown; filename stem = slash-command name) ──────────
|
|
353
|
+
installCommands(ctx) {
|
|
354
|
+
const { connector } = ctx;
|
|
355
|
+
if (connector.platforms[this.id]?.commands === false) {
|
|
356
|
+
return [{ platform: this.id, action: "skip", detail: "commands disabled for grok-build" }];
|
|
357
|
+
}
|
|
358
|
+
if (connector.commands.length === 0) {
|
|
359
|
+
return [{ platform: this.id, action: "skip", detail: "connector declares no commands" }];
|
|
360
|
+
}
|
|
361
|
+
return connector.commands.map(
|
|
362
|
+
(cmd) => this.writeContentFile(
|
|
363
|
+
this.commandPath(ctx, cmd.name),
|
|
364
|
+
// Grok's command markdown is the Claude legacy layout: description +
|
|
365
|
+
// argument-hint frontmatter. It has no allowed-tools/model keys on a
|
|
366
|
+
// COMMAND (those are skill/agent frontmatter fields), so both are dropped.
|
|
367
|
+
renderCommandMd(cmd, { includeToolsAndModel: false }),
|
|
368
|
+
ctx.dryRun
|
|
369
|
+
)
|
|
370
|
+
);
|
|
371
|
+
}
|
|
372
|
+
uninstallCommands(ctx) {
|
|
373
|
+
const { connector } = ctx;
|
|
374
|
+
if (connector.commands.length === 0) {
|
|
375
|
+
return [{ platform: this.id, action: "skip", detail: "connector declares no commands" }];
|
|
376
|
+
}
|
|
377
|
+
return connector.commands.map(
|
|
378
|
+
(cmd) => this.removeContentFile(this.commandPath(ctx, cmd.name), ctx.dryRun)
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
// ── Skills (Anthropic-format SKILL.md) ───────────────────────────────────
|
|
382
|
+
installSkills(ctx) {
|
|
383
|
+
const { connector } = ctx;
|
|
384
|
+
if (connector.platforms[this.id]?.skills === false) {
|
|
385
|
+
return [{ platform: this.id, action: "skip", detail: "skills disabled for grok-build" }];
|
|
386
|
+
}
|
|
387
|
+
if (connector.skills.length === 0) {
|
|
388
|
+
return [{ platform: this.id, action: "skip", detail: "connector declares no skills" }];
|
|
389
|
+
}
|
|
390
|
+
const changes = [];
|
|
391
|
+
for (const skill of connector.skills) {
|
|
392
|
+
const dir = this.skillDir(ctx, skill.name);
|
|
393
|
+
changes.push(this.writeContentFile(join(dir, "SKILL.md"), renderSkillMd(skill), ctx.dryRun));
|
|
394
|
+
for (const [rel, contents] of Object.entries(skill.resources ?? {})) {
|
|
395
|
+
const target = this.resolveWithin(dir, rel);
|
|
396
|
+
if (target === null) {
|
|
397
|
+
changes.push({
|
|
398
|
+
platform: this.id,
|
|
399
|
+
action: "warn",
|
|
400
|
+
detail: `skill resource "${rel}" escapes the skill dir; skipped`
|
|
401
|
+
});
|
|
402
|
+
continue;
|
|
403
|
+
}
|
|
404
|
+
changes.push(this.writeContentFile(target, contents, ctx.dryRun));
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
return changes;
|
|
408
|
+
}
|
|
409
|
+
uninstallSkills(ctx) {
|
|
410
|
+
const { connector } = ctx;
|
|
411
|
+
if (connector.skills.length === 0) {
|
|
412
|
+
return [{ platform: this.id, action: "skip", detail: "connector declares no skills" }];
|
|
413
|
+
}
|
|
414
|
+
const changes = [];
|
|
415
|
+
for (const skill of connector.skills) {
|
|
416
|
+
const dir = this.skillDir(ctx, skill.name);
|
|
417
|
+
changes.push(this.removeContentFile(join(dir, "SKILL.md"), ctx.dryRun));
|
|
418
|
+
for (const rel of Object.keys(skill.resources ?? {})) {
|
|
419
|
+
const target = this.resolveWithin(dir, rel);
|
|
420
|
+
if (target === null) continue;
|
|
421
|
+
changes.push(this.removeContentFile(target, ctx.dryRun));
|
|
422
|
+
}
|
|
423
|
+
changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));
|
|
424
|
+
}
|
|
425
|
+
return changes;
|
|
426
|
+
}
|
|
427
|
+
// ── Subagents (md + frontmatter: name, description, tools, model) ─────────
|
|
428
|
+
installSubagents(ctx) {
|
|
429
|
+
const { connector } = ctx;
|
|
430
|
+
if (connector.platforms[this.id]?.subagents === false) {
|
|
431
|
+
return [{ platform: this.id, action: "skip", detail: "subagents disabled for grok-build" }];
|
|
432
|
+
}
|
|
433
|
+
if (connector.subagents.length === 0) {
|
|
434
|
+
return [{ platform: this.id, action: "skip", detail: "connector declares no subagents" }];
|
|
435
|
+
}
|
|
436
|
+
return connector.subagents.map(
|
|
437
|
+
(agent) => this.writeContentFile(
|
|
438
|
+
this.subagentPath(ctx, agent.name),
|
|
439
|
+
this.renderSubagent(agent),
|
|
440
|
+
ctx.dryRun
|
|
441
|
+
)
|
|
442
|
+
);
|
|
443
|
+
}
|
|
444
|
+
uninstallSubagents(ctx) {
|
|
445
|
+
const { connector } = ctx;
|
|
446
|
+
if (connector.subagents.length === 0) {
|
|
447
|
+
return [{ platform: this.id, action: "skip", detail: "connector declares no subagents" }];
|
|
448
|
+
}
|
|
449
|
+
return connector.subagents.map(
|
|
450
|
+
(agent) => this.removeContentFile(this.subagentPath(ctx, agent.name), ctx.dryRun)
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Grok agent definitions are md + YAML frontmatter whose documented keys —
|
|
455
|
+
* name, description, tools, model — are exactly the shared renderer's shape
|
|
456
|
+
* (16-subagents.md shows `name`, `description`, `tools` in its frontmatter
|
|
457
|
+
* example). `extra` remains the escape hatch for Grok-only keys such as
|
|
458
|
+
* `mcpInheritance`.
|
|
459
|
+
*/
|
|
460
|
+
renderSubagent(agent) {
|
|
461
|
+
return renderSubagentMd(agent);
|
|
462
|
+
}
|
|
463
|
+
// ── Runtime dispatch ─────────────────────────────────────────────────────
|
|
464
|
+
parseEvent(event, raw) {
|
|
465
|
+
const input = raw ?? {};
|
|
466
|
+
const toolName = input.toolName ?? input.tool_name ?? "";
|
|
467
|
+
const toolInput = input.toolInput ?? input.tool_input ?? {};
|
|
468
|
+
const base = {
|
|
469
|
+
hostPlatform: this.id,
|
|
470
|
+
connectorId: "",
|
|
471
|
+
sessionId: input.sessionId ?? input.session_id ?? `pid-${process.ppid}`,
|
|
472
|
+
// `cwd` is the session's working directory; `workspaceRoot` is the repo
|
|
473
|
+
// root. Prefer cwd (matches every other adapter's projectDir semantics).
|
|
474
|
+
projectDir: input.cwd ?? input.workspaceRoot ?? process.cwd(),
|
|
475
|
+
raw
|
|
476
|
+
};
|
|
477
|
+
switch (event) {
|
|
478
|
+
case "PreToolUse":
|
|
479
|
+
return { ...base, toolName, toolInput };
|
|
480
|
+
case "PostToolUse":
|
|
481
|
+
return {
|
|
482
|
+
...base,
|
|
483
|
+
toolName,
|
|
484
|
+
toolInput,
|
|
485
|
+
// Upstream field is `toolResult` (aliased to `tool_response`).
|
|
486
|
+
toolOutput: coerceToolResult(input.toolResult ?? input.tool_response),
|
|
487
|
+
// Grok's PostToolUse payload has NO error flag: a dispatch failure or
|
|
488
|
+
// an MCP error result fires PostToolUseFailure instead. Never invent one.
|
|
489
|
+
isError: false
|
|
490
|
+
};
|
|
491
|
+
case "SessionStart":
|
|
492
|
+
return { ...base, source: normalizeSessionSource(input.source) };
|
|
493
|
+
case "SessionEnd":
|
|
494
|
+
return { ...base, reason: input.reason };
|
|
495
|
+
case "UserPromptSubmit":
|
|
496
|
+
return { ...base, prompt: input.prompt ?? "" };
|
|
497
|
+
case "PreCompact":
|
|
498
|
+
case "PostCompact":
|
|
499
|
+
return { ...base, trigger: input.source === "manual" ? "manual" : "auto" };
|
|
500
|
+
case "Stop":
|
|
501
|
+
return { ...base, stopHookActive: input.stopHookActive ?? false };
|
|
502
|
+
case "Notification":
|
|
503
|
+
return { ...base, message: input.message ?? input.notificationType ?? "" };
|
|
504
|
+
case "PostToolUseFailure":
|
|
505
|
+
return {
|
|
506
|
+
...base,
|
|
507
|
+
toolName,
|
|
508
|
+
toolInput,
|
|
509
|
+
error: input.error ?? "",
|
|
510
|
+
...typeof (input.toolUseId ?? input.tool_use_id) === "string" ? { toolUseId: input.toolUseId ?? input.tool_use_id } : {},
|
|
511
|
+
...typeof (input.isInterrupt ?? input.is_interrupt) === "boolean" ? { isInterrupt: input.isInterrupt ?? input.is_interrupt } : {},
|
|
512
|
+
...typeof (input.durationMs ?? input.duration_ms) === "number" ? { durationMs: input.durationMs ?? input.duration_ms } : {}
|
|
513
|
+
};
|
|
514
|
+
case "SubagentStart":
|
|
515
|
+
return {
|
|
516
|
+
...base,
|
|
517
|
+
...typeof input.subagentId === "string" ? { agentId: input.subagentId } : {},
|
|
518
|
+
...typeof input.subagentType === "string" ? { agentType: input.subagentType } : {}
|
|
519
|
+
};
|
|
520
|
+
case "SubagentStop":
|
|
521
|
+
return {
|
|
522
|
+
...base,
|
|
523
|
+
...typeof input.subagentId === "string" ? { agentId: input.subagentId } : {},
|
|
524
|
+
...typeof input.subagentType === "string" ? { agentType: input.subagentType } : {},
|
|
525
|
+
...typeof input.lastAssistantMessage === "string" ? { lastAssistantMessage: input.lastAssistantMessage } : {},
|
|
526
|
+
...typeof input.stopHookActive === "boolean" ? { stopHookActive: input.stopHookActive } : {}
|
|
527
|
+
};
|
|
528
|
+
case "PermissionRequest":
|
|
529
|
+
return { ...base, toolName, toolInput };
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
formatReply(event, response) {
|
|
533
|
+
if (response.decision === "deny") {
|
|
534
|
+
if (event === "PreToolUse") {
|
|
535
|
+
return {
|
|
536
|
+
exitCode: 0,
|
|
537
|
+
stdout: JSON.stringify({
|
|
538
|
+
hookSpecificOutput: {
|
|
539
|
+
hookEventName: "PreToolUse",
|
|
540
|
+
permissionDecision: "deny",
|
|
541
|
+
permissionDecisionReason: response.reason ?? "Blocked by hook"
|
|
542
|
+
}
|
|
543
|
+
})
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
if (event === "UserPromptSubmit" || event === "Stop" || event === "SubagentStop" || event === "PostToolUse") {
|
|
547
|
+
return {
|
|
548
|
+
exitCode: 0,
|
|
549
|
+
stdout: JSON.stringify({
|
|
550
|
+
decision: "block",
|
|
551
|
+
reason: response.reason ?? "Blocked by hook"
|
|
552
|
+
})
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
if (event === "PostToolUseFailure") {
|
|
556
|
+
return {
|
|
557
|
+
exitCode: 0,
|
|
558
|
+
stdout: JSON.stringify({
|
|
559
|
+
hookSpecificOutput: {
|
|
560
|
+
hookEventName: "PostToolUseFailure",
|
|
561
|
+
additionalContext: response.reason ?? "Blocked by hook"
|
|
562
|
+
}
|
|
563
|
+
})
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
return { exitCode: 0 };
|
|
567
|
+
}
|
|
568
|
+
if (response.decision === "ask" && event === "PreToolUse") {
|
|
569
|
+
return {
|
|
570
|
+
exitCode: 0,
|
|
571
|
+
stdout: JSON.stringify({
|
|
572
|
+
hookSpecificOutput: {
|
|
573
|
+
hookEventName: "PreToolUse",
|
|
574
|
+
permissionDecision: "ask",
|
|
575
|
+
permissionDecisionReason: response.reason ?? "Confirmation required by hook"
|
|
576
|
+
}
|
|
577
|
+
})
|
|
578
|
+
};
|
|
579
|
+
}
|
|
580
|
+
if (response.decision === "modify") {
|
|
581
|
+
if (event === "PreToolUse" && response.updatedInput) {
|
|
582
|
+
return {
|
|
583
|
+
exitCode: 0,
|
|
584
|
+
stdout: JSON.stringify({
|
|
585
|
+
hookSpecificOutput: {
|
|
586
|
+
hookEventName: "PreToolUse",
|
|
587
|
+
updatedInput: response.updatedInput
|
|
588
|
+
}
|
|
589
|
+
})
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
if (event === "PostToolUse" && response.updatedOutput !== void 0) {
|
|
593
|
+
return {
|
|
594
|
+
exitCode: 0,
|
|
595
|
+
stdout: JSON.stringify({
|
|
596
|
+
hookSpecificOutput: {
|
|
597
|
+
hookEventName: "PostToolUse",
|
|
598
|
+
updatedToolOutput: response.updatedOutput
|
|
599
|
+
}
|
|
600
|
+
})
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
return { exitCode: 0 };
|
|
604
|
+
}
|
|
605
|
+
if (response.additionalContext && (event === "PreToolUse" || event === "PostToolUse" || event === "PostToolUseFailure" || event === "Stop" || event === "SubagentStop")) {
|
|
606
|
+
return {
|
|
607
|
+
exitCode: 0,
|
|
608
|
+
stdout: JSON.stringify({
|
|
609
|
+
hookSpecificOutput: {
|
|
610
|
+
hookEventName: event,
|
|
611
|
+
additionalContext: response.additionalContext
|
|
612
|
+
}
|
|
613
|
+
})
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
return { exitCode: 0 };
|
|
617
|
+
}
|
|
618
|
+
// ── Internal helpers ─────────────────────────────────────────────────────
|
|
619
|
+
/** Resolve the per-platform server override into an effective ServerDef. */
|
|
620
|
+
effectiveServer(ctx) {
|
|
621
|
+
const override = ctx.connector.platforms[this.id]?.server;
|
|
622
|
+
if (override === false) return void 0;
|
|
623
|
+
const base = ctx.connector.server;
|
|
624
|
+
if (!base) return void 0;
|
|
625
|
+
return override ? { ...base, ...override } : base;
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
628
|
+
* Render the `[mcp_servers.<id>]` table. TOML has NO interpolation, so every
|
|
629
|
+
* `${env:VAR}` resolves to a literal at install time. Honors the telemetry
|
|
630
|
+
* serve-wrapper (stdio only — a remote server cannot be intercepted).
|
|
631
|
+
*/
|
|
632
|
+
renderMcpEntry(ctx, server) {
|
|
633
|
+
if (server.transport === "http" || server.transport === "sse") {
|
|
634
|
+
const remote = { url: resolveEnvRefsDeep(server.url ?? "") };
|
|
635
|
+
const headers = {};
|
|
636
|
+
if (server.auth?.type === "bearerEnv" && server.auth.bearerEnvVar) {
|
|
637
|
+
headers["Authorization"] = `Bearer \${${server.auth.bearerEnvVar}}`;
|
|
638
|
+
}
|
|
639
|
+
for (const [k, v] of Object.entries(resolveEnvRefsDeep(server.headers ?? {}))) {
|
|
640
|
+
headers[k] = String(v);
|
|
641
|
+
}
|
|
642
|
+
if (Object.keys(headers).length > 0) remote.headers = headers;
|
|
643
|
+
if (server.enabled === false) remote.enabled = false;
|
|
644
|
+
return remote;
|
|
645
|
+
}
|
|
646
|
+
let command = server.command;
|
|
647
|
+
let args = [...server.args ?? []];
|
|
648
|
+
({ command, args } = buildWrappedStdio(ctx, server, this.id, command, args));
|
|
649
|
+
command = resolveEnvRefsDeep(command);
|
|
650
|
+
args = resolveEnvRefsDeep(args);
|
|
651
|
+
const entry = { command };
|
|
652
|
+
if (args.length > 0) entry.args = args;
|
|
653
|
+
if (server.env && Object.keys(server.env).length > 0) {
|
|
654
|
+
const env = {};
|
|
655
|
+
for (const [k, v] of Object.entries(resolveEnvRefsDeep(server.env))) {
|
|
656
|
+
env[k] = String(v);
|
|
657
|
+
}
|
|
658
|
+
entry.env = env;
|
|
659
|
+
}
|
|
660
|
+
if (server.enabled === false) entry.enabled = false;
|
|
661
|
+
return entry;
|
|
662
|
+
}
|
|
663
|
+
/**
|
|
664
|
+
* Does this hooks-file entry belong to this connector for `event`? EVENT-
|
|
665
|
+
* SPECIFIC + path-normalized exact-command match, so an entry under one event
|
|
666
|
+
* key is never matched while iterating another.
|
|
667
|
+
*/
|
|
668
|
+
isOurEntry(ctx, event, entry) {
|
|
669
|
+
if (!entry || typeof entry !== "object" || !Array.isArray(entry.hooks)) return false;
|
|
670
|
+
const ours = buildHomeBinHookCommand(ctx.homeBinPath, "grok-build", event, ctx.connector.id);
|
|
671
|
+
const needle = ours.replace(/\\/g, "/");
|
|
672
|
+
return entry.hooks.some((h) => (h.command ?? "").replace(/\\/g, "/") === needle);
|
|
673
|
+
}
|
|
674
|
+
};
|
|
675
|
+
var adapter = new GrokBuildAdapter();
|
|
676
|
+
var grok_build_default = adapter;
|
|
677
|
+
export {
|
|
678
|
+
GrokBuildAdapter,
|
|
679
|
+
adapter,
|
|
680
|
+
grok_build_default as default
|
|
681
|
+
};
|
|
682
|
+
//# sourceMappingURL=grok-build-EP2ZUFXZ.js.map
|