dsh-strata-sync 0.8.1 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,28 +6,36 @@ A plugin that aligns **DeepSeek Harness (DSH)** with the model actually loaded b
6
6
 
7
7
  Open **Settings → dsh-strata-sync** to inspect differences, synchronize an existing Strata provider, or enable automatic synchronization when DSH starts. The interface and README are available in English, Simplified Chinese and Traditional Chinese. The interface automatically follows DSH’s language, including live changes. DSH `zh` uses Simplified Chinese; `zh-Hant`, `zh-TW`, `zh-HK` and `zh-MO` use Traditional Chinese. Other languages fall back to English. There is no separate language preference. Unknown backend diagnostics retain their original text for troubleshooting.
8
8
 
9
- Version 0.8.1 calculates a dynamic length target before each supported Strata summary and appends **one sentence** to DSH's native summary prompt. The original prompt, output cap and other settings remain unchanged. The settings page explains the formula and distinguishes this writing target from the hard output limit. Existing synchronization safeguards, startup behavior, capability verification and backups are retained.
9
+ Version 0.9.0 adds a **default-on summary guidance switch** and an adjustable **context divisor** to the settings page. When enabled, the plugin calculates a dynamic length target before each supported Strata summary and appends **one sentence** to DSH's native summary prompt. The original prompt, output cap and other settings remain unchanged. Existing synchronization safeguards, startup behavior, capability verification and backups are retained.
10
10
 
11
11
  ## What it does
12
12
 
13
13
  ### Dynamic summary guidance
14
14
 
15
- For supported Strata routes, the plugin calculates a fresh writing target for each native DSH summary request:
15
+ Summary guidance is enabled by default. For supported Strata routes, the plugin calculates a fresh writing target for each native DSH summary request:
16
16
 
17
17
  ```text
18
18
  context = min(verified Strata context, existing DSH model context)
19
- target = floor(min(context / 16,
19
+ divisor = summaryContextDivisor (default: 16)
20
+ target = floor(min(context / divisor,
20
21
  actual summary maxTokens / 2,
21
22
  selected-content estimated tokens / 2))
22
23
  ```
23
24
 
24
25
  The selected-content estimate covers only the conversation span being replaced, including any prior checkpoint in that span. It excludes the system prompt and tool schemas. Before each summary, read-only metadata queries verify Strata's loaded model and context; the current summary request supplies its actual output cap. The calculation uses the smaller of verified server context and the existing DSH model context, so a larger server window never silently expands a smaller client budget. The target is calculated at summary time, not fixed when DSH starts or when settings are synchronized.
25
26
 
26
- With a 4,096-token summary output cap and enough source content, 32K context gives a target of **2,048 tokens**, and 64K gives **2,048 tokens**. Shorter content lowers the target. **Settings → dsh-strata-sync** shows the formula and the maximum target for a preview; it cannot know the exact target of a future summary.
27
+ With the default divisor of 16, a 4,096-token summary output cap and enough source content, 32K context gives a target of **2,048 tokens**, and 64K gives **2,048 tokens**. Shorter content lowers the target. **Settings → dsh-strata-sync** shows the formula and the maximum target for a preview; it cannot know the exact target of a future summary.
28
+
29
+ In the **Dynamic summary target** card, toggle **Enable summary guidance** and set **Context divisor (context ÷ N)** to a positive safe integer. A smaller divisor allows a larger target; the summary-output and source-content bounds still apply. For example, with 32K context, a 4,096-token summary cap and enough content, divisors 32, 16 and 8 produce targets of 1,024, 2,048 and 2,048 tokens respectively. Click **Save preferences** to apply your choice to subsequent supported summary requests. Saving these controls does not synchronize model budgets or change Strata Server settings.
30
+
31
+ | Plugin preference | Default | Meaning |
32
+ |---|---:|---|
33
+ | `summaryGuidance` | `true` | Append the length-guidance sentence when the request is supported. Turning it off preserves DSH's native summary and automatic compaction. |
34
+ | `summaryContextDivisor` | `16` | Divide the verified context by this positive safe integer when calculating the target. |
27
35
 
28
36
  Exactly one supplemental English sentence asks the model to meet that target, retain information needed to continue the remaining work, consolidate prior summaries and remove redundant or obsolete details. The native instructions, eight-section format and existing request options are preserved. The target is a heuristic writing instruction, **not a new hard output limit, an optimal value, or a guarantee against truncation**. No automatic retry loop or extra inference request is added.
29
37
 
30
- If the route, required metadata or native summary format cannot be verified, or image/file attachment pricing cannot be estimated safely, the original DSH request is passed through unchanged. A cancelled request or disabled plugin also preserves native handling. Calculated targets below 256 tokens leave the native prompt unchanged, rather than imposing an impractically small target for eight sections; the plugin does not cancel the summary or replace content with an empty checkpoint. Disabling or removing this plugin removes the supplemental guidance; it does not rewrite saved conversation history.
38
+ If the route, required metadata or native summary format cannot be verified, or image/file attachment pricing cannot be estimated safely, the original DSH request is passed through unchanged. A cancelled request, disabled guidance or disabled plugin also preserves native handling. Calculated targets below 256 tokens leave the native prompt unchanged, rather than imposing an impractically small target for eight sections; the plugin does not cancel the summary or replace content with an empty checkpoint. Disabling the guidance or removing this plugin removes the supplemental sentence; it does not rewrite saved conversation history.
31
39
 
32
40
  ### Automatic model capabilities (0.4.0)
33
41
 
@@ -77,7 +85,7 @@ dsh plugin --profile desktop add dsh-strata-sync --registry=https://registry.npm
77
85
 
78
86
  Reopen DSH after installation. The bundle is automatically selected on its first installation; an already installed but disabled bundle must be enabled in DSH's plugin manager.
79
87
 
80
- To install **0.8.1 with dynamic summary guidance**, build from this source with Node.js 22 or newer, finish active tasks and fully quit DSH Desktop before the final installation command:
88
+ To install **0.9.0 with summary guidance controls** from source, use Node.js 22 or newer, finish active tasks and fully quit DSH Desktop before the final installation command:
81
89
 
82
90
  ```sh
83
91
  git clone https://github.com/ethan741205/dsh-strata-sync.git
@@ -85,7 +93,7 @@ cd dsh-strata-sync
85
93
  npm ci
86
94
  npm test
87
95
  npm pack
88
- dsh plugin --profile desktop add ./dsh-strata-sync-0.8.1.tgz
96
+ dsh plugin --profile desktop add ./dsh-strata-sync-0.9.0.tgz
89
97
  ```
