@agent-native/core 0.49.12 → 0.49.14

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.
Files changed (73) hide show
  1. package/dist/cli/pr-visual-recap-workflow.d.ts +1 -1
  2. package/dist/cli/pr-visual-recap-workflow.d.ts.map +1 -1
  3. package/dist/cli/pr-visual-recap-workflow.js +1 -1
  4. package/dist/cli/pr-visual-recap-workflow.js.map +1 -1
  5. package/dist/cli/recap.d.ts +37 -0
  6. package/dist/cli/recap.d.ts.map +1 -1
  7. package/dist/cli/recap.js +240 -0
  8. package/dist/cli/recap.js.map +1 -1
  9. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  10. package/dist/client/MultiTabAssistantChat.js +5 -10
  11. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  12. package/dist/client/blocks/library/question-form.js +1 -1
  13. package/dist/client/blocks/library/question-form.js.map +1 -1
  14. package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -1
  15. package/dist/client/extensions/EmbeddedExtension.js +4 -0
  16. package/dist/client/extensions/EmbeddedExtension.js.map +1 -1
  17. package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
  18. package/dist/client/extensions/ExtensionViewer.js +12 -4
  19. package/dist/client/extensions/ExtensionViewer.js.map +1 -1
  20. package/dist/client/extensions/ExtensionsListPage.d.ts.map +1 -1
  21. package/dist/client/extensions/ExtensionsListPage.js +14 -9
  22. package/dist/client/extensions/ExtensionsListPage.js.map +1 -1
  23. package/dist/client/extensions/ExtensionsSidebarSection.d.ts.map +1 -1
  24. package/dist/client/extensions/ExtensionsSidebarSection.js +6 -4
  25. package/dist/client/extensions/ExtensionsSidebarSection.js.map +1 -1
  26. package/dist/client/extensions/iframe-bridge.d.ts +8 -0
  27. package/dist/client/extensions/iframe-bridge.d.ts.map +1 -1
  28. package/dist/client/extensions/iframe-bridge.js +54 -0
  29. package/dist/client/extensions/iframe-bridge.js.map +1 -1
  30. package/dist/client/progress/RunsTray.d.ts.map +1 -1
  31. package/dist/client/progress/RunsTray.js +12 -3
  32. package/dist/client/progress/RunsTray.js.map +1 -1
  33. package/dist/client/resources/ResourceEditor.d.ts +1 -3
  34. package/dist/client/resources/ResourceEditor.d.ts.map +1 -1
  35. package/dist/client/resources/ResourceEditor.js +8 -23
  36. package/dist/client/resources/ResourceEditor.js.map +1 -1
  37. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
  38. package/dist/client/resources/ResourcesPanel.js +4 -9
  39. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  40. package/dist/client/settings/VoiceTranscriptionSection.d.ts.map +1 -1
  41. package/dist/client/settings/VoiceTranscriptionSection.js +1 -1
  42. package/dist/client/settings/VoiceTranscriptionSection.js.map +1 -1
  43. package/dist/client/sharing/ShareButton.d.ts +5 -1
  44. package/dist/client/sharing/ShareButton.d.ts.map +1 -1
  45. package/dist/client/sharing/ShareButton.js +15 -7
  46. package/dist/client/sharing/ShareButton.js.map +1 -1
  47. package/dist/client/sharing/ShareDialog.d.ts.map +1 -1
  48. package/dist/client/sharing/ShareDialog.js +6 -2
  49. package/dist/client/sharing/ShareDialog.js.map +1 -1
  50. package/dist/extensions/actions.d.ts.map +1 -1
  51. package/dist/extensions/actions.js +70 -2
  52. package/dist/extensions/actions.js.map +1 -1
  53. package/dist/extensions/html-shell.d.ts +12 -0
  54. package/dist/extensions/html-shell.d.ts.map +1 -1
  55. package/dist/extensions/html-shell.js.map +1 -1
  56. package/dist/extensions/local.d.ts +35 -0
  57. package/dist/extensions/local.d.ts.map +1 -0
  58. package/dist/extensions/local.js +334 -0
  59. package/dist/extensions/local.js.map +1 -0
  60. package/dist/extensions/routes.d.ts.map +1 -1
  61. package/dist/extensions/routes.js +92 -12
  62. package/dist/extensions/routes.js.map +1 -1
  63. package/dist/extensions/slots/store.d.ts.map +1 -1
  64. package/dist/extensions/slots/store.js +72 -4
  65. package/dist/extensions/slots/store.js.map +1 -1
  66. package/dist/local-artifacts/index.d.ts +4 -0
  67. package/dist/local-artifacts/index.d.ts.map +1 -1
  68. package/dist/local-artifacts/index.js +60 -35
  69. package/dist/local-artifacts/index.js.map +1 -1
  70. package/docs/content/extensions.md +65 -0
  71. package/docs/content/local-file-mode.md +171 -0
  72. package/docs/content/template-content.md +60 -4
  73. package/package.json +1 -1
