dsh-mnemon 0.5.27 → 0.5.28

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/lib/client.js CHANGED
@@ -30,6 +30,14 @@ window.__ModuleLoader__.load({
30
30
  const MNEMON_WRITE_CHANNEL = "/dsh-mnemon-write";
31
31
  const MNEMON_PACK_CHANNEL = "/dsh-mnemon-pack";
32
32
  const MNEMON_SYNC_CHANNEL = "/dsh-mnemon-sync";
33
+ /**
34
+ * The credential environment variable the sync channel reads before its stored
35
+ * token. The name travels to the browser so the settings form can tell the user
36
+ * which variable wins; the value never does.
37
+ */
38
+ const MNEMON_SYNC_TOKEN_ENV = "MNEMON_SYNC_GIT_TOKEN";
39
+ const MNEMON_SYNC_DEFAULT_AUTHOR_NAME = "dsh-mnemon sync";
40
+ const MNEMON_SYNC_DEFAULT_AUTHOR_EMAIL = "mnemon@localhost";
33
41
  const MNEMON_SETTINGS_CHANNEL = "/dsh-mnemon-settings";
34
42
  /**
35
43
  * Reconciliation is the only channel that changes memory after a human read it:
@@ -269,7 +277,10 @@ window.__ModuleLoader__.load({
269
277
  }
270
278
  async call(channel, endpoint, payload) {
271
279
  const response = await callMnemonRpc(this.connection, channel, endpoint, payload);
272
- if (!response.ok) throw new Error(response.error.message);
280
+ if (!response.ok) {
281
+ const reason = response.error.details?.reason;
282
+ throw Object.assign(new Error(response.error.message), typeof reason === "string" ? { reason } : {});
283
+ }
273
284
  return response.value;
274
285
  }
275
286
  scoped(payload = {}) {
@@ -662,7 +673,7 @@ window.__ModuleLoader__.load({
662
673
  }
663
674
  //#endregion
664
675
  //#region \0dsh-mnemon-css:/home/runner/work/dsh-mnemon/dsh-mnemon/src/client/MnemonSettingsCard.module.css.mjs
665
- const css$13 = "._v_wrq_page{box-sizing:border-box;width:100%;min-width:0;color:var(--dsw-alias-label-primary);flex-direction:column;gap:32px;font-family:inherit;display:flex}._v_wrq_surface{color:var(--dsw-alias-label-primary)}:where(._v_wrq_page,._v_wrq_surface) *,:where(._v_wrq_page,._v_wrq_surface) :before,:where(._v_wrq_page,._v_wrq_surface) :after{box-sizing:border-box}:where(._v_wrq_page,._v_wrq_surface) :where(button,input,select,textarea){color:inherit;font:inherit}._v_wrq_loading{min-height:140px;color:var(--dsw-alias-label-tertiary);text-align:center;margin:0;font-size:13px;line-height:140px}._v_wrq_section{flex-direction:column;gap:4px;min-width:0;display:flex}._v_wrq_sectionHeading{grid-template-columns:minmax(0,1fr) auto;align-items:start;column-gap:12px;min-width:0;display:grid}._v_wrq_sectionHeading h2{grid-column:1;margin:0;font-size:14px;font-weight:500;line-height:20px}._v_wrq_sectionHeading p{max-width:66ch;color:var(--dsw-alias-label-tertiary);grid-column:1;margin:2px 0 0;font-size:12px;line-height:18px}._v_wrq_sectionHeading ._v_wrq_miniSpinner{grid-area:1/2}._v_wrq_sectionHeading>._v_wrq_boardLinks{grid-column:1;padding-top:6px}._v_wrq_componentListNote{max-width:72ch;color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}._v_wrq_appliesNow{border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-xs);color:var(--dsw-alias-label-secondary);white-space:nowrap;grid-area:1/2;align-self:center;padding:1px 6px;font-size:11px;line-height:16px}._v_wrq_rows{flex-direction:column;min-width:0;display:flex}._v_wrq_settingRow,._v_wrq_toggleRow{border-bottom:.5px solid var(--dsw-alias-border-l2);flex-wrap:wrap;justify-content:space-between;align-items:center;gap:8px 16px;min-width:0;padding:14px 0;display:flex;position:relative}._v_wrq_rows>:last-child,._v_wrq_rows>._v_wrq_packRow:last-child>._v_wrq_settingRow{border-bottom:0}._v_wrq_rows>._v_wrq_packRow:last-child{padding-bottom:0}._v_wrq_settingRow[data-stacked]{flex-direction:column;align-items:stretch}._v_wrq_settingCopy{flex-direction:column;flex:1 1 0;gap:2px;min-width:min(240px,100%);display:flex}._v_wrq_settingCopy strong,._v_wrq_settingCopy label{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:400;line-height:22px}._v_wrq_settingCopy small{color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;font-size:12px;line-height:18px}._v_wrq_settingCopy code{font-family:var(--ds-font-family-code,ui-monospace, monospace)}._v_wrq_settingControl{flex:none;justify-content:flex-end;align-items:center;gap:8px;min-width:0;display:flex}._v_wrq_settingRow[data-stacked] ._v_wrq_settingControl{flex:auto;justify-content:stretch}._v_wrq_switch{flex:none}._v_wrq_rowNote{min-width:0;color:var(--dsw-alias-label-secondary);flex-wrap:wrap;align-items:center;gap:4px 8px;padding-top:4px;font-size:12px;line-height:18px;display:flex}._v_wrq_groupCallout{margin:8px 0 4px}._v_wrq_boardSection{container-type:inline-size}._v_wrq_board{flex-direction:column;min-width:0;margin-top:10px;display:flex}._v_wrq_boardProblem{margin:0 0 4px}._v_wrq_boardLoading{min-height:40px;color:var(--dsw-alias-label-secondary);align-items:center;gap:8px;margin:0;font-size:13px;line-height:20px;display:flex}._v_wrq_boardGroup{flex-direction:column;min-width:0;padding-top:14px;display:flex}._v_wrq_boardGroupHead{justify-content:space-between;align-items:baseline;gap:8px;min-width:0;display:flex}._v_wrq_boardGroupHead h3{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;font-weight:500;line-height:18px}._v_wrq_boardGroupHead span{color:var(--dsw-alias-label-tertiary);white-space:nowrap;font-size:12px;line-height:18px}._v_wrq_pageLink{appearance:none;border-radius:var(--dsw-radius-sm);max-width:100%;color:inherit;font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;align-items:center;padding:0;display:inline-flex}._v_wrq_pageLink>span{overflow-wrap:anywhere;min-width:0}._v_wrq_pageLink:hover>span{text-underline-offset:3px;text-decoration:underline}._v_wrq_settingCopy ._v_wrq_pageLink{width:fit-content;color:var(--dsw-alias-label-primary);font-size:14px;line-height:22px}._v_wrq_boardIconButton{border-radius:var(--dsw-radius-sm);width:28px;height:28px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;flex:none;place-items:center;padding:0;display:inline-grid}._v_wrq_boardIconButton:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}._v_wrq_boardLinks{flex-wrap:wrap;align-items:center;gap:4px;min-width:0;padding-top:4px;display:flex}._v_wrq_boardLink{appearance:none;border:.5px solid var(--dsw-alias-border-l3);max-width:100%;color:var(--dsw-alias-label-tertiary);font:inherit;white-space:nowrap;cursor:pointer;background:0 0;border-radius:999px;align-items:center;gap:4px;padding:0 8px;font-size:11px;line-height:18px;transition:color .12s,border-color .12s;display:inline-flex}._v_wrq_boardLink[data-on]{color:var(--dsw-alias-label-secondary)}._v_wrq_boardLink:hover{border-color:var(--dsw-alias-border-l4);color:var(--dsw-alias-label-primary)}._v_wrq_boardLink>svg{flex:none}._v_wrq_boardLinksLabel{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}._v_wrq_pageLink:focus-visible,._v_wrq_boardIconButton:focus-visible,._v_wrq_boardLink:focus-visible,._v_wrq_detailsBack:focus-visible,._v_wrq_boardSearch:focus-within{box-shadow:0 0 0 2px var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline:none}._v_wrq_boardSearch{border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-md);min-width:0;color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-bg-base);align-items:center;gap:8px;margin:12px 0 0;padding:0 10px;display:flex}._v_wrq_boardSearch input{min-width:0;height:32px;color:var(--dsw-alias-label-primary);font:inherit;background:0 0;border:0;outline:none;flex:1;font-size:13px}._v_wrq_detailsDialog{width:min(560px,100%);max-height:100%}._v_wrq_detailsScroll{overscroll-behavior:contain;min-height:0;overflow-y:auto}._v_wrq_detailsBody{flex-direction:column;gap:16px;min-width:0;display:flex}._v_wrq_detailsHead{flex-direction:column;gap:6px;min-width:0;display:flex}._v_wrq_detailsHeadLine{flex-wrap:wrap;align-items:center;gap:8px 10px;min-width:0;display:flex}._v_wrq_detailsPackage{min-width:0;color:var(--dsw-alias-label-tertiary);font-family:var(--ds-font-family-code,ui-monospace, monospace);text-overflow:ellipsis;white-space:nowrap;font-size:11px;line-height:16px;overflow:hidden}._v_wrq_detailsControl{align-items:center;margin-left:auto;display:flex}._v_wrq_detailsSection{border-top:.5px solid var(--dsw-alias-border-l2);flex-direction:column;gap:8px;min-width:0;padding-top:14px;display:flex}._v_wrq_detailsSection>h3{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;font-weight:500;line-height:18px}._v_wrq_detailsRelations{grid-template-columns:max-content minmax(0,1fr);gap:6px 16px;min-width:0;margin:0;font-size:13px;line-height:20px;display:grid}._v_wrq_detailsRelations>div{display:contents}._v_wrq_detailsRelations dt{color:var(--dsw-alias-label-secondary)}._v_wrq_detailsRelations dd{min-width:0;color:var(--dsw-alias-label-primary);flex-wrap:wrap;gap:4px 12px;margin:0;display:flex}._v_wrq_detailsName{appearance:none;color:inherit;font:inherit;cursor:pointer;background:0 0;border:0;align-items:center;gap:6px;padding:0;display:inline-flex}._v_wrq_detailsName:hover>span{text-underline-offset:3px;text-decoration:underline}._v_wrq_detailsBack{appearance:none;border-radius:var(--dsw-radius-sm);width:fit-content;color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;background:0 0;border:0;align-items:center;gap:2px;margin:-4px 0 -6px -4px;padding:2px 4px;font-size:12px;line-height:18px;display:inline-flex}._v_wrq_detailsBack:hover{color:var(--dsw-alias-label-primary)}._v_wrq_detailsMissing{color:var(--dsw-alias-label-secondary)}._v_wrq_detailsEffect{color:var(--dsw-alias-label-secondary);margin:0;font-size:12px;line-height:18px}._v_wrq_detailsBody ._v_wrq_optionsPanel{background:0 0;border-radius:0;margin:0;padding:0}._v_wrq_componentRowPage{flex-direction:column;gap:16px;min-width:0;display:flex}._v_wrq_detailsContributed{border-top:.5px solid var(--dsw-alias-border-l2);flex-direction:column;gap:16px;min-width:0;padding-top:14px;display:flex}._v_wrq_panelSection{flex-direction:column;gap:8px;min-width:0;display:flex}._v_wrq_panelHeading{grid-template-columns:minmax(0,1fr) auto;column-gap:12px;min-width:0;display:grid}._v_wrq_panelHeading h3{color:var(--dsw-alias-label-primary);margin:0;font-size:13px;font-weight:500;line-height:20px}._v_wrq_panelHeading p{color:var(--dsw-alias-label-tertiary);grid-column:1;margin:2px 0 0;font-size:12px;line-height:18px}._v_wrq_panelHeading ._v_wrq_miniSpinner{grid-area:1/2}._v_wrq_panelNote{color:var(--dsw-alias-label-secondary);margin:0;font-size:12px;line-height:18px}._v_wrq_panelActions{flex-wrap:wrap;justify-content:flex-end;align-items:center;gap:8px;min-width:0;padding-top:8px;display:flex}._v_wrq_panelActions>span{min-width:0;color:var(--dsw-alias-label-secondary);flex:1;font-size:12px;line-height:18px}._v_wrq_panelActions>span._v_wrq_panelError,._v_wrq_panelError{color:var(--dsw-alias-state-error-primary)}._v_wrq_rows>._v_wrq_panelActions{border-bottom:.5px solid var(--dsw-alias-border-l2);padding:10px 0}._v_wrq_rows>._v_wrq_panelNote{padding:8px 0}._v_wrq_panelError{margin:0;font-size:12px;line-height:18px}._v_wrq_boardRow{border-bottom:.5px solid var(--dsw-alias-border-l2);flex-direction:column;min-width:0;padding:14px 0;display:flex}._v_wrq_boardRowLine{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:8px 16px;min-width:0;display:flex}._v_wrq_boardGroup>._v_wrq_boardRow:last-child,._v_wrq_boardOthersList>._v_wrq_boardRow:last-child{border-bottom:0;padding-bottom:4px}._v_wrq_boardMain{padding-top:12px}._v_wrq_boardEmpty{color:var(--dsw-alias-label-tertiary);margin:0;padding:12px 0 4px;font-size:12px;line-height:18px}._v_wrq_boardOthers{flex-direction:column;min-width:0;padding-top:10px;display:flex}._v_wrq_boardOthersToggle{border-radius:var(--dsw-radius-sm);width:fit-content;color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;background:0 0;border:0;align-items:center;gap:6px;margin-left:-4px;padding:2px 4px;font-size:12px;font-weight:500;line-height:18px;display:inline-flex}._v_wrq_boardOthersToggle:hover{color:var(--dsw-alias-label-primary)}._v_wrq_boardOthersToggle>svg{transition:transform .14s;transform:rotate(-90deg)}._v_wrq_boardOthersToggle[aria-expanded=true]>svg{transform:rotate(0)}._v_wrq_boardOthersList{flex-direction:column;min-width:0;display:flex}._v_wrq_boardFootnote{color:var(--dsw-alias-label-tertiary);margin:12px 0 0;font-size:12px;line-height:18px}._v_wrq_optionsPanel{border-radius:var(--dsw-radius-lg);background:var(--dsw-alias-bg-module-platform);flex-direction:column;gap:14px;min-width:0;margin-top:12px;padding:14px 16px;display:flex}._v_wrq_optionField{flex-direction:column;gap:6px;min-width:0;display:flex}._v_wrq_optionLabel{justify-content:space-between;align-items:center;gap:8px;min-width:0;display:flex}._v_wrq_optionLabel label{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500;line-height:20px}._v_wrq_optionDefault{border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-xs);color:var(--dsw-alias-label-tertiary);padding:0 6px;font-size:11px;line-height:16px}._v_wrq_optionReset{border-radius:var(--dsw-radius-sm);color:var(--dsw-alias-state-business-primary);font:inherit;cursor:pointer;background:0 0;border:0;padding:0 4px;font-size:12px;line-height:18px}._v_wrq_optionReset:disabled{cursor:default;opacity:.5}._v_wrq_optionInput{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-md);width:100%;min-width:0;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-base);font:inherit;resize:vertical;outline:none;padding:7px 10px;font-size:13px;line-height:20px}._v_wrq_optionInput:focus-visible{border-color:var(--dsw-alias-state-business-primary)}._v_wrq_optionInput[aria-invalid=true]{border-color:var(--dsw-alias-state-error-primary)}._v_wrq_optionInput:disabled{opacity:.5}._v_wrq_optionHint{color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;font-size:12px;line-height:18px}._v_wrq_optionHint[data-error]{color:var(--dsw-alias-state-error-primary)}._v_wrq_optionChoices{flex-wrap:wrap;gap:6px 16px;min-width:0;display:flex}._v_wrq_optionEmpty{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}._v_wrq_boardControl{flex-wrap:wrap;flex:0 auto;justify-content:flex-end;align-items:center;gap:6px 12px;min-width:0;margin-left:auto;display:flex}._v_wrq_boardState{min-width:0;color:var(--dsw-alias-label-tertiary);white-space:nowrap;align-items:center;gap:6px;font-size:12px;line-height:18px;display:inline-flex}._v_wrq_boardState[data-tone=warning],._v_wrq_boardState[data-tone=error]{color:var(--dsw-alias-label-secondary)}._v_wrq_boardValue{color:var(--dsw-alias-label-secondary);font-size:13px;line-height:20px}@container (width<=420px){._v_wrq_boardMain ._v_wrq_boardControl{justify-content:stretch;width:100%}._v_wrq_boardMain ._v_wrq_boardControl>:last-child{flex:1}}@container (width<=180px){._v_wrq_boardSection ._v_wrq_sectionHeading p,._v_wrq_boardSection ._v_wrq_settingCopy small{display:none}._v_wrq_boardSection ._v_wrq_boardRow{padding:10px 0}._v_wrq_boardSection ._v_wrq_boardRowLine{grid-template-columns:minmax(0,1fr);gap:6px;display:grid}._v_wrq_boardSection ._v_wrq_settingCopy{min-width:0}._v_wrq_boardSection ._v_wrq_settingCopy strong{overflow-wrap:anywhere}._v_wrq_boardSection ._v_wrq_boardControl{justify-self:end}}._v_wrq_placeholderRow{border-bottom:.5px solid var(--dsw-alias-border-l2);justify-content:space-between;align-items:center;gap:16px;min-height:70px;display:flex}._v_wrq_placeholderRow span{background:var(--dsw-alias-bg-module-platform);border-radius:6px;height:12px;animation:1.4s ease-in-out infinite _v_wrq_placeholder-pulse}._v_wrq_placeholderRow span:first-child{width:38%}._v_wrq_placeholderRow span:last-child{border-radius:10px;width:36px;height:20px}@keyframes _v_wrq_placeholder-pulse{50%{opacity:.45}}@media (prefers-reduced-motion:reduce){._v_wrq_boardRowCopy,._v_wrq_boardOthersToggle>svg{transition:none}._v_wrq_placeholderRow span{animation:none}}._v_wrq_selector{appearance:none;border-radius:var(--dsw-radius-md);max-width:280px;height:36px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-module-platform);white-space:nowrap;cursor:pointer;border:0;align-items:center;gap:12px;padding:0 14px;font-size:14px;line-height:22px;display:inline-flex}._v_wrq_selector>span{text-overflow:ellipsis;min-width:0;overflow:hidden}._v_wrq_selector>svg{color:var(--dsw-alias-label-tertiary);flex:none}._v_wrq_selector:hover:not(:disabled),._v_wrq_selector[aria-expanded=true]{background:var(--dsw-alias-interactive-bg-hover)}._v_wrq_selector:disabled{cursor:default;opacity:.4}._v_wrq_selectMenu{min-width:220px}._v_wrq_selectOption{white-space:normal;gap:1px;min-width:0;display:grid}._v_wrq_selectOption>small{color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;font-size:12px;line-height:18px}._v_wrq_directoryInput{border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-md);width:100%;min-width:0;height:34px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-3);font-family:var(--ds-font-family-code,ui-monospace, monospace);outline:none;padding:0 12px;font-size:12px;line-height:20px}._v_wrq_directoryInput::placeholder{color:var(--dsw-alias-label-dimmed);font-family:var(--dsw-font-family);font-size:13px}._v_wrq_directoryInput:focus-visible{border-color:var(--dsw-alias-state-business-primary)}._v_wrq_directoryInput[aria-invalid=true]{border-color:var(--dsw-alias-state-error-primary)}._v_wrq_directoryInput:disabled{cursor:default;opacity:.5}._v_wrq_rowDetail{border-bottom:.5px solid var(--dsw-alias-border-l2);flex-direction:column;gap:10px;min-width:0;padding:0 0 14px;display:flex}._v_wrq_settingRow:has(+._v_wrq_rowDetail){border-bottom:0;padding-bottom:10px}._v_wrq_effectiveRoute{min-width:0;color:var(--dsw-alias-label-tertiary);justify-content:space-between;align-items:center;gap:12px;font-size:12px;line-height:18px;display:flex}._v_wrq_effectiveRoute code{border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-xs);min-width:0;color:var(--dsw-alias-label-secondary);font-family:var(--ds-font-family-code,ui-monospace, monospace);text-overflow:ellipsis;white-space:nowrap;padding:1px 6px;font-size:11px;line-height:16px;overflow:hidden}._v_wrq_effectiveRoute small{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:12px;overflow:hidden}._v_wrq_warning{color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere;margin:0;font-size:12px;line-height:18px}._v_wrq_advanced{min-width:0;padding:12px 0 2px}._v_wrq_advanced>summary{border-radius:var(--dsw-radius-sm);width:fit-content;color:var(--dsw-alias-label-secondary);cursor:pointer;align-items:center;gap:6px;margin-left:-4px;padding:2px 4px;font-size:12px;font-weight:500;line-height:18px;list-style:none;display:inline-flex}._v_wrq_advanced>summary::-webkit-details-marker{display:none}._v_wrq_advanced>summary>svg{transition:transform .14s}._v_wrq_advanced[open]>summary>svg{transform:rotate(180deg)}._v_wrq_advanced>summary:hover{color:var(--dsw-alias-label-primary)}._v_wrq_advanced>._v_wrq_fieldGrid{padding-top:12px}._v_wrq_miniSpinner{border:2px solid var(--dsw-alias-border-l2);border-top-color:var(--dsw-alias-label-secondary);border-radius:50%;flex:none;width:14px;height:14px;margin-top:4px;animation:.7s linear infinite _v_wrq_settings-spin}@keyframes _v_wrq_settings-spin{to{transform:rotate(360deg)}}._v_wrq_providerList{flex-direction:column;gap:8px;min-width:0;margin-top:10px;display:flex}._v_wrq_providerRow{border:.5px solid var(--dsw-alias-settings-card-stroke);border-radius:var(--dsw-radius-xl);background:var(--dsw-alias-settings-card-fill);overflow:hidden}._v_wrq_providerRowHeader{align-items:center;gap:12px;min-width:0;padding:12px 14px;display:flex}summary._v_wrq_providerRowHeader{cursor:pointer;list-style:none}summary._v_wrq_providerRowHeader::-webkit-details-marker{display:none}._v_wrq_providerDisclosure{appearance:none;min-width:0;color:inherit;cursor:pointer;text-align:left;background:0 0;border:0;outline:none;flex:1;align-items:center;gap:8px;padding:0;display:flex}._v_wrq_providerDisclosure:disabled{cursor:default}._v_wrq_providerDisclosure:focus-visible,summary._v_wrq_providerRowHeader:focus-visible{border-radius:var(--dsw-radius-md);box-shadow:0 0 0 2px var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary))}._v_wrq_providerIdentity{flex:1;align-items:center;gap:12px;min-width:0;display:flex}._v_wrq_providerIdentity>span{flex-direction:column;min-width:0;display:flex}._v_wrq_providerIdentity strong{font-size:14px;font-weight:500;line-height:22px}._v_wrq_providerIdentity small{color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;font-size:12px;line-height:18px;overflow:hidden}._v_wrq_providerMark{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1);flex:none;place-items:center;width:36px;height:36px;padding:6px;display:grid;overflow:hidden}._v_wrq_providerMark>img,._v_wrq_providerMark>svg{object-fit:contain;border-radius:4px;width:100%;height:100%;display:block}._v_wrq_providerEnableControl{flex:none;align-items:center;gap:10px;display:flex}._v_wrq_providerScopeTag{border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-xs);color:var(--dsw-alias-label-secondary);flex:none;padding:1px 6px;font-size:11px;line-height:16px}._v_wrq_providerScopeTag[data-scope=workspace]{border-color:color-mix(in srgb, var(--dsw-alias-state-business-primary) 30%, transparent);color:var(--dsw-alias-state-business-primary)}._v_wrq_providerState{color:var(--dsw-alias-label-tertiary);white-space:nowrap;flex:none;align-items:center;gap:6px;font-size:12px;line-height:18px;display:inline-flex}._v_wrq_providerState:before{content:\"\";background:var(--dsw-alias-state-idle-primary);border-radius:50%;flex:none;width:6px;height:6px}._v_wrq_providerState[data-enabled]:before{background:var(--dsw-alias-state-success-primary)}._v_wrq_providerChevron{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .14s}._v_wrq_providerDisclosure[aria-expanded=true] ._v_wrq_providerChevron,details[open]>summary ._v_wrq_providerChevron{transform:rotate(180deg)}._v_wrq_providerToggle{cursor:pointer;display:inline-flex;position:relative}._v_wrq_providerInlineBody{padding:0 14px 14px}._v_wrq_providerToggleError{color:var(--dsw-alias-state-error-primary);margin:0;padding:0 14px 12px;font-size:12px;line-height:18px}._v_wrq_providerServiceForm,._v_wrq_editor{border-radius:var(--dsw-radius-lg);background:var(--dsw-alias-bg-module-platform);flex-direction:column;gap:12px;min-width:0;padding:14px 16px;display:flex}._v_wrq_providerServicePrompt,._v_wrq_editorNote{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}._v_wrq_editorHeading h3{margin:0;font-size:14px;font-weight:500;line-height:22px}._v_wrq_editorHeading p{color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;margin:2px 0 0;font-size:12px;line-height:18px}._v_wrq_editor ._v_wrq_toggleRow{border-top:.5px solid var(--dsw-alias-border-l3);border-bottom:.5px solid var(--dsw-alias-border-l3);padding:10px 0}._v_wrq_embeddingTest{justify-content:space-between;align-items:center;gap:12px;min-width:0;display:flex}._v_wrq_embeddingTest>span{min-width:0;color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;font-size:12px;line-height:18px}._v_wrq_embeddingTest>span._v_wrq_error{color:var(--dsw-alias-state-error-primary)}._v_wrq_globalLocationSetting{flex-direction:column;min-width:0;display:flex}._v_wrq_providerServiceLocation{border-bottom:.5px solid var(--dsw-alias-border-l3);padding-bottom:12px}._v_wrq_providerServiceLocation>._v_wrq_nativeLocation{padding:0 0 12px}._v_wrq_providerLocationField{padding-top:2px}._v_wrq_nativeLocation{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:8px 16px;min-width:0;display:flex}._v_wrq_inlineChoices{border-radius:var(--dsw-radius-md);background:var(--dsw-alias-interactive-bg-hover);flex:none;align-items:center;gap:2px;padding:3px;display:inline-flex}._v_wrq_inlineChoices label{cursor:pointer;position:relative}._v_wrq_inlineChoices input{z-index:1;opacity:0;width:100%;height:100%;cursor:inherit;margin:0;position:absolute;inset:0}._v_wrq_inlineChoices span{border-radius:var(--dsw-radius-sm);height:28px;color:var(--dsw-alias-label-secondary);white-space:nowrap;align-items:center;padding:0 12px;font-size:13px;font-weight:500;line-height:20px;display:inline-flex}._v_wrq_inlineChoices input:checked+span{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-1);box-shadow:var(--dsw-elevation-soft)}._v_wrq_inlineChoices input:focus-visible+span{box-shadow:0 0 0 2px var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary))}._v_wrq_inlineChoices input:disabled+span{cursor:default;opacity:.4}._v_wrq_fieldGrid,._v_wrq_providerSettingsGrid{grid-template-columns:repeat(auto-fit,minmax(min(100%,200px),1fr));gap:12px;min-width:0;display:grid}._v_wrq_providerSettingsGrid{grid-template-columns:minmax(0,1fr)}._v_wrq_fieldGrid>label,._v_wrq_providerFieldControl>label:not(._v_wrq_providerBoolean){min-width:0;color:var(--dsw-alias-label-primary);flex-direction:column;gap:6px;font-size:13px;font-weight:500;line-height:20px;display:flex}._v_wrq_fieldGrid input,._v_wrq_fieldGrid select,._v_wrq_providerFieldControl input:not([type=checkbox]),._v_wrq_providerFieldControl select{border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-md);width:100%;min-width:0;height:34px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-3);font:inherit;outline:none;padding:0 12px;font-size:13px;font-weight:400;line-height:20px}._v_wrq_fieldGrid input::placeholder,._v_wrq_providerFieldControl input::placeholder{color:var(--dsw-alias-label-dimmed)}._v_wrq_fieldGrid select,._v_wrq_providerFieldControl select{appearance:none;cursor:pointer;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none'%3E%3Cpath d='M3 4.5L6 7.5L9 4.5' stroke='%2381858C' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");background-position:right 12px center;background-repeat:no-repeat;background-size:12px 12px;padding-right:32px}._v_wrq_fieldGrid select:disabled,._v_wrq_providerFieldControl select:disabled{cursor:default}._v_wrq_fieldGrid input:focus-visible,._v_wrq_fieldGrid select:focus-visible,._v_wrq_providerFieldControl input:focus-visible,._v_wrq_providerFieldControl select:focus-visible{border-color:var(--dsw-alias-state-business-primary)}._v_wrq_fieldGrid input[aria-invalid=true],._v_wrq_providerFieldControl input:invalid{border-color:var(--dsw-alias-state-error-primary)}._v_wrq_fieldGrid input:disabled,._v_wrq_fieldGrid select:disabled,._v_wrq_providerFieldControl input:disabled,._v_wrq_providerFieldControl select:disabled{opacity:.5}._v_wrq_providerFieldControl{flex-direction:column;justify-content:flex-end;gap:4px;min-width:0;display:flex}._v_wrq_providerBoolean{min-height:34px;color:var(--dsw-alias-label-primary);align-items:center;gap:8px;font-size:13px;display:flex}._v_wrq_providerBoolean input{width:16px;height:16px;accent-color:var(--dsw-alias-brand-primary);margin:0}._v_wrq_providerSecretInput{min-width:0;position:relative}._v_wrq_providerSecretInput>input{padding-right:40px}._v_wrq_providerSecretVisibility{appearance:none;border-radius:var(--dsw-radius-sm);width:28px;height:28px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;place-items:center;padding:0;display:grid;position:absolute;top:3px;right:3px}._v_wrq_providerSecretVisibility:hover:not(:disabled){color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}._v_wrq_providerSecretVisibility:focus-visible{box-shadow:0 0 0 2px var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline:none}._v_wrq_providerSecretVisibility:disabled{cursor:default;opacity:.35}._v_wrq_providerSecretVisibility svg{width:16px;height:16px}._v_wrq_memoryConfigFooter{justify-content:space-between;align-items:center;gap:10px;min-height:36px;display:flex}._v_wrq_memoryConfigFooter>div{align-items:center;gap:6px;display:flex}._v_wrq_providerServiceFooter{align-items:flex-end;min-height:0}._v_wrq_configFeedback{flex:1;min-width:0;font-size:12px;line-height:18px}._v_wrq_scopeChanging,._v_wrq_providerTarget{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}._v_wrq_scopeChanging{border-radius:var(--dsw-radius-md);color:var(--dsw-alias-state-warn-label,var(--dsw-alias-label-secondary));background:var(--dsw-alias-state-warn-tertiary,var(--dsw-alias-bg-module-platform));padding:8px 12px}._v_wrq_providerLoadError{justify-content:space-between;align-items:center;gap:10px;font-size:12px;display:flex}._v_wrq_visuallyHidden{clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}._v_wrq_location{align-items:baseline;gap:6px;min-width:0;display:flex}._v_wrq_locationRow{border-bottom:.5px solid var(--dsw-alias-border-l2);gap:10px;padding:14px 0}._v_wrq_rowActions{flex:none;align-items:center;gap:8px;display:flex}._v_wrq_packRow{flex-direction:column;gap:8px;min-width:0;padding-bottom:14px;display:flex}._v_wrq_packRow>._v_wrq_settingRow{border-bottom:0;padding-bottom:6px}._v_wrq_packRow:has(>._v_wrq_packFeedback:empty):not(:has(>._v_wrq_importBar))>._v_wrq_settingRow{padding-bottom:0}._v_wrq_rows>._v_wrq_packRow:not(:last-child){border-bottom:.5px solid var(--dsw-alias-border-l2)}._v_wrq_importBar{border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-module-platform);grid-template-columns:minmax(0,1fr) auto auto;align-items:center;gap:10px;min-width:0;padding:10px 12px;display:grid}._v_wrq_importBar>div{min-width:0;display:grid}._v_wrq_importBar strong{text-overflow:ellipsis;white-space:nowrap;font-size:13px;font-weight:500;line-height:20px;overflow:hidden}._v_wrq_importBar small{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}._v_wrq_packFeedback{gap:4px;display:grid}._v_wrq_packFeedback:empty{display:none}._v_wrq_packFeedback p{overflow-wrap:anywhere;margin:0;font-size:12px;line-height:18px}._v_wrq_error{color:var(--dsw-alias-state-error-primary)}._v_wrq_readOnlyNotice{color:var(--dsw-alias-label-tertiary);margin:0 0 -20px;font-size:12px;line-height:18px}._v_wrq_packSuccess{color:var(--dsw-alias-state-success-primary)}._v_wrq_syncRow{flex-direction:column;gap:8px;min-width:0;padding-bottom:14px;display:flex}._v_wrq_syncRow>._v_wrq_settingRow,._v_wrq_syncRow>._v_wrq_toggleRow{border-bottom:0;padding-bottom:6px}._v_wrq_syncRow:has(>._v_wrq_syncFeedback:empty):not(:has(>._v_wrq_syncForm)):not(:has(>._v_wrq_syncBar))>._v_wrq_settingRow{padding-bottom:0}._v_wrq_rows>._v_wrq_syncRow:not(:last-child){border-bottom:.5px solid var(--dsw-alias-border-l2)}._v_wrq_syncState{flex-wrap:wrap;align-items:center;gap:4px 10px;min-width:0;display:flex}._v_wrq_syncState>span{color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;font-size:12px;line-height:18px}._v_wrq_syncForm{border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-module-platform);grid-template-columns:repeat(auto-fit,minmax(min(100%,220px),1fr));gap:12px;min-width:0;padding:12px;display:grid}._v_wrq_syncField{flex-direction:column;gap:6px;min-width:0;display:flex}._v_wrq_syncField>label{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500;line-height:20px}._v_wrq_syncField>small{color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;font-size:12px;line-height:18px}._v_wrq_syncField>input{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-md);width:100%;min-width:0;height:34px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-3);font:inherit;outline:none;padding:0 12px;font-size:13px;line-height:20px}._v_wrq_syncField>input:focus-visible{border-color:var(--dsw-alias-state-business-primary)}._v_wrq_syncField>input[aria-invalid=true]{border-color:var(--dsw-alias-state-error-primary)}._v_wrq_syncField>input:disabled{cursor:default;opacity:.5}._v_wrq_syncBlock{border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-3);flex-direction:column;grid-column:1/-1;gap:8px;min-width:0;padding:12px;display:flex}._v_wrq_syncBlock>header{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:8px;min-width:0;display:flex}._v_wrq_syncBlock>header strong{font-size:13px;font-weight:500;line-height:20px}._v_wrq_syncBlock>small{color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;font-size:12px;line-height:18px}._v_wrq_syncBlock p{overflow-wrap:anywhere;margin:0;font-size:12px;line-height:18px}._v_wrq_syncBlock ._v_wrq_syncFormActions{grid-column:auto}._v_wrq_syncBlock ._v_wrq_syncField>select{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-md);width:100%;min-width:0;height:34px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-3);font:inherit;outline:none;padding:0 10px;font-size:13px;line-height:20px}._v_wrq_syncBlock ._v_wrq_syncField>select:disabled{cursor:default;opacity:.5}._v_wrq_syncAccount{align-items:center;gap:8px;min-width:0;display:flex}._v_wrq_syncAccount>span{color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere;font-size:12px;line-height:18px}._v_wrq_syncCode{flex-wrap:wrap;align-items:center;gap:8px;min-width:0;display:flex}._v_wrq_syncCode>code{border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-md);color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-3);font-family:var(--dsw-font-mono,ui-monospace, monospace);letter-spacing:.08em;padding:6px 10px;font-size:14px;font-weight:500}._v_wrq_syncCode>a{color:var(--dsw-alias-state-business-primary);font-size:12px;line-height:18px}._v_wrq_syncCheck{color:var(--dsw-alias-label-primary);align-items:center;gap:8px;font-size:13px;line-height:20px;display:flex}._v_wrq_syncCheck input{width:16px;height:16px;accent-color:var(--dsw-alias-brand-primary);margin:0}._v_wrq_syncFormActions{grid-column:1/-1;align-items:center;gap:8px;display:flex}._v_wrq_syncBar{border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-module-platform);grid-template-columns:minmax(0,1fr) auto auto;align-items:center;gap:10px;min-width:0;padding:10px 12px;display:grid}._v_wrq_syncBar>div{min-width:0;display:grid}._v_wrq_syncBar strong{text-overflow:ellipsis;white-space:nowrap;font-size:13px;font-weight:500;line-height:20px;overflow:hidden}._v_wrq_syncBar small{color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;font-size:12px;line-height:18px}._v_wrq_syncFeedback{gap:4px;display:grid}._v_wrq_syncFeedback:empty{display:none}._v_wrq_syncFeedback p{overflow-wrap:anywhere;margin:0;font-size:12px;line-height:18px}._v_wrq_syncSuccess{color:var(--dsw-alias-state-success-primary)}._v_wrq_reviewList{gap:8px;display:grid}._v_wrq_reviewEntry{border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-module-platform);flex-direction:column;gap:6px;min-width:0;padding:10px 12px;display:flex}._v_wrq_reviewEntry>header{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:8px;min-width:0;display:flex}._v_wrq_reviewEntry>small{color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;font-size:12px;line-height:18px}._v_wrq_reviewEntry>p{overflow-wrap:anywhere;margin:0;font-size:13px;line-height:20px}._v_wrq_reviewTitle{align-items:center;gap:8px;min-width:0;display:flex}._v_wrq_reviewTitle strong{overflow-wrap:anywhere;font-size:13px;font-weight:500;line-height:20px}._v_wrq_reviewOperations{gap:4px;margin:0;padding-left:18px;display:grid}._v_wrq_reviewOperations li{overflow-wrap:anywhere;font-size:12px;line-height:18px}._v_wrq_reviewOperations small{color:var(--dsw-alias-label-tertiary);display:block}._v_wrq_reviewOpinions{gap:4px;display:grid}._v_wrq_reviewOpinions>strong{font-size:12px;font-weight:500;line-height:18px}._v_wrq_reviewOpinions>small{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}._v_wrq_reviewOpinions>div{overflow-wrap:anywhere;gap:6px;min-width:0;font-size:12px;line-height:18px;display:flex}._v_wrq_reviewOpinions>div strong{color:var(--dsw-alias-label-secondary);flex:none;font-weight:500}._v_wrq_reviewOpinionForm{align-items:center;gap:8px;min-width:0;display:flex}._v_wrq_reviewOpinionForm>input{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-md);min-width:0;height:34px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-3);font:inherit;outline:none;flex:auto;padding:0 12px;font-size:13px;line-height:20px}._v_wrq_reviewOpinionForm>input:focus-visible{border-color:var(--dsw-alias-state-business-primary)}._v_wrq_reviewOpinionForm>input:disabled{cursor:default;opacity:.5}._v_wrq_reviewRules{border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-module-platform);gap:4px;padding:10px 12px;display:grid}._v_wrq_reviewRules>strong{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:500;line-height:18px}._v_wrq_reviewRules>ul{gap:2px;margin:0;padding-left:18px;display:grid}._v_wrq_reviewRules li{color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere;font-size:12px;line-height:18px}._v_wrq_reviewGuidance{gap:4px;display:grid}._v_wrq_reviewGuidance>label{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:500;line-height:18px}._v_wrq_reviewGuidance>input{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-md);width:100%;height:34px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-3);font:inherit;outline:none;padding:0 12px;font-size:13px;line-height:20px}._v_wrq_reviewGuidance>input:focus-visible{border-color:var(--dsw-alias-state-business-primary)}._v_wrq_reviewGuidance>input:disabled{cursor:default;opacity:.5}._v_wrq_reviewGuidance>small{color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;font-size:12px;line-height:18px}._v_wrq_reviewSelection{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:6px;min-width:0;display:flex}._v_wrq_reviewSelection>small,._v_wrq_reviewSelected{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}._v_wrq_reviewOperations>li{gap:2px;display:grid}._v_wrq_reviewOperations>li>label{cursor:pointer;align-items:flex-start;gap:6px;min-width:0;display:flex}._v_wrq_reviewOperations>li>label>input{flex:none;margin:3px 0 0}._v_wrq_reviewOperations>li>label>input:disabled{cursor:default;opacity:.5}._v_wrq_reviewOperations>li[data-applied=true]{opacity:.55}._v_wrq_syncBackups{border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-module-platform);gap:8px;padding:10px 12px;display:grid}._v_wrq_syncBackups>header{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:8px;min-width:0;display:flex}._v_wrq_syncBackups>header>strong{overflow-wrap:anywhere;font-size:13px;font-weight:500;line-height:20px}._v_wrq_syncBackups>small{color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;font-size:12px;line-height:18px}._v_wrq_syncBackupList{gap:6px;display:grid}._v_wrq_syncBackupEntry{border-radius:var(--dsw-radius-sm,var(--dsw-radius-md));background:var(--dsw-alias-bg-layer-3);flex-direction:column;gap:4px;min-width:0;padding:8px 10px;display:flex}._v_wrq_syncBackupEntry>header{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:8px;min-width:0;display:flex}._v_wrq_syncBackupEntry>small{color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;font-size:12px;line-height:18px}._v_wrq_syncBackupComponents{gap:2px;display:grid}._v_wrq_syncBackupComponents>small{color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere;font-size:12px;line-height:18px}._v_wrq_syncDiff{border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-module-platform);gap:8px;padding:10px 12px;display:grid}._v_wrq_syncDiff>header{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:8px;min-width:0;display:flex}._v_wrq_syncDiff>header>strong{overflow-wrap:anywhere;font-size:13px;font-weight:500;line-height:20px}._v_wrq_syncDiff>small{color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;font-size:12px;line-height:18px}._v_wrq_syncDiffColumns{grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));gap:10px;min-width:0;display:grid}._v_wrq_syncDiffColumns>div{align-content:start;gap:4px;min-width:0;display:grid}._v_wrq_syncDiffColumns>div>strong{font-size:12px;font-weight:500;line-height:18px}._v_wrq_syncDiffColumns>div>small{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}._v_wrq_syncDiffColumns ul{gap:4px;margin:0;padding:0;list-style:none;display:grid}._v_wrq_syncDiffColumns li{overflow-wrap:anywhere;gap:2px;font-size:12px;line-height:18px;display:grid}._v_wrq_syncDiffMeta{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}._v_wrq_syncDialogBody{gap:16px;display:grid}._v_wrq_syncDialogBody ._v_wrq_syncBackups,._v_wrq_syncDialogBody ._v_wrq_syncDiff{background:0 0;padding:0}._v_wrq_syncDialogBody ._v_wrq_syncBackups>header>strong,._v_wrq_syncDialogBody ._v_wrq_syncDiff>header>strong{font-size:14px;line-height:22px}._v_wrq_syncConflictList{gap:8px;display:grid}._v_wrq_syncConflict{border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-module-platform);gap:6px;min-width:0;padding:10px 12px;display:grid}._v_wrq_syncConflict>header{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:8px;min-width:0;display:flex}._v_wrq_syncConflict>header>strong{font-size:13px;font-weight:500;line-height:20px}._v_wrq_syncConflict>header>small{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}._v_wrq_syncConflictSides{grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));gap:8px;min-width:0;display:grid}._v_wrq_syncConflictSides>div{align-content:start;gap:2px;min-width:0;display:grid}._v_wrq_syncConflictSides>div>small{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}._v_wrq_syncConflictSides>div>span{overflow-wrap:anywhere;font-size:12px;line-height:18px}._v_wrq_syncDialogNote{color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;margin:0;font-size:12px;line-height:18px}._v_wrq_syncPlan{border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-module-platform);gap:8px;padding:10px 12px;display:grid}._v_wrq_syncPlan>p{overflow-wrap:anywhere;margin:0;font-size:13px;line-height:20px}._v_wrq_syncPlan>._v_wrq_rowActions{justify-content:flex-start}._v_wrq_selector:focus-visible{box-shadow:0 0 0 2px var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline:none}@media (width<=620px){._v_wrq_page{gap:28px}._v_wrq_rowActions{width:100%}._v_wrq_rowActions button{flex:1}._v_wrq_importBar{grid-template-columns:minmax(0,1fr) auto}._v_wrq_importBar>button:last-child{grid-column:1/-1}._v_wrq_syncBar{grid-template-columns:minmax(0,1fr) auto}._v_wrq_syncBar>button:last-child{grid-column:1/-1}._v_wrq_syncFormActions{flex-wrap:wrap}._v_wrq_syncFormActions button{flex:1}._v_wrq_reviewOpinionForm{flex-wrap:wrap}._v_wrq_reviewOpinionForm>input{flex:100%}._v_wrq_inlineChoices{width:100%}._v_wrq_inlineChoices label{flex:1}._v_wrq_inlineChoices span{justify-content:center;width:100%}._v_wrq_providerRowHeader{align-items:flex-start;gap:8px}._v_wrq_providerEnableControl{flex-wrap:wrap;justify-content:flex-end;gap:6px;max-width:132px}._v_wrq_providerState{text-overflow:ellipsis;max-width:120px;overflow:hidden}._v_wrq_memoryConfigFooter{flex-direction:column;align-items:stretch}._v_wrq_memoryConfigFooter>div:last-child{width:100%}._v_wrq_memoryConfigFooter button{flex:1}}@media (prefers-reduced-motion:reduce){._v_wrq_providerChevron,._v_wrq_advanced>summary>svg{transition:none}._v_wrq_miniSpinner{animation:none}}";
676
+ const css$13 = "._v_wrq_page{box-sizing:border-box;width:100%;min-width:0;color:var(--dsw-alias-label-primary);flex-direction:column;gap:32px;font-family:inherit;display:flex}._v_wrq_surface{color:var(--dsw-alias-label-primary)}:where(._v_wrq_page,._v_wrq_surface) *,:where(._v_wrq_page,._v_wrq_surface) :before,:where(._v_wrq_page,._v_wrq_surface) :after{box-sizing:border-box}:where(._v_wrq_page,._v_wrq_surface) :where(button,input,select,textarea){color:inherit;font:inherit}._v_wrq_loading{min-height:140px;color:var(--dsw-alias-label-tertiary);text-align:center;margin:0;font-size:13px;line-height:140px}._v_wrq_section{flex-direction:column;gap:4px;min-width:0;display:flex}._v_wrq_sectionHeading{grid-template-columns:minmax(0,1fr) auto;align-items:start;column-gap:12px;min-width:0;display:grid}._v_wrq_sectionHeading h2{grid-column:1;margin:0;font-size:14px;font-weight:500;line-height:20px}._v_wrq_sectionHeading p{max-width:66ch;color:var(--dsw-alias-label-tertiary);grid-column:1;margin:2px 0 0;font-size:12px;line-height:18px}._v_wrq_sectionHeading ._v_wrq_miniSpinner{grid-area:1/2}._v_wrq_sectionHeading>._v_wrq_boardLinks{grid-column:1;padding-top:6px}._v_wrq_componentListNote{max-width:72ch;color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}._v_wrq_appliesNow{border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-xs);color:var(--dsw-alias-label-secondary);white-space:nowrap;grid-area:1/2;align-self:center;padding:1px 6px;font-size:11px;line-height:16px}._v_wrq_rows{flex-direction:column;min-width:0;display:flex}._v_wrq_settingRow,._v_wrq_toggleRow{border-bottom:.5px solid var(--dsw-alias-border-l2);flex-wrap:wrap;justify-content:space-between;align-items:center;gap:8px 16px;min-width:0;padding:14px 0;display:flex;position:relative}._v_wrq_rows>:last-child,._v_wrq_rows>._v_wrq_packRow:last-child>._v_wrq_settingRow{border-bottom:0}._v_wrq_rows>._v_wrq_packRow:last-child{padding-bottom:0}._v_wrq_settingRow[data-stacked]{flex-direction:column;align-items:stretch}._v_wrq_settingCopy{flex-direction:column;flex:1 1 0;gap:2px;min-width:min(240px,100%);display:flex}._v_wrq_settingCopy strong,._v_wrq_settingCopy label{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:400;line-height:22px}._v_wrq_settingCopy small{color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;font-size:12px;line-height:18px}._v_wrq_settingCopy code{font-family:var(--ds-font-family-code,ui-monospace, monospace)}._v_wrq_settingControl{flex:none;justify-content:flex-end;align-items:center;gap:8px;min-width:0;display:flex}._v_wrq_settingRow[data-stacked] ._v_wrq_settingControl{flex:auto;justify-content:stretch}._v_wrq_switch{flex:none}._v_wrq_rowNote{min-width:0;color:var(--dsw-alias-label-secondary);flex-wrap:wrap;align-items:center;gap:4px 8px;padding-top:4px;font-size:12px;line-height:18px;display:flex}._v_wrq_groupCallout{margin:8px 0 4px}._v_wrq_boardSection{container-type:inline-size}._v_wrq_board{flex-direction:column;min-width:0;margin-top:10px;display:flex}._v_wrq_boardProblem{margin:0 0 4px}._v_wrq_boardLoading{min-height:40px;color:var(--dsw-alias-label-secondary);align-items:center;gap:8px;margin:0;font-size:13px;line-height:20px;display:flex}._v_wrq_boardGroup{flex-direction:column;min-width:0;padding-top:14px;display:flex}._v_wrq_boardGroupHead{justify-content:space-between;align-items:baseline;gap:8px;min-width:0;display:flex}._v_wrq_boardGroupHead h3{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;font-weight:500;line-height:18px}._v_wrq_boardGroupHead span{color:var(--dsw-alias-label-tertiary);white-space:nowrap;font-size:12px;line-height:18px}._v_wrq_pageLink{appearance:none;border-radius:var(--dsw-radius-sm);max-width:100%;color:inherit;font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;align-items:center;padding:0;display:inline-flex}._v_wrq_pageLink>span{overflow-wrap:anywhere;min-width:0}._v_wrq_pageLink:hover>span{text-underline-offset:3px;text-decoration:underline}._v_wrq_settingCopy ._v_wrq_pageLink{width:fit-content;color:var(--dsw-alias-label-primary);font-size:14px;line-height:22px}._v_wrq_boardIconButton{border-radius:var(--dsw-radius-sm);width:28px;height:28px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;flex:none;place-items:center;padding:0;display:inline-grid}._v_wrq_boardIconButton:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}._v_wrq_boardLinks{flex-wrap:wrap;align-items:center;gap:4px;min-width:0;padding-top:4px;display:flex}._v_wrq_boardLink{appearance:none;border:.5px solid var(--dsw-alias-border-l3);max-width:100%;color:var(--dsw-alias-label-tertiary);font:inherit;white-space:nowrap;cursor:pointer;background:0 0;border-radius:999px;align-items:center;gap:4px;padding:0 8px;font-size:11px;line-height:18px;transition:color .12s,border-color .12s;display:inline-flex}._v_wrq_boardLink[data-on]{color:var(--dsw-alias-label-secondary)}._v_wrq_boardLink:hover{border-color:var(--dsw-alias-border-l4);color:var(--dsw-alias-label-primary)}._v_wrq_boardLink>svg{flex:none}._v_wrq_boardLinksLabel{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}._v_wrq_pageLink:focus-visible,._v_wrq_boardIconButton:focus-visible,._v_wrq_boardLink:focus-visible,._v_wrq_detailsBack:focus-visible,._v_wrq_boardSearch:focus-within{box-shadow:0 0 0 2px var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline:none}._v_wrq_boardSearch{border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-md);min-width:0;color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-bg-base);align-items:center;gap:8px;margin:12px 0 0;padding:0 10px;display:flex}._v_wrq_boardSearch input{min-width:0;height:32px;color:var(--dsw-alias-label-primary);font:inherit;background:0 0;border:0;outline:none;flex:1;font-size:13px}._v_wrq_detailsDialog{width:min(560px,100%);max-height:100%}._v_wrq_detailsScroll{overscroll-behavior:contain;min-height:0;overflow-y:auto}._v_wrq_detailsBody{flex-direction:column;gap:16px;min-width:0;display:flex}._v_wrq_detailsHead{flex-direction:column;gap:6px;min-width:0;display:flex}._v_wrq_detailsHeadLine{flex-wrap:wrap;align-items:center;gap:8px 10px;min-width:0;display:flex}._v_wrq_detailsPackage{min-width:0;color:var(--dsw-alias-label-tertiary);font-family:var(--ds-font-family-code,ui-monospace, monospace);text-overflow:ellipsis;white-space:nowrap;font-size:11px;line-height:16px;overflow:hidden}._v_wrq_detailsControl{align-items:center;margin-left:auto;display:flex}._v_wrq_detailsSection{border-top:.5px solid var(--dsw-alias-border-l2);flex-direction:column;gap:8px;min-width:0;padding-top:14px;display:flex}._v_wrq_detailsSection>h3{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;font-weight:500;line-height:18px}._v_wrq_detailsRelations{grid-template-columns:max-content minmax(0,1fr);gap:6px 16px;min-width:0;margin:0;font-size:13px;line-height:20px;display:grid}._v_wrq_detailsRelations>div{display:contents}._v_wrq_detailsRelations dt{color:var(--dsw-alias-label-secondary)}._v_wrq_detailsRelations dd{min-width:0;color:var(--dsw-alias-label-primary);flex-wrap:wrap;gap:4px 12px;margin:0;display:flex}._v_wrq_detailsName{appearance:none;color:inherit;font:inherit;cursor:pointer;background:0 0;border:0;align-items:center;gap:6px;padding:0;display:inline-flex}._v_wrq_detailsName:hover>span{text-underline-offset:3px;text-decoration:underline}._v_wrq_detailsBack{appearance:none;border-radius:var(--dsw-radius-sm);width:fit-content;color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;background:0 0;border:0;align-items:center;gap:2px;margin:-4px 0 -6px -4px;padding:2px 4px;font-size:12px;line-height:18px;display:inline-flex}._v_wrq_detailsBack:hover{color:var(--dsw-alias-label-primary)}._v_wrq_detailsMissing{color:var(--dsw-alias-label-secondary)}._v_wrq_detailsEffect{color:var(--dsw-alias-label-secondary);margin:0;font-size:12px;line-height:18px}._v_wrq_detailsBody ._v_wrq_optionsPanel{background:0 0;border-radius:0;margin:0;padding:0}._v_wrq_componentRowPage{flex-direction:column;gap:16px;min-width:0;display:flex}._v_wrq_detailsContributed{border-top:.5px solid var(--dsw-alias-border-l2);flex-direction:column;gap:16px;min-width:0;padding-top:14px;display:flex}._v_wrq_panelSection{flex-direction:column;gap:8px;min-width:0;display:flex}._v_wrq_panelHeading{grid-template-columns:minmax(0,1fr) auto;column-gap:12px;min-width:0;display:grid}._v_wrq_panelHeading h3{color:var(--dsw-alias-label-primary);margin:0;font-size:13px;font-weight:500;line-height:20px}._v_wrq_panelHeading p{color:var(--dsw-alias-label-tertiary);grid-column:1;margin:2px 0 0;font-size:12px;line-height:18px}._v_wrq_panelHeading ._v_wrq_miniSpinner{grid-area:1/2}._v_wrq_panelNote{color:var(--dsw-alias-label-secondary);margin:0;font-size:12px;line-height:18px}._v_wrq_panelActions{flex-wrap:wrap;justify-content:flex-end;align-items:center;gap:8px;min-width:0;padding-top:8px;display:flex}._v_wrq_panelActions>span{min-width:0;color:var(--dsw-alias-label-secondary);flex:1;font-size:12px;line-height:18px}._v_wrq_panelActions>span._v_wrq_panelError,._v_wrq_panelError{color:var(--dsw-alias-state-error-primary)}._v_wrq_rows>._v_wrq_panelActions{border-bottom:.5px solid var(--dsw-alias-border-l2);padding:10px 0}._v_wrq_rows>._v_wrq_panelNote{padding:8px 0}._v_wrq_panelError{margin:0;font-size:12px;line-height:18px}._v_wrq_boardRow{border-bottom:.5px solid var(--dsw-alias-border-l2);flex-direction:column;min-width:0;padding:14px 0;display:flex}._v_wrq_boardRowLine{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:8px 16px;min-width:0;display:flex}._v_wrq_boardGroup>._v_wrq_boardRow:last-child,._v_wrq_boardOthersList>._v_wrq_boardRow:last-child{border-bottom:0;padding-bottom:4px}._v_wrq_boardMain{padding-top:12px}._v_wrq_boardEmpty{color:var(--dsw-alias-label-tertiary);margin:0;padding:12px 0 4px;font-size:12px;line-height:18px}._v_wrq_boardOthers{flex-direction:column;min-width:0;padding-top:10px;display:flex}._v_wrq_boardOthersToggle{border-radius:var(--dsw-radius-sm);width:fit-content;color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;background:0 0;border:0;align-items:center;gap:6px;margin-left:-4px;padding:2px 4px;font-size:12px;font-weight:500;line-height:18px;display:inline-flex}._v_wrq_boardOthersToggle:hover{color:var(--dsw-alias-label-primary)}._v_wrq_boardOthersToggle>svg{transition:transform .14s;transform:rotate(-90deg)}._v_wrq_boardOthersToggle[aria-expanded=true]>svg{transform:rotate(0)}._v_wrq_boardOthersList{flex-direction:column;min-width:0;display:flex}._v_wrq_boardFootnote{color:var(--dsw-alias-label-tertiary);margin:12px 0 0;font-size:12px;line-height:18px}._v_wrq_optionsPanel{border-radius:var(--dsw-radius-lg);background:var(--dsw-alias-bg-module-platform);flex-direction:column;gap:14px;min-width:0;margin-top:12px;padding:14px 16px;display:flex}._v_wrq_optionField{flex-direction:column;gap:6px;min-width:0;display:flex}._v_wrq_optionLabel{justify-content:space-between;align-items:center;gap:8px;min-width:0;display:flex}._v_wrq_optionLabel label{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500;line-height:20px}._v_wrq_optionDefault{border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-xs);color:var(--dsw-alias-label-tertiary);padding:0 6px;font-size:11px;line-height:16px}._v_wrq_optionReset{border-radius:var(--dsw-radius-sm);color:var(--dsw-alias-state-business-primary);font:inherit;cursor:pointer;background:0 0;border:0;padding:0 4px;font-size:12px;line-height:18px}._v_wrq_optionReset:disabled{cursor:default;opacity:.5}._v_wrq_optionInput{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-md);width:100%;min-width:0;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-base);font:inherit;resize:vertical;outline:none;padding:7px 10px;font-size:13px;line-height:20px}._v_wrq_optionInput:focus-visible{border-color:var(--dsw-alias-state-business-primary)}._v_wrq_optionInput[aria-invalid=true]{border-color:var(--dsw-alias-state-error-primary)}._v_wrq_optionInput:disabled{opacity:.5}._v_wrq_optionHint{color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;font-size:12px;line-height:18px}._v_wrq_optionHint[data-error]{color:var(--dsw-alias-state-error-primary)}._v_wrq_optionChoices{flex-wrap:wrap;gap:6px 16px;min-width:0;display:flex}._v_wrq_optionEmpty{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}._v_wrq_boardControl{flex-wrap:wrap;flex:0 auto;justify-content:flex-end;align-items:center;gap:6px 12px;min-width:0;margin-left:auto;display:flex}._v_wrq_boardState{min-width:0;color:var(--dsw-alias-label-tertiary);white-space:nowrap;align-items:center;gap:6px;font-size:12px;line-height:18px;display:inline-flex}._v_wrq_boardState[data-tone=warning],._v_wrq_boardState[data-tone=error]{color:var(--dsw-alias-label-secondary)}._v_wrq_boardValue{color:var(--dsw-alias-label-secondary);font-size:13px;line-height:20px}@container (width<=420px){._v_wrq_boardMain ._v_wrq_boardControl{justify-content:stretch;width:100%}._v_wrq_boardMain ._v_wrq_boardControl>:last-child{flex:1}}@container (width<=180px){._v_wrq_boardSection ._v_wrq_sectionHeading p,._v_wrq_boardSection ._v_wrq_settingCopy small{display:none}._v_wrq_boardSection ._v_wrq_boardRow{padding:10px 0}._v_wrq_boardSection ._v_wrq_boardRowLine{grid-template-columns:minmax(0,1fr);gap:6px;display:grid}._v_wrq_boardSection ._v_wrq_settingCopy{min-width:0}._v_wrq_boardSection ._v_wrq_settingCopy strong{overflow-wrap:anywhere}._v_wrq_boardSection ._v_wrq_boardControl{justify-self:end}}._v_wrq_placeholderRow{border-bottom:.5px solid var(--dsw-alias-border-l2);justify-content:space-between;align-items:center;gap:16px;min-height:70px;display:flex}._v_wrq_placeholderRow span{background:var(--dsw-alias-bg-module-platform);border-radius:6px;height:12px;animation:1.4s ease-in-out infinite _v_wrq_placeholder-pulse}._v_wrq_placeholderRow span:first-child{width:38%}._v_wrq_placeholderRow span:last-child{border-radius:10px;width:36px;height:20px}@keyframes _v_wrq_placeholder-pulse{50%{opacity:.45}}@media (prefers-reduced-motion:reduce){._v_wrq_boardRowCopy,._v_wrq_boardOthersToggle>svg{transition:none}._v_wrq_placeholderRow span{animation:none}}._v_wrq_selector{appearance:none;border-radius:var(--dsw-radius-md);max-width:280px;height:36px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-module-platform);white-space:nowrap;cursor:pointer;border:0;align-items:center;gap:12px;padding:0 14px;font-size:14px;line-height:22px;display:inline-flex}._v_wrq_selector>span{text-overflow:ellipsis;min-width:0;overflow:hidden}._v_wrq_selector>svg{color:var(--dsw-alias-label-tertiary);flex:none}._v_wrq_selector:hover:not(:disabled),._v_wrq_selector[aria-expanded=true]{background:var(--dsw-alias-interactive-bg-hover)}._v_wrq_selector:disabled{cursor:default;opacity:.4}._v_wrq_selectMenu{min-width:220px}._v_wrq_selectOption{white-space:normal;gap:1px;min-width:0;display:grid}._v_wrq_selectOption>small{color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;font-size:12px;line-height:18px}._v_wrq_directoryInput{border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-md);width:100%;min-width:0;height:34px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-3);font-family:var(--ds-font-family-code,ui-monospace, monospace);outline:none;padding:0 12px;font-size:12px;line-height:20px}._v_wrq_directoryInput::placeholder{color:var(--dsw-alias-label-dimmed);font-family:var(--dsw-font-family);font-size:13px}._v_wrq_directoryInput:focus-visible{border-color:var(--dsw-alias-state-business-primary)}._v_wrq_directoryInput[aria-invalid=true]{border-color:var(--dsw-alias-state-error-primary)}._v_wrq_directoryInput:disabled{cursor:default;opacity:.5}._v_wrq_rowDetail{border-bottom:.5px solid var(--dsw-alias-border-l2);flex-direction:column;gap:10px;min-width:0;padding:0 0 14px;display:flex}._v_wrq_settingRow:has(+._v_wrq_rowDetail){border-bottom:0;padding-bottom:10px}._v_wrq_effectiveRoute{min-width:0;color:var(--dsw-alias-label-tertiary);justify-content:space-between;align-items:center;gap:12px;font-size:12px;line-height:18px;display:flex}._v_wrq_effectiveRoute code{border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-xs);min-width:0;color:var(--dsw-alias-label-secondary);font-family:var(--ds-font-family-code,ui-monospace, monospace);text-overflow:ellipsis;white-space:nowrap;padding:1px 6px;font-size:11px;line-height:16px;overflow:hidden}._v_wrq_effectiveRoute small{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:12px;overflow:hidden}._v_wrq_warning{color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere;margin:0;font-size:12px;line-height:18px}._v_wrq_advanced{min-width:0;padding:12px 0 2px}._v_wrq_advanced>summary{border-radius:var(--dsw-radius-sm);width:fit-content;color:var(--dsw-alias-label-secondary);cursor:pointer;align-items:center;gap:6px;margin-left:-4px;padding:2px 4px;font-size:12px;font-weight:500;line-height:18px;list-style:none;display:inline-flex}._v_wrq_advanced>summary::-webkit-details-marker{display:none}._v_wrq_advanced>summary>svg{transition:transform .14s}._v_wrq_advanced[open]>summary>svg{transform:rotate(180deg)}._v_wrq_advanced>summary:hover{color:var(--dsw-alias-label-primary)}._v_wrq_advanced>._v_wrq_fieldGrid{padding-top:12px}._v_wrq_miniSpinner{border:2px solid var(--dsw-alias-border-l2);border-top-color:var(--dsw-alias-label-secondary);border-radius:50%;flex:none;width:14px;height:14px;margin-top:4px;animation:.7s linear infinite _v_wrq_settings-spin}@keyframes _v_wrq_settings-spin{to{transform:rotate(360deg)}}._v_wrq_providerList{flex-direction:column;gap:8px;min-width:0;margin-top:10px;display:flex}._v_wrq_providerRow{border:.5px solid var(--dsw-alias-settings-card-stroke);border-radius:var(--dsw-radius-xl);background:var(--dsw-alias-settings-card-fill);overflow:hidden}._v_wrq_providerRowHeader{align-items:center;gap:12px;min-width:0;padding:12px 14px;display:flex}summary._v_wrq_providerRowHeader{cursor:pointer;list-style:none}summary._v_wrq_providerRowHeader::-webkit-details-marker{display:none}._v_wrq_providerDisclosure{appearance:none;min-width:0;color:inherit;cursor:pointer;text-align:left;background:0 0;border:0;outline:none;flex:1;align-items:center;gap:8px;padding:0;display:flex}._v_wrq_providerDisclosure:disabled{cursor:default}._v_wrq_providerDisclosure:focus-visible,summary._v_wrq_providerRowHeader:focus-visible{border-radius:var(--dsw-radius-md);box-shadow:0 0 0 2px var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary))}._v_wrq_providerIdentity{flex:1;align-items:center;gap:12px;min-width:0;display:flex}._v_wrq_providerIdentity>span{flex-direction:column;min-width:0;display:flex}._v_wrq_providerIdentity strong{font-size:14px;font-weight:500;line-height:22px}._v_wrq_providerIdentity small{color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;font-size:12px;line-height:18px;overflow:hidden}._v_wrq_providerMark{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1);flex:none;place-items:center;width:36px;height:36px;padding:6px;display:grid;overflow:hidden}._v_wrq_providerMark>img,._v_wrq_providerMark>svg{object-fit:contain;border-radius:4px;width:100%;height:100%;display:block}._v_wrq_providerEnableControl{flex:none;align-items:center;gap:10px;display:flex}._v_wrq_providerScopeTag{border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-xs);color:var(--dsw-alias-label-secondary);flex:none;padding:1px 6px;font-size:11px;line-height:16px}._v_wrq_providerScopeTag[data-scope=workspace]{border-color:color-mix(in srgb, var(--dsw-alias-state-business-primary) 30%, transparent);color:var(--dsw-alias-state-business-primary)}._v_wrq_providerState{color:var(--dsw-alias-label-tertiary);white-space:nowrap;flex:none;align-items:center;gap:6px;font-size:12px;line-height:18px;display:inline-flex}._v_wrq_providerState:before{content:\"\";background:var(--dsw-alias-state-idle-primary);border-radius:50%;flex:none;width:6px;height:6px}._v_wrq_providerState[data-enabled]:before{background:var(--dsw-alias-state-success-primary)}._v_wrq_providerChevron{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .14s}._v_wrq_providerDisclosure[aria-expanded=true] ._v_wrq_providerChevron,details[open]>summary ._v_wrq_providerChevron{transform:rotate(180deg)}._v_wrq_providerToggle{cursor:pointer;display:inline-flex;position:relative}._v_wrq_providerInlineBody{padding:0 14px 14px}._v_wrq_providerToggleError{color:var(--dsw-alias-state-error-primary);margin:0;padding:0 14px 12px;font-size:12px;line-height:18px}._v_wrq_providerServiceForm,._v_wrq_editor{border-radius:var(--dsw-radius-lg);background:var(--dsw-alias-bg-module-platform);flex-direction:column;gap:12px;min-width:0;padding:14px 16px;display:flex}._v_wrq_providerServicePrompt,._v_wrq_editorNote{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}._v_wrq_editorHeading h3{margin:0;font-size:14px;font-weight:500;line-height:22px}._v_wrq_editorHeading p{color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;margin:2px 0 0;font-size:12px;line-height:18px}._v_wrq_editor ._v_wrq_toggleRow{border-top:.5px solid var(--dsw-alias-border-l3);border-bottom:.5px solid var(--dsw-alias-border-l3);padding:10px 0}._v_wrq_embeddingTest{justify-content:space-between;align-items:center;gap:12px;min-width:0;display:flex}._v_wrq_embeddingTest>span{min-width:0;color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;font-size:12px;line-height:18px}._v_wrq_embeddingTest>span._v_wrq_error{color:var(--dsw-alias-state-error-primary)}._v_wrq_globalLocationSetting{flex-direction:column;min-width:0;display:flex}._v_wrq_providerServiceLocation{border-bottom:.5px solid var(--dsw-alias-border-l3);padding-bottom:12px}._v_wrq_providerServiceLocation>._v_wrq_nativeLocation{padding:0 0 12px}._v_wrq_providerLocationField{padding-top:2px}._v_wrq_nativeLocation{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:8px 16px;min-width:0;display:flex}._v_wrq_inlineChoices{border-radius:var(--dsw-radius-md);background:var(--dsw-alias-interactive-bg-hover);flex:none;align-items:center;gap:2px;padding:3px;display:inline-flex}._v_wrq_inlineChoices label{cursor:pointer;position:relative}._v_wrq_inlineChoices input{z-index:1;opacity:0;width:100%;height:100%;cursor:inherit;margin:0;position:absolute;inset:0}._v_wrq_inlineChoices span{border-radius:var(--dsw-radius-sm);height:28px;color:var(--dsw-alias-label-secondary);white-space:nowrap;align-items:center;padding:0 12px;font-size:13px;font-weight:500;line-height:20px;display:inline-flex}._v_wrq_inlineChoices input:checked+span{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-1);box-shadow:var(--dsw-elevation-soft)}._v_wrq_inlineChoices input:focus-visible+span{box-shadow:0 0 0 2px var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary))}._v_wrq_inlineChoices input:disabled+span{cursor:default;opacity:.4}._v_wrq_fieldGrid,._v_wrq_providerSettingsGrid{grid-template-columns:repeat(auto-fit,minmax(min(100%,200px),1fr));gap:12px;min-width:0;display:grid}._v_wrq_providerSettingsGrid{grid-template-columns:minmax(0,1fr)}._v_wrq_fieldGrid>label,._v_wrq_providerFieldControl>label:not(._v_wrq_providerBoolean){min-width:0;color:var(--dsw-alias-label-primary);flex-direction:column;gap:6px;font-size:13px;font-weight:500;line-height:20px;display:flex}._v_wrq_fieldGrid input,._v_wrq_fieldGrid select,._v_wrq_providerFieldControl input:not([type=checkbox]),._v_wrq_providerFieldControl select{border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-md);width:100%;min-width:0;height:34px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-3);font:inherit;outline:none;padding:0 12px;font-size:13px;font-weight:400;line-height:20px}._v_wrq_fieldGrid input::placeholder,._v_wrq_providerFieldControl input::placeholder{color:var(--dsw-alias-label-dimmed)}._v_wrq_fieldGrid select,._v_wrq_providerFieldControl select{appearance:none;cursor:pointer;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none'%3E%3Cpath d='M3 4.5L6 7.5L9 4.5' stroke='%2381858C' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");background-position:right 12px center;background-repeat:no-repeat;background-size:12px 12px;padding-right:32px}._v_wrq_fieldGrid select:disabled,._v_wrq_providerFieldControl select:disabled{cursor:default}._v_wrq_fieldGrid input:focus-visible,._v_wrq_fieldGrid select:focus-visible,._v_wrq_providerFieldControl input:focus-visible,._v_wrq_providerFieldControl select:focus-visible{border-color:var(--dsw-alias-state-business-primary)}._v_wrq_fieldGrid input[aria-invalid=true],._v_wrq_providerFieldControl input:invalid{border-color:var(--dsw-alias-state-error-primary)}._v_wrq_fieldGrid input:disabled,._v_wrq_fieldGrid select:disabled,._v_wrq_providerFieldControl input:disabled,._v_wrq_providerFieldControl select:disabled{opacity:.5}._v_wrq_providerFieldControl{flex-direction:column;justify-content:flex-end;gap:4px;min-width:0;display:flex}._v_wrq_providerBoolean{min-height:34px;color:var(--dsw-alias-label-primary);align-items:center;gap:8px;font-size:13px;display:flex}._v_wrq_providerBoolean input{width:16px;height:16px;accent-color:var(--dsw-alias-brand-primary);margin:0}._v_wrq_providerSecretInput{min-width:0;position:relative}._v_wrq_providerSecretInput>input{padding-right:40px}._v_wrq_providerSecretVisibility{appearance:none;border-radius:var(--dsw-radius-sm);width:28px;height:28px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;place-items:center;padding:0;display:grid;position:absolute;top:3px;right:3px}._v_wrq_providerSecretVisibility:hover:not(:disabled){color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}._v_wrq_providerSecretVisibility:focus-visible{box-shadow:0 0 0 2px var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline:none}._v_wrq_providerSecretVisibility:disabled{cursor:default;opacity:.35}._v_wrq_providerSecretVisibility svg{width:16px;height:16px}._v_wrq_memoryConfigFooter{justify-content:space-between;align-items:center;gap:10px;min-height:36px;display:flex}._v_wrq_memoryConfigFooter>div{align-items:center;gap:6px;display:flex}._v_wrq_providerServiceFooter{align-items:flex-end;min-height:0}._v_wrq_configFeedback{flex:1;min-width:0;font-size:12px;line-height:18px}._v_wrq_scopeChanging,._v_wrq_providerTarget{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}._v_wrq_scopeChanging{border-radius:var(--dsw-radius-md);color:var(--dsw-alias-state-warn-label,var(--dsw-alias-label-secondary));background:var(--dsw-alias-state-warn-tertiary,var(--dsw-alias-bg-module-platform));padding:8px 12px}._v_wrq_providerLoadError{justify-content:space-between;align-items:center;gap:10px;font-size:12px;display:flex}._v_wrq_visuallyHidden{clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}._v_wrq_location{align-items:baseline;gap:6px;min-width:0;display:flex}._v_wrq_locationRow{border-bottom:.5px solid var(--dsw-alias-border-l2);gap:10px;padding:14px 0}._v_wrq_rowActions{flex:none;align-items:center;gap:8px;display:flex}._v_wrq_packRow{flex-direction:column;gap:8px;min-width:0;padding-bottom:14px;display:flex}._v_wrq_packRow>._v_wrq_settingRow{border-bottom:0;padding-bottom:6px}._v_wrq_packRow:has(>._v_wrq_packFeedback:empty):not(:has(>._v_wrq_importBar))>._v_wrq_settingRow{padding-bottom:0}._v_wrq_rows>._v_wrq_packRow:not(:last-child){border-bottom:.5px solid var(--dsw-alias-border-l2)}._v_wrq_importBar{border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-module-platform);grid-template-columns:minmax(0,1fr) auto auto;align-items:center;gap:10px;min-width:0;padding:10px 12px;display:grid}._v_wrq_importBar>div{min-width:0;display:grid}._v_wrq_importBar strong{text-overflow:ellipsis;white-space:nowrap;font-size:13px;font-weight:500;line-height:20px;overflow:hidden}._v_wrq_importBar small{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}._v_wrq_packFeedback{gap:4px;display:grid}._v_wrq_packFeedback:empty{display:none}._v_wrq_packFeedback p{overflow-wrap:anywhere;margin:0;font-size:12px;line-height:18px}._v_wrq_error{color:var(--dsw-alias-state-error-primary)}._v_wrq_readOnlyNotice{color:var(--dsw-alias-label-tertiary);margin:0 0 -20px;font-size:12px;line-height:18px}._v_wrq_packSuccess{color:var(--dsw-alias-state-success-primary)}._v_wrq_syncRow{flex-direction:column;gap:8px;min-width:0;padding-bottom:14px;display:flex}._v_wrq_syncRow>._v_wrq_settingRow,._v_wrq_syncRow>._v_wrq_toggleRow{border-bottom:0;padding-bottom:6px}._v_wrq_rows>._v_wrq_syncRow:not(:last-child){border-bottom:.5px solid var(--dsw-alias-border-l2)}._v_wrq_syncState{flex-wrap:wrap;align-items:center;gap:4px 10px;min-width:0;display:flex}._v_wrq_syncState>span{color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;font-size:12px;line-height:18px}._v_wrq_syncSuccess{color:var(--dsw-alias-state-success-primary)}._v_wrq_syncPanel{border:.5px solid var(--dsw-alias-settings-card-stroke);border-radius:var(--dsw-radius-xl);flex-direction:column;min-width:0;padding:2px 16px;display:flex}._v_wrq_syncPanel>._v_wrq_settingRow{padding:12px 0}._v_wrq_syncPanel>p{overflow-wrap:anywhere;margin:12px 0;font-size:12px;line-height:18px}._v_wrq_syncPanel>:last-child,._v_wrq_syncPanel>:last-child>._v_wrq_settingRow:last-child{border-bottom:0}._v_wrq_syncFeedbackLine{padding-top:2px;display:block}._v_wrq_syncWarning{border-radius:var(--dsw-radius-md);min-width:0;color:var(--dsw-alias-state-warn-label,var(--dsw-alias-label-secondary));background:var(--dsw-alias-state-warn-tertiary,var(--dsw-alias-bg-module-platform));flex-wrap:wrap;justify-content:space-between;align-items:center;gap:6px 12px;margin:10px 0 2px;padding:6px 6px 6px 12px;font-size:12px;line-height:18px;display:flex}._v_wrq_syncWarning>span{overflow-wrap:anywhere;min-width:0}._v_wrq_syncConnect{border-bottom:.5px solid var(--dsw-alias-border-l2);flex-direction:column;gap:4px;min-width:0;padding-bottom:14px;display:flex}._v_wrq_syncConnect>._v_wrq_settingRow{border-bottom:0;padding-bottom:4px}._v_wrq_syncRepositoryState{flex-direction:column;gap:2px;min-width:0;display:flex}._v_wrq_syncRepositoryName{min-width:0;color:var(--dsw-alias-label-secondary);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}._v_wrq_syncStateLine{flex-wrap:wrap;align-items:center;gap:4px 6px;min-width:0;display:inline-flex}._v_wrq_syncStateLine[data-tone=error]>span{color:var(--dsw-alias-state-error-primary)}._v_wrq_syncInlineAction{appearance:none;color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;text-decoration:underline;text-decoration-color:var(--dsw-alias-border-l4);text-underline-offset:2px;background:0 0;border:0;padding:0;font-size:12px;line-height:18px}._v_wrq_syncInlineAction:hover:not(:disabled){color:var(--dsw-alias-label-primary);text-decoration-color:currentColor}._v_wrq_syncInlineAction:disabled{cursor:default;opacity:.5}._v_wrq_syncInlineAction:focus-visible{border-radius:var(--dsw-radius-xs);box-shadow:0 0 0 2px var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline:none}._v_wrq_syncFieldLabel{min-width:0;color:var(--dsw-alias-label-primary);justify-content:space-between;align-items:center;gap:8px;font-size:13px;font-weight:500;line-height:20px;display:flex}._v_wrq_syncFieldLabel>label{font:inherit}._v_wrq_fieldGrid>._v_wrq_syncFieldBox{flex-direction:column;gap:6px;min-width:0;display:flex}._v_wrq_fieldGrid label small{color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;font-size:12px;font-weight:400;line-height:18px}._v_wrq_fieldGrid label small._v_wrq_error{color:var(--dsw-alias-state-error-primary)}._v_wrq_editor ._v_wrq_error,._v_wrq_editor ._v_wrq_syncSuccess{overflow-wrap:anywhere;margin:0;font-size:12px;line-height:18px}._v_wrq_syncAccount{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:8px;min-width:0;display:flex}._v_wrq_syncAccount>span{color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere;font-size:13px;line-height:20px}._v_wrq_syncDevice{gap:8px;min-width:0;display:grid}._v_wrq_syncCode{flex-wrap:wrap;align-items:center;gap:8px;min-width:0;display:flex}._v_wrq_syncCode>code{border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-md);color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-1);font-family:var(--ds-font-family-code,ui-monospace, monospace);letter-spacing:.08em;user-select:all;padding:4px 12px;font-size:16px;font-weight:500;line-height:24px}._v_wrq_syncPicker{gap:8px;min-width:0;display:grid}._v_wrq_syncRepositoryList{border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1);flex-direction:column;min-width:0;max-height:264px;margin:0;padding:0;list-style:none;display:flex;overflow:auto}._v_wrq_syncRepositoryList>li{border-bottom:.5px solid var(--dsw-alias-border-l2);min-width:0}._v_wrq_syncRepositoryList>li:last-child{border-bottom:0}._v_wrq_syncRepositoryList>li._v_wrq_editorNote{padding:10px 12px}._v_wrq_syncRepositoryOption{appearance:none;width:100%;min-width:0;color:var(--dsw-alias-label-primary);font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;align-items:center;gap:6px;padding:8px 12px;font-size:13px;line-height:20px;display:flex}._v_wrq_syncRepositoryOption>span{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}._v_wrq_syncRepositoryOption:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}._v_wrq_syncRepositoryOption:disabled{cursor:default;opacity:.5}._v_wrq_syncRepositoryOption[aria-current=true]>span{font-weight:500}._v_wrq_syncRepositoryOption:focus-visible{box-shadow:inset 0 0 0 2px var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline:none}._v_wrq_syncAdvanced{flex-direction:column;gap:4px;min-width:0;padding-bottom:12px;display:flex}._v_wrq_syncDisclosure{appearance:none;width:100%;min-width:0;color:inherit;font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;align-items:center;gap:10px;padding:12px 0 8px;display:flex}._v_wrq_syncDisclosure>span{color:var(--dsw-alias-label-primary);flex:none;font-size:14px;line-height:22px}._v_wrq_syncDisclosure>small{min-width:0;color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;flex:1;font-size:12px;line-height:18px;overflow:hidden}._v_wrq_syncDisclosure[aria-expanded=true] ._v_wrq_providerChevron{transform:rotate(180deg)}._v_wrq_syncDisclosure:focus-visible{border-radius:var(--dsw-radius-md);box-shadow:0 0 0 2px var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline:none}._v_wrq_editor>._v_wrq_inlineChoices{align-self:flex-start}._v_wrq_syncChoice{justify-items:start;gap:8px;min-width:0;display:grid}._v_wrq_syncChoice>._v_wrq_fieldGrid{width:100%}._v_wrq_syncDialogBody{gap:12px;min-width:0;display:grid}._v_wrq_syncDialogNote{color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;margin:0;font-size:12px;line-height:18px}._v_wrq_syncDialogBody>._v_wrq_error,._v_wrq_syncDialogBody>._v_wrq_syncSuccess{overflow-wrap:anywhere;margin:0;font-size:12px;line-height:18px}._v_wrq_syncHistoryList{margin:0;padding:0;list-style:none;display:grid}._v_wrq_syncHistoryEntry{border-bottom:.5px solid var(--dsw-alias-border-l2);gap:2px;min-width:0;padding:10px 0;display:grid}._v_wrq_syncHistoryEntry:first-child{padding-top:0}._v_wrq_syncHistoryEntry:last-child{border-bottom:0}._v_wrq_syncHistoryHead{flex-wrap:wrap;align-items:center;gap:4px 8px;min-width:0;display:flex}._v_wrq_syncHistoryHead>strong{font-size:13px;font-weight:500;line-height:20px}._v_wrq_syncHistoryHead>span{min-width:0;color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere;flex:1;font-size:12px;line-height:18px}._v_wrq_syncHistoryEntry>small{color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;font-size:12px;line-height:18px}._v_wrq_syncHistoryEntry>._v_wrq_syncHistoryMessage{color:var(--dsw-alias-label-secondary)}._v_wrq_syncCompareList{border:.5px solid var(--dsw-alias-settings-card-stroke);border-radius:var(--dsw-radius-md);margin:0;padding:0;list-style:none;display:grid}._v_wrq_syncCompareList>li{border-bottom:.5px solid var(--dsw-alias-border-l2);flex-wrap:wrap;justify-content:space-between;align-items:center;gap:4px 12px;min-width:0;padding:10px 12px;display:flex}._v_wrq_syncCompareList>li:last-child{border-bottom:0}._v_wrq_syncCompareList>li>span{font-size:13px;line-height:20px}._v_wrq_syncCompareList>li>small{color:var(--dsw-alias-label-tertiary);text-align:right;overflow-wrap:anywhere;font-size:12px;line-height:18px}._v_wrq_syncCompareList>li>small[data-differs]{color:var(--dsw-alias-label-primary)}._v_wrq_syncCompareNote{border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-module-platform);gap:6px;min-width:0;padding:10px 12px;display:grid}._v_wrq_syncCompareNote>._v_wrq_rowActions{justify-content:flex-start;gap:4px}._v_wrq_syncConflictList{gap:6px;margin:0;padding:0;list-style:none;display:grid}._v_wrq_syncConflict{border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-bg-layer-1);grid-template-columns:repeat(auto-fit,minmax(min(100%,220px),1fr));gap:8px;min-width:0;padding:8px 10px;display:grid}._v_wrq_syncConflict>span{overflow-wrap:anywhere;gap:2px;min-width:0;font-size:12px;line-height:18px;display:grid}._v_wrq_syncConflict>span>small{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}._v_wrq_reviewList{gap:8px;display:grid}._v_wrq_reviewEntry{border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-module-platform);flex-direction:column;gap:6px;min-width:0;padding:10px 12px;display:flex}._v_wrq_reviewEntry>header{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:8px;min-width:0;display:flex}._v_wrq_reviewEntry>small{color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;font-size:12px;line-height:18px}._v_wrq_reviewEntry>p{overflow-wrap:anywhere;margin:0;font-size:13px;line-height:20px}._v_wrq_reviewTitle{align-items:center;gap:8px;min-width:0;display:flex}._v_wrq_reviewTitle strong{overflow-wrap:anywhere;font-size:13px;font-weight:500;line-height:20px}._v_wrq_reviewOperations{gap:4px;margin:0;padding-left:18px;display:grid}._v_wrq_reviewOperations li{overflow-wrap:anywhere;font-size:12px;line-height:18px}._v_wrq_reviewOperations small{color:var(--dsw-alias-label-tertiary);display:block}._v_wrq_reviewOpinions{gap:4px;display:grid}._v_wrq_reviewOpinions>strong{font-size:12px;font-weight:500;line-height:18px}._v_wrq_reviewOpinions>small{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}._v_wrq_reviewOpinions>div{overflow-wrap:anywhere;gap:6px;min-width:0;font-size:12px;line-height:18px;display:flex}._v_wrq_reviewOpinions>div strong{color:var(--dsw-alias-label-secondary);flex:none;font-weight:500}._v_wrq_reviewOpinionForm{align-items:center;gap:8px;min-width:0;display:flex}._v_wrq_reviewOpinionForm>input{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-md);min-width:0;height:34px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-3);font:inherit;outline:none;flex:auto;padding:0 12px;font-size:13px;line-height:20px}._v_wrq_reviewOpinionForm>input:focus-visible{border-color:var(--dsw-alias-state-business-primary)}._v_wrq_reviewOpinionForm>input:disabled{cursor:default;opacity:.5}._v_wrq_reviewGuidance{gap:4px;display:grid}._v_wrq_reviewGuidance>label{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:500;line-height:18px}._v_wrq_reviewGuidance>input{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-md);width:100%;height:34px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-3);font:inherit;outline:none;padding:0 12px;font-size:13px;line-height:20px}._v_wrq_reviewGuidance>input:focus-visible{border-color:var(--dsw-alias-state-business-primary)}._v_wrq_reviewGuidance>input:disabled{cursor:default;opacity:.5}._v_wrq_reviewGuidance>small{color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;font-size:12px;line-height:18px}._v_wrq_reviewSelection{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:6px;min-width:0;display:flex}._v_wrq_reviewSelection>small,._v_wrq_reviewSelected{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}._v_wrq_reviewOperations>li{gap:2px;display:grid}._v_wrq_reviewOperations>li>label{cursor:pointer;align-items:flex-start;gap:6px;min-width:0;display:flex}._v_wrq_reviewOperations>li>label>input{flex:none;margin:3px 0 0}._v_wrq_reviewOperations>li>label>input:disabled{cursor:default;opacity:.5}._v_wrq_reviewOperations>li[data-applied=true]{opacity:.55}._v_wrq_selector:focus-visible{box-shadow:0 0 0 2px var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline:none}@media (width<=620px){._v_wrq_page{gap:28px}._v_wrq_rowActions{width:100%}._v_wrq_rowActions button{flex:1}._v_wrq_importBar{grid-template-columns:minmax(0,1fr) auto}._v_wrq_importBar>button:last-child{grid-column:1/-1}._v_wrq_reviewOpinionForm{flex-wrap:wrap}._v_wrq_reviewOpinionForm>input{flex:100%}._v_wrq_inlineChoices{width:100%}._v_wrq_inlineChoices label{flex:1}._v_wrq_inlineChoices span{justify-content:center;width:100%}._v_wrq_providerRowHeader{align-items:flex-start;gap:8px}._v_wrq_providerEnableControl{flex-wrap:wrap;justify-content:flex-end;gap:6px;max-width:132px}._v_wrq_providerState{text-overflow:ellipsis;max-width:120px;overflow:hidden}._v_wrq_memoryConfigFooter{flex-direction:column;align-items:stretch}._v_wrq_memoryConfigFooter>div:last-child{width:100%}._v_wrq_memoryConfigFooter button{flex:1}}@media (prefers-reduced-motion:reduce){._v_wrq_providerChevron,._v_wrq_advanced>summary>svg{transition:none}._v_wrq_miniSpinner{animation:none}}";
666
677
  const tagId$13 = "dsh-mnemon/src/client/MnemonSettingsCard.module.css";
667
678
  if (typeof document !== "undefined") {
668
679
  let tag = document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$13) + "]");
@@ -787,7 +798,6 @@ window.__ModuleLoader__.load({
787
798
  "reviewOperations": "_v_wrq_reviewOperations",
788
799
  "reviewOpinionForm": "_v_wrq_reviewOpinionForm",
789
800
  "reviewOpinions": "_v_wrq_reviewOpinions",
790
- "reviewRules": "_v_wrq_reviewRules",
791
801
  "reviewSelected": "_v_wrq_reviewSelected",
792
802
  "reviewSelection": "_v_wrq_reviewSelection",
793
803
  "reviewTitle": "_v_wrq_reviewTitle",
@@ -808,30 +818,37 @@ window.__ModuleLoader__.load({
808
818
  "surface": "_v_wrq_surface",
809
819
  "switch": "_v_wrq_switch",
810
820
  "syncAccount": "_v_wrq_syncAccount",
811
- "syncBackupComponents": "_v_wrq_syncBackupComponents",
812
- "syncBackupEntry": "_v_wrq_syncBackupEntry",
813
- "syncBackupList": "_v_wrq_syncBackupList",
814
- "syncBackups": "_v_wrq_syncBackups",
815
- "syncBar": "_v_wrq_syncBar",
816
- "syncBlock": "_v_wrq_syncBlock",
817
- "syncCheck": "_v_wrq_syncCheck",
821
+ "syncAdvanced": "_v_wrq_syncAdvanced",
822
+ "syncChoice": "_v_wrq_syncChoice",
818
823
  "syncCode": "_v_wrq_syncCode",
824
+ "syncCompareList": "_v_wrq_syncCompareList",
825
+ "syncCompareNote": "_v_wrq_syncCompareNote",
819
826
  "syncConflict": "_v_wrq_syncConflict",
820
827
  "syncConflictList": "_v_wrq_syncConflictList",
821
- "syncConflictSides": "_v_wrq_syncConflictSides",
828
+ "syncConnect": "_v_wrq_syncConnect",
829
+ "syncDevice": "_v_wrq_syncDevice",
822
830
  "syncDialogBody": "_v_wrq_syncDialogBody",
823
831
  "syncDialogNote": "_v_wrq_syncDialogNote",
824
- "syncDiff": "_v_wrq_syncDiff",
825
- "syncDiffColumns": "_v_wrq_syncDiffColumns",
826
- "syncDiffMeta": "_v_wrq_syncDiffMeta",
827
- "syncFeedback": "_v_wrq_syncFeedback",
828
- "syncField": "_v_wrq_syncField",
829
- "syncForm": "_v_wrq_syncForm",
830
- "syncFormActions": "_v_wrq_syncFormActions",
831
- "syncPlan": "_v_wrq_syncPlan",
832
+ "syncDisclosure": "_v_wrq_syncDisclosure",
833
+ "syncFeedbackLine": "_v_wrq_syncFeedbackLine",
834
+ "syncFieldBox": "_v_wrq_syncFieldBox",
835
+ "syncFieldLabel": "_v_wrq_syncFieldLabel",
836
+ "syncHistoryEntry": "_v_wrq_syncHistoryEntry",
837
+ "syncHistoryHead": "_v_wrq_syncHistoryHead",
838
+ "syncHistoryList": "_v_wrq_syncHistoryList",
839
+ "syncHistoryMessage": "_v_wrq_syncHistoryMessage",
840
+ "syncInlineAction": "_v_wrq_syncInlineAction",
841
+ "syncPanel": "_v_wrq_syncPanel",
842
+ "syncPicker": "_v_wrq_syncPicker",
843
+ "syncRepositoryList": "_v_wrq_syncRepositoryList",
844
+ "syncRepositoryName": "_v_wrq_syncRepositoryName",
845
+ "syncRepositoryOption": "_v_wrq_syncRepositoryOption",
846
+ "syncRepositoryState": "_v_wrq_syncRepositoryState",
832
847
  "syncRow": "_v_wrq_syncRow",
833
848
  "syncState": "_v_wrq_syncState",
849
+ "syncStateLine": "_v_wrq_syncStateLine",
834
850
  "syncSuccess": "_v_wrq_syncSuccess",
851
+ "syncWarning": "_v_wrq_syncWarning",
835
852
  "toggleRow": "_v_wrq_toggleRow",
836
853
  "visuallyHidden": "_v_wrq_visuallyHidden",
837
854
  "warning": "_v_wrq_warning"
@@ -2406,129 +2423,182 @@ window.__ModuleLoader__.load({
2406
2423
  "config.syncSimpleDescription": "把上述组件的数据同步到 Git 仓库;不含第三方 Provider 与密钥",
2407
2424
  "config.syncLoading": "正在读取同步状态…",
2408
2425
  "config.syncUnavailable": "当前 DSH 主机不支持 Mnemon 仓库同步通道。",
2409
- "config.syncNotConfigured": "尚未配置仓库",
2410
- "config.syncGitMissing": "缺少 Git {required} 或更高版本",
2411
- "config.syncRemoteBranchMissing": "远端还没有 {branch} 分支",
2412
- "config.syncRemoteUnreachable": "远端不可达",
2413
- "config.syncRemoteCommit": "远端 {commit}",
2414
- "config.syncTokenSaved": "已保存凭据",
2415
- "config.syncTokenNone": "未保存凭据",
2416
- "config.syncSave": "保存",
2417
- "config.syncSaved": "已保存仓库同步配置。",
2418
- "config.syncFailed": "同步操作失败:{error}",
2419
- "config.syncPush": "推送",
2420
- "config.syncPushing": "推送中…",
2421
- "config.syncPushed": "已推送 {commit}({files} 个文件,{size})。",
2422
- "config.syncPushedLocal": "已提交 {commit},但推送未完成:{reason}",
2423
- "config.syncPushIdle": "远端已是当前内容,没有新的提交。",
2424
- "config.syncPreview": "检查远端",
2425
- "config.syncPreviewing": "检查中…",
2426
- "config.syncPreviewReady": "远端 {commit} · {components} 个组件 · {size}",
2427
- "config.syncPreviewComponents": "{changed}/{total} 个组件与本地不同",
2428
- "config.syncPreviewFiles": "新增 {added} · 缺失 {removed} · 不同 {changed}",
2429
- "config.syncPull": "拉取并合并",
2430
- "config.syncPulling": "拉取中…",
2431
- "config.syncPulled": "已把远端 {commit} 合并到 {root}。",
2432
- "config.syncBackups": "备份历史",
2433
- "config.syncBackupsLoading": "读取中…",
2434
- "config.syncBackupsTitle": "{branch} 上的备份",
2435
- "config.syncBackupsHint": "每次推送在 {subdir} 留下一个提交;这里显示每次备份来自哪台设备、包含什么,一次读一页",
2436
- "config.syncBackupsEmpty": "远端分支上还没有备份。",
2437
- "config.syncBackupsMore": "读取更早的备份",
2438
- "config.syncBackupMeta": "来自 {machine} · {time}",
2439
- "config.syncBackupPushedAt": "推送于 {time}",
2440
- "config.syncBackupComponent": "{component}:{items} 条记忆 · {files} 个文件 · {size}",
2441
- "config.syncBackupNoComponents": "这次提交没有可读的清单。",
2442
- "config.syncBackupUnknownMachine": "未标注设备",
2443
- "config.syncDiffTitle": "与远端 {commit} 的记忆差异(共有 {shared} 条)",
2444
- "config.syncDiffSides": "本地 {local} 条 · 远端 {remote} 条 · 远端来自 {machine}",
2445
- "config.syncDiffTruncated": "差异超过上限,只列出了前一部分。",
2446
- "config.syncDiffTombstones": "远端记录了 {count} 条删除,本机尚未应用。",
2447
- "config.syncDiffLocalOnly": "只在本机({count})",
2448
- "config.syncDiffRemoteOnly": "只在远端({count})",
2449
- "config.syncDiffNone": "没有",
2450
- "config.syncDiffFrom": "来自 {machine}",
2451
- "config.syncDiffClear": "没有冲突:两边没有同一主题的两种写法。",
2452
- "config.syncDiffNothing": "本机与远端没有需要合并的记忆。",
2453
- "config.syncDiffConflicts": "有 {count} 个主题两边写法不同,需要整理。",
2454
- "config.syncDiffHere": "本机",
2455
- "config.syncDiffThere": "远端",
2456
- "config.syncDiffAdditions": "远端还有 {count} 条本机没有的记忆,可以直接新增。",
2457
- "config.syncDiffLocalOnlyNote": "本机还有 {count} 条远端没有的记忆,推送后即可共享。",
2458
- "config.syncDiffHeldBack": "远端还有 {count} 条记忆是本机以前删掉的;直接新增会按删除处理,把它们留在原处。",
2459
- "config.syncDiffAdd": "直接新增",
2460
- "config.syncDiffAdding": "新增中…",
2461
- "config.syncDiffRevive": "恢复这些记忆",
2462
- "config.syncDiffReviving": "恢复中…",
2463
- "config.syncDiffAdded": "已新增远端 {commit} 的记忆到 {root}。",
2464
- "config.syncDiffAddHeld": "其中 {count} 条本机以前删过,仍留在原处;要加回请点“恢复这些记忆”。",
2465
- "config.syncPlanWhere": "这份方案由下方“记忆整理”统一整理、审查与执行。",
2466
- "config.syncPlanGo": "到“记忆整理”处理",
2426
+ "config.syncUnavailableReason": "无法读取同步状态:{error}",
2427
+ "config.syncGitMissing": "同步需要 Git {required} 或更高版本",
2428
+ "config.syncRecheck": "重新检查",
2429
+ "config.syncFixCredentials": "设置凭据",
2430
+ "config.syncRepository": "仓库",
2431
+ "config.syncRepositoryHint": "选择保存记忆的 Git 仓库",
2432
+ "config.syncChange": "更改",
2433
+ "config.syncDisconnect": "断开",
2434
+ "config.syncDisconnectTitle": "断开这个仓库?",
2435
+ "config.syncDisconnectBody": "之后不再同步到 {repository},自动同步也会关闭。本机记忆和仓库里的内容都不会删除;保存的访问令牌会一并移除。",
2436
+ "config.syncDisconnected": "已断开仓库。",
2437
+ "config.syncStateChecking": "正在检查仓库…",
2438
+ "config.syncStateConnected": "已连接",
2439
+ "config.syncStateNewBranch": "已连接 · 首次同步会创建 {branch} 分支",
2440
+ "config.syncNoCredential": "推送需要 GitHub 登录或访问令牌",
2441
+ "config.syncNoCredentialToken": "推送需要访问令牌",
2442
+ "config.syncIssueAuthHttps": "需要凭据,请用 GitHub 登录或填写访问令牌",
2443
+ "config.syncIssueAuthToken": "需要凭据,请填写访问令牌",
2444
+ "config.syncIssueAuthSsh": "SSH 认证失败,请检查这台电脑的 SSH 密钥",
2445
+ "config.syncIssueAuth": "没有访问这个仓库的权限",
2446
+ "config.syncIssueNotFound": "找不到这个仓库,请检查地址和访问权限",
2447
+ "config.syncIssueNotFoundGitHub": "找不到这个仓库,请检查地址;私有仓库需要先登录或填写令牌",
2448
+ "config.syncIssueNetwork": "无法连接到仓库,请检查网络或代理",
2449
+ "config.syncIssueTimeout": "仓库没有及时响应",
2450
+ "config.syncIssueUnknown": "无法读取仓库:{error}",
2451
+ "config.syncViaGitHub": "通过 GitHub @{login}",
2452
+ "config.syncViaGitHubAnonymous": "通过 GitHub 登录",
2453
+ "config.syncViaToken": "使用访问令牌",
2454
+ "config.syncViaEnvironment": "使用环境变量 {env}",
2455
+ "config.syncViaSsh": "使用 SSH 密钥",
2456
+ "config.syncConnectWith": "连接方式",
2457
+ "config.syncModeGitHub": "GitHub 账号",
2458
+ "config.syncModeAddress": "仓库地址",
2467
2459
  "config.syncRepoUrl": "仓库地址",
2468
- "config.syncRepoUrlHint": "HTTPS、SSH 或本机绝对路径;不要把令牌写进地址",
2469
- "config.syncBranch": "分支",
2470
- "config.syncBranchHint": "默认 {branch}",
2471
- "config.syncSubdir": "远端目录",
2472
- "config.syncSubdirHint": "仓库内存放 payload 的目录,默认 {subdir}",
2460
+ "config.syncRepoUrlPlaceholder": "https://…、git@主机:路径 或本机绝对路径",
2461
+ "config.syncRepoUrlInvalid": "地址需要是 https://、ssh://、git@主机:路径 或本机绝对路径",
2462
+ "config.syncRepoUrlCredentials": "不要把令牌写进地址,请填在“访问令牌”里",
2473
2463
  "config.syncToken": "访问令牌",
2474
- "config.syncTokenHint": "只存在本机 {path}(0600);环境变量 {env} 优先",
2475
- "config.syncTokenKeep": "留空表示保持已保存的凭据",
2476
- "config.syncTokenClear": "清除凭据",
2477
- "config.syncTokenClearHint": "保存时删除本机保存的凭据",
2478
- "config.syncAuthorName": "提交者姓名",
2479
- "config.syncAuthorEmail": "提交者邮箱",
2480
- "config.syncAuthorOptional": "可选",
2481
- "config.syncAuthorHint": "留空则使用本机 Git 身份",
2482
- "config.syncAutoBackup": "自动备份",
2483
- "config.syncAutoBackupHint": "按下面的间隔自动推送一次;关闭后只在你点「推送」时推送",
2484
- "config.syncAutoBackupOff": "关闭(只手动)",
2485
- "config.syncAutoBackupHours": "{hours} 小时",
2486
- "config.syncAutoBackupDays": "{days} 天",
2487
- "config.syncAutoBackupSaved": "自动备份已设为 {interval}",
2488
- "config.syncAutoBackupNext": "下次自动备份:{at}",
2489
- "config.syncAutoBackupNever": "自动备份已关闭,只有你点「推送」时才会推送",
2490
- "config.syncAutoBackupLast": "最近一次自动备份:{at}",
2491
- "config.syncAutoBackupFailed": "最近一次自动备份失败:{error}",
2492
- "config.syncCompacted": "已把 {count} 个零散对象收进包,{before} → {after},之后克隆只需下载 {after}",
2493
- "config.syncGitHub": "GitHub 账号",
2494
- "config.syncGitHubHint": "登录后可直接选择或新建仓库,凭据只留在本机",
2495
- "config.syncGitHubUnavailable": "当前 DSH 主机没有可用的凭据存储,请改用访问令牌",
2464
+ "config.syncTokenOptional": "可选",
2465
+ "config.syncTokenSaved": "已保存;输入新令牌可替换",
2466
+ "config.syncTokenEnvironment": "正在使用环境变量 {env}",
2467
+ "config.syncTokenHint": "只有 HTTPS 地址需要令牌,令牌只保存在这台电脑",
2468
+ "config.syncTokenRemove": "移除",
2469
+ "config.syncTokenRemoved": "已移除访问令牌。",
2470
+ "config.syncConnect": "连接",
2471
+ "config.syncConnecting": "连接中…",
2472
+ "config.syncSave": "保存",
2473
+ "config.syncSaving": "保存中…",
2474
+ "config.syncGitHubHint": "登录后可直接选择或新建仓库;授权只保存在这台电脑",
2496
2475
  "config.syncGitHubReadOnly": "当前凭据存储只读,登录无法保存",
2497
2476
  "config.syncGitHubSignIn": "使用 GitHub 登录",
2498
2477
  "config.syncGitHubStarting": "获取设备码…",
2499
- "config.syncGitHubCode": "在 GitHub 输入此设备码:",
2500
- "config.syncGitHubCopy": "复制",
2501
- "config.syncGitHubCopied": "已复制",
2502
- "config.syncGitHubOpen": "打开 GitHub 授权页",
2478
+ "config.syncGitHubCode": "在 GitHub 页面输入这个设备码:",
2479
+ "config.syncGitHubCopyOpen": "复制并打开 GitHub",
2480
+ "config.syncGitHubCopied": "已复制,在打开的页面中粘贴即可;完成后会自动继续",
2481
+ "config.syncGitHubOpenBlocked": "浏览器没有打开新页面,请手动访问 {url}",
2503
2482
  "config.syncGitHubWaiting": "等待授权…完成后会自动继续",
2504
2483
  "config.syncGitHubSignedIn": "已登录 @{login}",
2505
2484
  "config.syncGitHubSignOut": "退出登录",
2506
2485
  "config.syncGitHubFailed": "GitHub 登录失败:{error}",
2507
2486
  "config.syncGitHubExpired": "设备码已过期,请重新登录",
2508
2487
  "config.syncGitHubDenied": "授权已被拒绝",
2509
- "config.syncTokenGitHub": "GitHub 登录",
2510
- "config.syncTokenEnvironment": "使用环境变量凭据",
2511
- "config.syncTokenOptional": "可选:也可以直接填访问令牌",
2512
- "config.syncRepositories": "选择仓库",
2513
- "config.syncRepositoriesHint": "从账号下的仓库中选择",
2514
- "config.syncRepositoriesSignIn": "登录后这里会列出你的仓库,可直接选用或新建;不登录也可以在手填表单里填写地址",
2515
- "config.syncRepositoriesLoading": "读取仓库…",
2516
- "config.syncRepositoriesLoad": "刷新列表",
2517
- "config.syncRepositoriesEmpty": "账号下还没有仓库,可以在下面新建",
2518
- "config.syncRepositoriesChoose": "选择已有仓库…",
2519
- "config.syncRepositoriesPrivate": "私有",
2520
- "config.syncRepositoriesNoPush": "无推送权限",
2521
- "config.syncRepositoryName": "新建仓库",
2522
- "config.syncRepositoryPrivate": "创建为私有仓库",
2523
- "config.syncRepositoryCreate": "新建并选用",
2488
+ "config.syncGitHubExpiredGrant": "GitHub 授权已失效,请重新登录",
2489
+ "config.syncGitHubSignInAgain": "重新登录",
2490
+ "config.syncRepositoryLabel": "仓库",
2491
+ "config.syncRepositorySearch": "搜索仓库,或输入新仓库名",
2492
+ "config.syncRepositoriesLoading": "正在读取仓库…",
2493
+ "config.syncRepositoriesFailed": "读取仓库失败:{error}",
2494
+ "config.syncRepositoriesRetry": "重试",
2495
+ "config.syncRepositoriesNone": "账号下还没有仓库,输入名称即可新建",
2496
+ "config.syncRepositoriesEmpty": "没有匹配的仓库",
2497
+ "config.syncRepositoriesMore": "还有 {count} 个仓库,输入名称缩小范围",
2498
+ "config.syncRepositoryPrivate": "私有",
2499
+ "config.syncRepositoryPublic": "公开",
2500
+ "config.syncRepositoryNoPush": "无推送权限",
2501
+ "config.syncRepositoryCurrent": "当前",
2502
+ "config.syncRepositoryCreate": "新建私有仓库 {name}",
2524
2503
  "config.syncRepositoryCreating": "创建中…",
2525
- "config.syncRepositoryCreated": "已新建 {name}。",
2504
+ "config.syncRepositoryNameInvalid": "仓库名只能包含字母、数字、点、短横线和下划线",
2505
+ "config.syncPublicTitle": "使用公开仓库?",
2506
+ "config.syncPublicBody": "{name} 是公开仓库:同步后任何人都能看到这些记忆。",
2507
+ "config.syncPublicConfirm": "仍然使用",
2508
+ "config.syncRowTitle": "同步",
2509
+ "config.syncNever": "同步时先合并仓库里的记忆,再推送本机的",
2510
+ "config.syncLast": "上次同步:{time}",
2511
+ "config.syncLastMerge": "上次合并:{time}",
2512
+ "config.syncCheck": "检查远端",
2513
+ "config.syncNow": "立即同步",
2514
+ "config.syncNowRunning": "同步中…",
2515
+ "config.syncDone": "已同步,推送了 {commit}。",
2516
+ "config.syncDoneMerged": "已同步:合并了 {count} 条远端记忆,推送了 {commit}。",
2517
+ "config.syncUpToDate": "已是最新,仓库与本机一致。",
2518
+ "config.syncUpToDateMerged": "合并了 {count} 条远端记忆,仓库已是最新。",
2519
+ "config.syncPushFailed": "已在本机提交,但推送没有完成:{reason}",
2520
+ "config.syncFailed": "同步失败:{error}",
2521
+ "config.syncReasonBusy": "另一个同步操作还在进行,请稍后再试",
2522
+ "config.syncReasonNoRepository": "还没有连接仓库",
2523
+ "config.syncReasonGitMissing": "这台电脑的 Git 不可用",
2524
+ "config.syncReasonRemoteEmpty": "仓库里还没有备份,先同步一次",
2525
+ "config.syncReasonRejected": "同步时仓库又被其他设备更新了,请再同步一次",
2526
+ "config.syncAuto": "自动同步",
2527
+ "config.syncAutoOff": "关闭",
2528
+ "config.syncAutoHour": "每小时",
2529
+ "config.syncAutoHours": "每 {hours} 小时",
2530
+ "config.syncAutoDay": "每天",
2531
+ "config.syncAutoDays": "每 {days} 天",
2532
+ "config.syncAutoHintOff": "只在你点“立即同步”时同步",
2533
+ "config.syncAutoHintOn": "按间隔在后台同步,和“立即同步”做的事一样",
2534
+ "config.syncAutoNext": "下次 {time}",
2535
+ "config.syncAutoLast": "上次 {time}",
2536
+ "config.syncAutoFailed": "上次自动同步失败:{error}",
2537
+ "config.syncHistory": "备份历史",
2538
+ "config.syncHistoryHint": "每次同步都在仓库里留下一个版本",
2539
+ "config.syncHistoryView": "查看",
2540
+ "config.syncHistoryLoading": "正在读取…",
2541
+ "config.syncHistoryEmpty": "仓库里还没有备份。",
2542
+ "config.syncHistoryMore": "读取更早的版本",
2543
+ "config.syncHistoryCapped": "这里只列出最近的 {count} 个版本",
2544
+ "config.syncHistoryFrom": "来自 {machine}",
2545
+ "config.syncHistoryUnknownMachine": "未标注设备",
2546
+ "config.syncComponentRuntime": "运行时记忆",
2547
+ "config.syncComponentDocuments": "项目档案",
2548
+ "config.syncComponentSpaces": "记忆空间",
2549
+ "config.syncCountRuntime": "运行时记忆 {count} 条",
2550
+ "config.syncCountDocuments": "项目档案 {count} 份",
2551
+ "config.syncCountSpaces": "记忆空间 {count} 个",
2552
+ "config.syncCompareTitle": "与远端比较",
2553
+ "config.syncCompareLoading": "正在读取远端…",
2554
+ "config.syncCompareRemote": "远端版本来自 {machine} · {time}",
2555
+ "config.syncCompareSame": "一致",
2556
+ "config.syncCompareDiffers": "有差异",
2557
+ "config.syncCompareRuntime": "远端独有 {remote} 条 · 本机独有 {local} 条",
2558
+ "config.syncCompareConflicts": "{count} 处写法不同",
2559
+ "config.syncCompareAllSame": "本机与远端一致,不需要同步。",
2560
+ "config.syncCompareTruncated": "差异较多,只统计了一部分。",
2561
+ "config.syncCompareRemovals": "远端记录了 {count} 条删除,同步时会在本机应用。",
2562
+ "config.syncCompareConflictNote": "{count} 个主题两边写法不同:同步会保留两种写法,之后可以用“记忆整理”合并。",
2563
+ "config.syncCompareShowConflicts": "查看",
2564
+ "config.syncCompareGoReview": "去记忆整理",
2565
+ "config.syncCompareHeldBack": "远端有 {count} 条记忆是本机以前删掉的,同步不会把它们加回。",
2566
+ "config.syncCompareRevive": "恢复这些记忆",
2567
+ "config.syncCompareReviving": "恢复中…",
2568
+ "config.syncCompareRevived": "已恢复 {count} 条记忆。",
2569
+ "config.syncDiffHere": "本机",
2570
+ "config.syncDiffThere": "远端",
2571
+ "config.syncMergeOnly": "只合并到本机",
2572
+ "config.syncMerging": "合并中…",
2573
+ "config.syncMerged": "已合并远端 {commit}。",
2574
+ "config.syncMergedCount": "已合并 {count} 条远端记忆。",
2575
+ "config.syncAdvanced": "高级设置",
2576
+ "config.syncBranch": "分支",
2577
+ "config.syncSubdir": "仓库内目录",
2578
+ "config.syncDefaultValue": "默认 {value}",
2579
+ "config.syncBranchInvalid": "分支名无效",
2580
+ "config.syncSubdirInvalid": "需要是仓库内的相对目录",
2581
+ "config.syncAuthor": "提交者",
2582
+ "config.syncAuthorDefault": "默认",
2583
+ "config.syncAuthorMachine": "本机 Git",
2584
+ "config.syncAuthorCustom": "自定义",
2585
+ "config.syncAuthorDefaultNote": "以 {identity} 提交",
2586
+ "config.syncAuthorMachineNote": "使用这台电脑的 Git 身份;没有配置时用默认身份",
2587
+ "config.syncAuthorName": "姓名",
2588
+ "config.syncAuthorEmail": "邮箱",
2589
+ "config.syncAuthorEmailInvalid": "邮箱格式不正确",
2590
+ "config.syncAdvancedNote": "保存后,下次同步写到新的分支或目录",
2591
+ "config.syncMachineName": "这台电脑的名称",
2592
+ "config.syncMachineHostname": "主机名",
2593
+ "config.syncMachineCustom": "自定义",
2594
+ "config.syncMachineNameLabel": "名称",
2595
+ "config.syncMachineHostnameNote": "使用主机名,备份历史里显示为“来自 {name}”",
2596
+ "config.syncMachineCustomNote": "备份历史里显示为“来自 {name}”",
2597
+ "config.syncMachineNameInvalid": "名称最多 120 个字符,且只能占一行",
2598
+ "config.syncMachineRenameNote": "保存后,之后的同步使用新名称;已有的版本保留原来的名称",
2599
+ "config.syncAdvancedSaved": "已保存高级设置。",
2526
2600
  "config.reconcileTitle": "记忆整理",
2527
2601
  "config.reconcileDescription": "模型读合并后的记忆,只提出建议,等你审查后才写入",
2528
- "review.rulesTitle": "运行规则",
2529
- "review.rulesPull": "后台拉取:后台只按「Git 同步」里「自动备份」的间隔推送一次,推送前先读取远端分支并与本机合并;这一步不产生任何建议。自动备份关闭时,只有你点「推送」才会读取远端。",
2530
- "review.rulesDiff": "差异:只有点「检查远端」或推送前的合并才会读出远端与本机的差别;差别只显示出来,不会自动写入。",
2531
- "review.rulesPlan": "方案:只有点「整理记忆」才会生成待办方案,每条方案都要你接受并应用之后才会真正写入记忆。",
2532
2602
  "review.reconcile": "整理记忆",
2533
2603
  "review.reconciling": "整理中…",
2534
2604
  "review.refresh": "刷新",
@@ -3208,129 +3278,182 @@ window.__ModuleLoader__.load({
3208
3278
  "config.syncSimpleDescription": "Syncs the components above to a Git repository, without third-party providers or credentials",
3209
3279
  "config.syncLoading": "Reading the sync status…",
3210
3280
  "config.syncUnavailable": "This DSH host does not provide the Mnemon repository sync channel.",
3211
- "config.syncNotConfigured": "No repository yet",
3212
- "config.syncGitMissing": "Git {required} or newer is unavailable",
3213
- "config.syncRemoteBranchMissing": "The remote has no {branch} branch yet",
3214
- "config.syncRemoteUnreachable": "The remote is unreachable",
3215
- "config.syncRemoteCommit": "Remote {commit}",
3216
- "config.syncTokenSaved": "Token saved",
3217
- "config.syncTokenNone": "No token saved",
3218
- "config.syncSave": "Save",
3219
- "config.syncSaved": "Saved the repository sync configuration.",
3220
- "config.syncFailed": "Sync operation failed: {error}",
3221
- "config.syncPush": "Push",
3222
- "config.syncPushing": "Pushing…",
3223
- "config.syncPushed": "Pushed {commit} ({files} files, {size}).",
3224
- "config.syncPushedLocal": "Committed {commit}, but the push did not finish: {reason}",
3225
- "config.syncPushIdle": "The remote already holds this payload; nothing to commit.",
3226
- "config.syncPreview": "Check remote",
3227
- "config.syncPreviewing": "Checking…",
3228
- "config.syncPreviewReady": "Remote {commit} · {components} components · {size}",
3229
- "config.syncPreviewComponents": "{changed} of {total} components differ from local",
3230
- "config.syncPreviewFiles": "{added} added · {removed} missing · {changed} changed",
3231
- "config.syncPull": "Pull and merge",
3232
- "config.syncPulling": "Pulling…",
3233
- "config.syncPulled": "Merged remote {commit} into {root}.",
3234
- "config.syncBackups": "Backups",
3235
- "config.syncBackupsLoading": "Reading…",
3236
- "config.syncBackupsTitle": "Backups on {branch}",
3237
- "config.syncBackupsHint": "Each push leaves one commit in {subdir}; this lists which installation published what, one page at a time",
3238
- "config.syncBackupsEmpty": "The branch holds no backup yet.",
3239
- "config.syncBackupsMore": "Load older backups",
3240
- "config.syncBackupMeta": "From {machine} · {time}",
3241
- "config.syncBackupPushedAt": "Pushed at {time}",
3242
- "config.syncBackupComponent": "{component}: {items} memories · {files} files · {size}",
3243
- "config.syncBackupNoComponents": "This commit holds no readable manifest.",
3244
- "config.syncBackupUnknownMachine": "Unattributed installation",
3245
- "config.syncDiffTitle": "Memory differences against remote {commit} ({shared} shared)",
3246
- "config.syncDiffSides": "{local} locally · {remote} remotely · remote from {machine}",
3247
- "config.syncDiffTruncated": "More differences exist than this list states.",
3248
- "config.syncDiffTombstones": "The branch recorded {count} removals this installation has not applied.",
3249
- "config.syncDiffLocalOnly": "Only here ({count})",
3250
- "config.syncDiffRemoteOnly": "Only remotely ({count})",
3251
- "config.syncDiffNone": "None",
3252
- "config.syncDiffFrom": "from {machine}",
3253
- "config.syncDiffClear": "No conflict: the two sides state no subject twice.",
3254
- "config.syncDiffNothing": "Nothing here and on the branch needs merging.",
3255
- "config.syncDiffConflicts": "{count} subjects are written differently on the two sides and need reconciling.",
3256
- "config.syncDiffHere": "Here",
3257
- "config.syncDiffThere": "Branch",
3258
- "config.syncDiffAdditions": "The branch also holds {count} memories this installation does not have; they can simply be added.",
3259
- "config.syncDiffLocalOnlyNote": "This installation also holds {count} memories the branch does not have; a push shares them.",
3260
- "config.syncDiffHeldBack": "The branch also holds {count} memories this installation deleted earlier; adding them honors that deletion and leaves them where they are.",
3261
- "config.syncDiffAdd": "Add them",
3262
- "config.syncDiffAdding": "Adding…",
3263
- "config.syncDiffRevive": "Bring them back",
3264
- "config.syncDiffReviving": "Bringing back…",
3265
- "config.syncDiffAdded": "Added the memories from remote {commit} into {root}.",
3266
- "config.syncDiffAddHeld": "{count} of them were deleted here earlier and stayed out; bring them back with “Bring them back”.",
3267
- "config.syncPlanWhere": "Memory reconciliation below is where this plan is made, reviewed and applied.",
3268
- "config.syncPlanGo": "Go to Memory reconciliation",
3269
- "config.syncRepoUrl": "Repository URL",
3270
- "config.syncRepoUrlHint": "HTTPS, SSH, or an absolute local path; never put the token in the URL",
3271
- "config.syncBranch": "Branch",
3272
- "config.syncBranchHint": "Defaults to {branch}",
3273
- "config.syncSubdir": "Remote directory",
3274
- "config.syncSubdirHint": "Where the payload lives inside the repository; defaults to {subdir}",
3281
+ "config.syncUnavailableReason": "Could not read the sync status: {error}",
3282
+ "config.syncGitMissing": "Syncing needs Git {required} or newer",
3283
+ "config.syncRecheck": "Check again",
3284
+ "config.syncFixCredentials": "Set credentials",
3285
+ "config.syncRepository": "Repository",
3286
+ "config.syncRepositoryHint": "Choose the Git repository that keeps your memory",
3287
+ "config.syncChange": "Change",
3288
+ "config.syncDisconnect": "Disconnect",
3289
+ "config.syncDisconnectTitle": "Disconnect this repository?",
3290
+ "config.syncDisconnectBody": "Memory stops syncing to {repository}, and automatic sync turns off. Nothing is deleted here or in the repository; a saved access token is removed.",
3291
+ "config.syncDisconnected": "Disconnected the repository.",
3292
+ "config.syncStateChecking": "Checking the repository…",
3293
+ "config.syncStateConnected": "Connected",
3294
+ "config.syncStateNewBranch": "Connected · the first sync creates the {branch} branch",
3295
+ "config.syncNoCredential": "pushing needs a GitHub sign-in or an access token",
3296
+ "config.syncNoCredentialToken": "pushing needs an access token",
3297
+ "config.syncIssueAuthHttps": "Needs credentials; sign in with GitHub or add an access token",
3298
+ "config.syncIssueAuthToken": "Needs credentials; add an access token",
3299
+ "config.syncIssueAuthSsh": "SSH authentication failed; check this computer's SSH key",
3300
+ "config.syncIssueAuth": "Access to this repository was refused",
3301
+ "config.syncIssueNotFound": "Repository not found; check the address and your access",
3302
+ "config.syncIssueNotFoundGitHub": "Repository not found; check the address, as a private repository needs a sign-in or a token",
3303
+ "config.syncIssueNetwork": "Cannot reach the repository; check the network or proxy",
3304
+ "config.syncIssueTimeout": "The repository did not answer in time",
3305
+ "config.syncIssueUnknown": "Cannot read the repository: {error}",
3306
+ "config.syncViaGitHub": "via GitHub @{login}",
3307
+ "config.syncViaGitHubAnonymous": "via a GitHub sign-in",
3308
+ "config.syncViaToken": "with an access token",
3309
+ "config.syncViaEnvironment": "with the {env} environment variable",
3310
+ "config.syncViaSsh": "with an SSH key",
3311
+ "config.syncConnectWith": "Connect with",
3312
+ "config.syncModeGitHub": "GitHub account",
3313
+ "config.syncModeAddress": "Repository address",
3314
+ "config.syncRepoUrl": "Repository address",
3315
+ "config.syncRepoUrlPlaceholder": "https://…, git@host:path, or an absolute local path",
3316
+ "config.syncRepoUrlInvalid": "Use an https:// or ssh:// URL, git@host:path, or an absolute local path",
3317
+ "config.syncRepoUrlCredentials": "Keep the token out of the address; enter it under Access token",
3275
3318
  "config.syncToken": "Access token",
3276
- "config.syncTokenHint": "Stored only on this machine at {path} (0600); the {env} environment variable wins",
3277
- "config.syncTokenKeep": "Leave empty to keep the saved token",
3278
- "config.syncTokenClear": "Clear token",
3279
- "config.syncTokenClearHint": "Deletes the token stored on this machine when you save",
3280
- "config.syncAuthorName": "Commit author name",
3281
- "config.syncAuthorEmail": "Commit author email",
3282
- "config.syncAuthorOptional": "Optional",
3283
- "config.syncAuthorHint": "Leave empty to use the Git identity of this machine",
3284
- "config.syncAutoBackup": "Automatic backup",
3285
- "config.syncAutoBackupHint": "Pushes once per interval below; switched off, the branch only moves when you press Push",
3286
- "config.syncAutoBackupOff": "Off (manual only)",
3287
- "config.syncAutoBackupHours": "{hours} hours",
3288
- "config.syncAutoBackupDays": "{days} days",
3289
- "config.syncAutoBackupSaved": "Automatic backup set to {interval}",
3290
- "config.syncAutoBackupNext": "Next automatic backup: {at}",
3291
- "config.syncAutoBackupNever": "Automatic backup is off; the branch moves only when you press Push",
3292
- "config.syncAutoBackupLast": "Last automatic backup: {at}",
3293
- "config.syncAutoBackupFailed": "The last automatic backup failed: {error}",
3294
- "config.syncCompacted": "Folded {count} loose objects into a pack, {before} → {after}; a clone now downloads {after}",
3295
- "config.syncGitHub": "GitHub account",
3296
- "config.syncGitHubHint": "Sign in to pick or create a repository; the grant stays on this machine",
3297
- "config.syncGitHubUnavailable": "This DSH host has no credentials store; use an access token instead",
3319
+ "config.syncTokenOptional": "Optional",
3320
+ "config.syncTokenSaved": "Saved; type a new one to replace it",
3321
+ "config.syncTokenEnvironment": "Using the {env} environment variable",
3322
+ "config.syncTokenHint": "Only an HTTPS address needs a token; it stays on this computer",
3323
+ "config.syncTokenRemove": "Remove",
3324
+ "config.syncTokenRemoved": "Removed the access token.",
3325
+ "config.syncConnect": "Connect",
3326
+ "config.syncConnecting": "Connecting…",
3327
+ "config.syncSave": "Save",
3328
+ "config.syncSaving": "Saving…",
3329
+ "config.syncGitHubHint": "Sign in to pick or create a repository; the grant stays on this computer",
3298
3330
  "config.syncGitHubReadOnly": "The credentials store is read-only, so a sign-in cannot be saved",
3299
3331
  "config.syncGitHubSignIn": "Sign in with GitHub",
3300
3332
  "config.syncGitHubStarting": "Requesting a device code…",
3301
3333
  "config.syncGitHubCode": "Enter this device code on GitHub:",
3302
- "config.syncGitHubCopy": "Copy",
3303
- "config.syncGitHubCopied": "Copied",
3304
- "config.syncGitHubOpen": "Open the GitHub authorization page",
3334
+ "config.syncGitHubCopyOpen": "Copy and open GitHub",
3335
+ "config.syncGitHubCopied": "Copied; paste it on the page that opened, and this continues on its own",
3336
+ "config.syncGitHubOpenBlocked": "The browser did not open a new page; visit {url} yourself",
3305
3337
  "config.syncGitHubWaiting": "Waiting for authorization… this continues on its own",
3306
3338
  "config.syncGitHubSignedIn": "Signed in as @{login}",
3307
3339
  "config.syncGitHubSignOut": "Sign out",
3308
3340
  "config.syncGitHubFailed": "GitHub sign-in failed: {error}",
3309
3341
  "config.syncGitHubExpired": "The device code expired; start the sign-in again",
3310
3342
  "config.syncGitHubDenied": "The authorization was denied",
3311
- "config.syncTokenGitHub": "GitHub sign-in",
3312
- "config.syncTokenEnvironment": "Credential from the environment",
3313
- "config.syncTokenOptional": "Optional: an access token also works",
3314
- "config.syncRepositories": "Choose a repository",
3315
- "config.syncRepositoriesHint": "Pick one of the repositories this account can reach",
3316
- "config.syncRepositoriesSignIn": "Sign in and this lists the repositories you can use, or create one; an address typed below works without a sign-in",
3343
+ "config.syncGitHubExpiredGrant": "The GitHub grant is no longer valid; sign in again",
3344
+ "config.syncGitHubSignInAgain": "Sign in again",
3345
+ "config.syncRepositoryLabel": "Repository",
3346
+ "config.syncRepositorySearch": "Search repositories, or type a new name",
3317
3347
  "config.syncRepositoriesLoading": "Reading repositories…",
3318
- "config.syncRepositoriesLoad": "Refresh list",
3319
- "config.syncRepositoriesEmpty": "This account has no repository yet; create one below",
3320
- "config.syncRepositoriesChoose": "Choose a repository…",
3321
- "config.syncRepositoriesPrivate": "private",
3322
- "config.syncRepositoriesNoPush": "no push access",
3323
- "config.syncRepositoryName": "New repository",
3324
- "config.syncRepositoryPrivate": "Create it private",
3325
- "config.syncRepositoryCreate": "Create and use it",
3348
+ "config.syncRepositoriesFailed": "Could not read repositories: {error}",
3349
+ "config.syncRepositoriesRetry": "Retry",
3350
+ "config.syncRepositoriesNone": "This account has no repository yet; type a name to create one",
3351
+ "config.syncRepositoriesEmpty": "No matching repository",
3352
+ "config.syncRepositoriesMore": "{count} more repositories; type to narrow the list",
3353
+ "config.syncRepositoryPrivate": "Private",
3354
+ "config.syncRepositoryPublic": "Public",
3355
+ "config.syncRepositoryNoPush": "No push access",
3356
+ "config.syncRepositoryCurrent": "Current",
3357
+ "config.syncRepositoryCreate": "Create the private repository {name}",
3326
3358
  "config.syncRepositoryCreating": "Creating…",
3327
- "config.syncRepositoryCreated": "Created {name}.",
3359
+ "config.syncRepositoryNameInvalid": "A repository name holds letters, digits, dots, dashes and underscores",
3360
+ "config.syncPublicTitle": "Use a public repository?",
3361
+ "config.syncPublicBody": "{name} is public: anyone can read the memory synced to it.",
3362
+ "config.syncPublicConfirm": "Use it anyway",
3363
+ "config.syncRowTitle": "Sync",
3364
+ "config.syncNever": "A sync merges the repository's memory here, then pushes this computer's",
3365
+ "config.syncLast": "Last synced {time}",
3366
+ "config.syncLastMerge": "Last merged {time}",
3367
+ "config.syncCheck": "Check remote",
3368
+ "config.syncNow": "Sync now",
3369
+ "config.syncNowRunning": "Syncing…",
3370
+ "config.syncDone": "Synced; pushed {commit}.",
3371
+ "config.syncDoneMerged": "Synced: merged {count} remote memories and pushed {commit}.",
3372
+ "config.syncUpToDate": "Up to date; the repository matches this computer.",
3373
+ "config.syncUpToDateMerged": "Merged {count} remote memories; the repository is up to date.",
3374
+ "config.syncPushFailed": "Committed here, but the push did not finish: {reason}",
3375
+ "config.syncFailed": "Sync failed: {error}",
3376
+ "config.syncReasonBusy": "Another sync is still running; try again shortly",
3377
+ "config.syncReasonNoRepository": "No repository is connected",
3378
+ "config.syncReasonGitMissing": "This computer's Git is unavailable",
3379
+ "config.syncReasonRemoteEmpty": "The repository holds no backup yet; sync once first",
3380
+ "config.syncReasonRejected": "Another device updated the repository during the sync; sync again",
3381
+ "config.syncAuto": "Automatic sync",
3382
+ "config.syncAutoOff": "Off",
3383
+ "config.syncAutoHour": "Every hour",
3384
+ "config.syncAutoHours": "Every {hours} hours",
3385
+ "config.syncAutoDay": "Every day",
3386
+ "config.syncAutoDays": "Every {days} days",
3387
+ "config.syncAutoHintOff": "Syncs only when you press Sync now",
3388
+ "config.syncAutoHintOn": "Syncs in the background at this interval, exactly as Sync now does",
3389
+ "config.syncAutoNext": "Next at {time}",
3390
+ "config.syncAutoLast": "Last at {time}",
3391
+ "config.syncAutoFailed": "The last automatic sync failed: {error}",
3392
+ "config.syncHistory": "Backup history",
3393
+ "config.syncHistoryHint": "Every sync leaves a version in the repository",
3394
+ "config.syncHistoryView": "View",
3395
+ "config.syncHistoryLoading": "Reading…",
3396
+ "config.syncHistoryEmpty": "The repository holds no backup yet.",
3397
+ "config.syncHistoryMore": "Load earlier versions",
3398
+ "config.syncHistoryCapped": "Only the latest {count} versions are listed here",
3399
+ "config.syncHistoryFrom": "from {machine}",
3400
+ "config.syncHistoryUnknownMachine": "an unnamed computer",
3401
+ "config.syncComponentRuntime": "Runtime Memory",
3402
+ "config.syncComponentDocuments": "Project Documents",
3403
+ "config.syncComponentSpaces": "Memory Spaces",
3404
+ "config.syncCountRuntime": "{count} runtime memories",
3405
+ "config.syncCountDocuments": "{count} documents",
3406
+ "config.syncCountSpaces": "{count} memory spaces",
3407
+ "config.syncCompareTitle": "Compare with the remote",
3408
+ "config.syncCompareLoading": "Reading the remote…",
3409
+ "config.syncCompareRemote": "The remote version is from {machine} · {time}",
3410
+ "config.syncCompareSame": "Same",
3411
+ "config.syncCompareDiffers": "Differs",
3412
+ "config.syncCompareRuntime": "{remote} only on the remote · {local} only here",
3413
+ "config.syncCompareConflicts": "{count} written differently",
3414
+ "config.syncCompareAllSame": "This computer and the remote match; there is nothing to sync.",
3415
+ "config.syncCompareTruncated": "More differences exist than these counts show.",
3416
+ "config.syncCompareRemovals": "The remote recorded {count} deletions; a sync applies them here.",
3417
+ "config.syncCompareConflictNote": "{count} subjects are written differently: a sync keeps both, and Memory reconciliation can merge them later.",
3418
+ "config.syncCompareShowConflicts": "Show",
3419
+ "config.syncCompareGoReview": "Go to Memory reconciliation",
3420
+ "config.syncCompareHeldBack": "{count} remote memories were deleted here earlier; a sync keeps them out.",
3421
+ "config.syncCompareRevive": "Bring them back",
3422
+ "config.syncCompareReviving": "Bringing back…",
3423
+ "config.syncCompareRevived": "Brought back {count} memories.",
3424
+ "config.syncDiffHere": "Here",
3425
+ "config.syncDiffThere": "Remote",
3426
+ "config.syncMergeOnly": "Merge here only",
3427
+ "config.syncMerging": "Merging…",
3428
+ "config.syncMerged": "Merged remote {commit}.",
3429
+ "config.syncMergedCount": "Merged {count} remote memories.",
3430
+ "config.syncAdvanced": "Advanced",
3431
+ "config.syncBranch": "Branch",
3432
+ "config.syncSubdir": "Directory in the repository",
3433
+ "config.syncDefaultValue": "Default {value}",
3434
+ "config.syncBranchInvalid": "Not a valid branch name",
3435
+ "config.syncSubdirInvalid": "Use a relative directory inside the repository",
3436
+ "config.syncAuthor": "Commit author",
3437
+ "config.syncAuthorDefault": "Default",
3438
+ "config.syncAuthorMachine": "This computer's Git",
3439
+ "config.syncAuthorCustom": "Custom",
3440
+ "config.syncAuthorDefaultNote": "Commits as {identity}",
3441
+ "config.syncAuthorMachineNote": "Uses this computer's Git identity, else the default one",
3442
+ "config.syncAuthorName": "Name",
3443
+ "config.syncAuthorEmail": "Email",
3444
+ "config.syncAuthorEmailInvalid": "Not an email address",
3445
+ "config.syncAdvancedNote": "After saving, the next sync writes to the new branch or directory",
3446
+ "config.syncMachineName": "This computer's name",
3447
+ "config.syncMachineHostname": "Host name",
3448
+ "config.syncMachineCustom": "Custom",
3449
+ "config.syncMachineNameLabel": "Name",
3450
+ "config.syncMachineHostnameNote": "Uses the host name; backup history shows “from {name}”",
3451
+ "config.syncMachineCustomNote": "Backup history shows “from {name}”",
3452
+ "config.syncMachineNameInvalid": "Up to 120 characters on one line",
3453
+ "config.syncMachineRenameNote": "After saving, later syncs use the new name; earlier versions keep theirs",
3454
+ "config.syncAdvancedSaved": "Saved the advanced settings.",
3328
3455
  "config.reconcileTitle": "Memory reconciliation",
3329
3456
  "config.reconcileDescription": "A model reads the merged memory and proposes changes; nothing is written until you review it",
3330
- "review.rulesTitle": "How this runs",
3331
- "review.rulesPull": "Background pull: the background only repeats the push at the interval set under Automatic backup in Git sync, and before pushing it reads the remote branch and merges it here; this step produces no proposal. With the automatic backup off, the remote branch is read only when you press Push.",
3332
- "review.rulesDiff": "Differences: only Check remote, or the merge before a push, reads what differs between the branch and this machine; a difference is shown, never written.",
3333
- "review.rulesPlan": "Proposals: only Reconcile writes a plan to answer, and every entry in it is applied one operation at a time, after you accept it.",
3334
3457
  "review.reconcile": "Reconcile",
3335
3458
  "review.reconciling": "Reconciling…",
3336
3459
  "review.refresh": "Refresh",
@@ -6565,7 +6688,7 @@ window.__ModuleLoader__.load({
6565
6688
  case "document-archive": return t("review.opArchive", { id: operation.documentId });
6566
6689
  }
6567
6690
  }
6568
- function stamp$1(value) {
6691
+ function stamp(value) {
6569
6692
  const parsed = new Date(value);
6570
6693
  return Number.isNaN(parsed.getTime()) ? value : parsed.toLocaleString();
6571
6694
  }
@@ -6746,12 +6869,12 @@ window.__ModuleLoader__.load({
6746
6869
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("review.meta", {
6747
6870
  count: entry.operations.length,
6748
6871
  machine: entry.machine.label,
6749
- time: stamp$1(entry.createdAt)
6872
+ time: stamp(entry.createdAt)
6750
6873
  }) }),
6751
6874
  entry.foreignMachines.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("review.foreign", { machines: entry.foreignMachines.join(", ") }) }),
6752
6875
  entry.appliedAt !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", {
6753
6876
  className: MnemonSettingsCard_module_css_default.syncSuccess,
6754
- children: t("review.appliedAt", { time: stamp$1(entry.appliedAt) })
6877
+ children: t("review.appliedAt", { time: stamp(entry.appliedAt) })
6755
6878
  }),
6756
6879
  (entry.appliedOperations ?? []).length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("review.appliedCount", {
6757
6880
  count: (entry.appliedOperations ?? []).length,
@@ -6867,14 +6990,6 @@ window.__ModuleLoader__.load({
6867
6990
  })]
6868
6991
  })
6869
6992
  }),
6870
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6871
- className: MnemonSettingsCard_module_css_default.reviewRules,
6872
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("review.rulesTitle") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("ul", { children: [
6873
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: t("review.rulesPull") }),
6874
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: t("review.rulesDiff") }),
6875
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: t("review.rulesPlan") })
6876
- ] })]
6877
- }),
6878
6993
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6879
6994
  className: MnemonSettingsCard_module_css_default.reviewGuidance,
6880
6995
  children: [
@@ -6947,16 +7062,79 @@ window.__ModuleLoader__.load({
6947
7062
  });
6948
7063
  }
6949
7064
  //#endregion
6950
- //#region src/client/MnemonSyncSection.tsx
6951
- /** How many backups one page of the branch history holds. */
6952
- const BACKUP_PAGE = 20;
6953
- /**
6954
- * The intervals the form offers. The floor is an hour: a backup more often than
6955
- * that is a repository being rewritten, not a memory being kept. The ceiling is
6956
- * a week, and off is the first choice because it is what a channel that has
6957
- * never been configured does.
6958
- */
6959
- const AUTO_BACKUP_CHOICES = [
7065
+ //#region src/client/sync-view.ts
7066
+ /** The transport one repository address uses. */
7067
+ function transportOf(url) {
7068
+ const value = url.trim();
7069
+ if (/^https:\/\//iu.test(value)) return "https";
7070
+ if (/^ssh:\/\//iu.test(value) || /^[A-Za-z0-9._-]+@[A-Za-z0-9._-]+:/u.test(value)) return "ssh";
7071
+ return "local";
7072
+ }
7073
+ /** Whether an address is HTTPS on github.com, the only host a GitHub sign-in is offered to. */
7074
+ function onGitHub(url) {
7075
+ try {
7076
+ const parsed = new URL(url.trim());
7077
+ return parsed.protocol === "https:" && parsed.hostname.toLowerCase() === "github.com";
7078
+ } catch {
7079
+ return false;
7080
+ }
7081
+ }
7082
+ /** A repository address as a reader recognizes it: host and path, without the scheme or `.git`. */
7083
+ function repositoryName(url) {
7084
+ const value = url.trim();
7085
+ if (transportOf(value) !== "https" && !/^ssh:\/\//iu.test(value)) return value;
7086
+ try {
7087
+ const parsed = new URL(value);
7088
+ return (parsed.host + parsed.pathname).replace(/\.git$/u, "").replace(/\/$/u, "");
7089
+ } catch {
7090
+ return value;
7091
+ }
7092
+ }
7093
+ function repositoryProblem(url) {
7094
+ const value = url.trim();
7095
+ if (value === "") return void 0;
7096
+ if (value.length > 2e3 || /\s/u.test(value)) return "format";
7097
+ if (/^[A-Za-z][A-Za-z0-9+.-]*:\/\//u.test(value)) {
7098
+ if (!/^(https|ssh):\/\/[^\s/]+(?::\d+)?\/[^\s]+$/u.test(value)) return "format";
7099
+ return /^https:\/\/[^/]*@/u.test(value) ? "credentials" : void 0;
7100
+ }
7101
+ if (/^[A-Za-z0-9._-]+@[A-Za-z0-9._-]+:[^\s]+$/u.test(value)) return void 0;
7102
+ return value.startsWith("/") || /^[A-Za-z]:[\\/]/u.test(value) || value.startsWith("\\\\") ? void 0 : "format";
7103
+ }
7104
+ /** A Git branch name, as the Host checks it. */
7105
+ function branchValid(value) {
7106
+ const name = value.trim();
7107
+ return name !== "" && name.length <= 200 && /^[A-Za-z0-9][A-Za-z0-9._/-]*$/u.test(name) && !name.includes("..") && !name.includes("//") && !name.includes("@{") && !name.endsWith("/") && !name.endsWith(".") && !name.endsWith(".lock");
7108
+ }
7109
+ /** A directory inside the branch, as the Host checks it. */
7110
+ function directoryValid(value) {
7111
+ const raw = value.trim().replaceAll("\\", "/");
7112
+ if (raw === "" || raw.length > 400 || /^[A-Za-z]:/u.test(raw)) return false;
7113
+ const parts = raw.split("/").filter((part) => part !== "");
7114
+ return parts.length > 0 && !parts.some((part) => part === "." || part === ".." || part.includes(":"));
7115
+ }
7116
+ function emailValid(value) {
7117
+ const email = value.trim();
7118
+ return email.length <= 320 && /^[^\s<>@]+@[^\s<>@]+$/u.test(email);
7119
+ }
7120
+ /** A name for this computer, as the Host stores one: one line, at most the shared limit. */
7121
+ function machineNameValid(value) {
7122
+ const name = value.trim();
7123
+ return name !== "" && name.length <= 120 && !/[\p{Cc}\u2028\u2029]/u.test(name);
7124
+ }
7125
+ /** A GitHub repository name, as GitHub accepts one. */
7126
+ function repositoryNameValid(value) {
7127
+ return /^(?!\.\.?$)[A-Za-z0-9._-]{1,100}$/u.test(value.trim());
7128
+ }
7129
+ function authorModeOf(name, email) {
7130
+ if (name === "dsh-mnemon sync" && email === "mnemon@localhost") return "default";
7131
+ if (name === "" && email === "") return "machine";
7132
+ return "custom";
7133
+ }
7134
+ /** The channel identity as a commit shows it. */
7135
+ const DEFAULT_AUTHOR = "dsh-mnemon sync <mnemon@localhost>";
7136
+ /** The intervals automatic sync offers, in minutes; off first, then an hour up to a week. */
7137
+ const AUTO_SYNC_CHOICES = [
6960
7138
  0,
6961
7139
  60,
6962
7140
  180,
@@ -6966,78 +7144,485 @@ window.__ModuleLoader__.load({
6966
7144
  4320,
6967
7145
  10080
6968
7146
  ];
6969
- /** One interval as the reader reads it: off, whole days, or whole hours. */
7147
+ /** One interval as a reader reads it. */
6970
7148
  function intervalLabel(t, minutes) {
6971
- if (minutes <= 0) return t("config.syncAutoBackupOff");
6972
- if (minutes % 1440 === 0) return t("config.syncAutoBackupDays", { days: minutes / 1440 });
6973
- return t("config.syncAutoBackupHours", { hours: minutes / 60 });
7149
+ if (minutes <= 0) return t("config.syncAutoOff");
7150
+ if (minutes === 60) return t("config.syncAutoHour");
7151
+ if (minutes === 1440) return t("config.syncAutoDay");
7152
+ if (minutes % 1440 === 0) return t("config.syncAutoDays", { days: minutes / 1440 });
7153
+ return t("config.syncAutoHours", { hours: minutes / 60 });
7154
+ }
7155
+ /** A time as a short local stamp: the time alone today, the date beside it otherwise. */
7156
+ function when(value, now = /* @__PURE__ */ new Date()) {
7157
+ if (value === void 0) return "";
7158
+ const at = new Date(value);
7159
+ if (Number.isNaN(at.getTime())) return value;
7160
+ return at.getFullYear() === now.getFullYear() && at.getMonth() === now.getMonth() && at.getDate() === now.getDate() ? at.toLocaleTimeString(void 0, {
7161
+ hour: "2-digit",
7162
+ minute: "2-digit"
7163
+ }) : at.toLocaleString(void 0, {
7164
+ year: "numeric",
7165
+ month: "short",
7166
+ day: "numeric",
7167
+ hour: "2-digit",
7168
+ minute: "2-digit"
7169
+ });
7170
+ }
7171
+ /** Why a remote could not be read, said for the transport the repository uses. */
7172
+ function issueText(t, issue, url, error) {
7173
+ const transport = transportOf(url);
7174
+ switch (issue) {
7175
+ case "auth":
7176
+ if (transport === "https") return onGitHub(url) ? t("config.syncIssueAuthHttps") : t("config.syncIssueAuthToken");
7177
+ return transport === "ssh" ? t("config.syncIssueAuthSsh") : t("config.syncIssueAuth");
7178
+ case "not-found": return onGitHub(url) ? t("config.syncIssueNotFoundGitHub") : t("config.syncIssueNotFound");
7179
+ case "network": return t("config.syncIssueNetwork");
7180
+ case "timeout": return t("config.syncIssueTimeout");
7181
+ default: return t("config.syncIssueUnknown", { error: error ?? "" });
7182
+ }
7183
+ }
7184
+ const REMOTE_ISSUE = {
7185
+ "remote-auth": "auth",
7186
+ "remote-not-found": "not-found",
7187
+ "remote-network": "network",
7188
+ "remote-timeout": "timeout"
7189
+ };
7190
+ /** A failure the Host named, in this page's language; anything it could not name keeps its own words. */
7191
+ function failureText(t, reason, message, url) {
7192
+ const issue = reason === void 0 ? void 0 : REMOTE_ISSUE[reason];
7193
+ if (issue !== void 0) return issueText(t, issue, url, message);
7194
+ switch (reason) {
7195
+ case "busy": return t("config.syncReasonBusy");
7196
+ case "no-repository": return t("config.syncReasonNoRepository");
7197
+ case "git-missing": return t("config.syncReasonGitMissing");
7198
+ case "remote-empty": return t("config.syncReasonRemoteEmpty");
7199
+ case "push-rejected": return t("config.syncReasonRejected");
7200
+ case "github-unauthorized": return t("config.syncGitHubExpiredGrant");
7201
+ default: return message;
7202
+ }
7203
+ }
7204
+ /** The reason a thrown failure carries, when the Host named one. */
7205
+ function reasonOf(error) {
7206
+ const reason = error instanceof Error ? error.reason : void 0;
7207
+ return typeof reason === "string" ? reason : void 0;
7208
+ }
7209
+ /** How a connected repository is authenticated, said as briefly as the state line allows. */
7210
+ function credentialText(t, status) {
7211
+ const transport = transportOf(status.config.repoUrl ?? "");
7212
+ if (transport === "ssh") return t("config.syncViaSsh");
7213
+ if (transport === "local") return void 0;
7214
+ switch (status.config.credentialSource) {
7215
+ case "github": return status.config.credentialLogin === void 0 ? t("config.syncViaGitHubAnonymous") : t("config.syncViaGitHub", { login: status.config.credentialLogin });
7216
+ case "environment": return t("config.syncViaEnvironment", { env: MNEMON_SYNC_TOKEN_ENV });
7217
+ case "token": return t("config.syncViaToken");
7218
+ default: return;
7219
+ }
6974
7220
  }
6975
- function draftOf(config) {
6976
- return {
6977
- repoUrl: config?.repoUrl ?? "",
6978
- branch: config?.branch ?? "mnemon-sync",
6979
- subdir: config?.subdir ?? "mnemon/",
6980
- token: "",
6981
- clearToken: false,
6982
- authorName: config?.authorName ?? "",
6983
- authorEmail: config?.authorEmail ?? "",
6984
- autoBackupMinutes: config?.autoBackupMinutes ?? 0
6985
- };
7221
+ //#endregion
7222
+ //#region src/client/MnemonSyncDialogs.tsx
7223
+ /** How many backups one page of the branch history holds. */
7224
+ const HISTORY_PAGE = 20;
7225
+ /** How many conflicting pairs the comparison lists before it only counts them. */
7226
+ const SHOWN_CONFLICTS = 5;
7227
+ /** One component's item count as a reader reads it. */
7228
+ function componentCount(t, component, count) {
7229
+ if (component === "runtime") return t("config.syncCountRuntime", { count });
7230
+ if (component === "documents") return t("config.syncCountDocuments", { count });
7231
+ return t("config.syncCountSpaces", { count });
7232
+ }
7233
+ function componentName(t, component) {
7234
+ if (component === "runtime") return t("config.syncComponentRuntime");
7235
+ if (component === "documents") return t("config.syncComponentDocuments");
7236
+ return t("config.syncComponentSpaces");
7237
+ }
7238
+ function clip(value, max) {
7239
+ const text = value.replace(/\s+/gu, " ").trim();
7240
+ return text.length <= max ? text : text.slice(0, max - 1) + "…";
6986
7241
  }
6987
- /** A repository is the one thing a save cannot invent, so it gates the save button. */
6988
- function configured(draft) {
6989
- return draft.repoUrl.trim() !== "";
7242
+ /** The commit message a sync writes on its own, which says nothing a backup's time does not. */
7243
+ const AUTOMATIC_MESSAGE = /^Mnemon sync \d{4}-\d{2}-\d{2}T[\d:.]+Z$/u;
7244
+ function summaryLine(t, summary) {
7245
+ return summary.map((entry) => componentCount(t, entry.component, entry.items)).join(" · ");
6990
7246
  }
6991
7247
  /**
6992
- * What a merge actually did. The Host states it as counts, because "added the branch's
6993
- * memories" is false when this machine's own deletions kept every one of them out, and a
6994
- * reader who is told the wrong thing will not look for the button that overrules them.
7248
+ * The versions the repository holds, newest first: when each was synced, from
7249
+ * which computer, and what it held. A page is read at a time; the commit is a
7250
+ * quiet tag, because the time and the computer are what a reader looks for.
6995
7251
  */
6996
- function addedNotice(t, result) {
6997
- const report = result.runtime;
6998
- const commit = result.commit.slice(0, 8);
6999
- const root = result.targetRoot;
7000
- if (report !== void 0 && report.added === 0 && report.held > 0) return t("config.syncDiffAddHeld", { count: report.held });
7001
- const parts = [t("config.syncDiffAdded", {
7002
- commit,
7003
- root
7004
- })];
7005
- if (report !== void 0 && report.held > 0) parts.push(t("config.syncDiffAddHeld", { count: report.held }));
7006
- return parts.join(" ");
7252
+ function SyncHistoryDialog({ client, repoUrl, t, onClose }) {
7253
+ const [history, setHistory] = (0, react.useState)(null);
7254
+ const [busy, setBusy] = (0, react.useState)(true);
7255
+ const [failed, setFailed] = (0, react.useState)(null);
7256
+ const [capped, setCapped] = (0, react.useState)(false);
7257
+ const load = (0, react.useCallback)(async (limit) => {
7258
+ setBusy(true);
7259
+ setFailed(null);
7260
+ try {
7261
+ const page = await client.syncBackups(limit);
7262
+ setHistory((current) => {
7263
+ if (current === null || limit === void 0) return page;
7264
+ const fresh = page.commits.filter((commit) => !current.commits.some((held) => held.commit === commit.commit));
7265
+ if (fresh.length === 0) setCapped(true);
7266
+ return {
7267
+ ...page,
7268
+ commits: [...current.commits, ...fresh]
7269
+ };
7270
+ });
7271
+ } catch (reason) {
7272
+ setFailed(failureText(t, reasonOf(reason), message(reason), repoUrl));
7273
+ } finally {
7274
+ setBusy(false);
7275
+ }
7276
+ }, [
7277
+ client,
7278
+ repoUrl,
7279
+ t
7280
+ ]);
7281
+ (0, react.useEffect)(() => {
7282
+ load();
7283
+ }, [load]);
7284
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MnemonDialog, {
7285
+ title: t("config.syncHistory"),
7286
+ description: t("config.syncHistoryHint"),
7287
+ closeLabel: t("common.close"),
7288
+ wide: true,
7289
+ busy,
7290
+ contentReady: history !== null || failed !== null,
7291
+ onClose,
7292
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7293
+ className: MnemonSettingsCard_module_css_default.syncDialogBody,
7294
+ children: [
7295
+ history === null && failed === null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7296
+ className: MnemonSettingsCard_module_css_default.syncDialogNote,
7297
+ role: "status",
7298
+ children: t("config.syncHistoryLoading")
7299
+ }),
7300
+ failed !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7301
+ className: MnemonSettingsCard_module_css_default.error,
7302
+ role: "alert",
7303
+ children: failed
7304
+ }),
7305
+ history !== null && history.commits.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7306
+ className: MnemonSettingsCard_module_css_default.syncDialogNote,
7307
+ children: t("config.syncHistoryEmpty")
7308
+ }),
7309
+ history !== null && history.commits.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ol", {
7310
+ className: MnemonSettingsCard_module_css_default.syncHistoryList,
7311
+ children: history.commits.map((commit) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
7312
+ className: MnemonSettingsCard_module_css_default.syncHistoryEntry,
7313
+ children: [
7314
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7315
+ className: MnemonSettingsCard_module_css_default.syncHistoryHead,
7316
+ children: [
7317
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: when(commit.pushedAt ?? commit.committedAt) }),
7318
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("config.syncHistoryFrom", { machine: commit.machine === void 0 ? t("config.syncHistoryUnknownMachine") : commit.machine.label.trim() || commit.machine.id }) }),
7319
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
7320
+ tone: "quiet",
7321
+ children: commit.commit.slice(0, 8)
7322
+ })
7323
+ ]
7324
+ }),
7325
+ commit.components.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: summaryLine(t, commit.components) }),
7326
+ !AUTOMATIC_MESSAGE.test(commit.message) && commit.message.trim() !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", {
7327
+ className: MnemonSettingsCard_module_css_default.syncHistoryMessage,
7328
+ children: commit.message
7329
+ })
7330
+ ]
7331
+ }, commit.commit))
7332
+ }),
7333
+ capped && history !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7334
+ className: MnemonSettingsCard_module_css_default.syncDialogNote,
7335
+ children: t("config.syncHistoryCapped", { count: history.commits.length })
7336
+ }),
7337
+ history?.truncated === true && !capped && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7338
+ className: MnemonSettingsCard_module_css_default.rowActions,
7339
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7340
+ variant: "outline",
7341
+ size: "sm",
7342
+ disabled: busy,
7343
+ onClick: () => void load(history.commits.length + HISTORY_PAGE),
7344
+ children: busy ? t("config.syncHistoryLoading") : t("config.syncHistoryMore")
7345
+ })
7346
+ })
7347
+ ]
7348
+ })
7349
+ });
7007
7350
  }
