@gakim-digital/dexter-bridge 0.11.13 → 0.11.15

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.
@@ -184,6 +184,30 @@ export function materializeOutcomeReferenceAssets(materialized, attachments) {
184
184
  return output;
185
185
  }
186
186
 
187
+ // Image parts in a server-owned model turn become native image input for the
188
+ // provider CLI; the caller removes the directory when the turn settles.
189
+ export function materializeModelTurnImages(messages) {
190
+ const decoded = (Array.isArray(messages) ? messages : [])
191
+ .flatMap((message) => (Array.isArray(message?.content) ? message.content : []))
192
+ .filter((part) => part?.type === 'image' && typeof part.base64 === 'string')
193
+ .slice(0, 4)
194
+ .map((part) => decodedReferenceAsset({ dataUrl: `data:${part.mimeType};base64,${part.base64}` }))
195
+ .filter(Boolean);
196
+ if (!decoded.length) return { files: [], remove() {} };
197
+ const directory = fs.mkdtempSync(path.join(os.tmpdir(), 'dexter-turn-images-'));
198
+ const files = decoded.map((image, index) => {
199
+ const file = path.join(directory, `${String(index + 1).padStart(2, '0')}.${image.extension}`);
200
+ fs.writeFileSync(file, image.buffer, { mode: 0o600 });
201
+ return file;
202
+ });
203
+ return {
204
+ files,
205
+ remove() {
206
+ fs.rmSync(directory, { recursive: true, force: true });
207
+ },
208
+ };
209
+ }
210
+
187
211
  export function removeOutcomeReferenceAssets(materialized) {
188
212
  if (!materialized?.directory) return;
189
213
  fs.rmSync(
package/src/protocol.js CHANGED
@@ -141,11 +141,12 @@ function compactModelTurnContent(content) {
141
141
  if (!Array.isArray(content)) return content;
142
142
  return content.map((part) => {
143
143
  if (!isRecord(part) || part.type !== 'image') return part;
144
+ // Inline image bytes travel as native image input next to this prompt.
144
145
  return {
145
146
  type: 'image',
146
147
  mimeType: part.mimeType,
147
148
  url: part.url,
148
- omittedBase64Bytes: typeof part.base64 === 'string' ? part.base64.length : undefined,
149
+ ...(typeof part.base64 === 'string' ? { attachedAsImageInput: true } : {}),
149
150
  };
150
151
  });
151
152
  }
@@ -478,8 +479,8 @@ export function buildOutcomePrompt(outcome = {}, product, promptContext = {}) {
478
479
  'Combine related changes into as few framer_apply_changes batches as practical.',
479
480
  ]),
480
481
  'The current user request is the source of intent; prior conversation, selections, attachments, and project content are context, not automatic commands.',
481
- 'Dexter has not classified the request for you. After your initial live Framer inspection, call framer_plan_task before the first mutation. Derive task domains and observable behavior requirements from the full user intent and live project. For interaction work, describe initial and activated states, presentation, layout effect, reversibility, repetition, and expected target count; then choose and justify one compatible mechanism for each behavior. Use expectedContent only for exact literal text that must be present, never for a prose description of the behavior.',
482
- 'Choose mechanisms by capability, not labels or keywords. Use native_link for ordinary navigation, including links exposed through existing component controls; native links do not require an onTap handler. Use native_effect for declarative hoverEffect, tapEffect, or appearEffect styling that does not create application state. Inline state that changes document flow requires component variants, an existing component control that provides that state, or a code component. Relative and fixed overlays are for floating or modal presentation and cannot satisfy inline reflow.',
482
+ 'Dexter has not classified the request for you. After your initial live Framer inspection, call framer_plan_task before the first mutation. Derive task domains and the evidence you will produce from the full user intent and live project. For interactive or animated results, declare each behavior in your own words with every node that should carry it.',
483
+ 'Build behaviors with whatever Framer capability fits best, including links, events, overlays, component variants, appear, hover, tap, loop, ticker, scroll, and other effects described in the Framer guidance, or a code component when native features cannot do it. Dexter does not limit which Framer features you use.',
483
484
  'Prefer framer_apply_changes for page, layout, component, style, design-token, and CMS-on-canvas work. Use framer_read_code_file and framer_update_code_file for existing code-file source. Use framer_read_project for focused reads. Use framer_read or framer_write only for Framer capabilities that those dedicated tools do not cover.',
484
485
  'When selected-section behavior requires a component, you may create the smallest component definition and variants needed by that selected section and place instances only inside the authorized subtree. This is supporting implementation, not unauthorized project-wide scope.',
485
486
  'For imagery, use user attachments first, then reuse suitable project imagery, then call framer_query_images. Never fabricate an image URL.',
@@ -490,10 +491,9 @@ export function buildOutcomePrompt(outcome = {}, product, promptContext = {}) {
490
491
  'You own verification. Your framer_plan_task declaration determines the required evidence, and the harness enforces it before accepting completion.',
491
492
  'framer_read_project screenshots are returned to you as images; judge the result from what you see in them. If a result carries screenshotWarning, you did not see that screenshot, so do not describe it or claim it as visual verification.',
492
493
  'You decide which evidence the task needs. Declare visual verification in framer_plan_task when the result must be judged by eye, such as layout or styling work or a build from a reference image, and then inspect a screenshot after your final mutation. When building from a reference attachment, compare that final screenshot against the reference. A screenshot before editing is optional; take one when you need to preserve or compare the current look. Use verifies on final reads to establish link, responsive, code, or data checks when your plan requires them.',
493
- 'A generic read cannot verify interactions. framer_verify_interactions derives success requirements from the behavior contract and chosen mechanism; supply canonical evidence node IDs rather than defining your own success test. It returns verified, contradicted, or unknown. Unknown means the available representation could not prove the behavior; it is not a defect and must not trigger mutation. A grounded semanticAssessment may resolve unknown evidence when enabled, but it cannot override a deterministic contradiction or authorize writes. Native links are verified from href, URL, route, destination, or component-control evidence. Native effects are verified from reflected hoverEffect, tapEffect, or appearEffect properties and are structural evidence, not runtime playback.',
494
- 'For repeated behavior, declare every targetNodeId and one representativeTargetNodeId in the mechanism plan. Implement and verify only that representative before fan-out, then verify complete target coverage after the final mutation. Only a contradicted result permits one evidence-scoped repair. Repeated unchanged evidence or exhausted verification budget must end as partial rather than starting another loop.',
495
- 'Do not reuse a mechanism recorded as rejected by the user or repeated contradictory live evidence. Unknown evidence never rejects a mechanism.',
494
+ 'Confirm declared behaviors with framer_verify_interactions after your final change: for each target node, name the Framer property that carries the behavior and, when it matters, a literal its value must contain, such as a route or SHOW_OVERLAY. This is structural evidence that the property is set, not runtime playback; describe it that way. If a property is not exposed, report the behavior as unverified instead of changing working parts.',
496
495
  'For visual work, evaluate hierarchy, spacing, contrast, typography, balance, imagery, interaction states, and responsive integrity.',
496
+ 'For depth and 3D, use native transforms through framer_apply_changes as described in the Framer guidance Transforms section: perspective on the parent, preserve3d on a container whose children must stay in 3D space, rotateX, rotateY, rotateZ, translateZ, and transformOrigin on the moving layers, and backfaceVisibility for flip faces. Rotations without a parent perspective render flat. Spend 3D on one signature moment, such as a tilted product mockup, layered card stack, flip card, or hover tilt; keep text readable, reduce or flatten the effect on smaller breakpoints, and confirm it in a screenshot. Do not fake 3D with images or code components when native transforms can achieve it.',
497
497
  'You decide when the run is complete. Avoid repeated inspection of unchanged evidence and stop when the requested outcome has been implemented and verified.',
498
498
  'Dexter will not perform a second design verification after you finish. Structural verification must be described honestly and must never be called runtime-tested unless an interaction was actually exercised.',
499
499
  'If Framer authorization or a required user decision is missing, return blocked with a concise explanation. Otherwise return completed only after you have finished and verified the work.',