@comty.io/core 0.1.1 → 0.1.3
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/README.md +1 -76
- package/comty-sdk.js +48 -520
- package/package.json +3 -14
- package/src/browser.d.ts +1 -3
- package/src/browser.js +35 -437
- package/src/comments.js +8 -12
- package/src/style.js +5 -71
- package/src/agent-process.mjs +0 -89
- package/src/claude-permission.mjs +0 -37
- package/src/claude.mjs +0 -120
- package/src/codex.mjs +0 -66
- package/src/companion.mjs +0 -207
- package/src/cursor.mjs +0 -49
- package/src/dev.mjs +0 -169
- package/src/vite.d.ts +0 -5
- package/src/vite.mjs +0 -66
package/comty-sdk.js
CHANGED
|
@@ -12,9 +12,7 @@ function getComtyStyle() {
|
|
|
12
12
|
--comty-foreground: #fafafa;
|
|
13
13
|
--comty-muted: var(--comty-toolbar-muted);
|
|
14
14
|
--comty-accent: #55aaf5;
|
|
15
|
-
--comty-
|
|
16
|
-
--comty-agent-success: #80c9a4;
|
|
17
|
-
--comty-agent-error: #ef7676;
|
|
15
|
+
--comty-error: #ef7676;
|
|
18
16
|
--comty-outline: oklch(0.62 0.18 255);
|
|
19
17
|
--comty-paper: #fff;
|
|
20
18
|
--comty-ink: #171717;
|
|
@@ -58,8 +56,6 @@ function getComtyStyle() {
|
|
|
58
56
|
--comty-dialog-width: 32rem;
|
|
59
57
|
--comty-dialog-shadow: 0 1.5rem 4rem rgb(0 0 0 / .16);
|
|
60
58
|
--comty-motion-duration: 220ms;
|
|
61
|
-
--comty-working-dot-size: .25em;
|
|
62
|
-
--comty-working-dot-gap: .125em;
|
|
63
59
|
--comty-ease-out: cubic-bezier(0.23, 1, 0.32, 1);
|
|
64
60
|
--comty-ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
|
|
65
61
|
position: fixed;
|
|
@@ -71,68 +67,7 @@ function getComtyStyle() {
|
|
|
71
67
|
font-family: var(--comty-font);
|
|
72
68
|
color-scheme: dark;
|
|
73
69
|
}
|
|
74
|
-
|
|
75
|
-
html.comty-agent-docked[data-comty-agent-side="left"] body { margin-left: 22rem; }
|
|
76
|
-
html.comty-agent-docked[data-comty-agent-side="right"] body { margin-right: 22rem; }
|
|
77
|
-
@media (max-width: 50rem) { html.comty-agent-docked body { margin-left: 0; margin-right: 0; } }
|
|
78
|
-
#comty-root > .comty-agent-panel { position: fixed; left: 0; top: 0; bottom: 0; z-index: 2147483647; width: min(22rem, calc(100vw - 3rem)); box-sizing: border-box; display: flex; flex-direction: column; overflow: hidden; pointer-events: auto; border-right: .0625rem solid var(--comty-hover-surface); background: var(--comty-surface); color: var(--comty-foreground); font: .875rem/1.4 ui-sans-serif, system-ui, sans-serif; transform: translateX(0); transition: transform var(--comty-motion-duration) var(--comty-ease-out); color-scheme: dark; }
|
|
79
|
-
#comty-root > .comty-agent-panel[data-side="right"] { left: auto; right: 0; border-right: 0; border-left: .0625rem solid var(--comty-hover-surface); }
|
|
80
|
-
#comty-root > .comty-agent-panel[data-closed] { transform: translateX(-100%); pointer-events: none; }
|
|
81
|
-
#comty-root > .comty-agent-panel[data-side="right"][data-closed] { transform: translateX(100%); }
|
|
82
|
-
#comty-root > .comty-agent-panel[hidden] { display: none; }
|
|
83
|
-
.comty-agent-panel *, .comty-agent-panel *::before { box-sizing: border-box; }
|
|
84
|
-
.comty-agent-panel-header { display: flex; flex: 0 0 auto; align-items: center; gap: .75rem; padding: .5rem .75rem; border-bottom: .0625rem solid var(--comty-hover-surface); }
|
|
85
|
-
.comty-agent-brand { display: grid; place-items: center; width: 2.375rem; height: 2.375rem; flex-shrink: 0; border-radius: .6875rem; color: var(--comty-accent); background: var(--comty-hover-surface); }
|
|
86
|
-
.comty-agent-panel svg { display: block; width: 1rem; height: 1rem; flex-shrink: 0; }
|
|
87
|
-
.comty-agent-brand svg { width: 1.25rem; height: 1.25rem; }
|
|
88
|
-
.comty-agent-heading { flex: 1; min-width: 0; }
|
|
89
|
-
.comty-agent-heading strong { display: block; font-weight: 600; font-size: .875rem; }
|
|
90
|
-
.comty-agent-panel-content { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; scrollbar-color: var(--comty-hover-surface) transparent; padding: .375rem .5rem 2rem; }
|
|
91
|
-
.comty-agent-item { padding: .375rem .25rem; overflow-wrap: anywhere; }
|
|
92
|
-
.comty-agent-item + .comty-agent-item { border-top: .0625rem solid var(--comty-hover-surface); }
|
|
93
|
-
.comty-agent-item h3 { margin: 0 0 .25rem; color: var(--comty-foreground); font: 500 .875rem/1.4 ui-sans-serif, system-ui, sans-serif; }
|
|
94
|
-
.comty-agent-list { display: grid; gap: .125rem; }
|
|
95
|
-
.comty-agent-row { position: relative; display: flex; align-items: center; gap: .625rem; min-height: 2rem; padding: .25rem .5rem; border-radius: .5rem; color: var(--comty-foreground); }
|
|
96
|
-
.comty-agent-row:hover { background: var(--comty-hover-surface); }
|
|
97
|
-
.comty-agent-dot { width: .4375rem; height: .4375rem; flex: 0 0 auto; border-radius: 50%; background: var(--comty-muted); }
|
|
98
|
-
.comty-working-indicator { display: inline-grid; grid-template-columns: repeat(3, var(--comty-working-dot-size)); gap: var(--comty-working-dot-gap); flex: 0 0 auto; color: var(--comty-foreground); }
|
|
99
|
-
.comty-working-indicator > i { display: block; width: var(--comty-working-dot-size); height: var(--comty-working-dot-size); border-radius: 50%; background: currentColor; opacity: .25; transition: opacity 150ms linear; }
|
|
100
|
-
.comty-working-indicator > i[data-active] { opacity: 1; }
|
|
101
|
-
.comty-agent-dot[data-status="success"] { background: var(--comty-agent-success); }
|
|
102
|
-
.comty-agent-dot[data-status="error"] { background: var(--comty-agent-error); }
|
|
103
|
-
.comty-agent-row-name { min-width: 0; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }
|
|
104
|
-
.comty-agent-row-state { flex: 0 0 auto; color: var(--comty-muted); font-size: .875rem; }
|
|
105
|
-
.comty-agent-row-actions { position: absolute; top: 50%; right: .25rem; display: flex; gap: .25rem; border-radius: .25rem; background: var(--comty-hover-surface); opacity: 0; pointer-events: none; transform: translateY(-50%); }
|
|
106
|
-
.comty-agent-row:hover .comty-agent-row-actions, .comty-agent-row-actions:has(.comty-agent-action:focus-visible) { opacity: 1; pointer-events: auto; }
|
|
107
|
-
@media (hover: none) { .comty-agent-row-actions { position: static; opacity: 1; pointer-events: auto; transform: none; background: transparent; } }
|
|
108
|
-
.comty-agent-panel .comty-agent-row-actions .comty-agent-action { min-height: 1.5rem; padding: .125rem .375rem; border-radius: .25rem; background: transparent; color: var(--comty-muted); font-size: .875rem; }
|
|
109
|
-
.comty-agent-panel .comty-agent-row-actions .comty-agent-action:hover { color: var(--comty-foreground); background: var(--comty-surface); }
|
|
110
|
-
.comty-agent-error-popover { position: fixed; z-index: 2147483647; width: min(20rem, calc(100vw - 1rem)); max-height: calc(100vh - 1rem); overflow: auto; padding: .75rem .875rem; border: 0; border-radius: .625rem; background: var(--comty-surface); box-shadow: var(--comty-floating-shadow); color: var(--comty-foreground); font: .875rem/1.4 ui-sans-serif, system-ui, sans-serif; pointer-events: none; color-scheme: dark; }
|
|
111
|
-
.comty-agent-error-popover strong { display: block; font-weight: 600; }
|
|
112
|
-
.comty-agent-error-popover p { margin: .375rem 0 0; color: var(--comty-muted); white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
113
|
-
.comty-agent-panel p { margin: .5rem 0 0; font: inherit; color: var(--comty-muted); }
|
|
114
|
-
.comty-agent-error { margin-top: .75rem; }
|
|
115
|
-
.comty-agent-error strong { display: block; font-weight: 500; color: var(--comty-foreground); }
|
|
116
|
-
.comty-agent-error p { margin-top: .25rem; }
|
|
117
|
-
.comty-agent-banner { margin-bottom: 1rem; }
|
|
118
|
-
.comty-agent-banner .comty-agent-error { margin-top: 0; }
|
|
119
|
-
.comty-agent-actions { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .875rem; }
|
|
120
|
-
.comty-agent-panel .comty-agent-action { display: inline-flex; align-items: center; justify-content: center; gap: .375rem; min-height: 2rem; margin: 0; padding: .375rem .625rem; border: 0; border-radius: .5rem; font: 500 .875rem/1.4 ui-sans-serif, system-ui, sans-serif; cursor: pointer; color: var(--comty-foreground); background: var(--comty-hover-surface); transition: background-color 150ms ease; }
|
|
121
|
-
.comty-agent-panel .comty-agent-action:hover { background: color-mix(in srgb, var(--comty-foreground) 12%, var(--comty-hover-surface)); }
|
|
122
|
-
.comty-agent-panel .comty-agent-action[data-primary] { color: var(--comty-paper); background: var(--comty-accent); }
|
|
123
|
-
.comty-agent-panel .comty-agent-action:disabled { opacity: .5; cursor: wait; }
|
|
124
|
-
.comty-agent-panel .comty-agent-close { width: 1.5rem; min-height: 1.5rem; padding: 0; background: transparent; color: var(--comty-muted); }
|
|
125
|
-
.comty-agent-panel :is(button, summary):focus-visible { outline: .125rem solid var(--comty-accent); outline-offset: .1875rem; }
|
|
126
|
-
.comty-agent-details { margin-top: .625rem; }
|
|
127
|
-
.comty-agent-panel summary { cursor: pointer; color: var(--comty-muted); font-size: .875rem; }
|
|
128
|
-
.comty-agent-panel pre { margin: .5rem 0 0; padding: .625rem; white-space: pre-wrap; overflow-wrap: anywhere; max-height: 10rem; overflow: auto; border-radius: .5rem; background: var(--comty-surface); color: var(--comty-muted); font: .875rem/1.4 ui-monospace, monospace; }
|
|
129
|
-
.comty-agent-empty { padding: 1rem .5rem; text-align: center; }
|
|
130
|
-
.comty-agent-empty .comty-agent-brand { margin: 0 auto .875rem; }
|
|
131
|
-
.comty-agent-empty strong { font-size: .875rem; font-weight: 500; }
|
|
132
|
-
.comty-agent-empty p { max-width: 15rem; margin: .5rem auto 0; font-size: .875rem; }
|
|
133
|
-
.comty-agent-working { position: fixed; z-index: 1; box-sizing: border-box; border: 2px solid var(--comty-accent); border-radius: .25rem; pointer-events: none; }
|
|
134
|
-
.comty-agent-working-badge { position: absolute; left: -.125rem; bottom: 100%; display: inline-flex; align-items: center; gap: .4rem; padding: .25rem .5rem; border-radius: .375rem .375rem 0 0; background: var(--comty-surface); color: var(--comty-foreground); font: 600 .6875rem/1.4 ui-sans-serif, system-ui, sans-serif; white-space: nowrap; }
|
|
135
|
-
.comty-agent-working[data-badge-below] .comty-agent-working-badge { bottom: auto; top: 100%; border-radius: 0 0 .375rem .375rem; }
|
|
70
|
+
|
|
136
71
|
#comty-root { cursor: default; }
|
|
137
72
|
#comty-root::backdrop { background: transparent; pointer-events: none; }
|
|
138
73
|
html.comty-comment-placement,
|
|
@@ -205,8 +140,7 @@ function getComtyStyle() {
|
|
|
205
140
|
#comty-root [hidden] { display: none !important; }
|
|
206
141
|
[data-comty-anchor-hidden] { visibility: hidden !important; pointer-events: none !important; }
|
|
207
142
|
@media (prefers-reduced-motion: reduce) {
|
|
208
|
-
|
|
209
|
-
.comty-toolbar, .comty-control-button, .comty-sidepanel, .comty-pin, .comty-bubble, .comty-agent-panel, .comty-agent-action, .comty-agent-dot, .comty-working-indicator > i { transition: none !important; animation: none !important; }
|
|
143
|
+
.comty-toolbar, .comty-control-button, .comty-sidepanel, .comty-pin, .comty-bubble { transition: none !important; animation: none !important; }
|
|
210
144
|
}
|
|
211
145
|
|
|
212
146
|
.comty-sidepanel {
|
|
@@ -767,12 +701,12 @@ function getComtyStyle() {
|
|
|
767
701
|
}
|
|
768
702
|
|
|
769
703
|
.comty-popover-item.comty-popover-item-destructive {
|
|
770
|
-
color: var(--comty-
|
|
704
|
+
color: var(--comty-error);
|
|
771
705
|
}
|
|
772
706
|
|
|
773
707
|
.comty-popover-item.comty-popover-item-destructive:hover,
|
|
774
708
|
.comty-popover-item.comty-popover-item-destructive:focus-visible {
|
|
775
|
-
background: color-mix(in srgb, var(--comty-
|
|
709
|
+
background: color-mix(in srgb, var(--comty-error) 12%, var(--comty-surface));
|
|
776
710
|
outline: none;
|
|
777
711
|
}
|
|
778
712
|
|
|
@@ -2328,7 +2262,7 @@ function createCommentThread(context) {
|
|
|
2328
2262
|
const {
|
|
2329
2263
|
root, apiUrl, projectKey, commentStatuses, selectedStatusFilters, placedPins,
|
|
2330
2264
|
closeBubbles, getCommentStatus, updateCommentStatus, applyStatusDot,
|
|
2331
|
-
renderSidepanelComments, applyStatusFilters,
|
|
2265
|
+
renderSidepanelComments, applyStatusFilters, createThreadItem,
|
|
2332
2266
|
isOwnCommentEntry, updateCommentContent, deleteSdkComment, getCommentId,
|
|
2333
2267
|
updateReplyContent, deleteSdkReply, createCommentAvatar, getSdkHeaders,
|
|
2334
2268
|
showAuthPrompt,
|
|
@@ -2358,7 +2292,7 @@ function createCommentThread(context) {
|
|
|
2358
2292
|
|
|
2359
2293
|
const title = document.createElement("h2");
|
|
2360
2294
|
title.className = "comty-bubble-title";
|
|
2361
|
-
title.innerText =
|
|
2295
|
+
title.innerText = "Comment";
|
|
2362
2296
|
header.appendChild(title);
|
|
2363
2297
|
|
|
2364
2298
|
const headerActions = document.createElement("div");
|
|
@@ -2402,7 +2336,7 @@ function createCommentThread(context) {
|
|
|
2402
2336
|
};
|
|
2403
2337
|
|
|
2404
2338
|
const saveStatus = async (nextStatus, control) => {
|
|
2405
|
-
if (!context.canWrite
|
|
2339
|
+
if (!context.canWrite) return false;
|
|
2406
2340
|
control.disabled = true;
|
|
2407
2341
|
const savedStatus = await updateCommentStatus(comment, nextStatus);
|
|
2408
2342
|
control.disabled = false;
|
|
@@ -2418,10 +2352,6 @@ function createCommentThread(context) {
|
|
|
2418
2352
|
syncStatusTrigger();
|
|
2419
2353
|
renderSidepanelComments();
|
|
2420
2354
|
applyStatusFilters();
|
|
2421
|
-
if (comment.local_agent && savedStatus === "done") {
|
|
2422
|
-
closeBubbles();
|
|
2423
|
-
void loadComments({ force: true });
|
|
2424
|
-
}
|
|
2425
2355
|
if (
|
|
2426
2356
|
selectedStatusFilters.size > 0 &&
|
|
2427
2357
|
!selectedStatusFilters.has(savedStatusOption.value)
|
|
@@ -2431,7 +2361,7 @@ function createCommentThread(context) {
|
|
|
2431
2361
|
return true;
|
|
2432
2362
|
};
|
|
2433
2363
|
|
|
2434
|
-
statusMenuButton.disabled =
|
|
2364
|
+
statusMenuButton.disabled = !context.canWrite;
|
|
2435
2365
|
statusMenuButton.onclick = (event) => {
|
|
2436
2366
|
event.stopPropagation();
|
|
2437
2367
|
const existingPopover = document.querySelector(
|
|
@@ -2574,7 +2504,7 @@ function createCommentThread(context) {
|
|
|
2574
2504
|
);
|
|
2575
2505
|
};
|
|
2576
2506
|
|
|
2577
|
-
const mainItem = createThreadItem(comment, { showMore:
|
|
2507
|
+
const mainItem = createThreadItem(comment, { showMore: isOwnCommentEntry(comment) });
|
|
2578
2508
|
|
|
2579
2509
|
const startEditingEntry = (entry, item, persist) => {
|
|
2580
2510
|
if (!isOwnCommentEntry(entry)) return;
|
|
@@ -2721,7 +2651,7 @@ function createCommentThread(context) {
|
|
|
2721
2651
|
const replyForm = document.createElement("div");
|
|
2722
2652
|
replyForm.className = "comty-reply-form";
|
|
2723
2653
|
|
|
2724
|
-
if (context.canWrite
|
|
2654
|
+
if (context.canWrite) {
|
|
2725
2655
|
replyForm.appendChild(createCommentAvatar(context.currentUser || { name: "You" }));
|
|
2726
2656
|
const replyField = document.createElement("div");
|
|
2727
2657
|
replyField.className = "comty-reply-field";
|
|
@@ -2792,7 +2722,7 @@ function createCommentThread(context) {
|
|
|
2792
2722
|
replyField.appendChild(replyInput);
|
|
2793
2723
|
replyField.appendChild(replyButton);
|
|
2794
2724
|
replyForm.appendChild(replyField);
|
|
2795
|
-
} else
|
|
2725
|
+
} else {
|
|
2796
2726
|
replyForm.classList.add("comty-reply-form-guest");
|
|
2797
2727
|
const signInButton = document.createElement("button");
|
|
2798
2728
|
signInButton.className = "comty-sign-in-reply";
|
|
@@ -2805,7 +2735,7 @@ function createCommentThread(context) {
|
|
|
2805
2735
|
replyForm.appendChild(signInButton);
|
|
2806
2736
|
}
|
|
2807
2737
|
|
|
2808
|
-
|
|
2738
|
+
thread.appendChild(replyForm);
|
|
2809
2739
|
bubble.appendChild(thread);
|
|
2810
2740
|
root.appendChild(bubble);
|
|
2811
2741
|
|
|
@@ -3042,17 +2972,7 @@ const instanceKey = Symbol.for("comty.sdk.instance");
|
|
|
3042
2972
|
/** Initialize once per document; safe to import and call during server rendering. */
|
|
3043
2973
|
function initComty(options = {}) {
|
|
3044
2974
|
if (typeof window === "undefined" || typeof document === "undefined") return Promise.resolve();
|
|
3045
|
-
const
|
|
3046
|
-
const agent = options.agent;
|
|
3047
|
-
if (agent && (!isLocalSite || typeof agent.token !== "string" || !/^[a-f0-9]{64}$/.test(agent.token))) {
|
|
3048
|
-
return Promise.reject(new TypeError("Comty: invalid local companion configuration"));
|
|
3049
|
-
}
|
|
3050
|
-
if (agent) {
|
|
3051
|
-
try {
|
|
3052
|
-
if (new URL(agent.url).origin !== window.location.origin) throw new Error();
|
|
3053
|
-
} catch { return Promise.reject(new TypeError("Comty: companion must share the page origin")); }
|
|
3054
|
-
}
|
|
3055
|
-
const projectKey = options.projectKey || (agent ? "local" : undefined);
|
|
2975
|
+
const projectKey = options.projectKey;
|
|
3056
2976
|
const apiUrl = options.apiUrl || "http://localhost:4000";
|
|
3057
2977
|
if (typeof projectKey !== "string" || !projectKey.trim()) {
|
|
3058
2978
|
return Promise.reject(new TypeError("Comty: projectKey is required"));
|
|
@@ -3064,14 +2984,12 @@ function initComty(options = {}) {
|
|
|
3064
2984
|
if (!["http:", "https:"].includes(parsedApi.protocol)) {
|
|
3065
2985
|
return Promise.reject(new TypeError("Comty: apiUrl must be an absolute HTTP(S) URL"));
|
|
3066
2986
|
}
|
|
3067
|
-
const configuration = JSON.stringify([projectKey, apiUrl
|
|
2987
|
+
const configuration = JSON.stringify([projectKey, apiUrl]);
|
|
3068
2988
|
const existing = window[instanceKey];
|
|
3069
2989
|
if (existing) {
|
|
3070
2990
|
return existing.configuration === configuration ? existing.ready
|
|
3071
2991
|
: Promise.reject(new Error("Comty: already initialized with different options"));
|
|
3072
2992
|
}
|
|
3073
|
-
const agentBridgeUrl = agent?.url;
|
|
3074
|
-
const localOnly = Boolean(agent && !options.projectKey);
|
|
3075
2993
|
const ready = new Promise((resolve, reject) => {
|
|
3076
2994
|
const mount = () => {
|
|
3077
2995
|
try { resolve(mountComty()); } catch (error) { reject(error); }
|
|
@@ -3085,19 +3003,10 @@ function initComty(options = {}) {
|
|
|
3085
3003
|
|
|
3086
3004
|
function mountComty() {
|
|
3087
3005
|
let projectId = null;
|
|
3088
|
-
let localTasks = [];
|
|
3089
|
-
let localApprovals = [];
|
|
3090
|
-
let agentPanelOpen = false;
|
|
3091
|
-
let agentPanelSignature = "";
|
|
3092
|
-
let agentPanelTransition = 0;
|
|
3093
|
-
let agentConnectionError = "";
|
|
3094
|
-
let agentActionError = "";
|
|
3095
|
-
const agentPendingActions = new Set();
|
|
3096
3006
|
const session = {
|
|
3097
3007
|
mode: "off",
|
|
3098
|
-
get comments() { return this.mode === "browse" || this.mode === "edit"
|
|
3099
|
-
get edit() { return this.mode === "edit"
|
|
3100
|
-
get agent() { return this.mode === "agent"; },
|
|
3008
|
+
get comments() { return this.mode === "browse" || this.mode === "edit"; },
|
|
3009
|
+
get edit() { return this.mode === "edit"; },
|
|
3101
3010
|
get inspect() { return this.mode === "inspect"; },
|
|
3102
3011
|
};
|
|
3103
3012
|
const selectedStatusFilters = new Set();
|
|
@@ -3118,10 +3027,9 @@ function initComty(options = {}) {
|
|
|
3118
3027
|
const tokenStorageKey = `comty:${projectKey}:token`;
|
|
3119
3028
|
let sdkToken = "";
|
|
3120
3029
|
const activeHoverCommentIds = new Set();
|
|
3121
|
-
/** @type {null | 'edit' | 'browse'
|
|
3030
|
+
/** @type {null | 'edit' | 'browse'} */
|
|
3122
3031
|
let sessionEntry = null;
|
|
3123
3032
|
const placedPins = new Map();
|
|
3124
|
-
const workingOutlines = new Map();
|
|
3125
3033
|
const placementDiagnostics = new Map();
|
|
3126
3034
|
let inspectedElement = null;
|
|
3127
3035
|
let selectedElement = null;
|
|
@@ -3168,7 +3076,6 @@ function initComty(options = {}) {
|
|
|
3168
3076
|
const root = document.createElement("div");
|
|
3169
3077
|
root.id = "comty-root";
|
|
3170
3078
|
document.body.appendChild(root);
|
|
3171
|
-
if (agent) document.documentElement.classList.add("comty-agent-enabled");
|
|
3172
3079
|
|
|
3173
3080
|
const style = document.createElement("style");
|
|
3174
3081
|
style.innerHTML = getComtyStyle();
|
|
@@ -3216,40 +3123,20 @@ function initComty(options = {}) {
|
|
|
3216
3123
|
const inspectorBtn = toolButton("Inspect · Shift I", '<path d="M8 3H5a2 2 0 0 0-2 2v3m13-5h3a2 2 0 0 1 2 2v3M3 16v3a2 2 0 0 0 2 2h3m13-5v3a2 2 0 0 1-2 2h-3"/><path d="m9 9 8 4-4 1-1 4Z"/>', () => setSession("inspect"));
|
|
3217
3124
|
const btn = toolButton("Comment · Shift C", '<path d="M21 11.5a8.4 8.4 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.4 8.4 0 0 1-3.8-.9L3 21l1.9-5.7a8.4 8.4 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6A8.4 8.4 0 0 1 12.5 3h.5a8.5 8.5 0 0 1 8 8v.5Z"/>', () => {
|
|
3218
3125
|
if (!canWrite) showAuthPrompt();
|
|
3219
|
-
else if (session.
|
|
3126
|
+
else if (session.inspect || !isSessionActive()) startEditSession();
|
|
3220
3127
|
else if (!session.edit) setSession("edit", { entry: sessionEntry });
|
|
3221
3128
|
});
|
|
3222
3129
|
btn.id = "comty-toggle";
|
|
3223
|
-
const agentBtn = isLocalSite
|
|
3224
|
-
? toolButton("Agent task · localhost only", '<path d="M8 7 3 12l5 5m8-10 5 5-5 5M14 4l-4 16"/>', () => {
|
|
3225
|
-
startAgentSession();
|
|
3226
|
-
})
|
|
3227
|
-
: null;
|
|
3228
3130
|
const divider = document.createElement("span");
|
|
3229
3131
|
divider.className = "comty-tool-divider";
|
|
3230
3132
|
toolbar.appendChild(divider);
|
|
3231
3133
|
const commentTools = document.createElement("div");
|
|
3232
3134
|
commentTools.className = "comty-tool-context";
|
|
3233
3135
|
toolbar.appendChild(commentTools);
|
|
3234
|
-
const agentTools = agentBtn ? document.createElement("div") : null;
|
|
3235
|
-
if (agentTools) {
|
|
3236
|
-
agentTools.className = "comty-tool-context";
|
|
3237
|
-
agentTools.hidden = true;
|
|
3238
|
-
toolbar.appendChild(agentTools);
|
|
3239
|
-
}
|
|
3240
|
-
const agentHistoryBtn = agentTools ? toolButton("Local agent history", '<path d="M3 12a9 9 0 1 0 3-6.7M3 4v4h4"/><path d="M12 7v5l3 2"/>', () => {
|
|
3241
|
-
if (!agent) { showAgentBridgeError(); return; }
|
|
3242
|
-
agentPanelOpen = !agentPanelOpen;
|
|
3243
|
-
renderAgentPanel();
|
|
3244
|
-
}) : null;
|
|
3245
|
-
if (agentHistoryBtn) {
|
|
3246
|
-
agentHistoryBtn.setAttribute("aria-expanded", "false");
|
|
3247
|
-
agentTools.appendChild(agentHistoryBtn);
|
|
3248
|
-
}
|
|
3249
3136
|
const primaryTools = document.createElement("div");
|
|
3250
3137
|
primaryTools.className = "comty-tool-primary";
|
|
3251
3138
|
toolbar.insertBefore(primaryTools, browseBtn);
|
|
3252
|
-
for (const button of [browseBtn, inspectorBtn, btn
|
|
3139
|
+
for (const button of [browseBtn, inspectorBtn, btn]) primaryTools.appendChild(button);
|
|
3253
3140
|
const inspectorTools = document.createElement("div");
|
|
3254
3141
|
inspectorTools.className = "comty-tool-context";
|
|
3255
3142
|
inspectorTools.hidden = true;
|
|
@@ -4098,50 +3985,6 @@ function initComty(options = {}) {
|
|
|
4098
3985
|
let toolbarMotionFrame = 0;
|
|
4099
3986
|
let toolbarAnimations = [];
|
|
4100
3987
|
const reducedMotion = matchMedia("(prefers-reduced-motion: reduce)");
|
|
4101
|
-
let workingIndicatorTimer = 0;
|
|
4102
|
-
function scheduleWorkingIndicators() {
|
|
4103
|
-
if (workingIndicatorTimer || reducedMotion.matches || document.hidden) return;
|
|
4104
|
-
workingIndicatorTimer = setTimeout(() => {
|
|
4105
|
-
workingIndicatorTimer = 0;
|
|
4106
|
-
if (!root.isConnected) return;
|
|
4107
|
-
const indicators = root.querySelectorAll('.comty-working-indicator');
|
|
4108
|
-
if (!indicators.length) return;
|
|
4109
|
-
for (const indicator of indicators) {
|
|
4110
|
-
const previous = Number(indicator.dataset.activeDots.split(',')[0]);
|
|
4111
|
-
const first = (previous + 1 + Math.floor(Math.random() * 8)) % 9;
|
|
4112
|
-
const second = (first + 1 + Math.floor(Math.random() * 8)) % 9;
|
|
4113
|
-
indicator.dataset.activeDots = `${first},${second}`;
|
|
4114
|
-
[...indicator.children].forEach((dot, index) => dot.toggleAttribute('data-active', index === first || index === second));
|
|
4115
|
-
}
|
|
4116
|
-
scheduleWorkingIndicators();
|
|
4117
|
-
}, 600);
|
|
4118
|
-
}
|
|
4119
|
-
function createWorkingIndicator() {
|
|
4120
|
-
const indicator = document.createElement('span');
|
|
4121
|
-
indicator.className = 'comty-working-indicator';
|
|
4122
|
-
indicator.setAttribute('aria-hidden', 'true');
|
|
4123
|
-
indicator.dataset.activeDots = '3,5';
|
|
4124
|
-
for (let index = 0; index < 9; index++) {
|
|
4125
|
-
const dot = document.createElement('i');
|
|
4126
|
-
dot.toggleAttribute('data-active', index === 3 || index === 5);
|
|
4127
|
-
indicator.appendChild(dot);
|
|
4128
|
-
}
|
|
4129
|
-
scheduleWorkingIndicators();
|
|
4130
|
-
return indicator;
|
|
4131
|
-
}
|
|
4132
|
-
function resetWorkingIndicators() {
|
|
4133
|
-
clearTimeout(workingIndicatorTimer);
|
|
4134
|
-
workingIndicatorTimer = 0;
|
|
4135
|
-
if (reducedMotion.matches) {
|
|
4136
|
-
for (const indicator of root.querySelectorAll('.comty-working-indicator')) {
|
|
4137
|
-
indicator.dataset.activeDots = '3,5';
|
|
4138
|
-
[...indicator.children].forEach((dot, index) => dot.toggleAttribute('data-active', index === 3 || index === 5));
|
|
4139
|
-
}
|
|
4140
|
-
}
|
|
4141
|
-
if (root.querySelector('.comty-working-indicator')) scheduleWorkingIndicators();
|
|
4142
|
-
}
|
|
4143
|
-
reducedMotion.addEventListener('change', resetWorkingIndicators);
|
|
4144
|
-
document.addEventListener('visibilitychange', resetWorkingIndicators);
|
|
4145
3988
|
const clampToolbar = (value, size, viewport) => Math.max(8, Math.min(value, viewport - size - 8));
|
|
4146
3989
|
function rememberToolbarPosition(left, top) {
|
|
4147
3990
|
const width = toolbar.offsetWidth, height = toolbar.offsetHeight;
|
|
@@ -4254,7 +4097,7 @@ function initComty(options = {}) {
|
|
|
4254
4097
|
|
|
4255
4098
|
function prepareToolbarMotion() {
|
|
4256
4099
|
if (toolbarMotionFrame) return;
|
|
4257
|
-
const nodes = [toolbarSurface, dragHandle, primaryTools, commentTools,
|
|
4100
|
+
const nodes = [toolbarSurface, dragHandle, primaryTools, commentTools, inspectorTools].filter(Boolean);
|
|
4258
4101
|
// Move each group's background with its icons, including when interrupted.
|
|
4259
4102
|
const before = new Map(nodes.filter(node => !node.hidden).map(node => [node, {
|
|
4260
4103
|
rect: node.getBoundingClientRect(), opacity: getComputedStyle(node).opacity,
|
|
@@ -4497,7 +4340,7 @@ function initComty(options = {}) {
|
|
|
4497
4340
|
return;
|
|
4498
4341
|
}
|
|
4499
4342
|
|
|
4500
|
-
if (
|
|
4343
|
+
if (session.edit && mode === "browse") {
|
|
4501
4344
|
closeBubbles();
|
|
4502
4345
|
}
|
|
4503
4346
|
const hadComments = session.comments;
|
|
@@ -4511,7 +4354,6 @@ function initComty(options = {}) {
|
|
|
4511
4354
|
} else {
|
|
4512
4355
|
hideInspector();
|
|
4513
4356
|
}
|
|
4514
|
-
if (session.agent && sidepanelOpen) setSidepanelOpen(false);
|
|
4515
4357
|
syncToolbar();
|
|
4516
4358
|
ensureLiveTracking();
|
|
4517
4359
|
if (renderComments || !hadComments) renderCachedComments();
|
|
@@ -4524,10 +4366,6 @@ function initComty(options = {}) {
|
|
|
4524
4366
|
}
|
|
4525
4367
|
|
|
4526
4368
|
function showAuthPrompt(forbidden = false) {
|
|
4527
|
-
if (localOnly) {
|
|
4528
|
-
showAgentBridgeError("Shared comments need a Comty project key. Use the Agent tool for local tasks without signing in.");
|
|
4529
|
-
return;
|
|
4530
|
-
}
|
|
4531
4369
|
document.querySelector(".comty-auth-backdrop")?.remove();
|
|
4532
4370
|
const opener = document.activeElement;
|
|
4533
4371
|
const backdrop = document.createElement("div");
|
|
@@ -4589,17 +4427,14 @@ function initComty(options = {}) {
|
|
|
4589
4427
|
}
|
|
4590
4428
|
|
|
4591
4429
|
function syncToolbar() {
|
|
4592
|
-
if (commentTools.hidden !==
|
|
4430
|
+
if (commentTools.hidden !== session.inspect || inspectorTools.hidden !== !session.inspect) prepareToolbarMotion();
|
|
4593
4431
|
root.classList.toggle("comty-active", session.comments || session.edit || sidepanelOpen || session.inspect);
|
|
4594
4432
|
browseBtn.setAttribute("aria-pressed", String(!session.edit && !session.inspect));
|
|
4595
4433
|
inspectorBtn.setAttribute("aria-pressed", String(session.inspect));
|
|
4596
|
-
btn.setAttribute("aria-pressed", String(session.edit
|
|
4597
|
-
|
|
4598
|
-
commentTools.hidden = session.inspect || session.agent;
|
|
4599
|
-
if (agentTools) agentTools.hidden = !session.agent;
|
|
4434
|
+
btn.setAttribute("aria-pressed", String(session.edit));
|
|
4435
|
+
commentTools.hidden = session.inspect;
|
|
4600
4436
|
inspectorTools.hidden = !session.inspect;
|
|
4601
4437
|
syncInspectorTools();
|
|
4602
|
-
renderAgentPanel();
|
|
4603
4438
|
}
|
|
4604
4439
|
|
|
4605
4440
|
const inspectionLayer = document.createElement("div");
|
|
@@ -5047,13 +4882,6 @@ function initComty(options = {}) {
|
|
|
5047
4882
|
setSession("edit", { renderComments: true });
|
|
5048
4883
|
}
|
|
5049
4884
|
|
|
5050
|
-
function startAgentSession() {
|
|
5051
|
-
if (!isLocalSite) return;
|
|
5052
|
-
if (session.agent) return;
|
|
5053
|
-
closeBubbles();
|
|
5054
|
-
setSession("agent", { renderComments: true });
|
|
5055
|
-
}
|
|
5056
|
-
|
|
5057
4885
|
function toggleSidepanel() {
|
|
5058
4886
|
if (sidepanelOpen) {
|
|
5059
4887
|
setSidepanelOpen(false);
|
|
@@ -5077,7 +4905,7 @@ function initComty(options = {}) {
|
|
|
5077
4905
|
showAuthPrompt();
|
|
5078
4906
|
return;
|
|
5079
4907
|
}
|
|
5080
|
-
if (session.
|
|
4908
|
+
if (session.inspect || !isSessionActive()) {
|
|
5081
4909
|
startEditSession();
|
|
5082
4910
|
return;
|
|
5083
4911
|
}
|
|
@@ -5852,7 +5680,7 @@ function initComty(options = {}) {
|
|
|
5852
5680
|
|
|
5853
5681
|
const textarea = document.createElement("textarea");
|
|
5854
5682
|
textarea.className = "comty-create-textarea";
|
|
5855
|
-
textarea.placeholder =
|
|
5683
|
+
textarea.placeholder = "Add a comment";
|
|
5856
5684
|
textarea.setAttribute("aria-label", textarea.placeholder);
|
|
5857
5685
|
textarea.rows = 1;
|
|
5858
5686
|
|
|
@@ -5861,7 +5689,7 @@ function initComty(options = {}) {
|
|
|
5861
5689
|
|
|
5862
5690
|
const submitBtn = document.createElement("button");
|
|
5863
5691
|
submitBtn.className = "comty-btn-submit";
|
|
5864
|
-
submitBtn.setAttribute("aria-label",
|
|
5692
|
+
submitBtn.setAttribute("aria-label", "Post comment");
|
|
5865
5693
|
submitBtn.innerHTML = `
|
|
5866
5694
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
5867
5695
|
<path d="M12 19V5M5 12l7-7 7 7"/>
|
|
@@ -5875,22 +5703,18 @@ function initComty(options = {}) {
|
|
|
5875
5703
|
submitBtn.disabled = true;
|
|
5876
5704
|
textarea.disabled = true;
|
|
5877
5705
|
|
|
5878
|
-
if (payload.kind === "agent" && !agent) {
|
|
5879
|
-
showAgentBridgeError(); submitBtn.disabled = false; textarea.disabled = false; return;
|
|
5880
|
-
}
|
|
5881
5706
|
payload.content = content;
|
|
5882
5707
|
textarea.textContent = content;
|
|
5883
5708
|
|
|
5884
5709
|
let post;
|
|
5885
5710
|
try {
|
|
5886
|
-
post = await fetch(
|
|
5711
|
+
post = await fetch(`${apiUrl}/api/comments`, {
|
|
5887
5712
|
method: "POST",
|
|
5888
|
-
headers:
|
|
5889
|
-
body: JSON.stringify(payload
|
|
5713
|
+
headers: getSdkHeaders({ "Content-Type": "application/json" }),
|
|
5714
|
+
body: JSON.stringify(payload),
|
|
5890
5715
|
});
|
|
5891
5716
|
} catch (error) {
|
|
5892
5717
|
console.error("Comty: save failed", error);
|
|
5893
|
-
if (payload.kind === "agent") showAgentBridgeError();
|
|
5894
5718
|
submitBtn.disabled = false;
|
|
5895
5719
|
textarea.disabled = false;
|
|
5896
5720
|
return;
|
|
@@ -5898,15 +5722,14 @@ function initComty(options = {}) {
|
|
|
5898
5722
|
|
|
5899
5723
|
if (!post.ok) {
|
|
5900
5724
|
console.error("Comty: save failed", await post.text());
|
|
5901
|
-
if (payload.kind === "agent") showAgentBridgeError();
|
|
5902
5725
|
submitBtn.disabled = false;
|
|
5903
5726
|
textarea.disabled = false;
|
|
5904
5727
|
return;
|
|
5905
5728
|
}
|
|
5906
5729
|
|
|
5907
5730
|
const data = await post.json();
|
|
5908
|
-
const commentId =
|
|
5909
|
-
const captureNodes = commentId
|
|
5731
|
+
const commentId = data?.id;
|
|
5732
|
+
const captureNodes = commentId
|
|
5910
5733
|
? createCaptureAnnotation(pin, bubble, content)
|
|
5911
5734
|
: [];
|
|
5912
5735
|
bubble.remove();
|
|
@@ -5914,10 +5737,9 @@ function initComty(options = {}) {
|
|
|
5914
5737
|
draftAnchor = null;
|
|
5915
5738
|
hideInspector();
|
|
5916
5739
|
if (commentId) {
|
|
5917
|
-
|
|
5918
|
-
else addLocalComment(String(commentId), payload);
|
|
5740
|
+
addLocalComment(String(commentId), payload);
|
|
5919
5741
|
void loadComments({ force: true });
|
|
5920
|
-
|
|
5742
|
+
void uploadCommentScreenshot(String(commentId), payload, captureNodes);
|
|
5921
5743
|
} else {
|
|
5922
5744
|
void loadComments({ force: true });
|
|
5923
5745
|
}
|
|
@@ -5974,223 +5796,6 @@ function initComty(options = {}) {
|
|
|
5974
5796
|
setTimeout(() => textarea.focus(), 10);
|
|
5975
5797
|
}
|
|
5976
5798
|
|
|
5977
|
-
function agentHeaders() { return { "Content-Type": "application/json", "X-Comty-Token": agent?.token || "" }; }
|
|
5978
|
-
|
|
5979
|
-
function showAgentBridgeError(message = "Start your app with comty dev to use the local agent. Check the terminal if it is already running.") {
|
|
5980
|
-
root.querySelectorAll(".comty-agent-task-toast").forEach((node) => node.remove());
|
|
5981
|
-
const toast = document.createElement("div");
|
|
5982
|
-
toast.className = "comty-auth-toast comty-agent-task-toast";
|
|
5983
|
-
toast.setAttribute("role", "alert");
|
|
5984
|
-
const issue = describeAgentError(message);
|
|
5985
|
-
toast.textContent = issue.title + ". " + issue.description;
|
|
5986
|
-
root.appendChild(toast);
|
|
5987
|
-
setTimeout(() => toast.remove(), 5000);
|
|
5988
|
-
}
|
|
5989
|
-
|
|
5990
|
-
function showAgentTaskToast() {
|
|
5991
|
-
agentPanelOpen = true;
|
|
5992
|
-
agentPanelSignature = "";
|
|
5993
|
-
renderAgentPanel();
|
|
5994
|
-
}
|
|
5995
|
-
|
|
5996
|
-
function describeAgentError(error) {
|
|
5997
|
-
const raw = typeof error === 'string' ? error : JSON.stringify(error, null, 2) || 'Unknown error';
|
|
5998
|
-
let value = error;
|
|
5999
|
-
for (let depth = 0; depth < 8; depth++) {
|
|
6000
|
-
if (typeof value === 'string') {
|
|
6001
|
-
try { value = JSON.parse(value); continue; } catch {}
|
|
6002
|
-
const start = value.indexOf('{'), end = value.lastIndexOf('}');
|
|
6003
|
-
if (start >= 0 && end > start) { try { value = JSON.parse(value.slice(start, end + 1)); continue; } catch {} }
|
|
6004
|
-
break;
|
|
6005
|
-
}
|
|
6006
|
-
if (!value || typeof value !== 'object') break;
|
|
6007
|
-
value = value.error || value.message || value.cause || value.stderr || value;
|
|
6008
|
-
}
|
|
6009
|
-
const message = typeof value === 'string' ? value : '';
|
|
6010
|
-
const source = raw + ' ' + message;
|
|
6011
|
-
const agentName = /codex/i.test(source) ? 'Codex' : /claude/i.test(source) ? 'Claude Code' : /cursor/i.test(source) ? 'Cursor' : 'your coding agent';
|
|
6012
|
-
let title, description;
|
|
6013
|
-
if (/requires a newer version|upgrade.*latest|outdated|unsupported.*version/i.test(source)) {
|
|
6014
|
-
title = 'Agent update required'; description = `Update ${agentName}, restart your local development session, then retry this task.`;
|
|
6015
|
-
} else if (/insufficient_quota|quota exceeded|credit balance|billing|usage limit/i.test(source)) {
|
|
6016
|
-
title = 'Usage limit reached'; description = 'Check your agent account’s usage allowance or billing, then retry when capacity is available.';
|
|
6017
|
-
} else if (/rate.?limit|too many requests|\b429\b/i.test(source)) {
|
|
6018
|
-
title = 'Too many requests'; description = 'The agent is temporarily rate limited. Wait a moment before retrying.';
|
|
6019
|
-
} else if (/unauthorized|unauthenticated|authentication|not logged|sign.?in|log.?in|invalid.api.key|\b401\b/i.test(source)) {
|
|
6020
|
-
title = 'Sign in to your agent'; description = `Open ${agentName} and sign in again, then retry this task.`;
|
|
6021
|
-
} else if (/model.*(?:not found|does not exist|unavailable|not supported)|unsupported model|model_not_found/i.test(source)) {
|
|
6022
|
-
title = 'Model unavailable'; description = 'Choose a model available to your agent account in the local Comty configuration, then restart and retry.';
|
|
6023
|
-
} else if (/disconnected|ECONNREFUSED|ENOTFOUND|network|failed to fetch|development server stopped/i.test(source)) {
|
|
6024
|
-
title = 'Connection lost'; description = 'Check that your local development server and coding agent are running. Reconnect before retrying; your task history is kept.';
|
|
6025
|
-
} else if (/timed? ?out|timeout|exceeded.*minutes/i.test(source)) {
|
|
6026
|
-
title = 'Task timed out'; description = 'Review any changes already made, then retry with a smaller, more specific request.';
|
|
6027
|
-
} else if (/permission|denied|forbidden|\b403\b/i.test(source)) {
|
|
6028
|
-
title = 'Permission needed'; description = 'Check the agent’s access to this project and any pending approval before retrying.';
|
|
6029
|
-
} else if (/ENOENT|command not found|not installed|executable.*not found/i.test(source)) {
|
|
6030
|
-
title = 'Agent not found'; description = `Install or configure ${agentName} in your local development environment, then restart and retry.`;
|
|
6031
|
-
} else if (/completion was not verified/i.test(source)) {
|
|
6032
|
-
title = 'Result needs checking'; description = 'The agent could not confirm completion. Review the changes before retrying.';
|
|
6033
|
-
} else {
|
|
6034
|
-
title = 'Task could not finish';
|
|
6035
|
-
description = message && !/[{}]|\[object Object\]/.test(message) ? message.slice(0, 300) : 'The agent reported an unexpected error. Review the technical details and any changes before retrying.';
|
|
6036
|
-
}
|
|
6037
|
-
return { title, description, raw, message };
|
|
6038
|
-
}
|
|
6039
|
-
|
|
6040
|
-
function renderAgentPanel() {
|
|
6041
|
-
if (!agent) return;
|
|
6042
|
-
let panel = root.querySelector(".comty-agent-panel");
|
|
6043
|
-
if (!panel) {
|
|
6044
|
-
panel = document.createElement("section");
|
|
6045
|
-
panel.className = "comty-agent-panel";
|
|
6046
|
-
panel.setAttribute("aria-label", "Local agent tasks");
|
|
6047
|
-
panel.hidden = true;
|
|
6048
|
-
// Keep the dock above inspection overlays and below the toolbar.
|
|
6049
|
-
root.insertBefore(panel, toolbar);
|
|
6050
|
-
}
|
|
6051
|
-
const open = session.agent && agentPanelOpen;
|
|
6052
|
-
if (open) {
|
|
6053
|
-
if (panel.hidden) {
|
|
6054
|
-
const rect = toolbar.getBoundingClientRect();
|
|
6055
|
-
panel.dataset.side = rect.left + rect.width / 2 < innerWidth / 2 ? "left" : "right";
|
|
6056
|
-
document.documentElement.dataset.comtyAgentSide = panel.dataset.side;
|
|
6057
|
-
panel.dataset.closed = "";
|
|
6058
|
-
panel.hidden = false;
|
|
6059
|
-
panel.getBoundingClientRect();
|
|
6060
|
-
}
|
|
6061
|
-
if (panel.hasAttribute("data-closed")) { agentPanelTransition++; delete panel.dataset.closed; }
|
|
6062
|
-
} else if (!panel.hidden && !panel.hasAttribute("data-closed")) {
|
|
6063
|
-
const transition = ++agentPanelTransition;
|
|
6064
|
-
panel.dataset.closed = "";
|
|
6065
|
-
const finish = () => { if (transition === agentPanelTransition && panel.hasAttribute("data-closed")) panel.hidden = true; };
|
|
6066
|
-
if (reducedMotion.matches) finish();
|
|
6067
|
-
else setTimeout(finish, parseFloat(getComputedStyle(root).getPropertyValue("--comty-motion-duration")));
|
|
6068
|
-
}
|
|
6069
|
-
panel.inert = !open;
|
|
6070
|
-
panel.setAttribute("aria-hidden", String(!open));
|
|
6071
|
-
document.documentElement.classList.toggle("comty-agent-docked", open);
|
|
6072
|
-
agentHistoryBtn?.setAttribute("aria-expanded", String(open));
|
|
6073
|
-
agentHistoryBtn?.setAttribute("aria-pressed", String(open));
|
|
6074
|
-
const signature = JSON.stringify([localTasks, localApprovals, agentConnectionError, agentActionError, agentPanelOpen]);
|
|
6075
|
-
if (signature === agentPanelSignature) return;
|
|
6076
|
-
agentPanelSignature = signature;
|
|
6077
|
-
root.querySelector('.comty-agent-error-popover')?.remove();
|
|
6078
|
-
const expanded = new Set([...panel.querySelectorAll('details[data-detail-key][open]')].map(node => node.dataset.detailKey));
|
|
6079
|
-
const focusKey = panel.contains(document.activeElement) ? document.activeElement.dataset.focusKey : null;
|
|
6080
|
-
const scrollTop = panel.querySelector('.comty-agent-panel-content')?.scrollTop || 0;
|
|
6081
|
-
const node = (tag, className, text) => {
|
|
6082
|
-
const element = document.createElement(tag);
|
|
6083
|
-
if (className) element.className = className;
|
|
6084
|
-
if (text != null) element.textContent = text;
|
|
6085
|
-
return element;
|
|
6086
|
-
};
|
|
6087
|
-
const codeIcon = '<path d="m8 6-6 6 6 6m8-12 6 6-6 6m-3-15-2 18"/>';
|
|
6088
|
-
const brand = () => { const element = node('span', 'comty-agent-brand'); element.innerHTML = icon(codeIcon); element.setAttribute('aria-hidden', 'true'); return element; };
|
|
6089
|
-
panel.replaceChildren();
|
|
6090
|
-
const header = node('header', 'comty-agent-panel-header');
|
|
6091
|
-
const heading = node('div', 'comty-agent-heading');
|
|
6092
|
-
heading.append(node('strong', '', 'Modifications'));
|
|
6093
|
-
const toggle = node('button', 'comty-agent-action comty-agent-close'); toggle.type = 'button';
|
|
6094
|
-
toggle.innerHTML = icon('<path d="m6 6 12 12M6 18 18 6"/>');
|
|
6095
|
-
toggle.setAttribute('aria-label', 'Close local agent sidebar'); toggle.title = 'Close sidebar'; toggle.dataset.focusKey = 'close';
|
|
6096
|
-
toggle.onclick = () => { agentPanelOpen = false; renderAgentPanel(); agentHistoryBtn?.focus({ preventScroll: true }); };
|
|
6097
|
-
header.append(heading, toggle); panel.appendChild(header);
|
|
6098
|
-
const content = node('div', 'comty-agent-panel-content'); panel.appendChild(content);
|
|
6099
|
-
const technicalDetails = (parent, raw, key) => {
|
|
6100
|
-
const details = node('details', 'comty-agent-details'); details.dataset.detailKey = key; details.open = expanded.has(key);
|
|
6101
|
-
const summary = node('summary', '', 'Technical details'); summary.dataset.focusKey = 'details-' + key;
|
|
6102
|
-
details.append(summary, node('pre', '', raw)); parent.appendChild(details);
|
|
6103
|
-
};
|
|
6104
|
-
const errorMessage = (parent, error, key) => {
|
|
6105
|
-
const issue = describeAgentError(error);
|
|
6106
|
-
const message = node('div', 'comty-agent-error');
|
|
6107
|
-
message.append(node('strong', '', issue.title), node('p', '', issue.description));
|
|
6108
|
-
parent.appendChild(message); technicalDetails(parent, issue.raw, key);
|
|
6109
|
-
};
|
|
6110
|
-
if (agentConnectionError || agentActionError) {
|
|
6111
|
-
const banner = node('div', 'comty-agent-item comty-agent-banner'); banner.setAttribute('role', 'alert');
|
|
6112
|
-
errorMessage(banner, agentConnectionError || agentActionError, 'connection'); content.appendChild(banner);
|
|
6113
|
-
}
|
|
6114
|
-
const action = (parent, label, path, input = {}, primary = false) => {
|
|
6115
|
-
const button = node('button', 'comty-agent-action', label); button.type = 'button';
|
|
6116
|
-
const key = path + JSON.stringify(input); button.dataset.focusKey = key;
|
|
6117
|
-
button.disabled = agentPendingActions.has(key);
|
|
6118
|
-
if (primary) button.dataset.primary = '';
|
|
6119
|
-
button.onclick = async () => {
|
|
6120
|
-
if (agentPendingActions.has(key)) return;
|
|
6121
|
-
agentActionError = '';
|
|
6122
|
-
agentPendingActions.add(key); button.disabled = true; button.textContent = 'Please wait…';
|
|
6123
|
-
try {
|
|
6124
|
-
const response = await fetch(`${agentBridgeUrl}/${path}`, { method: 'POST', headers: agentHeaders(), body: JSON.stringify(input) });
|
|
6125
|
-
if (!response.ok) {
|
|
6126
|
-
const body = await response.json().catch(() => null);
|
|
6127
|
-
throw new Error(typeof body?.error === 'string' ? body.error : JSON.stringify(body?.error || { status: response.status, message: 'Request failed' }));
|
|
6128
|
-
}
|
|
6129
|
-
await loadComments({ force: true });
|
|
6130
|
-
} catch (error) { agentActionError = error.message; }
|
|
6131
|
-
finally { agentPendingActions.delete(key); agentPanelSignature = ''; renderAgentPanel(); }
|
|
6132
|
-
};
|
|
6133
|
-
parent.appendChild(button);
|
|
6134
|
-
};
|
|
6135
|
-
for (const approval of localApprovals) {
|
|
6136
|
-
const section = node('div', 'comty-agent-item');
|
|
6137
|
-
section.append(node('h3', '', 'Approval required'));
|
|
6138
|
-
const task = localTasks.find(task => task.id === approval.taskId);
|
|
6139
|
-
if (task) section.appendChild(node('p', '', task.content));
|
|
6140
|
-
section.appendChild(node('p', '', 'Review this operation before allowing the agent to continue.'));
|
|
6141
|
-
const operation = approval.details?.command || approval.details?.file_path || approval.details?.path;
|
|
6142
|
-
if (typeof operation === 'string' || Array.isArray(operation)) section.appendChild(node('pre', '', Array.isArray(operation) ? operation.join(' ') : operation));
|
|
6143
|
-
technicalDetails(section, JSON.stringify(approval.details ?? {}, null, 2), 'approval-' + approval.id);
|
|
6144
|
-
const actions = node('div', 'comty-agent-actions');
|
|
6145
|
-
action(actions, 'Allow once', `approvals/${approval.id}`, { allow: true }, true);
|
|
6146
|
-
action(actions, 'Deny', `approvals/${approval.id}`, { allow: false });
|
|
6147
|
-
section.appendChild(actions); content.appendChild(section);
|
|
6148
|
-
}
|
|
6149
|
-
const list = node('div', 'comty-agent-list'); content.appendChild(list);
|
|
6150
|
-
const hideErrorPopover = () => root.querySelector('.comty-agent-error-popover')?.remove();
|
|
6151
|
-
content.addEventListener('scroll', hideErrorPopover, { passive: true });
|
|
6152
|
-
for (const [index, task] of [...localTasks].reverse().entries()) {
|
|
6153
|
-
const failed = Boolean(task.error) || task.status === 'in_review';
|
|
6154
|
-
const state = failed ? 'error' : task.status === 'done' ? 'success' : task.status === 'cancel' ? 'cancel' : 'working';
|
|
6155
|
-
const row = node('div', 'comty-agent-row'); row.dataset.taskId = task.id;
|
|
6156
|
-
const dot = state === 'working' ? createWorkingIndicator() : node('span', 'comty-agent-dot');
|
|
6157
|
-
dot.dataset.status = state; dot.setAttribute('aria-hidden', 'true');
|
|
6158
|
-
const name = node('span', 'comty-agent-row-name', task.content);
|
|
6159
|
-
row.append(dot, name);
|
|
6160
|
-
if (state === 'working') row.appendChild(node('span', 'comty-agent-row-state', task.status === 'todo' ? 'Starting' : 'Working'));
|
|
6161
|
-
const actions = node('div', 'comty-agent-row-actions');
|
|
6162
|
-
if (['in_review', 'cancel'].includes(task.status)) action(actions, 'Retry', `tasks/${task.id}/retry`);
|
|
6163
|
-
if (['todo', 'in_progress'].includes(task.status)) action(actions, 'Cancel', `tasks/${task.id}/cancel`);
|
|
6164
|
-
if (actions.childElementCount) row.appendChild(actions);
|
|
6165
|
-
row.setAttribute('aria-label', `${task.content}, ${state === 'error' ? 'failed' : state === 'success' ? 'completed' : state === 'cancel' ? 'cancelled' : task.status === 'todo' ? 'starting' : 'working'}`);
|
|
6166
|
-
if (failed) {
|
|
6167
|
-
const tooltipId = `comty-agent-error-${index}`;
|
|
6168
|
-
const showErrorPopover = () => {
|
|
6169
|
-
hideErrorPopover();
|
|
6170
|
-
const issue = describeAgentError(task.error || task.result?.summary || task.progress || 'Completion was not verified');
|
|
6171
|
-
const popover = node('div', 'comty-agent-error-popover'); popover.id = tooltipId; popover.setAttribute('role', 'tooltip');
|
|
6172
|
-
popover.append(node('strong', '', task.content), node('p', '', issue.message || issue.description));
|
|
6173
|
-
root.appendChild(popover);
|
|
6174
|
-
const rowRect = row.getBoundingClientRect();
|
|
6175
|
-
const popoverRect = popover.getBoundingClientRect();
|
|
6176
|
-
const left = panel.dataset.side === 'right' ? rowRect.left - popoverRect.width - 8 : rowRect.right + 8;
|
|
6177
|
-
popover.style.left = `${Math.max(8, Math.min(left, innerWidth - popoverRect.width - 8))}px`;
|
|
6178
|
-
popover.style.top = `${Math.max(8, Math.min(rowRect.top - 4, innerHeight - popoverRect.height - 8))}px`;
|
|
6179
|
-
};
|
|
6180
|
-
row.addEventListener('mouseenter', showErrorPopover);
|
|
6181
|
-
row.addEventListener('mouseleave', hideErrorPopover);
|
|
6182
|
-
}
|
|
6183
|
-
list.appendChild(row);
|
|
6184
|
-
}
|
|
6185
|
-
if (!localTasks.length && !localApprovals.length) {
|
|
6186
|
-
const empty = node('div', 'comty-agent-empty');
|
|
6187
|
-
empty.append(brand(), node('strong', '', localTasks.length ? 'All caught up' : 'What shall we change?'), node('p', '', 'Point at an element on the page and describe the change you want.'));
|
|
6188
|
-
content.appendChild(empty);
|
|
6189
|
-
}
|
|
6190
|
-
content.scrollTop = scrollTop;
|
|
6191
|
-
if (focusKey && open) [...panel.querySelectorAll('[data-focus-key]')].find(element => element.dataset.focusKey === focusKey)?.focus({ preventScroll: true });
|
|
6192
|
-
}
|
|
6193
|
-
|
|
6194
5799
|
function setSidepanelOpen(open) {
|
|
6195
5800
|
sidepanelOpen = open;
|
|
6196
5801
|
sidepanel.classList.toggle("comty-sidepanel-open", sidepanelOpen);
|
|
@@ -6244,7 +5849,6 @@ function initComty(options = {}) {
|
|
|
6244
5849
|
? sidepanelSearch.value.trim().toLowerCase()
|
|
6245
5850
|
: "";
|
|
6246
5851
|
let list = cachedComments.filter((comment) => {
|
|
6247
|
-
if (comment.local_agent || comment.kind === "agent") return false;
|
|
6248
5852
|
if (
|
|
6249
5853
|
search &&
|
|
6250
5854
|
!`${comment.content ?? ""} ${getCommentLabel(comment)}`
|
|
@@ -6430,15 +6034,14 @@ function initComty(options = {}) {
|
|
|
6430
6034
|
createStatusFilters();
|
|
6431
6035
|
|
|
6432
6036
|
async function updateCommentStatus(comment, status) {
|
|
6433
|
-
if (
|
|
6037
|
+
if (!projectId || !comment?.id) return false;
|
|
6434
6038
|
|
|
6435
6039
|
let res;
|
|
6436
6040
|
try {
|
|
6437
|
-
|
|
6438
|
-
res = await fetch(local ? `${agentBridgeUrl}/tasks/${encodeURIComponent(comment.id)}/status` : `${apiUrl}/api/comments/${comment.id}/status`, {
|
|
6041
|
+
res = await fetch(`${apiUrl}/api/comments/${comment.id}/status`, {
|
|
6439
6042
|
method: "POST",
|
|
6440
|
-
headers:
|
|
6441
|
-
body: JSON.stringify(
|
|
6043
|
+
headers: getSdkHeaders({ "Content-Type": "application/json" }),
|
|
6044
|
+
body: JSON.stringify({
|
|
6442
6045
|
projectKey,
|
|
6443
6046
|
host: window.location.host,
|
|
6444
6047
|
status,
|
|
@@ -6455,7 +6058,7 @@ function initComty(options = {}) {
|
|
|
6455
6058
|
}
|
|
6456
6059
|
|
|
6457
6060
|
const data = await res.json();
|
|
6458
|
-
comment.status = getCommentStatus(data.
|
|
6061
|
+
comment.status = getCommentStatus(data.status).value;
|
|
6459
6062
|
return comment.status;
|
|
6460
6063
|
}
|
|
6461
6064
|
|
|
@@ -6643,7 +6246,7 @@ function initComty(options = {}) {
|
|
|
6643
6246
|
const openCommentThread = createCommentThread({
|
|
6644
6247
|
root, apiUrl, projectKey, commentStatuses, selectedStatusFilters, placedPins,
|
|
6645
6248
|
closeBubbles, getCommentStatus, updateCommentStatus, applyStatusDot,
|
|
6646
|
-
renderSidepanelComments, applyStatusFilters,
|
|
6249
|
+
renderSidepanelComments, applyStatusFilters, createThreadItem,
|
|
6647
6250
|
isOwnCommentEntry, updateCommentContent, deleteSdkComment, getCommentId,
|
|
6648
6251
|
updateReplyContent, deleteSdkReply, createCommentAvatar, getSdkHeaders,
|
|
6649
6252
|
showAuthPrompt,
|
|
@@ -6872,12 +6475,12 @@ function initComty(options = {}) {
|
|
|
6872
6475
|
function reconcileComments(comments) {
|
|
6873
6476
|
const previous = new Map(cachedComments.map(comment => [String(comment.id), comment]));
|
|
6874
6477
|
cachedComments = comments
|
|
6875
|
-
.filter(comment => comment.kind !== "agent"
|
|
6478
|
+
.filter(comment => comment.kind !== "agent" && !comment.local_agent)
|
|
6876
6479
|
.map(comment => Object.assign(previous.get(String(comment.id)) || {}, comment));
|
|
6877
6480
|
}
|
|
6878
6481
|
|
|
6879
6482
|
async function loadComments({ force = false } = {}) {
|
|
6880
|
-
if (!projectId
|
|
6483
|
+
if (!projectId) return;
|
|
6881
6484
|
const pagePath = window.location.pathname;
|
|
6882
6485
|
if (!force && cachedPagePath === pagePath) { await renderComments(cachedComments); return; }
|
|
6883
6486
|
if (pendingCommentsLoad) {
|
|
@@ -6885,7 +6488,7 @@ function initComty(options = {}) {
|
|
|
6885
6488
|
if (!force) return;
|
|
6886
6489
|
}
|
|
6887
6490
|
pendingCommentsLoad = (async () => {
|
|
6888
|
-
let comments = cachedPagePath === pagePath ? cachedComments
|
|
6491
|
+
let comments = cachedPagePath === pagePath ? cachedComments : [];
|
|
6889
6492
|
if (projectId) {
|
|
6890
6493
|
try {
|
|
6891
6494
|
const url = new URL(`${apiUrl}/api/comments`);
|
|
@@ -6896,37 +6499,15 @@ function initComty(options = {}) {
|
|
|
6896
6499
|
if (Array.isArray(data.comments)) comments = data.comments;
|
|
6897
6500
|
} catch (error) { console.error("Comty: list comments failed", error); }
|
|
6898
6501
|
}
|
|
6899
|
-
if (agent) {
|
|
6900
|
-
try {
|
|
6901
|
-
const res = await fetch(`${agentBridgeUrl}/tasks`, { headers: agentHeaders(), cache: "no-store" });
|
|
6902
|
-
if (!res.ok) throw new Error("Local companion unavailable");
|
|
6903
|
-
const data = await res.json();
|
|
6904
|
-
if (Array.isArray(data.tasks)) localTasks = data.tasks;
|
|
6905
|
-
if (Array.isArray(data.approvals)) localApprovals = data.approvals;
|
|
6906
|
-
agentConnectionError = "";
|
|
6907
|
-
} catch (error) {
|
|
6908
|
-
agentConnectionError = "Local agent disconnected. Check the development server, then reload this page. Your task history is kept.";
|
|
6909
|
-
console.error("Comty: local tasks failed", error);
|
|
6910
|
-
}
|
|
6911
|
-
comments.push(...localTasks.filter(task => task.page_path === pagePath && !["done", "cancel"].includes(task.status)));
|
|
6912
|
-
renderAgentPanel();
|
|
6913
|
-
}
|
|
6914
6502
|
reconcileComments(comments);
|
|
6915
6503
|
cachedPagePath = pagePath;
|
|
6916
6504
|
renderSidepanelComments();
|
|
6917
6505
|
await renderComments(cachedComments);
|
|
6918
|
-
syncAgentWorkingOutlines();
|
|
6919
6506
|
ensureLiveTracking();
|
|
6920
6507
|
})();
|
|
6921
6508
|
try { await pendingCommentsLoad; } finally { pendingCommentsLoad = null; }
|
|
6922
6509
|
}
|
|
6923
6510
|
|
|
6924
|
-
if (agent) {
|
|
6925
|
-
setInterval(() => {
|
|
6926
|
-
if (!pendingCommentsLoad && document.visibilityState === "visible") void loadComments({ force: true });
|
|
6927
|
-
}, 2000);
|
|
6928
|
-
}
|
|
6929
|
-
|
|
6930
6511
|
function getPinPoint(pin) {
|
|
6931
6512
|
return { x: parseFloat(pin.style.left), y: parseFloat(pin.style.top) };
|
|
6932
6513
|
}
|
|
@@ -6993,50 +6574,16 @@ function initComty(options = {}) {
|
|
|
6993
6574
|
}
|
|
6994
6575
|
}
|
|
6995
6576
|
|
|
6996
|
-
function syncAgentWorkingOutlines() {
|
|
6997
|
-
const working = localTasks.filter(task => task.status === "in_progress" && task.page_path === window.location.pathname);
|
|
6998
|
-
const ids = new Set(working.map(task => String(task.id)));
|
|
6999
|
-
for (const [id, outline] of workingOutlines) {
|
|
7000
|
-
if (ids.has(id)) continue;
|
|
7001
|
-
outline.remove(); workingOutlines.delete(id);
|
|
7002
|
-
}
|
|
7003
|
-
const modal = getTopActiveModal();
|
|
7004
|
-
for (const task of working) {
|
|
7005
|
-
const id = String(task.id);
|
|
7006
|
-
let outline = workingOutlines.get(id);
|
|
7007
|
-
if (!outline) {
|
|
7008
|
-
outline = document.createElement("div");
|
|
7009
|
-
outline.className = "comty-agent-working";
|
|
7010
|
-
outline.setAttribute("aria-label", "Agent working on this element");
|
|
7011
|
-
const badge = document.createElement("span");
|
|
7012
|
-
badge.className = "comty-agent-working-badge";
|
|
7013
|
-
badge.append(createWorkingIndicator(), "Working");
|
|
7014
|
-
outline.appendChild(badge); root.appendChild(outline);
|
|
7015
|
-
workingOutlines.set(id, outline);
|
|
7016
|
-
}
|
|
7017
|
-
const target = resolveCommentElement(task);
|
|
7018
|
-
const point = target && getVisibleAnchorPoint(target, Number(task.rel_x), Number(task.rel_y), modal);
|
|
7019
|
-
outline.hidden = !point;
|
|
7020
|
-
if (!point) continue;
|
|
7021
|
-
const rect = target.getBoundingClientRect();
|
|
7022
|
-
setMeasuredRect(outline, rect);
|
|
7023
|
-
outline.toggleAttribute("data-badge-below", rect.top < 32);
|
|
7024
|
-
}
|
|
7025
|
-
}
|
|
7026
|
-
|
|
7027
6577
|
function onFrame() {
|
|
7028
6578
|
if (motion.enabled) updateMotion();
|
|
7029
6579
|
if (session.comments) syncCommentAnchors();
|
|
7030
|
-
if (session.agent || workingOutlines.size || localTasks.some(task => task.status === "in_progress" && task.page_path === window.location.pathname)) {
|
|
7031
|
-
syncAgentWorkingOutlines();
|
|
7032
|
-
}
|
|
7033
6580
|
if (session.inspect || session.edit || inspectionLayer.childNodes.length) renderInspector();
|
|
7034
6581
|
if (session.inspect && rulersEnabled) renderRulers();
|
|
7035
6582
|
if (session.inspect && rulersEnabled) measurements.render();
|
|
7036
6583
|
}
|
|
7037
6584
|
|
|
7038
6585
|
function ensureLiveTracking() {
|
|
7039
|
-
const active = motion.enabled || session.inspect || session.edit || (session.comments && cachedComments.length > 0)
|
|
6586
|
+
const active = motion.enabled || session.inspect || session.edit || (session.comments && cachedComments.length > 0);
|
|
7040
6587
|
if (!active || document.hidden) {
|
|
7041
6588
|
if (liveFrame) cancelAnimationFrame(liveFrame);
|
|
7042
6589
|
liveFrame = null;
|
|
@@ -7056,14 +6603,13 @@ function initComty(options = {}) {
|
|
|
7056
6603
|
syncOverlayHost();
|
|
7057
6604
|
|
|
7058
6605
|
function renderCachedComments() {
|
|
7059
|
-
if (!session.comments && !session.inspect && !session.edit
|
|
6606
|
+
if (!session.comments && !session.inspect && !session.edit) return;
|
|
7060
6607
|
if (resizeRenderFrame) {
|
|
7061
6608
|
window.cancelAnimationFrame(resizeRenderFrame);
|
|
7062
6609
|
}
|
|
7063
6610
|
resizeRenderFrame = window.requestAnimationFrame(() => {
|
|
7064
6611
|
resizeRenderFrame = null;
|
|
7065
6612
|
syncCommentAnchors();
|
|
7066
|
-
syncAgentWorkingOutlines();
|
|
7067
6613
|
renderInspector();
|
|
7068
6614
|
ensureLiveTracking();
|
|
7069
6615
|
});
|
|
@@ -7244,12 +6790,11 @@ function initComty(options = {}) {
|
|
|
7244
6790
|
const y = e.clientY;
|
|
7245
6791
|
|
|
7246
6792
|
const anchorContext = getAnchorContext(el);
|
|
7247
|
-
if (session.agent && anchorContext) anchorContext.inspectedStyles = getInspectRows(el);
|
|
7248
6793
|
|
|
7249
6794
|
const payload = {
|
|
7250
6795
|
...getDeviceContext(),
|
|
7251
6796
|
projectId,
|
|
7252
|
-
kind:
|
|
6797
|
+
kind: "comment",
|
|
7253
6798
|
host: window.location.host,
|
|
7254
6799
|
pagePath: window.location.pathname,
|
|
7255
6800
|
selector: getSelector(el),
|
|
@@ -7349,7 +6894,6 @@ function initComty(options = {}) {
|
|
|
7349
6894
|
window.addEventListener("blur", () => { measureAlt = false; renderInspector(); });
|
|
7350
6895
|
|
|
7351
6896
|
async function boot() {
|
|
7352
|
-
if (localOnly) { await loadComments(); return; }
|
|
7353
6897
|
const res = await fetch(`${apiUrl}/api/sdk/bootstrap`, {
|
|
7354
6898
|
method: "POST",
|
|
7355
6899
|
headers: getSdkHeaders({ "Content-Type": "application/json" }),
|
|
@@ -7362,7 +6906,6 @@ function initComty(options = {}) {
|
|
|
7362
6906
|
|
|
7363
6907
|
if (!res.ok) {
|
|
7364
6908
|
console.error("Comty: bootstrap failed", await res.text());
|
|
7365
|
-
if (agent) await loadComments();
|
|
7366
6909
|
return;
|
|
7367
6910
|
}
|
|
7368
6911
|
|
|
@@ -7398,26 +6941,12 @@ function initComty(options = {}) {
|
|
|
7398
6941
|
getDistanceSegments, getInspectRows, syncCommentAnchors,
|
|
7399
6942
|
setInspectorMode(enabled) { setSession(enabled ? "inspect" : "off"); },
|
|
7400
6943
|
startEditSession, startBrowseSession, endSession, showInspector,
|
|
7401
|
-
motion, setMotionEnabled, updateMotion,
|
|
7402
|
-
previewAgent(tasks, approvals = [], error = "") {
|
|
7403
|
-
localTasks = tasks;
|
|
7404
|
-
localApprovals = approvals;
|
|
7405
|
-
agentConnectionError = error;
|
|
7406
|
-
startAgentSession();
|
|
7407
|
-
agentPanelOpen = true;
|
|
7408
|
-
agentPanelSignature = "";
|
|
7409
|
-
renderAgentPanel();
|
|
7410
|
-
},
|
|
6944
|
+
motion, setMotionEnabled, updateMotion,
|
|
7411
6945
|
seed(comments) {
|
|
7412
6946
|
reconcileComments(comments);
|
|
7413
6947
|
setSession(session.comments ? session.mode : "browse", { entry: sessionEntry, renderComments: true });
|
|
7414
6948
|
return renderComments(cachedComments, { retry: false });
|
|
7415
6949
|
},
|
|
7416
|
-
seedAgentTasks(tasks) {
|
|
7417
|
-
localTasks = tasks;
|
|
7418
|
-
syncAgentWorkingOutlines();
|
|
7419
|
-
ensureLiveTracking();
|
|
7420
|
-
},
|
|
7421
6950
|
setCanWrite(value) { canWrite = value; },
|
|
7422
6951
|
invalidate() { anchorRevision += 1; },
|
|
7423
6952
|
});
|
|
@@ -7425,7 +6954,6 @@ function initComty(options = {}) {
|
|
|
7425
6954
|
|
|
7426
6955
|
return boot().catch(error => {
|
|
7427
6956
|
console.error("Comty: bootstrap failed", error);
|
|
7428
|
-
if (agent) return loadComments();
|
|
7429
6957
|
});
|
|
7430
6958
|
}
|
|
7431
6959
|
}
|