7008
- function stamp(value) {
7009
- if (value === void 0) return "";
7010
- const parsed = new Date(value);
7011
- return Number.isNaN(parsed.getTime()) ? value : parsed.toLocaleString();
7351
+ /**
7352
+ * What a sync would do, read before running it: per component whether the two
7353
+ * sides differ, and for runtime memory which entries are only on one side, which
7354
+ * subjects both wrote differently, which the branch holds that this computer
7355
+ * deleted, and which removals the branch recorded. Reading writes nothing; the
7356
+ * footer offers the sync itself and a merge that publishes nothing.
7357
+ */
7358
+ function SyncCompareDialog({ client, repoUrl, writable, t, onClose, onSync, onChanged }) {
7359
+ const [preview, setPreview] = (0, react.useState)(null);
7360
+ const [difference, setDifference] = (0, react.useState)(null);
7361
+ const [busy, setBusy] = (0, react.useState)("read");
7362
+ const [failed, setFailed] = (0, react.useState)(null);
7363
+ const [empty, setEmpty] = (0, react.useState)(false);
7364
+ const [notice, setNotice] = (0, react.useState)(null);
7365
+ const [showConflicts, setShowConflicts] = (0, react.useState)(false);
7366
+ const read = (0, react.useCallback)(async () => {
7367
+ setBusy("read");
7368
+ setFailed(null);
7369
+ setEmpty(false);
7370
+ try {
7371
+ const nextPreview = await client.previewSync();
7372
+ const nextDifference = await client.syncDiff();
7373
+ setPreview(nextPreview);
7374
+ setDifference(nextDifference);
7375
+ } catch (reason) {
7376
+ setPreview(null);
7377
+ setDifference(null);
7378
+ setEmpty(reasonOf(reason) === "remote-empty");
7379
+ setFailed(failureText(t, reasonOf(reason), message(reason), repoUrl));
7380
+ } finally {
7381
+ setBusy(null);
7382
+ }
7383
+ }, [
7384
+ client,
7385
+ repoUrl,
7386
+ t
7387
+ ]);
7388
+ (0, react.useEffect)(() => {
7389
+ read();
7390
+ }, [read]);
7391
+ const merge = async (revive) => {
7392
+ if (busy !== null) return;
7393
+ setBusy(revive ? "revive" : "merge");
7394
+ setFailed(null);
7395
+ setNotice(null);
7396
+ try {
7397
+ const result = await client.pullSync(void 0, revive);
7398
+ const added = result.runtime?.added ?? 0;
7399
+ setNotice(revive ? t("config.syncCompareRevived", { count: added }) : added > 0 ? t("config.syncMergedCount", { count: added }) : t("config.syncMerged", { commit: result.commit.slice(0, 8) }));
7400
+ onChanged();
7401
+ } catch (reason) {
7402
+ setFailed(failureText(t, reasonOf(reason), message(reason), repoUrl));
7403
+ } finally {
7404
+ setBusy(null);
7405
+ }
7406
+ await read();
7407
+ };
7408
+ const sync = async () => {
7409
+ if (busy !== null) return;
7410
+ setBusy("sync");
7411
+ setFailed(null);
7412
+ setNotice(null);
7413
+ const failure = await onSync();
7414
+ setBusy(null);
7415
+ if (failure === null) {
7416
+ onClose();
7417
+ return;
7418
+ }
7419
+ await read();
7420
+ setFailed(failure);
7421
+ };
7422
+ const goToReview = () => {
7423
+ onClose();
7424
+ const heading = document.getElementById("mnemon-review-heading");
7425
+ if (heading !== null && typeof heading.scrollIntoView === "function") heading.scrollIntoView({
7426
+ block: "start",
7427
+ behavior: "smooth"
7428
+ });
7429
+ };
7430
+ const conflicts = difference?.conflicts ?? [];
7431
+ const conflicted = new Set(conflicts.flatMap((conflict) => [conflict.target + "\0" + conflict.local.content, conflict.target + "\0" + conflict.remote.content]));
7432
+ const heldBack = difference?.heldBack ?? 0;
7433
+ const removals = difference?.remoteTombstones.length ?? 0;
7434
+ const remoteOnly = difference === null ? 0 : Math.max(difference.remoteOnly.filter((entry) => !conflicted.has(entry.target + "\0" + entry.content)).length - heldBack, 0);
7435
+ const localOnly = difference === null ? 0 : Math.max(difference.localOnly.filter((entry) => !conflicted.has(entry.target + "\0" + entry.content)).length - removals, 0);
7436
+ const differs = (component) => preview?.components.find((entry) => entry.component === component)?.changed === true;
7437
+ const runtimeDiffers = remoteOnly + localOnly + conflicts.length > 0;
7438
+ const anything = runtimeDiffers || removals + heldBack > 0 || differs("documents") || differs("memory-spaces");
7439
+ const mergeable = remoteOnly + conflicts.length + removals > 0 || differs("documents") || differs("memory-spaces");
7440
+ const ready = preview !== null && difference !== null;
7441
+ const machine = difference?.remote.machine === void 0 ? t("config.syncHistoryUnknownMachine") : difference.remote.machine.label.trim() || difference.remote.machine.id;
7442
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MnemonDialog, {
7443
+ title: t("config.syncCompareTitle"),
7444
+ closeLabel: t("common.close"),
7445
+ wide: true,
7446
+ busy: busy !== null && busy !== "read",
7447
+ contentReady: ready || failed !== null,
7448
+ onClose,
7449
+ footer: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7450
+ variant: "outline",
7451
+ size: "sm",
7452
+ disabled: busy !== null || !writable || !ready || !mergeable,
7453
+ onClick: () => void merge(false),
7454
+ children: busy === "merge" ? t("config.syncMerging") : t("config.syncMergeOnly")
7455
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7456
+ variant: "primary",
7457
+ size: "sm",
7458
+ disabled: busy !== null || !writable || !(ready || empty),
7459
+ onClick: () => void sync(),
7460
+ children: busy === "sync" ? t("config.syncNowRunning") : t("config.syncNow")
7461
+ })] }),
7462
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7463
+ className: MnemonSettingsCard_module_css_default.syncDialogBody,
7464
+ children: [
7465
+ busy === "read" && !ready && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7466
+ className: MnemonSettingsCard_module_css_default.syncDialogNote,
7467
+ role: "status",
7468
+ children: t("config.syncCompareLoading")
7469
+ }),
7470
+ failed !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7471
+ className: MnemonSettingsCard_module_css_default.error,
7472
+ role: "alert",
7473
+ children: failed
7474
+ }),
7475
+ notice !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7476
+ className: MnemonSettingsCard_module_css_default.syncSuccess,
7477
+ role: "status",
7478
+ children: notice
7479
+ }),
7480
+ ready && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
7481
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7482
+ className: MnemonSettingsCard_module_css_default.syncDialogNote,
7483
+ children: t("config.syncCompareRemote", {
7484
+ machine,
7485
+ time: when(difference.pushedAt ?? preview.pushedAt)
7486
+ })
7487
+ }),
7488
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("ul", {
7489
+ className: MnemonSettingsCard_module_css_default.syncCompareList,
7490
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: componentName(t, "runtime") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", {
7491
+ "data-differs": runtimeDiffers || void 0,
7492
+ children: runtimeDiffers ? [t("config.syncCompareRuntime", {
7493
+ remote: remoteOnly,
7494
+ local: localOnly
7495
+ }), ...conflicts.length > 0 ? [t("config.syncCompareConflicts", { count: conflicts.length })] : []].join(" · ") : t("config.syncCompareSame")
7496
+ })] }), ["documents", "memory-spaces"].map((component) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: componentName(t, component) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", {
7497
+ "data-differs": differs(component) || void 0,
7498
+ children: differs(component) ? t("config.syncCompareDiffers") : t("config.syncCompareSame")
7499
+ })] }, component))]
7500
+ }),
7501
+ !anything && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7502
+ className: MnemonSettingsCard_module_css_default.syncDialogNote,
7503
+ children: t("config.syncCompareAllSame")
7504
+ }),
7505
+ difference.truncated && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7506
+ className: MnemonSettingsCard_module_css_default.syncDialogNote,
7507
+ children: t("config.syncCompareTruncated")
7508
+ }),
7509
+ removals > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7510
+ className: MnemonSettingsCard_module_css_default.syncDialogNote,
7511
+ children: t("config.syncCompareRemovals", { count: removals })
7512
+ }),
7513
+ conflicts.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7514
+ className: MnemonSettingsCard_module_css_default.syncCompareNote,
7515
+ children: [
7516
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7517
+ className: MnemonSettingsCard_module_css_default.syncDialogNote,
7518
+ children: t("config.syncCompareConflictNote", { count: conflicts.length })
7519
+ }),
7520
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7521
+ className: MnemonSettingsCard_module_css_default.rowActions,
7522
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7523
+ variant: "ghost",
7524
+ size: "sm",
7525
+ "aria-expanded": showConflicts,
7526
+ onClick: () => setShowConflicts((value) => !value),
7527
+ children: showConflicts ? t("review.collapse") : t("config.syncCompareShowConflicts")
7528
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7529
+ variant: "ghost",
7530
+ size: "sm",
7531
+ onClick: goToReview,
7532
+ children: t("config.syncCompareGoReview")
7533
+ })]
7534
+ }),
7535
+ showConflicts && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
7536
+ className: MnemonSettingsCard_module_css_default.syncConflictList,
7537
+ children: conflicts.slice(0, SHOWN_CONFLICTS).map((conflict) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
7538
+ className: MnemonSettingsCard_module_css_default.syncConflict,
7539
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncDiffHere") }), clip(conflict.local.content, 240)] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncDiffThere") }), clip(conflict.remote.content, 240)] })]
7540
+ }, conflict.target + "\0" + conflict.local.content))
7541
+ })
7542
+ ]
7543
+ }),
7544
+ heldBack > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7545
+ className: MnemonSettingsCard_module_css_default.syncCompareNote,
7546
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7547
+ className: MnemonSettingsCard_module_css_default.syncDialogNote,
7548
+ children: t("config.syncCompareHeldBack", { count: heldBack })
7549
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7550
+ className: MnemonSettingsCard_module_css_default.rowActions,
7551
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7552
+ variant: "ghost",
7553
+ size: "sm",
7554
+ disabled: busy !== null || !writable,
7555
+ onClick: () => void merge(true),
7556
+ children: busy === "revive" ? t("config.syncCompareReviving") : t("config.syncCompareRevive")
7557
+ })
7558
+ })]
7559
+ })
7560
+ ] })
7561
+ ]
7562
+ })
7563
+ });
7012
7564
  }
