@trusty-squire/mcp 0.5.4 → 0.5.6

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.
@@ -10,10 +10,8 @@
10
10
  google-login.ts runHeadlessChrome). Deliberately uses ONLY noVNC's
11
11
  stable RFB API — the `RFB` default export, its constructor, the
12
12
  `scaleViewport`/`resizeSession` properties, the
13
- connect/disconnect/securityfailure events, and `rfb.focus()` (used
14
- to pop the mobile soft keyboard) — all stable across every noVNC
15
- 1.x release, so this page survives whatever version the host
16
- distro's `novnc` package pinned.
13
+ connect/disconnect/securityfailure events, and `rfb.sendKey()`
14
+ all stable across every noVNC 1.x release.
17
15
  -->
18
16
  <style>
19
17
  html, body { margin: 0; height: 100%; background: #0f1115; color: #e6e8ec;
@@ -32,36 +30,42 @@
32
30
  #dot.ok { background: #3fb950; }
33
31
  #dot.err { background: #f85149; }
34
32
  #screen { flex: 1; position: relative; background: #0f1115; min-height: 0; }
35
- #msg { position: absolute; top: 50%; left: 0; right: 0; text-align: center;
36
- transform: translateY(-50%); color: #9aa0ab; font-size: 14px; padding: 0 24px; }
37
- /* Show-keyboard button. The remote VNC view is just pixels the OS
38
- can't tell there's a typeable field, so a normal tap inside the
39
- remote Chrome doesn't pop the soft keyboard. This button focuses
40
- the hidden #kbInput element below; the OS sees an actual editable
41
- input gain focus and pops the keyboard. Each character the user
42
- types into #kbInput is forwarded to the VNC stream via
43
- rfb.sendKey() and the input is cleared, so the local input
44
- never accumulates the user's password. */
45
- #kb { position: absolute; right: 16px; bottom: 16px; width: 52px; height: 52px;
33
+ /* Overlay siblings of #screen `position: fixed` against the
34
+ viewport, NOT positioned inside #screen. RFB appends a <canvas>
35
+ child to #screen at connect time, and that canvas can cover any
36
+ absolutely-positioned children even with z-index. Sibling +
37
+ fixed keeps them above the canvas unconditionally. */
38
+ #msg { position: fixed; top: 50%; left: 0; right: 0; text-align: center;
39
+ transform: translateY(-50%); color: #9aa0ab; font-size: 14px; padding: 0 24px;
40
+ pointer-events: none; z-index: 9; }
41
+ /* The keyboard button. Always visible (no media-query gating
42
+ desktop users see a tiny ⌨ they ignore; better than a phone user
43
+ finding nothing). Position fixed against the viewport so the OS
44
+ gesture nav area at the bottom can't swallow taps meant for it. */
45
+ #kb {
46
+ position: fixed; right: 16px;
47
+ bottom: max(96px, env(safe-area-inset-bottom, 16px));
48
+ width: 64px; height: 64px;
49
+ display: flex; align-items: center; justify-content: center;
46
50
  border-radius: 50%; border: none; background: #4f46e5; color: #fff;
47
- font-size: 24px; line-height: 1; box-shadow: 0 4px 14px rgba(0, 0, 0, 0.4);
48
- cursor: pointer; z-index: 10; display: none;
51
+ font-size: 28px; line-height: 1; box-shadow: 0 4px 14px rgba(0, 0, 0, 0.4);
52
+ cursor: pointer; z-index: 20;
49
53
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
54
+ transition: background 120ms, transform 80ms;
50
55
  }
51
- #kb:active { transform: scale(0.96); }
52
- /* Only show the button on touch-capable devices — desktops already
53
- have a hardware keyboard and the button just clutters the view. */
54
- @media (hover: none) and (pointer: coarse) {
55
- #kb.ready { display: flex; align-items: center; justify-content: center; }
56
- }
57
- /* The hidden input the button focuses. Positioned in the viewport
58
- so iOS scrolls to it on focus (off-screen positioning is known to
59
- break focus() on iOS Safari), but visually neutered. */
56
+ #kb:active, #kb.tapped { transform: scale(0.92); background: #3fb950; }
57
+ /* Hidden input the button focuses. The noVNC-canonical pattern:
58
+ 1×1 px, positioned off-screen, matching foreground+background so
59
+ any flicker is invisible, z-index: -1 so it can't intercept any
60
+ tap. iOS Safari refuses to pop the soft keyboard for an element
61
+ it considers "invisible" — opacity:0 is one of those triggers —
62
+ but a 1px element positioned off-screen counts as visible enough. */
60
63
  #kbInput {
61
- position: absolute; right: 16px; bottom: 16px; width: 52px; height: 52px;
62
- opacity: 0; pointer-events: none; border: none; padding: 0; margin: 0;
63
- caret-color: transparent; background: transparent; color: transparent;
64
- z-index: 5;
64
+ position: fixed; left: -40px; top: 0;
65
+ width: 1px; height: 1px;
66
+ background: #fff; color: #fff; caret-color: transparent;
67
+ border: 0; padding: 0; margin: 0;
68
+ z-index: -1;
65
69
  }
66
70
  </style>
67
71
  </head>
