@worca/ui 0.43.0 → 0.45.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/app/main.bundle.js +2483 -2206
- package/app/main.bundle.js.map +4 -4
- package/app/styles.css +386 -0
- package/package.json +1 -1
- package/server/models-routes.js +573 -0
- package/server/paths.js +11 -0
- package/server/project-routes.js +29 -2
- package/server/settings-merge.js +104 -0
- package/server/templates-routes.js +165 -12
package/app/styles.css
CHANGED
|
@@ -8170,6 +8170,60 @@ sl-dialog.markdown-dialog::part(body) {
|
|
|
8170
8170
|
color: var(--fg);
|
|
8171
8171
|
}
|
|
8172
8172
|
|
|
8173
|
+
.template-action-dialog .dialog-collisions {
|
|
8174
|
+
border-left: 3px solid var(--sl-color-warning-500, #f59e0b);
|
|
8175
|
+
padding: 10px 12px;
|
|
8176
|
+
background: var(--sl-color-warning-50, rgba(245, 158, 11, 0.05));
|
|
8177
|
+
border-radius: 4px;
|
|
8178
|
+
min-width: 0;
|
|
8179
|
+
}
|
|
8180
|
+
.template-action-dialog .dialog-collisions-header {
|
|
8181
|
+
margin-bottom: 6px;
|
|
8182
|
+
}
|
|
8183
|
+
.template-action-dialog .dialog-collision-list {
|
|
8184
|
+
list-style: none;
|
|
8185
|
+
margin: 10px 0 0;
|
|
8186
|
+
padding: 0;
|
|
8187
|
+
display: flex;
|
|
8188
|
+
flex-direction: column;
|
|
8189
|
+
gap: 8px;
|
|
8190
|
+
}
|
|
8191
|
+
.template-action-dialog .dialog-collision-row {
|
|
8192
|
+
display: grid;
|
|
8193
|
+
grid-template-columns: minmax(90px, 140px) minmax(0, 1fr) minmax(0, 1fr);
|
|
8194
|
+
align-items: center;
|
|
8195
|
+
gap: 8px;
|
|
8196
|
+
min-width: 0;
|
|
8197
|
+
}
|
|
8198
|
+
.template-action-dialog .dialog-collision-alias {
|
|
8199
|
+
min-width: 0;
|
|
8200
|
+
overflow: hidden;
|
|
8201
|
+
text-overflow: ellipsis;
|
|
8202
|
+
white-space: nowrap;
|
|
8203
|
+
}
|
|
8204
|
+
.template-action-dialog .dialog-collision-alias code {
|
|
8205
|
+
font-family: var(--sl-font-mono);
|
|
8206
|
+
font-size: 13px;
|
|
8207
|
+
color: var(--fg);
|
|
8208
|
+
}
|
|
8209
|
+
.template-action-dialog .collision-action-select,
|
|
8210
|
+
.template-action-dialog .collision-rename-input {
|
|
8211
|
+
width: 100%;
|
|
8212
|
+
min-width: 0;
|
|
8213
|
+
}
|
|
8214
|
+
.template-action-dialog .dialog-collision-row[data-rename="false"] .collision-action-select {
|
|
8215
|
+
grid-column: 2 / span 2;
|
|
8216
|
+
}
|
|
8217
|
+
.template-action-dialog .dialog-new-aliases-hint {
|
|
8218
|
+
margin-top: 8px;
|
|
8219
|
+
}
|
|
8220
|
+
.template-action-dialog .dialog-new-aliases-hint code {
|
|
8221
|
+
font-family: var(--sl-font-mono);
|
|
8222
|
+
font-size: 12px;
|
|
8223
|
+
color: var(--fg);
|
|
8224
|
+
margin-right: 4px;
|
|
8225
|
+
}
|
|
8226
|
+
|
|
8173
8227
|
.editor-content {
|
|
8174
8228
|
flex: 1;
|
|
8175
8229
|
overflow-y: auto;
|
|
@@ -10031,3 +10085,335 @@ body.help-mode-active sl-tab {
|
|
|
10031
10085
|
background: rgba(34, 197, 94, 0.2);
|
|
10032
10086
|
color: #86efac;
|
|
10033
10087
|
}
|
|
10088
|
+
|
|
10089
|
+
/* ────────────────────────────────────────────────────────────────────────
|
|
10090
|
+
* Models page — mirrors Pipeline Templates structure.
|
|
10091
|
+
*
|
|
10092
|
+
* The list view inherits .pipelines-view / .pipelines-content /
|
|
10093
|
+
* .pipelines-tier-section / .pipelines-grid from the Pipelines page so
|
|
10094
|
+
* spacing, section collapsibles, and grid behavior match exactly. Only
|
|
10095
|
+
* the bits unique to model cards / model editor live here.
|
|
10096
|
+
* ────────────────────────────────────────────────────────────────────── */
|
|
10097
|
+
|
|
10098
|
+
/* Model card on the Models page. Distinct from .model-card (which the
|
|
10099
|
+
legacy Settings → Models tab used for in-place edit rows). */
|
|
10100
|
+
.model-tier-card {
|
|
10101
|
+
cursor: pointer;
|
|
10102
|
+
transition: border-color 120ms ease, box-shadow 120ms ease;
|
|
10103
|
+
}
|
|
10104
|
+
.model-tier-card:hover {
|
|
10105
|
+
border-color: var(--accent);
|
|
10106
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
|
10107
|
+
}
|
|
10108
|
+
.model-tier-card .run-card-actions {
|
|
10109
|
+
margin-top: auto;
|
|
10110
|
+
padding-top: 0.5rem;
|
|
10111
|
+
}
|
|
10112
|
+
.model-card-alt-badge {
|
|
10113
|
+
margin-left: auto;
|
|
10114
|
+
}
|
|
10115
|
+
.model-card-meta {
|
|
10116
|
+
display: flex;
|
|
10117
|
+
flex-wrap: wrap;
|
|
10118
|
+
gap: 0.5rem;
|
|
10119
|
+
}
|
|
10120
|
+
|
|
10121
|
+
/* ── Model editor ── */
|
|
10122
|
+
.model-editor .editor-content {
|
|
10123
|
+
display: flex;
|
|
10124
|
+
flex-direction: column;
|
|
10125
|
+
gap: 1.25rem;
|
|
10126
|
+
padding-top: 1rem;
|
|
10127
|
+
}
|
|
10128
|
+
.model-editor-section {
|
|
10129
|
+
background: var(--bg-secondary);
|
|
10130
|
+
border: 1px solid var(--border);
|
|
10131
|
+
border-radius: 8px;
|
|
10132
|
+
padding: 1rem 1.25rem;
|
|
10133
|
+
}
|
|
10134
|
+
.model-editor-section-head {
|
|
10135
|
+
display: flex;
|
|
10136
|
+
justify-content: space-between;
|
|
10137
|
+
align-items: flex-start;
|
|
10138
|
+
gap: 1rem;
|
|
10139
|
+
margin-bottom: 0.5rem;
|
|
10140
|
+
}
|
|
10141
|
+
.model-editor-section-head h3 {
|
|
10142
|
+
margin: 0;
|
|
10143
|
+
}
|
|
10144
|
+
.model-editor-resolves-banner {
|
|
10145
|
+
margin-bottom: 0.5rem;
|
|
10146
|
+
}
|
|
10147
|
+
.model-editor-resolves-banner code {
|
|
10148
|
+
margin-left: 0.4rem;
|
|
10149
|
+
margin-right: 0.4rem;
|
|
10150
|
+
background: var(--bg-tertiary);
|
|
10151
|
+
padding: 0.1rem 0.4rem;
|
|
10152
|
+
border-radius: 3px;
|
|
10153
|
+
}
|
|
10154
|
+
.model-editor-secret-banner {
|
|
10155
|
+
margin-bottom: 0.5rem;
|
|
10156
|
+
}
|
|
10157
|
+
/* Self-contained env-vars table — deliberately NOT sharing .pricing-table
|
|
10158
|
+
styles. Pricing rows are narrow numeric cells; env rows are wide
|
|
10159
|
+
key/value text fields that need to fill the remaining horizontal
|
|
10160
|
+
space evenly. Sharing the class would pull in the 104px max-width
|
|
10161
|
+
meant for the rate cells. */
|
|
10162
|
+
.model-editor-env-table {
|
|
10163
|
+
margin-top: 0.5rem;
|
|
10164
|
+
width: 100%;
|
|
10165
|
+
/* table-layout: fixed makes the column widths below actually apply
|
|
10166
|
+
instead of getting collapsed by sl-input min-width. */
|
|
10167
|
+
table-layout: fixed;
|
|
10168
|
+
border-collapse: collapse;
|
|
10169
|
+
font-size: 13px;
|
|
10170
|
+
}
|
|
10171
|
+
.model-editor-env-table th,
|
|
10172
|
+
.model-editor-env-table td {
|
|
10173
|
+
vertical-align: middle;
|
|
10174
|
+
padding: 0.3rem 0.5rem;
|
|
10175
|
+
box-sizing: border-box;
|
|
10176
|
+
}
|
|
10177
|
+
.model-editor-env-table th {
|
|
10178
|
+
text-align: left;
|
|
10179
|
+
font-weight: 600;
|
|
10180
|
+
color: var(--muted);
|
|
10181
|
+
font-size: 11px;
|
|
10182
|
+
text-transform: uppercase;
|
|
10183
|
+
letter-spacing: 0.04em;
|
|
10184
|
+
}
|
|
10185
|
+
/* Key + value split the row evenly between them; actions is a fixed
|
|
10186
|
+
icon-button column on the right. With table-layout: fixed every
|
|
10187
|
+
column needs an explicit width — otherwise the un-sized column
|
|
10188
|
+
takes 1/N of the remaining space (so 1/3 of the row, not 2.5rem). */
|
|
10189
|
+
.model-editor-env-table th:nth-child(1),
|
|
10190
|
+
.model-editor-env-table td:nth-child(1),
|
|
10191
|
+
.model-editor-env-table th:nth-child(2),
|
|
10192
|
+
.model-editor-env-table td:nth-child(2) {
|
|
10193
|
+
width: calc((100% - 3.5rem) / 2);
|
|
10194
|
+
}
|
|
10195
|
+
.model-editor-env-table th:nth-child(3),
|
|
10196
|
+
.model-editor-env-table td:nth-child(3) {
|
|
10197
|
+
width: 3.5rem;
|
|
10198
|
+
}
|
|
10199
|
+
.model-editor-env-actions {
|
|
10200
|
+
text-align: right;
|
|
10201
|
+
}
|
|
10202
|
+
.model-editor-env-table .model-editor-env-key,
|
|
10203
|
+
.model-editor-env-table .model-editor-env-value {
|
|
10204
|
+
width: 100%;
|
|
10205
|
+
max-width: none;
|
|
10206
|
+
display: block;
|
|
10207
|
+
}
|
|
10208
|
+
.model-editor-env-row--invalid sl-input::part(base) {
|
|
10209
|
+
border-color: var(--status-failed, #ef4444);
|
|
10210
|
+
}
|
|
10211
|
+
/* Placeholder-valued env rows (one of SECRET_PLACEHOLDERS): outline the VALUE
|
|
10212
|
+
input in red as a visual hint to swap in the real secret. Visual only — save
|
|
10213
|
+
stays enabled, the run-time decides whether the placeholder is acceptable. */
|
|
10214
|
+
.model-editor-env-row--placeholder .model-editor-env-value::part(base) {
|
|
10215
|
+
border-color: var(--status-failed, #ef4444);
|
|
10216
|
+
border-width: 2px;
|
|
10217
|
+
box-shadow: 0 0 0 1px rgba(239, 68, 68, 0.15);
|
|
10218
|
+
}
|
|
10219
|
+
.model-editor-env-error {
|
|
10220
|
+
display: block;
|
|
10221
|
+
color: var(--status-failed, #ef4444);
|
|
10222
|
+
font-size: 0.75rem;
|
|
10223
|
+
margin-top: 0.25rem;
|
|
10224
|
+
}
|
|
10225
|
+
.model-editor-env-warn {
|
|
10226
|
+
display: block;
|
|
10227
|
+
color: var(--status-failed, #ef4444);
|
|
10228
|
+
font-size: 0.75rem;
|
|
10229
|
+
margin-top: 0.25rem;
|
|
10230
|
+
font-weight: 500;
|
|
10231
|
+
}
|
|
10232
|
+
/* width handled by the .model-editor-env-table td:nth-child(3) rule
|
|
10233
|
+
above (table-layout: fixed needs the column-position selector, not
|
|
10234
|
+
the cell class, to win deterministically) — keep this rule for the
|
|
10235
|
+
text-align only. */
|
|
10236
|
+
.model-editor-env-empty {
|
|
10237
|
+
margin: 0.5rem 0 0;
|
|
10238
|
+
}
|
|
10239
|
+
.model-editor-pricing-accordion::part(base) {
|
|
10240
|
+
background: transparent;
|
|
10241
|
+
border: none;
|
|
10242
|
+
padding: 0;
|
|
10243
|
+
}
|
|
10244
|
+
.model-editor-pricing-accordion::part(header) {
|
|
10245
|
+
padding: 0.25rem 0;
|
|
10246
|
+
}
|
|
10247
|
+
.model-editor-pricing-summary {
|
|
10248
|
+
display: flex;
|
|
10249
|
+
align-items: center;
|
|
10250
|
+
gap: 0.75rem;
|
|
10251
|
+
}
|
|
10252
|
+
/* Right-aligned action row under the pricing table. Only renders when at
|
|
10253
|
+
least one field is set — "Clear pricing" wipes the entire entry. */
|
|
10254
|
+
.model-editor-pricing-actions {
|
|
10255
|
+
display: flex;
|
|
10256
|
+
justify-content: flex-end;
|
|
10257
|
+
margin-top: 0.75rem;
|
|
10258
|
+
}
|
|
10259
|
+
.model-editor-applied-list {
|
|
10260
|
+
margin: 0.5rem 0 0;
|
|
10261
|
+
padding-left: 1.25rem;
|
|
10262
|
+
}
|
|
10263
|
+
.model-editor-applied-list li {
|
|
10264
|
+
margin-bottom: 0.25rem;
|
|
10265
|
+
}
|
|
10266
|
+
|
|
10267
|
+
/* Grouped Applied-by layout — one row per template, tier badge + linked
|
|
10268
|
+
template name on the first line, agent chips wrapping below. */
|
|
10269
|
+
.model-editor-applied-count {
|
|
10270
|
+
flex-shrink: 0;
|
|
10271
|
+
}
|
|
10272
|
+
.model-editor-applied-groups {
|
|
10273
|
+
margin-top: 0.5rem;
|
|
10274
|
+
display: flex;
|
|
10275
|
+
flex-direction: column;
|
|
10276
|
+
gap: 0.5rem;
|
|
10277
|
+
}
|
|
10278
|
+
.model-editor-applied-row {
|
|
10279
|
+
padding: 0.5rem 0.75rem;
|
|
10280
|
+
background: var(--bg-tertiary, var(--bg));
|
|
10281
|
+
border-radius: 6px;
|
|
10282
|
+
border: 1px solid var(--border);
|
|
10283
|
+
}
|
|
10284
|
+
.model-editor-applied-row-head {
|
|
10285
|
+
display: flex;
|
|
10286
|
+
align-items: center;
|
|
10287
|
+
gap: 0.5rem;
|
|
10288
|
+
margin-bottom: 0.25rem;
|
|
10289
|
+
}
|
|
10290
|
+
.model-editor-applied-link {
|
|
10291
|
+
color: var(--accent);
|
|
10292
|
+
text-decoration: none;
|
|
10293
|
+
font-weight: 600;
|
|
10294
|
+
font-family: var(--sl-font-mono);
|
|
10295
|
+
font-size: 0.875rem;
|
|
10296
|
+
}
|
|
10297
|
+
.model-editor-applied-link:hover {
|
|
10298
|
+
text-decoration: underline;
|
|
10299
|
+
}
|
|
10300
|
+
.model-editor-applied-agents {
|
|
10301
|
+
display: flex;
|
|
10302
|
+
flex-wrap: wrap;
|
|
10303
|
+
gap: 0.35rem;
|
|
10304
|
+
margin-top: 0.35rem;
|
|
10305
|
+
padding-left: 0.25rem;
|
|
10306
|
+
}
|
|
10307
|
+
.model-editor-applied-agent {
|
|
10308
|
+
display: inline-block;
|
|
10309
|
+
padding: 0.1rem 0.45rem;
|
|
10310
|
+
background: var(--bg-secondary, var(--bg));
|
|
10311
|
+
border: 1px solid var(--border);
|
|
10312
|
+
border-radius: 3px;
|
|
10313
|
+
font-size: 0.75rem;
|
|
10314
|
+
color: var(--muted);
|
|
10315
|
+
}
|
|
10316
|
+
.model-editor-alias-input {
|
|
10317
|
+
min-width: 12rem;
|
|
10318
|
+
}
|
|
10319
|
+
.model-editor-id-input {
|
|
10320
|
+
max-width: 30rem;
|
|
10321
|
+
}
|
|
10322
|
+
.editor-readonly-badge {
|
|
10323
|
+
margin-left: 0.25rem;
|
|
10324
|
+
}
|
|
10325
|
+
|
|
10326
|
+
/* Tier picker pill for new model entries — replaces the read-only Storage
|
|
10327
|
+
badge while isNew=true so the user can flip the destination tier before
|
|
10328
|
+
saving. Styled as a field-pill so it sits next to the other subheader
|
|
10329
|
+
pills without breaking the row. */
|
|
10330
|
+
.editor-storage-pill {
|
|
10331
|
+
background: var(--bg-tertiary);
|
|
10332
|
+
border-radius: 999px;
|
|
10333
|
+
padding: 0 0.5rem;
|
|
10334
|
+
display: inline-flex;
|
|
10335
|
+
align-items: center;
|
|
10336
|
+
gap: 0.35rem;
|
|
10337
|
+
}
|
|
10338
|
+
.model-editor-tier-select {
|
|
10339
|
+
min-width: 7rem;
|
|
10340
|
+
}
|
|
10341
|
+
|
|
10342
|
+
/* Imported-from-bundle attribution. Dropped on first UI save (the server
|
|
10343
|
+
doesn't preserve _imported_from when writeModelEntry runs). */
|
|
10344
|
+
.model-editor-imported-banner {
|
|
10345
|
+
margin-bottom: 0.5rem;
|
|
10346
|
+
}
|
|
10347
|
+
.model-editor-imported-banner code {
|
|
10348
|
+
margin-left: 0.25rem;
|
|
10349
|
+
background: var(--bg-tertiary);
|
|
10350
|
+
padding: 0.1rem 0.4rem;
|
|
10351
|
+
border-radius: 3px;
|
|
10352
|
+
}
|
|
10353
|
+
/* Imported-from badge — let Shoelace's neutral variant draw both bg and
|
|
10354
|
+
text. The previous bg-tertiary override gave the badge a low-contrast
|
|
10355
|
+
gray-on-gray look (text used the default light neutral text color on
|
|
10356
|
+
a darker gray background and became unreadable). */
|
|
10357
|
+
|
|
10358
|
+
/* Model duplicate dialog (tier picker + alias input) */
|
|
10359
|
+
.model-duplicate-form {
|
|
10360
|
+
display: flex;
|
|
10361
|
+
flex-direction: column;
|
|
10362
|
+
gap: 0.75rem;
|
|
10363
|
+
}
|
|
10364
|
+
|
|
10365
|
+
/* Pipeline editor: per-agent model dropdown gains a tier badge inline
|
|
10366
|
+
in each option, plus a small "open in Models" jump link. */
|
|
10367
|
+
.agent-model-select-row {
|
|
10368
|
+
display: flex;
|
|
10369
|
+
align-items: center;
|
|
10370
|
+
gap: 0.4rem;
|
|
10371
|
+
}
|
|
10372
|
+
.agent-model-select-row sl-select {
|
|
10373
|
+
flex: 1;
|
|
10374
|
+
min-width: 0;
|
|
10375
|
+
}
|
|
10376
|
+
.agent-model-open-link {
|
|
10377
|
+
display: inline-flex;
|
|
10378
|
+
align-items: center;
|
|
10379
|
+
justify-content: center;
|
|
10380
|
+
width: 1.5rem;
|
|
10381
|
+
height: 1.5rem;
|
|
10382
|
+
border-radius: 4px;
|
|
10383
|
+
color: var(--muted);
|
|
10384
|
+
text-decoration: none;
|
|
10385
|
+
font-size: 1rem;
|
|
10386
|
+
font-weight: 600;
|
|
10387
|
+
flex-shrink: 0;
|
|
10388
|
+
}
|
|
10389
|
+
.agent-model-open-link:hover {
|
|
10390
|
+
background: var(--bg-tertiary);
|
|
10391
|
+
color: var(--accent);
|
|
10392
|
+
}
|
|
10393
|
+
|
|
10394
|
+
/* Costs & Budgets tab → notice linking to the Models page for per-model
|
|
10395
|
+
pricing edits. */
|
|
10396
|
+
.costs-budgets-models-link {
|
|
10397
|
+
margin-bottom: 1rem;
|
|
10398
|
+
}
|
|
10399
|
+
.costs-budgets-models-link a {
|
|
10400
|
+
color: var(--accent);
|
|
10401
|
+
text-decoration: underline;
|
|
10402
|
+
}
|
|
10403
|
+
|
|
10404
|
+
/* Import dialog — bundle-contents summary block (what lands where). */
|
|
10405
|
+
.dialog-bundle-summary {
|
|
10406
|
+
background: var(--bg-tertiary);
|
|
10407
|
+
border-radius: 6px;
|
|
10408
|
+
padding: 0.5rem 1rem;
|
|
10409
|
+
margin-bottom: 0.5rem;
|
|
10410
|
+
list-style: none;
|
|
10411
|
+
}
|
|
10412
|
+
.dialog-bundle-summary li {
|
|
10413
|
+
margin: 0.15rem 0;
|
|
10414
|
+
}
|
|
10415
|
+
.dialog-bundle-summary em {
|
|
10416
|
+
font-style: normal;
|
|
10417
|
+
font-weight: 600;
|
|
10418
|
+
color: var(--accent);
|
|
10419
|
+
}
|