codeam-cli 2.76.34 → 2.76.36
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 +15 -0
- package/dist/index.js +801 -486
- package/package.json +1 -1
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.36" : "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.36",
|
|
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.36" ? { ideVersion: "2.76.36" } : {}
|
|
12265
12983
|
};
|
|
12266
12984
|
try {
|
|
12267
12985
|
const res = await _postJson(`${API_BASE2}/api/plugin/heartbeat`, body, this.pollSecretHeader());
|
|
@@ -26033,6 +26751,18 @@ var ONE_M_CREDITS_MESSAGE = "\u{1F504} **Reconnect your Claude subscription to c
|
|
|
26033
26751
|
var TURN_FAILURE_MESSAGE = "\u26A0\uFE0F **The agent hit an error and couldn\u2019t finish this turn.** Please send your message again.";
|
|
26034
26752
|
var IDLE_TURN_FAILURE_MESSAGE = "\u26A0\uFE0F **The agent stopped responding, so this turn was ended.** Your message wasn\u2019t answered \u2014 send it again.";
|
|
26035
26753
|
var IDLE_TURN_RE = /ACP prompt idle/;
|
|
26754
|
+
var AGENT_FREE_LIMIT_RE = /Free usage limit reached/i;
|
|
26755
|
+
function looksLikeAgentFreeLimit(text) {
|
|
26756
|
+
return AGENT_FREE_LIMIT_RE.test(text);
|
|
26757
|
+
}
|
|
26758
|
+
var AGENT_FREE_LIMIT_MESSAGE = [
|
|
26759
|
+
"\u26A0\uFE0F **OpenCode\u2019s free models have hit their usage limit, so this message wasn\u2019t answered.**",
|
|
26760
|
+
"",
|
|
26761
|
+
"Messages will keep failing until the limit resets. To keep going now:",
|
|
26762
|
+
"\u2022 add your own provider key for opencode in **Profile \u203A Agents** (OpenRouter, Anthropic, OpenAI, \u2026),",
|
|
26763
|
+
"\u2022 switch this session to another agent, or",
|
|
26764
|
+
"\u2022 subscribe to OpenCode Go: [opencode.ai/go](https://opencode.ai/go)."
|
|
26765
|
+
].join("\n");
|
|
26036
26766
|
function emptyReplyMessage(agent) {
|
|
26037
26767
|
const label = isKnownAgentId(agent) ? AGENT_REGISTRY[agent].displayName : agent;
|
|
26038
26768
|
const binary = isKnownAgentId(agent) ? AGENT_REGISTRY[agent].binaryName : agent;
|
|
@@ -26096,6 +26826,9 @@ function failureBubble(opts) {
|
|
|
26096
26826
|
return houseAgentLimitMessage(`${opts.detail}
|
|
26097
26827
|
${opts.recentStderr}`);
|
|
26098
26828
|
}
|
|
26829
|
+
if (looksLikeAgentFreeLimit(opts.detail) || looksLikeAgentFreeLimit(opts.recentStderr)) {
|
|
26830
|
+
return AGENT_FREE_LIMIT_MESSAGE;
|
|
26831
|
+
}
|
|
26099
26832
|
if (looksLikeByoProviderBilling(opts.detail, env) || looksLikeByoProviderBilling(opts.recentStderr, env)) {
|
|
26100
26833
|
return byoProviderBillingMessage(byoProviderName({ env, agent: opts.agent }));
|
|
26101
26834
|
}
|
|
@@ -26438,470 +27171,22 @@ async function startInspectorProxy(opts) {
|
|
|
26438
27171
|
|
|
26439
27172
|
// src/services/preview/inspector-client.ts
|
|
26440
27173
|
var INSPECTOR_CHANNEL = "codeam-inspector";
|
|
27174
|
+
var INSPECTOR_MAX_MARKS = 4;
|
|
27175
|
+
var INSPECTOR_ACCENT = "#a855f7";
|
|
26441
27176
|
function inspectorClientSource(opts) {
|
|
26442
|
-
const
|
|
26443
|
-
|
|
27177
|
+
const script = pointPickerScript({
|
|
27178
|
+
channel: INSPECTOR_CHANNEL,
|
|
27179
|
+
channelField: "source",
|
|
27180
|
+
allowedParents: opts.allowedOrigins,
|
|
27181
|
+
mode: "multi",
|
|
27182
|
+
maxMarks: INSPECTOR_MAX_MARKS,
|
|
27183
|
+
accent: INSPECTOR_ACCENT,
|
|
27184
|
+
agentHighlights: true,
|
|
27185
|
+
reactSource: true,
|
|
27186
|
+
globalName: "__codeamInspector"
|
|
27187
|
+
});
|
|
26444
27188
|
return `<script id="codeam-inspector" data-codeam="inspector">
|
|
26445
|
-
|
|
26446
|
-
'use strict';
|
|
26447
|
-
try {
|
|
26448
|
-
var CHANNEL = ${channel};
|
|
26449
|
-
var ALLOWED = ${origins};
|
|
26450
|
-
|
|
26451
|
-
var enabled = false;
|
|
26452
|
-
var driver = null; // el origen que nos encendio
|
|
26453
|
-
var overlay = null;
|
|
26454
|
-
var label = null;
|
|
26455
|
-
var current = null;
|
|
26456
|
-
|
|
26457
|
-
function allowed(origin) {
|
|
26458
|
-
return ALLOWED.indexOf(origin) !== -1;
|
|
26459
|
-
}
|
|
26460
|
-
|
|
26461
|
-
// \xBFEstamos dentro del WebView de la app movil?
|
|
26462
|
-
//
|
|
26463
|
-
// \u26A0\uFE0F En un WebView el documento es de NIVEL SUPERIOR, asi que
|
|
26464
|
-
// \`window.parent === window\` y la via del iframe no existe: el script
|
|
26465
|
-
// hablaba solo, y en movil el inspector no devolvia nada. React Native
|
|
26466
|
-
// expone su propio canal, que es el unico que sale de ahi.
|
|
26467
|
-
function rnBridge() {
|
|
26468
|
-
return typeof window.ReactNativeWebView !== 'undefined' &&
|
|
26469
|
-
window.ReactNativeWebView &&
|
|
26470
|
-
typeof window.ReactNativeWebView.postMessage === 'function'
|
|
26471
|
-
? window.ReactNativeWebView
|
|
26472
|
-
: null;
|
|
26473
|
-
}
|
|
26474
|
-
|
|
26475
|
-
function send(type, payload) {
|
|
26476
|
-
if (!driver) return;
|
|
26477
|
-
var msg = { source: CHANNEL, type: type };
|
|
26478
|
-
for (var k in payload) if (Object.prototype.hasOwnProperty.call(payload, k)) msg[k] = payload[k];
|
|
26479
|
-
|
|
26480
|
-
var rn = rnBridge();
|
|
26481
|
-
if (rn) {
|
|
26482
|
-
// El canal de RN transporta CADENAS, no objetos: pasarle el objeto
|
|
26483
|
-
// llega al otro lado como "[object Object]".
|
|
26484
|
-
rn.postMessage(JSON.stringify(msg));
|
|
26485
|
-
return;
|
|
26486
|
-
}
|
|
26487
|
-
if (window.parent === window) return;
|
|
26488
|
-
window.parent.postMessage(msg, driver);
|
|
26489
|
-
}
|
|
26490
|
-
|
|
26491
|
-
// El resaltado. Un div fijo por encima de todo que NUNCA captura el
|
|
26492
|
-
// puntero: si lo capturara, el elemento de debajo dejaria de recibir el
|
|
26493
|
-
// mousemove y el resaltado se quedaria pegado al primero que tocara.
|
|
26494
|
-
function ensureOverlay() {
|
|
26495
|
-
if (overlay) return;
|
|
26496
|
-
overlay = document.createElement('div');
|
|
26497
|
-
overlay.setAttribute('data-codeam', 'inspector-overlay');
|
|
26498
|
-
overlay.style.cssText = [
|
|
26499
|
-
'position:fixed', 'pointer-events:none', 'z-index:2147483647',
|
|
26500
|
-
'border:1px solid #a855f7', 'background:rgba(168,85,247,0.14)',
|
|
26501
|
-
'border-radius:2px', 'transition:none', 'display:none'
|
|
26502
|
-
].join(';');
|
|
26503
|
-
label = document.createElement('div');
|
|
26504
|
-
label.setAttribute('data-codeam', 'inspector-label');
|
|
26505
|
-
label.style.cssText = [
|
|
26506
|
-
'position:fixed', 'pointer-events:none', 'z-index:2147483647',
|
|
26507
|
-
'background:#a855f7', 'color:#000', 'font:600 11px/1.4 ui-monospace,SFMono-Regular,Menlo,monospace',
|
|
26508
|
-
'padding:2px 6px', 'border-radius:3px', 'white-space:nowrap', 'display:none'
|
|
26509
|
-
].join(';');
|
|
26510
|
-
document.body.appendChild(overlay);
|
|
26511
|
-
document.body.appendChild(label);
|
|
26512
|
-
}
|
|
26513
|
-
|
|
26514
|
-
function removeOverlay() {
|
|
26515
|
-
if (overlay && overlay.parentNode) overlay.parentNode.removeChild(overlay);
|
|
26516
|
-
if (label && label.parentNode) label.parentNode.removeChild(label);
|
|
26517
|
-
overlay = null;
|
|
26518
|
-
label = null;
|
|
26519
|
-
}
|
|
26520
|
-
|
|
26521
|
-
// Fichero y linea del componente de React, cuando el dev server los
|
|
26522
|
-
// expone. Es lo que hace que el agente reciba
|
|
26523
|
-
// "components/whatsapp-button.tsx:42" en vez de "x:0.62 y:0.81".
|
|
26524
|
-
// Solo existe en builds de desarrollo; en produccion devuelve null y se
|
|
26525
|
-
// cae al selector CSS.
|
|
26526
|
-
function reactSource(el) {
|
|
26527
|
-
try {
|
|
26528
|
-
for (var key in el) {
|
|
26529
|
-
if (key.indexOf('__reactFiber$') !== 0) continue;
|
|
26530
|
-
var fiber = el[key];
|
|
26531
|
-
while (fiber) {
|
|
26532
|
-
var src = fiber._debugSource;
|
|
26533
|
-
if (src && src.fileName) {
|
|
26534
|
-
return { file: String(src.fileName), line: Number(src.lineNumber) || null };
|
|
26535
|
-
}
|
|
26536
|
-
fiber = fiber.return;
|
|
26537
|
-
}
|
|
26538
|
-
}
|
|
26539
|
-
} catch (e) { /* nunca romper la pagina por esto */ }
|
|
26540
|
-
return null;
|
|
26541
|
-
}
|
|
26542
|
-
|
|
26543
|
-
// Un selector corto y legible, el respaldo cuando no hay React.
|
|
26544
|
-
function selectorFor(el) {
|
|
26545
|
-
if (el.id) return '#' + el.id;
|
|
26546
|
-
var name = el.tagName ? el.tagName.toLowerCase() : 'node';
|
|
26547
|
-
var cls = (el.className && typeof el.className === 'string')
|
|
26548
|
-
? el.className.trim().split(/\\s+/).slice(0, 3).join('.')
|
|
26549
|
-
: '';
|
|
26550
|
-
return cls ? name + '.' + cls : name;
|
|
26551
|
-
}
|
|
26552
|
-
|
|
26553
|
-
function describe(el) {
|
|
26554
|
-
var r = el.getBoundingClientRect();
|
|
26555
|
-
var text = (el.textContent || '').replace(/\\s+/g, ' ').trim();
|
|
26556
|
-
return {
|
|
26557
|
-
tag: el.tagName ? el.tagName.toLowerCase() : 'node',
|
|
26558
|
-
id: el.id || null,
|
|
26559
|
-
classes: (el.className && typeof el.className === 'string') ? el.className.trim() : '',
|
|
26560
|
-
selector: selectorFor(el),
|
|
26561
|
-
// Un recorte, no el contenido: describir no es extraer.
|
|
26562
|
-
text: text.length > 120 ? text.slice(0, 120) + '\u2026' : text,
|
|
26563
|
-
rect: { x: r.left, y: r.top, w: r.width, h: r.height },
|
|
26564
|
-
viewport: { w: window.innerWidth, h: window.innerHeight },
|
|
26565
|
-
source: reactSource(el)
|
|
26566
|
-
};
|
|
26567
|
-
}
|
|
26568
|
-
|
|
26569
|
-
function paint(el) {
|
|
26570
|
-
ensureOverlay();
|
|
26571
|
-
var r = el.getBoundingClientRect();
|
|
26572
|
-
overlay.style.display = 'block';
|
|
26573
|
-
overlay.style.left = r.left + 'px';
|
|
26574
|
-
overlay.style.top = r.top + 'px';
|
|
26575
|
-
overlay.style.width = r.width + 'px';
|
|
26576
|
-
overlay.style.height = r.height + 'px';
|
|
26577
|
-
label.style.display = 'block';
|
|
26578
|
-
label.textContent = selectorFor(el) + ' ' + Math.round(r.width) + '\xD7' + Math.round(r.height);
|
|
26579
|
-
// Encima si cabe; si no, dentro. Una etiqueta cortada por el borde
|
|
26580
|
-
// superior no se lee.
|
|
26581
|
-
var above = r.top >= 20;
|
|
26582
|
-
label.style.left = r.left + 'px';
|
|
26583
|
-
label.style.top = (above ? r.top - 20 : r.top + 2) + 'px';
|
|
26584
|
-
}
|
|
26585
|
-
|
|
26586
|
-
function onMove(e) {
|
|
26587
|
-
if (!enabled) return;
|
|
26588
|
-
var el = e.target;
|
|
26589
|
-
if (!el || el === current || !el.getBoundingClientRect) return;
|
|
26590
|
-
if (el.getAttribute && el.getAttribute('data-codeam')) return;
|
|
26591
|
-
current = el;
|
|
26592
|
-
paint(el);
|
|
26593
|
-
send('hover', { element: describe(el) });
|
|
26594
|
-
}
|
|
26595
|
-
|
|
26596
|
-
// Captura, y se traga el evento: mientras el modo esta activo un clic
|
|
26597
|
-
// SELECCIONA, no navega. Sin esto, pulsar un enlace se llevaria el
|
|
26598
|
-
// preview a otra pagina en mitad del gesto.
|
|
26599
|
-
/**
|
|
26600
|
-
* Las marcas FIJADAS, dibujadas DENTRO de la pagina.
|
|
26601
|
-
*
|
|
26602
|
-
* \u26A0\uFE0F Antes las pintaba el dashboard, en una capa sobre el iframe. Como esa
|
|
26603
|
-
* capa vive fuera del documento, sus coordenadas son del VIEWPORT: al
|
|
26604
|
-
* hacer scroll dentro del preview las marcas se quedaban clavadas en la
|
|
26605
|
-
* pantalla mientras el elemento se iba (reportado el 2026-08-29).
|
|
26606
|
-
*
|
|
26607
|
-
* Aqui se anclan al DOCUMENTO (position:absolute mas el scroll sumado), asi
|
|
26608
|
-
* que acompa\xF1an al contenido igual que cualquier otro nodo de la pagina \u2014 y
|
|
26609
|
-
* ademas se recolocan si el layout cambia, que una capa externa no puede
|
|
26610
|
-
* saber.
|
|
26611
|
-
*/
|
|
26612
|
-
var picked = [];
|
|
26613
|
-
var seq = 0;
|
|
26614
|
-
var marksHost = null;
|
|
26615
|
-
|
|
26616
|
-
function ensureMarksHost() {
|
|
26617
|
-
if (marksHost && marksHost.parentNode) return marksHost;
|
|
26618
|
-
marksHost = document.createElement('div');
|
|
26619
|
-
marksHost.setAttribute('data-codeam', 'marks');
|
|
26620
|
-
marksHost.style.cssText = 'position:absolute;left:0;top:0;width:0;height:0;z-index:2147483646';
|
|
26621
|
-
document.body.appendChild(marksHost);
|
|
26622
|
-
return marksHost;
|
|
26623
|
-
}
|
|
26624
|
-
|
|
26625
|
-
function redrawMarks() {
|
|
26626
|
-
if (picked.length === 0) {
|
|
26627
|
-
if (marksHost && marksHost.parentNode) marksHost.parentNode.removeChild(marksHost);
|
|
26628
|
-
marksHost = null;
|
|
26629
|
-
return;
|
|
26630
|
-
}
|
|
26631
|
-
var host = ensureMarksHost();
|
|
26632
|
-
host.innerHTML = '';
|
|
26633
|
-
for (var i = 0; i < picked.length; i++) {
|
|
26634
|
-
var r = picked[i].el.getBoundingClientRect();
|
|
26635
|
-
// Coordenadas de DOCUMENTO: es lo que hace que la marca viaje con el
|
|
26636
|
-
// contenido en vez de quedarse pegada a la pantalla.
|
|
26637
|
-
var top = r.top + (window.scrollY || window.pageYOffset || 0);
|
|
26638
|
-
var left = r.left + (window.scrollX || window.pageXOffset || 0);
|
|
26639
|
-
|
|
26640
|
-
var box = document.createElement('div');
|
|
26641
|
-
box.setAttribute('data-codeam', 'mark');
|
|
26642
|
-
box.style.cssText = [
|
|
26643
|
-
'position:absolute', 'pointer-events:none', 'box-sizing:border-box',
|
|
26644
|
-
'border:1.5px solid #a855f7', 'background:rgba(168,85,247,0.12)',
|
|
26645
|
-
'border-radius:3px',
|
|
26646
|
-
'left:' + left + 'px', 'top:' + top + 'px',
|
|
26647
|
-
'width:' + r.width + 'px', 'height:' + r.height + 'px'
|
|
26648
|
-
].join(';');
|
|
26649
|
-
|
|
26650
|
-
var badge = document.createElement('div');
|
|
26651
|
-
badge.setAttribute('data-codeam', 'mark-badge');
|
|
26652
|
-
badge.style.cssText = [
|
|
26653
|
-
'position:absolute', 'left:-10px', 'top:-10px', 'width:20px', 'height:20px',
|
|
26654
|
-
'border-radius:10px', 'background:#a855f7', 'color:#000',
|
|
26655
|
-
'font:700 11px/20px ui-monospace,SFMono-Regular,Menlo,monospace',
|
|
26656
|
-
'text-align:center', 'pointer-events:none'
|
|
26657
|
-
].join(';');
|
|
26658
|
-
badge.textContent = String(i + 1);
|
|
26659
|
-
|
|
26660
|
-
box.appendChild(badge);
|
|
26661
|
-
host.appendChild(box);
|
|
26662
|
-
}
|
|
26663
|
-
}
|
|
26664
|
-
|
|
26665
|
-
function reposition() { if (picked.length) redrawMarks(); }
|
|
26666
|
-
|
|
26667
|
-
// Captura, y se traga el evento: mientras el modo esta activo un clic
|
|
26668
|
-
// SELECCIONA, no navega. Sin esto, pulsar un enlace se llevaria el
|
|
26669
|
-
// preview a otra pagina en mitad del gesto.
|
|
26670
|
-
function onClick(e) {
|
|
26671
|
-
if (!enabled) return;
|
|
26672
|
-
var el = e.target;
|
|
26673
|
-
if (el && el.getAttribute && el.getAttribute('data-codeam')) return;
|
|
26674
|
-
e.preventDefault();
|
|
26675
|
-
e.stopPropagation();
|
|
26676
|
-
if (!el) return;
|
|
26677
|
-
var id = 'p' + (++seq);
|
|
26678
|
-
picked.push({ id: id, el: el });
|
|
26679
|
-
redrawMarks();
|
|
26680
|
-
var described = describe(el);
|
|
26681
|
-
described.markId = id;
|
|
26682
|
-
send('pick', { element: described });
|
|
26683
|
-
}
|
|
26684
|
-
|
|
26685
|
-
/**
|
|
26686
|
-
* El dashboard manda la lista de ids que SIGUEN vivos, en su orden.
|
|
26687
|
-
*
|
|
26688
|
-
* Es la otra mitad de \xABla marca es un objeto\xBB: si el usuario borra un chip
|
|
26689
|
-
* en el composer, la marca tiene que desaparecer de la pagina \u2014 y las que
|
|
26690
|
-
* quedan renumerarse, porque lo que el usuario escribe (\xAB\u2460 se sale\xBB) mira
|
|
26691
|
-
* a estos numeros.
|
|
26692
|
-
*/
|
|
26693
|
-
function syncMarks(ids) {
|
|
26694
|
-
var byId = {};
|
|
26695
|
-
for (var i = 0; i < picked.length; i++) byId[picked[i].id] = picked[i];
|
|
26696
|
-
var next = [];
|
|
26697
|
-
for (var j = 0; j < ids.length; j++) if (byId[ids[j]]) next.push(byId[ids[j]]);
|
|
26698
|
-
picked = next;
|
|
26699
|
-
redrawMarks();
|
|
26700
|
-
}
|
|
26701
|
-
|
|
26702
|
-
/**
|
|
26703
|
-
* Las marcas del AGENTE \u2014 la herramienta highlight_element.
|
|
26704
|
-
*
|
|
26705
|
-
* Van aparte de las del usuario a proposito: no se numeran, no se pueden
|
|
26706
|
-
* borrar desde el composer y no dependen de que el modo inspector este
|
|
26707
|
-
* encendido. Son el agente SE\xD1ALANDO algo, y el usuario las ve aunque no
|
|
26708
|
-
* haya tocado nada: un cursor que viaja hasta el elemento, lo centra en
|
|
26709
|
-
* pantalla y deja una caja con su etiqueta.
|
|
26710
|
-
*
|
|
26711
|
-
* Mismo anclaje que las marcas fijadas (coordenadas de documento), asi que
|
|
26712
|
-
* acompa\xF1an al scroll. Un selector que no encuentra nada no pinta nada: el
|
|
26713
|
-
* agente ya sabe por la herramienta que puede fallar.
|
|
26714
|
-
*/
|
|
26715
|
-
var AGENT = '#22d3ee';
|
|
26716
|
-
var agentMarks = [];
|
|
26717
|
-
var agentHost = null;
|
|
26718
|
-
var agentCursor = null;
|
|
26719
|
-
var agentStyle = null;
|
|
26720
|
-
var agentListening = false;
|
|
26721
|
-
|
|
26722
|
-
function ensureAgentStyle() {
|
|
26723
|
-
if (agentStyle && agentStyle.parentNode) return;
|
|
26724
|
-
agentStyle = document.createElement('style');
|
|
26725
|
-
agentStyle.setAttribute('data-codeam', 'agent-style');
|
|
26726
|
-
agentStyle.textContent =
|
|
26727
|
-
'@keyframes codeam-agent-pulse{0%{box-shadow:0 0 0 0 rgba(34,211,238,.55)}' +
|
|
26728
|
-
'70%{box-shadow:0 0 0 10px rgba(34,211,238,0)}100%{box-shadow:0 0 0 0 rgba(34,211,238,0)}}' +
|
|
26729
|
-
'@keyframes codeam-agent-in{from{opacity:0;transform:scale(1.06)}to{opacity:1;transform:scale(1)}}';
|
|
26730
|
-
(document.head || document.documentElement).appendChild(agentStyle);
|
|
26731
|
-
}
|
|
26732
|
-
|
|
26733
|
-
function ensureAgentCursor() {
|
|
26734
|
-
if (agentCursor && agentCursor.parentNode) return agentCursor;
|
|
26735
|
-
agentCursor = document.createElement('div');
|
|
26736
|
-
agentCursor.setAttribute('data-codeam', 'agent-cursor');
|
|
26737
|
-
agentCursor.style.cssText = [
|
|
26738
|
-
'position:fixed', 'pointer-events:none', 'z-index:2147483647',
|
|
26739
|
-
'left:' + Math.round(window.innerWidth / 2) + 'px', 'top:' + Math.round(window.innerHeight - 40) + 'px',
|
|
26740
|
-
'transition:left .6s cubic-bezier(.22,1,.36,1),top .6s cubic-bezier(.22,1,.36,1),opacity .3s',
|
|
26741
|
-
'opacity:0'
|
|
26742
|
-
].join(';');
|
|
26743
|
-
agentCursor.innerHTML =
|
|
26744
|
-
'<svg width="22" height="22" viewBox="0 0 24 24" style="display:block;filter:drop-shadow(0 1px 2px rgba(0,0,0,.5))">' +
|
|
26745
|
-
'<path d="M4 2l15 8.5-6.6 1.6L9 18.5z" fill="' + AGENT + '" stroke="#000" stroke-width="1.2"/></svg>' +
|
|
26746
|
-
'<div style="margin:2px 0 0 14px;background:' + AGENT + ';color:#000;font:700 10px/1.5 ui-monospace,SFMono-Regular,Menlo,monospace;' +
|
|
26747
|
-
'padding:1px 6px;border-radius:8px;white-space:nowrap">Agent</div>';
|
|
26748
|
-
document.body.appendChild(agentCursor);
|
|
26749
|
-
return agentCursor;
|
|
26750
|
-
}
|
|
26751
|
-
|
|
26752
|
-
function redrawAgentMarks() {
|
|
26753
|
-
if (agentMarks.length === 0) {
|
|
26754
|
-
if (agentHost && agentHost.parentNode) agentHost.parentNode.removeChild(agentHost);
|
|
26755
|
-
agentHost = null;
|
|
26756
|
-
return;
|
|
26757
|
-
}
|
|
26758
|
-
if (!agentHost || !agentHost.parentNode) {
|
|
26759
|
-
agentHost = document.createElement('div');
|
|
26760
|
-
agentHost.setAttribute('data-codeam', 'agent-marks');
|
|
26761
|
-
agentHost.style.cssText = 'position:absolute;left:0;top:0;width:0;height:0;z-index:2147483646';
|
|
26762
|
-
document.body.appendChild(agentHost);
|
|
26763
|
-
}
|
|
26764
|
-
agentHost.innerHTML = '';
|
|
26765
|
-
var sx = window.scrollX || window.pageXOffset || 0;
|
|
26766
|
-
var sy = window.scrollY || window.pageYOffset || 0;
|
|
26767
|
-
for (var i = 0; i < agentMarks.length; i++) {
|
|
26768
|
-
var m = agentMarks[i];
|
|
26769
|
-
if (!m.el.isConnected) continue;
|
|
26770
|
-
var r = m.el.getBoundingClientRect();
|
|
26771
|
-
var box = document.createElement('div');
|
|
26772
|
-
box.setAttribute('data-codeam', 'agent-mark');
|
|
26773
|
-
box.style.cssText = [
|
|
26774
|
-
'position:absolute', 'pointer-events:none', 'box-sizing:border-box',
|
|
26775
|
-
'border:2px solid ' + AGENT, 'background:rgba(34,211,238,0.10)', 'border-radius:4px',
|
|
26776
|
-
'left:' + (r.left + sx - 3) + 'px', 'top:' + (r.top + sy - 3) + 'px',
|
|
26777
|
-
'width:' + (r.width + 6) + 'px', 'height:' + (r.height + 6) + 'px',
|
|
26778
|
-
'animation:codeam-agent-in .25s ease-out,codeam-agent-pulse 1.6s ease-out 3'
|
|
26779
|
-
].join(';');
|
|
26780
|
-
if (m.label) {
|
|
26781
|
-
var tag = document.createElement('div');
|
|
26782
|
-
tag.setAttribute('data-codeam', 'agent-mark-label');
|
|
26783
|
-
tag.style.cssText = [
|
|
26784
|
-
'position:absolute', 'left:-2px', (r.top >= 22 ? 'top:-22px' : 'bottom:-22px'),
|
|
26785
|
-
'background:' + AGENT, 'color:#000', 'font:700 11px/1.6 ui-monospace,SFMono-Regular,Menlo,monospace',
|
|
26786
|
-
'padding:0 6px', 'border-radius:3px', 'white-space:nowrap', 'max-width:260px',
|
|
26787
|
-
'overflow:hidden', 'text-overflow:ellipsis'
|
|
26788
|
-
].join(';');
|
|
26789
|
-
tag.textContent = m.label;
|
|
26790
|
-
box.appendChild(tag);
|
|
26791
|
-
}
|
|
26792
|
-
agentHost.appendChild(box);
|
|
26793
|
-
}
|
|
26794
|
-
}
|
|
26795
|
-
|
|
26796
|
-
function listenAgentLayout() {
|
|
26797
|
-
if (agentListening) return;
|
|
26798
|
-
agentListening = true;
|
|
26799
|
-
window.addEventListener('scroll', redrawAgentMarks, true);
|
|
26800
|
-
window.addEventListener('resize', redrawAgentMarks);
|
|
26801
|
-
}
|
|
26802
|
-
|
|
26803
|
-
function agentHighlight(selector, labelText) {
|
|
26804
|
-
var el = null;
|
|
26805
|
-
try { el = document.querySelector(String(selector)); } catch (e) { el = null; }
|
|
26806
|
-
if (!el || !el.getBoundingClientRect) return false;
|
|
26807
|
-
ensureAgentStyle();
|
|
26808
|
-
listenAgentLayout();
|
|
26809
|
-
try { el.scrollIntoView({ block: 'center', inline: 'nearest', behavior: 'smooth' }); } catch (e) { /* viejo */ }
|
|
26810
|
-
var cursor = ensureAgentCursor();
|
|
26811
|
-
// Tras el scroll suave: el cursor viaja al centro del elemento y, al
|
|
26812
|
-
// llegar, aparece la caja. El orden es lo que se lee como \xABel agente
|
|
26813
|
-
// lo esta se\xF1alando\xBB y no como un recuadro que salta.
|
|
26814
|
-
setTimeout(function () {
|
|
26815
|
-
var r = el.getBoundingClientRect();
|
|
26816
|
-
cursor.style.opacity = '1';
|
|
26817
|
-
cursor.style.left = Math.round(r.left + Math.min(r.width / 2, 40)) + 'px';
|
|
26818
|
-
cursor.style.top = Math.round(r.top + Math.min(r.height / 2, 24)) + 'px';
|
|
26819
|
-
setTimeout(function () {
|
|
26820
|
-
agentMarks.push({ el: el, label: labelText ? String(labelText).slice(0, 80) : '' });
|
|
26821
|
-
redrawAgentMarks();
|
|
26822
|
-
}, 620);
|
|
26823
|
-
}, 380);
|
|
26824
|
-
return true;
|
|
26825
|
-
}
|
|
26826
|
-
|
|
26827
|
-
function agentClear() {
|
|
26828
|
-
agentMarks = [];
|
|
26829
|
-
redrawAgentMarks();
|
|
26830
|
-
if (agentCursor && agentCursor.parentNode) agentCursor.parentNode.removeChild(agentCursor);
|
|
26831
|
-
agentCursor = null;
|
|
26832
|
-
if (agentStyle && agentStyle.parentNode) agentStyle.parentNode.removeChild(agentStyle);
|
|
26833
|
-
agentStyle = null;
|
|
26834
|
-
if (agentListening) {
|
|
26835
|
-
window.removeEventListener('scroll', redrawAgentMarks, true);
|
|
26836
|
-
window.removeEventListener('resize', redrawAgentMarks);
|
|
26837
|
-
agentListening = false;
|
|
26838
|
-
}
|
|
26839
|
-
}
|
|
26840
|
-
|
|
26841
|
-
function enable(origin) {
|
|
26842
|
-
if (enabled) return;
|
|
26843
|
-
enabled = true;
|
|
26844
|
-
driver = origin;
|
|
26845
|
-
document.addEventListener('mousemove', onMove, true);
|
|
26846
|
-
document.addEventListener('click', onClick, true);
|
|
26847
|
-
// El scroll y el resize mueven los elementos; las marcas los siguen.
|
|
26848
|
-
window.addEventListener('scroll', reposition, true);
|
|
26849
|
-
window.addEventListener('resize', reposition);
|
|
26850
|
-
send('ready', {});
|
|
26851
|
-
}
|
|
26852
|
-
|
|
26853
|
-
function disable() {
|
|
26854
|
-
if (!enabled) return;
|
|
26855
|
-
enabled = false;
|
|
26856
|
-
current = null;
|
|
26857
|
-
document.removeEventListener('mousemove', onMove, true);
|
|
26858
|
-
document.removeEventListener('click', onClick, true);
|
|
26859
|
-
window.removeEventListener('scroll', reposition, true);
|
|
26860
|
-
window.removeEventListener('resize', reposition);
|
|
26861
|
-
removeOverlay();
|
|
26862
|
-
// Las marcas fijadas SI sobreviven a salir del modo: siguen siendo el
|
|
26863
|
-
// contexto del mensaje que el usuario esta escribiendo.
|
|
26864
|
-
driver = null;
|
|
26865
|
-
}
|
|
26866
|
-
|
|
26867
|
-
window.addEventListener('message', function (e) {
|
|
26868
|
-
if (!allowed(e.origin)) return;
|
|
26869
|
-
var data = e.data;
|
|
26870
|
-
if (!data || data.source !== CHANNEL) return;
|
|
26871
|
-
if (data.type === 'enable') enable(e.origin);
|
|
26872
|
-
else if (data.type === 'disable') disable();
|
|
26873
|
-
else if (data.type === 'marks' && data.ids) syncMarks(data.ids);
|
|
26874
|
-
else if (data.type === 'agent-highlight' && data.selector) agentHighlight(data.selector, data.label);
|
|
26875
|
-
else if (data.type === 'agent-clear') agentClear();
|
|
26876
|
-
});
|
|
26877
|
-
|
|
26878
|
-
/**
|
|
26879
|
-
* La puerta para React Native, que no puede usar \`postMessage\`.
|
|
26880
|
-
*
|
|
26881
|
-
* \u26A0\uFE0F Aqui NO hay lista blanca de origenes, y no es un descuido: quien
|
|
26882
|
-
* llama esto es la app anfitriona sobre SU PROPIO WebView, via
|
|
26883
|
-
* \`injectJavaScript\` \u2014 no hay un tercero al que filtrar. La lista blanca
|
|
26884
|
-
* protege el caso del iframe, donde cualquier pagina puede embeber el
|
|
26885
|
-
* preview y mandar mensajes; ese caso sigue exactamente igual de cerrado.
|
|
26886
|
-
*
|
|
26887
|
-
* Solo se expone donde ese puente existe, para no dejar en una pagina
|
|
26888
|
-
* normal una funcion global que encienda el inspector sin permiso.
|
|
26889
|
-
*/
|
|
26890
|
-
if (rnBridge()) {
|
|
26891
|
-
window.__codeamInspector = {
|
|
26892
|
-
enable: function () { enable('react-native'); },
|
|
26893
|
-
disable: disable,
|
|
26894
|
-
// La app movil ya llamaba \`marks\` al borrar un chip y no existia:
|
|
26895
|
-
// la marca se quedaba pintada en la pagina.
|
|
26896
|
-
marks: function (ids) { if (ids && ids.length !== undefined) syncMarks(ids); },
|
|
26897
|
-
highlight: function (selector, text) { return agentHighlight(selector, text); },
|
|
26898
|
-
clear: agentClear,
|
|
26899
|
-
};
|
|
26900
|
-
}
|
|
26901
|
-
} catch (e) {
|
|
26902
|
-
// Pase lo que pase, la app del usuario sigue funcionando.
|
|
26903
|
-
}
|
|
26904
|
-
})();
|
|
27189
|
+
${script}
|
|
26905
27190
|
</script>`;
|
|
26906
27191
|
}
|
|
26907
27192
|
|
|
@@ -31845,6 +32130,7 @@ function isLocalSession(env = process.env) {
|
|
|
31845
32130
|
|
|
31846
32131
|
// src/agents/acp/adapters.ts
|
|
31847
32132
|
var require_ = require;
|
|
32133
|
+
var OPENCODE_FATAL_TURN_STDERR_RE = /message="stream error".*error\.error="[^"]*(Free usage limit reached|insufficient[_ ]quota|invalid[_ ]api[_ ]key|incorrect api key|unauthorized)/i;
|
|
31848
32134
|
function claudeBinaryWaiter(opts = {}) {
|
|
31849
32135
|
return waitForClaudeNativeBinary(opts).then((p2) => p2 !== null);
|
|
31850
32136
|
}
|
|
@@ -32004,8 +32290,12 @@ var REGISTRY = {
|
|
|
32004
32290
|
// the ACP client spawns the adapter with `env: { ...process.env, ...extraEnv }`.
|
|
32005
32291
|
opencode: () => ({
|
|
32006
32292
|
command: "opencode",
|
|
32007
|
-
|
|
32293
|
+
// `--print-logs --log-level ERROR`: opencode writes its provider errors only
|
|
32294
|
+
// to its own log file, so without these flags they never reach the adapter
|
|
32295
|
+
// stderr we read (see OPENCODE_FATAL_TURN_STDERR_RE).
|
|
32296
|
+
args: ["acp", "--print-logs", "--log-level", "ERROR"],
|
|
32008
32297
|
requiresAgentBinary: "opencode",
|
|
32298
|
+
fatalTurnStderr: OPENCODE_FATAL_TURN_STDERR_RE,
|
|
32009
32299
|
waitForBinary: async (o) => {
|
|
32010
32300
|
if (isLocalSession()) await ensureOpencodeInstalled();
|
|
32011
32301
|
augmentOpencodePath();
|
|
@@ -37132,6 +37422,9 @@ var _acpStartSeam = {
|
|
|
37132
37422
|
var PROTOCOL_VERSION3 = 1;
|
|
37133
37423
|
var FATAL_STARTUP_RE = /IneligibleTierError|UNSUPPORTED_CLIENT|no longer supported for Gemini Code Assist|not eligible for Gemini Code Assist|Error authenticating|ProjectIdRequiredError/i;
|
|
37134
37424
|
var NEWSESSION_TIMEOUT_MS = 12e4;
|
|
37425
|
+
function agentErrorOf(line) {
|
|
37426
|
+
return /error\.error="([^"]+)"/.exec(line)?.[1] ?? line;
|
|
37427
|
+
}
|
|
37135
37428
|
var MCP_STARTUP_TIMEOUT_MS = NEWSESSION_TIMEOUT_MS - 3e4;
|
|
37136
37429
|
var AGENT_ENV_WITHHELD = ["PREVIEW_TUNNEL_TOKEN", "PREVIEW_TUNNEL_HOSTNAME"];
|
|
37137
37430
|
var LOADSESSION_TIMEOUT_MS = 6e4;
|
|
@@ -37237,6 +37530,12 @@ var AcpClient = class {
|
|
|
37237
37530
|
* engages; with it, the crash rejects immediately → retry respawns once the
|
|
37238
37531
|
* install settles. Broader than {@link startupFailureReject} (newSession-only). */
|
|
37239
37532
|
startAbortReject = null;
|
|
37533
|
+
/** The adapter's {@link AdapterSpec.fatalTurnStderr}, set at spawn. */
|
|
37534
|
+
fatalTurnStderr = null;
|
|
37535
|
+
/** Set while a `session/prompt` is in flight; the stderr watcher calls it on
|
|
37536
|
+
* a {@link fatalTurnStderr} line to end the turn now (opencode keeps a turn
|
|
37537
|
+
* open forever after a terminal provider error — see the adapter spec). */
|
|
37538
|
+
turnFailureReject = null;
|
|
37240
37539
|
/**
|
|
37241
37540
|
* Spawn the adapter + handshake, retrying a TRANSIENT in-adapter spawn race.
|
|
37242
37541
|
*
|
|
@@ -37325,6 +37624,7 @@ var AcpClient = class {
|
|
|
37325
37624
|
"acpClient",
|
|
37326
37625
|
`provider routing ${formatProviderRouting(describeProviderRouting(childEnv, { cwd }), adapter.command)}`
|
|
37327
37626
|
);
|
|
37627
|
+
this.fatalTurnStderr = adapter.fatalTurnStderr ?? null;
|
|
37328
37628
|
const child = (0, import_node_child_process28.spawn)(adapter.command, adapter.args, {
|
|
37329
37629
|
cwd,
|
|
37330
37630
|
env: childEnv,
|
|
@@ -37350,16 +37650,7 @@ var AcpClient = class {
|
|
|
37350
37650
|
child.stderr?.on("data", (chunk) => {
|
|
37351
37651
|
for (const line of chunk.split(/\r?\n/)) {
|
|
37352
37652
|
const trimmed = line.trim();
|
|
37353
|
-
if (trimmed)
|
|
37354
|
-
log.info("acpAdapter", trimmed);
|
|
37355
|
-
this.opts.onStderr?.(trimmed);
|
|
37356
|
-
this.recentStderr.push(trimmed);
|
|
37357
|
-
if (this.recentStderr.length > 12) this.recentStderr.shift();
|
|
37358
|
-
if (this.startupFailureReject && FATAL_STARTUP_RE.test(trimmed)) {
|
|
37359
|
-
this.startupFailureReject(new Error(`AGENT_STARTUP_FAILED: ${trimmed}`));
|
|
37360
|
-
this.startupFailureReject = null;
|
|
37361
|
-
}
|
|
37362
|
-
}
|
|
37653
|
+
if (trimmed) this.onAdapterStderrLine(trimmed);
|
|
37363
37654
|
}
|
|
37364
37655
|
});
|
|
37365
37656
|
child.on("exit", (code, signal) => {
|
|
@@ -37559,9 +37850,16 @@ var AcpClient = class {
|
|
|
37559
37850
|
PROMPT_ACTIVE_IDLE_TIMEOUT_MS
|
|
37560
37851
|
);
|
|
37561
37852
|
this.promptIdle = idle;
|
|
37853
|
+
let fatalTripped = false;
|
|
37854
|
+
const fatal = new Promise((_2, reject) => {
|
|
37855
|
+
this.turnFailureReject = (err) => {
|
|
37856
|
+
fatalTripped = true;
|
|
37857
|
+
reject(err);
|
|
37858
|
+
};
|
|
37859
|
+
});
|
|
37562
37860
|
this.pendingToolCalls.clear();
|
|
37563
37861
|
try {
|
|
37564
|
-
const result = await Promise.race([send, idle.promise]);
|
|
37862
|
+
const result = await Promise.race([send, idle.promise, fatal]);
|
|
37565
37863
|
await new Promise((resolve13) => setImmediate(resolve13));
|
|
37566
37864
|
log.info(
|
|
37567
37865
|
"acpClient",
|
|
@@ -37575,15 +37873,32 @@ var AcpClient = class {
|
|
|
37575
37873
|
"acpClient",
|
|
37576
37874
|
`prompt \u2190 failed elapsedMs=${Date.now() - t0} err=${err instanceof Error ? err.message : String(err)}`
|
|
37577
37875
|
);
|
|
37578
|
-
if (idleTripped) await this.cancelAbandonedTurn(sessionId, send);
|
|
37876
|
+
if (idleTripped || fatalTripped) await this.cancelAbandonedTurn(sessionId, send);
|
|
37579
37877
|
throw err;
|
|
37580
37878
|
} finally {
|
|
37581
37879
|
idle.clear();
|
|
37582
37880
|
this.promptIdle = null;
|
|
37881
|
+
this.turnFailureReject = null;
|
|
37882
|
+
}
|
|
37883
|
+
}
|
|
37884
|
+
/** One non-empty adapter stderr line: logged, kept in the ring, and checked
|
|
37885
|
+
* for the fatal startup / fatal turn errors that end a stuck RPC early. */
|
|
37886
|
+
onAdapterStderrLine(trimmed) {
|
|
37887
|
+
log.info("acpAdapter", trimmed);
|
|
37888
|
+
this.opts.onStderr?.(trimmed);
|
|
37889
|
+
this.recentStderr.push(trimmed);
|
|
37890
|
+
if (this.recentStderr.length > 12) this.recentStderr.shift();
|
|
37891
|
+
if (this.startupFailureReject && FATAL_STARTUP_RE.test(trimmed)) {
|
|
37892
|
+
this.startupFailureReject(new Error(`AGENT_STARTUP_FAILED: ${trimmed}`));
|
|
37893
|
+
this.startupFailureReject = null;
|
|
37894
|
+
}
|
|
37895
|
+
if (this.turnFailureReject && this.fatalTurnStderr?.test(trimmed)) {
|
|
37896
|
+
this.turnFailureReject(new Error(`AGENT_TURN_FAILED: ${agentErrorOf(trimmed)}`));
|
|
37897
|
+
this.turnFailureReject = null;
|
|
37583
37898
|
}
|
|
37584
37899
|
}
|
|
37585
37900
|
/**
|
|
37586
|
-
* Cancel a turn the idle watchdog abandoned and wait, bounded, for the
|
|
37901
|
+
* Cancel a turn the idle watchdog (or a fatal stderr error) abandoned and wait, bounded, for the
|
|
37587
37902
|
* adapter to answer its `session/prompt` — the proof the turn is over before
|
|
37588
37903
|
* the next prompt is sent. Best-effort: a dead adapter can't hold the queue
|
|
37589
37904
|
* longer than {@link ABANDONED_TURN_SETTLE_MS}.
|
|
@@ -43678,7 +43993,7 @@ async function runStartTaskTurn(ctx, payload, blocks, promptText) {
|
|
|
43678
43993
|
reportTurn2(
|
|
43679
43994
|
ctx,
|
|
43680
43995
|
"failed",
|
|
43681
|
-
bubble === AUTH_FAILURE_MESSAGE ? "AUTH_FAILED" : bubble === ONE_M_CREDITS_MESSAGE ? "ONE_M_CREDITS" : failed.partialReplyKept ? "TURN_ERROR_PARTIAL" : "TURN_ERROR"
|
|
43996
|
+
bubble === AUTH_FAILURE_MESSAGE ? "AUTH_FAILED" : bubble === ONE_M_CREDITS_MESSAGE ? "ONE_M_CREDITS" : bubble === AGENT_FREE_LIMIT_MESSAGE ? "AGENT_FREE_LIMIT" : failed.partialReplyKept ? "TURN_ERROR_PARTIAL" : "TURN_ERROR"
|
|
43682
43997
|
);
|
|
43683
43998
|
if (bubble === AUTH_FAILURE_MESSAGE || bubble === ONE_M_CREDITS_MESSAGE) {
|
|
43684
43999
|
void reportCredentialInvalid(opts);
|
|
@@ -51622,7 +51937,7 @@ async function autoUpgradeBeforeCriticalCommand() {
|
|
|
51622
51937
|
if (process.env.NODE_ENV === "test") return;
|
|
51623
51938
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
51624
51939
|
if (process.env.CI) return;
|
|
51625
|
-
const current2 = true ? "2.76.
|
|
51940
|
+
const current2 = true ? "2.76.36" : null;
|
|
51626
51941
|
if (!current2) return;
|
|
51627
51942
|
const cache = readCache();
|
|
51628
51943
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -51639,7 +51954,7 @@ function checkForUpdates() {
|
|
|
51639
51954
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
51640
51955
|
if (process.env.CI) return;
|
|
51641
51956
|
if (!process.stdout.isTTY) return;
|
|
51642
|
-
const current2 = true ? "2.76.
|
|
51957
|
+
const current2 = true ? "2.76.36" : null;
|
|
51643
51958
|
if (!current2) return;
|
|
51644
51959
|
const cache = readCache();
|
|
51645
51960
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -51945,7 +52260,7 @@ var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
|
|
|
51945
52260
|
var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
|
|
51946
52261
|
var SELF_UPDATE_LS_TIMEOUT_MS = 15e3;
|
|
51947
52262
|
function currentCliVersion() {
|
|
51948
|
-
return true ? "2.76.
|
|
52263
|
+
return true ? "2.76.36" : null;
|
|
51949
52264
|
}
|
|
51950
52265
|
async function installedVersion(deps) {
|
|
51951
52266
|
const ls = await deps.run(
|
|
@@ -52168,7 +52483,7 @@ function signalHostReady(send = process.send?.bind(process)) {
|
|
|
52168
52483
|
}
|
|
52169
52484
|
function defaultDeps() {
|
|
52170
52485
|
return {
|
|
52171
|
-
ownVersion: true ? "2.76.
|
|
52486
|
+
ownVersion: true ? "2.76.36" : null,
|
|
52172
52487
|
root: cliVersionsRoot(),
|
|
52173
52488
|
args: process.argv.slice(3),
|
|
52174
52489
|
execPath: process.execPath,
|
|
@@ -54706,7 +55021,7 @@ function checkChokidar() {
|
|
|
54706
55021
|
}
|
|
54707
55022
|
async function doctor(args2 = []) {
|
|
54708
55023
|
const json = args2.includes("--json");
|
|
54709
|
-
const cliVersion = true ? "2.76.
|
|
55024
|
+
const cliVersion = true ? "2.76.36" : "0.0.0-dev";
|
|
54710
55025
|
const apiBase2 = resolveApiBaseUrl();
|
|
54711
55026
|
const diagnosticId = (0, import_node_crypto17.randomUUID)();
|
|
54712
55027
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -55242,7 +55557,7 @@ async function mcpWarm(argv = [], opts = {}) {
|
|
|
55242
55557
|
// src/commands/version.ts
|
|
55243
55558
|
var import_picocolors15 = __toESM(require("picocolors"));
|
|
55244
55559
|
function version2() {
|
|
55245
|
-
const v = true ? "2.76.
|
|
55560
|
+
const v = true ? "2.76.36" : "unknown";
|
|
55246
55561
|
console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
|
|
55247
55562
|
}
|
|
55248
55563
|
|