@osovv/vv-opencode 0.5.5 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +57 -4
- package/dist/commands/agent.js +124 -79
- package/dist/commands/agent.js.map +1 -1
- package/dist/commands/completion.js +40 -4
- package/dist/commands/completion.js.map +1 -1
- package/dist/commands/init.js +13 -4
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/install.js +11 -4
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/sync.js +10 -4
- package/dist/commands/sync.js.map +1 -1
- package/dist/lib/managed-agents.d.ts +17 -0
- package/dist/lib/managed-agents.js +129 -0
- package/dist/lib/managed-agents.js.map +1 -0
- package/dist/lib/opencode.d.ts +19 -0
- package/dist/lib/opencode.js +227 -6
- package/dist/lib/opencode.js.map +1 -1
- package/dist/lib/vvoc-paths.d.ts +1 -0
- package/dist/lib/vvoc-paths.js +7 -3
- package/dist/lib/vvoc-paths.js.map +1 -1
- package/dist/plugins/guardian/index.js +17 -17
- package/dist/plugins/guardian/index.js.map +1 -1
- package/dist/plugins/memory/index.js +9 -9
- package/dist/plugins/memory/index.js.map +1 -1
- package/dist/plugins/memory/system-instruction.md +8 -0
- package/package.json +4 -3
- package/templates/agents/code-reviewer.md +8 -0
- package/templates/agents/guardian.md +50 -0
- package/templates/agents/implementer.md +11 -0
- package/templates/agents/investitagor.md +11 -0
- package/templates/agents/memory-reviewer.md +25 -0
- package/templates/agents/spec-reviewer.md +8 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,6BAA6B;AAC7B,iBAAiB;AACjB,wBAAwB;AACxB,iQAAiQ;AACjQ,
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,6BAA6B;AAC7B,iBAAiB;AACjB,wBAAwB;AACxB,iQAAiQ;AACjQ,2KAA2K;AAC3K,0DAA0D;AAC1D,sCAAsC;AACtC,kBAAkB;AAClB,sBAAsB;AACtB,sBAAsB;AACtB,EAAE;AACF,mBAAmB;AACnB,gDAAgD;AAChD,2CAA2C;AAC3C,iBAAiB;AACjB,EAAE;AACF,uBAAuB;AACvB,0HAA0H;AAC1H,qBAAqB;AAErB,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,0BAA0B,EAC1B,mBAAmB,EACnB,mBAAmB,EACnB,YAAY,EACZ,gCAAgC,GAEjC,MAAM,oBAAoB,CAAC;AAE5B,eAAe,aAAa,CAAC;IAC3B,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM;QACZ,WAAW,EAAE,2CAA2C;KACzD;IACD,IAAI,EAAE;QACJ,KAAK,EAAE;YACL,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC;YAC9B,OAAO,EAAE,QAAQ;YACjB,WAAW,EAAE,qCAAqC;SACnD;QACD,OAAO,EAAE;YACP,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,oBAAoB;YAC7B,WAAW,EAAE,4CAA4C;SAC1D;QACD,iBAAiB,EAAE;YACjB,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,KAAK;YACd,WAAW,EAAE,4CAA4C;SAC1D;QACD,YAAY,EAAE;YACZ,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,kCAAkC;SAChD;KACF;IACD,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE;QAChB,uBAAuB;QACvB,MAAM,cAAc,GAAG,IAAI,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;QACxD,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAU,CAAC;QACzE,MAAM,SAAS,GAAG,OAAO,IAAI,CAAC,YAAY,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC1F,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QAE1B,CAAC,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAE7B,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC,CAAC;YACzD,CAAC,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;QAC3C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;gBACtD,CAAC,CAAC,MAAM,CAAC,0BAA0B,CAAC,CAAC;gBACrC,OAAO,CAAC,QAAQ,GAAG,GAAG,CAAC;YACzB,CAAC;iBAAM,CAAC;gBACN,CAAC,CAAC,MAAM,CAAC,yBAAyB,GAAG,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;gBACzF,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;QACD,qBAAqB;IACvB,CAAC;CACF,CAAC,CAAC;AAEH,KAAK,UAAU,OAAO,CAAC,OAKtB;IACC,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC;IAE1D,IAAI,aAAa,GAAU,KAAK,CAAC;IACjC,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,MAAM,WAAW,GAAG,MAAM,CAAC,CAAC,MAAM,CAAC;YACjC,OAAO,EAAE,4BAA4B;YACrC,OAAO,EAAE;gBACP,EAAE,KAAK,EAAE,uBAAuB,EAAE,KAAK,EAAE,QAAQ,EAAE;gBACnD,EAAE,KAAK,EAAE,kCAAkC,EAAE,KAAK,EAAE,SAAS,EAAE;aAChE;YACD,YAAY,EAAE,KAAK;SACpB,CAAC,CAAC;QAEH,IAAI,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC;QAC7B,CAAC;QACD,aAAa,GAAG,WAAoB,CAAC;QAErC,MAAM,aAAa,GAAG,MAAM,YAAY,CAAC,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;QACnF,MAAM,UAAU,GAAG,MAAM,mBAAmB,CAAC,aAAa,CAAC,CAAC;QAE5D,IAAI,UAAU,CAAC,QAAQ,CAAC,gBAAgB,EAAE,CAAC;YACzC,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,OAAO,CAAC;gBAChC,OAAO,EAAE,sDAAsD;gBAC/D,YAAY,EAAE,KAAK;aACpB,CAAC,CAAC;YAEH,IAAI,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC1B,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC;YAC7B,CAAC;YACD,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,CAAC,CAAC,MAAM,CAAC,wDAAwD,CAAC,CAAC;gBACnE,OAAO;YACT,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,YAAY,CAAC,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;IAEhF,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;IACvD,MAAM,SAAS,GAAG,MAAM,sBAAsB,CAAC,UAAU,CAAC,CAAC;IAC3D,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,GAAG,KAAK,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC;IAE5F,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;IAC/C,MAAM,iBAAiB,GAAG,MAAM,gCAAgC,CAAC,UAAU,CAAC,CAAC;IAC7E,CAAC,CAAC,GAAG,CAAC,IAAI,CACR,iBAAiB,CAAC,IAAI,GAAG,KAAK,GAAG,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAChG,CAAC;IAEF,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;IACnD,KAAK,MAAM,MAAM,IAAI,MAAM,0BAA0B,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;QACnF,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IAClD,CAAC;IAED,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;IAC7C,MAAM,cAAc,GAAG,MAAM,qBAAqB,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAChF,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,GAAG,KAAK,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IAEhE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;IAC3C,MAAM,YAAY,GAAG,MAAM,mBAAmB,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5E,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,GAAG,KAAK,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IAE5D,CAAC,CAAC,KAAK,CAAC;;;;0BAIgB,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,OAI3C;IACC,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IAC1C,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;IAE5D,MAAM,UAAU,GAAG,MAAM,mBAAmB,CAAC,KAAK,CAAC,CAAC;IACpD,IAAI,UAAU,CAAC,QAAQ,CAAC,gBAAgB,EAAE,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,wDAAwD,CAAC,CAAC;QACtE,OAAO;IACT,CAAC;IAED,MAAM,sBAAsB,CAAC,KAAK,CAAC,CAAC;IACpC,MAAM,gCAAgC,CAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,0BAA0B,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACzD,MAAM,qBAAqB,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACpD,MAAM,mBAAmB,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACpD,CAAC"}
|
package/dist/commands/install.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// FILE: src/commands/install.ts
|
|
2
|
-
// VERSION: 0.2.
|
|
2
|
+
// VERSION: 0.2.6
|
|
3
3
|
// START_MODULE_CONTRACT
|
|
4
4
|
// PURPOSE: Install vv-opencode into OpenCode config and bootstrap vvoc-managed config files.
|
|
5
|
-
// SCOPE: Scope parsing, path resolution, pinned plugin registration, and initial Guardian/Memory config creation.
|
|
5
|
+
// SCOPE: Scope parsing, path resolution, pinned plugin registration, managed agent prompt scaffolding, and initial Guardian/Memory config creation.
|
|
6
6
|
// DEPENDS: [citty, src/lib/opencode.ts]
|
|
7
7
|
// LINKS: [M-CLI-COMMANDS, M-CLI-CONFIG]
|
|
8
8
|
// ROLE: RUNTIME
|
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
// END_MODULE_MAP
|
|
15
15
|
//
|
|
16
16
|
// START_CHANGE_SUMMARY
|
|
17
|
-
// LAST_CHANGE: [v0.2.
|
|
17
|
+
// LAST_CHANGE: [v0.2.6 - Added managed subagent registration plus guardian/memory-reviewer prompt scaffolding to install.]
|
|
18
18
|
// END_CHANGE_SUMMARY
|
|
19
19
|
import { defineCommand } from "citty";
|
|
20
|
-
import { describeWriteResult, ensurePackageInstalled, installGuardianConfig, installMemoryConfig, installSecretsRedactionConfig, resolvePaths, } from "../lib/opencode.js";
|
|
20
|
+
import { describeWriteResult, ensurePackageInstalled, installGuardianConfig, installManagedAgentPrompts, installMemoryConfig, installSecretsRedactionConfig, resolvePaths, syncManagedSubagentRegistrations, } from "../lib/opencode.js";
|
|
21
21
|
export default defineCommand({
|
|
22
22
|
meta: {
|
|
23
23
|
name: "install",
|
|
@@ -64,7 +64,14 @@ export default defineCommand({
|
|
|
64
64
|
configDir,
|
|
65
65
|
});
|
|
66
66
|
const opencode = await ensurePackageInstalled(paths);
|
|
67
|
+
const managedSubagents = await syncManagedSubagentRegistrations(paths);
|
|
67
68
|
console.log(`${opencode.changed ? "Updated" : "Kept"} ${opencode.path}`);
|
|
69
|
+
console.log(`${managedSubagents.changed ? "Updated" : "Kept"} ${managedSubagents.path} (managed subagents)`);
|
|
70
|
+
for (const result of await installManagedAgentPrompts(paths, {
|
|
71
|
+
force: Boolean(args.force),
|
|
72
|
+
})) {
|
|
73
|
+
console.log(describeWriteResult(result));
|
|
74
|
+
}
|
|
68
75
|
if (args["guardian-config"] === false) {
|
|
69
76
|
console.log(`Skipped ${paths.guardianConfigPath} (guardian config disabled)`);
|
|
70
77
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,iBAAiB;AACjB,wBAAwB;AACxB,+FAA+F;AAC/F,
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/sync.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// FILE: src/commands/sync.ts
|
|
2
|
-
// VERSION: 0.2.
|
|
2
|
+
// VERSION: 0.2.6
|
|
3
3
|
// START_MODULE_CONTRACT
|
|
4
4
|
// PURPOSE: Sync managed vvoc config files and keep the OpenCode plugin specifier current.
|
|
5
|
-
// SCOPE: Scope parsing, path resolution, pinned plugin sync, and managed Guardian/Memory config rewrites.
|
|
5
|
+
// SCOPE: Scope parsing, path resolution, pinned plugin sync, managed agent prompt sync, and managed Guardian/Memory config rewrites.
|
|
6
6
|
// DEPENDS: [citty, src/lib/opencode.ts]
|
|
7
7
|
// LINKS: [M-CLI-COMMANDS, M-CLI-CONFIG]
|
|
8
8
|
// ROLE: RUNTIME
|
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
// END_MODULE_MAP
|
|
15
15
|
//
|
|
16
16
|
// START_CHANGE_SUMMARY
|
|
17
|
-
// LAST_CHANGE: [v0.2.
|
|
17
|
+
// LAST_CHANGE: [v0.2.6 - Added managed subagent registration plus guardian/memory-reviewer prompt syncing to vvoc sync.]
|
|
18
18
|
// END_CHANGE_SUMMARY
|
|
19
19
|
import { defineCommand } from "citty";
|
|
20
|
-
import { describeWriteResult, ensurePackageInstalled, resolvePaths, syncGuardianConfig, syncMemoryConfig, } from "../lib/opencode.js";
|
|
20
|
+
import { describeWriteResult, ensurePackageInstalled, resolvePaths, syncManagedAgentPrompts, syncManagedSubagentRegistrations, syncGuardianConfig, syncMemoryConfig, } from "../lib/opencode.js";
|
|
21
21
|
export default defineCommand({
|
|
22
22
|
meta: {
|
|
23
23
|
name: "sync",
|
|
@@ -49,9 +49,15 @@ export default defineCommand({
|
|
|
49
49
|
configDir,
|
|
50
50
|
});
|
|
51
51
|
const opencode = await ensurePackageInstalled(paths);
|
|
52
|
+
const managedSubagents = await syncManagedSubagentRegistrations(paths);
|
|
53
|
+
const managedPrompts = await syncManagedAgentPrompts(paths, { force: Boolean(args.force) });
|
|
52
54
|
const guardian = await syncGuardianConfig(paths, { force: Boolean(args.force) });
|
|
53
55
|
const memory = await syncMemoryConfig(paths, { force: Boolean(args.force) });
|
|
54
56
|
console.log(`${opencode.changed ? "Updated" : "Kept"} ${opencode.path}`);
|
|
57
|
+
console.log(`${managedSubagents.changed ? "Updated" : "Kept"} ${managedSubagents.path} (managed subagents)`);
|
|
58
|
+
for (const result of managedPrompts) {
|
|
59
|
+
console.log(describeWriteResult(result));
|
|
60
|
+
}
|
|
55
61
|
console.log(describeWriteResult(guardian));
|
|
56
62
|
console.log(describeWriteResult(memory));
|
|
57
63
|
// END_BLOCK_APPLY_SYNC_COMMAND
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"AAAA,6BAA6B;AAC7B,iBAAiB;AACjB,wBAAwB;AACxB,4FAA4F;AAC5F,
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare const MANAGED_SUBAGENT_NAMES: readonly ["implementer", "spec-reviewer", "code-reviewer", "investitagor"];
|
|
2
|
+
export type ManagedSubagentName = (typeof MANAGED_SUBAGENT_NAMES)[number];
|
|
3
|
+
export declare const MANAGED_AGENT_PROMPT_NAMES: readonly ["guardian", "memory-reviewer", "implementer", "spec-reviewer", "code-reviewer", "investitagor"];
|
|
4
|
+
export type ManagedAgentPromptName = (typeof MANAGED_AGENT_PROMPT_NAMES)[number];
|
|
5
|
+
export type ManagedSubagentDefinition = {
|
|
6
|
+
name: ManagedSubagentName;
|
|
7
|
+
description: string;
|
|
8
|
+
promptFileName: `${ManagedSubagentName}.md`;
|
|
9
|
+
steps?: number;
|
|
10
|
+
permission?: Record<string, unknown>;
|
|
11
|
+
};
|
|
12
|
+
export declare const MANAGED_SUBAGENTS: readonly ManagedSubagentDefinition[];
|
|
13
|
+
export declare function isManagedSubagentName(value: string): value is ManagedSubagentName;
|
|
14
|
+
export declare function getManagedSubagentDefinition(name: ManagedSubagentName): ManagedSubagentDefinition;
|
|
15
|
+
export declare function getManagedAgentPromptPath(agentsDirPath: string, name: ManagedAgentPromptName): string;
|
|
16
|
+
export declare function loadManagedAgentPromptTemplate(name: ManagedAgentPromptName): Promise<string>;
|
|
17
|
+
export declare function loadManagedAgentPromptText(directory: string, name: ManagedAgentPromptName): Promise<string>;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
// FILE: src/lib/managed-agents.ts
|
|
2
|
+
// VERSION: 0.2.0
|
|
3
|
+
// START_MODULE_CONTRACT
|
|
4
|
+
// PURPOSE: Describe vvoc-managed OpenCode agent prompts and load them from bundled templates or scoped vvoc config roots.
|
|
5
|
+
// SCOPE: Built-in subagent metadata, managed prompt names, prompt file path resolution, bundled template loading, and project/global prompt lookup.
|
|
6
|
+
// DEPENDS: [node:fs/promises, node:path, src/lib/vvoc-paths.ts]
|
|
7
|
+
// LINKS: [M-CLI-CONFIG, M-PLUGIN-GUARDIAN, M-PLUGIN-MEMORY]
|
|
8
|
+
// ROLE: RUNTIME
|
|
9
|
+
// MAP_MODE: EXPORTS
|
|
10
|
+
// END_MODULE_CONTRACT
|
|
11
|
+
//
|
|
12
|
+
// START_MODULE_MAP
|
|
13
|
+
// ManagedSubagentName - Canonical vvoc-managed subagent names.
|
|
14
|
+
// ManagedAgentPromptName - Canonical vvoc-managed agent prompt names including Guardian and memory-reviewer.
|
|
15
|
+
// ManagedSubagentDefinition - Metadata used to register a managed subagent in OpenCode config.
|
|
16
|
+
// MANAGED_SUBAGENT_NAMES - Ordered managed subagent names.
|
|
17
|
+
// MANAGED_AGENT_PROMPT_NAMES - Ordered managed agent prompt names.
|
|
18
|
+
// MANAGED_SUBAGENTS - Built-in managed subagent definitions.
|
|
19
|
+
// isManagedSubagentName - Checks whether a string is one of the managed subagent names.
|
|
20
|
+
// getManagedSubagentDefinition - Returns metadata for a managed subagent.
|
|
21
|
+
// getManagedAgentPromptPath - Resolves the prompt file path inside a vvoc agents directory.
|
|
22
|
+
// loadManagedAgentPromptTemplate - Loads the bundled prompt template for a managed agent prompt.
|
|
23
|
+
// loadManagedAgentPromptText - Loads a managed prompt from project or global vvoc config and errors if neither exists.
|
|
24
|
+
// END_MODULE_MAP
|
|
25
|
+
//
|
|
26
|
+
// START_CHANGE_SUMMARY
|
|
27
|
+
// LAST_CHANGE: [v0.2.0 - Added guardian and memory-reviewer prompt management with scoped vvoc config loading and no bundled runtime fallback.]
|
|
28
|
+
// END_CHANGE_SUMMARY
|
|
29
|
+
import { readFile } from "node:fs/promises";
|
|
30
|
+
import { join } from "node:path";
|
|
31
|
+
import { getGlobalVvocDir, getProjectVvocDir, getVvocAgentsDir } from "./vvoc-paths.js";
|
|
32
|
+
export const MANAGED_SUBAGENT_NAMES = [
|
|
33
|
+
"implementer",
|
|
34
|
+
"spec-reviewer",
|
|
35
|
+
"code-reviewer",
|
|
36
|
+
"investitagor",
|
|
37
|
+
];
|
|
38
|
+
export const MANAGED_AGENT_PROMPT_NAMES = [
|
|
39
|
+
"guardian",
|
|
40
|
+
"memory-reviewer",
|
|
41
|
+
...MANAGED_SUBAGENT_NAMES,
|
|
42
|
+
];
|
|
43
|
+
export const MANAGED_SUBAGENTS = [
|
|
44
|
+
{
|
|
45
|
+
name: "implementer",
|
|
46
|
+
description: "Implements approved changes with focused verification and a minimal diff.",
|
|
47
|
+
promptFileName: "implementer.md",
|
|
48
|
+
steps: 8,
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: "spec-reviewer",
|
|
52
|
+
description: "Checks an implementation against the requested spec and flags missing or extra behavior.",
|
|
53
|
+
promptFileName: "spec-reviewer.md",
|
|
54
|
+
steps: 6,
|
|
55
|
+
permission: {
|
|
56
|
+
edit: "deny",
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: "code-reviewer",
|
|
61
|
+
description: "Reviews changes for bugs, regressions, maintainability risks, and missing tests.",
|
|
62
|
+
promptFileName: "code-reviewer.md",
|
|
63
|
+
steps: 6,
|
|
64
|
+
permission: {
|
|
65
|
+
edit: "deny",
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
name: "investitagor",
|
|
70
|
+
description: "Investigates bugs and unclear behavior before implementation work begins.",
|
|
71
|
+
promptFileName: "investitagor.md",
|
|
72
|
+
steps: 6,
|
|
73
|
+
permission: {
|
|
74
|
+
edit: "deny",
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
];
|
|
78
|
+
const MANAGED_SUBAGENT_MAP = new Map(MANAGED_SUBAGENTS.map((definition) => [definition.name, definition]));
|
|
79
|
+
const MANAGED_AGENT_PROMPT_FILE_NAMES = new Map([
|
|
80
|
+
["guardian", "guardian.md"],
|
|
81
|
+
["memory-reviewer", "memory-reviewer.md"],
|
|
82
|
+
["implementer", "implementer.md"],
|
|
83
|
+
["spec-reviewer", "spec-reviewer.md"],
|
|
84
|
+
["code-reviewer", "code-reviewer.md"],
|
|
85
|
+
["investitagor", "investitagor.md"],
|
|
86
|
+
]);
|
|
87
|
+
export function isManagedSubagentName(value) {
|
|
88
|
+
return MANAGED_SUBAGENT_MAP.has(value);
|
|
89
|
+
}
|
|
90
|
+
export function getManagedSubagentDefinition(name) {
|
|
91
|
+
const definition = MANAGED_SUBAGENT_MAP.get(name);
|
|
92
|
+
if (!definition) {
|
|
93
|
+
throw new Error(`unknown managed subagent: ${name}`);
|
|
94
|
+
}
|
|
95
|
+
return definition;
|
|
96
|
+
}
|
|
97
|
+
export function getManagedAgentPromptPath(agentsDirPath, name) {
|
|
98
|
+
return join(agentsDirPath, getManagedAgentPromptFileName(name));
|
|
99
|
+
}
|
|
100
|
+
export async function loadManagedAgentPromptTemplate(name) {
|
|
101
|
+
const assetUrl = new URL(`../../templates/agents/${getManagedAgentPromptFileName(name)}`, import.meta.url);
|
|
102
|
+
return readFile(assetUrl, "utf8");
|
|
103
|
+
}
|
|
104
|
+
export async function loadManagedAgentPromptText(directory, name) {
|
|
105
|
+
const candidatePaths = [
|
|
106
|
+
getManagedAgentPromptPath(getVvocAgentsDir(getProjectVvocDir(directory)), name),
|
|
107
|
+
getManagedAgentPromptPath(getVvocAgentsDir(getGlobalVvocDir()), name),
|
|
108
|
+
];
|
|
109
|
+
for (const candidatePath of candidatePaths) {
|
|
110
|
+
try {
|
|
111
|
+
return await readFile(candidatePath, "utf8");
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
if (error.code === "ENOENT") {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
throw error;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
throw new Error(`vvoc managed prompt not found for ${name}. Run \`vvoc install\` or \`vvoc sync\`. Checked: ${candidatePaths.join(", ")}`);
|
|
121
|
+
}
|
|
122
|
+
function getManagedAgentPromptFileName(name) {
|
|
123
|
+
const promptFileName = MANAGED_AGENT_PROMPT_FILE_NAMES.get(name);
|
|
124
|
+
if (!promptFileName) {
|
|
125
|
+
throw new Error(`unknown managed agent prompt: ${name}`);
|
|
126
|
+
}
|
|
127
|
+
return promptFileName;
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=managed-agents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"managed-agents.js","sourceRoot":"","sources":["../../src/lib/managed-agents.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/opencode.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ManagedSubagentName } from "./managed-agents.js";
|
|
1
2
|
import { type MemoryConfigOverrides } from "../plugins/memory-store.js";
|
|
2
3
|
import { PACKAGE_NAME } from "./package.js";
|
|
3
4
|
export declare const CLI_NAME = "vvoc";
|
|
@@ -10,6 +11,7 @@ export type ResolvedPaths = {
|
|
|
10
11
|
configHome: string;
|
|
11
12
|
opencodeBaseDir: string;
|
|
12
13
|
vvocBaseDir: string;
|
|
14
|
+
managedAgentsDirPath: string;
|
|
13
15
|
opencodeConfigPath: string;
|
|
14
16
|
opencodeAlternatePaths: string[];
|
|
15
17
|
guardianConfigPath: string;
|
|
@@ -31,6 +33,7 @@ export type WriteResult = {
|
|
|
31
33
|
path: string;
|
|
32
34
|
reason?: string;
|
|
33
35
|
};
|
|
36
|
+
export type ManagedSubagentModelMap = Record<ManagedSubagentName, string | undefined>;
|
|
34
37
|
export type InstallationInspection = {
|
|
35
38
|
scope: Scope;
|
|
36
39
|
opencode: {
|
|
@@ -73,6 +76,22 @@ export declare function resolvePaths(options: {
|
|
|
73
76
|
configDir?: string;
|
|
74
77
|
}): Promise<ResolvedPaths>;
|
|
75
78
|
export declare function ensurePackageConfigText(text: string | undefined, packageSpecifier?: string): string;
|
|
79
|
+
export declare function ensureManagedSubagentsConfigText(text: string | undefined, paths: Pick<ResolvedPaths, "managedAgentsDirPath" | "opencodeConfigPath">): string;
|
|
80
|
+
export declare function syncManagedSubagentRegistrations(paths: ResolvedPaths): Promise<{
|
|
81
|
+
path: string;
|
|
82
|
+
changed: boolean;
|
|
83
|
+
}>;
|
|
84
|
+
export declare function installManagedAgentPrompts(paths: ResolvedPaths, options: {
|
|
85
|
+
force: boolean;
|
|
86
|
+
}): Promise<WriteResult[]>;
|
|
87
|
+
export declare function syncManagedAgentPrompts(paths: ResolvedPaths, options: {
|
|
88
|
+
force: boolean;
|
|
89
|
+
}): Promise<WriteResult[]>;
|
|
90
|
+
export declare function readManagedSubagentModels(paths: Pick<ResolvedPaths, "opencodeConfigPath">): Promise<ManagedSubagentModelMap>;
|
|
91
|
+
export declare function writeManagedSubagentModel(paths: Pick<ResolvedPaths, "managedAgentsDirPath" | "opencodeConfigPath">, agentName: ManagedSubagentName, options: {
|
|
92
|
+
model?: string;
|
|
93
|
+
ensureEntry: boolean;
|
|
94
|
+
}): Promise<WriteResult>;
|
|
76
95
|
export declare function parseGuardianConfigText(text: string, label: string): GuardianConfigOverrides;
|
|
77
96
|
export declare function renderGuardianConfig(overrides?: GuardianConfigOverrides): string;
|
|
78
97
|
export declare function ensurePackageInstalled(paths: ResolvedPaths): Promise<{
|
package/dist/lib/opencode.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// FILE: src/lib/opencode.ts
|
|
2
|
-
// VERSION: 0.2.
|
|
2
|
+
// VERSION: 0.2.7
|
|
3
3
|
// START_MODULE_CONTRACT
|
|
4
4
|
// PURPOSE: Manage OpenCode plugin registration and vvoc-owned config files.
|
|
5
|
-
// SCOPE: Scope-aware path resolution, pinned plugin writes, Guardian/Memory config rendering and sync, and installation inspection.
|
|
6
|
-
// DEPENDS: [jsonc-parser, node:fs/promises, node:path, src/lib/package.ts, src/lib/vvoc-paths.ts, src/plugins/memory-store.ts]
|
|
5
|
+
// SCOPE: Scope-aware path resolution, pinned plugin writes, managed subagent registration, managed agent prompt sync, Guardian/Memory config rendering and sync, and installation inspection.
|
|
6
|
+
// DEPENDS: [jsonc-parser, node:fs/promises, node:path, src/lib/managed-agents.ts, src/lib/package.ts, src/lib/vvoc-paths.ts, src/plugins/memory-store.ts]
|
|
7
7
|
// LINKS: [M-CLI-CONFIG]
|
|
8
8
|
// ROLE: RUNTIME
|
|
9
9
|
// MAP_MODE: EXPORTS
|
|
@@ -20,9 +20,15 @@
|
|
|
20
20
|
// InstallationInspection - Current OpenCode and vvoc installation status snapshot.
|
|
21
21
|
// resolvePaths - Resolves OpenCode and vvoc config paths for global/project scopes.
|
|
22
22
|
// ensurePackageConfigText - Ensures OpenCode config contains the pinned vvoc plugin specifier.
|
|
23
|
+
// ensureManagedSubagentsConfigText - Ensures OpenCode config contains the vvoc-managed subagent registrations.
|
|
23
24
|
// parseGuardianConfigText - Parses Guardian config JSONC into typed overrides.
|
|
24
25
|
// renderGuardianConfig - Renders managed Guardian config JSONC.
|
|
25
26
|
// ensurePackageInstalled - Writes the pinned vvoc plugin specifier into OpenCode config.
|
|
27
|
+
// syncManagedSubagentRegistrations - Syncs the canonical vvoc-managed subagent registrations into OpenCode config.
|
|
28
|
+
// installManagedAgentPrompts - Creates managed vvoc prompt files for the bundled Guardian/subagent agents when missing.
|
|
29
|
+
// syncManagedAgentPrompts - Rewrites managed vvoc prompt files for the bundled Guardian/subagent agents.
|
|
30
|
+
// readManagedSubagentModels - Reads model overrides for the bundled vvoc subagents from OpenCode config.
|
|
31
|
+
// writeManagedSubagentModel - Writes or removes a bundled vvoc subagent model override in OpenCode config.
|
|
26
32
|
// installGuardianConfig - Creates or preserves managed Guardian config.
|
|
27
33
|
// syncGuardianConfig - Rewrites managed Guardian config while preserving current values.
|
|
28
34
|
// writeGuardianConfig - Writes explicit Guardian overrides to managed config.
|
|
@@ -33,14 +39,15 @@
|
|
|
33
39
|
// END_MODULE_MAP
|
|
34
40
|
//
|
|
35
41
|
// START_CHANGE_SUMMARY
|
|
36
|
-
// LAST_CHANGE: [v0.2.
|
|
42
|
+
// LAST_CHANGE: [v0.2.7 - Expanded managed prompt scaffolding to cover guardian and memory-reviewer with no bundled runtime fallback.]
|
|
37
43
|
// END_CHANGE_SUMMARY
|
|
38
44
|
import { applyEdits, format, modify, parse } from "jsonc-parser";
|
|
39
45
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
40
|
-
import { dirname, join } from "node:path";
|
|
46
|
+
import { dirname, join, relative } from "node:path";
|
|
47
|
+
import { MANAGED_AGENT_PROMPT_NAMES, MANAGED_SUBAGENTS, getManagedAgentPromptPath, getManagedSubagentDefinition, loadManagedAgentPromptTemplate, } from "./managed-agents.js";
|
|
41
48
|
import { parseMemoryConfigText, renderMemoryConfig, } from "../plugins/memory-store.js";
|
|
42
49
|
import { getPinnedPackageSpecifier, PACKAGE_NAME } from "./package.js";
|
|
43
|
-
import { getConfigHome, getGlobalOpencodeDir, getGlobalVvocDir, getProjectVvocDir, } from "./vvoc-paths.js";
|
|
50
|
+
import { getConfigHome, getGlobalOpencodeDir, getGlobalVvocDir, getProjectVvocDir, getVvocAgentsDir, } from "./vvoc-paths.js";
|
|
44
51
|
export const CLI_NAME = "vvoc";
|
|
45
52
|
export { PACKAGE_NAME };
|
|
46
53
|
export const OPENCODE_SCHEMA_URL = "https://opencode.ai/config.json";
|
|
@@ -66,6 +73,7 @@ export async function resolvePaths(options) {
|
|
|
66
73
|
const vvocBaseDir = options.scope === "global"
|
|
67
74
|
? getGlobalVvocDir(options.configDir)
|
|
68
75
|
: getProjectVvocDir(options.cwd);
|
|
76
|
+
const managedAgentsDirPath = getVvocAgentsDir(vvocBaseDir);
|
|
69
77
|
const opencodeSelection = await selectPrimaryPath(OPENCODE_CONFIG_FILE_NAMES.map((name) => join(opencodeBaseDir, name)));
|
|
70
78
|
const guardianSelection = await selectPrimaryPath(GUARDIAN_CONFIG_FILE_NAMES.map((name) => join(vvocBaseDir, name)));
|
|
71
79
|
const memorySelection = await selectPrimaryPath(MEMORY_CONFIG_FILE_NAMES.map((name) => join(vvocBaseDir, name)));
|
|
@@ -76,6 +84,7 @@ export async function resolvePaths(options) {
|
|
|
76
84
|
configHome,
|
|
77
85
|
opencodeBaseDir,
|
|
78
86
|
vvocBaseDir,
|
|
87
|
+
managedAgentsDirPath,
|
|
79
88
|
opencodeConfigPath: opencodeSelection.primary,
|
|
80
89
|
opencodeAlternatePaths: opencodeSelection.alternates,
|
|
81
90
|
guardianConfigPath: guardianSelection.primary,
|
|
@@ -113,6 +122,138 @@ export function ensurePackageConfigText(text, packageSpecifier = PACKAGE_NAME) {
|
|
|
113
122
|
return ensureTrailingNewline(applyEdits(nextText, format(nextText, undefined, JSON_FORMAT)));
|
|
114
123
|
}
|
|
115
124
|
// END_BLOCK_ENSURE_OPENCODE_PLUGIN_CONFIG
|
|
125
|
+
// START_BLOCK_ENSURE_MANAGED_SUBAGENT_CONFIG
|
|
126
|
+
export function ensureManagedSubagentsConfigText(text, paths) {
|
|
127
|
+
if (!text?.trim()) {
|
|
128
|
+
return renderJson({
|
|
129
|
+
$schema: OPENCODE_SCHEMA_URL,
|
|
130
|
+
agent: Object.fromEntries(MANAGED_SUBAGENTS.map((definition) => [
|
|
131
|
+
definition.name,
|
|
132
|
+
getManagedSubagentRegistration(paths, definition.name),
|
|
133
|
+
])),
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
const document = parseObjectDocument(text, "OpenCode config");
|
|
137
|
+
const currentAgents = readAgentMap(document, "OpenCode config");
|
|
138
|
+
let nextText = text;
|
|
139
|
+
if (!Object.hasOwn(document, "$schema")) {
|
|
140
|
+
nextText = applyEdits(nextText, modify(nextText, ["$schema"], OPENCODE_SCHEMA_URL, {
|
|
141
|
+
formattingOptions: JSON_FORMAT,
|
|
142
|
+
getInsertionIndex: () => 0,
|
|
143
|
+
}));
|
|
144
|
+
}
|
|
145
|
+
for (const definition of MANAGED_SUBAGENTS) {
|
|
146
|
+
const currentEntry = currentAgents[definition.name];
|
|
147
|
+
const nextEntry = {
|
|
148
|
+
...getManagedSubagentRegistration(paths, definition.name),
|
|
149
|
+
...currentEntry,
|
|
150
|
+
};
|
|
151
|
+
if (JSON.stringify(currentEntry) === JSON.stringify(nextEntry)) {
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
nextText = applyEdits(nextText, modify(nextText, ["agent", definition.name], nextEntry, {
|
|
155
|
+
formattingOptions: JSON_FORMAT,
|
|
156
|
+
}));
|
|
157
|
+
}
|
|
158
|
+
return ensureTrailingNewline(applyEdits(nextText, format(nextText, undefined, JSON_FORMAT)));
|
|
159
|
+
}
|
|
160
|
+
export async function syncManagedSubagentRegistrations(paths) {
|
|
161
|
+
const currentText = await readOptionalText(paths.opencodeConfigPath);
|
|
162
|
+
const nextText = ensureManagedSubagentsConfigText(currentText, paths);
|
|
163
|
+
if (currentText === nextText) {
|
|
164
|
+
return { path: paths.opencodeConfigPath, changed: false };
|
|
165
|
+
}
|
|
166
|
+
await writeText(paths.opencodeConfigPath, nextText);
|
|
167
|
+
return { path: paths.opencodeConfigPath, changed: true };
|
|
168
|
+
}
|
|
169
|
+
export async function installManagedAgentPrompts(paths, options) {
|
|
170
|
+
const results = [];
|
|
171
|
+
for (const agentName of MANAGED_AGENT_PROMPT_NAMES) {
|
|
172
|
+
const promptPath = getManagedPromptPath(paths, agentName);
|
|
173
|
+
const currentText = await readOptionalText(promptPath);
|
|
174
|
+
if (!currentText) {
|
|
175
|
+
await writeText(promptPath, await renderManagedPrompt(agentName));
|
|
176
|
+
results.push({ action: "created", path: promptPath });
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
if (!options.force) {
|
|
180
|
+
if (!isManagedFile(currentText)) {
|
|
181
|
+
results.push({
|
|
182
|
+
action: "skipped",
|
|
183
|
+
path: promptPath,
|
|
184
|
+
reason: "existing file is not managed by vvoc",
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
results.push({ action: "kept", path: promptPath });
|
|
189
|
+
}
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
results.push(await syncManagedPrompt(paths, agentName, options));
|
|
193
|
+
}
|
|
194
|
+
return results;
|
|
195
|
+
}
|
|
196
|
+
export async function syncManagedAgentPrompts(paths, options) {
|
|
197
|
+
const results = [];
|
|
198
|
+
for (const agentName of MANAGED_AGENT_PROMPT_NAMES) {
|
|
199
|
+
results.push(await syncManagedPrompt(paths, agentName, options));
|
|
200
|
+
}
|
|
201
|
+
return results;
|
|
202
|
+
}
|
|
203
|
+
export async function readManagedSubagentModels(paths) {
|
|
204
|
+
const models = Object.fromEntries(MANAGED_SUBAGENTS.map((definition) => [definition.name, undefined]));
|
|
205
|
+
const currentText = await readOptionalText(paths.opencodeConfigPath);
|
|
206
|
+
if (!currentText) {
|
|
207
|
+
return models;
|
|
208
|
+
}
|
|
209
|
+
const document = parseObjectDocument(currentText, paths.opencodeConfigPath);
|
|
210
|
+
const agentMap = readAgentMap(document, paths.opencodeConfigPath);
|
|
211
|
+
for (const definition of MANAGED_SUBAGENTS) {
|
|
212
|
+
const currentEntry = agentMap[definition.name];
|
|
213
|
+
if (currentEntry?.model !== undefined) {
|
|
214
|
+
models[definition.name] = readNonEmptyString(currentEntry.model, `${definition.name}: model`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return models;
|
|
218
|
+
}
|
|
219
|
+
export async function writeManagedSubagentModel(paths, agentName, options) {
|
|
220
|
+
const currentText = await readOptionalText(paths.opencodeConfigPath);
|
|
221
|
+
if (!currentText && !options.ensureEntry) {
|
|
222
|
+
return { action: "kept", path: paths.opencodeConfigPath };
|
|
223
|
+
}
|
|
224
|
+
const baseText = options.ensureEntry
|
|
225
|
+
? ensureManagedSubagentsConfigText(currentText, paths)
|
|
226
|
+
: currentText;
|
|
227
|
+
if (!baseText) {
|
|
228
|
+
return { action: "kept", path: paths.opencodeConfigPath };
|
|
229
|
+
}
|
|
230
|
+
const document = parseObjectDocument(baseText, paths.opencodeConfigPath);
|
|
231
|
+
const agentMap = readAgentMap(document, paths.opencodeConfigPath);
|
|
232
|
+
const currentEntry = agentMap[agentName];
|
|
233
|
+
if (!currentEntry && !options.ensureEntry) {
|
|
234
|
+
return { action: "kept", path: paths.opencodeConfigPath };
|
|
235
|
+
}
|
|
236
|
+
const nextEntry = {
|
|
237
|
+
...getManagedSubagentRegistration(paths, agentName),
|
|
238
|
+
...currentEntry,
|
|
239
|
+
};
|
|
240
|
+
if (options.model) {
|
|
241
|
+
nextEntry.model = options.model;
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
delete nextEntry.model;
|
|
245
|
+
}
|
|
246
|
+
const nextText = updateAgentEntryText(baseText, agentName, nextEntry);
|
|
247
|
+
if ((currentText ?? "") === nextText) {
|
|
248
|
+
return { action: "kept", path: paths.opencodeConfigPath };
|
|
249
|
+
}
|
|
250
|
+
await writeText(paths.opencodeConfigPath, nextText);
|
|
251
|
+
return {
|
|
252
|
+
action: currentText ? "updated" : "created",
|
|
253
|
+
path: paths.opencodeConfigPath,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
// END_BLOCK_ENSURE_MANAGED_SUBAGENT_CONFIG
|
|
116
257
|
export function parseGuardianConfigText(text, label) {
|
|
117
258
|
return normalizeGuardianOverrides(parseObjectDocument(text, label), label);
|
|
118
259
|
}
|
|
@@ -513,6 +654,86 @@ function normalizePluginList(currentPlugins, packageSpecifier) {
|
|
|
513
654
|
function isPackagePluginSpecifier(value) {
|
|
514
655
|
return value === PACKAGE_NAME || value.startsWith(`${PACKAGE_NAME}@`);
|
|
515
656
|
}
|
|
657
|
+
// START_BLOCK_MANAGED_SUBAGENT_HELPERS
|
|
658
|
+
function readAgentMap(document, label) {
|
|
659
|
+
const raw = document.agent;
|
|
660
|
+
if (raw === undefined) {
|
|
661
|
+
return {};
|
|
662
|
+
}
|
|
663
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
664
|
+
throw new Error(`${label}: expected "agent" to be an object`);
|
|
665
|
+
}
|
|
666
|
+
const entries = {};
|
|
667
|
+
for (const [name, value] of Object.entries(raw)) {
|
|
668
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
669
|
+
throw new Error(`${label}: expected "agent.${name}" to be an object`);
|
|
670
|
+
}
|
|
671
|
+
entries[name] = value;
|
|
672
|
+
}
|
|
673
|
+
return entries;
|
|
674
|
+
}
|
|
675
|
+
function getManagedPromptPath(paths, agentName) {
|
|
676
|
+
return getManagedAgentPromptPath(paths.managedAgentsDirPath, agentName);
|
|
677
|
+
}
|
|
678
|
+
function getManagedSubagentPromptReference(paths, agentName) {
|
|
679
|
+
const promptPath = getManagedPromptPath(paths, agentName);
|
|
680
|
+
const promptRef = relative(dirname(paths.opencodeConfigPath), promptPath).replaceAll("\\", "/");
|
|
681
|
+
return `{file:${promptRef.startsWith(".") ? promptRef : `./${promptRef}`}}`;
|
|
682
|
+
}
|
|
683
|
+
function getManagedSubagentRegistration(paths, agentName) {
|
|
684
|
+
const definition = getManagedSubagentDefinition(agentName);
|
|
685
|
+
const registration = {
|
|
686
|
+
description: definition.description,
|
|
687
|
+
mode: "subagent",
|
|
688
|
+
prompt: getManagedSubagentPromptReference(paths, agentName),
|
|
689
|
+
};
|
|
690
|
+
if (definition.steps !== undefined) {
|
|
691
|
+
registration.steps = definition.steps;
|
|
692
|
+
}
|
|
693
|
+
if (definition.permission) {
|
|
694
|
+
registration.permission = definition.permission;
|
|
695
|
+
}
|
|
696
|
+
return registration;
|
|
697
|
+
}
|
|
698
|
+
async function renderManagedPrompt(agentName) {
|
|
699
|
+
const template = (await loadManagedAgentPromptTemplate(agentName)).trim();
|
|
700
|
+
const header = [
|
|
701
|
+
"<!-- Managed by vvoc.",
|
|
702
|
+
"`vvoc sync` rewrites files with this marker while preserving agent registration and model settings elsewhere.",
|
|
703
|
+
"Remove this comment if you want to manage the file manually.",
|
|
704
|
+
"-->",
|
|
705
|
+
"",
|
|
706
|
+
].join("\n");
|
|
707
|
+
return `${header}${template}\n`;
|
|
708
|
+
}
|
|
709
|
+
async function syncManagedPrompt(paths, agentName, options) {
|
|
710
|
+
const promptPath = getManagedPromptPath(paths, agentName);
|
|
711
|
+
const currentText = await readOptionalText(promptPath);
|
|
712
|
+
if (!currentText) {
|
|
713
|
+
await writeText(promptPath, await renderManagedPrompt(agentName));
|
|
714
|
+
return { action: "created", path: promptPath };
|
|
715
|
+
}
|
|
716
|
+
if (!options.force && !isManagedFile(currentText)) {
|
|
717
|
+
return {
|
|
718
|
+
action: "skipped",
|
|
719
|
+
path: promptPath,
|
|
720
|
+
reason: "existing file is not managed by vvoc",
|
|
721
|
+
};
|
|
722
|
+
}
|
|
723
|
+
const nextText = await renderManagedPrompt(agentName);
|
|
724
|
+
if (currentText === nextText) {
|
|
725
|
+
return { action: "kept", path: promptPath };
|
|
726
|
+
}
|
|
727
|
+
await writeText(promptPath, nextText);
|
|
728
|
+
return { action: "updated", path: promptPath };
|
|
729
|
+
}
|
|
730
|
+
function updateAgentEntryText(text, agentName, entry) {
|
|
731
|
+
const nextText = applyEdits(text, modify(text, ["agent", agentName], entry, {
|
|
732
|
+
formattingOptions: JSON_FORMAT,
|
|
733
|
+
}));
|
|
734
|
+
return ensureTrailingNewline(applyEdits(nextText, format(nextText, undefined, JSON_FORMAT)));
|
|
735
|
+
}
|
|
736
|
+
// END_BLOCK_MANAGED_SUBAGENT_HELPERS
|
|
516
737
|
function normalizeGuardianOverrides(raw, label) {
|
|
517
738
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
518
739
|
throw new Error(`${label}: expected a top-level object`);
|