@agent-native/core 0.40.2 → 0.41.1
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 +11 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +57 -0
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/index.js +16 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/pr-visual-recap-workflow.d.ts +11 -0
- package/dist/cli/pr-visual-recap-workflow.d.ts.map +1 -0
- package/dist/cli/pr-visual-recap-workflow.js +11 -0
- package/dist/cli/pr-visual-recap-workflow.js.map +1 -0
- package/dist/cli/recap.d.ts +52 -0
- package/dist/cli/recap.d.ts.map +1 -0
- package/dist/cli/recap.js +581 -0
- package/dist/cli/recap.js.map +1 -0
- package/dist/cli/skills.d.ts +17 -4
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +60 -16
- package/dist/cli/skills.js.map +1 -1
- package/dist/cli/templates-meta.js +1 -1
- package/dist/cli/templates-meta.js.map +1 -1
- package/dist/cli/workspacify.d.ts.map +1 -1
- package/dist/cli/workspacify.js +19 -4
- package/dist/cli/workspacify.js.map +1 -1
- package/dist/client/blocks/index.d.ts +3 -0
- package/dist/client/blocks/index.d.ts.map +1 -1
- package/dist/client/blocks/index.js +3 -0
- package/dist/client/blocks/index.js.map +1 -1
- package/dist/client/blocks/library/AnnotatedCodeBlock.d.ts +6 -0
- package/dist/client/blocks/library/AnnotatedCodeBlock.d.ts.map +1 -0
- package/dist/client/blocks/library/AnnotatedCodeBlock.js +134 -0
- package/dist/client/blocks/library/AnnotatedCodeBlock.js.map +1 -0
- package/dist/client/blocks/library/HighlightedCode.d.ts +21 -1
- package/dist/client/blocks/library/HighlightedCode.d.ts.map +1 -1
- package/dist/client/blocks/library/HighlightedCode.js +86 -4
- package/dist/client/blocks/library/HighlightedCode.js.map +1 -1
- package/dist/client/blocks/library/annotated-code.config.d.ts +58 -0
- package/dist/client/blocks/library/annotated-code.config.d.ts.map +1 -0
- package/dist/client/blocks/library/annotated-code.config.js +53 -0
- package/dist/client/blocks/library/annotated-code.config.js.map +1 -0
- package/dist/client/blocks/library/checklist.js +2 -2
- package/dist/client/blocks/library/checklist.js.map +1 -1
- package/dist/client/blocks/library/code-highlight.d.ts +16 -0
- package/dist/client/blocks/library/code-highlight.d.ts.map +1 -0
- package/dist/client/blocks/library/code-highlight.js +160 -0
- package/dist/client/blocks/library/code-highlight.js.map +1 -0
- package/dist/client/blocks/library/code-tabs.config.d.ts +6 -0
- package/dist/client/blocks/library/code-tabs.config.d.ts.map +1 -1
- package/dist/client/blocks/library/code-tabs.config.js +1 -0
- package/dist/client/blocks/library/code-tabs.config.js.map +1 -1
- package/dist/client/blocks/library/code-tabs.d.ts.map +1 -1
- package/dist/client/blocks/library/code-tabs.js +35 -5
- package/dist/client/blocks/library/code-tabs.js.map +1 -1
- package/dist/client/blocks/library/code.config.d.ts +43 -0
- package/dist/client/blocks/library/code.config.d.ts.map +1 -0
- package/dist/client/blocks/library/code.config.js +34 -0
- package/dist/client/blocks/library/code.config.js.map +1 -0
- package/dist/client/blocks/library/code.d.ts +3 -0
- package/dist/client/blocks/library/code.d.ts.map +1 -0
- package/dist/client/blocks/library/code.js +95 -0
- package/dist/client/blocks/library/code.js.map +1 -0
- package/dist/client/blocks/library/dev-doc-ui.d.ts +2 -1
- package/dist/client/blocks/library/dev-doc-ui.d.ts.map +1 -1
- package/dist/client/blocks/library/dev-doc-ui.js +2 -1
- package/dist/client/blocks/library/dev-doc-ui.js.map +1 -1
- package/dist/client/blocks/library/server-specs.d.ts.map +1 -1
- package/dist/client/blocks/library/server-specs.js +21 -0
- package/dist/client/blocks/library/server-specs.js.map +1 -1
- package/dist/client/blocks/library/specs.d.ts +1 -1
- package/dist/client/blocks/library/specs.d.ts.map +1 -1
- package/dist/client/blocks/library/specs.js +30 -2
- package/dist/client/blocks/library/specs.js.map +1 -1
- package/dist/client/blocks/server.d.ts +1 -0
- package/dist/client/blocks/server.d.ts.map +1 -1
- package/dist/client/blocks/server.js +1 -0
- package/dist/client/blocks/server.js.map +1 -1
- package/dist/client/blocks/types.d.ts +1 -1
- package/dist/client/blocks/types.js.map +1 -1
- package/dist/client/extensions/ExtensionsListPage.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionsListPage.js +28 -13
- package/dist/client/extensions/ExtensionsListPage.js.map +1 -1
- package/dist/client/extensions/ExtensionsSidebarSection.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionsSidebarSection.js +31 -9
- package/dist/client/extensions/ExtensionsSidebarSection.js.map +1 -1
- package/dist/client/rich-markdown-editor/CodeBlockNode.d.ts +49 -0
- package/dist/client/rich-markdown-editor/CodeBlockNode.d.ts.map +1 -0
- package/dist/client/rich-markdown-editor/CodeBlockNode.js +126 -0
- package/dist/client/rich-markdown-editor/CodeBlockNode.js.map +1 -0
- package/dist/client/rich-markdown-editor/RegistryBlockNode.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/RegistryBlockNode.js +26 -3
- package/dist/client/rich-markdown-editor/RegistryBlockNode.js.map +1 -1
- package/dist/client/rich-markdown-editor/RichMarkdownEditor.d.ts +1 -1
- package/dist/client/rich-markdown-editor/extensions.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/extensions.js +8 -8
- package/dist/client/rich-markdown-editor/extensions.js.map +1 -1
- package/dist/client/rich-markdown-editor/index.d.ts +1 -0
- package/dist/client/rich-markdown-editor/index.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/index.js +1 -0
- package/dist/client/rich-markdown-editor/index.js.map +1 -1
- package/dist/client/rich-markdown-editor/registrySlashCommands.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/registrySlashCommands.js +1 -0
- package/dist/client/rich-markdown-editor/registrySlashCommands.js.map +1 -1
- package/dist/extensions/actions.d.ts.map +1 -1
- package/dist/extensions/actions.js +63 -2
- package/dist/extensions/actions.js.map +1 -1
- package/dist/extensions/routes.d.ts.map +1 -1
- package/dist/extensions/routes.js +24 -3
- package/dist/extensions/routes.js.map +1 -1
- package/dist/extensions/schema.d.ts +43 -2
- package/dist/extensions/schema.d.ts.map +1 -1
- package/dist/extensions/schema.js +12 -0
- package/dist/extensions/schema.js.map +1 -1
- package/dist/extensions/store.d.ts +20 -0
- package/dist/extensions/store.d.ts.map +1 -1
- package/dist/extensions/store.js +82 -3
- package/dist/extensions/store.js.map +1 -1
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +13 -0
- package/dist/server/auth.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +11 -0
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/recap-image-route.d.ts +8 -0
- package/dist/server/recap-image-route.d.ts.map +1 -0
- package/dist/server/recap-image-route.js +200 -0
- package/dist/server/recap-image-route.js.map +1 -0
- package/dist/server/recap-image-store.d.ts +41 -0
- package/dist/server/recap-image-store.d.ts.map +1 -0
- package/dist/server/recap-image-store.js +138 -0
- package/dist/server/recap-image-store.js.map +1 -0
- package/dist/styles/rich-markdown-editor.css +66 -17
- package/dist/templates/default/pnpm-workspace.yaml +7 -0
- package/dist/templates/workspace-root/package.json +0 -5
- package/dist/templates/workspace-root/pnpm-workspace.yaml +14 -0
- package/docs/content/cloneable-saas.md +10 -0
- package/docs/content/external-agents.md +4 -7
- package/docs/content/faq.md +10 -0
- package/docs/content/getting-started.md +11 -0
- package/docs/content/pr-visual-recap.md +103 -0
- package/docs/content/skills-guide.md +1 -3
- package/docs/content/template-assets.md +1 -4
- package/docs/content/template-design.md +0 -57
- package/docs/content/template-plan.md +22 -18
- package/docs/content/visual-plans.md +10 -7
- package/docs/content/what-is-agent-native.md +2 -0
- package/package.json +5 -1
- package/src/templates/default/pnpm-workspace.yaml +7 -0
- package/src/templates/workspace-root/package.json +0 -5
- package/src/templates/workspace-root/pnpm-workspace.yaml +14 -0
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n\nimport { execSync, spawn } from \"child_process\";\nimport path from \"path\";\nimport fs from \"fs\";\nimport { fileURLToPath } from \"url\";\nimport * as Sentry from \"@sentry/node\";\n\n// Resolve version once at module scope — used by both --version and --help\nlet _version = \"unknown\";\ntry {\n const __dirname = path.dirname(fileURLToPath(import.meta.url));\n // dist/cli/index.js → ../../package.json\n const pkg = JSON.parse(\n fs.readFileSync(path.resolve(__dirname, \"../../package.json\"), \"utf-8\"),\n );\n _version = pkg.version;\n} catch {}\n\n/**\n * Build a redacted \"command\" tag from process.argv. Strips the value that\n * follows any --token / --key / --secret / --password / --api-key flag so\n * we don't ship developer secrets to Sentry alongside the crash.\n *\n * Supports both `--token foo` (separate argv item) and `--token=foo`\n * (combined argv item) forms.\n */\nconst SECRET_FLAG_RE = /^--?(token|key|secret|password|api[_-]?key)$/i;\nconst SECRET_FLAG_EQ_RE =\n /^(--?(token|key|secret|password|api[_-]?key))=(.*)$/i;\nfunction buildRedactedCommandTag(argv: string[]): string {\n const out: string[] = [];\n for (let i = 0; i < argv.length; i++) {\n const a = argv[i];\n if (SECRET_FLAG_RE.test(a)) {\n out.push(a);\n // Consume the next argv item as the secret value\n if (i + 1 < argv.length) {\n out.push(\"<redacted>\");\n i++;\n }\n continue;\n }\n const m = a.match(SECRET_FLAG_EQ_RE);\n if (m) {\n out.push(`${m[1]}=<redacted>`);\n continue;\n }\n out.push(a);\n }\n return out.join(\" \");\n}\n\nSentry.init({\n dsn: \"https://0d384e9eff2f6542af468b92769f2f5b@o117565.ingest.us.sentry.io/4511270386466816\",\n release: `agent-native-cli@${_version}`,\n // sendDefaultPii MUST stay false — the CLI runs in third-party developer\n // environments and we never want to ship request headers, IPs, cookies,\n // or process env contents to Sentry without explicit consent.\n sendDefaultPii: false,\n beforeSend(event) {\n // Drop expected user-input rejections (validateRepoName, etc.) so they\n // don't pollute Sentry with non-bug noise.\n const exceptionType = event.exception?.values?.[0]?.type;\n if (\n exceptionType === \"ValidationError\" ||\n event.tags?.handled === \"validation\"\n ) {\n return null;\n }\n\n // Defense in depth: strip any sensitive fields that may have been\n // attached to the event despite sendDefaultPii: false (e.g. integrations\n // that capture request metadata).\n if (event.request) {\n if (event.request.headers) {\n const headers = event.request.headers as Record<string, string>;\n for (const k of Object.keys(headers)) {\n const lk = k.toLowerCase();\n if (\n lk === \"cookie\" ||\n lk === \"authorization\" ||\n lk === \"set-cookie\" ||\n lk === \"proxy-authorization\"\n ) {\n delete headers[k];\n }\n }\n }\n // Cookies are also exposed via event.request.cookies as a separate field\n delete (event.request as Record<string, unknown>).cookies;\n }\n // Keep user info that was explicitly set via Sentry.setUser (id/email)\n // so we can attribute crashes back to the operator. Always strip\n // ip_address — the CLI runs on third-party machines and the IP is auto-\n // collected without consent. If only auto-collected fields remain,\n // drop the user object entirely.\n if (event.user) {\n const user = event.user as Record<string, unknown>;\n delete user.ip_address;\n const hasIdentity =\n typeof user.id === \"string\" ||\n typeof user.email === \"string\" ||\n typeof user.username === \"string\";\n if (!hasIdentity) {\n delete event.user;\n }\n }\n // Sentry's contexts can carry process.env snapshots — strip env-shaped\n // contexts so we don't leak deployment secrets.\n if (event.contexts && typeof event.contexts === \"object\") {\n delete (event.contexts as Record<string, unknown>).runtime_env;\n }\n\n event.tags = {\n ...event.tags,\n // Build the command tag from process.argv with secrets redacted so\n // `agent-native ... --token foo` doesn't leak `foo` to Sentry.\n command: buildRedactedCommandTag(process.argv.slice(2)),\n subcommand: process.argv[2] ?? \"none\",\n nodeVersion: process.version,\n platform: process.platform,\n };\n return event;\n },\n});\n\n// Identify the operator so future CLI errors carry spaceId / builderUserId\n// that we can map back to a real Builder user. The CLI doesn't have a real\n// email today — only the env-managed identifiers from the workspace's .env.\n{\n const builderUserId = process.env.BUILDER_USER_ID;\n const builderPublicKey = process.env.BUILDER_PUBLIC_KEY;\n if (builderUserId) {\n Sentry.setUser({ id: builderUserId });\n Sentry.setTag(\"builderUserId\", builderUserId);\n }\n if (builderPublicKey) {\n Sentry.setTag(\"spaceId\", builderPublicKey);\n }\n}\n\nconst FEEDBACK_URL =\n \"https://forms.agent-native.com/f/agent-native-feedback/_16ewV?source=cli\";\nconst BUGS_URL = \"https://github.com/BuilderIO/agent-native/issues\";\n\nconst command = process.argv[2];\n// Filter out bare \"--\" separators that pnpm inserts between its args and script args\nconst args = process.argv.slice(3).filter((a) => a !== \"--\");\n\nfunction parseScaffoldArgs(argv: string[]): {\n name?: string;\n template?: string;\n standalone: boolean;\n} {\n let name: string | undefined;\n let template: string | undefined;\n let standalone = false;\n\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n if (arg === \"--template\" && argv[i + 1]) {\n template = argv[++i];\n } else if (arg.startsWith(\"--template=\")) {\n template = arg.slice(\"--template=\".length);\n } else if (arg === \"--standalone\") {\n standalone = true;\n } else if (!arg.startsWith(\"-\") && !name) {\n name = arg;\n }\n }\n\n return { name, template, standalone };\n}\n\n// Track CLI usage (best-effort, non-blocking)\nfunction trackCli(event: string, props?: Record<string, unknown>): void {\n try {\n import(\"../tracking/registry.js\").then((m) => {\n m.track(event, { command, ...props });\n });\n import(\"../tracking/providers.js\").then((m) =>\n m.registerBuiltinProviders(),\n );\n } catch {}\n}\n\n// Global error handler — show feedback link on unhandled crashes\nprocess.on(\"uncaughtException\", (err) => {\n console.error(`\\n Unexpected error: ${err.message}\\n`);\n console.error(` Report this bug: ${BUGS_URL}`);\n console.error(` Send feedback: ${FEEDBACK_URL}\\n`);\n trackCli(\"cli.crash\", { error: err.message });\n Sentry.captureException(err);\n Sentry.flush(2000).finally(() => process.exit(1));\n});\n\nprocess.on(\"unhandledRejection\", (reason: any) => {\n console.error(`\\n Unhandled error: ${reason?.message ?? reason}\\n`);\n console.error(` Report this bug: ${BUGS_URL}`);\n console.error(` Send feedback: ${FEEDBACK_URL}\\n`);\n trackCli(\"cli.crash\", { error: reason?.message ?? String(reason) });\n Sentry.captureException(reason);\n Sentry.flush(2000).finally(() => process.exit(1));\n});\n\n// Surface a self-heal hint when an interrupted `npx @agent-native/core ...`\n// leaves a half-extracted package in the npx cache and a follow-up run fails\n// to load one of our own sub-modules.\nfunction handleScaffoldImportError(err: any): never {\n const msg = err?.message ?? String(err);\n const looksLikeCorruptCache =\n err?.code === \"ERR_MODULE_NOT_FOUND\" ||\n err?.code === \"MODULE_NOT_FOUND\" ||\n err?.code === \"ENOENT\" ||\n /Cannot find module|tarball|integrity|EINTEGRITY|corrupt|truncated/i.test(\n msg,\n );\n if (looksLikeCorruptCache) {\n console.error(\n `\\n Failed to load the scaffolder. This usually means an earlier\\n \\`npx\\` run was interrupted and left a corrupt cache.\\n\\n Clear the npx cache and try again:\\n rm -rf ~/.npm/_npx\\n npx @agent-native/core@latest create\\n\\n Original error: ${msg}\\n`,\n );\n } else {\n console.error(`\\n Failed to load the scaffolder: ${msg}\\n`);\n }\n trackCli(\"cli.scaffold.import_error\", { error: msg });\n Sentry.captureException(err);\n Sentry.flush(2000).finally(() => process.exit(1));\n throw err;\n}\n\nfunction findViteBin(): string {\n // Look for vite in node_modules/.bin\n const localVite = path.resolve(\"node_modules/.bin/vite\");\n if (fs.existsSync(localVite)) return localVite;\n return \"vite\"; // fallback to PATH\n}\n\nfunction findTsxBin(): string {\n const localTsx = path.resolve(\"node_modules/.bin/tsx\");\n if (fs.existsSync(localTsx)) return localTsx;\n return \"tsx\";\n}\n\nfunction findReactRouterBin(): string {\n const localBin = path.resolve(\"node_modules/.bin/react-router\");\n if (fs.existsSync(localBin)) return localBin;\n return \"react-router\";\n}\n\n/** Check if the project uses React Router framework mode (has react-router.config.ts) */\nfunction isReactRouterFramework(): boolean {\n return (\n fs.existsSync(path.resolve(\"react-router.config.ts\")) ||\n fs.existsSync(path.resolve(\"react-router.config.js\"))\n );\n}\n\nfunction isWorkspaceRoot(): boolean {\n const pkgPath = path.resolve(\"package.json\");\n if (!fs.existsSync(pkgPath)) return false;\n try {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf-8\"));\n return (\n typeof pkg?.[\"agent-native\"]?.workspaceCore === \"string\" &&\n fs.existsSync(path.resolve(\"apps\"))\n );\n } catch {\n return false;\n }\n}\n\nfunction run(\n cmd: string,\n cmdArgs: string[],\n opts?: { stdio?: \"inherit\" | \"pipe\" },\n) {\n const child = spawn(cmd, cmdArgs, {\n stdio: opts?.stdio ?? \"inherit\",\n shell: process.platform === \"win32\",\n env: process.env,\n });\n child.on(\"exit\", (code) => process.exit(code ?? 0));\n // Forward signals to child so Cmd+C doesn't leave zombie processes holding ports\n for (const sig of [\"SIGINT\", \"SIGTERM\", \"SIGHUP\"] as const) {\n process.on(sig, () => {\n child.kill(sig);\n setTimeout(() => {\n try {\n child.kill(\"SIGKILL\");\n } catch {}\n process.exit(1);\n }, 5000).unref();\n });\n }\n return child;\n}\n\n/**\n * Walk up from `cwd` and try to figure out which template / app this build\n * is running for. We look for two patterns:\n *\n * - `templates/<name>/...` — building inside the framework monorepo\n * - `apps/<name>/...` — building inside a scaffolded workspace\n *\n * Both, neither, or one may match. Used purely as Sentry tags so we can\n * filter the noisy \"Command failed: react-router build\" issues by template.\n */\nfunction inferBuildContext(cwd: string): {\n template?: string;\n app?: string;\n} {\n const segs = cwd.split(path.sep);\n let template: string | undefined;\n let app: string | undefined;\n for (let i = 0; i < segs.length - 1; i++) {\n if (segs[i] === \"templates\" && segs[i + 1] && !segs[i + 1].startsWith(\".\"))\n template = segs[i + 1];\n if (segs[i] === \"apps\" && segs[i + 1] && !segs[i + 1].startsWith(\".\"))\n app = segs[i + 1];\n }\n return { template, app };\n}\n\n/**\n * Run a build subcommand, streaming its stdout/stderr to the user's terminal\n * in real time while also capturing bounded tails for Sentry. On non-zero\n * exit we report a structured event (template, app, exit code, stderr/stdout\n * tails) and exit with the child's code. We deliberately do NOT throw — the\n * global uncaughtException handler would re-capture with a generic\n * \"Error: Command failed\" title, collapsing every template's failure into\n * one issue (which is exactly what we're trying to fix here).\n */\nfunction runBuildStep(\n cmd: string,\n cmdArgs: string[],\n opts: { label: string; env?: NodeJS.ProcessEnv },\n): Promise<void> {\n return new Promise<void>((resolve) => {\n const STDERR_TAIL_BYTES = 8000;\n const STDOUT_TAIL_BYTES = 4000;\n let stderrBuf = \"\";\n let stdoutBuf = \"\";\n\n const child = spawn(cmd, cmdArgs, {\n stdio: [\"inherit\", \"pipe\", \"pipe\"],\n shell: process.platform === \"win32\",\n env: opts.env ?? process.env,\n });\n\n child.stdout?.on(\"data\", (chunk: Buffer) => {\n process.stdout.write(chunk);\n const next = stdoutBuf + chunk.toString(\"utf-8\");\n stdoutBuf =\n next.length > STDOUT_TAIL_BYTES ? next.slice(-STDOUT_TAIL_BYTES) : next;\n });\n child.stderr?.on(\"data\", (chunk: Buffer) => {\n process.stderr.write(chunk);\n const next = stderrBuf + chunk.toString(\"utf-8\");\n stderrBuf =\n next.length > STDERR_TAIL_BYTES ? next.slice(-STDERR_TAIL_BYTES) : next;\n });\n\n child.on(\"error\", (err) => {\n // Failure to spawn (ENOENT, etc.).\n const cwd = process.cwd();\n const { template, app } = inferBuildContext(cwd);\n Sentry.captureException(err, {\n tags: {\n buildStep: opts.label,\n ...(template ? { template } : {}),\n ...(app ? { app } : {}),\n },\n extra: {\n command: `${cmd} ${cmdArgs.join(\" \")}`,\n cwd,\n stage: \"spawn\",\n },\n });\n Sentry.flush(2000).finally(() => process.exit(1));\n });\n\n child.on(\"exit\", (code, signal) => {\n const exitCode = code ?? (signal ? 1 : 0);\n if (exitCode === 0) {\n resolve();\n return;\n }\n const cwd = process.cwd();\n const { template, app } = inferBuildContext(cwd);\n const childCommand = `${cmd} ${cmdArgs.join(\" \")}`;\n const err = new Error(\n `Build step \"${opts.label}\" failed with exit code ${exitCode}` +\n (template ? ` (template=${template})` : \"\") +\n (app ? ` (app=${app})` : \"\"),\n );\n Sentry.captureException(err, {\n tags: {\n buildStep: opts.label,\n ...(template ? { template } : {}),\n ...(app ? { app } : {}),\n },\n extra: {\n command: childCommand,\n cwd,\n exitCode,\n signal: signal ?? null,\n stderrTail: stderrBuf,\n stdoutTail: stdoutBuf,\n },\n });\n // Don't throw — see comment on runBuildStep above.\n Sentry.flush(2000).finally(() => process.exit(exitCode));\n });\n });\n}\n\ntrackCli(\"cli.run\");\n\nswitch (command) {\n case \"dev\": {\n if (isWorkspaceRoot()) {\n import(\"./workspace-dev.js\")\n .then((m) => m.runWorkspaceDev({ args }))\n .catch((err) => {\n console.error(err?.message ?? err);\n process.exit(1);\n });\n break;\n }\n const vite = findViteBin();\n run(vite, args);\n break;\n }\n\n case \"workspace-dev\": {\n import(\"./workspace-dev.js\")\n .then((m) => m.runWorkspaceDev({ args }))\n .catch((err) => {\n console.error(err?.message ?? err);\n process.exit(1);\n });\n break;\n }\n\n case \"build\": {\n // React Router framework mode uses `react-router build` which\n // internally runs `vite build` with proper environment orchestration.\n // Legacy SPA mode uses `vite build` directly.\n //\n // Each step uses runBuildStep so that on failure we get a Sentry event\n // tagged with template/app and including stderr/stdout tails. If the\n // child exits non-zero, runBuildStep calls process.exit itself; the\n // continuation only runs on success.\n (async () => {\n if (isReactRouterFramework()) {\n const rr = findReactRouterBin();\n console.log(\"Building (React Router framework mode)...\");\n await runBuildStep(rr, [\"build\"], { label: \"react-router-build\" });\n } else {\n const vite = findViteBin();\n console.log(\"Building...\");\n await runBuildStep(vite, [\"build\"], { label: \"vite-build\" });\n }\n\n // Post-build: framework-mode apps also need a Nitro server bundle for\n // `agent-native start` and for serverless presets.\n if (isReactRouterFramework()) {\n const __dirname = path.dirname(fileURLToPath(import.meta.url));\n const deployBuild = path.resolve(__dirname, \"../deploy/build.js\");\n if (fs.existsSync(deployBuild)) {\n await runBuildStep(\"node\", [deployBuild], {\n label: \"deploy-build\",\n env: process.env,\n });\n } else {\n console.warn(\n `[build] Deploy build script not found at ${deployBuild}. Skipping post-build step.`,\n );\n }\n }\n\n console.log(\"\\nBuild complete.\");\n })().catch((err) => {\n // runBuildStep handles its own failures and exits, so reaching here\n // implies a programming error in the orchestration above. Capture\n // and exit so the global unhandledRejection handler doesn't double-\n // report with a generic title.\n Sentry.captureException(err);\n Sentry.flush(2000).finally(() => process.exit(1));\n });\n break;\n }\n\n case \"start\": {\n // Like `next start` — runs Nitro production server\n const serverEntry = path.resolve(\".output/server/index.mjs\");\n if (!fs.existsSync(serverEntry)) {\n console.error(\n 'No production build found. Run \"agent-native build\" first.',\n );\n process.exit(1);\n }\n run(\"node\", [serverEntry, ...args]);\n break;\n }\n\n case \"action\": {\n // Run an action from actions/ (or scripts/ for backwards compat)\n const actionName = args[0];\n if (!actionName) {\n console.error(\"Usage: agent-native action <name> [--args]\");\n process.exit(1);\n }\n const tsxAction = findTsxBin();\n // Try actions/run.ts first, fall back to scripts/run.ts\n const actionsRun = path.resolve(\"actions/run.ts\");\n const scriptsRun = path.resolve(\"scripts/run.ts\");\n const runFile = fs.existsSync(actionsRun) ? actionsRun : scriptsRun;\n run(tsxAction, [runFile, ...args]);\n break;\n }\n\n case \"script\": {\n // @deprecated — use `agent-native action` instead\n const scriptName = args[0];\n if (!scriptName) {\n console.error(\"Usage: agent-native script <name> [--args]\");\n process.exit(1);\n }\n const tsx = findTsxBin();\n // Try actions/run.ts first, fall back to scripts/run.ts\n const actionsRunScript = path.resolve(\"actions/run.ts\");\n const scriptsRunScript = path.resolve(\"scripts/run.ts\");\n const runFileScript = fs.existsSync(actionsRunScript)\n ? actionsRunScript\n : scriptsRunScript;\n run(tsx, [runFileScript, ...args]);\n break;\n }\n\n case \"typecheck\": {\n // Run TypeScript type checking\n // React Router framework mode generates route types first\n if (isReactRouterFramework()) {\n const rr = findReactRouterBin();\n try {\n execSync(`${rr} typegen`, { stdio: \"inherit\" });\n } catch {\n // typegen may fail if routes aren't set up yet — continue to tsc\n }\n }\n const tsc = path.resolve(\"node_modules/.bin/tsc\");\n const tscBin = fs.existsSync(tsc) ? tsc : \"tsc\";\n run(tscBin, [\"--noEmit\", ...args]);\n break;\n }\n\n case \"create\": {\n // Defaults to creating a workspace with a multi-select template picker.\n // Use --standalone for the old single-app flow.\n // --template foo,bar Pre-select multiple templates in the picker\n // --standalone Scaffold a single standalone app\n const parsed = parseScaffoldArgs(args);\n import(\"./create.js\")\n .then((m) =>\n m.createApp(parsed.name, {\n template: parsed.template,\n standalone: parsed.standalone,\n }),\n )\n .catch(handleScaffoldImportError);\n break;\n }\n\n case \"migrate\": {\n import(\"./migrate.js\")\n .then((m) => m.runMigrate(args))\n .catch(handleScaffoldImportError);\n break;\n }\n\n case \"code\": {\n import(\"./code.js\")\n .then((m) => m.runCode(args))\n .catch(handleScaffoldImportError);\n break;\n }\n\n case \"mcp\": {\n // Connect external coding agents (Claude Code, Cowork, Codex) over MCP.\n // `mcp serve` runs the stdio transport; install/uninstall/status/token\n // manage client configs + the local token.\n import(\"./mcp.js\")\n .then((m) => m.runMcp(args))\n .catch((err) => {\n console.error(err?.message ?? err);\n process.exit(1);\n });\n break;\n }\n\n case \"connect\": {\n // Wire your local coding agent to a DEPLOYED agent-native app via a\n // browser device-code flow (no token copying). `--all` connects every\n // first-party hosted app; `--token` is the no-browser fallback.\n import(\"./connect.js\")\n .then((m) => m.runConnect(args))\n .catch((err) => {\n console.error(err?.message ?? err);\n process.exit(1);\n });\n break;\n }\n\n case \"app-skill\": {\n // Package or install an agent-native app as a skill-backed MCP/app bundle.\n import(\"./app-skill.js\")\n .then((m) => m.runAppSkill(args))\n .catch((err) => {\n console.error(err?.message ?? err);\n process.exit(1);\n });\n break;\n }\n\n case \"skills\": {\n // Friendly skill install surface. Wraps open skills installation plus MCP.\n import(\"./skills.js\")\n .then((m) => m.runSkills(args))\n .catch((err) => {\n console.error(err?.message ?? err);\n process.exit(1);\n });\n break;\n }\n\n case \"create-workspace\": {\n // Deprecated alias for `create` (since workspace is now the default).\n const parsed = parseScaffoldArgs(args);\n import(\"./create-workspace.js\")\n .then((m) =>\n m.createWorkspace({ name: parsed.name, template: parsed.template }),\n )\n .catch(handleScaffoldImportError);\n break;\n }\n\n case \"add-app\": {\n // Add one or more apps to the current workspace.\n const parsed = parseScaffoldArgs(args);\n import(\"./create.js\")\n .then((m) =>\n m.addAppToWorkspace(parsed.name, { template: parsed.template }),\n )\n .catch(handleScaffoldImportError);\n break;\n }\n\n case \"deploy\": {\n // Build and deploy the entire workspace as one unit. Each app is served\n // at /<app>/* under the same origin.\n import(\"../deploy/workspace-deploy.js\")\n .then((m) => m.runWorkspaceDeploy({ args }))\n .catch((err) => {\n console.error(\"Deploy failed:\", err?.message ?? err);\n process.exit(1);\n });\n break;\n }\n\n case \"setup-agents\": {\n import(\"./setup-agents.js\").then((m) => m.runSetupAgents());\n break;\n }\n\n case \"info\": {\n // Print read-only info about an installable package (e.g. @agent-native/scheduling).\n // Lists subpath exports, source paths in node_modules, and docs pointers.\n import(\"./info.js\").then((m) => m.runInfo(args[0]));\n break;\n }\n\n case \"audit-agent-web\": {\n import(\"./audit-agent-web.js\")\n .then((m) => m.runAuditAgentWeb(args))\n .catch((err) => {\n console.error(err?.message ?? err);\n process.exit(1);\n });\n break;\n }\n\n case \"--version\":\n case \"-v\": {\n console.log(_version);\n break;\n }\n\n case undefined:\n import(\"./code.js\")\n .then((m) => m.runCode([]))\n .catch(handleScaffoldImportError);\n break;\n\n case \"--help\":\n case \"-h\":\n console.log(`agent-native v${_version}\n\nUsage:\n agent-native Launch Agent-Native Code workspace\n agent-native \"fix tests\" Start an Agent-Native Code coding session\n agent-native dev Start development server\n (or the workspace gateway at a workspace root)\n agent-native build Build for production (client + server)\n agent-native start Start production server\n agent-native action <name> Run an action from actions/\n agent-native script <name> Run an action (deprecated alias for 'action')\n agent-native typecheck Run TypeScript type checking\n agent-native create [name] Scaffold a new agent-native workspace with a\n multi-select template picker. Use --standalone\n for a single-app scaffold.\n agent-native code Launch Agent-Native Code workspace. Type a task or\n use goals like /migrate and /audit.\n agent-native code serve Run the Agent-Native Code remote connector.\n agent-native mcp <cmd> Connect external coding agents over MCP.\n cmds: serve | install | uninstall | status |\n token (--client claude-code|claude-code-cli|\n codex|cowork)\n agent-native connect <url> Authenticate your coding agent to a DEPLOYED app.\n OAuth-capable clients (Claude Code) get a /mcp\n authenticate prompt; Codex / Cowork use the\n browser device-code flow. --all connects every\n first-party app; --token is the no-browser\n fallback. Usually run for you by 'skills add'.\n agent-native app-skill <cmd> Install, launch, or package app-backed skills.\n cmds: ensure | launch | pack\n agent-native skills add assets|design-exploration|visual-plan|visual-questions|ui-plan|prototype-plan|plan-design\n Install the skill instructions, register the MCP\n connector, AND authenticate it in one step.\n --no-connect skips auth (run 'connect' later);\n non-interactive shells print the connect command.\n agent-native migrate <source> Create an Agent-Native Code /migrate session, or use\n --emit for a portable own-agent dossier.\n agent-native add-app [name] Add one or more apps to the current workspace\n agent-native workspace-dev Start the multi-app workspace gateway\n agent-native deploy Build & deploy every app in the workspace to\n a single origin (your-agents.com/<app>/*)\n agent-native setup-agents Create symlinks for all agent tools\n agent-native info <pkg> Print info about an installed package:\n exports, source paths, and docs links.\n agent-native audit-agent-web Audit a public URL for agent-readable surfaces\n\nOptions:\n -h, --help Show this help message\n -v, --version Show version number\n --template <names> Comma-separated templates to pre-select\n (mail,calendar,analytics,...) — or\n github:user/repo for community templates\n --standalone Scaffold a single standalone app (no workspace)\n --emit [dir] With migrate, emit an own-agent dossier\n --describe <text> With migrate, describe URL/prose-only sources\n --preset <name> Workspace deploy preset:\n cloudflare_pages (default), netlify, or vercel\n --build-only Build workspace deploy artifacts without publishing\n --eager With workspace dev, start every app immediately\n --url <url> URL to audit with audit-agent-web\n\nFeedback: ${FEEDBACK_URL}\nBugs: ${BUGS_URL}`);\n break;\n\n default:\n if (command && !command.startsWith(\"-\")) {\n import(\"./code.js\")\n .then((m) => m.runCode([command, ...args]))\n .catch(handleScaffoldImportError);\n break;\n }\n console.error(`Unknown command: ${command}`);\n console.error('Run \"agent-native --help\" for usage.');\n console.error(`Bugs: ${BUGS_URL}`);\n process.exit(1);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n\nimport { execSync, spawn } from \"child_process\";\nimport path from \"path\";\nimport fs from \"fs\";\nimport { fileURLToPath } from \"url\";\nimport * as Sentry from \"@sentry/node\";\n\n// Resolve version once at module scope — used by both --version and --help\nlet _version = \"unknown\";\ntry {\n const __dirname = path.dirname(fileURLToPath(import.meta.url));\n // dist/cli/index.js → ../../package.json\n const pkg = JSON.parse(\n fs.readFileSync(path.resolve(__dirname, \"../../package.json\"), \"utf-8\"),\n );\n _version = pkg.version;\n} catch {}\n\n/**\n * Build a redacted \"command\" tag from process.argv. Strips the value that\n * follows any --token / --key / --secret / --password / --api-key flag so\n * we don't ship developer secrets to Sentry alongside the crash.\n *\n * Supports both `--token foo` (separate argv item) and `--token=foo`\n * (combined argv item) forms.\n */\nconst SECRET_FLAG_RE = /^--?(token|key|secret|password|api[_-]?key)$/i;\nconst SECRET_FLAG_EQ_RE =\n /^(--?(token|key|secret|password|api[_-]?key))=(.*)$/i;\nfunction buildRedactedCommandTag(argv: string[]): string {\n const out: string[] = [];\n for (let i = 0; i < argv.length; i++) {\n const a = argv[i];\n if (SECRET_FLAG_RE.test(a)) {\n out.push(a);\n // Consume the next argv item as the secret value\n if (i + 1 < argv.length) {\n out.push(\"<redacted>\");\n i++;\n }\n continue;\n }\n const m = a.match(SECRET_FLAG_EQ_RE);\n if (m) {\n out.push(`${m[1]}=<redacted>`);\n continue;\n }\n out.push(a);\n }\n return out.join(\" \");\n}\n\nSentry.init({\n dsn: \"https://0d384e9eff2f6542af468b92769f2f5b@o117565.ingest.us.sentry.io/4511270386466816\",\n release: `agent-native-cli@${_version}`,\n // sendDefaultPii MUST stay false — the CLI runs in third-party developer\n // environments and we never want to ship request headers, IPs, cookies,\n // or process env contents to Sentry without explicit consent.\n sendDefaultPii: false,\n beforeSend(event) {\n // Drop expected user-input rejections (validateRepoName, etc.) so they\n // don't pollute Sentry with non-bug noise.\n const exceptionType = event.exception?.values?.[0]?.type;\n if (\n exceptionType === \"ValidationError\" ||\n event.tags?.handled === \"validation\"\n ) {\n return null;\n }\n\n // Defense in depth: strip any sensitive fields that may have been\n // attached to the event despite sendDefaultPii: false (e.g. integrations\n // that capture request metadata).\n if (event.request) {\n if (event.request.headers) {\n const headers = event.request.headers as Record<string, string>;\n for (const k of Object.keys(headers)) {\n const lk = k.toLowerCase();\n if (\n lk === \"cookie\" ||\n lk === \"authorization\" ||\n lk === \"set-cookie\" ||\n lk === \"proxy-authorization\"\n ) {\n delete headers[k];\n }\n }\n }\n // Cookies are also exposed via event.request.cookies as a separate field\n delete (event.request as Record<string, unknown>).cookies;\n }\n // Keep user info that was explicitly set via Sentry.setUser (id/email)\n // so we can attribute crashes back to the operator. Always strip\n // ip_address — the CLI runs on third-party machines and the IP is auto-\n // collected without consent. If only auto-collected fields remain,\n // drop the user object entirely.\n if (event.user) {\n const user = event.user as Record<string, unknown>;\n delete user.ip_address;\n const hasIdentity =\n typeof user.id === \"string\" ||\n typeof user.email === \"string\" ||\n typeof user.username === \"string\";\n if (!hasIdentity) {\n delete event.user;\n }\n }\n // Sentry's contexts can carry process.env snapshots — strip env-shaped\n // contexts so we don't leak deployment secrets.\n if (event.contexts && typeof event.contexts === \"object\") {\n delete (event.contexts as Record<string, unknown>).runtime_env;\n }\n\n event.tags = {\n ...event.tags,\n // Build the command tag from process.argv with secrets redacted so\n // `agent-native ... --token foo` doesn't leak `foo` to Sentry.\n command: buildRedactedCommandTag(process.argv.slice(2)),\n subcommand: process.argv[2] ?? \"none\",\n nodeVersion: process.version,\n platform: process.platform,\n };\n return event;\n },\n});\n\n// Identify the operator so future CLI errors carry spaceId / builderUserId\n// that we can map back to a real Builder user. The CLI doesn't have a real\n// email today — only the env-managed identifiers from the workspace's .env.\n{\n const builderUserId = process.env.BUILDER_USER_ID;\n const builderPublicKey = process.env.BUILDER_PUBLIC_KEY;\n if (builderUserId) {\n Sentry.setUser({ id: builderUserId });\n Sentry.setTag(\"builderUserId\", builderUserId);\n }\n if (builderPublicKey) {\n Sentry.setTag(\"spaceId\", builderPublicKey);\n }\n}\n\nconst FEEDBACK_URL =\n \"https://forms.agent-native.com/f/agent-native-feedback/_16ewV?source=cli\";\nconst BUGS_URL = \"https://github.com/BuilderIO/agent-native/issues\";\n\nconst command = process.argv[2];\n// Filter out bare \"--\" separators that pnpm inserts between its args and script args\nconst args = process.argv.slice(3).filter((a) => a !== \"--\");\n\nfunction parseScaffoldArgs(argv: string[]): {\n name?: string;\n template?: string;\n standalone: boolean;\n} {\n let name: string | undefined;\n let template: string | undefined;\n let standalone = false;\n\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n if (arg === \"--template\" && argv[i + 1]) {\n template = argv[++i];\n } else if (arg.startsWith(\"--template=\")) {\n template = arg.slice(\"--template=\".length);\n } else if (arg === \"--standalone\") {\n standalone = true;\n } else if (!arg.startsWith(\"-\") && !name) {\n name = arg;\n }\n }\n\n return { name, template, standalone };\n}\n\n// Track CLI usage (best-effort, non-blocking)\nfunction trackCli(event: string, props?: Record<string, unknown>): void {\n try {\n import(\"../tracking/registry.js\").then((m) => {\n m.track(event, { command, ...props });\n });\n import(\"../tracking/providers.js\").then((m) =>\n m.registerBuiltinProviders(),\n );\n } catch {}\n}\n\n// Global error handler — show feedback link on unhandled crashes\nprocess.on(\"uncaughtException\", (err) => {\n console.error(`\\n Unexpected error: ${err.message}\\n`);\n console.error(` Report this bug: ${BUGS_URL}`);\n console.error(` Send feedback: ${FEEDBACK_URL}\\n`);\n trackCli(\"cli.crash\", { error: err.message });\n Sentry.captureException(err);\n Sentry.flush(2000).finally(() => process.exit(1));\n});\n\nprocess.on(\"unhandledRejection\", (reason: any) => {\n console.error(`\\n Unhandled error: ${reason?.message ?? reason}\\n`);\n console.error(` Report this bug: ${BUGS_URL}`);\n console.error(` Send feedback: ${FEEDBACK_URL}\\n`);\n trackCli(\"cli.crash\", { error: reason?.message ?? String(reason) });\n Sentry.captureException(reason);\n Sentry.flush(2000).finally(() => process.exit(1));\n});\n\n// Surface a self-heal hint when an interrupted `npx @agent-native/core ...`\n// leaves a half-extracted package in the npx cache and a follow-up run fails\n// to load one of our own sub-modules.\nfunction handleScaffoldImportError(err: any): never {\n const msg = err?.message ?? String(err);\n const looksLikeCorruptCache =\n err?.code === \"ERR_MODULE_NOT_FOUND\" ||\n err?.code === \"MODULE_NOT_FOUND\" ||\n err?.code === \"ENOENT\" ||\n /Cannot find module|tarball|integrity|EINTEGRITY|corrupt|truncated/i.test(\n msg,\n );\n if (looksLikeCorruptCache) {\n console.error(\n `\\n Failed to load the scaffolder. This usually means an earlier\\n \\`npx\\` run was interrupted and left a corrupt cache.\\n\\n Clear the npx cache and try again:\\n rm -rf ~/.npm/_npx\\n npx @agent-native/core@latest create\\n\\n Original error: ${msg}\\n`,\n );\n } else {\n console.error(`\\n Failed to load the scaffolder: ${msg}\\n`);\n }\n trackCli(\"cli.scaffold.import_error\", { error: msg });\n Sentry.captureException(err);\n Sentry.flush(2000).finally(() => process.exit(1));\n throw err;\n}\n\nfunction findViteBin(): string {\n // Look for vite in node_modules/.bin\n const localVite = path.resolve(\"node_modules/.bin/vite\");\n if (fs.existsSync(localVite)) return localVite;\n return \"vite\"; // fallback to PATH\n}\n\nfunction findTsxBin(): string {\n const localTsx = path.resolve(\"node_modules/.bin/tsx\");\n if (fs.existsSync(localTsx)) return localTsx;\n return \"tsx\";\n}\n\nfunction findReactRouterBin(): string {\n const localBin = path.resolve(\"node_modules/.bin/react-router\");\n if (fs.existsSync(localBin)) return localBin;\n return \"react-router\";\n}\n\n/** Check if the project uses React Router framework mode (has react-router.config.ts) */\nfunction isReactRouterFramework(): boolean {\n return (\n fs.existsSync(path.resolve(\"react-router.config.ts\")) ||\n fs.existsSync(path.resolve(\"react-router.config.js\"))\n );\n}\n\nfunction isWorkspaceRoot(): boolean {\n const pkgPath = path.resolve(\"package.json\");\n if (!fs.existsSync(pkgPath)) return false;\n try {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf-8\"));\n return (\n typeof pkg?.[\"agent-native\"]?.workspaceCore === \"string\" &&\n fs.existsSync(path.resolve(\"apps\"))\n );\n } catch {\n return false;\n }\n}\n\nfunction run(\n cmd: string,\n cmdArgs: string[],\n opts?: { stdio?: \"inherit\" | \"pipe\" },\n) {\n const child = spawn(cmd, cmdArgs, {\n stdio: opts?.stdio ?? \"inherit\",\n shell: process.platform === \"win32\",\n env: process.env,\n });\n child.on(\"exit\", (code) => process.exit(code ?? 0));\n // Forward signals to child so Cmd+C doesn't leave zombie processes holding ports\n for (const sig of [\"SIGINT\", \"SIGTERM\", \"SIGHUP\"] as const) {\n process.on(sig, () => {\n child.kill(sig);\n setTimeout(() => {\n try {\n child.kill(\"SIGKILL\");\n } catch {}\n process.exit(1);\n }, 5000).unref();\n });\n }\n return child;\n}\n\n/**\n * Walk up from `cwd` and try to figure out which template / app this build\n * is running for. We look for two patterns:\n *\n * - `templates/<name>/...` — building inside the framework monorepo\n * - `apps/<name>/...` — building inside a scaffolded workspace\n *\n * Both, neither, or one may match. Used purely as Sentry tags so we can\n * filter the noisy \"Command failed: react-router build\" issues by template.\n */\nfunction inferBuildContext(cwd: string): {\n template?: string;\n app?: string;\n} {\n const segs = cwd.split(path.sep);\n let template: string | undefined;\n let app: string | undefined;\n for (let i = 0; i < segs.length - 1; i++) {\n if (segs[i] === \"templates\" && segs[i + 1] && !segs[i + 1].startsWith(\".\"))\n template = segs[i + 1];\n if (segs[i] === \"apps\" && segs[i + 1] && !segs[i + 1].startsWith(\".\"))\n app = segs[i + 1];\n }\n return { template, app };\n}\n\n/**\n * Run a build subcommand, streaming its stdout/stderr to the user's terminal\n * in real time while also capturing bounded tails for Sentry. On non-zero\n * exit we report a structured event (template, app, exit code, stderr/stdout\n * tails) and exit with the child's code. We deliberately do NOT throw — the\n * global uncaughtException handler would re-capture with a generic\n * \"Error: Command failed\" title, collapsing every template's failure into\n * one issue (which is exactly what we're trying to fix here).\n */\nfunction runBuildStep(\n cmd: string,\n cmdArgs: string[],\n opts: { label: string; env?: NodeJS.ProcessEnv },\n): Promise<void> {\n return new Promise<void>((resolve) => {\n const STDERR_TAIL_BYTES = 8000;\n const STDOUT_TAIL_BYTES = 4000;\n let stderrBuf = \"\";\n let stdoutBuf = \"\";\n\n const child = spawn(cmd, cmdArgs, {\n stdio: [\"inherit\", \"pipe\", \"pipe\"],\n shell: process.platform === \"win32\",\n env: opts.env ?? process.env,\n });\n\n child.stdout?.on(\"data\", (chunk: Buffer) => {\n process.stdout.write(chunk);\n const next = stdoutBuf + chunk.toString(\"utf-8\");\n stdoutBuf =\n next.length > STDOUT_TAIL_BYTES ? next.slice(-STDOUT_TAIL_BYTES) : next;\n });\n child.stderr?.on(\"data\", (chunk: Buffer) => {\n process.stderr.write(chunk);\n const next = stderrBuf + chunk.toString(\"utf-8\");\n stderrBuf =\n next.length > STDERR_TAIL_BYTES ? next.slice(-STDERR_TAIL_BYTES) : next;\n });\n\n child.on(\"error\", (err) => {\n // Failure to spawn (ENOENT, etc.).\n const cwd = process.cwd();\n const { template, app } = inferBuildContext(cwd);\n Sentry.captureException(err, {\n tags: {\n buildStep: opts.label,\n ...(template ? { template } : {}),\n ...(app ? { app } : {}),\n },\n extra: {\n command: `${cmd} ${cmdArgs.join(\" \")}`,\n cwd,\n stage: \"spawn\",\n },\n });\n Sentry.flush(2000).finally(() => process.exit(1));\n });\n\n child.on(\"exit\", (code, signal) => {\n const exitCode = code ?? (signal ? 1 : 0);\n if (exitCode === 0) {\n resolve();\n return;\n }\n const cwd = process.cwd();\n const { template, app } = inferBuildContext(cwd);\n const childCommand = `${cmd} ${cmdArgs.join(\" \")}`;\n const err = new Error(\n `Build step \"${opts.label}\" failed with exit code ${exitCode}` +\n (template ? ` (template=${template})` : \"\") +\n (app ? ` (app=${app})` : \"\"),\n );\n Sentry.captureException(err, {\n tags: {\n buildStep: opts.label,\n ...(template ? { template } : {}),\n ...(app ? { app } : {}),\n },\n extra: {\n command: childCommand,\n cwd,\n exitCode,\n signal: signal ?? null,\n stderrTail: stderrBuf,\n stdoutTail: stdoutBuf,\n },\n });\n // Don't throw — see comment on runBuildStep above.\n Sentry.flush(2000).finally(() => process.exit(exitCode));\n });\n });\n}\n\ntrackCli(\"cli.run\");\n\nswitch (command) {\n case \"dev\": {\n if (isWorkspaceRoot()) {\n import(\"./workspace-dev.js\")\n .then((m) => m.runWorkspaceDev({ args }))\n .catch((err) => {\n console.error(err?.message ?? err);\n process.exit(1);\n });\n break;\n }\n const vite = findViteBin();\n run(vite, args);\n break;\n }\n\n case \"workspace-dev\": {\n import(\"./workspace-dev.js\")\n .then((m) => m.runWorkspaceDev({ args }))\n .catch((err) => {\n console.error(err?.message ?? err);\n process.exit(1);\n });\n break;\n }\n\n case \"build\": {\n // React Router framework mode uses `react-router build` which\n // internally runs `vite build` with proper environment orchestration.\n // Legacy SPA mode uses `vite build` directly.\n //\n // Each step uses runBuildStep so that on failure we get a Sentry event\n // tagged with template/app and including stderr/stdout tails. If the\n // child exits non-zero, runBuildStep calls process.exit itself; the\n // continuation only runs on success.\n (async () => {\n if (isReactRouterFramework()) {\n const rr = findReactRouterBin();\n console.log(\"Building (React Router framework mode)...\");\n await runBuildStep(rr, [\"build\"], { label: \"react-router-build\" });\n } else {\n const vite = findViteBin();\n console.log(\"Building...\");\n await runBuildStep(vite, [\"build\"], { label: \"vite-build\" });\n }\n\n // Post-build: framework-mode apps also need a Nitro server bundle for\n // `agent-native start` and for serverless presets.\n if (isReactRouterFramework()) {\n const __dirname = path.dirname(fileURLToPath(import.meta.url));\n const deployBuild = path.resolve(__dirname, \"../deploy/build.js\");\n if (fs.existsSync(deployBuild)) {\n await runBuildStep(\"node\", [deployBuild], {\n label: \"deploy-build\",\n env: process.env,\n });\n } else {\n console.warn(\n `[build] Deploy build script not found at ${deployBuild}. Skipping post-build step.`,\n );\n }\n }\n\n console.log(\"\\nBuild complete.\");\n })().catch((err) => {\n // runBuildStep handles its own failures and exits, so reaching here\n // implies a programming error in the orchestration above. Capture\n // and exit so the global unhandledRejection handler doesn't double-\n // report with a generic title.\n Sentry.captureException(err);\n Sentry.flush(2000).finally(() => process.exit(1));\n });\n break;\n }\n\n case \"start\": {\n // Like `next start` — runs Nitro production server\n const serverEntry = path.resolve(\".output/server/index.mjs\");\n if (!fs.existsSync(serverEntry)) {\n console.error(\n 'No production build found. Run \"agent-native build\" first.',\n );\n process.exit(1);\n }\n run(\"node\", [serverEntry, ...args]);\n break;\n }\n\n case \"action\": {\n // Run an action from actions/ (or scripts/ for backwards compat)\n const actionName = args[0];\n if (!actionName) {\n console.error(\"Usage: agent-native action <name> [--args]\");\n process.exit(1);\n }\n const tsxAction = findTsxBin();\n // Try actions/run.ts first, fall back to scripts/run.ts\n const actionsRun = path.resolve(\"actions/run.ts\");\n const scriptsRun = path.resolve(\"scripts/run.ts\");\n const runFile = fs.existsSync(actionsRun) ? actionsRun : scriptsRun;\n run(tsxAction, [runFile, ...args]);\n break;\n }\n\n case \"script\": {\n // @deprecated — use `agent-native action` instead\n const scriptName = args[0];\n if (!scriptName) {\n console.error(\"Usage: agent-native script <name> [--args]\");\n process.exit(1);\n }\n const tsx = findTsxBin();\n // Try actions/run.ts first, fall back to scripts/run.ts\n const actionsRunScript = path.resolve(\"actions/run.ts\");\n const scriptsRunScript = path.resolve(\"scripts/run.ts\");\n const runFileScript = fs.existsSync(actionsRunScript)\n ? actionsRunScript\n : scriptsRunScript;\n run(tsx, [runFileScript, ...args]);\n break;\n }\n\n case \"typecheck\": {\n // Run TypeScript type checking\n // React Router framework mode generates route types first\n if (isReactRouterFramework()) {\n const rr = findReactRouterBin();\n try {\n execSync(`${rr} typegen`, { stdio: \"inherit\" });\n } catch {\n // typegen may fail if routes aren't set up yet — continue to tsc\n }\n }\n const tsc = path.resolve(\"node_modules/.bin/tsc\");\n const tscBin = fs.existsSync(tsc) ? tsc : \"tsc\";\n run(tscBin, [\"--noEmit\", ...args]);\n break;\n }\n\n case \"create\": {\n // Defaults to creating a workspace with a multi-select template picker.\n // Use --standalone for the old single-app flow.\n // --template foo,bar Pre-select multiple templates in the picker\n // --standalone Scaffold a single standalone app\n const parsed = parseScaffoldArgs(args);\n import(\"./create.js\")\n .then((m) =>\n m.createApp(parsed.name, {\n template: parsed.template,\n standalone: parsed.standalone,\n }),\n )\n .catch(handleScaffoldImportError);\n break;\n }\n\n case \"migrate\": {\n import(\"./migrate.js\")\n .then((m) => m.runMigrate(args))\n .catch(handleScaffoldImportError);\n break;\n }\n\n case \"code\": {\n import(\"./code.js\")\n .then((m) => m.runCode(args))\n .catch(handleScaffoldImportError);\n break;\n }\n\n case \"mcp\": {\n // Connect external coding agents (Claude Code, Cowork, Codex) over MCP.\n // `mcp serve` runs the stdio transport; install/uninstall/status/token\n // manage client configs + the local token.\n import(\"./mcp.js\")\n .then((m) => m.runMcp(args))\n .catch((err) => {\n console.error(err?.message ?? err);\n process.exit(1);\n });\n break;\n }\n\n case \"connect\": {\n // Wire your local coding agent to a DEPLOYED agent-native app via a\n // browser device-code flow (no token copying). `--all` connects every\n // first-party hosted app; `--token` is the no-browser fallback.\n import(\"./connect.js\")\n .then((m) => m.runConnect(args))\n .catch((err) => {\n console.error(err?.message ?? err);\n process.exit(1);\n });\n break;\n }\n\n case \"app-skill\": {\n // Package or install an agent-native app as a skill-backed MCP/app bundle.\n import(\"./app-skill.js\")\n .then((m) => m.runAppSkill(args))\n .catch((err) => {\n console.error(err?.message ?? err);\n process.exit(1);\n });\n break;\n }\n\n case \"skills\": {\n // Friendly skill install surface. Wraps open skills installation plus MCP.\n import(\"./skills.js\")\n .then((m) => m.runSkills(args))\n .catch((err) => {\n console.error(err?.message ?? err);\n process.exit(1);\n });\n break;\n }\n\n case \"recap\": {\n // PR visual recap helpers used by the GitHub Action (scan | build-prompt |\n // shot | comment). Promoted to the CLI so an installed repo's workflow can\n // call `agent-native recap …` instead of copying helper scripts.\n import(\"./recap.js\")\n .then((m) => m.runRecap(args))\n .catch((err) => {\n console.error(err?.message ?? err);\n process.exit(1);\n });\n break;\n }\n\n case \"create-workspace\": {\n // Deprecated alias for `create` (since workspace is now the default).\n const parsed = parseScaffoldArgs(args);\n import(\"./create-workspace.js\")\n .then((m) =>\n m.createWorkspace({ name: parsed.name, template: parsed.template }),\n )\n .catch(handleScaffoldImportError);\n break;\n }\n\n case \"add-app\": {\n // Add one or more apps to the current workspace.\n const parsed = parseScaffoldArgs(args);\n import(\"./create.js\")\n .then((m) =>\n m.addAppToWorkspace(parsed.name, { template: parsed.template }),\n )\n .catch(handleScaffoldImportError);\n break;\n }\n\n case \"deploy\": {\n // Build and deploy the entire workspace as one unit. Each app is served\n // at /<app>/* under the same origin.\n import(\"../deploy/workspace-deploy.js\")\n .then((m) => m.runWorkspaceDeploy({ args }))\n .catch((err) => {\n console.error(\"Deploy failed:\", err?.message ?? err);\n process.exit(1);\n });\n break;\n }\n\n case \"setup-agents\": {\n import(\"./setup-agents.js\").then((m) => m.runSetupAgents());\n break;\n }\n\n case \"info\": {\n // Print read-only info about an installable package (e.g. @agent-native/scheduling).\n // Lists subpath exports, source paths in node_modules, and docs pointers.\n import(\"./info.js\").then((m) => m.runInfo(args[0]));\n break;\n }\n\n case \"audit-agent-web\": {\n import(\"./audit-agent-web.js\")\n .then((m) => m.runAuditAgentWeb(args))\n .catch((err) => {\n console.error(err?.message ?? err);\n process.exit(1);\n });\n break;\n }\n\n case \"--version\":\n case \"-v\": {\n console.log(_version);\n break;\n }\n\n case undefined:\n import(\"./code.js\")\n .then((m) => m.runCode([]))\n .catch(handleScaffoldImportError);\n break;\n\n case \"--help\":\n case \"-h\":\n console.log(`agent-native v${_version}\n\nUsage:\n agent-native Launch Agent-Native Code workspace\n agent-native \"fix tests\" Start an Agent-Native Code coding session\n agent-native dev Start development server\n (or the workspace gateway at a workspace root)\n agent-native build Build for production (client + server)\n agent-native start Start production server\n agent-native action <name> Run an action from actions/\n agent-native script <name> Run an action (deprecated alias for 'action')\n agent-native typecheck Run TypeScript type checking\n agent-native create [name] Scaffold a new agent-native workspace with a\n multi-select template picker. Use --standalone\n for a single-app scaffold.\n agent-native code Launch Agent-Native Code workspace. Type a task or\n use goals like /migrate and /audit.\n agent-native code serve Run the Agent-Native Code remote connector.\n agent-native mcp <cmd> Connect external coding agents over MCP.\n cmds: serve | install | uninstall | status |\n token (--client claude-code|claude-code-cli|\n codex|cowork)\n agent-native connect <url> Authenticate your coding agent to a DEPLOYED app.\n OAuth-capable clients (Claude Code) get a /mcp\n authenticate prompt; Codex / Cowork use the\n browser device-code flow. --all connects every\n first-party app; --token is the no-browser\n fallback. Usually run for you by 'skills add'.\n agent-native app-skill <cmd> Install, launch, or package app-backed skills.\n cmds: ensure | launch | pack\n agent-native skills add assets|design-exploration|visual-plan|visual-questions|ui-plan|prototype-plan|plan-design\n Install the skill instructions, register the MCP\n connector, AND authenticate it in one step.\n --no-connect skips auth (run 'connect' later);\n non-interactive shells print the connect command.\n --with-github-action also writes the PR Visual\n Recap workflow into .github/workflows/.\n agent-native recap <cmd> PR visual recap helpers used by the GitHub Action.\n cmds: scan | build-prompt | shot | comment\n agent-native migrate <source> Create an Agent-Native Code /migrate session, or use\n --emit for a portable own-agent dossier.\n agent-native add-app [name] Add one or more apps to the current workspace\n agent-native workspace-dev Start the multi-app workspace gateway\n agent-native deploy Build & deploy every app in the workspace to\n a single origin (your-agents.com/<app>/*)\n agent-native setup-agents Create symlinks for all agent tools\n agent-native info <pkg> Print info about an installed package:\n exports, source paths, and docs links.\n agent-native audit-agent-web Audit a public URL for agent-readable surfaces\n\nOptions:\n -h, --help Show this help message\n -v, --version Show version number\n --template <names> Comma-separated templates to pre-select\n (mail,calendar,analytics,...) — or\n github:user/repo for community templates\n --standalone Scaffold a single standalone app (no workspace)\n --emit [dir] With migrate, emit an own-agent dossier\n --describe <text> With migrate, describe URL/prose-only sources\n --preset <name> Workspace deploy preset:\n cloudflare_pages (default), netlify, or vercel\n --build-only Build workspace deploy artifacts without publishing\n --eager With workspace dev, start every app immediately\n --url <url> URL to audit with audit-agent-web\n\nFeedback: ${FEEDBACK_URL}\nBugs: ${BUGS_URL}`);\n break;\n\n default:\n if (command && !command.startsWith(\"-\")) {\n import(\"./code.js\")\n .then((m) => m.runCode([command, ...args]))\n .catch(handleScaffoldImportError);\n break;\n }\n console.error(`Unknown command: ${command}`);\n console.error('Run \"agent-native --help\" for usage.');\n console.error(`Bugs: ${BUGS_URL}`);\n process.exit(1);\n}\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bundled copy of .github/workflows/pr-visual-recap.yml so the CLI can write the
|
|
3
|
+
* PR Visual Recap workflow into a user repo via
|
|
4
|
+
* `agent-native skills add visual-plan --with-github-action`.
|
|
5
|
+
*
|
|
6
|
+
* AUTO-GENERATED — keep byte-identical with the source workflow. A sync test in
|
|
7
|
+
* recap.spec.ts fails if these drift. Regenerate from the YAML with the snippet
|
|
8
|
+
* in recap.spec.ts.
|
|
9
|
+
*/
|
|
10
|
+
export declare const PR_VISUAL_RECAP_WORKFLOW_YML = "name: PR Visual Recap\n\n# Turns every PR into a \"visual code review\" \u2014 a reverse plan \u2014 by letting a real\n# coding agent RUN THE REPO'S visual-recap SKILL against the diff. The agent\n# (Claude Code by default, or Codex) reads the skill, reasons over the change,\n# publishes an Agent-Native Plan via the plan MCP tools, and writes the plan URL\n# to recap-url.txt. The workflow then screenshots that plan in headless Chrome,\n# uploads the PNG to the plan app's signed public image route, and upserts ONE\n# sticky PR comment with the inline screenshot + the interactive link.\n#\n# Design notes:\n# - Plain `pull_request` (NOT `pull_request_target`) so fork code can never see\n# the publish/agent secrets. Fork PRs are a silent no-op.\n# - The `gate` job is a cheap switch: drafts, forks, bot authors, and the\n# missing-secret case short-circuit with NO comment and NO compute. Merging\n# this workflow before the secrets exist is a safe no-op.\n# - The recap is INFORMATIONAL ONLY. It is not a required check and failures\n# surface as an explanatory sticky comment, never a red X on unrelated code.\n# - Backend is selectable with the `VISUAL_RECAP_AGENT` repo variable\n# (claude | codex; default claude). Model and reasoning depth are tunable with\n# `VISUAL_RECAP_MODEL` (e.g. gpt-5.5) and `VISUAL_RECAP_REASONING`\n# (none|minimal|low|medium|high|xhigh; Codex only). The CLI invocation is\n# auto-detected: local source inside this monorepo, the published\n# @agent-native/core elsewhere \u2014 no repo variable needed.\n# - Only two secrets are required: PLAN_RECAP_TOKEN (publish) and the chosen\n# backend's API key. PLAN_RECAP_APP_URL defaults to the hosted plan app.\n# - Nothing here is deterministic: the skill's instructions drive the recap.\n\non:\n # Run on PRs into any base branch \u2014 the generated workflow ships to repos whose\n # default branch may not be `main`. The gate job below still no-ops drafts,\n # forks, bots, and the missing-secret case, so this stays cheap.\n pull_request:\n types: [opened, synchronize, reopened, ready_for_review]\n\npermissions:\n contents: read\n issues: write\n pull-requests: write\n\nconcurrency:\n group: pr-visual-recap-${{ github.event.pull_request.number }}\n cancel-in-progress: true\n\nenv:\n VISUAL_RECAP_AGENT: ${{ vars.VISUAL_RECAP_AGENT || 'claude' }}\n\njobs:\n # --------------------------------------------------------------------------\n # Cheap gate: decide whether to do any work at all. Sets run=false (silent\n # no-op) for drafts, forks, bot authors, or when the publish secret / the\n # chosen backend's API key is absent.\n # --------------------------------------------------------------------------\n gate:\n name: Gate\n runs-on: ubuntu-latest\n outputs:\n run: ${{ steps.decide.outputs.run }}\n steps:\n - id: decide\n uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7\n env:\n # Presence-only signals \u2014 we never expose the secret VALUES to the gate.\n # PLAN_RECAP_APP_URL defaults to the hosted app, so only the token is required.\n HAS_PLAN: ${{ secrets.PLAN_RECAP_TOKEN != '' }}\n HAS_ANTHROPIC: ${{ secrets.ANTHROPIC_API_KEY != '' }}\n HAS_OPENAI: ${{ secrets.OPENAI_API_KEY != '' }}\n AGENT: ${{ env.VISUAL_RECAP_AGENT }}\n with:\n script: |\n const pr = context.payload.pull_request;\n const reasons = [];\n\n if (!pr) reasons.push('no pull_request payload');\n if (pr && pr.draft) reasons.push('draft PR');\n\n // Fork PRs: head repo differs from this repo. Plain pull_request runs\n // fork code with NO secrets, so publishing would fail anyway \u2014 skip.\n const headRepo = pr && pr.head && pr.head.repo && pr.head.repo.full_name;\n if (pr && headRepo && headRepo !== process.env.GITHUB_REPOSITORY) {\n reasons.push(`fork PR (${headRepo})`);\n }\n\n // Skip noisy automated authors.\n const login = (pr && pr.user && pr.user.login || '').toLowerCase();\n const botAuthors = ['dependabot[bot]', 'dependabot', 'renovate[bot]', 'renovate'];\n if (botAuthors.includes(login)) reasons.push(`bot author (${login})`);\n if (pr && pr.user && pr.user.type === 'Bot') reasons.push('bot author (type=Bot)');\n\n // Publish secret must be configured \u2014 otherwise this is a no-op so the\n // workflow can be merged before secrets exist.\n if (process.env.HAS_PLAN !== 'true') reasons.push('PLAN_RECAP_TOKEN not configured');\n\n // The chosen backend's API key must be present.\n const agent = (process.env.AGENT || 'claude').toLowerCase();\n if (agent === 'codex') {\n if (process.env.HAS_OPENAI !== 'true') reasons.push('OPENAI_API_KEY not configured (codex backend)');\n } else {\n if (process.env.HAS_ANTHROPIC !== 'true') reasons.push('ANTHROPIC_API_KEY not configured (claude backend)');\n }\n\n const run = reasons.length === 0;\n core.setOutput('run', run ? 'true' : 'false');\n core.info(run ? `Visual recap will run (${agent}).` : `Visual recap skipped: ${reasons.join('; ')}`);\n\n # --------------------------------------------------------------------------\n # Recap: collect the diff, let the agent run the skill + publish, screenshot\n # the result, and upsert the sticky comment.\n # --------------------------------------------------------------------------\n recap:\n name: Generate visual recap\n needs: gate\n if: needs.gate.outputs.run == 'true'\n runs-on: ubuntu-latest\n env:\n PLAN_RECAP_APP_URL: ${{ secrets.PLAN_RECAP_APP_URL || 'https://plan.agent-native.com' }}\n PLAN_RECAP_TOKEN: ${{ secrets.PLAN_RECAP_TOKEN }}\n GH_TOKEN: ${{ github.token }}\n PR_NUMBER: ${{ github.event.pull_request.number }}\n HEAD_SHA: ${{ github.event.pull_request.head.sha }}\n VISUAL_RECAP_MODEL: ${{ vars.VISUAL_RECAP_MODEL }}\n VISUAL_RECAP_REASONING: ${{ vars.VISUAL_RECAP_REASONING }}\n steps:\n - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1\n with:\n fetch-depth: 0\n\n # Resolve the CLI invocation once: dogfood local source inside this\n # monorepo, otherwise the published package. No repo variable needed. The\n # pnpm setup/install steps below run ONLY for the local-source path, so the\n # generated workflow works out-of-box in npm/yarn consumer repos (which\n # have no pnpm-lock.yaml) by falling back to `npx @agent-native/core`.\n - name: Resolve recap CLI\n id: cli\n run: |\n if [ -f packages/core/src/cli/index.ts ]; then\n echo \"RECAP_CLI=pnpm exec tsx packages/core/src/cli/index.ts\" >> \"$GITHUB_ENV\"\n echo \"local=true\" >> \"$GITHUB_OUTPUT\"\n else\n echo \"RECAP_CLI=npx -y @agent-native/core@latest\" >> \"$GITHUB_ENV\"\n echo \"local=false\" >> \"$GITHUB_OUTPUT\"\n fi\n\n - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0\n if: steps.cli.outputs.local == 'true'\n\n - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0\n with:\n node-version: \"22\"\n cache: ${{ steps.cli.outputs.local == 'true' && 'pnpm' || '' }}\n\n - name: Install workspace (local source only)\n if: steps.cli.outputs.local == 'true'\n run: pnpm install --frozen-lockfile\n\n # Collect a BOUNDED diff between the PR base and head. We exclude lockfiles,\n # build output, and snapshots (noise), and cap the byte size \u2014 over the cap\n # we set `huge=true` so the agent is told to produce a summarized recap.\n - name: Collect bounded diff\n id: diff\n env:\n BASE_SHA: ${{ github.event.pull_request.base.sha }}\n run: |\n set -euo pipefail\n git diff --no-color \"$BASE_SHA\"...\"$HEAD_SHA\" -- \\\n . \\\n ':(exclude)pnpm-lock.yaml' \\\n ':(exclude)**/dist/**' \\\n ':(exclude)**/*.snap' \\\n ':(exclude)**/*.lock' \\\n > recap.diff || true\n git diff --stat --no-color \"$BASE_SHA\"...\"$HEAD_SHA\" -- \\\n . \\\n ':(exclude)pnpm-lock.yaml' \\\n ':(exclude)**/dist/**' \\\n ':(exclude)**/*.snap' \\\n ':(exclude)**/*.lock' \\\n > recap.stat || true\n\n BYTES=$(wc -c < recap.diff | tr -d ' ')\n CHANGED=$(git diff --name-only \"$BASE_SHA\"...\"$HEAD_SHA\" -- \\\n . \\\n ':(exclude)pnpm-lock.yaml' \\\n ':(exclude)**/dist/**' \\\n ':(exclude)**/*.snap' \\\n ':(exclude)**/*.lock' \\\n | wc -l | tr -d ' ')\n echo \"bytes=$BYTES\" >> \"$GITHUB_OUTPUT\"\n echo \"changed=$CHANGED\" >> \"$GITHUB_OUTPUT\"\n\n # ~600KB cap.\n if [ \"$BYTES\" -gt 614400 ]; then\n echo \"huge=true\" >> \"$GITHUB_OUTPUT\"\n else\n echo \"huge=false\" >> \"$GITHUB_OUTPUT\"\n fi\n\n # Tiny diffs (<= 1 changed file AND <= 8 changed lines) aren't worth a\n # recap \u2014 skip generation cleanly.\n LINES=$(grep -cE '^[+-]' recap.diff || true)\n if [ \"$CHANGED\" -le 1 ] && [ \"${LINES:-0}\" -le 8 ]; then\n echo \"tiny=true\" >> \"$GITHUB_OUTPUT\"\n else\n echo \"tiny=false\" >> \"$GITHUB_OUTPUT\"\n fi\n\n # Secret pre-scan: refuse to hand a diff that looks like it leaks\n # credentials to the agent. Prints { suppressed, reason } and always exits 0.\n - name: Secret scan\n id: scan\n if: steps.diff.outputs.tiny != 'true'\n run: |\n set -uo pipefail\n SCAN_JSON=\"$($RECAP_CLI recap scan --diff recap.diff || echo '{}')\"\n echo \"json=$SCAN_JSON\" >> \"$GITHUB_OUTPUT\"\n SUPPRESSED=$(node -e 'try{process.stdout.write(JSON.parse(process.argv[1]).suppressed?\"true\":\"false\")}catch{process.stdout.write(\"false\")}' \"$SCAN_JSON\")\n echo \"suppressed=$SUPPRESSED\" >> \"$GITHUB_OUTPUT\"\n\n # Find the planId from the previous sticky comment so a re-push REPLACES the\n # same hosted plan (synchronize updates in place, no orphaned plans).\n - name: Read previous plan id\n id: prev\n continue-on-error: true\n run: |\n set -euo pipefail\n PLAN_ID=\"$($RECAP_CLI recap comment find-plan-id --repo \"$GITHUB_REPOSITORY\" --issue \"$PR_NUMBER\" --token \"$GH_TOKEN\")\"\n echo \"plan_id=$PLAN_ID\" >> \"$GITHUB_OUTPUT\"\n\n # Build the agent prompt = the repo's visual-recap SKILL.md + a task wrapper.\n - name: Build recap prompt\n id: prompt\n if: steps.diff.outputs.tiny != 'true' && steps.scan.outputs.suppressed != 'true'\n run: |\n set -euo pipefail\n PREV=\"\"\n if [ -n \"${{ steps.prev.outputs.plan_id }}\" ]; then PREV=\"--prev-plan-id ${{ steps.prev.outputs.plan_id }}\"; fi\n HUGE=\"\"\n if [ \"${{ steps.diff.outputs.huge }}\" = \"true\" ]; then HUGE=\"--huge\"; fi\n $RECAP_CLI recap build-prompt \\\n --diff recap.diff --stat recap.stat \\\n --pr \"$PR_NUMBER\" --head \"$HEAD_SHA\" \\\n --app-url \"$PLAN_RECAP_APP_URL\" \\\n --out recap-prompt.md \\\n $HUGE $PREV\n\n # Wire the plan MCP server for the chosen backend, then run the agent. The\n # agent follows the skill, calls create-visual-recap + set-resource-visibility,\n # and writes the published plan URL to recap-url.txt. continue-on-error so a\n # failed agent run becomes an explanatory comment, not a red X.\n - name: Run agent (Claude Code)\n id: claude\n if: env.VISUAL_RECAP_AGENT == 'claude' && steps.diff.outputs.tiny != 'true' && steps.scan.outputs.suppressed != 'true'\n continue-on-error: true\n env:\n ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}\n run: |\n set -uo pipefail\n MCP_CONFIG=\"$RUNNER_TEMP/plan-mcp.json\"\n node -e 'const fs=require(\"fs\");fs.writeFileSync(process.argv[1],JSON.stringify({mcpServers:{plan:{type:\"http\",url:process.env.PLAN_RECAP_APP_URL.replace(/\\/$/,\"\")+\"/_agent-native/mcp\",headers:{Authorization:\"Bearer \"+process.env.PLAN_RECAP_TOKEN}}}}))' \"$MCP_CONFIG\"\n # VISUAL_RECAP_MODEL picks the Claude model; reasoning depth is model-driven\n # for Claude Code, so VISUAL_RECAP_REASONING only applies to the Codex backend.\n CLAUDE_ARGS=(-p \"$(cat recap-prompt.md)\" --mcp-config \"$MCP_CONFIG\" --allowedTools \"Read,Write,Bash(git diff:*),mcp__plan__create-visual-recap,mcp__plan__set-resource-visibility\" --permission-mode dontAsk)\n if [ -n \"${VISUAL_RECAP_MODEL:-}\" ]; then CLAUDE_ARGS+=(--model \"$VISUAL_RECAP_MODEL\"); fi\n npx -y @anthropic-ai/claude-code@2 \"${CLAUDE_ARGS[@]}\" || true\n rm -f \"$MCP_CONFIG\" || true\n\n - name: Run agent (Codex)\n id: codex\n if: env.VISUAL_RECAP_AGENT == 'codex' && steps.diff.outputs.tiny != 'true' && steps.scan.outputs.suppressed != 'true'\n continue-on-error: true\n env:\n OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}\n run: |\n set -uo pipefail\n mkdir -p \"$HOME/.codex\"\n # JSON.stringify the URL into the TOML value so a stray quote/newline\n # in PLAN_RECAP_APP_URL can't break out of the string (TOML basic\n # strings share JSON's escaping); the key/env name stay literal.\n node -e 'const fs=require(\"fs\");const url=process.env.PLAN_RECAP_APP_URL.replace(/\\/$/,\"\")+\"/_agent-native/mcp\";fs.writeFileSync(process.env.HOME+\"/.codex/config.toml\",\"[mcp_servers.plan]\\nurl = \"+JSON.stringify(url)+\"\\nbearer_token_env_var = \\\"PLAN_RECAP_TOKEN\\\"\\n\")'\n # VISUAL_RECAP_MODEL (e.g. gpt-5.5) and VISUAL_RECAP_REASONING\n # (none|minimal|low|medium|high|xhigh) tune the Codex run.\n CODEX_ARGS=(exec --sandbox workspace-write --skip-git-repo-check)\n if [ -n \"${VISUAL_RECAP_MODEL:-}\" ]; then CODEX_ARGS+=(--model \"$VISUAL_RECAP_MODEL\"); fi\n # Validate reasoning against the known enum before embedding it in the\n # codex `-c` TOML override, so an unexpected value can't alter the config.\n case \"${VISUAL_RECAP_REASONING:-}\" in\n none|minimal|low|medium|high|xhigh)\n CODEX_ARGS+=(-c \"model_reasoning_effort=\\\"$VISUAL_RECAP_REASONING\\\"\") ;;\n \"\") ;;\n *) echo \"Ignoring invalid VISUAL_RECAP_REASONING: $VISUAL_RECAP_REASONING\" ;;\n esac\n npx -y @openai/codex@0 \"${CODEX_ARGS[@]}\" \"$(cat recap-prompt.md)\" || true\n\n # The agent's only hand-off: recap-url.txt with the published plan URL.\n - name: Read plan URL\n id: url\n if: steps.diff.outputs.tiny != 'true' && steps.scan.outputs.suppressed != 'true'\n run: |\n set -uo pipefail\n PLAN_URL=\"\"\n if [ -f recap-url.txt ]; then PLAN_URL=\"$(tr -d '\\r\\n' < recap-url.txt | tr -d ' ')\"; fi\n echo \"plan_url=$PLAN_URL\" >> \"$GITHUB_OUTPUT\"\n if [ -n \"$PLAN_URL\" ]; then echo \"ok=true\" >> \"$GITHUB_OUTPUT\"; else echo \"ok=false\" >> \"$GITHUB_OUTPUT\"; fi\n\n # Screenshot the published plan in headless Chrome and upload the PNG to the\n # plan app's signed public image route. Best-effort: never fails the job.\n - name: Screenshot + upload\n id: shot\n if: steps.url.outputs.ok == 'true'\n continue-on-error: true\n env:\n # Pass the agent-produced plan URL through the environment, never via\n # ${{ }} interpolation into the run script: recap-url.txt is untrusted\n # agent output, so inlining it would be a shell-injection vector.\n PLAN_URL: ${{ steps.url.outputs.plan_url }}\n run: |\n set -uo pipefail\n pnpm exec playwright install --with-deps chromium 2>/dev/null || npx -y playwright@1 install --with-deps chromium || true\n SHOT_JSON=\"$($RECAP_CLI recap shot --url \"$PLAN_URL\" --token \"$PLAN_RECAP_TOKEN\" --app-url \"$PLAN_RECAP_APP_URL\" --out recap.png || echo '{}')\"\n IMAGE_URL=$(node -e 'try{process.stdout.write(JSON.parse(process.argv[1]).imageUrl||\"\")}catch{process.stdout.write(\"\")}' \"$SHOT_JSON\")\n echo \"image_url=$IMAGE_URL\" >> \"$GITHUB_OUTPUT\"\n if [ -f recap.png ]; then echo \"captured=true\" >> \"$GITHUB_OUTPUT\"; else echo \"captured=false\" >> \"$GITHUB_OUTPUT\"; fi\n\n - name: Upload recap screenshot artifact\n if: steps.shot.outputs.captured == 'true'\n uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2\n with:\n name: pr-visual-recap-${{ github.event.pull_request.number }}\n path: recap.png\n if-no-files-found: ignore\n retention-days: 14\n\n # Upsert the single sticky comment: inline screenshot + link on success,\n # suppressed / failed / tiny variants otherwise. Runs even on a tiny diff\n # so a prior recap comment is refreshed (not left pointing at a stale SHA).\n - name: Upsert sticky comment\n if: always()\n env:\n PLAN_URL: ${{ steps.url.outputs.plan_url }}\n RECAP_IMAGE_URL: ${{ steps.shot.outputs.image_url }}\n SUPPRESSED: ${{ steps.scan.outputs.suppressed }}\n SUPPRESSED_JSON: ${{ steps.scan.outputs.json }}\n DIFF_HUGE: ${{ steps.diff.outputs.huge }}\n DIFF_TINY: ${{ steps.diff.outputs.tiny }}\n run: |\n set -euo pipefail\n ARGS=(recap comment upsert --repo \"$GITHUB_REPOSITORY\" --issue \"$PR_NUMBER\" --token \"$GH_TOKEN\")\n # On a tiny diff only REFRESH an existing recap comment \u2014 never create a\n # new one \u2014 so a tiny push doesn't add noise but also can't leave a\n # stale prior recap behind.\n if [ \"${DIFF_TINY:-}\" = \"true\" ]; then ARGS+=(--update-only); fi\n $RECAP_CLI \"${ARGS[@]}\"\n";
|
|
11
|
+
//# sourceMappingURL=pr-visual-recap-workflow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pr-visual-recap-workflow.d.ts","sourceRoot":"","sources":["../../src/cli/pr-visual-recap-workflow.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,4BAA4B,irkBACigkB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bundled copy of .github/workflows/pr-visual-recap.yml so the CLI can write the
|
|
3
|
+
* PR Visual Recap workflow into a user repo via
|
|
4
|
+
* `agent-native skills add visual-plan --with-github-action`.
|
|
5
|
+
*
|
|
6
|
+
* AUTO-GENERATED — keep byte-identical with the source workflow. A sync test in
|
|
7
|
+
* recap.spec.ts fails if these drift. Regenerate from the YAML with the snippet
|
|
8
|
+
* in recap.spec.ts.
|
|
9
|
+
*/
|
|
10
|
+
export const PR_VISUAL_RECAP_WORKFLOW_YML = 'name: PR Visual Recap\n\n# Turns every PR into a "visual code review" — a reverse plan — by letting a real\n# coding agent RUN THE REPO\'S visual-recap SKILL against the diff. The agent\n# (Claude Code by default, or Codex) reads the skill, reasons over the change,\n# publishes an Agent-Native Plan via the plan MCP tools, and writes the plan URL\n# to recap-url.txt. The workflow then screenshots that plan in headless Chrome,\n# uploads the PNG to the plan app\'s signed public image route, and upserts ONE\n# sticky PR comment with the inline screenshot + the interactive link.\n#\n# Design notes:\n# - Plain `pull_request` (NOT `pull_request_target`) so fork code can never see\n# the publish/agent secrets. Fork PRs are a silent no-op.\n# - The `gate` job is a cheap switch: drafts, forks, bot authors, and the\n# missing-secret case short-circuit with NO comment and NO compute. Merging\n# this workflow before the secrets exist is a safe no-op.\n# - The recap is INFORMATIONAL ONLY. It is not a required check and failures\n# surface as an explanatory sticky comment, never a red X on unrelated code.\n# - Backend is selectable with the `VISUAL_RECAP_AGENT` repo variable\n# (claude | codex; default claude). Model and reasoning depth are tunable with\n# `VISUAL_RECAP_MODEL` (e.g. gpt-5.5) and `VISUAL_RECAP_REASONING`\n# (none|minimal|low|medium|high|xhigh; Codex only). The CLI invocation is\n# auto-detected: local source inside this monorepo, the published\n# @agent-native/core elsewhere — no repo variable needed.\n# - Only two secrets are required: PLAN_RECAP_TOKEN (publish) and the chosen\n# backend\'s API key. PLAN_RECAP_APP_URL defaults to the hosted plan app.\n# - Nothing here is deterministic: the skill\'s instructions drive the recap.\n\non:\n # Run on PRs into any base branch — the generated workflow ships to repos whose\n # default branch may not be `main`. The gate job below still no-ops drafts,\n # forks, bots, and the missing-secret case, so this stays cheap.\n pull_request:\n types: [opened, synchronize, reopened, ready_for_review]\n\npermissions:\n contents: read\n issues: write\n pull-requests: write\n\nconcurrency:\n group: pr-visual-recap-${{ github.event.pull_request.number }}\n cancel-in-progress: true\n\nenv:\n VISUAL_RECAP_AGENT: ${{ vars.VISUAL_RECAP_AGENT || \'claude\' }}\n\njobs:\n # --------------------------------------------------------------------------\n # Cheap gate: decide whether to do any work at all. Sets run=false (silent\n # no-op) for drafts, forks, bot authors, or when the publish secret / the\n # chosen backend\'s API key is absent.\n # --------------------------------------------------------------------------\n gate:\n name: Gate\n runs-on: ubuntu-latest\n outputs:\n run: ${{ steps.decide.outputs.run }}\n steps:\n - id: decide\n uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7\n env:\n # Presence-only signals — we never expose the secret VALUES to the gate.\n # PLAN_RECAP_APP_URL defaults to the hosted app, so only the token is required.\n HAS_PLAN: ${{ secrets.PLAN_RECAP_TOKEN != \'\' }}\n HAS_ANTHROPIC: ${{ secrets.ANTHROPIC_API_KEY != \'\' }}\n HAS_OPENAI: ${{ secrets.OPENAI_API_KEY != \'\' }}\n AGENT: ${{ env.VISUAL_RECAP_AGENT }}\n with:\n script: |\n const pr = context.payload.pull_request;\n const reasons = [];\n\n if (!pr) reasons.push(\'no pull_request payload\');\n if (pr && pr.draft) reasons.push(\'draft PR\');\n\n // Fork PRs: head repo differs from this repo. Plain pull_request runs\n // fork code with NO secrets, so publishing would fail anyway — skip.\n const headRepo = pr && pr.head && pr.head.repo && pr.head.repo.full_name;\n if (pr && headRepo && headRepo !== process.env.GITHUB_REPOSITORY) {\n reasons.push(`fork PR (${headRepo})`);\n }\n\n // Skip noisy automated authors.\n const login = (pr && pr.user && pr.user.login || \'\').toLowerCase();\n const botAuthors = [\'dependabot[bot]\', \'dependabot\', \'renovate[bot]\', \'renovate\'];\n if (botAuthors.includes(login)) reasons.push(`bot author (${login})`);\n if (pr && pr.user && pr.user.type === \'Bot\') reasons.push(\'bot author (type=Bot)\');\n\n // Publish secret must be configured — otherwise this is a no-op so the\n // workflow can be merged before secrets exist.\n if (process.env.HAS_PLAN !== \'true\') reasons.push(\'PLAN_RECAP_TOKEN not configured\');\n\n // The chosen backend\'s API key must be present.\n const agent = (process.env.AGENT || \'claude\').toLowerCase();\n if (agent === \'codex\') {\n if (process.env.HAS_OPENAI !== \'true\') reasons.push(\'OPENAI_API_KEY not configured (codex backend)\');\n } else {\n if (process.env.HAS_ANTHROPIC !== \'true\') reasons.push(\'ANTHROPIC_API_KEY not configured (claude backend)\');\n }\n\n const run = reasons.length === 0;\n core.setOutput(\'run\', run ? \'true\' : \'false\');\n core.info(run ? `Visual recap will run (${agent}).` : `Visual recap skipped: ${reasons.join(\'; \')}`);\n\n # --------------------------------------------------------------------------\n # Recap: collect the diff, let the agent run the skill + publish, screenshot\n # the result, and upsert the sticky comment.\n # --------------------------------------------------------------------------\n recap:\n name: Generate visual recap\n needs: gate\n if: needs.gate.outputs.run == \'true\'\n runs-on: ubuntu-latest\n env:\n PLAN_RECAP_APP_URL: ${{ secrets.PLAN_RECAP_APP_URL || \'https://plan.agent-native.com\' }}\n PLAN_RECAP_TOKEN: ${{ secrets.PLAN_RECAP_TOKEN }}\n GH_TOKEN: ${{ github.token }}\n PR_NUMBER: ${{ github.event.pull_request.number }}\n HEAD_SHA: ${{ github.event.pull_request.head.sha }}\n VISUAL_RECAP_MODEL: ${{ vars.VISUAL_RECAP_MODEL }}\n VISUAL_RECAP_REASONING: ${{ vars.VISUAL_RECAP_REASONING }}\n steps:\n - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1\n with:\n fetch-depth: 0\n\n # Resolve the CLI invocation once: dogfood local source inside this\n # monorepo, otherwise the published package. No repo variable needed. The\n # pnpm setup/install steps below run ONLY for the local-source path, so the\n # generated workflow works out-of-box in npm/yarn consumer repos (which\n # have no pnpm-lock.yaml) by falling back to `npx @agent-native/core`.\n - name: Resolve recap CLI\n id: cli\n run: |\n if [ -f packages/core/src/cli/index.ts ]; then\n echo "RECAP_CLI=pnpm exec tsx packages/core/src/cli/index.ts" >> "$GITHUB_ENV"\n echo "local=true" >> "$GITHUB_OUTPUT"\n else\n echo "RECAP_CLI=npx -y @agent-native/core@latest" >> "$GITHUB_ENV"\n echo "local=false" >> "$GITHUB_OUTPUT"\n fi\n\n - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0\n if: steps.cli.outputs.local == \'true\'\n\n - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0\n with:\n node-version: "22"\n cache: ${{ steps.cli.outputs.local == \'true\' && \'pnpm\' || \'\' }}\n\n - name: Install workspace (local source only)\n if: steps.cli.outputs.local == \'true\'\n run: pnpm install --frozen-lockfile\n\n # Collect a BOUNDED diff between the PR base and head. We exclude lockfiles,\n # build output, and snapshots (noise), and cap the byte size — over the cap\n # we set `huge=true` so the agent is told to produce a summarized recap.\n - name: Collect bounded diff\n id: diff\n env:\n BASE_SHA: ${{ github.event.pull_request.base.sha }}\n run: |\n set -euo pipefail\n git diff --no-color "$BASE_SHA"..."$HEAD_SHA" -- \\\n . \\\n \':(exclude)pnpm-lock.yaml\' \\\n \':(exclude)**/dist/**\' \\\n \':(exclude)**/*.snap\' \\\n \':(exclude)**/*.lock\' \\\n > recap.diff || true\n git diff --stat --no-color "$BASE_SHA"..."$HEAD_SHA" -- \\\n . \\\n \':(exclude)pnpm-lock.yaml\' \\\n \':(exclude)**/dist/**\' \\\n \':(exclude)**/*.snap\' \\\n \':(exclude)**/*.lock\' \\\n > recap.stat || true\n\n BYTES=$(wc -c < recap.diff | tr -d \' \')\n CHANGED=$(git diff --name-only "$BASE_SHA"..."$HEAD_SHA" -- \\\n . \\\n \':(exclude)pnpm-lock.yaml\' \\\n \':(exclude)**/dist/**\' \\\n \':(exclude)**/*.snap\' \\\n \':(exclude)**/*.lock\' \\\n | wc -l | tr -d \' \')\n echo "bytes=$BYTES" >> "$GITHUB_OUTPUT"\n echo "changed=$CHANGED" >> "$GITHUB_OUTPUT"\n\n # ~600KB cap.\n if [ "$BYTES" -gt 614400 ]; then\n echo "huge=true" >> "$GITHUB_OUTPUT"\n else\n echo "huge=false" >> "$GITHUB_OUTPUT"\n fi\n\n # Tiny diffs (<= 1 changed file AND <= 8 changed lines) aren\'t worth a\n # recap — skip generation cleanly.\n LINES=$(grep -cE \'^[+-]\' recap.diff || true)\n if [ "$CHANGED" -le 1 ] && [ "${LINES:-0}" -le 8 ]; then\n echo "tiny=true" >> "$GITHUB_OUTPUT"\n else\n echo "tiny=false" >> "$GITHUB_OUTPUT"\n fi\n\n # Secret pre-scan: refuse to hand a diff that looks like it leaks\n # credentials to the agent. Prints { suppressed, reason } and always exits 0.\n - name: Secret scan\n id: scan\n if: steps.diff.outputs.tiny != \'true\'\n run: |\n set -uo pipefail\n SCAN_JSON="$($RECAP_CLI recap scan --diff recap.diff || echo \'{}\')"\n echo "json=$SCAN_JSON" >> "$GITHUB_OUTPUT"\n SUPPRESSED=$(node -e \'try{process.stdout.write(JSON.parse(process.argv[1]).suppressed?"true":"false")}catch{process.stdout.write("false")}\' "$SCAN_JSON")\n echo "suppressed=$SUPPRESSED" >> "$GITHUB_OUTPUT"\n\n # Find the planId from the previous sticky comment so a re-push REPLACES the\n # same hosted plan (synchronize updates in place, no orphaned plans).\n - name: Read previous plan id\n id: prev\n continue-on-error: true\n run: |\n set -euo pipefail\n PLAN_ID="$($RECAP_CLI recap comment find-plan-id --repo "$GITHUB_REPOSITORY" --issue "$PR_NUMBER" --token "$GH_TOKEN")"\n echo "plan_id=$PLAN_ID" >> "$GITHUB_OUTPUT"\n\n # Build the agent prompt = the repo\'s visual-recap SKILL.md + a task wrapper.\n - name: Build recap prompt\n id: prompt\n if: steps.diff.outputs.tiny != \'true\' && steps.scan.outputs.suppressed != \'true\'\n run: |\n set -euo pipefail\n PREV=""\n if [ -n "${{ steps.prev.outputs.plan_id }}" ]; then PREV="--prev-plan-id ${{ steps.prev.outputs.plan_id }}"; fi\n HUGE=""\n if [ "${{ steps.diff.outputs.huge }}" = "true" ]; then HUGE="--huge"; fi\n $RECAP_CLI recap build-prompt \\\n --diff recap.diff --stat recap.stat \\\n --pr "$PR_NUMBER" --head "$HEAD_SHA" \\\n --app-url "$PLAN_RECAP_APP_URL" \\\n --out recap-prompt.md \\\n $HUGE $PREV\n\n # Wire the plan MCP server for the chosen backend, then run the agent. The\n # agent follows the skill, calls create-visual-recap + set-resource-visibility,\n # and writes the published plan URL to recap-url.txt. continue-on-error so a\n # failed agent run becomes an explanatory comment, not a red X.\n - name: Run agent (Claude Code)\n id: claude\n if: env.VISUAL_RECAP_AGENT == \'claude\' && steps.diff.outputs.tiny != \'true\' && steps.scan.outputs.suppressed != \'true\'\n continue-on-error: true\n env:\n ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}\n run: |\n set -uo pipefail\n MCP_CONFIG="$RUNNER_TEMP/plan-mcp.json"\n node -e \'const fs=require("fs");fs.writeFileSync(process.argv[1],JSON.stringify({mcpServers:{plan:{type:"http",url:process.env.PLAN_RECAP_APP_URL.replace(/\\/$/,"")+"/_agent-native/mcp",headers:{Authorization:"Bearer "+process.env.PLAN_RECAP_TOKEN}}}}))\' "$MCP_CONFIG"\n # VISUAL_RECAP_MODEL picks the Claude model; reasoning depth is model-driven\n # for Claude Code, so VISUAL_RECAP_REASONING only applies to the Codex backend.\n CLAUDE_ARGS=(-p "$(cat recap-prompt.md)" --mcp-config "$MCP_CONFIG" --allowedTools "Read,Write,Bash(git diff:*),mcp__plan__create-visual-recap,mcp__plan__set-resource-visibility" --permission-mode dontAsk)\n if [ -n "${VISUAL_RECAP_MODEL:-}" ]; then CLAUDE_ARGS+=(--model "$VISUAL_RECAP_MODEL"); fi\n npx -y @anthropic-ai/claude-code@2 "${CLAUDE_ARGS[@]}" || true\n rm -f "$MCP_CONFIG" || true\n\n - name: Run agent (Codex)\n id: codex\n if: env.VISUAL_RECAP_AGENT == \'codex\' && steps.diff.outputs.tiny != \'true\' && steps.scan.outputs.suppressed != \'true\'\n continue-on-error: true\n env:\n OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}\n run: |\n set -uo pipefail\n mkdir -p "$HOME/.codex"\n # JSON.stringify the URL into the TOML value so a stray quote/newline\n # in PLAN_RECAP_APP_URL can\'t break out of the string (TOML basic\n # strings share JSON\'s escaping); the key/env name stay literal.\n node -e \'const fs=require("fs");const url=process.env.PLAN_RECAP_APP_URL.replace(/\\/$/,"")+"/_agent-native/mcp";fs.writeFileSync(process.env.HOME+"/.codex/config.toml","[mcp_servers.plan]\\nurl = "+JSON.stringify(url)+"\\nbearer_token_env_var = \\"PLAN_RECAP_TOKEN\\"\\n")\'\n # VISUAL_RECAP_MODEL (e.g. gpt-5.5) and VISUAL_RECAP_REASONING\n # (none|minimal|low|medium|high|xhigh) tune the Codex run.\n CODEX_ARGS=(exec --sandbox workspace-write --skip-git-repo-check)\n if [ -n "${VISUAL_RECAP_MODEL:-}" ]; then CODEX_ARGS+=(--model "$VISUAL_RECAP_MODEL"); fi\n # Validate reasoning against the known enum before embedding it in the\n # codex `-c` TOML override, so an unexpected value can\'t alter the config.\n case "${VISUAL_RECAP_REASONING:-}" in\n none|minimal|low|medium|high|xhigh)\n CODEX_ARGS+=(-c "model_reasoning_effort=\\"$VISUAL_RECAP_REASONING\\"") ;;\n "") ;;\n *) echo "Ignoring invalid VISUAL_RECAP_REASONING: $VISUAL_RECAP_REASONING" ;;\n esac\n npx -y @openai/codex@0 "${CODEX_ARGS[@]}" "$(cat recap-prompt.md)" || true\n\n # The agent\'s only hand-off: recap-url.txt with the published plan URL.\n - name: Read plan URL\n id: url\n if: steps.diff.outputs.tiny != \'true\' && steps.scan.outputs.suppressed != \'true\'\n run: |\n set -uo pipefail\n PLAN_URL=""\n if [ -f recap-url.txt ]; then PLAN_URL="$(tr -d \'\\r\\n\' < recap-url.txt | tr -d \' \')"; fi\n echo "plan_url=$PLAN_URL" >> "$GITHUB_OUTPUT"\n if [ -n "$PLAN_URL" ]; then echo "ok=true" >> "$GITHUB_OUTPUT"; else echo "ok=false" >> "$GITHUB_OUTPUT"; fi\n\n # Screenshot the published plan in headless Chrome and upload the PNG to the\n # plan app\'s signed public image route. Best-effort: never fails the job.\n - name: Screenshot + upload\n id: shot\n if: steps.url.outputs.ok == \'true\'\n continue-on-error: true\n env:\n # Pass the agent-produced plan URL through the environment, never via\n # ${{ }} interpolation into the run script: recap-url.txt is untrusted\n # agent output, so inlining it would be a shell-injection vector.\n PLAN_URL: ${{ steps.url.outputs.plan_url }}\n run: |\n set -uo pipefail\n pnpm exec playwright install --with-deps chromium 2>/dev/null || npx -y playwright@1 install --with-deps chromium || true\n SHOT_JSON="$($RECAP_CLI recap shot --url "$PLAN_URL" --token "$PLAN_RECAP_TOKEN" --app-url "$PLAN_RECAP_APP_URL" --out recap.png || echo \'{}\')"\n IMAGE_URL=$(node -e \'try{process.stdout.write(JSON.parse(process.argv[1]).imageUrl||"")}catch{process.stdout.write("")}\' "$SHOT_JSON")\n echo "image_url=$IMAGE_URL" >> "$GITHUB_OUTPUT"\n if [ -f recap.png ]; then echo "captured=true" >> "$GITHUB_OUTPUT"; else echo "captured=false" >> "$GITHUB_OUTPUT"; fi\n\n - name: Upload recap screenshot artifact\n if: steps.shot.outputs.captured == \'true\'\n uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2\n with:\n name: pr-visual-recap-${{ github.event.pull_request.number }}\n path: recap.png\n if-no-files-found: ignore\n retention-days: 14\n\n # Upsert the single sticky comment: inline screenshot + link on success,\n # suppressed / failed / tiny variants otherwise. Runs even on a tiny diff\n # so a prior recap comment is refreshed (not left pointing at a stale SHA).\n - name: Upsert sticky comment\n if: always()\n env:\n PLAN_URL: ${{ steps.url.outputs.plan_url }}\n RECAP_IMAGE_URL: ${{ steps.shot.outputs.image_url }}\n SUPPRESSED: ${{ steps.scan.outputs.suppressed }}\n SUPPRESSED_JSON: ${{ steps.scan.outputs.json }}\n DIFF_HUGE: ${{ steps.diff.outputs.huge }}\n DIFF_TINY: ${{ steps.diff.outputs.tiny }}\n run: |\n set -euo pipefail\n ARGS=(recap comment upsert --repo "$GITHUB_REPOSITORY" --issue "$PR_NUMBER" --token "$GH_TOKEN")\n # On a tiny diff only REFRESH an existing recap comment — never create a\n # new one — so a tiny push doesn\'t add noise but also can\'t leave a\n # stale prior recap behind.\n if [ "${DIFF_TINY:-}" = "true" ]; then ARGS+=(--update-only); fi\n $RECAP_CLI "${ARGS[@]}"\n';
|
|
11
|
+
//# sourceMappingURL=pr-visual-recap-workflow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pr-visual-recap-workflow.js","sourceRoot":"","sources":["../../src/cli/pr-visual-recap-workflow.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,CAAC,MAAM,4BAA4B,GACvC,wikBAAwikB,CAAC","sourcesContent":["/**\n * Bundled copy of .github/workflows/pr-visual-recap.yml so the CLI can write the\n * PR Visual Recap workflow into a user repo via\n * `agent-native skills add visual-plan --with-github-action`.\n *\n * AUTO-GENERATED — keep byte-identical with the source workflow. A sync test in\n * recap.spec.ts fails if these drift. Regenerate from the YAML with the snippet\n * in recap.spec.ts.\n */\n\nexport const PR_VISUAL_RECAP_WORKFLOW_YML =\n 'name: PR Visual Recap\\n\\n# Turns every PR into a \"visual code review\" — a reverse plan — by letting a real\\n# coding agent RUN THE REPO\\'S visual-recap SKILL against the diff. The agent\\n# (Claude Code by default, or Codex) reads the skill, reasons over the change,\\n# publishes an Agent-Native Plan via the plan MCP tools, and writes the plan URL\\n# to recap-url.txt. The workflow then screenshots that plan in headless Chrome,\\n# uploads the PNG to the plan app\\'s signed public image route, and upserts ONE\\n# sticky PR comment with the inline screenshot + the interactive link.\\n#\\n# Design notes:\\n# - Plain `pull_request` (NOT `pull_request_target`) so fork code can never see\\n# the publish/agent secrets. Fork PRs are a silent no-op.\\n# - The `gate` job is a cheap switch: drafts, forks, bot authors, and the\\n# missing-secret case short-circuit with NO comment and NO compute. Merging\\n# this workflow before the secrets exist is a safe no-op.\\n# - The recap is INFORMATIONAL ONLY. It is not a required check and failures\\n# surface as an explanatory sticky comment, never a red X on unrelated code.\\n# - Backend is selectable with the `VISUAL_RECAP_AGENT` repo variable\\n# (claude | codex; default claude). Model and reasoning depth are tunable with\\n# `VISUAL_RECAP_MODEL` (e.g. gpt-5.5) and `VISUAL_RECAP_REASONING`\\n# (none|minimal|low|medium|high|xhigh; Codex only). The CLI invocation is\\n# auto-detected: local source inside this monorepo, the published\\n# @agent-native/core elsewhere — no repo variable needed.\\n# - Only two secrets are required: PLAN_RECAP_TOKEN (publish) and the chosen\\n# backend\\'s API key. PLAN_RECAP_APP_URL defaults to the hosted plan app.\\n# - Nothing here is deterministic: the skill\\'s instructions drive the recap.\\n\\non:\\n # Run on PRs into any base branch — the generated workflow ships to repos whose\\n # default branch may not be `main`. The gate job below still no-ops drafts,\\n # forks, bots, and the missing-secret case, so this stays cheap.\\n pull_request:\\n types: [opened, synchronize, reopened, ready_for_review]\\n\\npermissions:\\n contents: read\\n issues: write\\n pull-requests: write\\n\\nconcurrency:\\n group: pr-visual-recap-${{ github.event.pull_request.number }}\\n cancel-in-progress: true\\n\\nenv:\\n VISUAL_RECAP_AGENT: ${{ vars.VISUAL_RECAP_AGENT || \\'claude\\' }}\\n\\njobs:\\n # --------------------------------------------------------------------------\\n # Cheap gate: decide whether to do any work at all. Sets run=false (silent\\n # no-op) for drafts, forks, bot authors, or when the publish secret / the\\n # chosen backend\\'s API key is absent.\\n # --------------------------------------------------------------------------\\n gate:\\n name: Gate\\n runs-on: ubuntu-latest\\n outputs:\\n run: ${{ steps.decide.outputs.run }}\\n steps:\\n - id: decide\\n uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7\\n env:\\n # Presence-only signals — we never expose the secret VALUES to the gate.\\n # PLAN_RECAP_APP_URL defaults to the hosted app, so only the token is required.\\n HAS_PLAN: ${{ secrets.PLAN_RECAP_TOKEN != \\'\\' }}\\n HAS_ANTHROPIC: ${{ secrets.ANTHROPIC_API_KEY != \\'\\' }}\\n HAS_OPENAI: ${{ secrets.OPENAI_API_KEY != \\'\\' }}\\n AGENT: ${{ env.VISUAL_RECAP_AGENT }}\\n with:\\n script: |\\n const pr = context.payload.pull_request;\\n const reasons = [];\\n\\n if (!pr) reasons.push(\\'no pull_request payload\\');\\n if (pr && pr.draft) reasons.push(\\'draft PR\\');\\n\\n // Fork PRs: head repo differs from this repo. Plain pull_request runs\\n // fork code with NO secrets, so publishing would fail anyway — skip.\\n const headRepo = pr && pr.head && pr.head.repo && pr.head.repo.full_name;\\n if (pr && headRepo && headRepo !== process.env.GITHUB_REPOSITORY) {\\n reasons.push(`fork PR (${headRepo})`);\\n }\\n\\n // Skip noisy automated authors.\\n const login = (pr && pr.user && pr.user.login || \\'\\').toLowerCase();\\n const botAuthors = [\\'dependabot[bot]\\', \\'dependabot\\', \\'renovate[bot]\\', \\'renovate\\'];\\n if (botAuthors.includes(login)) reasons.push(`bot author (${login})`);\\n if (pr && pr.user && pr.user.type === \\'Bot\\') reasons.push(\\'bot author (type=Bot)\\');\\n\\n // Publish secret must be configured — otherwise this is a no-op so the\\n // workflow can be merged before secrets exist.\\n if (process.env.HAS_PLAN !== \\'true\\') reasons.push(\\'PLAN_RECAP_TOKEN not configured\\');\\n\\n // The chosen backend\\'s API key must be present.\\n const agent = (process.env.AGENT || \\'claude\\').toLowerCase();\\n if (agent === \\'codex\\') {\\n if (process.env.HAS_OPENAI !== \\'true\\') reasons.push(\\'OPENAI_API_KEY not configured (codex backend)\\');\\n } else {\\n if (process.env.HAS_ANTHROPIC !== \\'true\\') reasons.push(\\'ANTHROPIC_API_KEY not configured (claude backend)\\');\\n }\\n\\n const run = reasons.length === 0;\\n core.setOutput(\\'run\\', run ? \\'true\\' : \\'false\\');\\n core.info(run ? `Visual recap will run (${agent}).` : `Visual recap skipped: ${reasons.join(\\'; \\')}`);\\n\\n # --------------------------------------------------------------------------\\n # Recap: collect the diff, let the agent run the skill + publish, screenshot\\n # the result, and upsert the sticky comment.\\n # --------------------------------------------------------------------------\\n recap:\\n name: Generate visual recap\\n needs: gate\\n if: needs.gate.outputs.run == \\'true\\'\\n runs-on: ubuntu-latest\\n env:\\n PLAN_RECAP_APP_URL: ${{ secrets.PLAN_RECAP_APP_URL || \\'https://plan.agent-native.com\\' }}\\n PLAN_RECAP_TOKEN: ${{ secrets.PLAN_RECAP_TOKEN }}\\n GH_TOKEN: ${{ github.token }}\\n PR_NUMBER: ${{ github.event.pull_request.number }}\\n HEAD_SHA: ${{ github.event.pull_request.head.sha }}\\n VISUAL_RECAP_MODEL: ${{ vars.VISUAL_RECAP_MODEL }}\\n VISUAL_RECAP_REASONING: ${{ vars.VISUAL_RECAP_REASONING }}\\n steps:\\n - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1\\n with:\\n fetch-depth: 0\\n\\n # Resolve the CLI invocation once: dogfood local source inside this\\n # monorepo, otherwise the published package. No repo variable needed. The\\n # pnpm setup/install steps below run ONLY for the local-source path, so the\\n # generated workflow works out-of-box in npm/yarn consumer repos (which\\n # have no pnpm-lock.yaml) by falling back to `npx @agent-native/core`.\\n - name: Resolve recap CLI\\n id: cli\\n run: |\\n if [ -f packages/core/src/cli/index.ts ]; then\\n echo \"RECAP_CLI=pnpm exec tsx packages/core/src/cli/index.ts\" >> \"$GITHUB_ENV\"\\n echo \"local=true\" >> \"$GITHUB_OUTPUT\"\\n else\\n echo \"RECAP_CLI=npx -y @agent-native/core@latest\" >> \"$GITHUB_ENV\"\\n echo \"local=false\" >> \"$GITHUB_OUTPUT\"\\n fi\\n\\n - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0\\n if: steps.cli.outputs.local == \\'true\\'\\n\\n - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0\\n with:\\n node-version: \"22\"\\n cache: ${{ steps.cli.outputs.local == \\'true\\' && \\'pnpm\\' || \\'\\' }}\\n\\n - name: Install workspace (local source only)\\n if: steps.cli.outputs.local == \\'true\\'\\n run: pnpm install --frozen-lockfile\\n\\n # Collect a BOUNDED diff between the PR base and head. We exclude lockfiles,\\n # build output, and snapshots (noise), and cap the byte size — over the cap\\n # we set `huge=true` so the agent is told to produce a summarized recap.\\n - name: Collect bounded diff\\n id: diff\\n env:\\n BASE_SHA: ${{ github.event.pull_request.base.sha }}\\n run: |\\n set -euo pipefail\\n git diff --no-color \"$BASE_SHA\"...\"$HEAD_SHA\" -- \\\\\\n . \\\\\\n \\':(exclude)pnpm-lock.yaml\\' \\\\\\n \\':(exclude)**/dist/**\\' \\\\\\n \\':(exclude)**/*.snap\\' \\\\\\n \\':(exclude)**/*.lock\\' \\\\\\n > recap.diff || true\\n git diff --stat --no-color \"$BASE_SHA\"...\"$HEAD_SHA\" -- \\\\\\n . \\\\\\n \\':(exclude)pnpm-lock.yaml\\' \\\\\\n \\':(exclude)**/dist/**\\' \\\\\\n \\':(exclude)**/*.snap\\' \\\\\\n \\':(exclude)**/*.lock\\' \\\\\\n > recap.stat || true\\n\\n BYTES=$(wc -c < recap.diff | tr -d \\' \\')\\n CHANGED=$(git diff --name-only \"$BASE_SHA\"...\"$HEAD_SHA\" -- \\\\\\n . \\\\\\n \\':(exclude)pnpm-lock.yaml\\' \\\\\\n \\':(exclude)**/dist/**\\' \\\\\\n \\':(exclude)**/*.snap\\' \\\\\\n \\':(exclude)**/*.lock\\' \\\\\\n | wc -l | tr -d \\' \\')\\n echo \"bytes=$BYTES\" >> \"$GITHUB_OUTPUT\"\\n echo \"changed=$CHANGED\" >> \"$GITHUB_OUTPUT\"\\n\\n # ~600KB cap.\\n if [ \"$BYTES\" -gt 614400 ]; then\\n echo \"huge=true\" >> \"$GITHUB_OUTPUT\"\\n else\\n echo \"huge=false\" >> \"$GITHUB_OUTPUT\"\\n fi\\n\\n # Tiny diffs (<= 1 changed file AND <= 8 changed lines) aren\\'t worth a\\n # recap — skip generation cleanly.\\n LINES=$(grep -cE \\'^[+-]\\' recap.diff || true)\\n if [ \"$CHANGED\" -le 1 ] && [ \"${LINES:-0}\" -le 8 ]; then\\n echo \"tiny=true\" >> \"$GITHUB_OUTPUT\"\\n else\\n echo \"tiny=false\" >> \"$GITHUB_OUTPUT\"\\n fi\\n\\n # Secret pre-scan: refuse to hand a diff that looks like it leaks\\n # credentials to the agent. Prints { suppressed, reason } and always exits 0.\\n - name: Secret scan\\n id: scan\\n if: steps.diff.outputs.tiny != \\'true\\'\\n run: |\\n set -uo pipefail\\n SCAN_JSON=\"$($RECAP_CLI recap scan --diff recap.diff || echo \\'{}\\')\"\\n echo \"json=$SCAN_JSON\" >> \"$GITHUB_OUTPUT\"\\n SUPPRESSED=$(node -e \\'try{process.stdout.write(JSON.parse(process.argv[1]).suppressed?\"true\":\"false\")}catch{process.stdout.write(\"false\")}\\' \"$SCAN_JSON\")\\n echo \"suppressed=$SUPPRESSED\" >> \"$GITHUB_OUTPUT\"\\n\\n # Find the planId from the previous sticky comment so a re-push REPLACES the\\n # same hosted plan (synchronize updates in place, no orphaned plans).\\n - name: Read previous plan id\\n id: prev\\n continue-on-error: true\\n run: |\\n set -euo pipefail\\n PLAN_ID=\"$($RECAP_CLI recap comment find-plan-id --repo \"$GITHUB_REPOSITORY\" --issue \"$PR_NUMBER\" --token \"$GH_TOKEN\")\"\\n echo \"plan_id=$PLAN_ID\" >> \"$GITHUB_OUTPUT\"\\n\\n # Build the agent prompt = the repo\\'s visual-recap SKILL.md + a task wrapper.\\n - name: Build recap prompt\\n id: prompt\\n if: steps.diff.outputs.tiny != \\'true\\' && steps.scan.outputs.suppressed != \\'true\\'\\n run: |\\n set -euo pipefail\\n PREV=\"\"\\n if [ -n \"${{ steps.prev.outputs.plan_id }}\" ]; then PREV=\"--prev-plan-id ${{ steps.prev.outputs.plan_id }}\"; fi\\n HUGE=\"\"\\n if [ \"${{ steps.diff.outputs.huge }}\" = \"true\" ]; then HUGE=\"--huge\"; fi\\n $RECAP_CLI recap build-prompt \\\\\\n --diff recap.diff --stat recap.stat \\\\\\n --pr \"$PR_NUMBER\" --head \"$HEAD_SHA\" \\\\\\n --app-url \"$PLAN_RECAP_APP_URL\" \\\\\\n --out recap-prompt.md \\\\\\n $HUGE $PREV\\n\\n # Wire the plan MCP server for the chosen backend, then run the agent. The\\n # agent follows the skill, calls create-visual-recap + set-resource-visibility,\\n # and writes the published plan URL to recap-url.txt. continue-on-error so a\\n # failed agent run becomes an explanatory comment, not a red X.\\n - name: Run agent (Claude Code)\\n id: claude\\n if: env.VISUAL_RECAP_AGENT == \\'claude\\' && steps.diff.outputs.tiny != \\'true\\' && steps.scan.outputs.suppressed != \\'true\\'\\n continue-on-error: true\\n env:\\n ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}\\n run: |\\n set -uo pipefail\\n MCP_CONFIG=\"$RUNNER_TEMP/plan-mcp.json\"\\n node -e \\'const fs=require(\"fs\");fs.writeFileSync(process.argv[1],JSON.stringify({mcpServers:{plan:{type:\"http\",url:process.env.PLAN_RECAP_APP_URL.replace(/\\\\/$/,\"\")+\"/_agent-native/mcp\",headers:{Authorization:\"Bearer \"+process.env.PLAN_RECAP_TOKEN}}}}))\\' \"$MCP_CONFIG\"\\n # VISUAL_RECAP_MODEL picks the Claude model; reasoning depth is model-driven\\n # for Claude Code, so VISUAL_RECAP_REASONING only applies to the Codex backend.\\n CLAUDE_ARGS=(-p \"$(cat recap-prompt.md)\" --mcp-config \"$MCP_CONFIG\" --allowedTools \"Read,Write,Bash(git diff:*),mcp__plan__create-visual-recap,mcp__plan__set-resource-visibility\" --permission-mode dontAsk)\\n if [ -n \"${VISUAL_RECAP_MODEL:-}\" ]; then CLAUDE_ARGS+=(--model \"$VISUAL_RECAP_MODEL\"); fi\\n npx -y @anthropic-ai/claude-code@2 \"${CLAUDE_ARGS[@]}\" || true\\n rm -f \"$MCP_CONFIG\" || true\\n\\n - name: Run agent (Codex)\\n id: codex\\n if: env.VISUAL_RECAP_AGENT == \\'codex\\' && steps.diff.outputs.tiny != \\'true\\' && steps.scan.outputs.suppressed != \\'true\\'\\n continue-on-error: true\\n env:\\n OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}\\n run: |\\n set -uo pipefail\\n mkdir -p \"$HOME/.codex\"\\n # JSON.stringify the URL into the TOML value so a stray quote/newline\\n # in PLAN_RECAP_APP_URL can\\'t break out of the string (TOML basic\\n # strings share JSON\\'s escaping); the key/env name stay literal.\\n node -e \\'const fs=require(\"fs\");const url=process.env.PLAN_RECAP_APP_URL.replace(/\\\\/$/,\"\")+\"/_agent-native/mcp\";fs.writeFileSync(process.env.HOME+\"/.codex/config.toml\",\"[mcp_servers.plan]\\\\nurl = \"+JSON.stringify(url)+\"\\\\nbearer_token_env_var = \\\\\"PLAN_RECAP_TOKEN\\\\\"\\\\n\")\\'\\n # VISUAL_RECAP_MODEL (e.g. gpt-5.5) and VISUAL_RECAP_REASONING\\n # (none|minimal|low|medium|high|xhigh) tune the Codex run.\\n CODEX_ARGS=(exec --sandbox workspace-write --skip-git-repo-check)\\n if [ -n \"${VISUAL_RECAP_MODEL:-}\" ]; then CODEX_ARGS+=(--model \"$VISUAL_RECAP_MODEL\"); fi\\n # Validate reasoning against the known enum before embedding it in the\\n # codex `-c` TOML override, so an unexpected value can\\'t alter the config.\\n case \"${VISUAL_RECAP_REASONING:-}\" in\\n none|minimal|low|medium|high|xhigh)\\n CODEX_ARGS+=(-c \"model_reasoning_effort=\\\\\"$VISUAL_RECAP_REASONING\\\\\"\") ;;\\n \"\") ;;\\n *) echo \"Ignoring invalid VISUAL_RECAP_REASONING: $VISUAL_RECAP_REASONING\" ;;\\n esac\\n npx -y @openai/codex@0 \"${CODEX_ARGS[@]}\" \"$(cat recap-prompt.md)\" || true\\n\\n # The agent\\'s only hand-off: recap-url.txt with the published plan URL.\\n - name: Read plan URL\\n id: url\\n if: steps.diff.outputs.tiny != \\'true\\' && steps.scan.outputs.suppressed != \\'true\\'\\n run: |\\n set -uo pipefail\\n PLAN_URL=\"\"\\n if [ -f recap-url.txt ]; then PLAN_URL=\"$(tr -d \\'\\\\r\\\\n\\' < recap-url.txt | tr -d \\' \\')\"; fi\\n echo \"plan_url=$PLAN_URL\" >> \"$GITHUB_OUTPUT\"\\n if [ -n \"$PLAN_URL\" ]; then echo \"ok=true\" >> \"$GITHUB_OUTPUT\"; else echo \"ok=false\" >> \"$GITHUB_OUTPUT\"; fi\\n\\n # Screenshot the published plan in headless Chrome and upload the PNG to the\\n # plan app\\'s signed public image route. Best-effort: never fails the job.\\n - name: Screenshot + upload\\n id: shot\\n if: steps.url.outputs.ok == \\'true\\'\\n continue-on-error: true\\n env:\\n # Pass the agent-produced plan URL through the environment, never via\\n # ${{ }} interpolation into the run script: recap-url.txt is untrusted\\n # agent output, so inlining it would be a shell-injection vector.\\n PLAN_URL: ${{ steps.url.outputs.plan_url }}\\n run: |\\n set -uo pipefail\\n pnpm exec playwright install --with-deps chromium 2>/dev/null || npx -y playwright@1 install --with-deps chromium || true\\n SHOT_JSON=\"$($RECAP_CLI recap shot --url \"$PLAN_URL\" --token \"$PLAN_RECAP_TOKEN\" --app-url \"$PLAN_RECAP_APP_URL\" --out recap.png || echo \\'{}\\')\"\\n IMAGE_URL=$(node -e \\'try{process.stdout.write(JSON.parse(process.argv[1]).imageUrl||\"\")}catch{process.stdout.write(\"\")}\\' \"$SHOT_JSON\")\\n echo \"image_url=$IMAGE_URL\" >> \"$GITHUB_OUTPUT\"\\n if [ -f recap.png ]; then echo \"captured=true\" >> \"$GITHUB_OUTPUT\"; else echo \"captured=false\" >> \"$GITHUB_OUTPUT\"; fi\\n\\n - name: Upload recap screenshot artifact\\n if: steps.shot.outputs.captured == \\'true\\'\\n uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2\\n with:\\n name: pr-visual-recap-${{ github.event.pull_request.number }}\\n path: recap.png\\n if-no-files-found: ignore\\n retention-days: 14\\n\\n # Upsert the single sticky comment: inline screenshot + link on success,\\n # suppressed / failed / tiny variants otherwise. Runs even on a tiny diff\\n # so a prior recap comment is refreshed (not left pointing at a stale SHA).\\n - name: Upsert sticky comment\\n if: always()\\n env:\\n PLAN_URL: ${{ steps.url.outputs.plan_url }}\\n RECAP_IMAGE_URL: ${{ steps.shot.outputs.image_url }}\\n SUPPRESSED: ${{ steps.scan.outputs.suppressed }}\\n SUPPRESSED_JSON: ${{ steps.scan.outputs.json }}\\n DIFF_HUGE: ${{ steps.diff.outputs.huge }}\\n DIFF_TINY: ${{ steps.diff.outputs.tiny }}\\n run: |\\n set -euo pipefail\\n ARGS=(recap comment upsert --repo \"$GITHUB_REPOSITORY\" --issue \"$PR_NUMBER\" --token \"$GH_TOKEN\")\\n # On a tiny diff only REFRESH an existing recap comment — never create a\\n # new one — so a tiny push doesn\\'t add noise but also can\\'t leave a\\n # stale prior recap behind.\\n if [ \"${DIFF_TINY:-}\" = \"true\" ]; then ARGS+=(--update-only); fi\\n $RECAP_CLI \"${ARGS[@]}\"\\n';\n"]}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `agent-native recap <scan|build-prompt|shot|comment>` — the helper surface
|
|
3
|
+
* used by the PR Visual Recap GitHub Action.
|
|
4
|
+
*
|
|
5
|
+
* The action no longer generates the recap deterministically. Instead a coding
|
|
6
|
+
* agent (Claude Code or Codex) RUNS THE REPO'S visual-recap skill against the
|
|
7
|
+
* diff and publishes the plan via the plan MCP tools. These subcommands are the
|
|
8
|
+
* thin, deterministic glue around that:
|
|
9
|
+
*
|
|
10
|
+
* scan Refuse to hand a secret-leaking diff to the agent.
|
|
11
|
+
* build-prompt Assemble the agent prompt = repo SKILL.md + a task wrapper.
|
|
12
|
+
* shot Screenshot the published plan and upload it to the plan app's
|
|
13
|
+
* signed public image route (for an inline PR-comment image).
|
|
14
|
+
* comment Find the previous plan id / upsert the sticky PR comment.
|
|
15
|
+
*
|
|
16
|
+
* Promoting these to the published CLI means an installed repo's workflow calls
|
|
17
|
+
* `agent-native recap …` instead of copying helper scripts into the repo.
|
|
18
|
+
*
|
|
19
|
+
* Node built-ins only (plus an optional dynamic `playwright` import for `shot`).
|
|
20
|
+
*/
|
|
21
|
+
/** GitHub secrets the installed PR Visual Recap workflow needs. */
|
|
22
|
+
export declare const PR_VISUAL_RECAP_SETUP: string[];
|
|
23
|
+
/** Write .github/workflows/pr-visual-recap.yml into a repo. */
|
|
24
|
+
export declare function writePrVisualRecapWorkflow(baseDir: string): {
|
|
25
|
+
path: string;
|
|
26
|
+
existed: boolean;
|
|
27
|
+
};
|
|
28
|
+
export declare function lineLooksSecret(line: string): boolean;
|
|
29
|
+
export declare function diffContainsSecret(diffText: string): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Locate the repo's visual-recap SKILL.md, preferring the host-agent install
|
|
32
|
+
* locations so a user's `agent-native skills add` copy wins, then falling back
|
|
33
|
+
* to the framework's own source locations.
|
|
34
|
+
*/
|
|
35
|
+
export declare function readRepoSkillMd(cwd?: string): {
|
|
36
|
+
text: string;
|
|
37
|
+
source: string;
|
|
38
|
+
};
|
|
39
|
+
export declare function buildRecapPrompt(input: {
|
|
40
|
+
skillMd: string;
|
|
41
|
+
pr: string;
|
|
42
|
+
head?: string;
|
|
43
|
+
appUrl: string;
|
|
44
|
+
diffPath: string;
|
|
45
|
+
statPath?: string;
|
|
46
|
+
prevPlanId?: string;
|
|
47
|
+
huge?: boolean;
|
|
48
|
+
}): string;
|
|
49
|
+
/** Build the sticky comment body from the workflow's environment. */
|
|
50
|
+
export declare function buildCommentBody(env?: NodeJS.ProcessEnv): string;
|
|
51
|
+
export declare function runRecap(argv: string[]): Promise<void>;
|
|
52
|
+
//# sourceMappingURL=recap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recap.d.ts","sourceRoot":"","sources":["../../src/cli/recap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAkDH,mEAAmE;AACnE,eAAO,MAAM,qBAAqB,EAAE,MAAM,EAQzC,CAAC;AAEF,+DAA+D;AAC/D,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;CAClB,CAOA;AA6BD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAErD;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAa5D;AAMD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,GAAE,MAAsB,GAAG;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB,CAgBA;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,GAAG,MAAM,CAkDT;AA8ID,qEAAqE;AACrE,wBAAgB,gBAAgB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAgG7E;AAmOD,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA0B5D"}
|