@foggy-projects/deepseek-harness-plugin 0.4.0-beta.9 → 0.4.0-rc.2
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 +55 -20
- package/docs/PUBLIC-BETA-READINESS.md +71 -15
- package/docs/RELEASE-CANDIDATE-0.4.0-RC.2.md +38 -0
- package/docs/WINDOWS-BETA-ACCEPTANCE.md +57 -22
- package/experience/linux/prepare.sh +2 -2
- package/lib/client.js +249 -27
- package/lib/diagnostics.js +86 -0
- package/lib/index.js +113 -15
- package/lib/remote-descriptor.js +16 -2
- package/lib/runtime-settings.js +89 -0
- package/lib/skill-provider.js +13 -8
- package/package.json +11 -10
- package/skills/foggy-deepseek-onboarding/SKILL.md +126 -127
- package/skills/foggy-deepseek-onboarding/assets/connection.schema.json +6 -8
- package/skills/foggy-deepseek-onboarding/assets/datasource.example.json +3 -2
- package/skills/foggy-deepseek-onboarding/assets/env.example +4 -4
- package/skills/foggy-deepseek-onboarding/assets/onboarding-state.schema.json +30 -1
- package/skills/foggy-deepseek-onboarding/assets/versions.json +54 -29
- package/skills/foggy-deepseek-onboarding/references/onboarding-workflow.md +134 -122
- package/skills/foggy-deepseek-onboarding/scripts/invoke-onboarding.ps1 +2 -0
- package/skills/foggy-deepseek-onboarding/scripts/onboarding.py +689 -81
package/lib/index.js
CHANGED
|
@@ -9,6 +9,12 @@ import { createFoggySkillProvider } from './skill-provider.js'
|
|
|
9
9
|
import { writeJsonAtomic } from './atomic-json.js'
|
|
10
10
|
import { ensurePythonRuntime, probePythonRuntime } from './python-runtime.js'
|
|
11
11
|
import { compatible, compatibleNode } from './version.js'
|
|
12
|
+
import { enrichRuntimeStartFailure } from './diagnostics.js'
|
|
13
|
+
import {
|
|
14
|
+
DEFAULT_RUNTIME_PORT,
|
|
15
|
+
readRuntimeSettings,
|
|
16
|
+
writeRuntimeSettings,
|
|
17
|
+
} from './runtime-settings.js'
|
|
12
18
|
|
|
13
19
|
const execFileAsync = promisify(execFile)
|
|
14
20
|
const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)))
|
|
@@ -131,6 +137,8 @@ async function assertSystemPrerequisites(kind) {
|
|
|
131
137
|
|
|
132
138
|
function createPythonProgressReporter(operation, path) {
|
|
133
139
|
let pending = Promise.resolve()
|
|
140
|
+
const runtimeStart = operation.kind === 'runtime-start'
|
|
141
|
+
const totalSteps = runtimeStart ? 6 : 7
|
|
134
142
|
return {
|
|
135
143
|
update(detail) {
|
|
136
144
|
const fraction = Math.max(0, Math.min(1, Number(detail.fraction) || 0))
|
|
@@ -139,11 +147,11 @@ function createPythonProgressReporter(operation, path) {
|
|
|
139
147
|
operationId: operation.id,
|
|
140
148
|
kind: operation.kind,
|
|
141
149
|
state: 'running',
|
|
142
|
-
phase: 'python',
|
|
143
|
-
message: detail.message || 'Preparing managed Python',
|
|
150
|
+
phase: runtimeStart ? 'runtime-preflight' : 'python',
|
|
151
|
+
message: runtimeStart ? 'Preparing the Foggy Runtime controller' : detail.message || 'Preparing managed Python',
|
|
144
152
|
currentFile: detail.currentFile || null,
|
|
145
|
-
percent: Math.round(((1 + fraction) /
|
|
146
|
-
step: { index: 2, total:
|
|
153
|
+
percent: runtimeStart ? Math.round(fraction * 3) : Math.round(((1 + fraction) / totalSteps) * 100),
|
|
154
|
+
step: { index: runtimeStart ? 1 : 2, total: totalSteps },
|
|
147
155
|
startedAt: operation.startedAt,
|
|
148
156
|
updatedAt: new Date().toISOString(),
|
|
149
157
|
}
|
|
@@ -194,13 +202,19 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
194
202
|
const statePath = join(roots.installRoot, 'install-state.json')
|
|
195
203
|
const runtimeStatePath = join(roots.dataRoot, 'runtime-state.json')
|
|
196
204
|
const progressPath = join(roots.dataRoot, 'operation-progress.json')
|
|
205
|
+
const portConflictPath = join(roots.dataRoot, 'last-runtime-port-conflict.json')
|
|
197
206
|
const manifest = await readJson(versionsFile)
|
|
207
|
+
const runtimeSettings = await readRuntimeSettings(roots.dataRoot, {
|
|
208
|
+
defaultPort: manifest.defaults?.port ?? DEFAULT_RUNTIME_PORT,
|
|
209
|
+
})
|
|
198
210
|
const python = await probePythonRuntime({ installRoot: roots.installRoot, manifest })
|
|
199
211
|
const java = compatible(await commandVersion(process.env.JAVA_EXE || 'java', ['-version']), '17.0')
|
|
200
212
|
let state = null
|
|
201
213
|
let runtime = null
|
|
214
|
+
let lastRuntimePortConflict = null
|
|
202
215
|
try { state = await readJson(statePath) } catch {}
|
|
203
216
|
try { runtime = await readJson(runtimeStatePath) } catch {}
|
|
217
|
+
try { lastRuntimePortConflict = await readJson(portConflictPath) } catch {}
|
|
204
218
|
let onboarding = { success: true, profiles: [], profileCount: 0 }
|
|
205
219
|
let profileMigration = { success: true, entries: [], pendingCount: 0, conflictCount: 0, profileStore: roots.profileStore }
|
|
206
220
|
if (state) {
|
|
@@ -214,8 +228,10 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
214
228
|
const cliPath = state?.cli?.command
|
|
215
229
|
const launcherPath = state?.launcher?.path
|
|
216
230
|
const analysisSkillPath = state?.skills?.analysis?.path || join(roots.installRoot, 'skills', 'foggy-ai-analysis')
|
|
231
|
+
const semanticQuerySkillPath = state?.skills?.semanticQuery?.path || join(roots.installRoot, 'skills', 'foggy-semantic-query')
|
|
217
232
|
const onboardingSkillPath = join(packageRoot, 'skills', 'foggy-deepseek-onboarding')
|
|
218
233
|
const analysisMarker = await readOptionalJson(join(analysisSkillPath, '.foggy-managed-skill.json'))
|
|
234
|
+
const semanticQueryMarker = await readOptionalJson(join(semanticQuerySkillPath, '.foggy-managed-skill.json'))
|
|
219
235
|
const components = {
|
|
220
236
|
python,
|
|
221
237
|
java,
|
|
@@ -235,6 +251,14 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
235
251
|
),
|
|
236
252
|
version: state?.skills?.analysis?.version ?? manifest.components.analysisSkill.version,
|
|
237
253
|
},
|
|
254
|
+
semanticQuerySkill: {
|
|
255
|
+
installed: Boolean(
|
|
256
|
+
await exists(join(semanticQuerySkillPath, 'SKILL.md'))
|
|
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,
|
|
261
|
+
},
|
|
238
262
|
onboardingSkill: {
|
|
239
263
|
installed: await exists(join(onboardingSkillPath, 'SKILL.md')),
|
|
240
264
|
version: manifest.packageVersion,
|
|
@@ -245,8 +269,10 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
245
269
|
&& components.cli.installed
|
|
246
270
|
&& components.launcher.installed
|
|
247
271
|
&& components.analysisSkill.installed
|
|
272
|
+
&& components.semanticQuerySkill.installed
|
|
248
273
|
&& components.onboardingSkill.installed
|
|
249
274
|
const running = Boolean(runtime && processRunning(Number(runtime.pid)))
|
|
275
|
+
const activePort = running && Number.isInteger(Number(runtime?.port)) ? Number(runtime.port) : null
|
|
250
276
|
const progress = await readOptionalJson(progressPath)
|
|
251
277
|
let operation = operationView(this.operation)
|
|
252
278
|
if (operation.state === 'running' && progress?.operationId === operation.id) {
|
|
@@ -270,6 +296,14 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
270
296
|
installed,
|
|
271
297
|
running,
|
|
272
298
|
runtimeUrl: running ? runtime.runtimeUrl ?? null : null,
|
|
299
|
+
runtimeSettings: {
|
|
300
|
+
...runtimeSettings,
|
|
301
|
+
activePort,
|
|
302
|
+
activeRuntimeUrl: running ? runtime.runtimeUrl ?? null : null,
|
|
303
|
+
pendingRestart: Boolean(running && activePort && activePort !== runtimeSettings.port),
|
|
304
|
+
lastConflict: lastRuntimePortConflict,
|
|
305
|
+
conflictApplies: Number(lastRuntimePortConflict?.port) === runtimeSettings.port,
|
|
306
|
+
},
|
|
273
307
|
roots,
|
|
274
308
|
components,
|
|
275
309
|
operation,
|
|
@@ -291,8 +325,8 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
291
325
|
'download and verify a pinned private Python runtime',
|
|
292
326
|
'create isolated Python environment',
|
|
293
327
|
'download and verify pinned CLI and Launcher assets',
|
|
294
|
-
'install the Foggy analysis
|
|
295
|
-
'register onboarding and
|
|
328
|
+
'install the Foggy analysis and semantic-query Skills into the global managed component directory',
|
|
329
|
+
'register onboarding, analysis, and semantic-query Skills through the native DSH Skill registry',
|
|
296
330
|
'write global install state; resolve each workspace from the DSH session cwd',
|
|
297
331
|
],
|
|
298
332
|
secretsInDshSettings: false,
|
|
@@ -323,6 +357,10 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
323
357
|
return this.startOperation('repair-analysis-skill', true, ['install', '--repair-component', 'analysis-skill'])
|
|
324
358
|
}
|
|
325
359
|
|
|
360
|
+
async repairSemanticQuerySkill() {
|
|
361
|
+
return this.startOperation('repair-semantic-query-skill', true, ['install', '--repair-component', 'semantic-query-skill'])
|
|
362
|
+
}
|
|
363
|
+
|
|
326
364
|
async migrateProfiles() {
|
|
327
365
|
return this.startOperation('profile-migration', false, ['profile-migrate', '--approve'])
|
|
328
366
|
}
|
|
@@ -330,6 +368,10 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
330
368
|
async diagnostics() {
|
|
331
369
|
const roots = defaultRoots()
|
|
332
370
|
const status = await this.status()
|
|
371
|
+
const lastRuntimeStartFailure = await enrichRuntimeStartFailure(
|
|
372
|
+
await readOptionalJson(join(roots.dataRoot, 'last-runtime-start-failure.json')),
|
|
373
|
+
roots.dataRoot,
|
|
374
|
+
)
|
|
333
375
|
let doctor
|
|
334
376
|
try {
|
|
335
377
|
doctor = await runOnboarding(['doctor', '--no-fail'])
|
|
@@ -348,6 +390,8 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
348
390
|
components: status.components,
|
|
349
391
|
onboarding: status.onboarding,
|
|
350
392
|
profileMigration: status.profileMigration,
|
|
393
|
+
runtimeSettings: status.runtimeSettings,
|
|
394
|
+
lastRuntimeStartFailure,
|
|
351
395
|
doctor,
|
|
352
396
|
}
|
|
353
397
|
const directory = join(roots.dataRoot, 'diagnostics')
|
|
@@ -358,11 +402,61 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
358
402
|
}
|
|
359
403
|
|
|
360
404
|
async runtimeStart() {
|
|
361
|
-
|
|
405
|
+
const roots = defaultRoots()
|
|
406
|
+
const manifest = await readJson(versionsFile)
|
|
407
|
+
const settings = await readRuntimeSettings(roots.dataRoot, {
|
|
408
|
+
defaultPort: manifest.defaults?.port ?? DEFAULT_RUNTIME_PORT,
|
|
409
|
+
})
|
|
410
|
+
if (!settings.valid) {
|
|
411
|
+
return {
|
|
412
|
+
success: false,
|
|
413
|
+
accepted: false,
|
|
414
|
+
error: {
|
|
415
|
+
code: 'RUNTIME_SETTINGS_INVALID',
|
|
416
|
+
message: `Runtime settings are invalid: ${settings.error}. Save a valid port in Foggy plugin settings.`,
|
|
417
|
+
},
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
return this.startOperation('runtime-start', false, [
|
|
421
|
+
'runtime-start', '--install-root', roots.installRoot, '--data-root', roots.dataRoot,
|
|
422
|
+
'--port', String(settings.port),
|
|
423
|
+
])
|
|
362
424
|
}
|
|
363
425
|
|
|
364
426
|
async runtimeStop() {
|
|
365
|
-
|
|
427
|
+
const roots = defaultRoots()
|
|
428
|
+
return this.startOperation('runtime-stop', false, [
|
|
429
|
+
'runtime-stop', '--install-root', roots.installRoot, '--data-root', roots.dataRoot,
|
|
430
|
+
])
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
async saveRuntimeSettings(input) {
|
|
434
|
+
const roots = defaultRoots()
|
|
435
|
+
if (this.operation?.state === 'running') {
|
|
436
|
+
return {
|
|
437
|
+
success: false,
|
|
438
|
+
error: { code: 'OPERATION_RUNNING', message: 'Wait for the current Foggy operation to finish before changing the Runtime port.' },
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
const runtime = await readOptionalJson(join(roots.dataRoot, 'runtime-state.json'))
|
|
442
|
+
if (runtime && processRunning(Number(runtime.pid))) {
|
|
443
|
+
return {
|
|
444
|
+
success: false,
|
|
445
|
+
error: { code: 'RUNTIME_RUNNING', message: 'Stop Foggy Runtime before changing its port.' },
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
try {
|
|
449
|
+
const settings = await writeRuntimeSettings(roots.dataRoot, input)
|
|
450
|
+
if (this.operation?.state === 'failed' && this.operation.result?.error?.code === 'RUNTIME_PORT_UNAVAILABLE') {
|
|
451
|
+
this.operation = null
|
|
452
|
+
}
|
|
453
|
+
return { success: true, settings }
|
|
454
|
+
} catch (error) {
|
|
455
|
+
return {
|
|
456
|
+
success: false,
|
|
457
|
+
error: { code: 'RUNTIME_PORT_INVALID', message: String(error?.message ?? error) },
|
|
458
|
+
}
|
|
459
|
+
}
|
|
366
460
|
}
|
|
367
461
|
|
|
368
462
|
startOperation(kind, replaceSkill, explicitArgs) {
|
|
@@ -371,7 +465,7 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
371
465
|
}
|
|
372
466
|
const id = `${Date.now()}-${Math.random().toString(16).slice(2, 10)}`
|
|
373
467
|
const args = explicitArgs ?? ['install']
|
|
374
|
-
const reportsProgress = args[0] === 'install'
|
|
468
|
+
const reportsProgress = args[0] === 'install' || args[0] === 'runtime-start'
|
|
375
469
|
if (reportsProgress) {
|
|
376
470
|
const roots = defaultRoots()
|
|
377
471
|
args.push('--progress-file', join(roots.dataRoot, 'operation-progress.json'), '--operation-id', id, '--operation-kind', kind)
|
|
@@ -380,6 +474,7 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
380
474
|
for (const cacheDir of (process.env.FOGGY_ASSET_CACHE_DIRS || '').split(delimiter).filter(Boolean)) {
|
|
381
475
|
args.push('--asset-cache-dir', cacheDir)
|
|
382
476
|
}
|
|
477
|
+
const runtimeStart = kind === 'runtime-start'
|
|
383
478
|
const operation = {
|
|
384
479
|
id,
|
|
385
480
|
kind,
|
|
@@ -394,10 +489,10 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
394
489
|
kind,
|
|
395
490
|
state: 'running',
|
|
396
491
|
phase: 'preflight',
|
|
397
|
-
message: 'Starting Foggy initialization',
|
|
492
|
+
message: runtimeStart ? 'Starting Foggy Runtime' : 'Starting Foggy initialization',
|
|
398
493
|
currentFile: null,
|
|
399
494
|
percent: 0,
|
|
400
|
-
step: { index: 1, total: 7 },
|
|
495
|
+
step: { index: 1, total: runtimeStart ? 6 : 7 },
|
|
401
496
|
} : null,
|
|
402
497
|
promise: null,
|
|
403
498
|
}
|
|
@@ -422,8 +517,10 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
422
517
|
operation.progress = {
|
|
423
518
|
...operation.progress,
|
|
424
519
|
state: operation.state,
|
|
425
|
-
phase: operation.state === 'succeeded' ? 'complete' : operation.progress.phase,
|
|
426
|
-
message: operation.state === 'succeeded'
|
|
520
|
+
phase: operation.state === 'succeeded' ? (runtimeStart ? 'runtime-complete' : 'complete') : operation.progress.phase,
|
|
521
|
+
message: operation.state === 'succeeded'
|
|
522
|
+
? (runtimeStart ? 'Foggy Runtime is ready' : 'Foggy initialization completed')
|
|
523
|
+
: (runtimeStart ? 'Foggy Runtime startup failed' : 'Foggy initialization failed'),
|
|
427
524
|
percent: operation.state === 'succeeded' ? 100 : operation.progress.percent,
|
|
428
525
|
}
|
|
429
526
|
}
|
|
@@ -437,7 +534,7 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
437
534
|
operation.progress = {
|
|
438
535
|
...operation.progress,
|
|
439
536
|
state: 'failed',
|
|
440
|
-
message: 'Foggy initialization failed',
|
|
537
|
+
message: runtimeStart ? 'Foggy Runtime startup failed' : 'Foggy initialization failed',
|
|
441
538
|
}
|
|
442
539
|
}
|
|
443
540
|
})
|
|
@@ -448,8 +545,9 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
448
545
|
|
|
449
546
|
const markerInitializers = []
|
|
450
547
|
for (const method of [
|
|
451
|
-
'status', 'plan', 'initialize', 'repair', 'repairPython', 'repairCli', 'repairLauncher', 'repairAnalysisSkill',
|
|
548
|
+
'status', 'plan', 'initialize', 'repair', 'repairPython', 'repairCli', 'repairLauncher', 'repairAnalysisSkill', 'repairSemanticQuerySkill',
|
|
452
549
|
'migrateProfiles', 'diagnostics', 'runtimeStart', 'runtimeStop',
|
|
550
|
+
'saveRuntimeSettings',
|
|
453
551
|
]) {
|
|
454
552
|
Remote(method)(FoggyIntegrationGateway.prototype[method], {
|
|
455
553
|
kind: 'method',
|
package/lib/remote-descriptor.js
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import { z } from 'zod'
|
|
2
2
|
|
|
3
3
|
const resultSchema = z.unknown()
|
|
4
|
+
const runtimeSettingsInputSchema = z.object({
|
|
5
|
+
port: z.number().int().min(1024).max(65535),
|
|
6
|
+
}).strict()
|
|
4
7
|
|
|
5
|
-
function descriptor(method) {
|
|
8
|
+
function descriptor(method, parameters = []) {
|
|
6
9
|
return {
|
|
7
10
|
id: `@foggy-projects/deepseek-harness-plugin#foggyIntegration/${method}`,
|
|
8
11
|
service: 'foggyIntegration',
|
|
9
12
|
namespace: 'foggyIntegration',
|
|
10
13
|
method,
|
|
11
14
|
invocation: { kind: 'direct' },
|
|
12
|
-
parameters
|
|
15
|
+
parameters,
|
|
13
16
|
result: {
|
|
14
17
|
mode: 'strict',
|
|
15
18
|
typeSymbol: '@foggy-projects/deepseek-harness-plugin#FoggyIntegrationResult',
|
|
@@ -25,6 +28,17 @@ export const descriptors = [
|
|
|
25
28
|
descriptor('initialize'),
|
|
26
29
|
descriptor('repair'),
|
|
27
30
|
descriptor('repairPython'),
|
|
31
|
+
descriptor('repairSemanticQuerySkill'),
|
|
28
32
|
descriptor('runtimeStart'),
|
|
29
33
|
descriptor('runtimeStop'),
|
|
34
|
+
descriptor('saveRuntimeSettings', [{
|
|
35
|
+
name: 'input',
|
|
36
|
+
wire: 'input',
|
|
37
|
+
source: 'json',
|
|
38
|
+
codec: {
|
|
39
|
+
mode: 'strict',
|
|
40
|
+
typeSymbol: '@foggy-projects/deepseek-harness-plugin#FoggyRuntimeSettingsInput',
|
|
41
|
+
schema: runtimeSettingsInputSchema,
|
|
42
|
+
},
|
|
43
|
+
}]),
|
|
30
44
|
]
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
import { writeJsonAtomic } from './atomic-json.js'
|
|
4
|
+
|
|
5
|
+
export const RUNTIME_SETTINGS_SCHEMA = 'foggy-deepseek-runtime-settings/v1'
|
|
6
|
+
export const DEFAULT_RUNTIME_PORT = 18166
|
|
7
|
+
export const MIN_RUNTIME_PORT = 1024
|
|
8
|
+
export const MAX_RUNTIME_PORT = 65535
|
|
9
|
+
|
|
10
|
+
export function normalizeRuntimePort(value) {
|
|
11
|
+
const port = typeof value === 'string' && value.trim() !== '' ? Number(value) : value
|
|
12
|
+
if (!Number.isInteger(port) || port < MIN_RUNTIME_PORT || port > MAX_RUNTIME_PORT) {
|
|
13
|
+
throw new Error(`Runtime port must be an integer between ${MIN_RUNTIME_PORT} and ${MAX_RUNTIME_PORT}`)
|
|
14
|
+
}
|
|
15
|
+
return port
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function runtimeUrlForPort(port) {
|
|
19
|
+
return `http://127.0.0.1:${normalizeRuntimePort(port)}`
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function runtimeSettingsPath(dataRoot) {
|
|
23
|
+
return join(dataRoot, 'runtime-settings.json')
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export async function readRuntimeSettings(dataRoot, { defaultPort = DEFAULT_RUNTIME_PORT } = {}) {
|
|
27
|
+
const path = runtimeSettingsPath(dataRoot)
|
|
28
|
+
const fallbackPort = normalizeRuntimePort(defaultPort)
|
|
29
|
+
try {
|
|
30
|
+
const payload = JSON.parse(await readFile(path, 'utf8'))
|
|
31
|
+
if (payload?.schemaVersion !== RUNTIME_SETTINGS_SCHEMA) {
|
|
32
|
+
throw new Error(`expected schemaVersion ${RUNTIME_SETTINGS_SCHEMA}`)
|
|
33
|
+
}
|
|
34
|
+
const port = normalizeRuntimePort(payload.runtimePort)
|
|
35
|
+
return {
|
|
36
|
+
valid: true,
|
|
37
|
+
source: 'configured',
|
|
38
|
+
schemaVersion: RUNTIME_SETTINGS_SCHEMA,
|
|
39
|
+
port,
|
|
40
|
+
runtimeUrl: runtimeUrlForPort(port),
|
|
41
|
+
updatedAt: payload.updatedAt ?? null,
|
|
42
|
+
path,
|
|
43
|
+
error: null,
|
|
44
|
+
}
|
|
45
|
+
} catch (error) {
|
|
46
|
+
if (error?.code === 'ENOENT') {
|
|
47
|
+
return {
|
|
48
|
+
valid: true,
|
|
49
|
+
source: 'default',
|
|
50
|
+
schemaVersion: RUNTIME_SETTINGS_SCHEMA,
|
|
51
|
+
port: fallbackPort,
|
|
52
|
+
runtimeUrl: runtimeUrlForPort(fallbackPort),
|
|
53
|
+
updatedAt: null,
|
|
54
|
+
path,
|
|
55
|
+
error: null,
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
valid: false,
|
|
60
|
+
source: 'invalid',
|
|
61
|
+
schemaVersion: RUNTIME_SETTINGS_SCHEMA,
|
|
62
|
+
port: fallbackPort,
|
|
63
|
+
runtimeUrl: runtimeUrlForPort(fallbackPort),
|
|
64
|
+
updatedAt: null,
|
|
65
|
+
path,
|
|
66
|
+
error: String(error?.message ?? error),
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export async function writeRuntimeSettings(dataRoot, input) {
|
|
72
|
+
const runtimePort = normalizeRuntimePort(input?.port)
|
|
73
|
+
const payload = {
|
|
74
|
+
schemaVersion: RUNTIME_SETTINGS_SCHEMA,
|
|
75
|
+
runtimePort,
|
|
76
|
+
updatedAt: new Date().toISOString(),
|
|
77
|
+
}
|
|
78
|
+
const path = runtimeSettingsPath(dataRoot)
|
|
79
|
+
await writeJsonAtomic(path, payload)
|
|
80
|
+
return {
|
|
81
|
+
valid: true,
|
|
82
|
+
source: 'configured',
|
|
83
|
+
...payload,
|
|
84
|
+
port: runtimePort,
|
|
85
|
+
runtimeUrl: runtimeUrlForPort(runtimePort),
|
|
86
|
+
path,
|
|
87
|
+
error: null,
|
|
88
|
+
}
|
|
89
|
+
}
|
package/lib/skill-provider.js
CHANGED
|
@@ -56,15 +56,15 @@ function candidate(name, description, path, source) {
|
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
async function
|
|
59
|
+
async function managedSkill(installRoot, manifest, { stateKey, componentKey, kind }) {
|
|
60
60
|
const state = await readOptionalJson(join(installRoot, 'install-state.json'))
|
|
61
|
-
const path = state?.skills?.
|
|
61
|
+
const path = state?.skills?.[stateKey]?.path
|
|
62
62
|
if (!path || !await exists(join(path, 'SKILL.md'))) return null
|
|
63
63
|
const marker = await readOptionalJson(join(path, '.foggy-managed-skill.json'))
|
|
64
64
|
if (
|
|
65
65
|
marker?.schemaVersion !== 'foggy-managed-skill/v1'
|
|
66
|
-
|| marker?.kind !==
|
|
67
|
-
|| marker?.componentVersion !== manifest.components.
|
|
66
|
+
|| marker?.kind !== kind
|
|
67
|
+
|| marker?.componentVersion !== manifest.components[componentKey].version
|
|
68
68
|
) return null
|
|
69
69
|
return join(path, 'SKILL.md')
|
|
70
70
|
}
|
|
@@ -83,10 +83,15 @@ export function createFoggySkillProvider({ installRoot, versionsFile }) {
|
|
|
83
83
|
'bundled',
|
|
84
84
|
)]
|
|
85
85
|
if (!manifest) return result
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
86
|
+
const managedSkills = [
|
|
87
|
+
{ name: 'foggy-ai-analysis', stateKey: 'analysis', componentKey: 'analysisSkill', kind: 'analysis' },
|
|
88
|
+
{ name: 'foggy-semantic-query', stateKey: 'semanticQuery', componentKey: 'semanticQuerySkill', kind: 'semantic-query' },
|
|
89
|
+
]
|
|
90
|
+
for (const spec of managedSkills) {
|
|
91
|
+
const path = await managedSkill(installRoot, manifest, spec)
|
|
92
|
+
if (!path) continue
|
|
93
|
+
const skill = parseSkill(await readFile(path, 'utf8'), spec.name)
|
|
94
|
+
result.push(candidate(spec.name, skill.metadata.description, path, 'bundled'))
|
|
90
95
|
}
|
|
91
96
|
return result
|
|
92
97
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@foggy-projects/deepseek-harness-plugin",
|
|
3
|
-
"version": "0.4.0-
|
|
3
|
+
"version": "0.4.0-rc.2",
|
|
4
4
|
"description": "Foggy Java data analysis engine integration for DeepSeek Harness",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"cordis.patch.yml",
|
|
21
21
|
"experience/linux/**",
|
|
22
22
|
"docs/PUBLIC-BETA-READINESS.md",
|
|
23
|
+
"docs/RELEASE-CANDIDATE-0.4.0-RC.2.md",
|
|
23
24
|
"docs/WINDOWS-BETA-ACCEPTANCE.md",
|
|
24
25
|
"THIRD-PARTY-RUNTIME-NOTICES.md",
|
|
25
26
|
"README.md"
|
|
@@ -48,16 +49,16 @@
|
|
|
48
49
|
},
|
|
49
50
|
"peerDependencies": {
|
|
50
51
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
51
|
-
"@deepseek-ai/dsh-api-remotes": "^0.1.
|
|
52
|
-
"@deepseek-ai/dsh-client-locale": "^0.1.
|
|
53
|
-
"@deepseek-ai/dsh-client-runtime": "^0.1.
|
|
54
|
-
"@deepseek-ai/dsh-client-ui-settings": "^0.1.
|
|
55
|
-
"@deepseek-ai/dsh-client-ui-settings-plugins": "^0.1.
|
|
56
|
-
"@deepseek-ai/dsh-skill": "^0.1.
|
|
57
|
-
"@deepseek-ai/dsh-typert-protocol": "^0.1.
|
|
52
|
+
"@deepseek-ai/dsh-api-remotes": "^0.1.2-rc.1",
|
|
53
|
+
"@deepseek-ai/dsh-client-locale": "^0.1.2-rc.1",
|
|
54
|
+
"@deepseek-ai/dsh-client-runtime": "^0.1.2-rc.1",
|
|
55
|
+
"@deepseek-ai/dsh-client-ui-settings": "^0.1.2-rc.1",
|
|
56
|
+
"@deepseek-ai/dsh-client-ui-settings-plugins": "^0.1.2-rc.1",
|
|
57
|
+
"@deepseek-ai/dsh-skill": "^0.1.2-rc.1",
|
|
58
|
+
"@deepseek-ai/dsh-typert-protocol": "^0.1.2-rc.1"
|
|
58
59
|
},
|
|
59
60
|
"scripts": {
|
|
60
|
-
"check": "node --check lib/index.js && node --check lib/atomic-json.js && node --check lib/python-runtime.js && node --check lib/skill-provider.js && node --check lib/client.js && node --check lib/typert.js && node --check lib/remote.js",
|
|
61
|
-
"test": "node --test test/package.test.js &&
|
|
61
|
+
"check": "node --check lib/index.js && node --check lib/atomic-json.js && node --check lib/diagnostics.js && node --check lib/python-runtime.js && node --check lib/runtime-settings.js && node --check lib/skill-provider.js && node --check lib/client.js && node --check lib/typert.js && node --check lib/remote.js",
|
|
62
|
+
"test": "node --test test/package.test.js && node test/run-onboarding-tests.js"
|
|
62
63
|
}
|
|
63
64
|
}
|