90
98
 
91
99
  Use an absolute tarball path if running the last command elsewhere. DSH's plugin installer selects the included bundle; it can require a desktop reload to mount the new browser entry. Finish any active task before restarting DSH.
@@ -98,8 +106,16 @@ Then open **Settings → dsh-strata-sync**:
98
106
  4. Optionally enable **Automatically sync when DSH starts** and save. It defaults to off and takes effect on the next start. Existing `autoSync: true` preferences now use startup behavior.
99
107
  5. Start a new conversation to use the new Agent preset revision.
100
108
 
109
+ The **Dynamic summary target** card is independent of model synchronization. Leave its guidance enabled and divisor at 16 to retain the previous behavior, or change these preferences and save. Turning this switch off does not disable DSH's own compaction.
110
+
101
111
  No API key needs to be copied into this plugin. Set up or repair credentials in DSH Models settings.
102
112
 
113
+ ## Changes in 0.9.0
114
+
115
+ - Adds a default-on switch for the supplemental summary guidance and an adjustable context divisor, defaulting to 16.
116
+ - Saves both controls through the existing preferences and revision checks, with matching English, Simplified Chinese and Traditional Chinese UI and documentation.
117
+ - Keeps native summary instructions, hard output limits, other budgets and server settings unchanged when saving these controls.
118
+
103
119
  ## Changes in 0.5.0
104
120
 
105
121
  - Follows DSH’s native locale service; removes the independent language selector and product disclaimer.
