@foggy-projects/deepseek-harness-plugin 0.4.0-rc.1 → 0.4.0-rc.3

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
@@ -3,7 +3,9 @@
3
3
  This package is the lightweight DeepSeek Harness Bundle for Foggy's Java data
4
4
  analysis engine. Installing the Bundle adds a native Foggy tab under **Settings
5
5
  → Plugins**. The private Python runtime, Launcher, and isolated CLI environment
6
- are downloaded only when the user selects **Initialize Foggy**.
6
+ are downloaded only when the user selects **Initialize and start** (or the
7
+ equivalent component action). Existing installations are not silently changed
8
+ when the plugin package is upgraded.
7
9
 
8
10
  DeepSeek Harness uses a system Node.js (`^22.19.0 || >=24.0.0`) and Foggy's Java
9
11
  Launcher uses a system Java 17+. Foggy manages its own pinned Python 3.12 runtime
@@ -14,7 +16,7 @@ modify `PATH`, or register Python globally. Advanced users may explicitly set
14
16
  ## Local beta installation
15
17
 
16
18
  ```powershell
17
- dsh plugin --profile web add --workspace-root ./foggy-projects-deepseek-harness-plugin-0.4.0-rc.1.tgz
19
+ dsh plugin --profile web add --workspace-root ./foggy-projects-deepseek-harness-plugin-0.4.0-rc.3.tgz
18
20
  ```
19
21
 
