@gakim-digital/dexter-bridge 0.11.14 → 0.11.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -47,18 +47,15 @@ Native shell, filesystem, web, and unrelated-project access are disabled for
47
47
  Framer outcome runs. Publishing is denied unless a future assignment explicitly
48
48
  authorizes it.
49
49
 
50
- Bridges advertise `framer-interaction-verification-v3`,
51
- `framer-behavior-contract-v1`, and `framer-mechanism-verification-v1` only
52
- when interaction work is declared as observable behavior, checked against the
53
- selected Framer mechanism before mutation, and verified from live canonical
54
- Framer nodes afterward. Verification is tri-state: `verified`,
55
- `contradicted`, or `unknown`. Unknown evidence cannot trigger a repair or
56
- reject a mechanism. Native navigation is verified from link and component
57
- control destinations instead of requiring synthetic frame events. Repeated
58
- behavior is verified on one declared representative target before the
59
- remaining targets are changed. Only a concrete contradiction may receive one
60
- scoped `SET` repair. Repeated unchanged evidence is bounded and exits as a
61
- partial result rather than looping.
50
+ Bridges advertise `framer-interaction-verification-v4`. Dexter does not model
51
+ Framer's interaction features: the model builds behaviors with any capability
52
+ the Framer guidance documents, declares each behavior with the nodes that
53
+ should carry it, and then names the Framer property that carries it on each
54
+ node (for example `loopEffect` or `link`). The bridge confirms that property on
55
+ the live node. Results are `verified`, `contradicted` (the value differs), or
56
+ `unknown` (the property was not found). Unknown never blocks edits and is
57
+ reported as unverified; an unchecked target or a contradiction leaves the run
58
+ incomplete.
62
59
 
63
60
  Project connection is handled inside Dexter and completes before the model
64
61
  starts:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gakim-digital/dexter-bridge",
3
- "version": "0.11.14",
3
+ "version": "0.11.16",
4
4
  "description": "Local bridge for InstaWebAI and Dexter — runs Codex, Claude Code, or OpenCode on your machine.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -45,6 +45,7 @@
45
45
  "@openrouter/ai-sdk-provider": "^3.0.0",
46
46
  "ai": "^7.0.85",
47
47
  "cross-spawn": "^7.0.6",
48
+ "js-tokens": "^10.0.0",
48
49
  "jsonrepair": "^3.15.0",
49
50
  "zod": "^4.5.4"
50
51
  }
package/src/agent.js CHANGED
@@ -2579,27 +2579,36 @@ async function executeOutcomeRun(run, send, agent, options = {}) {
2579
2579
  let providerAttempts = 0;
2580
2580
  let result;
2581
2581
  try {
2582
- if (framerAgentOutcome) {
2583
- await Promise.race([harnessTools.preflight(), cancellation]);
2584
- }
2582
+ const preflight = framerAgentOutcome
2583
+ ? await Promise.race([harnessTools.preflight(), cancellation])
2584
+ : null;
2585
2585
  const framerGuidance = framerAgentOutcome
2586
2586
  ? await Promise.race([
2587
2587
  harnessTools.loadProjectGuidance(),
2588
2588
  cancellation,
2589
2589
  ])
2590
2590
  : null;
2591
- harnessTools.configurePromptContext?.({
2592
- doctrineLoaded: Boolean(run?.doctrine),
2593
- doctrineVersion: run?.doctrineVersion,
2594
- });
2595
2591
  prompt = buildOutcomePrompt(executionOutcome, product, {
2596
2592
  doctrine: run?.doctrine,
2597
2593
  doctrineVersion: run?.doctrineVersion,
2598
2594
  framerGuidance: framerGuidance?.content,
2599
2595
  });
2596
+ const unresolvedTargets = preflight?.unresolvedTargets || [];
2597
+ if (unresolvedTargets.length > 0) {
2598
+ prompt = [
2599
+ prompt,
2600
+ '',
2601
+ `These selected layer IDs do not resolve to native nodes on the active page: ${unresolvedTargets.map((target) => target.id).join(', ')}. The user still means those layers. Locate them by name and position in the provided context and the live tree, treat the matching native nodes as the selection, and ask only if no layer clearly matches.`,
2602
+ ].join('\n');
2603
+ }
2600
2604
  if (materializedNativeSkills) {
2601
2605
  prompt = claudeNativeSkillPrompt(prompt, materializedNativeSkills);
2602
2606
  }
2607
+ harnessTools.configurePromptContext?.({
2608
+ doctrineLoaded: Boolean(run?.doctrine),
2609
+ doctrineVersion: run?.doctrineVersion,
2610
+ promptBytes: Buffer.byteLength(prompt, 'utf8'),
2611
+ });
2603
2612
  const gateway =
2604
2613
  definition.id === 'codex' ? null : await harnessTools.startGateway();
2605
2614
  const mcpServer = gateway
@@ -2796,7 +2805,7 @@ async function executeOutcomeRun(run, send, agent, options = {}) {
2796
2805
  rawCompletion.status === successStatus
2797
2806
  && typeof harnessTools.verificationRepairPrompt === 'function'
2798
2807
  ? harnessTools.verificationRepairPrompt()
2799
- : null;
2808
+ : harnessTools.unblockedFailurePrompt?.(rawCompletion) || null;
2800
2809
  if (
2801
2810
  repairPrompt
2802
2811
  && Date.now() - callStartedAt < outcomeMaxDurationMs - 5_000
@@ -2805,7 +2814,9 @@ async function executeOutcomeRun(run, send, agent, options = {}) {
2805
2814
  kind: 'status_update',
2806
2815
  source: 'harness',
2807
2816
  message:
2808
- 'I’m completing the final Framer verification before I finish.',
2817
+ rawCompletion.status === successStatus
2818
+ ? 'I’m completing the final Framer verification before I finish.'
2819
+ : 'Nothing is blocking this change, so I’m continuing the work.',
2809
2820
  });
2810
2821
  const repairResult = await Promise.race([
2811
2822
  executeProviderOutcome(
@@ -444,7 +444,7 @@ export function createClaudeProgressParser(onProgress, options = {}) {
444
444
  const block = event?.type === 'content_block_start' ? event.content_block : null;
445
445
  if (block?.type !== 'tool_use' || !block.id || drafting.has(block.id)) return;
446
446
  const shortName = String(block.name || '').replace(/^mcp__instawebai__/, '');
447
- if (!['framer_apply_changes', 'framer_update_code_file', 'framer_write'].includes(shortName)) return;
447
+ if (!['framer_apply_changes', 'framer_add_svg', 'framer_update_code_file', 'framer_write'].includes(shortName)) return;
448
448
  drafting.set(block.id, true);
449
449
  emit({
450
450
  kind: 'item_started',
package/src/config.js CHANGED
@@ -43,9 +43,7 @@ export const BRIDGE_CAPABILITIES = [
43
43
  'framer-agent-v1',
44
44
  'framer-project-bootstrap-v1',
45
45
  'framer-project-verification-v1',
46
- 'framer-interaction-verification-v3',
47
- 'framer-behavior-contract-v1',
48
- 'framer-mechanism-verification-v1',
46
+ 'framer-interaction-verification-v4',
49
47
  'project-shell-v1',
50
48
  'build-fingerprint-v1',
51
49
  'tool-schema-parity-v1',