@ghl-ai/aw 0.1.44-beta.3 → 0.1.44-beta.5
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/c4/index.mjs +0 -1
- package/c4/jsonMerge.mjs +23 -1
- package/c4/slimRouter.mjs +13 -95
- package/package.json +1 -1
package/c4/index.mjs
CHANGED
package/c4/jsonMerge.mjs
CHANGED
|
@@ -110,9 +110,23 @@ function commandMatchesAnyPattern(command, patterns) {
|
|
|
110
110
|
* @param {object} opts.newEntry Entry to append after dedup.
|
|
111
111
|
* @param {string[]} opts.commandPatterns Substrings; existing entries with
|
|
112
112
|
* a matching `command` field are stripped.
|
|
113
|
+
* @param {object} [opts.ensureTopLevel] Optional map of top-level keys to set
|
|
114
|
+
* on the JSON root (always overwritten).
|
|
115
|
+
* Used to guarantee schema-required
|
|
116
|
+
* markers like `{ version: 1 }` for
|
|
117
|
+
* Cursor's `~/.cursor/hooks.json`.
|
|
118
|
+
* Without this, Cursor's runtime fails
|
|
119
|
+
* open and silently skips the hook
|
|
120
|
+
* (cursor.com/docs/hooks §schema, §979).
|
|
113
121
|
* @returns {{ changed: boolean, prevEntriesRemoved: number }}
|
|
114
122
|
*/
|
|
115
|
-
export function jsonMergeWithDedup({
|
|
123
|
+
export function jsonMergeWithDedup({
|
|
124
|
+
filePath,
|
|
125
|
+
jsonPointer,
|
|
126
|
+
newEntry,
|
|
127
|
+
commandPatterns,
|
|
128
|
+
ensureTopLevel,
|
|
129
|
+
}) {
|
|
116
130
|
if (!filePath || typeof filePath !== 'string') throw new Error('filePath is required');
|
|
117
131
|
if (typeof jsonPointer !== 'string') throw new Error('jsonPointer is required');
|
|
118
132
|
if (newEntry == null || typeof newEntry !== 'object') throw new Error('newEntry must be an object');
|
|
@@ -142,6 +156,14 @@ export function jsonMergeWithDedup({ filePath, jsonPointer, newEntry, commandPat
|
|
|
142
156
|
filtered.push(newEntry);
|
|
143
157
|
parent[key] = filtered;
|
|
144
158
|
|
|
159
|
+
// Apply schema-required top-level keys last, so callers can pin invariants
|
|
160
|
+
// (e.g. `version: 1`) even if a stale on-disk file is missing them.
|
|
161
|
+
if (ensureTopLevel != null && typeof ensureTopLevel === 'object' && !Array.isArray(ensureTopLevel)) {
|
|
162
|
+
for (const [k, v] of Object.entries(ensureTopLevel)) {
|
|
163
|
+
root[k] = v;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
145
167
|
const serialized = JSON.stringify(root, null, 2) + '\n';
|
|
146
168
|
const changed = atomicWriteIfChanged(filePath, serialized);
|
|
147
169
|
|
package/c4/slimRouter.mjs
CHANGED
|
@@ -47,94 +47,6 @@ export const REQUIRED_STAGE_MARKERS_CURSOR = [
|
|
|
47
47
|
'Hard Gate',
|
|
48
48
|
];
|
|
49
49
|
|
|
50
|
-
/* MCP fallback markers — must be present on every cloud-harness card.
|
|
51
|
-
* Cursor Cloud only honors MCPs added via the dashboard; if the native
|
|
52
|
-
* `mcp_ghl-ai_*` surface is missing, the agent must reach ghl-ai via
|
|
53
|
-
* direct JSON-RPC over HTTP. These substrings let the slim-card validator
|
|
54
|
-
* fail loudly if a future edit accidentally drops the section. */
|
|
55
|
-
export const REQUIRED_MCP_FALLBACK_MARKERS = [
|
|
56
|
-
'MCP fallback',
|
|
57
|
-
'services.leadconnectorhq.com/agentic-workspace/mcp',
|
|
58
|
-
'GITHUB_PAT',
|
|
59
|
-
'Bearer',
|
|
60
|
-
'tools/list',
|
|
61
|
-
'tools/call',
|
|
62
|
-
'text/event-stream',
|
|
63
|
-
];
|
|
64
|
-
|
|
65
|
-
/* ─────────────────────────────────────────────────────────────────────────
|
|
66
|
-
* MCP fallback sections — appended to both slim cards. Cursor variant adds
|
|
67
|
-
* the dashboard-upgrade hint (cursor.com/agents); Claude variant omits it
|
|
68
|
-
* (Claude Code Web reads ~/.claude/settings.json::mcpServers natively).
|
|
69
|
-
* ───────────────────────────────────────────────────────────────────────── */
|
|
70
|
-
|
|
71
|
-
const MCP_FALLBACK_CURSOR = `
|
|
72
|
-
## MCP fallback — cloud harness only (use ONLY if native MCP is missing)
|
|
73
|
-
|
|
74
|
-
\`aw c4\` registers \`ghl-ai\` in \`~/.cursor/mcp.json\`, but Cursor Cloud
|
|
75
|
-
agents only honor MCPs added via the dashboard
|
|
76
|
-
(\`cursor.com/dashboard?tab=integrations\` for Team plans, or the MCP
|
|
77
|
-
dropdown at \`cursor.com/agents\` for personal). When \`mcp_ghl-ai_*\`
|
|
78
|
-
tools are missing from your tool surface, fall back to direct HTTP
|
|
79
|
-
JSON-RPC.
|
|
80
|
-
|
|
81
|
-
- Endpoint: \`https://services.leadconnectorhq.com/agentic-workspace/mcp\`
|
|
82
|
-
- Headers: \`Authorization: Bearer $GITHUB_PAT\`,
|
|
83
|
-
\`Content-Type: application/json\`,
|
|
84
|
-
\`Accept: application/json, text/event-stream\`
|
|
85
|
-
- Protocol: JSON-RPC 2.0 — call \`tools/list\` to discover, then
|
|
86
|
-
\`tools/call\` with \`{ name, arguments }\`. SSE responses arrive as
|
|
87
|
-
\`data: <json>\` lines; parse the first JSON payload.
|
|
88
|
-
|
|
89
|
-
Example (list GKE clusters):
|
|
90
|
-
|
|
91
|
-
\`\`\`bash
|
|
92
|
-
curl -sS -X POST \\
|
|
93
|
-
https://services.leadconnectorhq.com/agentic-workspace/mcp \\
|
|
94
|
-
-H "Authorization: Bearer $GITHUB_PAT" \\
|
|
95
|
-
-H "Content-Type: application/json" \\
|
|
96
|
-
-H "Accept: application/json, text/event-stream" \\
|
|
97
|
-
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
|
|
98
|
-
"params":{"name":"gcp_kube-list-clusters",
|
|
99
|
-
"arguments":{"location":"-"}}}'
|
|
100
|
-
\`\`\`
|
|
101
|
-
|
|
102
|
-
Security: NEVER echo, log, or print \`$GITHUB_PAT\` — it is sensitive.
|
|
103
|
-
Use this fallback ONLY when the native MCP tools are unavailable.
|
|
104
|
-
`;
|
|
105
|
-
|
|
106
|
-
const MCP_FALLBACK_CLAUDE = `
|
|
107
|
-
## MCP fallback (use ONLY if native MCP is missing)
|
|
108
|
-
|
|
109
|
-
\`aw c4\` registers \`ghl-ai\` in \`~/.claude/settings.json::mcpServers\`.
|
|
110
|
-
If the \`mcp_ghl-ai_*\` tool surface is unavailable in this runtime,
|
|
111
|
-
fall back to direct HTTP JSON-RPC.
|
|
112
|
-
|
|
113
|
-
- Endpoint: \`https://services.leadconnectorhq.com/agentic-workspace/mcp\`
|
|
114
|
-
- Headers: \`Authorization: Bearer $GITHUB_PAT\`,
|
|
115
|
-
\`Content-Type: application/json\`,
|
|
116
|
-
\`Accept: application/json, text/event-stream\`
|
|
117
|
-
- Protocol: JSON-RPC 2.0 — call \`tools/list\` to discover, then
|
|
118
|
-
\`tools/call\` with \`{ name, arguments }\`. SSE responses arrive as
|
|
119
|
-
\`data: <json>\` lines; parse the first JSON payload.
|
|
120
|
-
|
|
121
|
-
Example (list GKE clusters):
|
|
122
|
-
|
|
123
|
-
\`\`\`bash
|
|
124
|
-
curl -sS -X POST \\
|
|
125
|
-
https://services.leadconnectorhq.com/agentic-workspace/mcp \\
|
|
126
|
-
-H "Authorization: Bearer $GITHUB_PAT" \\
|
|
127
|
-
-H "Content-Type: application/json" \\
|
|
128
|
-
-H "Accept: application/json, text/event-stream" \\
|
|
129
|
-
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
|
|
130
|
-
"params":{"name":"gcp_kube-list-clusters",
|
|
131
|
-
"arguments":{"location":"-"}}}'
|
|
132
|
-
\`\`\`
|
|
133
|
-
|
|
134
|
-
Security: NEVER echo, log, or print \`$GITHUB_PAT\` — it is sensitive.
|
|
135
|
-
Use this fallback ONLY when the native MCP tools are unavailable.
|
|
136
|
-
`;
|
|
137
|
-
|
|
138
50
|
/* ─────────────────────────────────────────────────────────────────────────
|
|
139
51
|
* Card text — copied verbatim from spec.md::§"Slim card content".
|
|
140
52
|
* Trailing newline is intentional: Claude/Cursor parse the file as a single
|
|
@@ -206,7 +118,7 @@ Platform rules live under \`.aw/.aw_rules/platform/\` — search in this order:
|
|
|
206
118
|
\`~/.aw/.aw_registry/.aw_rules/platform/\`. Read \`universal/AGENTS.md\` and
|
|
207
119
|
\`security/AGENTS.md\` first, then the touched-domain \`AGENTS.md\` plus
|
|
208
120
|
\`references/*.md\` on demand.
|
|
209
|
-
|
|
121
|
+
`;
|
|
210
122
|
|
|
211
123
|
export const SLIM_CARD_CURSOR = `# AW Router (Compact) — using-aw-skills
|
|
212
124
|
|
|
@@ -273,7 +185,7 @@ Platform rules live under \`.aw/.aw_rules/platform/\` — search in this order:
|
|
|
273
185
|
\`~/.aw/.aw_registry/.aw_rules/platform/\`. Read \`universal/AGENTS.md\` and
|
|
274
186
|
\`security/AGENTS.md\` first, then the touched-domain \`AGENTS.md\` plus
|
|
275
187
|
\`references/*.md\` on demand.
|
|
276
|
-
|
|
188
|
+
`;
|
|
277
189
|
|
|
278
190
|
/* ─────────────────────────────────────────────────────────────────────────
|
|
279
191
|
* Hook scripts — embedded as bash one-liners that emit fixed JSON envelopes.
|
|
@@ -364,11 +276,6 @@ export function buildSlimRouterCard(harness) {
|
|
|
364
276
|
throw new Error(`Slim card for ${harness} missing stage marker: "${marker}"`);
|
|
365
277
|
}
|
|
366
278
|
}
|
|
367
|
-
for (const marker of REQUIRED_MCP_FALLBACK_MARKERS) {
|
|
368
|
-
if (!card.includes(marker)) {
|
|
369
|
-
throw new Error(`Slim card for ${harness} missing MCP fallback marker: "${marker}"`);
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
279
|
|
|
373
280
|
return { card, bytes };
|
|
374
281
|
}
|
|
@@ -497,6 +404,14 @@ function installCursorSlim({ home, escaped }) {
|
|
|
497
404
|
// Same rationale as installClaudeSlim — escape mode skips the card write.
|
|
498
405
|
ensureDir(dirname(hooksJsonPath));
|
|
499
406
|
|
|
407
|
+
// Cursor's hooks.json schema requires `"version": 1` at the top level
|
|
408
|
+
// (cursor.com/docs/hooks). Without it, the runtime silently fails open
|
|
409
|
+
// and never invokes our hooks — which is exactly the bug that prevented
|
|
410
|
+
// the slim card from reaching cursor-cloud agents in 0.1.44-beta.3.
|
|
411
|
+
// We pin this on every merge call so the file is always schema-valid,
|
|
412
|
+
// even if a stale or partial file already exists on disk.
|
|
413
|
+
const cursorHooksTopLevel = { version: 1 };
|
|
414
|
+
|
|
500
415
|
// (G1) The Node-adapter wrapper that satisfies Cursor's request-rewrite
|
|
501
416
|
// JSON contract. NEVER delegate to shared/user-prompt-submit.sh directly.
|
|
502
417
|
const promptHookCommand =
|
|
@@ -524,6 +439,7 @@ function installCursorSlim({ home, escaped }) {
|
|
|
524
439
|
'aw-slim-session-start.sh',
|
|
525
440
|
'.cursor/hooks/session-start.sh',
|
|
526
441
|
],
|
|
442
|
+
ensureTopLevel: cursorHooksTopLevel,
|
|
527
443
|
});
|
|
528
444
|
} else {
|
|
529
445
|
const fullEcc =
|
|
@@ -541,6 +457,7 @@ function installCursorSlim({ home, escaped }) {
|
|
|
541
457
|
'aw-slim-session-start.sh',
|
|
542
458
|
'.cursor/hooks/session-start.sh',
|
|
543
459
|
],
|
|
460
|
+
ensureTopLevel: cursorHooksTopLevel,
|
|
544
461
|
});
|
|
545
462
|
}
|
|
546
463
|
|
|
@@ -553,6 +470,7 @@ function installCursorSlim({ home, escaped }) {
|
|
|
553
470
|
description: 'AW per-prompt rules reminder (ECC Node-adapter)',
|
|
554
471
|
},
|
|
555
472
|
commandPatterns: ['before-submit-prompt.sh'],
|
|
473
|
+
ensureTopLevel: cursorHooksTopLevel,
|
|
556
474
|
});
|
|
557
475
|
|
|
558
476
|
return {
|