@ghl-ai/aw 0.1.44-beta.2 → 0.1.44-beta.4

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 CHANGED
@@ -35,6 +35,7 @@ export {
35
35
  REQUIRED_ENFORCEMENT_PHRASES,
36
36
  REQUIRED_STAGE_MARKERS_CLAUDE,
37
37
  REQUIRED_STAGE_MARKERS_CURSOR,
38
+ REQUIRED_MCP_FALLBACK_MARKERS,
38
39
  SLIM_CARD_CLAUDE,
39
40
  SLIM_CARD_CURSOR,
40
41
  buildSlimRouterCard,
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({ filePath, jsonPointer, newEntry, commandPatterns }) {
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,6 +47,94 @@ 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
+
50
138
  /* ─────────────────────────────────────────────────────────────────────────
51
139
  * Card text — copied verbatim from spec.md::§"Slim card content".
52
140
  * Trailing newline is intentional: Claude/Cursor parse the file as a single
@@ -118,7 +206,7 @@ Platform rules live under \`.aw/.aw_rules/platform/\` — search in this order:
118
206
  \`~/.aw/.aw_registry/.aw_rules/platform/\`. Read \`universal/AGENTS.md\` and
119
207
  \`security/AGENTS.md\` first, then the touched-domain \`AGENTS.md\` plus
120
208
  \`references/*.md\` on demand.
121
- `;
209
+ ${MCP_FALLBACK_CLAUDE}`;
122
210
 
123
211
  export const SLIM_CARD_CURSOR = `# AW Router (Compact) — using-aw-skills
124
212
 
@@ -185,7 +273,7 @@ Platform rules live under \`.aw/.aw_rules/platform/\` — search in this order:
185
273
  \`~/.aw/.aw_registry/.aw_rules/platform/\`. Read \`universal/AGENTS.md\` and
186
274
  \`security/AGENTS.md\` first, then the touched-domain \`AGENTS.md\` plus
187
275
  \`references/*.md\` on demand.
188
- `;
276
+ ${MCP_FALLBACK_CURSOR}`;
189
277
 
190
278
  /* ─────────────────────────────────────────────────────────────────────────
191
279
  * Hook scripts — embedded as bash one-liners that emit fixed JSON envelopes.
@@ -276,6 +364,11 @@ export function buildSlimRouterCard(harness) {
276
364
  throw new Error(`Slim card for ${harness} missing stage marker: "${marker}"`);
277
365
  }
278
366
  }
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
+ }
279
372
 
280
373
  return { card, bytes };
281
374
  }
@@ -404,6 +497,14 @@ function installCursorSlim({ home, escaped }) {
404
497
  // Same rationale as installClaudeSlim — escape mode skips the card write.
405
498
  ensureDir(dirname(hooksJsonPath));
406
499
 
500
+ // Cursor's hooks.json schema requires `"version": 1` at the top level
501
+ // (cursor.com/docs/hooks). Without it, the runtime silently fails open
502
+ // and never invokes our hooks — which is exactly the bug that prevented
503
+ // the slim card from reaching cursor-cloud agents in 0.1.44-beta.3.
504
+ // We pin this on every merge call so the file is always schema-valid,
505
+ // even if a stale or partial file already exists on disk.
506
+ const cursorHooksTopLevel = { version: 1 };
507
+
407
508
  // (G1) The Node-adapter wrapper that satisfies Cursor's request-rewrite
408
509
  // JSON contract. NEVER delegate to shared/user-prompt-submit.sh directly.
409
510
  const promptHookCommand =
@@ -431,6 +532,7 @@ function installCursorSlim({ home, escaped }) {
431
532
  'aw-slim-session-start.sh',
432
533
  '.cursor/hooks/session-start.sh',
433
534
  ],
535
+ ensureTopLevel: cursorHooksTopLevel,
434
536
  });
435
537
  } else {
436
538
  const fullEcc =
@@ -448,6 +550,7 @@ function installCursorSlim({ home, escaped }) {
448
550
  'aw-slim-session-start.sh',
449
551
  '.cursor/hooks/session-start.sh',
450
552
  ],
553
+ ensureTopLevel: cursorHooksTopLevel,
451
554
  });
452
555
  }
453
556
 
@@ -460,6 +563,7 @@ function installCursorSlim({ home, escaped }) {
460
563
  description: 'AW per-prompt rules reminder (ECC Node-adapter)',
461
564
  },
462
565
  commandPatterns: ['before-submit-prompt.sh'],
566
+ ensureTopLevel: cursorHooksTopLevel,
463
567
  });
464
568
 
465
569
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ghl-ai/aw",
3
- "version": "0.1.44-beta.2",
3
+ "version": "0.1.44-beta.4",
4
4
  "description": "Agentic Workspace CLI — pull, push & manage agents, skills and commands from the registry",
5
5
  "type": "module",
6
6
  "bin": {