7013
- /** The name a backup or a difference is attributed to, as a reader can act on it. */
7014
- function ownerName(t, machine) {
7015
- if (machine === void 0) return t("config.syncBackupUnknownMachine");
7016
- return machine.label.trim() === "" ? machine.id : machine.label;
7565
+ /** A short question before an action whose consequence is easy to miss. */
7566
+ function SyncConfirmDialog(props) {
7567
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MnemonDialog, {
7568
+ title: props.title,
7569
+ closeLabel: props.t("common.close"),
7570
+ busy: props.busy === true,
7571
+ onClose: props.onClose,
7572
+ footer: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7573
+ variant: "outline",
7574
+ size: "sm",
7575
+ disabled: props.busy === true,
7576
+ onClick: props.onClose,
7577
+ children: props.t("common.cancel")
7578
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7579
+ variant: "primary",
7580
+ size: "sm",
7581
+ disabled: props.busy === true,
7582
+ onClick: props.onConfirm,
7583
+ children: props.confirm
7584
+ })] }),
7585
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7586
+ className: MnemonSettingsCard_module_css_default.syncDialogBody,
7587
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7588
+ className: MnemonSettingsCard_module_css_default.syncDialogNote,
7589
+ children: props.body
7590
+ }), props.error !== void 0 && props.error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7591
+ className: MnemonSettingsCard_module_css_default.error,
7592
+ role: "alert",
7593
+ children: props.error
7594
+ })]
7595
+ })
7596
+ });
7017
7597
  }
