opencode-agenthub 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +373 -0
  3. package/dist/composer/bootstrap.js +493 -0
  4. package/dist/composer/builtin-assets.js +139 -0
  5. package/dist/composer/capabilities.js +20 -0
  6. package/dist/composer/compose.js +824 -0
  7. package/dist/composer/defaults.js +10 -0
  8. package/dist/composer/home-transfer.js +288 -0
  9. package/dist/composer/install-home.js +5 -0
  10. package/dist/composer/library/README.md +93 -0
  11. package/dist/composer/library/bundles/auto.json +18 -0
  12. package/dist/composer/library/bundles/build.json +17 -0
  13. package/dist/composer/library/bundles/hr-adapter.json +26 -0
  14. package/dist/composer/library/bundles/hr-cto.json +24 -0
  15. package/dist/composer/library/bundles/hr-evaluator.json +26 -0
  16. package/dist/composer/library/bundles/hr-planner.json +26 -0
  17. package/dist/composer/library/bundles/hr-sourcer.json +24 -0
  18. package/dist/composer/library/bundles/hr-verifier.json +26 -0
  19. package/dist/composer/library/bundles/hr.json +35 -0
  20. package/dist/composer/library/bundles/plan.json +19 -0
  21. package/dist/composer/library/instructions/hr-boundaries.md +38 -0
  22. package/dist/composer/library/instructions/hr-protocol.md +102 -0
  23. package/dist/composer/library/profiles/auto.json +9 -0
  24. package/dist/composer/library/profiles/hr.json +9 -0
  25. package/dist/composer/library/souls/auto.md +29 -0
  26. package/dist/composer/library/souls/build.md +21 -0
  27. package/dist/composer/library/souls/hr-adapter.md +64 -0
  28. package/dist/composer/library/souls/hr-cto.md +57 -0
  29. package/dist/composer/library/souls/hr-evaluator.md +64 -0
  30. package/dist/composer/library/souls/hr-planner.md +48 -0
  31. package/dist/composer/library/souls/hr-sourcer.md +70 -0
  32. package/dist/composer/library/souls/hr-verifier.md +62 -0
  33. package/dist/composer/library/souls/hr.md +186 -0
  34. package/dist/composer/library/souls/plan.md +23 -0
  35. package/dist/composer/library/workflow/auto-mode.json +139 -0
  36. package/dist/composer/model-utils.js +39 -0
  37. package/dist/composer/opencode-profile.js +2299 -0
  38. package/dist/composer/package-manager.js +75 -0
  39. package/dist/composer/package-version.js +20 -0
  40. package/dist/composer/platform.js +48 -0
  41. package/dist/composer/query.js +133 -0
  42. package/dist/composer/settings.js +400 -0
  43. package/dist/plugins/opencode-agenthub.js +310 -0
  44. package/dist/plugins/opencode-question.js +223 -0
  45. package/dist/plugins/plan-guidance.js +263 -0
  46. package/dist/plugins/runtime-config.js +57 -0
  47. package/dist/skills/agenthub-doctor/SKILL.md +238 -0
  48. package/dist/skills/agenthub-doctor/diagnose.js +213 -0
  49. package/dist/skills/agenthub-doctor/fix.js +293 -0
  50. package/dist/skills/agenthub-doctor/index.js +30 -0
  51. package/dist/skills/agenthub-doctor/interactive.js +756 -0
  52. package/dist/skills/hr-assembly/SKILL.md +121 -0
  53. package/dist/skills/hr-final-check/SKILL.md +98 -0
  54. package/dist/skills/hr-review/SKILL.md +100 -0
  55. package/dist/skills/hr-staffing/SKILL.md +85 -0
  56. package/dist/skills/hr-support/bin/sync_sources.py +560 -0
  57. package/dist/skills/hr-support/bin/validate_staged_package.py +290 -0
  58. package/dist/skills/hr-support/bin/vendor_stage_mcps.py +234 -0
  59. package/dist/skills/hr-support/bin/vendor_stage_skills.py +104 -0
  60. package/dist/types.js +11 -0
  61. package/package.json +54 -0
