@foggy-projects/deepseek-harness-plugin 0.4.0-beta.5 → 0.4.0-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -3
- package/lib/client.js +111 -3
- package/lib/index.js +69 -7
- package/package.json +2 -2
- package/skills/foggy-deepseek-onboarding/SKILL.md +33 -4
- package/skills/foggy-deepseek-onboarding/assets/onboarding-state.schema.json +20 -0
- package/skills/foggy-deepseek-onboarding/assets/versions.json +1 -1
- package/skills/foggy-deepseek-onboarding/references/onboarding-workflow.md +40 -4
- package/skills/foggy-deepseek-onboarding/scripts/onboarding.py +719 -140
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ only when the user selects **Initialize Foggy**.
|
|
|
8
8
|
## Local beta installation
|
|
9
9
|
|
|
10
10
|
```powershell
|
|
11
|
-
dsh plugin --profile web add --workspace-root ./foggy-projects-deepseek-harness-plugin-0.4.0-beta.
|
|
11
|
+
dsh plugin --profile web add --workspace-root ./foggy-projects-deepseek-harness-plugin-0.4.0-beta.7.tgz
|
|
12
12
|
```
|
|
13
13
|
|
|
14
14
|
Restart `dsh web`, open Settings → Plugins → Foggy Data Analysis, and initialize
|
|
@@ -23,8 +23,9 @@ dsh plugin --profile web add --workspace-root @foggy-projects/deepseek-harness-p
|
|
|
23
23
|
For development, `FOGGY_ASSET_CACHE_DIRS` can contain platform-delimited verified
|
|
24
24
|
asset-cache directories. It is not required for a normal install.
|
|
25
25
|
|
|
26
|
-
Database credentials
|
|
27
|
-
|
|
26
|
+
Database credentials remain outside the ordinary DSH settings document. The
|
|
27
|
+
bundled onboarding Skill drives datasource discovery, semantic drafting,
|
|
28
|
+
checkpointed publication, and bounded read-only query verification.
|
|
28
29
|
|
|
29
30
|
## Native Skill and workspace contract
|
|
30
31
|
|
|
@@ -34,6 +35,15 @@ are available in every DSH workspace without copying or symlinking `.agents`.
|
|
|
34
35
|
The current session `cwd` remains the workspace boundary for semantic drafts and
|
|
35
36
|
evidence.
|
|
36
37
|
|
|
38
|
+
Opaque CLI profiles default to the private persistent
|
|
39
|
+
`<dataRoot>/cli-profiles` directory. Composite onboarding commands are
|
|
40
|
+
idempotent: unchanged completed phases are resumed rather than re-adding a
|
|
41
|
+
datasource or re-registering a published bundle. Settings detects legacy
|
|
42
|
+
temporary profiles and offers an explicit, validated migration into the
|
|
43
|
+
persistent store. A completed profile can also be bound non-destructively to an
|
|
44
|
+
additional DSH workspace when its reviewed connection contract and published
|
|
45
|
+
semantic digest are unchanged.
|
|
46
|
+
|
|
37
47
|
CLI, Launcher, the analysis Skill, install state, and Runtime state live in the
|
|
38
48
|
user-level Foggy component directories. The managed CLI is intentionally isolated
|
|
39
49
|
and does not need to be on `PATH`. **Re-download / Repair** verifies the global
|
|
@@ -41,6 +51,19 @@ analysis Skill, backs up modified or outdated managed content, restores it, and
|
|
|
41
51
|
invalidates DSH's Skill catalog. The onboarding Skill is bundled with the plugin
|
|
42
52
|
and is restored by reinstalling or upgrading the plugin package.
|
|
43
53
|
|
|
54
|
+
The Foggy settings tab shows the persisted database/semantic onboarding stages,
|
|
55
|
+
offers pinned checks and repair for CLI, Launcher, and the managed analysis
|
|
56
|
+
Skill, and exports a private redacted diagnostics report. Runtime start is
|
|
57
|
+
idempotent: an already-recorded process is verified with `wait-ready` and
|
|
58
|
+
`capabilities` instead of being treated as a failed second start.
|
|
59
|
+
|
|
60
|
+
This beta remains a local dev/test integration. The bundled Runtime reports
|
|
61
|
+
`securityMode=none-dev-test-only` and must not be exposed to a network or used as
|
|
62
|
+
a production service.
|
|
63
|
+
|
|
64
|
+
See [`docs/PUBLIC-BETA-READINESS.md`](./docs/PUBLIC-BETA-READINESS.md) for the
|
|
65
|
+
tested public Beta scope, release gates, and stable-release blockers.
|
|
66
|
+
|
|
44
67
|
## Linux and WSL2 experience
|
|
45
68
|
|
|
46
69
|
Ubuntu and WSL2 users can use the checked-in preflighted installer under
|
package/lib/client.js
CHANGED
|
@@ -10,7 +10,10 @@ window.__ModuleLoader__.load({
|
|
|
10
10
|
const passthroughSchema = { parse: (value) => value }
|
|
11
11
|
const TYPERT_REMOTE = {
|
|
12
12
|
package: '@foggy-projects/deepseek-harness-plugin',
|
|
13
|
-
descriptors: [
|
|
13
|
+
descriptors: [
|
|
14
|
+
'status', 'plan', 'initialize', 'repair', 'repairCli', 'repairLauncher', 'repairAnalysisSkill',
|
|
15
|
+
'migrateProfiles', 'diagnostics', 'runtimeStart', 'runtimeStop',
|
|
16
|
+
].map((method) => ({
|
|
14
17
|
id: `@foggy-projects/deepseek-harness-plugin#foggyIntegration/${method}`,
|
|
15
18
|
service: 'foggyIntegration',
|
|
16
19
|
namespace: 'foggyIntegration',
|
|
@@ -51,6 +54,12 @@ window.__ModuleLoader__.load({
|
|
|
51
54
|
unavailable: '不可用',
|
|
52
55
|
initialize: '初始化 Foggy',
|
|
53
56
|
repair: '重新下载 / 修复',
|
|
57
|
+
repairTitle: '分组件检查与修复',
|
|
58
|
+
repairCli: '检查 / 修复 CLI',
|
|
59
|
+
repairLauncher: '检查 / 修复 Launcher',
|
|
60
|
+
repairAnalysisSkill: '检查 / 修复分析 Skill',
|
|
61
|
+
diagnostics: '导出诊断报告',
|
|
62
|
+
diagnosticsSaved: '诊断报告已保存',
|
|
54
63
|
start: '启动 Runtime',
|
|
55
64
|
stop: '停止 Runtime',
|
|
56
65
|
working: '操作进行中…',
|
|
@@ -68,6 +77,23 @@ window.__ModuleLoader__.load({
|
|
|
68
77
|
roots: '本地目录',
|
|
69
78
|
installRoot: '组件目录',
|
|
70
79
|
dataRoot: '数据目录',
|
|
80
|
+
profileStore: 'CLI Profile',
|
|
81
|
+
profileMigrationTitle: '旧 Profile 迁移',
|
|
82
|
+
profileMigrationPending: '检测到旧版临时 Profile。迁移只转移连接元数据和密码环境变量引用,不复制密码值。',
|
|
83
|
+
profileMigrationConflict: '旧 Profile 存在冲突或格式问题,请先导出诊断报告。',
|
|
84
|
+
migrateProfiles: '迁移到持久目录',
|
|
85
|
+
onboardingProgress: '数据库与语义层进度',
|
|
86
|
+
noOnboarding: '尚无数据库引导记录;请在对话中调用 Foggy onboarding Skill。',
|
|
87
|
+
projectRoot: '工作区',
|
|
88
|
+
resumeInChat: '未完成步骤应回到对应工作区,在对话中继续。',
|
|
89
|
+
stepPlanned: '规划',
|
|
90
|
+
stepDatasourceConfigured: '数据库连接',
|
|
91
|
+
stepDatasourceVerified: '连接验证',
|
|
92
|
+
stepSchemaDiscovered: 'Schema 发现',
|
|
93
|
+
stepSemanticDrafted: '语义层草拟',
|
|
94
|
+
stepSemanticValidated: '模型校验',
|
|
95
|
+
stepSemanticPublished: '发布',
|
|
96
|
+
stepSemanticVerified: '首次查询',
|
|
71
97
|
runtimeUrl: 'Runtime 地址',
|
|
72
98
|
nextTitle: '后续配置',
|
|
73
99
|
nextCopy: 'Skills 已通过 DeepSeek Harness 原生注册表提供给所有工作区;每个会话直接使用自己的工作目录。Runtime 启动成功后,将继续进入数据库连接与语义层向导。',
|
|
@@ -99,6 +125,12 @@ window.__ModuleLoader__.load({
|
|
|
99
125
|
unavailable: 'Unavailable',
|
|
100
126
|
initialize: 'Initialize Foggy',
|
|
101
127
|
repair: 'Re-download / Repair',
|
|
128
|
+
repairTitle: 'Component checks and repair',
|
|
129
|
+
repairCli: 'Check / repair CLI',
|
|
130
|
+
repairLauncher: 'Check / repair Launcher',
|
|
131
|
+
repairAnalysisSkill: 'Check / repair analysis Skill',
|
|
132
|
+
diagnostics: 'Export diagnostics',
|
|
133
|
+
diagnosticsSaved: 'Diagnostics saved',
|
|
102
134
|
start: 'Start Runtime',
|
|
103
135
|
stop: 'Stop Runtime',
|
|
104
136
|
working: 'Operation in progress…',
|
|
@@ -116,6 +148,23 @@ window.__ModuleLoader__.load({
|
|
|
116
148
|
roots: 'Local directories',
|
|
117
149
|
installRoot: 'Components',
|
|
118
150
|
dataRoot: 'Data',
|
|
151
|
+
profileStore: 'CLI profiles',
|
|
152
|
+
profileMigrationTitle: 'Legacy profile migration',
|
|
153
|
+
profileMigrationPending: 'Legacy temporary profiles were found. Migration transfers connection metadata and password environment-variable references, never password values.',
|
|
154
|
+
profileMigrationConflict: 'A legacy profile has a conflict or invalid format. Export diagnostics before continuing.',
|
|
155
|
+
migrateProfiles: 'Move to persistent store',
|
|
156
|
+
onboardingProgress: 'Database and semantic-layer progress',
|
|
157
|
+
noOnboarding: 'No database onboarding record yet. Invoke the Foggy onboarding Skill in a conversation.',
|
|
158
|
+
projectRoot: 'Workspace',
|
|
159
|
+
resumeInChat: 'Resume incomplete steps from a conversation in the matching workspace.',
|
|
160
|
+
stepPlanned: 'Plan',
|
|
161
|
+
stepDatasourceConfigured: 'Database connection',
|
|
162
|
+
stepDatasourceVerified: 'Connection test',
|
|
163
|
+
stepSchemaDiscovered: 'Schema discovery',
|
|
164
|
+
stepSemanticDrafted: 'Semantic draft',
|
|
165
|
+
stepSemanticValidated: 'Model validation',
|
|
166
|
+
stepSemanticPublished: 'Publish',
|
|
167
|
+
stepSemanticVerified: 'First query',
|
|
119
168
|
runtimeUrl: 'Runtime URL',
|
|
120
169
|
nextTitle: 'Next configuration',
|
|
121
170
|
nextCopy: 'Skills are provided to every workspace through the native DeepSeek Harness registry, and each session uses its own working directory. After Runtime starts, the database connection and semantic-layer wizard comes next.',
|
|
@@ -131,7 +180,7 @@ window.__ModuleLoader__.load({
|
|
|
131
180
|
.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}
|
|
132
181
|
.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}
|
|
133
182
|
.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}
|
|
134
|
-
.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{border-top:1px solid var(--dsw-alias-border-l2);padding-top:14px}.foggy-paths h4,.foggy-next 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{margin:0;color:var(--dsw-alias-label-secondary);font-size:13px;line-height:20px}
|
|
183
|
+
.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}
|
|
135
184
|
@media (width<=680px){.foggy-grid{grid-template-columns:minmax(0,1fr)}}
|
|
136
185
|
`
|
|
137
186
|
|
|
@@ -213,6 +262,41 @@ window.__ModuleLoader__.load({
|
|
|
213
262
|
})
|
|
214
263
|
}
|
|
215
264
|
|
|
265
|
+
function onboardingPanel(onboarding, t) {
|
|
266
|
+
const profile = onboarding?.profiles?.[0]
|
|
267
|
+
if (!profile) return jsxs('div', { className: 'foggy-section', children: [
|
|
268
|
+
jsx('h4', { children: t('onboardingProgress') }),
|
|
269
|
+
jsx('p', { children: t('noOnboarding') }),
|
|
270
|
+
] })
|
|
271
|
+
const steps = [
|
|
272
|
+
['planned', 'stepPlanned'],
|
|
273
|
+
['datasourceConfigured', 'stepDatasourceConfigured'],
|
|
274
|
+
['datasourceVerified', 'stepDatasourceVerified'],
|
|
275
|
+
['schemaDiscovered', 'stepSchemaDiscovered'],
|
|
276
|
+
['semanticDrafted', 'stepSemanticDrafted'],
|
|
277
|
+
['semanticValidated', 'stepSemanticValidated'],
|
|
278
|
+
['semanticPublished', 'stepSemanticPublished'],
|
|
279
|
+
['semanticVerified', 'stepSemanticVerified'],
|
|
280
|
+
]
|
|
281
|
+
const percent = Math.round(((profile.completedSteps || 0) / Math.max(profile.totalSteps || 8, 1)) * 100)
|
|
282
|
+
return jsxs('div', { className: 'foggy-section', children: [
|
|
283
|
+
jsxs('div', { className: 'foggy-onboarding-head', children: [
|
|
284
|
+
jsxs('div', { children: [
|
|
285
|
+
jsx('h4', { children: `${t('onboardingProgress')} · ${profile.profile}` }),
|
|
286
|
+
jsx('code', { children: `${t('projectRoot')}: ${profile.projectRoot || '—'}` }),
|
|
287
|
+
] }),
|
|
288
|
+
jsx('span', { className: 'foggy-progress-percent', children: `${percent}%` }),
|
|
289
|
+
] }),
|
|
290
|
+
jsx('div', { className: 'foggy-step-list', children: steps.map(([name, label]) => jsx('div', {
|
|
291
|
+
className: 'foggy-step',
|
|
292
|
+
'data-state': profile.steps?.[name]?.status || 'pending',
|
|
293
|
+
title: profile.steps?.[name]?.status || 'pending',
|
|
294
|
+
children: t(label),
|
|
295
|
+
}, name)) }),
|
|
296
|
+
profile.next?.status !== 'completed' ? jsx('p', { style: { marginTop: '9px' }, children: t('resumeInChat') }) : null,
|
|
297
|
+
] })
|
|
298
|
+
}
|
|
299
|
+
|
|
216
300
|
function FoggySettingsTab({ api, t }) {
|
|
217
301
|
const [view, setView] = useState({ phase: 'loading', status: null, message: '', error: false })
|
|
218
302
|
|
|
@@ -237,7 +321,12 @@ window.__ModuleLoader__.load({
|
|
|
237
321
|
setView((current) => ({ ...current, message: t('working'), error: false }))
|
|
238
322
|
try {
|
|
239
323
|
const result = unwrap(await api[method](), method)
|
|
240
|
-
|
|
324
|
+
const message = result.accepted
|
|
325
|
+
? t('accepted')
|
|
326
|
+
: result.path
|
|
327
|
+
? `${t('diagnosticsSaved')}: ${result.path}`
|
|
328
|
+
: ''
|
|
329
|
+
setView((current) => ({ ...current, message, error: result.success === false }))
|
|
241
330
|
await refresh()
|
|
242
331
|
} catch (error) {
|
|
243
332
|
setView((current) => ({ ...current, message: `${t('actionFailed')}: ${String(error.message || error)}`, error: true }))
|
|
@@ -266,6 +355,7 @@ window.__ModuleLoader__.load({
|
|
|
266
355
|
jsxs('div', { className: 'foggy-state', children: [jsx('span', { className: 'foggy-dot', 'data-state': status.state }), jsx('span', { children: t(stateLabels[status.state] || 'notInstalled') })] }),
|
|
267
356
|
jsxs('div', { className: 'foggy-actions', children: [
|
|
268
357
|
jsx('button', { className: 'foggy-button', type: 'button', disabled: busy, onClick: refresh, children: t('refresh') }),
|
|
358
|
+
jsx('button', { className: 'foggy-button', type: 'button', disabled: busy, onClick: () => run('diagnostics'), children: t('diagnostics') }),
|
|
269
359
|
status.state === 'not-installed' ? jsx('button', { className: 'foggy-button foggy-button-primary', type: 'button', disabled: busy, onClick: () => run('initialize'), children: t('initialize') }) : null,
|
|
270
360
|
status.state !== 'not-installed' ? jsx('button', { className: 'foggy-button', type: 'button', disabled: busy, onClick: () => run('repair'), children: t('repair') }) : null,
|
|
271
361
|
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,
|
|
@@ -283,11 +373,29 @@ window.__ModuleLoader__.load({
|
|
|
283
373
|
componentCard(t('onboardingSkill'), status.components.onboardingSkill, 'runtime', t),
|
|
284
374
|
componentCard(t('skillRegistry'), { installed: status.components.onboardingSkill?.provider === 'foggy-managed-skills', version: 'native' }, 'runtime', t),
|
|
285
375
|
] }),
|
|
376
|
+
jsxs('div', { className: 'foggy-section', children: [
|
|
377
|
+
jsx('h4', { children: t('repairTitle') }),
|
|
378
|
+
jsx('div', { className: 'foggy-section-actions', children: [
|
|
379
|
+
jsx('button', { className: 'foggy-button', type: 'button', disabled: busy, onClick: () => run('repairCli'), children: t('repairCli') }),
|
|
380
|
+
jsx('button', { className: 'foggy-button', type: 'button', disabled: busy, onClick: () => run('repairLauncher'), children: t('repairLauncher') }),
|
|
381
|
+
jsx('button', { className: 'foggy-button', type: 'button', disabled: busy, onClick: () => run('repairAnalysisSkill'), children: t('repairAnalysisSkill') }),
|
|
382
|
+
] }),
|
|
383
|
+
] }),
|
|
384
|
+
status.profileMigration?.pendingCount || status.profileMigration?.conflictCount ? jsxs('div', { className: 'foggy-warning', children: [
|
|
385
|
+
jsx('h4', { children: t('profileMigrationTitle') }),
|
|
386
|
+
jsx('p', { children: status.profileMigration.conflictCount ? t('profileMigrationConflict') : t('profileMigrationPending') }),
|
|
387
|
+
!status.profileMigration.conflictCount ? jsx('div', { className: 'foggy-section-actions', children: jsx('button', {
|
|
388
|
+
className: 'foggy-button foggy-button-primary', type: 'button', disabled: busy,
|
|
389
|
+
onClick: () => run('migrateProfiles'), children: t('migrateProfiles'),
|
|
390
|
+
}) }) : null,
|
|
391
|
+
] }) : null,
|
|
392
|
+
onboardingPanel(status.onboarding, t),
|
|
286
393
|
jsxs('div', { className: 'foggy-paths', children: [
|
|
287
394
|
jsx('h4', { children: t('roots') }),
|
|
288
395
|
jsxs('dl', { children: [
|
|
289
396
|
jsx('dt', { children: t('installRoot') }), jsx('dd', { children: status.roots.installRoot }),
|
|
290
397
|
jsx('dt', { children: t('dataRoot') }), jsx('dd', { children: status.roots.dataRoot }),
|
|
398
|
+
jsx('dt', { children: t('profileStore') }), jsx('dd', { children: status.roots.profileStore }),
|
|
291
399
|
status.runtimeUrl ? jsx('dt', { children: t('runtimeUrl') }) : null,
|
|
292
400
|
status.runtimeUrl ? jsx('dd', { children: status.runtimeUrl }) : null,
|
|
293
401
|
] }),
|
package/lib/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { execFile } from 'node:child_process'
|
|
2
|
-
import { access, readFile } from 'node:fs/promises'
|
|
2
|
+
import { access, mkdir, readFile, writeFile } from 'node:fs/promises'
|
|
3
3
|
import { constants as fsConstants } from 'node:fs'
|
|
4
4
|
import { dirname, join, delimiter } from 'node:path'
|
|
5
5
|
import { fileURLToPath } from 'node:url'
|
|
@@ -20,17 +20,20 @@ function defaultRoots() {
|
|
|
20
20
|
return {
|
|
21
21
|
installRoot: join(base, 'Foggy', 'DeepSeekHarness'),
|
|
22
22
|
dataRoot: join(base, 'Foggy', 'DeepSeekHarnessData'),
|
|
23
|
+
profileStore: process.env.FOGGY_RUNTIME_PROFILE_STORE || join(base, 'Foggy', 'DeepSeekHarnessData', 'cli-profiles'),
|
|
23
24
|
}
|
|
24
25
|
}
|
|
25
26
|
const home = process.env.HOME
|
|
26
27
|
if (!home) throw new Error('HOME is not set')
|
|
28
|
+
const dataRoot = process.env.XDG_STATE_HOME
|
|
29
|
+
? join(process.env.XDG_STATE_HOME, 'foggy', 'deepseek-harness')
|
|
30
|
+
: join(home, '.local', 'state', 'foggy', 'deepseek-harness')
|
|
27
31
|
return {
|
|
28
32
|
installRoot: process.env.XDG_DATA_HOME
|
|
29
33
|
? join(process.env.XDG_DATA_HOME, 'foggy', 'deepseek-harness')
|
|
30
34
|
: join(home, '.local', 'share', 'foggy', 'deepseek-harness'),
|
|
31
|
-
dataRoot
|
|
32
|
-
|
|
33
|
-
: join(home, '.local', 'state', 'foggy', 'deepseek-harness'),
|
|
35
|
+
dataRoot,
|
|
36
|
+
profileStore: process.env.FOGGY_RUNTIME_PROFILE_STORE || join(dataRoot, 'cli-profiles'),
|
|
34
37
|
}
|
|
35
38
|
}
|
|
36
39
|
|
|
@@ -154,6 +157,16 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
154
157
|
let runtime = null
|
|
155
158
|
try { state = await readJson(statePath) } catch {}
|
|
156
159
|
try { runtime = await readJson(runtimeStatePath) } catch {}
|
|
160
|
+
let onboarding = { success: true, profiles: [], profileCount: 0 }
|
|
161
|
+
let profileMigration = { success: true, entries: [], pendingCount: 0, conflictCount: 0, profileStore: roots.profileStore }
|
|
162
|
+
if (state) {
|
|
163
|
+
try { onboarding = await runOnboarding(['onboard-list']) } catch (error) {
|
|
164
|
+
onboarding = { success: false, profiles: [], profileCount: 0, error: String(error.message ?? error) }
|
|
165
|
+
}
|
|
166
|
+
try { profileMigration = await runOnboarding(['profile-migration-status']) } catch (error) {
|
|
167
|
+
profileMigration = { success: false, entries: [], pendingCount: 0, conflictCount: 0, profileStore: roots.profileStore, error: String(error.message ?? error) }
|
|
168
|
+
}
|
|
169
|
+
}
|
|
157
170
|
const cliPath = state?.cli?.command
|
|
158
171
|
const launcherPath = state?.launcher?.path
|
|
159
172
|
const analysisSkillPath = state?.skills?.analysis?.path || join(roots.installRoot, 'skills', 'foggy-ai-analysis')
|
|
@@ -215,6 +228,8 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
215
228
|
roots,
|
|
216
229
|
components,
|
|
217
230
|
operation,
|
|
231
|
+
onboarding,
|
|
232
|
+
profileMigration,
|
|
218
233
|
next: installed ? (running ? 'configure-database' : 'start-runtime') : 'initialize',
|
|
219
234
|
}
|
|
220
235
|
}
|
|
@@ -246,6 +261,49 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
246
261
|
return this.startOperation('repair', true)
|
|
247
262
|
}
|
|
248
263
|
|
|
264
|
+
async repairCli() {
|
|
265
|
+
return this.startOperation('repair-cli', false, ['install', '--repair-component', 'cli'])
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
async repairLauncher() {
|
|
269
|
+
return this.startOperation('repair-launcher', false, ['install', '--repair-component', 'launcher'])
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
async repairAnalysisSkill() {
|
|
273
|
+
return this.startOperation('repair-analysis-skill', true, ['install', '--repair-component', 'analysis-skill'])
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
async migrateProfiles() {
|
|
277
|
+
return this.startOperation('profile-migration', false, ['profile-migrate', '--approve'])
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
async diagnostics() {
|
|
281
|
+
const roots = defaultRoots()
|
|
282
|
+
const [status, doctor] = await Promise.all([
|
|
283
|
+
this.status(),
|
|
284
|
+
runOnboarding(['doctor', '--no-fail']),
|
|
285
|
+
])
|
|
286
|
+
const report = {
|
|
287
|
+
schemaVersion: 'foggy-deepseek-diagnostics/v1',
|
|
288
|
+
generatedAt: new Date().toISOString(),
|
|
289
|
+
packageVersion: status.packageVersion,
|
|
290
|
+
state: status.state,
|
|
291
|
+
installed: status.installed,
|
|
292
|
+
running: status.running,
|
|
293
|
+
runtimeUrl: status.runtimeUrl,
|
|
294
|
+
roots: status.roots,
|
|
295
|
+
components: status.components,
|
|
296
|
+
onboarding: status.onboarding,
|
|
297
|
+
profileMigration: status.profileMigration,
|
|
298
|
+
doctor,
|
|
299
|
+
}
|
|
300
|
+
const directory = join(roots.dataRoot, 'diagnostics')
|
|
301
|
+
await mkdir(directory, { recursive: true })
|
|
302
|
+
const path = join(directory, `diagnostics-${Date.now()}.json`)
|
|
303
|
+
await writeFile(path, `${JSON.stringify(report, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 })
|
|
304
|
+
return { success: true, path, report }
|
|
305
|
+
}
|
|
306
|
+
|
|
249
307
|
async runtimeStart() {
|
|
250
308
|
return this.startOperation('runtime-start', false, ['runtime-start'])
|
|
251
309
|
}
|
|
@@ -260,7 +318,8 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
260
318
|
}
|
|
261
319
|
const id = `${Date.now()}-${Math.random().toString(16).slice(2, 10)}`
|
|
262
320
|
const args = explicitArgs ?? ['install']
|
|
263
|
-
|
|
321
|
+
const reportsProgress = args[0] === 'install'
|
|
322
|
+
if (reportsProgress) {
|
|
264
323
|
const roots = defaultRoots()
|
|
265
324
|
args.push('--progress-file', join(roots.dataRoot, 'operation-progress.json'), '--operation-id', id, '--operation-kind', kind)
|
|
266
325
|
}
|
|
@@ -276,7 +335,7 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
276
335
|
finishedAt: null,
|
|
277
336
|
result: null,
|
|
278
337
|
error: null,
|
|
279
|
-
progress:
|
|
338
|
+
progress: reportsProgress ? {
|
|
280
339
|
schemaVersion: 'foggy-deepseek-onboarding-progress/v1',
|
|
281
340
|
operationId: id,
|
|
282
341
|
kind,
|
|
@@ -324,7 +383,10 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
324
383
|
}
|
|
325
384
|
|
|
326
385
|
const markerInitializers = []
|
|
327
|
-
for (const method of [
|
|
386
|
+
for (const method of [
|
|
387
|
+
'status', 'plan', 'initialize', 'repair', 'repairCli', 'repairLauncher', 'repairAnalysisSkill',
|
|
388
|
+
'migrateProfiles', 'diagnostics', 'runtimeStart', 'runtimeStop',
|
|
389
|
+
]) {
|
|
328
390
|
Remote(method)(FoggyIntegrationGateway.prototype[method], {
|
|
329
391
|
kind: 'method',
|
|
330
392
|
name: method,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@foggy-projects/deepseek-harness-plugin",
|
|
3
|
-
"version": "0.4.0-beta.
|
|
3
|
+
"version": "0.4.0-beta.7",
|
|
4
4
|
"description": "Foggy Java data analysis engine integration for DeepSeek Harness",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -55,6 +55,6 @@
|
|
|
55
55
|
},
|
|
56
56
|
"scripts": {
|
|
57
57
|
"check": "node --check lib/index.js && node --check lib/skill-provider.js && node --check lib/client.js && node --check lib/typert.js && node --check lib/remote.js",
|
|
58
|
-
"test": "node --test test/package.test.js"
|
|
58
|
+
"test": "node --test test/package.test.js && python test/onboarding_unit.py"
|
|
59
59
|
}
|
|
60
60
|
}
|
|
@@ -22,8 +22,14 @@ copy this Skill into the current workspace.
|
|
|
22
22
|
its absolute command in the global install state.
|
|
23
23
|
- Do not independently download or reinstall the CLI. If the global install state, managed marker, or
|
|
24
24
|
analysis Skill is missing or invalid, ask the user to open the Foggy plugin settings and use
|
|
25
|
-
|
|
25
|
+
the matching component repair action. Repair restores managed components and invalidates the
|
|
26
26
|
native DSH Skill catalog. Reinstall or upgrade the plugin itself to restore this bundled Skill.
|
|
27
|
+
- Treat the current DSH session workspace as the authoritative `projectRoot` for the whole onboarding
|
|
28
|
+
run. Do not redirect semantic drafts or contracts to a different repository merely because another
|
|
29
|
+
Skill or example was found there. Place non-secret contracts below
|
|
30
|
+
`<projectRoot>/.foggy/onboarding-contracts/<profile>/`, drafts below
|
|
31
|
+
`<projectRoot>/.foggy/onboarding-drafts/<profile>/`, and published files below the approved
|
|
32
|
+
project-relative `modelsDir`.
|
|
27
33
|
|
|
28
34
|
## Mandatory orchestration boundary
|
|
29
35
|
|
|
@@ -46,6 +52,9 @@ For every new-database onboarding session, this Skill is the orchestration autho
|
|
|
46
52
|
- Never read query-execution evidence back into the conversation. Report only validation state,
|
|
47
53
|
execution state, row count, and evidence path; do not report row values or generated SQL containing
|
|
48
54
|
business literals.
|
|
55
|
+
- Prefer one composite command per approval boundary. Do not inspect this Skill's Python implementation
|
|
56
|
+
or the CLI package source during a normal run; use the documented command contract and inspect code
|
|
57
|
+
only after a structured wrapper error requires troubleshooting.
|
|
49
58
|
|
|
50
59
|
## Boundaries
|
|
51
60
|
|
|
@@ -66,14 +75,21 @@ For every new-database onboarding session, this Skill is the orchestration autho
|
|
|
66
75
|
plugin's Repair action. Use the matching install script only when the plugin UI is unavailable;
|
|
67
76
|
use `--dry-run` first when paths or permissions are uncertain.
|
|
68
77
|
3. Run `runtime-start` and require successful `wait-ready` plus `capabilities`. Record engine,
|
|
69
|
-
Runtime API version, schema version, security mode, URL, namespace, PID, and evidence path.
|
|
78
|
+
Runtime API version, schema version, security mode, URL, namespace, PID, and evidence path. If the
|
|
79
|
+
recorded Runtime is already running, `runtime-start` verifies and reuses it instead of starting a
|
|
80
|
+
second process.
|
|
70
81
|
4. Load `foggy-ai-analysis` from the native DSH Skill registry. Do not require a workspace copy.
|
|
71
82
|
5. For a new business database, read [references/onboarding-workflow.md](references/onboarding-workflow.md)
|
|
72
83
|
and prefer its two composite `onboard-datasource-run` / `onboard-semantic-run` commands. Require the
|
|
73
|
-
trusted operator to create the private CLI profile outside Harness.
|
|
84
|
+
trusted operator to create the private CLI profile outside Harness. Unless the operator explicitly
|
|
85
|
+
overrides it, use the persistent profile store reported by the wrapper under the Foggy data root
|
|
86
|
+
(`<dataRoot>/cli-profiles`), never `/tmp`. Accept only the opaque profile
|
|
74
87
|
ID, exact revision, datasource name/type, and namespace; never request JDBC URL, username,
|
|
75
88
|
password, or password environment-variable name in Harness.
|
|
76
|
-
|
|
89
|
+
If plugin settings report a legacy temporary profile, use the explicit migration action before
|
|
90
|
+
onboarding. It moves only validated connection metadata and environment-variable references; it
|
|
91
|
+
never copies a password value and leaves a recoverable private backup below the Foggy data root.
|
|
92
|
+
6. After schema discovery, use `foggy-ai-analysis` only to author TM/QM files in the standard project-local
|
|
77
93
|
draft directory. Register, validate, publish, and verify them through this Skill's wrapper using the deterministic commands in
|
|
78
94
|
[references/onboarding-workflow.md](references/onboarding-workflow.md). Do not publish, prune, replace
|
|
79
95
|
a bundle, or execute a business-data query without the matching explicit flag and user approval.
|
|
@@ -98,5 +114,18 @@ In DeepSeek Harness, do not expand the composite onboarding commands back into t
|
|
|
98
114
|
operations. This order documents what the wrapper enforces internally and becomes a direct CLI workflow
|
|
99
115
|
only after onboarding is complete.
|
|
100
116
|
|
|
117
|
+
Composite commands are checkpointed and idempotent: a retry skips completed datasource, validation,
|
|
118
|
+
publication, and verification phases when the approved contract and draft digest are unchanged. Fix a
|
|
119
|
+
query payload in place and rerun the same semantic composite command; do not remove a successfully
|
|
120
|
+
published bundle merely to recover from a later query-validation failure.
|
|
121
|
+
|
|
122
|
+
An already-completed profile may be reused from another DSH workspace when the approved connection
|
|
123
|
+
contract is byte-for-byte equivalent. Run the datasource composite in the new workspace first; it adds
|
|
124
|
+
that workspace as a non-destructive binding and reuses datasource/schema checkpoints. Then pass the
|
|
125
|
+
current workspace explicitly as `--project-root` to the semantic composite. A secondary workspace may
|
|
126
|
+
reuse an identical published semantic digest and run its own bounded verification query, but it cannot
|
|
127
|
+
replace the published semantic layer; changes must be published from the original workspace or a new
|
|
128
|
+
profile.
|
|
129
|
+
|
|
101
130
|
Keep user business data separate from the sales-drop SQLite demo. Prefer a read-only database account,
|
|
102
131
|
opaque CLI profile references, and bounded query limits.
|
|
@@ -13,6 +13,26 @@
|
|
|
13
13
|
"installRoot": {"type": "string"},
|
|
14
14
|
"dataRoot": {"type": "string"},
|
|
15
15
|
"projectRoot": {"type": "string"},
|
|
16
|
+
"workspaceBindings": {
|
|
17
|
+
"type": "array",
|
|
18
|
+
"items": {"type": "string"},
|
|
19
|
+
"uniqueItems": true
|
|
20
|
+
},
|
|
21
|
+
"workspaceVerifications": {
|
|
22
|
+
"type": "array",
|
|
23
|
+
"items": {
|
|
24
|
+
"type": "object",
|
|
25
|
+
"required": ["projectRoot", "queryModel", "queryPayloadDigest", "verifiedAt"],
|
|
26
|
+
"properties": {
|
|
27
|
+
"projectRoot": {"type": "string"},
|
|
28
|
+
"queryModel": {"type": "string"},
|
|
29
|
+
"queryPayloadDigest": {"type": "string", "pattern": "^[a-f0-9]{64}$"},
|
|
30
|
+
"rowCount": {"type": ["integer", "null"], "minimum": 0},
|
|
31
|
+
"verifiedAt": {"type": "string", "format": "date-time"}
|
|
32
|
+
},
|
|
33
|
+
"additionalProperties": false
|
|
34
|
+
}
|
|
35
|
+
},
|
|
16
36
|
"runtime": {"type": "object"},
|
|
17
37
|
"connection": {"$ref": "connection.schema.json"},
|
|
18
38
|
"semantic": {"type": "object"},
|
|
@@ -23,6 +23,22 @@ to paste a password and do not put a JDBC URL, username, password environment-va
|
|
|
23
23
|
line, logs, or evidence. For non-SQLite databases, ask the user to set the named environment variable
|
|
24
24
|
before Runtime starts so the Java process inherits it. Recommend a read-only database account.
|
|
25
25
|
|
|
26
|
+
Use the current DSH session workspace as `projectRoot`. Store approved non-secret contracts at
|
|
27
|
+
`.foggy/onboarding-contracts/<profile>/`, semantic drafts at `.foggy/onboarding-drafts/<profile>/`, and
|
|
28
|
+
command evidence at `.foggy/onboarding-command-evidence/<profile>/`. Do not split these files across the
|
|
29
|
+
session workspace and a separate example repository. The wrapper rejects a query payload outside the
|
|
30
|
+
recorded project root before any semantic validation or publication mutation occurs.
|
|
31
|
+
|
|
32
|
+
The wrapper defaults `FOGGY_RUNTIME_PROFILE_STORE` to the private persistent directory
|
|
33
|
+
`<dataRoot>/cli-profiles`. An explicit operator-provided value still wins. Do not use `/tmp` for a profile
|
|
34
|
+
that must survive a WSL or Harness restart.
|
|
35
|
+
|
|
36
|
+
If plugin settings detect profiles in the legacy temporary store, use **Move to persistent store**.
|
|
37
|
+
Migration validates the opaque profile schema, rejects embedded passwords and conflicts, writes the
|
|
38
|
+
destination with private permissions, verifies it, and moves the legacy JSON to a recoverable private
|
|
39
|
+
backup below the Foggy data root.
|
|
40
|
+
Do not manually copy or edit opaque profile JSON.
|
|
41
|
+
|
|
26
42
|
Treat every user-supplied identifier and bound as immutable input: profile, datasource, namespace,
|
|
27
43
|
models directory, bundle name, TM/QM name, query fields, and limit. Do not swap in demo names, add
|
|
28
44
|
fields, raise the limit, or introduce replacement flags. If one of these inputs is missing, pause for
|
|
@@ -42,17 +58,32 @@ For Harness-driven onboarding, use the two composite commands below. Each writes
|
|
|
42
58
|
evidence internally and refuses to cross an unapproved mutation gate:
|
|
43
59
|
|
|
44
60
|
```text
|
|
45
|
-
onboard-datasource-run --
|
|
61
|
+
onboard-datasource-run --project-root <current-session-workspace> \
|
|
62
|
+
--connection-file <approved-json> \
|
|
46
63
|
--approve-configure --approve-bind --include-indexes
|
|
47
64
|
|
|
48
65
|
# After authoring the registered TM/QM draft from schema metadata:
|
|
49
|
-
onboard-semantic-run --
|
|
66
|
+
onboard-semantic-run --project-root <current-session-workspace> \
|
|
67
|
+
--semantic-plan <approved-json> --query-payload <approved-json> \
|
|
50
68
|
--approve-validate --approve-publish --approve-execute
|
|
51
69
|
```
|
|
52
70
|
|
|
53
71
|
Include an approval flag only after the user approves that exact action. Without it, the composite
|
|
54
72
|
command stops after the corresponding dry-run and returns `phaseStatus=awaiting-...-approval`.
|
|
55
73
|
|
|
74
|
+
Both composite commands are resumable. When the approved contract is unchanged, they skip completed
|
|
75
|
+
checkpoints instead of re-adding an existing datasource, revalidating an already published draft, or
|
|
76
|
+
registering the same bundle twice. If query validation fails after publication, correct the project-local
|
|
77
|
+
payload and rerun `onboard-semantic-run`; it resumes at query verification and leaves the active bundle in
|
|
78
|
+
place. A same-name datasource is accepted idempotently only when its public name and database type match
|
|
79
|
+
the approved plan; otherwise replacement still requires explicit approval.
|
|
80
|
+
|
|
81
|
+
When a completed profile already belongs to another workspace, the datasource composite may add the
|
|
82
|
+
current workspace as a binding only if the approved connection contract is identical and the datasource,
|
|
83
|
+
schema, and semantic publication checkpoints are complete. The semantic composite then accepts the same
|
|
84
|
+
published draft digest from the bound workspace and performs a workspace-specific bounded verification
|
|
85
|
+
query. It refuses semantic replacement from the secondary workspace.
|
|
86
|
+
|
|
56
87
|
The granular commands below remain available for manual troubleshooting and resumption. Do not expand
|
|
57
88
|
the composite commands into this list during a normal Harness turn.
|
|
58
89
|
|
|
@@ -68,8 +99,8 @@ semantic-validate --profile <profile>
|
|
|
68
99
|
semantic-validate --profile <profile> --apply
|
|
69
100
|
semantic-publish --profile <profile>
|
|
70
101
|
semantic-publish --profile <profile> --apply
|
|
71
|
-
semantic-verify --profile <profile> --query-payload <json>
|
|
72
|
-
semantic-verify --profile <profile> --query-payload <json> --execute
|
|
102
|
+
semantic-verify --profile <profile> --project-root <current-session-workspace> --query-payload <json>
|
|
103
|
+
semantic-verify --profile <profile> --project-root <current-session-workspace> --query-payload <json> --execute
|
|
73
104
|
onboard-status --profile <profile>
|
|
74
105
|
```
|
|
75
106
|
|
|
@@ -111,6 +142,11 @@ requires an integer `limit` from 1 through 100. The first `semantic-verify` call
|
|
|
111
142
|
validates the query; only `--execute` reads business data. Full results stay in evidence and the command
|
|
112
143
|
returns only counts and paths.
|
|
113
144
|
|
|
145
|
+
Before the first semantic mutation, the composite command checks that the query payload is inside
|
|
146
|
+
`projectRoot`, has a bounded limit, and targets a query model declared in the approved semantic plan.
|
|
147
|
+
After publication, `semantic-verify` always describes the live model before validation. If a field is
|
|
148
|
+
rejected, update the payload from those described names and rerun the same composite command.
|
|
149
|
+
|
|
114
150
|
Do not open, summarize, or quote `query-execute.json` or the Runtime's generated SQL after execution.
|
|
115
151
|
The conversational result may contain only `queryValidated`, `queryExecuted`, `rowCount`, the model
|
|
116
152
|
name, and the evidence path. A successful direct CLI command is not proof that onboarding completed;
|