7018
- /** One line of text as a reader scans it: whitespace collapsed, then cut to a readable length. */
7019
- function clip(value, max) {
7020
- const text = value.replace(/\s+/gu, " ").trim();
7021
- return text.length <= max ? text : text.slice(0, max - 1) + "…";
7598
+ //#endregion
7599
+ //#region src/client/MnemonSyncSection.tsx
7600
+ /** How long the row waits for the Host to report the switch it just saved. */
7601
+ const STATUS_SETTLE_MS = 250;
7602
+ const STATUS_SETTLE_ATTEMPTS = 20;
7603
+ /** How many repositories the picker lists before it asks for a narrower search. */
7604
+ const SHOWN_REPOSITORIES = 50;
7605
+ /** What an action just did, said beside the row that ran it. */
7606
+ function FeedbackLine({ value }) {
7607
+ if (value === null) return null;
7608
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7609
+ className: [MnemonSettingsCard_module_css_default.syncFeedbackLine, value.tone === "error" ? MnemonSettingsCard_module_css_default.error : MnemonSettingsCard_module_css_default.syncSuccess].join(" "),
7610
+ role: value.tone === "error" ? "alert" : "status",
7611
+ children: value.text
7612
+ });
7022
7613
  }
7023
7614
  /**
7024
- * Git repository sync: the repository this root publishes its Mnemon Pack to,
7025
- * the credential that authenticates the push, and the two operations that move
7026
- * the payload. The form reads the Host's status first, so a repository the Host
7027
- * cannot reach, a missing Git, or a read-only Host is visible before anything
7028
- * runs.
7615
+ * Git repository sync, in the order a person sets it up: connect a repository,
7616
+ * sync, choose how often it syncs on its own, look back at what it kept, and
7617
+ * only then the advanced choices of branch, directory and commit author.
7029
7618
  *
7030
- * The credential is optional: signing in to GitHub stores a grant the Host reads
7031
- * per operation, and the repository then comes from the account instead of being
7032
- * typed. The access token field stays as the fallback for every other host.
7619
+ * The switch is the whole gate: switched off, this is one row that asks the Host
7620
+ * nothing — no status, no repository, no Git.
7033
7621
  *
7034
- * The switch is the whole gate: switched off, this section is one row that asks
7035
- * the Host nothing — no status, no repository, no Git — and switching it on is
7036
- * what unfolds the form, the operations and the branch history.
7622
+ * A sync merges the repository's memory into this computer and then publishes
7623
+ * the result, so it is the one primary action. "Check remote" reads what a sync
7624
+ * would change and writes nothing until a button in it is pressed.
7037
7625
  */
