pmx-canvas 0.6.1 โ†’ 0.6.2

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.
@@ -135,8 +135,10 @@ const focusOperation = defineOperation<z.infer<typeof focusSchema>, Record<strin
135
135
  }
136
136
  const focus = canvasState.setAxFocus([nodeId], { source: 'api', recordHistory: false });
137
137
  ctx.emit('ax-state-changed', { focus });
138
- ctx.emit('canvas-focus-node', { nodeId, noPan });
138
+ // Apply the server fallback first; the browser then refines it using its
139
+ // actual canvas region and floating chrome instead of cancelling that fit.
139
140
  if (!noPan) ctx.emit('canvas-viewport-update', { viewport: canvasState.viewport });
141
+ ctx.emit('canvas-focus-node', { nodeId, noPan });
140
142
  return { ok: true, focused: nodeId, panned: !noPan, axFocus: focus };
141
143
  },
142
144
  });
@@ -250,6 +252,9 @@ const viewportSetOperation = defineOperation<z.infer<typeof viewportSetSchema>,
250
252
  // sizes to the human's actual window instead of a hardcoded 1440x900
251
253
  // (0.4.6 orb feedback #2).
252
254
  setClientViewportSize(body.clientWidth, body.clientHeight);
255
+ // A size-only report is not a camera command. Echoing the stored camera
256
+ // here would cancel an in-flight browser focus with its stale fallback.
257
+ if (![body.x, body.y, body.scale].some((value) => typeof value === 'number')) return { ok: true };
253
258
  const next = {
254
259
  x: typeof body.x === 'number' ? body.x : canvasState.viewport.x,
255
260
  y: typeof body.y === 'number' ? body.y : canvasState.viewport.y,
@@ -556,22 +556,22 @@ export async function startCanvasAutomationWebView(
556
556
  await closeCanvasAutomationWebViewInternal();
557
557
  }
558
558
 
559
- const view = new WebView({
560
- width: normalized.width,
561
- height: normalized.height,
562
- headless: true,
563
- backend,
564
- dataStore: normalized.dataStoreDir ? { directory: normalized.dataStoreDir } : 'ephemeral',
565
- });
566
-
559
+ let view: CanvasWebViewLike | null = null;
567
560
  try {
561
+ view = new WebView({
562
+ width: normalized.width,
563
+ height: normalized.height,
564
+ headless: true,
565
+ backend,
566
+ dataStore: normalized.dataStoreDir ? { directory: normalized.dataStoreDir } : 'ephemeral',
567
+ });
568
568
  await withCanvasAutomationWebViewTimeout(view.navigate(url), 'starting the workbench automation WebView');
569
569
  } catch (error) {
570
570
  canvasAutomationWebViewStatus = {
571
571
  ...canvasAutomationWebViewStatus,
572
572
  lastError: error instanceof Error ? error.message : String(error),
573
573
  };
574
- await Promise.resolve(view.close()).catch(() => undefined);
574
+ if (view) await Promise.resolve(view.close()).catch(() => undefined);
575
575
  throw error;
576
576
  }
577
577
 
@@ -56,14 +56,12 @@ function replay_filtered_stderr() {
56
56
 
57
57
  function run_with_filtered_stderr() {
58
58
  local stderr_file
59
+ local status
59
60
  stderr_file="$(mktemp)"
60
- if "$@" 2>"$stderr_file"; then
61
- replay_filtered_stderr "$stderr_file"
62
- rm -f "$stderr_file"
63
- return 0
64
- fi
65
-
66
- local status=$?
61
+ set +e
62
+ "$@" 2>"$stderr_file"
63
+ status=$?
64
+ set -e
67
65
  replay_filtered_stderr "$stderr_file"
68
66
  rm -f "$stderr_file"
69
67
  return "$status"
@@ -109,6 +107,17 @@ function ensure_bundle_dependencies() {
109
107
  fi
110
108
  done
111
109
 
110
+ # package.json lists the deps, but node_modules may not be in sync (e.g. fresh
111
+ # CI checkout where node_modules is gitignored). Run a regular install so the
112
+ # local binaries actually exist before we hand off to Parcel. The build
113
+ # allowlist is already persisted in package.json's pnpm.onlyBuiltDependencies
114
+ # by the original `pnpm add` step, so plain `install` is enough here.
115
+ if [ ! -x "./node_modules/.bin/parcel" ]; then
116
+ echo "๐Ÿ“ฆ Syncing bundling dependencies into node_modules..."
117
+ run_pnpm_quiet install
118
+ return 0
119
+ fi
120
+
112
121
  echo "โœ… Reusing existing bundling dependencies"
113
122
  }
114
123
 
@@ -150,7 +159,19 @@ rm -rf dist bundle.html
150
159
 
151
160
  # Build with Parcel
152
161
  echo "๐Ÿ”จ Building with Parcel..."
153
- run_with_filtered_stderr run_local_binary parcel build index.html --dist-dir dist --no-source-maps --log-level error
162
+ parcel_status=0
163
+ run_with_filtered_stderr run_local_binary parcel build index.html --dist-dir dist --no-source-maps --log-level error || parcel_status=$?
164
+
165
+ # Self-heal a wedged cache: these build projects are REUSED across artifact
166
+ # builds, and a parcel killed mid-write (e.g. the canvas server torn down
167
+ # during a build) leaves a corrupted .parcel-cache that makes every later
168
+ # build die before emitting anything โ€” permanently, until the cache goes.
169
+ # Retry exactly once from a cold cache, then preserve a genuine build failure.
170
+ if [ "$parcel_status" -ne 0 ] || [ ! -s "dist/index.html" ]; then
171
+ echo "๐Ÿงน Parcel build failed or produced no output โ€” clearing .parcel-cache and retrying cold..."
172
+ rm -rf .parcel-cache dist
173
+ run_with_filtered_stderr run_local_binary parcel build index.html --dist-dir dist --no-source-maps --log-level error
174
+ fi
154
175
 
155
176
  if [ ! -s "dist/index.html" ]; then
156
177
  echo "โŒ Error: Parcel did not produce dist/index.html" >&2