@sentropic/h2a 0.98.2 → 0.98.4

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 (47) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codex-plugin/plugin.json +1 -1
  3. package/dist/bin-routing.d.ts +52 -0
  4. package/dist/bin-routing.d.ts.map +1 -1
  5. package/dist/bin-routing.js +195 -0
  6. package/dist/bin-routing.js.map +1 -1
  7. package/dist/bin.js +3 -32
  8. package/dist/bin.js.map +1 -1
  9. package/dist/cli-command-map.d.ts.map +1 -1
  10. package/dist/cli-command-map.js +1 -0
  11. package/dist/cli-command-map.js.map +1 -1
  12. package/dist/cli.d.ts.map +1 -1
  13. package/dist/cli.js +50 -10
  14. package/dist/cli.js.map +1 -1
  15. package/dist/hosts/plugin.d.ts +2 -2
  16. package/dist/hosts/plugin.d.ts.map +1 -1
  17. package/dist/hosts/plugin.js +16 -1
  18. package/dist/hosts/plugin.js.map +1 -1
  19. package/dist/hosts/vibe.d.ts +15 -0
  20. package/dist/hosts/vibe.d.ts.map +1 -0
  21. package/dist/hosts/vibe.js +40 -0
  22. package/dist/hosts/vibe.js.map +1 -0
  23. package/dist/index.d.ts +2 -1
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +2 -1
  26. package/dist/index.js.map +1 -1
  27. package/dist/runtime/local-files/store.d.ts.map +1 -1
  28. package/dist/runtime/local-files/store.js +13 -2
  29. package/dist/runtime/local-files/store.js.map +1 -1
  30. package/dist/runtime/loop/index.d.ts +1 -1
  31. package/dist/runtime/loop/index.d.ts.map +1 -1
  32. package/dist/runtime/loop/index.js.map +1 -1
  33. package/dist/runtime/mcp/agent-launch.d.ts +1 -1
  34. package/dist/runtime/mcp/agent-launch.d.ts.map +1 -1
  35. package/dist/runtime/mcp/agent-launch.js +9 -3
  36. package/dist/runtime/mcp/agent-launch.js.map +1 -1
  37. package/dist/runtime/mcp/handlers.js +1 -1
  38. package/dist/runtime/mcp/handlers.js.map +1 -1
  39. package/dist/runtime/mcp/tools.js +5 -5
  40. package/dist/runtime/mcp/tools.js.map +1 -1
  41. package/dist/runtime/version/agent-version.d.ts.map +1 -1
  42. package/dist/runtime/version/agent-version.js +2 -1
  43. package/dist/runtime/version/agent-version.js.map +1 -1
  44. package/package.json +4 -4
  45. package/skills/h2a/SKILL.md +4 -0
  46. package/skills/h2a-run/SKILL.md +11 -9
  47. package/skills/harness/review/SKILL.md +8 -4
package/dist/cli.js CHANGED
@@ -70,6 +70,7 @@ import { H2A_AGY_HOST } from "./hosts/agy.js";
70
70
  import { H2A_HERMES_HOST } from "./hosts/hermes.js";
71
71
  import { H2A_OPENCODE_HOST } from "./hosts/opencode.js";
72
72
  import { H2A_MUSE_HOST } from "./hosts/muse.js";
73
+ import { H2A_VIBE_HOST } from "./hosts/vibe.js";
73
74
  import { doctorHostInstallations, findLiveSessionsPredatingHostConfig, inspectLegacyAccountArtifacts } from "./hosts/installation-doctor.js";
74
75
  import { H2A_CLI_MCP_TOOL_NAMES } from "./mcp.js";
75
76
  import { renderStopHook, claudeStopHookEntry, claudeDriveReceiveHookEntry, isH2ADriveReceiveHook, isH2ARecordHook, codexPluginManifest, codexMarketplaceManifest, codexPluginTrustCommands, H2A_CODEX_PLUGIN_NAME, H2A_HOST_PLUGIN_HOSTS } from "./hosts/plugin.js";
@@ -182,7 +183,8 @@ const CLI_HOSTS = [
182
183
  H2A_AGY_HOST,
183
184
  H2A_HERMES_HOST,
184
185
  H2A_OPENCODE_HOST,
185
- H2A_MUSE_HOST
186
+ H2A_MUSE_HOST,
187
+ H2A_VIBE_HOST
186
188
  ];
