@foggy-projects/deepseek-harness-plugin 0.4.0-beta.13 → 0.4.0-beta.15
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 +24 -14
- package/docs/PUBLIC-BETA-READINESS.md +32 -6
- package/docs/WINDOWS-BETA-ACCEPTANCE.md +28 -14
- package/experience/linux/prepare.sh +1 -1
- package/lib/client.js +191 -24
- package/lib/index.js +66 -0
- package/lib/remote-descriptor.js +15 -2
- package/lib/runtime-settings.js +89 -0
- package/package.json +2 -2
- package/skills/foggy-deepseek-onboarding/SKILL.md +106 -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 +23 -1
- package/skills/foggy-deepseek-onboarding/assets/versions.json +2 -2
- package/skills/foggy-deepseek-onboarding/references/onboarding-workflow.md +113 -123
- package/skills/foggy-deepseek-onboarding/scripts/onboarding.py +200 -27
package/lib/index.js
CHANGED
|
@@ -10,6 +10,11 @@ import { writeJsonAtomic } from './atomic-json.js'
|
|
|
10
10
|
import { ensurePythonRuntime, probePythonRuntime } from './python-runtime.js'
|
|
11
11
|
import { compatible, compatibleNode } from './version.js'
|
|
12
12
|
import { enrichRuntimeStartFailure } from './diagnostics.js'
|
|
13
|
+
import {
|
|
14
|
+
DEFAULT_RUNTIME_PORT,
|
|
15
|
+
readRuntimeSettings,
|
|
16
|
+
writeRuntimeSettings,
|
|
17
|
+
} from './runtime-settings.js'
|
|
13
18
|
|
|
14
19
|
const execFileAsync = promisify(execFile)
|
|
15
20
|
const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)))
|
|
@@ -197,13 +202,19 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
197
202
|
const statePath = join(roots.installRoot, 'install-state.json')
|
|
198
203
|
const runtimeStatePath = join(roots.dataRoot, 'runtime-state.json')
|
|
199
204
|
const progressPath = join(roots.dataRoot, 'operation-progress.json')
|
|
205
|
+
const portConflictPath = join(roots.dataRoot, 'last-runtime-port-conflict.json')
|
|
200
206
|
const manifest = await readJson(versionsFile)
|
|
207
|
+
const runtimeSettings = await readRuntimeSettings(roots.dataRoot, {
|
|
208
|
+
defaultPort: manifest.defaults?.port ?? DEFAULT_RUNTIME_PORT,
|
|
209
|
+
})
|
|
201
210
|
const python = await probePythonRuntime({ installRoot: roots.installRoot, manifest })
|
|
202
211
|
const java = compatible(await commandVersion(process.env.JAVA_EXE || 'java', ['-version']), '17.0')
|
|
203
212
|
let state = null
|
|
204
213
|
let runtime = null
|
|
214
|
+
let lastRuntimePortConflict = null
|
|
205
215
|
try { state = await readJson(statePath) } catch {}
|
|
206
216
|
try { runtime = await readJson(runtimeStatePath) } catch {}
|
|
217
|
+
try { lastRuntimePortConflict = await readJson(portConflictPath) } catch {}
|
|
207
218
|
let onboarding = { success: true, profiles: [], profileCount: 0 }
|
|
208
219
|
let profileMigration = { success: true, entries: [], pendingCount: 0, conflictCount: 0, profileStore: roots.profileStore }
|
|
209
220
|
if (state) {
|
|
@@ -250,6 +261,7 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
250
261
|
&& components.analysisSkill.installed
|
|
251
262
|
&& components.onboardingSkill.installed
|
|
252
263
|
const running = Boolean(runtime && processRunning(Number(runtime.pid)))
|
|
264
|
+
const activePort = running && Number.isInteger(Number(runtime?.port)) ? Number(runtime.port) : null
|
|
253
265
|
const progress = await readOptionalJson(progressPath)
|
|
254
266
|
let operation = operationView(this.operation)
|
|
255
267
|
if (operation.state === 'running' && progress?.operationId === operation.id) {
|
|
@@ -273,6 +285,14 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
273
285
|
installed,
|
|
274
286
|
running,
|
|
275
287
|
runtimeUrl: running ? runtime.runtimeUrl ?? null : null,
|
|
288
|
+
runtimeSettings: {
|
|
289
|
+
...runtimeSettings,
|
|
290
|
+
activePort,
|
|
291
|
+
activeRuntimeUrl: running ? runtime.runtimeUrl ?? null : null,
|
|
292
|
+
pendingRestart: Boolean(running && activePort && activePort !== runtimeSettings.port),
|
|
293
|
+
lastConflict: lastRuntimePortConflict,
|
|
294
|
+
conflictApplies: Number(lastRuntimePortConflict?.port) === runtimeSettings.port,
|
|
295
|
+
},
|
|
276
296
|
roots,
|
|
277
297
|
components,
|
|
278
298
|
operation,
|
|
@@ -355,6 +375,7 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
355
375
|
components: status.components,
|
|
356
376
|
onboarding: status.onboarding,
|
|
357
377
|
profileMigration: status.profileMigration,
|
|
378
|
+
runtimeSettings: status.runtimeSettings,
|
|
358
379
|
lastRuntimeStartFailure,
|
|
359
380
|
doctor,
|
|
360
381
|
}
|
|
@@ -367,8 +388,23 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
367
388
|
|
|
368
389
|
async runtimeStart() {
|
|
369
390
|
const roots = defaultRoots()
|
|
391
|
+
const manifest = await readJson(versionsFile)
|
|
392
|
+
const settings = await readRuntimeSettings(roots.dataRoot, {
|
|
393
|
+
defaultPort: manifest.defaults?.port ?? DEFAULT_RUNTIME_PORT,
|
|
394
|
+
})
|
|
395
|
+
if (!settings.valid) {
|
|
396
|
+
return {
|
|
397
|
+
success: false,
|
|
398
|
+
accepted: false,
|
|
399
|
+
error: {
|
|
400
|
+
code: 'RUNTIME_SETTINGS_INVALID',
|
|
401
|
+
message: `Runtime settings are invalid: ${settings.error}. Save a valid port in Foggy plugin settings.`,
|
|
402
|
+
},
|
|
403
|
+
}
|
|
404
|
+
}
|
|
370
405
|
return this.startOperation('runtime-start', false, [
|
|
371
406
|
'runtime-start', '--install-root', roots.installRoot, '--data-root', roots.dataRoot,
|
|
407
|
+
'--port', String(settings.port),
|
|
372
408
|
])
|
|
373
409
|
}
|
|
374
410
|
|
|
@@ -379,6 +415,35 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
379
415
|
])
|
|
380
416
|
}
|
|
381
417
|
|
|
418
|
+
async saveRuntimeSettings(input) {
|
|
419
|
+
const roots = defaultRoots()
|
|
420
|
+
if (this.operation?.state === 'running') {
|
|
421
|
+
return {
|
|
422
|
+
success: false,
|
|
423
|
+
error: { code: 'OPERATION_RUNNING', message: 'Wait for the current Foggy operation to finish before changing the Runtime port.' },
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
const runtime = await readOptionalJson(join(roots.dataRoot, 'runtime-state.json'))
|
|
427
|
+
if (runtime && processRunning(Number(runtime.pid))) {
|
|
428
|
+
return {
|
|
429
|
+
success: false,
|
|
430
|
+
error: { code: 'RUNTIME_RUNNING', message: 'Stop Foggy Runtime before changing its port.' },
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
try {
|
|
434
|
+
const settings = await writeRuntimeSettings(roots.dataRoot, input)
|
|
435
|
+
if (this.operation?.state === 'failed' && this.operation.result?.error?.code === 'RUNTIME_PORT_UNAVAILABLE') {
|
|
436
|
+
this.operation = null
|
|
437
|
+
}
|
|
438
|
+
return { success: true, settings }
|
|
439
|
+
} catch (error) {
|
|
440
|
+
return {
|
|
441
|
+
success: false,
|
|
442
|
+
error: { code: 'RUNTIME_PORT_INVALID', message: String(error?.message ?? error) },
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
382
447
|
startOperation(kind, replaceSkill, explicitArgs) {
|
|
383
448
|
if (this.operation?.state === 'running') {
|
|
384
449
|
return { success: false, accepted: false, operation: operationView(this.operation), error: 'another Foggy operation is running' }
|
|
@@ -467,6 +532,7 @@ const markerInitializers = []
|
|
|
467
532
|
for (const method of [
|
|
468
533
|
'status', 'plan', 'initialize', 'repair', 'repairPython', 'repairCli', 'repairLauncher', 'repairAnalysisSkill',
|
|
469
534
|
'migrateProfiles', 'diagnostics', 'runtimeStart', 'runtimeStop',
|
|
535
|
+
'saveRuntimeSettings',
|
|
470
536
|
]) {
|
|
471
537
|
Remote(method)(FoggyIntegrationGateway.prototype[method], {
|
|
472
538
|
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',
|
|
@@ -27,4 +30,14 @@ export const descriptors = [
|
|
|
27
30
|
descriptor('repairPython'),
|
|
28
31
|
descriptor('runtimeStart'),
|
|
29
32
|
descriptor('runtimeStop'),
|
|
33
|
+
descriptor('saveRuntimeSettings', [{
|
|
34
|
+
name: 'input',
|
|
35
|
+
wire: 'input',
|
|
36
|
+
source: 'json',
|
|
37
|
+
codec: {
|
|
38
|
+
mode: 'strict',
|
|
39
|
+
typeSymbol: '@foggy-projects/deepseek-harness-plugin#FoggyRuntimeSettingsInput',
|
|
40
|
+
schema: runtimeSettingsInputSchema,
|
|
41
|
+
},
|
|
42
|
+
}]),
|
|
30
43
|
]
|
|
@@ -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/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.15",
|
|
4
4
|
"description": "Foggy Java data analysis engine integration for DeepSeek Harness",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"@deepseek-ai/dsh-typert-protocol": "^0.1.2-rc.1"
|
|
58
58
|
},
|
|
59
59
|
"scripts": {
|
|
60
|
-
"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/skill-provider.js && node --check lib/client.js && node --check lib/typert.js && node --check lib/remote.js",
|
|
60
|
+
"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",
|
|
61
61
|
"test": "node --test test/package.test.js && node test/run-onboarding-tests.js"
|
|
62
62
|
}
|
|
63
63
|
}
|
|
@@ -1,137 +1,116 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: foggy-deepseek-onboarding
|
|
3
|
-
description:
|
|
3
|
+
description: Set up and use Foggy Runtime for data-source exploration and semantic-model development inside DeepSeek Harness. Use for local experience, datasource onboarding, TM/QM authoring, validation, and development publication; route production deployment or updates to a separate release workflow.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Foggy DeepSeek onboarding
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
5. For a new business database, read [references/onboarding-workflow.md](references/onboarding-workflow.md)
|
|
89
|
-
and prefer its two composite `onboard-datasource-run` / `onboard-semantic-run` commands. Require the
|
|
90
|
-
trusted operator to create the private CLI profile outside Harness. Unless the operator explicitly
|
|
91
|
-
overrides it, use the persistent profile store reported by the wrapper under the Foggy data root
|
|
92
|
-
(`<dataRoot>/cli-profiles`), never `/tmp`. Accept only the opaque profile
|
|
93
|
-
ID, exact revision, datasource name/type, and namespace; never request JDBC URL, username,
|
|
94
|
-
password, or password environment-variable name in Harness.
|
|
95
|
-
If plugin settings report a legacy temporary profile, use the explicit migration action before
|
|
96
|
-
onboarding. It moves only validated connection metadata and environment-variable references; it
|
|
97
|
-
never copies a password value and leaves a recoverable private backup below the Foggy data root.
|
|
98
|
-
6. After schema discovery, use `foggy-ai-analysis` only to author TM/QM files in the standard project-local
|
|
99
|
-
draft directory. Register, validate, publish, and verify them through this Skill's wrapper using the deterministic commands in
|
|
100
|
-
[references/onboarding-workflow.md](references/onboarding-workflow.md). Do not publish, prune, replace
|
|
101
|
-
a bundle, or execute a business-data query without the matching explicit flag and user approval.
|
|
102
|
-
7. Stop only the Runtime PID recorded by this package. Preserve Runtime data unless the user explicitly
|
|
103
|
-
requests purge.
|
|
104
|
-
|
|
105
|
-
## Command contract
|
|
106
|
-
|
|
107
|
-
All package scripts return one JSON object on stdout. Treat `success=false` or a nonzero exit code as a
|
|
108
|
-
failure. Do not infer readiness from a fixed sleep; require CLI `wait-ready` and `capabilities`.
|
|
109
|
-
|
|
110
|
-
Use this analysis order after setup:
|
|
8
|
+
Use this Skill for the normal DeepSeek Harness experience: connect a development datasource, inspect
|
|
9
|
+
it, create TM/QM files in the current workspace, and iterate until queries pass. Use the managed
|
|
10
|
+
`foggy-runtime` CLI and this Skill's wrappers; do not configure Foggy MCP for this local workflow.
|
|
11
|
+
|
|
12
|
+
## Product boundary
|
|
13
|
+
|
|
14
|
+
- Treat the plugin and bundled Launcher as local experience and development tooling.
|
|
15
|
+
- Datasources, namespace bindings, model Bundles, refreshes, and query checks are online Runtime
|
|
16
|
+
operations. They do not require a Runtime restart.
|
|
17
|
+
- Start Runtime only when it is absent. Reuse a healthy running Runtime. Restart only when the user
|
|
18
|
+
asks, a Launcher/JAR upgrade requires it, Runtime is unhealthy, or an actual startup setting such as
|
|
19
|
+
port, JVM options, Runtime authentication, or an opt-in module changes.
|
|
20
|
+
- Do not turn production publication into a continuation of local onboarding. When the user wants to
|
|
21
|
+
deploy or update a formal environment, recommend a manual release or a dedicated production
|
|
22
|
+
deployment workflow with separately supplied target access, credentials, version, verification, and
|
|
23
|
+
rollback information.
|
|
24
|
+
- Do not modify Foggy engine or CLI source. If progress genuinely requires either change, stop and ask
|
|
25
|
+
for explicit authorization.
|
|
26
|
+
|
|
27
|
+
## Managed installation
|
|
28
|
+
|
|
29
|
+
This Skill is registered through DeepSeek Harness's native Skill registry. Its scripts and references
|
|
30
|
+
are authoritative; do not copy the Skill into the current workspace.
|
|
31
|
+
|
|
32
|
+
- Linux install state: `${XDG_DATA_HOME:-$HOME/.local/share}/foggy/deepseek-harness/install-state.json`.
|
|
33
|
+
- Windows install state: `%LOCALAPPDATA%\Foggy\DeepSeekHarness\install-state.json`.
|
|
34
|
+
- Run this Skill's `doctor` wrapper with the current DSH workspace as `--project-root`. The managed CLI
|
|
35
|
+
is intentionally isolated, so absence from `PATH` does not mean it is missing.
|
|
36
|
+
- Use plugin settings to initialize or repair private Python, CLI, Launcher, or the managed analysis
|
|
37
|
+
Skill. Do not independently reinstall them during a normal analysis session.
|
|
38
|
+
- Treat the current DSH workspace as `projectRoot`. Keep model drafts and final model files there rather
|
|
39
|
+
than redirecting them to an example repository.
|
|
40
|
+
|
|
41
|
+
## Development workflow
|
|
42
|
+
|
|
43
|
+
1. Run `doctor`. Start Runtime only if it is not already healthy; require `wait-ready` and
|
|
44
|
+
`capabilities` after a new start.
|
|
45
|
+
2. Accept datasource connection details from the user's message, a user-supplied local JSON file, an
|
|
46
|
+
environment variable, or Runtime Console. Direct `password` is supported for local development.
|
|
47
|
+
The wrapper submits it to the public Runtime API without copying it into onboarding state or
|
|
48
|
+
evidence. Do not echo it in the response.
|
|
49
|
+
3. Create or select the namespace, add/test the datasource online, and bind it to the namespace. Do
|
|
50
|
+
not stop or restart Runtime to make a password available. A running Runtime can accept a direct
|
|
51
|
+
development password through its datasource API.
|
|
52
|
+
4. Inspect tables, columns, keys, and relationships. Small, bounded, read-only SQL samples are allowed
|
|
53
|
+
when they help infer captions, enums, units, or date semantics. Do not run mutations unless the user
|
|
54
|
+
explicitly requests them.
|
|
55
|
+
5. Load `foggy-ai-analysis` from the native registry only for TM/QM authoring and query tuning; its
|
|
56
|
+
generic installation, datasource-secret, and production-deployment guidance does not override this
|
|
57
|
+
development workflow. Default to a project-local `models/` directory unless the user specifies
|
|
58
|
+
another directory.
|
|
59
|
+
6. Iterate through model validation, Bundle registration/update, model refresh/describe, query
|
|
60
|
+
validation, and bounded query execution. Development publication means making the local model
|
|
61
|
+
directory effective in this local Runtime; it is not a production release.
|
|
62
|
+
7. When the model works, recommend committing the model directory to the user's own Git repository.
|
|
63
|
+
Do not initialize a repository, commit, push, or create a remote unless the user requests it.
|
|
64
|
+
|
|
65
|
+
Read [references/onboarding-workflow.md](references/onboarding-workflow.md) for the wrapper commands and
|
|
66
|
+
credential shapes. Use `foggy-ai-analysis` references for detailed TM/QM modeling and query tuning.
|
|
67
|
+
|
|
68
|
+
## Credential choices for local development
|
|
69
|
+
|
|
70
|
+
Choose the simplest source the user provides:
|
|
71
|
+
|
|
72
|
+
- `password` in a connection file: simplest for an experience session; the source file remains under
|
|
73
|
+
the user's control and should normally stay outside Git.
|
|
74
|
+
- `passwordEnv`: the wrapper reads the variable from the Agent process and submits the value online;
|
|
75
|
+
Runtime does not need to inherit it at startup.
|
|
76
|
+
- Opaque profile: optional for users who already have one; never require it for ordinary onboarding.
|
|
77
|
+
- Runtime Console: when a Launcher exposing Runtime Console is installed, the user may enter the
|
|
78
|
+
connection there using the management token shown by the host/plugin.
|
|
79
|
+
|
|
80
|
+
Keep only a minimal development safety baseline: do not echo passwords, put them in TM/QM files,
|
|
81
|
+
include them in evidence/diagnostics, or commit them to Git. Do not impose production IAM, audit,
|
|
82
|
+
approval, secret-store, or network-governance requirements on this local flow.
|
|
83
|
+
|
|
84
|
+
## Command behavior
|
|
85
|
+
|
|
86
|
+
All scripts emit one JSON object. Treat `success=false` or a nonzero exit code as failure. Prefer the
|
|
87
|
+
two resumable composite commands for a complete requested experience:
|
|
111
88
|
|
|
112
89
|
```text
|
|
113
|
-
datasource
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
90
|
+
onboard-datasource-run --project-root <workspace> --connection-file <json> \
|
|
91
|
+
--approve-configure --approve-bind --include-indexes
|
|
92
|
+
|
|
93
|
+
onboard-semantic-run --project-root <workspace> --semantic-plan <json> \
|
|
94
|
+
--query-payload <json> --approve-validate --approve-publish --approve-execute
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
When the user has already asked to connect, build, and test a new local model, those flags implement
|
|
98
|
+
that request and do not require separate question-by-question confirmation. Replacement, pruning, broad
|
|
99
|
+
queries, destructive SQL, Git push, and production deployment still require their own clear scope.
|
|
100
|
+
|
|
101
|
+
The normal analysis order is:
|
|
102
|
+
|
|
103
|
+
```text
|
|
104
|
+
datasource add/test -> namespace bind -> table/schema inspection
|
|
105
|
+
TM/QM authoring -> models validate -> bundle add/update -> refresh/describe
|
|
106
|
+
query validate -> bounded query execute -> tune -> optional Git handoff
|
|
117
107
|
```
|
|
118
108
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
query
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
An already-completed profile may be reused from another DSH workspace when the approved connection
|
|
129
|
-
contract is byte-for-byte equivalent. Run the datasource composite in the new workspace first; it adds
|
|
130
|
-
that workspace as a non-destructive binding and reuses datasource/schema checkpoints. Then pass the
|
|
131
|
-
current workspace explicitly as `--project-root` to the semantic composite. A secondary workspace may
|
|
132
|
-
reuse an identical published semantic digest and run its own bounded verification query, but it cannot
|
|
133
|
-
replace the published semantic layer; changes must be published from the original workspace or a new
|
|
134
|
-
profile.
|
|
135
|
-
|
|
136
|
-
Keep user business data separate from the sales-drop SQLite demo. Prefer a read-only database account,
|
|
137
|
-
opaque CLI profile references, and bounded query limits.
|
|
109
|
+
Stop only the PID recorded by this package and preserve the Runtime work directory unless the user
|
|
110
|
+
explicitly requests removal.
|
|
111
|
+
|
|
112
|
+
## Result
|
|
113
|
+
|
|
114
|
+
Report the Runtime URL, namespace, datasource name, model directory, Bundle and QueryModel names,
|
|
115
|
+
validation/query status, and useful evidence paths. Never include the password or business row values
|
|
116
|
+
unless the user specifically asks for those values.
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"type": {"enum": ["sqlite", "mysql", "postgres", "postgresql"]},
|
|
13
13
|
"jdbcUrl": {"type": "string", "minLength": 1},
|
|
14
14
|
"username": {"type": "string"},
|
|
15
|
+
"password": {"type": "string", "description": "Optional local development password. It is submitted once and is not copied into onboarding state or evidence."},
|
|
15
16
|
"passwordEnv": {"type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"},
|
|
16
17
|
"opaqueProfileId": {"type": "string", "pattern": "^fop_[a-f0-9]{32}$"},
|
|
17
18
|
"opaqueRevision": {"type": "string", "pattern": "^sha256:[a-f0-9]{64}$"},
|
|
@@ -27,6 +28,7 @@
|
|
|
27
28
|
"not": {"anyOf": [
|
|
28
29
|
{"required": ["jdbcUrl"]},
|
|
29
30
|
{"required": ["username"]},
|
|
31
|
+
{"required": ["password"]},
|
|
30
32
|
{"required": ["passwordEnv"]}
|
|
31
33
|
]}
|
|
32
34
|
},
|
|
@@ -38,13 +40,9 @@
|
|
|
38
40
|
]}
|
|
39
41
|
}
|
|
40
42
|
],
|
|
41
|
-
"allOf": [
|
|
42
|
-
{
|
|
43
|
-
"
|
|
44
|
-
"required": ["jdbcUrl"],
|
|
45
|
-
"properties": {"type": {"not": {"const": "sqlite"}}}
|
|
46
|
-
},
|
|
47
|
-
"then": {"required": ["passwordEnv"]}
|
|
43
|
+
"allOf": [{
|
|
44
|
+
"not": {
|
|
45
|
+
"required": ["password", "passwordEnv"]
|
|
48
46
|
}
|
|
49
|
-
]
|
|
47
|
+
}]
|
|
50
48
|
}
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
"profile": "business",
|
|
4
4
|
"name": "business-db",
|
|
5
5
|
"type": "mysql",
|
|
6
|
-
"
|
|
7
|
-
"
|
|
6
|
+
"jdbcUrl": "jdbc:mysql://127.0.0.1:3306/business",
|
|
7
|
+
"username": "business_dev",
|
|
8
|
+
"password": "replace-for-local-development",
|
|
8
9
|
"namespace": "business",
|
|
9
10
|
"schemas": ["public"],
|
|
10
11
|
"modelsDir": "models",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
#
|
|
2
|
-
#
|
|
1
|
+
# Optional development configuration. Direct passwords in a user-supplied connection file are also
|
|
2
|
+
# supported; the onboarding wrapper does not copy them into state or evidence.
|
|
3
3
|
|
|
4
|
-
FOGGY_RUNTIME_API_URL=http://127.0.0.1:
|
|
4
|
+
FOGGY_RUNTIME_API_URL=http://127.0.0.1:18166
|
|
5
5
|
FOGGY_NAMESPACE=default
|
|
6
6
|
|
|
7
7
|
# Optional when Runtime reports securityMode=auth-code.
|
|
@@ -10,5 +10,5 @@ FOGGY_NAMESPACE=default
|
|
|
10
10
|
# Optional data-plane authorization value.
|
|
11
11
|
# FOGGY_RUNTIME_AUTHORIZATION=
|
|
12
12
|
|
|
13
|
-
#
|
|
13
|
+
# Optional alternative to a direct development password.
|
|
14
14
|
# FOGGY_DATASOURCE_PASSWORD=
|
|
@@ -34,7 +34,29 @@
|
|
|
34
34
|
}
|
|
35
35
|
},
|
|
36
36
|
"runtime": {"type": "object"},
|
|
37
|
-
"connection": {
|
|
37
|
+
"connection": {
|
|
38
|
+
"type": "object",
|
|
39
|
+
"additionalProperties": false,
|
|
40
|
+
"required": ["schemaVersion", "connectionMode", "name", "type", "namespace"],
|
|
41
|
+
"properties": {
|
|
42
|
+
"schemaVersion": {"const": "foggy-deepseek-connection/v1"},
|
|
43
|
+
"connectionMode": {"enum": ["legacy-inline", "opaque-profile"]},
|
|
44
|
+
"credentialMode": {"enum": ["inline-development", "agent-environment", "opaque-profile", "none"]},
|
|
45
|
+
"name": {"type": "string"},
|
|
46
|
+
"type": {"type": "string"},
|
|
47
|
+
"jdbcUrl": {"type": ["string", "null"]},
|
|
48
|
+
"username": {"type": ["string", "null"]},
|
|
49
|
+
"passwordEnv": {"type": ["string", "null"]},
|
|
50
|
+
"opaqueProfileId": {"type": "string"},
|
|
51
|
+
"opaqueRevision": {"type": "string"},
|
|
52
|
+
"namespace": {"type": "string"},
|
|
53
|
+
"schemas": {"type": "array", "items": {"type": "string"}},
|
|
54
|
+
"modelsDir": {"type": "string"},
|
|
55
|
+
"readOnlyRecommended": {"type": "boolean"},
|
|
56
|
+
"profile": {"type": "string"},
|
|
57
|
+
"evidenceDir": {"type": "string"}
|
|
58
|
+
}
|
|
59
|
+
},
|
|
38
60
|
"semantic": {"type": "object"},
|
|
39
61
|
"steps": {"type": "object"},
|
|
40
62
|
"artifacts": {"type": "object"}
|