@agent-native/core 0.115.1 → 0.115.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/core/CHANGELOG.md +18 -0
  3. package/corpus/core/package.json +1 -1
  4. package/corpus/core/src/agent/production-agent.ts +17 -0
  5. package/corpus/core/src/cli/skills-content/visual-plan-skill.ts +19 -2
  6. package/corpus/core/src/client/blocks/library/wireframe.tsx +3 -1
  7. package/corpus/core/src/server/builder-browser.ts +34 -4
  8. package/corpus/core/src/server/core-routes-plugin.ts +1 -1
  9. package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +10 -1
  10. package/corpus/templates/plan/.agents/skills/visual-plan/SKILL.md +19 -2
  11. package/corpus/templates/plan/AGENTS.md +10 -0
  12. package/corpus/templates/plan/actions/create-prototype-plan.ts +27 -3
  13. package/corpus/templates/plan/actions/get-plan-blocks.ts +1 -1
  14. package/corpus/templates/plan/actions/update-visual-plan.ts +3 -2
  15. package/corpus/templates/plan/app/components/plan/PlanContentRenderer.tsx +18 -4
  16. package/corpus/templates/plan/app/components/plan/PlanVisualSurface.tsx +10 -3
  17. package/corpus/templates/plan/app/components/plan/wireframe/Wireframe.tsx +3 -1
  18. package/corpus/templates/plan/app/i18n/en-US.ts +6 -0
  19. package/corpus/templates/plan/app/lib/create-plan-routing.ts +39 -0
  20. package/corpus/templates/plan/app/pages/PlansPage.tsx +31 -107
  21. package/corpus/templates/plan/changelog/2026-07-22-high-fidelity-mockup-requests-now-preserve-branded-css-use-d.md +6 -0
  22. package/corpus/templates/plan/shared/plan-content.ts +110 -2
  23. package/dist/agent/production-agent.d.ts.map +1 -1
  24. package/dist/agent/production-agent.js +14 -0
  25. package/dist/agent/production-agent.js.map +1 -1
  26. package/dist/cli/skills-content/visual-plan-skill.d.ts +1 -1
  27. package/dist/cli/skills-content/visual-plan-skill.d.ts.map +1 -1
  28. package/dist/cli/skills-content/visual-plan-skill.js +19 -2
  29. package/dist/cli/skills-content/visual-plan-skill.js.map +1 -1
  30. package/dist/client/blocks/library/wireframe.d.ts.map +1 -1
  31. package/dist/client/blocks/library/wireframe.js +3 -2
  32. package/dist/client/blocks/library/wireframe.js.map +1 -1
  33. package/dist/progress/routes.d.ts +1 -1
  34. package/dist/server/builder-browser.d.ts +1 -0
  35. package/dist/server/builder-browser.d.ts.map +1 -1
  36. package/dist/server/builder-browser.js +27 -4
  37. package/dist/server/builder-browser.js.map +1 -1
  38. package/dist/server/core-routes-plugin.js +1 -1
  39. package/dist/server/core-routes-plugin.js.map +1 -1
  40. package/package.json +1 -1
  41. package/src/agent/production-agent.ts +17 -0
  42. package/src/cli/skills-content/visual-plan-skill.ts +19 -2
  43. package/src/client/blocks/library/wireframe.tsx +3 -1
  44. package/src/server/builder-browser.ts +34 -4
  45. package/src/server/core-routes-plugin.ts +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.115.1",
3
+ "version": "0.115.4",
4
4
  "description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
5
5
  "homepage": "https://github.com/BuilderIO/agent-native#readme",
