@oddessentials/agent-guild 0.12.0 → 0.12.1
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/package.json +1 -1
- package/web/app.js +42 -2
- package/web/styles.css +8 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oddessentials/agent-guild",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.1",
|
|
4
4
|
"description": "Launch and watch AI coding-assistant terminal sessions from one local web page. A bundled session manager owns the terminals so the page can close and reconnect.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
package/web/app.js
CHANGED
|
@@ -15,6 +15,7 @@ const RELEASES_URL = 'https://github.com/oddessentials/agent-guild/releases';
|
|
|
15
15
|
const isMac = /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent);
|
|
16
16
|
const reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)');
|
|
17
17
|
const finePointer = window.matchMedia('(hover: hover) and (pointer: fine)');
|
|
18
|
+
const coarsePointer = window.matchMedia('(pointer: coarse)');
|
|
18
19
|
|
|
19
20
|
const $ = (id) => document.getElementById(id);
|
|
20
21
|
const state = {
|
|
@@ -2747,7 +2748,7 @@ class TerminalView {
|
|
|
2747
2748
|
this.term = new window.Terminal({
|
|
2748
2749
|
cursorBlink: true,
|
|
2749
2750
|
fontFamily: 'ui-monospace, "Cascadia Code", "SF Mono", Menlo, Consolas, monospace',
|
|
2750
|
-
fontSize: 13,
|
|
2751
|
+
fontSize: coarsePointer.matches ? 14 : 13,
|
|
2751
2752
|
scrollback: 5000,
|
|
2752
2753
|
macOptionIsMeta: true,
|
|
2753
2754
|
theme: TERMINAL_THEME,
|
|
@@ -2828,12 +2829,51 @@ class TerminalView {
|
|
|
2828
2829
|
|
|
2829
2830
|
mount(host) {
|
|
2830
2831
|
host.replaceChildren(this.el);
|
|
2831
|
-
if (!this.opened) { this.term.open(this.el); this.opened = true; }
|
|
2832
|
+
if (!this.opened) { this.term.open(this.el); this.enableTouchScroll(); this.opened = true; }
|
|
2832
2833
|
this.resizeObserver.observe(host);
|
|
2833
2834
|
this.refit();
|
|
2834
2835
|
this.term.focus();
|
|
2835
2836
|
}
|
|
2836
2837
|
|
|
2838
|
+
/**
|
|
2839
|
+
* xterm.js 6 scrolls only for the mouse wheel, so a one-finger drag would
|
|
2840
|
+
* scroll the page behind the panel instead. Turn the drag into scrolling.
|
|
2841
|
+
* Full-screen programs and programs that read the mouse get a wheel event,
|
|
2842
|
+
* which xterm turns into arrow keys or mouse reports as it does for a real
|
|
2843
|
+
* wheel. Scrollback uses scrollLines, because xterm's scrollback reads the
|
|
2844
|
+
* legacy wheelDeltaY that a constructed WheelEvent leaves at 0.
|
|
2845
|
+
*/
|
|
2846
|
+
enableTouchScroll() {
|
|
2847
|
+
let lastY = null;
|
|
2848
|
+
let pending = 0;
|
|
2849
|
+
this.el.addEventListener('touchstart', (e) => {
|
|
2850
|
+
lastY = e.touches.length === 1 ? e.touches[0].clientY : null;
|
|
2851
|
+
pending = 0;
|
|
2852
|
+
}, { passive: true });
|
|
2853
|
+
this.el.addEventListener('touchmove', (e) => {
|
|
2854
|
+
if (lastY === null || e.touches.length !== 1) return;
|
|
2855
|
+
e.preventDefault();
|
|
2856
|
+
const touch = e.touches[0];
|
|
2857
|
+
const delta = lastY - touch.clientY;
|
|
2858
|
+
lastY = touch.clientY;
|
|
2859
|
+
if (this.term.buffer.active.type === 'alternate' || this.term.modes.mouseTrackingMode !== 'none') {
|
|
2860
|
+
const target = this.el.querySelector('.xterm-screen') || this.el;
|
|
2861
|
+
target.dispatchEvent(new WheelEvent('wheel', {
|
|
2862
|
+
deltaY: delta, deltaMode: WheelEvent.DOM_DELTA_PIXEL,
|
|
2863
|
+
clientX: touch.clientX, clientY: touch.clientY, bubbles: true, cancelable: true,
|
|
2864
|
+
}));
|
|
2865
|
+
return;
|
|
2866
|
+
}
|
|
2867
|
+
pending += delta;
|
|
2868
|
+
const lineHeight = this.el.querySelector('.xterm-rows')?.firstElementChild?.offsetHeight || 17;
|
|
2869
|
+
const lines = Math.trunc(pending / lineHeight);
|
|
2870
|
+
if (lines) { this.term.scrollLines(lines); pending -= lines * lineHeight; }
|
|
2871
|
+
}, { passive: false });
|
|
2872
|
+
const end = () => { lastY = null; };
|
|
2873
|
+
this.el.addEventListener('touchend', end);
|
|
2874
|
+
this.el.addEventListener('touchcancel', end);
|
|
2875
|
+
}
|
|
2876
|
+
|
|
2837
2877
|
unmount() {
|
|
2838
2878
|
this.resizeObserver.disconnect();
|
|
2839
2879
|
this.el.remove();
|
package/web/styles.css
CHANGED
|
@@ -354,6 +354,14 @@ body:has(#app[hidden]):has(#auth[hidden]):has(#stopped[hidden])::after {
|
|
|
354
354
|
.panel-actions { display: flex; gap: 8px; }
|
|
355
355
|
.terminal-host { flex: 1; min-height: 0; padding: 8px 4px 4px 10px; }
|
|
356
356
|
.terminal-host > div { height: 100%; }
|
|
357
|
+
@media (pointer: coarse) {
|
|
358
|
+
/* A drag on the panel would otherwise scroll the page behind it. */
|
|
359
|
+
body:has(#terminal-panel:not([hidden])) { overflow: hidden; }
|
|
360
|
+
}
|
|
361
|
+
@media (pointer: coarse) and (max-width: 900px) {
|
|
362
|
+
/* Tablets in portrait are wider than the phone layout but still want the whole width. */
|
|
363
|
+
.terminal-panel { inset: var(--topbar-h, 56px) 0 0; border-radius: 0; }
|
|
364
|
+
}
|
|
357
365
|
|
|
358
366
|
.models {
|
|
359
367
|
width: min(880px, calc(100vw - 32px)); max-height: calc(100vh - 48px); padding: 0; overflow: hidden;
|