dsh-strata-sync 0.10.5 → 0.10.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/client.js +67 -48
- package/docs/README.zh-CN.md +2 -0
- package/docs/README.zh-TW.md +2 -0
- package/docs/VALIDATION.md +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -44,6 +44,8 @@ Reopen DSH if needed to load the settings page. If the plugin is disabled, enabl
|
|
|
44
44
|
|
|
45
45
|
Open **Settings → dsh-strata-sync**:
|
|
46
46
|
|
|
47
|
+
The main flow appears first: **Check differences → Review changes → Back up and sync**. **Sync preferences** and the optional **Dynamic summary target** are collapsed below it; expand them to adjust options or edit the supplemental prompt.
|
|
48
|
+
|
|
47
49
|
1. Select your Strata provider and click **Save preferences**.
|
|
48
50
|
2. Click **Check differences** to inspect the loaded model and proposed changes.
|
|
49
51
|
3. While DSH is idle, click **Back up and sync**.
|
package/dist/client.js
CHANGED
|
@@ -151,10 +151,6 @@ window.__ModuleLoader__.load({
|
|
|
151
151
|
"zh-Hant": "本次預覽低於 256 tokens 的最低目標,將保留原生摘要提示詞。",
|
|
152
152
|
"zh-Hans": "本次预览低于 256 tokens 的最低目标,将保留原生摘要提示词。"
|
|
153
153
|
},
|
|
154
|
-
"Summary guidance is off. No extra sentence is added to the native prompt.": {
|
|
155
|
-
"zh-Hant": "摘要提示補充已關閉,不會在原生提示詞中加上額外句子。",
|
|
156
|
-
"zh-Hans": "摘要提示补充已关闭,不会在原生提示词中添加额外句子。"
|
|
157
|
-
},
|
|
158
154
|
"Save preferences to apply these controls to subsequent summary requests; other model and compaction settings stay unchanged.": {
|
|
159
155
|
"zh-Hant": "儲存偏好後,這些控制項會套用至後續摘要請求;其他模型與壓縮設定保持不變。",
|
|
160
156
|
"zh-Hans": "保存偏好后,这些控制项将应用于后续摘要请求;其他模型与压缩设置保持不变。"
|
|
@@ -369,6 +365,17 @@ window.__ModuleLoader__.load({
|
|
|
369
365
|
}
|
|
370
366
|
};
|
|
371
367
|
Object.assign(translations, {
|
|
368
|
+
'Sync the model and context budgets from Strata Server to DSH.': {'zh-Hant':'將 Strata Server 的模型與上下文預算同步至 DSH。','zh-Hans':'将 Strata Server 的模型与上下文预算同步到 DSH。'},
|
|
369
|
+
'Start here': {'zh-Hant':'從這裡開始','zh-Hans':'从这里开始'},
|
|
370
|
+
'First, check differences to read the loaded model and preview the changes.': {'zh-Hant':'先點「檢查差異」,讀取目前載入的模型並預覽變更。','zh-Hans':'先点击“检查差异”,读取当前加载的模型并预览更改。'},
|
|
371
|
+
'Review changes': {'zh-Hant':'預覽變更','zh-Hans':'预览更改'},
|
|
372
|
+
'Review the changes below, then back up and sync.': {'zh-Hant':'確認下方變更後,點「備份並同步」。','zh-Hans':'确认下方更改后,点击“备份并同步”。'},
|
|
373
|
+
'Check differences before syncing.': {'zh-Hant':'檢查差異後即可同步。','zh-Hans':'检查差异后即可同步。'},
|
|
374
|
+
'Sync preferences': {'zh-Hant':'同步偏好','zh-Hans':'同步偏好'},
|
|
375
|
+
'Output limit, default model and startup sync': {'zh-Hant':'輸出上限、預設模型與啟動同步','zh-Hans':'输出上限、默认模型与启动同步'},
|
|
376
|
+
'Optional': {'zh-Hant':'選用','zh-Hans':'可选'},
|
|
377
|
+
'Enabled': {'zh-Hant':'已啟用','zh-Hans':'已启用'},
|
|
378
|
+
'Save option changes below before checking differences again.': {'zh-Hant':'請先在下方儲存選項變更,再重新檢查差異。','zh-Hans':'请先在下方保存选项更改,再重新检查差异。'},
|
|
372
379
|
'Follow Strata output limit': {'zh-Hant':'輸出上限跟隨 Strata','zh-Hans':'输出上限跟随 Strata'},
|
|
373
380
|
'Use the verified server default. If none is available, calculate 30% of context, up to 16,384 tokens.': {'zh-Hant':'採用已確認的伺服器預設值;無固定值時,以上下文的 30% 計算,最多 16,384 tokens。','zh-Hans':'采用已确认的服务器默认值;无固定值时,按上下文的 30% 计算,最多 16,384 tokens。'},
|
|
374
381
|
'Advanced settings': {'zh-Hant':'進階設定','zh-Hans':'高级设置'},
|
|
@@ -400,6 +407,7 @@ window.__ModuleLoader__.load({
|
|
|
400
407
|
thresholdRatio: 'Compaction ratio ceiling', retainRatio: 'Recent conversation retention ratio',
|
|
401
408
|
};
|
|
402
409
|
const css = `.strata-sync{max-width:880px;color:inherit;font:inherit;line-height:1.6}.strata-sync *{box-sizing:border-box}.strata-sync header{border-bottom:1px solid #8884;padding-bottom:16px;margin-bottom:20px}.strata-sync h2{margin:0;font-size:22px}.strata-sync .ss-muted{opacity:.72;font-size:13px}.strata-sync .ss-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:14px}.strata-sync label{display:flex;flex-direction:column;gap:5px;font-size:14px}.strata-sync select,.strata-sync input[type=number],.strata-sync textarea{padding:9px;border:1px solid #8886;border-radius:7px;background:transparent;color:inherit;width:100%}.strata-sync textarea{resize:vertical;min-height:112px;font:inherit;line-height:1.5}.strata-sync .ss-prompt-label{margin:12px 0 8px}.strata-sync option{color:#17252b;background:#fff}.strata-sync button{padding:9px 15px;border:1px solid #8885;border-radius:7px;background:transparent;color:inherit;cursor:pointer}.strata-sync button.primary{background:#126c65;border-color:#126c65;color:#fff}.strata-sync button:disabled{opacity:.45;cursor:default}.strata-sync .ss-actions{display:flex;gap:9px;flex-wrap:wrap;margin:18px 0}.strata-sync .ss-check{display:flex;flex-direction:row;align-items:center;margin-top:13px}.strata-sync .ss-card{padding:16px;border:1px solid #8884;border-radius:9px;margin:16px 0}.strata-sync .ss-status{padding:10px 13px;border-left:3px solid #21867b;background:#21867b12;margin:13px 0;overflow-wrap:anywhere}.strata-sync .ss-error{border-color:#ce7140;background:#ce714012}.strata-sync table{width:100%;border-collapse:collapse;font-size:14px}.strata-sync td,.strata-sync th{padding:9px 8px;text-align:left;border-bottom:1px solid #8883;overflow-wrap:anywhere}.strata-sync code{font-size:12px;overflow-wrap:anywhere}.strata-sync .ss-scroll{overflow-x:auto;container-type:inline-size;border:1px solid #8883;border-radius:8px;margin-top:16px}.strata-sync table{table-layout:fixed}.strata-sync th,.strata-sync td{vertical-align:top;padding:12px;line-height:1.5}.strata-sync thead th{font-size:12px;font-weight:600;background:#8881}.strata-sync th:first-child{width:34%}.strata-sync thead th:not(:first-child){width:33%;text-align:right}.strata-sync tbody th{font-weight:500}.strata-sync tbody tr:last-child>*{border-bottom:0}.strata-sync .ss-before,.strata-sync .ss-after{text-align:right;font-variant-numeric:tabular-nums}.strata-sync .ss-before{color:inherit;opacity:.7}.strata-sync .ss-after{background:#21867b0b;font-weight:600}.strata-sync .ss-target{display:block;font-size:11px;font-weight:400;opacity:.65;margin-top:5px;overflow-wrap:anywhere}.strata-sync .ss-values{display:flex;gap:5px;flex-wrap:wrap;justify-content:flex-end}.strata-sync .ss-chip{display:inline-block;padding:2px 7px;border:1px solid #8883;border-radius:5px;font-size:12px;font-weight:400;max-width:100%;overflow-wrap:anywhere}.strata-sync .ss-details{text-align:left;font-weight:400;font-size:12px}.strata-sync .ss-details summary{cursor:pointer;overflow-wrap:anywhere}.strata-sync .ss-details pre{white-space:pre-wrap;overflow-wrap:anywhere;margin:8px 0 0;font-size:11px;line-height:1.5}.strata-sync .ss-empty{font-weight:400;font-size:12px;opacity:.65}@container(max-width:440px){.strata-sync tbody th:first-child{width:100%}.strata-sync table,.strata-sync tbody,.strata-sync tr,.strata-sync tbody th,.strata-sync td{display:block;width:100%}.strata-sync thead{display:none}.strata-sync tbody tr{padding:10px 12px;border-bottom:1px solid #8883}.strata-sync tbody th,.strata-sync td{border:0;padding:5px 0}.strata-sync td::before{content:attr(data-label);float:left;font-size:12px;font-weight:400;opacity:.7}.strata-sync td{display:flow-root;padding:7px}.strata-sync .ss-values{max-width:72%;margin-left:auto}.strata-sync .ss-details{margin-top:24px}}`;
|
|
410
|
+
const workflowCss = ".strata-sync h3{font-size:16px;margin:0 0 8px}.strata-sync .ss-workflow{border:1px solid #21867b66;border-radius:10px;padding:20px;margin-bottom:18px}.strata-sync .ss-workflow>p:first-of-type{margin:0 0 16px}.strata-sync .ss-steps{display:flex;flex-wrap:wrap;gap:10px 20px;list-style:none;margin:0 0 20px;padding:0;font-size:13px}.strata-sync .ss-steps li{display:flex;align-items:center;gap:7px;opacity:.65}.strata-sync .ss-steps li[aria-current]{opacity:1;font-weight:600}.strata-sync .ss-step-number{display:inline-grid;place-items:center;width:25px;height:25px;flex-shrink:0;border:1px solid #8885;border-radius:50%;font-variant-numeric:tabular-nums}.strata-sync [aria-current] .ss-step-number{background:#126c65;color:#fff;border-color:#126c65}.strata-sync .ss-options>summary{cursor:pointer;font-size:14px}.strata-sync .ss-option-title::marker{color:#888}.strata-sync .ss-option-title>span:first-child{font-weight:600}.strata-sync .ss-badge{display:inline-block;margin-left:10px;padding:1px 7px;border:1px solid #8884;border-radius:5px;font-size:11px;vertical-align:middle}.strata-sync .ss-option-description{display:inline-block;margin-left:12px;opacity:.65;font-size:12px}.strata-sync button:focus-visible,.strata-sync summary:focus-visible,.strata-sync select:focus-visible{outline:2px solid #21867b;outline-offset:3px}@media(max-width:520px){.strata-sync .ss-workflow{padding:14px}.strata-sync .ss-option-description{display:block;margin-left:16px;margin-top:3px}.strata-sync .ss-steps{gap:8px 12px}}";
|
|
403
411
|
const fmt = (v) => v == null ? 'Not set' : typeof v === 'number' ? v.toLocaleString('en-US') : typeof v === 'object' ? JSON.stringify(v) : String(v);
|
|
404
412
|
const warningText = {
|
|
405
413
|
INPUT_UNCONFIRMED: 'Input types are missing or unsupported in server metadata. Existing input settings are preserved.',
|
|
@@ -500,8 +508,8 @@ REASONING_DEFAULT_CONFLICT: 'The provider default reasoning level is not support
|
|
|
500
508
|
h('div',null,h('strong',null,outputSource(budget)),h('div',{className:'ss-muted'},t('Output limit source: '))));
|
|
501
509
|
const warnings=(items)=>(items||[]).map((w,i)=>h('div',{key:i,className:'ss-status ss-error'},typeof w==='string'?(t(warningText[w])||(w.startsWith('SLOTS_')?t('Live slot information is unavailable. Using the model context reported by Strata.'):w)):JSON.stringify(w)));
|
|
502
510
|
return h('section',{className:'strata-sync','aria-label':'dsh-strata-sync'},
|
|
503
|
-
h('style',null,css),
|
|
504
|
-
h('header',null,h('h2',null,'dsh-strata-sync'),h('p',{className:'ss-muted'},t('
|
|
511
|
+
h('style',null,css+workflowCss),
|
|
512
|
+
h('header',null,h('h2',null,'dsh-strata-sync'),h('p',{className:'ss-muted'},t('Sync the model and context budgets from Strata Server to DSH.'))),
|
|
505
513
|
!state&&!loadError&&h('div',{className:'ss-status',role:'status'},t('Loading sync settings...')),
|
|
506
514
|
state?.busy&&h('div',{className:'ss-status',role:'status'},t('DSH is running a task. Synchronization will wait until all tasks are idle.')),
|
|
507
515
|
(error||loadError)&&h('div',{className:'ss-status ss-error',role:'alert'},diagnostic(error||loadError)),
|
|
@@ -509,52 +517,20 @@ REASONING_DEFAULT_CONFLICT: 'The provider default reasoning level is not support
|
|
|
509
517
|
conflict&&h('div',{className:'ss-status ss-error'},
|
|
510
518
|
h('p',null,t('Preferences changed in another window. Reload the latest preferences before saving; this discards your unsaved edits.')),
|
|
511
519
|
h('button',{disabled:pending,onClick:()=>action(()=>refresh(true))},t('Reload latest preferences'))),
|
|
520
|
+
h('div',{className:'ss-workflow','data-testid':'sync-workflow'},
|
|
521
|
+
h('h3',null,t('Start here')),
|
|
522
|
+
h('p',{className:'ss-muted'},t('First, check differences to read the loaded model and preview the changes.')),
|
|
523
|
+
h('ol',{className:'ss-steps','aria-label':t('Sync the model and context budgets from Strata Server to DSH.')},
|
|
524
|
+
...['Check differences','Review changes','Back up and sync'].map((label,index)=>h('li',{key:label,'aria-current':index===(preview?1:result&&!dirty?2:0)?'step':undefined},h('span',{className:'ss-step-number','aria-hidden':true},index+1),t(label)))),
|
|
512
525
|
h('label',null,t('Strata provider'),h('select',{value:form.providerId,onChange:e=>edit({providerId:e.target.value}),disabled:pending||!state},
|
|
513
526
|
h('option',{value:''},t('Choose an existing provider')),...(state?.providers||[]).map(p=>h('option',{key:p.id,value:p.id},p.id)))),
|
|
514
527
|
h('p',{className:'ss-muted'},t('Uses the URL and credentials already configured in DSH. API keys are never displayed or copied here.')),
|
|
515
|
-
h('div',{className:'ss-card'},
|
|
516
|
-
h('label',{className:'ss-check'},h('input',{type:'checkbox',checked:!form.manual,'aria-label':t('Follow Strata output limit'),onChange:e=>edit({manual:!e.target.checked}),disabled:pending||!state}),t('Follow Strata output limit')),
|
|
517
|
-
h('p',{className:'ss-muted'},t('Use the verified server default. If none is available, calculate 30% of context, up to 16,384 tokens.')),
|
|
518
|
-
activeBudget?outputValues(activeBudget,preview.server?.model):h('p',{className:'ss-muted'},t('Check differences to read the server and effective limits.')),
|
|
519
|
-
h('details',{className:'ss-details',open:form.manual},h('summary',null,t('Advanced settings')),
|
|
520
|
-
h('label',null,t('Manual output limit'),h('input',{type:'number',min:1,step:1,value:form.output,onChange:e=>edit({output:e.target.value}),disabled:pending||!state||!form.manual})),
|
|
521
|
-
h('p',{className:'ss-muted'},t(form.manual?'A manual limit takes priority over the server default and automatic calculation.':'Turn off Follow Strata output limit to enter a manual override.')))),
|
|
522
|
-
h('label',{className:'ss-check'},h('input',{type:'checkbox',checked:form.follow,onChange:e=>edit({follow:e.target.checked}),disabled:pending||!state}),t('Follow the loaded Strata model as the default')),
|
|
523
|
-
h('label',{className:'ss-check'},h('input',{type:'checkbox',checked:form.auto,onChange:e=>edit({auto:e.target.checked}),disabled:pending||!state}),t('Automatically sync when DSH starts')),
|
|
524
|
-
h('p',{className:'ss-muted'},t('Runs once on the next DSH start. Waits for running tasks to finish; no periodic server checks.')),
|
|
525
|
-
h('div',{className:'ss-card','data-testid':'summary-target'},
|
|
526
|
-
h('strong',null,t('Dynamic summary target')),
|
|
527
|
-
h('label',{className:'ss-check'},h('input',{type:'checkbox','data-testid':'summary-guidance-toggle','aria-label':t('Enable summary guidance'),checked:form.summaryGuidance,onChange:e=>edit({summaryGuidance:e.target.checked}),disabled:pending||!state}),t('Enable summary guidance')),
|
|
528
|
-
h('div',{className:'ss-grid'},
|
|
529
|
-
h('label',null,t('Output budget divisor (estimated budget ÷ O)'),h('input',{type:'number','data-testid':'summary-output-divisor','aria-label':t('Output budget divisor (estimated budget ÷ O)'),'aria-invalid':!isDivisor(draft.summaryOutputDivisor),min:1,max:Number.MAX_SAFE_INTEGER,step:'any',value:form.summaryOutputDivisor,onChange:e=>edit({summaryOutputDivisor:e.target.value}),disabled:pending||!state})),
|
|
530
|
-
h('label',null,t('Source length divisor (source estimate ÷ S)'),h('input',{type:'number','data-testid':'summary-source-divisor','aria-label':t('Source length divisor (source estimate ÷ S)'),'aria-invalid':!isDivisor(draft.summarySourceDivisor),min:1,max:Number.MAX_SAFE_INTEGER,step:'any',value:form.summarySourceDivisor,onChange:e=>edit({summarySourceDivisor:e.target.value}),disabled:pending||!state}))),
|
|
531
|
-
state&&!validDivisor&&h('p',{className:'ss-status ss-error',role:'alert'},t('Enter a finite divisor of at least 1; decimals are allowed.')),
|
|
532
|
-
h('label',{className:'ss-prompt-label'},t('Supplemental summary prompt'),h('textarea',{'data-testid':'summary-prompt','aria-label':t('Supplemental summary prompt'),'aria-invalid':!validPrompt,rows:5,value:form.summaryPrompt,onChange:e=>edit({summaryPrompt:e.target.value}),disabled:pending||!state,spellCheck:false})),
|
|
533
|
-
state&&!validPrompt&&h('p',{className:'ss-status ss-error',role:'alert'},t('Use 1–2,048 characters and include {target}.')),
|
|
534
|
-
h('button',{type:'button','data-testid':'summary-prompt-reset',disabled:pending||!state?.defaultSummaryPromptTemplate||form.summaryPrompt===state.defaultSummaryPromptTemplate,onClick:()=>edit({summaryPrompt:state.defaultSummaryPromptTemplate})},t('Restore default prompt')),
|
|
535
|
-
h('p',{className:'ss-muted'},t("Appended to DSH's native prompt; {target} becomes the calculated token target. Save preferences to apply.")),
|
|
536
|
-
!form.summaryGuidance&&h('p',{className:'ss-status','data-testid':'summary-guidance-off'},t('Summary guidance is off. No extra sentence is added to the native prompt.')),
|
|
537
|
-
summaryTargetCeiling!==null&&(summaryTargetCeiling>=256
|
|
538
|
-
? h('p',{'data-testid':'summary-target-ceiling'},t('Maximum target for this preview: '),format(summaryTargetCeiling),' tokens')
|
|
539
|
-
: h('p',{className:'ss-status','data-testid':'summary-target-native'},t('This preview is below the 256-token minimum. The native summary prompt remains unchanged.'))),
|
|
540
|
-
h('details',{className:'ss-details','data-testid':'summary-details'},h('summary',null,t('Calculation and limits')),
|
|
541
|
-
h('p',{className:'ss-muted'},t('Target = floor(min(estimated effective output budget / O, selected content estimate / S)). Default divisors: 2 and 2 (50% each).')),
|
|
542
|
-
h('p',{className:'ss-muted'},t('The preview uses the proposed summary cap. Actual targets also account for the estimated remaining context and source length; they may be lower.'),' ',t('When guidance cannot be applied, DSH keeps its native summary behavior.')))),
|
|
543
528
|
h('div',{className:'ss-actions'},
|
|
544
|
-
h('button',{disabled:pending||!state||!form.providerId
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
}
|
|
549
|
-
h('button',{disabled:pending||!state||!form.providerId||dirty||conflict||!valid,onClick:()=>action(async()=>{setPreview(await rpc('preview',{providerId:form.providerId}));await refresh();})},pending?t('Working...'):t('Check differences')),
|
|
550
|
-
h('button',{className:'primary',disabled:pending||!state||dirty||conflict||!preview||state.busy||!preview.changes?.length,onClick:()=>action(async()=>{
|
|
551
|
-
const r=await rpc('apply',{fingerprint:preview.fingerprint,providerId:form.providerId});
|
|
552
|
-
const view=r.preview||preview;
|
|
553
|
-
setResult({at:new Date().toISOString(),modelId:view.server?.model?.id,providerId:view.providerId||form.providerId,budget:view.budget,capabilityStatus:view.capabilityStatus,serverOutputTokens:view.server?.model?.serverOutputTokens,outputLimitStatus:view.server?.model?.outputLimitStatus,backupPath:r.backupPath,applied:r.applied,warnings:view.server?.warnings});
|
|
554
|
-
setPreview(null);setNotice(r.applied?'Synced and backed up the original settings. Start a new conversation to use the updated compaction policy.':'Settings already match. No changes needed.');await refresh();
|
|
555
|
-
})},t('Back up and sync'))),
|
|
556
|
-
dirty&&!conflict&&h('p',{className:'ss-muted'},t('Save preferences before checking for differences.')),
|
|
557
|
-
preview&&h('div',{className:'ss-card'},
|
|
529
|
+
h('button',{className:preview?'':'primary','data-testid':'check-differences',disabled:pending||!state||!form.providerId||dirty||conflict||!valid,onClick:()=>action(async()=>{setPreview(await rpc('preview',{providerId:form.providerId}));await refresh();})},pending?t('Working...'):t('Check differences'))),
|
|
530
|
+
dirty&&!conflict&&h('p',{className:'ss-status'},t('Save option changes below before checking differences again.')),
|
|
531
|
+
preview&&h('div',{className:'ss-card','data-testid':'sync-preview'},
|
|
532
|
+
h('h3',null,t('Review changes')),
|
|
533
|
+
preview.changes?.length>0&&h('p',{className:'ss-muted'},t('Review the changes below, then back up and sync.')),
|
|
558
534
|
h('strong',null,'Strata Server'),h('p',null,h('code',null,preview.server?.model?.id)),
|
|
559
535
|
h('div',{className:'ss-grid'},
|
|
560
536
|
h('div',null,h('strong',null,format(preview.budget?.contextWindow)),h('div',{className:'ss-muted'},t('Context tokens'))),
|
|
@@ -575,6 +551,14 @@ REASONING_DEFAULT_CONFLICT: 'The provider default reasoning level is not support
|
|
|
575
551
|
!preview.changes?.length&&alignment(preview),
|
|
576
552
|
h('p',null,t('Effective compaction threshold: '),format(preview.budget?.thresholdTokens),' tokens (',preview.budget?.thresholdPercent?.toFixed(2),'%)'),
|
|
577
553
|
h('p',{className:'ss-muted'},t('Only DSH settings are updated. Sync does not switch server models, change Strata configuration, or send inference requests. Start a new conversation after syncing.'))),
|
|
554
|
+
h('div',{className:'ss-actions','data-testid':'sync-apply'},
|
|
555
|
+
h('button',{className:preview?.changes?.length?'primary':'',disabled:pending||!state||dirty||conflict||!preview||state.busy||!preview.changes?.length,onClick:()=>action(async()=>{
|
|
556
|
+
const r=await rpc('apply',{fingerprint:preview.fingerprint,providerId:form.providerId});
|
|
557
|
+
const view=r.preview||preview;
|
|
558
|
+
setResult({at:new Date().toISOString(),modelId:view.server?.model?.id,providerId:view.providerId||form.providerId,budget:view.budget,capabilityStatus:view.capabilityStatus,serverOutputTokens:view.server?.model?.serverOutputTokens,outputLimitStatus:view.server?.model?.outputLimitStatus,backupPath:r.backupPath,applied:r.applied,warnings:view.server?.warnings});
|
|
559
|
+
setPreview(null);setNotice(r.applied?'Synced and backed up the original settings. Start a new conversation to use the updated compaction policy.':'Settings already match. No changes needed.');await refresh();
|
|
560
|
+
})},t('Back up and sync'))),
|
|
561
|
+
!preview&&!result&&h('p',{className:'ss-muted'},t('Check differences before syncing.'))),
|
|
578
562
|
displayedResult?.budget&&h('div',{className:'ss-card','data-testid':'sync-result'},
|
|
579
563
|
h('strong',null,t('Latest synchronization result')),h('p',{className:'ss-muted'},t('This records the last synchronization, not a live server check.')),
|
|
580
564
|
h('p',null,t('Model'),': ',h('code',null,displayedResult.modelId)),h('p',null,t('Context window'),': ',format(displayedResult.budget.contextWindow)),
|
|
@@ -582,6 +566,41 @@ REASONING_DEFAULT_CONFLICT: 'The provider default reasoning level is not support
|
|
|
582
566
|
h('p',null,t(displayedResult.backupPath?'Backup created':'No settings changed; no new backup was needed.')),
|
|
583
567
|
displayedResult.backupPath&&h('p',{className:'ss-muted'},t('Original settings backup: '),h('code',null,displayedResult.backupPath)),
|
|
584
568
|
h('p',{className:'ss-muted'},t('Last sync: '),format(displayedResult.at)),...warnings(displayedResult.warnings)),
|
|
569
|
+
h('details',{className:'ss-card ss-options','data-testid':'sync-preferences'},
|
|
570
|
+
h('summary',{className:'ss-option-title'},h('span',null,t('Sync preferences')),h('span',{className:'ss-option-description'},t('Output limit, default model and startup sync'))),
|
|
571
|
+
h('div',{className:'ss-card'},
|
|
572
|
+
h('label',{className:'ss-check'},h('input',{type:'checkbox',checked:!form.manual,'aria-label':t('Follow Strata output limit'),onChange:e=>edit({manual:!e.target.checked}),disabled:pending||!state}),t('Follow Strata output limit')),
|
|
573
|
+
h('p',{className:'ss-muted'},t('Use the verified server default. If none is available, calculate 30% of context, up to 16,384 tokens.')),
|
|
574
|
+
activeBudget?outputValues(activeBudget,preview.server?.model):h('p',{className:'ss-muted'},t('Check differences to read the server and effective limits.')),
|
|
575
|
+
h('details',{className:'ss-details',open:form.manual},h('summary',null,t('Advanced settings')),
|
|
576
|
+
h('label',null,t('Manual output limit'),h('input',{type:'number',min:1,step:1,value:form.output,onChange:e=>edit({output:e.target.value}),disabled:pending||!state||!form.manual})),
|
|
577
|
+
h('p',{className:'ss-muted'},t(form.manual?'A manual limit takes priority over the server default and automatic calculation.':'Turn off Follow Strata output limit to enter a manual override.')))),
|
|
578
|
+
h('label',{className:'ss-check'},h('input',{type:'checkbox',checked:form.follow,onChange:e=>edit({follow:e.target.checked}),disabled:pending||!state}),t('Follow the loaded Strata model as the default')),
|
|
579
|
+
h('label',{className:'ss-check'},h('input',{type:'checkbox',checked:form.auto,onChange:e=>edit({auto:e.target.checked}),disabled:pending||!state}),t('Automatically sync when DSH starts')),
|
|
580
|
+
h('p',{className:'ss-muted'},t('Runs once on the next DSH start. Waits for running tasks to finish; no periodic server checks.'))),
|
|
581
|
+
h('details',{className:'ss-card ss-options','data-testid':'summary-target'},
|
|
582
|
+
h('summary',{className:'ss-option-title'},h('span',null,t('Dynamic summary target')),h('span',{className:'ss-badge'},t(form.summaryGuidance?'Enabled':'Optional'))),
|
|
583
|
+
h('label',{className:'ss-check'},h('input',{type:'checkbox','data-testid':'summary-guidance-toggle','aria-label':t('Enable summary guidance'),checked:form.summaryGuidance,onChange:e=>edit({summaryGuidance:e.target.checked}),disabled:pending||!state}),t('Enable summary guidance')),
|
|
584
|
+
h('div',{className:'ss-grid'},
|
|
585
|
+
h('label',null,t('Output budget divisor (estimated budget ÷ O)'),h('input',{type:'number','data-testid':'summary-output-divisor','aria-label':t('Output budget divisor (estimated budget ÷ O)'),'aria-invalid':!isDivisor(draft.summaryOutputDivisor),min:1,max:Number.MAX_SAFE_INTEGER,step:'any',value:form.summaryOutputDivisor,onChange:e=>edit({summaryOutputDivisor:e.target.value}),disabled:pending||!state})),
|
|
586
|
+
h('label',null,t('Source length divisor (source estimate ÷ S)'),h('input',{type:'number','data-testid':'summary-source-divisor','aria-label':t('Source length divisor (source estimate ÷ S)'),'aria-invalid':!isDivisor(draft.summarySourceDivisor),min:1,max:Number.MAX_SAFE_INTEGER,step:'any',value:form.summarySourceDivisor,onChange:e=>edit({summarySourceDivisor:e.target.value}),disabled:pending||!state}))),
|
|
587
|
+
state&&!validDivisor&&h('p',{className:'ss-status ss-error',role:'alert'},t('Enter a finite divisor of at least 1; decimals are allowed.')),
|
|
588
|
+
h('label',{className:'ss-prompt-label'},t('Supplemental summary prompt'),h('textarea',{'data-testid':'summary-prompt','aria-label':t('Supplemental summary prompt'),'aria-invalid':!validPrompt,rows:5,value:form.summaryPrompt,onChange:e=>edit({summaryPrompt:e.target.value}),disabled:pending||!state,spellCheck:false})),
|
|
589
|
+
state&&!validPrompt&&h('p',{className:'ss-status ss-error',role:'alert'},t('Use 1–2,048 characters and include {target}.')),
|
|
590
|
+
h('button',{type:'button','data-testid':'summary-prompt-reset',disabled:pending||!state?.defaultSummaryPromptTemplate||form.summaryPrompt===state.defaultSummaryPromptTemplate,onClick:()=>edit({summaryPrompt:state.defaultSummaryPromptTemplate})},t('Restore default prompt')),
|
|
591
|
+
h('p',{className:'ss-muted'},t("Appended to DSH's native prompt; {target} becomes the calculated token target. Save preferences to apply.")),
|
|
592
|
+
summaryTargetCeiling!==null&&(summaryTargetCeiling>=256
|
|
593
|
+
? h('p',{'data-testid':'summary-target-ceiling'},t('Maximum target for this preview: '),format(summaryTargetCeiling),' tokens')
|
|
594
|
+
: h('p',{className:'ss-status','data-testid':'summary-target-native'},t('This preview is below the 256-token minimum. The native summary prompt remains unchanged.'))),
|
|
595
|
+
h('details',{className:'ss-details','data-testid':'summary-details'},h('summary',null,t('Calculation and limits')),
|
|
596
|
+
h('p',{className:'ss-muted'},t('Target = floor(min(estimated effective output budget / O, selected content estimate / S)). Default divisors: 2 and 2 (50% each).')),
|
|
597
|
+
h('p',{className:'ss-muted'},t('The preview uses the proposed summary cap. Actual targets also account for the estimated remaining context and source length; they may be lower.'),' ',t('When guidance cannot be applied, DSH keeps its native summary behavior.')))),
|
|
598
|
+
h('div',{className:'ss-actions'},
|
|
599
|
+
h('button',{className:dirty?'primary':'',disabled:pending||!state||!form.providerId||!valid||!dirty||conflict,onClick:()=>action(async()=>{
|
|
600
|
+
const changes=Object.fromEntries(Object.entries(values(formRef.current)).filter(([key,value])=>!Object.is(value,baseline.current.values[key])));
|
|
601
|
+
const s=await rpc('configure',{...changes,expectedRevision:baseline.current.revision});
|
|
602
|
+
requestSeq.current++;acceptStatus(s,true);setPreview(null);setNotice('Sync preferences saved.');
|
|
603
|
+
})},t('Save preferences'))),
|
|
585
604
|
state?.lastError&&h('div',{className:'ss-status ss-error'},diagnostic(typeof state.lastError==='string'?state.lastError:state.lastError.message)));
|
|
586
605
|
}
|
|
587
606
|
function apply(ctx) {
|
package/docs/README.zh-CN.md
CHANGED
|
@@ -44,6 +44,8 @@ dsh plugin --profile desktop add dsh-strata-sync --registry=https://registry.npm
|
|
|
44
44
|
|
|
45
45
|
打开**设置 → dsh-strata-sync**:
|
|
46
46
|
|
|
47
|
+
页面上方是主要流程:**检查差异 → 预览更改 → 备份并同步**。下方的**同步偏好**与可选的**动态摘要目标**默认折叠;展开后即可调整选项或编辑摘要补充提示词。
|
|
48
|
+
|
|
47
49
|
1. 选择 Strata 提供方,点击**保存偏好**。
|
|
48
50
|
2. 点击**检查差异**,查看已加载模型与拟修改的设置。
|
|
49
51
|
3. 在 DSH 空闲时,点击**备份并同步**。
|
package/docs/README.zh-TW.md
CHANGED
|
@@ -44,6 +44,8 @@ dsh plugin --profile desktop add dsh-strata-sync --registry=https://registry.npm
|
|
|
44
44
|
|
|
45
45
|
開啟**設定 → dsh-strata-sync**:
|
|
46
46
|
|
|
47
|
+
頁面上方是主要流程:**檢查差異 → 預覽變更 → 備份並同步**。下方的**同步偏好**與選用的**動態摘要目標**預設收合;展開後即可調整選項或編輯摘要補充提示詞。
|
|
48
|
+
|
|
47
49
|
1. 選擇 Strata 提供方,點選**儲存偏好**。
|
|
48
50
|
2. 點選**檢查差異**,查看已載入模型與預計修改的設定。
|
|
49
51
|
3. 在 DSH 閒置時,點選**備份並同步**。
|
package/docs/VALIDATION.md
CHANGED
|
@@ -11,7 +11,7 @@ Validation date: 2026-10-30 (Asia/Taipei).
|
|
|
11
11
|
|
|
12
12
|
## Automated verification
|
|
13
13
|
|
|
14
|
-
All **
|
|
14
|
+
All **156 automated tests pass** for the current runtime. Coverage includes:
|
|
15
15
|
|
|
16
16
|
- Actual pi-ai context clamping across multiple input sizes, near-full and exhausted context, independent source length, additional prompt costs, disabled-mode zero discovery and restored native requests.
|
|
17
17
|
- Native Cordis waterfall dispatch, immutable messages, concurrent summaries, duplicate hooks, cancellation, metadata failures, early stream closure, native errors and unload.
|