20
22
  Restart `dsh web`, use the browser it opens (or the complete printed URL,
@@ -27,6 +29,13 @@ After npm beta publication, the corresponding one-line install is:
27
29
  dsh plugin --profile web add --workspace-root @foggy-projects/deepseek-harness-plugin@beta
28
30
  ```
29
31
 
32
+ After updating the plugin package, open **Settings → Plugins → Foggy Data
33
+ Analysis** and use **Update components** (or **Update and start**) to download
34
+ the pinned CLI, Launcher, and Skills. The settings page shows current and target
35
+ versions. Updates are blocked while Runtime is running so the active Java
36
+ process and the next-launcher state cannot diverge. Component-specific repair
37
+ actions remain available under **Advanced repair**.
38
+
30
39
  DeepSeek Harness 0.1.2-rc.1 applies pnpm's minimum-release-age policy to its
31
40
  profile lockfile. An upgrade performed shortly after publication can therefore
32
41
  fail while naming either the new plugin or the previously installed Beta. This
@@ -1,10 +1,10 @@
1
- # Public beta readiness: 0.4.0-rc.1
1
+ # Public beta readiness: 0.4.0-rc.2
2
2
 
3
3
  Assessment date: 2026-09-05
4
4
 
5
5
  ## Verdict
6
6
 
7
- `0.4.0-rc.1` is suitable for a scoped public beta on Windows 10/11 x64 and
7
+ `0.4.0-rc.2` is suitable for a scoped public beta on Windows 10/11 x64 and
8
8
  Linux/WSL2 x64. It is not a general-availability release.
9
9
 
10
10
  The plugin package stays small and downloads large components only during
@@ -31,7 +31,7 @@ system PATH, registry, or a user's existing Python installation.
31
31
  Runtime. The password is excluded from onboarding state and evidence, and
32
32
  datasource setup does not trigger Runtime restart. Opaque profiles remain an
33
33
  optional advanced path.
34
- - A real Launcher 0.1.20 smoke on Java 17 accepted a synthetic inline-password
34
+ - A real Launcher 0.1.21 smoke on Java 17 accepted a synthetic inline-password
35
35
  datasource through the public Runtime API while retaining the same Java PID.
36
36
  The isolated registry confirmed the documented local-development plaintext
37
37
  persistence boundary; the test datasource was then removed and the temporary
@@ -41,8 +41,8 @@ system PATH, registry, or a user's existing Python installation.
41
41
  PID, while the persisted onboarding state and command evidence contained no
42
42
  copy of the synthetic password.
43
43
  - The package and settings contract report Python 3.12.13 as `Foggy private`,
44
- CLI 0.1.23, Launcher 0.1.20, analysis Skill 0.1.17, and onboarding Skill
45
- 0.4.0-rc.1; the same component display was accepted in the preceding
44
+ CLI 0.1.23, Launcher 0.1.21, analysis/query Skills 0.1.18, and onboarding Skill
45
+ 0.4.0-rc.2; the same component display was accepted in the preceding
46
46
  native Windows beta run.
47
47
  - Runtime startup now reports the current phase, elapsed/timeout seconds, and a
48
48
  bounded progress value. A real Windows launch with Temurin 17 reached readiness
@@ -67,7 +67,7 @@ system PATH, registry, or a user's existing Python installation.
67
67
  new datasource tests cover secret-free persisted state, direct Runtime API
68
68
  submission, CLI bypass for inline development credentials, stable inline
69
69
  credential resumption, bounded transient connection retry, and output redaction.
70
- - A real Java 17 / Launcher 0.1.20 regression resumed the same completed inline
70
+ - A real Java 17 / Launcher 0.1.21 regression resumed the same completed inline
71
71
  datasource composite twice, retained the Runtime PID, and emitted a complete
72
72
  `01` through `06` workspace evidence sequence without falling back to granular
73
73
  commands.
@@ -0,0 +1,38 @@
1
+ # Foggy DeepSeek Harness plugin 0.4.0-rc.2 release candidate
2
+
3
+ Assessment date: 2026-09-06
4
+
5
+ ## Decision
6
+
7
+ This build is a public preview for Windows 10/11 x64 and Linux/WSL2 x64. It
8
+ remains a development and evaluation plugin; the bundled Runtime defaults are
9
+ not a production security profile.
10
+
11
+ No Java engine or `foggy-runtime-cli` source was changed for this candidate.
12
+ The plugin consumes the independently accepted CLI 0.1.23, Runtime Launcher
13
+ 0.1.21, foggy-ai-analysis Skill 0.1.18, and foggy-semantic-query Skill 0.1.18
14
+ public releases.
15
+
16
+ ## Delta from rc.1
17
+
18
+ - Upgrade Runtime Launcher from 0.1.20 to 0.1.21.
19
+ - Upgrade foggy-ai-analysis from 0.1.17 to 0.1.18.
20
+ - Install and register foggy-semantic-query 0.1.18 as a second managed Skill.
21
+ - Keep DeepSeek Harness 0.1.2-rc.1, managed Python 3.12.13, CLI 0.1.23, and the
22
+ default Runtime port 18166 unchanged.
23
+
24
+ The new public assets and their nested Skill manifests were independently
25
+ checksum-verified. Runtime acceptance covered automatic static-dictionary
26
+ captions, label-to-code filtering, dictionary member enumeration, self-date
27
+ dimensions, and the `$year`, `$month`, and `$yearMonth` describe/query path.
28
+
29
+ ## Publication gate
30
+
31
+ The plugin's existing automated tests and npm tarball inspection must pass.
32
+ The Runtime functional matrix is not repeated because the exact public
33
+ Launcher and Skill assets were accepted independently before this pin update.
34
+
35
+ DeepSeek Harness minimum-release-age policy can reject a recently published
36
+ version still present in a profile lockfile. Users should inspect and rebuild
37
+ the profile lockfile or wait for the policy window rather than weakening
38
+ plugin integrity checks.
@@ -0,0 +1,18 @@
1
+ # Foggy DeepSeek Harness plugin 0.4.0-rc.3 release candidate
2
+
3
+ Assessment date: 2026-09-06
4
+
5
+ ## Delta from rc.2
6
+
7
+ - Add a single **Initialize and start** action for first use.
8
+ - Add **Update components** and **Update and start** actions for managed CLI,
9
+ Launcher, and Skill assets after a plugin-package upgrade.
10
+ - Show current versus target component versions and an explicit update banner.
11
+ - Block component update/repair while Runtime is running; the active Launcher
12
+ process must not diverge from the persisted next-launcher version.
13
+ - Keep Refresh, diagnostics, and component-specific repair actions in the
14
+ secondary/advanced action areas.
15
+ - Add public documentation, plugin repository, release, and Runtime project
16
+ links to the settings page.
17
+
18
+ No Java engine or `foggy-runtime-cli` source was changed.
@@ -1,7 +1,7 @@
1
1
  # Native Windows Beta acceptance
2
2
 
3
3
  This runbook validates DeepSeek Harness `0.1.2-rc.1` with Foggy plugin
4
- `0.4.0-rc.1` on a clean 64-bit Windows 10 or Windows 11 machine. Use a local
4
+ `0.4.0-rc.2` on a clean 64-bit Windows 10 or Windows 11 machine. Use a local
5
5
  directory that is not synchronized by OneDrive.
6
6
 
7
7
  ## Prerequisites
@@ -60,9 +60,9 @@ Expected component state:
60
60
 
61
61
  - Python 3.12.13, source `Foggy private`;
62
62
  - CLI 0.1.23;
63
- - Launcher 0.1.20;
64
- - analysis Skill 0.1.17;
65
- - onboarding Skill 0.4.0-rc.1;
63
+ - Launcher 0.1.21;
64
+ - analysis/query Skills 0.1.18;
65
+ - onboarding Skill 0.4.0-rc.2;
66
66
  - Java 17+ available;
67
67
  - native DSH Skill registration available.
68
68
 
package/lib/client.js CHANGED
@@ -35,7 +35,7 @@ window.__ModuleLoader__.load({
35
35
  package: '@foggy-projects/deepseek-harness-plugin',
36
36
  descriptors: [
37
37
  ...[
38
- 'status', 'plan', 'initialize', 'repair', 'repairPython', 'repairCli', 'repairLauncher', 'repairAnalysisSkill',
38
+ 'status', 'plan', 'initialize', 'initializeAndStart', 'repair', 'updateComponents', 'repairPython', 'repairCli', 'repairLauncher', 'repairAnalysisSkill', 'repairSemanticQuerySkill',
39
39
  'migrateProfiles', 'diagnostics', 'runtimeStart', 'runtimeStop',
40
40
  ].map((method) => descriptor(method)),
41
41
  descriptor('saveRuntimeSettings', [{
@@ -54,7 +54,7 @@ window.__ModuleLoader__.load({
54
54
  const zh = {
55
55
  tab: 'Foggy 数据分析',
56
56
  title: 'Foggy Java 数据分析引擎',
57
- intro: '在 DeepSeek Harness 内管理 Foggy 私有 Python、CLI、Launcher、Skills 和本地 Runtime。大型组件在首次初始化时按需下载。',
57
+ intro: '在 DeepSeek Harness 内管理 Foggy 私有 Python、CLI、Launcher、Skills 和本地 Runtime。大型组件按需下载,插件升级后可在此处一键更新。',
58
58
  refresh: '刷新状态',
59
59
  loading: '正在读取 Foggy 状态…',
60
60
  failed: '暂时无法读取 Foggy 状态。',
@@ -66,25 +66,46 @@ window.__ModuleLoader__.load({
66
66
  cli: 'CLI',
67
67
  launcher: 'Launcher',
68
68
  analysisSkill: '分析 Skill',
69
+ semanticQuerySkill: '语义查询 Skill',
69
70
  onboardingSkill: '引导 Skill',
70
71
  skillRegistry: 'DSH Skill 注册',
71
72
  python: 'Python',
72
73
  java: 'Java',
73
74
  installed: '已安装',
74
75
  missing: '未安装',
76
+ upToDate: '最新',
77
+ updateAvailable: '有更新',
78
+ installedVersion: '当前版本',
79
+ targetVersion: '目标版本',
75
80
  available: '可用',
76
81
  unavailable: '不可用',
77
82
  initialize: '初始化 Foggy',
78
- repair: '重新下载 / 修复',
79
- repairTitle: '分组件检查与修复',
83
+ initializeAndStart: '初始化并启动',
84
+ initializeAndStartDone: 'Foggy 已初始化,Runtime 已启动。',
85
+ updateComponents: '更新组件',
86
+ updateAndStart: '更新并启动',
87
+ updateAndStartDone: '组件已更新,Runtime 已启动。',
88
+ repair: '修复组件',
89
+ repairTitle: '高级修复',
80
90
  repairPython: '检查 / 修复私有 Python',
81
91
  repairCli: '检查 / 修复 CLI',
82
92
  repairLauncher: '检查 / 修复 Launcher',
83
93
  repairAnalysisSkill: '检查 / 修复分析 Skill',
94
+ repairSemanticQuerySkill: '检查 / 修复语义查询 Skill',
84
95
  diagnostics: '导出诊断报告',
85
96
  diagnosticsSaved: '诊断报告已保存',
86
97
  start: '启动 Runtime',
87
98
  stop: '停止 Runtime',
99
+ updateBlockedRunning: 'Runtime 运行中,停止后才能更新组件。',
100
+ updateReady: '检测到组件更新;可点击“更新并启动”一次完成更新。',
101
+ updateNone: '所有托管组件均为当前版本。',
102
+ operationTimeout: '操作等待超时,请刷新状态或导出诊断报告。',
103
+ resourceTitle: '文档与项目',
104
+ docs: '使用文档',
105
+ project: '插件项目',
106
+ releases: '版本记录',
107
+ runtimeProject: 'Runtime 项目',
108
+ openExternal: '在新标签页打开',
88
109
  working: '操作进行中…',
89
110
  progressWorking: '正在初始化 Foggy…',
90
111
  progressPreflight: '检查运行环境',
@@ -92,6 +113,7 @@ window.__ModuleLoader__.load({
92
113
  progressCli: '准备 CLI',
93
114
  progressLauncher: '准备 Launcher',
94
115
  progressAnalysis: '准备分析 Skill',
116
+ progressSemanticQuery: '准备语义查询 Skill',
95
117
  progressSkills: '注册 DSH Skills',
96
118
  progressState: '写入安装状态',
97
119
  progressComplete: '初始化完成',
@@ -157,7 +179,7 @@ window.__ModuleLoader__.load({
157
179
  const en = {
158
180
  tab: 'Foggy Data Analysis',
159
181
  title: 'Foggy Java Data Analysis Engine',
160
- intro: 'Manage Foggy private Python, CLI, Launcher, Skills, and the local Runtime inside DeepSeek Harness. Large components are downloaded on first initialization.',
182
+ intro: 'Manage Foggy private Python, CLI, Launcher, Skills, and the local Runtime inside DeepSeek Harness. Large components download on demand, and plugin upgrades can be applied here in one step.',
161
183
  refresh: 'Refresh status',
162
184
  loading: 'Reading Foggy status…',
163
185
  failed: 'Foggy status is temporarily unavailable.',
@@ -169,25 +191,46 @@ window.__ModuleLoader__.load({
169
191
  cli: 'CLI',
170
192
  launcher: 'Launcher',
171
193
  analysisSkill: 'Analysis Skill',
194
+ semanticQuerySkill: 'Semantic Query Skill',
172
195
  onboardingSkill: 'Onboarding Skill',
173
196
  skillRegistry: 'DSH Skill registry',
174
197
  python: 'Python',
175
198
  java: 'Java',
176
199
  installed: 'Installed',
177
200
  missing: 'Missing',
201
+ upToDate: 'Up to date',
202
+ updateAvailable: 'Update available',
203
+ installedVersion: 'Current',
204
+ targetVersion: 'Target',
178
205
  available: 'Available',
179
206
  unavailable: 'Unavailable',
180
207
  initialize: 'Initialize Foggy',
181
- repair: 'Re-download / Repair',
182
- repairTitle: 'Component checks and repair',
208
+ initializeAndStart: 'Initialize and start',
209
+ initializeAndStartDone: 'Foggy was initialized and Runtime started.',
210
+ updateComponents: 'Update components',
211
+ updateAndStart: 'Update and start',
212
+ updateAndStartDone: 'Components were updated and Runtime started.',
213
+ repair: 'Repair components',
214
+ repairTitle: 'Advanced repair',
183
215
  repairPython: 'Check / repair private Python',
184
216
  repairCli: 'Check / repair CLI',
185
217
  repairLauncher: 'Check / repair Launcher',
186
218
  repairAnalysisSkill: 'Check / repair analysis Skill',
219
+ repairSemanticQuerySkill: 'Check / repair semantic query Skill',
187
220
  diagnostics: 'Export diagnostics',
188
221
  diagnosticsSaved: 'Diagnostics saved',
189
222
  start: 'Start Runtime',
190
223
  stop: 'Stop Runtime',
224
+ updateBlockedRunning: 'Runtime is running. Stop it before updating components.',
225
+ updateReady: 'Component updates are available. Use “Update and start” to finish in one step.',
226
+ updateNone: 'All managed components are up to date.',
227
+ operationTimeout: 'The operation timed out. Refresh the status or export diagnostics.',
228
+ resourceTitle: 'Documentation and project',
229
+ docs: 'User documentation',
230
+ project: 'Plugin project',
231
+ releases: 'Releases',
232
+ runtimeProject: 'Runtime project',
233
+ openExternal: 'Opens in a new tab',
191
234
  working: 'Operation in progress…',
192
235
  progressWorking: 'Initializing Foggy…',
193
236
  progressPreflight: 'Checking prerequisites',
@@ -195,6 +238,7 @@ window.__ModuleLoader__.load({
195
238
  progressCli: 'Preparing CLI',
196
239
  progressLauncher: 'Preparing Launcher',
197
240
  progressAnalysis: 'Preparing analysis Skill',
241
+ progressSemanticQuery: 'Preparing semantic query Skill',
198
242
  progressSkills: 'Registering DSH Skills',
199
243
  progressState: 'Writing install state',
200
244
  progressComplete: 'Initialization complete',
@@ -261,15 +305,17 @@ window.__ModuleLoader__.load({
261
305
  .foggy-settings{width:100%;max-width:820px;color:var(--dsw-alias-label-primary);display:flex;flex-direction:column;gap:16px}
262
306
  .foggy-hero{border:1px solid var(--dsw-alias-border-l2);background:linear-gradient(135deg,color-mix(in srgb,var(--dsw-alias-state-business-primary) 10%,var(--dsw-alias-bg-layer-3)),var(--dsw-alias-bg-layer-3));border-radius:12px;padding:18px}
263
307
  .foggy-title-row{display:flex;align-items:center;gap:10px}.foggy-title-row h3{margin:0;font-size:18px;line-height:26px}.foggy-beta{font-size:11px;padding:2px 7px;border-radius:999px;background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 14%,transparent);color:var(--dsw-alias-state-business-primary)}
264
- .foggy-intro{margin:8px 0 0;color:var(--dsw-alias-label-secondary);font-size:13px;line-height:20px}.foggy-toolbar{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}
308
+ .foggy-intro{margin:8px 0 0;color:var(--dsw-alias-label-secondary);font-size:13px;line-height:20px}.foggy-toolbar{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.foggy-toolbar-main,.foggy-toolbar-secondary{display:flex;gap:8px;flex-wrap:wrap;align-items:center}.foggy-toolbar-secondary{width:100%;padding-top:2px;border-top:1px solid var(--dsw-alias-border-l2)}
265
309
  .foggy-state{display:flex;align-items:center;gap:8px;font-size:14px;font-weight:600}.foggy-dot{width:9px;height:9px;border-radius:50%;background:var(--dsw-alias-label-tertiary)}.foggy-dot[data-state=ready],.foggy-dot[data-state=running]{background:var(--dsw-alias-state-success-primary)}.foggy-dot[data-state=degraded]{background:var(--dsw-alias-state-error-primary)}
266
- .foggy-actions{display:flex;gap:8px;flex-wrap:wrap}.foggy-button{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);font:inherit;border-radius:8px;padding:7px 12px;cursor:pointer}.foggy-button:hover{background:var(--dsw-alias-interactive-bg-hover)}.foggy-button:disabled{opacity:.55;cursor:not-allowed}.foggy-button-primary{border-color:var(--dsw-alias-state-business-primary);background:var(--dsw-alias-state-business-primary);color:white}
310
+ .foggy-actions{display:flex;gap:8px;flex-wrap:wrap}.foggy-button{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);font:inherit;border-radius:8px;padding:7px 12px;cursor:pointer;transition:background-color .15s ease,box-shadow .15s ease,transform .15s ease}.foggy-button:hover{background:var(--dsw-alias-interactive-bg-hover)}.foggy-button:active{transform:translateY(1px)}.foggy-button:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}.foggy-button:disabled{opacity:.55;cursor:not-allowed}.foggy-button-primary{border-color:var(--dsw-alias-state-business-primary);background:var(--dsw-alias-state-business-primary);color:white}
267
311
  .foggy-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}.foggy-card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:10px;padding:13px 14px}.foggy-card-head{display:flex;justify-content:space-between;gap:8px}.foggy-card strong{font-size:13px}.foggy-badge{font-size:11px;color:var(--dsw-alias-label-secondary)}.foggy-card code{display:block;margin-top:8px;color:var(--dsw-alias-label-tertiary);font-size:11px;overflow-wrap:anywhere}
268
312
  .foggy-progress{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:10px;padding:13px 14px}.foggy-progress-head{display:flex;align-items:center;justify-content:space-between;gap:12px;font-size:13px}.foggy-progress-head strong{font-weight:600}.foggy-progress-percent{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums}.foggy-progress-track{height:8px;margin-top:10px;border-radius:999px;background:var(--dsw-alias-bg-layer-1);overflow:hidden}.foggy-progress-fill{height:100%;border-radius:inherit;background:var(--dsw-alias-state-business-primary);transition:width .25s ease}.foggy-progress-meta{display:flex;justify-content:space-between;gap:12px;margin-top:8px;color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}.foggy-progress-file{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
269
313
  .foggy-runtime-settings{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:10px;padding:14px}.foggy-runtime-settings h4{margin:0;font-size:13px}.foggy-runtime-settings-row{display:grid;grid-template-columns:minmax(150px,220px) minmax(0,1fr) auto;align-items:end;gap:10px;margin-top:10px}.foggy-field{display:flex;flex-direction:column;gap:6px}.foggy-field label{font-size:12px;font-weight:600}.foggy-input{width:100%;box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);font:inherit;font-variant-numeric:tabular-nums;padding:8px 10px;outline:none}.foggy-input:focus{border-color:var(--dsw-alias-state-business-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--dsw-alias-state-business-primary) 18%,transparent)}.foggy-input[aria-invalid=true]{border-color:var(--dsw-alias-state-error-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--dsw-alias-state-error-primary) 14%,transparent)}.foggy-setting-meta{display:flex;flex-direction:column;gap:4px;min-width:0;color:var(--dsw-alias-label-tertiary);font-size:11px}.foggy-setting-meta code{overflow-wrap:anywhere;color:var(--dsw-alias-label-secondary)}
314
+ .foggy-update-banner{border:1px solid color-mix(in srgb,var(--dsw-alias-state-warning-primary) 55%,var(--dsw-alias-border-l2));background:color-mix(in srgb,var(--dsw-alias-state-warning-primary) 9%,transparent);border-radius:10px;padding:11px 13px;color:var(--dsw-alias-label-primary);font-size:12px;line-height:18px}.foggy-update-banner strong{color:var(--dsw-alias-state-warning-primary)}.foggy-update-list{margin:6px 0 0;padding-left:18px;color:var(--dsw-alias-label-secondary)}
315
+ .foggy-resources{border-top:1px solid var(--dsw-alias-border-l2);padding-top:14px}.foggy-resources h4{margin:0 0 9px;font-size:13px}.foggy-resource-links{display:flex;gap:8px;flex-wrap:wrap}.foggy-resource-link{display:inline-flex;align-items:center;gap:5px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:7px 10px;color:var(--dsw-alias-label-secondary);font-size:12px;text-decoration:none}.foggy-resource-link:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}.foggy-resource-link:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}
270
316
  .foggy-error-panel{border:2px solid var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 10%,var(--dsw-alias-bg-layer-3));border-radius:10px;padding:13px 14px;box-shadow:0 6px 18px color-mix(in srgb,var(--dsw-alias-state-error-primary) 13%,transparent)}.foggy-error-panel-head{display:flex;align-items:center;gap:8px;color:var(--dsw-alias-state-error-primary);font-size:14px;font-weight:700}.foggy-error-icon{display:grid;place-items:center;width:22px;height:22px;border-radius:50%;background:var(--dsw-alias-state-error-primary);color:white;font-size:14px}.foggy-error-panel p{margin:7px 0 0;color:var(--dsw-alias-label-primary);font-size:13px;line-height:20px;overflow-wrap:anywhere}.foggy-error-help{color:var(--dsw-alias-state-error-primary)!important;font-weight:600}
271
317
  .foggy-message{margin:0;font-size:13px;line-height:20px;color:var(--dsw-alias-label-secondary)}.foggy-message[data-error=true]{color:var(--dsw-alias-state-error-primary)}.foggy-paths,.foggy-next,.foggy-section{border-top:1px solid var(--dsw-alias-border-l2);padding-top:14px}.foggy-paths h4,.foggy-next h4,.foggy-section h4{margin:0 0 8px;font-size:13px}.foggy-paths dl{display:grid;grid-template-columns:100px minmax(0,1fr);gap:6px 10px;margin:0}.foggy-paths dt{color:var(--dsw-alias-label-tertiary);font-size:12px}.foggy-paths dd{margin:0;min-width:0;overflow-wrap:anywhere;font-family:var(--ds-font-family-code);font-size:11px}.foggy-next p,.foggy-section p{margin:0;color:var(--dsw-alias-label-secondary);font-size:13px;line-height:20px}.foggy-section-actions{display:flex;gap:8px;flex-wrap:wrap;margin-top:10px}.foggy-onboarding-head{display:flex;justify-content:space-between;gap:12px;align-items:start}.foggy-onboarding-head code{font-size:11px;color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere}.foggy-step-list{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:7px;margin-top:10px}.foggy-step{border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:8px;font-size:11px;color:var(--dsw-alias-label-tertiary)}.foggy-step[data-state=completed]{border-color:color-mix(in srgb,var(--dsw-alias-state-success-primary) 45%,var(--dsw-alias-border-l2));color:var(--dsw-alias-state-success-primary)}.foggy-step[data-state=failed],.foggy-step[data-state=invalid]{border-color:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-state-error-primary)}.foggy-warning{border:1px solid color-mix(in srgb,var(--dsw-alias-state-warning-primary) 55%,var(--dsw-alias-border-l2));background:color-mix(in srgb,var(--dsw-alias-state-warning-primary) 8%,transparent);border-radius:10px;padding:12px}.foggy-query-warning{margin-top:10px}.foggy-query-warning p+p{margin-top:5px}.foggy-query-warning code{overflow-wrap:anywhere}
272
- @media (width<=680px){.foggy-grid{grid-template-columns:minmax(0,1fr)}.foggy-runtime-settings-row{grid-template-columns:minmax(0,1fr)}.foggy-runtime-settings-row .foggy-button{width:100%}}
318
+ @media (width<=680px){.foggy-grid{grid-template-columns:minmax(0,1fr)}.foggy-runtime-settings-row{grid-template-columns:minmax(0,1fr)}.foggy-runtime-settings-row .foggy-button{width:100%}.foggy-toolbar-main{width:100%}.foggy-toolbar-main .foggy-button{flex:1}.foggy-resource-link{min-height:36px}}
273
319
  `
274
320
 
275
321
  if (typeof document !== 'undefined' && !document.querySelector('style[data-foggy-settings]')) {
@@ -289,16 +335,23 @@ window.__ModuleLoader__.load({
289
335
 
290
336
  function componentCard(label, component, kind, t) {
291
337
  const available = kind === 'runtime' ? component?.installed : component?.available
292
- const stateText = kind === 'runtime'
293
- ? t(available ? 'installed' : 'missing')
294
- : t(available ? 'available' : 'unavailable')
338
+ const stateText = component?.updateAvailable
339
+ ? t('updateAvailable')
340
+ : kind === 'runtime'
341
+ ? t(available ? 'installed' : 'missing')
342
+ : t(available ? 'available' : 'unavailable')
295
343
  const source = component?.source === 'managed'
296
344
  ? t('managedPrivate')
297
345
  : component?.source === 'override'
298
346
  ? t('configuredOverride')
299
347
  : null
300
348
  const detail = [
301
- component?.version || component?.output || '—',
349
+ component?.installedVersion
350
+ ? `${t('installedVersion')} ${component.installedVersion}`
351
+ : component?.version || component?.output || '—',
352
+ component?.targetVersion && component?.targetVersion !== component?.installedVersion
353
+ ? `${t('targetVersion')} ${component.targetVersion}`
354
+ : null,
302
355
  component?.minimum ? `≥${component.minimum}` : null,
303
356
  source,
304
357
  ].filter(Boolean).join(' · ')
@@ -315,6 +368,19 @@ window.__ModuleLoader__.load({
315
368
  })
316
369
  }
317
370
 
371
+ const componentLabels = {
372
+ cli: 'cli',
373
+ launcher: 'launcher',
374
+ analysisSkill: 'analysisSkill',
375
+ semanticQuerySkill: 'semanticQuerySkill',
376
+ }
377
+
378
+ function updateSummary(status, t) {
379
+ return Object.entries(status?.components || {})
380
+ .filter(([key, component]) => componentLabels[key] && component?.updateAvailable)
381
+ .map(([key, component]) => `${t(componentLabels[key])}: ${component.installedVersion || '—'} → ${component.targetVersion}`)
382
+ }
383
+
318
384
  function progressPanel(progress, t) {
319
385
  if (!progress) return null
320
386
  const percent = Math.max(0, Math.min(100, Number(progress.percent) || 0))
@@ -324,6 +390,7 @@ window.__ModuleLoader__.load({
324
390
  cli: 'progressCli',
325
391
  launcher: 'progressLauncher',
326
392
  'analysis-skill': 'progressAnalysis',
393
+ 'semantic-query-skill': 'progressSemanticQuery',
327
394
  'workspace-skills': 'progressSkills',
328
395
  state: 'progressState',
329
396
  complete: 'progressComplete',
@@ -436,6 +503,7 @@ window.__ModuleLoader__.load({
436
503
  const [view, setView] = useState({ phase: 'loading', status: null, message: '', error: false, errorCode: null })
437
504
  const [portDraft, setPortDraft] = useState('')
438
505
  const [portDirty, setPortDirty] = useState(false)
506
+ const [sequenceBusy, setSequenceBusy] = useState(false)
439
507
 
440
508
  const refresh = useCallback(async () => {
441
509
  setView((current) => ({ ...current, phase: current.status ? 'ready' : 'loading', error: false }))
@@ -462,6 +530,7 @@ window.__ModuleLoader__.load({
462
530
  }, [refresh, view.status?.operation?.state])
463
531
 
464
532
  const run = async (method) => {
533
+ setSequenceBusy(true)
465
534
  setView((current) => ({ ...current, message: t('working'), error: false, errorCode: null }))
466
535
  try {
467
536
  const result = unwrap(await api[method](), method)
@@ -474,6 +543,44 @@ window.__ModuleLoader__.load({
474
543
  await refresh()
475
544
  } catch (error) {
476
545
  setView((current) => ({ ...current, message: `${t('actionFailed')}: ${String(error.message || error)}`, error: true, errorCode: 'REMOTE_ERROR' }))
546
+ } finally {
547
+ setSequenceBusy(false)
548
+ }
549
+ }
550
+
551
+ const waitForOperation = async (operationId) => {
552
+ for (let attempt = 0; attempt < 900; attempt += 1) {
553
+ const status = unwrap(await api.status(), 'status')
554
+ const operation = status.operation
555
+ if (operation?.id === operationId && operation.state !== 'running') return status
556
+ await new Promise((resolve) => setTimeout(resolve, 1000))
557
+ }
558
+ throw new Error(t('operationTimeout'))
559
+ }
560
+
561
+ const runSequence = async (methods, successMessage) => {
562
+ setSequenceBusy(true)
563
+ setView((current) => ({ ...current, message: t('working'), error: false, errorCode: null }))
564
+ try {
565
+ for (const method of methods) {
566
+ const result = unwrap(await api[method](), method)
567
+ if (result.success === false) {
568
+ setView((current) => ({ ...current, message: result.error?.message || t('actionFailed'), error: true, errorCode: result.error?.code || null }))
569
+ return
570
+ }
571
+ if (result.accepted && result.operation?.id) {
572
+ const completed = await waitForOperation(result.operation.id)
573
+ if (completed.operation?.state === 'failed') {
574
+ throw new Error(completed.operation.error || completed.operation.result?.error?.message || t('actionFailed'))
575
+ }
576
+ }
577
+ }
578
+ setView((current) => ({ ...current, message: successMessage, error: false, errorCode: null }))
579
+ } catch (error) {
580
+ setView((current) => ({ ...current, message: `${t('actionFailed')}: ${String(error.message || error)}`, error: true, errorCode: 'REMOTE_ERROR' }))
581
+ } finally {
582
+ setSequenceBusy(false)
583
+ await refresh()
477
584
  }
478
585
  }
479
586
 
@@ -506,7 +613,7 @@ window.__ModuleLoader__.load({
506
613
  ] })
507
614
 
508
615
  const status = view.status
509
- const busy = status.operation?.state === 'running'
616
+ const busy = sequenceBusy || status.operation?.state === 'running'
510
617
  const portNumber = Number(portDraft)
511
618
  const portValid = Number.isInteger(portNumber) && portNumber >= 1024 && portNumber <= 65535
512
619
  const operationError = status.operation?.state === 'failed'
@@ -538,29 +645,57 @@ window.__ModuleLoader__.load({
538
645
  ? t('portUnavailableHelp')
539
646
  : alertCode === 'RUNTIME_PORT_INVALID'
540
647
  ? t('portInvalidHelp')
648
+ : alertCode === 'RUNTIME_RUNNING_UPDATE_REQUIRES_STOP'
649
+ ? t('updateBlockedRunning')
541
650
  : ''
542
651
  const progress = busy ? progressPanel(status.operation?.progress, t) : null
652
+ const pendingUpdates = updateSummary(status, t)
653
+ const hasPendingUpdates = pendingUpdates.length > 0
543
654
  const stateLabels = { 'not-installed': 'notInstalled', degraded: 'degraded', ready: 'ready', running: 'running' }
544
655
  return jsxs('section', { className: 'foggy-settings', children: [
545
656
  jsxs('div', { className: 'foggy-hero', children: [
546
657
  jsxs('div', { className: 'foggy-title-row', children: [jsx('h3', { children: t('title') }), jsx('span', { className: 'foggy-beta', children: t('beta') })] }),
547
658
  jsx('p', { className: 'foggy-intro', children: t('intro') }),
548
659
  ] }),
660
+ jsxs('div', { className: 'foggy-resources', children: [
661
+ jsx('h4', { children: t('resourceTitle') }),
662
+ jsxs('div', { className: 'foggy-resource-links', children: [
663
+ jsx('a', { className: 'foggy-resource-link', href: 'https://github.com/foggy-projects/foggy-deepseek-harness-plugin#readme', target: '_blank', rel: 'noreferrer noopener', title: t('openExternal'), children: t('docs') }),
664
+ jsx('a', { className: 'foggy-resource-link', href: 'https://github.com/foggy-projects/foggy-deepseek-harness-plugin', target: '_blank', rel: 'noreferrer noopener', title: t('openExternal'), children: t('project') }),
665
+ jsx('a', { className: 'foggy-resource-link', href: 'https://github.com/foggy-projects/foggy-deepseek-harness-plugin/releases', target: '_blank', rel: 'noreferrer noopener', title: t('openExternal'), children: t('releases') }),
666
+ jsx('a', { className: 'foggy-resource-link', href: 'https://github.com/f-projects/foggy-data-mcp-bridge', target: '_blank', rel: 'noreferrer noopener', title: t('openExternal'), children: t('runtimeProject') }),
667
+ ] }),
668
+ ] }),
549
669
  jsxs('div', { className: 'foggy-toolbar', children: [
550
- jsxs('div', { className: 'foggy-state', children: [jsx('span', { className: 'foggy-dot', 'data-state': status.state }), jsx('span', { children: t(stateLabels[status.state] || 'notInstalled') })] }),
551
- jsxs('div', { className: 'foggy-actions', children: [
670
+ jsxs('div', { className: 'foggy-state', children: [jsx('span', { className: 'foggy-dot', 'data-state': status.state }), jsx('span', { children: `${t(stateLabels[status.state] || 'notInstalled')}${hasPendingUpdates ? ` · ${t('updateAvailable')}` : ''}` })] }),
671
+ jsxs('div', { className: 'foggy-toolbar-main', children: [
672
+ status.state === 'not-installed'
673
+ ? jsx('button', { className: 'foggy-button foggy-button-primary', type: 'button', disabled: busy, onClick: () => runSequence(['initializeAndStart'], t('initializeAndStartDone')), children: t('initializeAndStart') })
674
+ : status.running
675
+ ? jsx('button', { className: 'foggy-button', type: 'button', disabled: busy, onClick: () => run('runtimeStop'), children: t('stop') })
676
+ : hasPendingUpdates && status.components.java.available
677
+ ? jsx('button', { className: 'foggy-button foggy-button-primary', type: 'button', disabled: busy, onClick: () => runSequence(['updateComponents', 'runtimeStart'], t('updateAndStartDone')), children: t('updateAndStart') })
678
+ : status.installed && status.components.java.available
679
+ ? jsx('button', { className: 'foggy-button foggy-button-primary', type: 'button', disabled: busy, onClick: () => run('runtimeStart'), children: t('start') })
680
+ : jsx('button', { className: 'foggy-button foggy-button-primary', type: 'button', disabled: busy, onClick: () => run('updateComponents'), children: t('updateComponents') }),
681
+ ] }),
682
+ jsxs('div', { className: 'foggy-toolbar-secondary', children: [
552
683
  jsx('button', { className: 'foggy-button', type: 'button', disabled: busy, onClick: refresh, children: t('refresh') }),
553
684
  jsx('button', { className: 'foggy-button', type: 'button', disabled: busy, onClick: () => run('diagnostics'), children: t('diagnostics') }),
554
- status.state === 'not-installed' ? jsx('button', { className: 'foggy-button foggy-button-primary', type: 'button', disabled: busy, onClick: () => run('initialize'), children: t('initialize') }) : null,
555
- status.state !== 'not-installed' ? jsx('button', { className: 'foggy-button', type: 'button', disabled: busy, onClick: () => run('repair'), children: t('repair') }) : null,
556
- status.installed && !status.running && status.components.java.available ? jsx('button', { className: 'foggy-button foggy-button-primary', type: 'button', disabled: busy, onClick: () => run('runtimeStart'), children: t('start') }) : null,
557
- status.running ? jsx('button', { className: 'foggy-button', type: 'button', disabled: busy, onClick: () => run('runtimeStop'), children: t('stop') }) : null,
685
+ status.state !== 'not-installed' && !status.running && hasPendingUpdates
686
+ ? jsx('button', { className: 'foggy-button', type: 'button', disabled: busy, onClick: () => run('updateComponents'), children: t('updateComponents') })
687
+ : null,
558
688
  ] }),
559
689
  ] }),
560
690
  errorPanel(alertTitle, alertMessage, alertHelp),
561
691
  progress,
562
692
  busy ? jsx('p', { className: 'foggy-message', children: t('working') }) : null,
563
693
  !busy && view.message && !view.error && !operationError ? jsx('p', { className: 'foggy-message', children: view.message }) : null,
694
+ !busy && hasPendingUpdates ? jsxs('div', { className: 'foggy-update-banner', role: 'status', children: [
695
+ jsx('strong', { children: t('updateAvailable') }),
696
+ jsx('span', { children: ` · ${status.running ? t('updateBlockedRunning') : t('updateReady')}` }),
697
+ jsx('ul', { className: 'foggy-update-list', children: pendingUpdates.map((item) => jsx('li', { children: item }, item)) }),
698
+ ] }) : null,
564
699
  jsxs('div', { className: 'foggy-runtime-settings', children: [
565
700
  jsx('h4', { children: t('runtimeSettingsTitle') }),
566
701
  jsxs('div', { className: 'foggy-runtime-settings-row', children: [
@@ -603,16 +738,18 @@ window.__ModuleLoader__.load({
603
738
  componentCard(t('cli'), status.components.cli, 'runtime', t),
604
739
  componentCard(t('launcher'), status.components.launcher, 'runtime', t),
605
740
  componentCard(t('analysisSkill'), status.components.analysisSkill, 'runtime', t),
741
+ componentCard(t('semanticQuerySkill'), status.components.semanticQuerySkill, 'runtime', t),
606
742
  componentCard(t('onboardingSkill'), status.components.onboardingSkill, 'runtime', t),
607
743
  componentCard(t('skillRegistry'), { installed: status.components.onboardingSkill?.provider === 'foggy-managed-skills', version: 'native' }, 'runtime', t),
608
744
  ] }),
609
745
  jsxs('div', { className: 'foggy-section', children: [
610
746
  jsx('h4', { children: t('repairTitle') }),
611
747
  jsx('div', { className: 'foggy-section-actions', children: [
612
- jsx('button', { className: 'foggy-button', type: 'button', disabled: busy, onClick: () => run('repairPython'), children: t('repairPython') }),
613
- jsx('button', { className: 'foggy-button', type: 'button', disabled: busy, onClick: () => run('repairCli'), children: t('repairCli') }),
614
- jsx('button', { className: 'foggy-button', type: 'button', disabled: busy, onClick: () => run('repairLauncher'), children: t('repairLauncher') }),
615
- jsx('button', { className: 'foggy-button', type: 'button', disabled: busy, onClick: () => run('repairAnalysisSkill'), children: t('repairAnalysisSkill') }),
748
+ jsx('button', { className: 'foggy-button', type: 'button', disabled: busy || status.running, title: status.running ? t('updateBlockedRunning') : undefined, onClick: () => run('repairPython'), children: t('repairPython') }),
749
+ jsx('button', { className: 'foggy-button', type: 'button', disabled: busy || status.running, title: status.running ? t('updateBlockedRunning') : undefined, onClick: () => run('repairCli'), children: t('repairCli') }),
750
+ jsx('button', { className: 'foggy-button', type: 'button', disabled: busy || status.running, title: status.running ? t('updateBlockedRunning') : undefined, onClick: () => run('repairLauncher'), children: t('repairLauncher') }),
751
+ jsx('button', { className: 'foggy-button', type: 'button', disabled: busy || status.running, title: status.running ? t('updateBlockedRunning') : undefined, onClick: () => run('repairAnalysisSkill'), children: t('repairAnalysisSkill') }),
752
+ jsx('button', { className: 'foggy-button', type: 'button', disabled: busy || status.running, title: status.running ? t('updateBlockedRunning') : undefined, onClick: () => run('repairSemanticQuerySkill'), children: t('repairSemanticQuerySkill') }),
616
753
  ] }),
617
754
  ] }),
618
755
  status.profileMigration?.pendingCount || status.profileMigration?.conflictCount ? jsxs('div', { className: 'foggy-warning', children: [