7038
- /** How long the row waits for the Host to report the switch it just saved. */
7039
- const STATUS_SETTLE_MS = 250;
7040
- const STATUS_SETTLE_ATTEMPTS = 20;
7041
7626
  function MnemonSyncSection({ connection, sessionId, workspaceId, disabled, enabled, onEnabled, t }) {
7042
7627
  const client = (0, react.useMemo)(() => connection === void 0 ? null : new MnemonClient(connection, sessionId, workspaceId), [
7043
7628
  connection,
@@ -7046,38 +7631,38 @@ window.__ModuleLoader__.load({
7046
7631
  ]);
7047
7632
  const [status, setStatus] = (0, react.useState)(null);
7048
7633
  const [loaded, setLoaded] = (0, react.useState)(false);
7049
- const [draft, setDraft] = (0, react.useState)(() => draftOf(void 0));
7050
- const [pending, setPending] = (0, react.useState)(null);
7051
- const [busy, setBusy] = (0, react.useState)(null);
7052
- const [failed, setFailed] = (0, react.useState)(null);
7053
- const [notice, setNotice] = (0, react.useState)(null);
7634
+ const [loadFailed, setLoadFailed] = (0, react.useState)(null);
7635
+ const [checking, setChecking] = (0, react.useState)(false);
7054
7636
  const [github, setGithub] = (0, react.useState)(null);
7055
- const [githubFailed, setGithubFailed] = (0, react.useState)(null);
7056
- const [repositories, setRepositories] = (0, react.useState)(null);
7057
- const [repositoryName, setRepositoryName] = (0, react.useState)("");
7058
- const [repositoryPrivate, setRepositoryPrivate] = (0, react.useState)(true);
7059
- const [backups, setBackups] = (0, react.useState)(null);
7060
- const [openCommit, setOpenCommit] = (0, react.useState)(null);
7061
- const [difference, setDifference] = (0, react.useState)(null);
7062
- const [dialog, setDialog] = (0, react.useState)(false);
7063
- const [copied, setCopied] = (0, react.useState)(false);
7064
- const [autoBackupSaving, setAutoBackupSaving] = (0, react.useState)(false);
7065
- const [pollTick, setPollTick] = (0, react.useState)(0);
7066
- const [pollMs, setPollMs] = (0, react.useState)(5e3);
7067
- const askedRepositories = (0, react.useRef)(false);
7068
- const refresh = (0, react.useCallback)(async () => {
7069
- if (client === null || !enabled) return;
7637
+ const [editing, setEditing] = (0, react.useState)(false);
7638
+ const [busy, setBusy] = (0, react.useState)(null);
7639
+ const [syncFeedback, setSyncFeedback] = (0, react.useState)(null);
7640
+ const [repositoryFeedback, setRepositoryFeedback] = (0, react.useState)(null);
7641
+ const [autoFeedback, setAutoFeedback] = (0, react.useState)(null);
7642
+ const [dialog, setDialog] = (0, react.useState)(null);
7643
+ const [disconnectFailed, setDisconnectFailed] = (0, react.useState)(null);
7644
+ const [editMode, setEditMode] = (0, react.useState)(void 0);
7645
+ const readStatus = (0, react.useCallback)(async () => {
7646
+ if (client === null) return;
7647
+ setChecking(true);
7070
7648
  try {
7071
7649
  setStatus(await client.syncStatus());
7650
+ setLoadFailed(null);
7072
7651
  } catch (reason) {
7073
- setFailed(message(reason));
7652
+ setLoadFailed(message(reason));
7074
7653
  } finally {
7654
+ setChecking(false);
7075
7655
  setLoaded(true);
7076
7656
  }
7657
+ }, [client]);
7658
+ const readGitHub = (0, react.useCallback)(async () => {
7659
+ if (client === null) return;
7077
7660
  try {
7078
7661
  setGithub(await client.githubStatus());
7079
- } catch {}
7080
- }, [client, enabled]);
7662
+ } catch {
7663
+ setGithub(null);
7664
+ }
7665
+ }, [client]);
7081
7666
  (0, react.useEffect)(() => {
7082
7667
  if (client === null) {
7083
7668
  setLoaded(true);
@@ -7096,11 +7681,12 @@ window.__ModuleLoader__.load({
7096
7681
  })().then((next) => {
7097
7682
  if (active) {
7098
7683
  setStatus(next);
7684
+ setLoadFailed(null);
7099
7685
  setLoaded(true);
7100
7686
  }
7101
7687
  }, (reason) => {
7102
7688
  if (active) {
7103
- setFailed(message(reason));
7689
+ setLoadFailed(message(reason));
7104
7690
  setLoaded(true);
7105
7691
  }
7106
7692
  });
@@ -7113,377 +7699,621 @@ window.__ModuleLoader__.load({
7113
7699
  active = false;
7114
7700
  };
7115
7701
  }, [client, enabled]);
7116
- const saved = status?.config;
7117
- (0, react.useEffect)(() => {
7118
- setDraft(draftOf(saved));
7119
- }, [
7120
- saved?.repoUrl,
7121
- saved?.branch,
7122
- saved?.subdir,
7123
- saved?.authorName,
7124
- saved?.authorEmail,
7125
- saved?.hasToken,
7126
- saved?.autoBackupMinutes
7127
- ]);
7128
- const save = async () => {
7129
- if (client === null || busy !== null) return;
7130
- setBusy("save");
7131
- setFailed(null);
7132
- setNotice(null);
7702
+ const repoUrl = status?.config.repoUrl;
7703
+ const connected = status !== null && status.enabled !== false && repoUrl !== void 0;
7704
+ const editable = !disabled && client !== null;
7705
+ const gitReady = status?.git.available === true;
7706
+ /**
7707
+ * The one primary action: merge the repository here, then publish the result.
7708
+ * Answers why it did not finish, or null when it did, for a caller that shows it elsewhere.
7709
+ */
7710
+ const sync = async () => {
7711
+ if (client === null || busy !== null || repoUrl === void 0) return null;
7712
+ setBusy("sync");
7713
+ setSyncFeedback(null);
7714
+ let failure = null;
7133
7715
  try {
7134
- const patch = {
7135
- branch: draft.branch,
7136
- subdir: draft.subdir,
7137
- authorName: draft.authorName,
7138
- authorEmail: draft.authorEmail,
7139
- autoBackupMinutes: draft.autoBackupMinutes,
7140
- repoUrl: draft.repoUrl.trim() === "" ? null : draft.repoUrl.trim()
7141
- };
7142
- if (draft.clearToken) patch.token = null;
7143
- else if (draft.token.trim() !== "") patch.token = draft.token.trim();
7144
- await client.configureSync(patch);
7145
- setNotice(t("config.syncSaved"));
7146
- setDraft((current) => ({
7147
- ...current,
7148
- token: "",
7149
- clearToken: false
7150
- }));
7151
- await refresh();
7716
+ const feedback = syncResult(t, await client.pushSync(), repoUrl);
7717
+ setSyncFeedback(feedback);
7718
+ if (feedback.tone === "error") failure = feedback.text;
7152
7719
  } catch (reason) {
7153
- setFailed(message(reason));
7720
+ failure = t("config.syncFailed", { error: failureText(t, reasonOf(reason), message(reason), repoUrl) });
7721
+ setSyncFeedback({
7722
+ tone: "error",
7723
+ text: failure
7724
+ });
7154
7725
  } finally {
7155
7726
  setBusy(null);
7156
7727
  }
7728
+ readStatus();
7729
+ return failure;
7157
7730
  };
7158
- const push = async () => {
7731
+ const setAutoSync = async (minutes) => {
7159
7732
  if (client === null || busy !== null) return;
7160
- setBusy("push");
7161
- setFailed(null);
7162
- setNotice(null);
7163
- setPending(null);
7164
- setBackups(null);
7165
- setDifference(null);
7166
- try {
7167
- const result = await client.pushSync();
7168
- const parts = [result.pushed ? t("config.syncPushed", {
7169
- commit: result.commit.slice(0, 8),
7170
- files: result.files,
7171
- size: humanBytes(result.bytes)
7172
- }) : result.committed ? t("config.syncPushedLocal", {
7173
- commit: result.commit.slice(0, 8),
7174
- reason: result.reason ?? ""
7175
- }) : t("config.syncPushIdle")];
7176
- const compaction = result.compaction;
7177
- if (compaction !== void 0 && compaction.warning === void 0 && compaction.loose > 0) parts.push(t("config.syncCompacted", {
7178
- count: compaction.loose,
7179
- before: humanBytes(compaction.bytes),
7180
- after: humanBytes(compaction.packedBytes)
7181
- }));
7182
- setNotice(parts.join(" "));
7183
- await refresh();
7184
- } catch (reason) {
7185
- setFailed(message(reason));
7186
- } finally {
7187
- setBusy(null);
7188
- }
7189
- };
7190
- /** Turning the automatic backup on, off or to another interval is one saved value. */
7191
- const setAutoBackup = async (minutes) => {
7192
- if (client === null || busy !== null || autoBackupSaving) return;
7193
- setAutoBackupSaving(true);
7194
- setFailed(null);
7195
- setNotice(null);
7733
+ setBusy("auto");
7734
+ setAutoFeedback(null);
7196
7735
  try {
7197
7736
  const next = await client.configureSync({ autoBackupMinutes: minutes });
7198
7737
  setStatus((current) => current === null ? current : {
7199
7738
  ...current,
7200
7739
  config: next
7201
7740
  });
7202
- setNotice(t("config.syncAutoBackupSaved", { interval: intervalLabel(t, minutes) }));
7741
+ readStatus();
7203
7742
  } catch (reason) {
7204
- setFailed(message(reason));
7205
- } finally {
7206
- setAutoBackupSaving(false);
7207
- }
7208
- };
7209
- const preview = async () => {
7210
- if (client === null || busy !== null) return;
7211
- setBusy("preview");
7212
- setFailed(null);
7213
- setNotice(null);
7214
- setPending(null);
7215
- setDifference(null);
7216
- try {
7217
- setPending(await client.previewSync());
7218
- try {
7219
- setDifference(await client.syncDiff());
7220
- setDialog(true);
7221
- } catch {
7222
- setDifference(null);
7223
- }
7224
- } catch (reason) {
7225
- setFailed(message(reason));
7226
- } finally {
7227
- setBusy(null);
7228
- }
7229
- };
7230
- const pull = async () => {
7231
- if (client === null || pending === null || busy !== null) return;
7232
- setBusy("pull");
7233
- setFailed(null);
7234
- setNotice(null);
7235
- try {
7236
- const result = await client.pullSync();
7237
- setNotice(t("config.syncPulled", {
7238
- commit: result.commit.slice(0, 8),
7239
- root: result.targetRoot
7240
- }));
7241
- setPending(null);
7242
- setBackups(null);
7243
- setDifference(null);
7244
- await refresh();
7245
- } catch (reason) {
7246
- setFailed(message(reason));
7743
+ setAutoFeedback({
7744
+ tone: "error",
7745
+ text: message(reason)
7746
+ });
7247
7747
  } finally {
7248
7748
  setBusy(null);
7249
7749
  }
7250
7750
  };
7251
- /**
7252
- * The branch as one reading: the history of what was published, when, and by which
7253
- * installation, and - below it - which memories differ. The commit message is whatever
7254
- * its author typed, so the manifest inside the commit is what names the machine and
7255
- * says what the backup held.
7256
- *
7257
- * A difference that cannot be read still leaves the history standing: the two answers
7258
- * are separate requests and either one alone is worth showing.
7259
- */
7260
- const loadHistory = async () => {
7751
+ const disconnect = async () => {
7261
7752
  if (client === null || busy !== null) return;
7262
- setBusy("backups");
7263
- setFailed(null);
7264
- setNotice(null);
7265
- setDialog(true);
7753
+ setBusy("disconnect");
7754
+ setRepositoryFeedback(null);
7755
+ setSyncFeedback(null);
7756
+ setDisconnectFailed(null);
7266
7757
  try {
7267
- setBackups(await client.syncBackups());
7758
+ await client.configureSync({
7759
+ repoUrl: null,
7760
+ token: null,
7761
+ autoBackupMinutes: 0
7762
+ });
7763
+ setDialog(null);
7764
+ setEditing(false);
7765
+ setRepositoryFeedback({
7766
+ tone: "success",
7767
+ text: t("config.syncDisconnected")
7768
+ });
7769
+ readStatus();
7268
7770
  } catch (reason) {
7269
- setFailed(message(reason));
7771
+ setDisconnectFailed(message(reason));
7270
7772
  } finally {
7271
7773
  setBusy(null);
7272
7774
  }
7273
- try {
7274
- setDifference(await client.syncDiff());
7275
- } catch {
7276
- setDifference(null);
7277
- }
7278
7775
  };
7279
7776
  /**
7280
- * Older backups, appended to the page already read. The branch's history is a window
7281
- * that grows one page at a time; a page the branch no longer holds is not read twice,
7282
- * so the list keeps what it already had.
7777
+ * A connection was saved: the editor closes and the repository is read again.
7778
+ * The state line under the repository is the answer, so nothing claims it is
7779
+ * connected before the Host has said whether it answers.
7283
7780
  */
7284
- const loadMore = async () => {
7285
- if (client === null || busy !== null || backups === null) return;
7286
- setBusy("more");
7287
- setFailed(null);
7288
- setNotice(null);
7289
- try {
7290
- const page = await client.syncBackups(backups.commits.length + BACKUP_PAGE);
7291
- setBackups({
7292
- ...page,
7293
- commits: [...backups.commits, ...page.commits.filter((commit) => !backups.commits.some((held) => held.commit === commit.commit))]
7294
- });
7295
- } catch (reason) {
7296
- setFailed(message(reason));
7297
- } finally {
7298
- setBusy(null);
7299
- }
7781
+ const connectedTo = async () => {
7782
+ setEditing(false);
7783
+ setSyncFeedback(null);
7784
+ setRepositoryFeedback(null);
7785
+ await readStatus();
7786
+ };
7787
+ /** The state line's own way out: credentials are changed in the editor that set them. */
7788
+ const fixCredentials = () => {
7789
+ setRepositoryFeedback(null);
7790
+ setEditMode(repoUrl !== void 0 && onGitHub(repoUrl) && github?.available === true ? "github" : "address");
7791
+ setEditing(true);
7300
7792
  };
7301
- /** Which memories are only here and which are only on the branch, before merging anything. */
7302
- const loadDifference = async () => {
7303
- if (client === null || busy !== null) return;
7304
- setBusy("diff");
7305
- setFailed(null);
7306
- setNotice(null);
7307
- setDialog(true);
7308
- try {
7309
- setDifference(await client.syncDiff());
7310
- } catch (reason) {
7311
- setFailed(message(reason));
7312
- } finally {
7313
- setBusy(null);
7314
- }
7793
+ const autoBackup = status?.autoBackup;
7794
+ const minutes = status?.config.autoBackupMinutes ?? 0;
7795
+ const autoOptions = AUTO_SYNC_CHOICES.map((choice) => ({
7796
+ value: String(choice),
7797
+ label: intervalLabel(t, choice)
7798
+ }));
7799
+ const autoHint = autoBackup?.lastError !== void 0 && minutes > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7800
+ className: MnemonSettingsCard_module_css_default.error,
7801
+ children: t("config.syncAutoFailed", { error: failureText(t, autoBackup.lastFailure, autoBackup.lastError, repoUrl ?? "") })
7802
+ }) : minutes <= 0 ? t("config.syncAutoHintOff") : [autoBackup?.nextAt === void 0 ? "" : t("config.syncAutoNext", { time: when(autoBackup.nextAt) }), autoBackup?.lastAt === void 0 ? "" : t("config.syncAutoLast", { time: when(autoBackup.lastAt) })].filter(Boolean).join(" · ") || t("config.syncAutoHintOn");
7803
+ const lastRun = status?.lastRun;
7804
+ const syncHint = lastRun === void 0 ? t("config.syncNever") : lastRun.kind === "merge" ? t("config.syncLastMerge", { time: when(lastRun.at) }) : t("config.syncLast", { time: when(lastRun.at) });
7805
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7806
+ className: MnemonSettingsCard_module_css_default.syncRow,
7807
+ role: "group",
7808
+ "aria-labelledby": "mnemon-sync-heading",
7809
+ children: [
7810
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToggleRow, {
7811
+ id: "mnemon-sync-enabled",
7812
+ titleId: "mnemon-sync-heading",
7813
+ label: t("config.syncTitle"),
7814
+ hint: t("config.syncSimpleDescription"),
7815
+ checked: enabled,
7816
+ disabled,
7817
+ onChange: onEnabled
7818
+ }),
7819
+ enabled && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7820
+ className: MnemonSettingsCard_module_css_default.syncPanel,
7821
+ children: [
7822
+ client === null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7823
+ className: MnemonSettingsCard_module_css_default.readOnly,
7824
+ children: t("config.syncUnavailable")
7825
+ }),
7826
+ client !== null && !loaded && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7827
+ className: MnemonSettingsCard_module_css_default.syncDialogNote,
7828
+ role: "status",
7829
+ children: t("config.syncLoading")
7830
+ }),
7831
+ client !== null && loaded && status === null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7832
+ className: MnemonSettingsCard_module_css_default.error,
7833
+ role: "alert",
7834
+ children: t("config.syncUnavailableReason", { error: loadFailed ?? "" })
7835
+ }),
7836
+ client !== null && loaded && status !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
7837
+ !gitReady && status.enabled !== false && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7838
+ className: MnemonSettingsCard_module_css_default.syncWarning,
7839
+ role: "status",
7840
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("config.syncGitMissing", { required: status.git.required }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7841
+ variant: "ghost",
7842
+ size: "sm",
7843
+ disabled: checking,
7844
+ onClick: () => void readStatus(),
7845
+ children: t("config.syncRecheck")
7846
+ })]
7847
+ }),
7848
+ connected && !editing ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(SettingRow, {
7849
+ title: t("config.syncRepository"),
7850
+ titleId: "mnemon-sync-repository-title",
7851
+ hint: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(RepositoryState, {
7852
+ status,
7853
+ checking,
7854
+ t,
7855
+ onRecheck: () => void readStatus(),
7856
+ onFix: editable ? fixCredentials : void 0
7857
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FeedbackLine, { value: repositoryFeedback })] }),
7858
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7859
+ variant: "outline",
7860
+ size: "sm",
7861
+ disabled: !editable || busy !== null,
7862
+ onClick: () => {
7863
+ setRepositoryFeedback(null);
7864
+ setEditMode(void 0);
7865
+ setEditing(true);
7866
+ },
7867
+ children: t("config.syncChange")
7868
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7869
+ variant: "ghost",
7870
+ size: "sm",
7871
+ disabled: !editable || busy !== null,
7872
+ onClick: () => setDialog("disconnect"),
7873
+ children: t("config.syncDisconnect")
7874
+ })]
7875
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7876
+ className: MnemonSettingsCard_module_css_default.syncConnect,
7877
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SettingRow, {
7878
+ title: t("config.syncRepository"),
7879
+ titleId: "mnemon-sync-repository-title",
7880
+ hint: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [t("config.syncRepositoryHint"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FeedbackLine, { value: repositoryFeedback })] })
7881
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RepositoryEditor, {
7882
+ client,
7883
+ status,
7884
+ github,
7885
+ disabled: !editable,
7886
+ cancellable: connected,
7887
+ initialMode: editMode,
7888
+ t,
7889
+ onGitHub: setGithub,
7890
+ onReadGitHub: readGitHub,
7891
+ onRefresh: readStatus,
7892
+ onCancel: () => {
7893
+ setEditing(false);
7894
+ readStatus();
7895
+ },
7896
+ onConnected: connectedTo
7897
+ })]
7898
+ }),
7899
+ connected && !editing && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
7900
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(SettingRow, {
7901
+ title: t("config.syncRowTitle"),
7902
+ titleId: "mnemon-sync-now-title",
7903
+ hint: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [syncHint, /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FeedbackLine, { value: syncFeedback })] }),
7904
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7905
+ variant: "outline",
7906
+ size: "sm",
7907
+ disabled: !gitReady || busy !== null,
7908
+ onClick: () => {
7909
+ setSyncFeedback(null);
7910
+ setDialog("compare");
7911
+ },
7912
+ children: t("config.syncCheck")
7913
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7914
+ variant: "primary",
7915
+ size: "sm",
7916
+ disabled: !gitReady || !editable || busy !== null,
7917
+ onClick: () => void sync(),
7918
+ children: busy === "sync" ? t("config.syncNowRunning") : t("config.syncNow")
7919
+ })]
7920
+ }),
7921
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SettingRow, {
7922
+ title: t("config.syncAuto"),
7923
+ titleId: "mnemon-sync-auto-title",
7924
+ hint: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [autoHint, /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FeedbackLine, { value: autoFeedback })] }),
7925
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SettingSelect, {
7926
+ labelledBy: "mnemon-sync-auto-title",
7927
+ value: String(minutes),
7928
+ options: autoOptions,
7929
+ disabled: !editable || busy !== null,
7930
+ onChange: (value) => void setAutoSync(Number(value))
7931
+ })
7932
+ }),
7933
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SettingRow, {
7934
+ title: t("config.syncHistory"),
7935
+ titleId: "mnemon-sync-history-title",
7936
+ hint: t("config.syncHistoryHint"),
7937
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7938
+ variant: "outline",
7939
+ size: "sm",
7940
+ disabled: !gitReady,
7941
+ onClick: () => setDialog("history"),
7942
+ children: t("config.syncHistoryView")
7943
+ })
7944
+ })
7945
+ ] }),
7946
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AdvancedSettings, {
7947
+ client,
7948
+ status,
7949
+ disabled: !editable,
7950
+ t,
7951
+ onSaved: readStatus
7952
+ })
7953
+ ] })
7954
+ ]
7955
+ }),
7956
+ client !== null && repoUrl !== void 0 && dialog === "compare" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SyncCompareDialog, {
7957
+ client,
7958
+ repoUrl,
7959
+ writable: editable,
7960
+ t,
7961
+ onClose: () => setDialog(null),
7962
+ onSync: sync,
7963
+ onChanged: () => void readStatus()
7964
+ }),
7965
+ client !== null && repoUrl !== void 0 && dialog === "history" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SyncHistoryDialog, {
7966
+ client,
7967
+ repoUrl,
7968
+ t,
7969
+ onClose: () => setDialog(null)
7970
+ }),
7971
+ repoUrl !== void 0 && dialog === "disconnect" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SyncConfirmDialog, {
7972
+ title: t("config.syncDisconnectTitle"),
7973
+ body: t("config.syncDisconnectBody", { repository: repositoryName(repoUrl) }),
7974
+ confirm: t("config.syncDisconnect"),
7975
+ busy: busy === "disconnect",
7976
+ error: disconnectFailed,
7977
+ t,
7978
+ onConfirm: () => void disconnect(),
7979
+ onClose: () => {
7980
+ setDialog(null);
7981
+ setDisconnectFailed(null);
7982
+ }
7983
+ })
7984
+ ]
7985
+ });
7986
+ }
7987
+ /** What one finished sync did, said as one line. */
7988
+ function syncResult(t, result, repoUrl) {
7989
+ const added = result.merged?.runtime?.added ?? 0;
7990
+ const commit = result.commit.slice(0, 8);
7991
+ if (result.pushed) return {
7992
+ tone: "success",
7993
+ text: added > 0 ? t("config.syncDoneMerged", {
7994
+ count: added,
7995
+ commit
7996
+ }) : t("config.syncDone", { commit })
7315
7997
  };
7316
- /**
7317
- * The plain case: the branch holds memories this installation does not, and no subject
7318
- * is stated twice. Merging is additive and honors the branch's removals, so there is
7319
- * nothing to decide - the entries are simply added.
7320
- */
7321
- const addRemote = async (revive = false) => {
7322
- if (client === null || busy !== null || difference === null) return;
7323
- setBusy(revive ? "revive" : "add");
7324
- setFailed(null);
7325
- setNotice(null);
7326
- try {
7327
- const result = await client.pullSync(void 0, revive);
7328
- setNotice(addedNotice(t, result));
7329
- setPending(null);
7330
- await refresh();
7331
- try {
7332
- setDifference(await client.syncDiff());
7333
- } catch {
7334
- setDifference(null);
7335
- }
7336
- } catch (reason) {
7337
- setFailed(message(reason));
7338
- } finally {
7339
- setBusy(null);
7340
- }
7998
+ if (!result.committed) return {
7999
+ tone: "success",
8000
+ text: added > 0 ? t("config.syncUpToDateMerged", { count: added }) : t("config.syncUpToDate")
7341
8001
  };
7342
- /**
7343
- * A conflict needs a plan, and the plan is the review ledger's: **整理记忆** below runs
7344
- * the reconciliation, reads the proposal and applies it, so this page never keeps a
7345
- * second copy of it. What this page does is read the branch and say what differs.
7346
- */
7347
- /**
7348
- * The plan is the review ledger's, and the review list below this row is the one place it
7349
- * is read, decided and applied. This closes the dialog and puts the reader on that row,
7350
- * so a conflict found here has one obvious way to be answered.
7351
- */
7352
- const goToReview = () => {
7353
- setDialog(false);
7354
- const heading = document.getElementById("mnemon-review-heading");
7355
- if (heading === null) return;
7356
- if (typeof heading.scrollIntoView === "function") heading.scrollIntoView({
7357
- block: "start",
7358
- behavior: "smooth"
7359
- });
8002
+ return {
8003
+ tone: "error",
8004
+ text: t("config.syncPushFailed", { reason: failureText(t, result.failure, result.reason ?? "", repoUrl) })
8005
+ };
8006
+ }
8007
+ /** Where the repository is, whether it answers, and how it is authenticated. */
8008
+ function RepositoryState({ status, checking, t, onRecheck, onFix }) {
8009
+ const url = status.config.repoUrl ?? "";
8010
+ const remote = status.remote;
8011
+ const credential = credentialText(t, status);
8012
+ const state = checking ? {
8013
+ dot: "ongoing",
8014
+ text: t("config.syncStateChecking")
8015
+ } : !status.git.available ? {
8016
+ dot: "idle",
8017
+ text: t("config.syncReasonGitMissing")
8018
+ } : !remote.reachable ? {
8019
+ dot: "error",
8020
+ text: issueText(t, remote.issue, url, remote.error)
8021
+ } : {
8022
+ dot: credential === void 0 && transportOf(url) === "https" ? "warning" : "done",
8023
+ text: [remote.branchExists ? t("config.syncStateConnected") : t("config.syncStateNewBranch", { branch: status.config.branch }), ...credential !== void 0 ? [credential] : transportOf(url) === "https" ? [onGitHub(url) ? t("config.syncNoCredential") : t("config.syncNoCredentialToken")] : []].join(" · ")
7360
8024
  };
7361
- /** Choosing a repository is the whole configuration step, so it is saved at once. */
7362
- const choose = async (repository) => {
7363
- if (client === null || busy !== null || !editable) return;
7364
- setBusy("save");
7365
- setFailed(null);
7366
- setNotice(null);
8025
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
8026
+ className: MnemonSettingsCard_module_css_default.syncRepositoryState,
8027
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8028
+ className: MnemonSettingsCard_module_css_default.syncRepositoryName,
8029
+ children: transportOf(url) === "local" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.PathLabel, { path: url }) : repositoryName(url)
8030
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
8031
+ className: MnemonSettingsCard_module_css_default.syncStateLine,
8032
+ "data-tone": state.dot,
8033
+ children: [
8034
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: state.dot }),
8035
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: state.text }),
8036
+ !checking && onFix !== void 0 && (remote.issue === "auth" || remote.issue === "not-found") && transportOf(url) === "https" && status.git.available && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
8037
+ type: "button",
8038
+ className: MnemonSettingsCard_module_css_default.syncInlineAction,
8039
+ onClick: onFix,
8040
+ children: t("config.syncFixCredentials")
8041
+ }),
8042
+ !checking && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
8043
+ type: "button",
8044
+ className: MnemonSettingsCard_module_css_default.syncInlineAction,
8045
+ onClick: onRecheck,
8046
+ children: t("config.syncRecheck")
8047
+ })
8048
+ ]
8049
+ })]
8050
+ });
8051
+ }
8052
+ /** Connect a repository: through a GitHub sign-in, or by its address. */
8053
+ function RepositoryEditor(props) {
8054
+ const { status, github, t } = props;
8055
+ const githubOffered = github?.available === true;
8056
+ const saved = status.config.repoUrl;
8057
+ const [mode, setMode] = (0, react.useState)(() => props.initialMode ?? (githubOffered && (saved === void 0 || onGitHub(saved)) ? "github" : "address"));
8058
+ const chosen = (0, react.useRef)(props.initialMode !== void 0);
8059
+ (0, react.useEffect)(() => {
8060
+ if (!chosen.current && githubOffered && saved === void 0) setMode("github");
8061
+ }, [githubOffered, saved]);
8062
+ const name = (0, react.useId)();
8063
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8064
+ className: MnemonSettingsCard_module_css_default.editor,
8065
+ children: [githubOffered && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8066
+ className: MnemonSettingsCard_module_css_default.inlineChoices,
8067
+ role: "radiogroup",
8068
+ "aria-label": t("config.syncConnectWith"),
8069
+ children: ["github", "address"].map((value) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
8070
+ type: "radio",
8071
+ name,
8072
+ value,
8073
+ checked: mode === value,
8074
+ disabled: props.disabled,
8075
+ onChange: () => {
8076
+ chosen.current = true;
8077
+ setMode(value);
8078
+ }
8079
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: value === "github" ? t("config.syncModeGitHub") : t("config.syncModeAddress") })] }, value))
8080
+ }), mode === "github" && githubOffered && github !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(GitHubConnect, {
8081
+ ...props,
8082
+ github
8083
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AddressConnect, { ...props })]
8084
+ });
8085
+ }
8086
+ /** Whether two HTTPS addresses name the same host, the one a saved token was saved for. */
8087
+ function sameHost(left, right) {
8088
+ try {
8089
+ return new URL(left.trim()).host.toLowerCase() === new URL(right.trim()).host.toLowerCase();
8090
+ } catch {
8091
+ return false;
8092
+ }
8093
+ }
8094
+ /** The address form: a repository URL, and a token where the address is HTTPS. */
8095
+ function AddressConnect({ client, status, disabled, cancellable, t, onRefresh, onCancel, onConnected }) {
8096
+ const saved = status.config.repoUrl ?? "";
8097
+ const [url, setUrl] = (0, react.useState)(saved);
8098
+ const [token, setToken] = (0, react.useState)("");
8099
+ const [busy, setBusy] = (0, react.useState)(null);
8100
+ const [feedback, setFeedback] = (0, react.useState)(null);
8101
+ const tokenId = (0, react.useId)();
8102
+ const problem = repositoryProblem(url);
8103
+ const https = transportOf(url) === "https";
8104
+ const environment = status.config.credentialSource === "environment";
8105
+ const storedToken = status.config.credentialSource === "token" && sameHost(url, saved);
8106
+ const changed = url.trim() !== saved || token.trim() !== "";
8107
+ const ready = url.trim() !== "" && problem === void 0 && changed;
8108
+ const connect = async () => {
8109
+ if (!ready || busy !== null) return;
8110
+ setBusy("connect");
8111
+ setFeedback(null);
7367
8112
  try {
7368
- await client.configureSync({ repoUrl: repository.url });
7369
- setNotice(t("config.syncSaved"));
7370
- await refresh();
8113
+ const next = url.trim();
8114
+ await client.configureSync({
8115
+ repoUrl: next,
8116
+ ...https && token.trim() !== "" ? { token: token.trim() } : {},
8117
+ ...https ? {} : { token: null }
8118
+ });
8119
+ setToken("");
8120
+ await onConnected();
7371
8121
  } catch (reason) {
7372
- setFailed(message(reason));
8122
+ setFeedback({
8123
+ tone: "error",
8124
+ text: message(reason)
8125
+ });
7373
8126
  } finally {
7374
8127
  setBusy(null);
7375
8128
  }
7376
8129
  };
7377
- const loadRepositories = (0, react.useCallback)(async () => {
7378
- if (client === null || busy !== null) return;
7379
- setBusy("repos");
7380
- setGithubFailed(null);
8130
+ const removeToken = async () => {
8131
+ if (busy !== null) return;
8132
+ setBusy("token");
8133
+ setFeedback(null);
7381
8134
  try {
7382
- const answer = await client.githubRepositories();
7383
- setRepositories(answer.repositories);
8135
+ await client.configureSync({ token: null });
8136
+ setFeedback({
8137
+ tone: "success",
8138
+ text: t("config.syncTokenRemoved")
8139
+ });
8140
+ onRefresh();
7384
8141
  } catch (reason) {
7385
- setGithubFailed(message(reason));
8142
+ setFeedback({
8143
+ tone: "error",
8144
+ text: message(reason)
8145
+ });
7386
8146
  } finally {
7387
8147
  setBusy(null);
7388
8148
  }
7389
- }, [client, busy]);
7390
- const signIn = async () => {
7391
- if (client === null || busy !== null) return;
7392
- setBusy("github");
7393
- setGithubFailed(null);
7394
- setNotice(null);
8149
+ };
8150
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
8151
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8152
+ className: MnemonSettingsCard_module_css_default.fieldGrid,
8153
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", { children: [t("config.syncRepoUrl"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
8154
+ type: "text",
8155
+ value: url,
8156
+ "aria-label": t("config.syncRepoUrl"),
8157
+ placeholder: t("config.syncRepoUrlPlaceholder"),
8158
+ disabled: disabled || busy !== null,
8159
+ "aria-invalid": problem === void 0 ? void 0 : true,
8160
+ autoComplete: "off",
8161
+ spellCheck: false,
8162
+ autoCapitalize: "none",
8163
+ autoCorrect: "off",
8164
+ onChange: (event) => setUrl(event.target.value),
8165
+ onKeyDown: (event) => {
8166
+ if (event.key === "Enter") connect();
8167
+ }
8168
+ })] }), https && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8169
+ className: MnemonSettingsCard_module_css_default.syncFieldBox,
8170
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
8171
+ className: MnemonSettingsCard_module_css_default.syncFieldLabel,
8172
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
8173
+ htmlFor: tokenId,
8174
+ children: t("config.syncToken")
8175
+ }), storedToken && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
8176
+ type: "button",
8177
+ className: MnemonSettingsCard_module_css_default.syncInlineAction,
8178
+ disabled: disabled || busy !== null,
8179
+ onClick: () => void removeToken(),
8180
+ children: t("config.syncTokenRemove")
8181
+ })]
8182
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
8183
+ id: tokenId,
8184
+ type: "password",
8185
+ value: token,
8186
+ "aria-label": t("config.syncToken"),
8187
+ disabled: disabled || busy !== null || environment,
8188
+ placeholder: environment ? t("config.syncTokenEnvironment", { env: "MNEMON_SYNC_GIT_TOKEN" }) : storedToken ? t("config.syncTokenSaved") : t("config.syncTokenOptional"),
8189
+ autoComplete: "new-password",
8190
+ spellCheck: false,
8191
+ onChange: (event) => setToken(event.target.value)
8192
+ })]
8193
+ })]
8194
+ }),
8195
+ problem !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8196
+ className: MnemonSettingsCard_module_css_default.error,
8197
+ children: problem === "credentials" ? t("config.syncRepoUrlCredentials") : t("config.syncRepoUrlInvalid")
8198
+ }),
8199
+ https && problem === void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8200
+ className: MnemonSettingsCard_module_css_default.editorNote,
8201
+ children: t("config.syncTokenHint")
8202
+ }),
8203
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8204
+ className: MnemonSettingsCard_module_css_default.memoryConfigFooter,
8205
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8206
+ className: MnemonSettingsCard_module_css_default.configFeedback,
8207
+ "aria-live": "polite",
8208
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FeedbackLine, { value: feedback })
8209
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [cancellable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
8210
+ variant: "ghost",
8211
+ size: "sm",
8212
+ disabled: busy !== null,
8213
+ onClick: onCancel,
8214
+ children: t("common.cancel")
8215
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
8216
+ variant: "primary",
8217
+ size: "sm",
8218
+ disabled: disabled || !ready || busy !== null,
8219
+ onClick: () => void connect(),
8220
+ children: busy === "connect" ? t("config.syncConnecting") : saved === "" ? t("config.syncConnect") : t("config.syncSave")
8221
+ })] })]
8222
+ })
8223
+ ] });
8224
+ }
8225
+ /** Sign in with the GitHub device flow, then pick or create the repository. */
8226
+ function GitHubConnect(props) {
8227
+ const { client, github, disabled, cancellable, t, onGitHub, onReadGitHub, onCancel, onConnected } = props;
8228
+ const [busy, setBusy] = (0, react.useState)(null);
8229
+ const [failed, setFailed] = (0, react.useState)(null);
8230
+ const [copied, setCopied] = (0, react.useState)(false);
8231
+ const [pollTick, setPollTick] = (0, react.useState)(0);
8232
+ const [pollMs, setPollMs] = (0, react.useState)(5e3);
8233
+ const flow = github.flow;
8234
+ const signedIn = github.signedIn;
8235
+ const start = async () => {
8236
+ if (busy !== null) return;
8237
+ setBusy("start");
8238
+ setFailed(null);
8239
+ setCopied(false);
7395
8240
  try {
7396
8241
  const next = await client.githubStart();
7397
- setGithub(next);
8242
+ onGitHub(next);
7398
8243
  setPollMs(next.flow?.intervalMs ?? 5e3);
7399
8244
  setPollTick(0);
7400
8245
  } catch (reason) {
7401
- setGithubFailed(message(reason));
8246
+ setFailed(t("config.syncGitHubFailed", { error: message(reason) }));
7402
8247
  } finally {
7403
8248
  setBusy(null);
7404
8249
  }
7405
8250
  };
7406
- const cancelSignIn = async () => {
7407
- if (client === null || busy !== null) return;
7408
- setBusy("github");
7409
- setGithubFailed(null);
8251
+ const cancel = async () => {
8252
+ if (busy !== null) return;
8253
+ setBusy("cancel");
8254
+ setFailed(null);
7410
8255
  try {
7411
- setGithub(await client.githubCancel());
8256
+ onGitHub(await client.githubCancel());
7412
8257
  } catch (reason) {
7413
- setGithubFailed(message(reason));
8258
+ setFailed(message(reason));
7414
8259
  } finally {
7415
8260
  setBusy(null);
7416
8261
  }
7417
8262
  };
7418
8263
  const signOut = async () => {
7419
- if (client === null || busy !== null) return;
7420
- setBusy("github");
7421
- setGithubFailed(null);
7422
- setNotice(null);
7423
- try {
7424
- setGithub(await client.githubSignOut());
7425
- askedRepositories.current = false;
7426
- setRepositories(null);
7427
- await refresh();
7428
- } catch (reason) {
7429
- setGithubFailed(message(reason));
7430
- } finally {
7431
- setBusy(null);
7432
- }
7433
- };
7434
- const createRepository = async () => {
7435
- if (client === null || busy !== null || repositoryName.trim() === "") return;
7436
- setBusy("create");
8264
+ if (busy !== null) return;
8265
+ setBusy("signout");
7437
8266
  setFailed(null);
7438
- setGithubFailed(null);
7439
- setNotice(null);
7440
8267
  try {
7441
- const created = await client.githubCreateRepository(repositoryName.trim(), repositoryPrivate);
7442
- setNotice(t("config.syncRepositoryCreated", { name: created.fullName }));
7443
- setRepositoryName("");
7444
- askedRepositories.current = false;
7445
- await loadRepositories();
7446
- await choose(created);
8268
+ onGitHub(await client.githubSignOut());
7447
8269
  } catch (reason) {
7448
- setGithubFailed(message(reason));
8270
+ setFailed(message(reason));
7449
8271
  } finally {
7450
8272
  setBusy(null);
7451
8273
  }
7452
8274
  };
7453
- const copyCode = async (code) => {
7454
- try {
7455
- setCopied(await (0, _deepseek_ai_dsh_client_ui_primitives.writeClipboard)(code));
7456
- } catch {
7457
- setCopied(false);
7458
- }
8275
+ /** A grant GitHub stopped honouring is replaced: sign out, then start a new sign-in. */
8276
+ const signInAgain = async () => {
8277
+ await signOut();
8278
+ await start();
8279
+ };
8280
+ /**
8281
+ * One click copies the code and opens the page it is typed into. The copy starts
8282
+ * first, while this page still has focus, and the page opens within the same click,
8283
+ * so neither the clipboard nor a popup blocker refuses it.
8284
+ */
8285
+ const copyAndOpen = async () => {
8286
+ if (flow === void 0) return;
8287
+ const copying = (0, _deepseek_ai_dsh_client_ui_primitives.writeClipboard)(flow.userCode).catch(() => false);
8288
+ const opened = window.open(flow.verificationUri, "_blank");
8289
+ if (opened !== null) opened.opener = null;
8290
+ setCopied(await copying);
8291
+ if (opened === null) setFailed(t("config.syncGitHubOpenBlocked", { url: flow.verificationUri }));
7459
8292
  };
7460
- const flow = github?.flow;
7461
- const signedIn = github?.signedIn === true;
7462
8293
  (0, react.useEffect)(() => {
7463
- if (client === null || !enabled || flow === void 0) return;
8294
+ if (flow === void 0 || signedIn) return;
7464
8295
  let active = true;
7465
8296
  const timer = setTimeout(() => {
7466
8297
  (async () => {
7467
8298
  try {
7468
8299
  const answer = await client.githubPoll();
7469
8300
  if (!active) return;
8301
+ setFailed(null);
7470
8302
  if (answer.status === "pending") {
7471
8303
  if (answer.intervalMs !== void 0) setPollMs(answer.intervalMs);
7472
8304
  setPollTick((current) => current + 1);
7473
8305
  return;
7474
8306
  }
7475
- const next = await client.githubStatus();
8307
+ await onReadGitHub();
7476
8308
  if (!active) return;
7477
- setGithub(next);
7478
- if (answer.status === "success") {
7479
- askedRepositories.current = false;
7480
- setRepositories(null);
7481
- setNotice(next.login === void 0 ? t("config.syncTokenGitHub") : t("config.syncGitHubSignedIn", { login: next.login }));
7482
- } else if (answer.status === "expired") setGithubFailed(t("config.syncGitHubExpired"));
7483
- else if (answer.status === "denied") setGithubFailed(t("config.syncGitHubDenied"));
7484
- else if (answer.message !== void 0) setGithubFailed(answer.message);
8309
+ if (answer.status === "expired") setFailed(t("config.syncGitHubExpired"));
8310
+ else if (answer.status === "denied") setFailed(t("config.syncGitHubDenied"));
8311
+ else if (answer.status === "error") setFailed(t("config.syncGitHubFailed", { error: answer.message ?? "" }));
7485
8312
  } catch (reason) {
7486
- if (active) setGithubFailed(message(reason));
8313
+ if (active) {
8314
+ setFailed(message(reason));
8315
+ setPollTick((current) => current + 1);
8316
+ }
7487
8317
  }
7488
8318
  })();
7489
8319
  }, Math.max(pollMs, 1e3));
@@ -7493,653 +8323,557 @@ window.__ModuleLoader__.load({
7493
8323
  };
7494
8324
  }, [
7495
8325
  client,
7496
- enabled,
7497
8326
  flow?.userCode,
8327
+ signedIn,
7498
8328
  pollMs,
7499
8329
  pollTick,
8330
+ onReadGitHub,
7500
8331
  t
7501
8332
  ]);
7502
- (0, react.useEffect)(() => {
7503
- if (!enabled || !signedIn || repositories !== null || askedRepositories.current) return;
7504
- askedRepositories.current = true;
7505
- loadRepositories();
7506
- }, [
7507
- enabled,
7508
- signedIn,
7509
- repositories,
7510
- loadRepositories
7511
- ]);
7512
- const states = [];
7513
- if (!loaded) states.push(t("config.syncLoading"));
7514
- else if (status === null) states.push(t("config.syncUnavailable"));
7515
- else if (status.enabled === false) states.push(t("config.syncLoading"));
7516
- else {
7517
- if (!status.configured) states.push(t("config.syncNotConfigured"));
7518
- if (!status.git.available) states.push(t("config.syncGitMissing", { required: status.git.required }));
7519
- if (status.configured && status.git.available) {
7520
- if (!status.remote.reachable) states.push(t("config.syncRemoteUnreachable"));
7521
- else if (!status.remote.branchExists) states.push(t("config.syncRemoteBranchMissing", { branch: status.config.branch }));
7522
- else if (status.remote.commit !== void 0) states.push(t("config.syncRemoteCommit", { commit: status.remote.commit.slice(0, 8) }));
8333
+ /** Choosing a repository connects it; the GitHub grant then authenticates, so no token is kept. */
8334
+ const choose = async (repository) => {
8335
+ setBusy("choose");
8336
+ setFailed(null);
8337
+ try {
8338
+ await client.configureSync({
8339
+ repoUrl: repository.url,
8340
+ token: null
8341
+ });
8342
+ await onConnected();
8343
+ } catch (reason) {
8344
+ setFailed(message(reason));
8345
+ } finally {
8346
+ setBusy(null);
7523
8347
  }
7524
- const credential = status.config.credentialSource;
7525
- if (credential === "github") states.push(status.config.credentialLogin === void 0 ? t("config.syncTokenGitHub") : t("config.syncGitHubSignedIn", { login: status.config.credentialLogin }));
7526
- else if (credential === "environment") states.push(t("config.syncTokenEnvironment"));
7527
- else if (credential === "token") states.push(t("config.syncTokenSaved"));
7528
- else states.push(t("config.syncTokenNone"));
7529
- }
7530
- const autoBackup = status?.autoBackup;
7531
- const ready = client !== null && status !== null && status.configured && status.git.available;
7532
- const editable = !disabled && client !== null;
7533
- const changed = pending?.components.filter((component) => component.changed).length ?? 0;
7534
- const selected = repositories?.some((repository) => repository.url === draft.repoUrl) === true ? draft.repoUrl : "";
7535
- const conflicts = difference?.conflicts ?? [];
7536
- const conflicted = new Set(conflicts.flatMap((conflict) => [conflict.target + "\0" + conflict.local.content, conflict.target + "\0" + conflict.remote.content]));
7537
- const additions = difference === null ? 0 : difference.remoteOnly.filter((entry) => !conflicted.has(entry.target + "\0" + entry.content)).length;
7538
- const heldBack = difference?.heldBack ?? 0;
7539
- const addable = Math.max(additions - heldBack, 0);
7540
- const onlyHere = difference === null ? 0 : difference.localOnly.filter((entry) => !conflicted.has(entry.target + "\0" + entry.content)).length;
7541
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7542
- className: MnemonSettingsCard_module_css_default.syncRow,
7543
- role: "group",
7544
- "aria-labelledby": "mnemon-sync-heading",
7545
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToggleRow, {
7546
- id: "mnemon-sync-enabled",
7547
- titleId: "mnemon-sync-heading",
7548
- label: t("config.syncTitle"),
7549
- hint: t("config.syncSimpleDescription"),
7550
- checked: enabled,
7551
- disabled,
7552
- onChange: onEnabled
7553
- }), enabled && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
8348
+ };
8349
+ const create = async (name) => {
8350
+ setBusy("create");
8351
+ setFailed(null);
8352
+ try {
8353
+ const created = await client.githubCreateRepository(name, true);
8354
+ await client.configureSync({
8355
+ repoUrl: created.url,
8356
+ token: null
8357
+ });
8358
+ await onConnected();
8359
+ } catch (reason) {
8360
+ setFailed(failureText(t, reasonOf(reason), message(reason), ""));
8361
+ } finally {
8362
+ setBusy(null);
8363
+ }
8364
+ };
8365
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
8366
+ !signedIn && flow === void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8367
+ className: MnemonSettingsCard_module_css_default.editorNote,
8368
+ children: github.writable ? t("config.syncGitHubHint") : t("config.syncGitHubReadOnly")
8369
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8370
+ className: MnemonSettingsCard_module_css_default.rowActions,
8371
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
8372
+ variant: "primary",
8373
+ size: "sm",
8374
+ disabled: disabled || !github.writable || busy !== null,
8375
+ onClick: () => void start(),
8376
+ children: busy === "start" ? t("config.syncGitHubStarting") : t("config.syncGitHubSignIn")
8377
+ }), cancellable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
8378
+ variant: "ghost",
8379
+ size: "sm",
8380
+ disabled: busy !== null,
8381
+ onClick: onCancel,
8382
+ children: t("common.cancel")
8383
+ })]
8384
+ })] }),
8385
+ !signedIn && flow !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8386
+ className: MnemonSettingsCard_module_css_default.syncDevice,
8387
+ children: [
8388
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8389
+ className: MnemonSettingsCard_module_css_default.editorNote,
8390
+ children: t("config.syncGitHubCode")
8391
+ }),
8392
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8393
+ className: MnemonSettingsCard_module_css_default.syncCode,
8394
+ children: [
8395
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { children: flow.userCode }),
8396
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
8397
+ variant: "primary",
8398
+ size: "sm",
8399
+ onClick: () => void copyAndOpen(),
8400
+ children: t("config.syncGitHubCopyOpen")
8401
+ }),
8402
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
8403
+ variant: "ghost",
8404
+ size: "sm",
8405
+ disabled: busy !== null,
8406
+ onClick: () => void cancel(),
8407
+ children: t("common.cancel")
8408
+ })
8409
+ ]
8410
+ }),
8411
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8412
+ className: MnemonSettingsCard_module_css_default.editorNote,
8413
+ role: "status",
8414
+ children: copied ? t("config.syncGitHubCopied") : t("config.syncGitHubWaiting")
8415
+ })
8416
+ ]
8417
+ }),
8418
+ signedIn && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
7554
8419
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7555
- className: MnemonSettingsCard_module_css_default.rowActions,
7556
- children: [
7557
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7558
- variant: "outline",
7559
- size: "sm",
7560
- disabled: !ready || busy !== null,
7561
- onClick: () => void preview(),
7562
- children: busy === "preview" ? t("config.syncPreviewing") : t("config.syncPreview")
7563
- }),
7564
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7565
- variant: "outline",
7566
- size: "sm",
7567
- disabled: !ready || busy !== null,
7568
- onClick: () => void loadHistory(),
7569
- children: busy === "backups" ? t("config.syncBackupsLoading") : t("config.syncBackups")
7570
- }),
7571
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7572
- variant: "primary",
7573
- size: "sm",
7574
- disabled: !ready || disabled || busy !== null,
7575
- onClick: () => void push(),
7576
- children: busy === "push" ? t("config.syncPushing") : t("config.syncPush")
7577
- })
7578
- ]
8420
+ className: MnemonSettingsCard_module_css_default.syncAccount,
8421
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: github.login === void 0 ? t("config.syncViaGitHubAnonymous") : t("config.syncGitHubSignedIn", { login: github.login }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
8422
+ variant: "ghost",
8423
+ size: "sm",
8424
+ disabled: disabled || busy !== null,
8425
+ onClick: () => void signOut(),
8426
+ children: t("config.syncGitHubSignOut")
8427
+ })]
7579
8428
  }),
