@comty.io/core 0.1.5 → 0.1.7
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 +82 -2
- package/comty-sdk.js +1350 -140
- package/package.json +17 -6
- package/src/acp.mjs +68 -0
- package/src/agent-process.mjs +89 -0
- package/src/anchors.js +58 -17
- package/src/browser.d.ts +3 -1
- package/src/browser.js +820 -88
- package/src/capture.js +10 -8
- package/src/claude-permission.mjs +37 -0
- package/src/claude.mjs +119 -0
- package/src/codex.mjs +64 -0
- package/src/comments.js +31 -11
- package/src/companion.mjs +201 -0
- package/src/cursor.mjs +49 -0
- package/src/dev.mjs +172 -0
- package/src/gemini.mjs +3 -0
- package/src/grok.mjs +3 -0
- package/src/inspect-markup.js +283 -0
- package/src/measurements.js +3 -3
- package/src/style.js +145 -13
- package/src/vite.d.ts +5 -0
- package/src/vite.mjs +69 -0
package/src/style.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export function getComtyStyle() {
|
|
2
2
|
const toolbarSurface = "#2b2d2f";
|
|
3
3
|
const toolbarMuted = "#b8babb";
|
|
4
|
-
const commentCursor = `<svg xmlns="http://www.w3.org/2000/svg" width="
|
|
4
|
+
const commentCursor = `<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 40 40"><path d="M20 2C30 2 38 10 38 20S30 38 20 38H3V28C2 25 2 23 2 20 2 10 10 2 20 2Z" fill="white" stroke="#d6dbe2"/><circle cx="20" cy="20" r="14" fill="#e6e6e6"/><path d="M20 14v12m-6-6h12" fill="none" stroke="#404040" stroke-width="2.5" stroke-linecap="round"/></svg>`;
|
|
5
5
|
const typographyCursor = `<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><rect x="8" y="8" width="23" height="23" rx="7" fill="${toolbarSurface}" stroke="${toolbarMuted}" stroke-width=".75"/><path d="m14 25 5.5-12L25 25m-8.5-4h6M13 25h4m5 0h4" fill="none" stroke="${toolbarMuted}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="m2 2 2 15 4-5 6-3Z" fill="${toolbarSurface}" stroke="${toolbarMuted}" stroke-width="1.5" stroke-linejoin="round"/></svg>`;
|
|
6
6
|
return `
|
|
7
7
|
#comty-root {
|
|
@@ -11,7 +11,7 @@ export function getComtyStyle() {
|
|
|
11
11
|
--comty-muted: var(--comty-toolbar-muted);
|
|
12
12
|
--comty-accent: #55aaf5;
|
|
13
13
|
--comty-error: #ef7676;
|
|
14
|
-
--comty-outline: var(--comty-
|
|
14
|
+
--comty-outline: var(--comty-accent);
|
|
15
15
|
--comty-comment-focus: var(--comty-toolbar-muted);
|
|
16
16
|
--comty-paper: #fff;
|
|
17
17
|
--comty-ink: #171717;
|
|
@@ -48,6 +48,10 @@ export function getComtyStyle() {
|
|
|
48
48
|
--comty-toolbar-selected: #505457;
|
|
49
49
|
--comty-toolbar-muted: ${toolbarMuted};
|
|
50
50
|
--comty-measure: #ff3b30;
|
|
51
|
+
--comty-markup-yellow: #facc15;
|
|
52
|
+
--comty-markup-green: #22c55e;
|
|
53
|
+
--comty-color-black: #000;
|
|
54
|
+
--comty-color-spectrum: linear-gradient(to right, #f00, #ff0, #0f0, #0ff, #00f, #f0f, #f00);
|
|
51
55
|
--comty-font: "Inter", ui-sans-serif, system-ui, sans-serif;
|
|
52
56
|
--comty-dialog-surface: var(--comty-surface);
|
|
53
57
|
--comty-dialog-ink: var(--comty-foreground);
|
|
@@ -58,6 +62,8 @@ export function getComtyStyle() {
|
|
|
58
62
|
--comty-dialog-width: 32rem;
|
|
59
63
|
--comty-dialog-shadow: 0 1.5rem 4rem rgb(0 0 0 / .16);
|
|
60
64
|
--comty-motion-duration: 220ms;
|
|
65
|
+
--comty-working-dot-size: .25em;
|
|
66
|
+
--comty-working-dot-gap: .125em;
|
|
61
67
|
--comty-ease-out: cubic-bezier(0.23, 1, 0.32, 1);
|
|
62
68
|
--comty-ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
|
|
63
69
|
position: fixed;
|
|
@@ -69,13 +75,80 @@ export function getComtyStyle() {
|
|
|
69
75
|
font-family: var(--comty-font);
|
|
70
76
|
color-scheme: dark;
|
|
71
77
|
}
|
|
72
|
-
|
|
78
|
+
#comty-root :is(button, .comty-comment-avatar) { user-select: none; -webkit-user-select: none; }
|
|
79
|
+
#comty-root .comty-comment-avatar img { -webkit-user-drag: none; }
|
|
80
|
+
#comty-root .comty-pin .comty-comment-avatar { pointer-events: none; }
|
|
81
|
+
#comty-root > .comty-agent-panel { position: fixed; right: 1rem; bottom: 5rem; z-index: 2147483647; width: min(22rem, calc(100vw - 2rem)); max-height: min(32rem, calc(100vh - 6rem)); box-sizing: border-box; display: flex; flex-direction: column; overflow: hidden; pointer-events: auto; border: .0625rem solid var(--comty-border); border-radius: 1rem; 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; transform: translateY(0); opacity: 1; transition: transform var(--comty-motion-duration) var(--comty-ease-out), opacity var(--comty-motion-duration) ease; color-scheme: dark; }
|
|
82
|
+
#comty-root > .comty-agent-panel[data-side="left"] { left: 1rem; right: auto; }
|
|
83
|
+
#comty-root > .comty-agent-panel[data-closed] { transform: translateY(.5rem); opacity: 0; pointer-events: none; }
|
|
84
|
+
#comty-root > .comty-agent-panel[hidden] { display: none; }
|
|
85
|
+
.comty-agent-panel *, .comty-agent-panel *::before { box-sizing: border-box; }
|
|
86
|
+
.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); }
|
|
87
|
+
.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); }
|
|
88
|
+
.comty-agent-brand.comty-agent-avatar { width: 2.375rem; height: 2.375rem; border-radius: 0; background: transparent; }
|
|
89
|
+
.comty-agent-panel svg { display: block; width: 1rem; height: 1rem; flex-shrink: 0; }
|
|
90
|
+
.comty-agent-brand svg { width: 1.25rem; height: 1.25rem; }
|
|
91
|
+
.comty-agent-brand.comty-agent-avatar svg { width: 100%; height: 100%; }
|
|
92
|
+
.comty-agent-answer { display: flex; align-items: flex-start; gap: .5rem; padding: .375rem .5rem .875rem; }
|
|
93
|
+
.comty-agent-answer .comty-agent-brand { width: 1.5rem; height: 1.5rem; }
|
|
94
|
+
.comty-agent-answer p { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; color: var(--comty-foreground); }
|
|
95
|
+
.comty-agent-heading { flex: 1; min-width: 0; }
|
|
96
|
+
.comty-agent-heading strong { display: block; font-weight: 600; font-size: .875rem; }
|
|
97
|
+
.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; }
|
|
98
|
+
.comty-agent-item { padding: .375rem .25rem; overflow-wrap: anywhere; }
|
|
99
|
+
.comty-agent-item + .comty-agent-item { border-top: .0625rem solid var(--comty-hover-surface); }
|
|
100
|
+
.comty-agent-item h3 { margin: 0 0 .25rem; color: var(--comty-foreground); font: 500 .875rem/1.4 ui-sans-serif, system-ui, sans-serif; }
|
|
101
|
+
.comty-agent-list { display: grid; gap: .125rem; }
|
|
102
|
+
.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); }
|
|
103
|
+
.comty-agent-row:hover { background: var(--comty-hover-surface); }
|
|
104
|
+
.comty-agent-dot { width: .4375rem; height: .4375rem; flex: 0 0 auto; border-radius: 50%; background: var(--comty-muted); }
|
|
105
|
+
.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); }
|
|
106
|
+
.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; }
|
|
107
|
+
.comty-working-indicator > i[data-active] { opacity: 1; }
|
|
108
|
+
.comty-agent-dot[data-status="success"] { background: var(--comty-agent-success); }
|
|
109
|
+
.comty-agent-dot[data-status="error"] { background: var(--comty-agent-error); }
|
|
110
|
+
.comty-agent-row-name { min-width: 0; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }
|
|
111
|
+
.comty-agent-row-state { flex: 0 0 auto; color: var(--comty-muted); font-size: .875rem; }
|
|
112
|
+
.comty-agent-row-actions { display: flex; flex-shrink: 0; gap: .25rem; }
|
|
113
|
+
.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; }
|
|
114
|
+
.comty-agent-panel .comty-agent-row-actions .comty-agent-action:hover { color: var(--comty-foreground); background: var(--comty-surface); }
|
|
115
|
+
#comty-root > .comty-agent-task-toast { position: fixed; right: 1rem; bottom: 1rem; z-index: 2147483647; width: min(20rem, calc(100vw - 2rem)); box-sizing: border-box; padding: .75rem 2rem .75rem .875rem; border: .0625rem solid var(--comty-border); border-radius: .75rem; background: var(--comty-surface); box-shadow: var(--comty-floating-shadow); color: var(--comty-foreground); font: .75rem/1.5 ui-sans-serif, system-ui, sans-serif; pointer-events: auto; opacity: 1; transform: translateY(0); transition: opacity 200ms ease, transform 200ms var(--comty-ease-out); animation: comty-agent-toast-in 200ms var(--comty-ease-out); color-scheme: dark; }
|
|
116
|
+
#comty-root > .comty-agent-task-toast[data-toolbar] { right: auto; bottom: auto; }
|
|
117
|
+
#comty-root > .comty-agent-task-toast[data-leaving] { opacity: 0; transform: translateY(.25rem); pointer-events: none; }
|
|
118
|
+
.comty-agent-task-toast strong { display: block; font-size: .8125rem; font-weight: 600; }
|
|
119
|
+
.comty-agent-task-toast p { margin: .25rem 0 0; color: var(--comty-muted); overflow-wrap: anywhere; }
|
|
120
|
+
.comty-agent-task-toast button { position: absolute; top: .5rem; right: .375rem; display: flex; align-items: center; justify-content: center; width: 1.5rem; height: 1.5rem; padding: 0; border: 0; border-radius: .25rem; background: transparent; color: var(--comty-muted); cursor: pointer; }
|
|
121
|
+
.comty-agent-task-toast button:hover { background: var(--comty-hover-surface); color: var(--comty-foreground); }
|
|
122
|
+
.comty-agent-task-toast button:focus-visible { outline: .125rem solid var(--comty-accent); outline-offset: .125rem; }
|
|
123
|
+
.comty-agent-task-toast svg { width: .875rem; height: .875rem; }
|
|
124
|
+
@keyframes comty-agent-toast-in { from { opacity: 0; transform: translateY(.25rem); } to { opacity: 1; transform: translateY(0); } }
|
|
125
|
+
.comty-agent-panel p { margin: .5rem 0 0; font: inherit; color: var(--comty-muted); }
|
|
126
|
+
.comty-agent-error { margin-top: .75rem; }
|
|
127
|
+
.comty-agent-error strong { display: block; font-weight: 500; color: var(--comty-foreground); }
|
|
128
|
+
.comty-agent-error p { margin-top: .25rem; }
|
|
129
|
+
.comty-agent-banner { margin-bottom: 1rem; }
|
|
130
|
+
.comty-agent-banner .comty-agent-error { margin-top: 0; }
|
|
131
|
+
.comty-agent-task-actions { display: flex; justify-content: flex-end; gap: .375rem; padding: .375rem .625rem; border-top: .0625rem solid var(--comty-border); }
|
|
132
|
+
.comty-agent-actions { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .875rem; }
|
|
133
|
+
:is(.comty-agent-panel, .comty-agent-task-thread) .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; }
|
|
134
|
+
.comty-agent-task-thread .comty-agent-action { min-height: 1.5rem; padding: .125rem .5rem; border-radius: .375rem; font-size: .75rem; }
|
|
135
|
+
:is(.comty-agent-panel, .comty-agent-task-thread) .comty-agent-action:hover { background: color-mix(in srgb, var(--comty-foreground) 12%, var(--comty-hover-surface)); }
|
|
136
|
+
:is(.comty-agent-panel, .comty-agent-task-thread) .comty-agent-action[data-primary] { color: var(--comty-paper); background: var(--comty-accent); }
|
|
137
|
+
:is(.comty-agent-panel, .comty-agent-task-thread) .comty-agent-action:disabled { opacity: .5; cursor: wait; }
|
|
138
|
+
.comty-agent-panel .comty-agent-close { width: 1.5rem; min-height: 1.5rem; padding: 0; background: transparent; color: var(--comty-muted); }
|
|
139
|
+
:is(.comty-agent-panel, .comty-agent-task-thread) :is(button, summary):focus-visible { outline: .125rem solid var(--comty-accent); outline-offset: .1875rem; }
|
|
140
|
+
.comty-agent-details { margin-top: .625rem; }
|
|
141
|
+
.comty-agent-panel summary { cursor: pointer; color: var(--comty-muted); font-size: .875rem; }
|
|
142
|
+
.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; }
|
|
143
|
+
.comty-agent-working { position: fixed; z-index: 1; box-sizing: border-box; border: 2px solid var(--comty-accent); border-radius: 0; pointer-events: none; }
|
|
144
|
+
.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; }
|
|
145
|
+
.comty-agent-working[data-badge-below] .comty-agent-working-badge { bottom: auto; top: 100%; border-radius: 0 0 .375rem .375rem; }
|
|
73
146
|
#comty-root { cursor: default; }
|
|
74
147
|
#comty-root::backdrop { background: transparent; pointer-events: none; }
|
|
75
148
|
html.comty-comment-placement,
|
|
76
149
|
html.comty-comment-placement body,
|
|
77
150
|
html.comty-comment-placement body *:not(#comty-root):not(#comty-root *) {
|
|
78
|
-
cursor: url("data:image/svg+xml,${encodeURIComponent(commentCursor)}")
|
|
151
|
+
cursor: url("data:image/svg+xml,${encodeURIComponent(commentCursor)}") 16 16, crosshair !important;
|
|
79
152
|
}
|
|
80
153
|
#comty-root > .comty-sidepanel-open, #comty-root > .comty-pin, #comty-root > .comty-bubble, #comty-root > .comty-create-bubble, #comty-root > .comty-popover, #comty-root > .comty-auth-backdrop, #comty-root > .comty-auth-toast { pointer-events: auto; }
|
|
81
154
|
.comty-toolbar {
|
|
@@ -142,7 +215,7 @@ export function getComtyStyle() {
|
|
|
142
215
|
#comty-root [hidden] { display: none !important; }
|
|
143
216
|
[data-comty-anchor-hidden] { visibility: hidden !important; pointer-events: none !important; }
|
|
144
217
|
@media (prefers-reduced-motion: reduce) {
|
|
145
|
-
.comty-toolbar, .comty-control-button, .comty-sidepanel, .comty-pin, .comty-bubble { transition: none !important; animation: none !important; }
|
|
218
|
+
.comty-toolbar, .comty-control-button, .comty-sidepanel, .comty-pin, .comty-bubble, .comty-agent-panel, .comty-agent-action, .comty-agent-dot, .comty-working-indicator > i, #comty-root > .comty-agent-task-toast { transition: none !important; animation: none !important; }
|
|
146
219
|
}
|
|
147
220
|
|
|
148
221
|
.comty-sidepanel {
|
|
@@ -324,6 +397,16 @@ export function getComtyStyle() {
|
|
|
324
397
|
white-space: nowrap;
|
|
325
398
|
}
|
|
326
399
|
|
|
400
|
+
.comty-anchor-badge {
|
|
401
|
+
display: inline-block;
|
|
402
|
+
margin-top: .375rem;
|
|
403
|
+
padding: .125rem .375rem;
|
|
404
|
+
border: 1px solid var(--comty-border);
|
|
405
|
+
border-radius: 999rem;
|
|
406
|
+
color: var(--comty-muted);
|
|
407
|
+
font: .6875rem/1.4 sans-serif;
|
|
408
|
+
}
|
|
409
|
+
|
|
327
410
|
.comty-pin {
|
|
328
411
|
position: fixed;
|
|
329
412
|
z-index: 2147483645;
|
|
@@ -605,6 +688,8 @@ export function getComtyStyle() {
|
|
|
605
688
|
height: 100%;
|
|
606
689
|
object-fit: cover;
|
|
607
690
|
}
|
|
691
|
+
.comty-comment-avatar.comty-agent-avatar { overflow: visible; border-radius: 0; background: transparent; color: var(--comty-paper); }
|
|
692
|
+
.comty-comment-avatar.comty-agent-avatar svg { display: block; width: 100%; height: 100%; }
|
|
608
693
|
|
|
609
694
|
.comty-pin-avatar {
|
|
610
695
|
width: 24px;
|
|
@@ -719,12 +804,12 @@ export function getComtyStyle() {
|
|
|
719
804
|
}
|
|
720
805
|
|
|
721
806
|
.comty-popover-item.comty-popover-item-destructive {
|
|
722
|
-
color: var(--comty-error);
|
|
807
|
+
color: var(--comty-agent-error);
|
|
723
808
|
}
|
|
724
809
|
|
|
725
810
|
.comty-popover-item.comty-popover-item-destructive:hover,
|
|
726
811
|
.comty-popover-item.comty-popover-item-destructive:focus-visible {
|
|
727
|
-
background: color-mix(in srgb, var(--comty-error) 12%, var(--comty-surface));
|
|
812
|
+
background: color-mix(in srgb, var(--comty-agent-error) 12%, var(--comty-surface));
|
|
728
813
|
outline: none;
|
|
729
814
|
}
|
|
730
815
|
|
|
@@ -853,6 +938,8 @@ export function getComtyStyle() {
|
|
|
853
938
|
}
|
|
854
939
|
|
|
855
940
|
.comty-hover-bubble .comty-thread {
|
|
941
|
+
display: grid;
|
|
942
|
+
gap: 1rem;
|
|
856
943
|
padding: 12px;
|
|
857
944
|
}
|
|
858
945
|
|
|
@@ -1095,19 +1182,23 @@ export function getComtyStyle() {
|
|
|
1095
1182
|
margin: 4px 0;
|
|
1096
1183
|
}
|
|
1097
1184
|
|
|
1098
|
-
html.comty-comments-active .comty-pin {
|
|
1185
|
+
html:is(.comty-comments-active, .comty-inspect-annotations) .comty-pin {
|
|
1099
1186
|
display: grid;
|
|
1100
1187
|
}
|
|
1101
1188
|
|
|
1102
|
-
html.comty-comments-active .comty-pin.comty-filtered-out {
|
|
1189
|
+
html:is(.comty-comments-active, .comty-inspect-annotations) .comty-pin.comty-filtered-out {
|
|
1103
1190
|
display: none;
|
|
1104
1191
|
}
|
|
1105
1192
|
|
|
1106
|
-
html.comty-comments-active .comty-bubble {
|
|
1193
|
+
html:is(.comty-comments-active, .comty-inspect-annotations) .comty-bubble {
|
|
1107
1194
|
display: block;
|
|
1108
1195
|
}
|
|
1109
1196
|
|
|
1110
1197
|
.comty-inspection-layer { position: relative; z-index: 2147483647; pointer-events: none; }
|
|
1198
|
+
.comty-markup-layer, .comty-markup-surface { position: fixed; inset: 0; width: 100%; height: 100%; z-index: 2; pointer-events: none; }
|
|
1199
|
+
.comty-markup-surface { pointer-events: auto; cursor: crosshair; touch-action: none; user-select: none; }
|
|
1200
|
+
.comty-markup-surface[aria-busy="true"] { cursor: progress; }
|
|
1201
|
+
.comty-capture-selection { position: absolute; box-sizing: border-box; border: .0625rem solid var(--comty-accent); box-shadow: 0 0 0 100vmax var(--comty-dialog-backdrop); color: var(--comty-paper); text-shadow: 0 .0625rem .125rem var(--comty-ink); font: .6875rem/1.5 var(--comty-font); padding: .25rem; white-space: nowrap; }
|
|
1111
1202
|
.comty-overlay-tools, .comty-layout-guides, .comty-layout-guide { position: fixed; inset: 0; pointer-events: none; }
|
|
1112
1203
|
.comty-overlay-tools { overflow: hidden; }
|
|
1113
1204
|
.comty-layout-guide { display: grid; box-sizing: border-box; }
|
|
@@ -1133,6 +1224,38 @@ export function getComtyStyle() {
|
|
|
1133
1224
|
.comty-guide-fields label { display: flex; align-items: center; justify-content: space-between; gap: .5rem; }
|
|
1134
1225
|
.comty-tool-panel input, .comty-tool-panel select { min-width: 0; width: 6rem; box-sizing: border-box; border: 0; border-radius: .25rem; padding: .25rem; background: var(--comty-surface); color: var(--comty-foreground); font: inherit; }
|
|
1135
1226
|
.comty-tool-panel input[type="color"] { height: 1.75rem; padding: .125rem; }
|
|
1227
|
+
.comty-tool-panel.comty-markup-panel { width: max-content; padding: .375rem; border-radius: .875rem; background: var(--comty-toolbar-group); }
|
|
1228
|
+
.comty-markup-controls, .comty-markup-options, .comty-markup-strokes, .comty-markup-colors { display: flex; align-items: center; gap: .125rem; }
|
|
1229
|
+
.comty-markup-controls { justify-content: space-between; }
|
|
1230
|
+
.comty-markup-options { margin-top: .375rem; padding-top: .375rem; border-top: .0625rem solid var(--comty-border); }
|
|
1231
|
+
.comty-markup-divider { flex: 0 0 .0625rem; height: 1rem; margin-inline: .25rem; background: var(--comty-border); }
|
|
1232
|
+
.comty-markup-panel button { flex: 0 0 auto; width: 2rem; height: 2rem; padding: 0; color: var(--comty-toolbar-muted); border-radius: .5rem; }
|
|
1233
|
+
.comty-markup-panel button svg { display: block; flex: 0 0 auto; width: 1rem; height: 1rem; }
|
|
1234
|
+
.comty-markup-panel button[aria-pressed="false"] { opacity: 1; }
|
|
1235
|
+
.comty-markup-panel button[aria-pressed="true"] { color: var(--comty-foreground); background: var(--comty-hover-surface); }
|
|
1236
|
+
.comty-markup-panel button:disabled { opacity: .35; cursor: default; }
|
|
1237
|
+
.comty-markup-panel button:disabled:hover { background: transparent; }
|
|
1238
|
+
.comty-markup-panel button:not(:disabled):active { transform: scale(.97); }
|
|
1239
|
+
.comty-markup-strokes button { width: 1.5rem; height: 1.5rem; }
|
|
1240
|
+
.comty-markup-colors button { width: 1.375rem; height: 1.5rem; background: transparent; }
|
|
1241
|
+
.comty-markup-colors button[aria-pressed="true"] { background: transparent; }
|
|
1242
|
+
.comty-markup-swatch { display: block; width: .875rem; height: .875rem; border-radius: 50%; background: var(--markup-swatch); box-shadow: inset 0 0 0 .0625rem color-mix(in srgb, var(--comty-paper) 15%, transparent); }
|
|
1243
|
+
.comty-markup-colors button[aria-pressed="true"] .comty-markup-swatch { outline: .0625rem solid var(--comty-foreground); outline-offset: .125rem; }
|
|
1244
|
+
.comty-markup-panel button.comty-markup-picker { width: 1rem; padding: 0; position: relative; flex: 0 0 1rem; height: 1rem; margin-inline: .25rem; border-radius: 50%; background: conic-gradient(var(--comty-measure), var(--comty-markup-yellow), var(--comty-markup-green), var(--comty-accent), var(--comty-error), var(--comty-measure)); }
|
|
1245
|
+
.comty-markup-picker[data-selected] { outline: .0625rem solid var(--comty-foreground); outline-offset: .125rem; }
|
|
1246
|
+
.comty-markup-picker:focus-visible { outline: .125rem solid var(--comty-accent); outline-offset: .125rem; }
|
|
1247
|
+
.comty-markup-color { display: grid; gap: .625rem; margin-top: .375rem; padding: .625rem .25rem .25rem; border-top: .0625rem solid var(--comty-border); }
|
|
1248
|
+
.comty-markup-color-field { position: relative; height: 8rem; border-radius: .5rem; background: linear-gradient(to top, var(--comty-color-black), transparent), linear-gradient(to right, var(--comty-paper), transparent), var(--markup-hue); touch-action: none; cursor: crosshair; }
|
|
1249
|
+
.comty-markup-color-field:focus-visible { outline: .125rem solid var(--comty-accent); outline-offset: .125rem; }
|
|
1250
|
+
.comty-markup-color-field > span { position: absolute; width: .625rem; height: .625rem; box-sizing: border-box; border: .125rem solid var(--comty-paper); border-radius: 50%; background: var(--markup-color); box-shadow: 0 0 0 .0625rem var(--comty-ink); transform: translate(-50%, -50%); pointer-events: none; }
|
|
1251
|
+
.comty-markup-color input.comty-markup-hue { appearance: none; -webkit-appearance: none; display: block; width: 100%; height: 1rem; margin: 0; padding: 0; border-radius: 1rem; background: var(--comty-color-spectrum); cursor: pointer; }
|
|
1252
|
+
.comty-markup-hue::-webkit-slider-thumb { appearance: none; -webkit-appearance: none; width: .875rem; height: .875rem; box-sizing: border-box; border: .125rem solid var(--comty-paper); border-radius: 50%; background: var(--markup-hue); box-shadow: 0 0 0 .0625rem var(--comty-ink); }
|
|
1253
|
+
.comty-markup-hue::-moz-range-thumb { width: .875rem; height: .875rem; box-sizing: border-box; border: .125rem solid var(--comty-paper); border-radius: 50%; background: var(--markup-hue); box-shadow: 0 0 0 .0625rem var(--comty-ink); }
|
|
1254
|
+
.comty-markup-hex { display: flex; align-items: center; gap: .5rem; padding: .25rem .5rem; border-radius: .5rem; background: var(--comty-surface); color: var(--comty-muted); font: .6875rem/1.5 var(--comty-font); }
|
|
1255
|
+
.comty-markup-color-preview { flex: 0 0 1rem; height: 1rem; border-radius: .25rem; background: var(--markup-color); box-shadow: inset 0 0 0 .0625rem var(--comty-border); }
|
|
1256
|
+
.comty-markup-hex input { flex: 1; width: 0; text-align: right; font-family: ui-monospace, monospace; }
|
|
1257
|
+
.comty-markup-hex input[aria-invalid="true"] { outline: .0625rem solid var(--comty-error); }
|
|
1258
|
+
|
|
1136
1259
|
.comty-ruler { position: fixed; background: var(--comty-surface); pointer-events: auto; touch-action: none; }
|
|
1137
1260
|
.comty-ruler-horizontal { left: 0; top: 0; width: 100vw; height: 1.125rem; border-bottom: .0625rem solid var(--comty-border); cursor: ns-resize; }
|
|
1138
1261
|
.comty-ruler-vertical { left: 0; top: 0; height: 100vh; width: 1.125rem; border-right: .0625rem solid var(--comty-border); cursor: ew-resize; }
|
|
@@ -1207,16 +1330,16 @@ export function getComtyStyle() {
|
|
|
1207
1330
|
.comty-motion-panel button[aria-pressed="true"] { opacity: 1; color: var(--comty-paper); background: var(--comty-hover-surface); }
|
|
1208
1331
|
.comty-motion-panel button[aria-pressed="false"] { opacity: 1; }
|
|
1209
1332
|
.comty-motion-panel [data-motion-status] { margin: .5rem; font-size: .75rem; color: var(--comty-muted); }
|
|
1210
|
-
@media (max-width:
|
|
1333
|
+
@media (max-width: 38rem) { #comty-root { --comty-tool-size: 2rem; --comty-toolbar-padding: .25rem; } .comty-toolbar { right: .5rem; bottom: .5rem; max-width: calc(100vw - 1rem); flex-wrap: wrap; justify-content: center; row-gap: .25rem; } .comty-tool-divider { display: none; } }
|
|
1211
1334
|
|
|
1212
1335
|
.comty-inspection-box {
|
|
1213
1336
|
position: fixed;
|
|
1214
1337
|
box-sizing: border-box;
|
|
1215
1338
|
border: .0625rem solid var(--comty-outline);
|
|
1216
|
-
background:
|
|
1339
|
+
background: transparent;
|
|
1340
|
+
border-radius: 0;
|
|
1217
1341
|
pointer-events: none;
|
|
1218
1342
|
}
|
|
1219
|
-
.comty-inspection-box[data-selected] { background: color-mix(in oklch, var(--comty-outline) 5%, transparent); }
|
|
1220
1343
|
.comty-inspect-spacing { position: fixed; pointer-events: none; background: var(--comty-spacing-color); }
|
|
1221
1344
|
.comty-inspect-margin { --comty-spacing-color: var(--comty-margin-fill); }
|
|
1222
1345
|
.comty-inspect-padding { --comty-spacing-color: var(--comty-padding-fill); }
|
|
@@ -1270,6 +1393,15 @@ export function getComtyStyle() {
|
|
|
1270
1393
|
height: 5.75rem;
|
|
1271
1394
|
border-radius: .75rem;
|
|
1272
1395
|
}
|
|
1396
|
+
.comty-agent-scope { display: inline-flex; align-items: center; gap: .375rem; color: var(--comty-muted); font: .6875rem/1.25 var(--comty-font); white-space: nowrap; cursor: pointer; pointer-events: auto; opacity: 0; visibility: hidden; }
|
|
1397
|
+
.comty-create-expanded .comty-agent-scope { opacity: 1; visibility: visible; }
|
|
1398
|
+
.comty-agent-scope input { position: absolute; width: 1px; height: 1px; margin: 0; opacity: 0; }
|
|
1399
|
+
.comty-agent-scope-track { position: relative; width: 1.5rem; height: .875rem; flex: 0 0 auto; border-radius: 999rem; background: var(--comty-border); transition: background-color 160ms ease; }
|
|
1400
|
+
.comty-agent-scope-track::after { content: ""; position: absolute; top: .125rem; left: .125rem; width: .625rem; height: .625rem; border-radius: 50%; background: var(--comty-paper); transition: transform 160ms ease; }
|
|
1401
|
+
.comty-agent-scope input:checked + .comty-agent-scope-track { background: var(--comty-accent); }
|
|
1402
|
+
.comty-agent-scope input:checked + .comty-agent-scope-track::after { transform: translateX(.625rem); }
|
|
1403
|
+
.comty-agent-scope input:focus-visible + .comty-agent-scope-track { outline: .125rem solid var(--comty-comment-focus); outline-offset: .125rem; }
|
|
1404
|
+
.comty-agent-thread-error { grid-column: 2; margin: .25rem 0 0; color: var(--comty-agent-error); font: .6875rem/1.3 var(--comty-font); }
|
|
1273
1405
|
|
|
1274
1406
|
.comty-create-bubble.comty-create-has-attachment { height: 7.5rem; }
|
|
1275
1407
|
.comty-create-bubble.comty-bubble-left { transform-origin: top right; }
|
package/src/vite.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Plugin } from 'vite';
|
|
2
|
+
import type { ComtyOptions } from './browser.js';
|
|
3
|
+
|
|
4
|
+
/** Development only: leaves production builds untouched. */
|
|
5
|
+
export function comty(options?: Pick<ComtyOptions, 'projectKey' | 'apiUrl'> & { agent?: 'codex' | 'claude' | 'cursor' | 'gemini' | 'grok'; model?: string }): Plugin;
|
package/src/vite.mjs
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { createCompanion, isLoopback } from './companion.mjs';
|
|
3
|
+
|
|
4
|
+
/** Starts the local companion on Vite's own origin, without a second port. */
|
|
5
|
+
export function comty(options = {}) {
|
|
6
|
+
let companion, origin, start;
|
|
7
|
+
return {
|
|
8
|
+
name: 'comty', apply: 'serve',
|
|
9
|
+
configureServer(server) {
|
|
10
|
+
const host = server.config.server.host;
|
|
11
|
+
if (host === true || (typeof host === 'string' && !isLoopback(host))) {
|
|
12
|
+
throw new Error('Comty Agent requires Vite to bind localhost or 127.0.0.1');
|
|
13
|
+
}
|
|
14
|
+
if (!server.httpServer) throw new Error('Comty requires a Vite HTTP server (middleware mode is unsupported)');
|
|
15
|
+
const runtime = new URL('./browser.js', import.meta.url);
|
|
16
|
+
const style = new URL('./style.js', import.meta.url);
|
|
17
|
+
const anchors = new URL('./anchors.js', import.meta.url);
|
|
18
|
+
const capture = new URL('./capture.js', import.meta.url);
|
|
19
|
+
const captureEngine = new URL('./capture-engine.js', import.meta.url);
|
|
20
|
+
const captureResources = new URL('./capture-resources.js', import.meta.url);
|
|
21
|
+
const comments = new URL('./comments.js', import.meta.url);
|
|
22
|
+
const measurements = new URL('./measurements.js', import.meta.url);
|
|
23
|
+
const markup = new URL('./inspect-markup.js', import.meta.url);
|
|
24
|
+
start = new Promise((resolve, reject) => {
|
|
25
|
+
const onError = error => {
|
|
26
|
+
// Vite retries the next port after EADDRINUSE unless strictPort is set.
|
|
27
|
+
if (error.code !== 'EADDRINUSE' || server.config.server.strictPort) reject(error);
|
|
28
|
+
};
|
|
29
|
+
server.httpServer.on('error', onError);
|
|
30
|
+
server.httpServer.once('listening', () => {
|
|
31
|
+
server.httpServer.off('error', onError);
|
|
32
|
+
try {
|
|
33
|
+
const address = server.httpServer.address();
|
|
34
|
+
const hostname = typeof host === 'string' ? host : 'localhost';
|
|
35
|
+
origin = `${server.config.server.https ? 'https' : 'http'}://${hostname}:${address.port}`;
|
|
36
|
+
companion = createCompanion({ cwd: server.config.root, origin, provider: options.agent, model: options.model });
|
|
37
|
+
server.httpServer.once('close', () => { void companion.close().catch(error => server.config.logger.error(`Comty: ${error.message}`)); });
|
|
38
|
+
resolve();
|
|
39
|
+
} catch (error) { reject(error); }
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
start.catch(error => server.config.logger.error(`Comty: ${error.message}`));
|
|
43
|
+
server.middlewares.use(async (request, response, next) => {
|
|
44
|
+
if (!request.url?.startsWith('/__comty/')) return next();
|
|
45
|
+
try {
|
|
46
|
+
await start;
|
|
47
|
+
if (request.headers.host !== new URL(origin).host || (request.headers.origin && request.headers.origin !== origin)) {
|
|
48
|
+
response.writeHead(403); response.end(); return;
|
|
49
|
+
}
|
|
50
|
+
const path = new URL(request.url, origin).pathname;
|
|
51
|
+
if (request.method === 'GET' && ['/__comty/browser.js', '/__comty/style.js', '/__comty/anchors.js', '/__comty/capture.js', '/__comty/capture-engine.js', '/__comty/capture-resources.js', '/__comty/comments.js', '/__comty/measurements.js', '/__comty/inspect-markup.js', '/__comty/start.js'].includes(path)) {
|
|
52
|
+
response.setHeader('Content-Type', 'text/javascript'); response.setHeader('Cache-Control', 'no-store');
|
|
53
|
+
response.setHeader('X-Content-Type-Options', 'nosniff');
|
|
54
|
+
response.end(path.endsWith('/browser.js') ? await readFile(runtime) : path.endsWith('/style.js') ? await readFile(style) : path.endsWith('/anchors.js') ? await readFile(anchors) : path.endsWith('/capture.js') ? await readFile(capture) : path.endsWith('/capture-engine.js') ? await readFile(captureEngine) : path.endsWith('/capture-resources.js') ? await readFile(captureResources) : path.endsWith('/comments.js') ? await readFile(comments) : path.endsWith('/measurements.js') ? await readFile(measurements) : path.endsWith('/inspect-markup.js') ? await readFile(markup) :
|
|
55
|
+
`import { initComty } from '/__comty/browser.js';\ninitComty(${JSON.stringify({ projectKey: options.projectKey, apiUrl: options.apiUrl, agent: { url: `${origin}/__comty`, token: companion.token } })}).catch(console.error);`);
|
|
56
|
+
} else await companion.handle(request, response);
|
|
57
|
+
} catch (error) { next(error); }
|
|
58
|
+
});
|
|
59
|
+
},
|
|
60
|
+
transformIndexHtml: {
|
|
61
|
+
order: 'pre',
|
|
62
|
+
async handler() {
|
|
63
|
+
await start;
|
|
64
|
+
return [{ tag: 'script', attrs: { type: 'module', src: '/__comty/start.js', 'vite-ignore': '' }, injectTo: 'head-prepend' }];
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
async closeBundle() { await companion?.close(); },
|
|
68
|
+
};
|
|
69
|
+
}
|