codeam-cli 2.76.35 → 2.76.37
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/CHANGELOG.md +19 -0
- package/dist/index.js +878 -482
- package/package.json +1 -1
- package/dist/postinstall.js +0 -33
package/dist/index.js
CHANGED
|
@@ -3458,6 +3458,724 @@ CRITICAL \u2014 setup_commands:
|
|
|
3458
3458
|
OUTPUT JSON ONLY. NO MARKDOWN. NO COMMENTARY.
|
|
3459
3459
|
`.trim();
|
|
3460
3460
|
|
|
3461
|
+
// ../../packages/shared/src/point-picker/script.ts
|
|
3462
|
+
var POINT_TEXT_MAX = 120;
|
|
3463
|
+
var POINT_HTML_MAX = 600;
|
|
3464
|
+
var DEFAULT_ACCENT = "#7C5CFF";
|
|
3465
|
+
var HEX = /^#[0-9A-Fa-f]{6}$/;
|
|
3466
|
+
var IDENT = /^[A-Za-z_$][\w$]*$/;
|
|
3467
|
+
function js(v) {
|
|
3468
|
+
return JSON.stringify(v).replace(/</g, "\\u003c");
|
|
3469
|
+
}
|
|
3470
|
+
function pointPickerScript(opts) {
|
|
3471
|
+
const multi = opts.mode === "multi";
|
|
3472
|
+
const maxMarks = opts.maxMarks ?? 4;
|
|
3473
|
+
const accent = opts.accent ?? DEFAULT_ACCENT;
|
|
3474
|
+
if (opts.channelField !== "channel" && opts.channelField !== "source") {
|
|
3475
|
+
throw new Error(`pointPickerScript: bad channelField ${String(opts.channelField)}`);
|
|
3476
|
+
}
|
|
3477
|
+
if (!HEX.test(accent))
|
|
3478
|
+
throw new Error(`pointPickerScript: accent must be #RRGGBB, got ${accent}`);
|
|
3479
|
+
if (!Number.isInteger(maxMarks) || maxMarks < 1) {
|
|
3480
|
+
throw new Error(`pointPickerScript: maxMarks must be a positive integer, got ${maxMarks}`);
|
|
3481
|
+
}
|
|
3482
|
+
if (opts.globalName !== void 0 && !IDENT.test(opts.globalName)) {
|
|
3483
|
+
throw new Error(`pointPickerScript: globalName must be an identifier, got ${opts.globalName}`);
|
|
3484
|
+
}
|
|
3485
|
+
return `(function () {
|
|
3486
|
+
'use strict';
|
|
3487
|
+
var W = window, D = document;
|
|
3488
|
+
var CH = ${js(opts.channel)};
|
|
3489
|
+
var FIELD = ${js(opts.channelField)};
|
|
3490
|
+
var ALLOWED = ${js(opts.allowedParents)};
|
|
3491
|
+
var MULTI = ${multi}, MAX_MARKS = ${maxMarks}, AGENT = ${!!opts.agentHighlights}, REACT_SOURCE = ${!!opts.reactSource};
|
|
3492
|
+
var GLOBAL = ${js(opts.globalName ?? null)};
|
|
3493
|
+
var DEFAULT_ACCENT = ${js(accent)};
|
|
3494
|
+
var GUARD = '__pointPicker:' + CH;
|
|
3495
|
+
if (W[GUARD]) return;
|
|
3496
|
+
try { Object.defineProperty(W, GUARD, { value: true }); } catch (e) { return; }
|
|
3497
|
+
try {
|
|
3498
|
+
var TEXT_MAX = ${POINT_TEXT_MAX}, HTML_MAX = ${POINT_HTML_MAX}, ATTR_MAX = 60;
|
|
3499
|
+
var ACCENT_RE = /^#[0-9A-Fa-f]{6}$/;
|
|
3500
|
+
var AGENT_ACCENT = '#22d3ee';
|
|
3501
|
+
var EASE = 'cubic-bezier(.2,.8,.2,1)';
|
|
3502
|
+
var CHIP_FONT = 'italic 500 13px/1.3 Georgia,"Times New Roman",serif';
|
|
3503
|
+
var CONTROLS = { BUTTON: 1, A: 1, INPUT: 1, SELECT: 1, TEXTAREA: 1, LABEL: 1, SUMMARY: 1 };
|
|
3504
|
+
var ROLES = { button: 1, link: 1, tab: 1, checkbox: 1, switch: 1, menuitem: 1, option: 1, radio: 1, slider: 1 };
|
|
3505
|
+
var VOID = { AREA: 1, BR: 1, COL: 1, EMBED: 1, HR: 1, IMG: 1, INPUT: 1, LINK: 1, META: 1, SOURCE: 1, TRACK: 1, WBR: 1 };
|
|
3506
|
+
var GRAIN = "url(\\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .08 0 0 0 0 .08 0 0 0 0 .09 0 0 0 .12 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E\\")";
|
|
3507
|
+
|
|
3508
|
+
var on = false, driver = null, accent = DEFAULT_ACCENT;
|
|
3509
|
+
var host = null, veil = null, ring = null, chip = null, style = null, leaving = null;
|
|
3510
|
+
var current = null, down = null, tapped = false, bound = [], swallow = null;
|
|
3511
|
+
// Multi mode: the pinned marks, drawn in the page and anchored to the document.
|
|
3512
|
+
// Mark ids carry a per-load prefix: after a reload \`seq\` restarts, and the
|
|
3513
|
+
// app may still hold the previous page's p\u2026-1.
|
|
3514
|
+
var picked = [], seq = 0, marksHost = null, marksRoot = null;
|
|
3515
|
+
var LOAD = (Math.random().toString(36).slice(2) + '0000').slice(0, 4);
|
|
3516
|
+
// The agent's highlights: separate from the person's marks, never numbered.
|
|
3517
|
+
var agentMarks = [], agentHost = null, agentRoot = null, agentLayer = null, agentCursor = null, agentListening = false;
|
|
3518
|
+
|
|
3519
|
+
// Inside a React Native WebView the document is TOP-LEVEL (window.parent ===
|
|
3520
|
+
// window), so the only way out is the bridge RN injects. It carries STRINGS.
|
|
3521
|
+
function rnBridge() {
|
|
3522
|
+
if (!GLOBAL) return null;
|
|
3523
|
+
var rn = W.ReactNativeWebView;
|
|
3524
|
+
return rn && typeof rn.postMessage === 'function' ? rn : null;
|
|
3525
|
+
}
|
|
3526
|
+
|
|
3527
|
+
function send(type, extra) {
|
|
3528
|
+
if (!driver) return;
|
|
3529
|
+
var msg = {};
|
|
3530
|
+
msg[FIELD] = CH;
|
|
3531
|
+
msg.type = type;
|
|
3532
|
+
if (extra) for (var k in extra) msg[k] = extra[k];
|
|
3533
|
+
var rn = rnBridge();
|
|
3534
|
+
if (rn) {
|
|
3535
|
+
try { rn.postMessage(JSON.stringify(msg)); } catch (e) {}
|
|
3536
|
+
return;
|
|
3537
|
+
}
|
|
3538
|
+
if (W.parent === W) return;
|
|
3539
|
+
try { W.parent.postMessage(msg, driver); } catch (e) {}
|
|
3540
|
+
}
|
|
3541
|
+
|
|
3542
|
+
function clip(s, max) { return s.length > max ? s.slice(0, max - 1) + '\\u2026' : s; }
|
|
3543
|
+
function squash(s) { return String(s == null ? '' : s).replace(/\\s+/g, ' ').trim(); }
|
|
3544
|
+
function attr(el, n) { var v = el.getAttribute ? el.getAttribute(n) : null; return v == null ? '' : String(v); }
|
|
3545
|
+
function tagOf(el) { return String(el.tagName || '').toLowerCase(); }
|
|
3546
|
+
function reduced() {
|
|
3547
|
+
try { return !!(W.matchMedia && W.matchMedia('(prefers-reduced-motion: reduce)').matches); } catch (e) { return false; }
|
|
3548
|
+
}
|
|
3549
|
+
function drop(node) { if (node && node.parentNode) node.parentNode.removeChild(node); }
|
|
3550
|
+
function shadowOf(el) { return el.attachShadow ? el.attachShadow({ mode: 'closed' }) : el; }
|
|
3551
|
+
function clear(node) { while (node && node.childNodes && node.childNodes.length) node.removeChild(node.childNodes[0]); }
|
|
3552
|
+
|
|
3553
|
+
// A tap lands on the innermost node (the <span> in a button, the <path> in
|
|
3554
|
+
// an icon); the person means the control around it.
|
|
3555
|
+
function target(el) {
|
|
3556
|
+
var n = el;
|
|
3557
|
+
for (var depth = 0; n && n !== D.body && n !== D.documentElement && depth < 6; depth++) {
|
|
3558
|
+
if (CONTROLS[String(n.tagName).toUpperCase()] || ROLES[attr(n, 'role')]) return n;
|
|
3559
|
+
n = n.parentElement;
|
|
3560
|
+
}
|
|
3561
|
+
n = el;
|
|
3562
|
+
while (n.ownerSVGElement) n = n.ownerSVGElement;
|
|
3563
|
+
return n;
|
|
3564
|
+
}
|
|
3565
|
+
|
|
3566
|
+
function pickable(el) {
|
|
3567
|
+
return !!el && el.nodeType === 1 && el !== D.documentElement && el !== D.body &&
|
|
3568
|
+
el !== host && el !== marksHost && el !== agentHost;
|
|
3569
|
+
}
|
|
3570
|
+
|
|
3571
|
+
// CSS.escape where the browser has it; else the same algorithm (CSSOM).
|
|
3572
|
+
// Without it a Tailwind class (\`md:flex\`, \`w-1/2\`) makes an invalid selector.
|
|
3573
|
+
function cssEsc(v) {
|
|
3574
|
+
v = String(v);
|
|
3575
|
+
try { if (W.CSS && typeof W.CSS.escape === 'function') return W.CSS.escape(v); } catch (e) {}
|
|
3576
|
+
var out = '';
|
|
3577
|
+
for (var i = 0; i < v.length; i++) {
|
|
3578
|
+
var ch = v.charAt(i), code = v.charCodeAt(i);
|
|
3579
|
+
if (code === 0) out += '\\uFFFD';
|
|
3580
|
+
else if ((code >= 1 && code <= 31) || code === 127 || (i === 0 && code >= 48 && code <= 57) ||
|
|
3581
|
+
(i === 1 && code >= 48 && code <= 57 && v.charAt(0) === '-')) out += '\\\\' + code.toString(16) + ' ';
|
|
3582
|
+
else if (i === 0 && ch === '-' && v.length === 1) out += '\\\\-';
|
|
3583
|
+
else if (code >= 128 || ch === '-' || ch === '_' || /[0-9A-Za-z]/.test(ch)) out += ch;
|
|
3584
|
+
else out += '\\\\' + ch;
|
|
3585
|
+
}
|
|
3586
|
+
return out;
|
|
3587
|
+
}
|
|
3588
|
+
|
|
3589
|
+
// One step of the path. \`lean\` (tag + position only) is the fallback for
|
|
3590
|
+
// a step that alone would not fit the budget.
|
|
3591
|
+
function step(el, lean) {
|
|
3592
|
+
var t = tagOf(el);
|
|
3593
|
+
if (el.id && !lean) return t + '#' + cssEsc(el.id);
|
|
3594
|
+
var c = lean ? [] : squash(attr(el, 'class')).split(' ').filter(Boolean).slice(0, 2);
|
|
3595
|
+
var s = t;
|
|
3596
|
+
for (var k = 0; k < c.length; k++) s += '.' + cssEsc(c[k]);
|
|
3597
|
+
var p = el.parentElement;
|
|
3598
|
+
if (p && p.children) {
|
|
3599
|
+
var same = 0, index = 0;
|
|
3600
|
+
for (var i = 0; i < p.children.length; i++) {
|
|
3601
|
+
if (p.children[i].tagName === el.tagName) {
|
|
3602
|
+
same++;
|
|
3603
|
+
if (p.children[i] === el) index = same;
|
|
3604
|
+
}
|
|
3605
|
+
}
|
|
3606
|
+
if (same > 1) s += ':nth-of-type(' + index + ')';
|
|
3607
|
+
}
|
|
3608
|
+
return s;
|
|
3609
|
+
}
|
|
3610
|
+
|
|
3611
|
+
// Never cut with an ellipsis (that would be no selector at all): drop the
|
|
3612
|
+
// outermost ancestors until the path fits, so it always matches the element.
|
|
3613
|
+
function selectorFor(el) {
|
|
3614
|
+
var parts = [], n = el;
|
|
3615
|
+
while (n && n.nodeType === 1 && n !== D.body && n !== D.documentElement && parts.length < 4) {
|
|
3616
|
+
parts.unshift(step(n));
|
|
3617
|
+
if (n.id) break;
|
|
3618
|
+
n = n.parentElement;
|
|
3619
|
+
}
|
|
3620
|
+
while (parts.length > 1 && parts.join(' > ').length > 200) parts.shift();
|
|
3621
|
+
if (parts[0].length > 200) parts[0] = step(el, true);
|
|
3622
|
+
return parts.join(' > ');
|
|
3623
|
+
}
|
|
3624
|
+
|
|
3625
|
+
function textOf(el) {
|
|
3626
|
+
return clip(squash(attr(el, 'aria-label') || el.textContent || attr(el, 'placeholder') || attr(el, 'alt') || attr(el, 'title')), TEXT_MAX);
|
|
3627
|
+
}
|
|
3628
|
+
|
|
3629
|
+
function esc(s) { return s.replace(/&/g, '&').replace(/</g, '<').replace(/"/g, '"'); }
|
|
3630
|
+
|
|
3631
|
+
// The element's markup within a budget: attributes trimmed, never more than
|
|
3632
|
+
// HTML_MAX characters walked, so a huge container costs nothing.
|
|
3633
|
+
function htmlOf(el) {
|
|
3634
|
+
var out = [], left = HTML_MAX + 1;
|
|
3635
|
+
function put(s) {
|
|
3636
|
+
if (left <= 0) return;
|
|
3637
|
+
out.push(s.length > left ? s.slice(0, left) : s);
|
|
3638
|
+
left -= s.length;
|
|
3639
|
+
}
|
|
3640
|
+
function walk(n, depth) {
|
|
3641
|
+
if (left <= 0) return;
|
|
3642
|
+
if (n.nodeType === 3) {
|
|
3643
|
+
var text = String(n.nodeValue == null ? '' : n.nodeValue).replace(/\\s+/g, ' ');
|
|
3644
|
+
if (text.trim()) put(esc(text));
|
|
3645
|
+
return;
|
|
3646
|
+
}
|
|
3647
|
+
if (n.nodeType !== 1) return;
|
|
3648
|
+
var t = tagOf(n);
|
|
3649
|
+
put('<' + t);
|
|
3650
|
+
var a = n.attributes || [];
|
|
3651
|
+
for (var i = 0; i < a.length; i++) put(' ' + a[i].name + '="' + esc(clip(String(a[i].value), ATTR_MAX)) + '"');
|
|
3652
|
+
put('>');
|
|
3653
|
+
if (VOID[t.toUpperCase()]) return;
|
|
3654
|
+
if (t === 'script' || t === 'style') put('\\u2026');
|
|
3655
|
+
else if (depth >= 4) { if (n.childNodes && n.childNodes.length) put('\\u2026'); }
|
|
3656
|
+
else for (var c = 0; n.childNodes && c < n.childNodes.length && left > 0; c++) walk(n.childNodes[c], depth + 1);
|
|
3657
|
+
put('</' + t + '>');
|
|
3658
|
+
}
|
|
3659
|
+
walk(el, 0);
|
|
3660
|
+
var s = out.join('');
|
|
3661
|
+
return s.length > HTML_MAX ? s.slice(0, HTML_MAX - 1) + '\\u2026' : s;
|
|
3662
|
+
}
|
|
3663
|
+
|
|
3664
|
+
// The React component's file and line, when a dev build exposes them: the
|
|
3665
|
+
// agent gets "components/buy-button.tsx:42" instead of a CSS path.
|
|
3666
|
+
function reactSourceOf(el) {
|
|
3667
|
+
try {
|
|
3668
|
+
for (var key in el) {
|
|
3669
|
+
if (key.indexOf('__reactFiber$') !== 0) continue;
|
|
3670
|
+
var fiber = el[key];
|
|
3671
|
+
while (fiber) {
|
|
3672
|
+
var src = fiber._debugSource;
|
|
3673
|
+
if (src && src.fileName) return { file: String(src.fileName), line: Number(src.lineNumber) || null };
|
|
3674
|
+
fiber = fiber.return;
|
|
3675
|
+
}
|
|
3676
|
+
}
|
|
3677
|
+
} catch (e) {}
|
|
3678
|
+
return null;
|
|
3679
|
+
}
|
|
3680
|
+
|
|
3681
|
+
function describe(el) {
|
|
3682
|
+
var r = el.getBoundingClientRect();
|
|
3683
|
+
var out = {
|
|
3684
|
+
tag: tagOf(el),
|
|
3685
|
+
id: el.id ? clip(String(el.id), 100) : null,
|
|
3686
|
+
classes: clip(squash(attr(el, 'class')), 200),
|
|
3687
|
+
selector: selectorFor(el),
|
|
3688
|
+
text: textOf(el),
|
|
3689
|
+
html: htmlOf(el),
|
|
3690
|
+
rect: { x: Math.round(r.left), y: Math.round(r.top), w: Math.round(r.width), h: Math.round(r.height) }
|
|
3691
|
+
};
|
|
3692
|
+
if (MULTI) out.viewport = { w: W.innerWidth, h: W.innerHeight };
|
|
3693
|
+
if (REACT_SOURCE) out.source = reactSourceOf(el);
|
|
3694
|
+
return out;
|
|
3695
|
+
}
|
|
3696
|
+
|
|
3697
|
+
function kindOf(el) {
|
|
3698
|
+
var t = tagOf(el), role = attr(el, 'role'), type = attr(el, 'type');
|
|
3699
|
+
if (t === 'button' || role === 'button' || (t === 'input' && /^(button|submit|reset)$/.test(type))) return 'button';
|
|
3700
|
+
if (t === 'a' || role === 'link') return 'link';
|
|
3701
|
+
if (t === 'input' || t === 'textarea' || t === 'select') return 'field';
|
|
3702
|
+
if (t === 'img' || t === 'svg' || t === 'picture' || t === 'canvas') return 'image';
|
|
3703
|
+
if (/^h[1-6]$/.test(t)) return 'heading';
|
|
3704
|
+
return t;
|
|
3705
|
+
}
|
|
3706
|
+
|
|
3707
|
+
function label(el) {
|
|
3708
|
+
var text = squash(textOf(el));
|
|
3709
|
+
var kind = kindOf(el);
|
|
3710
|
+
return text ? '\\u201c' + clip(text, 28) + '\\u201d ' + kind : kind;
|
|
3711
|
+
}
|
|
3712
|
+
|
|
3713
|
+
function cursor() {
|
|
3714
|
+
var svg = "<svg xmlns='http://www.w3.org/2000/svg' width='32' height='32'><circle cx='16' cy='16' r='9.5' fill='" + accent + "' fill-opacity='.14' stroke='" + accent + "' stroke-width='2'/><path d='M16 1v7M16 24v7M1 16h7M24 16h7' stroke='" + accent + "' stroke-width='1.6' stroke-linecap='round'/><circle cx='16' cy='16' r='1.6' fill='" + accent + "'/></svg>";
|
|
3715
|
+
return 'url("data:image/svg+xml,' + encodeURIComponent(svg) + '") 16 16, crosshair';
|
|
3716
|
+
}
|
|
3717
|
+
|
|
3718
|
+
function canHole() {
|
|
3719
|
+
try { return !!(W.CSS && W.CSS.supports && W.CSS.supports('clip-path', 'path(evenodd, "M0 0H1V1Z")')); } catch (e) { return false; }
|
|
3720
|
+
}
|
|
3721
|
+
|
|
3722
|
+
// The veil covers the app except a rounded window around the element.
|
|
3723
|
+
function holePath(r) {
|
|
3724
|
+
var w = Math.round(W.innerWidth), h = Math.round(W.innerHeight), p = 6;
|
|
3725
|
+
var x = Math.round(r.left - p), y = Math.round(r.top - p);
|
|
3726
|
+
var rw = Math.round(r.width + 2 * p), rh = Math.round(r.height + 2 * p);
|
|
3727
|
+
var k = Math.max(0, Math.min(12, Math.floor(rw / 2), Math.floor(rh / 2)));
|
|
3728
|
+
var arc = 'A' + k + ' ' + k + ' 0 0 1 ';
|
|
3729
|
+
return 'path(evenodd, "M0 0H' + w + 'V' + h + 'H0Z' +
|
|
3730
|
+
'M' + (x + k) + ' ' + y + 'H' + (x + rw - k) + arc + (x + rw) + ' ' + (y + k) +
|
|
3731
|
+
'V' + (y + rh - k) + arc + (x + rw - k) + ' ' + (y + rh) +
|
|
3732
|
+
'H' + (x + k) + arc + x + ' ' + (y + rh - k) +
|
|
3733
|
+
'V' + (y + k) + arc + (x + k) + ' ' + y + 'Z")';
|
|
3734
|
+
}
|
|
3735
|
+
|
|
3736
|
+
// The Remix ring and chip, shared by the pointer, the marks and the agent.
|
|
3737
|
+
function ringCss(color) {
|
|
3738
|
+
return 'box-sizing:border-box;border:2px solid ' + color + ';border-radius:12px;box-shadow:0 0 0 5px ' + color + '29';
|
|
3739
|
+
}
|
|
3740
|
+
function chipCss(color) {
|
|
3741
|
+
return 'white-space:nowrap;padding:4px 10px;border-radius:999px;background:#141416;color:#f6f3ee;font:' + CHIP_FONT +
|
|
3742
|
+
';box-shadow:0 0 0 1px ' + color;
|
|
3743
|
+
}
|
|
3744
|
+
|
|
3745
|
+
// A host for our nodes: a custom element, max z-index, its own closed
|
|
3746
|
+
// shadow root so the page's CSS can't restyle (or hide) what we draw. Last
|
|
3747
|
+
// child of <html>, so at an equal z-index it still paints on top.
|
|
3748
|
+
function makeHost(role, position) {
|
|
3749
|
+
var el = D.createElement('remix-point');
|
|
3750
|
+
if (role === 'point') el.setAttribute('data-remix-point', '');
|
|
3751
|
+
el.setAttribute('data-codeam', role);
|
|
3752
|
+
el.style.cssText = 'all:initial;position:' + position + ';top:0;left:0;width:0;height:0;pointer-events:none;z-index:2147483647';
|
|
3753
|
+
return el;
|
|
3754
|
+
}
|
|
3755
|
+
|
|
3756
|
+
function build() {
|
|
3757
|
+
if (leaving && leaving.parentNode) leaving.parentNode.removeChild(leaving);
|
|
3758
|
+
leaving = null;
|
|
3759
|
+
var motion = reduced() ? 'none' : 'transform .16s ' + EASE + ', width .16s ' + EASE + ', height .16s ' + EASE + ', opacity .16s';
|
|
3760
|
+
host = makeHost('point', 'fixed');
|
|
3761
|
+
var root = shadowOf(host);
|
|
3762
|
+
veil = D.createElement('div');
|
|
3763
|
+
veil.setAttribute('data-codeam', 'veil');
|
|
3764
|
+
veil.style.cssText = 'position:fixed;top:0;left:0;right:0;bottom:0;pointer-events:none;opacity:0;' +
|
|
3765
|
+
'background:rgba(246,243,238,.46) ' + GRAIN + ';-webkit-backdrop-filter:grayscale(.7);backdrop-filter:grayscale(.7);' +
|
|
3766
|
+
'transition:' + (reduced() ? 'none' : 'opacity .2s');
|
|
3767
|
+
ring = D.createElement('div');
|
|
3768
|
+
ring.setAttribute('data-codeam', 'ring');
|
|
3769
|
+
ring.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;pointer-events:none;opacity:0;' +
|
|
3770
|
+
ringCss(accent) + ';transition:' + motion;
|
|
3771
|
+
chip = D.createElement('div');
|
|
3772
|
+
chip.setAttribute('data-codeam', 'chip');
|
|
3773
|
+
chip.style.cssText = 'position:fixed;top:0;left:0;pointer-events:none;opacity:0;' + chipCss(accent) + ';transition:' + motion;
|
|
3774
|
+
root.appendChild(veil);
|
|
3775
|
+
root.appendChild(ring);
|
|
3776
|
+
root.appendChild(chip);
|
|
3777
|
+
D.documentElement.appendChild(host);
|
|
3778
|
+
style = D.createElement('style');
|
|
3779
|
+
style.textContent = 'html[data-remix-pointing],html[data-remix-pointing] *{cursor:' + cursor() + ' !important;' +
|
|
3780
|
+
'user-select:none !important;-webkit-user-select:none !important;-webkit-touch-callout:none !important}';
|
|
3781
|
+
(D.head || D.documentElement).appendChild(style);
|
|
3782
|
+
D.documentElement.setAttribute('data-remix-pointing', '');
|
|
3783
|
+
}
|
|
3784
|
+
|
|
3785
|
+
function paint(el) {
|
|
3786
|
+
current = el;
|
|
3787
|
+
var r = el.getBoundingClientRect();
|
|
3788
|
+
ring.style.transform = 'translate(' + Math.round(r.left - 4) + 'px,' + Math.round(r.top - 4) + 'px)';
|
|
3789
|
+
ring.style.width = Math.round(r.width + 8) + 'px';
|
|
3790
|
+
ring.style.height = Math.round(r.height + 8) + 'px';
|
|
3791
|
+
ring.style.opacity = '1';
|
|
3792
|
+
if (canHole()) {
|
|
3793
|
+
veil.style.clipPath = holePath(r);
|
|
3794
|
+
veil.style.opacity = '1';
|
|
3795
|
+
}
|
|
3796
|
+
chip.textContent = label(el);
|
|
3797
|
+
var top = r.top >= 34 ? r.top - 32 : r.top + r.height + 8;
|
|
3798
|
+
var left = Math.max(8, Math.min(r.left, W.innerWidth - 200));
|
|
3799
|
+
chip.style.transform = 'translate(' + Math.round(left) + 'px,' + Math.round(top) + 'px)';
|
|
3800
|
+
chip.style.opacity = '1';
|
|
3801
|
+
}
|
|
3802
|
+
|
|
3803
|
+
// Paint, and in multi mode tell the parent what is under the finger.
|
|
3804
|
+
function hoverTo(el) {
|
|
3805
|
+
var changed = el !== current;
|
|
3806
|
+
paint(el);
|
|
3807
|
+
if (changed && MULTI) send('hover', { element: describe(el) });
|
|
3808
|
+
}
|
|
3809
|
+
|
|
3810
|
+
// While pointing, the app never sees the gesture: no click, no focus, no
|
|
3811
|
+
// drag. Touch scrolling still works (its default is left alone).
|
|
3812
|
+
function block(e) {
|
|
3813
|
+
if (e.stopImmediatePropagation) e.stopImmediatePropagation();
|
|
3814
|
+
if (e.cancelable && e.type !== 'touchstart' && e.type !== 'touchmove') e.preventDefault();
|
|
3815
|
+
}
|
|
3816
|
+
|
|
3817
|
+
// What is under the pointer. Hit-testing first (a touch keeps targeting
|
|
3818
|
+
// the element it went down on); the event target where there is none.
|
|
3819
|
+
function at(e) {
|
|
3820
|
+
var el = null;
|
|
3821
|
+
if (D.elementFromPoint) {
|
|
3822
|
+
try { el = D.elementFromPoint(e.clientX, e.clientY); } catch (x) { el = null; }
|
|
3823
|
+
}
|
|
3824
|
+
if (!el && e.target && e.target.nodeType === 1) el = e.target;
|
|
3825
|
+
return pickable(el) ? target(el) : null;
|
|
3826
|
+
}
|
|
3827
|
+
|
|
3828
|
+
function onDown(e) {
|
|
3829
|
+
block(e);
|
|
3830
|
+
down = { id: e.pointerId };
|
|
3831
|
+
tapped = true;
|
|
3832
|
+
var el = at(e);
|
|
3833
|
+
if (el) hoverTo(el);
|
|
3834
|
+
}
|
|
3835
|
+
|
|
3836
|
+
function onMove(e) {
|
|
3837
|
+
block(e);
|
|
3838
|
+
var el = at(e);
|
|
3839
|
+
if (el && el !== current) hoverTo(el);
|
|
3840
|
+
}
|
|
3841
|
+
|
|
3842
|
+
// Browsers without pointer events (old WebViews) only send mouse events.
|
|
3843
|
+
// Never blocked: the app keeps its own mousemove, as it always did.
|
|
3844
|
+
function onMouseMove(e) {
|
|
3845
|
+
var el = at(e);
|
|
3846
|
+
if (el && el !== current) hoverTo(el);
|
|
3847
|
+
}
|
|
3848
|
+
|
|
3849
|
+
function onUp(e) {
|
|
3850
|
+
block(e);
|
|
3851
|
+
var d = down;
|
|
3852
|
+
down = null;
|
|
3853
|
+
if (!d || d.id !== e.pointerId || e.button > 0) return;
|
|
3854
|
+
var el = at(e) || current;
|
|
3855
|
+
if (el) {
|
|
3856
|
+
pick(el);
|
|
3857
|
+
armClickSwallow();
|
|
3858
|
+
}
|
|
3859
|
+
}
|
|
3860
|
+
|
|
3861
|
+
// The click that follows a tap was already picked on pointerup; a click
|
|
3862
|
+
// with no pointer gesture before it (an old WebView) is the pick itself.
|
|
3863
|
+
function onClick(e) {
|
|
3864
|
+
block(e);
|
|
3865
|
+
if (tapped) { tapped = false; return; }
|
|
3866
|
+
var el = at(e);
|
|
3867
|
+
if (el) pick(el);
|
|
3868
|
+
}
|
|
3869
|
+
|
|
3870
|
+
// The browser fires a click after the pointerup that picked. Once pointing
|
|
3871
|
+
// is off (single mode, or the parent turned it off in between) nothing of
|
|
3872
|
+
// ours would catch it, and a pointed-at link would navigate. One shot:
|
|
3873
|
+
// gone on the next click, or after 400 ms when no click comes.
|
|
3874
|
+
function armClickSwallow() {
|
|
3875
|
+
disarmClickSwallow();
|
|
3876
|
+
var fn = function (e) {
|
|
3877
|
+
block(e);
|
|
3878
|
+
disarmClickSwallow();
|
|
3879
|
+
};
|
|
3880
|
+
swallow = fn;
|
|
3881
|
+
W.addEventListener('click', fn, { capture: true, passive: false });
|
|
3882
|
+
W.setTimeout(function () { if (swallow === fn) disarmClickSwallow(); }, 400);
|
|
3883
|
+
}
|
|
3884
|
+
|
|
3885
|
+
function disarmClickSwallow() {
|
|
3886
|
+
if (!swallow) return;
|
|
3887
|
+
W.removeEventListener('click', swallow, { capture: true });
|
|
3888
|
+
swallow = null;
|
|
3889
|
+
}
|
|
3890
|
+
|
|
3891
|
+
// The browser took the touch over to scroll: that was not a tap.
|
|
3892
|
+
function onCancel(e) {
|
|
3893
|
+
block(e);
|
|
3894
|
+
down = null;
|
|
3895
|
+
tapped = false;
|
|
3896
|
+
}
|
|
3897
|
+
|
|
3898
|
+
function onKey(e) {
|
|
3899
|
+
block(e);
|
|
3900
|
+
// In multi mode the parent owns the toggle: Escape ends nothing it can't see.
|
|
3901
|
+
if (!MULTI && e.type === 'keydown' && (e.key === 'Escape' || e.key === 'Esc')) {
|
|
3902
|
+
send('cancel');
|
|
3903
|
+
off(false);
|
|
3904
|
+
}
|
|
3905
|
+
}
|
|
3906
|
+
|
|
3907
|
+
function onScroll() {
|
|
3908
|
+
if (current) paint(current);
|
|
3909
|
+
if (picked.length) drawMarks();
|
|
3910
|
+
}
|
|
3911
|
+
|
|
3912
|
+
var HANDLERS = [
|
|
3913
|
+
['pointerdown', onDown], ['pointermove', onMove], ['pointerup', onUp], ['pointercancel', onCancel],
|
|
3914
|
+
['mousedown', block], ['mouseup', block], ['mousemove', onMouseMove], ['click', onClick], ['dblclick', block], ['auxclick', block],
|
|
3915
|
+
['contextmenu', block], ['touchstart', block], ['touchmove', block], ['touchend', block],
|
|
3916
|
+
['submit', block], ['keydown', onKey], ['keyup', block], ['keypress', block]
|
|
3917
|
+
];
|
|
3918
|
+
|
|
3919
|
+
function pick(el) {
|
|
3920
|
+
var element = describe(el);
|
|
3921
|
+
if (!MULTI) {
|
|
3922
|
+
off(true);
|
|
3923
|
+
send('pick', { element: element });
|
|
3924
|
+
return;
|
|
3925
|
+
}
|
|
3926
|
+
// Past the cap the pick still goes up (the app says "4 marks max") but
|
|
3927
|
+
// leaves nothing in the page the app would never be able to remove.
|
|
3928
|
+
if (picked.length < MAX_MARKS) {
|
|
3929
|
+
var id = 'p' + LOAD + '-' + (++seq);
|
|
3930
|
+
picked.push({ id: id, el: el });
|
|
3931
|
+
element.markId = id;
|
|
3932
|
+
drawMarks(id);
|
|
3933
|
+
}
|
|
3934
|
+
send('pick', { element: element });
|
|
3935
|
+
}
|
|
3936
|
+
|
|
3937
|
+
// The pinned marks: Remix rings with a numbered chip, anchored to the
|
|
3938
|
+
// DOCUMENT (absolute + scroll) so they travel with the content.
|
|
3939
|
+
function drawMarks(fresh) {
|
|
3940
|
+
if (!picked.length) {
|
|
3941
|
+
drop(marksHost);
|
|
3942
|
+
marksHost = marksRoot = null;
|
|
3943
|
+
return;
|
|
3944
|
+
}
|
|
3945
|
+
if (!marksHost || !marksHost.parentNode) {
|
|
3946
|
+
marksHost = makeHost('marks', 'absolute');
|
|
3947
|
+
marksRoot = shadowOf(marksHost);
|
|
3948
|
+
D.documentElement.appendChild(marksHost);
|
|
3949
|
+
}
|
|
3950
|
+
clear(marksRoot);
|
|
3951
|
+
var calm = reduced();
|
|
3952
|
+
if (!calm) {
|
|
3953
|
+
var keys = D.createElement('style');
|
|
3954
|
+
keys.textContent = '@keyframes pp-pin{from{opacity:0;transform:scale(1.04)}to{opacity:1;transform:scale(1)}}';
|
|
3955
|
+
marksRoot.appendChild(keys);
|
|
3956
|
+
}
|
|
3957
|
+
var sx = W.scrollX || W.pageXOffset || 0, sy = W.scrollY || W.pageYOffset || 0;
|
|
3958
|
+
for (var i = 0; i < picked.length; i++) {
|
|
3959
|
+
var r = picked[i].el.getBoundingClientRect();
|
|
3960
|
+
var box = D.createElement('div');
|
|
3961
|
+
box.setAttribute('data-codeam', 'mark');
|
|
3962
|
+
box.style.cssText = 'position:absolute;pointer-events:none;' + ringCss(accent) +
|
|
3963
|
+
';left:' + Math.round(r.left + sx - 4) + 'px;top:' + Math.round(r.top + sy - 4) + 'px' +
|
|
3964
|
+
';width:' + Math.round(r.width + 8) + 'px;height:' + Math.round(r.height + 8) + 'px' +
|
|
3965
|
+
(!calm && picked[i].id === fresh ? ';animation:pp-pin .32s ' + EASE : '');
|
|
3966
|
+
var badge = D.createElement('div');
|
|
3967
|
+
badge.setAttribute('data-codeam', 'mark-badge');
|
|
3968
|
+
badge.style.cssText = 'position:absolute;left:-11px;top:-11px;width:22px;height:22px;border-radius:11px;' +
|
|
3969
|
+
'background:#141416;color:#f6f3ee;font:italic 600 12px/22px Georgia,"Times New Roman",serif;text-align:center;' +
|
|
3970
|
+
'box-shadow:0 0 0 1px ' + accent + ';pointer-events:none';
|
|
3971
|
+
badge.textContent = String(i + 1);
|
|
3972
|
+
box.appendChild(badge);
|
|
3973
|
+
marksRoot.appendChild(box);
|
|
3974
|
+
}
|
|
3975
|
+
}
|
|
3976
|
+
|
|
3977
|
+
// The parent sends the ids still alive, in order: a removed chip removes
|
|
3978
|
+
// its mark, and the rest renumber (what the person writes, "1 is off",
|
|
3979
|
+
// refers to these numbers).
|
|
3980
|
+
function syncMarks(ids) {
|
|
3981
|
+
var byId = {};
|
|
3982
|
+
for (var i = 0; i < picked.length; i++) byId[picked[i].id] = picked[i];
|
|
3983
|
+
var next = [];
|
|
3984
|
+
for (var j = 0; j < ids.length; j++) if (byId[ids[j]]) next.push(byId[ids[j]]);
|
|
3985
|
+
picked = next;
|
|
3986
|
+
drawMarks();
|
|
3987
|
+
}
|
|
3988
|
+
|
|
3989
|
+
// The agent pointing (highlight_element): a cursor travels to the element,
|
|
3990
|
+
// centres it, and leaves a cyan Remix ring with its label. Independent of
|
|
3991
|
+
// pointing mode, anchored to the document like the marks.
|
|
3992
|
+
function ensureAgent() {
|
|
3993
|
+
if (agentHost && agentHost.parentNode) return;
|
|
3994
|
+
agentHost = makeHost('agent', 'absolute');
|
|
3995
|
+
agentRoot = shadowOf(agentHost);
|
|
3996
|
+
var keys = D.createElement('style');
|
|
3997
|
+
keys.textContent =
|
|
3998
|
+
'@keyframes pp-agent-pulse{0%{box-shadow:0 0 0 0 rgba(34,211,238,.55)}70%{box-shadow:0 0 0 10px rgba(34,211,238,0)}100%{box-shadow:0 0 0 5px rgba(34,211,238,.16)}}' +
|
|
3999
|
+
'@keyframes pp-agent-in{from{opacity:0;transform:scale(1.04)}to{opacity:1;transform:scale(1)}}';
|
|
4000
|
+
agentRoot.appendChild(keys);
|
|
4001
|
+
agentLayer = D.createElement('div');
|
|
4002
|
+
agentRoot.appendChild(agentLayer);
|
|
4003
|
+
D.documentElement.appendChild(agentHost);
|
|
4004
|
+
}
|
|
4005
|
+
|
|
4006
|
+
function ensureAgentCursor() {
|
|
4007
|
+
if (agentCursor && agentCursor.parentNode) return agentCursor;
|
|
4008
|
+
agentCursor = D.createElement('div');
|
|
4009
|
+
agentCursor.setAttribute('data-codeam', 'agent-cursor');
|
|
4010
|
+
agentCursor.style.cssText = 'position:fixed;pointer-events:none;opacity:0;' +
|
|
4011
|
+
'left:' + Math.round(W.innerWidth / 2) + 'px;top:' + Math.round(W.innerHeight - 40) + 'px;' +
|
|
4012
|
+
'transition:' + (reduced() ? 'none' : 'left .6s cubic-bezier(.22,1,.36,1),top .6s cubic-bezier(.22,1,.36,1),opacity .3s');
|
|
4013
|
+
agentCursor.innerHTML =
|
|
4014
|
+
'<svg width="22" height="22" viewBox="0 0 24 24" style="display:block;filter:drop-shadow(0 1px 2px rgba(0,0,0,.5))">' +
|
|
4015
|
+
'<path d="M4 2l15 8.5-6.6 1.6L9 18.5z" fill="' + AGENT_ACCENT + '" stroke="#141416" stroke-width="1.2"/></svg>' +
|
|
4016
|
+
'<div style="margin:2px 0 0 14px;display:inline-block;' + chipCss(AGENT_ACCENT) + ';padding:2px 8px;font-size:11px">Agent</div>';
|
|
4017
|
+
agentRoot.appendChild(agentCursor);
|
|
4018
|
+
return agentCursor;
|
|
4019
|
+
}
|
|
4020
|
+
|
|
4021
|
+
function drawAgentMarks() {
|
|
4022
|
+
if (!agentLayer) return;
|
|
4023
|
+
clear(agentLayer);
|
|
4024
|
+
var calm = reduced();
|
|
4025
|
+
var sx = W.scrollX || W.pageXOffset || 0, sy = W.scrollY || W.pageYOffset || 0;
|
|
4026
|
+
for (var i = 0; i < agentMarks.length; i++) {
|
|
4027
|
+
var m = agentMarks[i];
|
|
4028
|
+
if (m.el.isConnected === false) continue;
|
|
4029
|
+
var r = m.el.getBoundingClientRect();
|
|
4030
|
+
var box = D.createElement('div');
|
|
4031
|
+
box.setAttribute('data-codeam', 'agent-mark');
|
|
4032
|
+
box.style.cssText = 'position:absolute;pointer-events:none;' + ringCss(AGENT_ACCENT) +
|
|
4033
|
+
';left:' + Math.round(r.left + sx - 4) + 'px;top:' + Math.round(r.top + sy - 4) + 'px' +
|
|
4034
|
+
';width:' + Math.round(r.width + 8) + 'px;height:' + Math.round(r.height + 8) + 'px' +
|
|
4035
|
+
(calm ? '' : ';animation:pp-agent-in .25s ' + EASE + ',pp-agent-pulse 1.6s ease-out 3');
|
|
4036
|
+
if (m.label) {
|
|
4037
|
+
var tag = D.createElement('div');
|
|
4038
|
+
tag.setAttribute('data-codeam', 'agent-mark-label');
|
|
4039
|
+
// Above the element when it fits, else below \u2014 same rule as the chip.
|
|
4040
|
+
tag.style.cssText = 'position:absolute;left:0;' + (r.top >= 34 ? 'top:-30px' : 'top:' + Math.round(r.height + 12) + 'px') +
|
|
4041
|
+
';pointer-events:none;' + chipCss(AGENT_ACCENT) + ';max-width:260px;overflow:hidden;text-overflow:ellipsis';
|
|
4042
|
+
tag.textContent = m.label;
|
|
4043
|
+
box.appendChild(tag);
|
|
4044
|
+
}
|
|
4045
|
+
agentLayer.appendChild(box);
|
|
4046
|
+
}
|
|
4047
|
+
}
|
|
4048
|
+
|
|
4049
|
+
function listenAgentLayout() {
|
|
4050
|
+
if (agentListening) return;
|
|
4051
|
+
agentListening = true;
|
|
4052
|
+
W.addEventListener('scroll', drawAgentMarks, true);
|
|
4053
|
+
W.addEventListener('resize', drawAgentMarks);
|
|
4054
|
+
}
|
|
4055
|
+
|
|
4056
|
+
function agentHighlight(selector, text) {
|
|
4057
|
+
var el = null;
|
|
4058
|
+
try { el = D.querySelector(String(selector)); } catch (e) { el = null; }
|
|
4059
|
+
if (!el || !el.getBoundingClientRect) return false;
|
|
4060
|
+
ensureAgent();
|
|
4061
|
+
listenAgentLayout();
|
|
4062
|
+
var calm = reduced();
|
|
4063
|
+
try { el.scrollIntoView({ block: 'center', inline: 'nearest', behavior: calm ? 'auto' : 'smooth' }); } catch (e) {}
|
|
4064
|
+
var pointer = ensureAgentCursor();
|
|
4065
|
+
var owner = agentHost;
|
|
4066
|
+
// After the smooth scroll the cursor travels to the element and, on
|
|
4067
|
+
// arrival, the ring appears: read as "the agent is pointing at this".
|
|
4068
|
+
W.setTimeout(function () {
|
|
4069
|
+
if (agentHost !== owner) return;
|
|
4070
|
+
var r = el.getBoundingClientRect();
|
|
4071
|
+
pointer.style.opacity = '1';
|
|
4072
|
+
pointer.style.left = Math.round(r.left + Math.min(r.width / 2, 40)) + 'px';
|
|
4073
|
+
pointer.style.top = Math.round(r.top + Math.min(r.height / 2, 24)) + 'px';
|
|
4074
|
+
W.setTimeout(function () {
|
|
4075
|
+
if (agentHost !== owner) return;
|
|
4076
|
+
agentMarks.push({ el: el, label: text ? String(text).slice(0, 80) : '' });
|
|
4077
|
+
drawAgentMarks();
|
|
4078
|
+
}, 620);
|
|
4079
|
+
}, 380);
|
|
4080
|
+
return true;
|
|
4081
|
+
}
|
|
4082
|
+
|
|
4083
|
+
function agentClear() {
|
|
4084
|
+
agentMarks = [];
|
|
4085
|
+
drop(agentHost);
|
|
4086
|
+
agentHost = agentRoot = agentLayer = agentCursor = null;
|
|
4087
|
+
if (agentListening) {
|
|
4088
|
+
W.removeEventListener('scroll', drawAgentMarks, true);
|
|
4089
|
+
W.removeEventListener('resize', drawAgentMarks);
|
|
4090
|
+
agentListening = false;
|
|
4091
|
+
}
|
|
4092
|
+
}
|
|
4093
|
+
|
|
4094
|
+
function enable(origin, a) {
|
|
4095
|
+
driver = origin;
|
|
4096
|
+
accent = typeof a === 'string' && ACCENT_RE.test(a) ? a : DEFAULT_ACCENT;
|
|
4097
|
+
if (!on) {
|
|
4098
|
+
on = true;
|
|
4099
|
+
build();
|
|
4100
|
+
for (var i = 0; i < HANDLERS.length; i++) {
|
|
4101
|
+
W.addEventListener(HANDLERS[i][0], HANDLERS[i][1], { capture: true, passive: false });
|
|
4102
|
+
bound.push(HANDLERS[i]);
|
|
4103
|
+
}
|
|
4104
|
+
W.addEventListener('scroll', onScroll, true);
|
|
4105
|
+
W.addEventListener('resize', onScroll, true);
|
|
4106
|
+
}
|
|
4107
|
+
send(MULTI ? 'ready' : 'on');
|
|
4108
|
+
}
|
|
4109
|
+
|
|
4110
|
+
function off(pinned) {
|
|
4111
|
+
if (!on) return;
|
|
4112
|
+
on = false;
|
|
4113
|
+
while (bound.length) {
|
|
4114
|
+
var h = bound.pop();
|
|
4115
|
+
W.removeEventListener(h[0], h[1], { capture: true });
|
|
4116
|
+
}
|
|
4117
|
+
W.removeEventListener('scroll', onScroll, true);
|
|
4118
|
+
W.removeEventListener('resize', onScroll, true);
|
|
4119
|
+
D.documentElement.removeAttribute('data-remix-pointing');
|
|
4120
|
+
if (style && style.parentNode) style.parentNode.removeChild(style);
|
|
4121
|
+
var node = host;
|
|
4122
|
+
if (pinned && node && !reduced()) {
|
|
4123
|
+
// A short "pinned" beat before the ring goes, so the tap feels taken.
|
|
4124
|
+
ring.style.transition = 'transform .32s ' + EASE + ', opacity .32s';
|
|
4125
|
+
ring.style.transform += ' scale(1.04)';
|
|
4126
|
+
ring.style.opacity = '0';
|
|
4127
|
+
veil.style.opacity = '0';
|
|
4128
|
+
chip.style.opacity = '0';
|
|
4129
|
+
leaving = node;
|
|
4130
|
+
W.setTimeout(function () {
|
|
4131
|
+
if (node.parentNode) node.parentNode.removeChild(node);
|
|
4132
|
+
if (leaving === node) leaving = null;
|
|
4133
|
+
}, 320);
|
|
4134
|
+
} else if (node && node.parentNode) {
|
|
4135
|
+
node.parentNode.removeChild(node);
|
|
4136
|
+
}
|
|
4137
|
+
host = veil = ring = chip = style = null;
|
|
4138
|
+
current = null;
|
|
4139
|
+
down = null;
|
|
4140
|
+
tapped = false;
|
|
4141
|
+
}
|
|
4142
|
+
|
|
4143
|
+
W.addEventListener('message', function (e) {
|
|
4144
|
+
if (ALLOWED.indexOf(e.origin) === -1 || e.source !== W.parent) return;
|
|
4145
|
+
var d = e.data;
|
|
4146
|
+
if (!d || typeof d !== 'object' || d[FIELD] !== CH) return;
|
|
4147
|
+
if (d.type === 'enable') enable(e.origin, d.accent);
|
|
4148
|
+
else if (d.type === 'disable' && e.origin === driver) off(false);
|
|
4149
|
+
else if (MULTI && d.type === 'marks' && d.ids && d.ids.length !== undefined) syncMarks(d.ids);
|
|
4150
|
+
else if (AGENT && d.type === 'agent-highlight' && d.selector) agentHighlight(d.selector, d.label);
|
|
4151
|
+
else if (AGENT && d.type === 'agent-clear') agentClear();
|
|
4152
|
+
});
|
|
4153
|
+
|
|
4154
|
+
if (!MULTI) {
|
|
4155
|
+
try {
|
|
4156
|
+
Object.defineProperty(W, '__remixPoint', {
|
|
4157
|
+
value: Object.freeze({ version: 1, active: function () { return on; } })
|
|
4158
|
+
});
|
|
4159
|
+
} catch (e) {}
|
|
4160
|
+
}
|
|
4161
|
+
|
|
4162
|
+
// The React Native door. Only where the bridge exists: on a normal page it
|
|
4163
|
+
// would be a global that turns the picker on with nobody's permission.
|
|
4164
|
+
if (GLOBAL && rnBridge()) {
|
|
4165
|
+
W[GLOBAL] = {
|
|
4166
|
+
enable: function () { enable('react-native'); },
|
|
4167
|
+
disable: function () { off(false); },
|
|
4168
|
+
marks: function (ids) { if (MULTI && ids && ids.length !== undefined) syncMarks(ids); },
|
|
4169
|
+
highlight: function (selector, text) { return AGENT ? agentHighlight(selector, text) : false; },
|
|
4170
|
+
clear: function () { if (AGENT) agentClear(); }
|
|
4171
|
+
};
|
|
4172
|
+
}
|
|
4173
|
+
} catch (e) {
|
|
4174
|
+
// Whatever happens, the person's app keeps working.
|
|
4175
|
+
}
|
|
4176
|
+
})();`;
|
|
4177
|
+
}
|
|
4178
|
+
|
|
3461
4179
|
// src/config.ts
|
|
3462
4180
|
var fs3 = __toESM(require("fs"));
|
|
3463
4181
|
var os2 = __toESM(require("os"));
|
|
@@ -10636,7 +11354,7 @@ function readAnonId() {
|
|
|
10636
11354
|
}
|
|
10637
11355
|
function superProperties() {
|
|
10638
11356
|
return {
|
|
10639
|
-
cliVersion: true ? "2.76.
|
|
11357
|
+
cliVersion: true ? "2.76.37" : "0.0.0-dev",
|
|
10640
11358
|
nodeVersion: process.version,
|
|
10641
11359
|
platform: process.platform,
|
|
10642
11360
|
arch: process.arch,
|
|
@@ -10885,7 +11603,7 @@ var http = __toESM(require("http"));
|
|
|
10885
11603
|
// package.json
|
|
10886
11604
|
var package_default = {
|
|
10887
11605
|
name: "codeam-cli",
|
|
10888
|
-
version: "2.76.
|
|
11606
|
+
version: "2.76.37",
|
|
10889
11607
|
description: "Workflow-continuity bridge for AI coding agents. Wrap Claude Code or Codex in a PTY and supervise, approve, and redirect the session from any device \u2014 async. The terminal companion for CodeAgent Mobile.",
|
|
10890
11608
|
type: "commonjs",
|
|
10891
11609
|
main: "dist/index.js",
|
|
@@ -12261,7 +12979,7 @@ var CommandRelayService = class _CommandRelayService {
|
|
|
12261
12979
|
// fresh + clear the "CLI update available" banner after a self-update
|
|
12262
12980
|
// (a codespace that reinstalls @latest reconnects via heartbeat, not
|
|
12263
12981
|
// pair/reconnect). Older backends ignore the extra field.
|
|
12264
|
-
..."2.76.
|
|
12982
|
+
..."2.76.37" ? { ideVersion: "2.76.37" } : {}
|
|
12265
12983
|
};
|
|
12266
12984
|
try {
|
|
12267
12985
|
const res = await _postJson(`${API_BASE2}/api/plugin/heartbeat`, body, this.pollSecretHeader());
|
|
@@ -23395,27 +24113,153 @@ var import_os10 = __toESM(require("os"));
|
|
|
23395
24113
|
var import_path5 = __toESM(require("path"));
|
|
23396
24114
|
var import_promises3 = require("stream/promises");
|
|
23397
24115
|
var import_which = __toESM(require("which"));
|
|
23398
|
-
var
|
|
24116
|
+
var CACHE_DIR = import_path5.default.join(import_os10.default.homedir(), ".codeam", "bin");
|
|
24117
|
+
var LEGACY_CACHED_BINARY = import_path5.default.join(CACHE_DIR, "cloudflared");
|
|
24118
|
+
function cachedCloudflaredPath(platform3 = process.platform) {
|
|
24119
|
+
return platform3 === "win32" ? import_path5.default.join(CACHE_DIR, "cloudflared.exe") : LEGACY_CACHED_BINARY;
|
|
24120
|
+
}
|
|
24121
|
+
var MIN_CLOUDFLARED_VERSION = [2026, 10, 2];
|
|
24122
|
+
var MIN_CLOUDFLARED_VERSION_DARWIN_NON_BREW = [2026, 10, 3];
|
|
24123
|
+
var DEFAULT_HOMEBREW_PREFIXES = [
|
|
24124
|
+
"/opt/homebrew/",
|
|
24125
|
+
"/usr/local/Cellar/",
|
|
24126
|
+
"/usr/local/Homebrew/",
|
|
24127
|
+
"/home/linuxbrew/"
|
|
24128
|
+
];
|
|
24129
|
+
function homebrewPrefixes(env = process.env) {
|
|
24130
|
+
const custom = env.HOMEBREW_PREFIX?.replace(/\/+$/, "");
|
|
24131
|
+
return custom ? [...DEFAULT_HOMEBREW_PREFIXES, `${custom}/`, `${custom}/Cellar/`] : [...DEFAULT_HOMEBREW_PREFIXES];
|
|
24132
|
+
}
|
|
24133
|
+
function parseCloudflaredVersion(output) {
|
|
24134
|
+
const m = /cloudflared version (\d+)\.(\d+)\.(\d+)/.exec(output);
|
|
24135
|
+
return m ? [Number(m[1]), Number(m[2]), Number(m[3])] : null;
|
|
24136
|
+
}
|
|
24137
|
+
function isHomebrewPath(bin, prefixes = homebrewPrefixes()) {
|
|
24138
|
+
return prefixes.some((prefix) => bin.startsWith(prefix));
|
|
24139
|
+
}
|
|
24140
|
+
function formatCloudflaredVersion(v) {
|
|
24141
|
+
return v.join(".");
|
|
24142
|
+
}
|
|
24143
|
+
function minimumCloudflaredVersion(bin, platform3 = process.platform, prefixes = homebrewPrefixes()) {
|
|
24144
|
+
return platform3 === "darwin" && !isHomebrewPath(bin, prefixes) ? MIN_CLOUDFLARED_VERSION_DARWIN_NON_BREW : MIN_CLOUDFLARED_VERSION;
|
|
24145
|
+
}
|
|
24146
|
+
function compareVersions(a, b) {
|
|
24147
|
+
for (let i = 0; i < 3; i++) {
|
|
24148
|
+
if (a[i] !== b[i]) return a[i] - b[i];
|
|
24149
|
+
}
|
|
24150
|
+
return 0;
|
|
24151
|
+
}
|
|
24152
|
+
function meetsMinimumCloudflaredVersion(version3, bin, platform3 = process.platform, prefixes = homebrewPrefixes()) {
|
|
24153
|
+
if (!version3) return false;
|
|
24154
|
+
return compareVersions(version3, minimumCloudflaredVersion(bin, platform3, prefixes)) >= 0;
|
|
24155
|
+
}
|
|
24156
|
+
var versionCache = /* @__PURE__ */ new Map();
|
|
24157
|
+
var warnedOutdated = /* @__PURE__ */ new Set();
|
|
24158
|
+
function readCloudflaredVersion(bin) {
|
|
24159
|
+
let cached2 = versionCache.get(bin);
|
|
24160
|
+
if (!cached2) {
|
|
24161
|
+
const pending2 = new Promise((resolve13) => {
|
|
24162
|
+
(0, import_child_process14.execFile)(bin, ["--version"], { timeout: 1e4 }, (err, stdout, stderr) => {
|
|
24163
|
+
resolve13(err ? null : parseCloudflaredVersion(`${stdout}
|
|
24164
|
+
${stderr}`));
|
|
24165
|
+
});
|
|
24166
|
+
}).then((version3) => {
|
|
24167
|
+
if (!version3 && versionCache.get(bin) === pending2) versionCache.delete(bin);
|
|
24168
|
+
return version3;
|
|
24169
|
+
});
|
|
24170
|
+
cached2 = pending2;
|
|
24171
|
+
versionCache.set(bin, pending2);
|
|
24172
|
+
}
|
|
24173
|
+
return cached2;
|
|
24174
|
+
}
|
|
24175
|
+
async function realpathOrSelf(p2) {
|
|
24176
|
+
try {
|
|
24177
|
+
return await import_promises2.default.realpath(p2);
|
|
24178
|
+
} catch {
|
|
24179
|
+
return p2;
|
|
24180
|
+
}
|
|
24181
|
+
}
|
|
24182
|
+
async function checkCloudflaredVersion(bin) {
|
|
24183
|
+
const version3 = await readCloudflaredVersion(bin);
|
|
24184
|
+
const real = await realpathOrSelf(bin);
|
|
24185
|
+
const prefixes = homebrewPrefixes();
|
|
24186
|
+
const customPrefix = process.env.HOMEBREW_PREFIX?.replace(/\/+$/, "");
|
|
24187
|
+
if (customPrefix) {
|
|
24188
|
+
const realPrefix = await realpathOrSelf(customPrefix);
|
|
24189
|
+
if (realPrefix !== customPrefix) prefixes.push(`${realPrefix}/`, `${realPrefix}/Cellar/`);
|
|
24190
|
+
}
|
|
24191
|
+
const brewBin = isHomebrewPath(bin, prefixes) ? bin : real;
|
|
24192
|
+
return {
|
|
24193
|
+
ok: meetsMinimumCloudflaredVersion(version3, brewBin, process.platform, prefixes),
|
|
24194
|
+
version: version3,
|
|
24195
|
+
min: minimumCloudflaredVersion(brewBin, process.platform, prefixes)
|
|
24196
|
+
};
|
|
24197
|
+
}
|
|
24198
|
+
async function migrateLegacyWindowsCache(target) {
|
|
24199
|
+
if (target === LEGACY_CACHED_BINARY) return;
|
|
24200
|
+
try {
|
|
24201
|
+
await import_promises2.default.access(target);
|
|
24202
|
+
return;
|
|
24203
|
+
} catch {
|
|
24204
|
+
}
|
|
24205
|
+
try {
|
|
24206
|
+
await import_promises2.default.access(LEGACY_CACHED_BINARY);
|
|
24207
|
+
await import_promises2.default.rename(LEGACY_CACHED_BINARY, target);
|
|
24208
|
+
} catch {
|
|
24209
|
+
}
|
|
24210
|
+
}
|
|
24211
|
+
function describeVersion(v) {
|
|
24212
|
+
return v ? formatCloudflaredVersion(v) : "an unknown version";
|
|
24213
|
+
}
|
|
23399
24214
|
async function resolveCloudflared(opts = {}) {
|
|
24215
|
+
let pathBin;
|
|
23400
24216
|
try {
|
|
23401
|
-
|
|
24217
|
+
pathBin = await (0, import_which.default)("cloudflared");
|
|
23402
24218
|
} catch {
|
|
23403
24219
|
}
|
|
24220
|
+
if (pathBin) {
|
|
24221
|
+
const check2 = await checkCloudflaredVersion(pathBin);
|
|
24222
|
+
if (check2.ok) return pathBin;
|
|
24223
|
+
if (!warnedOutdated.has(pathBin)) {
|
|
24224
|
+
warnedOutdated.add(pathBin);
|
|
24225
|
+
log.warn(
|
|
24226
|
+
"preview",
|
|
24227
|
+
`ignoring ${pathBin} (${describeVersion(check2.version)}): previews need cloudflared >= ${formatCloudflaredVersion(check2.min)}; upgrade cloudflared with your package manager (e.g. \`brew upgrade cloudflared\`). Using a CodeAgent-managed copy instead.`
|
|
24228
|
+
);
|
|
24229
|
+
}
|
|
24230
|
+
}
|
|
24231
|
+
const cached2 = cachedCloudflaredPath();
|
|
24232
|
+
await migrateLegacyWindowsCache(cached2);
|
|
24233
|
+
let staleCache = false;
|
|
23404
24234
|
try {
|
|
23405
|
-
await import_promises2.default.access(
|
|
23406
|
-
if (await isExecutableBinary(
|
|
23407
|
-
|
|
24235
|
+
await import_promises2.default.access(cached2);
|
|
24236
|
+
if (!await isExecutableBinary(cached2)) {
|
|
24237
|
+
await import_promises2.default.rm(cached2, { force: true });
|
|
24238
|
+
} else if ((await checkCloudflaredVersion(cached2)).ok) {
|
|
24239
|
+
return cached2;
|
|
24240
|
+
} else {
|
|
24241
|
+
staleCache = true;
|
|
23408
24242
|
}
|
|
23409
|
-
await import_promises2.default.rm(CACHED_BINARY, { force: true });
|
|
23410
24243
|
} catch {
|
|
23411
24244
|
}
|
|
23412
24245
|
if (opts.skipDownload) {
|
|
23413
24246
|
throw new Error(
|
|
23414
|
-
|
|
24247
|
+
`cloudflared not installed (or older than ${formatCloudflaredVersion(minimumCloudflaredVersion(cached2))}). Install or upgrade via \`brew install cloudflared\` (macOS) or download from https://github.com/cloudflare/cloudflared/releases.`
|
|
23415
24248
|
);
|
|
23416
24249
|
}
|
|
23417
|
-
await
|
|
23418
|
-
|
|
24250
|
+
if (staleCache) await import_promises2.default.rm(cached2, { force: true });
|
|
24251
|
+
versionCache.delete(cached2);
|
|
24252
|
+
await downloadCloudflared(cached2);
|
|
24253
|
+
versionCache.delete(cached2);
|
|
24254
|
+
const check = await checkCloudflaredVersion(cached2);
|
|
24255
|
+
if (!check.ok) {
|
|
24256
|
+
await import_promises2.default.rm(cached2, { force: true });
|
|
24257
|
+
versionCache.delete(cached2);
|
|
24258
|
+
throw new Error(
|
|
24259
|
+
`Downloaded cloudflared reports ${describeVersion(check.version)}, but previews need cloudflared >= ${formatCloudflaredVersion(check.min)}. Install the latest version manually via \`brew install cloudflared\` (macOS) or from https://github.com/cloudflare/cloudflared/releases.`
|
|
24260
|
+
);
|
|
24261
|
+
}
|
|
24262
|
+
return cached2;
|
|
23419
24263
|
}
|
|
23420
24264
|
async function downloadCloudflared(target) {
|
|
23421
24265
|
const url2 = downloadUrlForPlatform();
|
|
@@ -26453,470 +27297,22 @@ async function startInspectorProxy(opts) {
|
|
|
26453
27297
|
|
|
26454
27298
|
// src/services/preview/inspector-client.ts
|
|
26455
27299
|
var INSPECTOR_CHANNEL = "codeam-inspector";
|
|
27300
|
+
var INSPECTOR_MAX_MARKS = 4;
|
|
27301
|
+
var INSPECTOR_ACCENT = "#a855f7";
|
|
26456
27302
|
function inspectorClientSource(opts) {
|
|
26457
|
-
const
|
|
26458
|
-
|
|
27303
|
+
const script = pointPickerScript({
|
|
27304
|
+
channel: INSPECTOR_CHANNEL,
|
|
27305
|
+
channelField: "source",
|
|
27306
|
+
allowedParents: opts.allowedOrigins,
|
|
27307
|
+
mode: "multi",
|
|
27308
|
+
maxMarks: INSPECTOR_MAX_MARKS,
|
|
27309
|
+
accent: INSPECTOR_ACCENT,
|
|
27310
|
+
agentHighlights: true,
|
|
27311
|
+
reactSource: true,
|
|
27312
|
+
globalName: "__codeamInspector"
|
|
27313
|
+
});
|
|
26459
27314
|
return `<script id="codeam-inspector" data-codeam="inspector">
|
|
26460
|
-
|
|
26461
|
-
'use strict';
|
|
26462
|
-
try {
|
|
26463
|
-
var CHANNEL = ${channel};
|
|
26464
|
-
var ALLOWED = ${origins};
|
|
26465
|
-
|
|
26466
|
-
var enabled = false;
|
|
26467
|
-
var driver = null; // el origen que nos encendio
|
|
26468
|
-
var overlay = null;
|
|
26469
|
-
var label = null;
|
|
26470
|
-
var current = null;
|
|
26471
|
-
|
|
26472
|
-
function allowed(origin) {
|
|
26473
|
-
return ALLOWED.indexOf(origin) !== -1;
|
|
26474
|
-
}
|
|
26475
|
-
|
|
26476
|
-
// \xBFEstamos dentro del WebView de la app movil?
|
|
26477
|
-
//
|
|
26478
|
-
// \u26A0\uFE0F En un WebView el documento es de NIVEL SUPERIOR, asi que
|
|
26479
|
-
// \`window.parent === window\` y la via del iframe no existe: el script
|
|
26480
|
-
// hablaba solo, y en movil el inspector no devolvia nada. React Native
|
|
26481
|
-
// expone su propio canal, que es el unico que sale de ahi.
|
|
26482
|
-
function rnBridge() {
|
|
26483
|
-
return typeof window.ReactNativeWebView !== 'undefined' &&
|
|
26484
|
-
window.ReactNativeWebView &&
|
|
26485
|
-
typeof window.ReactNativeWebView.postMessage === 'function'
|
|
26486
|
-
? window.ReactNativeWebView
|
|
26487
|
-
: null;
|
|
26488
|
-
}
|
|
26489
|
-
|
|
26490
|
-
function send(type, payload) {
|
|
26491
|
-
if (!driver) return;
|
|
26492
|
-
var msg = { source: CHANNEL, type: type };
|
|
26493
|
-
for (var k in payload) if (Object.prototype.hasOwnProperty.call(payload, k)) msg[k] = payload[k];
|
|
26494
|
-
|
|
26495
|
-
var rn = rnBridge();
|
|
26496
|
-
if (rn) {
|
|
26497
|
-
// El canal de RN transporta CADENAS, no objetos: pasarle el objeto
|
|
26498
|
-
// llega al otro lado como "[object Object]".
|
|
26499
|
-
rn.postMessage(JSON.stringify(msg));
|
|
26500
|
-
return;
|
|
26501
|
-
}
|
|
26502
|
-
if (window.parent === window) return;
|
|
26503
|
-
window.parent.postMessage(msg, driver);
|
|
26504
|
-
}
|
|
26505
|
-
|
|
26506
|
-
// El resaltado. Un div fijo por encima de todo que NUNCA captura el
|
|
26507
|
-
// puntero: si lo capturara, el elemento de debajo dejaria de recibir el
|
|
26508
|
-
// mousemove y el resaltado se quedaria pegado al primero que tocara.
|
|
26509
|
-
function ensureOverlay() {
|
|
26510
|
-
if (overlay) return;
|
|
26511
|
-
overlay = document.createElement('div');
|
|
26512
|
-
overlay.setAttribute('data-codeam', 'inspector-overlay');
|
|
26513
|
-
overlay.style.cssText = [
|
|
26514
|
-
'position:fixed', 'pointer-events:none', 'z-index:2147483647',
|
|
26515
|
-
'border:1px solid #a855f7', 'background:rgba(168,85,247,0.14)',
|
|
26516
|
-
'border-radius:2px', 'transition:none', 'display:none'
|
|
26517
|
-
].join(';');
|
|
26518
|
-
label = document.createElement('div');
|
|
26519
|
-
label.setAttribute('data-codeam', 'inspector-label');
|
|
26520
|
-
label.style.cssText = [
|
|
26521
|
-
'position:fixed', 'pointer-events:none', 'z-index:2147483647',
|
|
26522
|
-
'background:#a855f7', 'color:#000', 'font:600 11px/1.4 ui-monospace,SFMono-Regular,Menlo,monospace',
|
|
26523
|
-
'padding:2px 6px', 'border-radius:3px', 'white-space:nowrap', 'display:none'
|
|
26524
|
-
].join(';');
|
|
26525
|
-
document.body.appendChild(overlay);
|
|
26526
|
-
document.body.appendChild(label);
|
|
26527
|
-
}
|
|
26528
|
-
|
|
26529
|
-
function removeOverlay() {
|
|
26530
|
-
if (overlay && overlay.parentNode) overlay.parentNode.removeChild(overlay);
|
|
26531
|
-
if (label && label.parentNode) label.parentNode.removeChild(label);
|
|
26532
|
-
overlay = null;
|
|
26533
|
-
label = null;
|
|
26534
|
-
}
|
|
26535
|
-
|
|
26536
|
-
// Fichero y linea del componente de React, cuando el dev server los
|
|
26537
|
-
// expone. Es lo que hace que el agente reciba
|
|
26538
|
-
// "components/whatsapp-button.tsx:42" en vez de "x:0.62 y:0.81".
|
|
26539
|
-
// Solo existe en builds de desarrollo; en produccion devuelve null y se
|
|
26540
|
-
// cae al selector CSS.
|
|
26541
|
-
function reactSource(el) {
|
|
26542
|
-
try {
|
|
26543
|
-
for (var key in el) {
|
|
26544
|
-
if (key.indexOf('__reactFiber$') !== 0) continue;
|
|
26545
|
-
var fiber = el[key];
|
|
26546
|
-
while (fiber) {
|
|
26547
|
-
var src = fiber._debugSource;
|
|
26548
|
-
if (src && src.fileName) {
|
|
26549
|
-
return { file: String(src.fileName), line: Number(src.lineNumber) || null };
|
|
26550
|
-
}
|
|
26551
|
-
fiber = fiber.return;
|
|
26552
|
-
}
|
|
26553
|
-
}
|
|
26554
|
-
} catch (e) { /* nunca romper la pagina por esto */ }
|
|
26555
|
-
return null;
|
|
26556
|
-
}
|
|
26557
|
-
|
|
26558
|
-
// Un selector corto y legible, el respaldo cuando no hay React.
|
|
26559
|
-
function selectorFor(el) {
|
|
26560
|
-
if (el.id) return '#' + el.id;
|
|
26561
|
-
var name = el.tagName ? el.tagName.toLowerCase() : 'node';
|
|
26562
|
-
var cls = (el.className && typeof el.className === 'string')
|
|
26563
|
-
? el.className.trim().split(/\\s+/).slice(0, 3).join('.')
|
|
26564
|
-
: '';
|
|
26565
|
-
return cls ? name + '.' + cls : name;
|
|
26566
|
-
}
|
|
26567
|
-
|
|
26568
|
-
function describe(el) {
|
|
26569
|
-
var r = el.getBoundingClientRect();
|
|
26570
|
-
var text = (el.textContent || '').replace(/\\s+/g, ' ').trim();
|
|
26571
|
-
return {
|
|
26572
|
-
tag: el.tagName ? el.tagName.toLowerCase() : 'node',
|
|
26573
|
-
id: el.id || null,
|
|
26574
|
-
classes: (el.className && typeof el.className === 'string') ? el.className.trim() : '',
|
|
26575
|
-
selector: selectorFor(el),
|
|
26576
|
-
// Un recorte, no el contenido: describir no es extraer.
|
|
26577
|
-
text: text.length > 120 ? text.slice(0, 120) + '\u2026' : text,
|
|
26578
|
-
rect: { x: r.left, y: r.top, w: r.width, h: r.height },
|
|
26579
|
-
viewport: { w: window.innerWidth, h: window.innerHeight },
|
|
26580
|
-
source: reactSource(el)
|
|
26581
|
-
};
|
|
26582
|
-
}
|
|
26583
|
-
|
|
26584
|
-
function paint(el) {
|
|
26585
|
-
ensureOverlay();
|
|
26586
|
-
var r = el.getBoundingClientRect();
|
|
26587
|
-
overlay.style.display = 'block';
|
|
26588
|
-
overlay.style.left = r.left + 'px';
|
|
26589
|
-
overlay.style.top = r.top + 'px';
|
|
26590
|
-
overlay.style.width = r.width + 'px';
|
|
26591
|
-
overlay.style.height = r.height + 'px';
|
|
26592
|
-
label.style.display = 'block';
|
|
26593
|
-
label.textContent = selectorFor(el) + ' ' + Math.round(r.width) + '\xD7' + Math.round(r.height);
|
|
26594
|
-
// Encima si cabe; si no, dentro. Una etiqueta cortada por el borde
|
|
26595
|
-
// superior no se lee.
|
|
26596
|
-
var above = r.top >= 20;
|
|
26597
|
-
label.style.left = r.left + 'px';
|
|
26598
|
-
label.style.top = (above ? r.top - 20 : r.top + 2) + 'px';
|
|
26599
|
-
}
|
|
26600
|
-
|
|
26601
|
-
function onMove(e) {
|
|
26602
|
-
if (!enabled) return;
|
|
26603
|
-
var el = e.target;
|
|
26604
|
-
if (!el || el === current || !el.getBoundingClientRect) return;
|
|
26605
|
-
if (el.getAttribute && el.getAttribute('data-codeam')) return;
|
|
26606
|
-
current = el;
|
|
26607
|
-
paint(el);
|
|
26608
|
-
send('hover', { element: describe(el) });
|
|
26609
|
-
}
|
|
26610
|
-
|
|
26611
|
-
// Captura, y se traga el evento: mientras el modo esta activo un clic
|
|
26612
|
-
// SELECCIONA, no navega. Sin esto, pulsar un enlace se llevaria el
|
|
26613
|
-
// preview a otra pagina en mitad del gesto.
|
|
26614
|
-
/**
|
|
26615
|
-
* Las marcas FIJADAS, dibujadas DENTRO de la pagina.
|
|
26616
|
-
*
|
|
26617
|
-
* \u26A0\uFE0F Antes las pintaba el dashboard, en una capa sobre el iframe. Como esa
|
|
26618
|
-
* capa vive fuera del documento, sus coordenadas son del VIEWPORT: al
|
|
26619
|
-
* hacer scroll dentro del preview las marcas se quedaban clavadas en la
|
|
26620
|
-
* pantalla mientras el elemento se iba (reportado el 2026-08-29).
|
|
26621
|
-
*
|
|
26622
|
-
* Aqui se anclan al DOCUMENTO (position:absolute mas el scroll sumado), asi
|
|
26623
|
-
* que acompa\xF1an al contenido igual que cualquier otro nodo de la pagina \u2014 y
|
|
26624
|
-
* ademas se recolocan si el layout cambia, que una capa externa no puede
|
|
26625
|
-
* saber.
|
|
26626
|
-
*/
|
|
26627
|
-
var picked = [];
|
|
26628
|
-
var seq = 0;
|
|
26629
|
-
var marksHost = null;
|
|
26630
|
-
|
|
26631
|
-
function ensureMarksHost() {
|
|
26632
|
-
if (marksHost && marksHost.parentNode) return marksHost;
|
|
26633
|
-
marksHost = document.createElement('div');
|
|
26634
|
-
marksHost.setAttribute('data-codeam', 'marks');
|
|
26635
|
-
marksHost.style.cssText = 'position:absolute;left:0;top:0;width:0;height:0;z-index:2147483646';
|
|
26636
|
-
document.body.appendChild(marksHost);
|
|
26637
|
-
return marksHost;
|
|
26638
|
-
}
|
|
26639
|
-
|
|
26640
|
-
function redrawMarks() {
|
|
26641
|
-
if (picked.length === 0) {
|
|
26642
|
-
if (marksHost && marksHost.parentNode) marksHost.parentNode.removeChild(marksHost);
|
|
26643
|
-
marksHost = null;
|
|
26644
|
-
return;
|
|
26645
|
-
}
|
|
26646
|
-
var host = ensureMarksHost();
|
|
26647
|
-
host.innerHTML = '';
|
|
26648
|
-
for (var i = 0; i < picked.length; i++) {
|
|
26649
|
-
var r = picked[i].el.getBoundingClientRect();
|
|
26650
|
-
// Coordenadas de DOCUMENTO: es lo que hace que la marca viaje con el
|
|
26651
|
-
// contenido en vez de quedarse pegada a la pantalla.
|
|
26652
|
-
var top = r.top + (window.scrollY || window.pageYOffset || 0);
|
|
26653
|
-
var left = r.left + (window.scrollX || window.pageXOffset || 0);
|
|
26654
|
-
|
|
26655
|
-
var box = document.createElement('div');
|
|
26656
|
-
box.setAttribute('data-codeam', 'mark');
|
|
26657
|
-
box.style.cssText = [
|
|
26658
|
-
'position:absolute', 'pointer-events:none', 'box-sizing:border-box',
|
|
26659
|
-
'border:1.5px solid #a855f7', 'background:rgba(168,85,247,0.12)',
|
|
26660
|
-
'border-radius:3px',
|
|
26661
|
-
'left:' + left + 'px', 'top:' + top + 'px',
|
|
26662
|
-
'width:' + r.width + 'px', 'height:' + r.height + 'px'
|
|
26663
|
-
].join(';');
|
|
26664
|
-
|
|
26665
|
-
var badge = document.createElement('div');
|
|
26666
|
-
badge.setAttribute('data-codeam', 'mark-badge');
|
|
26667
|
-
badge.style.cssText = [
|
|
26668
|
-
'position:absolute', 'left:-10px', 'top:-10px', 'width:20px', 'height:20px',
|
|
26669
|
-
'border-radius:10px', 'background:#a855f7', 'color:#000',
|
|
26670
|
-
'font:700 11px/20px ui-monospace,SFMono-Regular,Menlo,monospace',
|
|
26671
|
-
'text-align:center', 'pointer-events:none'
|
|
26672
|
-
].join(';');
|
|
26673
|
-
badge.textContent = String(i + 1);
|
|
26674
|
-
|
|
26675
|
-
box.appendChild(badge);
|
|
26676
|
-
host.appendChild(box);
|
|
26677
|
-
}
|
|
26678
|
-
}
|
|
26679
|
-
|
|
26680
|
-
function reposition() { if (picked.length) redrawMarks(); }
|
|
26681
|
-
|
|
26682
|
-
// Captura, y se traga el evento: mientras el modo esta activo un clic
|
|
26683
|
-
// SELECCIONA, no navega. Sin esto, pulsar un enlace se llevaria el
|
|
26684
|
-
// preview a otra pagina en mitad del gesto.
|
|
26685
|
-
function onClick(e) {
|
|
26686
|
-
if (!enabled) return;
|
|
26687
|
-
var el = e.target;
|
|
26688
|
-
if (el && el.getAttribute && el.getAttribute('data-codeam')) return;
|
|
26689
|
-
e.preventDefault();
|
|
26690
|
-
e.stopPropagation();
|
|
26691
|
-
if (!el) return;
|
|
26692
|
-
var id = 'p' + (++seq);
|
|
26693
|
-
picked.push({ id: id, el: el });
|
|
26694
|
-
redrawMarks();
|
|
26695
|
-
var described = describe(el);
|
|
26696
|
-
described.markId = id;
|
|
26697
|
-
send('pick', { element: described });
|
|
26698
|
-
}
|
|
26699
|
-
|
|
26700
|
-
/**
|
|
26701
|
-
* El dashboard manda la lista de ids que SIGUEN vivos, en su orden.
|
|
26702
|
-
*
|
|
26703
|
-
* Es la otra mitad de \xABla marca es un objeto\xBB: si el usuario borra un chip
|
|
26704
|
-
* en el composer, la marca tiene que desaparecer de la pagina \u2014 y las que
|
|
26705
|
-
* quedan renumerarse, porque lo que el usuario escribe (\xAB\u2460 se sale\xBB) mira
|
|
26706
|
-
* a estos numeros.
|
|
26707
|
-
*/
|
|
26708
|
-
function syncMarks(ids) {
|
|
26709
|
-
var byId = {};
|
|
26710
|
-
for (var i = 0; i < picked.length; i++) byId[picked[i].id] = picked[i];
|
|
26711
|
-
var next = [];
|
|
26712
|
-
for (var j = 0; j < ids.length; j++) if (byId[ids[j]]) next.push(byId[ids[j]]);
|
|
26713
|
-
picked = next;
|
|
26714
|
-
redrawMarks();
|
|
26715
|
-
}
|
|
26716
|
-
|
|
26717
|
-
/**
|
|
26718
|
-
* Las marcas del AGENTE \u2014 la herramienta highlight_element.
|
|
26719
|
-
*
|
|
26720
|
-
* Van aparte de las del usuario a proposito: no se numeran, no se pueden
|
|
26721
|
-
* borrar desde el composer y no dependen de que el modo inspector este
|
|
26722
|
-
* encendido. Son el agente SE\xD1ALANDO algo, y el usuario las ve aunque no
|
|
26723
|
-
* haya tocado nada: un cursor que viaja hasta el elemento, lo centra en
|
|
26724
|
-
* pantalla y deja una caja con su etiqueta.
|
|
26725
|
-
*
|
|
26726
|
-
* Mismo anclaje que las marcas fijadas (coordenadas de documento), asi que
|
|
26727
|
-
* acompa\xF1an al scroll. Un selector que no encuentra nada no pinta nada: el
|
|
26728
|
-
* agente ya sabe por la herramienta que puede fallar.
|
|
26729
|
-
*/
|
|
26730
|
-
var AGENT = '#22d3ee';
|
|
26731
|
-
var agentMarks = [];
|
|
26732
|
-
var agentHost = null;
|
|
26733
|
-
var agentCursor = null;
|
|
26734
|
-
var agentStyle = null;
|
|
26735
|
-
var agentListening = false;
|
|
26736
|
-
|
|
26737
|
-
function ensureAgentStyle() {
|
|
26738
|
-
if (agentStyle && agentStyle.parentNode) return;
|
|
26739
|
-
agentStyle = document.createElement('style');
|
|
26740
|
-
agentStyle.setAttribute('data-codeam', 'agent-style');
|
|
26741
|
-
agentStyle.textContent =
|
|
26742
|
-
'@keyframes codeam-agent-pulse{0%{box-shadow:0 0 0 0 rgba(34,211,238,.55)}' +
|
|
26743
|
-
'70%{box-shadow:0 0 0 10px rgba(34,211,238,0)}100%{box-shadow:0 0 0 0 rgba(34,211,238,0)}}' +
|
|
26744
|
-
'@keyframes codeam-agent-in{from{opacity:0;transform:scale(1.06)}to{opacity:1;transform:scale(1)}}';
|
|
26745
|
-
(document.head || document.documentElement).appendChild(agentStyle);
|
|
26746
|
-
}
|
|
26747
|
-
|
|
26748
|
-
function ensureAgentCursor() {
|
|
26749
|
-
if (agentCursor && agentCursor.parentNode) return agentCursor;
|
|
26750
|
-
agentCursor = document.createElement('div');
|
|
26751
|
-
agentCursor.setAttribute('data-codeam', 'agent-cursor');
|
|
26752
|
-
agentCursor.style.cssText = [
|
|
26753
|
-
'position:fixed', 'pointer-events:none', 'z-index:2147483647',
|
|
26754
|
-
'left:' + Math.round(window.innerWidth / 2) + 'px', 'top:' + Math.round(window.innerHeight - 40) + 'px',
|
|
26755
|
-
'transition:left .6s cubic-bezier(.22,1,.36,1),top .6s cubic-bezier(.22,1,.36,1),opacity .3s',
|
|
26756
|
-
'opacity:0'
|
|
26757
|
-
].join(';');
|
|
26758
|
-
agentCursor.innerHTML =
|
|
26759
|
-
'<svg width="22" height="22" viewBox="0 0 24 24" style="display:block;filter:drop-shadow(0 1px 2px rgba(0,0,0,.5))">' +
|
|
26760
|
-
'<path d="M4 2l15 8.5-6.6 1.6L9 18.5z" fill="' + AGENT + '" stroke="#000" stroke-width="1.2"/></svg>' +
|
|
26761
|
-
'<div style="margin:2px 0 0 14px;background:' + AGENT + ';color:#000;font:700 10px/1.5 ui-monospace,SFMono-Regular,Menlo,monospace;' +
|
|
26762
|
-
'padding:1px 6px;border-radius:8px;white-space:nowrap">Agent</div>';
|
|
26763
|
-
document.body.appendChild(agentCursor);
|
|
26764
|
-
return agentCursor;
|
|
26765
|
-
}
|
|
26766
|
-
|
|
26767
|
-
function redrawAgentMarks() {
|
|
26768
|
-
if (agentMarks.length === 0) {
|
|
26769
|
-
if (agentHost && agentHost.parentNode) agentHost.parentNode.removeChild(agentHost);
|
|
26770
|
-
agentHost = null;
|
|
26771
|
-
return;
|
|
26772
|
-
}
|
|
26773
|
-
if (!agentHost || !agentHost.parentNode) {
|
|
26774
|
-
agentHost = document.createElement('div');
|
|
26775
|
-
agentHost.setAttribute('data-codeam', 'agent-marks');
|
|
26776
|
-
agentHost.style.cssText = 'position:absolute;left:0;top:0;width:0;height:0;z-index:2147483646';
|
|
26777
|
-
document.body.appendChild(agentHost);
|
|
26778
|
-
}
|
|
26779
|
-
agentHost.innerHTML = '';
|
|
26780
|
-
var sx = window.scrollX || window.pageXOffset || 0;
|
|
26781
|
-
var sy = window.scrollY || window.pageYOffset || 0;
|
|
26782
|
-
for (var i = 0; i < agentMarks.length; i++) {
|
|
26783
|
-
var m = agentMarks[i];
|
|
26784
|
-
if (!m.el.isConnected) continue;
|
|
26785
|
-
var r = m.el.getBoundingClientRect();
|
|
26786
|
-
var box = document.createElement('div');
|
|
26787
|
-
box.setAttribute('data-codeam', 'agent-mark');
|
|
26788
|
-
box.style.cssText = [
|
|
26789
|
-
'position:absolute', 'pointer-events:none', 'box-sizing:border-box',
|
|
26790
|
-
'border:2px solid ' + AGENT, 'background:rgba(34,211,238,0.10)', 'border-radius:4px',
|
|
26791
|
-
'left:' + (r.left + sx - 3) + 'px', 'top:' + (r.top + sy - 3) + 'px',
|
|
26792
|
-
'width:' + (r.width + 6) + 'px', 'height:' + (r.height + 6) + 'px',
|
|
26793
|
-
'animation:codeam-agent-in .25s ease-out,codeam-agent-pulse 1.6s ease-out 3'
|
|
26794
|
-
].join(';');
|
|
26795
|
-
if (m.label) {
|
|
26796
|
-
var tag = document.createElement('div');
|
|
26797
|
-
tag.setAttribute('data-codeam', 'agent-mark-label');
|
|
26798
|
-
tag.style.cssText = [
|
|
26799
|
-
'position:absolute', 'left:-2px', (r.top >= 22 ? 'top:-22px' : 'bottom:-22px'),
|
|
26800
|
-
'background:' + AGENT, 'color:#000', 'font:700 11px/1.6 ui-monospace,SFMono-Regular,Menlo,monospace',
|
|
26801
|
-
'padding:0 6px', 'border-radius:3px', 'white-space:nowrap', 'max-width:260px',
|
|
26802
|
-
'overflow:hidden', 'text-overflow:ellipsis'
|
|
26803
|
-
].join(';');
|
|
26804
|
-
tag.textContent = m.label;
|
|
26805
|
-
box.appendChild(tag);
|
|
26806
|
-
}
|
|
26807
|
-
agentHost.appendChild(box);
|
|
26808
|
-
}
|
|
26809
|
-
}
|
|
26810
|
-
|
|
26811
|
-
function listenAgentLayout() {
|
|
26812
|
-
if (agentListening) return;
|
|
26813
|
-
agentListening = true;
|
|
26814
|
-
window.addEventListener('scroll', redrawAgentMarks, true);
|
|
26815
|
-
window.addEventListener('resize', redrawAgentMarks);
|
|
26816
|
-
}
|
|
26817
|
-
|
|
26818
|
-
function agentHighlight(selector, labelText) {
|
|
26819
|
-
var el = null;
|
|
26820
|
-
try { el = document.querySelector(String(selector)); } catch (e) { el = null; }
|
|
26821
|
-
if (!el || !el.getBoundingClientRect) return false;
|
|
26822
|
-
ensureAgentStyle();
|
|
26823
|
-
listenAgentLayout();
|
|
26824
|
-
try { el.scrollIntoView({ block: 'center', inline: 'nearest', behavior: 'smooth' }); } catch (e) { /* viejo */ }
|
|
26825
|
-
var cursor = ensureAgentCursor();
|
|
26826
|
-
// Tras el scroll suave: el cursor viaja al centro del elemento y, al
|
|
26827
|
-
// llegar, aparece la caja. El orden es lo que se lee como \xABel agente
|
|
26828
|
-
// lo esta se\xF1alando\xBB y no como un recuadro que salta.
|
|
26829
|
-
setTimeout(function () {
|
|
26830
|
-
var r = el.getBoundingClientRect();
|
|
26831
|
-
cursor.style.opacity = '1';
|
|
26832
|
-
cursor.style.left = Math.round(r.left + Math.min(r.width / 2, 40)) + 'px';
|
|
26833
|
-
cursor.style.top = Math.round(r.top + Math.min(r.height / 2, 24)) + 'px';
|
|
26834
|
-
setTimeout(function () {
|
|
26835
|
-
agentMarks.push({ el: el, label: labelText ? String(labelText).slice(0, 80) : '' });
|
|
26836
|
-
redrawAgentMarks();
|
|
26837
|
-
}, 620);
|
|
26838
|
-
}, 380);
|
|
26839
|
-
return true;
|
|
26840
|
-
}
|
|
26841
|
-
|
|
26842
|
-
function agentClear() {
|
|
26843
|
-
agentMarks = [];
|
|
26844
|
-
redrawAgentMarks();
|
|
26845
|
-
if (agentCursor && agentCursor.parentNode) agentCursor.parentNode.removeChild(agentCursor);
|
|
26846
|
-
agentCursor = null;
|
|
26847
|
-
if (agentStyle && agentStyle.parentNode) agentStyle.parentNode.removeChild(agentStyle);
|
|
26848
|
-
agentStyle = null;
|
|
26849
|
-
if (agentListening) {
|
|
26850
|
-
window.removeEventListener('scroll', redrawAgentMarks, true);
|
|
26851
|
-
window.removeEventListener('resize', redrawAgentMarks);
|
|
26852
|
-
agentListening = false;
|
|
26853
|
-
}
|
|
26854
|
-
}
|
|
26855
|
-
|
|
26856
|
-
function enable(origin) {
|
|
26857
|
-
if (enabled) return;
|
|
26858
|
-
enabled = true;
|
|
26859
|
-
driver = origin;
|
|
26860
|
-
document.addEventListener('mousemove', onMove, true);
|
|
26861
|
-
document.addEventListener('click', onClick, true);
|
|
26862
|
-
// El scroll y el resize mueven los elementos; las marcas los siguen.
|
|
26863
|
-
window.addEventListener('scroll', reposition, true);
|
|
26864
|
-
window.addEventListener('resize', reposition);
|
|
26865
|
-
send('ready', {});
|
|
26866
|
-
}
|
|
26867
|
-
|
|
26868
|
-
function disable() {
|
|
26869
|
-
if (!enabled) return;
|
|
26870
|
-
enabled = false;
|
|
26871
|
-
current = null;
|
|
26872
|
-
document.removeEventListener('mousemove', onMove, true);
|
|
26873
|
-
document.removeEventListener('click', onClick, true);
|
|
26874
|
-
window.removeEventListener('scroll', reposition, true);
|
|
26875
|
-
window.removeEventListener('resize', reposition);
|
|
26876
|
-
removeOverlay();
|
|
26877
|
-
// Las marcas fijadas SI sobreviven a salir del modo: siguen siendo el
|
|
26878
|
-
// contexto del mensaje que el usuario esta escribiendo.
|
|
26879
|
-
driver = null;
|
|
26880
|
-
}
|
|
26881
|
-
|
|
26882
|
-
window.addEventListener('message', function (e) {
|
|
26883
|
-
if (!allowed(e.origin)) return;
|
|
26884
|
-
var data = e.data;
|
|
26885
|
-
if (!data || data.source !== CHANNEL) return;
|
|
26886
|
-
if (data.type === 'enable') enable(e.origin);
|
|
26887
|
-
else if (data.type === 'disable') disable();
|
|
26888
|
-
else if (data.type === 'marks' && data.ids) syncMarks(data.ids);
|
|
26889
|
-
else if (data.type === 'agent-highlight' && data.selector) agentHighlight(data.selector, data.label);
|
|
26890
|
-
else if (data.type === 'agent-clear') agentClear();
|
|
26891
|
-
});
|
|
26892
|
-
|
|
26893
|
-
/**
|
|
26894
|
-
* La puerta para React Native, que no puede usar \`postMessage\`.
|
|
26895
|
-
*
|
|
26896
|
-
* \u26A0\uFE0F Aqui NO hay lista blanca de origenes, y no es un descuido: quien
|
|
26897
|
-
* llama esto es la app anfitriona sobre SU PROPIO WebView, via
|
|
26898
|
-
* \`injectJavaScript\` \u2014 no hay un tercero al que filtrar. La lista blanca
|
|
26899
|
-
* protege el caso del iframe, donde cualquier pagina puede embeber el
|
|
26900
|
-
* preview y mandar mensajes; ese caso sigue exactamente igual de cerrado.
|
|
26901
|
-
*
|
|
26902
|
-
* Solo se expone donde ese puente existe, para no dejar en una pagina
|
|
26903
|
-
* normal una funcion global que encienda el inspector sin permiso.
|
|
26904
|
-
*/
|
|
26905
|
-
if (rnBridge()) {
|
|
26906
|
-
window.__codeamInspector = {
|
|
26907
|
-
enable: function () { enable('react-native'); },
|
|
26908
|
-
disable: disable,
|
|
26909
|
-
// La app movil ya llamaba \`marks\` al borrar un chip y no existia:
|
|
26910
|
-
// la marca se quedaba pintada en la pagina.
|
|
26911
|
-
marks: function (ids) { if (ids && ids.length !== undefined) syncMarks(ids); },
|
|
26912
|
-
highlight: function (selector, text) { return agentHighlight(selector, text); },
|
|
26913
|
-
clear: agentClear,
|
|
26914
|
-
};
|
|
26915
|
-
}
|
|
26916
|
-
} catch (e) {
|
|
26917
|
-
// Pase lo que pase, la app del usuario sigue funcionando.
|
|
26918
|
-
}
|
|
26919
|
-
})();
|
|
27315
|
+
${script}
|
|
26920
27316
|
</script>`;
|
|
26921
27317
|
}
|
|
26922
27318
|
|
|
@@ -50767,9 +51163,9 @@ async function probeCodeamPair(provider, workspace) {
|
|
|
50767
51163
|
}
|
|
50768
51164
|
async function stopWorkspaceFromLocal(target) {
|
|
50769
51165
|
if (target.provider.id === "github-codespaces") {
|
|
50770
|
-
const { execFile:
|
|
51166
|
+
const { execFile: execFile22 } = await import("child_process");
|
|
50771
51167
|
const { promisify: promisify17 } = await import("util");
|
|
50772
|
-
const execFileP10 = promisify17(
|
|
51168
|
+
const execFileP10 = promisify17(execFile22);
|
|
50773
51169
|
await execFileP10("gh", ["codespace", "stop", "-c", target.id], { maxBuffer: 8 * 1024 * 1024 });
|
|
50774
51170
|
return;
|
|
50775
51171
|
}
|
|
@@ -51667,7 +52063,7 @@ async function autoUpgradeBeforeCriticalCommand() {
|
|
|
51667
52063
|
if (process.env.NODE_ENV === "test") return;
|
|
51668
52064
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
51669
52065
|
if (process.env.CI) return;
|
|
51670
|
-
const current2 = true ? "2.76.
|
|
52066
|
+
const current2 = true ? "2.76.37" : null;
|
|
51671
52067
|
if (!current2) return;
|
|
51672
52068
|
const cache = readCache();
|
|
51673
52069
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -51684,7 +52080,7 @@ function checkForUpdates() {
|
|
|
51684
52080
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
51685
52081
|
if (process.env.CI) return;
|
|
51686
52082
|
if (!process.stdout.isTTY) return;
|
|
51687
|
-
const current2 = true ? "2.76.
|
|
52083
|
+
const current2 = true ? "2.76.37" : null;
|
|
51688
52084
|
if (!current2) return;
|
|
51689
52085
|
const cache = readCache();
|
|
51690
52086
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -51990,7 +52386,7 @@ var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
|
|
|
51990
52386
|
var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
|
|
51991
52387
|
var SELF_UPDATE_LS_TIMEOUT_MS = 15e3;
|
|
51992
52388
|
function currentCliVersion() {
|
|
51993
|
-
return true ? "2.76.
|
|
52389
|
+
return true ? "2.76.37" : null;
|
|
51994
52390
|
}
|
|
51995
52391
|
async function installedVersion(deps) {
|
|
51996
52392
|
const ls = await deps.run(
|
|
@@ -52213,7 +52609,7 @@ function signalHostReady(send = process.send?.bind(process)) {
|
|
|
52213
52609
|
}
|
|
52214
52610
|
function defaultDeps() {
|
|
52215
52611
|
return {
|
|
52216
|
-
ownVersion: true ? "2.76.
|
|
52612
|
+
ownVersion: true ? "2.76.37" : null,
|
|
52217
52613
|
root: cliVersionsRoot(),
|
|
52218
52614
|
args: process.argv.slice(3),
|
|
52219
52615
|
execPath: process.execPath,
|
|
@@ -54751,7 +55147,7 @@ function checkChokidar() {
|
|
|
54751
55147
|
}
|
|
54752
55148
|
async function doctor(args2 = []) {
|
|
54753
55149
|
const json = args2.includes("--json");
|
|
54754
|
-
const cliVersion = true ? "2.76.
|
|
55150
|
+
const cliVersion = true ? "2.76.37" : "0.0.0-dev";
|
|
54755
55151
|
const apiBase2 = resolveApiBaseUrl();
|
|
54756
55152
|
const diagnosticId = (0, import_node_crypto17.randomUUID)();
|
|
54757
55153
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -55287,7 +55683,7 @@ async function mcpWarm(argv = [], opts = {}) {
|
|
|
55287
55683
|
// src/commands/version.ts
|
|
55288
55684
|
var import_picocolors15 = __toESM(require("picocolors"));
|
|
55289
55685
|
function version2() {
|
|
55290
|
-
const v = true ? "2.76.
|
|
55686
|
+
const v = true ? "2.76.37" : "unknown";
|
|
55291
55687
|
console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
|
|
55292
55688
|
}
|
|
55293
55689
|
|