@mars-sea/dsh-commandcode-provider 0.11.2 → 0.11.4
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/CHANGELOG.md +17 -0
- package/lib/client.js +228 -146
- package/lib/client.js.map +1 -1
- package/lib/index.d.ts +25 -0
- package/lib/index.js +265 -13
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,23 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.11.4] - 2026-09-17
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
- **The Command Code Remotes keep registering on the next Harness generation** ([#49](https://github.com/Mars-Sea/dsh-commandcode-provider/issues/49)). The Typert protocol changed the strict result codec's shape inside the same `mode: 'strict'` tag: every released engine (`0.1.2-rc.1` … `0.1.6-alpha.1`, all 21 published versions) declares `schema: TypertSchema` and refuses registration with `strict codec has no parse() method` without it, while master after `e459e3263` replaced that member with the lazy factory `create: () => TypertSchema` and refuses with `strict codec has no create() factory`. All six Command Code Remotes (`report`, `models`, `prices`, `loginBegin`, `loginStatus`, `loginCancel`) come from one descriptor factory that carried `schema` alone, so on that newer generation none of them registers: the settings page's account card, the plans & quota panel, the price table and the browser login all lose their Host data. `makeRemoteDescriptor()` now carries both members, where `create: () => schema` names the same hand-rolled validator rather than a second copy, so the two generations can never validate against different rules. This is a version-agnostic fix instead of a runtime probe: neither generation inspects the member it does not know, and the member the running engine ignores is inert — which matters because a single-member codec is broken in either direction, and the one-line patch the issue proposed (`schema` → `create`) would have fixed unreleased master by breaking every install that exists today. `tests/wire-shared.test.ts` pins it by running both generations' real validators over every shipped descriptor, with negative controls proving that a codec carrying only one member is rejected by the other generation. The helper is inlined into both `lib/index.js` and `lib/client.js`, so a fix is dead until the bundle is rebuilt — hence the rebuilt bundles in this release.
|
|
13
|
+
|
|
14
|
+
## [0.11.3] - 2026-09-16
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
- **Thinking text is also read from `reasoning_details`.** The gateway does not normalize the reasoning field across model families, and the difference is per family rather than global: DeepSeek answers with the scalar `reasoning` **plus** an OpenRouter-shaped `reasoning_details` array (`[{ type: 'reasoning.text', text, format, index }]`), while GLM, Qwen and Kimi answer with the DeepSeek-native `reasoning_content` (all measured against the live API on 2026-09-16, alongside the catalog sweep below). The adapter already read the first two spellings, so nothing was broken; the array is now a third fallback, so a family whose thinking arrives only that way is not silently dropped. Entries are read by their `text` member rather than filtered on `type === 'reasoning.text'`: the sibling shapes in that protocol carry `summary` or an encrypted blob instead of `text`, so a plain read already ignores them, while a type filter would drop a text-bearing variant added later — and losing thinking is the failure this exists to prevent.
|
|
18
|
+
- **`transportMaxRetries`: how many transport failures one request absorbs before the failure surfaces** (default 5, 0–50; Settings → Command Code → Advanced). It exists because the route's retry policy cannot express this: `providerRetryPolicy()` is captured once per route, so `TRANSPORT` had to share the near-unbounded window that `RATE_LIMIT`/`SERVER` need, and a connection that cannot be established is not a failure that asks to be waited out. The retries still run on the policy's own cadence (500 ms doubling), so the default spends ~15.5 s (0.5+1+2+4+8) on a blip before reporting it.
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
- **Claude models work again on Provider API accounts** ([#46](https://github.com/Mars-Sea/dsh-commandcode-provider/issues/46)). The Provider API serves the whole Claude family only through `/provider/v1/messages`: posted to `/provider/v1/chat/completions`, every catalog Claude id — all eight, verified by posting all 69 models to that endpoint on 2026-09-16 — answers `400 Model "<id>" must be called via /provider/v1/messages (Anthropic Messages shape)`. The adapter's only pre-stream fallback was the Go-plan `upgrade_required` 403, so the rejection surfaced to the user as `PROVIDER_HTTP_ERROR`; and because the non-Go tiers are exactly the ones `resolveProtocol()` sends to the Provider API, the accounts ENTITLED to Claude were the ones that could never use it. Those models now take the CLI transport, which routes every one of them (a lower-plan key gets the ordinary `MODEL_NOT_IN_PLAN` 403 there, never a routing error), so no Messages transport is needed in the adapter. The decision is deliberately NOT written to `protocolCache`, which is keyed by API key alone: remembering it would pin the whole ACCOUNT to the CLI transport and drag DeepSeek, GLM and Qwen — all correctly served by the Provider API — along with it, which is why `rememberProtocol()` is not called on that path. `MESSAGES_ONLY_MODELS` in `src/capabilities.ts` records the measured set, and `requiresMessagesEndpoint()` also treats any `claude-*` id as Messages-only, so a Claude model shipping after this release is routed correctly by an un-updated plugin instead of hard-failing with the 400 above. The same sweep also confirmed the neighbouring report is a non-issue for this plugin: the reasoning-replay and thinking-display paths read every field spelling the gateway emits (see Added).
|
|
22
|
+
- **A transport failure no longer retries toward the 1000-attempt budget** ([#39](https://github.com/Mars-Sea/dsh-commandcode-provider/issues/39), second report). The report after 0.11.1 showed no context-window rejection at all: at ~710k tokens the adapter failed with undici's own `Connect Timeout Error ... timeout: 10000ms` (its default connect timeout — this plugin's `requestTimeoutMs` is 60 s and the connection phase never runs against the body upload) and, on another attempt, `read ECONNRESET` against `/alpha/generate`. Both are `TRANSPORT`, which the retry policy whitelists, so each entered the same 1000-attempt loop the 0.11.2 context-window fix left untouched: with waits doubling from 500 ms, the wait before attempt 11 alone is 512 s and the cumulative wait before it is ~500 s — the `模型请求重试已取消(11/1000)· 482s` row in the report is that 512 s countdown, 30 s in. `TRANSPORT` failures now consume a bounded budget on the `agent/request-error` hook: the first five are retried (~15.5 s of grace — 0.5+1+2+4+8 s waits, and the reporter's own first screenshot, a single `read ECONNRESET` that recovered on the next attempt, stays invisible), and the sixth surfaces the turn with a diagnosis that says what it is (connectivity, *not* a context-window or request-size rejection) and what usually fixes it. The check runs before the budget, so a cancelled turn is never retried and never spends a slot; the budget resets at each new step (one step *is* one model request, so the cap is per request and every step of a turn gets its own grace); and the accounting is keyed per agent, so one session's outage cannot disable another's retries. Everything else — the rate-limit window, a gateway 520, account rotation, the 413 image step-down — is unchanged. The report's "long context" correlation is a red herring, and this change does not depend on ruling it in or out: verified against the live endpoint, request bodies of 1/8/30 MB all returned the provider's own `401` in 1.9/2.7/5.7 s. `tests/transport-retry.test.ts` pins the budget, the per-agent isolation, the cancellation ordering and the message.
|
|
23
|
+
- **A message with no `source` tag no longer kills the whole stream** ([#47](https://github.com/Mars-Sea/dsh-commandcode-provider/issues/47)). `messagesToCC` read `message.source.kind` at four sites to tell a tool result from a plain user message. `source` is producer-supplied and nothing validates it — dsh-llm's type declares it required, but the runtime never checks it and every adapter shipped before this one ignored the field entirely (`dsh-llm-deepseek` never reads it) — so a third-party plugin that assembles its own history can omit it and keep working everywhere else. This adapter, the first to actually read the field, was therefore the first to crash on such a message: `TypeError: Cannot read properties of undefined (reading 'kind')` in the serialization phase, 0–8 ms in, before a request was sent, with an error naming neither the message nor the producer. Both transports now classify a message through one predicate (`isToolResultMessage()`): a PRESENT tag stays authoritative, while an ABSENT one falls back to the content shape — a `user` message whose first block is a `tool-result` is still a tool result, because `pairedToolCalls()` counts such a block from ANY message and dropping it at emission would leave the assistant's tool call unanswered, which the gateway rejects. An untagged plain user message (the reported case, from dsh-mneme's memory pipeline) is now simply converted as the user message it is. Pinned by three tests in `tests/adapter.test.ts`, each run through both transports: the untagged user message, the untagged tool result, and the authoritative tag.
|
|
24
|
+
- **The plugin's stylesheet no longer reaches into other components' markup** ([#48](https://github.com/Mars-Sea/dsh-commandcode-provider/issues/48)). Installing the plugin stacked the `ask_user_question` dialog's side-by-side buttons vertically. The cause was one rule in the panel stylesheet, `[class*="_footerActions"]{flex-direction:column}`, written for the sidebar's footer-action container so this card's full-width line and ui-cordis's chip stack instead of overflowing the shell's flex ROW. `footerActions` is not a stem the sidebar owns alone: `@deepseek-ai/dsh-client-ui-user-questions` renders that dialog's button row as `Mbwy4a_footerActions`, so the unanchored attribute-substring selector matched it too and overrode the row's `display:flex`. The rule is now anchored to the sidebar's own foot area (`[class*="_footArea"] [class*="_footerActions"]`), a stem declared by dsh-client-ui-sidebar alone — audited across every client bundle of the 0.1.6-alpha.1 engine, together with our own `cc-`/`ccp-` class names, which collide with no engine class — so the sidebar layout fix is unchanged and no other component can be reached. The settings-page stylesheet moved to `src/client/page-styles.ts` so both sheets can be audited without importing the React tree, and `tests/styles.test.ts` now enforces the containment in two layers: a structural audit of every selector compound in both sheets, and a simulation against the real foreign class stems proving the dialog's row is no longer matched while the sidebar's still is.
|
|
25
|
+
|
|
9
26
|
## [0.11.2] - 2026-09-15
|
|
10
27
|
|
|
11
28
|
### Added
|
package/lib/client.js
CHANGED
|
@@ -157,6 +157,10 @@ window.__ModuleLoader__.load({
|
|
|
157
157
|
min: 1,
|
|
158
158
|
max: MAX_TIMEOUT_MS
|
|
159
159
|
}),
|
|
160
|
+
numberField$1("transportMaxRetries", {
|
|
161
|
+
min: 0,
|
|
162
|
+
max: 50
|
|
163
|
+
}),
|
|
160
164
|
booleanField$1("filterModelsByPlan"),
|
|
161
165
|
booleanField$1("webSearch"),
|
|
162
166
|
booleanField$1("showSidebarQuota"),
|
|
@@ -310,6 +314,7 @@ window.__ModuleLoader__.load({
|
|
|
310
314
|
defaultWorkingDir: this.defaultWorkingDir,
|
|
311
315
|
requestTimeoutMs: this.field("requestTimeoutMs"),
|
|
312
316
|
streamIdleTimeoutMs: this.field("streamIdleTimeoutMs"),
|
|
317
|
+
transportMaxRetries: this.field("transportMaxRetries"),
|
|
313
318
|
filterModelsByPlan: this.field("filterModelsByPlan"),
|
|
314
319
|
webSearch: this.field("webSearch"),
|
|
315
320
|
showSidebarQuota: this.field("showSidebarQuota"),
|
|
@@ -1673,6 +1678,12 @@ window.__ModuleLoader__.load({
|
|
|
1673
1678
|
* only its own facts.
|
|
1674
1679
|
*/
|
|
1675
1680
|
function makeRemoteDescriptor(endpoint, method, typeSymbol, schema) {
|
|
1681
|
+
const result = {
|
|
1682
|
+
mode: "strict",
|
|
1683
|
+
typeSymbol,
|
|
1684
|
+
schema,
|
|
1685
|
+
create: () => schema
|
|
1686
|
+
};
|
|
1676
1687
|
return {
|
|
1677
1688
|
id: `${REMOTE_PACKAGE}#${endpoint}`,
|
|
1678
1689
|
service: REMOTE_SERVICE,
|
|
@@ -1680,11 +1691,7 @@ window.__ModuleLoader__.load({
|
|
|
1680
1691
|
method,
|
|
1681
1692
|
invocation: { kind: "direct" },
|
|
1682
1693
|
parameters: [],
|
|
1683
|
-
result
|
|
1684
|
-
mode: "strict",
|
|
1685
|
-
typeSymbol,
|
|
1686
|
-
schema
|
|
1687
|
-
}
|
|
1694
|
+
result
|
|
1688
1695
|
};
|
|
1689
1696
|
}
|
|
1690
1697
|
//#endregion
|
|
@@ -2150,7 +2157,7 @@ window.__ModuleLoader__.load({
|
|
|
2150
2157
|
}
|
|
2151
2158
|
//#endregion
|
|
2152
2159
|
//#region package.json
|
|
2153
|
-
var version = "0.11.
|
|
2160
|
+
var version = "0.11.4";
|
|
2154
2161
|
var repository = {
|
|
2155
2162
|
"type": "git",
|
|
2156
2163
|
"url": "git+https://github.com/Mars-Sea/dsh-commandcode-provider.git"
|
|
@@ -2349,6 +2356,7 @@ window.__ModuleLoader__.load({
|
|
|
2349
2356
|
"workingDir",
|
|
2350
2357
|
"requestTimeoutMs",
|
|
2351
2358
|
"streamIdleTimeoutMs",
|
|
2359
|
+
"transportMaxRetries",
|
|
2352
2360
|
"filterModelsByPlan",
|
|
2353
2361
|
"webSearch",
|
|
2354
2362
|
"showSidebarQuota"
|
|
@@ -2494,6 +2502,17 @@ window.__ModuleLoader__.load({
|
|
|
2494
2502
|
onReset: () => onReset("streamIdleTimeoutMs"),
|
|
2495
2503
|
t
|
|
2496
2504
|
}),
|
|
2505
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Field, {
|
|
2506
|
+
id: "cc-transport-max-retries",
|
|
2507
|
+
label: t("transportMaxRetries"),
|
|
2508
|
+
hint: t("transportMaxRetriesHint"),
|
|
2509
|
+
state: state.transportMaxRetries,
|
|
2510
|
+
disabled,
|
|
2511
|
+
numeric: true,
|
|
2512
|
+
onEdit: (text) => onEdit("transportMaxRetries", text),
|
|
2513
|
+
onReset: () => onReset("transportMaxRetries"),
|
|
2514
|
+
t
|
|
2515
|
+
}),
|
|
2497
2516
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToggleField, {
|
|
2498
2517
|
id: "cc-filter-models-by-plan",
|
|
2499
2518
|
label: t("filterModelsByPlan"),
|
|
@@ -5582,6 +5601,165 @@ window.__ModuleLoader__.load({
|
|
|
5582
5601
|
"data-ccp-session-cost-anchor": ""
|
|
5583
5602
|
});
|
|
5584
5603
|
}
|
|
5604
|
+
//#endregion
|
|
5605
|
+
//#region src/client/page-styles.ts
|
|
5606
|
+
/**
|
|
5607
|
+
* Stylesheet for the Command Code settings page — and the Models-page provider
|
|
5608
|
+
* card, which shares its `cc-` classes.
|
|
5609
|
+
*
|
|
5610
|
+
* Returned as a string rather than injected here so the modules stay free of
|
|
5611
|
+
* DOM side effects at import time: `./index.ts` installs it once, keyed by
|
|
5612
|
+
* `PAGE_CSS_ID`. It is a module of its own rather than a literal inside the
|
|
5613
|
+
* client entry so `tests/styles.test.ts` can audit every rule without importing
|
|
5614
|
+
* the React tree (which pulls `*.module.css` through the primitives package and
|
|
5615
|
+
* needs a loader registered first).
|
|
5616
|
+
*
|
|
5617
|
+
* Every colour comes from a harness theme alias with a neutral fallback, so the
|
|
5618
|
+
* page follows the active theme (light/dark and any brand pack) without
|
|
5619
|
+
* hardcoded values. Classes are `cc-` prefixed to stay clear of the panel's
|
|
5620
|
+
* `ccp-` set.
|
|
5621
|
+
*
|
|
5622
|
+
* @module dsh-commandcode-provider/client/page-styles
|
|
5623
|
+
*/
|
|
5624
|
+
/**
|
|
5625
|
+
* Stylesheet id (the `data-plugin-css` value that makes injection idempotent).
|
|
5626
|
+
*
|
|
5627
|
+
* The package prefix must match the one the panel stylesheet uses
|
|
5628
|
+
* (`PANEL_CSS_ID` in `./panel-styles.ts`) and this package's real name: an id is
|
|
5629
|
+
* the injection's identity, so a stale fork prefix would let a second copy of
|
|
5630
|
+
* the plugin inject the same rules twice and would misreport the owner in the
|
|
5631
|
+
* DOM. The two ids must also stay distinct from each other — they key two
|
|
5632
|
+
* separate style tags, and a shared id would make the second injection a no-op
|
|
5633
|
+
* that silently drops one stylesheet.
|
|
5634
|
+
*/
|
|
5635
|
+
const PAGE_CSS_ID = "@mars-sea/dsh-commandcode-provider/CommandCodeSettingsPage.module.css";
|
|
5636
|
+
/** The settings-page stylesheet. */
|
|
5637
|
+
const PAGE_CSS = `
|
|
5638
|
+
.cc-section{max-width:720px;color:var(--dsw-alias-label-primary);flex-direction:column;gap:12px;display:flex}
|
|
5639
|
+
.cc-title{margin:0;font-size:18px;font-weight:600}
|
|
5640
|
+
.cc-intro{color:var(--dsw-alias-label-tertiary);margin:0;font-size:13px;line-height:1.5}
|
|
5641
|
+
.cc-readOnly{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}
|
|
5642
|
+
.cc-card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;padding:4px 16px}
|
|
5643
|
+
.cc-field{flex-direction:column;gap:6px;padding:12px 0;display:flex}
|
|
5644
|
+
.cc-field+.cc-field{border-top:1px solid var(--dsw-alias-border-l2)}
|
|
5645
|
+
.cc-fieldHead{align-items:center;gap:8px;display:flex}
|
|
5646
|
+
.cc-label{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:13px;font-weight:500;line-height:1.5}
|
|
5647
|
+
.cc-badges{align-items:center;gap:8px;display:inline-flex}
|
|
5648
|
+
.cc-badge{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}
|
|
5649
|
+
.cc-badgeMuted{white-space:nowrap;color:var(--dsw-alias-label-tertiary);border-radius:999px;padding:1px 8px;font-size:11px;line-height:17px}
|
|
5650
|
+
.cc-reset{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;padding:0;font-size:12px;line-height:1.5}
|
|
5651
|
+
.cc-reset:hover:not(:disabled){color:var(--dsw-alias-label-primary)}
|
|
5652
|
+
.cc-reset:disabled{cursor:default;opacity:.5}
|
|
5653
|
+
.cc-input{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font-size:13px;line-height:1.5}
|
|
5654
|
+
.cc-input:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}
|
|
5655
|
+
.cc-input:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}
|
|
5656
|
+
/* The routing-rule model multi-select: a button trigger that opens an
|
|
5657
|
+
* anchored Menu of checkbox rows. The trigger mirrors .cc-input sizing so it
|
|
5658
|
+
* sits flush with the sibling account select. */
|
|
5659
|
+
.cc-ruleTrigger{align-items:center;gap:8px;display:flex;width:100%;text-align:left;cursor:pointer}
|
|
5660
|
+
.cc-ruleTrigger:disabled{cursor:default}
|
|
5661
|
+
.cc-ruleTriggerText{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
5662
|
+
.cc-ruleCaret{flex-shrink:0;border-right:1.5px solid var(--dsw-alias-label-tertiary);border-bottom:1.5px solid var(--dsw-alias-label-tertiary);width:6px;height:6px;margin-right:4px;margin-bottom:2px;transform:rotate(45deg)}
|
|
5663
|
+
.cc-checkRow{align-items:center;gap:8px;display:inline-flex;min-width:0}
|
|
5664
|
+
.cc-checkRow:hover{cursor:pointer}
|
|
5665
|
+
.cc-check{appearance:none;flex-shrink:0;width:15px;height:15px;margin:0;border:1px solid var(--dsw-alias-border-l2);border-radius:4px;background:var(--dsw-alias-bg-layer-1);position:relative}
|
|
5666
|
+
.cc-check:checked{background:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary)}
|
|
5667
|
+
.cc-check:checked::after{content:'';position:absolute;top:2px;left:5px;width:3px;height:7px;border:solid #fff;border-width:0 1.5px 1.5px 0;transform:rotate(45deg)}
|
|
5668
|
+
.cc-checkName{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
5669
|
+
/* The model multi-select search box: stacked under the trigger while the
|
|
5670
|
+
* dropdown is open, same input sizing so the pair reads as one control. The
|
|
5671
|
+
* box lives inside the Menu anchor (which renders inside the Menu's root
|
|
5672
|
+
* span), so focusing/typing it never trips the Menu's outside-click close. */
|
|
5673
|
+
.cc-modelSelectAnchor{flex-direction:column;gap:6px;display:flex;width:100%}
|
|
5674
|
+
.cc-modelSearch{width:100%}
|
|
5675
|
+
.cc-modelSearch::-webkit-search-cancel-button{cursor:pointer}
|
|
5676
|
+
/* Selects need their own treatment to sit flush with the text inputs:
|
|
5677
|
+
* the UA stylesheet renders <select> border-box (34px total vs the inputs'
|
|
5678
|
+
* 36px) and forces its own menulist text metrics, so drop the native
|
|
5679
|
+
* chrome entirely (appearance:none), restore content-box so the outer box
|
|
5680
|
+
* matches the inputs again, and draw the chevron ourselves. Longhand
|
|
5681
|
+
* background-* only — the shorthand would reset .cc-input's background. */
|
|
5682
|
+
select.cc-input{appearance:none;-webkit-appearance:none;-moz-appearance:none;box-sizing:content-box;padding-right:32px;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='7' viewBox='0 0 12 7'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23888f98' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 11px center}
|
|
5683
|
+
.cc-inputInvalid{border-color:var(--dsw-alias-label-error)}
|
|
5684
|
+
.cc-invalid{color:var(--dsw-alias-label-error);margin:0;font-size:12px;line-height:1.5}
|
|
5685
|
+
/* The Advanced card: its header row is one full-width toggle button; the
|
|
5686
|
+
* chevron is two borders on a rotated square (no icon dependency). */
|
|
5687
|
+
.cc-advancedHead{align-items:center;gap:8px;display:flex;width:100%;padding:12px 0;background:0 0;border:none;cursor:pointer;font:inherit;text-align:left}
|
|
5688
|
+
.cc-advancedHead:hover .cc-advancedTitle{color:var(--dsw-alias-label-primary)}
|
|
5689
|
+
.cc-advancedTitle{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500;line-height:1.5}
|
|
5690
|
+
.cc-advancedSpacer{flex:1}
|
|
5691
|
+
.cc-chevron{flex-shrink:0;border-right:1.5px solid var(--dsw-alias-label-tertiary);border-bottom:1.5px solid var(--dsw-alias-label-tertiary);width:8px;height:8px;margin-right:4px;margin-bottom:2px;transform:rotate(45deg);transition:transform .15s ease}
|
|
5692
|
+
.cc-chevronUp{transform:rotate(-135deg);margin-bottom:-3px}
|
|
5693
|
+
.cc-advancedBody{flex-direction:column;display:flex}
|
|
5694
|
+
.cc-advancedBody>.cc-field:first-of-type{border-top:1px solid var(--dsw-alias-border-l2)}
|
|
5695
|
+
.cc-hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}
|
|
5696
|
+
.cc-footer{justify-content:flex-end;align-items:center;gap:8px;display:flex}
|
|
5697
|
+
.cc-toggleRow{align-items:center;gap:8px;cursor:pointer;display:flex}
|
|
5698
|
+
.cc-toggleRow:has(.cc-toggle:disabled){cursor:default}
|
|
5699
|
+
.cc-toggle{appearance:none;flex-shrink:0;background:var(--dsw-alias-border-l2);border-radius:999px;width:30px;height:18px;margin:0;cursor:pointer;position:relative;transition:background .15s ease}
|
|
5700
|
+
.cc-toggle:checked{background:var(--dsw-alias-brand-primary)}
|
|
5701
|
+
.cc-toggle::after{content:'';background:#fff;border-radius:50%;width:14px;height:14px;position:absolute;top:2px;left:2px;transition:left .15s ease}
|
|
5702
|
+
.cc-toggle:checked::after{left:14px}
|
|
5703
|
+
.cc-toggle:disabled{cursor:default;opacity:.5}
|
|
5704
|
+
.cc-failed{min-width:0;color:var(--dsw-alias-label-error);flex:1;margin:0;font-size:12px;line-height:1.5}
|
|
5705
|
+
.cc-usageCard{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;padding:14px 16px;flex-direction:column;gap:12px;display:flex}
|
|
5706
|
+
.cc-usageHead{align-items:center;gap:8px;display:flex}
|
|
5707
|
+
.cc-usageTitle{color:var(--dsw-alias-label-primary);flex:1;margin:0;font-size:13px;font-weight:600;line-height:1.5}
|
|
5708
|
+
.cc-usageAccount{max-width:40%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}
|
|
5709
|
+
.cc-usagePlan{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-brand-primary);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:600;line-height:17px}
|
|
5710
|
+
.cc-usagePlanStatus{white-space:nowrap;color:var(--dsw-alias-label-error);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}
|
|
5711
|
+
.cc-usageRefresh{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;padding:0;font-size:12px;line-height:1.5}
|
|
5712
|
+
.cc-usageRefresh:hover:not(:disabled){color:var(--dsw-alias-label-primary)}
|
|
5713
|
+
.cc-usageRefresh:disabled{cursor:default;opacity:.5}
|
|
5714
|
+
.cc-usageHint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}
|
|
5715
|
+
.cc-usageError{align-items:center;gap:8px;color:var(--dsw-alias-label-error);margin:0;font-size:12px;line-height:1.5;display:flex}
|
|
5716
|
+
.cc-usageStats{grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:8px;display:grid}
|
|
5717
|
+
.cc-usageStat{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);border-radius:8px;padding:8px 10px;flex-direction:column;gap:2px;display:flex}
|
|
5718
|
+
.cc-usageStatLabel{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:1.5}
|
|
5719
|
+
.cc-usageStatValue{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}
|
|
5720
|
+
.cc-usageStatSub{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:1.5}
|
|
5721
|
+
.cc-usageWindows{flex-direction:column;gap:16px;display:flex}
|
|
5722
|
+
.cc-usageWindow{flex-direction:column;gap:6px;display:flex}
|
|
5723
|
+
.cc-usageWindowHead{align-items:baseline;gap:8px;display:flex}
|
|
5724
|
+
.cc-usageWindowLabel{color:var(--dsw-alias-label-secondary);flex:1;font-size:12px;font-weight:500;line-height:1.5}
|
|
5725
|
+
.cc-usageWindowValue{color:var(--dsw-alias-label-primary);font-size:12px;font-weight:500;line-height:1.5}
|
|
5726
|
+
.cc-usageExceeded{color:var(--dsw-alias-label-error);font-size:11px;font-weight:500;line-height:1.5}
|
|
5727
|
+
.cc-usageBar{overflow:hidden;background:var(--dsw-alias-bg-layer-1);border-radius:999px;height:6px}
|
|
5728
|
+
.cc-usageBarFill{background:var(--dsw-alias-brand-primary);border-radius:999px;height:100%;transition:width .3s ease}
|
|
5729
|
+
.cc-usageBarFillWarn{background:var(--dsw-alias-label-error)}
|
|
5730
|
+
@media (prefers-reduced-motion:reduce){.cc-chevron,.cc-toggle,.cc-toggle::after,.cc-usageBarFill{transition:none}}.cc-usageWindowReset{color:var(--dsw-alias-label-tertiary);margin:0;font-size:11px;line-height:1.5}
|
|
5731
|
+
.cc-usageMeta{align-items:center;gap:8px;display:flex}
|
|
5732
|
+
.cc-accountReport{flex-direction:column;gap:12px;display:flex}
|
|
5733
|
+
.cc-tabs{flex-wrap:wrap;gap:6px;display:flex}
|
|
5734
|
+
.cc-tab{align-items:center;font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);border-radius:999px;padding:2px 10px;font-size:12px;line-height:18px;display:inline-flex;gap:6px}
|
|
5735
|
+
.cc-tab:hover:not(.cc-tabActive){color:var(--dsw-alias-label-primary)}
|
|
5736
|
+
.cc-tabActive{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-brand-primary)}
|
|
5737
|
+
.cc-tabDotOk{background:var(--dsw-alias-brand-primary);border-radius:50%;width:6px;height:6px}
|
|
5738
|
+
.cc-tabDotWarn{background:#d97706;border-radius:50%;width:6px;height:6px}
|
|
5739
|
+
.cc-tabDotError{background:var(--dsw-alias-label-error);border-radius:50%;width:6px;height:6px}
|
|
5740
|
+
.cc-usageMetaSpacer{flex:1}
|
|
5741
|
+
.cc-usageUpdated{color:var(--dsw-alias-label-tertiary);margin:0;font-size:11px;line-height:1.5}
|
|
5742
|
+
.cc-usagePartial{color:var(--dsw-alias-label-error);margin:0;font-size:11px;line-height:1.5}
|
|
5743
|
+
.cc-usageBlocked{border:1px solid var(--dsw-alias-label-error);border-radius:10px;padding:10px 12px;display:flex;flex-direction:column;gap:4px}
|
|
5744
|
+
.cc-usageBlockedTitle{color:var(--dsw-alias-label-error);margin:0;font-size:13px;font-weight:600;line-height:1.5}
|
|
5745
|
+
.cc-usageBlockedHint{color:var(--dsw-alias-label-secondary);margin:0;font-size:12px;line-height:1.5}
|
|
5746
|
+
.cc-version{margin:4px 0 0;text-align:center;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5}
|
|
5747
|
+
/* The Models-page provider panel root: unstyled by design — the row card the
|
|
5748
|
+
* Models page owns supplies the surface, the panel only stacks its controls. */
|
|
5749
|
+
.cc-providerCard{flex-direction:column;display:flex}
|
|
5750
|
+
/* The update hint rides the footer version line: warning-tinted (with a
|
|
5751
|
+
* muted fallback for themes without the alias), quiet until hovered. */
|
|
5752
|
+
.cc-versionLink{color:var(--dsw-alias-state-warning-primary,var(--dsw-alias-label-secondary));text-decoration:none}
|
|
5753
|
+
.cc-versionLink:hover{color:var(--dsw-alias-label-primary);text-decoration:underline;text-underline-position:under}
|
|
5754
|
+
/* The login panel rides the connection card as one more field row; the
|
|
5755
|
+
* authorization link is the only branded element on it. */
|
|
5756
|
+
.cc-loginLink{color:var(--dsw-alias-brand-primary);text-decoration:none;font-size:12px;line-height:1.5}
|
|
5757
|
+
.cc-loginLink:hover{text-decoration:underline;text-underline-position:under}
|
|
5758
|
+
.cc-loginDone{color:var(--dsw-alias-state-success-primary,var(--dsw-alias-label-secondary))}
|
|
5759
|
+
.cc-loginError{color:var(--dsw-alias-label-error)}
|
|
5760
|
+
.cc-saved{color:var(--dsw-alias-state-success-primary,var(--dsw-alias-label-secondary));margin:0;font-size:12px;font-weight:500;line-height:1.5}
|
|
5761
|
+
.cc-badgeWarn{background:var(--dsw-alias-state-warning-secondary,var(--dsw-alias-bg-module-platform));color:var(--dsw-alias-state-warning-primary,var(--dsw-alias-label-secondary))}
|
|
5762
|
+
`;
|
|
5585
5763
|
//#endregion
|
|
5586
5764
|
//#region src/client/panel-styles.ts
|
|
5587
5765
|
/**
|
|
@@ -5590,8 +5768,16 @@ window.__ModuleLoader__.load({
|
|
|
5590
5768
|
*
|
|
5591
5769
|
* Returned as a string rather than injected here so the modules stay free of
|
|
5592
5770
|
* DOM side effects at import time — the client entry installs it once, keyed
|
|
5593
|
-
* by the same `data-plugin-css` attribute the settings-page stylesheet
|
|
5594
|
-
* and removes it again when the plugin's fiber
|
|
5771
|
+
* by the same `data-plugin-css` attribute the settings-page stylesheet
|
|
5772
|
+
* (`./page-styles.ts`) uses, and removes it again when the plugin's fiber
|
|
5773
|
+
* unwinds.
|
|
5774
|
+
*
|
|
5775
|
+
* These rules are GLOBAL CSS: every selector in here can match markup this
|
|
5776
|
+
* plugin did not render. So each one is either qualified by a `ccp-` class of
|
|
5777
|
+
* our own, or anchored to the sidebar region it has to lay out — and the one
|
|
5778
|
+
* foreign anchor carries its justification in place (see the footer card
|
|
5779
|
+
* block; issue #48). `tests/styles.test.ts` audits that containment for both
|
|
5780
|
+
* stylesheets and simulates it against the real foreign class stems.
|
|
5595
5781
|
*
|
|
5596
5782
|
* Every colour comes from a harness theme alias with a neutral fallback, so
|
|
5597
5783
|
* the panel follows the active theme (light/dark and any brand pack) without
|
|
@@ -5604,9 +5790,12 @@ window.__ModuleLoader__.load({
|
|
|
5604
5790
|
* Stylesheet id (the `data-plugin-css` value that makes injection idempotent).
|
|
5605
5791
|
*
|
|
5606
5792
|
* The package prefix must match the one the settings-page stylesheet uses
|
|
5607
|
-
* (`
|
|
5608
|
-
* injection's identity, so a stale fork prefix would let a second copy of
|
|
5609
|
-
* plugin inject the same rules twice and would misreport the owner in the
|
|
5793
|
+
* (`PAGE_CSS_ID` in `./page-styles.ts`) and this package's real name: an id is
|
|
5794
|
+
* the injection's identity, so a stale fork prefix would let a second copy of
|
|
5795
|
+
* the plugin inject the same rules twice and would misreport the owner in the
|
|
5796
|
+
* DOM. The two ids must also stay distinct from each other — they key two
|
|
5797
|
+
* separate style tags, and a shared id would make the second injection a no-op
|
|
5798
|
+
* that silently drops one stylesheet.
|
|
5610
5799
|
*/
|
|
5611
5800
|
const PANEL_CSS_ID = "@mars-sea/dsh-commandcode-provider/CommandCodePanel.module.css";
|
|
5612
5801
|
/** The panel stylesheet. */
|
|
@@ -5620,11 +5809,28 @@ window.__ModuleLoader__.load({
|
|
|
5620
5809
|
|
|
5621
5810
|
The shell's container is a flex ROW whose occupants (this card and ui-cordis's
|
|
5622
5811
|
footer chip) each declare a full-width line and shrink-proof flex, so as a row
|
|
5623
|
-
it would overflow the column
|
|
5624
|
-
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
|
|
5812
|
+
it would overflow the column: this card's flex:0 0 auto cannot shrink, and the
|
|
5813
|
+
chip's width:100% basis would absorb the whole overflow and collapse to
|
|
5814
|
+
nothing. Both were written for a full-width line, which is exactly what a
|
|
5815
|
+
column gives them. Matched by the CSS-module class STEM — never a hashed name
|
|
5816
|
+
— so a dsh that renames it degrades to the shell's own row rather than
|
|
5817
|
+
breaking.
|
|
5818
|
+
|
|
5819
|
+
THE ANCHOR IS LOAD-BEARING, and it is the whole reason this selector is not
|
|
5820
|
+
just [class*="_footerActions"] (issue #48). "footerActions" is NOT a stem this
|
|
5821
|
+
shell owns alone: @deepseek-ai/dsh-client-ui-user-questions renders the
|
|
5822
|
+
ask-user-question dialog's button row as Mbwy4a_footerActions, so the
|
|
5823
|
+
unanchored rule forced THAT row into a column too and stacked the dialog's
|
|
5824
|
+
side-by-side buttons on every page. "footArea" is declared by
|
|
5825
|
+
dsh-client-ui-sidebar alone — verified against every client bundle of the
|
|
5826
|
+
0.1.6-alpha.1 engine, and against our own cc-/ccp- class names, which collide
|
|
5827
|
+
with no engine class — so anchoring under it keeps the sidebar layout fix and
|
|
5828
|
+
cannot reach another component's markup. The descendant combinator (rather
|
|
5829
|
+
than a child one) deliberately survives a wrapper element appearing between
|
|
5830
|
+
the two: a renamed or restructured shell should degrade to its own row, not
|
|
5831
|
+
lose the fix. tests/styles.test.ts pins both halves of this — the dialog row
|
|
5832
|
+
is no longer matched, the sidebar row still is. */
|
|
5833
|
+
[class*="_footArea"] [class*="_footerActions"]{flex-direction:column}
|
|
5628
5834
|
.ccp-foot{box-sizing:border-box;flex:0 0 auto;width:100%;min-width:0;font:inherit;color:var(--dsw-alias-label-secondary);text-align:left;cursor:pointer;background:0 0;border:1px solid transparent;border-radius:10px;flex-direction:column;gap:6px;margin:0 0 4px;padding:8px;display:flex}
|
|
5629
5835
|
.ccp-foot:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover);border-color:var(--dsw-alias-border-l2)}
|
|
5630
5836
|
.ccp-foot:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}
|
|
@@ -5750,6 +5956,8 @@ window.__ModuleLoader__.load({
|
|
|
5750
5956
|
requestTimeoutMsHint: "等待响应首个字节的超时;默认 60000。",
|
|
5751
5957
|
streamIdleTimeoutMs: "流空闲超时(毫秒)",
|
|
5752
5958
|
streamIdleTimeoutMsHint: "生成流停滞多久视为断连;默认 300000(长思考模型可静默数分钟,默认值刻意放宽)。",
|
|
5959
|
+
transportMaxRetries: "网络失败重试次数",
|
|
5960
|
+
transportMaxRetriesHint: "连接失败时自动重试几次,默认 5(各次等待 0.5+1+2+4+8 秒,合计约 15 秒)。超过后直接报错,不再按指数退避长时间等待;填 0 表示不重试。限流、5xx 等由服务端要求重试的失败不受此项影响。",
|
|
5753
5961
|
advancedSettings: "高级设置",
|
|
5754
5962
|
advancedSettingsHint: "API 地址、工作目录、超时、模型过滤、联网搜索与侧边栏额度卡片等不常修改的选项。",
|
|
5755
5963
|
advancedOverriddenOne: "已自定义 1 项",
|
|
@@ -5884,6 +6092,8 @@ window.__ModuleLoader__.load({
|
|
|
5884
6092
|
requestTimeoutMsHint: "Time to wait for the first response byte; default 60000.",
|
|
5885
6093
|
streamIdleTimeoutMs: "Stream idle timeout (ms)",
|
|
5886
6094
|
streamIdleTimeoutMsHint: "How long a stalled stream is treated as dead; default 300000 (deliberately generous — long-thinking models can stay silent for minutes).",
|
|
6095
|
+
transportMaxRetries: "Transport retries",
|
|
6096
|
+
transportMaxRetriesHint: "How many times a failed connection is retried automatically; default 5 (waits of 0.5+1+2+4+8s, ~15s in total). After that the failure is reported instead of waiting on the exponential backoff. 0 disables the retries. Rate limits and 5xx answers keep their own, longer retry window.",
|
|
5887
6097
|
advancedSettings: "Advanced",
|
|
5888
6098
|
advancedSettingsHint: "Rarely touched options: API base URL, working directory, timeouts, model filtering, web search, and the sidebar quota card.",
|
|
5889
6099
|
advancedOverriddenOne: "1 customized",
|
|
@@ -6003,141 +6213,13 @@ window.__ModuleLoader__.load({
|
|
|
6003
6213
|
};
|
|
6004
6214
|
//#endregion
|
|
6005
6215
|
//#region src/client/index.ts
|
|
6006
|
-
/** CSS for the settings page, injected once (harness bundle convention). */
|
|
6007
|
-
const PAGE_CSS = `
|
|
6008
|
-
.cc-section{max-width:720px;color:var(--dsw-alias-label-primary);flex-direction:column;gap:12px;display:flex}
|
|
6009
|
-
.cc-title{margin:0;font-size:18px;font-weight:600}
|
|
6010
|
-
.cc-intro{color:var(--dsw-alias-label-tertiary);margin:0;font-size:13px;line-height:1.5}
|
|
6011
|
-
.cc-readOnly{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}
|
|
6012
|
-
.cc-card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;padding:4px 16px}
|
|
6013
|
-
.cc-field{flex-direction:column;gap:6px;padding:12px 0;display:flex}
|
|
6014
|
-
.cc-field+.cc-field{border-top:1px solid var(--dsw-alias-border-l2)}
|
|
6015
|
-
.cc-fieldHead{align-items:center;gap:8px;display:flex}
|
|
6016
|
-
.cc-label{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:13px;font-weight:500;line-height:1.5}
|
|
6017
|
-
.cc-badges{align-items:center;gap:8px;display:inline-flex}
|
|
6018
|
-
.cc-badge{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}
|
|
6019
|
-
.cc-badgeMuted{white-space:nowrap;color:var(--dsw-alias-label-tertiary);border-radius:999px;padding:1px 8px;font-size:11px;line-height:17px}
|
|
6020
|
-
.cc-reset{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;padding:0;font-size:12px;line-height:1.5}
|
|
6021
|
-
.cc-reset:hover:not(:disabled){color:var(--dsw-alias-label-primary)}
|
|
6022
|
-
.cc-reset:disabled{cursor:default;opacity:.5}
|
|
6023
|
-
.cc-input{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font-size:13px;line-height:1.5}
|
|
6024
|
-
.cc-input:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}
|
|
6025
|
-
.cc-input:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}
|
|
6026
|
-
/* The routing-rule model multi-select: a button trigger that opens an
|
|
6027
|
-
* anchored Menu of checkbox rows. The trigger mirrors .cc-input sizing so it
|
|
6028
|
-
* sits flush with the sibling account select. */
|
|
6029
|
-
.cc-ruleTrigger{align-items:center;gap:8px;display:flex;width:100%;text-align:left;cursor:pointer}
|
|
6030
|
-
.cc-ruleTrigger:disabled{cursor:default}
|
|
6031
|
-
.cc-ruleTriggerText{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
6032
|
-
.cc-ruleCaret{flex-shrink:0;border-right:1.5px solid var(--dsw-alias-label-tertiary);border-bottom:1.5px solid var(--dsw-alias-label-tertiary);width:6px;height:6px;margin-right:4px;margin-bottom:2px;transform:rotate(45deg)}
|
|
6033
|
-
.cc-checkRow{align-items:center;gap:8px;display:inline-flex;min-width:0}
|
|
6034
|
-
.cc-checkRow:hover{cursor:pointer}
|
|
6035
|
-
.cc-check{appearance:none;flex-shrink:0;width:15px;height:15px;margin:0;border:1px solid var(--dsw-alias-border-l2);border-radius:4px;background:var(--dsw-alias-bg-layer-1);position:relative}
|
|
6036
|
-
.cc-check:checked{background:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary)}
|
|
6037
|
-
.cc-check:checked::after{content:'';position:absolute;top:2px;left:5px;width:3px;height:7px;border:solid #fff;border-width:0 1.5px 1.5px 0;transform:rotate(45deg)}
|
|
6038
|
-
.cc-checkName{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
6039
|
-
/* The model multi-select search box: stacked under the trigger while the
|
|
6040
|
-
* dropdown is open, same input sizing so the pair reads as one control. The
|
|
6041
|
-
* box lives inside the Menu anchor (which renders inside the Menu's root
|
|
6042
|
-
* span), so focusing/typing it never trips the Menu's outside-click close. */
|
|
6043
|
-
.cc-modelSelectAnchor{flex-direction:column;gap:6px;display:flex;width:100%}
|
|
6044
|
-
.cc-modelSearch{width:100%}
|
|
6045
|
-
.cc-modelSearch::-webkit-search-cancel-button{cursor:pointer}
|
|
6046
|
-
/* Selects need their own treatment to sit flush with the text inputs:
|
|
6047
|
-
* the UA stylesheet renders <select> border-box (34px total vs the inputs'
|
|
6048
|
-
* 36px) and forces its own menulist text metrics, so drop the native
|
|
6049
|
-
* chrome entirely (appearance:none), restore content-box so the outer box
|
|
6050
|
-
* matches the inputs again, and draw the chevron ourselves. Longhand
|
|
6051
|
-
* background-* only — the shorthand would reset .cc-input's background. */
|
|
6052
|
-
select.cc-input{appearance:none;-webkit-appearance:none;-moz-appearance:none;box-sizing:content-box;padding-right:32px;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='7' viewBox='0 0 12 7'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23888f98' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 11px center}
|
|
6053
|
-
.cc-inputInvalid{border-color:var(--dsw-alias-label-error)}
|
|
6054
|
-
.cc-invalid{color:var(--dsw-alias-label-error);margin:0;font-size:12px;line-height:1.5}
|
|
6055
|
-
/* The Advanced card: its header row is one full-width toggle button; the
|
|
6056
|
-
* chevron is two borders on a rotated square (no icon dependency). */
|
|
6057
|
-
.cc-advancedHead{align-items:center;gap:8px;display:flex;width:100%;padding:12px 0;background:0 0;border:none;cursor:pointer;font:inherit;text-align:left}
|
|
6058
|
-
.cc-advancedHead:hover .cc-advancedTitle{color:var(--dsw-alias-label-primary)}
|
|
6059
|
-
.cc-advancedTitle{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500;line-height:1.5}
|
|
6060
|
-
.cc-advancedSpacer{flex:1}
|
|
6061
|
-
.cc-chevron{flex-shrink:0;border-right:1.5px solid var(--dsw-alias-label-tertiary);border-bottom:1.5px solid var(--dsw-alias-label-tertiary);width:8px;height:8px;margin-right:4px;margin-bottom:2px;transform:rotate(45deg);transition:transform .15s ease}
|
|
6062
|
-
.cc-chevronUp{transform:rotate(-135deg);margin-bottom:-3px}
|
|
6063
|
-
.cc-advancedBody{flex-direction:column;display:flex}
|
|
6064
|
-
.cc-advancedBody>.cc-field:first-of-type{border-top:1px solid var(--dsw-alias-border-l2)}
|
|
6065
|
-
.cc-hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}
|
|
6066
|
-
.cc-footer{justify-content:flex-end;align-items:center;gap:8px;display:flex}
|
|
6067
|
-
.cc-toggleRow{align-items:center;gap:8px;cursor:pointer;display:flex}
|
|
6068
|
-
.cc-toggleRow:has(.cc-toggle:disabled){cursor:default}
|
|
6069
|
-
.cc-toggle{appearance:none;flex-shrink:0;background:var(--dsw-alias-border-l2);border-radius:999px;width:30px;height:18px;margin:0;cursor:pointer;position:relative;transition:background .15s ease}
|
|
6070
|
-
.cc-toggle:checked{background:var(--dsw-alias-brand-primary)}
|
|
6071
|
-
.cc-toggle::after{content:'';background:#fff;border-radius:50%;width:14px;height:14px;position:absolute;top:2px;left:2px;transition:left .15s ease}
|
|
6072
|
-
.cc-toggle:checked::after{left:14px}
|
|
6073
|
-
.cc-toggle:disabled{cursor:default;opacity:.5}
|
|
6074
|
-
.cc-failed{min-width:0;color:var(--dsw-alias-label-error);flex:1;margin:0;font-size:12px;line-height:1.5}
|
|
6075
|
-
.cc-usageCard{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;padding:14px 16px;flex-direction:column;gap:12px;display:flex}
|
|
6076
|
-
.cc-usageHead{align-items:center;gap:8px;display:flex}
|
|
6077
|
-
.cc-usageTitle{color:var(--dsw-alias-label-primary);flex:1;margin:0;font-size:13px;font-weight:600;line-height:1.5}
|
|
6078
|
-
.cc-usageAccount{max-width:40%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}
|
|
6079
|
-
.cc-usagePlan{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-brand-primary);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:600;line-height:17px}
|
|
6080
|
-
.cc-usagePlanStatus{white-space:nowrap;color:var(--dsw-alias-label-error);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}
|
|
6081
|
-
.cc-usageRefresh{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;padding:0;font-size:12px;line-height:1.5}
|
|
6082
|
-
.cc-usageRefresh:hover:not(:disabled){color:var(--dsw-alias-label-primary)}
|
|
6083
|
-
.cc-usageRefresh:disabled{cursor:default;opacity:.5}
|
|
6084
|
-
.cc-usageHint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}
|
|
6085
|
-
.cc-usageError{align-items:center;gap:8px;color:var(--dsw-alias-label-error);margin:0;font-size:12px;line-height:1.5;display:flex}
|
|
6086
|
-
.cc-usageStats{grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:8px;display:grid}
|
|
6087
|
-
.cc-usageStat{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);border-radius:8px;padding:8px 10px;flex-direction:column;gap:2px;display:flex}
|
|
6088
|
-
.cc-usageStatLabel{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:1.5}
|
|
6089
|
-
.cc-usageStatValue{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}
|
|
6090
|
-
.cc-usageStatSub{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:1.5}
|
|
6091
|
-
.cc-usageWindows{flex-direction:column;gap:16px;display:flex}
|
|
6092
|
-
.cc-usageWindow{flex-direction:column;gap:6px;display:flex}
|
|
6093
|
-
.cc-usageWindowHead{align-items:baseline;gap:8px;display:flex}
|
|
6094
|
-
.cc-usageWindowLabel{color:var(--dsw-alias-label-secondary);flex:1;font-size:12px;font-weight:500;line-height:1.5}
|
|
6095
|
-
.cc-usageWindowValue{color:var(--dsw-alias-label-primary);font-size:12px;font-weight:500;line-height:1.5}
|
|
6096
|
-
.cc-usageExceeded{color:var(--dsw-alias-label-error);font-size:11px;font-weight:500;line-height:1.5}
|
|
6097
|
-
.cc-usageBar{overflow:hidden;background:var(--dsw-alias-bg-layer-1);border-radius:999px;height:6px}
|
|
6098
|
-
.cc-usageBarFill{background:var(--dsw-alias-brand-primary);border-radius:999px;height:100%;transition:width .3s ease}
|
|
6099
|
-
.cc-usageBarFillWarn{background:var(--dsw-alias-label-error)}
|
|
6100
|
-
@media (prefers-reduced-motion:reduce){.cc-chevron,.cc-toggle,.cc-toggle::after,.cc-usageBarFill{transition:none}}.cc-usageWindowReset{color:var(--dsw-alias-label-tertiary);margin:0;font-size:11px;line-height:1.5}
|
|
6101
|
-
.cc-usageMeta{align-items:center;gap:8px;display:flex}
|
|
6102
|
-
.cc-accountReport{flex-direction:column;gap:12px;display:flex}
|
|
6103
|
-
.cc-tabs{flex-wrap:wrap;gap:6px;display:flex}
|
|
6104
|
-
.cc-tab{align-items:center;font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);border-radius:999px;padding:2px 10px;font-size:12px;line-height:18px;display:inline-flex;gap:6px}
|
|
6105
|
-
.cc-tab:hover:not(.cc-tabActive){color:var(--dsw-alias-label-primary)}
|
|
6106
|
-
.cc-tabActive{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-brand-primary)}
|
|
6107
|
-
.cc-tabDotOk{background:var(--dsw-alias-brand-primary);border-radius:50%;width:6px;height:6px}
|
|
6108
|
-
.cc-tabDotWarn{background:#d97706;border-radius:50%;width:6px;height:6px}
|
|
6109
|
-
.cc-tabDotError{background:var(--dsw-alias-label-error);border-radius:50%;width:6px;height:6px}
|
|
6110
|
-
.cc-usageMetaSpacer{flex:1}
|
|
6111
|
-
.cc-usageUpdated{color:var(--dsw-alias-label-tertiary);margin:0;font-size:11px;line-height:1.5}
|
|
6112
|
-
.cc-usagePartial{color:var(--dsw-alias-label-error);margin:0;font-size:11px;line-height:1.5}
|
|
6113
|
-
.cc-usageBlocked{border:1px solid var(--dsw-alias-label-error);border-radius:10px;padding:10px 12px;display:flex;flex-direction:column;gap:4px}
|
|
6114
|
-
.cc-usageBlockedTitle{color:var(--dsw-alias-label-error);margin:0;font-size:13px;font-weight:600;line-height:1.5}
|
|
6115
|
-
.cc-usageBlockedHint{color:var(--dsw-alias-label-secondary);margin:0;font-size:12px;line-height:1.5}
|
|
6116
|
-
.cc-version{margin:4px 0 0;text-align:center;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5}
|
|
6117
|
-
/* The Models-page provider panel root: unstyled by design — the row card the
|
|
6118
|
-
* Models page owns supplies the surface, the panel only stacks its controls. */
|
|
6119
|
-
.cc-providerCard{flex-direction:column;display:flex}
|
|
6120
|
-
/* The update hint rides the footer version line: warning-tinted (with a
|
|
6121
|
-
* muted fallback for themes without the alias), quiet until hovered. */
|
|
6122
|
-
.cc-versionLink{color:var(--dsw-alias-state-warning-primary,var(--dsw-alias-label-secondary));text-decoration:none}
|
|
6123
|
-
.cc-versionLink:hover{color:var(--dsw-alias-label-primary);text-decoration:underline;text-underline-position:under}
|
|
6124
|
-
/* The login panel rides the connection card as one more field row; the
|
|
6125
|
-
* authorization link is the only branded element on it. */
|
|
6126
|
-
.cc-loginLink{color:var(--dsw-alias-brand-primary);text-decoration:none;font-size:12px;line-height:1.5}
|
|
6127
|
-
.cc-loginLink:hover{text-decoration:underline;text-underline-position:under}
|
|
6128
|
-
.cc-loginDone{color:var(--dsw-alias-state-success-primary,var(--dsw-alias-label-secondary))}
|
|
6129
|
-
.cc-loginError{color:var(--dsw-alias-label-error)}
|
|
6130
|
-
.cc-saved{color:var(--dsw-alias-state-success-primary,var(--dsw-alias-label-secondary));margin:0;font-size:12px;font-weight:500;line-height:1.5}
|
|
6131
|
-
.cc-badgeWarn{background:var(--dsw-alias-state-warning-secondary,var(--dsw-alias-bg-module-platform));color:var(--dsw-alias-state-warning-primary,var(--dsw-alias-label-secondary))}
|
|
6132
|
-
`;
|
|
6133
6216
|
/** Inject the page stylesheet once (idempotent per tag). */
|
|
6134
6217
|
function injectPageCss() {
|
|
6135
6218
|
if (typeof document === "undefined") return;
|
|
6136
|
-
|
|
6137
|
-
if (document.querySelector(`style[data-plugin-css="${id}"]`) !== null) return;
|
|
6219
|
+
if (document.querySelector(`style[data-plugin-css="@mars-sea/dsh-commandcode-provider/CommandCodeSettingsPage.module.css"]`) !== null) return;
|
|
6138
6220
|
const tag = document.createElement("style");
|
|
6139
6221
|
tag.dataset.plugin = "@mars-sea/dsh-commandcode-provider";
|
|
6140
|
-
tag.dataset.pluginCss =
|
|
6222
|
+
tag.dataset.pluginCss = PAGE_CSS_ID;
|
|
6141
6223
|
tag.textContent = PAGE_CSS;
|
|
6142
6224
|
document.head.appendChild(tag);
|
|
6143
6225
|
}
|