hermes-action-bridge 0.2.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 (74) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/CONTRIBUTING.md +28 -0
  3. package/LICENSE +21 -0
  4. package/README.md +323 -0
  5. package/dist/adapters/hermes-cli.d.ts +3 -0
  6. package/dist/adapters/hermes-cli.js +48 -0
  7. package/dist/adapters/hermes-cli.js.map +1 -0
  8. package/dist/cli.d.ts +2 -0
  9. package/dist/cli.js +271 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/config.d.ts +5 -0
  12. package/dist/config.js +172 -0
  13. package/dist/config.js.map +1 -0
  14. package/dist/context.d.ts +2 -0
  15. package/dist/context.js +15 -0
  16. package/dist/context.js.map +1 -0
  17. package/dist/doctor.d.ts +18 -0
  18. package/dist/doctor.js +77 -0
  19. package/dist/doctor.js.map +1 -0
  20. package/dist/install/file-edit.d.ts +12 -0
  21. package/dist/install/file-edit.js +18 -0
  22. package/dist/install/file-edit.js.map +1 -0
  23. package/dist/install/install-service.d.ts +26 -0
  24. package/dist/install/install-service.js +59 -0
  25. package/dist/install/install-service.js.map +1 -0
  26. package/dist/install/managed-file.d.ts +9 -0
  27. package/dist/install/managed-file.js +157 -0
  28. package/dist/install/managed-file.js.map +1 -0
  29. package/dist/install/marker-block.d.ts +10 -0
  30. package/dist/install/marker-block.js +61 -0
  31. package/dist/install/marker-block.js.map +1 -0
  32. package/dist/install/mcp-config.d.ts +15 -0
  33. package/dist/install/mcp-config.js +65 -0
  34. package/dist/install/mcp-config.js.map +1 -0
  35. package/dist/install/paths.d.ts +6 -0
  36. package/dist/install/paths.js +22 -0
  37. package/dist/install/paths.js.map +1 -0
  38. package/dist/install/templates.d.ts +16 -0
  39. package/dist/install/templates.js +86 -0
  40. package/dist/install/templates.js.map +1 -0
  41. package/dist/install/types.d.ts +18 -0
  42. package/dist/install/types.js +2 -0
  43. package/dist/install/types.js.map +1 -0
  44. package/dist/mcp-server.d.ts +1 -0
  45. package/dist/mcp-server.js +69 -0
  46. package/dist/mcp-server.js.map +1 -0
  47. package/dist/policy.d.ts +9 -0
  48. package/dist/policy.js +25 -0
  49. package/dist/policy.js.map +1 -0
  50. package/dist/prompt.d.ts +2 -0
  51. package/dist/prompt.js +34 -0
  52. package/dist/prompt.js.map +1 -0
  53. package/dist/run.d.ts +2 -0
  54. package/dist/run.js +27 -0
  55. package/dist/run.js.map +1 -0
  56. package/dist/status.d.ts +8 -0
  57. package/dist/status.js +10 -0
  58. package/dist/status.js.map +1 -0
  59. package/dist/types.d.ts +77 -0
  60. package/dist/types.js +2 -0
  61. package/dist/types.js.map +1 -0
  62. package/dist/version.d.ts +1 -0
  63. package/dist/version.js +12 -0
  64. package/dist/version.js.map +1 -0
  65. package/docs/ARCHITECTURE.md +105 -0
  66. package/docs/FUNCTIONAL-TESTS.md +97 -0
  67. package/examples/claude-code/CLAUDE.md +21 -0
  68. package/examples/claude-code/SKILL.md +55 -0
  69. package/examples/codex/AGENTS.md +21 -0
  70. package/examples/codex/SKILL.md +55 -0
  71. package/examples/configs/basic.yaml +36 -0
  72. package/examples/configs/strict.yaml +26 -0
  73. package/examples/configs/yolo.yaml +19 -0
  74. package/package.json +59 -0