7580
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7581
- className: MnemonSettingsCard_module_css_default.syncState,
7582
- "aria-live": "polite",
7583
- children: states.map((state) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: state }, state))
8429
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RepositoryPicker, {
8430
+ client,
8431
+ login: github.login,
8432
+ current: props.status.config.repoUrl,
8433
+ disabled: disabled || busy !== null,
8434
+ creating: busy === "create",
8435
+ t,
8436
+ onChoose: choose,
8437
+ onCreate: create,
8438
+ onSignInAgain: () => void signInAgain()
7584
8439
  }),
7585
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7586
- className: MnemonSettingsCard_module_css_default.syncForm,
7587
- children: [
7588
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7589
- className: MnemonSettingsCard_module_css_default.syncBlock,
7590
- children: [
7591
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("config.syncGitHub") }), signedIn && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7592
- className: MnemonSettingsCard_module_css_default.syncAccount,
7593
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: github?.login === void 0 ? t("config.syncTokenGitHub") : t("config.syncGitHubSignedIn", { login: github.login }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7594
- variant: "ghost",
7595
- size: "sm",
7596
- disabled: !editable || busy !== null,
7597
- onClick: () => void signOut(),
7598
- children: t("config.syncGitHubSignOut")
7599
- })]
7600
- })] }),
7601
- github === null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncLoading") }),
7602
- github !== null && !github.available && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncGitHubUnavailable") }),
7603
- github !== null && github.available && !signedIn && flow === void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncGitHubHint") }), github.writable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7604
- className: MnemonSettingsCard_module_css_default.syncFormActions,
7605
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7606
- variant: "outline",
7607
- size: "sm",
7608
- disabled: !editable || busy !== null,
7609
- onClick: () => void signIn(),
7610
- children: busy === "github" ? t("config.syncGitHubStarting") : t("config.syncGitHubSignIn")
7611
- })
7612
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncGitHubReadOnly") })] }),
7613
- flow !== void 0 && !signedIn && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
7614
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncGitHubCode") }),
7615
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7616
- className: MnemonSettingsCard_module_css_default.syncCode,
7617
- children: [
7618
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { children: flow.userCode }),
7619
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7620
- variant: "outline",
7621
- size: "sm",
7622
- onClick: () => void copyCode(flow.userCode),
7623
- children: copied ? t("config.syncGitHubCopied") : t("config.syncGitHubCopy")
7624
- }),
7625
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
7626
- href: flow.verificationUri,
7627
- target: "_blank",
7628
- rel: "noreferrer noopener",
7629
- children: t("config.syncGitHubOpen")
7630
- })
7631
- ]
7632
- }),
7633
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncGitHubWaiting") }),
7634
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7635
- className: MnemonSettingsCard_module_css_default.syncFormActions,
7636
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7637
- variant: "ghost",
7638
- size: "sm",
7639
- disabled: busy !== null,
7640
- onClick: () => void cancelSignIn(),
7641
- children: t("common.cancel")
7642
- })
7643
- })
7644
- ] }),
7645
- githubFailed !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7646
- className: MnemonSettingsCard_module_css_default.error,
7647
- children: t("config.syncGitHubFailed", { error: githubFailed })
7648
- })
7649
- ]
7650
- }),
7651
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7652
- className: MnemonSettingsCard_module_css_default.syncBlock,
8440
+ cancellable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8441
+ className: MnemonSettingsCard_module_css_default.rowActions,
8442
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
8443
+ variant: "ghost",
8444
+ size: "sm",
8445
+ disabled: busy !== null,
8446
+ onClick: onCancel,
8447
+ children: t("common.cancel")
8448
+ })
8449
+ })
8450
+ ] }),
8451
+ failed !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8452
+ className: MnemonSettingsCard_module_css_default.error,
8453
+ role: "alert",
8454
+ children: failed
8455
+ })
8456
+ ] });
8457
+ }
8458
+ /**
8459
+ * The account's repositories, searched by name. A name that matches none can be
8460
+ * created on the spot, private; a public repository is used only after the
8461
+ * reader confirms that anyone can then read the memory.
8462
+ */
8463
+ function RepositoryPicker({ client, login, current, disabled, creating, t, onChoose, onCreate, onSignInAgain }) {
8464
+ const [repositories, setRepositories] = (0, react.useState)(null);
8465
+ const [loading, setLoading] = (0, react.useState)(false);
8466
+ const [failed, setFailed] = (0, react.useState)(null);
8467
+ const [query, setQuery] = (0, react.useState)("");
8468
+ const [confirming, setConfirming] = (0, react.useState)(null);
8469
+ const load = (0, react.useCallback)(async () => {
8470
+ setLoading(true);
8471
+ setFailed(null);
8472
+ try {
8473
+ setRepositories((await client.githubRepositories()).repositories);
8474
+ } catch (reason) {
8475
+ const expired = reasonOf(reason) === "github-unauthorized";
8476
+ setFailed({
8477
+ text: expired ? t("config.syncGitHubExpiredGrant") : t("config.syncRepositoriesFailed", { error: message(reason) }),
8478
+ expired
8479
+ });
8480
+ } finally {
8481
+ setLoading(false);
8482
+ }
8483
+ }, [client, t]);
8484
+ (0, react.useEffect)(() => {
8485
+ load();
8486
+ }, [load]);
8487
+ const needle = query.trim().toLowerCase();
8488
+ const matches = (repositories ?? []).filter((repository) => needle === "" || repository.fullName.toLowerCase().includes(needle));
8489
+ const exact = (repositories ?? []).some((repository) => repository.name.toLowerCase() === needle && (login === void 0 || repository.owner.toLowerCase() === login.toLowerCase()));
8490
+ const creatable = needle !== "" && !exact && repositoryNameValid(query) && !query.includes("/");
8491
+ const pick = (repository) => {
8492
+ if (!repository.private) {
8493
+ setConfirming(repository);
8494
+ return;
8495
+ }
8496
+ onChoose(repository);
8497
+ };
8498
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8499
+ className: MnemonSettingsCard_module_css_default.syncPicker,
8500
+ children: [
8501
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8502
+ className: MnemonSettingsCard_module_css_default.fieldGrid,
8503
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", { children: [t("config.syncRepositoryLabel"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
8504
+ type: "search",
8505
+ value: query,
8506
+ "aria-label": t("config.syncRepositorySearch"),
8507
+ placeholder: t("config.syncRepositorySearch"),
8508
+ disabled,
8509
+ autoComplete: "off",
8510
+ spellCheck: false,
8511
+ autoCapitalize: "none",
8512
+ autoCorrect: "off",
8513
+ onChange: (event) => setQuery(event.target.value)
8514
+ })] })
8515
+ }),
8516
+ loading && repositories === null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8517
+ className: MnemonSettingsCard_module_css_default.editorNote,
8518
+ role: "status",
8519
+ children: t("config.syncRepositoriesLoading")
8520
+ }),
8521
+ failed !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8522
+ className: MnemonSettingsCard_module_css_default.syncWarning,
8523
+ role: "alert",
8524
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: failed.text }), failed.expired ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
8525
+ variant: "ghost",
8526
+ size: "sm",
8527
+ onClick: onSignInAgain,
8528
+ children: t("config.syncGitHubSignInAgain")
8529
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
8530
+ variant: "ghost",
8531
+ size: "sm",
8532
+ disabled: loading,
8533
+ onClick: () => void load(),
8534
+ children: t("config.syncRepositoriesRetry")
8535
+ })]
8536
+ }),
8537
+ repositories !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("ul", {
8538
+ className: MnemonSettingsCard_module_css_default.syncRepositoryList,
8539
+ "aria-label": t("config.syncRepositoryLabel"),
8540
+ children: [
8541
+ creatable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
8542
+ type: "button",
8543
+ className: MnemonSettingsCard_module_css_default.syncRepositoryOption,
8544
+ disabled,
8545
+ onClick: () => void onCreate(query.trim()),
8546
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: creating ? t("config.syncRepositoryCreating") : t("config.syncRepositoryCreate", { name: (login === void 0 ? "" : login + "/") + query.trim() }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
8547
+ tone: "quiet",
8548
+ children: t("config.syncRepositoryPrivate")
8549
+ })]
8550
+ }) }),
8551
+ matches.slice(0, SHOWN_REPOSITORIES).map((repository) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
8552
+ type: "button",
8553
+ className: MnemonSettingsCard_module_css_default.syncRepositoryOption,
8554
+ disabled: disabled || !repository.push,
8555
+ "aria-current": repository.url === current ? "true" : void 0,
8556
+ onClick: () => pick(repository),
7653
8557
  children: [
7654
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("header", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("config.syncAutoBackup") }) }),
7655
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncAutoBackupHint") }),
7656
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7657
- className: MnemonSettingsCard_module_css_default.syncField,
7658
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
7659
- htmlFor: "mnemon-sync-auto-backup",
7660
- children: t("config.syncAutoBackup")
7661
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
7662
- id: "mnemon-sync-auto-backup",
7663
- value: String(draft.autoBackupMinutes),
7664
- disabled: !editable || autoBackupSaving,
7665
- onChange: (event) => void setAutoBackup(Number(event.target.value)),
7666
- children: AUTO_BACKUP_CHOICES.map((minutes) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
7667
- value: String(minutes),
7668
- children: intervalLabel(t, minutes)
7669
- }, minutes))
7670
- })]
8558
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: repository.fullName }),
8559
+ repository.url === current && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
8560
+ tone: "outline",
8561
+ children: t("config.syncRepositoryCurrent")
7671
8562
  }),
