@oar-sh/oar 0.9.23 → 0.9.25
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/.github/extensions/web-relay/skills/reasoning-stream.mjs +3 -1
- package/CHANGELOG.md +307 -0
- package/README.md +12 -11
- package/bin/oar.js +54 -4
- package/package.json +11 -7
- package/server/agent-sdk-loader.mjs +116 -0
- package/server/agent-sdks/claude/entry.mjs +4 -0
- package/server/agent-sdks/claude/package-lock.json +1438 -0
- package/server/agent-sdks/claude/package.json +13 -0
- package/server/agent-sdks/cursor/entry-sqlite.mjs +2 -0
- package/server/agent-sdks/cursor/entry.mjs +3 -0
- package/server/agent-sdks/cursor/package-lock.json +171 -0
- package/server/agent-sdks/cursor/package.json +11 -0
- package/server/agent-sdks/koffi/entry.cjs +2 -0
- package/server/agent-sdks/koffi/package-lock.json +368 -0
- package/server/agent-sdks/koffi/package.json +10 -0
- package/server/claude-worker/claude-preview-tool.mjs +5 -2
- package/server/claude-worker/claude-remote-relay-tool.mjs +20 -2
- package/server/claude-worker/claude-sdk-adapter.mjs +4 -1
- package/server/claude-worker/sdk-message-normalizer.mjs +29 -1
- package/server/copilot-worker/copilot-sdk-session-process.mjs +13 -8
- package/server/cursor-worker/cursor-sdk-adapter.mjs +5 -3
- package/server/cursor-worker/sdk-message-normalizer.mjs +13 -0
- package/server/db-schema.mjs +19 -0
- package/server/grok-worker/sdk-message-normalizer.mjs +3 -0
- package/server/migrations/0039-media-index.mjs +167 -0
- package/server/migrations/0040-image-session-defaults.mjs +93 -0
- package/server/public/app/agent-sdk-ui.js +349 -0
- package/server/public/app/api-client.js +149 -8
- package/server/public/app/ask-user-view.js +2 -1
- package/server/public/app/attachments-view.js +66 -9
- package/server/public/app/bootstrap.js +289 -94
- package/server/public/app/chat-actions-menu-state.mjs +1 -0
- package/server/public/app/context-media-tab.js +143 -0
- package/server/public/app/conversation-view.js +90 -5
- package/server/public/app/image-composer-ui.js +518 -0
- package/server/public/app/image-turn-placeholder.mjs +233 -0
- package/server/public/app/journal-view.js +12 -2
- package/server/public/app/media-gallery-model.mjs +202 -0
- package/server/public/app/media-gallery-ui.js +524 -0
- package/server/public/app/media-view.js +79 -0
- package/server/public/app/model-refresh-ui.mjs +413 -0
- package/server/public/app/no-conversation-state.mjs +5 -2
- package/server/public/app/openai-image-composer.mjs +492 -0
- package/server/public/app/openai-image-cost-ui.js +426 -0
- package/server/public/app/openai-image-spend.mjs +443 -0
- package/server/public/app/plan-usage-view.mjs +38 -6
- package/server/public/app/provider-readiness.mjs +67 -4
- package/server/public/app/relay-error-ctas.mjs +5 -0
- package/server/public/app/session-history-ui.js +2 -0
- package/server/public/app/settings-modal.js +171 -0
- package/server/public/app/socket-handlers.js +47 -0
- package/server/public/app/tab-strip-fade.mjs +1 -1
- package/server/public/app/viewer-gallery.mjs +23 -1
- package/server/public/index.html +478 -9
- package/server/relay-tools.md +1 -0
- package/server/repositories/image-conversation-repository.mjs +69 -0
- package/server/repositories/media-repository.mjs +305 -0
- package/server/routes/agent-sdk-routes.mjs +73 -0
- package/server/routes/media-routes.mjs +361 -0
- package/server/routes/messages-routes.mjs +1467 -343
- package/server/routes/sessions-routes.mjs +596 -123
- package/server/server-runtime.mjs +414 -81
- package/server/services/about-service.mjs +26 -6
- package/server/services/agent-sdk-launch-gate.mjs +124 -0
- package/server/services/agent-sdk-paths.mjs +307 -0
- package/server/services/agent-sdk-store.mjs +1211 -0
- package/server/services/claude-api-settings-service.mjs +54 -17
- package/server/services/cli-install-service.mjs +3 -2
- package/server/services/copilot-model-discovery-service.mjs +7 -1
- package/server/services/database-file.mjs +23 -5
- package/server/services/deepseek-settings-service.mjs +58 -20
- package/server/services/earlier-database-service.mjs +4 -2
- package/server/services/generated-image-cleanup-service.mjs +2 -1
- package/server/services/generated-image-files.mjs +110 -0
- package/server/services/image-input-paths.mjs +389 -0
- package/server/services/image-operation-service.mjs +6 -2
- package/server/services/media-extract.mjs +653 -0
- package/server/services/media-index-service.mjs +221 -0
- package/server/services/model-refresh-scheduler.mjs +153 -0
- package/server/services/model-variant-catalog-service.mjs +141 -9
- package/server/services/oar-cli-helpers.mjs +72 -9
- package/server/services/oar-state-migration-service.mjs +2 -12
- package/server/services/oar-state-root.mjs +17 -0
- package/server/services/openai-image-preview-turns.mjs +330 -0
- package/server/services/openai-image-spend-service.mjs +516 -0
- package/server/services/openai-image-stream.mjs +170 -0
- package/server/services/plan-usage-openai-image.mjs +148 -0
- package/server/services/provider-model-refresh.mjs +326 -0
- package/server/services/provider-model-state.mjs +395 -0
- package/server/services/relay-singleton-guard.mjs +72 -10
- package/server/services/remote-relay-caller-context.mjs +6 -0
- package/server/services/remote-relay-dispatcher.mjs +386 -22
- package/server/services/remote-relay-registry-service.mjs +3 -1
- package/server/services/session-worker-launch-service.mjs +13 -0
- package/server/services/session-worker-supervisor-service.mjs +19 -1
- package/server/services/session-worker-websocket-service.mjs +15 -0
- package/server/services/token-usage-service.mjs +15 -0
- package/server/services/update-install-service.mjs +2 -2
- package/server/services/worker-launch-note-service.mjs +14 -2
- package/server/services/worker-recycle-service.mjs +145 -11
- package/shared/image-header.mjs +90 -0
- package/shared/model-refresh-schedule.mjs +120 -0
- package/shared/openai-image-options.mjs +299 -0
- package/shared/openai-image-presets.mjs +175 -0
- package/shared/openai-image-previews.mjs +40 -0
- package/shared/openai-image-prices.mjs +291 -0
- package/shared/openai-image-spend.mjs +90 -0
- package/shared/remote-relay-contract.mjs +126 -4
- package/shared/worker-runtime/direct-openai-image.mjs +98 -48
package/server/public/index.html
CHANGED
|
@@ -891,6 +891,8 @@
|
|
|
891
891
|
.inbox-count.is-urgent { background: var(--danger); color: #fff; }
|
|
892
892
|
body.inbox-view-active #input-area { display: none; }
|
|
893
893
|
body.inbox-view-active #pending-question-banner { display: none; }
|
|
894
|
+
body.media-view-active #input-area { display: none; }
|
|
895
|
+
body.media-view-active #pending-question-banner { display: none; }
|
|
894
896
|
.inbox-view { display: grid; gap: calc(7px * var(--ui-scale)); padding: calc(4px * var(--ui-scale)) 0 calc(12px * var(--ui-scale)); }
|
|
895
897
|
.inbox-filter { display: flex; gap: calc(3px * var(--ui-scale)); flex-wrap: wrap; }
|
|
896
898
|
.inbox-filter-option {
|
|
@@ -1673,6 +1675,15 @@
|
|
|
1673
1675
|
background: transparent;
|
|
1674
1676
|
border-color: transparent;
|
|
1675
1677
|
}
|
|
1678
|
+
/* Select Models: new models found that the modal has not shown yet. */
|
|
1679
|
+
.chat-menu-new-dot {
|
|
1680
|
+
width: calc(8px * var(--ui-scale));
|
|
1681
|
+
height: calc(8px * var(--ui-scale));
|
|
1682
|
+
border-radius: 50%;
|
|
1683
|
+
background: var(--accent);
|
|
1684
|
+
flex-shrink: 0;
|
|
1685
|
+
}
|
|
1686
|
+
.chat-menu-new-dot[hidden] { display: none; }
|
|
1676
1687
|
.chat-actions-menu-meta {
|
|
1677
1688
|
display: inline-flex;
|
|
1678
1689
|
align-items: center;
|
|
@@ -1828,6 +1839,31 @@
|
|
|
1828
1839
|
/* Two classes: .settings-help, later in this sheet, would grey it out. */
|
|
1829
1840
|
.settings-help.claude-api-field-error { color: var(--danger); }
|
|
1830
1841
|
.settings-help.claude-api-field-error[hidden] { display: none; }
|
|
1842
|
+
/* OpenAI's image cap and presets (openai-image-cost-ui.js). */
|
|
1843
|
+
.settings-help.openai-image-field-error { color: var(--danger); }
|
|
1844
|
+
.settings-help.openai-image-field-error[hidden] { display: none; }
|
|
1845
|
+
#openai-image-cap-input {
|
|
1846
|
+
background: var(--bg);
|
|
1847
|
+
color: var(--text);
|
|
1848
|
+
border: 1px solid var(--border);
|
|
1849
|
+
border-radius: calc(6px * var(--ui-scale));
|
|
1850
|
+
padding: calc(3px * var(--ui-scale)) calc(7px * var(--ui-scale));
|
|
1851
|
+
outline: none;
|
|
1852
|
+
font-size: var(--fs-meta-md);
|
|
1853
|
+
width: min(calc(140px * var(--ui-scale)), 100%);
|
|
1854
|
+
}
|
|
1855
|
+
#openai-image-cap-input[aria-invalid="true"] { border-color: var(--danger); }
|
|
1856
|
+
.openai-image-cap-row { display: flex; flex-wrap: wrap; gap: calc(6px * var(--ui-scale)); align-items: center; }
|
|
1857
|
+
#openai-image-spend-line[data-state="warning"] { color: var(--warn); }
|
|
1858
|
+
#openai-image-spend-line[data-state="error"] { color: var(--danger); }
|
|
1859
|
+
#openai-image-allow-today-btn[hidden],
|
|
1860
|
+
#openai-image-stop-allowing-btn[hidden] { display: none; }
|
|
1861
|
+
.openai-image-presets-list { list-style: none; margin: 0; padding: 0; width: 100%; display: flex; flex-direction: column; gap: calc(4px * var(--ui-scale)); }
|
|
1862
|
+
.openai-image-preset-row { display: flex; align-items: center; gap: calc(6px * var(--ui-scale)); min-width: 0; }
|
|
1863
|
+
.openai-image-preset-text { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
|
|
1864
|
+
.openai-image-preset-text strong { font-weight: 600; overflow-wrap: anywhere; }
|
|
1865
|
+
.openai-image-preset-details { color: var(--muted); font-size: var(--fs-meta-sm); overflow-wrap: anywhere; }
|
|
1866
|
+
.openai-image-preset-tag { color: var(--muted); font-size: var(--fs-meta-xs); flex: 0 0 auto; }
|
|
1831
1867
|
/* The native spin buttons of a number field follow the theme: light ones
|
|
1832
1868
|
on a dark field read as a glitch. */
|
|
1833
1869
|
:root:not([data-theme="light"]) input[type="number"] { color-scheme: dark; }
|
|
@@ -1954,6 +1990,17 @@
|
|
|
1954
1990
|
.settings-auth-row { gap: calc(5px * var(--ui-scale)); align-items: center; width: 100%; margin-top: calc(4px * var(--ui-scale)); }
|
|
1955
1991
|
.settings-auth-row-wrap { flex-wrap: wrap; row-gap: calc(4px * var(--ui-scale)); }
|
|
1956
1992
|
.settings-radio-stack { display: flex; flex-direction: column; gap: calc(4px * var(--ui-scale)); }
|
|
1993
|
+
/* Models: one "Check <provider>" row per provider, its last check under
|
|
1994
|
+
the name in the help text's colour. */
|
|
1995
|
+
#settings-modal .settings-row.model-refresh-provider-row:has(> input[type="checkbox"]) > label {
|
|
1996
|
+
flex-direction: column; align-items: flex-start; justify-content: center;
|
|
1997
|
+
}
|
|
1998
|
+
.model-refresh-provider-last {
|
|
1999
|
+
color: var(--muted);
|
|
2000
|
+
font-size: var(--fs-meta-sm);
|
|
2001
|
+
font-weight: normal;
|
|
2002
|
+
overflow-wrap: anywhere;
|
|
2003
|
+
}
|
|
1957
2004
|
/* These rows are laid out as flex and hidden from script via `.hidden = true`.
|
|
1958
2005
|
Their `display: flex` lives HERE rather than in a style="" attribute on
|
|
1959
2006
|
purpose: an inline declaration outranks every selector-based rule (short of
|
|
@@ -2479,6 +2526,27 @@
|
|
|
2479
2526
|
width: 100%; max-width: 100%; box-sizing: border-box;
|
|
2480
2527
|
min-width: 0;
|
|
2481
2528
|
}
|
|
2529
|
+
/* A running image turn in the live bubble (image-turn-placeholder.mjs): the
|
|
2530
|
+
image area keeps the size's aspect ratio from the first second, so a
|
|
2531
|
+
partial arriving does not move the transcript. */
|
|
2532
|
+
.image-turn-placeholder { display: flex; flex-direction: column; gap: calc(4px * var(--ui-scale)); margin: calc(2px * var(--ui-scale)) 0 calc(6px * var(--ui-scale)); }
|
|
2533
|
+
.thinking-bubble:has(> .image-turn-placeholder) > .dots { display: none; }
|
|
2534
|
+
.image-turn-placeholder-meta { display: flex; align-items: baseline; flex-wrap: wrap; gap: calc(6px * var(--ui-scale)); color: var(--text); font-size: var(--fs-meta-md); }
|
|
2535
|
+
.image-turn-placeholder-timer { font-variant-numeric: tabular-nums; color: var(--muted); }
|
|
2536
|
+
.image-turn-placeholder-retry { color: var(--muted); font-style: italic; }
|
|
2537
|
+
.image-turn-placeholder-retry[hidden] { display: none; }
|
|
2538
|
+
.image-turn-placeholder-details { color: var(--muted); font-size: var(--fs-meta-sm); overflow-wrap: anywhere; }
|
|
2539
|
+
.image-turn-placeholder-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: calc(6px * var(--ui-scale)); width: min(100%, calc(360px * var(--ui-scale))); }
|
|
2540
|
+
.image-turn-placeholder-grid:not([data-count="1"]) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
2541
|
+
.image-turn-placeholder-tile {
|
|
2542
|
+
position: relative; overflow: hidden; border-radius: calc(10px * var(--ui-scale));
|
|
2543
|
+
border: 1px solid var(--border); background: var(--bg3);
|
|
2544
|
+
animation: image-turn-pulse 1.8s ease-in-out infinite;
|
|
2545
|
+
}
|
|
2546
|
+
.image-turn-placeholder-tile.has-preview { animation: none; }
|
|
2547
|
+
.image-turn-placeholder-tile img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
|
|
2548
|
+
@keyframes image-turn-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.55; } }
|
|
2549
|
+
@media (prefers-reduced-motion: reduce) { .image-turn-placeholder-tile { animation: none; } }
|
|
2482
2550
|
/* Sticky inside the scroller: Stop on the live bubble is the only way to
|
|
2483
2551
|
stop a turn, and a long turn must stay stoppable without scrolling back
|
|
2484
2552
|
up. It sticks within its own bubble only, so it never rides over the
|
|
@@ -3295,6 +3363,190 @@
|
|
|
3295
3363
|
border-color: var(--accent);
|
|
3296
3364
|
color: var(--accent);
|
|
3297
3365
|
}
|
|
3366
|
+
/* The media gallery (media-gallery-ui.js): the 🧠 Media tab and the global
|
|
3367
|
+
Media view. A messenger's shared media: square tiles under month
|
|
3368
|
+
headers, 3 columns on a phone; a Files tab as a list. */
|
|
3369
|
+
.media-gallery {
|
|
3370
|
+
display: flex;
|
|
3371
|
+
flex-direction: column;
|
|
3372
|
+
gap: calc(8px * var(--ui-scale));
|
|
3373
|
+
min-width: 0;
|
|
3374
|
+
}
|
|
3375
|
+
.media-gallery[data-scope="global"] {
|
|
3376
|
+
padding: calc(12px * var(--ui-scale));
|
|
3377
|
+
max-width: calc(1100px * var(--ui-scale));
|
|
3378
|
+
margin: 0 auto;
|
|
3379
|
+
width: 100%;
|
|
3380
|
+
box-sizing: border-box;
|
|
3381
|
+
}
|
|
3382
|
+
.media-gallery-tabs,
|
|
3383
|
+
.media-gallery-chips,
|
|
3384
|
+
.context-tab-strip {
|
|
3385
|
+
display: flex;
|
|
3386
|
+
align-items: center;
|
|
3387
|
+
gap: calc(4px * var(--ui-scale));
|
|
3388
|
+
flex-wrap: wrap;
|
|
3389
|
+
}
|
|
3390
|
+
.media-gallery-tab,
|
|
3391
|
+
.media-gallery-chip,
|
|
3392
|
+
.context-tab {
|
|
3393
|
+
flex: 0 0 auto;
|
|
3394
|
+
border: 1px solid var(--border);
|
|
3395
|
+
background: var(--bg2);
|
|
3396
|
+
color: var(--text);
|
|
3397
|
+
border-radius: calc(8px * var(--ui-scale));
|
|
3398
|
+
height: calc(28px * var(--ui-scale));
|
|
3399
|
+
padding: 0 calc(10px * var(--ui-scale));
|
|
3400
|
+
font-size: var(--fs-meta-md);
|
|
3401
|
+
white-space: nowrap;
|
|
3402
|
+
cursor: pointer;
|
|
3403
|
+
}
|
|
3404
|
+
.media-gallery-tab[aria-selected="true"],
|
|
3405
|
+
.media-gallery-chip[aria-pressed="true"],
|
|
3406
|
+
.context-tab[aria-selected="true"] {
|
|
3407
|
+
border-color: var(--accent);
|
|
3408
|
+
color: var(--accent);
|
|
3409
|
+
}
|
|
3410
|
+
.context-tab-count {
|
|
3411
|
+
margin-left: calc(4px * var(--ui-scale));
|
|
3412
|
+
color: var(--muted);
|
|
3413
|
+
}
|
|
3414
|
+
.context-tab-strip {
|
|
3415
|
+
margin-bottom: calc(10px * var(--ui-scale));
|
|
3416
|
+
}
|
|
3417
|
+
.media-gallery-filters {
|
|
3418
|
+
display: flex;
|
|
3419
|
+
flex-wrap: wrap;
|
|
3420
|
+
align-items: center;
|
|
3421
|
+
gap: calc(6px * var(--ui-scale));
|
|
3422
|
+
}
|
|
3423
|
+
.media-gallery-select,
|
|
3424
|
+
.media-gallery-search {
|
|
3425
|
+
height: calc(28px * var(--ui-scale));
|
|
3426
|
+
border: 1px solid var(--border);
|
|
3427
|
+
border-radius: calc(8px * var(--ui-scale));
|
|
3428
|
+
background: var(--bg2);
|
|
3429
|
+
color: var(--text);
|
|
3430
|
+
font-size: var(--fs-meta-md);
|
|
3431
|
+
padding: 0 calc(6px * var(--ui-scale));
|
|
3432
|
+
max-width: 100%;
|
|
3433
|
+
}
|
|
3434
|
+
.media-gallery-select[data-media-filter="session"] {
|
|
3435
|
+
max-width: calc(260px * var(--ui-scale));
|
|
3436
|
+
}
|
|
3437
|
+
.media-gallery-search {
|
|
3438
|
+
flex: 1 1 calc(180px * var(--ui-scale));
|
|
3439
|
+
min-width: 0;
|
|
3440
|
+
}
|
|
3441
|
+
.media-gallery-toggle {
|
|
3442
|
+
display: inline-flex;
|
|
3443
|
+
align-items: center;
|
|
3444
|
+
gap: calc(4px * var(--ui-scale));
|
|
3445
|
+
font-size: var(--fs-meta-md);
|
|
3446
|
+
color: var(--muted);
|
|
3447
|
+
}
|
|
3448
|
+
.media-gallery-status p {
|
|
3449
|
+
margin: calc(4px * var(--ui-scale)) 0;
|
|
3450
|
+
color: var(--muted);
|
|
3451
|
+
font-size: var(--fs-meta-md);
|
|
3452
|
+
}
|
|
3453
|
+
.media-month-label {
|
|
3454
|
+
position: sticky;
|
|
3455
|
+
top: 0;
|
|
3456
|
+
z-index: 1;
|
|
3457
|
+
margin: 0;
|
|
3458
|
+
padding: calc(6px * var(--ui-scale)) calc(2px * var(--ui-scale));
|
|
3459
|
+
background: var(--bg);
|
|
3460
|
+
color: var(--muted);
|
|
3461
|
+
font-size: var(--fs-meta-md);
|
|
3462
|
+
font-weight: 600;
|
|
3463
|
+
}
|
|
3464
|
+
.media-grid {
|
|
3465
|
+
display: grid;
|
|
3466
|
+
grid-template-columns: repeat(auto-fill, minmax(calc(140px * var(--ui-scale)), 1fr));
|
|
3467
|
+
gap: 2px;
|
|
3468
|
+
}
|
|
3469
|
+
.media-tile {
|
|
3470
|
+
position: relative;
|
|
3471
|
+
aspect-ratio: 1;
|
|
3472
|
+
padding: 0;
|
|
3473
|
+
border: 0;
|
|
3474
|
+
background: var(--bg3);
|
|
3475
|
+
overflow: hidden;
|
|
3476
|
+
cursor: pointer;
|
|
3477
|
+
content-visibility: auto;
|
|
3478
|
+
contain-intrinsic-size: calc(140px * var(--ui-scale));
|
|
3479
|
+
}
|
|
3480
|
+
.media-tile img,
|
|
3481
|
+
.media-tile video {
|
|
3482
|
+
width: 100%;
|
|
3483
|
+
height: 100%;
|
|
3484
|
+
object-fit: cover;
|
|
3485
|
+
display: block;
|
|
3486
|
+
pointer-events: none;
|
|
3487
|
+
}
|
|
3488
|
+
.media-tile:focus-visible {
|
|
3489
|
+
outline: 2px solid var(--accent);
|
|
3490
|
+
outline-offset: -2px;
|
|
3491
|
+
}
|
|
3492
|
+
.media-tile-archived img,
|
|
3493
|
+
.media-tile-archived video {
|
|
3494
|
+
opacity: 0.6;
|
|
3495
|
+
}
|
|
3496
|
+
.media-tile-badge,
|
|
3497
|
+
.media-tile-play {
|
|
3498
|
+
position: absolute;
|
|
3499
|
+
font-size: calc(12px * var(--ui-scale));
|
|
3500
|
+
line-height: 1;
|
|
3501
|
+
padding: calc(3px * var(--ui-scale)) calc(4px * var(--ui-scale));
|
|
3502
|
+
border-radius: calc(6px * var(--ui-scale));
|
|
3503
|
+
background: rgba(0, 0, 0, 0.55);
|
|
3504
|
+
color: #fff;
|
|
3505
|
+
}
|
|
3506
|
+
.media-tile-badge { right: calc(4px * var(--ui-scale)); bottom: calc(4px * var(--ui-scale)); }
|
|
3507
|
+
.media-tile-play { left: calc(4px * var(--ui-scale)); bottom: calc(4px * var(--ui-scale)); }
|
|
3508
|
+
.media-file-list {
|
|
3509
|
+
display: flex;
|
|
3510
|
+
flex-direction: column;
|
|
3511
|
+
}
|
|
3512
|
+
.media-file-row {
|
|
3513
|
+
display: flex;
|
|
3514
|
+
align-items: center;
|
|
3515
|
+
gap: calc(10px * var(--ui-scale));
|
|
3516
|
+
padding: calc(8px * var(--ui-scale)) calc(4px * var(--ui-scale));
|
|
3517
|
+
border: 0;
|
|
3518
|
+
border-bottom: 1px solid var(--border);
|
|
3519
|
+
background: transparent;
|
|
3520
|
+
color: var(--text);
|
|
3521
|
+
text-align: left;
|
|
3522
|
+
cursor: pointer;
|
|
3523
|
+
}
|
|
3524
|
+
.media-file-icon { font-size: calc(22px * var(--ui-scale)); }
|
|
3525
|
+
.media-file-text { display: flex; flex-direction: column; min-width: 0; }
|
|
3526
|
+
.media-file-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
3527
|
+
.media-file-meta { color: var(--muted); font-size: var(--fs-meta-md); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
3528
|
+
.media-gallery-more {
|
|
3529
|
+
align-self: center;
|
|
3530
|
+
border: 1px solid var(--border);
|
|
3531
|
+
background: var(--bg2);
|
|
3532
|
+
color: var(--text);
|
|
3533
|
+
border-radius: calc(8px * var(--ui-scale));
|
|
3534
|
+
padding: calc(4px * var(--ui-scale)) calc(12px * var(--ui-scale));
|
|
3535
|
+
cursor: pointer;
|
|
3536
|
+
}
|
|
3537
|
+
.media-gallery-sentinel { height: 1px; }
|
|
3538
|
+
@media (max-width: 680px) {
|
|
3539
|
+
.media-grid { grid-template-columns: repeat(3, 1fr); }
|
|
3540
|
+
.media-gallery[data-scope="global"] { padding: calc(8px * var(--ui-scale)) calc(4px * var(--ui-scale)); }
|
|
3541
|
+
.media-gallery-select[data-media-filter="session"] { max-width: 100%; flex: 1 1 100%; }
|
|
3542
|
+
.media-gallery-tabs,
|
|
3543
|
+
.media-gallery-chips,
|
|
3544
|
+
.context-tab-strip {
|
|
3545
|
+
flex-wrap: nowrap;
|
|
3546
|
+
overflow-x: auto;
|
|
3547
|
+
scrollbar-width: none;
|
|
3548
|
+
}
|
|
3549
|
+
}
|
|
3298
3550
|
.plan-usage-card-titles {
|
|
3299
3551
|
display: flex;
|
|
3300
3552
|
flex-direction: column;
|
|
@@ -3391,6 +3643,17 @@
|
|
|
3391
3643
|
background: var(--bg3);
|
|
3392
3644
|
}
|
|
3393
3645
|
.plan-usage-meter-secondary .plan-usage-bar { height: calc(6px * var(--ui-scale)); border-radius: calc(3px * var(--ui-scale)); }
|
|
3646
|
+
/* A bar with a mark on it (the OpenAI images card's 80 % warning line). */
|
|
3647
|
+
.plan-usage-bar-marked { position: relative; }
|
|
3648
|
+
.plan-usage-bar-mark {
|
|
3649
|
+
position: absolute;
|
|
3650
|
+
top: 0;
|
|
3651
|
+
bottom: 0;
|
|
3652
|
+
width: 2px;
|
|
3653
|
+
margin-left: -1px;
|
|
3654
|
+
background: var(--text);
|
|
3655
|
+
opacity: 0.55;
|
|
3656
|
+
}
|
|
3394
3657
|
.plan-usage-bar-fill {
|
|
3395
3658
|
display: block;
|
|
3396
3659
|
height: 100%;
|
|
@@ -4274,7 +4537,12 @@
|
|
|
4274
4537
|
#mode-select,
|
|
4275
4538
|
#model-select,
|
|
4276
4539
|
#reasoning-effort-select,
|
|
4277
|
-
#context-tier-select
|
|
4540
|
+
#context-tier-select,
|
|
4541
|
+
#image-size-custom-input,
|
|
4542
|
+
#image-preset-select,
|
|
4543
|
+
#image-count-select,
|
|
4544
|
+
#image-format-select,
|
|
4545
|
+
#image-background-select {
|
|
4278
4546
|
background: var(--bg3); border: 1px solid var(--border); color: var(--text);
|
|
4279
4547
|
border-radius: calc(8px * var(--ui-scale)); height: calc(30px * var(--ui-scale)); padding: 0 calc(8px * var(--ui-scale)); font-size: var(--fs-core-control);
|
|
4280
4548
|
width: 100%; min-width: 0; outline: none;
|
|
@@ -4282,7 +4550,64 @@
|
|
|
4282
4550
|
#mode-select:focus,
|
|
4283
4551
|
#model-select:focus,
|
|
4284
4552
|
#reasoning-effort-select:focus,
|
|
4285
|
-
#context-tier-select:focus
|
|
4553
|
+
#context-tier-select:focus,
|
|
4554
|
+
#image-size-custom-input:focus,
|
|
4555
|
+
#image-preset-select:focus,
|
|
4556
|
+
#image-count-select:focus,
|
|
4557
|
+
#image-format-select:focus,
|
|
4558
|
+
#image-background-select:focus { border-color: var(--accent); }
|
|
4559
|
+
/* An image model's custom W×H under the Size select, and Count, Format and
|
|
4560
|
+
Background side by side: three narrow selects fit the 340px popover and
|
|
4561
|
+
the phone's bottom sheet alike. */
|
|
4562
|
+
#image-size-custom-input { box-sizing: border-box; font-family: var(--mono, monospace); }
|
|
4563
|
+
/* No iOS focus zoom (see #conv-filter-input). */
|
|
4564
|
+
@media (pointer: coarse), (max-width: 680px) {
|
|
4565
|
+
#image-size-custom-input { font-size: max(16px, 1rem); }
|
|
4566
|
+
}
|
|
4567
|
+
#image-size-custom-input[aria-invalid="true"] { border-color: var(--danger); }
|
|
4568
|
+
.image-size-custom-row { display: flex; flex-direction: column; gap: calc(3px * var(--ui-scale)); margin-top: calc(4px * var(--ui-scale)); }
|
|
4569
|
+
.image-size-custom-row[hidden],
|
|
4570
|
+
.image-size-custom-error[hidden],
|
|
4571
|
+
.composer-settings-image-row[hidden],
|
|
4572
|
+
.composer-settings-image-row .composer-settings-field[hidden] { display: none; }
|
|
4573
|
+
.image-size-custom-error { color: var(--danger); font-size: var(--fs-meta-sm); overflow-wrap: anywhere; }
|
|
4574
|
+
.composer-settings-image-row { display: flex; gap: calc(6px * var(--ui-scale)); min-width: 0; }
|
|
4575
|
+
/* An image model's Preset select with "Save as preset…" beside it, and
|
|
4576
|
+
what a pick skipped or a save answered under them. */
|
|
4577
|
+
#image-preset-field[hidden],
|
|
4578
|
+
.image-preset-note[hidden] { display: none; }
|
|
4579
|
+
.image-preset-row { display: flex; gap: calc(6px * var(--ui-scale)); min-width: 0; align-items: center; }
|
|
4580
|
+
.image-preset-row #image-preset-select { flex: 1 1 auto; }
|
|
4581
|
+
.image-preset-save-btn {
|
|
4582
|
+
flex: 0 0 auto;
|
|
4583
|
+
background: var(--bg3); border: 1px solid var(--border); color: var(--text);
|
|
4584
|
+
border-radius: calc(8px * var(--ui-scale)); height: calc(30px * var(--ui-scale)); padding: 0 calc(8px * var(--ui-scale));
|
|
4585
|
+
font-size: var(--fs-core-control); cursor: pointer; white-space: nowrap;
|
|
4586
|
+
}
|
|
4587
|
+
.image-preset-save-btn:hover { border-color: var(--accent); }
|
|
4588
|
+
.image-preset-save-btn:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
4589
|
+
.image-preset-note { color: var(--muted); font-size: var(--fs-meta-sm); overflow-wrap: anywhere; }
|
|
4590
|
+
.image-preset-note[data-state="error"] { color: var(--danger); }
|
|
4591
|
+
/* Today's OpenAI image spend in an image chat: amber from the warning
|
|
4592
|
+
mark, red once the cap stops image turns. */
|
|
4593
|
+
#openai-image-spend-banner {
|
|
4594
|
+
background: var(--bg2);
|
|
4595
|
+
background: color-mix(in srgb, var(--warn) 14%, var(--bg2));
|
|
4596
|
+
border: 1px solid var(--warn);
|
|
4597
|
+
color: var(--warn);
|
|
4598
|
+
border-radius: calc(8px * var(--ui-scale));
|
|
4599
|
+
padding: calc(3px * var(--ui-scale)) calc(8px * var(--ui-scale));
|
|
4600
|
+
margin-bottom: calc(5px * var(--ui-scale));
|
|
4601
|
+
font-size: var(--fs-meta-sm);
|
|
4602
|
+
overflow-wrap: anywhere;
|
|
4603
|
+
}
|
|
4604
|
+
#openai-image-spend-banner[hidden] { display: none; }
|
|
4605
|
+
#openai-image-spend-banner[data-kind="reached"] {
|
|
4606
|
+
background: color-mix(in srgb, var(--danger) 14%, var(--bg2));
|
|
4607
|
+
border-color: var(--danger);
|
|
4608
|
+
color: var(--danger);
|
|
4609
|
+
}
|
|
4610
|
+
.composer-settings-image-row .composer-settings-field { flex: 1 1 0; }
|
|
4286
4611
|
/* Live background-task fold above the composer. The summary reuses the
|
|
4287
4612
|
relay tones so its running state matches the sidebar dot / burger bars. */
|
|
4288
4613
|
#background-tasks-panel {
|
|
@@ -5933,6 +6258,42 @@
|
|
|
5933
6258
|
border-color: var(--warn, #f7c873);
|
|
5934
6259
|
color: var(--warn, #f7c873);
|
|
5935
6260
|
}
|
|
6261
|
+
.model-reasoning-chip-new {
|
|
6262
|
+
border-color: var(--accent);
|
|
6263
|
+
color: var(--accent);
|
|
6264
|
+
}
|
|
6265
|
+
/* "Turn new models on automatically" at the top of a provider tab. */
|
|
6266
|
+
.model-auto-enable-row {
|
|
6267
|
+
display: flex;
|
|
6268
|
+
align-items: center;
|
|
6269
|
+
gap: calc(5px * var(--ui-scale));
|
|
6270
|
+
padding: calc(4px * var(--ui-scale)) calc(7px * var(--ui-scale));
|
|
6271
|
+
border: 1px solid var(--border);
|
|
6272
|
+
border-radius: calc(10px * var(--ui-scale));
|
|
6273
|
+
background: var(--bg3);
|
|
6274
|
+
font-size: 0.84rem;
|
|
6275
|
+
min-height: calc(30px * var(--ui-scale));
|
|
6276
|
+
cursor: pointer;
|
|
6277
|
+
}
|
|
6278
|
+
.model-auto-enable-toggle {
|
|
6279
|
+
width: calc(18px * var(--ui-scale));
|
|
6280
|
+
height: calc(18px * var(--ui-scale));
|
|
6281
|
+
flex-shrink: 0;
|
|
6282
|
+
accent-color: var(--accent);
|
|
6283
|
+
}
|
|
6284
|
+
.model-auto-enable-copy {
|
|
6285
|
+
display: flex;
|
|
6286
|
+
flex-direction: column;
|
|
6287
|
+
gap: calc(2px * var(--ui-scale));
|
|
6288
|
+
min-width: 0;
|
|
6289
|
+
}
|
|
6290
|
+
.model-auto-enable-title {
|
|
6291
|
+
font-weight: 600;
|
|
6292
|
+
}
|
|
6293
|
+
.model-auto-enable-help {
|
|
6294
|
+
color: var(--muted);
|
|
6295
|
+
font-size: 0.78rem;
|
|
6296
|
+
}
|
|
5936
6297
|
.model-variant-list {
|
|
5937
6298
|
display: flex;
|
|
5938
6299
|
flex-direction: column;
|
|
@@ -6734,6 +7095,10 @@
|
|
|
6734
7095
|
/* CWD-pick mode is launched from the summary / new-chat modals (z 12050),
|
|
6735
7096
|
so the browser must stack above them; #relay-toast stays on top at 12600. */
|
|
6736
7097
|
#repo-browser-modal.cwd-pick-mode { z-index: 12400; }
|
|
7098
|
+
/* A picture opened from the 🧠 Media tab shows above that modal, and its
|
|
7099
|
+
annotate editor above the picture. */
|
|
7100
|
+
#file-preview-modal.over-summary { z-index: 12200; }
|
|
7101
|
+
body:has(#file-preview-modal.over-summary) #image-annotate-modal { z-index: 12300; }
|
|
6737
7102
|
.repo-cwd-pick-bar {
|
|
6738
7103
|
display: flex;
|
|
6739
7104
|
align-items: center;
|
|
@@ -7816,19 +8181,22 @@
|
|
|
7816
8181
|
width is the scroll padding too, so a tab scrolled into view (the
|
|
7817
8182
|
selected one, a focused one) clears it. */
|
|
7818
8183
|
.settings-tab-strip,
|
|
7819
|
-
.plan-usage-tab-strip
|
|
8184
|
+
.plan-usage-tab-strip,
|
|
8185
|
+
.context-tab-strip,
|
|
8186
|
+
.media-gallery-tabs,
|
|
8187
|
+
.media-gallery-chips {
|
|
7820
8188
|
--tab-strip-fade: calc(44px * var(--ui-scale));
|
|
7821
8189
|
scroll-padding-inline: var(--tab-strip-fade);
|
|
7822
8190
|
}
|
|
7823
|
-
:is(.settings-tab-strip, .plan-usage-tab-strip)[data-fade="right"] {
|
|
8191
|
+
:is(.settings-tab-strip, .plan-usage-tab-strip, .context-tab-strip, .media-gallery-tabs, .media-gallery-chips)[data-fade="right"] {
|
|
7824
8192
|
-webkit-mask-image: linear-gradient(to left, transparent, #000 var(--tab-strip-fade));
|
|
7825
8193
|
mask-image: linear-gradient(to left, transparent, #000 var(--tab-strip-fade));
|
|
7826
8194
|
}
|
|
7827
|
-
:is(.settings-tab-strip, .plan-usage-tab-strip)[data-fade="both"] {
|
|
8195
|
+
:is(.settings-tab-strip, .plan-usage-tab-strip, .context-tab-strip, .media-gallery-tabs, .media-gallery-chips)[data-fade="both"] {
|
|
7828
8196
|
-webkit-mask-image: linear-gradient(to right, transparent, #000 var(--tab-strip-fade), #000 calc(100% - var(--tab-strip-fade)), transparent);
|
|
7829
8197
|
mask-image: linear-gradient(to right, transparent, #000 var(--tab-strip-fade), #000 calc(100% - var(--tab-strip-fade)), transparent);
|
|
7830
8198
|
}
|
|
7831
|
-
:is(.settings-tab-strip, .plan-usage-tab-strip)[data-fade="left"] {
|
|
8199
|
+
:is(.settings-tab-strip, .plan-usage-tab-strip, .context-tab-strip, .media-gallery-tabs, .media-gallery-chips)[data-fade="left"] {
|
|
7832
8200
|
-webkit-mask-image: linear-gradient(to right, transparent, #000 var(--tab-strip-fade));
|
|
7833
8201
|
mask-image: linear-gradient(to right, transparent, #000 var(--tab-strip-fade));
|
|
7834
8202
|
}
|
|
@@ -7907,7 +8275,8 @@
|
|
|
7907
8275
|
min-height: calc(32px * var(--ui-scale));
|
|
7908
8276
|
padding: calc(5px * var(--ui-scale)) calc(4px * var(--ui-scale));
|
|
7909
8277
|
}
|
|
7910
|
-
.model-variant-checkbox
|
|
8278
|
+
.model-variant-checkbox,
|
|
8279
|
+
.model-auto-enable-toggle {
|
|
7911
8280
|
width: calc(22px * var(--ui-scale));
|
|
7912
8281
|
height: calc(22px * var(--ui-scale));
|
|
7913
8282
|
}
|
|
@@ -8209,6 +8578,7 @@
|
|
|
8209
8578
|
<button id="chat-menu-watching" class="chat-actions-menu-item chat-menu-meta-chip" type="button" role="menuitem" hidden>👁 Watching sessions…</button>
|
|
8210
8579
|
<button id="chat-menu-schedules" class="chat-actions-menu-item chat-menu-meta-chip" type="button" role="menuitem" hidden>⏰ Schedules…</button>
|
|
8211
8580
|
<button id="chat-menu-origin" class="chat-actions-menu-item chat-menu-meta-chip" type="button" role="menuitem" hidden>↗ Started by an agent</button>
|
|
8581
|
+
<div id="chat-menu-image-cost" class="chat-actions-menu-meta" data-testid="chat-menu-image-cost" hidden><span id="chat-menu-image-cost-value" class="chat-actions-menu-meta-secondary">OpenAI images: …</span></div>
|
|
8212
8582
|
<button id="chat-menu-edit-title" class="chat-actions-menu-item" type="button" role="menuitem">✍️ Edit conversation title</button>
|
|
8213
8583
|
<button id="chat-menu-questions" class="chat-actions-menu-item chat-menu-twin" type="button" role="menuitem" hidden>📓 Questions</button>
|
|
8214
8584
|
<button id="chat-menu-pins" class="chat-actions-menu-item chat-menu-twin" type="button" role="menuitem" hidden>📍 Pinned messages</button>
|
|
@@ -8226,11 +8596,12 @@
|
|
|
8226
8596
|
<button id="chat-menu-group" class="chat-actions-menu-item" type="button" role="menuitem">🧩 Session group…</button>
|
|
8227
8597
|
<button id="chat-menu-refresh-history" class="chat-actions-menu-item" type="button" role="menuitem" hidden disabled aria-hidden="true" tabindex="-1" style="display:none">🔄️ Refresh history</button>
|
|
8228
8598
|
<button id="chat-menu-inspect-tmux" class="chat-actions-menu-item" type="button" role="menuitem">🖥️ Inspect tmux console</button>
|
|
8229
|
-
<button id="chat-menu-select-models" class="chat-actions-menu-item" type="button" role="menuitem">🤗 Select Models
|
|
8599
|
+
<button id="chat-menu-select-models" class="chat-actions-menu-item" type="button" role="menuitem">🤗 Select Models<span id="chat-menu-select-models-dot" class="chat-menu-new-dot" aria-hidden="true" hidden></span></button>
|
|
8230
8600
|
<button id="chat-menu-change-cwd" class="chat-actions-menu-item" type="button" role="menuitem">🗂️ Change CWD</button>
|
|
8231
8601
|
<button id="chat-menu-git-changes" class="chat-actions-menu-item" type="button" role="menuitem">🌿 Git changes</button>
|
|
8232
8602
|
<button id="chat-menu-open-cloud-session" class="chat-actions-menu-item" type="button" role="menuitem" hidden>☁️ Open on claude.ai</button>
|
|
8233
|
-
<button id="chat-menu-
|
|
8603
|
+
<button id="chat-menu-media" class="chat-actions-menu-item" type="button" role="menuitem">🖼️ Media</button>
|
|
8604
|
+
<button id="chat-menu-settings" class="chat-actions-menu-item" type="button" role="menuitem">⚙️ Settings</button>
|
|
8234
8605
|
<button id="chat-menu-about" class="chat-actions-menu-item" type="button" role="menuitem">ℹ️ About OAR</button>
|
|
8235
8606
|
<button id="chat-menu-restart-relay" class="chat-actions-menu-item" type="button" role="menuitem">🌄 Restart web relay</button>
|
|
8236
8607
|
<button id="chat-menu-suspend-host" class="chat-actions-menu-item" type="button" role="menuitem" onclick="openSuspendHostConfirmation()">💤 Suspend host</button>
|
|
@@ -8253,6 +8624,8 @@
|
|
|
8253
8624
|
<div id="share-preview-banner" role="note"></div>
|
|
8254
8625
|
<div id="model-banner"></div>
|
|
8255
8626
|
<div id="usage-limit-banner" role="status" aria-live="polite" hidden></div>
|
|
8627
|
+
<!-- Today's OpenAI image spend in an image chat (openai-image-cost-ui.js). -->
|
|
8628
|
+
<div id="openai-image-spend-banner" data-testid="openai-image-spend-banner" role="status" aria-live="polite" hidden></div>
|
|
8256
8629
|
<div id="cloud-session-line" aria-label="Cloud session" hidden></div>
|
|
8257
8630
|
<div id="model-metadata-blocker" aria-live="polite">
|
|
8258
8631
|
<span id="model-metadata-blocker-text">Model metadata is unavailable. Refresh to choose a model and reasoning effort.</span>
|
|
@@ -8310,6 +8683,15 @@
|
|
|
8310
8683
|
</select>
|
|
8311
8684
|
<div id="model-lock-note" hidden></div>
|
|
8312
8685
|
</div>
|
|
8686
|
+
<!-- An image model's presets (image-composer-ui.js). -->
|
|
8687
|
+
<div id="image-preset-field" class="composer-settings-field" data-field="image-preset" hidden>
|
|
8688
|
+
<label class="composer-settings-field-label" for="image-preset-select">Preset</label>
|
|
8689
|
+
<div class="image-preset-row">
|
|
8690
|
+
<select id="image-preset-select" data-testid="image-preset-select" title="Image preset"><option value="">None</option></select>
|
|
8691
|
+
<button id="image-preset-save-btn" data-testid="image-preset-save" type="button" class="image-preset-save-btn" title="Save the image options below as a preset">Save as preset…</button>
|
|
8692
|
+
</div>
|
|
8693
|
+
<div id="image-preset-note" data-testid="image-preset-note" class="image-preset-note" role="status" aria-live="polite" hidden></div>
|
|
8694
|
+
</div>
|
|
8313
8695
|
<div class="composer-settings-field" data-field="effort">
|
|
8314
8696
|
<label id="reasoning-effort-label" class="composer-settings-field-label" for="reasoning-effort-select">Effort</label>
|
|
8315
8697
|
<select id="reasoning-effort-select" title="Reasoning effort" disabled>
|
|
@@ -8321,6 +8703,26 @@
|
|
|
8321
8703
|
<select id="context-tier-select" title="Context window">
|
|
8322
8704
|
<option value="default">—</option>
|
|
8323
8705
|
</select>
|
|
8706
|
+
<!-- An image model's "Custom…" size (image-composer-ui.js). -->
|
|
8707
|
+
<div id="image-size-custom-row" class="image-size-custom-row" hidden>
|
|
8708
|
+
<input id="image-size-custom-input" type="text" inputmode="text" autocomplete="off" autocapitalize="off" spellcheck="false" placeholder="2048x1152" aria-label="Custom image size, width x height" aria-describedby="image-size-custom-error">
|
|
8709
|
+
<div id="image-size-custom-error" class="image-size-custom-error" role="alert" hidden></div>
|
|
8710
|
+
</div>
|
|
8711
|
+
</div>
|
|
8712
|
+
<!-- An image model's Count, Format and Background (image-composer-ui.js). -->
|
|
8713
|
+
<div id="image-options-row" class="composer-settings-image-row" hidden>
|
|
8714
|
+
<div class="composer-settings-field" data-field="image-count">
|
|
8715
|
+
<label class="composer-settings-field-label" for="image-count-select">Count</label>
|
|
8716
|
+
<select id="image-count-select" title="Images per turn"></select>
|
|
8717
|
+
</div>
|
|
8718
|
+
<div class="composer-settings-field" data-field="image-format">
|
|
8719
|
+
<label class="composer-settings-field-label" for="image-format-select">Format</label>
|
|
8720
|
+
<select id="image-format-select" title="Image format"></select>
|
|
8721
|
+
</div>
|
|
8722
|
+
<div class="composer-settings-field" data-field="image-background">
|
|
8723
|
+
<label class="composer-settings-field-label" for="image-background-select">Background</label>
|
|
8724
|
+
<select id="image-background-select" title="Image background"></select>
|
|
8725
|
+
</div>
|
|
8324
8726
|
</div>
|
|
8325
8727
|
<!-- Subscription | API key in a Claude chat (claude-billing-toggle-ui.js). -->
|
|
8326
8728
|
<div id="claude-billing-toggle" class="claude-billing-toggle composer-settings-field" data-field="billing" hidden></div>
|
|
@@ -8663,6 +9065,31 @@
|
|
|
8663
9065
|
</div>
|
|
8664
9066
|
<div class="settings-help settings-gap-xs">A sub-agent's record keeps every tool call's full input and the first 4 KB of each result. After this many days the relay removes them from finished agents, once a day; the thoughts, the reply, notes and the one-line summary of each call stay. Always keeps everything. A setting of this relay.</div>
|
|
8665
9067
|
</section>
|
|
9068
|
+
<section class="settings-section" id="settings-section-models" aria-labelledby="settings-section-models-title">
|
|
9069
|
+
<h3 class="settings-section-title" id="settings-section-models-title">Models</h3>
|
|
9070
|
+
<div class="settings-row settings-gap">
|
|
9071
|
+
<label for="model-refresh-auto-toggle">Check for new models</label>
|
|
9072
|
+
<input
|
|
9073
|
+
id="model-refresh-auto-toggle"
|
|
9074
|
+
type="checkbox"
|
|
9075
|
+
onchange="updateModelRefreshAutoSetting(this.checked)"
|
|
9076
|
+
aria-label="Check for new models"
|
|
9077
|
+
checked
|
|
9078
|
+
>
|
|
9079
|
+
</div>
|
|
9080
|
+
<div class="settings-row settings-gap">
|
|
9081
|
+
<label for="model-refresh-interval-select">How often</label>
|
|
9082
|
+
<select id="model-refresh-interval-select" onchange="updateModelRefreshIntervalSetting(this.value)" aria-label="How often to check for new models">
|
|
9083
|
+
<option value="6">Every 6 h</option>
|
|
9084
|
+
<option value="12">Every 12 h</option>
|
|
9085
|
+
<option value="24" selected>Every 24 h</option>
|
|
9086
|
+
<option value="72">Every 3 days</option>
|
|
9087
|
+
<option value="168">Every 7 days</option>
|
|
9088
|
+
</select>
|
|
9089
|
+
</div>
|
|
9090
|
+
<div id="model-refresh-providers" class="settings-gap" role="group" aria-label="Providers checked for new models"></div>
|
|
9091
|
+
<div class="settings-help settings-gap-xs">The relay asks each switched-on provider for its model list this often. A provider whose list was refreshed in the meantime (Refresh in Select Models, a settings save, a sign-in) waits a full interval again, and a failed check is tried again after an hour at the earliest. Whether a new model starts on is set per provider in Select Models. A setting of this relay.</div>
|
|
9092
|
+
</section>
|
|
8666
9093
|
<section class="settings-section" id="settings-section-relay" aria-labelledby="settings-section-relay-title">
|
|
8667
9094
|
<h3 class="settings-section-title" id="settings-section-relay-title">This relay</h3>
|
|
8668
9095
|
<div class="settings-row settings-row-column settings-gap">
|
|
@@ -8734,6 +9161,9 @@
|
|
|
8734
9161
|
<code id="windows-autostart-manual-command" style="display: block; margin-top: calc(4px * var(--ui-scale)); user-select: all;"></code>
|
|
8735
9162
|
</div>
|
|
8736
9163
|
</div>
|
|
9164
|
+
<!-- The Windows helper (koffi) the relay's lock check reads process start
|
|
9165
|
+
times with; agent-sdk-ui.js draws the row, on a Windows relay only. -->
|
|
9166
|
+
<div id="agent-sdk-koffi-row" class="settings-gap" data-agent-sdk="koffi" hidden></div>
|
|
8737
9167
|
</section>
|
|
8738
9168
|
<section class="settings-section" id="settings-section-updates" aria-labelledby="settings-section-updates-title">
|
|
8739
9169
|
<h3 class="settings-section-title" id="settings-section-updates-title">Updates</h3>
|
|
@@ -8951,6 +9381,37 @@
|
|
|
8951
9381
|
</div>
|
|
8952
9382
|
<div class="settings-help">Leave the key blank to keep the saved key, or enter a new one to replace it. Provider changes also update conversations that have not sent a message yet. The Base URL is useful for OpenAI-compatible endpoints or for pointing to the capture proxy (<code>node server/tools/capture-proxy.mjs</code>) to inspect requests.</div>
|
|
8953
9383
|
</div>
|
|
9384
|
+
<!-- Image turns: the daily cap, today's spend and the presets (openai-image-cost-ui.js). -->
|
|
9385
|
+
<div id="openai-image-spend-section" class="settings-row settings-row-column settings-gap" data-testid="openai-image-spend-section">
|
|
9386
|
+
<label for="openai-image-cap-input">Daily image cap (USD)</label>
|
|
9387
|
+
<div class="openai-image-cap-row">
|
|
9388
|
+
<input
|
|
9389
|
+
id="openai-image-cap-input"
|
|
9390
|
+
data-testid="openai-image-cap-input"
|
|
9391
|
+
type="number"
|
|
9392
|
+
inputmode="decimal"
|
|
9393
|
+
min="0"
|
|
9394
|
+
max="10000"
|
|
9395
|
+
step="0.01"
|
|
9396
|
+
value="5"
|
|
9397
|
+
aria-label="Daily image cap in US dollars, 0 for no cap"
|
|
9398
|
+
aria-describedby="openai-image-spend-error openai-image-cap-help"
|
|
9399
|
+
>
|
|
9400
|
+
<button id="openai-image-cap-save-btn" data-testid="openai-image-cap-save" type="button" class="summary-btn">Save cap</button>
|
|
9401
|
+
</div>
|
|
9402
|
+
<div id="openai-image-spend-error" data-testid="openai-image-spend-error" class="settings-help openai-image-field-error" role="alert" hidden></div>
|
|
9403
|
+
<div id="openai-image-cap-help" class="settings-help">What image turns may cost this relay per day (relay time), estimates included. Once today's spend reaches it, new image turns are refused until tomorrow or until you allow more for today; a running turn finishes. 0 means no cap.</div>
|
|
9404
|
+
<div id="openai-image-spend-line" data-testid="openai-image-spend-line" class="settings-help settings-provider-status" role="status">Today's image spend is not known yet.</div>
|
|
9405
|
+
<div class="settings-actions">
|
|
9406
|
+
<button id="openai-image-allow-today-btn" data-testid="openai-image-allow-today" type="button" class="summary-btn" hidden>Allow past the cap for today</button>
|
|
9407
|
+
<button id="openai-image-stop-allowing-btn" data-testid="openai-image-stop-allowing" type="button" class="summary-btn" hidden>Stop allowing</button>
|
|
9408
|
+
</div>
|
|
9409
|
+
<div id="openai-image-spend-status" class="settings-help" role="status" aria-live="polite"></div>
|
|
9410
|
+
<label class="settings-gap-sm" id="openai-image-presets-label">Image presets</label>
|
|
9411
|
+
<ul id="openai-image-presets-list" data-testid="openai-image-presets-list" class="openai-image-presets-list" aria-labelledby="openai-image-presets-label"></ul>
|
|
9412
|
+
<div id="openai-image-presets-error" class="settings-help openai-image-field-error" role="alert" hidden></div>
|
|
9413
|
+
<div id="openai-image-presets-note" class="settings-help"></div>
|
|
9414
|
+
</div>
|
|
8954
9415
|
</div>
|
|
8955
9416
|
<div
|
|
8956
9417
|
id="settings-provider-panel-claude"
|
|
@@ -8980,6 +9441,8 @@
|
|
|
8980
9441
|
<pre id="cli-claude-log"></pre>
|
|
8981
9442
|
</details>
|
|
8982
9443
|
</div>
|
|
9444
|
+
<!-- Agent SDK row; agent-sdk-ui.js draws it. -->
|
|
9445
|
+
<div id="agent-sdk-claude-row" data-agent-sdk="claude" style="margin-bottom: calc(6px * var(--ui-scale));"></div>
|
|
8983
9446
|
<!-- Claude account auth UI (Relogin / Logout); claude-auth-ui.js drives the state. -->
|
|
8984
9447
|
<div id="claude-auth-section">
|
|
8985
9448
|
<div class="settings-row" style="margin-bottom: 0;">
|
|
@@ -9069,6 +9532,8 @@
|
|
|
9069
9532
|
data-settings-provider-panel="claude-api"
|
|
9070
9533
|
hidden
|
|
9071
9534
|
>
|
|
9535
|
+
<!-- Claude API chats run on the Claude Agent SDK; agent-sdk-ui.js draws the row. -->
|
|
9536
|
+
<div id="agent-sdk-claude-api-row" data-agent-sdk="claude"></div>
|
|
9072
9537
|
<div class="settings-row settings-row-column settings-gap">
|
|
9073
9538
|
<label for="claude-api-key-input">Claude API</label>
|
|
9074
9539
|
<div class="settings-row settings-row-full settings-row-lead">
|
|
@@ -9274,6 +9739,8 @@
|
|
|
9274
9739
|
data-settings-provider-panel="cursor"
|
|
9275
9740
|
hidden
|
|
9276
9741
|
>
|
|
9742
|
+
<!-- Agent SDK row; agent-sdk-ui.js draws it. -->
|
|
9743
|
+
<div id="agent-sdk-cursor-row" data-agent-sdk="cursor"></div>
|
|
9277
9744
|
<div class="settings-row settings-row-column settings-gap">
|
|
9278
9745
|
<label for="cursor-api-key-input">Cursor SDK</label>
|
|
9279
9746
|
<div class="settings-row settings-row-full settings-row-lead">
|
|
@@ -9367,6 +9834,8 @@
|
|
|
9367
9834
|
data-settings-provider-panel="deepseek"
|
|
9368
9835
|
hidden
|
|
9369
9836
|
>
|
|
9837
|
+
<!-- DeepSeek chats run on the Claude Agent SDK; agent-sdk-ui.js draws the row. -->
|
|
9838
|
+
<div id="agent-sdk-deepseek-row" data-agent-sdk="claude"></div>
|
|
9370
9839
|
<div class="settings-row settings-row-column settings-gap">
|
|
9371
9840
|
<label for="deepseek-api-key-input">DeepSeek</label>
|
|
9372
9841
|
<div class="settings-row settings-row-full settings-row-lead">
|