@foggy-projects/deepseek-harness-plugin 0.4.0-rc.2 → 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 +11 -2
- package/docs/RELEASE-CANDIDATE-0.4.0-RC.3.md +18 -0
- package/lib/client.js +154 -26
- package/lib/index.js +148 -24
- package/lib/remote-descriptor.js +2 -0
- package/package.json +2 -1
- package/skills/foggy-deepseek-onboarding/assets/versions.json +1 -1
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
|
|
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.
|
|
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
|
|
@@ -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.
|
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', 'repairSemanticQuerySkill',
|
|
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 状态。',
|
|
@@ -73,11 +73,20 @@ window.__ModuleLoader__.load({
|
|
|
73
73
|
java: 'Java',
|
|
74
74
|
installed: '已安装',
|
|
75
75
|
missing: '未安装',
|
|
76
|
+
upToDate: '最新',
|
|
77
|
+
updateAvailable: '有更新',
|
|
78
|
+
installedVersion: '当前版本',
|
|
79
|
+
targetVersion: '目标版本',
|
|
76
80
|
available: '可用',
|
|
77
81
|
unavailable: '不可用',
|
|
78
82
|
initialize: '初始化 Foggy',
|
|
79
|
-
|
|
80
|
-
|
|
83
|
+
initializeAndStart: '初始化并启动',
|
|
84
|
+
initializeAndStartDone: 'Foggy 已初始化,Runtime 已启动。',
|
|
85
|
+
updateComponents: '更新组件',
|
|
86
|
+
updateAndStart: '更新并启动',
|
|
87
|
+
updateAndStartDone: '组件已更新,Runtime 已启动。',
|
|
88
|
+
repair: '修复组件',
|
|
89
|
+
repairTitle: '高级修复',
|
|
81
90
|
repairPython: '检查 / 修复私有 Python',
|
|
82
91
|
repairCli: '检查 / 修复 CLI',
|
|
83
92
|
repairLauncher: '检查 / 修复 Launcher',
|
|
@@ -87,6 +96,16 @@ window.__ModuleLoader__.load({
|
|
|
87
96
|
diagnosticsSaved: '诊断报告已保存',
|
|
88
97
|
start: '启动 Runtime',
|
|
89
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: '在新标签页打开',
|
|
90
109
|
working: '操作进行中…',
|
|
91
110
|
progressWorking: '正在初始化 Foggy…',
|
|
92
111
|
progressPreflight: '检查运行环境',
|
|
@@ -160,7 +179,7 @@ window.__ModuleLoader__.load({
|
|
|
160
179
|
const en = {
|
|
161
180
|
tab: 'Foggy Data Analysis',
|
|
162
181
|
title: 'Foggy Java Data Analysis Engine',
|
|
163
|
-
intro: 'Manage Foggy private Python, CLI, Launcher, Skills, and the local Runtime inside DeepSeek Harness. Large components
|
|
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.',
|
|
164
183
|
refresh: 'Refresh status',
|
|
165
184
|
loading: 'Reading Foggy status…',
|
|
166
185
|
failed: 'Foggy status is temporarily unavailable.',
|
|
@@ -179,11 +198,20 @@ window.__ModuleLoader__.load({
|
|
|
179
198
|
java: 'Java',
|
|
180
199
|
installed: 'Installed',
|
|
181
200
|
missing: 'Missing',
|
|
201
|
+
upToDate: 'Up to date',
|
|
202
|
+
updateAvailable: 'Update available',
|
|
203
|
+
installedVersion: 'Current',
|
|
204
|
+
targetVersion: 'Target',
|
|
182
205
|
available: 'Available',
|
|
183
206
|
unavailable: 'Unavailable',
|
|
184
207
|
initialize: 'Initialize Foggy',
|
|
185
|
-
|
|
186
|
-
|
|
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',
|
|
187
215
|
repairPython: 'Check / repair private Python',
|
|
188
216
|
repairCli: 'Check / repair CLI',
|
|
189
217
|
repairLauncher: 'Check / repair Launcher',
|
|
@@ -193,6 +221,16 @@ window.__ModuleLoader__.load({
|
|
|
193
221
|
diagnosticsSaved: 'Diagnostics saved',
|
|
194
222
|
start: 'Start Runtime',
|
|
195
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',
|
|
196
234
|
working: 'Operation in progress…',
|
|
197
235
|
progressWorking: 'Initializing Foggy…',
|
|
198
236
|
progressPreflight: 'Checking prerequisites',
|
|
@@ -267,15 +305,17 @@ window.__ModuleLoader__.load({
|
|
|
267
305
|
.foggy-settings{width:100%;max-width:820px;color:var(--dsw-alias-label-primary);display:flex;flex-direction:column;gap:16px}
|
|
268
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}
|
|
269
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)}
|
|
270
|
-
.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)}
|
|
271
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)}
|
|
272
|
-
.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}
|
|
273
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}
|
|
274
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}
|
|
275
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}
|
|
276
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}
|
|
277
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}
|
|
278
|
-
@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}}
|
|
279
319
|
`
|
|
280
320
|
|
|
281
321
|
if (typeof document !== 'undefined' && !document.querySelector('style[data-foggy-settings]')) {
|
|
@@ -295,16 +335,23 @@ window.__ModuleLoader__.load({
|
|
|
295
335
|
|
|
296
336
|
function componentCard(label, component, kind, t) {
|
|
297
337
|
const available = kind === 'runtime' ? component?.installed : component?.available
|
|
298
|
-
const stateText =
|
|
299
|
-
? t(
|
|
300
|
-
:
|
|
338
|
+
const stateText = component?.updateAvailable
|
|
339
|
+
? t('updateAvailable')
|
|
340
|
+
: kind === 'runtime'
|
|
341
|
+
? t(available ? 'installed' : 'missing')
|
|
342
|
+
: t(available ? 'available' : 'unavailable')
|
|
301
343
|
const source = component?.source === 'managed'
|
|
302
344
|
? t('managedPrivate')
|
|
303
345
|
: component?.source === 'override'
|
|
304
346
|
? t('configuredOverride')
|
|
305
347
|
: null
|
|
306
348
|
const detail = [
|
|
307
|
-
component?.
|
|
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,
|
|
308
355
|
component?.minimum ? `≥${component.minimum}` : null,
|
|
309
356
|
source,
|
|
310
357
|
].filter(Boolean).join(' · ')
|
|
@@ -321,6 +368,19 @@ window.__ModuleLoader__.load({
|
|
|
321
368
|
})
|
|
322
369
|
}
|
|
323
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
|
+
|
|
324
384
|
function progressPanel(progress, t) {
|
|
325
385
|
if (!progress) return null
|
|
326
386
|
const percent = Math.max(0, Math.min(100, Number(progress.percent) || 0))
|
|
@@ -443,6 +503,7 @@ window.__ModuleLoader__.load({
|
|
|
443
503
|
const [view, setView] = useState({ phase: 'loading', status: null, message: '', error: false, errorCode: null })
|
|
444
504
|
const [portDraft, setPortDraft] = useState('')
|
|
445
505
|
const [portDirty, setPortDirty] = useState(false)
|
|
506
|
+
const [sequenceBusy, setSequenceBusy] = useState(false)
|
|
446
507
|
|
|
447
508
|
const refresh = useCallback(async () => {
|
|
448
509
|
setView((current) => ({ ...current, phase: current.status ? 'ready' : 'loading', error: false }))
|
|
@@ -469,6 +530,7 @@ window.__ModuleLoader__.load({
|
|
|
469
530
|
}, [refresh, view.status?.operation?.state])
|
|
470
531
|
|
|
471
532
|
const run = async (method) => {
|
|
533
|
+
setSequenceBusy(true)
|
|
472
534
|
setView((current) => ({ ...current, message: t('working'), error: false, errorCode: null }))
|
|
473
535
|
try {
|
|
474
536
|
const result = unwrap(await api[method](), method)
|
|
@@ -481,6 +543,44 @@ window.__ModuleLoader__.load({
|
|
|
481
543
|
await refresh()
|
|
482
544
|
} catch (error) {
|
|
483
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()
|
|
484
584
|
}
|
|
485
585
|
}
|
|
486
586
|
|
|
@@ -513,7 +613,7 @@ window.__ModuleLoader__.load({
|
|
|
513
613
|
] })
|
|
514
614
|
|
|
515
615
|
const status = view.status
|
|
516
|
-
const busy = status.operation?.state === 'running'
|
|
616
|
+
const busy = sequenceBusy || status.operation?.state === 'running'
|
|
517
617
|
const portNumber = Number(portDraft)
|
|
518
618
|
const portValid = Number.isInteger(portNumber) && portNumber >= 1024 && portNumber <= 65535
|
|
519
619
|
const operationError = status.operation?.state === 'failed'
|
|
@@ -545,29 +645,57 @@ window.__ModuleLoader__.load({
|
|
|
545
645
|
? t('portUnavailableHelp')
|
|
546
646
|
: alertCode === 'RUNTIME_PORT_INVALID'
|
|
547
647
|
? t('portInvalidHelp')
|
|
648
|
+
: alertCode === 'RUNTIME_RUNNING_UPDATE_REQUIRES_STOP'
|
|
649
|
+
? t('updateBlockedRunning')
|
|
548
650
|
: ''
|
|
549
651
|
const progress = busy ? progressPanel(status.operation?.progress, t) : null
|
|
652
|
+
const pendingUpdates = updateSummary(status, t)
|
|
653
|
+
const hasPendingUpdates = pendingUpdates.length > 0
|
|
550
654
|
const stateLabels = { 'not-installed': 'notInstalled', degraded: 'degraded', ready: 'ready', running: 'running' }
|
|
551
655
|
return jsxs('section', { className: 'foggy-settings', children: [
|
|
552
656
|
jsxs('div', { className: 'foggy-hero', children: [
|
|
553
657
|
jsxs('div', { className: 'foggy-title-row', children: [jsx('h3', { children: t('title') }), jsx('span', { className: 'foggy-beta', children: t('beta') })] }),
|
|
554
658
|
jsx('p', { className: 'foggy-intro', children: t('intro') }),
|
|
555
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
|
+
] }),
|
|
556
669
|
jsxs('div', { className: 'foggy-toolbar', children: [
|
|
557
|
-
jsxs('div', { className: 'foggy-state', children: [jsx('span', { className: 'foggy-dot', 'data-state': status.state }), jsx('span', { children: t(stateLabels[status.state] || 'notInstalled') })] }),
|
|
558
|
-
jsxs('div', { className: 'foggy-
|
|
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: [
|
|
559
683
|
jsx('button', { className: 'foggy-button', type: 'button', disabled: busy, onClick: refresh, children: t('refresh') }),
|
|
560
684
|
jsx('button', { className: 'foggy-button', type: 'button', disabled: busy, onClick: () => run('diagnostics'), children: t('diagnostics') }),
|
|
561
|
-
status.state
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
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,
|
|
565
688
|
] }),
|
|
566
689
|
] }),
|
|
567
690
|
errorPanel(alertTitle, alertMessage, alertHelp),
|
|
568
691
|
progress,
|
|
569
692
|
busy ? jsx('p', { className: 'foggy-message', children: t('working') }) : null,
|
|
570
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,
|
|
571
699
|
jsxs('div', { className: 'foggy-runtime-settings', children: [
|
|
572
700
|
jsx('h4', { children: t('runtimeSettingsTitle') }),
|
|
573
701
|
jsxs('div', { className: 'foggy-runtime-settings-row', children: [
|
|
@@ -617,11 +745,11 @@ window.__ModuleLoader__.load({
|
|
|
617
745
|
jsxs('div', { className: 'foggy-section', children: [
|
|
618
746
|
jsx('h4', { children: t('repairTitle') }),
|
|
619
747
|
jsx('div', { className: 'foggy-section-actions', children: [
|
|
620
|
-
jsx('button', { className: 'foggy-button', type: 'button', disabled: busy, onClick: () => run('repairPython'), children: t('repairPython') }),
|
|
621
|
-
jsx('button', { className: 'foggy-button', type: 'button', disabled: busy, onClick: () => run('repairCli'), children: t('repairCli') }),
|
|
622
|
-
jsx('button', { className: 'foggy-button', type: 'button', disabled: busy, onClick: () => run('repairLauncher'), children: t('repairLauncher') }),
|
|
623
|
-
jsx('button', { className: 'foggy-button', type: 'button', disabled: busy, onClick: () => run('repairAnalysisSkill'), children: t('repairAnalysisSkill') }),
|
|
624
|
-
jsx('button', { className: 'foggy-button', type: 'button', disabled: busy, onClick: () => run('repairSemanticQuerySkill'), children: t('repairSemanticQuerySkill') }),
|
|
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') }),
|
|
625
753
|
] }),
|
|
626
754
|
] }),
|
|
627
755
|
status.profileMigration?.pendingCount || status.profileMigration?.conflictCount ? jsxs('div', { className: 'foggy-warning', children: [
|
package/lib/index.js
CHANGED
|
@@ -45,6 +45,18 @@ function defaultRoots() {
|
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
function componentReleaseState({ installed, installedVersion, targetVersion }) {
|
|
49
|
+
const normalizedInstalled = installedVersion || null
|
|
50
|
+
const normalizedTarget = targetVersion || null
|
|
51
|
+
const updateAvailable = Boolean(installed && normalizedInstalled && normalizedTarget && normalizedInstalled !== normalizedTarget)
|
|
52
|
+
return {
|
|
53
|
+
installed: Boolean(installed && !updateAvailable),
|
|
54
|
+
installedVersion: normalizedInstalled,
|
|
55
|
+
targetVersion: normalizedTarget,
|
|
56
|
+
updateAvailable,
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
48
60
|
async function exists(path) {
|
|
49
61
|
try {
|
|
50
62
|
await access(path, fsConstants.F_OK)
|
|
@@ -66,6 +78,22 @@ async function readOptionalJson(path) {
|
|
|
66
78
|
}
|
|
67
79
|
}
|
|
68
80
|
|
|
81
|
+
async function runtimeRunningUpdateGuard() {
|
|
82
|
+
const roots = defaultRoots()
|
|
83
|
+
const runtime = await readOptionalJson(join(roots.dataRoot, 'runtime-state.json'))
|
|
84
|
+
if (runtime && processRunning(Number(runtime.pid))) {
|
|
85
|
+
return {
|
|
86
|
+
success: false,
|
|
87
|
+
accepted: false,
|
|
88
|
+
error: {
|
|
89
|
+
code: 'RUNTIME_RUNNING_UPDATE_REQUIRES_STOP',
|
|
90
|
+
message: 'Stop Foggy Runtime before updating or repairing managed components.',
|
|
91
|
+
},
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return null
|
|
95
|
+
}
|
|
96
|
+
|
|
69
97
|
async function commandVersion(command, args) {
|
|
70
98
|
try {
|
|
71
99
|
const { stdout, stderr } = await execFileAsync(command, args, {
|
|
@@ -232,32 +260,50 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
232
260
|
const onboardingSkillPath = join(packageRoot, 'skills', 'foggy-deepseek-onboarding')
|
|
233
261
|
const analysisMarker = await readOptionalJson(join(analysisSkillPath, '.foggy-managed-skill.json'))
|
|
234
262
|
const semanticQueryMarker = await readOptionalJson(join(semanticQuerySkillPath, '.foggy-managed-skill.json'))
|
|
263
|
+
const cliPresent = Boolean(cliPath && await exists(cliPath))
|
|
264
|
+
const launcherPresent = Boolean(launcherPath && await exists(launcherPath))
|
|
265
|
+
const analysisSkillPresent = await exists(join(analysisSkillPath, 'SKILL.md'))
|
|
266
|
+
&& analysisMarker?.schemaVersion === 'foggy-managed-skill/v1'
|
|
267
|
+
const semanticQuerySkillPresent = await exists(join(semanticQuerySkillPath, 'SKILL.md'))
|
|
268
|
+
&& semanticQueryMarker?.schemaVersion === 'foggy-managed-skill/v1'
|
|
269
|
+
const cliRelease = componentReleaseState({
|
|
270
|
+
installed: cliPresent,
|
|
271
|
+
installedVersion: state?.cli?.version,
|
|
272
|
+
targetVersion: manifest.components.cli.version,
|
|
273
|
+
})
|
|
274
|
+
const launcherRelease = componentReleaseState({
|
|
275
|
+
installed: launcherPresent,
|
|
276
|
+
installedVersion: state?.launcher?.version,
|
|
277
|
+
targetVersion: manifest.components.launcher.version,
|
|
278
|
+
})
|
|
279
|
+
const analysisRelease = componentReleaseState({
|
|
280
|
+
installed: analysisSkillPresent,
|
|
281
|
+
installedVersion: analysisMarker?.componentVersion || state?.skills?.analysis?.version,
|
|
282
|
+
targetVersion: manifest.components.analysisSkill.version,
|
|
283
|
+
})
|
|
284
|
+
const semanticQueryRelease = componentReleaseState({
|
|
285
|
+
installed: semanticQuerySkillPresent,
|
|
286
|
+
installedVersion: semanticQueryMarker?.componentVersion || state?.skills?.semanticQuery?.version,
|
|
287
|
+
targetVersion: manifest.components.semanticQuerySkill.version,
|
|
288
|
+
})
|
|
235
289
|
const components = {
|
|
236
290
|
python,
|
|
237
291
|
java,
|
|
238
292
|
cli: {
|
|
239
|
-
|
|
240
|
-
version:
|
|
293
|
+
...cliRelease,
|
|
294
|
+
version: cliRelease.installedVersion ?? manifest.components.cli.version,
|
|
241
295
|
},
|
|
242
296
|
launcher: {
|
|
243
|
-
|
|
244
|
-
version:
|
|
297
|
+
...launcherRelease,
|
|
298
|
+
version: launcherRelease.installedVersion ?? manifest.components.launcher.version,
|
|
245
299
|
},
|
|
246
300
|
analysisSkill: {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
&& analysisMarker?.schemaVersion === 'foggy-managed-skill/v1'
|
|
250
|
-
&& analysisMarker?.componentVersion === manifest.components.analysisSkill.version
|
|
251
|
-
),
|
|
252
|
-
version: state?.skills?.analysis?.version ?? manifest.components.analysisSkill.version,
|
|
301
|
+
...analysisRelease,
|
|
302
|
+
version: analysisRelease.installedVersion ?? manifest.components.analysisSkill.version,
|
|
253
303
|
},
|
|
254
304
|
semanticQuerySkill: {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
&& semanticQueryMarker?.schemaVersion === 'foggy-managed-skill/v1'
|
|
258
|
-
&& semanticQueryMarker?.componentVersion === manifest.components.semanticQuerySkill.version
|
|
259
|
-
),
|
|
260
|
-
version: state?.skills?.semanticQuery?.version ?? manifest.components.semanticQuerySkill.version,
|
|
305
|
+
...semanticQueryRelease,
|
|
306
|
+
version: semanticQueryRelease.installedVersion ?? manifest.components.semanticQuerySkill.version,
|
|
261
307
|
},
|
|
262
308
|
onboardingSkill: {
|
|
263
309
|
installed: await exists(join(onboardingSkillPath, 'SKILL.md')),
|
|
@@ -271,6 +317,7 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
271
317
|
&& components.analysisSkill.installed
|
|
272
318
|
&& components.semanticQuerySkill.installed
|
|
273
319
|
&& components.onboardingSkill.installed
|
|
320
|
+
const updateAvailable = Object.values(components).some((component) => component?.updateAvailable)
|
|
274
321
|
const running = Boolean(runtime && processRunning(Number(runtime.pid)))
|
|
275
322
|
const activePort = running && Number.isInteger(Number(runtime?.port)) ? Number(runtime.port) : null
|
|
276
323
|
const progress = await readOptionalJson(progressPath)
|
|
@@ -294,6 +341,7 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
294
341
|
packageVersion: manifest.packageVersion,
|
|
295
342
|
state: running ? 'running' : installed ? 'ready' : state ? 'degraded' : 'not-installed',
|
|
296
343
|
installed,
|
|
344
|
+
updateAvailable,
|
|
297
345
|
running,
|
|
298
346
|
runtimeUrl: running ? runtime.runtimeUrl ?? null : null,
|
|
299
347
|
runtimeSettings: {
|
|
@@ -309,7 +357,13 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
309
357
|
operation,
|
|
310
358
|
onboarding,
|
|
311
359
|
profileMigration,
|
|
312
|
-
next:
|
|
360
|
+
next: !state
|
|
361
|
+
? 'initialize'
|
|
362
|
+
: updateAvailable
|
|
363
|
+
? 'update-components'
|
|
364
|
+
: installed
|
|
365
|
+
? (running ? 'configure-database' : 'start-runtime')
|
|
366
|
+
: 'repair',
|
|
313
367
|
}
|
|
314
368
|
}
|
|
315
369
|
|
|
@@ -337,27 +391,96 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
337
391
|
return this.startOperation('initialize', false)
|
|
338
392
|
}
|
|
339
393
|
|
|
394
|
+
async initializeAndStart() {
|
|
395
|
+
const status = await this.status()
|
|
396
|
+
if (status.state !== 'not-installed') {
|
|
397
|
+
return {
|
|
398
|
+
success: false,
|
|
399
|
+
accepted: false,
|
|
400
|
+
error: { code: 'FOGGY_ALREADY_INITIALIZED', message: 'Foggy is already initialized; use Start Runtime or Update components.' },
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
return this.startOperation('initialize-and-start', false, undefined, async ({ operation, progressPath, pythonProgress }) => {
|
|
404
|
+
await assertSystemPrerequisites('initialize')
|
|
405
|
+
const cacheArgs = (process.env.FOGGY_ASSET_CACHE_DIRS || '').split(delimiter).filter(Boolean)
|
|
406
|
+
.flatMap((cacheDir) => ['--asset-cache-dir', cacheDir])
|
|
407
|
+
const install = await runOnboarding([
|
|
408
|
+
'install', '--progress-file', progressPath, '--operation-id', operation.id, '--operation-kind', 'initialize',
|
|
409
|
+
...cacheArgs,
|
|
410
|
+
], 15 * 60_000, {
|
|
411
|
+
ensurePython: true,
|
|
412
|
+
onPythonProgress: (detail) => pythonProgress?.update(detail),
|
|
413
|
+
flushPythonProgress: () => pythonProgress?.flush(),
|
|
414
|
+
})
|
|
415
|
+
if (install.success === false) return install
|
|
416
|
+
|
|
417
|
+
await assertSystemPrerequisites('runtime-start')
|
|
418
|
+
const roots = defaultRoots()
|
|
419
|
+
const manifest = await readJson(versionsFile)
|
|
420
|
+
const settings = await readRuntimeSettings(roots.dataRoot, {
|
|
421
|
+
defaultPort: manifest.defaults?.port ?? DEFAULT_RUNTIME_PORT,
|
|
422
|
+
})
|
|
423
|
+
if (!settings.valid) {
|
|
424
|
+
return {
|
|
425
|
+
success: false,
|
|
426
|
+
error: { code: 'RUNTIME_SETTINGS_INVALID', message: `Runtime settings are invalid: ${settings.error}` },
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
return runOnboarding([
|
|
430
|
+
'runtime-start', '--install-root', roots.installRoot, '--data-root', roots.dataRoot,
|
|
431
|
+
'--port', String(settings.port), '--progress-file', progressPath, '--operation-id', operation.id,
|
|
432
|
+
'--operation-kind', 'runtime-start',
|
|
433
|
+
], 15 * 60_000, { ensurePython: false })
|
|
434
|
+
})
|
|
435
|
+
}
|
|
436
|
+
|
|
340
437
|
async repair() {
|
|
438
|
+
const blocked = await runtimeRunningUpdateGuard()
|
|
439
|
+
if (blocked) return blocked
|
|
341
440
|
return this.startOperation('repair', true)
|
|
342
441
|
}
|
|
343
442
|
|
|
443
|
+
async updateComponents() {
|
|
444
|
+
const blocked = await runtimeRunningUpdateGuard()
|
|
445
|
+
if (blocked) return blocked
|
|
446
|
+
const status = await this.status()
|
|
447
|
+
if (status.state === 'not-installed') {
|
|
448
|
+
return {
|
|
449
|
+
success: false,
|
|
450
|
+
accepted: false,
|
|
451
|
+
error: { code: 'FOGGY_NOT_INITIALIZED', message: 'Initialize Foggy before updating managed components.' },
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
return this.startOperation('update-components', true)
|
|
455
|
+
}
|
|
456
|
+
|
|
344
457
|
async repairCli() {
|
|
458
|
+
const blocked = await runtimeRunningUpdateGuard()
|
|
459
|
+
if (blocked) return blocked
|
|
345
460
|
return this.startOperation('repair-cli', false, ['install', '--repair-component', 'cli'])
|
|
346
461
|
}
|
|
347
462
|
|
|
348
463
|
async repairPython() {
|
|
464
|
+
const blocked = await runtimeRunningUpdateGuard()
|
|
465
|
+
if (blocked) return blocked
|
|
349
466
|
return this.startOperation('repair-python', false, ['install'])
|
|
350
467
|
}
|
|
351
468
|
|
|
352
469
|
async repairLauncher() {
|
|
470
|
+
const blocked = await runtimeRunningUpdateGuard()
|
|
471
|
+
if (blocked) return blocked
|
|
353
472
|
return this.startOperation('repair-launcher', false, ['install', '--repair-component', 'launcher'])
|
|
354
473
|
}
|
|
355
474
|
|
|
356
475
|
async repairAnalysisSkill() {
|
|
476
|
+
const blocked = await runtimeRunningUpdateGuard()
|
|
477
|
+
if (blocked) return blocked
|
|
357
478
|
return this.startOperation('repair-analysis-skill', true, ['install', '--repair-component', 'analysis-skill'])
|
|
358
479
|
}
|
|
359
480
|
|
|
360
481
|
async repairSemanticQuerySkill() {
|
|
482
|
+
const blocked = await runtimeRunningUpdateGuard()
|
|
483
|
+
if (blocked) return blocked
|
|
361
484
|
return this.startOperation('repair-semantic-query-skill', true, ['install', '--repair-component', 'semantic-query-skill'])
|
|
362
485
|
}
|
|
363
486
|
|
|
@@ -459,22 +582,22 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
459
582
|
}
|
|
460
583
|
}
|
|
461
584
|
|
|
462
|
-
startOperation(kind, replaceSkill, explicitArgs) {
|
|
585
|
+
startOperation(kind, replaceSkill, explicitArgs, runner = null) {
|
|
463
586
|
if (this.operation?.state === 'running') {
|
|
464
587
|
return { success: false, accepted: false, operation: operationView(this.operation), error: 'another Foggy operation is running' }
|
|
465
588
|
}
|
|
466
589
|
const id = `${Date.now()}-${Math.random().toString(16).slice(2, 10)}`
|
|
467
590
|
const args = explicitArgs ?? ['install']
|
|
468
|
-
const reportsProgress = args[0] === 'install' || args[0] === 'runtime-start'
|
|
591
|
+
const reportsProgress = args[0] === 'install' || args[0] === 'runtime-start' || runner !== null
|
|
592
|
+
const progressPath = reportsProgress ? join(defaultRoots().dataRoot, 'operation-progress.json') : null
|
|
469
593
|
if (reportsProgress) {
|
|
470
|
-
|
|
471
|
-
args.push('--progress-file', join(roots.dataRoot, 'operation-progress.json'), '--operation-id', id, '--operation-kind', kind)
|
|
594
|
+
args.push('--progress-file', progressPath, '--operation-id', id, '--operation-kind', kind)
|
|
472
595
|
}
|
|
473
596
|
if (replaceSkill) args.push('--replace-skill')
|
|
474
597
|
for (const cacheDir of (process.env.FOGGY_ASSET_CACHE_DIRS || '').split(delimiter).filter(Boolean)) {
|
|
475
598
|
args.push('--asset-cache-dir', cacheDir)
|
|
476
599
|
}
|
|
477
|
-
const runtimeStart = kind === 'runtime-start'
|
|
600
|
+
const runtimeStart = kind === 'runtime-start' || kind.endsWith('-and-start')
|
|
478
601
|
const operation = {
|
|
479
602
|
id,
|
|
480
603
|
kind,
|
|
@@ -497,10 +620,11 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
497
620
|
promise: null,
|
|
498
621
|
}
|
|
499
622
|
const pythonProgress = reportsProgress
|
|
500
|
-
? createPythonProgressReporter(operation,
|
|
623
|
+
? createPythonProgressReporter(operation, progressPath)
|
|
501
624
|
: null
|
|
502
625
|
operation.promise = (async () => {
|
|
503
626
|
await assertSystemPrerequisites(kind)
|
|
627
|
+
if (runner) return runner({ operation, progressPath, pythonProgress })
|
|
504
628
|
return runOnboarding(args, 15 * 60_000, {
|
|
505
629
|
ensurePython: true,
|
|
506
630
|
forcePython: kind === 'repair-python',
|
|
@@ -545,7 +669,7 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
545
669
|
|
|
546
670
|
const markerInitializers = []
|
|
547
671
|
for (const method of [
|
|
548
|
-
'status', 'plan', 'initialize', 'repair', 'repairPython', 'repairCli', 'repairLauncher', 'repairAnalysisSkill', 'repairSemanticQuerySkill',
|
|
672
|
+
'status', 'plan', 'initialize', 'initializeAndStart', 'repair', 'updateComponents', 'repairPython', 'repairCli', 'repairLauncher', 'repairAnalysisSkill', 'repairSemanticQuerySkill',
|
|
549
673
|
'migrateProfiles', 'diagnostics', 'runtimeStart', 'runtimeStop',
|
|
550
674
|
'saveRuntimeSettings',
|
|
551
675
|
]) {
|
package/lib/remote-descriptor.js
CHANGED
|
@@ -26,7 +26,9 @@ export const descriptors = [
|
|
|
26
26
|
descriptor('status'),
|
|
27
27
|
descriptor('plan'),
|
|
28
28
|
descriptor('initialize'),
|
|
29
|
+
descriptor('initializeAndStart'),
|
|
29
30
|
descriptor('repair'),
|
|
31
|
+
descriptor('updateComponents'),
|
|
30
32
|
descriptor('repairPython'),
|
|
31
33
|
descriptor('repairSemanticQuerySkill'),
|
|
32
34
|
descriptor('runtimeStart'),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@foggy-projects/deepseek-harness-plugin",
|
|
3
|
-
"version": "0.4.0-rc.
|
|
3
|
+
"version": "0.4.0-rc.3",
|
|
4
4
|
"description": "Foggy Java data analysis engine integration for DeepSeek Harness",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"experience/linux/**",
|
|
22
22
|
"docs/PUBLIC-BETA-READINESS.md",
|
|
23
23
|
"docs/RELEASE-CANDIDATE-0.4.0-RC.2.md",
|
|
24
|
+
"docs/RELEASE-CANDIDATE-0.4.0-RC.3.md",
|
|
24
25
|
"docs/WINDOWS-BETA-ACCEPTANCE.md",
|
|
25
26
|
"THIRD-PARTY-RUNTIME-NOTICES.md",
|
|
26
27
|
"README.md"
|