7672
- autoBackup !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: autoBackup.available ? autoBackup.nextAt === void 0 ? "" : t("config.syncAutoBackupNext", { at: stamp(autoBackup.nextAt) }) : t("config.syncAutoBackupNever") }),
7673
- autoBackup?.lastAt !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncAutoBackupLast", { at: stamp(autoBackup.lastAt) }) }),
7674
- autoBackup?.lastError !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", {
7675
- className: MnemonSettingsCard_module_css_default.error,
7676
- children: t("config.syncAutoBackupFailed", { error: autoBackup.lastError })
8563
+ !repository.push && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
8564
+ tone: "quiet",
8565
+ children: t("config.syncRepositoryNoPush")
8566
+ }),
8567
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
8568
+ tone: "quiet",
8569
+ children: repository.private ? t("config.syncRepositoryPrivate") : t("config.syncRepositoryPublic")
7677
8570
  })
7678
8571
  ]
8572
+ }) }, repository.fullName)),
8573
+ matches.length === 0 && !creatable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", {
8574
+ className: MnemonSettingsCard_module_css_default.editorNote,
8575
+ children: needle === "" ? t("config.syncRepositoriesNone") : t("config.syncRepositoriesEmpty")
7679
8576
  }),
7680
- github !== null && github.available && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7681
- className: MnemonSettingsCard_module_css_default.syncBlock,
7682
- children: [
7683
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("config.syncRepositories") }), repositories !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7684
- variant: "ghost",
7685
- size: "sm",
7686
- disabled: !editable || busy !== null,
7687
- onClick: () => void loadRepositories(),
7688
- children: busy === "repos" ? t("config.syncRepositoriesLoading") : t("config.syncRepositoriesLoad")
7689
- })] }),
7690
- !signedIn && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncRepositoriesSignIn") }),
7691
- signedIn && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
7692
- repositories === null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: busy === "repos" ? t("config.syncRepositoriesLoading") : t("config.syncRepositoriesHint") }),
7693
- repositories !== null && repositories.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncRepositoriesEmpty") }),
7694
- repositories !== null && repositories.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7695
- className: MnemonSettingsCard_module_css_default.syncField,
7696
- children: [
7697
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
7698
- htmlFor: "mnemon-sync-repository",
7699
- children: t("config.syncRepositories")
7700
- }),
7701
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
7702
- id: "mnemon-sync-repository",
7703
- value: selected,
7704
- disabled: !editable || busy !== null,
7705
- onChange: (event) => {
7706
- const repository = repositories.find((candidate) => candidate.url === event.target.value);
7707
- if (repository !== void 0) choose(repository);
7708
- },
7709
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
7710
- value: "",
7711
- children: t("config.syncRepositoriesChoose")
7712
- }), repositories.map((repository) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
7713
- value: repository.url,
7714
- disabled: !repository.push,
7715
- children: repository.fullName + (repository.private ? " · " + t("config.syncRepositoriesPrivate") : "") + (repository.push ? "" : " · " + t("config.syncRepositoriesNoPush"))
7716
- }, repository.fullName))]
7717
- }),
7718
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncRepoUrlHint") })
7719
- ]
7720
- }),
7721
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7722
- className: MnemonSettingsCard_module_css_default.syncField,
7723
- children: [
7724
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
7725
- htmlFor: "mnemon-sync-repository-name",
7726
- children: t("config.syncRepositoryName")
7727
- }),
7728
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
7729
- id: "mnemon-sync-repository-name",
7730
- type: "text",
7731
- value: repositoryName,
7732
- placeholder: "mnemon-memory",
7733
- disabled: !editable || busy !== null,
7734
- autoComplete: "off",
7735
- spellCheck: false,
7736
- autoCapitalize: "none",
7737
- autoCorrect: "off",
7738
- onChange: (event) => setRepositoryName(event.target.value)
7739
- }),
7740
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
7741
- className: MnemonSettingsCard_module_css_default.syncCheck,
7742
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
7743
- type: "checkbox",
7744
- checked: repositoryPrivate,
7745
- disabled: !editable || busy !== null,
7746
- onChange: (event) => setRepositoryPrivate(event.target.checked)
7747
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("config.syncRepositoryPrivate") })]
7748
- })
7749
- ]
8577
+ matches.length > SHOWN_REPOSITORIES && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", {
8578
+ className: MnemonSettingsCard_module_css_default.editorNote,
8579
+ children: t("config.syncRepositoriesMore", { count: matches.length - SHOWN_REPOSITORIES })
8580
+ })
8581
+ ]
8582
+ }),
8583
+ needle !== "" && !creatable && !exact && !repositoryNameValid(query) && !query.includes("/") && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8584
+ className: MnemonSettingsCard_module_css_default.error,
8585
+ children: t("config.syncRepositoryNameInvalid")
8586
+ }),
8587
+ confirming !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SyncConfirmDialog, {
8588
+ title: t("config.syncPublicTitle"),
8589
+ body: t("config.syncPublicBody", { name: confirming.fullName }),
8590
+ confirm: t("config.syncPublicConfirm"),
8591
+ t,
8592
+ onClose: () => setConfirming(null),
8593
+ onConfirm: () => {
8594
+ const repository = confirming;
8595
+ setConfirming(null);
8596
+ onChoose(repository);
8597
+ }
8598
+ })
8599
+ ]
8600
+ });
8601
+ }
8602
+ /**
8603
+ * What this computer is called, where on the branch the memory goes and whose name
8604
+ * its commits carry. Each field shows the value in use; the computer's name is the
8605
+ * host name or a typed one, and the author an explicit choice between the channel's
8606
+ * own identity, this computer's Git identity, and a typed one.
8607
+ */
8608
+ function AdvancedSettings({ client, status, disabled, t, onSaved }) {
8609
+ const [open, setOpen] = (0, react.useState)(false);
8610
+ const config = status.config;
8611
+ const savedMode = authorModeOf(config.authorName, config.authorEmail);
8612
+ const [branch, setBranch] = (0, react.useState)(config.branch);
8613
+ const [subdir, setSubdir] = (0, react.useState)(config.subdir);
8614
+ const [mode, setMode] = (0, react.useState)(savedMode);
8615
+ const [name, setName] = (0, react.useState)(savedMode === "custom" ? config.authorName : "");
8616
+ const [email, setEmail] = (0, react.useState)(savedMode === "custom" ? config.authorEmail : "");
8617
+ const savedLabel = status.machine?.label ?? "";
8618
+ const savedSource = status.machineLabel?.source ?? "hostname";
8619
+ const hostname = status.machineLabel?.hostname ?? savedLabel;
8620
+ const [nameSource, setNameSource] = (0, react.useState)(savedSource);
8621
+ const [machineName, setMachineName] = (0, react.useState)(savedSource === "custom" ? savedLabel : "");
8622
+ const [busy, setBusy] = (0, react.useState)(false);
8623
+ const [feedback, setFeedback] = (0, react.useState)(null);
8624
+ const radio = (0, react.useId)();
8625
+ const nameRadio = (0, react.useId)();
8626
+ (0, react.useEffect)(() => {
8627
+ setBranch(config.branch);
8628
+ setSubdir(config.subdir);
8629
+ const next = authorModeOf(config.authorName, config.authorEmail);
8630
+ setMode(next);
8631
+ setName(next === "custom" ? config.authorName : "");
8632
+ setEmail(next === "custom" ? config.authorEmail : "");
8633
+ }, [
8634
+ config.branch,
8635
+ config.subdir,
8636
+ config.authorName,
8637
+ config.authorEmail
8638
+ ]);
8639
+ (0, react.useEffect)(() => {
8640
+ setNameSource(savedSource);
8641
+ setMachineName(savedSource === "custom" ? savedLabel : "");
8642
+ }, [savedSource, savedLabel]);
8643
+ const author = mode === "default" ? {
8644
+ authorName: MNEMON_SYNC_DEFAULT_AUTHOR_NAME,
8645
+ authorEmail: MNEMON_SYNC_DEFAULT_AUTHOR_EMAIL
8646
+ } : mode === "machine" ? {
8647
+ authorName: "",
8648
+ authorEmail: ""
8649
+ } : {
8650
+ authorName: name.trim(),
8651
+ authorEmail: email.trim()
8652
+ };
8653
+ const branchOk = branchValid(branch);
8654
+ const subdirOk = directoryValid(subdir);
8655
+ const authorChanged = author.authorName !== config.authorName || author.authorEmail !== config.authorEmail;
8656
+ const customOk = mode !== "custom" || !authorChanged || name.trim() !== "" && emailValid(email);
8657
+ const normalizedSubdir = subdir.trim().replaceAll("\\", "/").split("/").filter((part) => part !== "").join("/") + "/";
8658
+ const moved = branch.trim() !== config.branch || normalizedSubdir !== config.subdir;
8659
+ const nameOk = nameSource === "hostname" || machineNameValid(machineName);
8660
+ const renamed = nameSource !== savedSource || nameSource === "custom" && machineName.trim() !== savedLabel;
8661
+ const ready = (moved || renamed || author.authorName !== config.authorName || author.authorEmail !== config.authorEmail) && branchOk && subdirOk && customOk && nameOk;
8662
+ const shownName = nameSource === "hostname" ? hostname : machineName.trim();
8663
+ const save = async () => {
8664
+ if (!ready || busy) return;
8665
+ setBusy(true);
8666
+ setFeedback(null);
8667
+ try {
8668
+ await client.configureSync({
8669
+ branch: branch.trim(),
8670
+ subdir: subdir.trim(),
8671
+ ...author,
8672
+ ...renamed ? { machineLabel: nameSource === "hostname" ? null : machineName.trim() } : {}
8673
+ });
8674
+ setFeedback({
8675
+ tone: "success",
8676
+ text: t("config.syncAdvancedSaved")
8677
+ });
8678
+ onSaved();
8679
+ } catch (reason) {
8680
+ setFeedback({
8681
+ tone: "error",
8682
+ text: message(reason)
8683
+ });
8684
+ } finally {
8685
+ setBusy(false);
8686
+ }
8687
+ };
8688
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8689
+ className: MnemonSettingsCard_module_css_default.syncAdvanced,
8690
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
8691
+ type: "button",
8692
+ className: MnemonSettingsCard_module_css_default.syncDisclosure,
8693
+ "aria-expanded": open,
8694
+ onClick: () => setOpen((value) => !value),
8695
+ children: [
8696
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("config.syncAdvanced") }),
8697
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: [
8698
+ savedLabel,
8699
+ config.branch,
8700
+ config.subdir,
8701
+ savedMode === "default" ? t("config.syncAuthorDefault") : savedMode === "machine" ? t("config.syncAuthorMachine") : config.authorName || config.authorEmail || t("config.syncAuthorCustom")
8702
+ ].filter((part) => part !== "").join(" · ") }),
8703
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineRegular, {
8704
+ className: MnemonSettingsCard_module_css_default.providerChevron,
8705
+ size: 14
8706
+ })
8707
+ ]
8708
+ }), open && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8709
+ className: MnemonSettingsCard_module_css_default.editor,
8710
+ children: [
8711
+ status.machine !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8712
+ className: MnemonSettingsCard_module_css_default.syncChoice,
8713
+ children: [
8714
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8715
+ className: MnemonSettingsCard_module_css_default.syncFieldLabel,
8716
+ id: nameRadio + "-label",
8717
+ children: t("config.syncMachineName")
8718
+ }),
8719
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8720
+ className: MnemonSettingsCard_module_css_default.inlineChoices,
8721
+ role: "radiogroup",
8722
+ "aria-labelledby": nameRadio + "-label",
8723
+ children: ["hostname", "custom"].map((value) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
8724
+ type: "radio",
8725
+ name: nameRadio,
8726
+ value,
8727
+ checked: nameSource === value,
8728
+ disabled: disabled || busy,
8729
+ onChange: () => setNameSource(value)
8730
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: value === "hostname" ? t("config.syncMachineHostname") : t("config.syncMachineCustom") })] }, value))
8731
+ }),
8732
+ nameSource === "custom" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8733
+ className: MnemonSettingsCard_module_css_default.fieldGrid,
8734
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", { children: [
8735
+ t("config.syncMachineNameLabel"),
8736
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
8737
+ type: "text",
8738
+ value: machineName,
8739
+ "aria-label": t("config.syncMachineName"),
8740
+ disabled: disabled || busy,
8741
+ "aria-invalid": machineName.trim() === "" || nameOk ? void 0 : true,
8742
+ autoComplete: "off",
8743
+ spellCheck: false,
8744
+ onChange: (event) => setMachineName(event.target.value)
7750
8745
  }),
