@agent-native/core 0.45.0 → 0.45.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.
Files changed (93) hide show
  1. package/dist/action.d.ts +8 -1
  2. package/dist/action.d.ts.map +1 -1
  3. package/dist/action.js +20 -10
  4. package/dist/action.js.map +1 -1
  5. package/dist/cli/app-skill.d.ts +3 -1
  6. package/dist/cli/app-skill.d.ts.map +1 -1
  7. package/dist/cli/app-skill.js +50 -8
  8. package/dist/cli/app-skill.js.map +1 -1
  9. package/dist/cli/connect.d.ts.map +1 -1
  10. package/dist/cli/connect.js +39 -5
  11. package/dist/cli/connect.js.map +1 -1
  12. package/dist/cli/create.d.ts.map +1 -1
  13. package/dist/cli/create.js +9 -7
  14. package/dist/cli/create.js.map +1 -1
  15. package/dist/cli/index.js +42 -10
  16. package/dist/cli/index.js.map +1 -1
  17. package/dist/cli/mcp-config-writers.d.ts +10 -0
  18. package/dist/cli/mcp-config-writers.d.ts.map +1 -1
  19. package/dist/cli/mcp-config-writers.js +60 -6
  20. package/dist/cli/mcp-config-writers.js.map +1 -1
  21. package/dist/cli/mcp.d.ts.map +1 -1
  22. package/dist/cli/mcp.js +4 -6
  23. package/dist/cli/mcp.js.map +1 -1
  24. package/dist/cli/plan-local.d.ts.map +1 -1
  25. package/dist/cli/plan-local.js +15 -2
  26. package/dist/cli/plan-local.js.map +1 -1
  27. package/dist/cli/plan-publish-store.d.ts +17 -7
  28. package/dist/cli/plan-publish-store.d.ts.map +1 -1
  29. package/dist/cli/plan-publish-store.js +33 -8
  30. package/dist/cli/plan-publish-store.js.map +1 -1
  31. package/dist/cli/pr-visual-recap-workflow.d.ts +1 -1
  32. package/dist/cli/pr-visual-recap-workflow.d.ts.map +1 -1
  33. package/dist/cli/pr-visual-recap-workflow.js +1 -1
  34. package/dist/cli/pr-visual-recap-workflow.js.map +1 -1
  35. package/dist/cli/recap.d.ts +63 -5
  36. package/dist/cli/recap.d.ts.map +1 -1
  37. package/dist/cli/recap.js +641 -48
  38. package/dist/cli/recap.js.map +1 -1
  39. package/dist/cli/skills.d.ts +26 -11
  40. package/dist/cli/skills.d.ts.map +1 -1
  41. package/dist/cli/skills.js +644 -972
  42. package/dist/cli/skills.js.map +1 -1
  43. package/dist/cli/templates-meta.d.ts.map +1 -1
  44. package/dist/cli/templates-meta.js +3 -2
  45. package/dist/cli/templates-meta.js.map +1 -1
  46. package/dist/client/blocks/library/AnnotatedCodeBlock.d.ts.map +1 -1
  47. package/dist/client/blocks/library/AnnotatedCodeBlock.js +37 -9
  48. package/dist/client/blocks/library/AnnotatedCodeBlock.js.map +1 -1
  49. package/dist/client/blocks/library/DiffBlock.d.ts.map +1 -1
  50. package/dist/client/blocks/library/DiffBlock.js +44 -12
  51. package/dist/client/blocks/library/DiffBlock.js.map +1 -1
  52. package/dist/client/blocks/library/annotation-rail.d.ts +12 -3
  53. package/dist/client/blocks/library/annotation-rail.d.ts.map +1 -1
  54. package/dist/client/blocks/library/annotation-rail.js +29 -3
  55. package/dist/client/blocks/library/annotation-rail.js.map +1 -1
  56. package/dist/client/blocks/library/html.d.ts.map +1 -1
  57. package/dist/client/blocks/library/html.js +3 -1
  58. package/dist/client/blocks/library/html.js.map +1 -1
  59. package/dist/client/blocks/library/question-form.d.ts.map +1 -1
  60. package/dist/client/blocks/library/question-form.js +4 -1
  61. package/dist/client/blocks/library/question-form.js.map +1 -1
  62. package/dist/db/migrations.d.ts.map +1 -1
  63. package/dist/db/migrations.js +2 -1
  64. package/dist/db/migrations.js.map +1 -1
  65. package/dist/extensions/routes.d.ts +18 -0
  66. package/dist/extensions/routes.d.ts.map +1 -1
  67. package/dist/extensions/routes.js +30 -8
  68. package/dist/extensions/routes.js.map +1 -1
  69. package/dist/oauth-tokens/store.d.ts.map +1 -1
  70. package/dist/oauth-tokens/store.js +42 -5
  71. package/dist/oauth-tokens/store.js.map +1 -1
  72. package/dist/scripts/db/index.d.ts.map +1 -1
  73. package/dist/scripts/db/index.js +1 -0
  74. package/dist/scripts/db/index.js.map +1 -1
  75. package/dist/scripts/db/migrate-encrypt-oauth-tokens.d.ts +28 -0
  76. package/dist/scripts/db/migrate-encrypt-oauth-tokens.d.ts.map +1 -0
  77. package/dist/scripts/db/migrate-encrypt-oauth-tokens.js +164 -0
  78. package/dist/scripts/db/migrate-encrypt-oauth-tokens.js.map +1 -0
  79. package/dist/scripts/db/scoping.d.ts.map +1 -1
  80. package/dist/scripts/db/scoping.js +7 -5
  81. package/dist/scripts/db/scoping.js.map +1 -1
  82. package/dist/secrets/index.d.ts +1 -0
  83. package/dist/secrets/index.d.ts.map +1 -1
  84. package/dist/secrets/index.js +4 -0
  85. package/dist/secrets/index.js.map +1 -1
  86. package/dist/sharing/actions/set-resource-visibility.d.ts.map +1 -1
  87. package/dist/sharing/actions/set-resource-visibility.js +4 -1
  88. package/dist/sharing/actions/set-resource-visibility.js.map +1 -1
  89. package/docs/content/plan-plugin.md +21 -6
  90. package/docs/content/pr-visual-recap.md +52 -3
  91. package/docs/content/skills-guide.md +13 -0
  92. package/docs/content/template-plan.md +18 -7
  93. package/package.json +5 -1