package/dist/cli/recap.js CHANGED
@@ -16,6 +16,8 @@
16
16
  * huge/tiny flags.
17
17
  * mcp-config Write the plan MCP client config for the chosen backend
18
18
  * (Claude Code JSON or Codex config.toml).
19
+ * mcp-smoke Verify the configured Plan MCP endpoint exposes the publish
20
+ * tools before spending runner time on Claude/Codex.
19
21
  * scan Refuse to hand a secret-leaking diff to the agent.
20
22
  * build-prompt Assemble the agent prompt = latest visual-recap skill bundle
21
23
  * + a task wrapper (or repo-pinned skill with --skill-source).
@@ -193,6 +195,11 @@ export function writePrVisualRecapReusableCallerWorkflow(baseDir, options = {})
193
195
  }
194
196
  const DEFAULT_RECAP_APP_URL = "https://plan.agent-native.com";
195
197
  const RECAP_MCP_CLIENT_HEADER = "agent-native-pr-visual-recap";
198
+ export const RECAP_MCP_REQUIRED_TOOLS = [
199
+ "get-plan-blocks",
200
+ "create-visual-recap",
201
+ "set-resource-visibility",
202
+ ];
196
203
  export function normalizeRecapAgent(value) {
197
204
  const agent = (value || "claude").toLowerCase();
198
205
  if (agent === "codex")
@@ -1113,6 +1120,230 @@ export function buildRecapCodexMcpConfig(appUrl) {
1113
1120
  'bearer_token_env_var = "PLAN_RECAP_TOKEN"\n' +
1114
1121
  'http_headers = { "X-Agent-Native-MCP-Client" = "agent-native-pr-visual-recap", "X-Agent-Native-MCP-Full-Catalog" = "1" }\n');
1115
1122
  }