7751
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7752
- className: MnemonSettingsCard_module_css_default.syncFormActions,
7753
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7754
- variant: "outline",
7755
- size: "sm",
7756
- disabled: !editable || busy !== null || repositoryName.trim() === "",
7757
- onClick: () => void createRepository(),
7758
- children: busy === "create" ? t("config.syncRepositoryCreating") : t("config.syncRepositoryCreate")
7759
- })
8746
+ machineName.trim() !== "" && !nameOk && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", {
8747
+ className: MnemonSettingsCard_module_css_default.error,
8748
+ children: t("config.syncMachineNameInvalid")
7760
8749
  })
7761
8750
  ] })
7762
- ]
7763
- }),
7764
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7765
- className: MnemonSettingsCard_module_css_default.syncField,
7766
- children: [
7767
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
7768
- htmlFor: "mnemon-sync-repo",
7769
- children: t("config.syncRepoUrl")
7770
- }),
7771
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
7772
- id: "mnemon-sync-repo",
7773
- type: "text",
7774
- value: draft.repoUrl,
7775
- placeholder: "https://github.com/owner/repository.git",
7776
- disabled: !editable,
7777
- autoComplete: "off",
7778
- spellCheck: false,
7779
- autoCapitalize: "none",
7780
- autoCorrect: "off",
7781
- onChange: (event) => setDraft((current) => ({
7782
- ...current,
7783
- repoUrl: event.target.value
7784
- }))
7785
- }),
7786
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncRepoUrlHint") })
7787
- ]
7788
- }),
7789
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7790
- className: MnemonSettingsCard_module_css_default.syncField,
7791
- children: [
7792
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
7793
- htmlFor: "mnemon-sync-branch",
7794
- children: t("config.syncBranch")
7795
- }),
7796
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
7797
- id: "mnemon-sync-branch",
7798
- type: "text",
7799
- value: draft.branch,
7800
- placeholder: saved?.branch ?? "mnemon-sync",
7801
- disabled: !editable,
7802
- autoComplete: "off",
7803
- spellCheck: false,
7804
- autoCapitalize: "none",
7805
- autoCorrect: "off",
7806
- onChange: (event) => setDraft((current) => ({
7807
- ...current,
7808
- branch: event.target.value
7809
- }))
7810
- }),
7811
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncBranchHint", { branch: saved?.branch ?? "mnemon-sync" }) })
7812
- ]
7813
- }),
7814
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7815
- className: MnemonSettingsCard_module_css_default.syncField,
7816
- children: [
7817
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
7818
- htmlFor: "mnemon-sync-subdir",
7819
- children: t("config.syncSubdir")
7820
- }),
7821
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
7822
- id: "mnemon-sync-subdir",
7823
- type: "text",
7824
- value: draft.subdir,
7825
- placeholder: saved?.subdir ?? "mnemon/",
7826
- disabled: !editable,
7827
- autoComplete: "off",
7828
- spellCheck: false,
7829
- autoCapitalize: "none",
7830
- autoCorrect: "off",
7831
- onChange: (event) => setDraft((current) => ({
7832
- ...current,
7833
- subdir: event.target.value
7834
- }))
7835
- }),
7836
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncSubdirHint", { subdir: saved?.subdir ?? "mnemon/" }) })
7837
- ]
7838
- }),
7839
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7840
- className: MnemonSettingsCard_module_css_default.syncField,
7841
- children: [
7842
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
7843
- htmlFor: "mnemon-sync-token",
7844
- children: t("config.syncToken")
7845
- }),
7846
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
7847
- id: "mnemon-sync-token",
7848
- type: "password",
7849
- value: draft.token,
7850
- disabled: !editable || draft.clearToken,
7851
- placeholder: saved?.hasToken ? t("config.syncTokenSaved") : t("config.syncTokenNone"),
7852
- autoComplete: "new-password",
7853
- spellCheck: false,
7854
- onChange: (event) => setDraft((current) => ({
7855
- ...current,
7856
- token: event.target.value
7857
- }))
7858
- }),
7859
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncTokenOptional") }),
7860
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncTokenHint", {
7861
- path: status?.configPath ?? "",
7862
- env: "MNEMON_SYNC_GIT_TOKEN"
7863
- }) }),
7864
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncTokenKeep") }),
7865
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
7866
- className: MnemonSettingsCard_module_css_default.syncCheck,
7867
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
7868
- type: "checkbox",
7869
- checked: draft.clearToken,
7870
- disabled: !editable,
7871
- onChange: (event) => setDraft((current) => ({
7872
- ...current,
7873
- clearToken: event.target.checked,
7874
- token: ""
7875
- }))
7876
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("config.syncTokenClear") })]
7877
- })
7878
- ]
7879
- }),
7880
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7881
- className: MnemonSettingsCard_module_css_default.syncField,
7882
- children: [
7883
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
7884
- htmlFor: "mnemon-sync-author-name",
7885
- children: t("config.syncAuthorName")
7886
- }),
7887
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
7888
- id: "mnemon-sync-author-name",
7889
- type: "text",
7890
- value: draft.authorName,
7891
- placeholder: t("config.syncAuthorOptional"),
7892
- disabled: !editable,
7893
- autoComplete: "off",
7894
- spellCheck: false,
7895
- onChange: (event) => setDraft((current) => ({
7896
- ...current,
7897
- authorName: event.target.value
7898
- }))
7899
- }),
7900
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncAuthorHint") })
7901
- ]
7902
- }),
7903
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7904
- className: MnemonSettingsCard_module_css_default.syncField,
7905
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
7906
- htmlFor: "mnemon-sync-author-email",
7907
- children: t("config.syncAuthorEmail")
7908
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
7909
- id: "mnemon-sync-author-email",
8751
+ }),
8752
+ (nameSource === "hostname" || nameOk) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8753
+ className: MnemonSettingsCard_module_css_default.editorNote,
8754
+ children: nameSource === "hostname" ? t("config.syncMachineHostnameNote", { name: shownName }) : t("config.syncMachineCustomNote", { name: shownName })
8755
+ })
8756
+ ]
8757
+ }),
8758
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8759
+ className: MnemonSettingsCard_module_css_default.fieldGrid,
8760
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", { children: [
8761
+ t("config.syncBranch"),
8762
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
7910
8763
  type: "text",
7911
- value: draft.authorEmail,
7912
- placeholder: t("config.syncAuthorOptional"),
7913
- disabled: !editable,
8764
+ value: branch,
8765
+ "aria-label": t("config.syncBranch"),
8766
+ disabled: disabled || busy,
8767
+ "aria-invalid": branchOk ? void 0 : true,
7914
8768
  autoComplete: "off",
7915
8769
  spellCheck: false,
7916
- onChange: (event) => setDraft((d) => ({
7917
- ...d,
7918
- authorEmail: event.target.value
7919
- }))
7920
- })]
7921
- }),
7922
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7923
- className: MnemonSettingsCard_module_css_default.syncFormActions,
7924
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7925
- variant: "primary",
7926
- size: "sm",
7927
- disabled: !editable || busy !== null || !configured(draft),
7928
- onClick: () => void save(),
7929
- children: busy === "save" ? t("config.syncSave") + "…" : t("config.syncSave")
8770
+ autoCapitalize: "none",
8771
+ autoCorrect: "off",
8772
+ onChange: (event) => setBranch(event.target.value)
8773
+ }),
8774
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: branchOk ? t("config.syncDefaultValue", { value: "mnemon-sync" }) : t("config.syncBranchInvalid") })
8775
+ ] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", { children: [
8776
+ t("config.syncSubdir"),
8777
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
8778
+ type: "text",
8779
+ value: subdir,
8780
+ "aria-label": t("config.syncSubdir"),
8781
+ disabled: disabled || busy,
8782
+ "aria-invalid": subdirOk ? void 0 : true,
8783
+ autoComplete: "off",
8784
+ spellCheck: false,
8785
+ autoCapitalize: "none",
8786
+ autoCorrect: "off",
8787
+ onChange: (event) => setSubdir(event.target.value)
8788
+ }),
8789
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: subdirOk ? t("config.syncDefaultValue", { value: "mnemon/" }) : t("config.syncSubdirInvalid") })
8790
+ ] })]
8791
+ }),
8792
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8793
+ className: MnemonSettingsCard_module_css_default.syncChoice,
8794
+ children: [
8795
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8796
+ className: MnemonSettingsCard_module_css_default.syncFieldLabel,
8797
+ id: radio + "-label",
8798
+ children: t("config.syncAuthor")
8799
+ }),
8800
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8801
+ className: MnemonSettingsCard_module_css_default.inlineChoices,
8802
+ role: "radiogroup",
8803
+ "aria-labelledby": radio + "-label",
8804
+ children: [
8805
+ "default",
8806
+ "machine",
8807
+ "custom"
8808
+ ].map((value) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
8809
+ type: "radio",
8810
+ name: radio,
8811
+ value,
8812
+ checked: mode === value,
8813
+ disabled: disabled || busy,
8814
+ onChange: () => setMode(value)
8815
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: value === "default" ? t("config.syncAuthorDefault") : value === "machine" ? t("config.syncAuthorMachine") : t("config.syncAuthorCustom") })] }, value))
8816
+ }),
8817
+ mode === "default" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8818
+ className: MnemonSettingsCard_module_css_default.editorNote,
8819
+ children: t("config.syncAuthorDefaultNote", { identity: DEFAULT_AUTHOR })
8820
+ }),
8821
+ mode === "machine" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8822
+ className: MnemonSettingsCard_module_css_default.editorNote,
8823
+ children: t("config.syncAuthorMachineNote")
8824
+ }),
8825
+ mode === "custom" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8826
+ className: MnemonSettingsCard_module_css_default.fieldGrid,
8827
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", { children: [t("config.syncAuthorName"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
8828
+ type: "text",
8829
+ value: name,
8830
+ "aria-label": t("config.syncAuthorName"),
8831
+ disabled: disabled || busy,
8832
+ autoComplete: "off",
8833
+ spellCheck: false,
8834
+ onChange: (event) => setName(event.target.value)
8835
+ })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", { children: [
8836
+ t("config.syncAuthorEmail"),
8837
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
8838
+ type: "email",
8839
+ value: email,
8840
+ "aria-label": t("config.syncAuthorEmail"),
8841
+ disabled: disabled || busy,
8842
+ "aria-invalid": email.trim() === "" || emailValid(email) ? void 0 : true,
8843
+ autoComplete: "off",
8844
+ spellCheck: false,
8845
+ onChange: (event) => setEmail(event.target.value)
8846
+ }),
8847
+ email.trim() !== "" && !emailValid(email) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", {
8848
+ className: MnemonSettingsCard_module_css_default.error,
8849
+ children: t("config.syncAuthorEmailInvalid")
8850
+ })
8851
+ ] })]
7930
8852
  })
7931
- })
7932
- ]
7933
- }),
7934
- pending !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7935
- className: MnemonSettingsCard_module_css_default.syncBar,
7936
- role: "status",
7937
- children: [
7938
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [
7939
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("config.syncPreviewReady", {
7940
- commit: pending.commit.slice(0, 8),
7941
- components: pending.manifest.components.length,
7942
- size: humanBytes(pending.archiveBytes)
7943
- }) }),
7944
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncPreviewComponents", {
7945
- changed,
7946
- total: pending.components.length
7947
- }) }),
7948
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncPreviewFiles", {
7949
- added: pending.files.added,
7950
- removed: pending.files.removed,
7951
- changed: pending.files.changed
7952
- }) })
7953
- ] }),
7954
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7955
- variant: "ghost",
7956
- size: "sm",
7957
- disabled: busy !== null,
7958
- onClick: () => setPending(null),
7959
- children: t("common.cancel")
7960
- }),
7961
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
8853
+ ]
8854
+ }),
8855
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8856
+ className: MnemonSettingsCard_module_css_default.memoryConfigFooter,
8857
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8858
+ className: MnemonSettingsCard_module_css_default.configFeedback,
8859
+ "aria-live": "polite",
8860
+ children: feedback !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FeedbackLine, { value: feedback }) : moved && branchOk && subdirOk ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8861
+ className: MnemonSettingsCard_module_css_default.editorNote,
8862
+ children: t("config.syncAdvancedNote")
8863
+ }) : renamed && nameOk ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8864
+ className: MnemonSettingsCard_module_css_default.editorNote,
8865
+ children: t("config.syncMachineRenameNote")
8866
+ }) : null
8867
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7962
8868
  variant: "primary",
7963
8869
  size: "sm",
7964
- disabled: busy !== null || disabled,
7965
- onClick: () => void pull(),
7966
- children: busy === "pull" ? t("config.syncPulling") : t("config.syncPull")
7967
- })
7968
- ]
7969
- }),
7970
- dialog && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MnemonDialog, {
7971
- title: t("config.syncBackups"),
7972
- closeLabel: t("common.close"),
7973
- wide: true,
7974
- busy: busy !== null,
7975
- onClose: () => setDialog(false),
7976
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7977
- className: MnemonSettingsCard_module_css_default.syncDialogBody,
7978
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7979
- className: MnemonSettingsCard_module_css_default.syncBackups,
7980
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("config.syncBackupsTitle", { branch: backups?.branch ?? status?.config.branch ?? "" }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7981
- className: MnemonSettingsCard_module_css_default.rowActions,
7982
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7983
- variant: "ghost",
7984
- size: "sm",
7985
- disabled: busy !== null,
7986
- onClick: () => void loadHistory(),
7987
- children: busy === "backups" ? t("config.syncBackupsLoading") : t("review.refresh")
7988
- })
7989
- })] }), backups === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncBackupsLoading") }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncBackupsHint", { subdir: backups.subdir }) }), backups.commits.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncBackupsEmpty") }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7990
- className: MnemonSettingsCard_module_css_default.syncBackupList,
7991
- children: [backups.commits.map((commit) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7992
- className: MnemonSettingsCard_module_css_default.syncBackupEntry,
7993
- children: [
7994
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7995
- className: MnemonSettingsCard_module_css_default.reviewTitle,
7996
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: commit.message }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
7997
- tone: "quiet",
7998
- children: commit.commit.slice(0, 8)
7999
- })]
8000
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8001
- className: MnemonSettingsCard_module_css_default.rowActions,
8002
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
8003
- variant: "ghost",
8004
- size: "sm",
8005
- disabled: busy !== null,
8006
- onClick: () => setOpenCommit(openCommit === commit.commit ? null : commit.commit),
8007
- children: openCommit === commit.commit ? t("review.collapse") : t("review.expand")
8008
- })
8009
- })] }),
8010
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncBackupMeta", {
8011
- machine: ownerName(t, commit.machine),
8012
- time: stamp(commit.committedAt)
8013
- }) }),
8014
- commit.pushedAt !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncBackupPushedAt", { time: stamp(commit.pushedAt) }) }),
8015
- openCommit === commit.commit && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8016
- className: MnemonSettingsCard_module_css_default.syncBackupComponents,
8017
- children: commit.components.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncBackupNoComponents") }) : commit.components.map((component) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncBackupComponent", {
8018
- component: component.component,
8019
- items: component.items,
8020
- files: component.files,
8021
- size: humanBytes(component.bytes)
8022
- }) }, component.component))
8023
- })
8024
- ]
8025
- }, commit.commit)), backups.truncated && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8026
- className: MnemonSettingsCard_module_css_default.rowActions,
8027
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
8028
- variant: "outline",
8029
- size: "sm",
8030
- disabled: busy !== null,
8031
- onClick: () => void loadMore(),
8032
- children: busy === "more" ? t("config.syncBackupsLoading") : t("config.syncBackupsMore")
8033
- })
8034
- })]
8035
- })] })]
8036
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8037
- className: MnemonSettingsCard_module_css_default.syncDiff,
8038
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("config.syncDiffTitle", {
8039
- commit: difference?.commit.slice(0, 8) ?? "",
8040
- shared: difference?.shared ?? 0
8041
- }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8042
- className: MnemonSettingsCard_module_css_default.rowActions,
8043
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
8044
- variant: "ghost",
8045
- size: "sm",
8046
- disabled: busy !== null,
8047
- onClick: () => void loadDifference(),
8048
- children: busy === "diff" ? t("config.syncPreviewing") : t("review.refresh")
8049
- })
8050
- })] }), difference === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncBackupsLoading") }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
8051
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncDiffSides", {
8052
- local: difference.local.entries,
8053
- remote: difference.remote.entries,
8054
- machine: ownerName(t, difference.remote.machine)
8055
- }) }),
8056
- difference.truncated && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncDiffTruncated") }),
8057
- difference.remoteTombstones.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncDiffTombstones", { count: difference.remoteTombstones.length }) }),
8058
- conflicts.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8059
- className: MnemonSettingsCard_module_css_default.syncDialogNote,
8060
- children: additions === 0 ? t("config.syncDiffNothing") : t("config.syncDiffClear")
8061
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8062
- className: MnemonSettingsCard_module_css_default.syncDialogNote,
8063
- children: t("config.syncDiffConflicts", { count: conflicts.length })
8064
- }),
8065
- conflicts.length === 0 && addable > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8066
- className: MnemonSettingsCard_module_css_default.syncDialogNote,
8067
- children: t("config.syncDiffAdditions", { count: addable })
8068
- }),
8069
- conflicts.length === 0 && heldBack > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8070
- className: MnemonSettingsCard_module_css_default.syncDialogNote,
8071
- children: t("config.syncDiffHeldBack", { count: heldBack })
8072
- }),
8073
- conflicts.length === 0 && onlyHere > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8074
- className: MnemonSettingsCard_module_css_default.syncDialogNote,
8075
- children: t("config.syncDiffLocalOnlyNote", { count: onlyHere })
8076
- }),
8077
- conflicts.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8078
- className: MnemonSettingsCard_module_css_default.syncConflictList,
8079
- children: conflicts.map((conflict) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8080
- className: MnemonSettingsCard_module_css_default.syncConflict,
8081
- "data-target": conflict.target,
8082
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t(conflict.target === "user" ? "review.targetUser" : "review.targetMemory") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: conflict.local.importance + " · " + Math.round(conflict.similarity * 100) + "%" })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8083
- className: MnemonSettingsCard_module_css_default.syncConflictSides,
8084
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncDiffHere") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: clip(conflict.local.content, 400) })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("config.syncDiffThere") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: clip(conflict.remote.content, 400) })] })]
8085
- })]
8086
- }, conflict.target + "\0" + conflict.local.content))
8087
- }),
8088
- conflicts.length === 0 && (addable > 0 || heldBack > 0) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8089
- className: MnemonSettingsCard_module_css_default.rowActions,
8090
- children: [addable > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
8091
- variant: "primary",
8092
- size: "sm",
8093
- disabled: busy !== null || disabled,
8094
- onClick: () => void addRemote(),
8095
- children: busy === "add" ? t("config.syncDiffAdding") : t("config.syncDiffAdd")
8096
- }), heldBack > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
8097
- variant: "outline",
8098
- size: "sm",
8099
- disabled: busy !== null || disabled,
8100
- onClick: () => void addRemote(true),
8101
- children: busy === "revive" ? t("config.syncDiffReviving") : t("config.syncDiffRevive")
8102
- })]
8103
- }),
8104
- conflicts.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8105
- className: MnemonSettingsCard_module_css_default.syncPlan,
8106
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8107
- className: MnemonSettingsCard_module_css_default.syncDialogNote,
8108
- children: t("config.syncPlanWhere")
8109
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8110
- className: MnemonSettingsCard_module_css_default.rowActions,
8111
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
8112
- variant: "outline",
8113
- size: "sm",
8114
- onClick: goToReview,
8115
- children: t("config.syncPlanGo")
8116
- })
8117
- })]
8118
- })
8119
- ] })]
8120
- })]
8870
+ disabled: disabled || !ready || busy,
8871
+ onClick: () => void save(),
8872
+ children: busy ? t("config.syncSaving") : t("config.syncSave")
8873
+ }) })]
8121
8874
  })
8122
- }),
8123
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8124
- className: MnemonSettingsCard_module_css_default.syncFeedback,
8125
- "aria-live": "polite",
8126
- children: [
8127
- failed !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8128
- className: MnemonSettingsCard_module_css_default.error,
8129
- role: "alert",
8130
- children: t("config.syncFailed", { error: failed })
8131
- }),
8132
- notice !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8133
- className: MnemonSettingsCard_module_css_default.syncSuccess,
8134
- children: notice
8135
- }),
8136
- client === null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8137
- className: MnemonSettingsCard_module_css_default.readOnly,
8138
- children: t("config.syncUnavailable")
8139
- })
8140
- ]
8141
- })
8142
- ] })]
8875
+ ]
8876
+ })]
8143
8877
  });
8144
8878
  }
8145
8879
  //#endregion
@@ -12945,7 +13679,7 @@ window.__ModuleLoader__.load({
12945
13679
  })
12946
13680
  });
12947
13681
  }
12948
- function MnemonWorkspace({ connection, settingsScope, sessionId, workspaceId, workspaceSelection, surface = "sidebar", active = true, onClose, configuration, componentChanges, sourcePageDirectory = EMPTY_SOURCE_PAGE_DIRECTORY, renderSlot }) {
13682
+ function MnemonWorkspace({ connection, settingsScope, sessionId, workspaceId, workspaceSelection, surface = "sidebar", active = true, titleBar = false, onClose, configuration, componentChanges, sourcePageDirectory = EMPTY_SOURCE_PAGE_DIRECTORY, renderSlot }) {
12949
13683
  const t = useT();
12950
13684
  const locale = useLocale();
12951
13685
  const configurationSeat = configuration ?? NO_ACTION_SEAT;
@@ -13475,6 +14209,7 @@ window.__ModuleLoader__.load({
13475
14209
  children: [
13476
14210
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
13477
14211
  className: appearanceClass(MnemonView_module_css_default.masthead, MnemonSidebarView_module_css_default.masthead),
14212
+ "data-window-drag": titleBar || void 0,
13478
14213
  children: [
13479
14214
  onClose !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
13480
14215
  type: "button",
@@ -13643,7 +14378,7 @@ window.__ModuleLoader__.load({
13643
14378
  }
13644
14379
  //#endregion
13645
14380
  //#region \0dsh-mnemon-css:/home/runner/work/dsh-mnemon/dsh-mnemon/src/client/MnemonWorkspace.module.css.mjs
13646
- const css = ".NS3bAW_workspacePanel{box-sizing:border-box;background:var(--dsw-alias-bg-overlay,var(--dsw-alias-bg-base));pointer-events:auto;min-width:0;min-height:0;display:flex;position:fixed;overflow:hidden}.NS3bAW_workspacePanel>*{flex:auto;width:100%;min-width:0}.NS3bAW_betterSidebarSeat,.NS3bAW_nativeWorkspace{flex:auto;width:100%;min-width:0;height:100%;min-height:0;display:flex;overflow:hidden}.NS3bAW_betterSidebarSeat>*,.NS3bAW_nativeWorkspace>*{flex:auto;min-width:0}.NS3bAW_nativeWorkspace{z-index:2;position:relative}.NS3bAW_nativeWorkspace[data-dsh-mnemon-main-seat]{box-sizing:border-box;padding-block-start:var(--dsh-frame-top-clearance,0px)}.NS3bAW_nativeWorkspace[hidden]{display:none}.NS3bAW_entry{box-sizing:border-box;border-radius:var(--dsw-radius-md);width:calc(100% - 4px);min-height:36px;color:var(--dsw-alias-label-primary);font:inherit;text-align:left;white-space:nowrap;cursor:pointer;background:0 0;border:none;align-items:center;gap:8px;margin:0 2px;padding:7px 8px;line-height:22px;display:flex}.NS3bAW_entry:hover,.NS3bAW_entry[data-active]{background:var(--dsw-alias-interactive-bg-hover)}.NS3bAW_entry:focus-visible{outline:var(--dsw-focus-ring-width) solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:-2px}.NS3bAW_entryIcon{flex:none;justify-content:center;align-items:center;display:inline-flex}.NS3bAW_entryIcon svg{width:16px;height:16px;display:block}.NS3bAW_entryLabel{text-overflow:ellipsis;min-width:0;overflow:hidden}[data-sidebar-collapsed] .NS3bAW_entry{justify-content:center;width:36px;height:36px;min-height:36px;margin:0 auto 12px;padding:0}[data-sidebar-collapsed] .NS3bAW_entryIcon svg{width:18px;height:18px}[data-sidebar-collapsed] .NS3bAW_entryLabel{display:none}";
14381
+ const css = ".NS3bAW_workspacePanel{box-sizing:border-box;background:var(--dsw-alias-bg-overlay,var(--dsw-alias-bg-base));pointer-events:auto;min-width:0;min-height:0;display:flex;position:fixed;overflow:hidden}.NS3bAW_workspacePanel>*{flex:auto;width:100%;min-width:0}.NS3bAW_betterSidebarSeat,.NS3bAW_nativeWorkspace{flex:auto;width:100%;min-width:0;height:100%;min-height:0;display:flex;overflow:hidden}.NS3bAW_betterSidebarSeat>*,.NS3bAW_nativeWorkspace>*{flex:auto;min-width:0}.NS3bAW_nativeWorkspace{z-index:2;position:relative}.NS3bAW_nativeWorkspace[data-dsh-mnemon-main-seat]{box-sizing:border-box;padding-block-start:var(--dsh-frame-top-clearance,0px)}.NS3bAW_windowDragBand{height:var(--dsh-frame-top-clearance,0px);position:absolute;inset:0 0 auto}.NS3bAW_nativeWorkspace[hidden]{display:none}.NS3bAW_entry{box-sizing:border-box;border-radius:var(--dsw-radius-md);width:calc(100% - 4px);min-height:36px;color:var(--dsw-alias-label-primary);font:inherit;text-align:left;white-space:nowrap;cursor:pointer;background:0 0;border:none;align-items:center;gap:8px;margin:0 2px;padding:7px 8px;line-height:22px;display:flex}.NS3bAW_entry:hover,.NS3bAW_entry[data-active]{background:var(--dsw-alias-interactive-bg-hover)}.NS3bAW_entry:focus-visible{outline:var(--dsw-focus-ring-width) solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:-2px}.NS3bAW_entryIcon{flex:none;justify-content:center;align-items:center;display:inline-flex}.NS3bAW_entryIcon svg{width:16px;height:16px;display:block}.NS3bAW_entryLabel{text-overflow:ellipsis;min-width:0;overflow:hidden}[data-sidebar-collapsed] .NS3bAW_entry{justify-content:center;width:36px;height:36px;min-height:36px;margin:0 auto 12px;padding:0}[data-sidebar-collapsed] .NS3bAW_entryIcon svg{width:18px;height:18px}[data-sidebar-collapsed] .NS3bAW_entryLabel{display:none}";
13647
14382
  const tagId = "dsh-mnemon/src/client/MnemonWorkspace.module.css";
13648
14383
  if (typeof document !== "undefined") {
13649
14384
  let tag = document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]");
@@ -13660,6 +14395,7 @@ window.__ModuleLoader__.load({
13660
14395
  "entryIcon": "NS3bAW_entryIcon",
13661
14396
  "entryLabel": "NS3bAW_entryLabel",
13662
14397
  "nativeWorkspace": "NS3bAW_nativeWorkspace",
14398
+ "windowDragBand": "NS3bAW_windowDragBand",
13663
14399
  "workspacePanel": "NS3bAW_workspacePanel"
13664
14400
  };
13665
14401
  //#endregion
@@ -13881,6 +14617,7 @@ window.__ModuleLoader__.load({
13881
14617
  ...resolvedSelectedId === void 0 ? {} : { workspaceId: resolvedSelectedId },
13882
14618
  workspaceSelection: selection,
13883
14619
  active: props.active ?? true,
14620
+ titleBar: props.titleBar === true,
13884
14621
  t: props.t,
13885
14622
  locale: locale.active,
13886
14623
  sourcePageDirectory: props.sourcePageDirectory,
@@ -13995,7 +14732,8 @@ window.__ModuleLoader__.load({
13995
14732
  "aria-label": props.t("tab.label"),
13996
14733
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MnemonWorkspaceHost, {
13997
14734
  ...props,
13998
- active: state.open
14735
+ active: state.open,
14736
+ titleBar: true
13999
14737
  })
14000
14738
  }), nativeSidebar.target),
14001
14739
  !nativeSidebar?.available && bounds !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("section", {
@@ -14136,7 +14874,12 @@ window.__ModuleLoader__.load({
14136
14874
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
14137
14875
  ref: parent,
14138
14876
  className: MnemonWorkspace_module_css_default.nativeWorkspace,
14139
- "data-dsh-mnemon-main-seat": true
14877
+ "data-dsh-mnemon-main-seat": true,
14878
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
14879
+ className: MnemonWorkspace_module_css_default.windowDragBand,
14880
+ "data-window-drag": true,
14881
+ "aria-hidden": "true"
14882
+ })
14140
14883
  });
14141
14884
  }
14142
14885
  /** Use the published panel contract, with a fallback for replacement layouts. */