package/dist/cli.js ADDED
@@ -0,0 +1,271 @@
1
+ #!/usr/bin/env node
2
+ import { mkdirSync, writeFileSync } from "node:fs";
3
+ import { homedir } from "node:os";
4
+ import { dirname, resolve } from "node:path";
5
+ import { Argument, Command, Option } from "commander";
6
+ import { defaultProjectConfig, loadConfig } from "./config.js";
7
+ import { buildEffectiveRun } from "./run.js";
8
+ import { runHermesCli } from "./adapters/hermes-cli.js";
9
+ import { checkHermesStatus } from "./status.js";
10
+ import { startMcpServer } from "./mcp-server.js";
11
+ import { version } from "./version.js";
12
+ import { installHint, installSkills, previewSkills, uninstallHint, uninstallSkills } from "./install/install-service.js";
13
+ import { mcpSnippets, removeMcpJson, writeMcpJson } from "./install/mcp-config.js";
14
+ import { coreChecks, formatDoctor, probeCheck, toReport } from "./doctor.js";
15
+ const program = new Command();
16
+ program
17
+ .name("hermes-action")
18
+ .description("Delegate actions from external agents to Hermes Agent through configurable policies and presets.")
19
+ .version(version);
20
+ program
21
+ .command("init")
22
+ .description("Create a project .hermes-action.yaml config file")
23
+ .option("-f, --file <path>", "config file path", ".hermes-action.yaml")
24
+ .option("--force", "overwrite existing file", false)
25
+ .action((options) => {
26
+ const path = resolve(process.cwd(), options.file);
27
+ mkdirSync(dirname(path), { recursive: true });
28
+ if (!options.force) {
29
+ try {
30
+ writeFileSync(path, defaultProjectConfig(), { flag: "wx" });
31
+ }
32
+ catch (error) {
33
+ if (error.code === "EEXIST") {
34
+ throw new Error(`Config already exists: ${path}. Use --force to overwrite.`);
35
+ }
36
+ throw error;
37
+ }
38
+ }
39
+ else {
40
+ writeFileSync(path, defaultProjectConfig());
41
+ }
42
+ console.log(`Created ${path}`);
43
+ });
44
+ program
45
+ .command("run")
46
+ .description("Delegate a request to Hermes")
47
+ .argument("<prompt...>", "request for Hermes")
48
+ .addOption(new Option("--mode <mode>", "execution mode").choices(["plan", "draft", "execute", "request-approval"]))
49
+ .option("--preset <name>", "config preset")
50
+ .option("--context <path...>", "context file(s) to include", [])
51
+ .option("--config <path>", "config file path")
52
+ .option("--profile <name>", "Hermes profile")
53
+ .option("--provider <name>", "Hermes provider")
54
+ .option("--model <name>", "Hermes model")
55
+ .option("--max-turns <number>", "Hermes max tool-calling iterations", parsePositiveInt)
56
+ .option("--source <name>", "Hermes source tag")
57
+ .option("--yolo", "bypass bridge policy and pass --yolo to Hermes", false)
58
+ .option("--dry-run", "print the Hermes command and prompt without executing", false)
59
+ .option("--json", "print structured JSON", false)
60
+ .action(async (promptParts, options) => {
61
+ const config = loadConfig(process.cwd(), options.config);
62
+ const run = buildEffectiveRun(config, {
63
+ prompt: promptParts.join(" "),
64
+ mode: options.mode,
65
+ preset: options.preset,
66
+ contextFiles: options.context || [],
67
+ yolo: options.yolo,
68
+ dryRun: options.dryRun,
69
+ json: options.json,
70
+ profile: options.profile,
71
+ provider: options.provider,
72
+ model: options.model,
73
+ maxTurns: options.maxTurns,
74
+ source: options.source,
75
+ });
76
+ const result = await runHermesCli(config, run, options.dryRun);
77
+ if (options.json) {
78
+ console.log(JSON.stringify({ ...result, effective: { mode: run.mode, requestedMode: run.requestedMode, preset: run.presetName, yolo: run.yolo, detectedRisks: run.detectedRisks } }, null, 2));
79
+ }
80
+ else {
81
+ if (result.stdout.trim())
82
+ console.log(result.stdout.trimEnd());
83
+ if (result.stderr.trim())
84
+ console.error(result.stderr.trimEnd());
85
+ }
86
+ process.exitCode = result.exitCode;
87
+ });
88
+ program
89
+ .command("presets")
90
+ .description("List configured presets")
91
+ .option("--config <path>", "config file path")
92
+ .option("--json", "print structured JSON", false)
93
+ .action((options) => {
94
+ const config = loadConfig(process.cwd(), options.config);
95
+ if (options.json) {
96
+ console.log(JSON.stringify(config.presets, null, 2));
97
+ return;
98
+ }
99
+ for (const [name, preset] of Object.entries(config.presets)) {
100
+ console.log(`${name}${preset.description ? ` - ${preset.description}` : ""}`);
101
+ }
102
+ });
103
+ program
104
+ .command("status")
105
+ .description("Check the configured Hermes command")
106
+ .option("--config <path>", "config file path")
107
+ .option("--json", "print structured JSON", false)
108
+ .action((options) => {
109
+ const config = loadConfig(process.cwd(), options.config);
110
+ const status = checkHermesStatus(config);
111
+ if (options.json)
112
+ console.log(JSON.stringify(status, null, 2));
113
+ else
114
+ console.log(status.available ? `Hermes available: ${status.version}` : `Hermes unavailable: ${status.error}`);
115
+ process.exitCode = status.available ? 0 : 1;
116
+ });
117
+ program
118
+ .command("mcp")
119
+ .description("Run an MCP server exposing hermes_run, hermes_plan, hermes_presets, and hermes_status")
120
+ .option("--config <path>", "config file path")
121
+ .action(async (options) => {
122
+ await startMcpServer(options.config);
123
+ });
124
+ program
125
+ .command("install")
126
+ .description("Install the hermes-action-bridge skill (or print/write MCP config) for a coding agent")
127
+ .addArgument(new Argument("<target>", "which agent").choices(["claude-code", "codex", "all", "mcp"]))
128
+ .option("--project", "install a project-local skill instead of the global one", false)
129
+ .option("--project-hint", "also add a hint block to CLAUDE.md / AGENTS.md", false)
130
+ .option("--mcp", "also print the MCP config snippets", false)
131
+ .option("--write", "for the mcp target, write/merge the project .mcp.json (Claude Code)", false)
132
+ .option("--force", "replace an existing managed skill", false)
133
+ .option("--dry-run", "print planned operations, write nothing", false)
134
+ .option("--print", "print the generated skill content, write nothing", false)
135
+ .option("--yes", "non-interactive", false)
136
+ .action((target, options) => {
137
+ const ctx = pathContext();
138
+ if (target === "mcp") {
139
+ if (options.write)
140
+ reportChange(writeMcpJson(mcpJsonPath(ctx), options.dryRun), options.dryRun);
141
+ else
142
+ printMcpSnippets();
143
+ return;
144
+ }
145
+ const skillTarget = target;
146
+ const scope = options.project ? "project" : "global";
147
+ if (options.print) {
148
+ for (const preview of previewSkills(skillTarget, ctx, scope)) {
149
+ for (const file of preview.files) {
150
+ console.log(`# ${preview.agent} -> ${file.path}`);
151
+ console.log(file.content);
152
+ }
153
+ }
154
+ return;
155
+ }
156
+ const opts = serviceOptions(options, scope);
157
+ const results = installSkills(skillTarget, ctx, opts);
158
+ if (options.projectHint)
159
+ results.push(...installHint(skillTarget, ctx, opts));
160
+ reportResults(results, options.dryRun);
161
+ if (options.mcp)
162
+ printMcpSnippets();
163
+ });
164
+ program
165
+ .command("uninstall")
166
+ .description("Remove the hermes-action-bridge skill (or MCP config) for a coding agent")
167
+ .addArgument(new Argument("<target>", "which agent").choices(["claude-code", "codex", "all", "mcp"]))
168
+ .option("--project", "remove a project-local skill instead of the global one", false)
169
+ .option("--project-hint", "also remove the CLAUDE.md / AGENTS.md hint block", false)
170
+ .option("--write", "for the mcp target, remove hermes-action from the project .mcp.json", false)
171
+ .option("--force", "remove even a locally modified skill", false)
172
+ .option("--dry-run", "print planned removals, write nothing", false)
173
+ .option("--yes", "non-interactive", false)
174
+ .action((target, options) => {
175
+ const ctx = pathContext();
176
+ if (target === "mcp") {
177
+ if (options.write)
178
+ reportChange(removeMcpJson(mcpJsonPath(ctx), options.dryRun), options.dryRun);
179
+ else
180
+ console.log("Use --write to remove hermes-action from the project .mcp.json.");
181
+ return;
182
+ }
183
+ const skillTarget = target;
184
+ const scope = options.project ? "project" : "global";
185
+ const opts = serviceOptions(options, scope);
186
+ const results = uninstallSkills(skillTarget, ctx, opts);
187
+ if (options.projectHint)
188
+ results.push(...uninstallHint(skillTarget, ctx, opts));
189
+ reportResults(results, options.dryRun);
190
+ });
191
+ program
192
+ .command("doctor")
193
+ .description("Check the environment for using hermes-action and its skills")
194
+ .option("--config <path>", "config file path")
195
+ .option("--json", "print structured JSON", false)
196
+ .option("--probe", "additionally run a live Hermes plan call (spends provider tokens)", false)
197
+ .action(async (options) => {
198
+ const ctx = pathContext();
199
+ let config = null;
200
+ let configError;
201
+ try {
202
+ config = loadConfig(ctx.cwd, options.config);
203
+ }
204
+ catch (error) {
205
+ configError = error instanceof Error ? error.message : String(error);
206
+ }
207
+ const checks = coreChecks(config, ctx, configError);
208
+ if (options.probe && config) {
209
+ try {
210
+ checks.push(await probeCheck(config));
211
+ }
212
+ catch (error) {
213
+ checks.push({ id: "probe", status: "warn", detail: error instanceof Error ? error.message : String(error) });
214
+ }
215
+ }
216
+ const report = toReport(checks);
217
+ console.log(options.json ? JSON.stringify(report, null, 2) : formatDoctor(report));
218
+ process.exitCode = report.ok ? 0 : 1;
219
+ });
220
+ program.parseAsync(process.argv).catch((error) => {
221
+ console.error(error instanceof Error ? error.message : String(error));
222
+ process.exitCode = 1;
223
+ });
224
+ function parsePositiveInt(value) {
225
+ const parsed = Number.parseInt(value, 10);
226
+ if (!Number.isInteger(parsed) || parsed <= 0)
227
+ throw new Error(`Expected a positive integer, got: ${value}`);
228
+ return parsed;
229
+ }
230
+ function pathContext() {
231
+ return { homeDir: homedir(), cwd: process.cwd() };
232
+ }
233
+ function mcpJsonPath(ctx) {
234
+ return resolve(ctx.cwd, ".mcp.json");
235
+ }
236
+ function serviceOptions(options, scope) {
237
+ return { scope, force: options.force, dryRun: options.dryRun };
238
+ }
239
+ function printMcpSnippets() {
240
+ for (const snippet of mcpSnippets()) {
241
+ console.log(`# ${snippet.client} (${snippet.location})`);
242
+ console.log(snippet.content);
243
+ }
244
+ }
245
+ function reportChange(change, dryRun) {
246
+ if (change.action === "refused") {
247
+ console.error(`refused (${change.reason ?? "unknown reason"})`);
248
+ process.exitCode = 1;
249
+ }
250
+ else {
251
+ console.log(`${change.action} ${change.path}${dryRun ? " (dry-run)" : ""}`);
252
+ }
253
+ }
254
+ function reportResults(results, dryRun) {
255
+ for (const result of results) {
256
+ if (result.changes.length === 0) {
257
+ console.log(`${result.agent}: nothing to do`);
258
+ continue;
259
+ }
260
+ for (const change of result.changes) {
261
+ if (change.action === "refused") {
262
+ console.error(`${result.agent}: refused (${change.reason ?? "unknown reason"})`);
263
+ }
264
+ else {
265
+ console.log(`${result.agent}: ${change.action} ${change.path}${dryRun ? " (dry-run)" : ""}`);
266
+ }
267
+ }
268
+ }
269
+ process.exitCode = results.every((result) => result.ok) ? 0 : 1;
270
+ }
271
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,EAAE,aAAa,EAAE,eAAe,EAA4D,MAAM,8BAA8B,CAAC;AACnL,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACnF,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAK7E,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAC9B,OAAO;KACJ,IAAI,CAAC,eAAe,CAAC;KACrB,WAAW,CAAC,kGAAkG,CAAC;KAC/G,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,kDAAkD,CAAC;KAC/D,MAAM,CAAC,mBAAmB,EAAE,kBAAkB,EAAE,qBAAqB,CAAC;KACtE,MAAM,CAAC,SAAS,EAAE,yBAAyB,EAAE,KAAK,CAAC;KACnD,MAAM,CAAC,CAAC,OAAyC,EAAE,EAAE;IACpD,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACnB,IAAI,CAAC;YACH,aAAa,CAAC,IAAI,EAAE,oBAAoB,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACvD,MAAM,IAAI,KAAK,CAAC,0BAA0B,IAAI,6BAA6B,CAAC,CAAC;YAC/E,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;SAAM,CAAC;QACN,aAAa,CAAC,IAAI,EAAE,oBAAoB,EAAE,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;AACjC,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,KAAK,CAAC;KACd,WAAW,CAAC,8BAA8B,CAAC;KAC3C,QAAQ,CAAC,aAAa,EAAE,oBAAoB,CAAC;KAC7C,SAAS,CAAC,IAAI,MAAM,CAAC,eAAe,EAAE,gBAAgB,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,kBAAkB,CAAC,CAAC,CAAC;KAClH,MAAM,CAAC,iBAAiB,EAAE,eAAe,CAAC;KAC1C,MAAM,CAAC,qBAAqB,EAAE,4BAA4B,EAAE,EAAE,CAAC;KAC/D,MAAM,CAAC,iBAAiB,EAAE,kBAAkB,CAAC;KAC7C,MAAM,CAAC,kBAAkB,EAAE,gBAAgB,CAAC;KAC5C,MAAM,CAAC,mBAAmB,EAAE,iBAAiB,CAAC;KAC9C,MAAM,CAAC,gBAAgB,EAAE,cAAc,CAAC;KACxC,MAAM,CAAC,sBAAsB,EAAE,oCAAoC,EAAE,gBAAgB,CAAC;KACtF,MAAM,CAAC,iBAAiB,EAAE,mBAAmB,CAAC;KAC9C,MAAM,CAAC,QAAQ,EAAE,gDAAgD,EAAE,KAAK,CAAC;KACzE,MAAM,CAAC,WAAW,EAAE,uDAAuD,EAAE,KAAK,CAAC;KACnF,MAAM,CAAC,QAAQ,EAAE,uBAAuB,EAAE,KAAK,CAAC;KAChD,MAAM,CAAC,KAAK,EAAE,WAAqB,EAAE,OAA0B,EAAE,EAAE;IAClE,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACzD,MAAM,GAAG,GAAG,iBAAiB,CAAC,MAAM,EAAE;QACpC,MAAM,EAAE,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC;QAC7B,IAAI,EAAE,OAAO,CAAC,IAA8B;QAC5C,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,YAAY,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE;QACnC,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/D,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,MAAM,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,CAAC,UAAU,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,CAAC,aAAa,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACjM,CAAC;SAAM,CAAC;QACN,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE;YAAE,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QAC/D,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE;YAAE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;IACnE,CAAC;IACD,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;AACrC,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,yBAAyB,CAAC;KACtC,MAAM,CAAC,iBAAiB,EAAE,kBAAkB,CAAC;KAC7C,MAAM,CAAC,QAAQ,EAAE,uBAAuB,EAAE,KAAK,CAAC;KAChD,MAAM,CAAC,CAAC,OAA2C,EAAE,EAAE;IACtD,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACzD,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACrD,OAAO;IACT,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5D,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAChF,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,qCAAqC,CAAC;KAClD,MAAM,CAAC,iBAAiB,EAAE,kBAAkB,CAAC;KAC7C,MAAM,CAAC,QAAQ,EAAE,uBAAuB,EAAE,KAAK,CAAC;KAChD,MAAM,CAAC,CAAC,OAA2C,EAAE,EAAE;IACtD,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACzD,MAAM,MAAM,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACzC,IAAI,OAAO,CAAC,IAAI;QAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;;QAC1D,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,qBAAqB,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,uBAAuB,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;IACnH,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9C,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,KAAK,CAAC;KACd,WAAW,CAAC,uFAAuF,CAAC;KACpG,MAAM,CAAC,iBAAiB,EAAE,kBAAkB,CAAC;KAC7C,MAAM,CAAC,KAAK,EAAE,OAA4B,EAAE,EAAE;IAC7C,MAAM,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;AACvC,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,uFAAuF,CAAC;KACpG,WAAW,CAAC,IAAI,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;KACpG,MAAM,CAAC,WAAW,EAAE,yDAAyD,EAAE,KAAK,CAAC;KACrF,MAAM,CAAC,gBAAgB,EAAE,gDAAgD,EAAE,KAAK,CAAC;KACjF,MAAM,CAAC,OAAO,EAAE,oCAAoC,EAAE,KAAK,CAAC;KAC5D,MAAM,CAAC,SAAS,EAAE,qEAAqE,EAAE,KAAK,CAAC;KAC/F,MAAM,CAAC,SAAS,EAAE,mCAAmC,EAAE,KAAK,CAAC;KAC7D,MAAM,CAAC,WAAW,EAAE,yCAAyC,EAAE,KAAK,CAAC;KACrE,MAAM,CAAC,SAAS,EAAE,kDAAkD,EAAE,KAAK,CAAC;KAC5E,MAAM,CAAC,OAAO,EAAE,iBAAiB,EAAE,KAAK,CAAC;KACzC,MAAM,CAAC,CAAC,MAAc,EAAE,OAA8B,EAAE,EAAE;IACzD,MAAM,GAAG,GAAG,WAAW,EAAE,CAAC;IAC1B,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;QACrB,IAAI,OAAO,CAAC,KAAK;YAAE,YAAY,CAAC,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;;YAC3F,gBAAgB,EAAE,CAAC;QACxB,OAAO;IACT,CAAC;IACD,MAAM,WAAW,GAAG,MAAqB,CAAC;IAC1C,MAAM,KAAK,GAAiB,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC;IACnE,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,KAAK,MAAM,OAAO,IAAI,aAAa,CAAC,WAAW,EAAE,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC;YAC7D,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;gBACjC,OAAO,CAAC,GAAG,CAAC,KAAK,OAAO,CAAC,KAAK,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;gBAClD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;QACD,OAAO;IACT,CAAC;IACD,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,aAAa,CAAC,WAAW,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;IACtD,IAAI,OAAO,CAAC,WAAW;QAAE,OAAO,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,WAAW,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;IAC9E,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACvC,IAAI,OAAO,CAAC,GAAG;QAAE,gBAAgB,EAAE,CAAC;AACtC,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,WAAW,CAAC;KACpB,WAAW,CAAC,0EAA0E,CAAC;KACvF,WAAW,CAAC,IAAI,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;KACpG,MAAM,CAAC,WAAW,EAAE,wDAAwD,EAAE,KAAK,CAAC;KACpF,MAAM,CAAC,gBAAgB,EAAE,kDAAkD,EAAE,KAAK,CAAC;KACnF,MAAM,CAAC,SAAS,EAAE,qEAAqE,EAAE,KAAK,CAAC;KAC/F,MAAM,CAAC,SAAS,EAAE,sCAAsC,EAAE,KAAK,CAAC;KAChE,MAAM,CAAC,WAAW,EAAE,uCAAuC,EAAE,KAAK,CAAC;KACnE,MAAM,CAAC,OAAO,EAAE,iBAAiB,EAAE,KAAK,CAAC;KACzC,MAAM,CAAC,CAAC,MAAc,EAAE,OAAgC,EAAE,EAAE;IAC3D,MAAM,GAAG,GAAG,WAAW,EAAE,CAAC;IAC1B,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;QACrB,IAAI,OAAO,CAAC,KAAK;YAAE,YAAY,CAAC,aAAa,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;;YAC5F,OAAO,CAAC,GAAG,CAAC,iEAAiE,CAAC,CAAC;QACpF,OAAO;IACT,CAAC;IACD,MAAM,WAAW,GAAG,MAAqB,CAAC;IAC1C,MAAM,KAAK,GAAiB,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC;IACnE,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,eAAe,CAAC,WAAW,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;IACxD,IAAI,OAAO,CAAC,WAAW;QAAE,OAAO,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,WAAW,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;IAChF,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;AACzC,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,8DAA8D,CAAC;KAC3E,MAAM,CAAC,iBAAiB,EAAE,kBAAkB,CAAC;KAC7C,MAAM,CAAC,QAAQ,EAAE,uBAAuB,EAAE,KAAK,CAAC;KAChD,MAAM,CAAC,SAAS,EAAE,mEAAmE,EAAE,KAAK,CAAC;KAC7F,MAAM,CAAC,KAAK,EAAE,OAA2D,EAAE,EAAE;IAC5E,MAAM,GAAG,GAAG,WAAW,EAAE,CAAC;IAC1B,IAAI,MAAM,GAAwB,IAAI,CAAC;IACvC,IAAI,WAA+B,CAAC;IACpC,IAAI,CAAC;QACH,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,WAAW,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,CAAC;IACD,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC;IACpD,IAAI,OAAO,CAAC,KAAK,IAAI,MAAM,EAAE,CAAC;QAC5B,IAAI,CAAC;YACH,MAAM,CAAC,IAAI,CAAC,MAAM,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;QACxC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC/G,CAAC;IACH,CAAC;IACD,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;IAChC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;IACnF,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACvC,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IACxD,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACtE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC;AAiBH,SAAS,gBAAgB,CAAC,KAAa;IACrC,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC1C,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,MAAM,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,KAAK,EAAE,CAAC,CAAC;IAC5G,OAAO,MAAM,CAAC;AAChB,CAAC;AAeD,SAAS,WAAW;IAClB,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC;AACpD,CAAC;AAED,SAAS,WAAW,CAAC,GAAgB;IACnC,OAAO,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;AACvC,CAAC;AAED,SAAS,cAAc,CAAC,OAA4C,EAAE,KAAmB;IACvF,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;AACjE,CAAC;AAED,SAAS,gBAAgB;IACvB,KAAK,MAAM,OAAO,IAAI,WAAW,EAAE,EAAE,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,KAAK,OAAO,CAAC,MAAM,KAAK,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACzD,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,MAAkB,EAAE,MAAe;IACvD,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,CAAC,KAAK,CAAC,YAAY,MAAM,CAAC,MAAM,IAAI,gBAAgB,GAAG,CAAC,CAAC;QAChE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC9E,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,OAAuB,EAAE,MAAe;IAC7D,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,KAAK,iBAAiB,CAAC,CAAC;YAC9C,SAAS;QACX,CAAC;QACD,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACpC,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBAChC,OAAO,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,KAAK,cAAc,MAAM,CAAC,MAAM,IAAI,gBAAgB,GAAG,CAAC,CAAC;YACnF,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,KAAK,KAAK,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC/F,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,CAAC,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { BridgeConfig } from "./types.js";
2
+ export declare const defaultConfig: BridgeConfig;
3
+ export declare function defaultProjectConfig(): string;
4
+ export declare function loadConfig(cwd?: string, explicitPath?: string): BridgeConfig;
5
+ export declare function configPaths(cwd?: string, explicitPath?: string): string[];
package/dist/config.js ADDED
@@ -0,0 +1,172 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { join, resolve } from "node:path";
4
+ import YAML from "yaml";
5
+ import { z } from "zod";
6
+ const modeSchema = z.enum(["plan", "draft", "execute", "request-approval"]);
7
+ const riskSchema = z.enum([
8
+ "publish_external",
9
+ "send_message",
10
+ "send_email",
11
+ "delete",
12
+ "payment",
13
+ "git_push",
14
+ "credential_change",
15
+ ]);
16
+ const defaultRequireApprovalFor = [
17
+ "publish_external",
18
+ "send_message",
19
+ "send_email",
20
+ "delete",
21
+ "payment",
22
+ "git_push",
23
+ "credential_change",
24
+ ];
25
+ const rawConfigSchema = z.object({
26
+ runtime: z
27
+ .object({
28
+ adapter: z.literal("hermes-cli").default("hermes-cli"),
29
+ command: z.string().min(1).default("hermes"),
30
+ })
31
+ .default({ adapter: "hermes-cli", command: "hermes" }),
32
+ defaults: z
33
+ .object({
34
+ mode: modeSchema.default("plan"),
35
+ profile: z.string().min(1).optional(),
36
+ source: z.string().min(1).default("external-agent"),
37
+ max_turns: z.number().int().positive().default(30),
38
+ preset: z.string().min(1).default("default"),
39
+ })
40
+ .default({ mode: "plan", source: "external-agent", max_turns: 30, preset: "default" }),
41
+ presets: z
42
+ .record(z.string(), z.object({
43
+ description: z.string().optional(),
44
+ skills: z.array(z.string()).default([]),
45
+ toolsets: z.array(z.string()).default([]),
46
+ provider: z.string().optional(),
47
+ model: z.string().optional(),
48
+ profile: z.string().optional(),
49
+ max_turns: z.number().int().positive().optional(),
50
+ source: z.string().optional(),
51
+ }))
52
+ .default({ default: { skills: [], toolsets: [] } }),
53
+ policy: z
54
+ .object({
55
+ yolo: z.boolean().default(false),
56
+ require_approval_for: z.array(riskSchema).default(defaultRequireApprovalFor),
57
+ })
58
+ .default({ yolo: false, require_approval_for: defaultRequireApprovalFor }),
59
+ });
60
+ export const defaultConfig = {
61
+ runtime: { adapter: "hermes-cli", command: "hermes" },
62
+ defaults: { mode: "plan", source: "external-agent", maxTurns: 30, preset: "default" },
63
+ presets: { default: { skills: [], toolsets: [] } },
64
+ policy: {
65
+ yolo: false,
66
+ requireApprovalFor: [...defaultRequireApprovalFor],
67
+ },
68
+ };
69
+ export function defaultProjectConfig() {
70
+ return YAML.stringify({
71
+ runtime: { adapter: "hermes-cli", command: "hermes" },
72
+ defaults: { mode: "plan", source: "external-agent", max_turns: 30, preset: "default" },
73
+ presets: {
74
+ default: { description: "No extra skills or toolsets. Uses the active Hermes profile.", skills: [], toolsets: [] },
75
+ research: { description: "General research and synthesis.", skills: [], toolsets: ["web", "terminal", "file"] },
76
+ coding: { description: "Repository inspection and runtime validation.", skills: ["developer-assurance-and-validation", "runtime-debugging"], toolsets: ["terminal", "file"] },
77
+ },
78
+ policy: {
79
+ yolo: false,
80
+ require_approval_for: defaultRequireApprovalFor,
81
+ },
82
+ });
83
+ }
84
+ export function loadConfig(cwd = process.cwd(), explicitPath) {
85
+ const paths = configPaths(cwd, explicitPath);
86
+ const raws = paths.filter(existsSync).map((path) => readYaml(path));
87
+ const merged = raws.reduce((acc, item) => deepMerge(acc, item), structuredClone(toRaw(defaultConfig)));
88
+ const parsed = rawConfigSchema.parse(merged);
89
+ return normalizeConfig(parsed);
90
+ }
91
+ export function configPaths(cwd = process.cwd(), explicitPath) {
92
+ if (explicitPath)
93
+ return [resolve(cwd, explicitPath)];
94
+ const xdg = process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
95
+ return [join(xdg, "hermes-action", "config.yaml"), join(cwd, ".hermes-action.yaml")];
96
+ }
97
+ function readYaml(path) {
98
+ const content = readFileSync(path, "utf8");
99
+ const parsed = YAML.parse(content);
100
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed))
101
+ return {};
102
+ return parsed;
103
+ }
104
+ function deepMerge(base, patch) {
105
+ const result = { ...base };
106
+ for (const [key, value] of Object.entries(patch)) {
107
+ const current = result[key];
108
+ if (isPlainObject(current) && isPlainObject(value)) {
109
+ result[key] = deepMerge(current, value);
110
+ }
111
+ else {
112
+ result[key] = value;
113
+ }
114
+ }
115
+ return result;
116
+ }
117
+ function isPlainObject(value) {
118
+ return typeof value === "object" && value !== null && !Array.isArray(value);
119
+ }
120
+ function toRaw(config) {
121
+ return {
122
+ runtime: config.runtime,
123
+ defaults: {
124
+ mode: config.defaults.mode,
125
+ profile: config.defaults.profile,
126
+ source: config.defaults.source,
127
+ max_turns: config.defaults.maxTurns,
128
+ preset: config.defaults.preset,
129
+ },
130
+ presets: Object.fromEntries(Object.entries(config.presets).map(([name, preset]) => [
131
+ name,
132
+ {
133
+ description: preset.description,
134
+ skills: preset.skills,
135
+ toolsets: preset.toolsets,
136
+ provider: preset.provider,
137
+ model: preset.model,
138
+ profile: preset.profile,
139
+ max_turns: preset.maxTurns,
140
+ source: preset.source,
141
+ },
142
+ ])),
143
+ policy: { yolo: config.policy.yolo, require_approval_for: config.policy.requireApprovalFor },
144
+ };
145
+ }
146
+ function normalizeConfig(raw) {
147
+ return {
148
+ runtime: raw.runtime,
149
+ defaults: {
150
+ mode: raw.defaults.mode,
151
+ profile: raw.defaults.profile,
152
+ source: raw.defaults.source,
153
+ maxTurns: raw.defaults.max_turns,
154
+ preset: raw.defaults.preset,
155
+ },
156
+ presets: Object.fromEntries(Object.entries(raw.presets).map(([name, preset]) => [
157
+ name,
158
+ {
159
+ description: preset.description,
160
+ skills: preset.skills,
161
+ toolsets: preset.toolsets,
162
+ provider: preset.provider,
163
+ model: preset.model,
164
+ profile: preset.profile,
165
+ maxTurns: preset.max_turns,
166
+ source: preset.source,
167
+ },
168
+ ])),
169
+ policy: { yolo: raw.policy.yolo, requireApprovalFor: raw.policy.require_approval_for },
170
+ };
171
+ }
172
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { ContextDocument } from "./types.js";
2
+ export declare function readContextFiles(paths: string[], cwd?: string): ContextDocument[];
@@ -0,0 +1,15 @@
1
+ import { readFileSync, statSync } from "node:fs";
2
+ import { resolve } from "node:path";
3
+ const maxContextBytes = 250_000;
4
+ export function readContextFiles(paths, cwd = process.cwd()) {
5
+ return paths.map((inputPath) => {
6
+ const path = resolve(cwd, inputPath);
7
+ const stat = statSync(path);
8
+ if (!stat.isFile())
9
+ throw new Error(`Context path is not a file: ${inputPath}`);
10
+ if (stat.size > maxContextBytes)
11
+ throw new Error(`Context file is too large (${stat.size} bytes, max ${maxContextBytes}): ${inputPath}`);
12
+ return { path, content: readFileSync(path, "utf8") };
13
+ });
14
+ }
15
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,MAAM,eAAe,GAAG,OAAO,CAAC;AAEhC,MAAM,UAAU,gBAAgB,CAAC,KAAe,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IACnE,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE;QAC7B,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QACrC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,SAAS,EAAE,CAAC,CAAC;QAChF,IAAI,IAAI,CAAC,IAAI,GAAG,eAAe;YAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,IAAI,CAAC,IAAI,eAAe,eAAe,MAAM,SAAS,EAAE,CAAC,CAAC;QACzI,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC;IACvD,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { BridgeConfig } from "./types.js";
2
+ import type { PathContext } from "./install/types.js";
3
+ export type CheckStatus = "pass" | "warn" | "fail";
4
+ export interface DoctorCheck {
5
+ id: string;
6
+ status: CheckStatus;
7
+ detail?: string | undefined;
8
+ }
9
+ export interface DoctorReport {
10
+ ok: boolean;
11
+ checks: DoctorCheck[];
12
+ }
13
+ /** Synchronous environment checks. The optional `--probe` check is added separately by the caller. */
14
+ export declare function coreChecks(config: BridgeConfig | null, ctx: PathContext, configError?: string): DoctorCheck[];
15
+ export declare function toReport(checks: DoctorCheck[]): DoctorReport;
16
+ /** Optional live check (spends provider tokens): ask Hermes to echo a sentinel through the full pipeline. */
17
+ export declare function probeCheck(config: BridgeConfig): Promise<DoctorCheck>;
18
+ export declare function formatDoctor(report: DoctorReport): string;
package/dist/doctor.js ADDED
@@ -0,0 +1,77 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { defaultConfig } from "./config.js";
3
+ import { checkHermesStatus } from "./status.js";
4
+ import { buildEffectiveRun } from "./run.js";
5
+ import { runHermesCli } from "./adapters/hermes-cli.js";
6
+ import { skillStates } from "./install/install-service.js";
7
+ const minNodeMajor = 20;
8
+ const agentCommand = { "claude-code": "claude", codex: "codex" };
9
+ /** Synchronous environment checks. The optional `--probe` check is added separately by the caller. */
10
+ export function coreChecks(config, ctx, configError) {
11
+ const checks = [nodeCheck(), configCheck(config, configError), hermesCheck(config ?? defaultConfig)];
12
+ for (const agent of Object.keys(agentCommand)) {
13
+ checks.push(agentAvailabilityCheck(agent));
14
+ }
15
+ for (const { agent, state } of skillStates(ctx, "global")) {
16
+ checks.push(skillCheck(agent, state));
17
+ }
18
+ return checks;
19
+ }
20
+ export function toReport(checks) {
21
+ return { ok: !checks.some((check) => check.status === "fail"), checks };
22
+ }
23
+ /** Optional live check (spends provider tokens): ask Hermes to echo a sentinel through the full pipeline. */
24
+ export async function probeCheck(config) {
25
+ const run = buildEffectiveRun(config, {
26
+ prompt: "Return the word BRIDGE_OK only. Do not use tools.",
27
+ mode: "plan",
28
+ contextFiles: [],
29
+ yolo: false,
30
+ dryRun: false,
31
+ json: false,
32
+ });
33
+ const result = await runHermesCli(config, run, false);
34
+ const ok = result.ok && `${result.stdout}${result.stderr}`.includes("BRIDGE_OK");
35
+ return { id: "probe", status: ok ? "pass" : "warn", detail: ok ? "Hermes responded" : `exit ${result.exitCode}` };
36
+ }
37
+ export function formatDoctor(report) {
38
+ const label = { pass: "ok", warn: "warn", fail: "FAIL" };
39
+ const lines = report.checks.map((check) => `[${label[check.status]}] ${check.id}${check.detail ? `: ${check.detail}` : ""}`);
40
+ lines.push(report.ok ? "All required checks passed." : "Some required checks failed.");
41
+ return lines.join("\n");
42
+ }
43
+ function nodeCheck() {
44
+ const major = Number.parseInt(process.versions.node.split(".")[0] ?? "0", 10);
45
+ return { id: "node", status: major >= minNodeMajor ? "pass" : "fail", detail: `v${process.versions.node}` };
46
+ }
47
+ function configCheck(config, configError) {
48
+ if (config)
49
+ return { id: "config", status: "pass", detail: "loaded" };
50
+ return { id: "config", status: "fail", detail: configError ?? "could not load configuration" };
51
+ }
52
+ function hermesCheck(config) {
53
+ const status = checkHermesStatus(config);
54
+ if (status.available)
55
+ return { id: "hermes", status: "pass", detail: status.version };
56
+ return { id: "hermes", status: "fail", detail: status.error };
57
+ }
58
+ function agentAvailabilityCheck(agent) {
59
+ const command = agentCommand[agent];
60
+ const result = spawnSync(command, ["--version"], { encoding: "utf8" });
61
+ if (result.error)
62
+ return { id: agent, status: "warn", detail: `${command} not found on PATH` };
63
+ if (result.status !== 0)
64
+ return { id: agent, status: "warn", detail: `${command} --version exited with ${result.status ?? `signal ${result.signal}`}` };
65
+ return { id: agent, status: "pass", detail: result.stdout.trim() || result.stderr.trim() };
66
+ }
67
+ const skillStateDetail = {
68
+ current: "up to date",
69
+ absent: "not installed",
70
+ stale: "out of date (run: install --force)",
71
+ "user-modified": "modified locally",
72
+ foreign: "a non-managed file is present",
73
+ };
74
+ function skillCheck(agent, state) {
75
+ return { id: `skill:${agent}`, status: state === "current" ? "pass" : "warn", detail: skillStateDetail[state] };
76
+ }
77
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAiB3D,MAAM,YAAY,GAAG,EAAE,CAAC;AACxB,MAAM,YAAY,GAA+B,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAE7F,sGAAsG;AACtG,MAAM,UAAU,UAAU,CAAC,MAA2B,EAAE,GAAgB,EAAE,WAAoB;IAC5F,MAAM,MAAM,GAAkB,CAAC,SAAS,EAAE,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,WAAW,CAAC,MAAM,IAAI,aAAa,CAAC,CAAC,CAAC;IACpH,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC,YAAY,CAAiB,EAAE,CAAC;QAC9D,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7C,CAAC;IACD,KAAK,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,WAAW,CAAC,GAAG,EAAE,QAAQ,CAAC,EAAE,CAAC;QAC1D,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;IACxC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,MAAqB;IAC5C,OAAO,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;AAC1E,CAAC;AAED,6GAA6G;AAC7G,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAoB;IACnD,MAAM,GAAG,GAAG,iBAAiB,CAAC,MAAM,EAAE;QACpC,MAAM,EAAE,mDAAmD;QAC3D,IAAI,EAAE,MAAM;QACZ,YAAY,EAAE,EAAE;QAChB,IAAI,EAAE,KAAK;QACX,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,KAAK;KACZ,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;IACtD,MAAM,EAAE,GAAG,MAAM,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IACjF,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,QAAQ,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;AACpH,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAoB;IAC/C,MAAM,KAAK,GAAgC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IACtF,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,KAAK,CAAC,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC7H,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,6BAA6B,CAAC,CAAC,CAAC,8BAA8B,CAAC,CAAC;IACvF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,SAAS;IAChB,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;IAC9E,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;AAC9G,CAAC;AAED,SAAS,WAAW,CAAC,MAA2B,EAAE,WAAoB;IACpE,IAAI,MAAM;QAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IACtE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,IAAI,8BAA8B,EAAE,CAAC;AACjG,CAAC;AAED,SAAS,WAAW,CAAC,MAAoB;IACvC,MAAM,MAAM,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACzC,IAAI,MAAM,CAAC,SAAS;QAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;IACtF,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC;AAChE,CAAC;AAED,SAAS,sBAAsB,CAAC,KAAiB;IAC/C,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IACvE,IAAI,MAAM,CAAC,KAAK;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,oBAAoB,EAAE,CAAC;IAC/F,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,0BAA0B,MAAM,CAAC,MAAM,IAAI,UAAU,MAAM,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC;IACxJ,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;AAC7F,CAAC;AAED,MAAM,gBAAgB,GAAiC;IACrD,OAAO,EAAE,YAAY;IACrB,MAAM,EAAE,eAAe;IACvB,KAAK,EAAE,oCAAoC;IAC3C,eAAe,EAAE,kBAAkB;IACnC,OAAO,EAAE,+BAA+B;CACzC,CAAC;AAEF,SAAS,UAAU,CAAC,KAAiB,EAAE,KAAmB;IACxD,OAAO,EAAE,EAAE,EAAE,SAAS,KAAK,EAAE,EAAE,MAAM,EAAE,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC;AAClH,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { FileChange } from "./types.js";
2
+ export interface EditResult {
3
+ content: string;
4
+ action: FileChange["action"];
5
+ reason?: string | undefined;
6
+ }
7
+ /**
8
+ * Read a file (or null when absent), apply a pure edit, and write only when it actually changes.
9
+ * Total: a filesystem error (permission, race) is reported as a refused change rather than thrown,
10
+ * so callers that are not already wrapped in per-item isolation stay graceful.
11
+ */
12
+ export declare function applyFileEdit(file: string, edit: (existing: string | null) => EditResult, dryRun: boolean): FileChange;
@@ -0,0 +1,18 @@
1
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
+ /**
3
+ * Read a file (or null when absent), apply a pure edit, and write only when it actually changes.
4
+ * Total: a filesystem error (permission, race) is reported as a refused change rather than thrown,
5
+ * so callers that are not already wrapped in per-item isolation stay graceful.
6
+ */
7
+ export function applyFileEdit(file, edit, dryRun) {
8
+ try {
9
+ const result = edit(existsSync(file) ? readFileSync(file, "utf8") : null);
10
+ if (result.action !== "unchanged" && result.action !== "refused" && !dryRun)
11
+ writeFileSync(file, result.content, "utf8");
12
+ return { path: file, action: result.action, reason: result.reason };
13
+ }
14
+ catch (error) {
15
+ return { path: file, action: "refused", reason: error instanceof Error ? error.message : String(error) };
16
+ }
17
+ }
18
+ //# sourceMappingURL=file-edit.js.map