@@ -1 +1 @@
1
- {"version":3,"file":"templates-meta.d.ts","sourceRoot":"","sources":["../../src/cli/templates-meta.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,WAAW,YAAY;IAC3B,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,8BAA8B;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,uBAAuB;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6CAA6C;IAC7C,WAAW,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IAC7B,uEAAuE;IACvE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,8EAA8E;IAC9E,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,mEAAmE;IACnE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,+EAA+E;IAC/E,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,wEAAwE;IACxE,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,eAAO,MAAM,SAAS,EAAE,YAAY,EA2LnC,CAAC;AAEF,yEAAyE;AACzE,wBAAgB,gBAAgB,IAAI,YAAY,EAAE,CAEjD;AAED,gFAAgF;AAChF,wBAAgB,aAAa,IAAI,YAAY,EAAE,CAE9C;AAED,2DAA2D;AAC3D,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAQlE;AAED,gEAAgE;AAChE,wBAAgB,gBAAgB,IAAI,MAAM,EAAE,CAE3C"}
1
+ {"version":3,"file":"templates-meta.d.ts","sourceRoot":"","sources":["../../src/cli/templates-meta.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,WAAW,YAAY;IAC3B,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,8BAA8B;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,uBAAuB;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6CAA6C;IAC7C,WAAW,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IAC7B,uEAAuE;IACvE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,8EAA8E;IAC9E,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,mEAAmE;IACnE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,+EAA+E;IAC/E,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,wEAAwE;IACxE,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,eAAO,MAAM,SAAS,EAAE,YAAY,EA4LnC,CAAC;AAEF,yEAAyE;AACzE,wBAAgB,gBAAgB,IAAI,YAAY,EAAE,CAEjD;AAED,gFAAgF;AAChF,wBAAgB,aAAa,IAAI,YAAY,EAAE,CAE9C;AAED,2DAA2D;AAC3D,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAQlE;AAED,gEAAgE;AAChE,wBAAgB,gBAAgB,IAAI,MAAM,EAAE,CAE3C"}
@@ -43,7 +43,7 @@ export const TEMPLATES = [
43
43
  {
44
44
  name: "plan",
45
45
  label: "Plan",
46
- hint: "Agent-native HTML plans with diagrams, wireframes, prototypes, annotations, sharing, and proof gates",
46
+ hint: "Structured visual plans and PR recaps with diagrams, wireframes, prototypes, annotations, and sharing",
47
47
  icon: "FileText",
48
48
  color: "#52525B",
49
49
  colorRgb: "82 82 91",
@@ -133,6 +133,7 @@ export const TEMPLATES = [
133
133
  color: "#71717A",
134
134
  colorRgb: "113 113 122",
135
135
  devPort: 8089,
136
+ prodUrl: "https://starter.agent-native.com",
136
137
  defaultMode: "prod",
137
138
  alwaysAvailable: true,
138
139
  core: true,
@@ -153,7 +154,7 @@ export const TEMPLATES = [
153
154
  {
154
155
  name: "brain",
155
156
  label: "Brain",
156
- hint: "Cited company memory from Slack, meetings, transcripts, and decisions",
157
+ hint: "Cited company knowledge from Slack, meetings, transcripts, and decisions",
157
158
  icon: "Brain",
158
159
  color: "#8B5CF6",
159
160
  colorRgb: "139 92 246",
@@ -1 +1 @@
1
- {"version":3,"file":"templates-meta.js","sourceRoot":"","sources":["../../src/cli/templates-meta.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * First-party template metadata used by the `agent-native` CLI.\n *\n * This file is intentionally inlined here (rather than imported from a\n * separate workspace package) so that the published `@agent-native/core`\n * has no `workspace:*` runtime dependencies. Without this inlining, `npx\n * @agent-native/core create ...` fails on a fresh machine with:\n *\n * npm error code EUNSUPPORTEDPROTOCOL\n * npm error Unsupported URL Type \"workspace:\": workspace:*\n *\n * Keep this list in sync with `packages/shared-app-config/templates.ts`,\n * which serves the same metadata to the desktop / mobile / frame packages\n * that always run inside the workspace. Duplication is intentional: the\n * CLI must remain installable outside the monorepo.\n */\n\nexport interface TemplateMeta {\n /** Directory name under templates/ and package name */\n name: string;\n /** Display name in pickers */\n label: string;\n /** One-line description shown in the picker */\n hint: string;\n /** Longer description (optional) */\n description?: string;\n /** Tabler icon name used in the desktop sidebar */\n icon: string;\n /** Hex accent color */\n color: string;\n /** CSS-safe RGB triplet (e.g. \"59 130 246\") */\n colorRgb: string;\n /** Dev server port for desktop `pnpm dev` */\n devPort: number;\n /** Production URL when running as a first-party app on agent-native.com */\n prodUrl?: string;\n /** Default URL path when deployed in a workspace (defaults to \"/<name>\") */\n prodPath?: string;\n /** Default mode when added to desktop app */\n defaultMode?: \"dev\" | \"prod\";\n /** Hide from pickers but still scaffoldable via explicit --template */\n hidden?: boolean;\n /** Include as a built-in connected A2A agent even when hidden from pickers */\n defaultAgent?: boolean;\n /** Always scaffold without prompting (e.g. starter as fallback) */\n alwaysAvailable?: boolean;\n /** Internal workspace packages this template depends on (e.g. \"scheduling\") */\n requiredPackages?: string[];\n /** Core app — featured in the CLI picker, homepage, and docs gallery */\n core?: boolean;\n}\n\nexport const TEMPLATES: TemplateMeta[] = [\n {\n name: \"calendar\",\n label: \"Calendar\",\n hint: \"Agent-native Google Calendar — manage events, sync, and public booking\",\n icon: \"CalendarDays\",\n color: \"#00B5FF\",\n colorRgb: \"0 181 255\",\n devPort: 8082,\n prodUrl: \"https://calendar.agent-native.com\",\n defaultMode: \"prod\",\n requiredPackages: [\"scheduling\"],\n core: true,\n },\n {\n name: \"content\",\n label: \"Content\",\n hint: \"Agent-native Notion/Google Docs — write and organize with agent assistance\",\n icon: \"FileText\",\n color: \"#10B981\",\n colorRgb: \"16 185 129\",\n devPort: 8083,\n prodUrl: \"https://content.agent-native.com\",\n defaultMode: \"prod\",\n core: true,\n },\n {\n name: \"plan\",\n label: \"Plan\",\n hint: \"Agent-native HTML plans with diagrams, wireframes, prototypes, annotations, sharing, and proof gates\",\n icon: \"FileText\",\n color: \"#52525B\",\n colorRgb: \"82 82 91\",\n devPort: 8105,\n prodUrl: \"https://plan.agent-native.com\",\n defaultMode: \"prod\",\n core: true,\n },\n {\n name: \"slides\",\n label: \"Slides\",\n hint: \"Agent-native Google Slides — generate and edit React presentations\",\n icon: \"GalleryHorizontal\",\n color: \"#EC4899\",\n colorRgb: \"236 72 153\",\n devPort: 8086,\n prodUrl: \"https://slides.agent-native.com\",\n defaultMode: \"prod\",\n requiredPackages: [\"pinpoint\"],\n core: true,\n },\n {\n name: \"videos\",\n label: \"Video\",\n hint: \"Agent-native video editing with Remotion\",\n icon: \"Video\",\n color: \"#EF4444\",\n colorRgb: \"239 68 68\",\n devPort: 8087,\n prodUrl: \"https://videos.agent-native.com\",\n defaultMode: \"prod\",\n requiredPackages: [\"pinpoint\"],\n },\n {\n name: \"analytics\",\n label: \"Analytics\",\n hint: \"Agent-native Amplitude/Mixpanel — connect data sources, prompt for charts\",\n icon: \"BarChart2\",\n color: \"#F59E0B\",\n colorRgb: \"245 158 11\",\n devPort: 8088,\n prodUrl: \"https://analytics.agent-native.com\",\n defaultMode: \"prod\",\n core: true,\n },\n {\n name: \"mail\",\n label: \"Mail\",\n hint: \"Agent-native Superhuman — email client with keyboard shortcuts and AI triage\",\n icon: \"Mail\",\n color: \"#3B82F6\",\n colorRgb: \"59 130 246\",\n devPort: 8085,\n prodUrl: \"https://mail.agent-native.com\",\n defaultMode: \"prod\",\n core: true,\n },\n {\n name: \"dispatch\",\n label: \"Dispatch\",\n hint: \"Central Slack/Telegram router with jobs, memory, approvals, and A2A delegation\",\n icon: \"MessageCircle\",\n color: \"#14B8A6\",\n colorRgb: \"20 184 166\",\n devPort: 8092,\n prodUrl: \"https://dispatch.agent-native.com\",\n defaultMode: \"prod\",\n core: true,\n },\n {\n name: \"forms\",\n label: \"Forms\",\n hint: \"Agent-native form builder — create, edit, and manage forms\",\n icon: \"ClipboardList\",\n color: \"#06B6D4\",\n colorRgb: \"6 182 212\",\n devPort: 8084,\n prodUrl: \"https://forms.agent-native.com\",\n defaultMode: \"prod\",\n core: true,\n },\n {\n name: \"starter\",\n label: \"Starter\",\n hint: \"Minimal scaffold with the agent chat and core architecture wired up\",\n icon: \"Code\",\n color: \"#71717A\",\n colorRgb: \"113 113 122\",\n devPort: 8089,\n defaultMode: \"prod\",\n alwaysAvailable: true,\n core: true,\n hidden: true,\n },\n {\n name: \"clips\",\n label: \"Clips\",\n hint: \"Screen recording, meeting notes, and voice dictation — all with AI\",\n icon: \"ScreenShare\",\n color: \"#0EA5E9\",\n colorRgb: \"14 165 233\",\n devPort: 8094,\n prodUrl: \"https://clips.agent-native.com\",\n defaultMode: \"prod\",\n core: true,\n },\n {\n name: \"brain\",\n label: \"Brain\",\n hint: \"Cited company memory from Slack, meetings, transcripts, and decisions\",\n icon: \"Brain\",\n color: \"#8B5CF6\",\n colorRgb: \"139 92 246\",\n devPort: 8102,\n prodUrl: \"https://brain.agent-native.com\",\n defaultMode: \"prod\",\n defaultAgent: true,\n core: true,\n },\n {\n name: \"design\",\n label: \"Design\",\n hint: \"Agent-native design tool — create and edit visual designs with agent assistance\",\n icon: \"Brush\",\n color: \"#F472B6\",\n colorRgb: \"244 114 182\",\n devPort: 8099,\n prodUrl: \"https://design.agent-native.com\",\n defaultMode: \"prod\",\n requiredPackages: [\"pinpoint\", \"embedding\"],\n core: true,\n },\n {\n name: \"assets\",\n label: \"Assets\",\n hint: \"Digital asset manager — upload, organize, search, and generate on-brand images and videos\",\n icon: \"Photo\",\n color: \"#0F766E\",\n colorRgb: \"15 118 110\",\n devPort: 8100,\n prodUrl: \"https://assets.agent-native.com\",\n defaultMode: \"prod\",\n defaultAgent: true,\n core: true,\n },\n {\n name: \"macros\",\n label: \"Macros\",\n hint: \"Internal template — not shown in pickers\",\n icon: \"Code\",\n color: \"#71717A\",\n colorRgb: \"113 113 122\",\n devPort: 8093,\n prodUrl: \"https://macros.agent-native.com\",\n hidden: true,\n defaultMode: \"dev\",\n },\n];\n\n/** Return templates visible in user-facing pickers (excludes hidden). */\nexport function visibleTemplates(): TemplateMeta[] {\n return TEMPLATES.filter((t) => !t.hidden);\n}\n\n/** Return core templates — the featured set shown in CLI pickers by default. */\nexport function coreTemplates(): TemplateMeta[] {\n return TEMPLATES.filter((t) => t.core);\n}\n\n/** Lookup by name. Returns undefined for unknown names. */\nexport function getTemplate(name: string): TemplateMeta | undefined {\n // Tolerate legacy / renamed aliases.\n if (name === \"video\") name = \"videos\";\n if (name === \"image\" || name === \"images\" || name === \"asset\") {\n name = \"assets\";\n }\n if (name === \"contracts\" || name === \"visual-plans\") name = \"plan\";\n return TEMPLATES.find((t) => t.name === name);\n}\n\n/** Names of all templates (including hidden) for validation. */\nexport function allTemplateNames(): string[] {\n return TEMPLATES.map((t) => t.name);\n}\n"]}
1
+ {"version":3,"file":"templates-meta.js","sourceRoot":"","sources":["../../src/cli/templates-meta.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * First-party template metadata used by the `agent-native` CLI.\n *\n * This file is intentionally inlined here (rather than imported from a\n * separate workspace package) so that the published `@agent-native/core`\n * has no `workspace:*` runtime dependencies. Without this inlining, `npx\n * @agent-native/core create ...` fails on a fresh machine with:\n *\n * npm error code EUNSUPPORTEDPROTOCOL\n * npm error Unsupported URL Type \"workspace:\": workspace:*\n *\n * Keep this list in sync with `packages/shared-app-config/templates.ts`,\n * which serves the same metadata to the desktop / mobile / frame packages\n * that always run inside the workspace. Duplication is intentional: the\n * CLI must remain installable outside the monorepo.\n */\n\nexport interface TemplateMeta {\n /** Directory name under templates/ and package name */\n name: string;\n /** Display name in pickers */\n label: string;\n /** One-line description shown in the picker */\n hint: string;\n /** Longer description (optional) */\n description?: string;\n /** Tabler icon name used in the desktop sidebar */\n icon: string;\n /** Hex accent color */\n color: string;\n /** CSS-safe RGB triplet (e.g. \"59 130 246\") */\n colorRgb: string;\n /** Dev server port for desktop `pnpm dev` */\n devPort: number;\n /** Production URL when running as a first-party app on agent-native.com */\n prodUrl?: string;\n /** Default URL path when deployed in a workspace (defaults to \"/<name>\") */\n prodPath?: string;\n /** Default mode when added to desktop app */\n defaultMode?: \"dev\" | \"prod\";\n /** Hide from pickers but still scaffoldable via explicit --template */\n hidden?: boolean;\n /** Include as a built-in connected A2A agent even when hidden from pickers */\n defaultAgent?: boolean;\n /** Always scaffold without prompting (e.g. starter as fallback) */\n alwaysAvailable?: boolean;\n /** Internal workspace packages this template depends on (e.g. \"scheduling\") */\n requiredPackages?: string[];\n /** Core app — featured in the CLI picker, homepage, and docs gallery */\n core?: boolean;\n}\n\nexport const TEMPLATES: TemplateMeta[] = [\n {\n name: \"calendar\",\n label: \"Calendar\",\n hint: \"Agent-native Google Calendar — manage events, sync, and public booking\",\n icon: \"CalendarDays\",\n color: \"#00B5FF\",\n colorRgb: \"0 181 255\",\n devPort: 8082,\n prodUrl: \"https://calendar.agent-native.com\",\n defaultMode: \"prod\",\n requiredPackages: [\"scheduling\"],\n core: true,\n },\n {\n name: \"content\",\n label: \"Content\",\n hint: \"Agent-native Notion/Google Docs — write and organize with agent assistance\",\n icon: \"FileText\",\n color: \"#10B981\",\n colorRgb: \"16 185 129\",\n devPort: 8083,\n prodUrl: \"https://content.agent-native.com\",\n defaultMode: \"prod\",\n core: true,\n },\n {\n name: \"plan\",\n label: \"Plan\",\n hint: \"Structured visual plans and PR recaps with diagrams, wireframes, prototypes, annotations, and sharing\",\n icon: \"FileText\",\n color: \"#52525B\",\n colorRgb: \"82 82 91\",\n devPort: 8105,\n prodUrl: \"https://plan.agent-native.com\",\n defaultMode: \"prod\",\n core: true,\n },\n {\n name: \"slides\",\n label: \"Slides\",\n hint: \"Agent-native Google Slides — generate and edit React presentations\",\n icon: \"GalleryHorizontal\",\n color: \"#EC4899\",\n colorRgb: \"236 72 153\",\n devPort: 8086,\n prodUrl: \"https://slides.agent-native.com\",\n defaultMode: \"prod\",\n requiredPackages: [\"pinpoint\"],\n core: true,\n },\n {\n name: \"videos\",\n label: \"Video\",\n hint: \"Agent-native video editing with Remotion\",\n icon: \"Video\",\n color: \"#EF4444\",\n colorRgb: \"239 68 68\",\n devPort: 8087,\n prodUrl: \"https://videos.agent-native.com\",\n defaultMode: \"prod\",\n requiredPackages: [\"pinpoint\"],\n },\n {\n name: \"analytics\",\n label: \"Analytics\",\n hint: \"Agent-native Amplitude/Mixpanel — connect data sources, prompt for charts\",\n icon: \"BarChart2\",\n color: \"#F59E0B\",\n colorRgb: \"245 158 11\",\n devPort: 8088,\n prodUrl: \"https://analytics.agent-native.com\",\n defaultMode: \"prod\",\n core: true,\n },\n {\n name: \"mail\",\n label: \"Mail\",\n hint: \"Agent-native Superhuman — email client with keyboard shortcuts and AI triage\",\n icon: \"Mail\",\n color: \"#3B82F6\",\n colorRgb: \"59 130 246\",\n devPort: 8085,\n prodUrl: \"https://mail.agent-native.com\",\n defaultMode: \"prod\",\n core: true,\n },\n {\n name: \"dispatch\",\n label: \"Dispatch\",\n hint: \"Central Slack/Telegram router with jobs, memory, approvals, and A2A delegation\",\n icon: \"MessageCircle\",\n color: \"#14B8A6\",\n colorRgb: \"20 184 166\",\n devPort: 8092,\n prodUrl: \"https://dispatch.agent-native.com\",\n defaultMode: \"prod\",\n core: true,\n },\n {\n name: \"forms\",\n label: \"Forms\",\n hint: \"Agent-native form builder — create, edit, and manage forms\",\n icon: \"ClipboardList\",\n color: \"#06B6D4\",\n colorRgb: \"6 182 212\",\n devPort: 8084,\n prodUrl: \"https://forms.agent-native.com\",\n defaultMode: \"prod\",\n core: true,\n },\n {\n name: \"starter\",\n label: \"Starter\",\n hint: \"Minimal scaffold with the agent chat and core architecture wired up\",\n icon: \"Code\",\n color: \"#71717A\",\n colorRgb: \"113 113 122\",\n devPort: 8089,\n prodUrl: \"https://starter.agent-native.com\",\n defaultMode: \"prod\",\n alwaysAvailable: true,\n core: true,\n hidden: true,\n },\n {\n name: \"clips\",\n label: \"Clips\",\n hint: \"Screen recording, meeting notes, and voice dictation — all with AI\",\n icon: \"ScreenShare\",\n color: \"#0EA5E9\",\n colorRgb: \"14 165 233\",\n devPort: 8094,\n prodUrl: \"https://clips.agent-native.com\",\n defaultMode: \"prod\",\n core: true,\n },\n {\n name: \"brain\",\n label: \"Brain\",\n hint: \"Cited company knowledge from Slack, meetings, transcripts, and decisions\",\n icon: \"Brain\",\n color: \"#8B5CF6\",\n colorRgb: \"139 92 246\",\n devPort: 8102,\n prodUrl: \"https://brain.agent-native.com\",\n defaultMode: \"prod\",\n defaultAgent: true,\n core: true,\n },\n {\n name: \"design\",\n label: \"Design\",\n hint: \"Agent-native design tool — create and edit visual designs with agent assistance\",\n icon: \"Brush\",\n color: \"#F472B6\",\n colorRgb: \"244 114 182\",\n devPort: 8099,\n prodUrl: \"https://design.agent-native.com\",\n defaultMode: \"prod\",\n requiredPackages: [\"pinpoint\", \"embedding\"],\n core: true,\n },\n {\n name: \"assets\",\n label: \"Assets\",\n hint: \"Digital asset manager — upload, organize, search, and generate on-brand images and videos\",\n icon: \"Photo\",\n color: \"#0F766E\",\n colorRgb: \"15 118 110\",\n devPort: 8100,\n prodUrl: \"https://assets.agent-native.com\",\n defaultMode: \"prod\",\n defaultAgent: true,\n core: true,\n },\n {\n name: \"macros\",\n label: \"Macros\",\n hint: \"Internal template — not shown in pickers\",\n icon: \"Code\",\n color: \"#71717A\",\n colorRgb: \"113 113 122\",\n devPort: 8093,\n prodUrl: \"https://macros.agent-native.com\",\n hidden: true,\n defaultMode: \"dev\",\n },\n];\n\n/** Return templates visible in user-facing pickers (excludes hidden). */\nexport function visibleTemplates(): TemplateMeta[] {\n return TEMPLATES.filter((t) => !t.hidden);\n}\n\n/** Return core templates — the featured set shown in CLI pickers by default. */\nexport function coreTemplates(): TemplateMeta[] {\n return TEMPLATES.filter((t) => t.core);\n}\n\n/** Lookup by name. Returns undefined for unknown names. */\nexport function getTemplate(name: string): TemplateMeta | undefined {\n // Tolerate legacy / renamed aliases.\n if (name === \"video\") name = \"videos\";\n if (name === \"image\" || name === \"images\" || name === \"asset\") {\n name = \"assets\";\n }\n if (name === \"contracts\" || name === \"visual-plans\") name = \"plan\";\n return TEMPLATES.find((t) => t.name === name);\n}\n\n/** Names of all templates (including hidden) for validation. */\nexport function allTemplateNames(): string[] {\n return TEMPLATES.map((t) => t.name);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"AnnotatedCodeBlock.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/AnnotatedCodeBlock.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,KAAK,EAEV,iBAAiB,EAClB,MAAM,4BAA4B,CAAC;AAmBpC;;;;;;;;;;;;;;;;;;GAkBG;AAIH,iBAAS,iBAAiB,CAAC,EACzB,IAAI,EACJ,OAAO,EACP,KAAK,EACL,OAAO,EACP,GAAG,GACJ,EAAE,cAAc,CAAC,iBAAiB,CAAC,2CAuKnC;AAOD,iBAAS,iBAAiB,CAAC,EACzB,IAAI,EACJ,QAAQ,EACR,QAAQ,GACT,EAAE,cAAc,CAAC,iBAAiB,CAAC,2CAiJnC;AAED,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,CAAC"}
1
+ {"version":3,"file":"AnnotatedCodeBlock.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/AnnotatedCodeBlock.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,KAAK,EAEV,iBAAiB,EAClB,MAAM,4BAA4B,CAAC;AAmBpC;;;;;;;;;;;;;;;;;;GAkBG;AAIH,iBAAS,iBAAiB,CAAC,EACzB,IAAI,EACJ,OAAO,EACP,KAAK,EACL,OAAO,EACP,GAAG,GACJ,EAAE,cAAc,CAAC,iBAAiB,CAAC,2CA6MnC;AAOD,iBAAS,iBAAiB,CAAC,EACzB,IAAI,EACJ,QAAQ,EACR,QAAQ,GACT,EAAE,cAAc,CAAC,iBAAiB,CAAC,2CAiJnC;AAED,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,CAAC"}
@@ -63,27 +63,55 @@ function AnnotatedCodeRead({ data, blockId, title, summary, ctx, }) {
63
63
  const isAnnotated = !!markers?.length;
64
64
  const isActive = activeIndex != null &&
65
65
  !!markers?.some((m) => m.index === activeIndex);
66
- return (_jsxs("div", { ref: (node) => setLineRef(lineNo, node), "data-code-line": lineNo, "data-annot-row": isAnnotated ? markers?.[0].index : undefined, className: cn("flex w-full", isActive
66
+ const buildAnchorForRow = (el) => {
67
+ if (!markers)
68
+ return null;
69
+ const primaryMarker = markers[0];
70
+ const anchorLine = primaryMarker.range?.start ?? lineNo;
71
+ const anchorRow = lineRefs.current.get(anchorLine) ?? el;
72
+ return anchorFromElements(codeRef.current, anchorRow);
73
+ };
74
+ return (_jsxs("div", { ref: (node) => setLineRef(lineNo, node), "data-code-line": lineNo, "data-annot-row": isAnnotated ? markers?.[0].index : undefined,
75
+ // tabIndex makes annotated rows keyboard-focusable so screen
76
+ // readers and keyboard users can access notes without a mouse.
77
+ tabIndex: isAnnotated ? 0 : undefined, role: isAnnotated ? "button" : undefined, "aria-expanded": isAnnotated ? isActive : undefined, "aria-label": isAnnotated ? `Line ${lineNo} annotation` : undefined, className: cn("flex w-full", isAnnotated && "cursor-pointer", isActive
67
78
  ? "bg-amber-400/20 dark:bg-amber-300/15"
68
79
  : isAnnotated
69
80
  ? "bg-amber-400/[0.07] dark:bg-amber-300/[0.07]"
70
81
  : null), onMouseEnter: isAnnotated && markers
71
82
  ? (event) => {
72
- const primaryMarker = markers[0];
73
- const anchorLine = primaryMarker.range?.start ?? lineNo;
74
- const anchorRow = lineRefs.current.get(anchorLine) ??
75
- event.currentTarget;
76
- const anchor = anchorFromElements(codeRef.current, anchorRow);
83
+ const anchor = buildAnchorForRow(event.currentTarget);
77
84
  if (anchor)
78
- hover.open(primaryMarker.index, anchor);
85
+ hover.open(markers[0].index, anchor);
79
86
  }
80
- : undefined, onMouseLeave: isAnnotated ? () => hover.scheduleClose() : undefined, children: [_jsx("span", { "aria-hidden": true, className: cn("w-[3px] shrink-0 self-stretch", isAnnotated
87
+ : undefined, onMouseLeave: isAnnotated ? () => hover.scheduleClose() : undefined, onClick: isAnnotated && markers
88
+ ? (event) => {
89
+ const anchor = buildAnchorForRow(event.currentTarget);
90
+ if (anchor)
91
+ hover.open(markers[0].index, anchor);
92
+ }
93
+ : undefined, onKeyDown: isAnnotated && markers
94
+ ? (event) => {
95
+ if (event.key !== "Enter" && event.key !== " ")
96
+ return;
97
+ event.preventDefault();
98
+ const anchor = buildAnchorForRow(event.currentTarget);
99
+ if (anchor)
100
+ hover.open(markers[0].index, anchor);
101
+ }
102
+ : undefined, onFocus: isAnnotated && markers
103
+ ? (event) => {
104
+ const anchor = buildAnchorForRow(event.currentTarget);
105
+ if (anchor)
106
+ hover.open(markers[0].index, anchor);
107
+ }
108
+ : undefined, onBlur: isAnnotated ? () => hover.scheduleClose() : undefined, children: [_jsx("span", { "aria-hidden": true, className: cn("w-[3px] shrink-0 self-stretch", isAnnotated
81
109
  ? isActive
82
110
  ? "bg-amber-500 dark:bg-amber-400"
83
111
  : "bg-amber-400/45 dark:bg-amber-300/35"
84
112
  : null) }), _jsx("span", { className: "w-11 shrink-0 select-none px-3 text-right text-[11px] tabular-nums text-plan-muted/60", children: lineNo }), _jsx("span", { className: "flex-1 whitespace-pre pr-4 text-plan-code-text", children: highlightedLines[idx] })] }, lineNo));
85
113
  }) }) })] }));
86
- return (_jsxs("section", { className: "plan-block relative", "data-block-id": blockId, children: [title && _jsx("div", { className: "plan-block-label", children: title }), codeSurface, hasAnnotations && _jsx(AnnotationHiddenStack, { items: resolved, ctx: ctx }), hasAnnotations && activeItem && hover.anchor && (_jsx(AnnotationHoverCard, { item: activeItem, anchor: hover.anchor, ctx: ctx, onMouseEnter: hover.cancelClose, onMouseLeave: hover.scheduleClose })), summary && _jsx("p", { className: "mt-5 text-plan-muted", children: summary })] }));
114
+ return (_jsxs("section", { className: "plan-block relative", "data-block-id": blockId, children: [title && _jsx("div", { className: "plan-block-label", children: title }), codeSurface, hasAnnotations && _jsx(AnnotationHiddenStack, { items: resolved, ctx: ctx }), hasAnnotations && activeItem && hover.anchor && (_jsx(AnnotationHoverCard, { item: activeItem, anchor: hover.anchor, ctx: ctx, onMouseEnter: hover.cancelClose, onMouseLeave: hover.scheduleClose, onClose: hover.close })), summary && _jsx("p", { className: "mt-5 text-plan-muted", children: summary })] }));
87
115
  }
88
116
  /* ── Edit (panel) ──────────────────────────────────────────────────────────── */
89
117
  const codeAreaClass = "min-h-[160px] font-mono [font-size:var(--plan-code-size)] leading-5";
@@ -1 +1 @@
1
- {"version":3,"file":"AnnotatedCodeBlock.js","sourceRoot":"","sources":["../../../../src/client/blocks/library/AnnotatedCodeBlock.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useMemo, useRef } from \"react\";\nimport { IconCode, IconPlus, IconTrash } from \"@tabler/icons-react\";\nimport { cn } from \"../../utils.js\";\nimport type { BlockEditProps, BlockReadProps } from \"../types.js\";\nimport type {\n AnnotatedCodeAnnotation,\n AnnotatedCodeData,\n} from \"./annotated-code.config.js\";\nimport {\n highlightCode,\n inferLanguageFromFilename,\n normalizeCodeLanguage,\n} from \"./code-highlight.js\";\nimport {\n AnnotationHiddenStack,\n AnnotationHoverCard,\n anchorFromElements,\n buildLineMarkerMap,\n hasRailAnnotations,\n resolveAnnotations,\n useAnnotationHover,\n type ResolvedAnnotation,\n} from \"./annotation-rail.js\";\nimport { CodeFilenameLabel } from \"./code-filename-label.js\";\nimport { DevInput, DevLabel, DevTextarea } from \"./dev-doc-ui.js\";\n\n/**\n * \"Explain this code\" walkthrough block: a standard syntax-highlighted code\n * surface on the left with line-anchored annotation cards on the right (the\n * Stripe-docs / Sourcegraph layout). Each annotated line range gets a subtle\n * highlight band + an accent rail down the gutter; its card shows the `lines`\n * range, optional `label`, and the always-visible markdown `note` (via\n * `ctx.renderMarkdown`). Hovering a card highlights its lines and vice-versa.\n *\n * Syntax highlighting reuses the shared `highlightCode` lowlight helper (the same\n * colorful palette as the `code-tabs` block) per line, so it matches the app's\n * standard code styling and supports per-line bands without an async loader. The\n * surface uses the plan `--plan-code*`/`--plan-*` tokens and Tailwind `dark:`\n * pairs, so it reads correctly in BOTH light and dark mode. Code lines render as\n * `<span>`s (never one `<pre>` per line) so they don't pick up document\n * code/pre chrome. Lives in core so any app can register the dev-doc block.\n *\n * Editing is panel-driven (config-style, like the diff/HTML blocks): a monospace\n * code Textarea, filename/language Inputs, and add/remove-able annotation rows.\n */\n\n/* ── Read ──────────────────────────────────────────────────────────────────── */\n\nfunction AnnotatedCodeRead({\n data,\n blockId,\n title,\n summary,\n ctx,\n}: BlockReadProps<AnnotatedCodeData>) {\n // On-hover popover (anchored to the right of the code) replaces the old\n // persistent rail: nothing is visible when idle. `codeRef` measures the code\n // block's right edge; `hover` carries the active index + captured geometry.\n const hover = useAnnotationHover();\n const { activeIndex } = hover;\n const codeRef = useRef<HTMLDivElement | null>(null);\n const lineRefs = useRef(new Map<number, HTMLDivElement>());\n\n const setLineRef = (lineNo: number, node: HTMLDivElement | null) => {\n if (node) lineRefs.current.set(lineNo, node);\n else lineRefs.current.delete(lineNo);\n };\n\n const lines = useMemo(\n () => data.code.replace(/\\n$/, \"\").split(\"\\n\"),\n [data.code],\n );\n const lineCount = lines.length;\n\n const language = useMemo(\n () =>\n normalizeCodeLanguage(data.language) ??\n inferLanguageFromFilename(data.filename),\n [data.language, data.filename],\n );\n\n // Highlight each line once; empty lines keep their height with a NBSP.\n const highlightedLines = useMemo(\n () =>\n lines.map((text) => (text.length ? highlightCode(text, language) : \" \")),\n [lines, language],\n );\n\n const resolved = useMemo(\n () => resolveAnnotations(data.annotations, () => lineCount),\n [data.annotations, lineCount],\n );\n\n // line number (1-based) → resolved annotations covering it.\n const lineMarkers = useMemo(() => buildLineMarkerMap(resolved), [resolved]);\n\n const hasAnnotations = hasRailAnnotations(resolved);\n const langChip = data.language?.trim();\n const hasFilename = Boolean(data.filename?.trim());\n const showLangChip = Boolean(langChip && !hasFilename);\n\n // The resolved annotation whose card is currently shown on hover.\n const activeItem =\n useMemo<ResolvedAnnotation<AnnotatedCodeAnnotation> | null>(\n () =>\n activeIndex == null\n ? null\n : (resolved.find((item) => item.index === activeIndex) ?? null),\n [activeIndex, resolved],\n );\n\n const codeSurface = (\n <div\n ref={codeRef}\n className=\"overflow-hidden rounded-xl border border-plan-line bg-plan-code\"\n >\n {(hasFilename || showLangChip) && (\n <div className=\"flex items-center gap-2 border-b border-plan-line bg-plan-block/50 px-3.5 py-2\">\n <IconCode className=\"size-3.5 shrink-0 text-plan-muted\" />\n <CodeFilenameLabel\n filename={data.filename}\n className=\"text-[13px] font-medium\"\n directoryClassName=\"text-plan-muted\"\n basenameClassName=\"text-plan-code-text\"\n />\n {showLangChip && (\n <span className=\"shrink-0 rounded border border-plan-line px-1.5 py-0.5 font-mono text-[10px] uppercase tracking-wide text-plan-muted\">\n {langChip}\n </span>\n )}\n </div>\n )}\n <div className=\"overflow-x-auto py-1.5\" data-code-surface>\n <div className=\"min-w-full font-mono [font-size:var(--plan-doc-code-size)] leading-[22px]\">\n {lines.map((_text, idx) => {\n const lineNo = idx + 1;\n const markers = lineMarkers.get(lineNo);\n const isAnnotated = !!markers?.length;\n const isActive =\n activeIndex != null &&\n !!markers?.some((m) => m.index === activeIndex);\n return (\n <div\n key={lineNo}\n ref={(node) => setLineRef(lineNo, node)}\n data-code-line={lineNo}\n data-annot-row={isAnnotated ? markers?.[0].index : undefined}\n className={cn(\n \"flex w-full\",\n isActive\n ? \"bg-amber-400/20 dark:bg-amber-300/15\"\n : isAnnotated\n ? \"bg-amber-400/[0.07] dark:bg-amber-300/[0.07]\"\n : null,\n )}\n onMouseEnter={\n isAnnotated && markers\n ? (event) => {\n const primaryMarker = markers[0];\n const anchorLine = primaryMarker.range?.start ?? lineNo;\n const anchorRow =\n lineRefs.current.get(anchorLine) ??\n event.currentTarget;\n const anchor = anchorFromElements(\n codeRef.current,\n anchorRow,\n );\n if (anchor) hover.open(primaryMarker.index, anchor);\n }\n : undefined\n }\n onMouseLeave={\n isAnnotated ? () => hover.scheduleClose() : undefined\n }\n >\n {/* Accent rail: amber on annotated lines, brighter when active. */}\n <span\n aria-hidden\n className={cn(\n \"w-[3px] shrink-0 self-stretch\",\n isAnnotated\n ? isActive\n ? \"bg-amber-500 dark:bg-amber-400\"\n : \"bg-amber-400/45 dark:bg-amber-300/35\"\n : null,\n )}\n />\n <span className=\"w-11 shrink-0 select-none px-3 text-right text-[11px] tabular-nums text-plan-muted/60\">\n {lineNo}\n </span>\n <span className=\"flex-1 whitespace-pre pr-4 text-plan-code-text\">\n {highlightedLines[idx]}\n </span>\n </div>\n );\n })}\n </div>\n </div>\n </div>\n );\n\n return (\n <section className=\"plan-block relative\" data-block-id={blockId}>\n {title && <div className=\"plan-block-label\">{title}</div>}\n {/* The code keeps its full width — no persistent annotation column. Notes\n live in a visually-hidden stack (a11y + tests) and surface ONE at a\n time as an on-hover popover anchored to the right of the code. */}\n {codeSurface}\n {hasAnnotations && <AnnotationHiddenStack items={resolved} ctx={ctx} />}\n {hasAnnotations && activeItem && hover.anchor && (\n <AnnotationHoverCard\n item={activeItem}\n anchor={hover.anchor}\n ctx={ctx}\n onMouseEnter={hover.cancelClose}\n onMouseLeave={hover.scheduleClose}\n />\n )}\n {summary && <p className=\"mt-5 text-plan-muted\">{summary}</p>}\n </section>\n );\n}\n\n/* ── Edit (panel) ──────────────────────────────────────────────────────────── */\n\nconst codeAreaClass =\n \"min-h-[160px] font-mono [font-size:var(--plan-code-size)] leading-5\";\n\nfunction AnnotatedCodeEdit({\n data,\n onChange,\n editable,\n}: BlockEditProps<AnnotatedCodeData>) {\n const annotations = data.annotations ?? [];\n const patch = (next: Partial<AnnotatedCodeData>) =>\n onChange({ ...data, ...next });\n\n const updateAnnotation = (\n index: number,\n next: Partial<AnnotatedCodeAnnotation>,\n ) =>\n patch({\n annotations: annotations.map((annotation, i) =>\n i === index ? { ...annotation, ...next } : annotation,\n ),\n });\n\n const removeAnnotation = (index: number) =>\n patch({ annotations: annotations.filter((_, i) => i !== index) });\n\n const addAnnotation = () => {\n if (annotations.length >= 80) return; // schema max\n patch({\n annotations: [...annotations, { lines: \"1\", label: \"\", note: \"\" }],\n });\n };\n\n return (\n <div className=\"flex flex-col gap-3\" data-plan-interactive>\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-1.5\">\n <DevLabel htmlFor=\"annotated-code-filename\" className=\"text-xs\">\n Filename\n </DevLabel>\n <DevInput\n id=\"annotated-code-filename\"\n value={data.filename ?? \"\"}\n placeholder=\"src/server/auth.ts\"\n disabled={!editable}\n onChange={(event) =>\n patch({ filename: event.target.value || undefined })\n }\n />\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <DevLabel htmlFor=\"annotated-code-language\" className=\"text-xs\">\n Language\n </DevLabel>\n <DevInput\n id=\"annotated-code-language\"\n value={data.language ?? \"\"}\n placeholder=\"ts\"\n disabled={!editable}\n onChange={(event) =>\n patch({ language: event.target.value || undefined })\n }\n />\n </div>\n </div>\n\n <div className=\"flex flex-col gap-1.5\">\n <DevLabel htmlFor=\"annotated-code-code\" className=\"text-xs\">\n Code\n </DevLabel>\n <DevTextarea\n id=\"annotated-code-code\"\n spellCheck={false}\n className={codeAreaClass}\n value={data.code}\n disabled={!editable}\n onChange={(event) => patch({ code: event.target.value })}\n />\n </div>\n\n <div className=\"flex flex-col gap-2\">\n <div className=\"flex items-center justify-between\">\n <DevLabel className=\"text-xs\">Annotations</DevLabel>\n {editable && annotations.length < 80 && (\n <button\n type=\"button\"\n data-plan-interactive\n onClick={addAnnotation}\n className=\"flex cursor-pointer items-center gap-1 rounded-md px-2 py-1 text-xs font-medium text-plan-muted transition-colors hover:bg-plan-block/60 hover:text-plan-text\"\n >\n <IconPlus className=\"size-3.5\" />\n Add annotation\n </button>\n )}\n </div>\n {annotations.length === 0 && (\n <p className=\"text-xs text-plan-muted\">\n No annotations yet. Add one to anchor a note to a line range.\n </p>\n )}\n {annotations.map((annotation, index) => (\n <div\n key={index}\n className=\"flex flex-col gap-2 rounded-md border border-plan-line bg-plan-block/30 p-2\"\n >\n <div className=\"grid gap-2 sm:grid-cols-[120px_minmax(0,1fr)_auto]\">\n <DevInput\n aria-label={`Annotation ${index + 1} lines`}\n value={annotation.lines}\n placeholder=\"3-5\"\n disabled={!editable}\n onChange={(event) =>\n updateAnnotation(index, { lines: event.target.value })\n }\n />\n <DevInput\n aria-label={`Annotation ${index + 1} label`}\n value={annotation.label ?? \"\"}\n placeholder=\"Label (optional)\"\n disabled={!editable}\n onChange={(event) =>\n updateAnnotation(index, {\n label: event.target.value || undefined,\n })\n }\n />\n {editable && (\n <button\n type=\"button\"\n data-plan-interactive\n aria-label={`Remove annotation ${index + 1}`}\n onClick={() => removeAnnotation(index)}\n className=\"flex size-9 shrink-0 cursor-pointer items-center justify-center rounded-md text-plan-muted transition-colors hover:bg-muted hover:text-foreground\"\n >\n <IconTrash className=\"size-4\" />\n </button>\n )}\n </div>\n <DevTextarea\n aria-label={`Annotation ${index + 1} note`}\n className=\"min-h-[60px] text-sm\"\n value={annotation.note}\n placeholder=\"Explain what these lines do…\"\n disabled={!editable}\n onChange={(event) =>\n updateAnnotation(index, { note: event.target.value })\n }\n />\n </div>\n ))}\n </div>\n </div>\n );\n}\n\nexport { AnnotatedCodeRead, AnnotatedCodeEdit };\n"]}
1
+ {"version":3,"file":"AnnotatedCodeBlock.js","sourceRoot":"","sources":["../../../../src/client/blocks/library/AnnotatedCodeBlock.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useMemo, useRef } from \"react\";\nimport { IconCode, IconPlus, IconTrash } from \"@tabler/icons-react\";\nimport { cn } from \"../../utils.js\";\nimport type { BlockEditProps, BlockReadProps } from \"../types.js\";\nimport type {\n AnnotatedCodeAnnotation,\n AnnotatedCodeData,\n} from \"./annotated-code.config.js\";\nimport {\n highlightCode,\n inferLanguageFromFilename,\n normalizeCodeLanguage,\n} from \"./code-highlight.js\";\nimport {\n AnnotationHiddenStack,\n AnnotationHoverCard,\n anchorFromElements,\n buildLineMarkerMap,\n hasRailAnnotations,\n resolveAnnotations,\n useAnnotationHover,\n type ResolvedAnnotation,\n} from \"./annotation-rail.js\";\nimport { CodeFilenameLabel } from \"./code-filename-label.js\";\nimport { DevInput, DevLabel, DevTextarea } from \"./dev-doc-ui.js\";\n\n/**\n * \"Explain this code\" walkthrough block: a standard syntax-highlighted code\n * surface on the left with line-anchored annotation cards on the right (the\n * Stripe-docs / Sourcegraph layout). Each annotated line range gets a subtle\n * highlight band + an accent rail down the gutter; its card shows the `lines`\n * range, optional `label`, and the always-visible markdown `note` (via\n * `ctx.renderMarkdown`). Hovering a card highlights its lines and vice-versa.\n *\n * Syntax highlighting reuses the shared `highlightCode` lowlight helper (the same\n * colorful palette as the `code-tabs` block) per line, so it matches the app's\n * standard code styling and supports per-line bands without an async loader. The\n * surface uses the plan `--plan-code*`/`--plan-*` tokens and Tailwind `dark:`\n * pairs, so it reads correctly in BOTH light and dark mode. Code lines render as\n * `<span>`s (never one `<pre>` per line) so they don't pick up document\n * code/pre chrome. Lives in core so any app can register the dev-doc block.\n *\n * Editing is panel-driven (config-style, like the diff/HTML blocks): a monospace\n * code Textarea, filename/language Inputs, and add/remove-able annotation rows.\n */\n\n/* ── Read ──────────────────────────────────────────────────────────────────── */\n\nfunction AnnotatedCodeRead({\n data,\n blockId,\n title,\n summary,\n ctx,\n}: BlockReadProps<AnnotatedCodeData>) {\n // On-hover popover (anchored to the right of the code) replaces the old\n // persistent rail: nothing is visible when idle. `codeRef` measures the code\n // block's right edge; `hover` carries the active index + captured geometry.\n const hover = useAnnotationHover();\n const { activeIndex } = hover;\n const codeRef = useRef<HTMLDivElement | null>(null);\n const lineRefs = useRef(new Map<number, HTMLDivElement>());\n\n const setLineRef = (lineNo: number, node: HTMLDivElement | null) => {\n if (node) lineRefs.current.set(lineNo, node);\n else lineRefs.current.delete(lineNo);\n };\n\n const lines = useMemo(\n () => data.code.replace(/\\n$/, \"\").split(\"\\n\"),\n [data.code],\n );\n const lineCount = lines.length;\n\n const language = useMemo(\n () =>\n normalizeCodeLanguage(data.language) ??\n inferLanguageFromFilename(data.filename),\n [data.language, data.filename],\n );\n\n // Highlight each line once; empty lines keep their height with a NBSP.\n const highlightedLines = useMemo(\n () =>\n lines.map((text) => (text.length ? highlightCode(text, language) : \" \")),\n [lines, language],\n );\n\n const resolved = useMemo(\n () => resolveAnnotations(data.annotations, () => lineCount),\n [data.annotations, lineCount],\n );\n\n // line number (1-based) → resolved annotations covering it.\n const lineMarkers = useMemo(() => buildLineMarkerMap(resolved), [resolved]);\n\n const hasAnnotations = hasRailAnnotations(resolved);\n const langChip = data.language?.trim();\n const hasFilename = Boolean(data.filename?.trim());\n const showLangChip = Boolean(langChip && !hasFilename);\n\n // The resolved annotation whose card is currently shown on hover.\n const activeItem =\n useMemo<ResolvedAnnotation<AnnotatedCodeAnnotation> | null>(\n () =>\n activeIndex == null\n ? null\n : (resolved.find((item) => item.index === activeIndex) ?? null),\n [activeIndex, resolved],\n );\n\n const codeSurface = (\n <div\n ref={codeRef}\n className=\"overflow-hidden rounded-xl border border-plan-line bg-plan-code\"\n >\n {(hasFilename || showLangChip) && (\n <div className=\"flex items-center gap-2 border-b border-plan-line bg-plan-block/50 px-3.5 py-2\">\n <IconCode className=\"size-3.5 shrink-0 text-plan-muted\" />\n <CodeFilenameLabel\n filename={data.filename}\n className=\"text-[13px] font-medium\"\n directoryClassName=\"text-plan-muted\"\n basenameClassName=\"text-plan-code-text\"\n />\n {showLangChip && (\n <span className=\"shrink-0 rounded border border-plan-line px-1.5 py-0.5 font-mono text-[10px] uppercase tracking-wide text-plan-muted\">\n {langChip}\n </span>\n )}\n </div>\n )}\n <div className=\"overflow-x-auto py-1.5\" data-code-surface>\n <div className=\"min-w-full font-mono [font-size:var(--plan-doc-code-size)] leading-[22px]\">\n {lines.map((_text, idx) => {\n const lineNo = idx + 1;\n const markers = lineMarkers.get(lineNo);\n const isAnnotated = !!markers?.length;\n const isActive =\n activeIndex != null &&\n !!markers?.some((m) => m.index === activeIndex);\n\n const buildAnchorForRow = (el: HTMLElement) => {\n if (!markers) return null;\n const primaryMarker = markers[0];\n const anchorLine = primaryMarker.range?.start ?? lineNo;\n const anchorRow = lineRefs.current.get(anchorLine) ?? el;\n return anchorFromElements(codeRef.current, anchorRow);\n };\n\n return (\n <div\n key={lineNo}\n ref={(node) => setLineRef(lineNo, node)}\n data-code-line={lineNo}\n data-annot-row={isAnnotated ? markers?.[0].index : undefined}\n // tabIndex makes annotated rows keyboard-focusable so screen\n // readers and keyboard users can access notes without a mouse.\n tabIndex={isAnnotated ? 0 : undefined}\n role={isAnnotated ? \"button\" : undefined}\n aria-expanded={isAnnotated ? isActive : undefined}\n aria-label={\n isAnnotated ? `Line ${lineNo} annotation` : undefined\n }\n className={cn(\n \"flex w-full\",\n isAnnotated && \"cursor-pointer\",\n isActive\n ? \"bg-amber-400/20 dark:bg-amber-300/15\"\n : isAnnotated\n ? \"bg-amber-400/[0.07] dark:bg-amber-300/[0.07]\"\n : null,\n )}\n onMouseEnter={\n isAnnotated && markers\n ? (event) => {\n const anchor = buildAnchorForRow(event.currentTarget);\n if (anchor) hover.open(markers[0].index, anchor);\n }\n : undefined\n }\n onMouseLeave={\n isAnnotated ? () => hover.scheduleClose() : undefined\n }\n onClick={\n isAnnotated && markers\n ? (event) => {\n const anchor = buildAnchorForRow(event.currentTarget);\n if (anchor) hover.open(markers[0].index, anchor);\n }\n : undefined\n }\n onKeyDown={\n isAnnotated && markers\n ? (event) => {\n if (event.key !== \"Enter\" && event.key !== \" \") return;\n event.preventDefault();\n const anchor = buildAnchorForRow(event.currentTarget);\n if (anchor) hover.open(markers[0].index, anchor);\n }\n : undefined\n }\n onFocus={\n isAnnotated && markers\n ? (event) => {\n const anchor = buildAnchorForRow(event.currentTarget);\n if (anchor) hover.open(markers[0].index, anchor);\n }\n : undefined\n }\n onBlur={isAnnotated ? () => hover.scheduleClose() : undefined}\n >\n {/* Accent rail: amber on annotated lines, brighter when active. */}\n <span\n aria-hidden\n className={cn(\n \"w-[3px] shrink-0 self-stretch\",\n isAnnotated\n ? isActive\n ? \"bg-amber-500 dark:bg-amber-400\"\n : \"bg-amber-400/45 dark:bg-amber-300/35\"\n : null,\n )}\n />\n <span className=\"w-11 shrink-0 select-none px-3 text-right text-[11px] tabular-nums text-plan-muted/60\">\n {lineNo}\n </span>\n <span className=\"flex-1 whitespace-pre pr-4 text-plan-code-text\">\n {highlightedLines[idx]}\n </span>\n </div>\n );\n })}\n </div>\n </div>\n </div>\n );\n\n return (\n <section className=\"plan-block relative\" data-block-id={blockId}>\n {title && <div className=\"plan-block-label\">{title}</div>}\n {/* The code keeps its full width — no persistent annotation column. Notes\n live in a visually-hidden stack (a11y + tests) and surface ONE at a\n time as an on-hover popover anchored to the right of the code. */}\n {codeSurface}\n {hasAnnotations && <AnnotationHiddenStack items={resolved} ctx={ctx} />}\n {hasAnnotations && activeItem && hover.anchor && (\n <AnnotationHoverCard\n item={activeItem}\n anchor={hover.anchor}\n ctx={ctx}\n onMouseEnter={hover.cancelClose}\n onMouseLeave={hover.scheduleClose}\n onClose={hover.close}\n />\n )}\n {summary && <p className=\"mt-5 text-plan-muted\">{summary}</p>}\n </section>\n );\n}\n\n/* ── Edit (panel) ──────────────────────────────────────────────────────────── */\n\nconst codeAreaClass =\n \"min-h-[160px] font-mono [font-size:var(--plan-code-size)] leading-5\";\n\nfunction AnnotatedCodeEdit({\n data,\n onChange,\n editable,\n}: BlockEditProps<AnnotatedCodeData>) {\n const annotations = data.annotations ?? [];\n const patch = (next: Partial<AnnotatedCodeData>) =>\n onChange({ ...data, ...next });\n\n const updateAnnotation = (\n index: number,\n next: Partial<AnnotatedCodeAnnotation>,\n ) =>\n patch({\n annotations: annotations.map((annotation, i) =>\n i === index ? { ...annotation, ...next } : annotation,\n ),\n });\n\n const removeAnnotation = (index: number) =>\n patch({ annotations: annotations.filter((_, i) => i !== index) });\n\n const addAnnotation = () => {\n if (annotations.length >= 80) return; // schema max\n patch({\n annotations: [...annotations, { lines: \"1\", label: \"\", note: \"\" }],\n });\n };\n\n return (\n <div className=\"flex flex-col gap-3\" data-plan-interactive>\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-1.5\">\n <DevLabel htmlFor=\"annotated-code-filename\" className=\"text-xs\">\n Filename\n </DevLabel>\n <DevInput\n id=\"annotated-code-filename\"\n value={data.filename ?? \"\"}\n placeholder=\"src/server/auth.ts\"\n disabled={!editable}\n onChange={(event) =>\n patch({ filename: event.target.value || undefined })\n }\n />\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <DevLabel htmlFor=\"annotated-code-language\" className=\"text-xs\">\n Language\n </DevLabel>\n <DevInput\n id=\"annotated-code-language\"\n value={data.language ?? \"\"}\n placeholder=\"ts\"\n disabled={!editable}\n onChange={(event) =>\n patch({ language: event.target.value || undefined })\n }\n />\n </div>\n </div>\n\n <div className=\"flex flex-col gap-1.5\">\n <DevLabel htmlFor=\"annotated-code-code\" className=\"text-xs\">\n Code\n </DevLabel>\n <DevTextarea\n id=\"annotated-code-code\"\n spellCheck={false}\n className={codeAreaClass}\n value={data.code}\n disabled={!editable}\n onChange={(event) => patch({ code: event.target.value })}\n />\n </div>\n\n <div className=\"flex flex-col gap-2\">\n <div className=\"flex items-center justify-between\">\n <DevLabel className=\"text-xs\">Annotations</DevLabel>\n {editable && annotations.length < 80 && (\n <button\n type=\"button\"\n data-plan-interactive\n onClick={addAnnotation}\n className=\"flex cursor-pointer items-center gap-1 rounded-md px-2 py-1 text-xs font-medium text-plan-muted transition-colors hover:bg-plan-block/60 hover:text-plan-text\"\n >\n <IconPlus className=\"size-3.5\" />\n Add annotation\n </button>\n )}\n </div>\n {annotations.length === 0 && (\n <p className=\"text-xs text-plan-muted\">\n No annotations yet. Add one to anchor a note to a line range.\n </p>\n )}\n {annotations.map((annotation, index) => (\n <div\n key={index}\n className=\"flex flex-col gap-2 rounded-md border border-plan-line bg-plan-block/30 p-2\"\n >\n <div className=\"grid gap-2 sm:grid-cols-[120px_minmax(0,1fr)_auto]\">\n <DevInput\n aria-label={`Annotation ${index + 1} lines`}\n value={annotation.lines}\n placeholder=\"3-5\"\n disabled={!editable}\n onChange={(event) =>\n updateAnnotation(index, { lines: event.target.value })\n }\n />\n <DevInput\n aria-label={`Annotation ${index + 1} label`}\n value={annotation.label ?? \"\"}\n placeholder=\"Label (optional)\"\n disabled={!editable}\n onChange={(event) =>\n updateAnnotation(index, {\n label: event.target.value || undefined,\n })\n }\n />\n {editable && (\n <button\n type=\"button\"\n data-plan-interactive\n aria-label={`Remove annotation ${index + 1}`}\n onClick={() => removeAnnotation(index)}\n className=\"flex size-9 shrink-0 cursor-pointer items-center justify-center rounded-md text-plan-muted transition-colors hover:bg-muted hover:text-foreground\"\n >\n <IconTrash className=\"size-4\" />\n </button>\n )}\n </div>\n <DevTextarea\n aria-label={`Annotation ${index + 1} note`}\n className=\"min-h-[60px] text-sm\"\n value={annotation.note}\n placeholder=\"Explain what these lines do…\"\n disabled={!editable}\n onChange={(event) =>\n updateAnnotation(index, { note: event.target.value })\n }\n />\n </div>\n ))}\n </div>\n </div>\n );\n}\n\nexport { AnnotatedCodeRead, AnnotatedCodeEdit };\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"DiffBlock.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/DiffBlock.tsx"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,KAAK,EAAkB,QAAQ,EAAY,MAAM,kBAAkB,CAAC;AAe3E;;;;;;;;;;;;;;;GAeG;AAIH,UAAU,MAAM;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAqBD;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAsEjE;AAoeD,iBAAS,QAAQ,CAAC,EAChB,IAAI,EACJ,OAAO,EACP,KAAK,EACL,OAAO,EACP,GAAG,GACJ,EAAE,cAAc,CAAC,QAAQ,CAAC,2CAoS1B;AAkcD,iBAAS,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,cAAc,CAAC,QAAQ,CAAC,2CA2LvE;AAED,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC"}
1
+ {"version":3,"file":"DiffBlock.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/DiffBlock.tsx"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,KAAK,EAAkB,QAAQ,EAAY,MAAM,kBAAkB,CAAC;AAe3E;;;;;;;;;;;;;;;GAeG;AAIH,UAAU,MAAM;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAqBD;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAsEjE;AAoeD,iBAAS,QAAQ,CAAC,EAChB,IAAI,EACJ,OAAO,EACP,KAAK,EACL,OAAO,EACP,GAAG,GACJ,EAAE,cAAc,CAAC,QAAQ,CAAC,2CAkT1B;AAsfD,iBAAS,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,cAAc,CAAC,QAAQ,CAAC,2CA2LvE;AAED,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC"}
@@ -548,6 +548,12 @@ function DiffRead({ data, blockId, title, summary, ctx, }) {
548
548
  hover.open(index, anchor);
549
549
  }, [hover]);
550
550
  const onRowLeave = useCallback(() => hover.scheduleClose(), [hover]);
551
+ const onRowClick = useCallback((index, rowEl) => {
552
+ const startRow = codeRef.current?.querySelector(`[data-annot-row="${index}"]`) ?? rowEl;
553
+ const anchor = anchorFromElements(codeRef.current, startRow);
554
+ if (anchor)
555
+ hover.open(index, anchor);
556
+ }, [hover]);
551
557
  // Side-scoped line → markers maps so a row only lights from its own side.
552
558
  const beforeMarkers = useMemo(() => buildLineMarkerMap(resolved.filter((r) => annotationSide(r.annotation) === "before")), [resolved]);
553
559
  const afterMarkers = useMemo(() => buildLineMarkerMap(resolved.filter((r) => annotationSide(r.annotation) !== "before")), [resolved]);
@@ -610,10 +616,10 @@ function DiffRead({ data, blockId, title, summary, ctx, }) {
610
616
  // The bordered code box. It always spans its full width — annotations surface
611
617
  // as an on-hover popover anchored to this box's right edge, never as a column.
612
618
  // `codeRef` measures that right edge for the popover's placement.
613
- const diffBox = (_jsxs("div", { ref: codeRef, className: "overflow-hidden rounded-md border border-border bg-background", children: [_jsxs("div", { className: "flex min-h-10 flex-wrap items-center gap-2 border-b border-border bg-muted/60 px-3 py-1.5", children: [_jsx(IconFileDiff, { className: "size-4 shrink-0 text-muted-foreground" }), _jsxs("span", { className: "flex min-w-0 flex-1 items-baseline gap-1.5 font-mono", title: data.filename || undefined, children: [_jsx("span", { className: "min-w-0 max-w-[16rem] truncate text-[13px] font-semibold leading-5 text-foreground", children: fileParts.basename }), fileParts.directory && (_jsx("span", { className: "min-w-0 flex-1 truncate text-[11px] leading-5 text-muted-foreground/70", children: fileParts.directory }))] }), _jsxs("span", { className: "ml-1 flex shrink-0 items-center gap-2 font-mono text-xs", children: [_jsxs("span", { className: "text-emerald-700 dark:text-emerald-300", children: ["+", added] }), _jsxs("span", { className: "text-destructive", children: ["\u2212", removed] })] }), canSplit && (_jsxs("div", { className: "pointer-events-none ml-auto flex shrink-0 items-center overflow-hidden rounded-md border border-border bg-background opacity-0 transition-opacity group-hover/diff-block:pointer-events-auto group-hover/diff-block:opacity-100 group-focus-within/diff-block:pointer-events-auto group-focus-within/diff-block:opacity-100", children: [_jsx(ModeButton, { active: mode === "unified", onClick: () => setMode("unified"), icon: _jsx(IconList, { className: "size-3.5" }), label: "Unified" }), _jsx(ModeButton, { active: mode === "split", onClick: () => setMode("split"), icon: _jsx(IconColumns, { className: "size-3.5" }), label: "Split" })] }))] }), unchanged ? (_jsx("div", { className: "px-4 py-6 text-center font-mono text-sm text-muted-foreground", children: "No changes" })) : effectiveMode === "split" ? (_jsx(SplitView, { rows: rows, language: language, rowLimit: rowLimit, markersForRow: markersForRow, activeIndex: activeIndex, onRowEnter: onRowEnter, onRowLeave: onRowLeave })) : (_jsx(UnifiedView, { rows: displayedRows, language: language, expanded: expanded, onToggleRun: toggleRun, markersForRow: markersForRow, anchoredRow: anchoredRow, activeIndex: activeIndex, onRowEnter: onRowEnter, onRowLeave: onRowLeave })), !unchanged && shouldLimitRows && (_jsxs("button", { type: "button", "data-plan-interactive": true, "aria-expanded": showAllRows, onClick: () => setShowAllRows((current) => !current), className: "flex h-7 w-full items-center justify-center gap-1.5 border-t border-border bg-background px-2 text-[11px] font-medium text-muted-foreground transition-colors hover:bg-muted/70 hover:text-foreground", children: [_jsx(IconChevronRight, { className: cn("size-3 shrink-0 transition-transform", showAllRows ? "-rotate-90" : "rotate-90") }), showAllRows
619
+ const diffBox = (_jsxs("div", { ref: codeRef, className: "overflow-hidden rounded-md border border-border bg-background", children: [_jsxs("div", { className: "flex min-h-10 flex-wrap items-center gap-2 border-b border-border bg-muted/60 px-3 py-1.5", children: [_jsx(IconFileDiff, { className: "size-4 shrink-0 text-muted-foreground" }), _jsxs("span", { className: "flex min-w-0 flex-1 items-baseline gap-1.5 font-mono", title: data.filename || undefined, children: [_jsx("span", { className: "min-w-0 max-w-[16rem] truncate text-[13px] font-semibold leading-5 text-foreground", children: fileParts.basename }), fileParts.directory && (_jsx("span", { className: "min-w-0 flex-1 truncate text-[11px] leading-5 text-muted-foreground/70", children: fileParts.directory }))] }), _jsxs("span", { className: "ml-1 flex shrink-0 items-center gap-2 font-mono text-xs", children: [_jsxs("span", { className: "text-emerald-700 dark:text-emerald-300", children: ["+", added] }), _jsxs("span", { className: "text-destructive", children: ["\u2212", removed] })] }), canSplit && (_jsxs("div", { className: "pointer-events-none ml-auto flex shrink-0 items-center overflow-hidden rounded-md border border-border bg-background opacity-0 transition-opacity group-hover/diff-block:pointer-events-auto group-hover/diff-block:opacity-100 group-focus-within/diff-block:pointer-events-auto group-focus-within/diff-block:opacity-100", children: [_jsx(ModeButton, { active: mode === "unified", onClick: () => setMode("unified"), icon: _jsx(IconList, { className: "size-3.5" }), label: "Unified" }), _jsx(ModeButton, { active: mode === "split", onClick: () => setMode("split"), icon: _jsx(IconColumns, { className: "size-3.5" }), label: "Split" })] }))] }), unchanged ? (_jsx("div", { className: "px-4 py-6 text-center font-mono text-sm text-muted-foreground", children: "No changes" })) : effectiveMode === "split" ? (_jsx(SplitView, { rows: rows, language: language, rowLimit: rowLimit, markersForRow: markersForRow, activeIndex: activeIndex, onRowEnter: onRowEnter, onRowLeave: onRowLeave, onRowClick: onRowClick })) : (_jsx(UnifiedView, { rows: displayedRows, language: language, expanded: expanded, onToggleRun: toggleRun, markersForRow: markersForRow, anchoredRow: anchoredRow, activeIndex: activeIndex, onRowEnter: onRowEnter, onRowLeave: onRowLeave, onRowClick: onRowClick })), !unchanged && shouldLimitRows && (_jsxs("button", { type: "button", "data-plan-interactive": true, "aria-expanded": showAllRows, onClick: () => setShowAllRows((current) => !current), className: "flex h-7 w-full items-center justify-center gap-1.5 border-t border-border bg-background px-2 text-[11px] font-medium text-muted-foreground transition-colors hover:bg-muted/70 hover:text-foreground", children: [_jsx(IconChevronRight, { className: cn("size-3 shrink-0 transition-transform", showAllRows ? "-rotate-90" : "rotate-90") }), showAllRows
614
620
  ? "Show fewer"
615
621
  : `Show all ${totalVisibleLineCount} lines`] }))] }));
616
- return (_jsxs("section", { ref: containerRef, className: "relative plan-block group/diff-block", "data-block-id": blockId, children: [title && _jsx("div", { className: "plan-block-label", children: title }), summary && (_jsx("p", { className: "mb-3 text-sm leading-relaxed text-plan-muted", children: summary })), diffBox, hasAnnotations && (_jsx(AnnotationHiddenStack, { items: resolved, ctx: ctx, showMarker: true })), hasAnnotations && activeItem && hover.anchor && (_jsx(AnnotationHoverCard, { item: activeItem, anchor: hover.anchor, ctx: ctx, showMarker: true, onMouseEnter: hover.cancelClose, onMouseLeave: hover.scheduleClose }))] }));
622
+ return (_jsxs("section", { ref: containerRef, className: "relative plan-block group/diff-block", "data-block-id": blockId, children: [title && _jsx("div", { className: "plan-block-label", children: title }), summary && (_jsx("p", { className: "mb-3 text-sm leading-relaxed text-plan-muted", children: summary })), diffBox, hasAnnotations && (_jsx(AnnotationHiddenStack, { items: resolved, ctx: ctx, showMarker: true })), hasAnnotations && activeItem && hover.anchor && (_jsx(AnnotationHoverCard, { item: activeItem, anchor: hover.anchor, ctx: ctx, showMarker: true, onMouseEnter: hover.cancelClose, onMouseLeave: hover.scheduleClose, onClose: hover.close }))] }));
617
623
  }
618
624
  function ModeButton({ active, onClick, icon, label, }) {
619
625
  return (_jsxs("button", { type: "button", "data-plan-interactive": true, onClick: onClick, "aria-pressed": active, className: cn("flex cursor-pointer items-center gap-1 px-2 py-1 text-xs font-medium transition-colors", active
@@ -653,7 +659,7 @@ function isMarkerRangeStart(row, marker) {
653
659
  return lineNo === marker.range.start;
654
660
  }
655
661
  /* ── Unified view ──────────────────────────────────────────────────────────── */
656
- function UnifiedView({ rows, language, expanded, onToggleRun, markersForRow, anchoredRow, activeIndex, onRowEnter, onRowLeave, }) {
662
+ function UnifiedView({ rows, language, expanded, onToggleRun, markersForRow, anchoredRow, activeIndex, onRowEnter, onRowLeave, onRowClick, }) {
657
663
  const segments = useMemo(() => segmentRows(rows, anchoredRow), [rows, anchoredRow]);
658
664
  // Any annotation present ⇒ reserve the marker column so rows stay aligned.
659
665
  const showMarkerColumn = useMemo(() => rows.some((row) => markersForRow(row).length > 0), [rows, markersForRow]);
@@ -663,6 +669,7 @@ function UnifiedView({ rows, language, expanded, onToggleRun, markersForRow, anc
663
669
  activeIndex,
664
670
  onRowEnter,
665
671
  onRowLeave,
672
+ onRowClick,
666
673
  showMarkerColumn,
667
674
  };
668
675
  let runIndex = 0;
@@ -676,13 +683,25 @@ function UnifiedView({ rows, language, expanded, onToggleRun, markersForRow, anc
676
683
  return _jsx(UnifiedRow, { row: segment, ...rowProps }, idx);
677
684
  }) }) }));
678
685
  }
679
- function UnifiedRow({ language, row, markersForRow, activeIndex, onRowEnter, onRowLeave, showMarkerColumn, }) {
686
+ function UnifiedRow({ language, row, markersForRow, activeIndex, onRowEnter, onRowLeave, onRowClick, showMarkerColumn, }) {
680
687
  const markers = markersForRow(row);
681
688
  const info = rowMarkerInfo(markers, activeIndex);
682
689
  const startMarker = markers.find((marker) => isMarkerRangeStart(row, marker));
683
- return (_jsxs("div", { "data-annot-row": startMarker ? startMarker.index : undefined, className: cn("flex min-h-5 min-w-full", ROW_BG[row.kind], annotatedRowBg(info)), onMouseEnter: info
684
- ? (event) => onRowEnter(startMarker?.index ?? info.primaryIndex, event.currentTarget)
685
- : undefined, onMouseLeave: info ? () => onRowLeave() : undefined, children: [_jsx("span", { className: cn(LINE_NO_CLASS, "w-[52px]"), children: row.oldNo ?? "" }), _jsx("span", { className: cn(LINE_NO_CLASS, "w-[52px]"), children: row.newNo ?? "" }), _jsx("span", { className: cn("w-6 shrink-0 select-none py-0 text-center font-semibold leading-5", GUTTER_BG[row.kind], SIGN_COLOR[row.kind]), children: SIGN[row.kind] }), showMarkerColumn && (_jsx(MarkerCell, { startMarker: startMarker, active: startMarker != null && startMarker.index === activeIndex })), _jsx(DiffLineText, { text: row.text, language: language })] }));
690
+ const primaryIndex = startMarker?.index ?? info?.primaryIndex;
691
+ return (_jsxs("div", { "data-annot-row": startMarker ? startMarker.index : undefined, tabIndex: info ? 0 : undefined, role: info ? "button" : undefined, "aria-expanded": info ? info.isActive : undefined, className: cn("flex min-h-5 min-w-full", info && "cursor-pointer", ROW_BG[row.kind], annotatedRowBg(info)), onMouseEnter: info && primaryIndex != null
692
+ ? (event) => onRowEnter(primaryIndex, event.currentTarget)
693
+ : undefined, onMouseLeave: info ? () => onRowLeave() : undefined, onClick: info && primaryIndex != null
694
+ ? (event) => onRowClick(primaryIndex, event.currentTarget)
695
+ : undefined, onKeyDown: info && primaryIndex != null
696
+ ? (event) => {
697
+ if (event.key !== "Enter" && event.key !== " ")
698
+ return;
699
+ event.preventDefault();
700
+ onRowClick(primaryIndex, event.currentTarget);
701
+ }
702
+ : undefined, onFocus: info && primaryIndex != null
703
+ ? (event) => onRowEnter(primaryIndex, event.currentTarget)
704
+ : undefined, onBlur: info ? () => onRowLeave() : undefined, children: [_jsx("span", { className: cn(LINE_NO_CLASS, "w-[52px]"), children: row.oldNo ?? "" }), _jsx("span", { className: cn(LINE_NO_CLASS, "w-[52px]"), children: row.newNo ?? "" }), _jsx("span", { className: cn("w-6 shrink-0 select-none py-0 text-center font-semibold leading-5", GUTTER_BG[row.kind], SIGN_COLOR[row.kind]), children: SIGN[row.kind] }), showMarkerColumn && (_jsx(MarkerCell, { startMarker: startMarker, active: startMarker != null && startMarker.index === activeIndex })), _jsx(DiffLineText, { text: row.text, language: language })] }));
686
705
  }
687
706
  /**
688
707
  * The fixed-width marker column rendered between the sign gutter and the code.
@@ -726,7 +745,7 @@ function pairSplitRows(rows) {
726
745
  }
727
746
  return out;
728
747
  }
729
- function SplitView({ language, rowLimit, rows, markersForRow, activeIndex, onRowEnter, onRowLeave, }) {
748
+ function SplitView({ language, rowLimit, rows, markersForRow, activeIndex, onRowEnter, onRowLeave, onRowClick, }) {
730
749
  const pairs = useMemo(() => pairSplitRows(rows), [rows]);
731
750
  const displayedPairs = rowLimit ? pairs.slice(0, rowLimit) : pairs;
732
751
  // Reserve the marker column on a side only if any visible row there has one.
@@ -738,10 +757,11 @@ function SplitView({ language, rowLimit, rows, markersForRow, activeIndex, onRow
738
757
  activeIndex,
739
758
  onRowEnter,
740
759
  onRowLeave,
760
+ onRowClick,
741
761
  };
742
762
  return (_jsxs("div", { className: "flex w-full bg-background font-mono [font-size:var(--plan-doc-code-size)] leading-5", "data-code-surface": true, children: [_jsx("div", { className: "min-w-0 flex-1 overflow-x-auto border-r border-border", children: _jsx("div", { className: "inline-block min-w-full", children: displayedPairs.map((pair, idx) => (_jsx(SplitCell, { row: pair.left, side: "old", showMarkerColumn: showOldMarkers, ...cellProps }, `old-${idx}`))) }) }), _jsx("div", { className: "min-w-0 flex-1 overflow-x-auto", children: _jsx("div", { className: "inline-block min-w-full", children: displayedPairs.map((pair, idx) => (_jsx(SplitCell, { row: pair.right, side: "new", showMarkerColumn: showNewMarkers, ...cellProps }, `new-${idx}`))) }) })] }));
743
763
  }
744
- function SplitCell({ language, row, side, markersForRow, activeIndex, onRowEnter, onRowLeave, showMarkerColumn, }) {
764
+ function SplitCell({ language, row, side, markersForRow, activeIndex, onRowEnter, onRowLeave, onRowClick, showMarkerColumn, }) {
745
765
  if (!row) {
746
766
  return (_jsxs("div", { className: "flex min-h-5 min-w-full bg-muted/40 opacity-70", children: [_jsx("span", { className: cn(LINE_NO_CLASS, "w-[52px]") }), _jsx("span", { className: "w-6 shrink-0 bg-muted/60" }), showMarkerColumn && _jsx("span", { className: "w-6 shrink-0" }), _jsx("span", { className: DIFF_LINE_CLASS, children: " " })] }));
747
767
  }
@@ -750,9 +770,21 @@ function SplitCell({ language, row, side, markersForRow, activeIndex, onRowEnter
750
770
  const markers = markersForRow(row, side);
751
771
  const info = rowMarkerInfo(markers, activeIndex);
752
772
  const startMarker = markers.find((marker) => isMarkerRangeStart(row, marker));
753
- return (_jsxs("div", { "data-annot-row": startMarker ? startMarker.index : undefined, className: cn("flex min-h-5 min-w-full", ROW_BG[row.kind], annotatedRowBg(info)), onMouseEnter: info
754
- ? (event) => onRowEnter(startMarker?.index ?? info.primaryIndex, event.currentTarget)
755
- : undefined, onMouseLeave: info ? () => onRowLeave() : undefined, children: [_jsx("span", { className: cn(LINE_NO_CLASS, "w-[52px]"), children: side === "old" ? (row.oldNo ?? "") : (row.newNo ?? "") }), _jsx("span", { className: cn("w-6 shrink-0 select-none py-0 text-center font-semibold leading-5", GUTTER_BG[row.kind], SIGN_COLOR[row.kind]), children: showSign ? sign : " " }), showMarkerColumn && (_jsx(MarkerCell, { startMarker: startMarker, active: startMarker != null && startMarker.index === activeIndex })), _jsx(DiffLineText, { text: row.text, language: language })] }));
773
+ const primaryIndex = startMarker?.index ?? info?.primaryIndex;
774
+ return (_jsxs("div", { "data-annot-row": startMarker ? startMarker.index : undefined, tabIndex: info ? 0 : undefined, role: info ? "button" : undefined, "aria-expanded": info ? info.isActive : undefined, className: cn("flex min-h-5 min-w-full", info && "cursor-pointer", ROW_BG[row.kind], annotatedRowBg(info)), onMouseEnter: info && primaryIndex != null
775
+ ? (event) => onRowEnter(primaryIndex, event.currentTarget)
776
+ : undefined, onMouseLeave: info ? () => onRowLeave() : undefined, onClick: info && primaryIndex != null
777
+ ? (event) => onRowClick(primaryIndex, event.currentTarget)
778
+ : undefined, onKeyDown: info && primaryIndex != null
779
+ ? (event) => {
780
+ if (event.key !== "Enter" && event.key !== " ")
781
+ return;
782
+ event.preventDefault();
783
+ onRowClick(primaryIndex, event.currentTarget);
784
+ }
785
+ : undefined, onFocus: info && primaryIndex != null
786
+ ? (event) => onRowEnter(primaryIndex, event.currentTarget)
787
+ : undefined, onBlur: info ? () => onRowLeave() : undefined, children: [_jsx("span", { className: cn(LINE_NO_CLASS, "w-[52px]"), children: side === "old" ? (row.oldNo ?? "") : (row.newNo ?? "") }), _jsx("span", { className: cn("w-6 shrink-0 select-none py-0 text-center font-semibold leading-5", GUTTER_BG[row.kind], SIGN_COLOR[row.kind]), children: showSign ? sign : " " }), showMarkerColumn && (_jsx(MarkerCell, { startMarker: startMarker, active: startMarker != null && startMarker.index === activeIndex })), _jsx(DiffLineText, { text: row.text, language: language })] }));
756
788
  }
757
789
  /* ── Edit (panel) ──────────────────────────────────────────────────────────── */
758
790
  const codeAreaClass = "min-h-[140px] font-mono [font-size:var(--plan-code-size)] leading-5";