@grant-vine/wunderkind 0.8.0 → 0.9.2
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/.claude-plugin/plugin.json +1 -1
- package/README.md +209 -27
- package/commands/docs-index.md +44 -0
- package/dist/agents/docs-config.d.ts +6 -0
- package/dist/agents/docs-config.d.ts.map +1 -1
- package/dist/agents/docs-config.js +15 -1
- package/dist/agents/docs-config.js.map +1 -1
- package/dist/agents/docs-index-plan.d.ts +28 -0
- package/dist/agents/docs-index-plan.d.ts.map +1 -0
- package/dist/agents/docs-index-plan.js +118 -0
- package/dist/agents/docs-index-plan.js.map +1 -0
- package/dist/cli/cli-installer.d.ts +9 -1
- package/dist/cli/cli-installer.d.ts.map +1 -1
- package/dist/cli/cli-installer.js +65 -7
- package/dist/cli/cli-installer.js.map +1 -1
- package/dist/cli/config-manager/index.d.ts +17 -1
- package/dist/cli/config-manager/index.d.ts.map +1 -1
- package/dist/cli/config-manager/index.js +415 -177
- package/dist/cli/config-manager/index.js.map +1 -1
- package/dist/cli/doctor.d.ts +4 -0
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +113 -35
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/index.js +69 -22
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/init.d.ts +0 -4
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +144 -38
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/personality-meta.d.ts +8 -0
- package/dist/cli/personality-meta.d.ts.map +1 -0
- package/dist/cli/personality-meta.js +213 -0
- package/dist/cli/personality-meta.js.map +1 -0
- package/dist/cli/tui-installer.d.ts.map +1 -1
- package/dist/cli/tui-installer.js +57 -42
- package/dist/cli/tui-installer.js.map +1 -1
- package/dist/cli/types.d.ts +34 -22
- package/dist/cli/types.d.ts.map +1 -1
- package/dist/cli/uninstall.d.ts +6 -0
- package/dist/cli/uninstall.d.ts.map +1 -0
- package/dist/cli/uninstall.js +64 -0
- package/dist/cli/uninstall.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -8
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
- package/schemas/wunderkind.config.schema.json +67 -0
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
4
5
|
import { parse as parseJsonc } from "jsonc-parser";
|
|
5
6
|
const PACKAGE_NAME = "@grant-vine/wunderkind";
|
|
7
|
+
const WUNDERKIND_SCHEMA_URL = "https://raw.githubusercontent.com/grant-vine/wunderkind/main/schemas/wunderkind.config.schema.json";
|
|
6
8
|
const CONFIG_DIR = join(homedir(), ".config", "opencode");
|
|
7
9
|
const CONFIG_JSON = join(CONFIG_DIR, "opencode.json");
|
|
8
10
|
const CONFIG_JSONC = join(CONFIG_DIR, "opencode.jsonc");
|
|
@@ -13,16 +15,107 @@ const GLOBAL_WUNDERKIND_CONFIG = join(GLOBAL_WUNDERKIND_DIR, "wunderkind.config.
|
|
|
13
15
|
const WUNDERKIND_DIR = join(process.cwd(), ".wunderkind");
|
|
14
16
|
const WUNDERKIND_CONFIG = join(WUNDERKIND_DIR, "wunderkind.config.jsonc");
|
|
15
17
|
const LEGACY_WUNDERKIND_CONFIG = join(process.cwd(), "wunderkind.config.jsonc");
|
|
16
|
-
|
|
18
|
+
const PROJECT_CONFIG_KEYS = [
|
|
19
|
+
"teamCulture",
|
|
20
|
+
"orgStructure",
|
|
21
|
+
"cisoPersonality",
|
|
22
|
+
"ctoPersonality",
|
|
23
|
+
"cmoPersonality",
|
|
24
|
+
"qaPersonality",
|
|
25
|
+
"productPersonality",
|
|
26
|
+
"opsPersonality",
|
|
27
|
+
"creativePersonality",
|
|
28
|
+
"brandPersonality",
|
|
29
|
+
"devrelPersonality",
|
|
30
|
+
"legalPersonality",
|
|
31
|
+
"supportPersonality",
|
|
32
|
+
"dataAnalystPersonality",
|
|
33
|
+
"docsEnabled",
|
|
34
|
+
"docsPath",
|
|
35
|
+
"docHistoryMode",
|
|
36
|
+
];
|
|
37
|
+
const DEFAULT_INSTALL_CONFIG = {
|
|
38
|
+
region: "Global",
|
|
39
|
+
industry: "",
|
|
40
|
+
primaryRegulation: "GDPR",
|
|
41
|
+
secondaryRegulation: "",
|
|
42
|
+
teamCulture: "pragmatic-balanced",
|
|
43
|
+
orgStructure: "flat",
|
|
44
|
+
cisoPersonality: "pragmatic-risk-manager",
|
|
45
|
+
ctoPersonality: "code-archaeologist",
|
|
46
|
+
cmoPersonality: "data-driven",
|
|
47
|
+
qaPersonality: "risk-based-pragmatist",
|
|
48
|
+
productPersonality: "outcome-obsessed",
|
|
49
|
+
opsPersonality: "on-call-veteran",
|
|
50
|
+
creativePersonality: "pragmatic-problem-solver",
|
|
51
|
+
brandPersonality: "authentic-builder",
|
|
52
|
+
devrelPersonality: "dx-engineer",
|
|
53
|
+
legalPersonality: "pragmatic-advisor",
|
|
54
|
+
supportPersonality: "systematic-triage",
|
|
55
|
+
dataAnalystPersonality: "insight-storyteller",
|
|
56
|
+
docsEnabled: false,
|
|
57
|
+
docsPath: "./docs",
|
|
58
|
+
docHistoryMode: "overwrite",
|
|
59
|
+
};
|
|
60
|
+
const DEFAULT_GLOBAL_CONFIG = {
|
|
61
|
+
region: DEFAULT_INSTALL_CONFIG.region,
|
|
62
|
+
industry: DEFAULT_INSTALL_CONFIG.industry,
|
|
63
|
+
primaryRegulation: DEFAULT_INSTALL_CONFIG.primaryRegulation,
|
|
64
|
+
secondaryRegulation: DEFAULT_INSTALL_CONFIG.secondaryRegulation,
|
|
65
|
+
};
|
|
66
|
+
const DEFAULT_PROJECT_CONFIG = {
|
|
67
|
+
teamCulture: DEFAULT_INSTALL_CONFIG.teamCulture,
|
|
68
|
+
orgStructure: DEFAULT_INSTALL_CONFIG.orgStructure,
|
|
69
|
+
cisoPersonality: DEFAULT_INSTALL_CONFIG.cisoPersonality,
|
|
70
|
+
ctoPersonality: DEFAULT_INSTALL_CONFIG.ctoPersonality,
|
|
71
|
+
cmoPersonality: DEFAULT_INSTALL_CONFIG.cmoPersonality,
|
|
72
|
+
qaPersonality: DEFAULT_INSTALL_CONFIG.qaPersonality,
|
|
73
|
+
productPersonality: DEFAULT_INSTALL_CONFIG.productPersonality,
|
|
74
|
+
opsPersonality: DEFAULT_INSTALL_CONFIG.opsPersonality,
|
|
75
|
+
creativePersonality: DEFAULT_INSTALL_CONFIG.creativePersonality,
|
|
76
|
+
brandPersonality: DEFAULT_INSTALL_CONFIG.brandPersonality,
|
|
77
|
+
devrelPersonality: DEFAULT_INSTALL_CONFIG.devrelPersonality,
|
|
78
|
+
legalPersonality: DEFAULT_INSTALL_CONFIG.legalPersonality,
|
|
79
|
+
supportPersonality: DEFAULT_INSTALL_CONFIG.supportPersonality,
|
|
80
|
+
dataAnalystPersonality: DEFAULT_INSTALL_CONFIG.dataAnalystPersonality,
|
|
81
|
+
docsEnabled: DEFAULT_INSTALL_CONFIG.docsEnabled,
|
|
82
|
+
docsPath: DEFAULT_INSTALL_CONFIG.docsPath,
|
|
83
|
+
docHistoryMode: DEFAULT_INSTALL_CONFIG.docHistoryMode,
|
|
84
|
+
};
|
|
85
|
+
export function getDefaultInstallConfig() {
|
|
86
|
+
return { ...DEFAULT_INSTALL_CONFIG };
|
|
87
|
+
}
|
|
88
|
+
export function getDefaultGlobalConfig() {
|
|
89
|
+
return { ...DEFAULT_GLOBAL_CONFIG };
|
|
90
|
+
}
|
|
91
|
+
export function getDefaultProjectConfig() {
|
|
92
|
+
return { ...DEFAULT_PROJECT_CONFIG };
|
|
93
|
+
}
|
|
94
|
+
export function resolveOpenCodeConfigPath(scope) {
|
|
95
|
+
if (scope === "project") {
|
|
96
|
+
const projectJson = join(process.cwd(), "opencode.json");
|
|
97
|
+
const projectJsonc = join(process.cwd(), "opencode.jsonc");
|
|
98
|
+
const projectLegacyJson = join(process.cwd(), "config.json");
|
|
99
|
+
const projectLegacyJsonc = join(process.cwd(), "config.jsonc");
|
|
100
|
+
if (existsSync(projectJson))
|
|
101
|
+
return { path: projectJson, format: "json", source: "opencode.json" };
|
|
102
|
+
if (existsSync(projectJsonc))
|
|
103
|
+
return { path: projectJsonc, format: "jsonc", source: "opencode.jsonc" };
|
|
104
|
+
if (existsSync(projectLegacyJson))
|
|
105
|
+
return { path: projectLegacyJson, format: "json", source: "config.json" };
|
|
106
|
+
if (existsSync(projectLegacyJsonc))
|
|
107
|
+
return { path: projectLegacyJsonc, format: "jsonc", source: "config.jsonc" };
|
|
108
|
+
return { path: projectJson, format: "none", source: "default" };
|
|
109
|
+
}
|
|
17
110
|
if (existsSync(CONFIG_JSON))
|
|
18
|
-
return { path: CONFIG_JSON, format: "json" };
|
|
111
|
+
return { path: CONFIG_JSON, format: "json", source: "opencode.json" };
|
|
19
112
|
if (existsSync(CONFIG_JSONC))
|
|
20
|
-
return { path: CONFIG_JSONC, format: "jsonc" };
|
|
113
|
+
return { path: CONFIG_JSONC, format: "jsonc", source: "opencode.jsonc" };
|
|
21
114
|
if (existsSync(LEGACY_CONFIG_JSON))
|
|
22
|
-
return { path: LEGACY_CONFIG_JSON, format: "json" };
|
|
115
|
+
return { path: LEGACY_CONFIG_JSON, format: "json", source: "config.json" };
|
|
23
116
|
if (existsSync(LEGACY_CONFIG_JSONC))
|
|
24
|
-
return { path: LEGACY_CONFIG_JSONC, format: "jsonc" };
|
|
25
|
-
return { path: CONFIG_JSON, format: "none" };
|
|
117
|
+
return { path: LEGACY_CONFIG_JSONC, format: "jsonc", source: "config.jsonc" };
|
|
118
|
+
return { path: CONFIG_JSON, format: "none", source: "default" };
|
|
26
119
|
}
|
|
27
120
|
function parseConfig(path) {
|
|
28
121
|
try {
|
|
@@ -50,128 +143,280 @@ function parseWunderkindConfig(path) {
|
|
|
50
143
|
return null;
|
|
51
144
|
}
|
|
52
145
|
}
|
|
146
|
+
function coerceGlobalConfig(source) {
|
|
147
|
+
const result = {};
|
|
148
|
+
if (typeof source["region"] === "string")
|
|
149
|
+
result.region = source["region"];
|
|
150
|
+
if (typeof source["industry"] === "string")
|
|
151
|
+
result.industry = source["industry"];
|
|
152
|
+
if (typeof source["primaryRegulation"] === "string")
|
|
153
|
+
result.primaryRegulation = source["primaryRegulation"];
|
|
154
|
+
if (typeof source["secondaryRegulation"] === "string")
|
|
155
|
+
result.secondaryRegulation = source["secondaryRegulation"];
|
|
156
|
+
return result;
|
|
157
|
+
}
|
|
158
|
+
function coerceProjectConfig(source) {
|
|
159
|
+
const result = {};
|
|
160
|
+
if (typeof source["teamCulture"] === "string")
|
|
161
|
+
result.teamCulture = source["teamCulture"];
|
|
162
|
+
if (typeof source["orgStructure"] === "string")
|
|
163
|
+
result.orgStructure = source["orgStructure"];
|
|
164
|
+
if (typeof source["cisoPersonality"] === "string")
|
|
165
|
+
result.cisoPersonality = source["cisoPersonality"];
|
|
166
|
+
if (typeof source["ctoPersonality"] === "string")
|
|
167
|
+
result.ctoPersonality = source["ctoPersonality"];
|
|
168
|
+
if (typeof source["cmoPersonality"] === "string")
|
|
169
|
+
result.cmoPersonality = source["cmoPersonality"];
|
|
170
|
+
if (typeof source["qaPersonality"] === "string")
|
|
171
|
+
result.qaPersonality = source["qaPersonality"];
|
|
172
|
+
if (typeof source["productPersonality"] === "string") {
|
|
173
|
+
result.productPersonality = source["productPersonality"];
|
|
174
|
+
}
|
|
175
|
+
if (typeof source["opsPersonality"] === "string")
|
|
176
|
+
result.opsPersonality = source["opsPersonality"];
|
|
177
|
+
if (typeof source["creativePersonality"] === "string") {
|
|
178
|
+
result.creativePersonality = source["creativePersonality"];
|
|
179
|
+
}
|
|
180
|
+
if (typeof source["brandPersonality"] === "string")
|
|
181
|
+
result.brandPersonality = source["brandPersonality"];
|
|
182
|
+
if (typeof source["devrelPersonality"] === "string")
|
|
183
|
+
result.devrelPersonality = source["devrelPersonality"];
|
|
184
|
+
if (typeof source["legalPersonality"] === "string")
|
|
185
|
+
result.legalPersonality = source["legalPersonality"];
|
|
186
|
+
if (typeof source["supportPersonality"] === "string") {
|
|
187
|
+
result.supportPersonality = source["supportPersonality"];
|
|
188
|
+
}
|
|
189
|
+
if (typeof source["dataAnalystPersonality"] === "string") {
|
|
190
|
+
result.dataAnalystPersonality = source["dataAnalystPersonality"];
|
|
191
|
+
}
|
|
192
|
+
if (typeof source["docsEnabled"] === "boolean")
|
|
193
|
+
result.docsEnabled = source["docsEnabled"];
|
|
194
|
+
if (typeof source["docsPath"] === "string")
|
|
195
|
+
result.docsPath = source["docsPath"];
|
|
196
|
+
if (typeof source["docHistoryMode"] === "string")
|
|
197
|
+
result.docHistoryMode = source["docHistoryMode"];
|
|
198
|
+
return result;
|
|
199
|
+
}
|
|
200
|
+
function listLegacyGlobalProjectFields(source) {
|
|
201
|
+
return PROJECT_CONFIG_KEYS.filter((key) => key in source);
|
|
202
|
+
}
|
|
203
|
+
function hasWunderkindPlugin(plugins) {
|
|
204
|
+
return plugins.some((p) => p === PACKAGE_NAME || p === "wunderkind" || p.startsWith(`${PACKAGE_NAME}@`) || p.startsWith("wunderkind@"));
|
|
205
|
+
}
|
|
206
|
+
function detectRegistration() {
|
|
207
|
+
const projectResolution = resolveOpenCodeConfigPath("project");
|
|
208
|
+
const globalResolution = resolveOpenCodeConfigPath("global");
|
|
209
|
+
const projectOpenCodeConfigPath = projectResolution.path;
|
|
210
|
+
const globalOpenCodeConfigPath = globalResolution.path;
|
|
211
|
+
const projectConfig = existsSync(projectOpenCodeConfigPath) ? parseConfig(projectOpenCodeConfigPath) : null;
|
|
212
|
+
const globalConfig = existsSync(globalOpenCodeConfigPath) ? parseConfig(globalOpenCodeConfigPath) : null;
|
|
213
|
+
const projectInstalled = hasWunderkindPlugin((projectConfig?.plugin ?? []));
|
|
214
|
+
const globalInstalled = hasWunderkindPlugin((globalConfig?.plugin ?? []));
|
|
215
|
+
let registrationScope = "none";
|
|
216
|
+
if (projectInstalled && globalInstalled) {
|
|
217
|
+
registrationScope = "both";
|
|
218
|
+
}
|
|
219
|
+
else if (projectInstalled) {
|
|
220
|
+
registrationScope = "project";
|
|
221
|
+
}
|
|
222
|
+
else if (globalInstalled) {
|
|
223
|
+
registrationScope = "global";
|
|
224
|
+
}
|
|
225
|
+
return {
|
|
226
|
+
projectInstalled,
|
|
227
|
+
globalInstalled,
|
|
228
|
+
registrationScope,
|
|
229
|
+
projectOpenCodeConfigPath,
|
|
230
|
+
globalOpenCodeConfigPath,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
53
233
|
export function readWunderkindConfig() {
|
|
54
234
|
const projectConfig = existsSync(WUNDERKIND_CONFIG) ? parseWunderkindConfig(WUNDERKIND_CONFIG) : null;
|
|
55
235
|
const globalConfig = existsSync(GLOBAL_WUNDERKIND_CONFIG) ? parseWunderkindConfig(GLOBAL_WUNDERKIND_CONFIG) : null;
|
|
56
236
|
if (!projectConfig && !globalConfig) {
|
|
57
237
|
return null;
|
|
58
238
|
}
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
239
|
+
const globalSafe = coerceGlobalConfig(globalConfig ?? {});
|
|
240
|
+
const projectLocal = coerceProjectConfig(projectConfig ?? {});
|
|
241
|
+
return {
|
|
242
|
+
...globalSafe,
|
|
243
|
+
...projectLocal,
|
|
62
244
|
};
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
245
|
+
}
|
|
246
|
+
export function readGlobalWunderkindConfig() {
|
|
247
|
+
const globalConfig = existsSync(GLOBAL_WUNDERKIND_CONFIG) ? parseWunderkindConfig(GLOBAL_WUNDERKIND_CONFIG) : null;
|
|
248
|
+
return globalConfig ? coerceGlobalConfig(globalConfig) : null;
|
|
249
|
+
}
|
|
250
|
+
export function readProjectWunderkindConfig() {
|
|
251
|
+
const projectConfig = existsSync(WUNDERKIND_CONFIG) ? parseWunderkindConfig(WUNDERKIND_CONFIG) : null;
|
|
252
|
+
return projectConfig ? coerceProjectConfig(projectConfig) : null;
|
|
253
|
+
}
|
|
254
|
+
function ensureConfigDir(configDir, configPath) {
|
|
255
|
+
try {
|
|
256
|
+
if (!existsSync(configDir)) {
|
|
257
|
+
mkdirSync(configDir, { recursive: true });
|
|
258
|
+
}
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
catch (err) {
|
|
262
|
+
return { success: false, configPath, error: String(err) };
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
function renderGlobalWunderkindConfig(config) {
|
|
266
|
+
return [
|
|
267
|
+
`// Wunderkind global configuration — safe defaults shared across projects`,
|
|
268
|
+
`{`,
|
|
269
|
+
` "$schema": ${JSON.stringify(WUNDERKIND_SCHEMA_URL)},`,
|
|
270
|
+
` // Geographic region — e.g. "South Africa", "United States", "United Kingdom", "Australia"`,
|
|
271
|
+
` "region": ${JSON.stringify(config.region)},`,
|
|
272
|
+
` // Industry vertical — e.g. "SaaS", "FinTech", "eCommerce", "HealthTech"`,
|
|
273
|
+
` "industry": ${JSON.stringify(config.industry)},`,
|
|
274
|
+
` // Primary data-protection regulation — e.g. "GDPR", "POPIA", "CCPA", "LGPD"`,
|
|
275
|
+
` "primaryRegulation": ${JSON.stringify(config.primaryRegulation)},`,
|
|
276
|
+
` // Optional secondary regulation`,
|
|
277
|
+
` "secondaryRegulation": ${JSON.stringify(config.secondaryRegulation)}`,
|
|
278
|
+
`}`,
|
|
279
|
+
``,
|
|
280
|
+
].join("\n");
|
|
281
|
+
}
|
|
282
|
+
function renderProjectWunderkindConfig(config) {
|
|
283
|
+
return [
|
|
284
|
+
`// Wunderkind project configuration — edit these values to tailor agents to this project`,
|
|
285
|
+
`{`,
|
|
286
|
+
` "$schema": ${JSON.stringify(WUNDERKIND_SCHEMA_URL)},`,
|
|
287
|
+
` // Team culture baseline — affects all agents' communication style and decision rigour`,
|
|
288
|
+
` // "formal-strict" | "pragmatic-balanced" | "experimental-informal"`,
|
|
289
|
+
` "teamCulture": ${JSON.stringify(config.teamCulture)},`,
|
|
290
|
+
` // Org structure — "flat" (peers, escalate to user) | "hierarchical" (domain authority applies, CISO has hard veto)`,
|
|
291
|
+
` "orgStructure": ${JSON.stringify(config.orgStructure)},`,
|
|
292
|
+
``,
|
|
293
|
+
` // Agent personalities — controls each agent's default character archetype`,
|
|
294
|
+
` // CISO: "paranoid-enforcer" | "pragmatic-risk-manager" | "educator-collaborator"`,
|
|
295
|
+
` "cisoPersonality": ${JSON.stringify(config.cisoPersonality)},`,
|
|
296
|
+
` // CTO/Fullstack: "grizzled-sysadmin" | "startup-bro" | "code-archaeologist"`,
|
|
297
|
+
` "ctoPersonality": ${JSON.stringify(config.ctoPersonality)},`,
|
|
298
|
+
` // CMO/Marketing: "data-driven" | "brand-storyteller" | "growth-hacker"`,
|
|
299
|
+
` "cmoPersonality": ${JSON.stringify(config.cmoPersonality)},`,
|
|
300
|
+
` // QA: "rule-enforcer" | "risk-based-pragmatist" | "rubber-duck"`,
|
|
301
|
+
` "qaPersonality": ${JSON.stringify(config.qaPersonality)},`,
|
|
302
|
+
` // Product: "user-advocate" | "velocity-optimizer" | "outcome-obsessed"`,
|
|
303
|
+
` "productPersonality": ${JSON.stringify(config.productPersonality)},`,
|
|
304
|
+
` // Operations: "on-call-veteran" | "efficiency-maximiser" | "process-purist"`,
|
|
305
|
+
` "opsPersonality": ${JSON.stringify(config.opsPersonality)},`,
|
|
306
|
+
` // Creative Director: "perfectionist-craftsperson" | "bold-provocateur" | "pragmatic-problem-solver"`,
|
|
307
|
+
` "creativePersonality": ${JSON.stringify(config.creativePersonality)},`,
|
|
308
|
+
` // Brand Builder: "community-evangelist" | "pr-spinner" | "authentic-builder"`,
|
|
309
|
+
` "brandPersonality": ${JSON.stringify(config.brandPersonality)},`,
|
|
310
|
+
` // DevRel Wunderkind: "community-champion" | "docs-perfectionist" | "dx-engineer"`,
|
|
311
|
+
` "devrelPersonality": ${JSON.stringify(config.devrelPersonality)},`,
|
|
312
|
+
` // Legal Counsel: "cautious-gatekeeper" | "pragmatic-advisor" | "plain-english-counselor"`,
|
|
313
|
+
` "legalPersonality": ${JSON.stringify(config.legalPersonality)},`,
|
|
314
|
+
` // Support Engineer: "empathetic-resolver" | "systematic-triage" | "knowledge-builder"`,
|
|
315
|
+
` "supportPersonality": ${JSON.stringify(config.supportPersonality)},`,
|
|
316
|
+
` // Data Analyst: "rigorous-statistician" | "insight-storyteller" | "pragmatic-quant"`,
|
|
317
|
+
` "dataAnalystPersonality": ${JSON.stringify(config.dataAnalystPersonality)},`,
|
|
318
|
+
``,
|
|
319
|
+
` // Docs output settings`,
|
|
320
|
+
` // Enable or disable writing docs outputs to disk`,
|
|
321
|
+
` "docsEnabled": ${JSON.stringify(config.docsEnabled)},`,
|
|
322
|
+
` // Directory path where docs outputs are written`,
|
|
323
|
+
` "docsPath": ${JSON.stringify(config.docsPath)},`,
|
|
324
|
+
` // History mode: "overwrite" | "append-dated" | "new-dated-file" | "overwrite-archive"`,
|
|
325
|
+
` "docHistoryMode": ${JSON.stringify(config.docHistoryMode)}`,
|
|
326
|
+
`}`,
|
|
327
|
+
``,
|
|
328
|
+
].join("\n");
|
|
329
|
+
}
|
|
330
|
+
export function writeGlobalWunderkindConfig(config) {
|
|
331
|
+
const setupError = ensureConfigDir(GLOBAL_WUNDERKIND_DIR, GLOBAL_WUNDERKIND_CONFIG);
|
|
332
|
+
if (setupError)
|
|
333
|
+
return setupError;
|
|
334
|
+
try {
|
|
335
|
+
writeFileSync(GLOBAL_WUNDERKIND_CONFIG, renderGlobalWunderkindConfig(config));
|
|
336
|
+
return { success: true, configPath: GLOBAL_WUNDERKIND_CONFIG };
|
|
337
|
+
}
|
|
338
|
+
catch (err) {
|
|
339
|
+
return { success: false, configPath: GLOBAL_WUNDERKIND_CONFIG, error: String(err) };
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
export function writeProjectWunderkindConfig(config) {
|
|
343
|
+
const setupError = ensureConfigDir(WUNDERKIND_DIR, WUNDERKIND_CONFIG);
|
|
344
|
+
if (setupError)
|
|
345
|
+
return setupError;
|
|
346
|
+
try {
|
|
347
|
+
writeFileSync(WUNDERKIND_CONFIG, renderProjectWunderkindConfig(config));
|
|
348
|
+
return { success: true, configPath: WUNDERKIND_CONFIG };
|
|
349
|
+
}
|
|
350
|
+
catch (err) {
|
|
351
|
+
return { success: false, configPath: WUNDERKIND_CONFIG, error: String(err) };
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
export function readWunderkindConfigForScope(scope) {
|
|
355
|
+
if (scope === "global") {
|
|
356
|
+
return readGlobalWunderkindConfig();
|
|
357
|
+
}
|
|
358
|
+
return readProjectWunderkindConfig();
|
|
109
359
|
}
|
|
110
360
|
export function detectCurrentConfig() {
|
|
111
|
-
const
|
|
361
|
+
const projectResolution = resolveOpenCodeConfigPath("project");
|
|
362
|
+
const globalResolution = resolveOpenCodeConfigPath("global");
|
|
363
|
+
const defaults = getDefaultInstallConfig();
|
|
364
|
+
const detectedDefaults = {
|
|
112
365
|
isInstalled: false,
|
|
113
366
|
scope: "global",
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
cisoPersonality: "pragmatic-risk-manager",
|
|
121
|
-
ctoPersonality: "code-archaeologist",
|
|
122
|
-
cmoPersonality: "data-driven",
|
|
123
|
-
qaPersonality: "risk-based-pragmatist",
|
|
124
|
-
productPersonality: "outcome-obsessed",
|
|
125
|
-
opsPersonality: "on-call-veteran",
|
|
126
|
-
creativePersonality: "pragmatic-problem-solver",
|
|
127
|
-
brandPersonality: "authentic-builder",
|
|
128
|
-
devrelPersonality: "dx-engineer",
|
|
129
|
-
legalPersonality: "pragmatic-advisor",
|
|
130
|
-
supportPersonality: "systematic-triage",
|
|
131
|
-
dataAnalystPersonality: "insight-storyteller",
|
|
132
|
-
docsEnabled: false,
|
|
133
|
-
docsPath: "./docs",
|
|
134
|
-
docHistoryMode: "overwrite",
|
|
367
|
+
projectInstalled: false,
|
|
368
|
+
globalInstalled: false,
|
|
369
|
+
registrationScope: "none",
|
|
370
|
+
projectOpenCodeConfigPath: projectResolution.path,
|
|
371
|
+
globalOpenCodeConfigPath: globalResolution.path,
|
|
372
|
+
...defaults,
|
|
135
373
|
};
|
|
136
|
-
const
|
|
137
|
-
if (
|
|
138
|
-
return
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
const
|
|
374
|
+
const registration = detectRegistration();
|
|
375
|
+
if (registration.registrationScope === "none") {
|
|
376
|
+
return {
|
|
377
|
+
...detectedDefaults,
|
|
378
|
+
...registration,
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
const globalConfig = existsSync(GLOBAL_WUNDERKIND_CONFIG) ? parseWunderkindConfig(GLOBAL_WUNDERKIND_CONFIG) : null;
|
|
382
|
+
const legacyGlobalProjectFields = globalConfig ? listLegacyGlobalProjectFields(globalConfig) : [];
|
|
383
|
+
const globalSafe = readGlobalWunderkindConfig();
|
|
384
|
+
const projectLocal = readProjectWunderkindConfig();
|
|
385
|
+
const legacyGlobalProject = coerceProjectConfig(globalConfig ?? {});
|
|
147
386
|
return {
|
|
148
387
|
isInstalled: true,
|
|
149
|
-
scope: "global",
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
388
|
+
scope: registration.projectInstalled ? "project" : "global",
|
|
389
|
+
projectInstalled: registration.projectInstalled,
|
|
390
|
+
globalInstalled: registration.globalInstalled,
|
|
391
|
+
registrationScope: registration.registrationScope,
|
|
392
|
+
projectOpenCodeConfigPath: registration.projectOpenCodeConfigPath,
|
|
393
|
+
globalOpenCodeConfigPath: registration.globalOpenCodeConfigPath,
|
|
394
|
+
legacyGlobalProjectFields,
|
|
395
|
+
region: globalSafe?.region ?? defaults.region,
|
|
396
|
+
industry: globalSafe?.industry ?? defaults.industry,
|
|
397
|
+
primaryRegulation: globalSafe?.primaryRegulation ?? defaults.primaryRegulation,
|
|
398
|
+
secondaryRegulation: globalSafe?.secondaryRegulation ?? defaults.secondaryRegulation,
|
|
399
|
+
teamCulture: projectLocal?.teamCulture ?? legacyGlobalProject.teamCulture ?? defaults.teamCulture,
|
|
400
|
+
orgStructure: projectLocal?.orgStructure ?? legacyGlobalProject.orgStructure ?? defaults.orgStructure,
|
|
401
|
+
cisoPersonality: projectLocal?.cisoPersonality ?? legacyGlobalProject.cisoPersonality ?? defaults.cisoPersonality,
|
|
402
|
+
ctoPersonality: projectLocal?.ctoPersonality ?? legacyGlobalProject.ctoPersonality ?? defaults.ctoPersonality,
|
|
403
|
+
cmoPersonality: projectLocal?.cmoPersonality ?? legacyGlobalProject.cmoPersonality ?? defaults.cmoPersonality,
|
|
404
|
+
qaPersonality: projectLocal?.qaPersonality ?? legacyGlobalProject.qaPersonality ?? defaults.qaPersonality,
|
|
405
|
+
productPersonality: projectLocal?.productPersonality ?? legacyGlobalProject.productPersonality ?? defaults.productPersonality,
|
|
406
|
+
opsPersonality: projectLocal?.opsPersonality ?? legacyGlobalProject.opsPersonality ?? defaults.opsPersonality,
|
|
407
|
+
creativePersonality: projectLocal?.creativePersonality ?? legacyGlobalProject.creativePersonality ?? defaults.creativePersonality,
|
|
408
|
+
brandPersonality: projectLocal?.brandPersonality ?? legacyGlobalProject.brandPersonality ?? defaults.brandPersonality,
|
|
409
|
+
devrelPersonality: projectLocal?.devrelPersonality ?? legacyGlobalProject.devrelPersonality ?? defaults.devrelPersonality,
|
|
410
|
+
legalPersonality: projectLocal?.legalPersonality ?? legacyGlobalProject.legalPersonality ?? defaults.legalPersonality,
|
|
411
|
+
supportPersonality: projectLocal?.supportPersonality ?? legacyGlobalProject.supportPersonality ?? defaults.supportPersonality,
|
|
412
|
+
dataAnalystPersonality: projectLocal?.dataAnalystPersonality ?? legacyGlobalProject.dataAnalystPersonality ?? defaults.dataAnalystPersonality,
|
|
413
|
+
docsEnabled: projectLocal?.docsEnabled ?? legacyGlobalProject.docsEnabled ?? defaults.docsEnabled,
|
|
414
|
+
docsPath: projectLocal?.docsPath ?? legacyGlobalProject.docsPath ?? defaults.docsPath,
|
|
415
|
+
docHistoryMode: projectLocal?.docHistoryMode ?? legacyGlobalProject.docHistoryMode ?? defaults.docHistoryMode,
|
|
171
416
|
};
|
|
172
417
|
}
|
|
173
418
|
export function addPluginToOpenCodeConfig(scope) {
|
|
174
|
-
const targetPath = scope
|
|
419
|
+
const targetPath = resolveOpenCodeConfigPath(scope).path;
|
|
175
420
|
const targetDir = scope === "project" ? process.cwd() : CONFIG_DIR;
|
|
176
421
|
try {
|
|
177
422
|
if (!existsSync(targetDir)) {
|
|
@@ -189,7 +434,7 @@ export function addPluginToOpenCodeConfig(scope) {
|
|
|
189
434
|
}
|
|
190
435
|
const config = parseConfig(targetPath) ?? {};
|
|
191
436
|
const plugins = (config.plugin ?? []);
|
|
192
|
-
const already = plugins
|
|
437
|
+
const already = hasWunderkindPlugin(plugins);
|
|
193
438
|
if (already) {
|
|
194
439
|
const idx = plugins.findIndex((p) => p === "wunderkind" || p.startsWith("wunderkind@"));
|
|
195
440
|
if (idx !== -1) {
|
|
@@ -209,79 +454,72 @@ export function addPluginToOpenCodeConfig(scope) {
|
|
|
209
454
|
}
|
|
210
455
|
}
|
|
211
456
|
export function writeWunderkindConfig(installConfig, scope) {
|
|
212
|
-
|
|
213
|
-
|
|
457
|
+
if (scope === "global") {
|
|
458
|
+
return writeGlobalWunderkindConfig(installConfig);
|
|
459
|
+
}
|
|
460
|
+
return writeProjectWunderkindConfig(installConfig);
|
|
461
|
+
}
|
|
462
|
+
export function detectLegacyConfig() {
|
|
463
|
+
return existsSync(LEGACY_WUNDERKIND_CONFIG);
|
|
464
|
+
}
|
|
465
|
+
export function removePluginFromOpenCodeConfig(scope) {
|
|
466
|
+
const targetPath = resolveOpenCodeConfigPath(scope).path;
|
|
214
467
|
try {
|
|
215
|
-
if (!existsSync(
|
|
216
|
-
|
|
468
|
+
if (!existsSync(targetPath)) {
|
|
469
|
+
return { success: true, configPath: targetPath, changed: false };
|
|
470
|
+
}
|
|
471
|
+
const config = parseConfig(targetPath);
|
|
472
|
+
if (!config) {
|
|
473
|
+
return { success: false, configPath: targetPath, error: "Invalid OpenCode config format" };
|
|
474
|
+
}
|
|
475
|
+
const plugins = (config.plugin ?? []);
|
|
476
|
+
if (plugins.length === 0) {
|
|
477
|
+
return { success: true, configPath: targetPath, changed: false };
|
|
478
|
+
}
|
|
479
|
+
const filtered = plugins.filter((p) => !(p === PACKAGE_NAME || p === "wunderkind" || p.startsWith(`${PACKAGE_NAME}@`) || p.startsWith("wunderkind@")));
|
|
480
|
+
if (filtered.length === plugins.length) {
|
|
481
|
+
return { success: true, configPath: targetPath, changed: false };
|
|
217
482
|
}
|
|
483
|
+
if (filtered.length === 0) {
|
|
484
|
+
delete config.plugin;
|
|
485
|
+
}
|
|
486
|
+
else {
|
|
487
|
+
config.plugin = filtered;
|
|
488
|
+
}
|
|
489
|
+
writeFileSync(targetPath, JSON.stringify(config, null, 2) + "\n");
|
|
490
|
+
return { success: true, configPath: targetPath, changed: true };
|
|
218
491
|
}
|
|
219
492
|
catch (err) {
|
|
220
|
-
return { success: false, configPath, error: String(err) };
|
|
493
|
+
return { success: false, configPath: targetPath, error: String(err) };
|
|
221
494
|
}
|
|
495
|
+
}
|
|
496
|
+
export function writeOmoAgentConfig(targetDir) {
|
|
497
|
+
const omoConfigPath = join(targetDir, ".opencode", "oh-my-opencode.jsonc");
|
|
222
498
|
try {
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
` "industry": ${JSON.stringify(installConfig.industry)},`,
|
|
230
|
-
` // Primary data-protection regulation — e.g. "GDPR", "POPIA", "CCPA", "LGPD"`,
|
|
231
|
-
` "primaryRegulation": ${JSON.stringify(installConfig.primaryRegulation)},`,
|
|
232
|
-
` // Optional secondary regulation`,
|
|
233
|
-
` "secondaryRegulation": ${JSON.stringify(installConfig.secondaryRegulation)},`,
|
|
234
|
-
``,
|
|
235
|
-
` // Team culture baseline — affects all agents' communication style and decision rigour`,
|
|
236
|
-
` // "formal-strict" | "pragmatic-balanced" | "experimental-informal"`,
|
|
237
|
-
` "teamCulture": ${JSON.stringify(installConfig.teamCulture)},`,
|
|
238
|
-
` // Org structure — "flat" (peers, escalate to user) | "hierarchical" (domain authority applies, CISO has hard veto)`,
|
|
239
|
-
` "orgStructure": ${JSON.stringify(installConfig.orgStructure)},`,
|
|
240
|
-
``,
|
|
241
|
-
` // Agent personalities — controls each agent's default character archetype`,
|
|
242
|
-
` // CISO: "paranoid-enforcer" | "pragmatic-risk-manager" | "educator-collaborator"`,
|
|
243
|
-
` "cisoPersonality": ${JSON.stringify(installConfig.cisoPersonality)},`,
|
|
244
|
-
` // CTO/Fullstack: "grizzled-sysadmin" | "startup-bro" | "code-archaeologist"`,
|
|
245
|
-
` "ctoPersonality": ${JSON.stringify(installConfig.ctoPersonality)},`,
|
|
246
|
-
` // CMO/Marketing: "data-driven" | "brand-storyteller" | "growth-hacker"`,
|
|
247
|
-
` "cmoPersonality": ${JSON.stringify(installConfig.cmoPersonality)},`,
|
|
248
|
-
` // QA: "rule-enforcer" | "risk-based-pragmatist" | "rubber-duck"`,
|
|
249
|
-
` "qaPersonality": ${JSON.stringify(installConfig.qaPersonality)},`,
|
|
250
|
-
` // Product: "user-advocate" | "velocity-optimizer" | "outcome-obsessed"`,
|
|
251
|
-
` "productPersonality": ${JSON.stringify(installConfig.productPersonality)},`,
|
|
252
|
-
` // Operations: "on-call-veteran" | "efficiency-maximiser" | "process-purist"`,
|
|
253
|
-
` "opsPersonality": ${JSON.stringify(installConfig.opsPersonality)},`,
|
|
254
|
-
` // Creative Director: "perfectionist-craftsperson" | "bold-provocateur" | "pragmatic-problem-solver"`,
|
|
255
|
-
` "creativePersonality": ${JSON.stringify(installConfig.creativePersonality)},`,
|
|
256
|
-
` // Brand Builder: "community-evangelist" | "pr-spinner" | "authentic-builder"`,
|
|
257
|
-
` "brandPersonality": ${JSON.stringify(installConfig.brandPersonality)},`,
|
|
258
|
-
` // DevRel Wunderkind: "community-champion" | "docs-perfectionist" | "dx-engineer"`,
|
|
259
|
-
` "devrelPersonality": ${JSON.stringify(installConfig.devrelPersonality)},`,
|
|
260
|
-
` // Legal Counsel: "cautious-gatekeeper" | "pragmatic-advisor" | "plain-english-counselor"`,
|
|
261
|
-
` "legalPersonality": ${JSON.stringify(installConfig.legalPersonality)},`,
|
|
262
|
-
` // Support Engineer: "empathetic-resolver" | "systematic-triage" | "knowledge-builder"`,
|
|
263
|
-
` "supportPersonality": ${JSON.stringify(installConfig.supportPersonality)},`,
|
|
264
|
-
` // Data Analyst: "rigorous-statistician" | "insight-storyteller" | "pragmatic-quant"`,
|
|
265
|
-
` "dataAnalystPersonality": ${JSON.stringify(installConfig.dataAnalystPersonality)},`,
|
|
266
|
-
``,
|
|
267
|
-
` // Docs output settings`,
|
|
268
|
-
` // Enable or disable writing docs outputs to disk`,
|
|
269
|
-
` "docsEnabled": ${JSON.stringify(installConfig.docsEnabled)},`,
|
|
270
|
-
` // Directory path where docs outputs are written`,
|
|
271
|
-
` "docsPath": ${JSON.stringify(installConfig.docsPath)},`,
|
|
272
|
-
` // History mode: "overwrite" | "append-dated" | "new-dated-file" | "overwrite-archive"`,
|
|
273
|
-
` "docHistoryMode": ${JSON.stringify(installConfig.docHistoryMode)}`,
|
|
274
|
-
`}`,
|
|
275
|
-
``,
|
|
276
|
-
].join("\n");
|
|
277
|
-
writeFileSync(configPath, content);
|
|
278
|
-
return { success: true, configPath };
|
|
499
|
+
const sourceUrl = new URL("../../../oh-my-opencode.jsonc", import.meta.url);
|
|
500
|
+
const sourceFilePath = fileURLToPath(sourceUrl);
|
|
501
|
+
const contents = readFileSync(sourceFilePath, "utf-8");
|
|
502
|
+
mkdirSync(join(targetDir, ".opencode"), { recursive: true });
|
|
503
|
+
writeFileSync(omoConfigPath, contents);
|
|
504
|
+
return { success: true, configPath: omoConfigPath };
|
|
279
505
|
}
|
|
280
506
|
catch (err) {
|
|
281
|
-
return { success: false, configPath, error: String(err) };
|
|
507
|
+
return { success: false, configPath: omoConfigPath, error: String(err) };
|
|
282
508
|
}
|
|
283
509
|
}
|
|
284
|
-
export function
|
|
285
|
-
|
|
510
|
+
export function removeGlobalWunderkindConfig() {
|
|
511
|
+
try {
|
|
512
|
+
if (!existsSync(GLOBAL_WUNDERKIND_CONFIG)) {
|
|
513
|
+
return { success: true, configPath: GLOBAL_WUNDERKIND_CONFIG, changed: false };
|
|
514
|
+
}
|
|
515
|
+
rmSync(GLOBAL_WUNDERKIND_CONFIG, { force: true });
|
|
516
|
+
if (existsSync(GLOBAL_WUNDERKIND_DIR) && readdirSync(GLOBAL_WUNDERKIND_DIR).length === 0) {
|
|
517
|
+
rmSync(GLOBAL_WUNDERKIND_DIR, { recursive: false, force: true });
|
|
518
|
+
}
|
|
519
|
+
return { success: true, configPath: GLOBAL_WUNDERKIND_CONFIG, changed: true };
|
|
520
|
+
}
|
|
521
|
+
catch (err) {
|
|
522
|
+
return { success: false, configPath: GLOBAL_WUNDERKIND_CONFIG, error: String(err) };
|
|
523
|
+
}
|
|
286
524
|
}
|
|
287
525
|
//# sourceMappingURL=index.js.map
|