@osovv/vv-opencode 0.35.19 → 0.35.21
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/CHANGELOG.md +20 -0
- package/README.md +67 -24
- package/dist/cli.js +3 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/completion.js +2 -0
- package/dist/commands/completion.js.map +1 -1
- package/dist/commands/config-validate.d.ts +8 -1
- package/dist/commands/config-validate.js +31 -8
- package/dist/commands/config-validate.js.map +1 -1
- package/dist/commands/doctor.d.ts +3 -3
- package/dist/commands/doctor.js +14 -13
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.js +10 -12
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/install.js +6 -6
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/launch.d.ts +35 -0
- package/dist/commands/launch.js +123 -0
- package/dist/commands/launch.js.map +1 -0
- package/dist/commands/patch-provider.d.ts +8 -0
- package/dist/commands/patch-provider.js +13 -4
- package/dist/commands/patch-provider.js.map +1 -1
- package/dist/commands/plugin-list.d.ts +6 -6
- package/dist/commands/plugin-list.js +30 -24
- package/dist/commands/plugin-list.js.map +1 -1
- package/dist/commands/plugin-toggle.js +5 -3
- package/dist/commands/plugin-toggle.js.map +1 -1
- package/dist/commands/preset.d.ts +7 -0
- package/dist/commands/preset.js +37 -9
- package/dist/commands/preset.js.map +1 -1
- package/dist/commands/role.d.ts +3 -0
- package/dist/commands/role.js +45 -11
- package/dist/commands/role.js.map +1 -1
- package/dist/commands/status.d.ts +3 -3
- package/dist/commands/status.js +14 -13
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/sync.js +6 -7
- package/dist/commands/sync.js.map +1 -1
- package/dist/commands/upgrade.js +4 -3
- package/dist/commands/upgrade.js.map +1 -1
- package/dist/lib/config-layers.d.ts +56 -0
- package/dist/lib/config-layers.js +256 -0
- package/dist/lib/config-layers.js.map +1 -0
- package/dist/lib/opencode.d.ts +13 -5
- package/dist/lib/opencode.js +105 -39
- package/dist/lib/opencode.js.map +1 -1
- package/dist/lib/plugin-toggle-config.d.ts +5 -1
- package/dist/lib/plugin-toggle-config.js +20 -33
- package/dist/lib/plugin-toggle-config.js.map +1 -1
- package/dist/lib/vvoc-config.js +14 -1
- package/dist/lib/vvoc-config.js.map +1 -1
- package/dist/lib/vvoc-paths.d.ts +2 -2
- package/dist/lib/vvoc-paths.js +12 -9
- package/dist/lib/vvoc-paths.js.map +1 -1
- package/dist/plugins/guardian/index.js +30 -37
- package/dist/plugins/guardian/index.js.map +1 -1
- package/dist/plugins/model-roles/index.js +11 -27
- package/dist/plugins/model-roles/index.js.map +1 -1
- package/dist/plugins/secrets-redaction/config.d.ts +1 -1
- package/dist/plugins/secrets-redaction/config.js +28 -39
- package/dist/plugins/secrets-redaction/config.js.map +1 -1
- package/dist/plugins/system-context-injection/index.js +19 -7
- package/dist/plugins/system-context-injection/index.js.map +1 -1
- package/package.json +1 -1
- package/schemas/vvoc/v3.json +1 -1
- package/templates/agents/vv-controller.md +9 -8
- package/templates/skills/vv-execute/SKILL.md +8 -8
- package/templates/skills/vv-plan/SKILL.md +11 -6
- package/templates/skills/vv-plan/references/plan-template.xml +1 -0
- package/templates/skills/vv-spec/SKILL.md +29 -3
- package/templates/skills/vv-spec/references/design-context-template.xml +62 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { type VvocConfig } from "./vvoc-config.js";
|
|
2
|
+
export declare const VVOC_CONFIG_ENV = "VVOC_CONFIG";
|
|
3
|
+
export declare const OPENCODE_CONFIG_ENV = "OPENCODE_CONFIG";
|
|
4
|
+
export type ConfigWriteScope = "global" | "project";
|
|
5
|
+
export type ConfigReadScope = ConfigWriteScope | "effective";
|
|
6
|
+
export type ConfigSourceKind = "env" | "project" | "global" | "default" | "missing";
|
|
7
|
+
export type ConfigSource = {
|
|
8
|
+
kind: ConfigSourceKind;
|
|
9
|
+
path?: string;
|
|
10
|
+
rootDir?: string;
|
|
11
|
+
reason?: string;
|
|
12
|
+
};
|
|
13
|
+
export type ProjectConfigRoot = {
|
|
14
|
+
rootDir: string;
|
|
15
|
+
vvocConfigPath?: string;
|
|
16
|
+
opencodeConfigPath?: string;
|
|
17
|
+
};
|
|
18
|
+
export type ConfigLayerOptions = {
|
|
19
|
+
cwd: string;
|
|
20
|
+
configDir?: string;
|
|
21
|
+
env?: NodeJS.ProcessEnv;
|
|
22
|
+
};
|
|
23
|
+
export type ConfigWriteTargets = {
|
|
24
|
+
scope: ConfigWriteScope;
|
|
25
|
+
projectRoot?: string;
|
|
26
|
+
opencodeBaseDir: string;
|
|
27
|
+
vvocBaseDir: string;
|
|
28
|
+
opencodeConfigPath: string;
|
|
29
|
+
vvocConfigPath: string;
|
|
30
|
+
};
|
|
31
|
+
export declare function findNearestProjectConfigRoot(cwd: string): Promise<ProjectConfigRoot | undefined>;
|
|
32
|
+
export declare function resolveProjectWriteRoot(cwd: string): Promise<string>;
|
|
33
|
+
export declare function resolveProjectOpenCodeConfigPath(projectRoot: string): Promise<string>;
|
|
34
|
+
export declare function resolveVvocConfigSource(options: ConfigLayerOptions & {
|
|
35
|
+
scope: ConfigReadScope;
|
|
36
|
+
allowDefault: boolean;
|
|
37
|
+
}): Promise<ConfigSource>;
|
|
38
|
+
export declare function resolveOpenCodeConfigSource(options: ConfigLayerOptions & {
|
|
39
|
+
scope: ConfigReadScope;
|
|
40
|
+
}): Promise<ConfigSource>;
|
|
41
|
+
export declare function resolveConfigWriteTargets(options: ConfigLayerOptions & {
|
|
42
|
+
scope: ConfigWriteScope;
|
|
43
|
+
}): Promise<ConfigWriteTargets>;
|
|
44
|
+
export declare function loadVvocConfigForRead(options: ConfigLayerOptions & {
|
|
45
|
+
scope: ConfigReadScope;
|
|
46
|
+
allowDefault: boolean;
|
|
47
|
+
}): Promise<{
|
|
48
|
+
config: VvocConfig;
|
|
49
|
+
source: ConfigSource;
|
|
50
|
+
warnings: string[];
|
|
51
|
+
}>;
|
|
52
|
+
export declare function loadEffectiveVvocConfigForRuntime(options?: Partial<ConfigLayerOptions>): Promise<{
|
|
53
|
+
config: VvocConfig;
|
|
54
|
+
source: ConfigSource;
|
|
55
|
+
warnings: string[];
|
|
56
|
+
}>;
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
// FILE: src/lib/config-layers.ts
|
|
2
|
+
// VERSION: 1.0.0
|
|
3
|
+
// START_MODULE_CONTRACT
|
|
4
|
+
// PURPOSE: Resolve vvoc and OpenCode config layers for global, project, and effective scopes.
|
|
5
|
+
// SCOPE: Env override handling, ancestor project-root discovery, project write-root selection, global fallback paths, runtime vvoc loading, and source metadata.
|
|
6
|
+
// DEPENDS: [node:fs/promises, node:path, src/lib/vvoc-config.ts, src/lib/vvoc-paths.ts]
|
|
7
|
+
// LINKS: [M-CONFIG-LAYERS, M-CLI-CONFIG]
|
|
8
|
+
// ROLE: RUNTIME
|
|
9
|
+
// MAP_MODE: EXPORTS
|
|
10
|
+
// END_MODULE_CONTRACT
|
|
11
|
+
//
|
|
12
|
+
// START_MODULE_MAP
|
|
13
|
+
// VVOC_CONFIG_ENV - Environment variable name for explicit vvoc config selection.
|
|
14
|
+
// OPENCODE_CONFIG_ENV - Environment variable name for explicit OpenCode config selection.
|
|
15
|
+
// ConfigWriteScope - Supported write scopes for mutating commands.
|
|
16
|
+
// ConfigReadScope - Supported read scopes for list/show/diagnostic commands.
|
|
17
|
+
// ConfigSourceKind - Source kind labels for selected config sources.
|
|
18
|
+
// ConfigSource - Metadata describing a selected config source.
|
|
19
|
+
// ConfigWriteTargets - Resolved global or project write target paths.
|
|
20
|
+
// ProjectConfigRoot - Nearest project config layer metadata.
|
|
21
|
+
// ConfigLayerOptions - Common layered config resolution inputs.
|
|
22
|
+
// findNearestProjectConfigRoot - Finds the closest ancestor with .vvoc/vvoc.json or .opencode/opencode.json(c).
|
|
23
|
+
// resolveProjectWriteRoot - Selects the project root that project-scope mutations write to.
|
|
24
|
+
// resolveProjectOpenCodeConfigPath - Selects the canonical project .opencode/opencode.json(c) path.
|
|
25
|
+
// resolveVvocConfigSource - Resolves vvoc source metadata for global, project, or effective reads.
|
|
26
|
+
// resolveOpenCodeConfigSource - Resolves OpenCode source metadata for global, project, or effective reads.
|
|
27
|
+
// resolveConfigWriteTargets - Returns canonical global or project write paths.
|
|
28
|
+
// loadVvocConfigForRead - Loads vvoc config for CLI read/list/show commands without creating files.
|
|
29
|
+
// loadEffectiveVvocConfigForRuntime - Loads the effective vvoc config for runtime plugins.
|
|
30
|
+
// END_MODULE_MAP
|
|
31
|
+
//
|
|
32
|
+
// START_CHANGE_SUMMARY
|
|
33
|
+
// LAST_CHANGE: [v1.0.0 - Added layered config source discovery, write target resolution, and runtime vvoc loading.]
|
|
34
|
+
// END_CHANGE_SUMMARY
|
|
35
|
+
import { access, readFile } from "node:fs/promises";
|
|
36
|
+
import { dirname, join, resolve } from "node:path";
|
|
37
|
+
import { createDefaultVvocConfig, loadLenientVvocConfigText, parseVvocConfigText, } from "./vvoc-config.js";
|
|
38
|
+
import { getGlobalOpencodeDir, getGlobalVvocConfigPath, getGlobalVvocDir, getProjectOpencodeDir, getProjectVvocConfigPath, } from "./vvoc-paths.js";
|
|
39
|
+
export const VVOC_CONFIG_ENV = "VVOC_CONFIG";
|
|
40
|
+
export const OPENCODE_CONFIG_ENV = "OPENCODE_CONFIG";
|
|
41
|
+
const OPENCODE_CONFIG_FILE_NAMES = ["opencode.json", "opencode.jsonc"];
|
|
42
|
+
// START_BLOCK_PROJECT_LAYER_DISCOVERY
|
|
43
|
+
export async function findNearestProjectConfigRoot(cwd) {
|
|
44
|
+
let currentDir = resolve(cwd);
|
|
45
|
+
while (true) {
|
|
46
|
+
const vvocConfigPath = getProjectVvocConfigPath(currentDir);
|
|
47
|
+
const opencodeConfigPath = await findExistingProjectOpenCodeConfigPath(currentDir);
|
|
48
|
+
const hasVvocConfig = await pathExists(vvocConfigPath);
|
|
49
|
+
if (hasVvocConfig || opencodeConfigPath) {
|
|
50
|
+
return {
|
|
51
|
+
rootDir: currentDir,
|
|
52
|
+
vvocConfigPath: hasVvocConfig ? vvocConfigPath : undefined,
|
|
53
|
+
opencodeConfigPath,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const parentDir = dirname(currentDir);
|
|
57
|
+
if (parentDir === currentDir) {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
currentDir = parentDir;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
export async function resolveProjectWriteRoot(cwd) {
|
|
64
|
+
return (await findNearestProjectConfigRoot(cwd))?.rootDir ?? resolve(cwd);
|
|
65
|
+
}
|
|
66
|
+
export async function resolveProjectOpenCodeConfigPath(projectRoot) {
|
|
67
|
+
return ((await findExistingProjectOpenCodeConfigPath(projectRoot)) ??
|
|
68
|
+
join(getProjectOpencodeDir(projectRoot), "opencode.json"));
|
|
69
|
+
}
|
|
70
|
+
// END_BLOCK_PROJECT_LAYER_DISCOVERY
|
|
71
|
+
// START_BLOCK_SOURCE_RESOLUTION
|
|
72
|
+
export async function resolveVvocConfigSource(options) {
|
|
73
|
+
if (options.scope === "global") {
|
|
74
|
+
return resolveGlobalVvocSource(options.configDir);
|
|
75
|
+
}
|
|
76
|
+
if (options.scope === "project") {
|
|
77
|
+
return resolveProjectVvocSource(options.cwd);
|
|
78
|
+
}
|
|
79
|
+
const envSource = readEnvConfigSource(options.env, VVOC_CONFIG_ENV);
|
|
80
|
+
if (envSource) {
|
|
81
|
+
return envSource;
|
|
82
|
+
}
|
|
83
|
+
const projectSource = await resolveProjectVvocSource(options.cwd);
|
|
84
|
+
if (projectSource.kind === "project") {
|
|
85
|
+
return projectSource;
|
|
86
|
+
}
|
|
87
|
+
const globalSource = await resolveGlobalVvocSource(options.configDir);
|
|
88
|
+
if (globalSource.kind === "global") {
|
|
89
|
+
return globalSource;
|
|
90
|
+
}
|
|
91
|
+
if (options.allowDefault) {
|
|
92
|
+
return { kind: "default", reason: "no vvoc config found" };
|
|
93
|
+
}
|
|
94
|
+
return globalSource.kind === "missing" ? globalSource : projectSource;
|
|
95
|
+
}
|
|
96
|
+
export async function resolveOpenCodeConfigSource(options) {
|
|
97
|
+
if (options.scope === "global") {
|
|
98
|
+
return resolveGlobalOpenCodeSource(options.configDir);
|
|
99
|
+
}
|
|
100
|
+
if (options.scope === "project") {
|
|
101
|
+
return resolveProjectOpenCodeSource(options.cwd);
|
|
102
|
+
}
|
|
103
|
+
const envSource = readEnvConfigSource(options.env, OPENCODE_CONFIG_ENV);
|
|
104
|
+
if (envSource) {
|
|
105
|
+
return envSource;
|
|
106
|
+
}
|
|
107
|
+
const projectSource = await resolveProjectOpenCodeSource(options.cwd);
|
|
108
|
+
if (projectSource.kind === "project") {
|
|
109
|
+
return projectSource;
|
|
110
|
+
}
|
|
111
|
+
return resolveGlobalOpenCodeSource(options.configDir);
|
|
112
|
+
}
|
|
113
|
+
export async function resolveConfigWriteTargets(options) {
|
|
114
|
+
if (options.scope === "global") {
|
|
115
|
+
const opencodeBaseDir = getGlobalOpencodeDir(options.configDir);
|
|
116
|
+
const opencodeConfigPath = await selectExistingPath(OPENCODE_CONFIG_FILE_NAMES.map((name) => join(opencodeBaseDir, name)));
|
|
117
|
+
return {
|
|
118
|
+
scope: "global",
|
|
119
|
+
opencodeBaseDir,
|
|
120
|
+
vvocBaseDir: getGlobalVvocDir(options.configDir),
|
|
121
|
+
opencodeConfigPath,
|
|
122
|
+
vvocConfigPath: getGlobalVvocConfigPath(options.configDir),
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
const projectRoot = await resolveProjectWriteRoot(options.cwd);
|
|
126
|
+
const opencodeBaseDir = getProjectOpencodeDir(projectRoot);
|
|
127
|
+
return {
|
|
128
|
+
scope: "project",
|
|
129
|
+
projectRoot,
|
|
130
|
+
opencodeBaseDir,
|
|
131
|
+
vvocBaseDir: dirname(getProjectVvocConfigPath(projectRoot)),
|
|
132
|
+
opencodeConfigPath: await resolveProjectOpenCodeConfigPath(projectRoot),
|
|
133
|
+
vvocConfigPath: getProjectVvocConfigPath(projectRoot),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
// END_BLOCK_SOURCE_RESOLUTION
|
|
137
|
+
// START_BLOCK_RUNTIME_VVOC_LOADING
|
|
138
|
+
export async function loadVvocConfigForRead(options) {
|
|
139
|
+
const source = await resolveVvocConfigSource(options);
|
|
140
|
+
if (source.kind === "default" ||
|
|
141
|
+
(source.kind === "missing" && options.scope === "global" && options.allowDefault)) {
|
|
142
|
+
return {
|
|
143
|
+
config: createDefaultVvocConfig(),
|
|
144
|
+
source: { kind: "default", reason: source.reason },
|
|
145
|
+
warnings: [],
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
if (source.kind === "missing") {
|
|
149
|
+
throw new Error(source.reason ?? `vvoc config missing${source.path ? ` at ${source.path}` : ""}`);
|
|
150
|
+
}
|
|
151
|
+
if (!source.path) {
|
|
152
|
+
throw new Error(`selected vvoc config source has no path (${source.kind})`);
|
|
153
|
+
}
|
|
154
|
+
return {
|
|
155
|
+
config: parseVvocConfigText(await readFile(source.path, "utf8"), source.path),
|
|
156
|
+
source,
|
|
157
|
+
warnings: [],
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
export async function loadEffectiveVvocConfigForRuntime(options = {}) {
|
|
161
|
+
const source = await resolveVvocConfigSource({
|
|
162
|
+
scope: "effective",
|
|
163
|
+
allowDefault: true,
|
|
164
|
+
cwd: options.cwd ?? process.cwd(),
|
|
165
|
+
configDir: options.configDir,
|
|
166
|
+
env: options.env,
|
|
167
|
+
});
|
|
168
|
+
if (source.kind === "default") {
|
|
169
|
+
return { config: createDefaultVvocConfig(), source, warnings: [] };
|
|
170
|
+
}
|
|
171
|
+
if (!source.path) {
|
|
172
|
+
throw new Error(`selected vvoc config source has no path (${source.kind})`);
|
|
173
|
+
}
|
|
174
|
+
const text = await readFile(source.path, "utf8");
|
|
175
|
+
if (source.kind === "env" || source.kind === "project") {
|
|
176
|
+
return { config: parseVvocConfigText(text, source.path), source, warnings: [] };
|
|
177
|
+
}
|
|
178
|
+
const warnings = [];
|
|
179
|
+
const config = loadLenientVvocConfigText(text, source.path, warnings);
|
|
180
|
+
return { config, source, warnings };
|
|
181
|
+
}
|
|
182
|
+
// END_BLOCK_RUNTIME_VVOC_LOADING
|
|
183
|
+
async function resolveProjectVvocSource(cwd) {
|
|
184
|
+
const root = await findNearestProjectConfigRoot(cwd);
|
|
185
|
+
if (root?.vvocConfigPath) {
|
|
186
|
+
return { kind: "project", path: root.vvocConfigPath, rootDir: root.rootDir };
|
|
187
|
+
}
|
|
188
|
+
return {
|
|
189
|
+
kind: "missing",
|
|
190
|
+
reason: "project vvoc config missing; run vvoc install --scope project",
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
async function resolveProjectOpenCodeSource(cwd) {
|
|
194
|
+
const root = await findNearestProjectConfigRoot(cwd);
|
|
195
|
+
if (root?.opencodeConfigPath) {
|
|
196
|
+
return { kind: "project", path: root.opencodeConfigPath, rootDir: root.rootDir };
|
|
197
|
+
}
|
|
198
|
+
return {
|
|
199
|
+
kind: "missing",
|
|
200
|
+
reason: "project OpenCode config missing; run vvoc install --scope project",
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
async function resolveGlobalVvocSource(configDir) {
|
|
204
|
+
const path = getGlobalVvocConfigPath(configDir);
|
|
205
|
+
return (await pathExists(path))
|
|
206
|
+
? { kind: "global", path }
|
|
207
|
+
: { kind: "missing", path, reason: "global vvoc config missing" };
|
|
208
|
+
}
|
|
209
|
+
async function resolveGlobalOpenCodeSource(configDir) {
|
|
210
|
+
const baseDir = getGlobalOpencodeDir(configDir);
|
|
211
|
+
const path = await findExistingOpenCodeConfigPath(baseDir);
|
|
212
|
+
return path
|
|
213
|
+
? { kind: "global", path }
|
|
214
|
+
: {
|
|
215
|
+
kind: "missing",
|
|
216
|
+
path: join(baseDir, "opencode.json"),
|
|
217
|
+
reason: "global OpenCode config missing",
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
function readEnvConfigSource(env, name) {
|
|
221
|
+
const value = env ? env[name] : process.env[name];
|
|
222
|
+
if (typeof value !== "string" || !value.trim()) {
|
|
223
|
+
return undefined;
|
|
224
|
+
}
|
|
225
|
+
return { kind: "env", path: resolve(value.trim()), reason: name };
|
|
226
|
+
}
|
|
227
|
+
async function findExistingProjectOpenCodeConfigPath(projectRoot) {
|
|
228
|
+
return findExistingOpenCodeConfigPath(getProjectOpencodeDir(projectRoot));
|
|
229
|
+
}
|
|
230
|
+
async function findExistingOpenCodeConfigPath(baseDir) {
|
|
231
|
+
for (const name of OPENCODE_CONFIG_FILE_NAMES) {
|
|
232
|
+
const candidate = join(baseDir, name);
|
|
233
|
+
if (await pathExists(candidate)) {
|
|
234
|
+
return candidate;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return undefined;
|
|
238
|
+
}
|
|
239
|
+
async function selectExistingPath(candidates) {
|
|
240
|
+
for (const candidate of candidates) {
|
|
241
|
+
if (await pathExists(candidate)) {
|
|
242
|
+
return candidate;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return candidates[0];
|
|
246
|
+
}
|
|
247
|
+
async function pathExists(path) {
|
|
248
|
+
try {
|
|
249
|
+
await access(path);
|
|
250
|
+
return true;
|
|
251
|
+
}
|
|
252
|
+
catch {
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
//# sourceMappingURL=config-layers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-layers.js","sourceRoot":"","sources":["../../src/lib/config-layers.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/opencode.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type ManagedOpenCodeAgentName } from "./managed-agents.js";
|
|
2
2
|
import { type GuardianConfig, type GuardianConfigOverrides, type SecretsRedactionConfig, type VvocConfig } from "./vvoc-config.js";
|
|
3
3
|
import { PACKAGE_NAME } from "./package.js";
|
|
4
|
+
import { type ConfigReadScope, type ConfigSource } from "./config-layers.js";
|
|
4
5
|
export declare const CLI_NAME = "vvoc";
|
|
5
6
|
export { PACKAGE_NAME };
|
|
6
7
|
export declare const OPENCODE_SCHEMA_URL = "https://opencode.ai/config.json";
|
|
@@ -11,11 +12,11 @@ export type ResolvedPaths = {
|
|
|
11
12
|
scope: Scope;
|
|
12
13
|
cwd: string;
|
|
13
14
|
configHome: string;
|
|
15
|
+
projectRoot?: string;
|
|
14
16
|
opencodeBaseDir: string;
|
|
15
17
|
vvocBaseDir: string;
|
|
16
18
|
vvocConfigPath: string;
|
|
17
19
|
managedAgentsDirPath: string;
|
|
18
|
-
managedPlansDirPath: string;
|
|
19
20
|
managedSkillsDirPath: string;
|
|
20
21
|
opencodeConfigPath: string;
|
|
21
22
|
opencodeAlternatePaths: string[];
|
|
@@ -31,7 +32,7 @@ export type OpenCodeAgentOverride = {
|
|
|
31
32
|
};
|
|
32
33
|
export type ManagedAgentOverrideMap = Record<ManagedOpenCodeAgentName, OpenCodeAgentOverride>;
|
|
33
34
|
export type InstallationInspection = {
|
|
34
|
-
scope:
|
|
35
|
+
scope: ConfigReadScope;
|
|
35
36
|
opencode: {
|
|
36
37
|
path: string;
|
|
37
38
|
exists: boolean;
|
|
@@ -74,7 +75,7 @@ export declare function resolvePaths(options: {
|
|
|
74
75
|
configDir?: string;
|
|
75
76
|
}): Promise<ResolvedPaths>;
|
|
76
77
|
export declare function ensurePackageConfigText(text: string | undefined, packageSpecifier?: string): string;
|
|
77
|
-
export declare function ensureManagedAgentRegistrationsConfigText(text: string | undefined, paths: Pick<ResolvedPaths, "managedAgentsDirPath" | "opencodeConfigPath">): string;
|
|
78
|
+
export declare function ensureManagedAgentRegistrationsConfigText(text: string | undefined, paths: Pick<ResolvedPaths, "managedAgentsDirPath" | "managedSkillsDirPath" | "opencodeConfigPath">): string;
|
|
78
79
|
export declare function syncManagedAgentRegistrations(paths: ResolvedPaths): Promise<{
|
|
79
80
|
path: string;
|
|
80
81
|
changed: boolean;
|
|
@@ -85,7 +86,6 @@ export declare function installManagedAgentPrompts(paths: ResolvedPaths, options
|
|
|
85
86
|
export declare function syncManagedAgentPrompts(paths: ResolvedPaths, options: {
|
|
86
87
|
force: boolean;
|
|
87
88
|
}): Promise<WriteResult[]>;
|
|
88
|
-
export declare function ensureManagedPlanDirectory(paths: Pick<ResolvedPaths, "managedPlansDirPath">): Promise<WriteResult>;
|
|
89
89
|
export declare function installManagedSkillFiles(paths: ResolvedPaths, options: {
|
|
90
90
|
force: boolean;
|
|
91
91
|
}): Promise<WriteResult[]>;
|
|
@@ -107,7 +107,7 @@ export declare function writeOpenCodeDefaultModel(paths: Pick<ResolvedPaths, "op
|
|
|
107
107
|
ensureEntry: boolean;
|
|
108
108
|
}): Promise<WriteResult>;
|
|
109
109
|
export declare function writeOpenCodeProviderObject(paths: Pick<ResolvedPaths, "opencodeConfigPath">, providerID: string, value: JsonObject): Promise<WriteResult>;
|
|
110
|
-
export declare function writeManagedAgentModel(paths: Pick<ResolvedPaths, "managedAgentsDirPath" | "opencodeConfigPath">, agentName: ManagedOpenCodeAgentName, options: {
|
|
110
|
+
export declare function writeManagedAgentModel(paths: Pick<ResolvedPaths, "managedAgentsDirPath" | "managedSkillsDirPath" | "opencodeConfigPath">, agentName: ManagedOpenCodeAgentName, options: {
|
|
111
111
|
model?: string;
|
|
112
112
|
ensureEntry: boolean;
|
|
113
113
|
}): Promise<WriteResult>;
|
|
@@ -125,4 +125,12 @@ export declare function writeGuardianConfig(paths: Pick<ResolvedPaths, "vvocConf
|
|
|
125
125
|
merge?: boolean;
|
|
126
126
|
}): Promise<WriteResult>;
|
|
127
127
|
export declare function inspectInstallation(paths: ResolvedPaths): Promise<InstallationInspection>;
|
|
128
|
+
export declare function inspectInstallationForScope(options: {
|
|
129
|
+
scope: ConfigReadScope;
|
|
130
|
+
cwd: string;
|
|
131
|
+
configDir?: string;
|
|
132
|
+
}): Promise<InstallationInspection & {
|
|
133
|
+
opencodeSource: ConfigSource;
|
|
134
|
+
vvocSource: ConfigSource;
|
|
135
|
+
}>;
|
|
128
136
|
export declare function describeWriteResult(result: WriteResult): string;
|
package/dist/lib/opencode.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// FILE: src/lib/opencode.ts
|
|
2
2
|
// VERSION: 1.0.0
|
|
3
3
|
// START_MODULE_CONTRACT
|
|
4
|
-
// PURPOSE: Manage OpenCode config mutation, provider patching, and
|
|
5
|
-
// SCOPE:
|
|
6
|
-
// DEPENDS: [jsonc-parser, node:fs/promises, node:path, src/lib/managed-agents.ts, src/lib/managed-skills.ts, src/lib/package.ts, src/lib/vvoc-config.ts, src/lib/vvoc-paths.ts]
|
|
4
|
+
// PURPOSE: Manage OpenCode config mutation, provider patching, and scoped vvoc.json config files.
|
|
5
|
+
// SCOPE: Layer-aware path resolution, pinned plugin writes, managed OpenCode defaults, local skills path registration, provider patching, managed prompts/skills, version-aware vvoc config rendering, and installation inspection.
|
|
6
|
+
// DEPENDS: [jsonc-parser, node:fs/promises, node:path, src/lib/config-layers.ts, src/lib/managed-agents.ts, src/lib/managed-skills.ts, src/lib/package.ts, src/lib/vvoc-config.ts, src/lib/vvoc-paths.ts]
|
|
7
7
|
// LINKS: [M-CLI-CONFIG]
|
|
8
8
|
// ROLE: RUNTIME
|
|
9
9
|
// MAP_MODE: EXPORTS
|
|
@@ -33,7 +33,6 @@
|
|
|
33
33
|
// syncManagedAgentRegistrations - Syncs the canonical vvoc-managed OpenCode agent registrations and tool gating into OpenCode config.
|
|
34
34
|
// installManagedAgentPrompts - Creates managed vvoc prompt files for the bundled Guardian and managed OpenCode agents when missing.
|
|
35
35
|
// syncManagedAgentPrompts - Rewrites managed vvoc prompt files for the bundled Guardian and managed OpenCode agents.
|
|
36
|
-
// ensureManagedPlanDirectory - Creates the managed vvoc planning artifact directory when missing.
|
|
37
36
|
// installManagedSkillFiles - Creates managed vvoc skill files from bundled templates.
|
|
38
37
|
// syncManagedSkillFiles - Rewrites managed vvoc skill files from bundled templates.
|
|
39
38
|
// ensureManagedSkillSymlink - Creates symlink from OpenCode skills dir to vvoc skills dir for skill discovery.
|
|
@@ -45,6 +44,7 @@
|
|
|
45
44
|
// writeManagedAgentModel - Writes or removes a bundled vvoc-managed OpenCode agent model override in OpenCode config.
|
|
46
45
|
// writeGuardianConfig - Writes the guardian section into the canonical vvoc.json document.
|
|
47
46
|
// inspectInstallation - Reads current OpenCode/vvoc installation state for status and doctor commands.
|
|
47
|
+
// inspectInstallationForScope - Reads installation state using strict/effective layered source resolution.
|
|
48
48
|
// describeWriteResult - Formats config write outcomes for CLI output.
|
|
49
49
|
// ManagedAgentModelMap - Map of managed agent names to model selections.
|
|
50
50
|
// OpenCodeAgentOverride - Agent override config for OpenCode.
|
|
@@ -56,8 +56,10 @@
|
|
|
56
56
|
// END_MODULE_MAP
|
|
57
57
|
//
|
|
58
58
|
// START_CHANGE_SUMMARY
|
|
59
|
+
// LAST_CHANGE: [v1.1.1 - Fixed syncManagedSkillFiles to not sync references when parent skill is skipped (user-owned/custom). Added regression coverage.]
|
|
60
|
+
// LAST_CHANGE: [v1.1.0 - Switched project-scope writes to .opencode/.vvoc layers and added local managed skills path registration.]
|
|
59
61
|
// LAST_CHANGE: [v0.5.1 - Added ensureManagedSkillSymlink. Fixed renderManagedSkill to preserve YAML frontmatter.]
|
|
60
|
-
// LAST_CHANGE: [v1.0.1 - Added managed plan directory resolution and creation for analyst/architect artifacts.]
|
|
62
|
+
// LAST_CHANGE: [v1.0.1 - Added managed plan directory resolution and creation for analyst/architect artifacts. Removed in v1.2.0 — superseded by spec package layout under .vvoc/specs/<id>/.]
|
|
61
63
|
// LAST_CHANGE: [v0.5.0 - Replaced managed command registrations (vv-plan/vv-review) with managed skills system. Added managedSkillsDirPath to ResolvedPaths. Added installManagedSkillFiles and syncManagedSkillFiles.]
|
|
62
64
|
// LAST_CHANGE: [v0.9.7 - Removed variant splitting from agent model read/write helpers so provider/model:free passes through unchanged.]
|
|
63
65
|
// LAST_CHANGE: [v0.9.6 - Added managed OpenCode `tools.apply_patch = false` writes during install/init/sync so sessions stay on the hashline-backed `edit` override.]
|
|
@@ -76,7 +78,8 @@ import { MANAGED_SKILL_NAMES, getManagedSkillFilePath, listManagedSkillReference
|
|
|
76
78
|
import { BUILTIN_ROLE_NAMES, getBuiltInRoleBindings, ROLE_REFERENCE_PREFIX, } from "./model-roles.js";
|
|
77
79
|
import { createDefaultVvocConfig, createGuardianConfig, parseVersionedVvocConfigText, parseVvocConfigText, renderVvocConfig, } from "./vvoc-config.js";
|
|
78
80
|
import { getPinnedPackageSpecifier, PACKAGE_NAME } from "./package.js";
|
|
79
|
-
import {
|
|
81
|
+
import { resolveConfigWriteTargets, resolveOpenCodeConfigSource, resolveVvocConfigSource, } from "./config-layers.js";
|
|
82
|
+
import { getConfigHome, getGlobalOpencodeSkillsDir, getGlobalVvocDir, getVvocAgentsDir, getVvocSkillsDir, } from "./vvoc-paths.js";
|
|
80
83
|
export const CLI_NAME = "vvoc";
|
|
81
84
|
export { PACKAGE_NAME };
|
|
82
85
|
export const OPENCODE_SCHEMA_URL = "https://opencode.ai/config.json";
|
|
@@ -111,26 +114,22 @@ const JSON_FORMAT = {
|
|
|
111
114
|
};
|
|
112
115
|
// START_BLOCK_RESOLVE_CONFIG_PATHS
|
|
113
116
|
export async function resolvePaths(options) {
|
|
117
|
+
const targets = await resolveConfigWriteTargets(options);
|
|
114
118
|
const configHome = getConfigHome(options.configDir);
|
|
115
|
-
const
|
|
116
|
-
const
|
|
117
|
-
const managedAgentsBaseDir = options.scope === "global" ? vvocBaseDir : getProjectVvocDir(options.cwd);
|
|
118
|
-
const managedAgentsDirPath = getVvocAgentsDir(managedAgentsBaseDir);
|
|
119
|
-
const managedPlansDirPath = getVvocPlansDir(managedAgentsBaseDir);
|
|
120
|
-
const managedSkillsDirPath = getVvocSkillsDir(managedAgentsBaseDir);
|
|
121
|
-
const opencodeSelection = await selectPrimaryPath(OPENCODE_CONFIG_FILE_NAMES.map((name) => join(opencodeBaseDir, name)));
|
|
119
|
+
const managedAgentsDirPath = getVvocAgentsDir(targets.vvocBaseDir);
|
|
120
|
+
const managedSkillsDirPath = getVvocSkillsDir(targets.vvocBaseDir);
|
|
122
121
|
return {
|
|
123
122
|
scope: options.scope,
|
|
124
123
|
cwd: options.cwd,
|
|
125
124
|
configHome,
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
125
|
+
projectRoot: targets.projectRoot,
|
|
126
|
+
opencodeBaseDir: targets.opencodeBaseDir,
|
|
127
|
+
vvocBaseDir: targets.vvocBaseDir,
|
|
128
|
+
vvocConfigPath: targets.vvocConfigPath,
|
|
129
129
|
managedAgentsDirPath,
|
|
130
|
-
managedPlansDirPath,
|
|
131
130
|
managedSkillsDirPath,
|
|
132
|
-
opencodeConfigPath:
|
|
133
|
-
opencodeAlternatePaths:
|
|
131
|
+
opencodeConfigPath: targets.opencodeConfigPath,
|
|
132
|
+
opencodeAlternatePaths: await resolveOpenCodeAlternates(targets.opencodeBaseDir, targets.opencodeConfigPath),
|
|
134
133
|
};
|
|
135
134
|
}
|
|
136
135
|
// END_BLOCK_RESOLVE_CONFIG_PATHS
|
|
@@ -187,6 +186,9 @@ export function ensureManagedAgentRegistrationsConfigText(text, paths) {
|
|
|
187
186
|
...Object.fromEntries(Object.entries(builtInAgentModelRefs).map(([name, model]) => [name, { model }])),
|
|
188
187
|
...managedRegistrations,
|
|
189
188
|
},
|
|
189
|
+
skills: {
|
|
190
|
+
paths: [getManagedSkillsPathReference(paths)],
|
|
191
|
+
},
|
|
190
192
|
command: {},
|
|
191
193
|
});
|
|
192
194
|
}
|
|
@@ -252,7 +254,7 @@ export function ensureManagedAgentRegistrationsConfigText(text, paths) {
|
|
|
252
254
|
}));
|
|
253
255
|
}
|
|
254
256
|
}
|
|
255
|
-
return ensureTrailingNewline(applyEdits(nextText, format(nextText, undefined, JSON_FORMAT)));
|
|
257
|
+
return ensureManagedSkillsPathConfigText(ensureTrailingNewline(applyEdits(nextText, format(nextText, undefined, JSON_FORMAT))), paths);
|
|
256
258
|
}
|
|
257
259
|
export async function syncManagedAgentRegistrations(paths) {
|
|
258
260
|
const currentText = await readOptionalText(paths.opencodeConfigPath);
|
|
@@ -300,13 +302,6 @@ export async function syncManagedAgentPrompts(paths, options) {
|
|
|
300
302
|
}
|
|
301
303
|
return results;
|
|
302
304
|
}
|
|
303
|
-
export async function ensureManagedPlanDirectory(paths) {
|
|
304
|
-
const createdPath = await mkdir(paths.managedPlansDirPath, { recursive: true });
|
|
305
|
-
return {
|
|
306
|
-
action: createdPath ? "created" : "kept",
|
|
307
|
-
path: paths.managedPlansDirPath,
|
|
308
|
-
};
|
|
309
|
-
}
|
|
310
305
|
// START_BLOCK_MANAGED_SKILL_FUNCTIONS
|
|
311
306
|
export async function installManagedSkillFiles(paths, options) {
|
|
312
307
|
const results = [];
|
|
@@ -341,9 +336,13 @@ export async function installManagedSkillFiles(paths, options) {
|
|
|
341
336
|
export async function syncManagedSkillFiles(paths, options) {
|
|
342
337
|
const results = [];
|
|
343
338
|
for (const skillName of MANAGED_SKILL_NAMES) {
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
339
|
+
const skillResult = await syncManagedSkill(paths, skillName, options);
|
|
340
|
+
results.push(skillResult);
|
|
341
|
+
// Only sync references when the parent skill was not skipped (user-owned/custom)
|
|
342
|
+
if (skillResult.action !== "skipped") {
|
|
343
|
+
const refResults = await syncManagedSkillReferences(paths.managedSkillsDirPath, skillName);
|
|
344
|
+
results.push(...refResults);
|
|
345
|
+
}
|
|
347
346
|
}
|
|
348
347
|
return results;
|
|
349
348
|
}
|
|
@@ -682,6 +681,51 @@ export async function inspectInstallation(paths) {
|
|
|
682
681
|
problems,
|
|
683
682
|
};
|
|
684
683
|
}
|
|
684
|
+
export async function inspectInstallationForScope(options) {
|
|
685
|
+
const [opencodeSource, vvocSource] = await Promise.all([
|
|
686
|
+
resolveOpenCodeConfigSource({
|
|
687
|
+
scope: options.scope,
|
|
688
|
+
cwd: options.cwd,
|
|
689
|
+
configDir: options.configDir,
|
|
690
|
+
}),
|
|
691
|
+
resolveVvocConfigSource({
|
|
692
|
+
scope: options.scope,
|
|
693
|
+
cwd: options.cwd,
|
|
694
|
+
configDir: options.configDir,
|
|
695
|
+
allowDefault: options.scope === "effective",
|
|
696
|
+
}),
|
|
697
|
+
]);
|
|
698
|
+
if (options.scope === "project") {
|
|
699
|
+
const missingSource = [opencodeSource, vvocSource].find((source) => source.kind === "missing");
|
|
700
|
+
if (missingSource) {
|
|
701
|
+
throw new Error(missingSource.reason ?? "project config missing; run vvoc install --scope project");
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
const fallbackPaths = await resolvePaths({
|
|
705
|
+
scope: options.scope === "global" ? "global" : "project",
|
|
706
|
+
cwd: options.cwd,
|
|
707
|
+
configDir: options.configDir,
|
|
708
|
+
});
|
|
709
|
+
const opencodeConfigPath = opencodeSource.path ?? fallbackPaths.opencodeConfigPath;
|
|
710
|
+
const vvocConfigPath = vvocSource.path ?? fallbackPaths.vvocConfigPath;
|
|
711
|
+
const scopedPaths = {
|
|
712
|
+
...fallbackPaths,
|
|
713
|
+
opencodeBaseDir: dirname(opencodeConfigPath),
|
|
714
|
+
vvocBaseDir: dirname(vvocConfigPath),
|
|
715
|
+
opencodeConfigPath,
|
|
716
|
+
vvocConfigPath,
|
|
717
|
+
opencodeAlternatePaths: [],
|
|
718
|
+
managedAgentsDirPath: getVvocAgentsDir(dirname(vvocConfigPath)),
|
|
719
|
+
managedSkillsDirPath: getVvocSkillsDir(dirname(vvocConfigPath)),
|
|
720
|
+
};
|
|
721
|
+
const inspection = await inspectInstallation(scopedPaths);
|
|
722
|
+
return {
|
|
723
|
+
...inspection,
|
|
724
|
+
scope: options.scope,
|
|
725
|
+
opencodeSource,
|
|
726
|
+
vvocSource,
|
|
727
|
+
};
|
|
728
|
+
}
|
|
685
729
|
// END_BLOCK_INSPECT_INSTALLATION_STATE
|
|
686
730
|
export function describeWriteResult(result) {
|
|
687
731
|
let message = "";
|
|
@@ -726,6 +770,12 @@ function readPluginList(document, label) {
|
|
|
726
770
|
}
|
|
727
771
|
return raw.slice();
|
|
728
772
|
}
|
|
773
|
+
function readStringArray(value, label) {
|
|
774
|
+
if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string")) {
|
|
775
|
+
throw new Error(`${label}: expected an array of strings`);
|
|
776
|
+
}
|
|
777
|
+
return value.slice();
|
|
778
|
+
}
|
|
729
779
|
function normalizePluginList(currentPlugins, packageSpecifier) {
|
|
730
780
|
const nextPlugins = [];
|
|
731
781
|
const seen = new Set();
|
|
@@ -873,6 +923,25 @@ function getManagedOpenCodeAgentPromptReference(paths, agentName) {
|
|
|
873
923
|
const promptRef = relative(dirname(paths.opencodeConfigPath), promptPath).replaceAll("\\", "/");
|
|
874
924
|
return `{file:${promptRef.startsWith(".") ? promptRef : `./${promptRef}`}}`;
|
|
875
925
|
}
|
|
926
|
+
function getManagedSkillsPathReference(paths) {
|
|
927
|
+
const skillsRef = relative(dirname(paths.opencodeConfigPath), paths.managedSkillsDirPath).replaceAll("\\", "/");
|
|
928
|
+
return skillsRef.startsWith(".") ? skillsRef : `./${skillsRef}`;
|
|
929
|
+
}
|
|
930
|
+
function ensureManagedSkillsPathConfigText(text, paths) {
|
|
931
|
+
const document = parseObjectDocument(text, "OpenCode config");
|
|
932
|
+
const skills = readOptionalObject(document, "skills", "OpenCode config");
|
|
933
|
+
const rawPaths = skills?.paths;
|
|
934
|
+
const currentPaths = rawPaths === undefined ? [] : readStringArray(rawPaths, "OpenCode config: skills.paths");
|
|
935
|
+
const managedSkillsPath = getManagedSkillsPathReference(paths);
|
|
936
|
+
if (currentPaths.includes(managedSkillsPath)) {
|
|
937
|
+
return text;
|
|
938
|
+
}
|
|
939
|
+
const nextPaths = [...currentPaths, managedSkillsPath];
|
|
940
|
+
const nextText = applyEdits(text, modify(text, ["skills", "paths"], nextPaths, {
|
|
941
|
+
formattingOptions: JSON_FORMAT,
|
|
942
|
+
}));
|
|
943
|
+
return ensureTrailingNewline(applyEdits(nextText, format(nextText, undefined, JSON_FORMAT)));
|
|
944
|
+
}
|
|
876
945
|
function getLegacyTrackedManagedPromptReferences(paths, agentName) {
|
|
877
946
|
const promptPath = join(paths.managedAgentsDirPath, LEGACY_TRACKED_PROMPT_FILE_NAMES[agentName]);
|
|
878
947
|
const promptRef = relative(dirname(paths.opencodeConfigPath), promptPath).replaceAll("\\", "/");
|
|
@@ -1188,17 +1257,14 @@ async function writeText(path, text) {
|
|
|
1188
1257
|
await mkdir(dirname(path), { recursive: true });
|
|
1189
1258
|
await writeFile(path, text, "utf8");
|
|
1190
1259
|
}
|
|
1191
|
-
async function
|
|
1192
|
-
const
|
|
1193
|
-
for (const candidate of
|
|
1194
|
-
if ((await readOptionalText(candidate)) !== undefined) {
|
|
1195
|
-
|
|
1260
|
+
async function resolveOpenCodeAlternates(opencodeBaseDir, selectedPath) {
|
|
1261
|
+
const alternates = [];
|
|
1262
|
+
for (const candidate of OPENCODE_CONFIG_FILE_NAMES.map((name) => join(opencodeBaseDir, name))) {
|
|
1263
|
+
if (candidate !== selectedPath && (await readOptionalText(candidate)) !== undefined) {
|
|
1264
|
+
alternates.push(candidate);
|
|
1196
1265
|
}
|
|
1197
1266
|
}
|
|
1198
|
-
return
|
|
1199
|
-
primary: existing[0] ?? candidates[0],
|
|
1200
|
-
alternates: existing.slice(1),
|
|
1201
|
-
};
|
|
1267
|
+
return alternates;
|
|
1202
1268
|
}
|
|
1203
1269
|
// END_BLOCK_FILESYSTEM_HELPERS
|
|
1204
1270
|
//# sourceMappingURL=opencode.js.map
|