6
6
  "bugs": {
@@ -3087,6 +3087,21 @@ function normalizeToolCallInputForHistory(
3087
3087
  return { rawInput: input };
3088
3088
  }
3089
3089
 
3090
+ function dedupeAssistantToolCallsById(
3091
+ content: import("./engine/types.js").EngineContentPart[],
3092
+ ): import("./engine/types.js").EngineContentPart[] {
3093
+ const seenToolCallIds = new Set<string>();
3094
+ const deduped: import("./engine/types.js").EngineContentPart[] = [];
3095
+ for (const part of content) {
3096
+ if (part.type === "tool-call") {
3097
+ if (seenToolCallIds.has(part.id)) continue;
3098
+ seenToolCallIds.add(part.id);
3099
+ }
3100
+ deduped.push(part);
3101
+ }
3102
+ return deduped;
3103
+ }
3104
+
3090
3105
  function toolInputSchemaErrorResult(
3091
3106
  toolName: string,
3092
3107
  input: unknown,
@@ -3996,6 +4011,8 @@ export async function runAgentLoop(opts: {
3996
4011
  }
3997
4012
  }
3998
4013
 
4014
+ assistantContent = dedupeAssistantToolCallsById(assistantContent);
4015
+
3999
4016
  const assistantContentForHistory = assistantContent.map((part) =>
4000
4017
  part.type === "tool-call"
4001
4018
  ? {
@@ -301,6 +301,18 @@ and screen ids across both surfaces. The canvas is the inspectable static refere
301
301
  the prototype is the interactive version of that same flow, not a separate
302
302
  design direction.
303
303
 
304
+ Treat “higher fidelity,” “pixel-accurate,” “polished mockup,” “production-like,”
305
+ “real design,” and “not a sketch/wireframe” as design-first language even when
306
+ the request also says “mockup.” For a new plan, use \`create-plan-design\`. For
307
+ an existing plan, keep the same plan id and call \`update-visual-plan\` with a
308
+ \`set-visual-render-mode\` patch using \`renderMode: "design"\` plus the upgraded
309
+ screen HTML/CSS in the same update. Ground the result in the real app shell,
310
+ tokens, typography, spacing, and states, and add stable \`data-design-id\`
311
+ targets. Put scoped styles in each screen's \`css\` field, never in a \`<style>\`
312
+ tag. The viewer-local Clean toggle only changes one browser's wireframe
313
+ preference; it is not a fidelity upgrade. Do not create a duplicate plan to
314
+ handle a fidelity follow-up.
315
+
304
316
  ## Wireframe quality — read \`references/wireframe.md\`
305
317
 
306
318
  UI recap/plan wireframes must meet a strict quality bar — full-width chrome,
@@ -349,7 +361,9 @@ directory before authoring a plan.
349
361
  visual surface, canvas only, or canvas + prototype.
350
362
  - \`create-ui-plan\`: start a UI-first plan when the work is primarily product UI.
351
363
  - \`create-prototype-plan\`: start a prototype-first plan with a functional top
352
- review surface.
364
+ review surface. If the interaction itself must also be high fidelity, set each
365
+ screen's \`renderMode\` to \`design\` and pass scoped styles through \`css\`;
366
+ otherwise use \`create-plan-design\` for design-first review.
353
367
  - \`create-plan-design\`: start a full-fidelity branded Design-tab plan with an
354
368
  optional matching Prototype tab.
355
369
  - \`convert-visual-plan-to-prototype\`: convert an existing HTML wireframe canvas
@@ -357,7 +371,10 @@ directory before authoring a plan.
357
371
  - \`create-visual-questions\`: use only when the user explicitly asks for a visual
358
372
  intake questionnaire, not as \`/visual-plan\` preflight.
359
373
  - \`update-visual-plan\`: revise content, status, or comments with targeted
360
- \`contentPatches\` (see Core Workflow steps 6-7). \`replace-blocks\` and full
374
+ \`contentPatches\` (see Core Workflow steps 6-7). Use
375
+ \`set-visual-render-mode\` with \`renderMode: "design"\` when promoting an
376
+ existing plan to high fidelity, together with deliberate screen HTML/CSS;
377
+ render mode alone only removes sketch treatment. \`replace-blocks\` and full
361
378
  \`content\` replacement require \`expectedUpdatedAt\` from a fresh
362
379
  \`get-visual-plan\` call.
363
380
  - \`read-visual-plan-source\`: read the normalized plan as \`plan.mdx\`,
@@ -142,7 +142,7 @@ function ArtboardFrame({
142
142
  const fitRef = useRef<HTMLDivElement>(null);
143
143
  const isDark = useIsDark();
144
144
  const theme: "light" | "dark" = isDark ? "dark" : "light";
145
- const style = useWireframeStyle();
145
+ const preferredStyle = useWireframeStyle();
146
146
  const preset = SURFACE_PRESETS[surface] ?? SURFACE_PRESETS.desktop;
147
147
  const width = canvasWidth ?? preset.width;
148
148
  // AUTO-HEIGHT: with no explicit `canvasSize` the artboard height is driven by
@@ -164,6 +164,7 @@ function ArtboardFrame({
164
164
  fixedHeight ?? null,
165
165
  );
166
166
  const designMode = renderMode === "design";
167
+ const style = designMode ? "clean" : preferredStyle;
167
168
  const sketchy = !designMode && style === "sketchy" && !skeleton;
168
169
  const roughEnabled = sketchy && roughOverlay;
169
170
  const frameBorder = skeleton
@@ -409,6 +410,7 @@ function KitArtboard({
409
410
  surface={data.surface}
410
411
  compact={compact}
411
412
  skeleton={data.skeleton}
413
+ renderMode={data.renderMode}
412
414
  showFrame={showFrame}
413
415
  selector="[data-rough]"
414
416
  caption={data.caption}
@@ -26,6 +26,8 @@ export const BUILDER_RELAY_STATE_PARAM = "_an_relay";
26
26
  export const BUILDER_RELAY_SECRET_ENV = "AGENT_NATIVE_BUILDER_RELAY_SECRET";
27
27
  export const BUILDER_RELAY_TARGET_ORIGINS_ENV =
28
28
  "AGENT_NATIVE_BUILDER_RELAY_TARGET_ORIGINS";
29
+ export const BUILDER_RELAY_TARGET_DOMAIN_SUFFIXES_ENV =
30
+ "AGENT_NATIVE_BUILDER_RELAY_TARGET_DOMAIN_SUFFIXES";
29
31
  export const BUILDER_RELAY_TIMESTAMP_HEADER = "x-agent-native-relay-timestamp";
30
32
  export const BUILDER_RELAY_FLOW_HEADER = "x-agent-native-relay-flow";
31
33
  export const BUILDER_RELAY_SIGNATURE_HEADER = "x-agent-native-relay-signature";
@@ -151,15 +153,18 @@ export function isTrustedBuilderRelayTargetOrigin(value: string): boolean {
151
153
  ) {
152
154
  return false;
153
155
  }
154
- const configured = process.env[BUILDER_RELAY_TARGET_ORIGINS_ENV];
155
- if (!configured) return false;
156
- return configured
156
+ const exactOriginMatch = (process.env[BUILDER_RELAY_TARGET_ORIGINS_ENV] ?? "")
157
157
  .split(",")
158
158
  .map((origin) => origin.trim())
159
159
  .filter(Boolean)
160
160
  .some((origin) => origin === value && !origin.includes("*"));
161
+ return (
162
+ exactOriginMatch ||
163
+ builderRelayTargetDomainSuffixes().some((suffix) =>
164
+ hostname.endsWith(suffix),
165
+ )
166
+ );
161
167
  }
162
-
163
168
  export function signBuilderPreviewRelayState(input: {
164
169
  ownerEmail: string;
165
170
  targetOrigin: string;
@@ -191,6 +196,31 @@ export function signBuilderPreviewRelayState(input: {
191
196
  return { state: `${encoded}.${builderRelayMac(encoded)}`, payload };
192
197
  }
193
198
 
199
+ function builderRelayTargetDomainSuffixes(): string[] {
200
+ return (process.env[BUILDER_RELAY_TARGET_DOMAIN_SUFFIXES_ENV] ?? "")
201
+ .split(",")
202
+ .map((suffix) => suffix.trim().toLowerCase())
203
+ .filter((suffix) => {
204
+ if (!suffix.startsWith(".") || suffix.includes("*")) return false;
205
+ const hostname = suffix.slice(1);
206
+ if (!hostname.includes(".") || hostname.length > 253) return false;
207
+ if (
208
+ !hostname
209
+ .split(".")
210
+ .every((label) =>
211
+ /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(label),
212
+ )
213
+ ) {
214
+ return false;
215
+ }
216
+ try {
217
+ return new URL(`https://${hostname}`).hostname === hostname;
218
+ } catch {
219
+ return false;
220
+ }
221
+ });
222
+ }
223
+
194
224
  export function verifyBuilderPreviewRelayState(
195
225
  state: string | null | undefined,
196
226
  options: { now?: number } = {},
@@ -2345,7 +2345,7 @@ export function createCoreRoutesPlugin(
2345
2345
  timestamp: getHeader(event, BUILDER_RELAY_TIMESTAMP_HEADER),
2346
2346
  flowId: getHeader(event, BUILDER_RELAY_FLOW_HEADER),
2347
2347
  signature: getHeader(event, BUILDER_RELAY_SIGNATURE_HEADER),
2348
- requestOrigin: getFrameworkRouteRequestUrl(event).origin,
2348
+ requestOrigin: getBuilderBrowserOriginForEvent(event),
2349
2349
  requestBasePath: getAppBasePath(),
2350
2350
  },
2351
2351
  {