newmark-agent 0.5.9 → 0.5.11

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.
@@ -8383,7 +8383,7 @@ var require_createWorker = __commonJS({
8383
8383
  ...defaultOptions,
8384
8384
  ..._options
8385
8385
  });
8386
- const promises2 = {};
8386
+ const promises3 = {};
8387
8387
  const currentLangs = typeof langs === "string" ? langs.split("+") : langs;
8388
8388
  let currentOem = oem;
8389
8389
  let currentConfig = config;
@@ -8403,7 +8403,7 @@ var require_createWorker = __commonJS({
8403
8403
  const startJob = ({ id: jobId, action, payload }) => new Promise((resolve16, reject) => {
8404
8404
  log2(`[${id}]: Start ${jobId}, action=${action}`);
8405
8405
  const promiseId = `${action}-${jobId}`;
8406
- promises2[promiseId] = { resolve: resolve16, reject };
8406
+ promises3[promiseId] = { resolve: resolve16, reject };
8407
8407
  send(worker, {
8408
8408
  workerId: id,
8409
8409
  jobId,
@@ -8508,11 +8508,11 @@ var require_createWorker = __commonJS({
8508
8508
  const promiseId = `${action}-${jobId}`;
8509
8509
  if (status === "resolve") {
8510
8510
  log2(`[${workerId}]: Complete ${jobId}`);
8511
- promises2[promiseId].resolve({ jobId, data });
8512
- delete promises2[promiseId];
8511
+ promises3[promiseId].resolve({ jobId, data });
8512
+ delete promises3[promiseId];
8513
8513
  } else if (status === "reject") {
8514
- promises2[promiseId].reject(data);
8515
- delete promises2[promiseId];
8514
+ promises3[promiseId].reject(data);
8515
+ delete promises3[promiseId];
8516
8516
  if (action === "load") workerResReject(data);
8517
8517
  if (errorHandler) {
8518
8518
  errorHandler(data);
@@ -54006,18 +54006,18 @@ var require_proxy_agent = __commonJS({
54006
54006
  }
54007
54007
  }
54008
54008
  [kClose]() {
54009
- const promises2 = [this[kAgent].close()];
54009
+ const promises3 = [this[kAgent].close()];
54010
54010
  if (this[kClient]) {
54011
- promises2.push(this[kClient].close());
54011
+ promises3.push(this[kClient].close());
54012
54012
  }
54013
- return Promise.all(promises2);
54013
+ return Promise.all(promises3);
54014
54014
  }
54015
54015
  [kDestroy]() {
54016
- const promises2 = [this[kAgent].destroy()];
54016
+ const promises3 = [this[kAgent].destroy()];
54017
54017
  if (this[kClient]) {
54018
- promises2.push(this[kClient].destroy());
54018
+ promises3.push(this[kClient].destroy());
54019
54019
  }
54020
- return Promise.all(promises2);
54020
+ return Promise.all(promises3);
54021
54021
  }
54022
54022
  };
54023
54023
  function buildHeaders(headers) {
@@ -344923,6 +344923,7 @@ var fs24 = __toESM(require("fs"));
344923
344923
  var path27 = __toESM(require("path"));
344924
344924
  var import_crypto14 = require("crypto");
344925
344925
  var processStates = /* @__PURE__ */ new Map();
344926
+ var preparedPreviousStates = /* @__PURE__ */ new Map();
344926
344927
  function stateKey(root2, role) {
344927
344928
  return `${path27.resolve(root2)}\0${role}`;
344928
344929
  }
@@ -344968,7 +344969,8 @@ function beginRuntimeLifecycle(root2, role = "main") {
344968
344969
  const key3 = stateKey(root2, role);
344969
344970
  const existingProcessState = processStates.get(key3);
344970
344971
  if (existingProcessState) return existingProcessState;
344971
- const previousStates = readActiveStates(root2, role);
344972
+ const previousStates = preparedPreviousStates.get(key3) || readActiveStates(root2, role);
344973
+ preparedPreviousStates.delete(key3);
344972
344974
  const previousOwnerAlive = previousStates.some((previous) => isRuntimeProcessAlive(Number(previous.pid)));
344973
344975
  const state = {
344974
344976
  role,
@@ -344991,12 +344993,12 @@ function markRuntimeLifecycleClean(root2, role = "main") {
344991
344993
  const current = processStates.get(key3);
344992
344994
  if (!current) return;
344993
344995
  try {
344994
- writeState(root2, role, {
344995
- ...current,
344996
- active: false,
344997
- cleanExitAt: (/* @__PURE__ */ new Date()).toISOString()
344998
- });
344996
+ fs24.unlinkSync(statePath(root2, role, current.ownerId));
344999
344997
  } catch {
344998
+ try {
344999
+ writeState(root2, role, { ...current, active: false, cleanExitAt: (/* @__PURE__ */ new Date()).toISOString() });
345000
+ } catch {
345001
+ }
345000
345002
  }
345001
345003
  }
345002
345004
 
@@ -9,6 +9,8 @@ export interface RuntimeLifecycleState {
9
9
  active: true;
10
10
  }
11
11
  export declare function isRuntimeProcessAlive(pid: number): boolean;
12
+ /** Prepare crash-recovery markers asynchronously after the startup shell is visible. */
13
+ export declare function prepareRuntimeLifecycle(root: string, role?: RuntimeLifecycleRole): Promise<void>;
12
14
  /**
13
15
  * Claim this process/role as the current runtime owner.
14
16
  *
@@ -34,6 +34,7 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.isRuntimeProcessAlive = isRuntimeProcessAlive;
37
+ exports.prepareRuntimeLifecycle = prepareRuntimeLifecycle;
37
38
  exports.beginRuntimeLifecycle = beginRuntimeLifecycle;
38
39
  exports.markRuntimeLifecycleClean = markRuntimeLifecycleClean;
39
40
  exports.runtimeLifecycleState = runtimeLifecycleState;
@@ -41,6 +42,8 @@ const fs = __importStar(require("fs"));
41
42
  const path = __importStar(require("path"));
42
43
  const crypto_1 = require("crypto");
43
44
  const processStates = new Map();
45
+ const preparedPreviousStates = new Map();
46
+ const lifecyclePreparations = new Map();
44
47
  function stateKey(root, role) {
45
48
  return `${path.resolve(root)}\u0000${role}`;
46
49
  }
@@ -89,6 +92,50 @@ function readActiveStates(root, role) {
89
92
  return [];
90
93
  }
91
94
  }
95
+ /** Prepare crash-recovery markers asynchronously after the startup shell is visible. */
96
+ function prepareRuntimeLifecycle(root, role = 'main') {
97
+ const key = stateKey(root, role);
98
+ if (processStates.has(key) || preparedPreviousStates.has(key))
99
+ return Promise.resolve();
100
+ const current = lifecyclePreparations.get(key);
101
+ if (current)
102
+ return current.then(() => undefined);
103
+ const preparation = (async () => {
104
+ const directory = path.join(root, '.newmark-runtime');
105
+ let files;
106
+ try {
107
+ files = (await fs.promises.readdir(directory))
108
+ .filter(file => file.startsWith(`lifecycle-${role}`) && file.endsWith('.json'));
109
+ }
110
+ catch {
111
+ return [];
112
+ }
113
+ const active = [];
114
+ for (let offset = 0; offset < files.length; offset += 24) {
115
+ const states = await Promise.all(files.slice(offset, offset + 24).map(async (file) => {
116
+ const filePath = path.join(directory, file);
117
+ try {
118
+ const state = JSON.parse(await fs.promises.readFile(filePath, 'utf-8'));
119
+ if (state?.active === true)
120
+ return state;
121
+ }
122
+ catch {
123
+ // A corrupt marker cannot establish a live owner.
124
+ }
125
+ await fs.promises.unlink(filePath).catch(() => undefined);
126
+ return null;
127
+ }));
128
+ for (const state of states)
129
+ if (state)
130
+ active.push(state);
131
+ }
132
+ return active;
133
+ })();
134
+ lifecyclePreparations.set(key, preparation);
135
+ return preparation.then(states => {
136
+ preparedPreviousStates.set(key, states);
137
+ }).finally(() => lifecyclePreparations.delete(key));
138
+ }
92
139
  /**
93
140
  * Claim this process/role as the current runtime owner.
94
141
  *
@@ -101,7 +148,8 @@ function beginRuntimeLifecycle(root, role = 'main') {
101
148
  const existingProcessState = processStates.get(key);
102
149
  if (existingProcessState)
103
150
  return existingProcessState;
104
- const previousStates = readActiveStates(root, role);
151
+ const previousStates = preparedPreviousStates.get(key) || readActiveStates(root, role);
152
+ preparedPreviousStates.delete(key);
105
153
  const previousOwnerAlive = previousStates.some(previous => isRuntimeProcessAlive(Number(previous.pid)));
106
154
  const state = {
107
155
  role,
@@ -129,15 +177,16 @@ function markRuntimeLifecycleClean(root, role = 'main') {
129
177
  if (!current)
130
178
  return;
131
179
  try {
132
- writeState(root, role, {
133
- ...current,
134
- active: false,
135
- cleanExitAt: new Date().toISOString(),
136
- });
180
+ fs.unlinkSync(statePath(root, role, current.ownerId));
137
181
  }
138
182
  catch {
139
- // Leaving the marker active is safer than claiming a clean exit after a
140
- // failed durable write.
183
+ try {
184
+ writeState(root, role, { ...current, active: false, cleanExitAt: new Date().toISOString() });
185
+ }
186
+ catch {
187
+ // Leaving the marker active is safer than claiming a clean exit after a
188
+ // failed durable write.
189
+ }
141
190
  }
142
191
  }
143
192
  function runtimeLifecycleState(root, role = 'main') {
package/dist/main.js CHANGED
@@ -1803,12 +1803,10 @@ else {
1803
1803
  };
1804
1804
  let firstRunInitialized = false;
1805
1805
  if (!automationWakeMode) {
1806
- // Attempt one loads the real desktop immediately. The renderer keeps a
1807
- // startup cover above it until the main-process readiness acknowledgement,
1808
- // avoiding a startup.html -> index.html renderer navigation on the hot path.
1809
- startupAttempt = 1;
1810
- startupShellLoadedAt = Date.now();
1811
- startupWindow = createDesktopWindow(true, true, startupAttempt);
1806
+ // Keep Chromium's heavy index renderer off the event loop until the
1807
+ // lightweight startup shell is painted and durable recovery is ready.
1808
+ startupAttempt = 0;
1809
+ startupWindow = createDesktopWindow(false, true);
1812
1810
  mainWindow = startupWindow;
1813
1811
  createTray();
1814
1812
  }
@@ -1901,6 +1899,8 @@ else {
1901
1899
  recordStartup('first-run-init');
1902
1900
  }
1903
1901
  if (!agent) {
1902
+ await (0, runtimeLifecycle_1.prepareRuntimeLifecycle)(root, 'main');
1903
+ recordStartup('runtime-lifecycle-prepared');
1904
1904
  agent = new agent_1.Agent(root);
1905
1905
  mcpManager = new mcpManager_1.McpManager(root);
1906
1906
  activeAgentBackendMode = process.platform === 'win32' && agent.config.getBool('agent', 'run_in_wsl') ? 'wsl' : 'windows';
@@ -1102,6 +1102,9 @@ button.left-ws-item {
1102
1102
  }
1103
1103
  .conversation-selection-float.conversation-drag-following {
1104
1104
  transition: opacity 120ms var(--ease-out-expo) !important;
1105
+ transform-origin: center;
1106
+ translate: 0 var(--liquid-boundary-y, 0px);
1107
+ scale: calc(1 + var(--liquid-boundary-pull, 0) * .06) calc(1 - var(--liquid-boundary-pull, 0) * .025);
1105
1108
  }
1106
1109
  .conversation-drag-content {
1107
1110
  position: absolute;
@@ -3575,11 +3578,32 @@ button.todo-item { background: transparent; }
3575
3578
  #right-tabs { position: relative; }
3576
3579
  .left-nav-icon.liquid-tool-active,
3577
3580
  .lt-item.liquid-tool-active { background: var(--control-hover-bg); color: var(--text-bright); }
3581
+ .left-nav-icon.liquid-selection-covered,
3582
+ .lt-item.liquid-selection-covered,
3583
+ .left-ws-item.liquid-selection-covered,
3584
+ .tab-btn.liquid-selection-covered,
3585
+ .stab-btn.liquid-selection-covered,
3586
+ .mode-toggle-btn.liquid-selection-covered,
3587
+ .memory-lab-view-menu button.liquid-selection-covered {
3588
+ background: transparent !important;
3589
+ border-color: transparent !important;
3590
+ box-shadow: none !important;
3591
+ }
3592
+ .left-nav-icon:active,
3593
+ .lt-item:active,
3594
+ .left-ws-item:active,
3595
+ .tab-btn:active,
3596
+ .stab-btn:active,
3597
+ .mode-toggle-btn:active,
3598
+ .memory-lab-view-menu button:active { transform: none !important; scale: 1 !important; }
3578
3599
  .liquid-selection-float {
3579
3600
  --liquid-lift-scale: .94;
3580
3601
  --liquid-motion-angle: 0rad;
3581
3602
  --liquid-motion-stretch: 1;
3582
3603
  --liquid-motion-squash: 1;
3604
+ --liquid-boundary-x: 0px;
3605
+ --liquid-boundary-y: 0px;
3606
+ --liquid-boundary-pull: 0;
3583
3607
  position: absolute;
3584
3608
  z-index: 4;
3585
3609
  display: flex;
@@ -3599,15 +3623,17 @@ button.todo-item { background: transparent; }
3599
3623
  backdrop-filter: none;
3600
3624
  -webkit-backdrop-filter: none;
3601
3625
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.22), inset 0 -1px 0 rgba(0,0,0,0.18), 0 9px 24px rgba(0,0,0,0.28);
3602
- transition: top 240ms var(--ease-out-expo), left 240ms var(--ease-out-expo), width 240ms var(--ease-out-expo), height 240ms var(--ease-out-expo), opacity 80ms var(--ease-out-expo), transform 24ms linear;
3626
+ transition: top 240ms var(--ease-out-expo), left 240ms var(--ease-out-expo), width 240ms var(--ease-out-expo), height 240ms var(--ease-out-expo), opacity 80ms var(--ease-out-expo), transform 24ms linear, translate 110ms var(--ease-out-expo), scale 80ms linear;
3603
3627
  will-change: top, left, width, height, transform;
3628
+ translate: var(--liquid-boundary-x) var(--liquid-boundary-y);
3629
+ scale: calc(1 + var(--liquid-boundary-pull) * .06) calc(1 - var(--liquid-boundary-pull) * .025);
3604
3630
  }
3605
3631
  .liquid-selection-float.visible { opacity: 1; --liquid-lift-scale: 1; }
3606
3632
  .liquid-selection-float.liquid-selection-landing {
3607
3633
  opacity: 0;
3608
3634
  --liquid-lift-scale: .86;
3609
3635
  transform: scale(var(--liquid-lift-scale)) rotate(var(--liquid-motion-angle)) scaleX(var(--liquid-motion-stretch)) scaleY(var(--liquid-motion-squash)) rotate(calc(-1 * var(--liquid-motion-angle)));
3610
- transition: opacity 120ms var(--ease-out-expo), transform 120ms var(--ease-out-expo) !important;
3636
+ transition: opacity 180ms var(--ease-out-expo), transform 180ms var(--ease-out-expo) !important;
3611
3637
  }
3612
3638
  .liquid-selection-float.liquid-selection-viewport {
3613
3639
  position: fixed;
@@ -3617,6 +3643,51 @@ button.todo-item { background: transparent; }
3617
3643
  border: 0;
3618
3644
  }
3619
3645
  .liquid-selection-float.liquid-selection-primed { transition: none !important; }
3646
+ .liquid-selection-float.liquid-fixed-control-float {
3647
+ color: var(--text);
3648
+ box-shadow: var(--liquid-top-highlight), var(--liquid-inner-shadow), 0 5px 16px rgba(0,0,0,.14);
3649
+ }
3650
+ .liquid-selection-float.liquid-fixed-control-float.liquid-selection-primed {
3651
+ box-shadow: none;
3652
+ }
3653
+ .liquid-fixed-control-content {
3654
+ position: absolute;
3655
+ inset: 0;
3656
+ z-index: 2;
3657
+ display: flex;
3658
+ align-items: center;
3659
+ justify-content: center;
3660
+ gap: 6px;
3661
+ color: inherit;
3662
+ pointer-events: none;
3663
+ }
3664
+ .liquid-fixed-control-content * { color: inherit !important; }
3665
+ .liquid-fixed-control-content svg { fill: none; stroke: currentColor !important; }
3666
+ .liquid-fixed-source-covered {
3667
+ color: transparent !important;
3668
+ background: transparent !important;
3669
+ background-color: transparent !important;
3670
+ background-image: none !important;
3671
+ border-color: transparent !important;
3672
+ box-shadow: none !important;
3673
+ text-shadow: none !important;
3674
+ }
3675
+ .liquid-fixed-source-covered > * { visibility: hidden !important; }
3676
+ .liquid-fixed-source-covered::before,
3677
+ .liquid-fixed-source-covered::after {
3678
+ content: none !important;
3679
+ opacity: 0 !important;
3680
+ visibility: hidden !important;
3681
+ box-shadow: none !important;
3682
+ background: transparent !important;
3683
+ }
3684
+ [data-theme="light"] .liquid-selection-float.liquid-fixed-control-float {
3685
+ color: var(--text);
3686
+ box-shadow: inset 0 1px 0 rgba(255,255,255,.7), inset 0 -1px 0 rgba(42,52,82,.05), 0 4px 13px rgba(42,52,82,.08);
3687
+ }
3688
+ [data-theme="light"] .liquid-selection-float.liquid-fixed-control-float.liquid-selection-primed {
3689
+ box-shadow: none;
3690
+ }
3620
3691
  .liquid-selection-float.liquid-selection-viewport:popover-open { display: flex; }
3621
3692
  .liquid-selection-float::-webkit-scrollbar { display: none; }
3622
3693
  .liquid-selection-canvas {
@@ -3883,6 +3954,8 @@ button.todo-item { background: transparent; }
3883
3954
 
3884
3955
  #submit-btn:hover { transform: scale(1.08); box-shadow: 0 4px 20px rgba(91,120,255,0.5); }
3885
3956
  #submit-btn:active { transform: scale(0.92); transition: transform 80ms var(--ease-out-expo); }
3957
+ #submit-btn::after { display: none !important; }
3958
+ #submit-btn:active { transform: none; scale: 1; }
3886
3959
 
3887
3960
  #submit-btn.working {
3888
3961
  background: linear-gradient(135deg, #3a3a60 0%, #4a4a70 100%);
@@ -5733,6 +5806,26 @@ button:active:not(:disabled) {
5733
5806
  button:active:not(:disabled)::after { opacity: 1; }
5734
5807
  button:disabled { opacity: 0.5; }
5735
5808
 
5809
+ /* Unified glass controls are rendered by a real top-layer float. Their local
5810
+ pseudo glass is disabled so the original color block cannot look like a
5811
+ second, legacy press surface under the carried glass. */
5812
+ .left-nav-icon::after,
5813
+ .lt-item::after,
5814
+ .left-ws-item::after,
5815
+ .tab-btn::after,
5816
+ .stab-btn::after,
5817
+ .mode-toggle-btn::after,
5818
+ .memory-lab-view-menu button::after,
5819
+ .left-collapse-btn::after,
5820
+ .sec-btn::after,
5821
+ .right-open-btn::after,
5822
+ .shell-btn::after,
5823
+ .option-btn::after,
5824
+ .stack-icon-btn::after { display: none !important; }
5825
+ #left-ws-add::after { display: none !important; }
5826
+ #left-ws-add:active,
5827
+ .left-collapse-btn:active { transform: none !important; scale: 1 !important; }
5828
+
5736
5829
  /* Borderless utility actions stay visually quiet; they never gain a glass plate. */
5737
5830
  .msg-action-btn::after,
5738
5831
  .top-btn::after,
@@ -5799,7 +5892,25 @@ input[type="checkbox"].liquid-switch-dragging::before {
5799
5892
  box-shadow: var(--liquid-top-highlight), var(--liquid-inner-shadow), 0 7px 18px rgba(0,0,0,.32);
5800
5893
  transform: translateX(var(--liquid-switch-x)) translateY(-2px) scale(1.22);
5801
5894
  transition: none;
5895
+ opacity: 0;
5896
+ }
5897
+ .liquid-switch-float {
5898
+ position: fixed;
5899
+ z-index: 1200;
5900
+ pointer-events: none;
5901
+ width: 22px;
5902
+ height: 22px;
5903
+ border-radius: var(--radius-full);
5904
+ background: var(--liquid-refraction);
5905
+ backdrop-filter: blur(calc(var(--glass-blur-3) * 4)) saturate(145%);
5906
+ -webkit-backdrop-filter: blur(calc(var(--glass-blur-3) * 4)) saturate(145%);
5907
+ box-shadow: var(--liquid-top-highlight), var(--liquid-inner-shadow), 0 7px 18px rgba(0,0,0,.32);
5908
+ opacity: 0;
5909
+ transform: translate(-50%, -50%) scale(.86);
5910
+ transition: opacity 105ms var(--ease-out-expo), transform 105ms var(--ease-out-expo);
5802
5911
  }
5912
+ .liquid-switch-float.visible { opacity: 1; transform: translate(-50%, -50%) scale(1.22); }
5913
+ .liquid-switch-float.landing { opacity: 0; transform: translate(-50%, -50%) scale(.86); }
5803
5914
 
5804
5915
  /* Center composer and terminal stay solid. Only their left/right edge catches
5805
5916
  light so the glass sidebars remain the visual frame. */
@@ -13545,10 +13656,6 @@ var liquidKyantFragmentSource = '#version 300 es\nprecision highp float;\n' +
13545
13656
 
13546
13657
  function createKyantLiquidRenderer() {
13547
13658
  var canvas = document.createElement('canvas');
13548
- var displayCanvas = document.createElement('canvas');
13549
- displayCanvas.className = 'liquid-selection-canvas';
13550
- var displayContext = displayCanvas.getContext('2d', { alpha:true });
13551
- if (!displayContext) return null;
13552
13659
  var gl = canvas.getContext('webgl2', { alpha:true, antialias:false, premultipliedAlpha:true, powerPreference:'high-performance' });
13553
13660
  if (!gl) return null;
13554
13661
  var vs = compileLiquidShader(gl, gl.VERTEX_SHADER, liquidKyantVertexSource);
@@ -13588,8 +13695,8 @@ function createKyantLiquidRenderer() {
13588
13695
  gl.uniform1i(uniforms.content, 0);
13589
13696
  var renderer = {
13590
13697
  canvas: canvas,
13591
- displayCanvas: displayCanvas,
13592
- displayContext: displayContext,
13698
+ displayCanvas: null,
13699
+ displayContext: null,
13593
13700
  gl: gl,
13594
13701
  program: program,
13595
13702
  texture: texture,
@@ -13628,7 +13735,20 @@ function acquireKyantLiquidRenderer(float) {
13628
13735
  renderer.generation += 1;
13629
13736
  if (renderer.renderFrame) cancelAnimationFrame(renderer.renderFrame);
13630
13737
  renderer.renderFrame = 0;
13631
- renderer.displayCanvas.remove();
13738
+ if (renderer.displayCanvas) renderer.displayCanvas.remove();
13739
+ // The WebGL program/texture may be pooled, but the visible 2D canvas must
13740
+ // never move between floats. Chromium can retain the old promoted-layer
13741
+ // bounds when the same canvas is detached from a large float and mounted
13742
+ // into a smaller popover, producing modal-sized white compositor planes.
13743
+ var displayCanvas = document.createElement('canvas');
13744
+ displayCanvas.className = 'liquid-selection-canvas';
13745
+ var displayContext = displayCanvas.getContext('2d', { alpha:true });
13746
+ if (!displayContext) {
13747
+ renderer.owner = null;
13748
+ return null;
13749
+ }
13750
+ renderer.displayCanvas = displayCanvas;
13751
+ renderer.displayContext = displayContext;
13632
13752
  renderer.lastGeometry = null;
13633
13753
  renderer.pendingGeometry = null;
13634
13754
  return renderer;
@@ -13642,6 +13762,10 @@ function uploadKyantLiquidFrame(renderer, frame) {
13642
13762
  gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,gl.RGBA,gl.UNSIGNED_BYTE,frame.bitmap);
13643
13763
  renderer.textureReady = true;
13644
13764
  renderer.frameId = frame.id;
13765
+ // A new backdrop must be copied into the visible canvas even when the
13766
+ // float geometry has not changed. Otherwise the geometry cache skips the
13767
+ // draw and leaves the previously captured backdrop on screen.
13768
+ renderer.lastGeometry = null;
13645
13769
  return true;
13646
13770
  }
13647
13771
 
@@ -13665,6 +13789,7 @@ function attachKyantLiquidRenderer(float, frame) {
13665
13789
  var canvas = renderer.canvas;
13666
13790
  var displayCanvas = renderer.displayCanvas;
13667
13791
  var displayContext = renderer.displayContext;
13792
+ if (!displayCanvas || !displayContext) { float.dataset.kyantRenderer = 'display-unavailable'; return; }
13668
13793
  var gl = renderer.gl;
13669
13794
  var program = renderer.program;
13670
13795
  var texture = renderer.texture;
@@ -13672,8 +13797,11 @@ function attachKyantLiquidRenderer(float, frame) {
13672
13797
  var generation = renderer.generation;
13673
13798
  float.dataset.kyantRenderer = 'webgl2';
13674
13799
  float._kyantTextureReady = false;
13675
- float._kyantDrawReady = false;
13676
- delete float.dataset.kyantDrawReady;
13800
+ var hasVisibleDraw = float._kyantDrawReady === true && displayCanvas.parentNode === float;
13801
+ if (!hasVisibleDraw) {
13802
+ float._kyantDrawReady = false;
13803
+ delete float.dataset.kyantDrawReady;
13804
+ }
13677
13805
  float._renderKyantGlass = function(geometry, immediate) {
13678
13806
  renderer.pendingGeometry = geometry || null;
13679
13807
  if (!renderer.textureReady || renderer.owner !== float || !float.isConnected) return;
@@ -13703,6 +13831,8 @@ function attachKyantLiquidRenderer(float, frame) {
13703
13831
  if (canvas.height !== pixelHeight) canvas.height = pixelHeight;
13704
13832
  if (displayCanvas.width !== pixelWidth) displayCanvas.width = pixelWidth;
13705
13833
  if (displayCanvas.height !== pixelHeight) displayCanvas.height = pixelHeight;
13834
+ displayCanvas.style.width = width + 'px';
13835
+ displayCanvas.style.height = height + 'px';
13706
13836
  gl.viewport(0,0,pixelWidth,pixelHeight);
13707
13837
  gl.useProgram(program);
13708
13838
  function uniformChanged(key, values, apply) {
@@ -13743,6 +13873,8 @@ function attachKyantLiquidRenderer(float, frame) {
13743
13873
  renderer.lastGeometry = null;
13744
13874
  renderer.pendingGeometry = null;
13745
13875
  displayCanvas.remove();
13876
+ renderer.displayCanvas = null;
13877
+ renderer.displayContext = null;
13746
13878
  delete float._kyantRendererRef;
13747
13879
  };
13748
13880
  if (frame && frame.bitmap && renderer.owner === float && renderer.generation === generation && float.isConnected) {
@@ -13870,13 +14002,25 @@ function landLiquidSelectionFloat(float, cleanup, onComplete) {
13870
14002
  if (!float) { cleanup(); if (onComplete) onComplete(); return; }
13871
14003
  var reducedMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
13872
14004
  if (!float.isConnected) { cleanup(); if (onComplete) onComplete(); return; }
14005
+ var liftStartedAt = Number(float._liquidLiftStartedAt || performance.now());
14006
+ var remainingLift = reducedMotion ? 0 : Math.max(0, 360 - (performance.now() - liftStartedAt));
14007
+ if (remainingLift > 0) {
14008
+ setTimeout(function() { landLiquidSelectionFloat(float, cleanup, onComplete); }, remainingLift);
14009
+ return;
14010
+ }
13873
14011
  stopLiquidMotionTracking(float);
13874
14012
  float.classList.add('liquid-selection-landing');
13875
14013
  float._liquidLandingTimer = setTimeout(function() {
13876
14014
  cleanup();
13877
14015
  scheduleLiquidBackdropPrime();
13878
14016
  if (onComplete) onComplete();
13879
- }, reducedMotion ? 0 : 120);
14017
+ }, reducedMotion ? 0 : 180);
14018
+ }
14019
+
14020
+ function beginLiquidSelectionLift(float) {
14021
+ if (!float) return;
14022
+ if (!float._liquidLiftStartedAt) float._liquidLiftStartedAt = performance.now();
14023
+ float.classList.add('visible');
13880
14024
  }
13881
14025
 
13882
14026
  function wireLiquidMenuInteractions(menu) {
@@ -14008,7 +14152,7 @@ function wireLiquidMenuInteractions(menu) {
14008
14152
  if (float._liquidLandingTimer) clearTimeout(float._liquidLandingTimer);
14009
14153
  float._liquidLandingTimer = 0;
14010
14154
  float.classList.remove('liquid-selection-landing');
14011
- float.classList.add('visible');
14155
+ beginLiquidSelectionLift(float);
14012
14156
  position(target);
14013
14157
  } else {
14014
14158
  var selected = menu.querySelector('button.model-select-menu-option.selected, button.newmark-select-option.selected');
@@ -14024,7 +14168,7 @@ function wireLiquidMenuInteractions(menu) {
14024
14168
  requestAnimationFrame(function() {
14025
14169
  if (!float) return;
14026
14170
  float.classList.remove('liquid-selection-primed');
14027
- float.classList.add('visible');
14171
+ beginLiquidSelectionLift(float);
14028
14172
  requestAnimationFrame(function() { if (float) position(target); });
14029
14173
  });
14030
14174
  }
@@ -14059,6 +14203,16 @@ function wireLiquidRailInteractions(container, selector) {
14059
14203
  }
14060
14204
  function position(item) {
14061
14205
  if (!item || !float) return;
14206
+ float.style.setProperty('--liquid-boundary-x', '0px');
14207
+ float.style.setProperty('--liquid-boundary-y', '0px');
14208
+ float.style.setProperty('--liquid-boundary-pull', '0');
14209
+ if (float._liquidCovered && float._liquidCovered !== item) {
14210
+ float._liquidCovered.classList.remove('liquid-selection-covered');
14211
+ }
14212
+ if (item !== source) {
14213
+ item.classList.add('liquid-selection-covered');
14214
+ float._liquidCovered = item;
14215
+ }
14062
14216
  if (float.classList.contains('liquid-selection-viewport')) {
14063
14217
  var rect = item.getBoundingClientRect();
14064
14218
  var edge = liquidInteractionEdgePx();
@@ -14103,6 +14257,8 @@ function wireLiquidRailInteractions(container, selector) {
14103
14257
  var minCenter = Math.min.apply(null, centers);
14104
14258
  var maxCenter = Math.max.apply(null, centers);
14105
14259
  var projectedCenter = Math.max(minCenter, Math.min(maxCenter, pointerAxis));
14260
+ var blockedDelta = pointerAxis < minCenter ? pointerAxis - minCenter : pointerAxis > maxCenter ? pointerAxis - maxCenter : 0;
14261
+ var resisted = Math.sign(blockedDelta) * Math.sqrt(Math.abs(blockedDelta)) * 0.6;
14106
14262
  var edge = liquidInteractionEdgePx();
14107
14263
  var left = horizontal ? projectedCenter - rect.width / 2 - edge : rect.left - edge;
14108
14264
  var top = horizontal ? rect.top - edge : projectedCenter - rect.height / 2 - edge;
@@ -14110,6 +14266,14 @@ function wireLiquidRailInteractions(container, selector) {
14110
14266
  float.style.top = top + 'px';
14111
14267
  float.style.width = (rect.width + edge * 2) + 'px';
14112
14268
  float.style.height = (rect.height + edge * 2) + 'px';
14269
+ float.style.setProperty('--liquid-boundary-x', horizontal ? resisted.toFixed(2) + 'px' : '0px');
14270
+ float.style.setProperty('--liquid-boundary-y', horizontal ? '0px' : resisted.toFixed(2) + 'px');
14271
+ float.style.setProperty('--liquid-boundary-pull', Math.min(1, Math.abs(resisted) / 28).toFixed(3));
14272
+ if (target && target !== source) {
14273
+ if (float._liquidCovered && float._liquidCovered !== target) float._liquidCovered.classList.remove('liquid-selection-covered');
14274
+ target.classList.add('liquid-selection-covered');
14275
+ float._liquidCovered = target;
14276
+ }
14113
14277
  }
14114
14278
  function detachWindowTracking() {
14115
14279
  window.removeEventListener('pointermove', onPointerMove, true);
@@ -14119,6 +14283,7 @@ function wireLiquidRailInteractions(container, selector) {
14119
14283
  function clear() {
14120
14284
  detachWindowTracking();
14121
14285
  if (source) source.classList.remove('liquid-selection-source');
14286
+ if (float && float._liquidCovered) float._liquidCovered.classList.remove('liquid-selection-covered');
14122
14287
  stopLiquidMotionTracking(float);
14123
14288
  if (float && float._liquidLandingTimer) clearTimeout(float._liquidLandingTimer);
14124
14289
  if (float && float._releaseKyantGlass) float._releaseKyantGlass();
@@ -14142,6 +14307,9 @@ function wireLiquidRailInteractions(container, selector) {
14142
14307
  try { container.releasePointerCapture(pointer); } catch (_) {}
14143
14308
  pointer = null;
14144
14309
  if (commit) {
14310
+ float.style.setProperty('--liquid-boundary-x', '0px');
14311
+ float.style.setProperty('--liquid-boundary-y', '0px');
14312
+ float.style.setProperty('--liquid-boundary-pull', '0');
14145
14313
  position(commit);
14146
14314
  }
14147
14315
  waitForLiquidSelectionArrival(float, function() {
@@ -14178,7 +14346,7 @@ function wireLiquidRailInteractions(container, selector) {
14178
14346
  if (float._liquidLandingTimer) clearTimeout(float._liquidLandingTimer);
14179
14347
  float._liquidLandingTimer = 0;
14180
14348
  float.classList.remove('liquid-selection-landing');
14181
- float.classList.add('visible');
14349
+ beginLiquidSelectionLift(float);
14182
14350
  position(target);
14183
14351
  } else {
14184
14352
  source = container.querySelector('.liquid-tool-active') || container.querySelector(selector + '.active') || pressed;
@@ -14193,7 +14361,7 @@ function wireLiquidRailInteractions(container, selector) {
14193
14361
  requestAnimationFrame(function() {
14194
14362
  if (!float) return;
14195
14363
  float.classList.remove('liquid-selection-primed');
14196
- float.classList.add('visible');
14364
+ beginLiquidSelectionLift(float);
14197
14365
  requestAnimationFrame(function() { if (float) position(target); });
14198
14366
  });
14199
14367
  }
@@ -14208,12 +14376,238 @@ function wireLiquidRailInteractions(container, selector) {
14208
14376
  }, true);
14209
14377
  }
14210
14378
 
14379
+ // Legacy glass buttons used to rely on local :active scaling. Bridge only the
14380
+ // explicitly glass interaction classes to the same single-float lifecycle as
14381
+ // rails and menus; structural/content buttons are intentionally excluded.
14382
+ function wireLegacyLiquidButtons() {
14383
+ // Disabled: the broad document-level bridge could leave source controls
14384
+ // hidden when their click rebuilt or closed the owning surface. Fixed
14385
+ // controls are migrated individually instead of mutating every matching
14386
+ // button through one global capture listener.
14387
+ return;
14388
+ var selector = [
14389
+ '.top-btn', '#left-ws-add', '.left-collapse-btn', '.sec-btn', '.right-open-btn', '#submit-btn',
14390
+ '.shell-btn', '.option-btn', '.stack-icon-btn'
14391
+ ].join(',');
14392
+ var active = null;
14393
+ function clearFloat(commit) {
14394
+ if (!active) return;
14395
+ var item = active;
14396
+ active = null;
14397
+ landLiquidSelectionFloat(item.float, function() {
14398
+ item.source.classList.remove('liquid-click-source');
14399
+ item.source.style.removeProperty('visibility');
14400
+ delete item.source.dataset.liquidClickPending;
14401
+ if (item.float._releaseKyantGlass) item.float._releaseKyantGlass();
14402
+ if (item.float.parentNode) item.float.parentNode.removeChild(item.float);
14403
+ }, function() {
14404
+ if (!commit || !item.source.isConnected) return;
14405
+ item.source.dataset.liquidClickReplayed = 'true';
14406
+ item.source.click();
14407
+ });
14408
+ }
14409
+ document.addEventListener('pointerdown', function(event) {
14410
+ var source = event.target && event.target.closest ? event.target.closest(selector) : null;
14411
+ if (!source || source.disabled || event.button !== 0 ||
14412
+ source.closest('.liquid-selection-float, #mode-toggle, #left-tool-surface, #left-thumb, #left-ws-list, #right-tabs, .model-select-menu, .newmark-select-menu')) return;
14413
+ event.preventDefault();
14414
+ event.stopPropagation();
14415
+ if (active) clearFloat(false);
14416
+ var rect = source.getBoundingClientRect();
14417
+ var edge = liquidInteractionEdgePx();
14418
+ var float = document.createElement('div');
14419
+ float.className = 'liquid-selection-float liquid-selection-primed';
14420
+ var floatContent = document.createElement('div');
14421
+ floatContent.className = 'liquid-click-content';
14422
+ Array.from(source.childNodes).forEach(function(node) {
14423
+ floatContent.appendChild(node.cloneNode(true));
14424
+ });
14425
+ float.appendChild(floatContent);
14426
+ float.style.left = (rect.left - edge) + 'px';
14427
+ float.style.top = (rect.top - edge) + 'px';
14428
+ float.style.width = (rect.width + edge * 2) + 'px';
14429
+ float.style.height = (rect.height + edge * 2) + 'px';
14430
+ float._liquidTargetRect = { left: rect.left - edge, top: rect.top - edge, width: rect.width + edge * 2, height: rect.height + edge * 2 };
14431
+ mountLiquidViewportFloat(float);
14432
+ active = { source: source, float: float, pointer: event.pointerId, rect: rect, startX: event.clientX, startY: event.clientY };
14433
+ source.dataset.liquidClickPending = 'true';
14434
+ source.classList.add('liquid-click-source');
14435
+ showLiquidViewportFloat(float);
14436
+ requestAnimationFrame(function() {
14437
+ if (!active || active.float !== float) return;
14438
+ float.classList.remove('liquid-selection-primed');
14439
+ beginLiquidSelectionLift(float);
14440
+ });
14441
+ function onMove(move) {
14442
+ if (!active || active.float !== float || move.pointerId !== event.pointerId) return;
14443
+ var dx = move.clientX - active.startX;
14444
+ var dy = move.clientY - active.startY;
14445
+ var distance = Math.hypot(dx, dy);
14446
+ if (distance < 2) return;
14447
+ move.preventDefault();
14448
+ var resistedDistance = Math.min(4.5, Math.sqrt(distance) * 0.625);
14449
+ var ratio = resistedDistance / Math.max(1, distance);
14450
+ float.style.setProperty('--liquid-boundary-x', (dx * ratio).toFixed(2) + 'px');
14451
+ float.style.setProperty('--liquid-boundary-y', (dy * ratio).toFixed(2) + 'px');
14452
+ float.style.setProperty('--liquid-boundary-pull', Math.min(1, resistedDistance / 18).toFixed(3));
14453
+ }
14454
+ function finish(commit) {
14455
+ document.removeEventListener('pointermove', onMove, true);
14456
+ document.removeEventListener('pointerup', onUp, true);
14457
+ document.removeEventListener('pointercancel', onCancel, true);
14458
+ float.style.setProperty('--liquid-boundary-x', '0px');
14459
+ float.style.setProperty('--liquid-boundary-y', '0px');
14460
+ float.style.setProperty('--liquid-boundary-pull', '0');
14461
+ clearFloat(commit);
14462
+ }
14463
+ function onUp(up) { if (up.pointerId === event.pointerId) finish(true); }
14464
+ function onCancel(cancel) { if (cancel.pointerId === event.pointerId) finish(false); }
14465
+ document.addEventListener('pointermove', onMove, true);
14466
+ document.addEventListener('pointerup', onUp, true);
14467
+ document.addEventListener('pointercancel', onCancel, true);
14468
+ }, true);
14469
+ document.addEventListener('click', function(event) {
14470
+ var source = event.target && event.target.closest ? event.target.closest(selector) : null;
14471
+ if (!source) return;
14472
+ if (source.dataset.liquidClickReplayed === 'true') {
14473
+ delete source.dataset.liquidClickReplayed;
14474
+ return;
14475
+ }
14476
+ if (source.dataset.liquidClickPending === 'true') {
14477
+ event.preventDefault();
14478
+ event.stopImmediatePropagation();
14479
+ return;
14480
+ }
14481
+ if (active && active.source === source) {
14482
+ event.preventDefault();
14483
+ event.stopImmediatePropagation();
14484
+ }
14485
+ }, true);
14486
+ }
14487
+
14488
+ function wireFixedPrimaryLiquidButtons() {
14489
+ if (document.documentElement.dataset.fixedPrimaryLiquidWired === 'true') return;
14490
+ document.documentElement.dataset.fixedPrimaryLiquidWired = 'true';
14491
+ var selector = [
14492
+ '#left-ws-add', '.left-collapse-btn', '.sec-btn', '.et-btn.primary',
14493
+ '.right-open-btn', '.shell-btn', '.option-btn', '.stack-icon-btn',
14494
+ '#submit-btn'
14495
+ ].join(',');
14496
+ var excludedSelector = [
14497
+ '.msg-action-btn', '.conv-more-btn', '.provider-icon-btn',
14498
+ '.work-review-toggle', '.conversation-work-run-head',
14499
+ '.shell-block-header', '.diff-block-header', '.work-review-head',
14500
+ '.message-edit-submit', '.message-edit-cancel'
14501
+ ].join(',');
14502
+ document.addEventListener('pointerdown', function(event) {
14503
+ var source = event.target && event.target.closest ? event.target.closest(selector) : null;
14504
+ if (!source || source.matches(excludedSelector) || source.disabled || event.button !== 0 || source.dataset.fixedLiquidActive === 'true') return;
14505
+ event.preventDefault();
14506
+ event.stopImmediatePropagation();
14507
+ source.dataset.fixedLiquidActive = 'true';
14508
+ var rect = source.getBoundingClientRect();
14509
+ var edge = liquidInteractionEdgePx();
14510
+ var float = document.createElement('div');
14511
+ float.className = 'liquid-selection-float liquid-selection-primed liquid-fixed-control-float';
14512
+ var content = document.createElement('div');
14513
+ content.className = 'liquid-fixed-control-content';
14514
+ Array.from(source.childNodes).forEach(function(node) { content.appendChild(node.cloneNode(true)); });
14515
+ float.appendChild(content);
14516
+ float.style.left = (rect.left - edge) + 'px';
14517
+ float.style.top = (rect.top - edge) + 'px';
14518
+ float.style.width = (rect.width + edge * 2) + 'px';
14519
+ float.style.height = (rect.height + edge * 2) + 'px';
14520
+ float._liquidTargetRect = { left: rect.left - edge, top: rect.top - edge, width: rect.width + edge * 2, height: rect.height + edge * 2 };
14521
+ mountLiquidViewportFloat(float);
14522
+ showLiquidViewportFloat(float);
14523
+ source.classList.add('liquid-fixed-source-covered');
14524
+ requestAnimationFrame(function() {
14525
+ if (!float.isConnected) return;
14526
+ float.classList.remove('liquid-selection-primed');
14527
+ beginLiquidSelectionLift(float);
14528
+ });
14529
+ var startX = event.clientX;
14530
+ var startY = event.clientY;
14531
+ var finishing = false;
14532
+ function move(value) {
14533
+ if (value.pointerId !== event.pointerId || !float.isConnected) return;
14534
+ var dx = value.clientX - startX;
14535
+ var dy = value.clientY - startY;
14536
+ var distance = Math.hypot(dx, dy);
14537
+ if (distance < 2) return;
14538
+ value.preventDefault();
14539
+ var resistedDistance = Math.min(4.5, Math.sqrt(distance) * .625);
14540
+ var ratio = resistedDistance / Math.max(1, distance);
14541
+ float.style.setProperty('--liquid-boundary-x', (dx * ratio).toFixed(2) + 'px');
14542
+ float.style.setProperty('--liquid-boundary-y', (dy * ratio).toFixed(2) + 'px');
14543
+ float.style.setProperty('--liquid-boundary-pull', Math.min(1, resistedDistance / 18).toFixed(3));
14544
+ }
14545
+ function finish(commit) {
14546
+ if (finishing) return;
14547
+ finishing = true;
14548
+ window.removeEventListener('pointermove', move, true);
14549
+ window.removeEventListener('pointerup', up, true);
14550
+ window.removeEventListener('pointercancel', cancel, true);
14551
+ window.removeEventListener('blur', blur, true);
14552
+ window.removeEventListener('pagehide', pagehide, true);
14553
+ float.style.setProperty('--liquid-boundary-x', '0px');
14554
+ float.style.setProperty('--liquid-boundary-y', '0px');
14555
+ float.style.setProperty('--liquid-boundary-pull', '0');
14556
+ landLiquidSelectionFloat(float, function() {
14557
+ source.classList.remove('liquid-fixed-source-covered');
14558
+ delete source.dataset.fixedLiquidActive;
14559
+ if (float._releaseKyantGlass) float._releaseKyantGlass();
14560
+ if (float.parentNode) float.parentNode.removeChild(float);
14561
+ }, function() {
14562
+ if (!commit || !source.isConnected) return;
14563
+ source.dataset.fixedLiquidReplay = 'true';
14564
+ source.click();
14565
+ });
14566
+ }
14567
+ function up(value) { if (value.pointerId === event.pointerId) finish(true); }
14568
+ function cancel(value) { if (value.pointerId === event.pointerId) finish(false); }
14569
+ function blur() { finish(false); }
14570
+ function pagehide() { finish(false); }
14571
+ window.addEventListener('pointermove', move, true);
14572
+ window.addEventListener('pointerup', up, true);
14573
+ window.addEventListener('pointercancel', cancel, true);
14574
+ window.addEventListener('blur', blur, true);
14575
+ window.addEventListener('pagehide', pagehide, true);
14576
+ setTimeout(function() {
14577
+ if (source.dataset.fixedLiquidActive !== 'true') return;
14578
+ finish(false);
14579
+ }, 1200);
14580
+ }, true);
14581
+ document.addEventListener('click', function(event) {
14582
+ var source = event.target && event.target.closest ? event.target.closest(selector) : null;
14583
+ if (!source) return;
14584
+ if (source.dataset.fixedLiquidReplay === 'true') {
14585
+ delete source.dataset.fixedLiquidReplay;
14586
+ return;
14587
+ }
14588
+ if (source.dataset.fixedLiquidActive === 'true') {
14589
+ event.preventDefault();
14590
+ event.stopImmediatePropagation();
14591
+ }
14592
+ }, true);
14593
+ }
14594
+
14211
14595
  requestAnimationFrame(function() {
14596
+ document.querySelectorAll('.liquid-click-source').forEach(function(source) {
14597
+ source.classList.remove('liquid-click-source');
14598
+ source.style.removeProperty('visibility');
14599
+ source.style.removeProperty('opacity');
14600
+ });
14601
+ document.querySelectorAll('[data-liquid-click-pending]').forEach(function(source) {
14602
+ delete source.dataset.liquidClickPending;
14603
+ });
14212
14604
  wireLiquidRailInteractions(document.getElementById('mode-toggle'), '.mode-toggle-btn[data-mode]');
14213
14605
  wireLiquidRailInteractions(document.getElementById('left-tool-surface'), '.left-nav-icon');
14214
14606
  wireLiquidRailInteractions(document.getElementById('left-thumb'), '.lt-item');
14215
14607
  wireLiquidRailInteractions(document.getElementById('left-ws-list'), '.left-ws-item');
14216
14608
  wireLiquidRailInteractions(document.getElementById('right-tabs'), '.tab-btn[data-tab]');
14609
+ wireLegacyLiquidButtons();
14610
+ wireFixedPrimaryLiquidButtons();
14217
14611
  });
14218
14612
 
14219
14613
  // Checkbox switches use one pointer-captured glass thumb that follows the
@@ -21470,9 +21864,15 @@ function followConversationDragPointer() {
21470
21864
  var minTop = firstRect.top - rowRect.height;
21471
21865
  var maxTop = Math.max(minTop, lastRect.bottom);
21472
21866
  var trackTop = Math.max(minTop, Math.min(maxTop, projectedTop));
21867
+ // Keep the reorder anchor fixed at the edge, but give a held glass float a
21868
+ // damped visual pull so blocked dragging still feels elastic and alive.
21869
+ var blockedDelta = projectedTop < minTop ? projectedTop - minTop : projectedTop > maxTop ? projectedTop - maxTop : 0;
21870
+ var resisted = Math.sign(blockedDelta) * Math.sqrt(Math.abs(blockedDelta)) * 0.6;
21473
21871
  var edge = liquidInteractionEdgePx();
21474
21872
  drag.float.style.left = (rowRect.left - edge) + 'px';
21475
21873
  drag.float.style.top = (trackTop - edge) + 'px';
21874
+ drag.float.style.setProperty('--liquid-boundary-y', resisted.toFixed(2) + 'px');
21875
+ drag.float.style.setProperty('--liquid-boundary-pull', Math.min(1, Math.abs(resisted) / 28).toFixed(3));
21476
21876
  if (drag.float._renderKyantGlass) drag.float._renderKyantGlass();
21477
21877
  }
21478
21878
 
@@ -21583,7 +21983,7 @@ window.animateConversationGlassTo = function(target, options) {
21583
21983
  requestAnimationFrame(function() {
21584
21984
  if (conversationGlassFlight.generation !== generation || !float.isConnected) return;
21585
21985
  float.classList.remove('liquid-selection-primed');
21586
- float.classList.add('visible');
21986
+ beginLiquidSelectionLift(float);
21587
21987
  place(target);
21588
21988
  });
21589
21989
  window.setLiquidSidebarGestureLock('conversation-flight', true);
@@ -8383,7 +8383,7 @@ var require_createWorker = __commonJS({
8383
8383
  ...defaultOptions,
8384
8384
  ..._options
8385
8385
  });
8386
- const promises2 = {};
8386
+ const promises3 = {};
8387
8387
  const currentLangs = typeof langs === "string" ? langs.split("+") : langs;
8388
8388
  let currentOem = oem;
8389
8389
  let currentConfig = config;
@@ -8403,7 +8403,7 @@ var require_createWorker = __commonJS({
8403
8403
  const startJob = ({ id: jobId, action, payload }) => new Promise((resolve16, reject) => {
8404
8404
  log2(`[${id}]: Start ${jobId}, action=${action}`);
8405
8405
  const promiseId = `${action}-${jobId}`;
8406
- promises2[promiseId] = { resolve: resolve16, reject };
8406
+ promises3[promiseId] = { resolve: resolve16, reject };
8407
8407
  send(worker, {
8408
8408
  workerId: id,
8409
8409
  jobId,
@@ -8508,11 +8508,11 @@ var require_createWorker = __commonJS({
8508
8508
  const promiseId = `${action}-${jobId}`;
8509
8509
  if (status === "resolve") {
8510
8510
  log2(`[${workerId}]: Complete ${jobId}`);
8511
- promises2[promiseId].resolve({ jobId, data });
8512
- delete promises2[promiseId];
8511
+ promises3[promiseId].resolve({ jobId, data });
8512
+ delete promises3[promiseId];
8513
8513
  } else if (status === "reject") {
8514
- promises2[promiseId].reject(data);
8515
- delete promises2[promiseId];
8514
+ promises3[promiseId].reject(data);
8515
+ delete promises3[promiseId];
8516
8516
  if (action === "load") workerResReject(data);
8517
8517
  if (errorHandler) {
8518
8518
  errorHandler(data);
@@ -54006,18 +54006,18 @@ var require_proxy_agent = __commonJS({
54006
54006
  }
54007
54007
  }
54008
54008
  [kClose]() {
54009
- const promises2 = [this[kAgent].close()];
54009
+ const promises3 = [this[kAgent].close()];
54010
54010
  if (this[kClient]) {
54011
- promises2.push(this[kClient].close());
54011
+ promises3.push(this[kClient].close());
54012
54012
  }
54013
- return Promise.all(promises2);
54013
+ return Promise.all(promises3);
54014
54014
  }
54015
54015
  [kDestroy]() {
54016
- const promises2 = [this[kAgent].destroy()];
54016
+ const promises3 = [this[kAgent].destroy()];
54017
54017
  if (this[kClient]) {
54018
- promises2.push(this[kClient].destroy());
54018
+ promises3.push(this[kClient].destroy());
54019
54019
  }
54020
- return Promise.all(promises2);
54020
+ return Promise.all(promises3);
54021
54021
  }
54022
54022
  };
54023
54023
  function buildHeaders(headers) {
@@ -344927,6 +344927,7 @@ var fs24 = __toESM(require("fs"));
344927
344927
  var path27 = __toESM(require("path"));
344928
344928
  var import_crypto14 = require("crypto");
344929
344929
  var processStates = /* @__PURE__ */ new Map();
344930
+ var preparedPreviousStates = /* @__PURE__ */ new Map();
344930
344931
  function stateKey(root2, role) {
344931
344932
  return `${path27.resolve(root2)}\0${role}`;
344932
344933
  }
@@ -344972,7 +344973,8 @@ function beginRuntimeLifecycle(root2, role = "main") {
344972
344973
  const key3 = stateKey(root2, role);
344973
344974
  const existingProcessState = processStates.get(key3);
344974
344975
  if (existingProcessState) return existingProcessState;
344975
- const previousStates = readActiveStates(root2, role);
344976
+ const previousStates = preparedPreviousStates.get(key3) || readActiveStates(root2, role);
344977
+ preparedPreviousStates.delete(key3);
344976
344978
  const previousOwnerAlive = previousStates.some((previous) => isRuntimeProcessAlive(Number(previous.pid)));
344977
344979
  const state = {
344978
344980
  role,
@@ -344995,12 +344997,12 @@ function markRuntimeLifecycleClean(root2, role = "main") {
344995
344997
  const current = processStates.get(key3);
344996
344998
  if (!current) return;
344997
344999
  try {
344998
- writeState(root2, role, {
344999
- ...current,
345000
- active: false,
345001
- cleanExitAt: (/* @__PURE__ */ new Date()).toISOString()
345002
- });
345000
+ fs24.unlinkSync(statePath(root2, role, current.ownerId));
345003
345001
  } catch {
345002
+ try {
345003
+ writeState(root2, role, { ...current, active: false, cleanExitAt: (/* @__PURE__ */ new Date()).toISOString() });
345004
+ } catch {
345005
+ }
345004
345006
  }
345005
345007
  }
345006
345008
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "newmark-agent",
3
3
  "productName": "Newmark Agent",
4
- "version": "0.5.9",
4
+ "version": "0.5.11",
5
5
  "description": "Newmark Agent — Portable AI coding agent with rich GUI and CLI (TypeScript)",
6
6
  "homepage": "https://github.com/positer/Newmark-Agent",
7
7
  "repository": {
@@ -82,6 +82,7 @@
82
82
  "test:tool-process": "npm run build && node dist/tests/toolProcessVerify.js",
83
83
  "test:real-tool-concurrency": "npm run build && node dist/tests/realProviderToolConcurrencyStress.js",
84
84
  "test:startup-prewarm": "npm run build && node dist/tests/startupPrewarmVerify.js",
85
+ "test:startup-responsiveness": "npm run build && node dist/tests/runtimeLifecycleStartupVerify.js && node dist/tests/startupPrewarmVerify.js && node scripts/measure-startup-responsiveness.cjs",
85
86
  "test:browser-use-electron": "npm run build && electron dist/tests/browserUseElectronVerify.js",
86
87
  "test:dev009": "npm run build && node dist/tests/dev009Verify.js && node dist/tests/runtimeIsolationVerify.js && node dist/tests/guideWorkRunVerify.js && node dist/tests/guideUiReconcileVerify.js && node dist/tests/queueAttachmentIsolationVerify.js && node dist/tests/workspaceMenuVerify.js && node dist/tests/userImagePersistenceVerify.js && node dist/tests/visualPreferencesVerify.js && node dist/tests/browserUseVerify.js && node dist/tests/toolProcessVerify.js && node dist/tests/startupPrewarmVerify.js && node dist/tests/pdfPreviewServerVerify.js && node dist/tests/editorLifecycleVerify.js && node dist/tests/computerUsePerformanceVerify.js && electron dist/tests/browserUseElectronVerify.js",
87
88
  "test:dev008": "npm run build && node dist/tests/dev008-subagent.js",