package/dist/client.js CHANGED
@@ -91,13 +91,45 @@ window.__ModuleLoader__.load({
91
91
  "zh-Hant": "目標如何計算",
92
92
  "zh-Hans": "目标如何计算"
93
93
  },
94
- "Before each supported Strata summary, calculates a length target and appends one sentence to DSH's native summary prompt.": {
95
- "zh-Hant": "每次支援的 Strata 摘要請求前,計算長度目標,並在 DSH 原生摘要提示詞後補充一句。",
96
- "zh-Hans": "每次支持的 Strata 摘要请求前,计算长度目标,并在 DSH 原生摘要提示词后补充一句。"
94
+ "When enabled, before each supported Strata summary, calculates a length target and appends one sentence to DSH's native summary prompt.": {
95
+ "zh-Hant": "啟用後,在每次支援的 Strata 摘要請求前,計算長度目標,並在 DSH 原生摘要提示詞後補充一句。",
96
+ "zh-Hans": "启用后,在每次支持的 Strata 摘要请求前,计算长度目标,并在 DSH 原生摘要提示词后补充一句。"
97
97
  },
98
- "Target = floor(min(context / 16, summary output limit / 2, selected content estimate / 2)).": {
99
- "zh-Hant": "目標 = floor(min(上下文 / 16, 摘要輸出上限 / 2, 待壓縮內容估算 / 2))。",
100
- "zh-Hans": "目标 = floor(min(上下文 / 16, 摘要输出上限 / 2, 待压缩内容估算 / 2))。"
98
+ "Target = floor(min(context / N, summary output limit / 2, selected content estimate / 2)).": {
99
+ "zh-Hant": "目標 = floor(min(上下文 / N, 摘要輸出上限 / 2, 待壓縮內容估算 / 2))。",
100
+ "zh-Hans": "目标 = floor(min(上下文 / N, 摘要输出上限 / 2, 待压缩内容估算 / 2))。"
101
+ },
102
+ "Enable summary guidance": {
103
+ "zh-Hant": "啟用摘要提示補充",
104
+ "zh-Hans": "启用摘要提示补充"
105
+ },
106
+ "Enabled by default. Turning this off keeps DSH's native summary and automatic compaction behavior.": {
107
+ "zh-Hant": "預設開啟。關閉後保留 DSH 原生摘要與自動壓縮行為。",
108
+ "zh-Hans": "默认开启。关闭后保留 DSH 原生摘要与自动压缩行为。"
109
+ },
110
+ "Context divisor (context ÷ N)": {
111
+ "zh-Hant": "上下文除數(上下文 ÷ N)",
112
+ "zh-Hans": "上下文除数(上下文 ÷ N)"
113
+ },
114
+ "Default: 16. A smaller divisor allows a larger target, still bounded by half the summary output limit and half the selected content estimate.": {
115
+ "zh-Hant": "預設為 16。除數越小,允許的目標越大,但仍受摘要輸出上限的一半與待壓縮內容估算的一半限制。",
116
+ "zh-Hans": "默认为 16。除数越小,允许的目标越大,但仍受摘要输出上限的一半与待压缩内容估算的一半限制。"
117
+ },
118
+ "Enter a positive whole-number divisor.": {
119
+ "zh-Hant": "請輸入正整數除數。",
120
+ "zh-Hans": "请输入正整数除数。"
121
+ },
122
+ "This preview is below the 256-token minimum. The native summary prompt remains unchanged.": {
123
+ "zh-Hant": "本次預覽低於 256 tokens 的最低目標,將保留原生摘要提示詞。",
124
+ "zh-Hans": "本次预览低于 256 tokens 的最低目标,将保留原生摘要提示词。"
125
+ },
126
+ "Summary guidance is off. No extra sentence is added to the native prompt.": {
127
+ "zh-Hant": "摘要提示補充已關閉,不會在原生提示詞中加上額外句子。",
128
+ "zh-Hans": "摘要提示补充已关闭,不会在原生提示词中添加额外句子。"
129
+ },
130
+ "Save preferences to apply these controls to subsequent summary requests; other model and compaction settings stay unchanged.": {
131
+ "zh-Hant": "儲存偏好後,這些控制項會套用至後續摘要請求;其他模型與壓縮設定保持不變。",
132
+ "zh-Hans": "保存偏好后,这些控制项将应用于后续摘要请求;其他模型与压缩设置保持不变。"
101
133
  },
102
134
  "Context uses the smaller of the verified Strata window and the existing DSH model window. The preview ceiling assumes the proposed budgets; existing conversation settings can make the actual target lower.": {
103
135
  "zh-Hant": "上下文採用已確認的 Strata 視窗與 DSH 既有模型視窗的較小值。預覽上限依提議預算計算,既有對話設定可能讓實際目標更低。",
@@ -367,19 +399,19 @@ REASONING_DEFAULT_CONFLICT: 'The provider default reasoning level is not support
367
399
  };
368
400
  const diagnostic = (message) => translations[message] ? t(message) : language === 'en' ? message : t('Server diagnostic: ') + message;
369
401
  const [state,setState] = React.useState(null), [preview,setPreview] = React.useState(null), [result,setResult] = React.useState(null);
370
- const [form,setForm] = React.useState({providerId:'',output:'',manual:false,auto:false,follow:true});
402
+ const [form,setForm] = React.useState({providerId:'',output:'',manual:false,auto:false,follow:true,summaryGuidance:true,summaryDivisor:'16'});
371
403
  const [pending,setPending] = React.useState(false), [error,setError] = React.useState(''), [loadError,setLoadError] = React.useState('');
372
404
  const [notice,setNotice] = React.useState(''), [conflict,setConflict] = React.useState(false);
373
405
  const formRef=React.useRef(form), baseline=React.useRef(null), requestSeq=React.useRef(0), alive=React.useRef(true);
374
- const values = (f) => ({providerId:f.providerId,outputTokens:f.manual ? (f.output.trim()==='' ? NaN : Number(f.output)) : null,autoSync:f.auto,followLoadedModel:f.follow});
375
- const preferences = (s) => ({providerId:s.providerId || '',outputTokens:s.outputTokens ?? null,autoSync:!!s.autoSync,followLoadedModel:s.followLoadedModel !== false});
406
+ const values = (f) => ({providerId:f.providerId,outputTokens:f.manual ? (f.output.trim()==='' ? NaN : Number(f.output)) : null,autoSync:f.auto,followLoadedModel:f.follow,summaryGuidance:f.summaryGuidance,summaryContextDivisor:f.summaryDivisor.trim()===''?NaN:Number(f.summaryDivisor)});
407
+ const preferences = (s) => ({providerId:s.providerId || '',outputTokens:s.outputTokens ?? null,autoSync:!!s.autoSync,followLoadedModel:s.followLoadedModel !== false,summaryGuidance:s.summaryGuidance!==false,summaryContextDivisor:s.summaryContextDivisor??16});
376
408
  const equal = (a,b) => Object.keys(a).every(key=>Object.is(a[key],b[key]));
377
409
  const acceptStatus = React.useCallback((s,force=false) => {
378
410
  if (!alive.current) return;
379
411
  const next=preferences(s), old=baseline.current;
380
412
  const untouched=!old || equal(values(formRef.current),old.values);
381
413
  if (force || untouched) {
382
- const nextForm={providerId:next.providerId,output:next.outputTokens==null?'':String(next.outputTokens),manual:next.outputTokens!=null,auto:next.autoSync,follow:next.followLoadedModel};
414
+ const nextForm={providerId:next.providerId,output:next.outputTokens==null?'':String(next.outputTokens),manual:next.outputTokens!=null,auto:next.autoSync,follow:next.followLoadedModel,summaryGuidance:next.summaryGuidance,summaryDivisor:String(next.summaryContextDivisor)};
383
415
  formRef.current=nextForm; setForm(nextForm); setConflict(false);
384
416
  baseline.current={values:next,revision:s.settingsRevision};
385
417
  } else if (old.revision!==s.settingsRevision || !equal(old.values,next)) {
@@ -411,12 +443,13 @@ REASONING_DEFAULT_CONFLICT: 'The provider default reasoning level is not support
411
443
  else setError(e.code==='unsupported-route'?'This provider uses an unsupported model catalog configuration. Configure an explicit custom model list in DSH before syncing.':e.message||'The operation failed.');
412
444
  } finally { if(alive.current)setPending(false); }
413
445
  }
414
- const draft=values(form), valid=draft.outputTokens===null || Number.isSafeInteger(draft.outputTokens)&&draft.outputTokens>0;
446
+ const draft=values(form), validDivisor=Number.isSafeInteger(draft.summaryContextDivisor)&&draft.summaryContextDivisor>0;
447
+ const valid=validDivisor&&(draft.outputTokens===null || Number.isSafeInteger(draft.outputTokens)&&draft.outputTokens>0);
415
448
  const dirty=!!baseline.current&&!equal(draft,baseline.current.values);
416
449
  const displayedResult=!result || state?.lastApplied?.at>result.at ? state?.lastApplied : result;
417
450
  const activeBudget=preview?.budget;
418
- const summaryTargetCeiling=Number.isSafeInteger(activeBudget?.contextWindow)&&activeBudget.contextWindow>0&&Number.isSafeInteger(activeBudget?.summaryMaxTokens)&&activeBudget.summaryMaxTokens>0
419
- ? Math.floor(Math.min(activeBudget.contextWindow/16,activeBudget.summaryMaxTokens/2)) : null;
451
+ const summaryTargetCeiling=form.summaryGuidance&&validDivisor&&Number.isSafeInteger(activeBudget?.contextWindow)&&activeBudget.contextWindow>0&&Number.isSafeInteger(activeBudget?.summaryMaxTokens)&&activeBudget.summaryMaxTokens>0
452
+ ? Math.floor(Math.min(activeBudget.contextWindow/draft.summaryContextDivisor,activeBudget.summaryMaxTokens/2)) : null;
420
453
  const outputSource=(budget)=>t(({server:'Strata Server default',manual:'Manual override',calculated:'Automatic calculation'})[budget?.outputSource]||'Automatic calculation');
421
454
  const preserved=(view)=>{
422
455
  const status=view?.capabilityStatus;
@@ -458,6 +491,27 @@ REASONING_DEFAULT_CONFLICT: 'The provider default reasoning level is not support
458
491
  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')),
459
492
  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')),
460
493
  h('p',{className:'ss-muted'},t('Runs once on the next DSH start. Waits for running tasks to finish; no periodic server checks.')),
494
+ h('div',{className:'ss-card','data-testid':'summary-target'},
495
+ h('strong',null,t('Dynamic summary target')),
496
+ 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')),
497
+ h('p',{className:'ss-muted'},t("Enabled by default. Turning this off keeps DSH's native summary and automatic compaction behavior.")),
498
+ h('label',null,t('Context divisor (context ÷ N)'),h('input',{type:'number','data-testid':'summary-divisor','aria-label':t('Context divisor (context ÷ N)'),'aria-invalid':!validDivisor,min:1,max:Number.MAX_SAFE_INTEGER,step:1,value:form.summaryDivisor,onChange:e=>edit({summaryDivisor:e.target.value}),disabled:pending||!state})),
499
+ state&&!validDivisor&&h('p',{className:'ss-status ss-error',role:'alert'},t('Enter a positive whole-number divisor.')),
500
+ h('p',{className:'ss-muted'},t('Default: 16. A smaller divisor allows a larger target, still bounded by half the summary output limit and half the selected content estimate.')),
501
+ h('p',{className:'ss-muted'},t('Save preferences to apply these controls to subsequent summary requests; other model and compaction settings stay unchanged.')),
502
+ !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.')),
503
+ h('p',null,t("When enabled, before each supported Strata summary, calculates a length target and appends one sentence to DSH's native summary prompt.")),
504
+ summaryTargetCeiling!==null&&(summaryTargetCeiling>=256
505
+ ? h('p',{'data-testid':'summary-target-ceiling'},t('Maximum target for this preview: '),format(summaryTargetCeiling),' tokens')
506
+ : 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.'))),
507
+ h('details',{className:'ss-details'},h('summary',null,t('How the target is calculated')),
508
+ h('p',{className:'ss-muted'},t('Target = floor(min(context / N, summary output limit / 2, selected content estimate / 2)).')),
509
+ h('p',{className:'ss-muted'},t('Context uses the smaller of the verified Strata window and the existing DSH model window. The preview ceiling assumes the proposed budgets; existing conversation settings can make the actual target lower.')),
510
+ h('p',{className:'ss-muted'},t('The actual target may be lower for shorter content. System prompts and tool schemas are excluded from the content estimate.')),
511
+ h('p',{className:'ss-muted'},t('The original prompt, output cap and other settings stay unchanged. This is a writing target, not a guaranteed length or an optimal value.')),
512
+ h('p',{className:'ss-muted'},t('Targets below 256 tokens leave the original prompt unchanged; the native summary still runs.')),
513
+ h('p',{className:'ss-muted'},t('If the route or native summary format cannot be verified, DSH uses its original prompt.')),
514
+ h('p',{className:'ss-muted'},t('Unpriced image/file attachments, cancellation or a disabled plugin preserve native request handling.')))),
461
515
  h('div',{className:'ss-actions'},
462
516
  h('button',{disabled:pending||!state||!form.providerId||!valid||!dirty||conflict,onClick:()=>action(async()=>{
463
517
  const changes=Object.fromEntries(Object.entries(values(formRef.current)).filter(([key,value])=>!Object.is(value,baseline.current.values[key])));
@@ -472,18 +526,6 @@ REASONING_DEFAULT_CONFLICT: 'The provider default reasoning level is not support
472
526
  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();
473
527
  })},t('Back up and sync'))),
474
528
  dirty&&!conflict&&h('p',{className:'ss-muted'},t('Save preferences before checking for differences.')),
475
- h('div',{className:'ss-card','data-testid':'summary-target'},
476
- h('strong',null,t('Dynamic summary target')),
477
- h('p',null,t("Before each supported Strata summary, calculates a length target and appends one sentence to DSH's native summary prompt.")),
478
- summaryTargetCeiling!==null&&h('p',{'data-testid':'summary-target-ceiling'},t('Maximum target for this preview: '),format(summaryTargetCeiling),' tokens'),
479
- h('details',{className:'ss-details'},h('summary',null,t('How the target is calculated')),
480
- h('p',{className:'ss-muted'},t('Target = floor(min(context / 16, summary output limit / 2, selected content estimate / 2)).')),
481
- h('p',{className:'ss-muted'},t('Context uses the smaller of the verified Strata window and the existing DSH model window. The preview ceiling assumes the proposed budgets; existing conversation settings can make the actual target lower.')),
482
- h('p',{className:'ss-muted'},t('The actual target may be lower for shorter content. System prompts and tool schemas are excluded from the content estimate.')),
483
- h('p',{className:'ss-muted'},t('The original prompt, output cap and other settings stay unchanged. This is a writing target, not a guaranteed length or an optimal value.')),
484
- h('p',{className:'ss-muted'},t('Targets below 256 tokens leave the original prompt unchanged; the native summary still runs.')),
485
- h('p',{className:'ss-muted'},t('If the route or native summary format cannot be verified, DSH uses its original prompt.')),
486
- h('p',{className:'ss-muted'},t('Unpriced image/file attachments, cancellation or a disabled plugin preserve native request handling.')))),
487
529
  preview&&h('div',{className:'ss-card'},
488
530
  h('strong',null,'Strata Server'),h('p',null,h('code',null,preview.server?.model?.id)),
489
531
  h('div',{className:'ss-grid'},
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import { mkdir, readFile, writeFile } from 'node:fs/promises';
3
3
  import { dirname, join } from 'node:path';
4
4
  import z from '@deepseek-ai/schemastery';
5
5
  import { discoverStrata, planBudget, StrataSyncError } from './core.mjs';
6
- import { installSummaryGuidance } from './summary.mjs';
6
+ import { DEFAULT_SUMMARY_DIVISOR, installSummaryGuidance } from './summary.mjs';
7
7
 
8
8
  export const inject = ['configEditor', 'connection', 'agents', 'credentials', 'agentPresets'];
9
9
  export const Config = z.object({
@@ -11,6 +11,8 @@ export const Config = z.object({
11
11
  autoSync: z.boolean().default(false),
12
12
  followLoadedModel: z.boolean().default(true),
13
13
  outputTokens: z.number().step(1).min(1),
14
+ summaryGuidance: z.boolean().default(true),
15
+ summaryContextDivisor: z.number().step(1).min(1).max(Number.MAX_SAFE_INTEGER).default(DEFAULT_SUMMARY_DIVISOR),
14
16
  });
15
17
 
16
18
  const PACKAGE = 'dsh-strata-sync';
@@ -139,7 +141,8 @@ export function apply(ctx, initialConfig) {
139
141
  }
140
142
  function publicSettings(value = settings) {
141
143
  return { providerId: value.providerId ?? '', autoSync: value.autoSync ?? false,
142
- followLoadedModel: value.followLoadedModel ?? true, outputTokens: value.outputTokens ?? null };
144
+ followLoadedModel: value.followLoadedModel ?? true, outputTokens: value.outputTokens ?? null,
145
+ summaryGuidance: value.summaryGuidance ?? true, summaryContextDivisor: value.summaryContextDivisor ?? DEFAULT_SUMMARY_DIVISOR };
143
146
  }
144
147
  function status() {
145
148
  refreshSettings();
@@ -193,7 +196,11 @@ export function apply(ctx, initialConfig) {
193
196
  // A server/client mismatch must not enlarge the target past either capacity.
194
197
  return Math.min(discovered.model.contextWindow, model.contextWindow);
195
198
  }
196
- installSummaryGuidance(ctx, summaryContext);
199
+ installSummaryGuidance(ctx, summaryContext, () => {
200
+ ensureOpen();
201
+ refreshSettings();
202
+ return settings;
203
+ });
197
204
  async function preview(request = {}) {
198
205
  ensureOpen();
199
206
  payload(request, ['providerId', 'outputTokens']);
@@ -377,7 +384,7 @@ export function apply(ctx, initialConfig) {
377
384
  }
378
385
  async function configure(request) {
379
386
  ensureOpen();
380
- payload(request, ['providerId', 'autoSync', 'followLoadedModel', 'outputTokens', 'expectedRevision']);
387
+ payload(request, ['providerId', 'autoSync', 'followLoadedModel', 'outputTokens', 'summaryGuidance', 'summaryContextDivisor', 'expectedRevision']);
381
388
  refreshSettings();
382
389
  if (typeof request.expectedRevision !== 'string' || request.expectedRevision !== hash(publicSettings())) {
383
390
  refuse('stale-settings', 'Sync preferences changed. Reload the latest preferences before saving.');
@@ -388,11 +395,17 @@ export function apply(ctx, initialConfig) {
388
395
  if (typeof request.providerId !== 'string') refuse('invalid-request', 'Provider must be a string.');
389
396
  next.providerId = request.providerId;
390
397
  }
391
- for (const key of ['autoSync', 'followLoadedModel']) {
398
+ for (const key of ['autoSync', 'followLoadedModel', 'summaryGuidance']) {
392
399
  if (!own(request, key)) continue;
393
400
  if (typeof request[key] !== 'boolean') refuse('invalid-request', `${key} must be a boolean.`);
394
401
  next[key] = request[key];
395
402
  }
403
+ if (own(request, 'summaryContextDivisor')) {
404
+ if (!Number.isSafeInteger(request.summaryContextDivisor) || request.summaryContextDivisor < 1) {
405
+ refuse('invalid-budget', 'Summary context divisor must be a positive safe integer.');
406
+ }
407
+ next.summaryContextDivisor = request.summaryContextDivisor;
408
+ }
396
409
  if (own(request, 'outputTokens')) {
397
410
  if (request.outputTokens === null) delete next.outputTokens;
398
411
  else if (Number.isSafeInteger(request.outputTokens) && request.outputTokens > 0) next.outputTokens = request.outputTokens;
@@ -403,8 +416,7 @@ export function apply(ctx, initialConfig) {
403
416
  // Editing our own entry can dispose this plugin before edit() resolves.
404
417
  // Build the response while this Cordis scope is still alive; never read its
405
418
  // injected services after Loader replaces it.
406
- const response = { ...status(), providerId: next.providerId, autoSync: next.autoSync,
407
- followLoadedModel: next.followLoadedModel, outputTokens: next.outputTokens ?? null,
419
+ const response = { ...status(), ...publicSettings(next),
408
420
  settingsRevision: hash(publicSettings(next)), lastPreview: null, lastError: null };
409
421
  await backup();
410
422
  ensureOpen();
package/dist/summary.mjs CHANGED
@@ -7,10 +7,11 @@ const positive = value => Number.isSafeInteger(value) && value > 0;
7
7
  // Eight mandatory headings need enough space for a meaningful checkpoint. Do
8
8
  // not round a tiny target UP; leave native behavior intact instead.
9
9
  export const MIN_SUMMARY_TARGET = 256;
10
+ export const DEFAULT_SUMMARY_DIVISOR = 16;
10
11
 
11
- export function planSummaryTarget(contextWindow, summaryMaxTokens, sourceTokens) {
12
- if (![contextWindow, summaryMaxTokens, sourceTokens].every(positive)) return null;
13
- const target = Math.floor(Math.min(contextWindow / 16, summaryMaxTokens / 2, sourceTokens / 2));
12
+ export function planSummaryTarget(contextWindow, summaryMaxTokens, sourceTokens, divisor = DEFAULT_SUMMARY_DIVISOR) {
13
+ if (![contextWindow, summaryMaxTokens, sourceTokens, divisor].every(positive)) return null;
14
+ const target = Math.floor(Math.min(contextWindow / divisor, summaryMaxTokens / 2, sourceTokens / 2));
14
15
  return target >= MIN_SUMMARY_TARGET ? target : null;
15
16
  }
16
17
 
@@ -65,12 +66,24 @@ export function estimateSummarySource(messages) {
65
66
  * messages property for the lifetime of this stream; never mutate frozen
66
67
  * messages or recursively dispatch a second LLM request.
67
68
  */
68
- export function installSummaryGuidance(ctx, resolveContext) {
69
+ export function installSummaryGuidance(ctx, resolveContext, getSettings = () => ({})) {
69
70
  let closed = false;
71
+ function preferences() {
72
+ try {
73
+ const value = getSettings();
74
+ const enabled = value.summaryGuidance === undefined ? true : value.summaryGuidance;
75
+ const divisor = value.summaryContextDivisor === undefined ? DEFAULT_SUMMARY_DIVISOR : value.summaryContextDivisor;
76
+ return enabled === true && positive(divisor) ? { divisor } : null;
77
+ } catch { return null; }
78
+ }
70
79
  const remove = ctx.on('llm/stream', (options, next) => {
71
80
  const native = nativeSummaryMessage(options);
72
81
  const descriptor = options && Object.getOwnPropertyDescriptor(options, 'messages');
73
82
  if (closed || !native || !descriptor?.writable || options.signal?.aborted) return next();
83
+ // Disabled guidance must not perform even metadata discovery. Native DSH
84
+ // compaction and its request options still pass through unchanged.
85
+ const selected = preferences();
86
+ if (!selected) return next();
74
87
  const sourceTokens = estimateSummarySource(options.messages);
75
88
  if (!positive(sourceTokens) || !positive(options.maxTokens)) return next();
76
89
  return (async function* () {
@@ -80,8 +93,9 @@ export function installSummaryGuidance(ctx, resolveContext) {
80
93
  let contextWindow;
81
94
  try { contextWindow = await resolveContext(options); }
82
95
  catch { /* Metadata/compatibility failure must not break native inference. */ }
83
- const target = planSummaryTarget(contextWindow, options.maxTokens, sourceTokens);
84
- if (!closed && !options.signal?.aborted && target !== null && options.messages === original) {
96
+ const target = planSummaryTarget(contextWindow, options.maxTokens, sourceTokens, selected.divisor);
97
+ const current = preferences();
98
+ if (!closed && !options.signal?.aborted && current?.divisor === selected.divisor && target !== null && options.messages === original) {
85
99
  const last = { ...native, content: [{ ...native.content[0], text: `${native.content[0].text}\n- ${summaryInstruction(target)}` }] };
86
100
  augmented = [...original.slice(0, -1), last];
87
101
  options.messages = augmented;
@@ -6,28 +6,36 @@
6
6
 
7
7
  UI 支持 English、简体中文、繁體中文。自动跟随 DSH 界面语言并实时更新,不提供独立语言菜单。DSH 的 `zh` 对应简体中文,`zh-Hant`、`zh-TW`、`zh-HK`、`zh-MO` 对应繁体中文;其他语言使用英文。服务器返回的未知诊断消息保留原文,方便排查。
8
8
 
9
- 0.8.1 的动态摘要引导会在每次支持的 Strata 摘要请求前计算长度目标,并在 DSH 原生摘要提示词后**只补充一句**。保留原提示词、输出硬上限与其他设置;设置页解释公式,并区分写作目标与输出硬上限。已有同步保护、启动行为、能力验证及备份机制保持不变。
9
+ 0.9.0 在设置页加入**默认开启的摘要提示补充开关**与可调整的**上下文除数**。启用时,在每次支持的 Strata 摘要请求前计算长度目标,并在 DSH 原生摘要提示词后**只补充一句**。保留原提示词、输出硬上限与其他设置;已有同步保护、启动行为、能力验证及备份机制保持不变。
10
10
 
11
11
  ## 功能
12
12
 
13
13
  ### 动态摘要引导
14
14
 
15
- 对于支持的 Strata 路由,插件在每次 DSH 原生摘要请求前重新计算写作目标:
15
+ 摘要提示补充默认开启。对于支持的 Strata 路由,插件在每次 DSH 原生摘要请求前重新计算写作目标:
16
16
 
17
17
  ```text
18
18
  上下文 = min(已确认的 Strata 上下文, DSH 已有模型上下文)
19
- 目标 = floor(min(上下文 / 16,
19
+ 除数 = summaryContextDivisor(默认 16)
20
+ 目标 = floor(min(上下文 / 除数,
20
21
  本次摘要实际 maxTokens / 2,
21
22
  待替换内容的估算 tokens / 2))
22
23
  ```
23
24
 
24
25
  内容估算只包含这次要替换的对话片段,以及片段内已有的摘要;不包含系统提示词和工具定义。插件在每次摘要前通过只读查询核对 Strata 当前加载模型与上下文,并读取本次摘要请求的实际输出硬上限。上下文取服务器已确认值与 DSH 已有模型设置的较小值,不会因为服务器窗口较大而悄悄扩大较小的客户端预算。目标不是启动 DSH 或同步设置时固定下来的。
25
26
 
26
- 摘要硬上限为 4,096、原文足够长时,32K 上下文对应 **2,048 tokens**,64K 对应 **2,048 tokens**;内容较短时目标会降低。**设置 → dsh-strata-sync** 显示公式与本次预览的目标上限,无法提前得知未来摘要的实际目标。
27
+ 采用默认除数 16、摘要硬上限为 4,096、原文足够长时,32K 上下文对应 **2,048 tokens**,64K 对应 **2,048 tokens**;内容较短时目标会降低。**设置 → dsh-strata-sync** 显示公式与本次预览的目标上限,无法提前得知未来摘要的实际目标。
28
+
29
+ 在“动态摘要目标”区域,可切换“**启用摘要提示补充**”,并将“**上下文除数(上下文 ÷ N)**”设为正的安全整数。除数越小,目标可能越大,但仍受摘要输出上限和原文长度约束。例如,32K 上下文、4,096-token 摘要上限且原文足够长时,除数 32、16、8 的目标分别为 1,024、2,048、2,048 tokens。点击“**保存偏好**”后,后续支持的摘要请求会采用新选择。仅保存这两个控件不会同步模型预算或修改 Strata Server 设置。
30
+
31
+ | 插件偏好 | 默认值 | 含义 |
32
+ |---|---:|---|
33
+ | `summaryGuidance` | `true` | 对支持的摘要请求补充长度指令;关闭后仍保留 DSH 原生摘要和自动压缩。 |
34
+ | `summaryContextDivisor` | `16` | 以上下文除以此正的安全整数,计算摘要目标的一个约束。 |
27
35
 
28
36
  插件只补充一句英文,要求模型按目标长度完成摘要、保留接续未完成工作所需的信息、整合旧摘要,并删除重复或过时细节。原生提示词、八个章节和已有请求参数保持不变。这是启发式写作目标,**不是新的输出硬上限、最佳值,也不能保证不截断**;不增加自动重试流程或额外推理请求。
29
37
 
30
- 无法确认路由、必要信息或原生摘要格式,或无法安全估算图片/文件附件的 token 用量时,原请求不变并交给 DSH 处理。请求已取消或插件已禁用时也保留原生处理。计算目标小于 256 tokens 时不补充句子,避免给八个章节强加过小的目标;不取消原生摘要,也不以空摘要替换原文。禁用或移除插件后不再补充这句话,不会改写已保存的对话历史。
38
+ 无法确认路由、必要信息或原生摘要格式,或无法安全估算图片/文件附件的 token 用量时,原请求不变并交给 DSH 处理。请求已取消、提示补充已关闭或插件已禁用时也保留原生处理。计算目标小于 256 tokens 时不补充句子,避免给八个章节强加过小的目标;不取消原生摘要,也不以空摘要替换原文。关闭提示补充或移除插件后不再补充这句话,不会改写已保存的对话历史。
31
39
 
32
40
  ### 模型能力自动同步(0.4.0)
33
41
 
@@ -66,7 +74,7 @@ dsh plugin --profile desktop add dsh-strata-sync --registry=https://registry.npm
66
74
 
67
75
  完成后重新打开 DSH。首次安装会自动选中 bundle;已安装但禁用的 bundle 需在插件管理器重新启用。
68
76
 
69
- 要安装**包含动态摘要引导的 0.8.1**,请使用 Node.js 22 或更新版本从此源码构建,并在最后的安装命令前完成任务、完全退出 DSH Desktop:
77
+ 要从源码安装**包含摘要提示补充控件的 0.9.0**,请使用 Node.js 22 或更新版本构建,并在最后的安装命令前完成任务、完全退出 DSH Desktop:
70
78
 
71
79
  ```sh
72
80
  git clone https://github.com/ethan741205/dsh-strata-sync.git
@@ -74,7 +82,7 @@ cd dsh-strata-sync
74
82
  npm ci
75
83
  npm test
76
84
  npm pack
77
- dsh plugin --profile desktop add ./dsh-strata-sync-0.8.1.tgz
85
+ dsh plugin --profile desktop add ./dsh-strata-sync-0.9.0.tgz
78
86
  ```
79
87
 
80
88
  执行最后一行前同样需要完全退出 DSH Desktop,安装完成后重新打开。在其他目录执行时,请使用安装包的绝对路径。
@@ -87,6 +95,8 @@ dsh plugin --profile desktop add ./dsh-strata-sync-0.8.1.tgz
87
95
  4. 如需自动同步,勾选“启动 DSH 时自动同步”并保存,下次启动生效。原有 `autoSync: true` 会沿用为启动同步。
88
96
  5. 开启新对话,使用更新后的 Agent 预设。
89
97
 
98
+ “动态摘要目标”控件独立于模型同步。保持“启用摘要提示补充”开启、除数为 16 即沿用先前行为,也可修改后保存偏好。关闭此开关不会禁用 DSH 自身的压缩功能。
99
+
90
100
  无需把 API key 复制到此插件;认证问题请在 DSH 模型设置处理。
91
101
 
92
102
  ## 兼容性
@@ -135,6 +145,8 @@ ConfigEditor 负责单项原子写入与热加载;跨多项设置采用补偿
135
145
 
136
146
  ## 开发与版本
137
147
 
148
+ 0.9.0 加入默认开启的摘要提示补充开关及可调整的上下文除数(默认 16),沿用偏好保存与版本冲突保护,并同步三语界面和文档。保存这两个控件不改变原生摘要指令、输出硬上限、其他预算或服务器设置。
149
+
138
150
  0.5.0 移除独立语言菜单与产品声明,改为跟随 DSH 语言及启动时单次同步。0.3.0 首次加入三语 UI,0.2.0 将 UI 移入原生设置。
139
151
 
140
152
  `src/plugin.mjs` 为宿主插件,`src/client.js` 为原生 ModuleLoader/React UI,`src/core.mjs` 负责信息读取与纯预算计算,`src/summary.mjs` 提供原生摘要请求中间件。执行 `npm test`、`npm run build`、`npm pack --dry-run` 验证。安装包只包含原创插件代码,不包含私人应用程序源码、认证或对话。
@@ -6,28 +6,36 @@
6
6
 
7
7
  UI 支援 English、简体中文、繁體中文。自動跟隨 DSH 介面語言並即時更新,不提供獨立語言選單。DSH 的 `zh` 對應簡體中文,`zh-Hant`、`zh-TW`、`zh-HK`、`zh-MO` 對應繁體中文;其他語言使用英文。伺服器傳回的未知診斷訊息保留原文,以利排查。
8
8
 
9
- 0.8.1 的動態摘要引導會在每次支援的 Strata 摘要請求前計算長度目標,並在 DSH 原生摘要提示詞後**只補充一句**。保留原提示詞、輸出硬上限與其他設定;設定頁解釋公式,並區分寫作目標與輸出硬上限。既有同步保護、啟動行為、能力驗證及備份機制保持不變。
9
+ 0.9.0 在設定頁加入**預設開啟的摘要提示補充開關**與可調整的**上下文除數**。啟用時,在每次支援的 Strata 摘要請求前計算長度目標,並在 DSH 原生摘要提示詞後**只補充一句**。保留原提示詞、輸出硬上限與其他設定;既有同步保護、啟動行為、能力驗證及備份機制保持不變。
10
10
 
11
11
  ## 功能
12
12
 
13
13
  ### 動態摘要引導
14
14
 
15
- 對於支援的 Strata 路由,外掛在每次 DSH 原生摘要請求前重新計算寫作目標:
15
+ 摘要提示補充預設開啟。對於支援的 Strata 路由,外掛在每次 DSH 原生摘要請求前重新計算寫作目標:
16
16
 
17
17
  ```text
18
18
  上下文 = min(已確認的 Strata 上下文, DSH 既有模型上下文)
19
- 目標 = floor(min(上下文 / 16,
19
+ 除數 = summaryContextDivisor(預設 16)
20
+ 目標 = floor(min(上下文 / 除數,
20
21
  本次摘要實際 maxTokens / 2,
21
22
  待替換內容的估算 tokens / 2))
22
23
  ```
23
24
 
24
25
  內容估算只包含這次要替換的對話片段,以及片段內既有的摘要;不包含系統提示詞和工具定義。外掛在每次摘要前透過唯讀查詢核對 Strata 目前載入模型與上下文,並讀取本次摘要請求的實際輸出硬上限。上下文取伺服器已確認值與 DSH 既有模型設定的較小值,不會因為伺服器視窗較大而偷偷擴大較小的客戶端預算。目標不是啟動 DSH 或同步設定時固定下來的。
25
26
 
26
- 摘要硬上限為 4,096、原文足夠長時,32K 上下文對應 **2,048 tokens**,64K 對應 **2,048 tokens**;內容較短時目標會降低。**設定 → dsh-strata-sync** 顯示公式與本次預覽的目標上限,無法提前得知未來摘要的實際目標。
27
+ 採用預設除數 16、摘要硬上限為 4,096、原文足夠長時,32K 上下文對應 **2,048 tokens**,64K 對應 **2,048 tokens**;內容較短時目標會降低。**設定 → dsh-strata-sync** 顯示公式與本次預覽的目標上限,無法提前得知未來摘要的實際目標。
28
+
29
+ 在「動態摘要目標」區域,可切換「**啟用摘要提示補充**」,並將「**上下文除數(上下文 ÷ N)**」設為正的安全整數。除數越小,目標可能越大,但仍受摘要輸出上限和原文長度約束。例如,32K 上下文、4,096-token 摘要上限且原文足夠長時,除數 32、16、8 的目標分別為 1,024、2,048、2,048 tokens。按「**儲存偏好**」後,後續支援的摘要請求會採用新選擇。僅儲存這兩個控制項不會同步模型預算或修改 Strata Server 設定。
30
+
31
+ | 外掛偏好 | 預設值 | 含義 |
32
+ |---|---:|---|
33
+ | `summaryGuidance` | `true` | 對支援的摘要請求補充長度指令;關閉後仍保留 DSH 原生摘要和自動壓縮。 |
34
+ | `summaryContextDivisor` | `16` | 以上下文除以此正的安全整數,計算摘要目標的一項限制。 |
27
35
 
28
36
  外掛只補充一句英文,要求模型依目標長度完成摘要、保留接續未完成工作所需的資訊、整合舊摘要,並刪除重複或過時細節。原生提示詞、八個章節和既有請求參數保持不變。這是啟發式寫作目標,**不是新的輸出硬上限、最佳值,也不能保證不截斷**;不增加自動重試流程或額外推論請求。
29
37
 
30
- 無法確認路由、必要資訊或原生摘要格式,或無法安全估算圖片/檔案附件的 token 用量時,原請求不變並交由 DSH 處理。請求已取消或外掛已停用時也保留原生處理。計算目標小於 256 tokens 時不補充句子,避免給八個章節強加過小的目標;不取消原生摘要,也不以空摘要替換原文。停用或移除外掛後不再補充這句話,不會改寫已儲存的對話歷史。
38
+ 無法確認路由、必要資訊或原生摘要格式,或無法安全估算圖片/檔案附件的 token 用量時,原請求不變並交由 DSH 處理。請求已取消、提示補充已關閉或外掛已停用時也保留原生處理。計算目標小於 256 tokens 時不補充句子,避免給八個章節強加過小的目標;不取消原生摘要,也不以空摘要替換原文。關閉提示補充或移除外掛後不再補充這句話,不會改寫已儲存的對話歷史。
31
39
 
32
40
  ### 模型能力自動同步(0.4.0)
33
41
 
@@ -66,7 +74,7 @@ dsh plugin --profile desktop add dsh-strata-sync --registry=https://registry.npm
66
74
 
67
75
  完成後重新開啟 DSH。首次安裝會自動選取 bundle;已安裝但停用的 bundle 需在外掛管理員重新啟用。
68
76
 
69
- 要安裝**包含動態摘要引導的 0.8.1**,請使用 Node.js 22 或更新版本從此原始碼建置,並在最後的安裝命令前完成工作、完全結束 DSH Desktop:
77
+ 要從原始碼安裝**包含摘要提示補充控制項的 0.9.0**,請使用 Node.js 22 或更新版本建置,並在最後的安裝命令前完成工作、完全結束 DSH Desktop:
70
78
 
71
79
  ```sh
72
80
  git clone https://github.com/ethan741205/dsh-strata-sync.git
@@ -74,7 +82,7 @@ cd dsh-strata-sync
74
82
  npm ci
75
83
  npm test
76
84
  npm pack
77
- dsh plugin --profile desktop add ./dsh-strata-sync-0.8.1.tgz
85
+ dsh plugin --profile desktop add ./dsh-strata-sync-0.9.0.tgz
78
86
  ```
79
87
 
80
88
  執行最後一行前同樣需要完全結束 DSH Desktop,安裝完成後重新開啟。在其他目錄執行時,請使用套件的絕對路徑。
@@ -87,6 +95,8 @@ dsh plugin --profile desktop add ./dsh-strata-sync-0.8.1.tgz
87
95
  4. 如需自動同步,勾選「啟動 DSH 時自動同步」並儲存,下次啟動生效。原有 `autoSync: true` 會沿用為啟動同步。
88
96
  5. 開啟新對話,使用更新後的 Agent 範本。
89
97
 
98
+ 「動態摘要目標」控制項獨立於模型同步。保持「啟用摘要提示補充」開啟、除數為 16 即沿用先前行為,也可修改後儲存偏好。關閉此開關不會停用 DSH 自身的壓縮功能。
99
+
90
100
  不需要把 API key 複製到此外掛;認證問題請在 DSH 模型設定處理。
91
101
 
92
102
  ## 相容性
@@ -135,6 +145,8 @@ ConfigEditor 負責個別原子寫入與熱載入;跨多項設定採補償回
135
145
 
136
146
  ## 開發與版本
137
147
 
148
+ 0.9.0 加入預設開啟的摘要提示補充開關及可調整的上下文除數(預設 16),沿用偏好儲存與版本衝突保護,並同步三語介面和文件。儲存這兩個控制項不改變原生摘要指令、輸出硬上限、其他預算或伺服器設定。
149
+
138
150
  0.5.0 移除獨立語言選單與產品聲明,改為跟隨 DSH 語言及啟動時單次同步。0.3.0 首次加入三語 UI,0.2.0 將 UI 移入原生設定。
139
151
 
140
152
  `src/plugin.mjs` 為宿主外掛,`src/client.js` 為原生 ModuleLoader/React UI,`src/core.mjs` 負責資訊讀取與純預算計算,`src/summary.mjs` 提供原生摘要請求中介層。執行 `npm test`、`npm run build`、`npm pack --dry-run` 驗證。套件只包含原創外掛程式,不包含私人應用程式原始碼、認證或對話。
@@ -2,6 +2,13 @@
2
2
 
3
3
  Validation date: 2026-10-30 (Asia/Taipei).
4
4
 
5
+ ## Summary guidance controls 0.9.0
6
+
7
+ - Adds persisted `summaryGuidance` (default `true`) and `summaryContextDivisor` (default `16`). The divisor must be a positive safe integer. Saving these controls uses the existing backup, idle and revision checks and leaves model settings and compaction budgets unchanged.
8
+ - Backend tests cover native schema defaults and validation, persisted controls across reloads, disabling without metadata requests, re-enabling with a custom divisor, unchanged native compaction, source/output bounds, and changes during discovery. The three-language UI tests cover default-on controls, saving, invalid input, external changes/conflicts, custom previews, disabled state and below-256 fallback messages.
9
+ - A local probe exercised the installed DSH 0.2.1-rc.3 `BasicCompactionEngine.summarize()` through its actual Cordis waterfall. At 32K with a 4,096 summary cap, the default divisor produced 2,048, divisor 32 produced 1,024, disabled guidance preserved the native prompt without discovery, and divisor 8 remained capped at 2,048. Original prompt content, input, output cap, tools and configuration were preserved; unloading restored native behavior. Responses were synthetic: no inference requests were sent.
10
+ - All **142 automated tests pass**, including the package verifier and 33 settings UI tests. These checks validate configuration and integration, not a measured reduction in real-model truncation or compaction frequency.
11
+
5
12
  ## Package rename and target ratio 0.8.1
6
13
 
7
14
  - Package identity, native bundle and client module now use `dsh-strata-sync`; the GitHub repository is unchanged. Existing scoped installations must be migrated, not loaded alongside the renamed plugin.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-strata-sync",
3
- "version": "0.8.1",
3
+ "version": "0.9.0",
4
4
  "description": "Native DSH settings UI for synchronizing Strata Server models, context and compaction budgets",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",