@foggy-projects/deepseek-harness-plugin 0.4.0-beta.4 → 0.4.0-beta.5
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 +15 -16
- package/lib/client.js +7 -13
- package/lib/index.js +21 -29
- package/lib/skill-provider.js +111 -0
- package/package.json +3 -2
- package/skills/foggy-deepseek-onboarding/SKILL.md +21 -20
- package/skills/foggy-deepseek-onboarding/assets/versions.json +2 -2
- package/skills/foggy-deepseek-onboarding/scripts/onboarding.py +33 -135
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.5.tgz
|
|
12
12
|
```
|
|
13
13
|
|
|
14
14
|
Restart `dsh web`, open Settings → Plugins → Foggy Data Analysis, and initialize
|
|
@@ -20,27 +20,26 @@ After npm beta publication, the corresponding one-line install is:
|
|
|
20
20
|
dsh plugin --profile web add --workspace-root @foggy-projects/deepseek-harness-plugin@beta
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
For development, `
|
|
24
|
-
|
|
25
|
-
asset-cache directories. Neither variable is required for a normal install.
|
|
23
|
+
For development, `FOGGY_ASSET_CACHE_DIRS` can contain platform-delimited verified
|
|
24
|
+
asset-cache directories. It is not required for a normal install.
|
|
26
25
|
|
|
27
26
|
Database credentials are deliberately outside the ordinary DSH settings
|
|
28
27
|
document. The database and semantic-layer wizard is the next Bundle milestone.
|
|
29
28
|
|
|
30
|
-
##
|
|
29
|
+
## Native Skill and workspace contract
|
|
31
30
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
31
|
+
The Bundle registers `foggy-deepseek-onboarding` and the downloaded
|
|
32
|
+
`foggy-ai-analysis` through DeepSeek Harness's native Skill provider API. Skills
|
|
33
|
+
are available in every DSH workspace without copying or symlinking `.agents`.
|
|
34
|
+
The current session `cwd` remains the workspace boundary for semantic drafts and
|
|
35
|
+
evidence.
|
|
37
36
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
37
|
+
CLI, Launcher, the analysis Skill, install state, and Runtime state live in the
|
|
38
|
+
user-level Foggy component directories. The managed CLI is intentionally isolated
|
|
39
|
+
and does not need to be on `PATH`. **Re-download / Repair** verifies the global
|
|
40
|
+
analysis Skill, backs up modified or outdated managed content, restores it, and
|
|
41
|
+
invalidates DSH's Skill catalog. The onboarding Skill is bundled with the plugin
|
|
42
|
+
and is restored by reinstalling or upgrading the plugin package.
|
|
44
43
|
|
|
45
44
|
## Linux and WSL2 experience
|
|
46
45
|
|
package/lib/client.js
CHANGED
|
@@ -42,7 +42,7 @@ window.__ModuleLoader__.load({
|
|
|
42
42
|
launcher: 'Launcher',
|
|
43
43
|
analysisSkill: '分析 Skill',
|
|
44
44
|
onboardingSkill: '引导 Skill',
|
|
45
|
-
|
|
45
|
+
skillRegistry: 'DSH Skill 注册',
|
|
46
46
|
python: 'Python',
|
|
47
47
|
java: 'Java',
|
|
48
48
|
installed: '已安装',
|
|
@@ -59,7 +59,7 @@ window.__ModuleLoader__.load({
|
|
|
59
59
|
progressCli: '准备 CLI',
|
|
60
60
|
progressLauncher: '准备 Launcher',
|
|
61
61
|
progressAnalysis: '准备分析 Skill',
|
|
62
|
-
progressSkills: '
|
|
62
|
+
progressSkills: '注册 DSH Skills',
|
|
63
63
|
progressState: '写入安装状态',
|
|
64
64
|
progressComplete: '初始化完成',
|
|
65
65
|
progressFiles: '文件',
|
|
@@ -69,10 +69,8 @@ window.__ModuleLoader__.load({
|
|
|
69
69
|
installRoot: '组件目录',
|
|
70
70
|
dataRoot: '数据目录',
|
|
71
71
|
runtimeUrl: 'Runtime 地址',
|
|
72
|
-
projectRoot: 'Skill 目标工作区',
|
|
73
|
-
contextPath: '对话发现文件',
|
|
74
72
|
nextTitle: '后续配置',
|
|
75
|
-
nextCopy: '
|
|
73
|
+
nextCopy: 'Skills 已通过 DeepSeek Harness 原生注册表提供给所有工作区;每个会话直接使用自己的工作目录。Runtime 启动成功后,将继续进入数据库连接与语义层向导。',
|
|
76
74
|
beta: 'Beta',
|
|
77
75
|
}
|
|
78
76
|
|
|
@@ -92,7 +90,7 @@ window.__ModuleLoader__.load({
|
|
|
92
90
|
launcher: 'Launcher',
|
|
93
91
|
analysisSkill: 'Analysis Skill',
|
|
94
92
|
onboardingSkill: 'Onboarding Skill',
|
|
95
|
-
|
|
93
|
+
skillRegistry: 'DSH Skill registry',
|
|
96
94
|
python: 'Python',
|
|
97
95
|
java: 'Java',
|
|
98
96
|
installed: 'Installed',
|
|
@@ -109,7 +107,7 @@ window.__ModuleLoader__.load({
|
|
|
109
107
|
progressCli: 'Preparing CLI',
|
|
110
108
|
progressLauncher: 'Preparing Launcher',
|
|
111
109
|
progressAnalysis: 'Preparing analysis Skill',
|
|
112
|
-
progressSkills: '
|
|
110
|
+
progressSkills: 'Registering DSH Skills',
|
|
113
111
|
progressState: 'Writing install state',
|
|
114
112
|
progressComplete: 'Initialization complete',
|
|
115
113
|
progressFiles: 'files',
|
|
@@ -119,10 +117,8 @@ window.__ModuleLoader__.load({
|
|
|
119
117
|
installRoot: 'Components',
|
|
120
118
|
dataRoot: 'Data',
|
|
121
119
|
runtimeUrl: 'Runtime URL',
|
|
122
|
-
projectRoot: 'Skill target workspace',
|
|
123
|
-
contextPath: 'Conversation discovery file',
|
|
124
120
|
nextTitle: 'Next configuration',
|
|
125
|
-
nextCopy: '
|
|
121
|
+
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.',
|
|
126
122
|
beta: 'Beta',
|
|
127
123
|
}
|
|
128
124
|
|
|
@@ -285,15 +281,13 @@ window.__ModuleLoader__.load({
|
|
|
285
281
|
componentCard(t('launcher'), status.components.launcher, 'runtime', t),
|
|
286
282
|
componentCard(t('analysisSkill'), status.components.analysisSkill, 'runtime', t),
|
|
287
283
|
componentCard(t('onboardingSkill'), status.components.onboardingSkill, 'runtime', t),
|
|
288
|
-
componentCard(t('
|
|
284
|
+
componentCard(t('skillRegistry'), { installed: status.components.onboardingSkill?.provider === 'foggy-managed-skills', version: 'native' }, 'runtime', t),
|
|
289
285
|
] }),
|
|
290
286
|
jsxs('div', { className: 'foggy-paths', children: [
|
|
291
287
|
jsx('h4', { children: t('roots') }),
|
|
292
288
|
jsxs('dl', { children: [
|
|
293
289
|
jsx('dt', { children: t('installRoot') }), jsx('dd', { children: status.roots.installRoot }),
|
|
294
290
|
jsx('dt', { children: t('dataRoot') }), jsx('dd', { children: status.roots.dataRoot }),
|
|
295
|
-
jsx('dt', { children: t('projectRoot') }), jsx('dd', { children: status.projectRoot }),
|
|
296
|
-
jsx('dt', { children: t('contextPath') }), jsx('dd', { children: status.contextPath }),
|
|
297
291
|
status.runtimeUrl ? jsx('dt', { children: t('runtimeUrl') }) : null,
|
|
298
292
|
status.runtimeUrl ? jsx('dd', { children: status.runtimeUrl }) : null,
|
|
299
293
|
] }),
|
package/lib/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import { dirname, join, delimiter } from 'node:path'
|
|
|
5
5
|
import { fileURLToPath } from 'node:url'
|
|
6
6
|
import { promisify } from 'node:util'
|
|
7
7
|
import { Remote, TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol'
|
|
8
|
+
import { createFoggySkillProvider } from './skill-provider.js'
|
|
8
9
|
import { compatible } from './version.js'
|
|
9
10
|
|
|
10
11
|
const execFileAsync = promisify(execFile)
|
|
@@ -120,20 +121,26 @@ function operationView(operation) {
|
|
|
120
121
|
}
|
|
121
122
|
|
|
122
123
|
export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
124
|
+
static inject = ['skills']
|
|
125
|
+
|
|
123
126
|
operation = null
|
|
127
|
+
skillProviderControl = null
|
|
124
128
|
|
|
125
129
|
constructor(ctx) {
|
|
126
130
|
super(ctx, 'foggyIntegration')
|
|
131
|
+
const roots = defaultRoots()
|
|
132
|
+
ctx.skills.registerProvider((control) => {
|
|
133
|
+
this.skillProviderControl = control
|
|
134
|
+
return createFoggySkillProvider({ installRoot: roots.installRoot, versionsFile })
|
|
135
|
+
})
|
|
127
136
|
for (const initialize of markerInitializers) initialize.call(this)
|
|
128
137
|
}
|
|
129
138
|
|
|
130
139
|
async status() {
|
|
131
140
|
const roots = defaultRoots()
|
|
132
|
-
const projectRoot = process.env.FOGGY_PROJECT_ROOT || process.cwd()
|
|
133
141
|
const statePath = join(roots.installRoot, 'install-state.json')
|
|
134
142
|
const runtimeStatePath = join(roots.dataRoot, 'runtime-state.json')
|
|
135
143
|
const progressPath = join(roots.dataRoot, 'operation-progress.json')
|
|
136
|
-
const contextPath = join(projectRoot, '.foggy', 'deepseek-harness', 'context.json')
|
|
137
144
|
const manifest = await readJson(versionsFile)
|
|
138
145
|
let pythonProbe
|
|
139
146
|
try {
|
|
@@ -145,16 +152,13 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
145
152
|
const java = compatible(await commandVersion(process.env.JAVA_EXE || 'java', ['-version']), '17.0')
|
|
146
153
|
let state = null
|
|
147
154
|
let runtime = null
|
|
148
|
-
let context = null
|
|
149
155
|
try { state = await readJson(statePath) } catch {}
|
|
150
156
|
try { runtime = await readJson(runtimeStatePath) } catch {}
|
|
151
|
-
try { context = await readJson(contextPath) } catch {}
|
|
152
157
|
const cliPath = state?.cli?.command
|
|
153
158
|
const launcherPath = state?.launcher?.path
|
|
154
|
-
const analysisSkillPath = state?.skills?.analysis?.path || join(
|
|
155
|
-
const onboardingSkillPath =
|
|
159
|
+
const analysisSkillPath = state?.skills?.analysis?.path || join(roots.installRoot, 'skills', 'foggy-ai-analysis')
|
|
160
|
+
const onboardingSkillPath = join(packageRoot, 'skills', 'foggy-deepseek-onboarding')
|
|
156
161
|
const analysisMarker = await readOptionalJson(join(analysisSkillPath, '.foggy-managed-skill.json'))
|
|
157
|
-
const onboardingMarker = await readOptionalJson(join(onboardingSkillPath, '.foggy-managed-skill.json'))
|
|
158
162
|
const components = {
|
|
159
163
|
python,
|
|
160
164
|
java,
|
|
@@ -175,28 +179,15 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
175
179
|
version: state?.skills?.analysis?.version ?? manifest.components.analysisSkill.version,
|
|
176
180
|
},
|
|
177
181
|
onboardingSkill: {
|
|
178
|
-
installed:
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
&& onboardingMarker?.packageVersion === manifest.packageVersion
|
|
182
|
-
),
|
|
183
|
-
version: state?.skills?.onboarding?.version ?? state?.packageVersion ?? manifest.packageVersion,
|
|
184
|
-
},
|
|
185
|
-
projectContext: {
|
|
186
|
-
installed: Boolean(
|
|
187
|
-
context?.schemaVersion === 'foggy-deepseek-harness-context/v1'
|
|
188
|
-
&& context?.packageVersion === manifest.packageVersion
|
|
189
|
-
&& context?.projectRoot === projectRoot
|
|
190
|
-
&& context?.installStatePath === statePath
|
|
191
|
-
),
|
|
192
|
-
version: context?.schemaVersion ?? 'foggy-deepseek-harness-context/v1',
|
|
182
|
+
installed: await exists(join(onboardingSkillPath, 'SKILL.md')),
|
|
183
|
+
version: manifest.packageVersion,
|
|
184
|
+
provider: 'foggy-managed-skills',
|
|
193
185
|
},
|
|
194
186
|
}
|
|
195
187
|
const installed = components.cli.installed
|
|
196
188
|
&& components.launcher.installed
|
|
197
189
|
&& components.analysisSkill.installed
|
|
198
190
|
&& components.onboardingSkill.installed
|
|
199
|
-
&& components.projectContext.installed
|
|
200
191
|
const running = Boolean(runtime && processRunning(Number(runtime.pid)))
|
|
201
192
|
const progress = await readOptionalJson(progressPath)
|
|
202
193
|
let operation = operationView(this.operation)
|
|
@@ -222,8 +213,6 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
222
213
|
running,
|
|
223
214
|
runtimeUrl: running ? runtime.runtimeUrl ?? null : null,
|
|
224
215
|
roots,
|
|
225
|
-
projectRoot,
|
|
226
|
-
contextPath,
|
|
227
216
|
components,
|
|
228
217
|
operation,
|
|
229
218
|
next: installed ? (running ? 'configure-database' : 'start-runtime') : 'initialize',
|
|
@@ -236,13 +225,14 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
236
225
|
return {
|
|
237
226
|
success: true,
|
|
238
227
|
roots,
|
|
239
|
-
|
|
228
|
+
workspaceMode: 'dsh-session-cwd',
|
|
240
229
|
versions: Object.fromEntries(Object.entries(manifest.components).map(([name, value]) => [name, value.version])),
|
|
241
230
|
operations: [
|
|
242
231
|
'create isolated Python environment',
|
|
243
232
|
'download and verify pinned CLI and Launcher assets',
|
|
244
|
-
'install Foggy analysis
|
|
245
|
-
'
|
|
233
|
+
'install the Foggy analysis Skill into the global managed component directory',
|
|
234
|
+
'register onboarding and analysis Skills through the native DSH Skill registry',
|
|
235
|
+
'write global install state; resolve each workspace from the DSH session cwd',
|
|
246
236
|
],
|
|
247
237
|
secretsInDshSettings: false,
|
|
248
238
|
}
|
|
@@ -269,7 +259,7 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
269
259
|
return { success: false, accepted: false, operation: operationView(this.operation), error: 'another Foggy operation is running' }
|
|
270
260
|
}
|
|
271
261
|
const id = `${Date.now()}-${Math.random().toString(16).slice(2, 10)}`
|
|
272
|
-
const args = explicitArgs ?? ['install'
|
|
262
|
+
const args = explicitArgs ?? ['install']
|
|
273
263
|
if (!explicitArgs) {
|
|
274
264
|
const roots = defaultRoots()
|
|
275
265
|
args.push('--progress-file', join(roots.dataRoot, 'operation-progress.json'), '--operation-id', id, '--operation-kind', kind)
|
|
@@ -304,6 +294,7 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
304
294
|
operation.state = result.success === false ? 'failed' : 'succeeded'
|
|
305
295
|
operation.result = result
|
|
306
296
|
operation.finishedAt = new Date().toISOString()
|
|
297
|
+
this.skillProviderControl?.invalidate()
|
|
307
298
|
if (operation.progress) {
|
|
308
299
|
operation.progress = {
|
|
309
300
|
...operation.progress,
|
|
@@ -318,6 +309,7 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
318
309
|
operation.state = 'failed'
|
|
319
310
|
operation.error = String(error.message ?? error)
|
|
320
311
|
operation.finishedAt = new Date().toISOString()
|
|
312
|
+
this.skillProviderControl?.invalidate()
|
|
321
313
|
if (operation.progress) {
|
|
322
314
|
operation.progress = {
|
|
323
315
|
...operation.progress,
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { access, readFile } from 'node:fs/promises'
|
|
2
|
+
import { constants as fsConstants } from 'node:fs'
|
|
3
|
+
import { dirname, join } from 'node:path'
|
|
4
|
+
import { fileURLToPath } from 'node:url'
|
|
5
|
+
import { BUNDLED_SKILL_RANK } from '@deepseek-ai/dsh-skill'
|
|
6
|
+
|
|
7
|
+
const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)))
|
|
8
|
+
const onboardingRoot = join(packageRoot, 'skills', 'foggy-deepseek-onboarding')
|
|
9
|
+
const onboardingPath = join(onboardingRoot, 'SKILL.md')
|
|
10
|
+
const providerName = 'foggy-managed-skills'
|
|
11
|
+
const invocation = { modelInvocable: true, userInvocable: true }
|
|
12
|
+
|
|
13
|
+
async function exists(path) {
|
|
14
|
+
try {
|
|
15
|
+
await access(path, fsConstants.F_OK)
|
|
16
|
+
return true
|
|
17
|
+
} catch {
|
|
18
|
+
return false
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async function readOptionalJson(path) {
|
|
23
|
+
try {
|
|
24
|
+
return JSON.parse(await readFile(path, 'utf8'))
|
|
25
|
+
} catch {
|
|
26
|
+
return null
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function parseSkill(source, expectedName) {
|
|
31
|
+
const match = source.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/)
|
|
32
|
+
if (!match) throw new Error(`Foggy Skill ${expectedName} has no valid frontmatter`)
|
|
33
|
+
const metadata = Object.fromEntries(match[1].split(/\r?\n/).flatMap((line) => {
|
|
34
|
+
const separator = line.indexOf(':')
|
|
35
|
+
if (separator < 1) return []
|
|
36
|
+
return [[line.slice(0, separator).trim(), line.slice(separator + 1).trim().replace(/^(['\"])(.*)\1$/, '$2')]]
|
|
37
|
+
}))
|
|
38
|
+
if (metadata.name !== expectedName || !metadata.description) {
|
|
39
|
+
throw new Error(`Foggy Skill ${expectedName} has invalid name or description metadata`)
|
|
40
|
+
}
|
|
41
|
+
return { metadata, content: match[2] }
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function candidate(name, description, path, source) {
|
|
45
|
+
const root = dirname(path)
|
|
46
|
+
return {
|
|
47
|
+
name,
|
|
48
|
+
description,
|
|
49
|
+
invocation,
|
|
50
|
+
provider: providerName,
|
|
51
|
+
source,
|
|
52
|
+
resourceBase: { kind: 'directory', path: root },
|
|
53
|
+
rank: BUNDLED_SKILL_RANK,
|
|
54
|
+
locator: { name, path },
|
|
55
|
+
path,
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async function managedAnalysisSkill(installRoot, manifest) {
|
|
60
|
+
const state = await readOptionalJson(join(installRoot, 'install-state.json'))
|
|
61
|
+
const path = state?.skills?.analysis?.path
|
|
62
|
+
if (!path || !await exists(join(path, 'SKILL.md'))) return null
|
|
63
|
+
const marker = await readOptionalJson(join(path, '.foggy-managed-skill.json'))
|
|
64
|
+
if (
|
|
65
|
+
marker?.schemaVersion !== 'foggy-managed-skill/v1'
|
|
66
|
+
|| marker?.kind !== 'analysis'
|
|
67
|
+
|| marker?.componentVersion !== manifest.components.analysisSkill.version
|
|
68
|
+
) return null
|
|
69
|
+
return join(path, 'SKILL.md')
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function createFoggySkillProvider({ installRoot, versionsFile }) {
|
|
73
|
+
return {
|
|
74
|
+
name: providerName,
|
|
75
|
+
async list(options = {}) {
|
|
76
|
+
if (options.signal?.aborted) return []
|
|
77
|
+
const manifest = await readOptionalJson(versionsFile)
|
|
78
|
+
const onboarding = parseSkill(await readFile(onboardingPath, 'utf8'), 'foggy-deepseek-onboarding')
|
|
79
|
+
const result = [candidate(
|
|
80
|
+
'foggy-deepseek-onboarding',
|
|
81
|
+
onboarding.metadata.description,
|
|
82
|
+
onboardingPath,
|
|
83
|
+
'bundled',
|
|
84
|
+
)]
|
|
85
|
+
if (!manifest) return result
|
|
86
|
+
const analysisPath = await managedAnalysisSkill(installRoot, manifest)
|
|
87
|
+
if (analysisPath) {
|
|
88
|
+
const analysis = parseSkill(await readFile(analysisPath, 'utf8'), 'foggy-ai-analysis')
|
|
89
|
+
result.push(candidate('foggy-ai-analysis', analysis.metadata.description, analysisPath, 'bundled'))
|
|
90
|
+
}
|
|
91
|
+
return result
|
|
92
|
+
},
|
|
93
|
+
async get(selected, options = {}) {
|
|
94
|
+
if (options.signal?.aborted) return undefined
|
|
95
|
+
const locator = selected?.locator
|
|
96
|
+
if (!locator?.name || !locator?.path || !await exists(locator.path)) return undefined
|
|
97
|
+
const parsed = parseSkill(await readFile(locator.path, 'utf8'), locator.name)
|
|
98
|
+
return {
|
|
99
|
+
name: locator.name,
|
|
100
|
+
description: parsed.metadata.description,
|
|
101
|
+
invocation,
|
|
102
|
+
provider: providerName,
|
|
103
|
+
source: selected.source,
|
|
104
|
+
resourceBase: { kind: 'directory', path: dirname(locator.path) },
|
|
105
|
+
content: parsed.content,
|
|
106
|
+
path: locator.path,
|
|
107
|
+
metadata: parsed.metadata,
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
}
|
|
111
|
+
}
|
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.5",
|
|
4
4
|
"description": "Foggy Java data analysis engine integration for DeepSeek Harness",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -50,10 +50,11 @@
|
|
|
50
50
|
"@deepseek-ai/dsh-client-runtime": "^0.1.1-rc.2",
|
|
51
51
|
"@deepseek-ai/dsh-client-ui-settings": "^0.1.1-rc.2",
|
|
52
52
|
"@deepseek-ai/dsh-client-ui-settings-plugins": "^0.1.1-rc.2",
|
|
53
|
+
"@deepseek-ai/dsh-skill": "^0.1.1-rc.2",
|
|
53
54
|
"@deepseek-ai/dsh-typert-protocol": "^0.1.1-rc.2"
|
|
54
55
|
},
|
|
55
56
|
"scripts": {
|
|
56
|
-
"check": "node --check lib/index.js && node --check lib/client.js && node --check lib/typert.js && node --check lib/remote.js",
|
|
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",
|
|
57
58
|
"test": "node --test test/package.test.js"
|
|
58
59
|
}
|
|
59
60
|
}
|
|
@@ -7,22 +7,23 @@ description: Install and operate a pinned Foggy CLI-first dev/test environment f
|
|
|
7
7
|
|
|
8
8
|
Set up Foggy through shell and `foggy-runtime` CLI. Do not configure Foggy MCP for this local workflow.
|
|
9
9
|
|
|
10
|
-
##
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
10
|
+
## Native registry and installed-state gate
|
|
11
|
+
|
|
12
|
+
This Skill is registered by the Foggy plugin through DeepSeek Harness's native Skill registry. Its
|
|
13
|
+
resource base is the authoritative location for these scripts and references; do not search for or
|
|
14
|
+
copy this Skill into the current workspace.
|
|
15
|
+
|
|
16
|
+
- Resolve the global install state from the platform default component directory: on Linux use
|
|
17
|
+
`${XDG_DATA_HOME:-$HOME/.local/share}/foggy/deepseek-harness/install-state.json`; on Windows use
|
|
18
|
+
`%LOCALAPPDATA%\Foggy\DeepSeekHarness\install-state.json`.
|
|
19
|
+
- Confirm the installation with this Skill's `doctor` wrapper and pass the current DSH session
|
|
20
|
+
workspace as `--project-root`. The absence of `foggy-runtime` from `PATH` is not evidence that the
|
|
21
|
+
managed CLI is missing; the plugin intentionally installs it in an isolated environment and records
|
|
22
|
+
its absolute command in the global install state.
|
|
23
|
+
- Do not independently download or reinstall the CLI. If the global install state, managed marker, or
|
|
24
|
+
analysis Skill is missing or invalid, ask the user to open the Foggy plugin settings and use
|
|
25
|
+
**Re-download / Repair**. Repair restores the global managed analysis Skill and invalidates the
|
|
26
|
+
native DSH Skill catalog. Reinstall or upgrade the plugin itself to restore this bundled Skill.
|
|
26
27
|
|
|
27
28
|
## Mandatory orchestration boundary
|
|
28
29
|
|
|
@@ -59,14 +60,14 @@ For every new-database onboarding session, this Skill is the orchestration autho
|
|
|
59
60
|
|
|
60
61
|
## Workflow
|
|
61
62
|
|
|
62
|
-
1.
|
|
63
|
-
`bash scripts/doctor.sh --project-root <
|
|
64
|
-
2. If the pinned CLI, Launcher,
|
|
63
|
+
1. Run `scripts/doctor.ps1 --project-root <current-session-workspace>` on Windows or
|
|
64
|
+
`bash scripts/doctor.sh --project-root <current-session-workspace>` on Linux.
|
|
65
|
+
2. If the pinned CLI, Launcher, or global managed analysis Skill is missing, use the Foggy
|
|
65
66
|
plugin's Repair action. Use the matching install script only when the plugin UI is unavailable;
|
|
66
67
|
use `--dry-run` first when paths or permissions are uncertain.
|
|
67
68
|
3. Run `runtime-start` and require successful `wait-ready` plus `capabilities`. Record engine,
|
|
68
69
|
Runtime API version, schema version, security mode, URL, namespace, PID, and evidence path.
|
|
69
|
-
4.
|
|
70
|
+
4. Load `foggy-ai-analysis` from the native DSH Skill registry. Do not require a workspace copy.
|
|
70
71
|
5. For a new business database, read [references/onboarding-workflow.md](references/onboarding-workflow.md)
|
|
71
72
|
and prefer its two composite `onboard-datasource-run` / `onboard-semantic-run` commands. Require the
|
|
72
73
|
trusted operator to create the private CLI profile outside Harness. Accept only the opaque profile
|
|
@@ -25,7 +25,6 @@ import zipfile
|
|
|
25
25
|
STATE_SCHEMA = "foggy-deepseek-onboarding-install/v1"
|
|
26
26
|
RUNTIME_STATE_SCHEMA = "foggy-deepseek-onboarding-runtime/v1"
|
|
27
27
|
ONBOARDING_STATE_SCHEMA = "foggy-deepseek-onboarding-state/v1"
|
|
28
|
-
CONTEXT_SCHEMA = "foggy-deepseek-harness-context/v1"
|
|
29
28
|
MANAGED_SKILL_SCHEMA = "foggy-managed-skill/v1"
|
|
30
29
|
MANAGED_SKILL_MARKER = ".foggy-managed-skill.json"
|
|
31
30
|
LEGACY_SKILL_MARKER = ".foggy-onboarding-install.json"
|
|
@@ -420,60 +419,13 @@ def write_skill_marker(
|
|
|
420
419
|
return marker
|
|
421
420
|
|
|
422
421
|
|
|
423
|
-
def backup_skill(destination: Path,
|
|
424
|
-
backup_root = project_root / ".foggy" / "onboarding-backups"
|
|
422
|
+
def backup_skill(destination: Path, backup_root: Path) -> Path:
|
|
425
423
|
backup_root.mkdir(parents=True, exist_ok=True)
|
|
426
424
|
backup = backup_root / f"{destination.name}-{dt.datetime.now().strftime('%Y%m%d-%H%M%S-%f')}"
|
|
427
425
|
shutil.move(str(destination), str(backup))
|
|
428
426
|
return backup
|
|
429
427
|
|
|
430
428
|
|
|
431
|
-
def project_context_path(project_root: Path) -> Path:
|
|
432
|
-
return project_root / ".foggy" / "deepseek-harness" / "context.json"
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
def project_relative(path: Path, project_root: Path) -> str:
|
|
436
|
-
try:
|
|
437
|
-
return path.resolve(strict=False).relative_to(project_root.resolve(strict=False)).as_posix()
|
|
438
|
-
except ValueError:
|
|
439
|
-
return str(path)
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
def write_project_context(state: dict) -> Path:
|
|
443
|
-
project_root = normalized(state["projectRoot"])
|
|
444
|
-
install_root = normalized(state["installRoot"])
|
|
445
|
-
data_root = normalized(state["dataRoot"])
|
|
446
|
-
context_path = project_context_path(project_root)
|
|
447
|
-
skills = {}
|
|
448
|
-
for kind in ("onboarding", "analysis"):
|
|
449
|
-
item = state["skills"][kind]
|
|
450
|
-
skill_path = normalized(item["path"])
|
|
451
|
-
skills[kind] = {
|
|
452
|
-
"version": item.get("version"),
|
|
453
|
-
"path": project_relative(skill_path, project_root),
|
|
454
|
-
"absolutePath": str(skill_path),
|
|
455
|
-
"markerPath": project_relative(skill_path / MANAGED_SKILL_MARKER, project_root),
|
|
456
|
-
"managed": bool(item.get("managed")),
|
|
457
|
-
}
|
|
458
|
-
payload = {
|
|
459
|
-
"schemaVersion": CONTEXT_SCHEMA,
|
|
460
|
-
"managedBy": "@foggy-projects/deepseek-harness-plugin",
|
|
461
|
-
"packageVersion": state["packageVersion"],
|
|
462
|
-
"generatedAt": now_utc(),
|
|
463
|
-
"projectRoot": str(project_root),
|
|
464
|
-
"installStatePath": str(install_root / "install-state.json"),
|
|
465
|
-
"runtimeStatePath": str(data_root / "runtime-state.json"),
|
|
466
|
-
"operationProgressPath": str(data_root / "operation-progress.json"),
|
|
467
|
-
"cli": state["cli"],
|
|
468
|
-
"launcher": state["launcher"],
|
|
469
|
-
"skills": skills,
|
|
470
|
-
"securityMode": state["securityMode"],
|
|
471
|
-
"productionReady": False,
|
|
472
|
-
}
|
|
473
|
-
atomic_json(context_path, payload)
|
|
474
|
-
return context_path
|
|
475
|
-
|
|
476
|
-
|
|
477
429
|
def read_json_object(path: Path, label: str) -> dict:
|
|
478
430
|
if not path.is_file():
|
|
479
431
|
raise OnboardingError(f"{label} not found: {path}")
|
|
@@ -766,13 +718,13 @@ def safe_extract(zip_path: Path, destination: Path) -> None:
|
|
|
766
718
|
|
|
767
719
|
def install_analysis_skill(
|
|
768
720
|
zip_path: Path,
|
|
769
|
-
|
|
721
|
+
install_root: Path,
|
|
770
722
|
version: str,
|
|
771
723
|
expected_hash: str,
|
|
772
724
|
package_version: str,
|
|
773
725
|
replace: bool,
|
|
774
726
|
) -> dict:
|
|
775
|
-
skills_root =
|
|
727
|
+
skills_root = install_root / "skills"
|
|
776
728
|
destination = skills_root / "foggy-ai-analysis"
|
|
777
729
|
with tempfile.TemporaryDirectory(prefix="foggy-skill-") as temporary:
|
|
778
730
|
extract_root = Path(temporary)
|
|
@@ -804,7 +756,7 @@ def install_analysis_skill(
|
|
|
804
756
|
return {"path": str(destination), "version": version, "digest": marker["installedDigest"], "managed": True, "action": "kept-matching"}
|
|
805
757
|
if not replace:
|
|
806
758
|
raise OnboardingError(f"Analysis Skill is missing, modified, or outdated at {destination}; use the plugin Repair action to back it up and restore it")
|
|
807
|
-
backup_skill(destination,
|
|
759
|
+
backup_skill(destination, install_root / "skill-backups")
|
|
808
760
|
skills_root.mkdir(parents=True, exist_ok=True)
|
|
809
761
|
shutil.copytree(source, destination)
|
|
810
762
|
marker = write_skill_marker(
|
|
@@ -818,46 +770,6 @@ def install_analysis_skill(
|
|
|
818
770
|
return {"path": str(destination), "version": version, "digest": marker["installedDigest"], "managed": True, "action": "installed"}
|
|
819
771
|
|
|
820
772
|
|
|
821
|
-
def install_onboarding_skill(project_root: Path, package_version: str, replace: bool) -> dict:
|
|
822
|
-
destination = project_root / ".agents" / "skills" / "foggy-deepseek-onboarding"
|
|
823
|
-
source = skill_root()
|
|
824
|
-
source_digest = skill_tree_digest(source)
|
|
825
|
-
if source.resolve() == destination.resolve(strict=False):
|
|
826
|
-
return {"path": str(destination), "version": package_version, "digest": source_digest, "managed": True, "action": "already-running-from-target"}
|
|
827
|
-
if destination.exists():
|
|
828
|
-
marker = read_skill_marker(destination)
|
|
829
|
-
actual_digest = skill_tree_digest(destination)
|
|
830
|
-
if (
|
|
831
|
-
marker
|
|
832
|
-
and marker.get("schemaVersion") == MANAGED_SKILL_SCHEMA
|
|
833
|
-
and marker.get("kind") == "onboarding"
|
|
834
|
-
and actual_digest == source_digest
|
|
835
|
-
and marker.get("sourceDigest") in (None, source_digest)
|
|
836
|
-
and marker.get("installedDigest") in (None, source_digest)
|
|
837
|
-
):
|
|
838
|
-
written = write_skill_marker(
|
|
839
|
-
destination,
|
|
840
|
-
kind="onboarding",
|
|
841
|
-
package_version=package_version,
|
|
842
|
-
component_version=package_version,
|
|
843
|
-
source_digest=source_digest,
|
|
844
|
-
)
|
|
845
|
-
return {"path": str(destination), "version": package_version, "digest": written["installedDigest"], "managed": True, "action": "kept-matching"}
|
|
846
|
-
if not replace:
|
|
847
|
-
raise OnboardingError(f"Onboarding Skill is missing, modified, or outdated at {destination}; use the plugin Repair action to back it up and restore it")
|
|
848
|
-
backup_skill(destination, project_root)
|
|
849
|
-
destination.parent.mkdir(parents=True, exist_ok=True)
|
|
850
|
-
shutil.copytree(source, destination)
|
|
851
|
-
marker = write_skill_marker(
|
|
852
|
-
destination,
|
|
853
|
-
kind="onboarding",
|
|
854
|
-
package_version=package_version,
|
|
855
|
-
component_version=package_version,
|
|
856
|
-
source_digest=source_digest,
|
|
857
|
-
)
|
|
858
|
-
return {"path": str(destination), "version": package_version, "digest": marker["installedDigest"], "managed": True, "action": "installed"}
|
|
859
|
-
|
|
860
|
-
|
|
861
773
|
def read_install_state(install_root: Path, required: bool = True) -> dict | None:
|
|
862
774
|
path = install_root / "install-state.json"
|
|
863
775
|
if not path.is_file():
|
|
@@ -884,7 +796,6 @@ def install_command(args: argparse.Namespace) -> dict:
|
|
|
884
796
|
versions = load_versions()
|
|
885
797
|
install_root = normalized(args.install_root or default_install_root())
|
|
886
798
|
data_root = normalized(args.data_root or default_data_root())
|
|
887
|
-
project_root = normalized(args.project_root or Path.cwd())
|
|
888
799
|
cache_dirs = [normalized(item) for item in args.asset_cache_dir]
|
|
889
800
|
components = versions["components"]
|
|
890
801
|
assert_managed_root(install_root, "Install root")
|
|
@@ -895,9 +806,9 @@ def install_command(args: argparse.Namespace) -> dict:
|
|
|
895
806
|
"schemaVersion": "foggy-deepseek-onboarding-plan/v1",
|
|
896
807
|
"installRoot": str(install_root),
|
|
897
808
|
"dataRoot": str(data_root),
|
|
898
|
-
"
|
|
809
|
+
"workspaceMode": "dsh-session-cwd",
|
|
899
810
|
"versions": {name: value.get("version") for name, value in components.items()},
|
|
900
|
-
"operations": ["install isolated CLI", "verify Launcher assets", "install
|
|
811
|
+
"operations": ["install isolated CLI", "verify Launcher assets", "install global analysis Skill", "write install state"],
|
|
901
812
|
"productionReady": False,
|
|
902
813
|
}
|
|
903
814
|
if args.dry_run:
|
|
@@ -911,8 +822,6 @@ def install_command(args: argparse.Namespace) -> dict:
|
|
|
911
822
|
progress.update("preflight", 0, "Checking prerequisites")
|
|
912
823
|
if sys.version_info < (3, 11):
|
|
913
824
|
raise OnboardingError(f"Python 3.11+ required, got {sys.version.split()[0]}")
|
|
914
|
-
if not project_root.is_dir():
|
|
915
|
-
raise OnboardingError(f"Project root not found: {project_root}")
|
|
916
825
|
install_root.mkdir(parents=True, exist_ok=True)
|
|
917
826
|
data_root.mkdir(parents=True, exist_ok=True)
|
|
918
827
|
downloads = install_root / "downloads"
|
|
@@ -1017,21 +926,26 @@ def install_command(args: argparse.Namespace) -> dict:
|
|
|
1017
926
|
zip_asset = next(item for item in analysis_assets if item["role"] == "zip")
|
|
1018
927
|
progress.update("analysis-skill", 3, "Installing analysis Skill", fraction=0.9, current_file=zip_asset["file"])
|
|
1019
928
|
analysis_skill = install_analysis_skill(
|
|
1020
|
-
downloads / "skill" / zip_asset["file"],
|
|
929
|
+
downloads / "skill" / zip_asset["file"], install_root, components["analysisSkill"]["version"],
|
|
1021
930
|
zip_asset["sha256"], versions["packageVersion"], args.replace_skill,
|
|
1022
931
|
)
|
|
1023
932
|
progress.update("analysis-skill", 3, "Analysis Skill ready", fraction=1.0)
|
|
1024
|
-
progress.update("workspace-skills", 4, "
|
|
1025
|
-
onboarding_skill =
|
|
1026
|
-
|
|
933
|
+
progress.update("workspace-skills", 4, "Registering native DSH Skills", fraction=0.1)
|
|
934
|
+
onboarding_skill = {
|
|
935
|
+
"path": str(skill_root()),
|
|
936
|
+
"version": versions["packageVersion"],
|
|
937
|
+
"managed": False,
|
|
938
|
+
"action": "provided-by-plugin",
|
|
939
|
+
"provider": "foggy-managed-skills",
|
|
940
|
+
}
|
|
941
|
+
progress.update("workspace-skills", 4, "Native DSH Skills ready", fraction=1.0)
|
|
1027
942
|
state = {
|
|
1028
943
|
"schemaVersion": STATE_SCHEMA,
|
|
1029
944
|
"installedAt": now_utc(),
|
|
1030
945
|
"packageVersion": versions["packageVersion"],
|
|
1031
946
|
"installRoot": str(install_root),
|
|
1032
947
|
"dataRoot": str(data_root),
|
|
1033
|
-
"
|
|
1034
|
-
"contextPath": str(project_context_path(project_root)),
|
|
948
|
+
"workspaceMode": "dsh-session-cwd",
|
|
1035
949
|
"cli": {"version": cli_component["version"], "command": str(cli_command), "mode": cli_mode},
|
|
1036
950
|
"launcher": {"version": components["launcher"]["version"], "path": str(launcher_dir)},
|
|
1037
951
|
"skills": {"onboarding": onboarding_skill, "analysis": analysis_skill},
|
|
@@ -1041,8 +955,6 @@ def install_command(args: argparse.Namespace) -> dict:
|
|
|
1041
955
|
}
|
|
1042
956
|
progress.update("state", 5, "Writing install state", fraction=0.2, current_file="install-state.json")
|
|
1043
957
|
atomic_json(install_root / "install-state.json", state)
|
|
1044
|
-
progress.update("state", 5, "Writing project context", fraction=0.7, current_file=".foggy/deepseek-harness/context.json")
|
|
1045
|
-
context_path = write_project_context(state)
|
|
1046
958
|
progress.finish()
|
|
1047
959
|
ACTIVE_PROGRESS = None
|
|
1048
960
|
return {
|
|
@@ -1051,8 +963,7 @@ def install_command(args: argparse.Namespace) -> dict:
|
|
|
1051
963
|
"statePath": str(install_root / "install-state.json"),
|
|
1052
964
|
"installRoot": str(install_root),
|
|
1053
965
|
"dataRoot": str(data_root),
|
|
1054
|
-
"
|
|
1055
|
-
"contextPath": str(context_path),
|
|
966
|
+
"workspaceMode": "dsh-session-cwd",
|
|
1056
967
|
"cliVersion": cli_component["version"],
|
|
1057
968
|
"launcherVersion": components["launcher"]["version"],
|
|
1058
969
|
"analysisSkill": analysis_skill,
|
|
@@ -1314,7 +1225,7 @@ def require_opaque_profile_cli(install_state: dict) -> None:
|
|
|
1314
1225
|
def onboarding_plan_command(args: argparse.Namespace) -> dict:
|
|
1315
1226
|
install_root, install_state, data_root, runtime_state = onboarding_context(args, require_runtime=False)
|
|
1316
1227
|
profile = safe_profile(args.profile)
|
|
1317
|
-
project_root = normalized(args.project_root or
|
|
1228
|
+
project_root = normalized(args.project_root or Path.cwd())
|
|
1318
1229
|
if not project_root.is_dir():
|
|
1319
1230
|
raise OnboardingError(f"Project root not found: {project_root}")
|
|
1320
1231
|
connection_file = normalized(args.connection_file)
|
|
@@ -1974,7 +1885,7 @@ def save_composite_result(evidence_dir: Path, name: str, payload: dict, files: l
|
|
|
1974
1885
|
|
|
1975
1886
|
def datasource_run_command(args: argparse.Namespace) -> dict:
|
|
1976
1887
|
_install_root, install_state, data_root, _runtime_state = onboarding_context(args, require_runtime=True)
|
|
1977
|
-
project_root = normalized(args.project_root or
|
|
1888
|
+
project_root = normalized(args.project_root or Path.cwd())
|
|
1978
1889
|
requested_connection = validate_connection(read_json_object(normalized(args.connection_file), "Connection plan"))
|
|
1979
1890
|
if not requested_connection.get("profile"):
|
|
1980
1891
|
raise OnboardingError("Composite datasource onboarding requires connection.profile in the approved contract")
|
|
@@ -2234,24 +2145,17 @@ def doctor_command(args: argparse.Namespace) -> dict:
|
|
|
2234
2145
|
path = launcher_dir / asset["file"]
|
|
2235
2146
|
launcher_checks.append({"file": asset["file"], "present": path.is_file(), "sha256Valid": path.is_file() and sha256(path) == asset["sha256"]})
|
|
2236
2147
|
launcher_ok = bool(launcher_checks) and all(item["present"] and item["sha256Valid"] for item in launcher_checks)
|
|
2237
|
-
analysis_skill_root =
|
|
2238
|
-
onboarding_skill_root =
|
|
2148
|
+
analysis_skill_root = normalized(state.get("skills", {}).get("analysis", {}).get("path") or install_root / "skills" / "foggy-ai-analysis") if state else install_root / "skills" / "foggy-ai-analysis"
|
|
2149
|
+
onboarding_skill_root = skill_root()
|
|
2239
2150
|
analysis_skill = managed_skill_status(analysis_skill_root, "analysis", versions["components"]["analysisSkill"]["version"])
|
|
2240
|
-
onboarding_skill =
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
context_ok = bool(
|
|
2249
|
-
context
|
|
2250
|
-
and context.get("schemaVersion") == CONTEXT_SCHEMA
|
|
2251
|
-
and context.get("packageVersion") == versions["packageVersion"]
|
|
2252
|
-
and normalized(context.get("projectRoot", "")) == project_root
|
|
2253
|
-
and normalized(context.get("installStatePath", "")) == install_root / "install-state.json"
|
|
2254
|
-
)
|
|
2151
|
+
onboarding_skill = {
|
|
2152
|
+
"path": str(onboarding_skill_root),
|
|
2153
|
+
"present": (onboarding_skill_root / "SKILL.md").is_file(),
|
|
2154
|
+
"managed": False,
|
|
2155
|
+
"version": versions["packageVersion"],
|
|
2156
|
+
"provider": "foggy-managed-skills",
|
|
2157
|
+
"valid": (onboarding_skill_root / "SKILL.md").is_file(),
|
|
2158
|
+
}
|
|
2255
2159
|
runtime = {"status": "stopped"}
|
|
2256
2160
|
if state:
|
|
2257
2161
|
data_root = normalized(state["dataRoot"])
|
|
@@ -2267,7 +2171,6 @@ def doctor_command(args: argparse.Namespace) -> dict:
|
|
|
2267
2171
|
"launcher": launcher_ok,
|
|
2268
2172
|
"analysisSkill": analysis_skill["valid"],
|
|
2269
2173
|
"onboardingSkill": onboarding_skill["valid"],
|
|
2270
|
-
"projectContext": context_ok,
|
|
2271
2174
|
}
|
|
2272
2175
|
if args.strict_runtime:
|
|
2273
2176
|
required["runtime"] = runtime["status"] == "running"
|
|
@@ -2282,7 +2185,7 @@ def doctor_command(args: argparse.Namespace) -> dict:
|
|
|
2282
2185
|
"cli": cli,
|
|
2283
2186
|
"launcherAssets": launcher_checks,
|
|
2284
2187
|
"skills": {"analysis": analysis_skill, "onboarding": onboarding_skill},
|
|
2285
|
-
"
|
|
2188
|
+
"workspace": {"path": str(project_root), "mode": "dsh-session-cwd"},
|
|
2286
2189
|
"runtime": runtime,
|
|
2287
2190
|
"environmentPresence": {name: bool(os.environ.get(name)) for name in ("DEEPSEEK_API_KEY", "ALIYUN_TOKEN_PLAN_API_KEY", "FOGGY_RUNTIME_API_AUTH_CODE", "FOGGY_RUNTIME_AUTHORIZATION")},
|
|
2288
2191
|
"productionReady": False,
|
|
@@ -2298,13 +2201,8 @@ def uninstall_command(args: argparse.Namespace) -> dict:
|
|
|
2298
2201
|
assert_managed_root(data_root, "Data root")
|
|
2299
2202
|
if install_root == data_root:
|
|
2300
2203
|
raise OnboardingError("Install root and data root must be different")
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
skill_targets = [skills_root / name for name in ("foggy-deepseek-onboarding", "foggy-ai-analysis")]
|
|
2304
|
-
if args.remove_skills:
|
|
2305
|
-
for target in skill_targets:
|
|
2306
|
-
if target.exists() and (target.is_symlink() or not is_child(target, skills_root)):
|
|
2307
|
-
raise OnboardingError(f"Refusing to remove unexpected Skill path: {target}")
|
|
2204
|
+
skills_root = install_root / "skills"
|
|
2205
|
+
skill_targets = [skills_root / "foggy-ai-analysis"]
|
|
2308
2206
|
plan = {"installRoot": str(install_root), "dataRoot": str(data_root), "removeSkills": args.remove_skills, "purgeData": args.purge_data}
|
|
2309
2207
|
if args.dry_run:
|
|
2310
2208
|
return {"success": True, "dryRun": True, "plan": plan}
|