@agent-native/core 0.49.9 → 0.49.11
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/dist/cli/pr-visual-recap-workflow.d.ts +1 -1
- package/dist/cli/pr-visual-recap-workflow.d.ts.map +1 -1
- package/dist/cli/pr-visual-recap-workflow.js +1 -1
- package/dist/cli/pr-visual-recap-workflow.js.map +1 -1
- package/dist/cli/recap.d.ts +4 -1
- package/dist/cli/recap.d.ts.map +1 -1
- package/dist/cli/recap.js +97 -23
- package/dist/cli/recap.js.map +1 -1
- package/dist/cli/skills.d.ts +5 -5
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +219 -24
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/blocks/library/annotation-rail.d.ts.map +1 -1
- package/dist/client/blocks/library/annotation-rail.js +16 -6
- package/dist/client/blocks/library/annotation-rail.js.map +1 -1
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +10 -2
- package/dist/deploy/build.js.map +1 -1
- package/dist/extensions/actions.js +1 -1
- package/dist/extensions/actions.js.map +1 -1
- package/dist/local-artifacts/index.d.ts +101 -0
- package/dist/local-artifacts/index.d.ts.map +1 -0
- package/dist/local-artifacts/index.js +507 -0
- package/dist/local-artifacts/index.js.map +1 -0
- package/dist/secrets/substitution.js +2 -2
- package/dist/secrets/substitution.js.map +1 -1
- package/dist/server/auth-marketing.d.ts +1 -0
- package/dist/server/auth-marketing.d.ts.map +1 -1
- package/dist/server/auth-marketing.js +5 -0
- package/dist/server/auth-marketing.js.map +1 -1
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +59 -37
- package/dist/server/auth.js.map +1 -1
- package/dist/server/entry-server.d.ts +27 -4
- package/dist/server/entry-server.d.ts.map +1 -1
- package/dist/server/entry-server.js +63 -43
- package/dist/server/entry-server.js.map +1 -1
- package/dist/server/onboarding-html.d.ts.map +1 -1
- package/dist/server/onboarding-html.js +3 -3
- package/dist/server/onboarding-html.js.map +1 -1
- package/dist/server/social-og-image.d.ts +2 -0
- package/dist/server/social-og-image.d.ts.map +1 -1
- package/dist/server/social-og-image.js +20 -7
- package/dist/server/social-og-image.js.map +1 -1
- package/dist/server/ssr-handler.d.ts.map +1 -1
- package/dist/server/ssr-handler.js +2 -2
- package/dist/server/ssr-handler.js.map +1 -1
- package/dist/shared/index.d.ts +1 -1
- package/dist/shared/index.d.ts.map +1 -1
- package/dist/shared/index.js +1 -1
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/social-meta.d.ts +2 -0
- package/dist/shared/social-meta.d.ts.map +1 -1
- package/dist/shared/social-meta.js +5 -0
- package/dist/shared/social-meta.js.map +1 -1
- package/dist/templates/default/.agents/skills/storing-data/SKILL.md +3 -1
- package/dist/templates/default/app/entry.server.tsx +8 -2
- package/dist/templates/starter-shell-sync.spec.ts +4 -3
- package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +3 -2
- package/dist/templates/workspace-core/.agents/skills/storing-data/SKILL.md +3 -1
- package/docs/content/pr-visual-recap.md +4 -4
- package/docs/content/template-content.md +9 -0
- package/package.json +6 -1
- package/src/templates/default/.agents/skills/storing-data/SKILL.md +3 -1
- package/src/templates/default/app/entry.server.tsx +8 -2
- package/src/templates/starter-shell-sync.spec.ts +4 -3
- package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +3 -2
- package/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +3 -1
package/dist/cli/recap.js
CHANGED
|
@@ -192,6 +192,7 @@ export function writePrVisualRecapReusableCallerWorkflow(baseDir, options = {})
|
|
|
192
192
|
return { status: "written", path: rel, existed: false };
|
|
193
193
|
}
|
|
194
194
|
const DEFAULT_RECAP_APP_URL = "https://plan.agent-native.com";
|
|
195
|
+
const RECAP_MCP_CLIENT_HEADER = "agent-native-pr-visual-recap";
|
|
195
196
|
export function normalizeRecapAgent(value) {
|
|
196
197
|
const agent = (value || "claude").toLowerCase();
|
|
197
198
|
if (agent === "codex")
|
|
@@ -1088,7 +1089,11 @@ export function buildRecapClaudeMcpConfig(appUrl, token) {
|
|
|
1088
1089
|
plan: {
|
|
1089
1090
|
type: "http",
|
|
1090
1091
|
url,
|
|
1091
|
-
headers: {
|
|
1092
|
+
headers: {
|
|
1093
|
+
Authorization: "Bearer " + token,
|
|
1094
|
+
"X-Agent-Native-MCP-Client": RECAP_MCP_CLIENT_HEADER,
|
|
1095
|
+
"X-Agent-Native-MCP-Full-Catalog": "1",
|
|
1096
|
+
},
|
|
1092
1097
|
},
|
|
1093
1098
|
},
|
|
1094
1099
|
});
|
|
@@ -1105,7 +1110,8 @@ export function buildRecapCodexMcpConfig(appUrl) {
|
|
|
1105
1110
|
"url = " +
|
|
1106
1111
|
JSON.stringify(url) +
|
|
1107
1112
|
"\n" +
|
|
1108
|
-
'bearer_token_env_var = "PLAN_RECAP_TOKEN"\n'
|
|
1113
|
+
'bearer_token_env_var = "PLAN_RECAP_TOKEN"\n' +
|
|
1114
|
+
'http_headers = { "X-Agent-Native-MCP-Client" = "agent-native-pr-visual-recap", "X-Agent-Native-MCP-Full-Catalog" = "1" }\n');
|
|
1109
1115
|
}
|
|
1110
1116
|
/**
|
|
1111
1117
|
* `recap mcp-config` — write the plan MCP client config for the chosen backend,
|
|
@@ -1319,7 +1325,7 @@ export function buildRecapPrompt(input) {
|
|
|
1319
1325
|
else {
|
|
1320
1326
|
lines.push("## Publish (this is the only way to produce output)");
|
|
1321
1327
|
lines.push(`The \`plan\` MCP server is configured for you. Call its tools by name (your host may expose them as \`get-plan-blocks\` / \`create-visual-recap\` or \`mcp__plan__get-plan-blocks\` / \`mcp__plan__create-visual-recap\` — same tools).`);
|
|
1322
|
-
lines.push("This is a one-shot GitHub Actions run. Do not schedule wakeups, reminders, follow-ups, or retries in another turn
|
|
1328
|
+
lines.push("This is a one-shot GitHub Actions run. Do not wait, sleep, back off, schedule wakeups, reminders, follow-ups, or retries in another turn. Either publish the recap and write `recap-url.txt` in this process, or report the MCP/tool failure plainly.");
|
|
1323
1329
|
lines.push("First call `get-plan-blocks`, then call `create-visual-recap`. If `create-visual-recap` is available but `get-plan-blocks` is not, the Plan MCP is connected but the block-registry tool is not visible to this runner. Report that the runner must expose `get-plan-blocks` through the workflow/tool allowlist or compact MCP catalog; do not describe that case as a disconnected Plan MCP.");
|
|
1324
1330
|
lines.push(`1. Call the **create-visual-recap** tool on the \`plan\` MCP server with grounded MDX derived ONLY from the real diff, passing \`visibility: "org"\` so the recap is published org-scoped (never public) server-side${input.prevPlanId
|
|
1325
1331
|
? `, and also passing \`planId: "${input.prevPlanId}"\` so this REPLACES the existing recap plan`
|
|
@@ -1350,6 +1356,9 @@ export function buildRecapPrompt(input) {
|
|
|
1350
1356
|
const MARKER = "<!-- pr-visual-recap -->";
|
|
1351
1357
|
const RECAP_IMAGE_URL_PATH_PATTERN = /\/_agent-native\/recap-image\/[0-9a-f]{32,128}\.png$/;
|
|
1352
1358
|
const RECAP_SCREENSHOT_QUERY_PARAM = "recapScreenshot";
|
|
1359
|
+
const RECAP_SCREENSHOT_THEME_QUERY_PARAM = "recapScreenshotTheme";
|
|
1360
|
+
const GITHUB_LIGHT_CANVAS_BACKGROUND = "#ffffff";
|
|
1361
|
+
const GITHUB_DARK_CANVAS_BACKGROUND = "#0d1117";
|
|
1353
1362
|
function repoParts(repoFullName) {
|
|
1354
1363
|
const [owner, repo] = repoFullName.split("/");
|
|
1355
1364
|
if (!owner || !repo)
|
|
@@ -1437,6 +1446,14 @@ function originOf(url) {
|
|
|
1437
1446
|
return "";
|
|
1438
1447
|
}
|
|
1439
1448
|
}
|
|
1449
|
+
function trustedRecapImageUrl(raw, base) {
|
|
1450
|
+
const value = (raw || "").trim();
|
|
1451
|
+
return value &&
|
|
1452
|
+
sameOrigin(value, base) &&
|
|
1453
|
+
RECAP_IMAGE_URL_PATH_PATTERN.test(value)
|
|
1454
|
+
? value
|
|
1455
|
+
: "";
|
|
1456
|
+
}
|
|
1440
1457
|
/** Build the sticky comment body from the workflow's environment. */
|
|
1441
1458
|
export function buildCommentBody(env = process.env) {
|
|
1442
1459
|
const lines = [MARKER];
|
|
@@ -1513,28 +1530,29 @@ export function buildCommentBody(env = process.env) {
|
|
|
1513
1530
|
lines.push(diagnostic);
|
|
1514
1531
|
}
|
|
1515
1532
|
}
|
|
1516
|
-
// Keep a link to the last-good recap so reviewers are not left in the dark.
|
|
1517
|
-
if (prevPlanId && base) {
|
|
1518
|
-
const prevSafeUrl = `${base}/recaps/${prevPlanId}`;
|
|
1519
|
-
lines.push("", `Previous recap (from an earlier push): [Open recap](${prevSafeUrl})`);
|
|
1520
|
-
}
|
|
1521
1533
|
if (markerPlanId)
|
|
1522
1534
|
lines.push("", `<!-- plan-id: ${markerPlanId} -->`);
|
|
1523
1535
|
return lines.join("\n");
|
|
1524
1536
|
}
|
|
1525
|
-
//
|
|
1537
|
+
// Image URLs are produced by our own recap-image route, but validate each is
|
|
1526
1538
|
// same-origin and matches the canonical hex-token path before embedding it, so
|
|
1527
|
-
//
|
|
1528
|
-
const
|
|
1529
|
-
const
|
|
1530
|
-
|
|
1531
|
-
RECAP_IMAGE_URL_PATH_PATTERN.test(imageUrlRaw)
|
|
1532
|
-
? imageUrlRaw
|
|
1533
|
-
: "";
|
|
1539
|
+
// they likewise cannot inject markdown or HTML.
|
|
1540
|
+
const lightImageUrl = trustedRecapImageUrl(env.RECAP_LIGHT_IMAGE_URL || env.RECAP_IMAGE_URL, base);
|
|
1541
|
+
const darkImageUrl = trustedRecapImageUrl(env.RECAP_DARK_IMAGE_URL, base);
|
|
1542
|
+
const fallbackImageUrl = lightImageUrl || darkImageUrl;
|
|
1534
1543
|
lines.push(`### Here's a [visual recap](${safeUrl}) of what changed:`);
|
|
1535
1544
|
lines.push("");
|
|
1536
|
-
if (
|
|
1537
|
-
lines.push(
|
|
1545
|
+
if (lightImageUrl && darkImageUrl) {
|
|
1546
|
+
lines.push(`<a href="${safeUrl}">`);
|
|
1547
|
+
lines.push(`<picture>`);
|
|
1548
|
+
lines.push(` <source media="(prefers-color-scheme: dark)" srcset="${darkImageUrl}">`);
|
|
1549
|
+
lines.push(` <img alt="Visual recap" src="${lightImageUrl}">`);
|
|
1550
|
+
lines.push(`</picture>`);
|
|
1551
|
+
lines.push(`</a>`);
|
|
1552
|
+
lines.push("");
|
|
1553
|
+
}
|
|
1554
|
+
else if (fallbackImageUrl) {
|
|
1555
|
+
lines.push(`[](${safeUrl})`);
|
|
1538
1556
|
lines.push("");
|
|
1539
1557
|
}
|
|
1540
1558
|
lines.push(`**[Open the full interactive recap](${safeUrl})**`);
|
|
@@ -1711,10 +1729,25 @@ async function defaultImportPlaywright() {
|
|
|
1711
1729
|
return (await import("@playwright/test"));
|
|
1712
1730
|
}
|
|
1713
1731
|
}
|
|
1714
|
-
|
|
1732
|
+
function parseRecapScreenshotTheme(value) {
|
|
1733
|
+
if (value === undefined)
|
|
1734
|
+
return undefined;
|
|
1735
|
+
if (value === "light" || value === "dark")
|
|
1736
|
+
return value;
|
|
1737
|
+
throw new Error("--theme must be light or dark.");
|
|
1738
|
+
}
|
|
1739
|
+
function recapScreenshotBackground(theme) {
|
|
1740
|
+
return theme === "dark"
|
|
1741
|
+
? GITHUB_DARK_CANVAS_BACKGROUND
|
|
1742
|
+
: GITHUB_LIGHT_CANVAS_BACKGROUND;
|
|
1743
|
+
}
|
|
1744
|
+
export function withRecapScreenshotParams(url, options = {}) {
|
|
1715
1745
|
try {
|
|
1716
1746
|
const parsed = new URL(url);
|
|
1717
1747
|
parsed.searchParams.set(RECAP_SCREENSHOT_QUERY_PARAM, "1");
|
|
1748
|
+
if (options.theme) {
|
|
1749
|
+
parsed.searchParams.set(RECAP_SCREENSHOT_THEME_QUERY_PARAM, options.theme);
|
|
1750
|
+
}
|
|
1718
1751
|
return parsed.toString();
|
|
1719
1752
|
}
|
|
1720
1753
|
catch {
|
|
@@ -1728,6 +1761,7 @@ importPlaywright = defaultImportPlaywright) {
|
|
|
1728
1761
|
const out = optionalArg(args, "out") ?? "recap.png";
|
|
1729
1762
|
const token = optionalArg(args, "token");
|
|
1730
1763
|
const appUrl = optionalArg(args, "app-url");
|
|
1764
|
+
const theme = parseRecapScreenshotTheme(optionalArg(args, "theme"));
|
|
1731
1765
|
const done = (obj) => {
|
|
1732
1766
|
process.stdout.write(`${JSON.stringify(obj)}\n`);
|
|
1733
1767
|
};
|
|
@@ -1753,7 +1787,7 @@ importPlaywright = defaultImportPlaywright) {
|
|
|
1753
1787
|
return;
|
|
1754
1788
|
}
|
|
1755
1789
|
}
|
|
1756
|
-
const captureUrl = withRecapScreenshotParams(url);
|
|
1790
|
+
const captureUrl = withRecapScreenshotParams(url, { theme });
|
|
1757
1791
|
let chromium;
|
|
1758
1792
|
try {
|
|
1759
1793
|
({ chromium } = await importPlaywright());
|
|
@@ -1773,7 +1807,33 @@ importPlaywright = defaultImportPlaywright) {
|
|
|
1773
1807
|
const context = await browser.newContext({
|
|
1774
1808
|
viewport: RECAP_SHOT_VIEWPORT,
|
|
1775
1809
|
deviceScaleFactor: RECAP_SHOT_DEVICE_SCALE_FACTOR,
|
|
1810
|
+
...(theme ? { colorScheme: theme } : {}),
|
|
1776
1811
|
});
|
|
1812
|
+
if (theme) {
|
|
1813
|
+
await context.addInitScript(({ background, nextTheme }) => {
|
|
1814
|
+
const applyTheme = () => {
|
|
1815
|
+
try {
|
|
1816
|
+
window.localStorage.setItem("theme", nextTheme);
|
|
1817
|
+
}
|
|
1818
|
+
catch {
|
|
1819
|
+
/* ignore */
|
|
1820
|
+
}
|
|
1821
|
+
const root = document.documentElement;
|
|
1822
|
+
root.classList.remove("light", "dark");
|
|
1823
|
+
root.classList.add(nextTheme);
|
|
1824
|
+
root.setAttribute("data-theme", nextTheme);
|
|
1825
|
+
root.style.colorScheme = nextTheme;
|
|
1826
|
+
root.style.backgroundColor = background;
|
|
1827
|
+
if (document.body) {
|
|
1828
|
+
document.body.style.backgroundColor = background;
|
|
1829
|
+
}
|
|
1830
|
+
};
|
|
1831
|
+
applyTheme();
|
|
1832
|
+
document.addEventListener("DOMContentLoaded", applyTheme, {
|
|
1833
|
+
once: true,
|
|
1834
|
+
});
|
|
1835
|
+
}, { background: recapScreenshotBackground(theme), nextTheme: theme });
|
|
1836
|
+
}
|
|
1777
1837
|
if (attachToken) {
|
|
1778
1838
|
// Attach the bearer ONLY to same-origin requests. Context-wide
|
|
1779
1839
|
// extraHTTPHeaders would also send it to every cross-origin subresource
|
|
@@ -1813,9 +1873,23 @@ importPlaywright = defaultImportPlaywright) {
|
|
|
1813
1873
|
}
|
|
1814
1874
|
}
|
|
1815
1875
|
await page.waitForTimeout(matched ? 1_200 : 500);
|
|
1816
|
-
await page.evaluate(() => {
|
|
1876
|
+
await page.evaluate((background) => {
|
|
1817
1877
|
document.documentElement.style.zoom = "100%";
|
|
1818
|
-
|
|
1878
|
+
if (!background)
|
|
1879
|
+
return;
|
|
1880
|
+
const root = document.documentElement;
|
|
1881
|
+
root.style.backgroundColor = background;
|
|
1882
|
+
document.body.style.backgroundColor = background;
|
|
1883
|
+
for (const selector of [
|
|
1884
|
+
".plans-workspace",
|
|
1885
|
+
"[data-plan-reader]",
|
|
1886
|
+
"[data-plan-document]",
|
|
1887
|
+
]) {
|
|
1888
|
+
const el = document.querySelector(selector);
|
|
1889
|
+
if (el)
|
|
1890
|
+
el.style.backgroundColor = background;
|
|
1891
|
+
}
|
|
1892
|
+
}, theme ? recapScreenshotBackground(theme) : "");
|
|
1819
1893
|
const measuredHeight = await page.evaluate((maxHeight) => {
|
|
1820
1894
|
const readHeights = (selectors) => {
|
|
1821
1895
|
const result = [];
|
|
@@ -2682,7 +2756,7 @@ Usage:
|
|
|
2682
2756
|
npx @agent-native/core@latest recap mcp-config --agent claude|codex --app-url <url> [--out <path>]
|
|
2683
2757
|
npx @agent-native/core@latest recap scan --diff <path>
|
|
2684
2758
|
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>]
|
|
2685
|
-
npx @agent-native/core@latest recap shot --url <planUrl> [--token <planToken>] [--app-url <url>] [--out recap.png]
|
|
2759
|
+
npx @agent-native/core@latest recap shot --url <planUrl> [--token <planToken>] [--app-url <url>] [--out recap.png] [--theme light|dark]
|
|
2686
2760
|
npx @agent-native/core@latest recap usage --plan-url <planUrl> --result-file <path> --app-url <url> --token <planToken> [--agent claude|codex] [--model <id>]
|
|
2687
2761
|
npx @agent-native/core@latest recap agent-summary --result-file <path> [--stderr-file <path>] [--exit-code-file <path>] [--agent claude|codex]
|
|
2688
2762
|
npx @agent-native/core@latest recap comment <find-plan-id|upsert> --repo owner/name --issue <n> --token <github-token>
|