@@ -71,16 +75,17 @@
71
75
  <b>Trusty Squire</b>
72
76
  <span class="sub">— sign in to your account, then return to your terminal.</span>
73
77
  </div>
74
- <div id="screen">
75
- <div id="msg">Connecting to the secure login window&hellip;</div>
76
- <!-- inputmode=text + autocorrect/autocapitalize/spellcheck off so the
77
- soft keyboard never offers autocomplete suggestions for a typed
78
- password, and never enriches characters before we forward them. -->
79
- <input id="kbInput" type="text" inputmode="text" autocomplete="off"
80
- autocorrect="off" autocapitalize="off" spellcheck="false"
81
- aria-hidden="true" tabindex="-1" />
82
- <button id="kb" type="button" aria-label="Show keyboard">⌨</button>
83
- </div>
78
+ <div id="screen"></div>
79
+ <!-- Overlays as body-level siblings, not children of #screen — see
80
+ the #msg / #kb CSS comments above. -->
81
+ <div id="msg">Connecting to the secure login window&hellip;</div>
82
+ <!-- inputmode=text + autocorrect/autocapitalize/spellcheck off so the
83
+ soft keyboard never offers autocomplete suggestions for a typed
84
+ password, and never enriches characters before we forward them. -->
85
+ <input id="kbInput" type="text" inputmode="text" autocomplete="off"
86
+ autocorrect="off" autocapitalize="off" spellcheck="false"
87
+ aria-hidden="true" tabindex="-1" />
88
+ <button id="kb" type="button" aria-label="Show keyboard">⌨</button>
84
89
  <script type="module">
85
90
  import RFB from "./core/rfb.js";
86
91
 
@@ -114,11 +119,6 @@
114
119
  rfb.addEventListener("connect", () => {
115
120
  dot.className = "ok";
116
121
  msg.style.display = "none";
117
- // Reveal the soft-keyboard button (CSS gates it to touch
118
- // devices via the pointer:coarse media query). Connection
119
- // success is the right moment — earlier and the button would
120
- // suggest a typing target that isn't connected yet.
121
- kbBtn.classList.add("ready");
122
122
  });
123
123
  rfb.addEventListener("disconnect", () => {
124
124
  dot.className = "err";
@@ -126,7 +126,6 @@
126
126
  msg.textContent =
127
127
  "Login window closed. If you finished signing in, return to " +
128
128
  "your terminal — you can close this tab.";
129
- kbBtn.classList.remove("ready");
130
129
  });
131
130
  rfb.addEventListener("securityfailure", () => {
132
131
  dot.className = "err";
@@ -134,14 +133,24 @@
134
133
  msg.textContent = "Could not authenticate to the login window.";
135
134
  });
136
135
 
137
- // Tap → kbInput.focus() inside the click handler so the focus
138
- // happens synchronously in response to a user gesture. iOS /
139
- // Android browsers won't pop the soft keyboard for a programmatic
140
- // focus outside a gesture, so this MUST stay inline. Focusing
141
- // a real <input> is what triggers the OS keyboard — focusing
142
- // the RFB div (rfb.focus() in noVNC 1.x) wouldn't.
136
+ // Tap → soft keyboard pop. The blur+focus dance is load-bearing:
137
+ // focus() on an already-focused element is a no-op so the OS
138
+ // won't re-trigger the keyboard; blur first forces a fresh focus
139
+ // event. The whole sequence stays inside the click handler so
140
+ // iOS Safari and Android Chrome both accept the focus() as
141
+ // gesture-bound. Focusing a real <input> is what pops the OS
142
+ // keyboard — focusing the RFB div (rfb.focus() in noVNC 1.x)
143
+ // wouldn't.
144
+ //
145
+ // The .tapped class flashes the button green for 200ms so the
146
+ // user can see the tap registered even if the OS doesn't (yet)
147
+ // pop the keyboard — separates "did my tap reach the button?"
148
+ // from "does focus() pop the keyboard on this device?"
143
149
  kbBtn.addEventListener("click", (e) => {
144
150
  e.preventDefault();
151
+ kbBtn.classList.add("tapped");
152
+ setTimeout(() => kbBtn.classList.remove("tapped"), 200);
153
+ kbInput.blur();
145
154
  kbInput.value = "";
146
155
  kbInput.focus();
147
156
  });
@@ -164,10 +173,9 @@
164
173
 
165
174
  // Forward typed characters. The `input` event fires once per
166
175
  // commit (each char on most soft keyboards; sometimes batched
167
- // when an IME finalizes). We diff against the previous value
168
- // to handle paste / autocorrect insertions, send a press+release
169
- // for each new character, then clear the input so it never
170
- // accumulates the user's password.
176
+ // when an IME finalizes). We send a press+release for each
177
+ // character, then clear the input so it never accumulates the
178
+ // user's password.
171
179
  let lastKbValue = "";
172
180
  kbInput.addEventListener("input", () => {
173
181
  const newValue = kbInput.value;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trusty-squire/mcp",
3
- "version": "0.5.4",
3
+ "version": "0.5.6",
4
4
  "type": "module",
5
5
  "description": "Local MCP server vibe coding agents install. Thin relay to the Trusty Squire API, with the bundled universal signup bot.",
6
6
  "main": "./dist/server.js",