187
189
  export function renderCliHelp() {
188
190
  return [
@@ -261,14 +263,14 @@ export function renderCliHelp() {
261
263
  " h2a drumbeat escalations [--root <path>]",
262
264
  " h2a drumbeat relance-inbox [--instance <id>] [--relauncher logging|local-tmux|headless|auto] [--root <path>]",
263
265
  " h2a drumbeat watch [--interval-ms <n>] [--max-relances <n>] [--relauncher logging|local-tmux|remote|headless|auto] [--instance <signer> --private-key <pem>] [--decider logging|<command>] [--decider-after <k>] [--decider-enforce] [--root <path>]",
264
- " h2a host setup --host <codex|claude|gemini|agy|hermes|opencode|muse> [--endpoint local|remote] [--url <https://…/mcp>] [--root <path>] [--print | --write <file>] [--force] [--no-wake] (selects exactly one h2a endpoint; local renders mcp-serve --auto-open --auto-upgrade --wake auto by default)",
266
+ " h2a host setup --host <codex|claude|gemini|agy|hermes|opencode|muse|vibe> [--endpoint local|remote] [--url <https://…/mcp>] [--root <path>] [--print | --write <file>] [--force] [--no-wake] (selects exactly one h2a endpoint; local renders mcp-serve --auto-open --auto-upgrade --wake auto by default)",
265
267
  " h2a host status [--host <name>]",
266
- " h2a host plugin --host <codex|claude|gemini|agy|hermes|opencode|muse> --instance <id> [--status <work-status>] [--root <path>] [--write <settings.json> [--force]] [--scaffold <dir>] (--write installs the Stop hook for claude|gemini|codex|hermes|opencode; --scaffold writes codex's full local marketplace + trust step; agy and muse are poll-only)",
268
+ " h2a host plugin --host <codex|claude|gemini|agy|hermes|opencode|muse|vibe> --instance <id> [--status <work-status>] [--root <path>] [--write <settings.json> [--force]] [--scaffold <dir>] (--write installs the Stop hook for claude|gemini|codex|hermes|opencode; --scaffold writes codex's full local marketplace + trust step; vibe records via a post_agent hook in ~/.vibe/hooks.toml; agy and muse are poll-only)",
267
269
  " h2a store migrate [--from <v>] [--to <v>] [--sanitize-paths] [--dry-run] [--root <path>]",
268
270
  " h2a store index-launch --root <absolute-path> (derived indexes; original logs retained)",
269
271
  "",
270
272
  "High-level coordination (DEC-054):",
271
- " h2a connect --host <codex|claude|gemini|agy|hermes|opencode|muse|remote> [--root <path>] [--instance <id>] [--name <display>]",
273
+ " h2a connect --host <codex|claude|gemini|agy|hermes|opencode|muse|vibe|remote> [--root <path>] [--instance <id>] [--name <display>]",
272
274
  " h2a conductor [--workspace <id|path>] [--root <path>] (who is the live conductor/owner of a workspace — derived from presence; conductor=role CONDUCTOR if set, else null; candidates=in-workspace live agents)",
273
275
  " h2a conductor-launch-check [--workspace <id|path>] [--root <path>] [--idle-ms <ms>] (DRY-RUN: polls track workspace-activity; recommends launching a conductor if work is stalled and none is live — h2a does NOT spawn; launch parked pending spawn policy + remote)",
274
276
  " h2a conductor-launch --workspace <id|path> [--root <path>] [--idle-ms <ms>] [--confirm] [--remote <instance>] [--instance <self>] (D3 EMIT: if stalled+no conductor, emits a launch-REQUEST envelope to a live remote agent — gated by --confirm + 1/30min/workspace cap; h2a NEVER spawns; remote does the actual spawn)",
@@ -292,7 +294,7 @@ export function renderCliHelp() {
292
294
  " h2a blockage list [--scope <s>] [--active] [--root <path>]",
293
295
  " h2a blockage resolve --instance <id> [--by <id>] [--root <path>]",
294
296
  " h2a sysml verify --json <envelope> --public-key <pem-file> [--by <id>] [--content-integrity --api-base <url> [--auth <token>]]",
295
- " h2a install-skills --host <claude|codex|gemini|agy|muse> [--scope user|project] [--force]",
297
+ " h2a install-skills --host <claude|codex|gemini|agy|muse|vibe> [--scope user|project] [--force]",
296
298
  " h2a deploy k8s-sidecar [--instance <id>] [--host <h>] [--root <path>] [--image <ref>] [--cli-version <ver>] [--write <file>]",
297
299
  " h2a deploy k8s-tenant [--namespace <ns>] [--root <path>] [--replicas <n>] [--storage <size>] [--storage-class <sc>] [--lease-ms <ms>] [--image <ref>] [--cli-version <ver>] [--write <file>]",
298
300
  " h2a loop create --name <n> --goal <text> [--auto-tick] [--repo <path[:role]>] [--track <json>] [--agent <host:role:placement> [--launch-stdin]] [--root <path>]",
@@ -3575,6 +3577,7 @@ function isUnsupportedHostWritePath(host, path) {
3575
3577
  // TOML/YAML/JSONC file as JSON, even with --force: preserving unrelated MCP
3576
3578
  // configuration is stronger than a convenient write path.
3577
3579
  return ((host === "codex" && normalized.endsWith(".toml")) ||
3580
+ (host === "vibe" && normalized.endsWith(".toml")) ||
3578
3581
  (host === "hermes" && (normalized.endsWith(".yaml") || normalized.endsWith(".yml"))) ||
3579
3582
  (host === "opencode" && normalized.endsWith(".jsonc")));
3580
3583
  }
@@ -3702,6 +3705,9 @@ function cmdHostSetup(flags, streams, options) {
3702
3705
  else if (host === "muse") {
3703
3706
  snippet = H2A_MUSE_HOST.renderMcpConfig(renderOpts);
3704
3707
  }
3708
+ else if (host === "vibe") {
3709
+ snippet = H2A_VIBE_HOST.renderMcpConfig(renderOpts);
3710
+ }
3705
3711
  else {
3706
3712
  streams.stderr.write(`h2a host setup: unknown --host "${host}". Supported: ${CLI_HOSTS.map((h) => h.host).join(", ")}.\n`);
3707
3713
  return 1;
@@ -3951,6 +3957,15 @@ function cmdHostPlugin(flags, streams) {
3951
3957
  // verified against `~/.codex/.../hooks/hooks.json`). agy is poll-only (no
3952
3958
  // daemon), so --write is refused for it and the rendered hook + hint surface.
3953
3959
  if (flags.write) {
3960
+ // Vibe's hook file is `~/.vibe/hooks.toml` — TOML, and the JSON hook merger
3961
+ // is deliberately format-strict (same refusal as `host setup --write` for
3962
+ // TOML targets): --print carries the rendered record + the TOML placement
3963
+ // hint. agy/muse are poll-only (no verified stop-hook surface at all).
3964
+ if (flags.host === "vibe") {
3965
+ streams.stderr.write(`h2a host plugin: --write is not available for vibe (~/.vibe/hooks.toml is TOML and the hook merger is format-strict). ` +
3966
+ `Register the rendered record command as a post_agent hook; --print carries the TOML translation.\n`);
3967
+ return 1;
3968
+ }
3954
3969
  if (flags.host === "agy" || flags.host === "muse") {
3955
3970
  streams.stderr.write(`h2a host plugin: --write is not available for ${flags.host} (poll-only, no verified stop-hook surface). ` +
3956
3971
  `Use the poll path: ${render.poll}\n`);
@@ -4887,6 +4902,7 @@ function cmdDoctor(flags, streams, options = {}) {
4887
4902
  "hermes",
4888
4903
  "opencode",
4889
4904
  "muse",
4905
+ "vibe",
4890
4906
  "remote"
4891
4907
  ]);
4892
4908
  // Reconstruct an address from a dir name: double-underscore → colon.
@@ -5361,11 +5377,11 @@ function cmdKeysProveControl(flags, streams) {
5361
5377
  }
5362
5378
  function cmdConnect(flags, streams) {
5363
5379
  if (!flags.host) {
5364
- streams.stderr.write("h2a connect: --host <codex|claude|gemini|agy|hermes|opencode|muse|remote> is required\n");
5380
+ streams.stderr.write("h2a connect: --host <codex|claude|gemini|agy|hermes|opencode|muse|vibe|remote> is required\n");
5365
5381
  return 1;
5366
5382
  }
5367
- if (!["codex", "claude", "gemini", "agy", "hermes", "opencode", "muse", "remote"].includes(flags.host)) {
5368
- streams.stderr.write(`h2a connect: unknown --host "${flags.host}". Supported: codex, claude, gemini, agy, hermes, opencode, muse, remote.\n`);
5383
+ if (!["codex", "claude", "gemini", "agy", "hermes", "opencode", "muse", "vibe", "remote"].includes(flags.host)) {
5384
+ streams.stderr.write(`h2a connect: unknown --host "${flags.host}". Supported: codex, claude, gemini, agy, hermes, opencode, muse, vibe, remote.\n`);
5369
5385
  return 1;
5370
5386
  }
5371
5387
  const cwd = streams.cwd ?? (() => process.cwd());
@@ -5542,6 +5558,25 @@ function targetSpecFor(host, cwd) {
5542
5558
  }
5543
5559
  };
5544
5560
  }
5561
+ if (host === "vibe") {
5562
+ // Vibe (Mistral Vibe CLI) uses the standard SKILL.md format, discovered
5563
+ // from ~/.vibe/skills/ (user scope) or <project>/.vibe/skills/ (project
5564
+ // scope requires a trusted folder). Verified against the unified harness:
5565
+ // installed skills are listed at session open.
5566
+ return {
5567
+ host: "vibe",
5568
+ userBase: join(homedir(), ".vibe", "skills"),
5569
+ projectBase: join(cwd, ".vibe", "skills"),
5570
+ extension: "SKILL.md",
5571
+ write: (base, skillName, _parsed, raw) => {
5572
+ const dir = join(base, skillName);
5573
+ mkdirSync(dir, { recursive: true });
5574
+ const target = join(dir, "SKILL.md");
5575
+ writeFileSync(target, raw, "utf8");
5576
+ return target;
5577
+ }
5578
+ };
5579
+ }
5545
5580
  if (host === "muse") {
5546
5581
  // Muse Code consumes Claude-format SKILL.md. User scope is verified:
5547
5582
  // `muse skills install --scope user` lands in $CONFIG_DIR/skills
@@ -5780,13 +5815,13 @@ function collectInstallableSkills() {
5780
5815
  function cmdInstallSkills(flags, streams) {
5781
5816
  const host = flags.host;
5782
5817
  if (!host) {
5783
- streams.stderr.write("h2a install-skills: --host <claude|codex|gemini|agy|hermes|opencode|muse> is required\n");
5818
+ streams.stderr.write("h2a install-skills: --host <claude|codex|gemini|agy|hermes|opencode|muse|vibe> is required\n");
5784
5819
  return 1;
5785
5820
  }
5786
5821
  const cwd = streams.cwd ?? (() => process.cwd());
5787
5822
  const spec = targetSpecFor(host, cwd());
5788
5823
  if (!spec) {
5789
- streams.stderr.write(`h2a install-skills: unknown --host "${host}". Supported: claude, codex, gemini, agy, hermes, opencode, muse.\n`);
5824
+ streams.stderr.write(`h2a install-skills: unknown --host "${host}". Supported: claude, codex, gemini, agy, hermes, opencode, muse, vibe.\n`);
5790
5825
  return 1;
5791
5826
  }
5792
5827
  if (!existsSync(SKILLS_DIR)) {
@@ -5854,6 +5889,11 @@ function cmdInstallSkills(flags, streams) {
5854
5889
  // step — verify pickup with `muse skills list`.
5855
5890
  ...(host === "muse"
5856
5891
  ? { verifyHint: "muse skills list # project scope (.muse/skills) needs workspace trust" }
5892
+ : {}),
5893
+ // vibe ships the standard SKILL.md layout under ~/.vibe/skills
5894
+ // (verified: the unified harness lists installed skills at open).
5895
+ ...(host === "vibe"
5896
+ ? { verifyHint: "vibe # skills load at session open; project scope (.vibe/skills) needs workspace trust" }
5857
5897
  : {})
5858
5898
  }, null, 2)}\n`);
5859
5899
  return skipped.length === 0 ? 0 : 2;