@osovv/vv-opencode 1.4.5 → 1.6.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/CHANGELOG.md +23 -0
- package/README.md +47 -16
- package/dist/commands/patch-provider.d.ts +5 -5
- package/dist/commands/patch-provider.js +10 -6
- package/dist/commands/patch-provider.js.map +1 -1
- package/dist/lib/agent-tool-catalog.d.ts +144 -0
- package/dist/lib/agent-tool-catalog.js +2551 -0
- package/dist/lib/agent-tool-catalog.js.map +1 -0
- package/dist/lib/agent-tool-contract.d.ts +200 -0
- package/dist/lib/agent-tool-contract.js +407 -0
- package/dist/lib/agent-tool-contract.js.map +1 -0
- package/dist/lib/opencode/agent-registrations.d.ts +33 -0
- package/dist/lib/opencode/agent-registrations.js +469 -0
- package/dist/lib/opencode/agent-registrations.js.map +1 -0
- package/dist/lib/opencode/inspection.d.ts +84 -0
- package/dist/lib/opencode/inspection.js +367 -0
- package/dist/lib/opencode/inspection.js.map +1 -0
- package/dist/lib/opencode/model-overrides.d.ts +19 -0
- package/dist/lib/opencode/model-overrides.js +221 -0
- package/dist/lib/opencode/model-overrides.js.map +1 -0
- package/dist/lib/opencode/paths.d.ts +21 -0
- package/dist/lib/opencode/paths.js +62 -0
- package/dist/lib/opencode/paths.js.map +1 -0
- package/dist/lib/opencode/plugin-registration.d.ts +17 -0
- package/dist/lib/opencode/plugin-registration.js +210 -0
- package/dist/lib/opencode/plugin-registration.js.map +1 -0
- package/dist/lib/opencode/shared-utils.d.ts +30 -0
- package/dist/lib/opencode/shared-utils.js +183 -0
- package/dist/lib/opencode/shared-utils.js.map +1 -0
- package/dist/lib/opencode/vvoc-config-io.d.ts +9 -0
- package/dist/lib/opencode/vvoc-config-io.js +58 -0
- package/dist/lib/opencode/vvoc-config-io.js.map +1 -0
- package/dist/lib/opencode.d.ts +15 -174
- package/dist/lib/opencode.js +19 -1387
- package/dist/lib/opencode.js.map +1 -1
- package/dist/lib/spec-lint/cross-file-rules.d.ts +2 -0
- package/dist/lib/spec-lint/cross-file-rules.js +33 -0
- package/dist/lib/spec-lint/cross-file-rules.js.map +1 -0
- package/dist/lib/spec-lint/delegated-extraction.d.ts +8 -0
- package/dist/lib/spec-lint/delegated-extraction.js +112 -0
- package/dist/lib/spec-lint/delegated-extraction.js.map +1 -0
- package/dist/lib/spec-lint/lint.d.ts +7 -0
- package/dist/lib/spec-lint/lint.js +92 -0
- package/dist/lib/spec-lint/lint.js.map +1 -0
- package/dist/lib/spec-lint/parser.d.ts +101 -0
- package/dist/lib/spec-lint/parser.js +482 -0
- package/dist/lib/spec-lint/parser.js.map +1 -0
- package/dist/lib/spec-lint/plan-rules.d.ts +38 -0
- package/dist/lib/spec-lint/plan-rules.js +745 -0
- package/dist/lib/spec-lint/plan-rules.js.map +1 -0
- package/dist/lib/spec-lint/spec-rules.d.ts +8 -0
- package/dist/lib/spec-lint/spec-rules.js +188 -0
- package/dist/lib/spec-lint/spec-rules.js.map +1 -0
- package/dist/lib/spec-lint.d.ts +4 -63
- package/dist/lib/spec-lint.js +13 -1505
- package/dist/lib/spec-lint.js.map +1 -1
- package/dist/lib/vvoc-preset-registry.d.ts +7 -7
- package/dist/lib/vvoc-preset-registry.js +8 -8
- package/dist/lib/vvoc-preset-registry.js.map +1 -1
- package/dist/lib/workflow-contract.d.ts +12 -0
- package/dist/lib/workflow-contract.js +71 -18
- package/dist/lib/workflow-contract.js.map +1 -1
- package/dist/plugins/hashline-edit/index.js +102 -97
- package/dist/plugins/hashline-edit/index.js.map +1 -1
- package/dist/plugins/hashline-edit/normalize-edits.d.ts +2 -8
- package/dist/plugins/hashline-edit/normalize-edits.js +32 -17
- package/dist/plugins/hashline-edit/normalize-edits.js.map +1 -1
- package/dist/plugins/hashline-edit/schemas.d.ts +246 -0
- package/dist/plugins/hashline-edit/schemas.js +659 -0
- package/dist/plugins/hashline-edit/schemas.js.map +1 -0
- package/dist/plugins/hashline-edit/str-replace-editor.d.ts +6 -17
- package/dist/plugins/hashline-edit/str-replace-editor.js +19 -21
- package/dist/plugins/hashline-edit/str-replace-editor.js.map +1 -1
- package/dist/plugins/hashline-edit/tool-description.d.ts +1 -0
- package/dist/plugins/hashline-edit/tool-description.js +20 -4
- package/dist/plugins/hashline-edit/tool-description.js.map +1 -1
- package/dist/plugins/web-tools/fetch-service.d.ts +8 -5
- package/dist/plugins/web-tools/fetch-service.js +30 -45
- package/dist/plugins/web-tools/fetch-service.js.map +1 -1
- package/dist/plugins/web-tools/index.js +23 -5
- package/dist/plugins/web-tools/index.js.map +1 -1
- package/dist/plugins/web-tools/schemas.d.ts +469 -0
- package/dist/plugins/web-tools/schemas.js +523 -0
- package/dist/plugins/web-tools/schemas.js.map +1 -0
- package/dist/plugins/web-tools/search-service.d.ts +6 -3
- package/dist/plugins/web-tools/search-service.js +24 -29
- package/dist/plugins/web-tools/search-service.js.map +1 -1
- package/dist/plugins/workflow/authority.d.ts +6 -0
- package/dist/plugins/workflow/authority.js +45 -10
- package/dist/plugins/workflow/authority.js.map +1 -1
- package/dist/plugins/workflow/authorization.d.ts +30 -0
- package/dist/plugins/workflow/authorization.js +147 -0
- package/dist/plugins/workflow/authorization.js.map +1 -0
- package/dist/plugins/workflow/checkpoints.d.ts +41 -2
- package/dist/plugins/workflow/checkpoints.js +176 -47
- package/dist/plugins/workflow/checkpoints.js.map +1 -1
- package/dist/plugins/workflow/delegated.d.ts +15 -1
- package/dist/plugins/workflow/delegated.js +65 -35
- package/dist/plugins/workflow/delegated.js.map +1 -1
- package/dist/plugins/workflow/execution.d.ts +15 -30
- package/dist/plugins/workflow/execution.js +133 -33
- package/dist/plugins/workflow/execution.js.map +1 -1
- package/dist/plugins/workflow/index.js +197 -435
- package/dist/plugins/workflow/index.js.map +1 -1
- package/dist/plugins/workflow/input-validation.d.ts +48 -0
- package/dist/plugins/workflow/input-validation.js +536 -0
- package/dist/plugins/workflow/input-validation.js.map +1 -0
- package/dist/plugins/workflow/inspection.d.ts +60 -0
- package/dist/plugins/workflow/inspection.js +316 -0
- package/dist/plugins/workflow/inspection.js.map +1 -0
- package/dist/plugins/workflow/protocol.d.ts +2 -0
- package/dist/plugins/workflow/protocol.js +26 -4
- package/dist/plugins/workflow/protocol.js.map +1 -1
- package/dist/plugins/workflow/recovery.d.ts +18 -0
- package/dist/plugins/workflow/recovery.js +217 -0
- package/dist/plugins/workflow/recovery.js.map +1 -0
- package/dist/plugins/workflow/repair.d.ts +1 -1
- package/dist/plugins/workflow/repair.js +9 -10
- package/dist/plugins/workflow/repair.js.map +1 -1
- package/dist/plugins/workflow/results.d.ts +2566 -0
- package/dist/plugins/workflow/results.js +1111 -0
- package/dist/plugins/workflow/results.js.map +1 -0
- package/dist/plugins/workflow/schemas.d.ts +398 -0
- package/dist/plugins/workflow/schemas.js +399 -0
- package/dist/plugins/workflow/schemas.js.map +1 -0
- package/dist/plugins/workflow/state.d.ts +3 -2
- package/dist/plugins/workflow/state.js +15 -8
- package/dist/plugins/workflow/state.js.map +1 -1
- package/dist/plugins/workflow/system-instruction.md +17 -1
- package/dist/plugins/workflow/tooling.d.ts +11 -82
- package/dist/plugins/workflow/tooling.js +478 -461
- package/dist/plugins/workflow/tooling.js.map +1 -1
- package/dist/plugins/workflow/transactions.d.ts +13 -0
- package/dist/plugins/workflow/transactions.js +13 -3
- package/dist/plugins/workflow/transactions.js.map +1 -1
- package/package.json +6 -3
- package/schemas/vvoc/v3.json +1 -1
- package/templates/agents/vv-code-reviewer.md +13 -4
- package/templates/agents/vv-implementer.md +16 -9
- package/templates/agents/vv-spec-reviewer.md +13 -4
- package/templates/skills/vv-execute/SKILL.md +3 -3
- package/templates/skills/vv-execute/references/tool-contracts.md +1750 -0
- package/templates/skills/vv-review/SKILL.md +1 -1
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type Scope = "global" | "project";
|
|
2
|
+
export type ResolvedPaths = {
|
|
3
|
+
scope: Scope;
|
|
4
|
+
cwd: string;
|
|
5
|
+
configHome: string;
|
|
6
|
+
projectRoot?: string;
|
|
7
|
+
opencodeBaseDir: string;
|
|
8
|
+
vvocBaseDir: string;
|
|
9
|
+
vvocConfigPath: string;
|
|
10
|
+
managedAgentsDirPath: string;
|
|
11
|
+
managedSkillsDirPath: string;
|
|
12
|
+
opencodeConfigPath: string;
|
|
13
|
+
opencodeAlternatePaths: string[];
|
|
14
|
+
opencodeTuiConfigPath: string;
|
|
15
|
+
opencodeTuiAlternatePaths: string[];
|
|
16
|
+
};
|
|
17
|
+
export declare function resolvePaths(options: {
|
|
18
|
+
scope: Scope;
|
|
19
|
+
cwd: string;
|
|
20
|
+
configDir?: string;
|
|
21
|
+
}): Promise<ResolvedPaths>;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// FILE: src/lib/opencode/paths.ts
|
|
2
|
+
// VERSION: 1.0.0
|
|
3
|
+
// START_MODULE_CONTRACT
|
|
4
|
+
// PURPOSE: Scope-aware path resolution for OpenCode runtime/TUI and vvoc config locations.
|
|
5
|
+
// SCOPE: Global/project write-target resolution, managed agents/skills directory derivation, alternate config file discovery for opencode.json(c) and tui.json(c), and the Scope/ResolvedPaths contract shared by every config-mutating zone.
|
|
6
|
+
// DEPENDS: [node:path, src/lib/config-layers.ts, src/lib/vvoc-paths.ts, src/lib/opencode/shared-utils.ts]
|
|
7
|
+
// LINKS: [M-CLI-CONFIG, M-CONFIG-LAYERS]
|
|
8
|
+
// ROLE: RUNTIME
|
|
9
|
+
// MAP_MODE: EXPORTS
|
|
10
|
+
// END_MODULE_CONTRACT
|
|
11
|
+
//
|
|
12
|
+
// START_MODULE_MAP
|
|
13
|
+
// Scope - Supported installation scopes for vvoc config writes.
|
|
14
|
+
// ResolvedPaths - Scope-aware path bundle for OpenCode runtime/TUI and vvoc config locations.
|
|
15
|
+
// resolvePaths - Resolves OpenCode runtime/TUI and vvoc config paths for global/project scopes.
|
|
16
|
+
// END_MODULE_MAP
|
|
17
|
+
//
|
|
18
|
+
// START_CHANGE_SUMMARY
|
|
19
|
+
// LAST_CHANGE: [C-OPENCODE-MODULE-SPLIT - Extracted path resolution and alternate-config discovery from the former src/lib/opencode.ts monolith into this zone module.]
|
|
20
|
+
// END_CHANGE_SUMMARY
|
|
21
|
+
import { join } from "node:path";
|
|
22
|
+
import { resolveConfigWriteTargets } from "../config-layers.js";
|
|
23
|
+
import { getConfigHome, getVvocAgentsDir, getVvocSkillsDir } from "../vvoc-paths.js";
|
|
24
|
+
import { readOptionalText } from "./shared-utils.js";
|
|
25
|
+
const OPENCODE_CONFIG_FILE_NAMES = ["opencode.json", "opencode.jsonc"];
|
|
26
|
+
const OPENCODE_TUI_CONFIG_FILE_NAMES = ["tui.json", "tui.jsonc"];
|
|
27
|
+
// START_BLOCK_RESOLVE_CONFIG_PATHS
|
|
28
|
+
export async function resolvePaths(options) {
|
|
29
|
+
const targets = await resolveConfigWriteTargets(options);
|
|
30
|
+
const configHome = getConfigHome(options.configDir);
|
|
31
|
+
const managedAgentsDirPath = getVvocAgentsDir(targets.vvocBaseDir);
|
|
32
|
+
const managedSkillsDirPath = getVvocSkillsDir(targets.vvocBaseDir);
|
|
33
|
+
return {
|
|
34
|
+
scope: options.scope,
|
|
35
|
+
cwd: options.cwd,
|
|
36
|
+
configHome,
|
|
37
|
+
projectRoot: targets.projectRoot,
|
|
38
|
+
opencodeBaseDir: targets.opencodeBaseDir,
|
|
39
|
+
vvocBaseDir: targets.vvocBaseDir,
|
|
40
|
+
vvocConfigPath: targets.vvocConfigPath,
|
|
41
|
+
managedAgentsDirPath,
|
|
42
|
+
managedSkillsDirPath,
|
|
43
|
+
opencodeConfigPath: targets.opencodeConfigPath,
|
|
44
|
+
opencodeAlternatePaths: await resolveOpenCodeAlternates(targets.opencodeBaseDir, targets.opencodeConfigPath),
|
|
45
|
+
opencodeTuiConfigPath: targets.opencodeTuiConfigPath,
|
|
46
|
+
opencodeTuiAlternatePaths: await resolveConfigAlternates(targets.opencodeBaseDir, targets.opencodeTuiConfigPath, OPENCODE_TUI_CONFIG_FILE_NAMES),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
async function resolveOpenCodeAlternates(opencodeBaseDir, selectedPath) {
|
|
50
|
+
return resolveConfigAlternates(opencodeBaseDir, selectedPath, OPENCODE_CONFIG_FILE_NAMES);
|
|
51
|
+
}
|
|
52
|
+
async function resolveConfigAlternates(baseDir, selectedPath, fileNames) {
|
|
53
|
+
const alternates = [];
|
|
54
|
+
for (const candidate of fileNames.map((name) => join(baseDir, name))) {
|
|
55
|
+
if (candidate !== selectedPath && (await readOptionalText(candidate)) !== undefined) {
|
|
56
|
+
alternates.push(candidate);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return alternates;
|
|
60
|
+
}
|
|
61
|
+
// END_BLOCK_RESOLVE_CONFIG_PATHS
|
|
62
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../src/lib/opencode/paths.ts"],"names":[],"mappings":"AAAA,kCAAkC;AAClC,iBAAiB;AACjB,wBAAwB;AACxB,6FAA6F;AAC7F,gPAAgP;AAChP,4GAA4G;AAC5G,2CAA2C;AAC3C,kBAAkB;AAClB,sBAAsB;AACtB,sBAAsB;AACtB,EAAE;AACF,mBAAmB;AACnB,kEAAkE;AAClE,gGAAgG;AAChG,kGAAkG;AAClG,iBAAiB;AACjB,EAAE;AACF,uBAAuB;AACvB,0KAA0K;AAC1K,qBAAqB;AAErB,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACrF,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,0BAA0B,GAAG,CAAC,eAAe,EAAE,gBAAgB,CAAU,CAAC;AAChF,MAAM,8BAA8B,GAAG,CAAC,UAAU,EAAE,WAAW,CAAU,CAAC;AAoB1E,mCAAmC;AACnC,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAIlC;IACC,MAAM,OAAO,GAAG,MAAM,yBAAyB,CAAC,OAAO,CAAC,CAAC;IACzD,MAAM,UAAU,GAAG,aAAa,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACpD,MAAM,oBAAoB,GAAG,gBAAgB,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACnE,MAAM,oBAAoB,GAAG,gBAAgB,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAEnE,OAAO;QACL,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,UAAU;QACV,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,eAAe,EAAE,OAAO,CAAC,eAAe;QACxC,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,cAAc,EAAE,OAAO,CAAC,cAAc;QACtC,oBAAoB;QACpB,oBAAoB;QACpB,kBAAkB,EAAE,OAAO,CAAC,kBAAkB;QAC9C,sBAAsB,EAAE,MAAM,yBAAyB,CACrD,OAAO,CAAC,eAAe,EACvB,OAAO,CAAC,kBAAkB,CAC3B;QACD,qBAAqB,EAAE,OAAO,CAAC,qBAAqB;QACpD,yBAAyB,EAAE,MAAM,uBAAuB,CACtD,OAAO,CAAC,eAAe,EACvB,OAAO,CAAC,qBAAqB,EAC7B,8BAA8B,CAC/B;KACF,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,yBAAyB,CACtC,eAAuB,EACvB,YAAoB;IAEpB,OAAO,uBAAuB,CAAC,eAAe,EAAE,YAAY,EAAE,0BAA0B,CAAC,CAAC;AAC5F,CAAC;AAED,KAAK,UAAU,uBAAuB,CACpC,OAAe,EACf,YAAoB,EACpB,SAA4B;IAE5B,MAAM,UAAU,GAAa,EAAE,CAAC;IAEhC,KAAK,MAAM,SAAS,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC;QACrE,IAAI,SAAS,KAAK,YAAY,IAAI,CAAC,MAAM,gBAAgB,CAAC,SAAS,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;YACpF,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AACD,iCAAiC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type JsonObject, type WriteResult } from "./shared-utils.js";
|
|
2
|
+
import type { ResolvedPaths } from "./paths.js";
|
|
3
|
+
export declare const TUI_PACKAGE_SPECIFIER: string;
|
|
4
|
+
export declare const MINIMUM_TUI_OPENCODE_VERSION = "1.18.2";
|
|
5
|
+
export type TuiPluginEntry = string | [string, JsonObject];
|
|
6
|
+
export declare function ensurePackageConfigText(text: string | undefined, packageSpecifier?: string): string;
|
|
7
|
+
export declare function ensureTuiPackageConfigText(text: string | undefined, packageSpecifier?: string): string;
|
|
8
|
+
export declare function ensureTuiPackageInstalled(paths: Pick<ResolvedPaths, "opencodeTuiConfigPath">): Promise<WriteResult>;
|
|
9
|
+
export declare function ensurePackageInstalled(paths: ResolvedPaths): Promise<{
|
|
10
|
+
path: string;
|
|
11
|
+
changed: boolean;
|
|
12
|
+
}>;
|
|
13
|
+
export declare function readPluginList(document: JsonObject, label: string): string[];
|
|
14
|
+
export declare function readTuiPluginList(document: JsonObject, label: string): TuiPluginEntry[];
|
|
15
|
+
export declare function isPackagePluginSpecifier(value: string): boolean;
|
|
16
|
+
export declare function readTuiPluginName(entry: TuiPluginEntry): string;
|
|
17
|
+
export declare function isTuiPackageSpecifier(value: string): boolean;
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
// FILE: src/lib/opencode/plugin-registration.ts
|
|
2
|
+
// VERSION: 1.0.0
|
|
3
|
+
// START_MODULE_CONTRACT
|
|
4
|
+
// PURPOSE: Conservative pinned runtime and TUI plugin registration for OpenCode config.
|
|
5
|
+
// SCOPE: Pinned base-package specifier constants, plugin-list parsing and normalization with legacy /tui spec migration and tuple-option preservation, and idempotent writes of the pinned vvoc plugin into opencode.json(c) and the pinned base package into tui.json(c).
|
|
6
|
+
// DEPENDS: [jsonc-parser, src/lib/package.ts, src/lib/opencode/shared-utils.ts]
|
|
7
|
+
// LINKS: [M-CLI-CONFIG]
|
|
8
|
+
// ROLE: RUNTIME
|
|
9
|
+
// MAP_MODE: EXPORTS
|
|
10
|
+
// END_MODULE_CONTRACT
|
|
11
|
+
//
|
|
12
|
+
// START_MODULE_MAP
|
|
13
|
+
// TUI_PACKAGE_SPECIFIER - Pinned base package specifier registered in tui.json(c) so OpenCode selects its ./tui export.
|
|
14
|
+
// MINIMUM_TUI_OPENCODE_VERSION - Minimum OpenCode host version supported by the managed TUI plugin.
|
|
15
|
+
// TuiPluginEntry - Supported TUI plugin string or tuple entry.
|
|
16
|
+
// ensurePackageConfigText - Ensures OpenCode config contains the pinned vvoc plugin specifier.
|
|
17
|
+
// ensureTuiPackageConfigText - Ensures TUI config contains the pinned vvoc base package while preserving tuple options.
|
|
18
|
+
// ensureTuiPackageInstalled - Writes the pinned vvoc base package into dedicated tui.json(c).
|
|
19
|
+
// ensurePackageInstalled - Writes the pinned vvoc plugin specifier into OpenCode config.
|
|
20
|
+
// readPluginList - Reads the runtime plugin array from a parsed OpenCode config.
|
|
21
|
+
// readTuiPluginList - Reads the TUI plugin array accepting string and tuple entries.
|
|
22
|
+
// isPackagePluginSpecifier - True when a plugin entry is the vvoc base package.
|
|
23
|
+
// isTuiPackageSpecifier - True when a TUI entry equals the pinned base package specifier.
|
|
24
|
+
// readTuiPluginName - Extracts the name from a TUI plugin entry.
|
|
25
|
+
// END_MODULE_MAP
|
|
26
|
+
//
|
|
27
|
+
// START_CHANGE_SUMMARY
|
|
28
|
+
// LAST_CHANGE: [C-OPENCODE-MODULE-SPLIT - Extracted runtime/TUI plugin pinning and plugin-list normalization from the former src/lib/opencode.ts monolith into this zone module.]
|
|
29
|
+
// END_CHANGE_SUMMARY
|
|
30
|
+
import { applyEdits, format, modify } from "jsonc-parser";
|
|
31
|
+
import { getPinnedPackageSpecifier, PACKAGE_NAME, PACKAGE_VERSION } from "../package.js";
|
|
32
|
+
import { ensureTrailingNewline, isJsonObject, OPENCODE_SCHEMA_URL, OPENCODE_TUI_SCHEMA_URL, parseObjectDocument, readOptionalText, renderJson, writeText, } from "./shared-utils.js";
|
|
33
|
+
export const TUI_PACKAGE_SPECIFIER = `${PACKAGE_NAME}@${PACKAGE_VERSION}`;
|
|
34
|
+
export const MINIMUM_TUI_OPENCODE_VERSION = "1.18.2";
|
|
35
|
+
const JSON_FORMAT = {
|
|
36
|
+
insertSpaces: true,
|
|
37
|
+
tabSize: 2,
|
|
38
|
+
eol: "\n",
|
|
39
|
+
};
|
|
40
|
+
// START_BLOCK_ENSURE_OPENCODE_PLUGIN_CONFIG
|
|
41
|
+
export function ensurePackageConfigText(text, packageSpecifier = PACKAGE_NAME) {
|
|
42
|
+
if (!text?.trim()) {
|
|
43
|
+
return renderJson({
|
|
44
|
+
$schema: OPENCODE_SCHEMA_URL,
|
|
45
|
+
plugin: [packageSpecifier],
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
const document = parseObjectDocument(text, "OpenCode config");
|
|
49
|
+
const currentPlugins = readPluginList(document, "OpenCode config");
|
|
50
|
+
let nextText = text;
|
|
51
|
+
if (!Object.hasOwn(document, "$schema")) {
|
|
52
|
+
nextText = applyEdits(nextText, modify(nextText, ["$schema"], OPENCODE_SCHEMA_URL, {
|
|
53
|
+
formattingOptions: JSON_FORMAT,
|
|
54
|
+
getInsertionIndex: () => 0,
|
|
55
|
+
}));
|
|
56
|
+
}
|
|
57
|
+
const nextPlugins = normalizePluginList(currentPlugins, packageSpecifier);
|
|
58
|
+
if (JSON.stringify(nextPlugins) !== JSON.stringify(currentPlugins)) {
|
|
59
|
+
nextText = applyEdits(nextText, modify(nextText, ["plugin"], nextPlugins, {
|
|
60
|
+
formattingOptions: JSON_FORMAT,
|
|
61
|
+
}));
|
|
62
|
+
}
|
|
63
|
+
return ensureTrailingNewline(applyEdits(nextText, format(nextText, undefined, JSON_FORMAT)));
|
|
64
|
+
}
|
|
65
|
+
// END_BLOCK_ENSURE_OPENCODE_PLUGIN_CONFIG
|
|
66
|
+
// START_BLOCK_ENSURE_TUI_PLUGIN_CONFIG
|
|
67
|
+
export function ensureTuiPackageConfigText(text, packageSpecifier = TUI_PACKAGE_SPECIFIER) {
|
|
68
|
+
if (!text?.trim()) {
|
|
69
|
+
return renderJson({
|
|
70
|
+
$schema: OPENCODE_TUI_SCHEMA_URL,
|
|
71
|
+
plugin: [packageSpecifier],
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
const document = parseObjectDocument(text, "OpenCode TUI config");
|
|
75
|
+
const currentPlugins = readTuiPluginList(document, "OpenCode TUI config");
|
|
76
|
+
let nextText = text;
|
|
77
|
+
if (!Object.hasOwn(document, "$schema")) {
|
|
78
|
+
nextText = applyEdits(nextText, modify(nextText, ["$schema"], OPENCODE_TUI_SCHEMA_URL, {
|
|
79
|
+
formattingOptions: JSON_FORMAT,
|
|
80
|
+
getInsertionIndex: () => 0,
|
|
81
|
+
}));
|
|
82
|
+
}
|
|
83
|
+
const nextPlugins = normalizeTuiPluginList(currentPlugins, packageSpecifier);
|
|
84
|
+
if (JSON.stringify(nextPlugins) !== JSON.stringify(currentPlugins)) {
|
|
85
|
+
nextText = applyEdits(nextText, modify(nextText, ["plugin"], nextPlugins, {
|
|
86
|
+
formattingOptions: JSON_FORMAT,
|
|
87
|
+
}));
|
|
88
|
+
}
|
|
89
|
+
return ensureTrailingNewline(applyEdits(nextText, format(nextText, undefined, JSON_FORMAT)));
|
|
90
|
+
}
|
|
91
|
+
export async function ensureTuiPackageInstalled(paths) {
|
|
92
|
+
const currentText = await readOptionalText(paths.opencodeTuiConfigPath);
|
|
93
|
+
const nextText = ensureTuiPackageConfigText(currentText);
|
|
94
|
+
if ((currentText ?? "") === nextText) {
|
|
95
|
+
return { action: "kept", path: paths.opencodeTuiConfigPath };
|
|
96
|
+
}
|
|
97
|
+
await writeText(paths.opencodeTuiConfigPath, nextText);
|
|
98
|
+
return {
|
|
99
|
+
action: currentText ? "updated" : "created",
|
|
100
|
+
path: paths.opencodeTuiConfigPath,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
// END_BLOCK_ENSURE_TUI_PLUGIN_CONFIG
|
|
104
|
+
// START_BLOCK_INSTALL_PACKAGE_AND_GUARDIAN_CONFIG
|
|
105
|
+
export async function ensurePackageInstalled(paths) {
|
|
106
|
+
const currentText = await readOptionalText(paths.opencodeConfigPath);
|
|
107
|
+
const nextText = ensurePackageConfigText(currentText, await getPinnedPackageSpecifier());
|
|
108
|
+
if (currentText === nextText) {
|
|
109
|
+
return { path: paths.opencodeConfigPath, changed: false };
|
|
110
|
+
}
|
|
111
|
+
await writeText(paths.opencodeConfigPath, nextText);
|
|
112
|
+
return { path: paths.opencodeConfigPath, changed: true };
|
|
113
|
+
}
|
|
114
|
+
// END_BLOCK_INSTALL_PACKAGE_AND_GUARDIAN_CONFIG
|
|
115
|
+
// START_BLOCK_PARSE_AND_NORMALIZE_CONFIG_VALUES
|
|
116
|
+
export function readPluginList(document, label) {
|
|
117
|
+
const raw = document.plugin;
|
|
118
|
+
if (raw === undefined)
|
|
119
|
+
return [];
|
|
120
|
+
if (!Array.isArray(raw) || raw.some((entry) => typeof entry !== "string")) {
|
|
121
|
+
throw new Error(`${label}: expected "plugin" to be an array of strings`);
|
|
122
|
+
}
|
|
123
|
+
return raw.slice();
|
|
124
|
+
}
|
|
125
|
+
export function readTuiPluginList(document, label) {
|
|
126
|
+
const raw = document.plugin;
|
|
127
|
+
if (raw === undefined)
|
|
128
|
+
return [];
|
|
129
|
+
if (!Array.isArray(raw)) {
|
|
130
|
+
throw new Error(`${label}: expected "plugin" to be an array`);
|
|
131
|
+
}
|
|
132
|
+
return raw.map((entry, index) => {
|
|
133
|
+
if (typeof entry === "string") {
|
|
134
|
+
return entry;
|
|
135
|
+
}
|
|
136
|
+
if (Array.isArray(entry) &&
|
|
137
|
+
entry.length === 2 &&
|
|
138
|
+
typeof entry[0] === "string" &&
|
|
139
|
+
isJsonObject(entry[1])) {
|
|
140
|
+
return [entry[0], entry[1]];
|
|
141
|
+
}
|
|
142
|
+
throw new Error(`${label}: expected "plugin[${index}]" to be a string or [string, options] tuple`);
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
function normalizePluginList(currentPlugins, packageSpecifier) {
|
|
146
|
+
const nextPlugins = [];
|
|
147
|
+
const seen = new Set();
|
|
148
|
+
let insertedPackage = false;
|
|
149
|
+
const push = (value) => {
|
|
150
|
+
if (!seen.has(value)) {
|
|
151
|
+
seen.add(value);
|
|
152
|
+
nextPlugins.push(value);
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
for (const plugin of currentPlugins) {
|
|
156
|
+
if (isPackagePluginSpecifier(plugin)) {
|
|
157
|
+
if (!insertedPackage) {
|
|
158
|
+
push(packageSpecifier);
|
|
159
|
+
insertedPackage = true;
|
|
160
|
+
}
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
push(plugin);
|
|
164
|
+
}
|
|
165
|
+
if (!insertedPackage) {
|
|
166
|
+
push(packageSpecifier);
|
|
167
|
+
}
|
|
168
|
+
return nextPlugins;
|
|
169
|
+
}
|
|
170
|
+
function normalizeTuiPluginList(currentPlugins, packageSpecifier) {
|
|
171
|
+
const nextPlugins = [];
|
|
172
|
+
let insertedPackage = false;
|
|
173
|
+
for (const entry of currentPlugins) {
|
|
174
|
+
if (!isManagedTuiPackageSpecifier(readTuiPluginName(entry))) {
|
|
175
|
+
nextPlugins.push(entry);
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
if (insertedPackage) {
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
nextPlugins.push(typeof entry === "string" ? packageSpecifier : [packageSpecifier, entry[1]]);
|
|
182
|
+
insertedPackage = true;
|
|
183
|
+
}
|
|
184
|
+
if (!insertedPackage) {
|
|
185
|
+
nextPlugins.push(packageSpecifier);
|
|
186
|
+
}
|
|
187
|
+
return nextPlugins;
|
|
188
|
+
}
|
|
189
|
+
export function isPackagePluginSpecifier(value) {
|
|
190
|
+
return value === PACKAGE_NAME || value.startsWith(`${PACKAGE_NAME}@`);
|
|
191
|
+
}
|
|
192
|
+
export function readTuiPluginName(entry) {
|
|
193
|
+
return typeof entry === "string" ? entry : entry[0];
|
|
194
|
+
}
|
|
195
|
+
function isManagedTuiPackageSpecifier(value) {
|
|
196
|
+
return (isBasePackageSpecifier(value) ||
|
|
197
|
+
value === `${PACKAGE_NAME}/tui` ||
|
|
198
|
+
(value.startsWith(`${PACKAGE_NAME}@`) && value.endsWith("/tui")));
|
|
199
|
+
}
|
|
200
|
+
export function isTuiPackageSpecifier(value) {
|
|
201
|
+
return value === TUI_PACKAGE_SPECIFIER;
|
|
202
|
+
}
|
|
203
|
+
function isBasePackageSpecifier(value) {
|
|
204
|
+
if (value === PACKAGE_NAME)
|
|
205
|
+
return true;
|
|
206
|
+
const prefix = `${PACKAGE_NAME}@`;
|
|
207
|
+
return value.startsWith(prefix) && !value.slice(prefix.length).includes("/");
|
|
208
|
+
}
|
|
209
|
+
// END_BLOCK_PARSE_AND_NORMALIZE_CONFIG_VALUES
|
|
210
|
+
//# sourceMappingURL=plugin-registration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-registration.js","sourceRoot":"","sources":["../../../src/lib/opencode/plugin-registration.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type VvocConfig } from "../vvoc-config.js";
|
|
2
|
+
export declare const CLI_NAME = "vvoc";
|
|
3
|
+
export declare const OPENCODE_SCHEMA_URL = "https://opencode.ai/config.json";
|
|
4
|
+
export declare const OPENCODE_TUI_SCHEMA_URL = "https://opencode.ai/tui.json";
|
|
5
|
+
export type JsonObject = Record<string, unknown>;
|
|
6
|
+
export type WriteResult = {
|
|
7
|
+
action: "created" | "updated" | "kept" | "skipped";
|
|
8
|
+
path: string;
|
|
9
|
+
reason?: string;
|
|
10
|
+
};
|
|
11
|
+
export type OpenCodeAgentOverride = {
|
|
12
|
+
model?: string;
|
|
13
|
+
};
|
|
14
|
+
export declare function parseObjectDocument(text: string, label: string): JsonObject;
|
|
15
|
+
export declare function readStringArray(value: unknown, label: string): string[];
|
|
16
|
+
export declare function updateAgentEntryText(text: string, agentName: string, entry: JsonObject): string;
|
|
17
|
+
export declare function ensureOpenCodeConfigText(text: string | undefined): string;
|
|
18
|
+
export declare function readNonEmptyString(value: unknown, label: string): string;
|
|
19
|
+
export declare function isJsonObject(value: unknown): value is JsonObject;
|
|
20
|
+
export declare function mergeJsonObjects(current: JsonObject, patch: JsonObject): JsonObject;
|
|
21
|
+
export declare function readOptionalObject(document: JsonObject, key: string, label: string): JsonObject | undefined;
|
|
22
|
+
export declare function readAgentOverride(entry: JsonObject | undefined, label: string): OpenCodeAgentOverride;
|
|
23
|
+
export declare function isManagedFile(text: string): boolean;
|
|
24
|
+
export declare function hasYamlFrontmatter(text: string): boolean;
|
|
25
|
+
export declare function renderJson(value: unknown): string;
|
|
26
|
+
export declare function stripMarkdownFrontmatter(text: string): string;
|
|
27
|
+
export declare function ensureTrailingNewline(text: string): string;
|
|
28
|
+
export declare function writeResolvedVvocConfig(path: string, currentText: string | undefined, config: VvocConfig): Promise<WriteResult>;
|
|
29
|
+
export declare function readOptionalText(path: string): Promise<string | undefined>;
|
|
30
|
+
export declare function writeText(path: string, text: string): Promise<void>;
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
// FILE: src/lib/opencode/shared-utils.ts
|
|
2
|
+
// VERSION: 1.0.0
|
|
3
|
+
// START_MODULE_CONTRACT
|
|
4
|
+
// PURPOSE: Private shared JSONC document, value, text, and filesystem helpers plus cross-zone constants used by every src/lib/opencode zone module.
|
|
5
|
+
// SCOPE: JSONC parse/edit primitives with strict object validation, bounded string/array readers, shared role-agnostic agent value readers, managed-file markers, canonical JSON rendering, strict vvoc render-and-write, atomic-ish text IO, write-result shape, and the OpenCode schema URL constants consumed by config-producing zones.
|
|
6
|
+
// DEPENDS: [jsonc-parser, node:fs/promises, node:path, src/lib/vvoc-config.ts]
|
|
7
|
+
// LINKS: [M-CLI-CONFIG]
|
|
8
|
+
// ROLE: RUNTIME
|
|
9
|
+
// MAP_MODE: EXPORTS
|
|
10
|
+
// END_MODULE_CONTRACT
|
|
11
|
+
//
|
|
12
|
+
// START_MODULE_MAP
|
|
13
|
+
// CLI_NAME - Canonical vvoc CLI binary name.
|
|
14
|
+
// OPENCODE_SCHEMA_URL - OpenCode config schema URL.
|
|
15
|
+
// OPENCODE_TUI_SCHEMA_URL - OpenCode TUI config schema URL.
|
|
16
|
+
// JsonObject - Internal mutable JSON object shape.
|
|
17
|
+
// WriteResult - Result shape returned by managed config write operations.
|
|
18
|
+
// OpenCodeAgentOverride - Agent override config for OpenCode.
|
|
19
|
+
// parseObjectDocument - Strict JSONC parse returning a top-level object or throwing a labeled error.
|
|
20
|
+
// readStringArray - Reads a required string array with a labeled error.
|
|
21
|
+
// updateAgentEntryText - Rewrites one agent.<name> object with formatting.
|
|
22
|
+
// ensureOpenCodeConfigText - Ensures an OpenCode config document with $schema exists.
|
|
23
|
+
// readNonEmptyString - Reads a required non-empty trimmed string with a labeled error.
|
|
24
|
+
// isJsonObject - Narrows an unknown value to JsonObject.
|
|
25
|
+
// mergeJsonObjects - Deep-merges a patch object into a current object.
|
|
26
|
+
// readOptionalObject - Reads an optional object field with a labeled error.
|
|
27
|
+
// readAgentOverride - Reads the model override from one agent entry.
|
|
28
|
+
// isManagedFile - True when text carries the vvoc managed marker.
|
|
29
|
+
// hasYamlFrontmatter - True when text starts with a YAML frontmatter block.
|
|
30
|
+
// renderJson - Renders a value as canonical two-space JSON with trailing newline.
|
|
31
|
+
// stripMarkdownFrontmatter - Removes a leading YAML frontmatter block.
|
|
32
|
+
// ensureTrailingNewline - Appends a trailing newline when missing.
|
|
33
|
+
// writeResolvedVvocConfig - Renders and writes a vvoc config only when text changed.
|
|
34
|
+
// readOptionalText - Reads a file as text, returning undefined on ENOENT.
|
|
35
|
+
// writeText - Writes text, creating parent directories.
|
|
36
|
+
// END_MODULE_MAP
|
|
37
|
+
//
|
|
38
|
+
// START_CHANGE_SUMMARY
|
|
39
|
+
// LAST_CHANGE: [C-OPENCODE-MODULE-SPLIT - Extracted the shared JSON/value/text/filesystem helper block and cross-zone constants from the former src/lib/opencode.ts monolith into this zone module.]
|
|
40
|
+
// END_CHANGE_SUMMARY
|
|
41
|
+
import { applyEdits, format, modify, parse } from "jsonc-parser";
|
|
42
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
43
|
+
import { dirname } from "node:path";
|
|
44
|
+
import { renderVvocConfig } from "../vvoc-config.js";
|
|
45
|
+
export const CLI_NAME = "vvoc";
|
|
46
|
+
export const OPENCODE_SCHEMA_URL = "https://opencode.ai/config.json";
|
|
47
|
+
export const OPENCODE_TUI_SCHEMA_URL = "https://opencode.ai/tui.json";
|
|
48
|
+
const MANAGED_MARKER = "Managed by vvoc";
|
|
49
|
+
const JSON_FORMAT = {
|
|
50
|
+
insertSpaces: true,
|
|
51
|
+
tabSize: 2,
|
|
52
|
+
eol: "\n",
|
|
53
|
+
};
|
|
54
|
+
// START_BLOCK_SHARED_DOCUMENT_UTILS
|
|
55
|
+
export function parseObjectDocument(text, label) {
|
|
56
|
+
const errors = [];
|
|
57
|
+
const value = parse(text, errors, {
|
|
58
|
+
allowEmptyContent: false,
|
|
59
|
+
allowTrailingComma: true,
|
|
60
|
+
disallowComments: false,
|
|
61
|
+
});
|
|
62
|
+
if (errors.length > 0) {
|
|
63
|
+
throw new Error(`${label}: failed to parse JSONC (${errors.length} error(s))`);
|
|
64
|
+
}
|
|
65
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
66
|
+
throw new Error(`${label}: expected a top-level object`);
|
|
67
|
+
}
|
|
68
|
+
return value;
|
|
69
|
+
}
|
|
70
|
+
export function readStringArray(value, label) {
|
|
71
|
+
if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string")) {
|
|
72
|
+
throw new Error(`${label}: expected an array of strings`);
|
|
73
|
+
}
|
|
74
|
+
return value.slice();
|
|
75
|
+
}
|
|
76
|
+
export function updateAgentEntryText(text, agentName, entry) {
|
|
77
|
+
const nextText = applyEdits(text, modify(text, ["agent", agentName], entry, {
|
|
78
|
+
formattingOptions: JSON_FORMAT,
|
|
79
|
+
}));
|
|
80
|
+
return ensureTrailingNewline(applyEdits(nextText, format(nextText, undefined, JSON_FORMAT)));
|
|
81
|
+
}
|
|
82
|
+
export function ensureOpenCodeConfigText(text) {
|
|
83
|
+
if (!text?.trim()) {
|
|
84
|
+
return renderJson({
|
|
85
|
+
$schema: OPENCODE_SCHEMA_URL,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
const document = parseObjectDocument(text, "OpenCode config");
|
|
89
|
+
let nextText = text;
|
|
90
|
+
if (!Object.hasOwn(document, "$schema")) {
|
|
91
|
+
nextText = applyEdits(nextText, modify(nextText, ["$schema"], OPENCODE_SCHEMA_URL, {
|
|
92
|
+
formattingOptions: JSON_FORMAT,
|
|
93
|
+
getInsertionIndex: () => 0,
|
|
94
|
+
}));
|
|
95
|
+
}
|
|
96
|
+
return ensureTrailingNewline(applyEdits(nextText, format(nextText, undefined, JSON_FORMAT)));
|
|
97
|
+
}
|
|
98
|
+
// END_BLOCK_SHARED_DOCUMENT_UTILS
|
|
99
|
+
// START_BLOCK_JSON_VALUE_HELPERS
|
|
100
|
+
export function readNonEmptyString(value, label) {
|
|
101
|
+
if (typeof value !== "string" || !value.trim()) {
|
|
102
|
+
throw new Error(`${label}: expected a non-empty string`);
|
|
103
|
+
}
|
|
104
|
+
return value.trim();
|
|
105
|
+
}
|
|
106
|
+
export function isJsonObject(value) {
|
|
107
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
108
|
+
}
|
|
109
|
+
export function mergeJsonObjects(current, patch) {
|
|
110
|
+
const merged = { ...current };
|
|
111
|
+
for (const [key, patchValue] of Object.entries(patch)) {
|
|
112
|
+
const currentValue = merged[key];
|
|
113
|
+
merged[key] =
|
|
114
|
+
isJsonObject(currentValue) && isJsonObject(patchValue)
|
|
115
|
+
? mergeJsonObjects(currentValue, patchValue)
|
|
116
|
+
: patchValue;
|
|
117
|
+
}
|
|
118
|
+
return merged;
|
|
119
|
+
}
|
|
120
|
+
export function readOptionalObject(document, key, label) {
|
|
121
|
+
const value = document[key];
|
|
122
|
+
if (value === undefined) {
|
|
123
|
+
return undefined;
|
|
124
|
+
}
|
|
125
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
126
|
+
throw new Error(`${label}: expected "${key}" to be an object`);
|
|
127
|
+
}
|
|
128
|
+
return value;
|
|
129
|
+
}
|
|
130
|
+
export function readAgentOverride(entry, label) {
|
|
131
|
+
if (!entry) {
|
|
132
|
+
return {};
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
model: entry.model === undefined ? undefined : readNonEmptyString(entry.model, `${label}.model`),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
// END_BLOCK_JSON_VALUE_HELPERS
|
|
139
|
+
// START_BLOCK_FILESYSTEM_HELPERS
|
|
140
|
+
export function isManagedFile(text) {
|
|
141
|
+
return text.includes(MANAGED_MARKER);
|
|
142
|
+
}
|
|
143
|
+
export function hasYamlFrontmatter(text) {
|
|
144
|
+
return text.startsWith("---\n");
|
|
145
|
+
}
|
|
146
|
+
export function renderJson(value) {
|
|
147
|
+
return `${JSON.stringify(value, null, 2)}\n`;
|
|
148
|
+
}
|
|
149
|
+
export function stripMarkdownFrontmatter(text) {
|
|
150
|
+
const normalized = text.replaceAll("\r\n", "\n");
|
|
151
|
+
return normalized.replace(/^---\n[\s\S]*?\n---\n?/, "");
|
|
152
|
+
}
|
|
153
|
+
export function ensureTrailingNewline(text) {
|
|
154
|
+
return text.endsWith("\n") ? text : `${text}\n`;
|
|
155
|
+
}
|
|
156
|
+
export async function writeResolvedVvocConfig(path, currentText, config) {
|
|
157
|
+
const nextText = renderVvocConfig(config);
|
|
158
|
+
if ((currentText ?? "") === nextText) {
|
|
159
|
+
return { action: "kept", path };
|
|
160
|
+
}
|
|
161
|
+
await writeText(path, nextText);
|
|
162
|
+
return {
|
|
163
|
+
action: currentText ? "updated" : "created",
|
|
164
|
+
path,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
export async function readOptionalText(path) {
|
|
168
|
+
try {
|
|
169
|
+
return await readFile(path, "utf8");
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
if (error.code === "ENOENT") {
|
|
173
|
+
return undefined;
|
|
174
|
+
}
|
|
175
|
+
throw error;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
export async function writeText(path, text) {
|
|
179
|
+
await mkdir(dirname(path), { recursive: true });
|
|
180
|
+
await writeFile(path, text, "utf8");
|
|
181
|
+
}
|
|
182
|
+
// END_BLOCK_FILESYSTEM_HELPERS
|
|
183
|
+
//# sourceMappingURL=shared-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared-utils.js","sourceRoot":"","sources":["../../../src/lib/opencode/shared-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type GuardianConfigOverrides, type VvocConfig } from "../vvoc-config.js";
|
|
2
|
+
import { type WriteResult } from "./shared-utils.js";
|
|
3
|
+
import type { ResolvedPaths } from "./paths.js";
|
|
4
|
+
export declare function readVvocConfig(paths: Pick<ResolvedPaths, "vvocConfigPath">): Promise<VvocConfig | undefined>;
|
|
5
|
+
export declare function installVvocConfig(paths: Pick<ResolvedPaths, "vvocConfigPath">): Promise<WriteResult>;
|
|
6
|
+
export declare function syncVvocConfig(paths: Pick<ResolvedPaths, "vvocConfigPath">): Promise<WriteResult>;
|
|
7
|
+
export declare function writeGuardianConfig(paths: Pick<ResolvedPaths, "vvocConfigPath">, overrides: GuardianConfigOverrides, options?: {
|
|
8
|
+
merge?: boolean;
|
|
9
|
+
}): Promise<WriteResult>;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// FILE: src/lib/opencode/vvoc-config-io.ts
|
|
2
|
+
// VERSION: 1.0.0
|
|
3
|
+
// START_MODULE_CONTRACT
|
|
4
|
+
// PURPOSE: Strict scoped IO for the canonical vvoc.json config document.
|
|
5
|
+
// SCOPE: Read the canonical vvoc.json when present, create/refresh it with materialized plugin-owned entries (hashline-edit routing, tool-history-compaction, peak-hours, spec-guard), rewrite it preserving valid current values, and merge or replace the guardian section.
|
|
6
|
+
// DEPENDS: [src/lib/vvoc-config.ts, src/lib/plugin-toggle-config.ts, src/lib/opencode/shared-utils.ts, src/lib/opencode/paths.ts]
|
|
7
|
+
// LINKS: [M-CLI-CONFIG]
|
|
8
|
+
// ROLE: RUNTIME
|
|
9
|
+
// MAP_MODE: EXPORTS
|
|
10
|
+
// END_MODULE_CONTRACT
|
|
11
|
+
//
|
|
12
|
+
// START_MODULE_MAP
|
|
13
|
+
// readVvocConfig - Loads the canonical vvoc.json document when present.
|
|
14
|
+
// installVvocConfig - Creates or refreshes the canonical vvoc.json document.
|
|
15
|
+
// syncVvocConfig - Rewrites the canonical vvoc.json document while preserving valid current values.
|
|
16
|
+
// writeGuardianConfig - Writes the guardian section into the canonical vvoc.json document.
|
|
17
|
+
// END_MODULE_MAP
|
|
18
|
+
//
|
|
19
|
+
// START_CHANGE_SUMMARY
|
|
20
|
+
// LAST_CHANGE: [C-OPENCODE-MODULE-SPLIT - Extracted canonical vvoc.json IO from the former src/lib/opencode.ts monolith into this zone module.]
|
|
21
|
+
// END_CHANGE_SUMMARY
|
|
22
|
+
import { createDefaultVvocConfig, createGuardianConfig, parseVvocConfigText, } from "../vvoc-config.js";
|
|
23
|
+
import { materializeHashlineEditEntry, materializeToolHistoryCompactionEntry, materializePeakHoursEntry, materializeSpecGuardEntry, } from "../plugin-toggle-config.js";
|
|
24
|
+
import { readOptionalText, writeResolvedVvocConfig } from "./shared-utils.js";
|
|
25
|
+
// START_BLOCK_VVOC_CONFIG_IO
|
|
26
|
+
export async function readVvocConfig(paths) {
|
|
27
|
+
const currentText = await readOptionalText(paths.vvocConfigPath);
|
|
28
|
+
return currentText ? parseVvocConfigText(currentText, paths.vvocConfigPath) : undefined;
|
|
29
|
+
}
|
|
30
|
+
export async function installVvocConfig(paths) {
|
|
31
|
+
return syncVvocConfig(paths);
|
|
32
|
+
}
|
|
33
|
+
export async function syncVvocConfig(paths) {
|
|
34
|
+
const currentText = await readOptionalText(paths.vvocConfigPath);
|
|
35
|
+
const nextConfig = currentText
|
|
36
|
+
? parseVvocConfigText(currentText, paths.vvocConfigPath)
|
|
37
|
+
: createDefaultVvocConfig();
|
|
38
|
+
nextConfig.plugins["hashline-edit"] = materializeHashlineEditEntry(nextConfig.plugins["hashline-edit"]);
|
|
39
|
+
nextConfig.plugins["tool-history-compaction"] = materializeToolHistoryCompactionEntry(nextConfig.plugins["tool-history-compaction"]);
|
|
40
|
+
nextConfig.plugins["peak-hours"] = materializePeakHoursEntry(nextConfig.plugins["peak-hours"]);
|
|
41
|
+
nextConfig.plugins["spec-guard"] = materializeSpecGuardEntry(nextConfig.plugins["spec-guard"]);
|
|
42
|
+
return writeResolvedVvocConfig(paths.vvocConfigPath, currentText, nextConfig);
|
|
43
|
+
}
|
|
44
|
+
export async function writeGuardianConfig(paths, overrides, options = {}) {
|
|
45
|
+
const currentText = await readOptionalText(paths.vvocConfigPath);
|
|
46
|
+
const currentConfig = currentText
|
|
47
|
+
? parseVvocConfigText(currentText, paths.vvocConfigPath)
|
|
48
|
+
: createDefaultVvocConfig();
|
|
49
|
+
const nextConfig = {
|
|
50
|
+
...currentConfig,
|
|
51
|
+
guardian: options.merge
|
|
52
|
+
? createGuardianConfig({ ...currentConfig.guardian, ...overrides })
|
|
53
|
+
: createGuardianConfig(overrides),
|
|
54
|
+
};
|
|
55
|
+
return writeResolvedVvocConfig(paths.vvocConfigPath, currentText, nextConfig);
|
|
56
|
+
}
|
|
57
|
+
// END_BLOCK_VVOC_CONFIG_IO
|
|
58
|
+
//# sourceMappingURL=vvoc-config-io.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vvoc-config-io.js","sourceRoot":"","sources":["../../../src/lib/opencode/vvoc-config-io.ts"],"names":[],"mappings":"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"}
|