viveworker 0.5.3 → 0.6.0
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 +178 -27
- package/package.json +7 -2
- package/scripts/a2a-cli.mjs +11 -6
- package/scripts/share-cli.mjs +576 -0
- package/scripts/viveworker-bridge.mjs +305 -14
- package/scripts/viveworker.mjs +771 -130
- package/web/app.css +100 -0
- package/web/app.js +184 -5
- package/web/i18n.js +204 -14
package/web/app.css
CHANGED
|
@@ -611,6 +611,7 @@ code {
|
|
|
611
611
|
|
|
612
612
|
.settings-compose-badge {
|
|
613
613
|
display: inline-flex;
|
|
614
|
+
align-items: center;
|
|
614
615
|
align-self: flex-start;
|
|
615
616
|
flex: 0 0 auto;
|
|
616
617
|
padding: 0.12rem 0.42rem;
|
|
@@ -622,6 +623,16 @@ code {
|
|
|
622
623
|
white-space: nowrap;
|
|
623
624
|
}
|
|
624
625
|
|
|
626
|
+
.settings-compose-badge svg {
|
|
627
|
+
width: 0.85rem;
|
|
628
|
+
height: 0.85rem;
|
|
629
|
+
display: block;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
.settings-compose-badge:has(> svg) {
|
|
633
|
+
padding: 0.18rem 0.3rem;
|
|
634
|
+
}
|
|
635
|
+
|
|
625
636
|
.settings-compose-badge--post {
|
|
626
637
|
background: rgba(67, 160, 255, 0.18);
|
|
627
638
|
color: rgba(121, 196, 255, 0.92);
|
|
@@ -2182,6 +2193,95 @@ code {
|
|
|
2182
2193
|
padding-inline: 0.1rem;
|
|
2183
2194
|
}
|
|
2184
2195
|
|
|
2196
|
+
.ambient-suggestions {
|
|
2197
|
+
display: grid;
|
|
2198
|
+
gap: 0.95rem;
|
|
2199
|
+
}
|
|
2200
|
+
|
|
2201
|
+
.ambient-suggestions__intro > :first-child {
|
|
2202
|
+
margin-top: 0;
|
|
2203
|
+
}
|
|
2204
|
+
|
|
2205
|
+
.ambient-suggestions__intro > :last-child {
|
|
2206
|
+
margin-bottom: 0;
|
|
2207
|
+
}
|
|
2208
|
+
|
|
2209
|
+
.ambient-suggestions__list {
|
|
2210
|
+
display: grid;
|
|
2211
|
+
gap: 0.8rem;
|
|
2212
|
+
}
|
|
2213
|
+
|
|
2214
|
+
.ambient-suggestion-card {
|
|
2215
|
+
display: grid;
|
|
2216
|
+
gap: 0.72rem;
|
|
2217
|
+
padding: 0.95rem 1rem;
|
|
2218
|
+
border-radius: 18px;
|
|
2219
|
+
background: rgba(10, 17, 22, 0.54);
|
|
2220
|
+
border: 1px solid rgba(156, 181, 197, 0.12);
|
|
2221
|
+
}
|
|
2222
|
+
|
|
2223
|
+
.ambient-suggestion-card__header {
|
|
2224
|
+
display: grid;
|
|
2225
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
2226
|
+
gap: 0.7rem;
|
|
2227
|
+
align-items: start;
|
|
2228
|
+
}
|
|
2229
|
+
|
|
2230
|
+
.ambient-suggestion-card__title,
|
|
2231
|
+
.ambient-suggestion-card__description,
|
|
2232
|
+
.ambient-suggestion-card__prompt-label,
|
|
2233
|
+
.ambient-suggestion-card__prompt {
|
|
2234
|
+
margin: 0;
|
|
2235
|
+
}
|
|
2236
|
+
|
|
2237
|
+
.ambient-suggestion-card__title {
|
|
2238
|
+
font-size: 1rem;
|
|
2239
|
+
line-height: 1.4;
|
|
2240
|
+
color: var(--text);
|
|
2241
|
+
overflow-wrap: anywhere;
|
|
2242
|
+
}
|
|
2243
|
+
|
|
2244
|
+
.ambient-suggestion-card__description {
|
|
2245
|
+
color: var(--muted);
|
|
2246
|
+
line-height: 1.55;
|
|
2247
|
+
overflow-wrap: anywhere;
|
|
2248
|
+
}
|
|
2249
|
+
|
|
2250
|
+
.ambient-suggestion-card__copy-button {
|
|
2251
|
+
min-height: 2.35rem;
|
|
2252
|
+
padding: 0.65rem 0.9rem;
|
|
2253
|
+
border-radius: 14px;
|
|
2254
|
+
font-size: 0.84rem;
|
|
2255
|
+
white-space: nowrap;
|
|
2256
|
+
flex: 0 0 auto;
|
|
2257
|
+
}
|
|
2258
|
+
|
|
2259
|
+
.ambient-suggestion-card__prompt-wrap {
|
|
2260
|
+
display: grid;
|
|
2261
|
+
gap: 0.42rem;
|
|
2262
|
+
}
|
|
2263
|
+
|
|
2264
|
+
.ambient-suggestion-card__prompt-label {
|
|
2265
|
+
color: var(--muted);
|
|
2266
|
+
font-size: 0.78rem;
|
|
2267
|
+
font-weight: 700;
|
|
2268
|
+
letter-spacing: 0.01em;
|
|
2269
|
+
}
|
|
2270
|
+
|
|
2271
|
+
.ambient-suggestion-card__prompt {
|
|
2272
|
+
padding: 0.88rem 0.92rem;
|
|
2273
|
+
border-radius: 15px;
|
|
2274
|
+
background: rgba(255, 255, 255, 0.04);
|
|
2275
|
+
border: 1px solid rgba(156, 181, 197, 0.12);
|
|
2276
|
+
color: #eef8ff;
|
|
2277
|
+
font-size: 0.9rem;
|
|
2278
|
+
line-height: 1.55;
|
|
2279
|
+
white-space: pre-wrap;
|
|
2280
|
+
word-break: break-word;
|
|
2281
|
+
overflow-wrap: anywhere;
|
|
2282
|
+
font-family: "SFMono-Regular", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
2283
|
+
}
|
|
2284
|
+
|
|
2185
2285
|
.detail-diff-thread__header {
|
|
2186
2286
|
width: 100%;
|
|
2187
2287
|
display: grid;
|
package/web/app.js
CHANGED
|
@@ -55,6 +55,7 @@ const state = {
|
|
|
55
55
|
a2aTaskExecutorPick: "codex",
|
|
56
56
|
pushNotice: "",
|
|
57
57
|
pushError: "",
|
|
58
|
+
ambientSuggestionCopyState: null,
|
|
58
59
|
deviceNotice: "",
|
|
59
60
|
deviceError: "",
|
|
60
61
|
imageViewer: null,
|
|
@@ -676,6 +677,7 @@ function timelineKindFilterOptions() {
|
|
|
676
677
|
const codexClaudeOptions = [
|
|
677
678
|
allOption,
|
|
678
679
|
{ id: "messages", label: L("timeline.kindFilter.messages"), icon: "timeline" },
|
|
680
|
+
{ id: "suggestions", label: L("timeline.kindFilter.suggestions"), icon: "suggestions" },
|
|
679
681
|
{ id: "files", label: L("timeline.kindFilter.files"), icon: "file-event" },
|
|
680
682
|
{ id: "approvals", label: L("timeline.kindFilter.approvals"), icon: "approval" },
|
|
681
683
|
{ id: "plans", label: L("timeline.kindFilter.plans"), icon: "plan" },
|
|
@@ -710,6 +712,8 @@ function timelineEntryMatchesKindFilter(entry, filterId) {
|
|
|
710
712
|
switch (filterId) {
|
|
711
713
|
case "messages":
|
|
712
714
|
return TIMELINE_MESSAGE_KINDS.has(kind);
|
|
715
|
+
case "suggestions":
|
|
716
|
+
return kind === "ambient_suggestions";
|
|
713
717
|
case "files":
|
|
714
718
|
return kind === "file_event";
|
|
715
719
|
case "approvals":
|
|
@@ -2347,6 +2351,10 @@ function timelineEntryThreadLabel(item, isMessage) {
|
|
|
2347
2351
|
}
|
|
2348
2352
|
|
|
2349
2353
|
function timelineEntryPrimaryText(item, status, { isMessageLike = false, isFileEvent = false } = {}) {
|
|
2354
|
+
if (item?.kind === "ambient_suggestions") {
|
|
2355
|
+
return item.summary || fallbackSummaryForKind(item.kind, status, item.provider);
|
|
2356
|
+
}
|
|
2357
|
+
|
|
2350
2358
|
if (isMessageLike) {
|
|
2351
2359
|
return item.summary || fallbackSummaryForKind(item.kind, status, item.provider);
|
|
2352
2360
|
}
|
|
@@ -2359,6 +2367,10 @@ function timelineEntryPrimaryText(item, status, { isMessageLike = false, isFileE
|
|
|
2359
2367
|
}
|
|
2360
2368
|
|
|
2361
2369
|
function timelineEntrySecondaryText(item, status, primaryText, { isMessageLike = false, isFileEvent = false } = {}) {
|
|
2370
|
+
if (item?.kind === "ambient_suggestions") {
|
|
2371
|
+
return "";
|
|
2372
|
+
}
|
|
2373
|
+
|
|
2362
2374
|
if (isMessageLike) {
|
|
2363
2375
|
return "";
|
|
2364
2376
|
}
|
|
@@ -3607,8 +3619,9 @@ function renderSettingsA2aSharePage(context) {
|
|
|
3607
3619
|
const visible = items.slice(0, visibleCount);
|
|
3608
3620
|
const hasMore = items.length > visibleCount;
|
|
3609
3621
|
const filesList = visible.map((item) => {
|
|
3622
|
+
const passwordLabel = L("settings.a2aShare.passwordProtected");
|
|
3610
3623
|
const lock = item.hasPassword
|
|
3611
|
-
? `<span class="settings-compose-badge settings-compose-badge--reply" title="${escapeHtml(
|
|
3624
|
+
? `<span class="settings-compose-badge settings-compose-badge--reply" role="img" title="${escapeHtml(passwordLabel)}" aria-label="${escapeHtml(passwordLabel)}">${renderIcon("lock")}</span>`
|
|
3612
3625
|
: "";
|
|
3613
3626
|
const label = escapeHtml(item.originalName || item.slug);
|
|
3614
3627
|
const link = item.url
|
|
@@ -3825,8 +3838,9 @@ function renderStandardDetailDesktop(detail) {
|
|
|
3825
3838
|
${renderMoltbookDraftComposer(detail)}
|
|
3826
3839
|
${renderA2ATaskDetail(detail)}
|
|
3827
3840
|
${renderThreadShareDetail(detail)}
|
|
3841
|
+
${renderAmbientSuggestionsSection(detail)}
|
|
3828
3842
|
${
|
|
3829
|
-
detail.kind === "moltbook_draft" || detail.kind === "moltbook_reply" || detail.kind === "a2a_task" || detail.kind === "a2a_task_result" || detail.kind === "thread_share"
|
|
3843
|
+
detail.kind === "moltbook_draft" || detail.kind === "moltbook_reply" || detail.kind === "a2a_task" || detail.kind === "a2a_task_result" || detail.kind === "thread_share" || detail.kind === "ambient_suggestions"
|
|
3830
3844
|
? ""
|
|
3831
3845
|
: plainIntro
|
|
3832
3846
|
? plainIntro
|
|
@@ -3863,8 +3877,9 @@ function renderStandardDetailMobile(detail) {
|
|
|
3863
3877
|
${renderMoltbookDraftComposer(detail, { mobile: true })}
|
|
3864
3878
|
${renderA2ATaskDetail(detail, { mobile: true })}
|
|
3865
3879
|
${renderThreadShareDetail(detail, { mobile: true })}
|
|
3880
|
+
${renderAmbientSuggestionsSection(detail, { mobile: true })}
|
|
3866
3881
|
${
|
|
3867
|
-
detail.kind === "moltbook_draft" || detail.kind === "moltbook_reply" || detail.kind === "a2a_task" || detail.kind === "a2a_task_result" || detail.kind === "thread_share"
|
|
3882
|
+
detail.kind === "moltbook_draft" || detail.kind === "moltbook_reply" || detail.kind === "a2a_task" || detail.kind === "a2a_task_result" || detail.kind === "thread_share" || detail.kind === "ambient_suggestions"
|
|
3868
3883
|
? ""
|
|
3869
3884
|
: plainIntro
|
|
3870
3885
|
? plainIntro
|
|
@@ -3889,6 +3904,65 @@ function renderStandardDetailMobile(detail) {
|
|
|
3889
3904
|
`;
|
|
3890
3905
|
}
|
|
3891
3906
|
|
|
3907
|
+
function renderAmbientSuggestionsSection(detail, options = {}) {
|
|
3908
|
+
if (detail?.kind !== "ambient_suggestions") {
|
|
3909
|
+
return "";
|
|
3910
|
+
}
|
|
3911
|
+
|
|
3912
|
+
const suggestions = normalizeClientAmbientSuggestions(detail?.suggestions);
|
|
3913
|
+
if (suggestions.length === 0) {
|
|
3914
|
+
return `
|
|
3915
|
+
<section class="detail-card detail-card--body ${options.mobile ? "detail-card--mobile" : ""}">
|
|
3916
|
+
<div class="detail-body markdown">${detail.messageHtml || ""}</div>
|
|
3917
|
+
</section>
|
|
3918
|
+
`;
|
|
3919
|
+
}
|
|
3920
|
+
|
|
3921
|
+
return `
|
|
3922
|
+
<section class="detail-card detail-card--body ${options.mobile ? "detail-card--mobile" : ""}">
|
|
3923
|
+
<div class="ambient-suggestions">
|
|
3924
|
+
${detail.messageHtml ? `<div class="ambient-suggestions__intro markdown">${detail.messageHtml}</div>` : ""}
|
|
3925
|
+
<div class="ambient-suggestions__list">
|
|
3926
|
+
${suggestions
|
|
3927
|
+
.map((suggestion, index) => renderAmbientSuggestionCard(detail, suggestion, index))
|
|
3928
|
+
.join("")}
|
|
3929
|
+
</div>
|
|
3930
|
+
</div>
|
|
3931
|
+
</section>
|
|
3932
|
+
`;
|
|
3933
|
+
}
|
|
3934
|
+
|
|
3935
|
+
function renderAmbientSuggestionCard(detail, suggestion, index) {
|
|
3936
|
+
const copyKey = ambientSuggestionCopyKey(detail?.token || "", suggestion?.id || "", index);
|
|
3937
|
+
const copyStatus = state.ambientSuggestionCopyState?.key === copyKey
|
|
3938
|
+
? state.ambientSuggestionCopyState?.status || ""
|
|
3939
|
+
: "";
|
|
3940
|
+
const copyLabel = copyStatus === "success"
|
|
3941
|
+
? L("detail.ambientSuggestions.copyPromptDone")
|
|
3942
|
+
: copyStatus === "error"
|
|
3943
|
+
? L("detail.ambientSuggestions.copyPromptFailed")
|
|
3944
|
+
: L("detail.ambientSuggestions.copyPrompt");
|
|
3945
|
+
return `
|
|
3946
|
+
<article class="ambient-suggestion-card">
|
|
3947
|
+
<div class="ambient-suggestion-card__header">
|
|
3948
|
+
<h3 class="ambient-suggestion-card__title">${escapeHtml(suggestion.title)}</h3>
|
|
3949
|
+
<button
|
|
3950
|
+
type="button"
|
|
3951
|
+
class="secondary ambient-suggestion-card__copy-button"
|
|
3952
|
+
data-copy-ambient-suggestion
|
|
3953
|
+
data-copy-ambient-suggestion-token="${escapeHtml(detail?.token || "")}"
|
|
3954
|
+
data-copy-ambient-suggestion-index="${escapeHtml(String(index))}"
|
|
3955
|
+
>${escapeHtml(copyLabel)}</button>
|
|
3956
|
+
</div>
|
|
3957
|
+
${suggestion.description ? `<p class="ambient-suggestion-card__description">${escapeHtml(suggestion.description)}</p>` : ""}
|
|
3958
|
+
<div class="ambient-suggestion-card__prompt-wrap">
|
|
3959
|
+
<p class="ambient-suggestion-card__prompt-label">${escapeHtml(L("detail.ambientSuggestions.prompt"))}</p>
|
|
3960
|
+
<pre class="ambient-suggestion-card__prompt">${escapeHtml(suggestion.prompt)}</pre>
|
|
3961
|
+
</div>
|
|
3962
|
+
</article>
|
|
3963
|
+
`;
|
|
3964
|
+
}
|
|
3965
|
+
|
|
3892
3966
|
function renderDetailPlainIntro(detail, options = {}) {
|
|
3893
3967
|
if (!["approval", "diff_thread", "file_event"].includes(detail?.kind || "")) {
|
|
3894
3968
|
return "";
|
|
@@ -5290,6 +5364,41 @@ function bindShellInteractions() {
|
|
|
5290
5364
|
});
|
|
5291
5365
|
}
|
|
5292
5366
|
|
|
5367
|
+
for (const button of document.querySelectorAll("[data-copy-ambient-suggestion]")) {
|
|
5368
|
+
button.addEventListener("click", async (event) => {
|
|
5369
|
+
event.preventDefault();
|
|
5370
|
+
event.stopPropagation();
|
|
5371
|
+
const detail = state.currentDetail;
|
|
5372
|
+
if (!detail || detail.kind !== "ambient_suggestions") {
|
|
5373
|
+
return;
|
|
5374
|
+
}
|
|
5375
|
+
if ((button.dataset.copyAmbientSuggestionToken || "") !== (detail.token || "")) {
|
|
5376
|
+
return;
|
|
5377
|
+
}
|
|
5378
|
+
const index = Math.max(0, Number(button.dataset.copyAmbientSuggestionIndex) || 0);
|
|
5379
|
+
const suggestions = normalizeClientAmbientSuggestions(detail.suggestions);
|
|
5380
|
+
const suggestion = suggestions[index];
|
|
5381
|
+
if (!suggestion?.prompt) {
|
|
5382
|
+
return;
|
|
5383
|
+
}
|
|
5384
|
+
const copyKey = ambientSuggestionCopyKey(detail.token || "", suggestion.id || "", index);
|
|
5385
|
+
try {
|
|
5386
|
+
await copyTextToClipboard(suggestion.prompt);
|
|
5387
|
+
state.ambientSuggestionCopyState = { key: copyKey, status: "success" };
|
|
5388
|
+
} catch {
|
|
5389
|
+
state.ambientSuggestionCopyState = { key: copyKey, status: "error" };
|
|
5390
|
+
}
|
|
5391
|
+
await renderShell();
|
|
5392
|
+
window.setTimeout(async () => {
|
|
5393
|
+
if (state.ambientSuggestionCopyState?.key !== copyKey) {
|
|
5394
|
+
return;
|
|
5395
|
+
}
|
|
5396
|
+
state.ambientSuggestionCopyState = null;
|
|
5397
|
+
await renderShell();
|
|
5398
|
+
}, 1600);
|
|
5399
|
+
});
|
|
5400
|
+
}
|
|
5401
|
+
|
|
5293
5402
|
for (const button of document.querySelectorAll("[data-diff-thread-file-toggle]")) {
|
|
5294
5403
|
button.addEventListener("click", async (event) => {
|
|
5295
5404
|
event.preventDefault();
|
|
@@ -6314,7 +6423,7 @@ function tabForItemKind(kind, fallback) {
|
|
|
6314
6423
|
if (kind === "diff_thread") {
|
|
6315
6424
|
return "diff";
|
|
6316
6425
|
}
|
|
6317
|
-
if (kind === "file_event") {
|
|
6426
|
+
if (kind === "file_event" || kind === "ambient_suggestions") {
|
|
6318
6427
|
return "timeline";
|
|
6319
6428
|
}
|
|
6320
6429
|
if (TIMELINE_MESSAGE_KINDS.has(kind)) {
|
|
@@ -6346,6 +6455,8 @@ function kindMeta(kind, item) {
|
|
|
6346
6455
|
return { label: L("common.assistantCommentary"), tone: "plan", icon: "assistant-commentary" };
|
|
6347
6456
|
case "assistant_final":
|
|
6348
6457
|
return { label: L("common.assistantFinal"), tone: "completion", icon: "assistant-final" };
|
|
6458
|
+
case "ambient_suggestions":
|
|
6459
|
+
return { label: L("common.ambientSuggestions"), tone: "neutral", icon: "suggestions" };
|
|
6349
6460
|
case "approval":
|
|
6350
6461
|
return { label: L("common.approval"), tone: "approval", icon: "approval" };
|
|
6351
6462
|
case "plan":
|
|
@@ -6391,6 +6502,9 @@ function itemIntentText(kind, status = "pending", provider) {
|
|
|
6391
6502
|
if (kind === "file_event") {
|
|
6392
6503
|
return L("intent.fileEvent");
|
|
6393
6504
|
}
|
|
6505
|
+
if (kind === "ambient_suggestions") {
|
|
6506
|
+
return L("intent.ambientSuggestions");
|
|
6507
|
+
}
|
|
6394
6508
|
if (kind === "user_message") {
|
|
6395
6509
|
return L("intent.userMessage");
|
|
6396
6510
|
}
|
|
@@ -6425,6 +6539,9 @@ function detailIntentText(detail) {
|
|
|
6425
6539
|
if (detail.kind === "file_event") {
|
|
6426
6540
|
return itemIntentText(detail.kind, "timeline", provider);
|
|
6427
6541
|
}
|
|
6542
|
+
if (detail.kind === "ambient_suggestions") {
|
|
6543
|
+
return itemIntentText(detail.kind, "timeline", provider);
|
|
6544
|
+
}
|
|
6428
6545
|
if (TIMELINE_MESSAGE_KINDS.has(detail.kind)) {
|
|
6429
6546
|
return itemIntentText(detail.kind, "timeline", provider);
|
|
6430
6547
|
}
|
|
@@ -6443,7 +6560,11 @@ function renderDetailTitle(detail) {
|
|
|
6443
6560
|
}
|
|
6444
6561
|
|
|
6445
6562
|
function detailDisplayTitle(detail) {
|
|
6446
|
-
const threadLabel =
|
|
6563
|
+
const threadLabel = sanitizeThreadLabelForDisplay(detail?.threadLabel || "", detail?.threadId || "");
|
|
6564
|
+
if (detail?.kind === "ambient_suggestions") {
|
|
6565
|
+
const ambientTitle = sanitizeThreadLabelForDisplay(detail?.title || "", detail?.threadId || "");
|
|
6566
|
+
return ambientTitle || L("common.ambientSuggestions");
|
|
6567
|
+
}
|
|
6447
6568
|
if (threadLabel) {
|
|
6448
6569
|
return threadLabel;
|
|
6449
6570
|
}
|
|
@@ -6491,6 +6612,8 @@ function fallbackSummaryForKind(kind, status, provider) {
|
|
|
6491
6612
|
return L("summary.diffThread");
|
|
6492
6613
|
case "file_event":
|
|
6493
6614
|
return L("summary.fileEvent", vars);
|
|
6615
|
+
case "ambient_suggestions":
|
|
6616
|
+
return L("summary.ambientSuggestions", { count: 0, firstTitle: "", more: 0 });
|
|
6494
6617
|
case "user_message":
|
|
6495
6618
|
return L("summary.userMessage");
|
|
6496
6619
|
case "assistant_commentary":
|
|
@@ -6707,6 +6830,8 @@ function renderIcon(name) {
|
|
|
6707
6830
|
return `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.85" stroke-linecap="round" stroke-linejoin="round"><path d="M12 6.2v5.6"/><path d="M9.2 9h5.6"/><path d="M6 14.8a6.7 6.7 0 0 0 12 0"/><path d="M8 4.8a7.6 7.6 0 0 1 8 0"/></svg>`;
|
|
6708
6831
|
case "assistant-final":
|
|
6709
6832
|
return `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.85" stroke-linecap="round" stroke-linejoin="round"><path d="M6 6.5h12a1.8 1.8 0 0 1 1.8 1.8v6.1A1.8 1.8 0 0 1 18 16.2h-5.3L9 19.4v-3.2H6a1.8 1.8 0 0 1-1.8-1.8V8.3A1.8 1.8 0 0 1 6 6.5Z"/><path d="m9.2 11.3 1.7 1.7 3.6-3.8"/></svg>`;
|
|
6833
|
+
case "suggestions":
|
|
6834
|
+
return `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.85" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3.8 13 6.7l3 .5-2.2 2.2.5 3-2.3-1.2-2.3 1.2.5-3L8 7.2l3-.5Z"/><path d="M6.2 14.6h11.6"/><path d="M8.4 18.2h7.2"/></svg>`;
|
|
6710
6835
|
case "completed":
|
|
6711
6836
|
return `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="8.5"/><path d="m8.7 12.2 2.1 2.1 4.6-4.8"/></svg>`;
|
|
6712
6837
|
case "settings":
|
|
@@ -6733,6 +6858,8 @@ function renderIcon(name) {
|
|
|
6733
6858
|
return `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M5 7h14"/><path d="M8 12h8"/><path d="M10.5 17h3"/></svg>`;
|
|
6734
6859
|
case "check":
|
|
6735
6860
|
return `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="m6.8 12.5 3.2 3.2 7.2-7.4"/></svg>`;
|
|
6861
|
+
case "lock":
|
|
6862
|
+
return `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><rect x="5.5" y="10.5" width="13" height="9" rx="2"/><path d="M8 10.5V7.5a4 4 0 0 1 8 0v3"/></svg>`;
|
|
6736
6863
|
case "back":
|
|
6737
6864
|
return `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m15 18-6-6 6-6"/></svg>`;
|
|
6738
6865
|
case "chevron-down":
|
|
@@ -6979,6 +7106,58 @@ function normalizeClientFileRefs(fileRefs) {
|
|
|
6979
7106
|
return deduped;
|
|
6980
7107
|
}
|
|
6981
7108
|
|
|
7109
|
+
function normalizeClientAmbientSuggestions(value) {
|
|
7110
|
+
if (!Array.isArray(value)) {
|
|
7111
|
+
return [];
|
|
7112
|
+
}
|
|
7113
|
+
return value
|
|
7114
|
+
.map((entry) => {
|
|
7115
|
+
const title = normalizeClientText(entry?.title);
|
|
7116
|
+
const prompt = normalizeClientText(entry?.prompt);
|
|
7117
|
+
if (!title || !prompt) {
|
|
7118
|
+
return null;
|
|
7119
|
+
}
|
|
7120
|
+
return {
|
|
7121
|
+
id: normalizeClientText(entry?.id),
|
|
7122
|
+
title,
|
|
7123
|
+
prompt,
|
|
7124
|
+
description: normalizeClientText(entry?.description),
|
|
7125
|
+
};
|
|
7126
|
+
})
|
|
7127
|
+
.filter(Boolean);
|
|
7128
|
+
}
|
|
7129
|
+
|
|
7130
|
+
function ambientSuggestionCopyKey(token, suggestionId, index) {
|
|
7131
|
+
return [normalizeClientText(token), normalizeClientText(suggestionId), String(Math.max(0, Number(index) || 0))].join(":");
|
|
7132
|
+
}
|
|
7133
|
+
|
|
7134
|
+
async function copyTextToClipboard(text) {
|
|
7135
|
+
const normalized = String(text ?? "");
|
|
7136
|
+
if (!normalized) {
|
|
7137
|
+
throw new Error("empty");
|
|
7138
|
+
}
|
|
7139
|
+
|
|
7140
|
+
if (navigator.clipboard?.writeText) {
|
|
7141
|
+
await navigator.clipboard.writeText(normalized);
|
|
7142
|
+
return;
|
|
7143
|
+
}
|
|
7144
|
+
|
|
7145
|
+
const textarea = document.createElement("textarea");
|
|
7146
|
+
textarea.value = normalized;
|
|
7147
|
+
textarea.setAttribute("readonly", "true");
|
|
7148
|
+
textarea.style.position = "fixed";
|
|
7149
|
+
textarea.style.opacity = "0";
|
|
7150
|
+
textarea.style.pointerEvents = "none";
|
|
7151
|
+
document.body.appendChild(textarea);
|
|
7152
|
+
textarea.select();
|
|
7153
|
+
textarea.setSelectionRange(0, textarea.value.length);
|
|
7154
|
+
const copied = document.execCommand("copy");
|
|
7155
|
+
document.body.removeChild(textarea);
|
|
7156
|
+
if (!copied) {
|
|
7157
|
+
throw new Error("copy-failed");
|
|
7158
|
+
}
|
|
7159
|
+
}
|
|
7160
|
+
|
|
6982
7161
|
function fileRefLabel(fileRef) {
|
|
6983
7162
|
const normalized = normalizeClientText(fileRef);
|
|
6984
7163
|
if (!normalized) {
|