1123
+ function recapMcpUrl(appUrl) {
1124
+ return appUrl.replace(/\/$/, "") + "/_agent-native/mcp";
1125
+ }
1126
+ function recapMcpSmokeHeaders(token) {
1127
+ return {
1128
+ authorization: `Bearer ${token}`,
1129
+ accept: "application/json, text/event-stream",
1130
+ "content-type": "application/json",
1131
+ "mcp-protocol-version": "2025-06-18",
1132
+ "x-agent-native-mcp-client": RECAP_MCP_CLIENT_HEADER,
1133
+ "x-agent-native-mcp-full-catalog": "1",
1134
+ };
1135
+ }
1136
+ function parseSseJsonPayload(raw) {
1137
+ const dataLines = raw
1138
+ .split(/\r?\n/)
1139
+ .map((line) => line.trim())
1140
+ .filter((line) => line.startsWith("data:"))
1141
+ .map((line) => line.slice("data:".length).trim())
1142
+ .filter((line) => line && line !== "[DONE]");
1143
+ for (let i = dataLines.length - 1; i >= 0; i -= 1) {
1144
+ try {
1145
+ return JSON.parse(dataLines[i]);
1146
+ }
1147
+ catch {
1148
+ // Keep looking for a parseable event payload.
1149
+ }
1150
+ }
1151
+ return null;
1152
+ }
1153
+ function parseMcpJsonPayload(raw) {
1154
+ const trimmed = raw.trim();
1155
+ if (!trimmed)
1156
+ return null;
1157
+ try {
1158
+ return JSON.parse(trimmed);
1159
+ }
1160
+ catch {
1161
+ return parseSseJsonPayload(trimmed);
1162
+ }
1163
+ }
1164
+ function mcpRpcErrorMessage(payload) {
1165
+ if (!payload || typeof payload !== "object")
1166
+ return null;
1167
+ const error = payload.error;
1168
+ if (!error || typeof error !== "object")
1169
+ return null;
1170
+ const message = error.message;
1171
+ return typeof message === "string" && message.trim()
1172
+ ? message.trim()
1173
+ : JSON.stringify(error);
1174
+ }
1175
+ async function postRecapMcpRpc(input) {
1176
+ const response = await input.fetchFn(input.mcpUrl, {
1177
+ method: "POST",
1178
+ headers: recapMcpSmokeHeaders(input.token),
1179
+ body: JSON.stringify({
1180
+ jsonrpc: "2.0",
1181
+ id: input.id,
1182
+ method: input.method,
1183
+ params: input.params ?? {},
1184
+ }),
1185
+ });
1186
+ const raw = await response.text().catch((err) => String(err));
1187
+ if (!response.ok) {
1188
+ const detail = sanitizeAgentFailureSummary(raw, 300);
1189
+ return {
1190
+ ok: false,
1191
+ status: response.status,
1192
+ raw,
1193
+ reason: `Plan MCP ${input.method} returned HTTP ${response.status}${detail ? `: ${detail}` : ""}`,
1194
+ };
1195
+ }
1196
+ const payload = parseMcpJsonPayload(raw);
1197
+ if (!payload) {
1198
+ return {
1199
+ ok: false,
1200
+ raw,
1201
+ reason: `Plan MCP ${input.method} returned an unreadable response`,
1202
+ };
1203
+ }
1204
+ const rpcError = mcpRpcErrorMessage(payload);
1205
+ if (rpcError) {
1206
+ return {
1207
+ ok: false,
1208
+ raw,
1209
+ reason: `Plan MCP ${input.method} failed: ${sanitizeAgentFailureSummary(rpcError, 300)}`,
1210
+ };
1211
+ }
1212
+ return { ok: true, payload };
1213
+ }
1214
+ function extractMcpToolNames(payload) {
1215
+ const result = payload && typeof payload === "object"
1216
+ ? payload.result
1217
+ : undefined;
1218
+ const tools = result && typeof result === "object"
1219
+ ? result.tools
1220
+ : undefined;
1221
+ if (!Array.isArray(tools))
1222
+ return [];
1223
+ return tools
1224
+ .map((tool) => tool && typeof tool === "object"
1225
+ ? tool.name
1226
+ : undefined)
1227
+ .filter((name) => typeof name === "string" && !!name)
1228
+ .sort();
1229
+ }
1230
+ function recapMcpSmokeFailure(input) {
1231
+ const tools = input.tools ?? [];
1232
+ const reason = sanitizeAgentFailureSummary(input.reason, 500);
1233
+ return {
1234
+ ok: false,
1235
+ appUrl: input.appUrl,
1236
+ mcpUrl: input.mcpUrl,
1237
+ toolCount: tools.length,
1238
+ tools,
1239
+ requiredTools: [...input.requiredTools],
1240
+ reason,
1241
+ summary: `Plan MCP smoke check failed: ${reason}`,
1242
+ };
1243
+ }
1244
+ /**
1245
+ * Non-mutating live contract check for PR Visual Recap publishing.
1246
+ *
1247
+ * The previous workflow discovered a broken Plan MCP catalog only after the
1248
+ * agent tried to publish and failed to create `recap-url.txt`. This probes the
1249
+ * same authenticated MCP endpoint first and requires the three tools that the
1250
+ * visual-recap skill needs to publish a hosted recap.
1251
+ */
1252
+ export async function smokeRecapMcpTools(input) {
1253
+ const appUrl = input.appUrl ?? DEFAULT_RECAP_APP_URL;
1254
+ const mcpUrl = recapMcpUrl(appUrl);
1255
+ const requiredTools = input.requiredTools ?? RECAP_MCP_REQUIRED_TOOLS;
1256
+ const token = input.token?.trim();
1257
+ if (!token) {
1258
+ return recapMcpSmokeFailure({
1259
+ appUrl,
1260
+ mcpUrl,
1261
+ requiredTools,
1262
+ reason: "PLAN_RECAP_TOKEN is empty",
1263
+ });
1264
+ }
1265
+ const fetchFn = input.fetchFn ?? fetch;
1266
+ try {
1267
+ const init = await postRecapMcpRpc({
1268
+ fetchFn,
1269
+ mcpUrl,
1270
+ token,
1271
+ method: "initialize",
1272
+ id: 1,
1273
+ params: {
1274
+ protocolVersion: "2025-06-18",
1275
+ capabilities: {},
1276
+ clientInfo: {
1277
+ name: RECAP_MCP_CLIENT_HEADER,
1278
+ version: "1.0.0",
1279
+ },
1280
+ },
1281
+ });
1282
+ if (!init.ok) {
1283
+ return recapMcpSmokeFailure({
1284
+ appUrl,
1285
+ mcpUrl,
1286
+ requiredTools,
1287
+ reason: init.reason,
1288
+ });
1289
+ }
1290
+ const listed = await postRecapMcpRpc({
1291
+ fetchFn,
1292
+ mcpUrl,
1293
+ token,
1294
+ method: "tools/list",
1295
+ id: 2,
1296
+ });
1297
+ if (!listed.ok) {
1298
+ return recapMcpSmokeFailure({
1299
+ appUrl,
1300
+ mcpUrl,
1301
+ requiredTools,
1302
+ reason: listed.reason,
1303
+ });
1304
+ }
1305
+ const tools = extractMcpToolNames(listed.payload);
1306
+ const missing = requiredTools.filter((name) => !tools.includes(name));
1307
+ if (missing.length > 0) {
1308
+ return recapMcpSmokeFailure({
1309
+ appUrl,
1310
+ mcpUrl,
1311
+ tools,
1312
+ requiredTools,
1313
+ reason: `Plan MCP tools/list returned ${tools.length} tools but is missing required publishing tools: ${missing.join(", ")}`,
1314
+ });
1315
+ }
1316
+ return {
1317
+ ok: true,
1318
+ appUrl,
1319
+ mcpUrl,
1320
+ toolCount: tools.length,
1321
+ tools,
1322
+ requiredTools: [...requiredTools],
1323
+ summary: `Plan MCP smoke check passed: tools/list exposes ${requiredTools.join(", ")}.`,
1324
+ };
1325
+ }
1326
+ catch (err) {
1327
+ return recapMcpSmokeFailure({
1328
+ appUrl,
1329
+ mcpUrl,
1330
+ requiredTools,
1331
+ reason: `Plan MCP smoke check could not reach ${mcpUrl}: ${String(err)}`,
1332
+ });
1333
+ }
1334
+ }
1335
+ async function runMcpSmoke(args) {
1336
+ const appUrl = optionalArg(args, "app-url") ??
1337
+ process.env.PLAN_RECAP_APP_URL ??
1338
+ DEFAULT_RECAP_APP_URL;
1339
+ const token = optionalArg(args, "token") ?? process.env.PLAN_RECAP_TOKEN;
1340
+ const result = await smokeRecapMcpTools({ appUrl, token });
1341
+ writeGitHubOutput("ok", result.ok ? "true" : "false");
1342
+ writeGitHubOutput("summary", result.summary);
1343
+ process.stdout.write(`${JSON.stringify(result)}\n`);
1344
+ if (!result.ok)
1345
+ process.exitCode = 1;
1346
+ }
1116
1347
  /**
1117
1348
  * `recap mcp-config` — write the plan MCP client config for the chosen backend,
1118
1349
  * replacing the two `node -e '...'` one-liners that previously lived inline in
@@ -2754,6 +2985,7 @@ Usage:
2754
2985
  npx @agent-native/core@latest recap doctor [--repo owner/name] [--agent claude|codex] [--app-url <url>]
2755
2986
  npx @agent-native/core@latest recap collect-diff --base <baseSha> --head <headSha> [--out recap.diff] [--stat recap.stat]
2756
2987
  npx @agent-native/core@latest recap mcp-config --agent claude|codex --app-url <url> [--out <path>]
2988
+ npx @agent-native/core@latest recap mcp-smoke [--app-url <url>] [--token <planToken>]
2757
2989
  npx @agent-native/core@latest recap scan --diff <path>
2758
2990
  npx @agent-native/core@latest recap build-prompt --pr <n> [--repo owner/name] [--head <sha>] [--app-url <url>] [--diff <path>] [--stat <path>] [--prev-plan-id <id>] [--huge] [--local-files] [--local-dir <folder>] [--skill-source auto|latest|repo] [--out <path>]
2759
2991
  npx @agent-native/core@latest recap shot --url <planUrl> [--token <planToken>] [--app-url <url>] [--out recap.png] [--theme light|dark]
@@ -2787,6 +3019,11 @@ Usage:
2787
3019
  Read the captured Claude/Codex result file and write a sanitized one-line
2788
3020
  summary to stdout and $GITHUB_OUTPUT (summary). Used only when no plan URL
2789
3021
  was produced, so PR comments/checks explain the actual failure.
3022
+ npx @agent-native/core@latest recap mcp-smoke
3023
+ Non-mutating Plan MCP JSON-RPC smoke test. Calls initialize + tools/list
3024
+ against PLAN_RECAP_APP_URL / PLAN_RECAP_TOKEN and requires get-plan-blocks,
3025
+ create-visual-recap, and set-resource-visibility to be exposed. Writes
3026
+ ok=<true|false> and summary=<diagnostic> to $GITHUB_OUTPUT.
2790
3027
  npx @agent-native/core@latest recap setup
2791
3028
  Write/refresh .github/workflows/pr-visual-recap.yml, then configure GitHub
2792
3029
  Actions secrets and variables with gh when values are available from env or
@@ -2812,6 +3049,9 @@ export async function runRecap(argv) {
2812
3049
  case "mcp-config":
2813
3050
  runMcpConfig(args);
2814
3051
  return;
3052
+ case "mcp-smoke":
3053
+ await runMcpSmoke(args);
3054
+ return;
2815
3055
  case "scan":
2816
3056
  runScan(args);
2817
3057
  return;