@@ -0,0 +1,213 @@
1
+ import { readdir, readFile, access } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { readAgentHubSettings } from "../../composer/settings.js";
4
+ const readJson = async (filePath) => {
5
+ const content = await readFile(filePath, "utf-8");
6
+ return JSON.parse(content);
7
+ };
8
+ const pathExists = async (p) => {
9
+ try {
10
+ await access(p);
11
+ return true;
12
+ } catch {
13
+ return false;
14
+ }
15
+ };
16
+ const REQUIRED_GUARDS = ["read_only", "no_task", "no_omo"];
17
+ async function runDiagnostics(targetRoot) {
18
+ const report = {
19
+ healthy: [],
20
+ issues: [],
21
+ metadata: {
22
+ targetRoot,
23
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
24
+ }
25
+ };
26
+ const settingsPath = path.join(targetRoot, "settings.json");
27
+ if (!await pathExists(settingsPath)) {
28
+ report.issues.push({
29
+ type: "invalid_settings",
30
+ severity: "error",
31
+ message: "settings.json not found",
32
+ details: { path: settingsPath }
33
+ });
34
+ return report;
35
+ }
36
+ report.healthy.push("Settings file exists");
37
+ const settings = await readAgentHubSettings(targetRoot);
38
+ if (!settings) {
39
+ report.issues.push({
40
+ type: "invalid_settings",
41
+ severity: "error",
42
+ message: "Failed to read settings.json"
43
+ });
44
+ return report;
45
+ }
46
+ const missingGuards = await diagnoseMissingGuards(settings);
47
+ if (missingGuards.length > 0) {
48
+ report.issues.push({
49
+ type: "missing_guards",
50
+ severity: "warning",
51
+ message: `Missing guards: ${missingGuards.join(", ")}`,
52
+ details: { guards: missingGuards }
53
+ });
54
+ } else {
55
+ report.healthy.push("All required guards present");
56
+ }
57
+ const orphanedSouls = await diagnoseOrphanedSouls(targetRoot);
58
+ if (orphanedSouls.length > 0) {
59
+ report.issues.push({
60
+ type: "orphaned_souls",
61
+ severity: "warning",
62
+ message: `${orphanedSouls.length} souls not referenced by any bundle`,
63
+ details: { souls: orphanedSouls }
64
+ });
65
+ } else {
66
+ report.healthy.push("All souls have bundles");
67
+ }
68
+ const orphanedSkills = await diagnoseOrphanedSkills(targetRoot);
69
+ if (orphanedSkills.length > 0) {
70
+ report.issues.push({
71
+ type: "orphaned_skills",
72
+ severity: "info",
73
+ message: `${orphanedSkills.length} skills not referenced by any bundle`,
74
+ details: { skills: orphanedSkills }
75
+ });
76
+ }
77
+ const profilesExist = await diagnoseProfiles(targetRoot);
78
+ if (!profilesExist) {
79
+ report.issues.push({
80
+ type: "no_profiles",
81
+ severity: "error",
82
+ message: "No profiles found - cannot run agents"
83
+ });
84
+ } else {
85
+ report.healthy.push("Profiles exist");
86
+ }
87
+ const bundlesExist = await diagnoseBundles(targetRoot);
88
+ if (!bundlesExist) {
89
+ report.issues.push({
90
+ type: "no_bundles",
91
+ severity: "error",
92
+ message: "No bundles found - cannot compose agents"
93
+ });
94
+ } else {
95
+ report.healthy.push("Bundles exist");
96
+ }
97
+ const omoIssue = await diagnoseOmoMixedProfile(targetRoot);
98
+ if (omoIssue) {
99
+ report.issues.push(omoIssue);
100
+ }
101
+ return report;
102
+ }
103
+ async function diagnoseMissingGuards(settings) {
104
+ if (!settings) return REQUIRED_GUARDS;
105
+ const existingGuards = Object.keys(settings.guards || {});
106
+ return REQUIRED_GUARDS.filter((guard) => !existingGuards.includes(guard));
107
+ }
108
+ async function diagnoseOrphanedSouls(targetRoot) {
109
+ const soulsDir = path.join(targetRoot, "souls");
110
+ if (!await pathExists(soulsDir)) return [];
111
+ const entries = await readdir(soulsDir, { withFileTypes: true });
112
+ const soulNames = entries.filter((entry) => entry.isFile() && entry.name.endsWith(".md")).map((entry) => entry.name.replace(/\.md$/, ""));
113
+ const bundlesDir = path.join(targetRoot, "bundles");
114
+ if (!await pathExists(bundlesDir)) return soulNames;
115
+ const bundleEntries = await readdir(bundlesDir, { withFileTypes: true });
116
+ const referencedSouls = /* @__PURE__ */ new Set();
117
+ for (const entry of bundleEntries) {
118
+ if (!entry.isFile() || !entry.name.endsWith(".json")) continue;
119
+ try {
120
+ const bundlePath = path.join(bundlesDir, entry.name);
121
+ const bundle = await readJson(bundlePath);
122
+ if (bundle.soul) {
123
+ referencedSouls.add(bundle.soul);
124
+ }
125
+ } catch {
126
+ }
127
+ }
128
+ return soulNames.filter((soul) => !referencedSouls.has(soul));
129
+ }
130
+ async function diagnoseOrphanedSkills(targetRoot) {
131
+ const skillsDir = path.join(targetRoot, "skills");
132
+ if (!await pathExists(skillsDir)) return [];
133
+ const entries = await readdir(skillsDir, { withFileTypes: true });
134
+ const skillNames = entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);
135
+ const bundlesDir = path.join(targetRoot, "bundles");
136
+ if (!await pathExists(bundlesDir)) return skillNames;
137
+ const bundleEntries = await readdir(bundlesDir, { withFileTypes: true });
138
+ const referencedSkills = /* @__PURE__ */ new Set();
139
+ for (const entry of bundleEntries) {
140
+ if (!entry.isFile() || !entry.name.endsWith(".json")) continue;
141
+ try {
142
+ const bundlePath = path.join(bundlesDir, entry.name);
143
+ const bundle = await readJson(bundlePath);
144
+ if (bundle.skills) {
145
+ for (const skill of bundle.skills) {
146
+ referencedSkills.add(skill);
147
+ }
148
+ }
149
+ } catch {
150
+ }
151
+ }
152
+ return skillNames.filter((skill) => !referencedSkills.has(skill));
153
+ }
154
+ async function diagnoseProfiles(targetRoot) {
155
+ const profilesDir = path.join(targetRoot, "profiles");
156
+ if (!await pathExists(profilesDir)) return false;
157
+ const entries = await readdir(profilesDir, { withFileTypes: true });
158
+ return entries.some((entry) => entry.isFile() && entry.name.endsWith(".json"));
159
+ }
160
+ async function diagnoseBundles(targetRoot) {
161
+ const bundlesDir = path.join(targetRoot, "bundles");
162
+ if (!await pathExists(bundlesDir)) return false;
163
+ const entries = await readdir(bundlesDir, { withFileTypes: true });
164
+ return entries.some((entry) => entry.isFile() && entry.name.endsWith(".json"));
165
+ }
166
+ async function diagnoseOmoMixedProfile(targetRoot) {
167
+ const profilesDir = path.join(targetRoot, "profiles");
168
+ if (!await pathExists(profilesDir)) return null;
169
+ const profileEntries = await readdir(profilesDir, { withFileTypes: true });
170
+ const profileFiles = profileEntries.filter(
171
+ (e) => e.isFile() && e.name.endsWith(".json")
172
+ );
173
+ for (const profileEntry of profileFiles) {
174
+ const profilePath = path.join(profilesDir, profileEntry.name);
175
+ try {
176
+ const profile = await readJson(profilePath);
177
+ if (!profile.bundles || profile.bundles.length === 0) continue;
178
+ const bundlesDir = path.join(targetRoot, "bundles");
179
+ const omoBundles = [];
180
+ const nativeWithoutOmoGuard = [];
181
+ for (const bundleName of profile.bundles) {
182
+ const bundlePath = path.join(bundlesDir, `${bundleName}.json`);
183
+ if (!await pathExists(bundlePath)) continue;
184
+ const bundle = await readJson(bundlePath);
185
+ const runtime = bundle.runtime || "native";
186
+ if (runtime === "omo") {
187
+ omoBundles.push(bundleName);
188
+ } else if (runtime === "native") {
189
+ if (!bundle.guards?.includes("no_omo")) {
190
+ nativeWithoutOmoGuard.push(bundleName);
191
+ }
192
+ }
193
+ }
194
+ if (omoBundles.length > 0 && nativeWithoutOmoGuard.length > 0) {
195
+ return {
196
+ type: "omo_mixed_profile",
197
+ severity: "warning",
198
+ message: `Profile '${profileEntry.name.replace(".json", "")}' has OMO bundles but native agents lack no_omo guard`,
199
+ details: {
200
+ profile: profileEntry.name.replace(".json", ""),
201
+ omoBundles,
202
+ nativeWithoutOmoGuard
203
+ }
204
+ };
205
+ }
206
+ } catch {
207
+ }
208
+ }
209
+ return null;
210
+ }
211
+ export {
212
+ runDiagnostics
213
+ };
@@ -0,0 +1,293 @@
1
+ import path from "node:path";
2
+ import { readdir, readFile, writeFile, access } from "node:fs/promises";
3
+ import { getDefaultProfilePlugins } from "../../composer/defaults.js";
4
+ import { readAgentHubSettings, writeAgentHubSettings } from "../../composer/settings.js";
5
+ const readJson = async (filePath) => {
6
+ const content = await readFile(filePath, "utf-8");
7
+ return JSON.parse(content);
8
+ };
9
+ const writeJson = async (filePath, data) => {
10
+ await writeFile(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
11
+ };
12
+ const pathExists = async (p) => {
13
+ try {
14
+ await access(p);
15
+ return true;
16
+ } catch {
17
+ return false;
18
+ }
19
+ };
20
+ const DEFAULT_GUARDS = {
21
+ read_only: {
22
+ description: "Read-only access - no file modifications",
23
+ permission: {
24
+ edit: "deny",
25
+ write: "deny",
26
+ bash: "deny"
27
+ }
28
+ },
29
+ no_subagent: {
30
+ description: "Legacy alias for no_task",
31
+ blockedTools: ["task"],
32
+ permission: {
33
+ task: { "*": "deny" }
34
+ }
35
+ },
36
+ no_task: {
37
+ description: "Block task tool",
38
+ blockedTools: ["task"],
39
+ permission: {
40
+ task: { "*": "deny" }
41
+ }
42
+ },
43
+ no_omo: {
44
+ description: "Block OMO (Oh-My-OpenCode) multi-agent calls - for native agents in OMO profiles",
45
+ blockedTools: ["call_omo_agent"],
46
+ permission: {
47
+ call_omo_agent: "deny"
48
+ }
49
+ }
50
+ };
51
+ async function fixMissingGuards(targetRoot, guardsToAdd) {
52
+ try {
53
+ const settings = await readAgentHubSettings(targetRoot);
54
+ if (!settings) {
55
+ return {
56
+ success: false,
57
+ message: "settings.json not found or invalid"
58
+ };
59
+ }
60
+ if (!settings.guards) {
61
+ settings.guards = {};
62
+ }
63
+ let addedCount = 0;
64
+ for (const guardName of guardsToAdd) {
65
+ if (!settings.guards[guardName] && DEFAULT_GUARDS[guardName]) {
66
+ settings.guards[guardName] = DEFAULT_GUARDS[guardName];
67
+ addedCount++;
68
+ }
69
+ }
70
+ await writeAgentHubSettings(targetRoot, settings);
71
+ return {
72
+ success: true,
73
+ message: `Added ${addedCount} guard(s) to settings.json`,
74
+ details: { guards: guardsToAdd }
75
+ };
76
+ } catch (error) {
77
+ return {
78
+ success: false,
79
+ message: `Failed to fix guards: ${error.message}`
80
+ };
81
+ }
82
+ }
83
+ const readBundleAgentReferences = async (targetRoot, bundleNames) => Promise.all(
84
+ bundleNames.map(async (bundleName) => {
85
+ const bundlePath = path.join(targetRoot, "bundles", `${bundleName}.json`);
86
+ if (!await pathExists(bundlePath)) {
87
+ throw new Error(`Bundle '${bundleName}' not found in ${path.join(targetRoot, "bundles")}.`);
88
+ }
89
+ const bundle = await readJson(bundlePath);
90
+ const agentName = bundle.agent?.name?.trim();
91
+ if (!agentName) {
92
+ throw new Error(`Bundle '${bundleName}' is missing required agent.name.`);
93
+ }
94
+ return { bundleName, agentName };
95
+ })
96
+ );
97
+ async function resolveDefaultAgentForBundles(targetRoot, bundleNames, requestedDefaultAgent) {
98
+ const references = await readBundleAgentReferences(targetRoot, bundleNames);
99
+ const explicitDefaultAgent = requestedDefaultAgent?.trim();
100
+ if (explicitDefaultAgent) {
101
+ const bundleMatch = references.find(
102
+ (reference) => reference.bundleName === explicitDefaultAgent
103
+ );
104
+ if (bundleMatch && bundleMatch.agentName !== explicitDefaultAgent) {
105
+ throw new Error(
106
+ `Default agent '${explicitDefaultAgent}' matches bundle name, but profile defaultAgent must use bundle agent.name '${bundleMatch.agentName}'.`
107
+ );
108
+ }
109
+ if (references.some((reference) => reference.agentName === explicitDefaultAgent)) {
110
+ return explicitDefaultAgent;
111
+ }
112
+ return explicitDefaultAgent;
113
+ }
114
+ return references[0].agentName;
115
+ }
116
+ async function createBundleForSoul(targetRoot, soulName, options = {}) {
117
+ try {
118
+ const bundlesDir = path.join(targetRoot, "bundles");
119
+ const bundlePath = path.join(bundlesDir, `${soulName}.json`);
120
+ if (await pathExists(bundlePath)) {
121
+ return {
122
+ success: false,
123
+ message: `Bundle '${soulName}' already exists`
124
+ };
125
+ }
126
+ const bundle = {
127
+ name: soulName,
128
+ runtime: "native",
129
+ soul: soulName,
130
+ skills: options.skills || [],
131
+ mcp: options.mcp || [],
132
+ agent: {
133
+ name: options.agentName ?? soulName,
134
+ mode: options.mode ?? "primary",
135
+ model: options.model || "github-copilot/claude-sonnet-4.5",
136
+ description: "Auto-generated bundle for imported soul"
137
+ }
138
+ };
139
+ if (options.guards && options.guards.length > 0) {
140
+ bundle.guards = options.guards;
141
+ }
142
+ await writeJson(bundlePath, bundle);
143
+ return {
144
+ success: true,
145
+ message: `Created bundle '${soulName}'`,
146
+ details: { path: bundlePath }
147
+ };
148
+ } catch (error) {
149
+ return {
150
+ success: false,
151
+ message: `Failed to create bundle for '${soulName}': ${error.message}`
152
+ };
153
+ }
154
+ }
155
+ async function createBundlesForSouls(targetRoot, soulNames, options = {}) {
156
+ const results = [];
157
+ for (const soulName of soulNames) {
158
+ const result = await createBundleForSoul(targetRoot, soulName, options);
159
+ results.push(result);
160
+ }
161
+ const successCount = results.filter((r) => r.success).length;
162
+ const failureCount = results.length - successCount;
163
+ return {
164
+ success: successCount > 0,
165
+ message: `Created ${successCount} bundle(s)${failureCount > 0 ? `, ${failureCount} failed` : ""}`,
166
+ details: { results }
167
+ };
168
+ }
169
+ async function createProfile(targetRoot, profileName, options = {}) {
170
+ try {
171
+ const profilesDir = path.join(targetRoot, "profiles");
172
+ const profilePath = path.join(profilesDir, `${profileName}.json`);
173
+ if (await pathExists(profilePath)) {
174
+ return {
175
+ success: false,
176
+ message: `Profile '${profileName}' already exists`
177
+ };
178
+ }
179
+ let bundleNames = options.bundleNames;
180
+ if (!bundleNames) {
181
+ bundleNames = await getAllBundleNames(targetRoot);
182
+ }
183
+ if (bundleNames.length === 0) {
184
+ return {
185
+ success: false,
186
+ message: "No bundles found to include in profile"
187
+ };
188
+ }
189
+ const defaultAgent = await resolveDefaultAgentForBundles(
190
+ targetRoot,
191
+ bundleNames,
192
+ options.defaultAgent
193
+ );
194
+ const profile = {
195
+ name: profileName,
196
+ description: options.description || "Auto-generated profile for imported assets",
197
+ bundles: bundleNames,
198
+ defaultAgent,
199
+ plugins: getDefaultProfilePlugins()
200
+ };
201
+ await writeJson(profilePath, profile);
202
+ return {
203
+ success: true,
204
+ message: `Created profile '${profileName}' with ${bundleNames.length} bundle(s)`,
205
+ details: { path: profilePath, bundles: bundleNames }
206
+ };
207
+ } catch (error) {
208
+ return {
209
+ success: false,
210
+ message: `Failed to create profile '${profileName}': ${error.message}`
211
+ };
212
+ }
213
+ }
214
+ async function getAllBundleNames(targetRoot) {
215
+ const bundlesDir = path.join(targetRoot, "bundles");
216
+ if (!await pathExists(bundlesDir)) return [];
217
+ const entries = await readdir(bundlesDir, { withFileTypes: true });
218
+ return entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.replace(/\.json$/, ""));
219
+ }
220
+ async function validateAndFix(targetRoot, options = {}) {
221
+ const results = [];
222
+ if (options.fixGuards) {
223
+ const guardsResult = await fixMissingGuards(targetRoot, [
224
+ "read_only",
225
+ "no_task",
226
+ "no_omo"
227
+ ]);
228
+ results.push(guardsResult);
229
+ }
230
+ if (options.createBundles) {
231
+ const { runDiagnostics } = await import("./diagnose.js");
232
+ const report = await runDiagnostics(targetRoot);
233
+ const orphanedSoulsIssue = report.issues.find((i) => i.type === "orphaned_souls");
234
+ if (orphanedSoulsIssue && orphanedSoulsIssue.details) {
235
+ const souls = orphanedSoulsIssue.details.souls;
236
+ if (souls.length > 0) {
237
+ const bundlesResult = await createBundlesForSouls(targetRoot, souls, {
238
+ model: options.model
239
+ });
240
+ results.push(bundlesResult);
241
+ }
242
+ }
243
+ }
244
+ if (options.createProfile) {
245
+ const profileResult = await createProfile(
246
+ targetRoot,
247
+ options.profileName || "imported"
248
+ );
249
+ results.push(profileResult);
250
+ }
251
+ return results;
252
+ }
253
+ async function fixOmoMixedProfile(targetRoot, details) {
254
+ try {
255
+ const bundlesDir = path.join(targetRoot, "bundles");
256
+ const fixed = [];
257
+ for (const bundleName of details.nativeWithoutOmoGuard) {
258
+ const bundlePath = path.join(bundlesDir, `${bundleName}.json`);
259
+ if (!await pathExists(bundlePath)) continue;
260
+ const bundle = await readJson(bundlePath);
261
+ if (!bundle.guards?.includes("no_omo")) {
262
+ bundle.guards = [...bundle.guards || [], "no_omo"];
263
+ await writeJson(bundlePath, bundle);
264
+ fixed.push(bundleName);
265
+ }
266
+ }
267
+ if (fixed.length === 0) {
268
+ return {
269
+ success: true,
270
+ message: "All native agents already have no_omo guard"
271
+ };
272
+ }
273
+ return {
274
+ success: true,
275
+ message: `Added no_omo guard to ${fixed.length} native agent(s): ${fixed.join(", ")}`,
276
+ details: { fixed }
277
+ };
278
+ } catch (error) {
279
+ return {
280
+ success: false,
281
+ message: `Failed to fix OMO mixed profile: ${error.message}`
282
+ };
283
+ }
284
+ }
285
+ export {
286
+ createBundleForSoul,
287
+ createBundlesForSouls,
288
+ createProfile,
289
+ fixMissingGuards,
290
+ fixOmoMixedProfile,
291
+ resolveDefaultAgentForBundles,
292
+ validateAndFix
293
+ };
@@ -0,0 +1,30 @@
1
+ import { runDiagnostics } from "./diagnose.js";
2
+ import {
3
+ fixMissingGuards,
4
+ createBundleForSoul,
5
+ createBundlesForSouls,
6
+ createProfile,
7
+ validateAndFix,
8
+ fixOmoMixedProfile
9
+ } from "./fix.js";
10
+ import {
11
+ interactiveAssembly,
12
+ interactiveDoctor,
13
+ updateAgentModelOverride,
14
+ updateAgentPromptOverride
15
+ } from "./interactive.js";
16
+ import { getAvailableBundles } from "./interactive.js";
17
+ export {
18
+ createBundleForSoul,
19
+ createBundlesForSouls,
20
+ createProfile,
21
+ fixMissingGuards,
22
+ fixOmoMixedProfile,
23
+ getAvailableBundles,
24
+ interactiveAssembly,
25
+ interactiveDoctor,
26
+ runDiagnostics,
27
+ updateAgentModelOverride,
28
+ updateAgentPromptOverride,
29
+ validateAndFix
30
+ };