dsh-env-manager-plugin 0.0.0-stage → 0.1.0
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/LICENSE +21 -0
- package/README.md +249 -2
- package/client.js +2581 -0
- package/cordis.patch.yml +4 -0
- package/docs/00-project/current-state.md +246 -0
- package/docs/00-project/glossary.md +215 -0
- package/docs/00-project/project-brief.md +114 -0
- package/docs/00-project/roadmap.md +89 -0
- package/docs/01-architecture/DSH_Environment_Service_Memory_Skill_Brainstorm.md +493 -0
- package/docs/01-architecture/api-verification.md +416 -0
- package/docs/01-architecture/architecture-overview.md +222 -0
- package/docs/01-architecture/data-model.md +930 -0
- package/docs/01-architecture/decisions/ADR-0001-plugin-as-bundle.md +29 -0
- package/docs/01-architecture/decisions/ADR-0002-file-based-storage.md +25 -0
- package/docs/01-architecture/decisions/ADR-0003-skill-router-over-search.md +25 -0
- package/docs/01-architecture/decisions/ADR-0004-typescript-host-js-client.md +31 -0
- package/docs/01-architecture/decisions/ADR-0005-layered-rule-resolution.md +36 -0
- package/docs/01-architecture/decisions/ADR-0006-credentials-as-references.md +30 -0
- package/docs/01-architecture/decisions/ADR-0007-session-scoped-default-environment.md +28 -0
- package/docs/01-architecture/decisions/ADR-0008-memory-bridge-not-second-store.md +31 -0
- package/docs/01-architecture/decisions/ADR-0009-client-host-http-transport.md +87 -0
- package/docs/01-architecture/decisions/ADR-0010-environment-plane-model.md +87 -0
- package/docs/01-architecture/decisions/ADR-0011-k8s-node-execution-model.md +92 -0
- package/docs/01-architecture/design.md +666 -0
- package/docs/01-architecture/detailed-design.md +961 -0
- package/docs/01-architecture/implementation-plan.md +323 -0
- package/docs/01-architecture/module-boundaries.md +306 -0
- package/docs/01-architecture/security-model.md +227 -0
- package/docs/01-architecture/storage-contract.md +224 -0
- package/docs/01-architecture/tool-contract.md +438 -0
- package/docs/01-architecture/ui-design.md +587 -0
- package/docs/02-harness/agent-behavior.md +36 -0
- package/docs/02-harness/change-snapshot-policy.md +29 -0
- package/docs/02-harness/client-ui-integration.md +110 -0
- package/docs/02-harness/context-policy.md +43 -0
- package/docs/02-harness/harness-standard.md +91 -0
- package/docs/02-harness/task-execution-policy.md +26 -0
- package/docs/02-harness/verification-policy.md +97 -0
- package/docs/03-openspec/archive-rule.md +25 -0
- package/docs/03-openspec/bugfix-rule.md +30 -0
- package/docs/03-openspec/design-rule.md +33 -0
- package/docs/03-openspec/openspec-usage-guide.md +31 -0
- package/docs/03-openspec/proposal-rule.md +70 -0
- package/docs/03-openspec/spec-rule.md +33 -0
- package/docs/03-openspec/tasks-rule.md +31 -0
- package/docs/04-development/coding-style.md +67 -0
- package/docs/04-development/dependency-policy.md +43 -0
- package/docs/04-development/development-guide.md +85 -0
- package/docs/04-development/directory-convention.md +105 -0
- package/docs/04-development/local-run-guide.md +55 -0
- package/docs/04-development/testing-guide.md +102 -0
- package/docs/05-domain/deployment-template.md +76 -0
- package/docs/05-domain/environment-template.md +165 -0
- package/docs/05-domain/operation-binding-template.md +55 -0
- package/docs/05-domain/operation-record-template.md +55 -0
- package/docs/05-domain/prompt-template.md +90 -0
- package/docs/05-domain/rule-template.md +73 -0
- package/docs/05-domain/service-template.md +39 -0
- package/docs/06-operations/deployment-guide.md +54 -0
- package/docs/06-operations/release.md +188 -0
- package/docs/06-operations/security-policy.md +53 -0
- package/docs/06-operations/troubleshooting.md +91 -0
- package/docs/07-templates/adr-template.md +21 -0
- package/docs/07-templates/bugfix-template.md +11 -0
- package/docs/07-templates/case-template.md +15 -0
- package/docs/07-templates/design-template.md +29 -0
- package/docs/07-templates/proposal-template.md +19 -0
- package/docs/07-templates/spec-template.md +15 -0
- package/docs/07-templates/tasks-template.md +12 -0
- package/docs/99-archive/README.md +13 -0
- package/docs/README.md +142 -0
- package/icon.svg +4 -0
- package/index.js +8 -0
- package/lib/app/app.d.ts +67 -0
- package/lib/app/app.js +494 -0
- package/lib/app/app.js.map +1 -0
- package/lib/config.d.ts +55 -0
- package/lib/config.js +42 -0
- package/lib/config.js.map +1 -0
- package/lib/domain/constants.d.ts +21 -0
- package/lib/domain/constants.js +59 -0
- package/lib/domain/constants.js.map +1 -0
- package/lib/domain/errors.d.ts +20 -0
- package/lib/domain/errors.js +22 -0
- package/lib/domain/errors.js.map +1 -0
- package/lib/domain/schemas.d.ts +28 -0
- package/lib/domain/schemas.js +445 -0
- package/lib/domain/schemas.js.map +1 -0
- package/lib/domain/types.d.ts +412 -0
- package/lib/domain/types.js +2 -0
- package/lib/domain/types.js.map +1 -0
- package/lib/index.d.ts +18 -0
- package/lib/index.js +89 -0
- package/lib/index.js.map +1 -0
- package/lib/logger.d.ts +8 -0
- package/lib/logger.js +13 -0
- package/lib/logger.js.map +1 -0
- package/lib/memory/bridge.d.ts +18 -0
- package/lib/memory/bridge.js +13 -0
- package/lib/memory/bridge.js.map +1 -0
- package/lib/registry/integrity.d.ts +10 -0
- package/lib/registry/integrity.js +204 -0
- package/lib/registry/integrity.js.map +1 -0
- package/lib/registry/registry.d.ts +14 -0
- package/lib/registry/registry.js +182 -0
- package/lib/registry/registry.js.map +1 -0
- package/lib/resolver/merge.d.ts +23 -0
- package/lib/resolver/merge.js +90 -0
- package/lib/resolver/merge.js.map +1 -0
- package/lib/resolver/resolve.d.ts +18 -0
- package/lib/resolver/resolve.js +288 -0
- package/lib/resolver/resolve.js.map +1 -0
- package/lib/resolver/template.d.ts +10 -0
- package/lib/resolver/template.js +42 -0
- package/lib/resolver/template.js.map +1 -0
- package/lib/router/params.d.ts +3 -0
- package/lib/router/params.js +83 -0
- package/lib/router/params.js.map +1 -0
- package/lib/router/router.d.ts +11 -0
- package/lib/router/router.js +204 -0
- package/lib/router/router.js.map +1 -0
- package/lib/session/session.d.ts +16 -0
- package/lib/session/session.js +64 -0
- package/lib/session/session.js.map +1 -0
- package/lib/skill.d.ts +17 -0
- package/lib/skill.js +56 -0
- package/lib/skill.js.map +1 -0
- package/lib/storage/atomic.d.ts +10 -0
- package/lib/storage/atomic.js +107 -0
- package/lib/storage/atomic.js.map +1 -0
- package/lib/storage/paths.d.ts +10 -0
- package/lib/storage/paths.js +50 -0
- package/lib/storage/paths.js.map +1 -0
- package/lib/storage/records.d.ts +16 -0
- package/lib/storage/records.js +112 -0
- package/lib/storage/records.js.map +1 -0
- package/lib/storage/sessions.d.ts +17 -0
- package/lib/storage/sessions.js +65 -0
- package/lib/storage/sessions.js.map +1 -0
- package/lib/tools/tools.d.ts +14 -0
- package/lib/tools/tools.js +472 -0
- package/lib/tools/tools.js.map +1 -0
- package/lib/transport/http.d.ts +3 -0
- package/lib/transport/http.js +217 -0
- package/lib/transport/http.js.map +1 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +97 -4
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { WRITE_OPERATIONS } from '../domain/constants.js';
|
|
2
|
+
import { EnvManagerError } from '../domain/errors.js';
|
|
3
|
+
import { matchShape } from '../domain/schemas.js';
|
|
4
|
+
import { resolveParameters } from './params.js';
|
|
5
|
+
const RANK = {
|
|
6
|
+
deployment: 1,
|
|
7
|
+
'environment-service': 2,
|
|
8
|
+
service: 3,
|
|
9
|
+
'category-mode': 4,
|
|
10
|
+
global: 5,
|
|
11
|
+
};
|
|
12
|
+
function matches(binding, context) {
|
|
13
|
+
const match = binding.match;
|
|
14
|
+
if (match.environmentId && match.environmentId !== context.environmentId)
|
|
15
|
+
return false;
|
|
16
|
+
if (match.serviceId && match.serviceId !== context.serviceId)
|
|
17
|
+
return false;
|
|
18
|
+
if (match.deploymentId && match.deploymentId !== context.deploymentId)
|
|
19
|
+
return false;
|
|
20
|
+
if (match.deploymentMode && match.deploymentMode !== context.runtimeMode)
|
|
21
|
+
return false;
|
|
22
|
+
if (match.serviceCategory && match.serviceCategory !== context.serviceCategory)
|
|
23
|
+
return false;
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
function levelOf(binding) {
|
|
27
|
+
const shape = matchShape(binding.match);
|
|
28
|
+
return shape ?? null;
|
|
29
|
+
}
|
|
30
|
+
function skillDiagnostic(code, message, severity, details) {
|
|
31
|
+
return { code, severity, message, details };
|
|
32
|
+
}
|
|
33
|
+
async function checkSkill(binding, context, skills, signal) {
|
|
34
|
+
const ref = binding.skill;
|
|
35
|
+
if (!skills) {
|
|
36
|
+
return {
|
|
37
|
+
skill: { name: ref.name, available: 'unknown' },
|
|
38
|
+
diagnostics: [
|
|
39
|
+
skillDiagnostic('SKILL_REGISTRY_UNAVAILABLE', 'Skill catalog is unavailable; availability could not be verified', 'warning', { skill: ref.name }),
|
|
40
|
+
],
|
|
41
|
+
ok: true,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
let snapshot;
|
|
45
|
+
try {
|
|
46
|
+
snapshot = await skills.snapshot({ signal });
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
return {
|
|
50
|
+
skill: { name: ref.name, available: 'unknown' },
|
|
51
|
+
diagnostics: [
|
|
52
|
+
skillDiagnostic('SKILL_REGISTRY_UNAVAILABLE', `Skill catalog could not be read: ${error instanceof Error ? error.message : String(error)}`, 'warning', { skill: ref.name }),
|
|
53
|
+
],
|
|
54
|
+
ok: true,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
if (!snapshot.complete) {
|
|
58
|
+
return {
|
|
59
|
+
skill: { name: ref.name, available: 'unknown' },
|
|
60
|
+
diagnostics: [
|
|
61
|
+
skillDiagnostic('SKILL_REGISTRY_UNAVAILABLE', 'Skill discovery did not complete; availability could not be verified', 'warning', { skill: ref.name }),
|
|
62
|
+
],
|
|
63
|
+
ok: true,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
const found = snapshot.skills.find((item) => item.name === ref.name);
|
|
67
|
+
if (!found) {
|
|
68
|
+
return {
|
|
69
|
+
skill: { name: ref.name, available: false },
|
|
70
|
+
diagnostics: [
|
|
71
|
+
skillDiagnostic('SKILL_UNAVAILABLE', `Skill "${ref.name}" is not installed`, 'error', {
|
|
72
|
+
skill: ref.name,
|
|
73
|
+
operation: binding.operation,
|
|
74
|
+
}),
|
|
75
|
+
],
|
|
76
|
+
ok: false,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
if (ref.expectedSource && found.source !== ref.expectedSource) {
|
|
80
|
+
return {
|
|
81
|
+
skill: { name: ref.name, source: found.source, provider: found.provider, available: false },
|
|
82
|
+
diagnostics: [
|
|
83
|
+
skillDiagnostic('SKILL_UNAVAILABLE', `Skill "${ref.name}" has source "${found.source}"; expected "${ref.expectedSource}"`, 'error', { skill: ref.name, expectedSource: ref.expectedSource, actualSource: found.source }),
|
|
84
|
+
],
|
|
85
|
+
ok: false,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
if (ref.expectedProvider && found.provider !== ref.expectedProvider) {
|
|
89
|
+
return {
|
|
90
|
+
skill: { name: ref.name, source: found.source, provider: found.provider, available: false },
|
|
91
|
+
diagnostics: [
|
|
92
|
+
skillDiagnostic('SKILL_UNAVAILABLE', `Skill "${ref.name}" has provider "${found.provider}"; expected "${ref.expectedProvider}"`, 'error', {
|
|
93
|
+
skill: ref.name,
|
|
94
|
+
expectedProvider: ref.expectedProvider,
|
|
95
|
+
actualProvider: found.provider,
|
|
96
|
+
}),
|
|
97
|
+
],
|
|
98
|
+
ok: false,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
skill: {
|
|
103
|
+
name: ref.name,
|
|
104
|
+
source: found.source,
|
|
105
|
+
provider: found.provider,
|
|
106
|
+
available: true,
|
|
107
|
+
},
|
|
108
|
+
diagnostics: [],
|
|
109
|
+
ok: true,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
export async function resolveOperation(input) {
|
|
113
|
+
const { operation, context, bindings, skills, signal } = input;
|
|
114
|
+
const requested = {
|
|
115
|
+
environmentId: context.environmentId,
|
|
116
|
+
serviceId: context.serviceId,
|
|
117
|
+
deploymentId: context.deploymentId,
|
|
118
|
+
};
|
|
119
|
+
const base = {
|
|
120
|
+
ok: false,
|
|
121
|
+
operation,
|
|
122
|
+
requested,
|
|
123
|
+
diagnostics: [],
|
|
124
|
+
};
|
|
125
|
+
const candidates = bindings.filter((binding) => binding.enabled && binding.operation === operation && matches(binding, context));
|
|
126
|
+
if (candidates.length === 0) {
|
|
127
|
+
return {
|
|
128
|
+
...base,
|
|
129
|
+
diagnostics: [
|
|
130
|
+
skillDiagnostic('BINDING_NOT_FOUND', `No enabled operation binding matches "${operation}" for ${context.environmentId}/${context.serviceId}`, 'error', { operation }),
|
|
131
|
+
],
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
const ranked = candidates
|
|
135
|
+
.map((binding) => ({ binding, level: levelOf(binding) }))
|
|
136
|
+
.filter((item) => item.level !== null);
|
|
137
|
+
if (ranked.length === 0) {
|
|
138
|
+
return {
|
|
139
|
+
...base,
|
|
140
|
+
diagnostics: [
|
|
141
|
+
skillDiagnostic('RECORD_INVALID', 'Matching bindings do not have a valid match shape', 'error'),
|
|
142
|
+
],
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
ranked.sort((a, b) => RANK[a.level] - RANK[b.level]);
|
|
146
|
+
const topRank = RANK[ranked[0].level];
|
|
147
|
+
const winners = ranked.filter((item) => RANK[item.level] === topRank);
|
|
148
|
+
if (winners.length > 1) {
|
|
149
|
+
return {
|
|
150
|
+
...base,
|
|
151
|
+
diagnostics: [
|
|
152
|
+
skillDiagnostic('BINDING_CONFLICT', `Operation "${operation}" has ${winners.length} bindings at the same priority (${winners[0].level})`, 'error', {
|
|
153
|
+
candidates: winners.map((item) => item.binding.id),
|
|
154
|
+
level: winners[0].level,
|
|
155
|
+
}),
|
|
156
|
+
],
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
const selected = winners[0];
|
|
160
|
+
const selectedBinding = selected.binding;
|
|
161
|
+
const skillResult = await checkSkill(selectedBinding, context, skills, signal);
|
|
162
|
+
const policy = {
|
|
163
|
+
requiresApproval: selectedBinding.policy?.requiresApproval ?? WRITE_OPERATIONS.has(operation),
|
|
164
|
+
allowProduction: selectedBinding.policy?.allowProduction ?? false,
|
|
165
|
+
};
|
|
166
|
+
const diagnostics = [...skillResult.diagnostics];
|
|
167
|
+
let ok = skillResult.ok;
|
|
168
|
+
if (context.environmentCategory === 'production' && policy.allowProduction !== true) {
|
|
169
|
+
ok = false;
|
|
170
|
+
diagnostics.push(skillDiagnostic('POLICY_DENIED', `Operation "${operation}" is not allowed in production by binding ${selectedBinding.id}`, 'error', { binding: selectedBinding.id, environmentId: context.environmentId }));
|
|
171
|
+
}
|
|
172
|
+
let parameters;
|
|
173
|
+
try {
|
|
174
|
+
parameters = resolveParameters(selectedBinding.parameters, context);
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
ok = false;
|
|
178
|
+
diagnostics.push(error instanceof EnvManagerError
|
|
179
|
+
? {
|
|
180
|
+
code: error.code,
|
|
181
|
+
severity: 'error',
|
|
182
|
+
message: error.message,
|
|
183
|
+
details: error.details,
|
|
184
|
+
}
|
|
185
|
+
: {
|
|
186
|
+
code: 'PARAMETER_RESOLUTION_FAILED',
|
|
187
|
+
severity: 'error',
|
|
188
|
+
message: error instanceof Error ? error.message : String(error),
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
return {
|
|
192
|
+
ok,
|
|
193
|
+
operation,
|
|
194
|
+
requested,
|
|
195
|
+
matchedBindingId: selectedBinding.id,
|
|
196
|
+
matchLevel: selected.level,
|
|
197
|
+
skill: skillResult.skill,
|
|
198
|
+
parameters,
|
|
199
|
+
policy,
|
|
200
|
+
diagnostics,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
export { RANK };
|
|
204
|
+
//# sourceMappingURL=router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/router/router.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Diagnostic, SessionContext } from '../domain/types.js';
|
|
2
|
+
export interface SessionResult {
|
|
3
|
+
context: SessionContext;
|
|
4
|
+
diagnostics: Diagnostic[];
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Per-session default environment. The file is authoritative; a process-local
|
|
8
|
+
* cache keeps the current process consistent when a write fails.
|
|
9
|
+
*/
|
|
10
|
+
export declare class SessionStore {
|
|
11
|
+
private readonly dataDir;
|
|
12
|
+
private readonly cache;
|
|
13
|
+
constructor(dataDir: string);
|
|
14
|
+
get(sessionId: string): Promise<SessionResult>;
|
|
15
|
+
set(sessionId: string, environmentId: string | null): Promise<SessionResult>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { readSessionFile, writeSessionFile } from '../storage/sessions.js';
|
|
2
|
+
/**
|
|
3
|
+
* Per-session default environment. The file is authoritative; a process-local
|
|
4
|
+
* cache keeps the current process consistent when a write fails.
|
|
5
|
+
*/
|
|
6
|
+
export class SessionStore {
|
|
7
|
+
dataDir;
|
|
8
|
+
cache = new Map();
|
|
9
|
+
constructor(dataDir) {
|
|
10
|
+
this.dataDir = dataDir;
|
|
11
|
+
}
|
|
12
|
+
async get(sessionId) {
|
|
13
|
+
const read = await readSessionFile(this.dataDir, sessionId);
|
|
14
|
+
if (read.status === 'ok') {
|
|
15
|
+
this.cache.set(sessionId, read.value.defaultEnvironmentId);
|
|
16
|
+
return {
|
|
17
|
+
context: {
|
|
18
|
+
sessionId,
|
|
19
|
+
defaultEnvironmentId: read.value.defaultEnvironmentId,
|
|
20
|
+
persisted: true,
|
|
21
|
+
},
|
|
22
|
+
diagnostics: [],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
const cached = this.cache.get(sessionId);
|
|
26
|
+
const fallback = cached ?? null;
|
|
27
|
+
const diagnostics = read.status === 'corrupt'
|
|
28
|
+
? [
|
|
29
|
+
{
|
|
30
|
+
code: 'SESSION_CONTEXT_UNPERSISTED',
|
|
31
|
+
severity: 'warning',
|
|
32
|
+
message: `Session context file for ${sessionId} is unreadable (${read.reason}); using no default`,
|
|
33
|
+
},
|
|
34
|
+
]
|
|
35
|
+
: [];
|
|
36
|
+
return {
|
|
37
|
+
context: { sessionId, defaultEnvironmentId: fallback, persisted: false },
|
|
38
|
+
diagnostics,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
async set(sessionId, environmentId) {
|
|
42
|
+
this.cache.set(sessionId, environmentId);
|
|
43
|
+
try {
|
|
44
|
+
await writeSessionFile(this.dataDir, sessionId, environmentId);
|
|
45
|
+
return {
|
|
46
|
+
context: { sessionId, defaultEnvironmentId: environmentId, persisted: true },
|
|
47
|
+
diagnostics: [],
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
return {
|
|
52
|
+
context: { sessionId, defaultEnvironmentId: environmentId, persisted: false },
|
|
53
|
+
diagnostics: [
|
|
54
|
+
{
|
|
55
|
+
code: 'SESSION_CONTEXT_UNPERSISTED',
|
|
56
|
+
severity: 'warning',
|
|
57
|
+
message: `Session default was updated in memory but not persisted: ${error instanceof Error ? error.message : String(error)}`,
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/session/session.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AAO1E;;;GAGG;AACH,MAAM,OAAO,YAAY;IAGM;IAFZ,KAAK,GAAG,IAAI,GAAG,EAAyB,CAAA;IAEzD,YAA6B,OAAe;QAAf,YAAO,GAAP,OAAO,CAAQ;IAAG,CAAC;IAEhD,KAAK,CAAC,GAAG,CAAC,SAAiB;QACzB,MAAM,IAAI,GAAG,MAAM,eAAe,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAA;QAC3D,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;YACzB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAA;YAC1D,OAAO;gBACL,OAAO,EAAE;oBACP,SAAS;oBACT,oBAAoB,EAAE,IAAI,CAAC,KAAK,CAAC,oBAAoB;oBACrD,SAAS,EAAE,IAAI;iBAChB;gBACD,WAAW,EAAE,EAAE;aAChB,CAAA;QACH,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;QACxC,MAAM,QAAQ,GAAG,MAAM,IAAI,IAAI,CAAA;QAC/B,MAAM,WAAW,GACf,IAAI,CAAC,MAAM,KAAK,SAAS;YACvB,CAAC,CAAC;gBACE;oBACE,IAAI,EAAE,6BAA6B;oBACnC,QAAQ,EAAE,SAAS;oBACnB,OAAO,EAAE,4BAA4B,SAAS,mBAAmB,IAAI,CAAC,MAAM,qBAAqB;iBAClG;aACF;YACH,CAAC,CAAC,EAAE,CAAA;QACR,OAAO;YACL,OAAO,EAAE,EAAE,SAAS,EAAE,oBAAoB,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE;YACxE,WAAW;SACZ,CAAA;IACH,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,SAAiB,EAAE,aAA4B;QACvD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,aAAa,CAAC,CAAA;QACxC,IAAI,CAAC;YACH,MAAM,gBAAgB,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,aAAa,CAAC,CAAA;YAC9D,OAAO;gBACL,OAAO,EAAE,EAAE,SAAS,EAAE,oBAAoB,EAAE,aAAa,EAAE,SAAS,EAAE,IAAI,EAAE;gBAC5E,WAAW,EAAE,EAAE;aAChB,CAAA;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,OAAO,EAAE,EAAE,SAAS,EAAE,oBAAoB,EAAE,aAAa,EAAE,SAAS,EAAE,KAAK,EAAE;gBAC7E,WAAW,EAAE;oBACX;wBACE,IAAI,EAAE,6BAA6B;wBACnC,QAAQ,EAAE,SAAS;wBACnB,OAAO,EAAE,4DACP,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CACvD,EAAE;qBACH;iBACF;aACF,CAAA;QACH,CAAC;IACH,CAAC;CACF"}
|
package/lib/skill.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare const ENV_MANAGER_SKILL_NAME = "dsh-env-manager";
|
|
2
|
+
export declare const ENV_MANAGER_SKILL_DESCRIPTION = "Use when the user mentions DSH Environment Manager, a registered environment, host, service, deployment, log collection, restart or deploy, or asks where a registered service runs.";
|
|
3
|
+
export declare const ENV_MANAGER_SKILL_WHEN_TO_USE = "The user asks which environment to use, where a registered service or host runs, how to find its paths or logs, or wants an operation on a registered environment.";
|
|
4
|
+
export declare const ENV_MANAGER_SKILL_CONTENT = "# DSH Environment Manager\n\nUse the environment registry as the source of truth for registered environments, hosts,\nservices, deployments and operation routes. This is not the operating-system or Python\n\"environment\"; it is the DSH Environment Manager registry.\n\n## Workflow\n\n1. Discover before guessing.\n - Use `env_list` for an inventory.\n - Use `env_find` with an id, name, alias or category fragment.\n - If more than one candidate matches, ask which one the user means; do not pick one.\n\n2. Pin the session when the user commits to one environment.\n - Call `env_set_context` with the environment id.\n - Use `env_get_context` to confirm it.\n - Once pinned, later calls may omit `environmentId`.\n\n3. Resolve concrete context.\n - Use `env_get` when the raw record or YAML is needed.\n - Use `env_resolve` for the service context, paths, logs, variables and provenance.\n - Prefer the resolver over reconstructing paths from templates.\n\n4. Route an operation before acting.\n - Before deploy, redeploy, restart, rollback, collect-logs or a similar action, call\n `env_resolve_operation` with the environment and service or deployment.\n - A missing, ambiguous or conflicting binding is an error; do not invent a skill or\n fall back to a different environment.\n - `env_resolve_operation` returns a route; it does not execute the skill.\n\n## Boundaries\n\n- Do not assume the current workspace's files are the registry.\n- Do not print credential values; report only whether a credential is configured.\n- Respect approval and policy results; never bypass them because a route looks obvious.\n- If the user says \"not this environment\", clear or replace the session default with\n `env_set_context`; do not silently keep the old one.\n";
|
|
5
|
+
export interface EnvironmentManagerSkill {
|
|
6
|
+
name: string;
|
|
7
|
+
description: string;
|
|
8
|
+
whenToUse: string;
|
|
9
|
+
content: string;
|
|
10
|
+
source: 'runtime';
|
|
11
|
+
provider: string;
|
|
12
|
+
invocation: {
|
|
13
|
+
modelInvocable: boolean;
|
|
14
|
+
userInvocable: boolean;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export declare function createEnvironmentManagerSkill(): EnvironmentManagerSkill;
|
package/lib/skill.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export const ENV_MANAGER_SKILL_NAME = 'dsh-env-manager';
|
|
2
|
+
export const ENV_MANAGER_SKILL_DESCRIPTION = 'Use when the user mentions DSH Environment Manager, a registered environment, host, service, deployment, log collection, restart or deploy, or asks where a registered service runs.';
|
|
3
|
+
export const ENV_MANAGER_SKILL_WHEN_TO_USE = 'The user asks which environment to use, where a registered service or host runs, how to find its paths or logs, or wants an operation on a registered environment.';
|
|
4
|
+
export const ENV_MANAGER_SKILL_CONTENT = `# DSH Environment Manager
|
|
5
|
+
|
|
6
|
+
Use the environment registry as the source of truth for registered environments, hosts,
|
|
7
|
+
services, deployments and operation routes. This is not the operating-system or Python
|
|
8
|
+
"environment"; it is the DSH Environment Manager registry.
|
|
9
|
+
|
|
10
|
+
## Workflow
|
|
11
|
+
|
|
12
|
+
1. Discover before guessing.
|
|
13
|
+
- Use \`env_list\` for an inventory.
|
|
14
|
+
- Use \`env_find\` with an id, name, alias or category fragment.
|
|
15
|
+
- If more than one candidate matches, ask which one the user means; do not pick one.
|
|
16
|
+
|
|
17
|
+
2. Pin the session when the user commits to one environment.
|
|
18
|
+
- Call \`env_set_context\` with the environment id.
|
|
19
|
+
- Use \`env_get_context\` to confirm it.
|
|
20
|
+
- Once pinned, later calls may omit \`environmentId\`.
|
|
21
|
+
|
|
22
|
+
3. Resolve concrete context.
|
|
23
|
+
- Use \`env_get\` when the raw record or YAML is needed.
|
|
24
|
+
- Use \`env_resolve\` for the service context, paths, logs, variables and provenance.
|
|
25
|
+
- Prefer the resolver over reconstructing paths from templates.
|
|
26
|
+
|
|
27
|
+
4. Route an operation before acting.
|
|
28
|
+
- Before deploy, redeploy, restart, rollback, collect-logs or a similar action, call
|
|
29
|
+
\`env_resolve_operation\` with the environment and service or deployment.
|
|
30
|
+
- A missing, ambiguous or conflicting binding is an error; do not invent a skill or
|
|
31
|
+
fall back to a different environment.
|
|
32
|
+
- \`env_resolve_operation\` returns a route; it does not execute the skill.
|
|
33
|
+
|
|
34
|
+
## Boundaries
|
|
35
|
+
|
|
36
|
+
- Do not assume the current workspace's files are the registry.
|
|
37
|
+
- Do not print credential values; report only whether a credential is configured.
|
|
38
|
+
- Respect approval and policy results; never bypass them because a route looks obvious.
|
|
39
|
+
- If the user says "not this environment", clear or replace the session default with
|
|
40
|
+
\`env_set_context\`; do not silently keep the old one.
|
|
41
|
+
`;
|
|
42
|
+
export function createEnvironmentManagerSkill() {
|
|
43
|
+
return {
|
|
44
|
+
name: ENV_MANAGER_SKILL_NAME,
|
|
45
|
+
description: ENV_MANAGER_SKILL_DESCRIPTION,
|
|
46
|
+
whenToUse: ENV_MANAGER_SKILL_WHEN_TO_USE,
|
|
47
|
+
content: ENV_MANAGER_SKILL_CONTENT,
|
|
48
|
+
source: 'runtime',
|
|
49
|
+
provider: 'dsh-env-manager',
|
|
50
|
+
invocation: {
|
|
51
|
+
modelInvocable: true,
|
|
52
|
+
userInvocable: true,
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=skill.js.map
|
package/lib/skill.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill.js","sourceRoot":"","sources":["../src/skill.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,sBAAsB,GAAG,iBAAiB,CAAA;AAEvD,MAAM,CAAC,MAAM,6BAA6B,GACxC,sLAAsL,CAAA;AAExL,MAAM,CAAC,MAAM,6BAA6B,GACxC,oKAAoK,CAAA;AAEtK,MAAM,CAAC,MAAM,yBAAyB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqCxC,CAAA;AAeD,MAAM,UAAU,6BAA6B;IAC3C,OAAO;QACL,IAAI,EAAE,sBAAsB;QAC5B,WAAW,EAAE,6BAA6B;QAC1C,SAAS,EAAE,6BAA6B;QACxC,OAAO,EAAE,yBAAyB;QAClC,MAAM,EAAE,SAAS;QACjB,QAAQ,EAAE,iBAAiB;QAC3B,UAAU,EAAE;YACV,cAAc,EAAE,IAAI;YACpB,aAAa,EAAE,IAAI;SACpB;KACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serialize writes to one absolute path within this process.
|
|
3
|
+
* No cross-process lock exists in V1.
|
|
4
|
+
*/
|
|
5
|
+
export declare function serialize<T>(key: string, work: () => Promise<T>): Promise<T>;
|
|
6
|
+
export declare function writeTextAtomic(target: string, text: string): Promise<void>;
|
|
7
|
+
export declare function rotateBackup(source: string, backupDirectory: string, extension: string): Promise<void>;
|
|
8
|
+
/** Remove orphan `.tmp` files older than one hour. */
|
|
9
|
+
export declare function cleanupTempFiles(dataDir: string): Promise<number>;
|
|
10
|
+
export declare function ensureLayout(dataDir: string): Promise<void>;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { promises as fs } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { randomUUID } from 'node:crypto';
|
|
4
|
+
import { LIMITS } from '../domain/constants.js';
|
|
5
|
+
const queues = new Map();
|
|
6
|
+
/**
|
|
7
|
+
* Serialize writes to one absolute path within this process.
|
|
8
|
+
* No cross-process lock exists in V1.
|
|
9
|
+
*/
|
|
10
|
+
export function serialize(key, work) {
|
|
11
|
+
const previous = queues.get(key) ?? Promise.resolve();
|
|
12
|
+
const run = previous.then(work, work);
|
|
13
|
+
const guard = run.then(() => undefined, () => undefined);
|
|
14
|
+
queues.set(key, guard);
|
|
15
|
+
return run.finally(() => {
|
|
16
|
+
if (queues.get(key) === guard)
|
|
17
|
+
queues.delete(key);
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
export async function writeTextAtomic(target, text) {
|
|
21
|
+
await fs.mkdir(path.dirname(target), { recursive: true });
|
|
22
|
+
const temp = path.join(path.dirname(target), `.${path.basename(target)}.${process.pid}.${randomUUID()}.tmp`);
|
|
23
|
+
const handle = await fs.open(temp, 'w');
|
|
24
|
+
try {
|
|
25
|
+
await handle.writeFile(text, 'utf8');
|
|
26
|
+
await handle.sync();
|
|
27
|
+
}
|
|
28
|
+
finally {
|
|
29
|
+
await handle.close();
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
await fs.rename(temp, target);
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
await fs.rm(temp, { force: true }).catch(() => undefined);
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export async function rotateBackup(source, backupDirectory, extension) {
|
|
40
|
+
let text;
|
|
41
|
+
try {
|
|
42
|
+
text = await fs.readFile(source, 'utf8');
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
await fs.mkdir(backupDirectory, { recursive: true });
|
|
48
|
+
const stamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
49
|
+
const target = path.join(backupDirectory, `${stamp}-${process.pid}-${randomUUID().slice(0, 8)}.${extension}`);
|
|
50
|
+
await fs.writeFile(target, text, { encoding: 'utf8', flag: 'wx' });
|
|
51
|
+
const entries = await fs.readdir(backupDirectory);
|
|
52
|
+
const backups = entries
|
|
53
|
+
.filter((entry) => entry.endsWith(`.${extension}`))
|
|
54
|
+
.sort()
|
|
55
|
+
.reverse();
|
|
56
|
+
for (const stale of backups.slice(LIMITS.backupCount)) {
|
|
57
|
+
await fs.rm(path.join(backupDirectory, stale), { force: true }).catch(() => undefined);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
async function collectTempFiles(dir, cutoff) {
|
|
61
|
+
const found = [];
|
|
62
|
+
let entries;
|
|
63
|
+
try {
|
|
64
|
+
entries = await fs.readdir(dir, { withFileTypes: true });
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return found;
|
|
68
|
+
}
|
|
69
|
+
for (const entry of entries) {
|
|
70
|
+
const full = path.join(dir, entry.name);
|
|
71
|
+
if (entry.isDirectory()) {
|
|
72
|
+
if (entry.name === '.backups' || entry.name === 'node_modules')
|
|
73
|
+
continue;
|
|
74
|
+
found.push(...(await collectTempFiles(full, cutoff)));
|
|
75
|
+
}
|
|
76
|
+
else if (entry.name.endsWith('.tmp')) {
|
|
77
|
+
try {
|
|
78
|
+
const stat = await fs.stat(full);
|
|
79
|
+
if (stat.mtimeMs < cutoff)
|
|
80
|
+
found.push(full);
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
// Ignore a temp file that disappeared during the scan.
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return found;
|
|
88
|
+
}
|
|
89
|
+
/** Remove orphan `.tmp` files older than one hour. */
|
|
90
|
+
export async function cleanupTempFiles(dataDir) {
|
|
91
|
+
const files = await collectTempFiles(dataDir, Date.now() - 60 * 60 * 1000);
|
|
92
|
+
let removed = 0;
|
|
93
|
+
for (const file of files) {
|
|
94
|
+
try {
|
|
95
|
+
await fs.rm(file, { force: true });
|
|
96
|
+
removed += 1;
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// Best effort; a locked temp file is retried on the next startup.
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return removed;
|
|
103
|
+
}
|
|
104
|
+
export async function ensureLayout(dataDir) {
|
|
105
|
+
await fs.mkdir(dataDir, { recursive: true });
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=atomic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atomic.js","sourceRoot":"","sources":["../../src/storage/atomic.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { RecordKind } from '../domain/types.js';
|
|
2
|
+
export declare function resolveDataDir(configured: string, profileDir: string, cwd: string, home: string): string;
|
|
3
|
+
export declare function kindDir(dataDir: string, kind: RecordKind): string;
|
|
4
|
+
export declare function isValidId(id: string): boolean;
|
|
5
|
+
export declare function resolveRecordPath(dataDir: string, kind: RecordKind, id: string): string;
|
|
6
|
+
export declare function sessionFileName(sessionId: string): string;
|
|
7
|
+
export declare function sessionPath(dataDir: string, sessionId: string): string;
|
|
8
|
+
export declare function backupsDir(dataDir: string): string;
|
|
9
|
+
export declare function backupDir(dataDir: string, kind: RecordKind, id: string): string;
|
|
10
|
+
export declare function sessionBackupDir(dataDir: string, sessionId: string): string;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
import { ID_PATTERN, KIND_DIRECTORIES, SESSION_ID_PATTERN } from '../domain/constants.js';
|
|
4
|
+
export function resolveDataDir(configured, profileDir, cwd, home) {
|
|
5
|
+
const value = configured.trim();
|
|
6
|
+
if (!value)
|
|
7
|
+
return path.join(profileDir, 'data');
|
|
8
|
+
if (value.startsWith('~'))
|
|
9
|
+
return path.join(home, value.slice(1));
|
|
10
|
+
return path.isAbsolute(value) ? value : path.resolve(profileDir || cwd, value);
|
|
11
|
+
}
|
|
12
|
+
export function kindDir(dataDir, kind) {
|
|
13
|
+
return path.join(dataDir, KIND_DIRECTORIES[kind]);
|
|
14
|
+
}
|
|
15
|
+
export function isValidId(id) {
|
|
16
|
+
return ID_PATTERN.test(id);
|
|
17
|
+
}
|
|
18
|
+
export function resolveRecordPath(dataDir, kind, id) {
|
|
19
|
+
if (!isValidId(id)) {
|
|
20
|
+
throw new Error(`Invalid record id: ${JSON.stringify(id)}`);
|
|
21
|
+
}
|
|
22
|
+
const dir = kindDir(dataDir, kind);
|
|
23
|
+
const target = path.resolve(dir, `${id}.yaml`);
|
|
24
|
+
const root = path.resolve(dir) + path.sep;
|
|
25
|
+
if (!target.startsWith(root))
|
|
26
|
+
throw new Error(`Record path escapes ${dir}`);
|
|
27
|
+
return target;
|
|
28
|
+
}
|
|
29
|
+
export function sessionFileName(sessionId) {
|
|
30
|
+
if (SESSION_ID_PATTERN.test(sessionId))
|
|
31
|
+
return `${sessionId}.json`;
|
|
32
|
+
const digest = createHash('sha256').update(sessionId).digest('hex');
|
|
33
|
+
return `s-${digest}.json`;
|
|
34
|
+
}
|
|
35
|
+
export function sessionPath(dataDir, sessionId) {
|
|
36
|
+
return path.join(dataDir, 'sessions', sessionFileName(sessionId));
|
|
37
|
+
}
|
|
38
|
+
export function backupsDir(dataDir) {
|
|
39
|
+
return path.join(dataDir, '.backups');
|
|
40
|
+
}
|
|
41
|
+
export function backupDir(dataDir, kind, id) {
|
|
42
|
+
return path.join(backupsDir(dataDir), KIND_DIRECTORIES[kind], id);
|
|
43
|
+
}
|
|
44
|
+
export function sessionBackupDir(dataDir, sessionId) {
|
|
45
|
+
const name = SESSION_ID_PATTERN.test(sessionId)
|
|
46
|
+
? sessionId
|
|
47
|
+
: createHash('sha256').update(sessionId).digest('hex');
|
|
48
|
+
return path.join(backupsDir(dataDir), 'sessions', name);
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/storage/paths.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AnyRecord, RecordKind } from '../domain/types.js';
|
|
2
|
+
export interface RawRecord {
|
|
3
|
+
found: boolean;
|
|
4
|
+
text?: string;
|
|
5
|
+
raw?: unknown;
|
|
6
|
+
bytes?: number;
|
|
7
|
+
}
|
|
8
|
+
export declare function parseYamlText(text: string, file?: string): unknown;
|
|
9
|
+
export declare function stringifyRecord(record: AnyRecord): string;
|
|
10
|
+
export declare function readRecordRaw(dataDir: string, kind: RecordKind, id: string): Promise<RawRecord>;
|
|
11
|
+
export declare function writeRecordFile(dataDir: string, kind: RecordKind, record: AnyRecord): Promise<void>;
|
|
12
|
+
export declare function deleteRecordFile(dataDir: string, kind: RecordKind, id: string): Promise<void>;
|
|
13
|
+
export declare function listRecordIds(dataDir: string, kind: RecordKind): Promise<string[]>;
|
|
14
|
+
export declare function fileForRecord(dataDir: string, kind: RecordKind, id: string): string;
|
|
15
|
+
export declare function recordExists(dataDir: string, kind: RecordKind, id: string): Promise<boolean>;
|
|
16
|
+
export declare function relativeFile(dataDir: string, target: string): string;
|