@phnx-labs/agents-cli 1.15.0 → 1.17.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 (111) hide show
  1. package/CHANGELOG.md +143 -39
  2. package/README.md +6 -6
  3. package/dist/commands/alias.js +2 -2
  4. package/dist/commands/browser-picker.d.ts +21 -0
  5. package/dist/commands/browser-picker.js +114 -0
  6. package/dist/commands/browser.js +793 -83
  7. package/dist/commands/cloud.js +8 -0
  8. package/dist/commands/commands.js +72 -22
  9. package/dist/commands/daemon.js +2 -2
  10. package/dist/commands/exec.js +70 -1
  11. package/dist/commands/hooks.js +71 -26
  12. package/dist/commands/mcp.js +81 -39
  13. package/dist/commands/plugins.js +224 -17
  14. package/dist/commands/prune.js +29 -1
  15. package/dist/commands/pull.js +3 -3
  16. package/dist/commands/repo.js +1 -1
  17. package/dist/commands/routines.js +2 -2
  18. package/dist/commands/secrets.js +154 -20
  19. package/dist/commands/sessions.js +62 -19
  20. package/dist/commands/{init.d.ts → setup.d.ts} +7 -6
  21. package/dist/commands/{init.js → setup.js} +22 -21
  22. package/dist/commands/skills.js +60 -19
  23. package/dist/commands/subagents.js +41 -13
  24. package/dist/commands/utils.d.ts +16 -0
  25. package/dist/commands/utils.js +32 -0
  26. package/dist/commands/view.js +78 -20
  27. package/dist/commands/workflows.d.ts +10 -0
  28. package/dist/commands/workflows.js +457 -0
  29. package/dist/index.d.ts +1 -1
  30. package/dist/index.js +48 -36
  31. package/dist/lib/agents.js +2 -2
  32. package/dist/lib/auto-pull-worker.js +2 -3
  33. package/dist/lib/auto-pull.js +2 -2
  34. package/dist/lib/browser/cdp.d.ts +7 -1
  35. package/dist/lib/browser/cdp.js +32 -1
  36. package/dist/lib/browser/chrome.d.ts +10 -0
  37. package/dist/lib/browser/chrome.js +41 -3
  38. package/dist/lib/browser/devices.d.ts +4 -0
  39. package/dist/lib/browser/devices.js +27 -0
  40. package/dist/lib/browser/drivers/local.js +22 -6
  41. package/dist/lib/browser/drivers/ssh.js +9 -2
  42. package/dist/lib/browser/input.d.ts +1 -0
  43. package/dist/lib/browser/input.js +3 -0
  44. package/dist/lib/browser/ipc.js +158 -23
  45. package/dist/lib/browser/profiles.d.ts +10 -2
  46. package/dist/lib/browser/profiles.js +122 -37
  47. package/dist/lib/browser/service.d.ts +91 -13
  48. package/dist/lib/browser/service.js +767 -132
  49. package/dist/lib/browser/types.d.ts +91 -3
  50. package/dist/lib/browser/types.js +16 -0
  51. package/dist/lib/cloud/rush.d.ts +28 -1
  52. package/dist/lib/cloud/rush.js +69 -14
  53. package/dist/lib/cloud/store.js +2 -2
  54. package/dist/lib/commands.d.ts +1 -15
  55. package/dist/lib/commands.js +11 -7
  56. package/dist/lib/daemon.js +2 -3
  57. package/dist/lib/doctor-diff.js +4 -4
  58. package/dist/lib/events.js +2 -2
  59. package/dist/lib/hooks.d.ts +11 -7
  60. package/dist/lib/hooks.js +138 -49
  61. package/dist/lib/migrate.d.ts +1 -1
  62. package/dist/lib/migrate.js +1237 -22
  63. package/dist/lib/models.js +2 -2
  64. package/dist/lib/permissions.d.ts +8 -66
  65. package/dist/lib/permissions.js +18 -18
  66. package/dist/lib/plugins.d.ts +94 -24
  67. package/dist/lib/plugins.js +702 -123
  68. package/dist/lib/pty-server.js +9 -10
  69. package/dist/lib/resource-patterns.d.ts +41 -0
  70. package/dist/lib/resource-patterns.js +82 -0
  71. package/dist/lib/resources/hooks.d.ts +5 -1
  72. package/dist/lib/resources/hooks.js +21 -4
  73. package/dist/lib/resources/index.d.ts +17 -0
  74. package/dist/lib/resources/index.js +7 -0
  75. package/dist/lib/resources/types.d.ts +1 -1
  76. package/dist/lib/resources/workflows.d.ts +24 -0
  77. package/dist/lib/resources/workflows.js +110 -0
  78. package/dist/lib/resources.d.ts +6 -1
  79. package/dist/lib/resources.js +12 -2
  80. package/dist/lib/rotate.js +3 -4
  81. package/dist/lib/session/active.d.ts +3 -0
  82. package/dist/lib/session/active.js +92 -6
  83. package/dist/lib/session/cloud.js +2 -2
  84. package/dist/lib/session/db.d.ts +18 -0
  85. package/dist/lib/session/db.js +109 -5
  86. package/dist/lib/session/discover.d.ts +6 -0
  87. package/dist/lib/session/discover.js +55 -29
  88. package/dist/lib/session/team-filter.js +2 -2
  89. package/dist/lib/shims.d.ts +4 -52
  90. package/dist/lib/shims.js +23 -15
  91. package/dist/lib/skills.js +6 -2
  92. package/dist/lib/sqlite.js +10 -4
  93. package/dist/lib/state.d.ts +101 -16
  94. package/dist/lib/state.js +179 -31
  95. package/dist/lib/subagents.d.ts +28 -0
  96. package/dist/lib/subagents.js +98 -1
  97. package/dist/lib/sync-manifest.d.ts +1 -1
  98. package/dist/lib/sync-manifest.js +3 -3
  99. package/dist/lib/teams/persistence.js +15 -5
  100. package/dist/lib/teams/registry.js +2 -2
  101. package/dist/lib/types.d.ts +75 -17
  102. package/dist/lib/types.js +3 -3
  103. package/dist/lib/usage.js +2 -2
  104. package/dist/lib/versions.d.ts +3 -0
  105. package/dist/lib/versions.js +158 -47
  106. package/dist/lib/workflows.d.ts +79 -0
  107. package/dist/lib/workflows.js +233 -0
  108. package/package.json +1 -5
  109. package/scripts/postinstall.js +60 -59
  110. package/dist/commands/fork.d.ts +0 -10
  111. package/dist/commands/fork.js +0 -146
package/dist/lib/hooks.js CHANGED
@@ -14,8 +14,42 @@ import * as TOML from 'smol-toml';
14
14
  import { AGENTS, HOOKS_CAPABLE_AGENTS } from './agents.js';
15
15
  import { supports, explainSkip } from './capabilities.js';
16
16
  import { setGeminiAutoUpdateDisabled, updateGeminiSettings } from './gemini-settings.js';
17
- import { getAgentsDir, getHooksDir as getSystemHooksDir, getUserHooksDir, getUserAgentsDir, getProjectAgentsDir } from './state.js';
17
+ import { getHooksDir as getSystemHooksDir, getUserHooksDir, getUserAgentsDir, getSystemAgentsDir, getProjectAgentsDir, getTrashHooksDir, getEnabledExtraRepos } from './state.js';
18
18
  function getCentralHooksDir() { return getUserHooksDir(); }
19
+ /**
20
+ * Resolve a hook script's absolute path. Checks user dir first, then enabled
21
+ * extra repos in insertion order, then system dir. Returns null if not found.
22
+ */
23
+ function resolveHookScriptPath(script) {
24
+ const extraDirs = getEnabledExtraRepos().map(e => e.dir);
25
+ for (const root of [getUserAgentsDir(), ...extraDirs, getSystemAgentsDir()]) {
26
+ const candidate = path.join(root, 'hooks', script);
27
+ if (fs.existsSync(candidate))
28
+ return candidate;
29
+ }
30
+ return null;
31
+ }
32
+ /**
33
+ * Prefixes used for stale-entry cleanup in agent settings files. A registered
34
+ * hook command is considered "managed" if it lives under any known hooks dir
35
+ * (user, extra repos, or system). Entries from removed extra repos are also
36
+ * garbage-collected because they won't appear in this list any more.
37
+ */
38
+ function getManagedHookPrefixes() {
39
+ const extraDirs = getEnabledExtraRepos().map(e => e.dir);
40
+ return [
41
+ path.join(getUserAgentsDir(), 'hooks') + path.sep,
42
+ ...extraDirs.map(d => path.join(d, 'hooks') + path.sep),
43
+ path.join(getSystemAgentsDir(), 'hooks') + path.sep,
44
+ ];
45
+ }
46
+ function isManagedHookCommand(command, prefixes) {
47
+ for (const prefix of prefixes) {
48
+ if (command.startsWith(prefix))
49
+ return true;
50
+ }
51
+ return false;
52
+ }
19
53
  import { getEffectiveHome, getVersionHomePath, listInstalledVersions } from './versions.js';
20
54
  const SCRIPT_EXTENSIONS = new Set([
21
55
  '.sh',
@@ -366,10 +400,32 @@ export function installHookToVersion(agent, version, hookName) {
366
400
  }
367
401
  /**
368
402
  * Remove a single hook (script + data file) from a specific version home.
403
+ * Soft-deletes to ~/.agents/.trash/hooks/.
369
404
  */
370
405
  export function removeHookFromVersion(agent, version, hookName) {
371
406
  try {
372
- removeHookFiles(getVersionHooksDir(agent, version), hookName);
407
+ const hooksDir = getVersionHooksDir(agent, version);
408
+ if (!fs.existsSync(hooksDir))
409
+ return { success: true };
410
+ const stamp = new Date().toISOString().replace(/[:.]/g, '-');
411
+ const trashDir = path.join(getTrashHooksDir(), agent, version, hookName, stamp);
412
+ let moved = false;
413
+ const files = fs.readdirSync(hooksDir);
414
+ for (const file of files) {
415
+ const ext = path.extname(file);
416
+ const base = path.basename(file, ext);
417
+ if (base === hookName) {
418
+ const fullPath = path.join(hooksDir, file);
419
+ const stat = fs.statSync(fullPath);
420
+ if (stat.isFile()) {
421
+ if (!moved) {
422
+ fs.mkdirSync(trashDir, { recursive: true, mode: 0o700 });
423
+ moved = true;
424
+ }
425
+ fs.renameSync(fullPath, path.join(trashDir, file));
426
+ }
427
+ }
428
+ }
373
429
  }
374
430
  catch (err) {
375
431
  return { success: false, error: err.message };
@@ -502,32 +558,37 @@ export function listCentralHooks() {
502
558
  return results;
503
559
  }
504
560
  /**
505
- * Parse hooks.yaml manifests. Reads BOTH system (~/.agents-system/hooks.yaml)
506
- * and user (~/.agents/hooks.yaml), merging with user-wins-on-key-collision
507
- * precedence. A user entry with `enabled: false` disables the system-shipped
508
- * hook of the same name without forking the system file.
561
+ * Parse hook manifests. Reads system hooks from ~/.agents-system/hooks.yaml
562
+ * (npm-shipped defaults) and user hooks from the `hooks:` section of
563
+ * ~/.agents/agents.yaml. Merges with user-wins-on-key-collision precedence.
564
+ * A user entry with `enabled: false` disables the system-shipped hook of
565
+ * the same name without forking the system file.
509
566
  *
510
567
  * Hooks marked `enabled: false` are dropped from the returned map.
511
568
  */
512
569
  export function parseHookManifest() {
513
570
  const merged = {};
514
- // System first (lower precedence), user second (overrides).
515
- for (const dir of [getAgentsDir(), getUserAgentsDir()]) {
516
- const manifestPath = path.join(dir, 'hooks.yaml');
517
- if (!fs.existsSync(manifestPath))
518
- continue;
571
+ // System layer: hooks: section of agents.yaml (npm-shipped, separate repo).
572
+ const systemPath = path.join(getSystemAgentsDir(), 'agents.yaml');
573
+ if (fs.existsSync(systemPath)) {
519
574
  try {
520
- const content = fs.readFileSync(manifestPath, 'utf-8');
521
- const parsed = yaml.parse(content);
522
- if (!parsed)
523
- continue;
524
- for (const [name, def] of Object.entries(parsed)) {
525
- merged[name] = def;
526
- }
575
+ const meta = yaml.parse(fs.readFileSync(systemPath, 'utf-8'));
576
+ if (meta?.hooks)
577
+ for (const [name, def] of Object.entries(meta.hooks))
578
+ merged[name] = def;
527
579
  }
528
- catch {
529
- /* skip unreadable manifest, keep going */
580
+ catch { /* skip unreadable manifest */ }
581
+ }
582
+ // User layer: hooks: section of agents.yaml.
583
+ const userMetaPath = path.join(getUserAgentsDir(), 'agents.yaml');
584
+ if (fs.existsSync(userMetaPath)) {
585
+ try {
586
+ const meta = yaml.parse(fs.readFileSync(userMetaPath, 'utf-8'));
587
+ if (meta?.hooks)
588
+ for (const [name, def] of Object.entries(meta.hooks))
589
+ merged[name] = def;
530
590
  }
591
+ catch { /* skip unreadable meta */ }
531
592
  }
532
593
  // Strip disabled hooks so they never reach the registrar.
533
594
  for (const [name, def] of Object.entries(merged)) {
@@ -542,25 +603,50 @@ const CODEX_MATCHER_EVENTS = new Set(['PreToolUse', 'PostToolUse', 'SessionStart
542
603
  /**
543
604
  * Register hooks as lifecycle events in an agent's config.
544
605
  * Reads hooks.yaml manifest, merges into the agent's config file(s).
545
- * Only manages hooks whose command paths are under ~/.agents/hooks/.
546
- * Does not remove user-added hooks.
606
+ * Only manages hooks whose command paths are under ~/.agents/hooks/ or
607
+ * ~/.agents-system/hooks/. Does not remove user-added hooks.
547
608
  *
548
- * @param agentsDirOverride - Override the agents dir (used in tests to inject a temp path).
609
+ * @param agentsDirOverride - When provided, treats this single dir as the
610
+ * only managed hook root. Used by tests to inject a temp path. In normal
611
+ * operation, both user and system roots are consulted with user precedence.
549
612
  */
550
613
  export function registerHooksToSettings(agentId, versionHome, hookManifest, agentsDirOverride) {
551
614
  const manifest = hookManifest || parseHookManifest();
552
615
  if (Object.keys(manifest).length === 0) {
553
616
  return { registered: [], errors: [] };
554
617
  }
555
- const agentsDir = agentsDirOverride ?? getAgentsDir();
618
+ const overrideRoots = agentsDirOverride ? [agentsDirOverride] : null;
619
+ // Scripts are copied into the version home during sync — prefer that stable
620
+ // local path so registered commands don't break when source dirs change.
621
+ const localHooksDir = !overrideRoots
622
+ ? path.join(versionHome, `.${agentId}`, AGENTS[agentId].hooksDir)
623
+ : null;
624
+ const resolveScript = (script) => {
625
+ if (overrideRoots) {
626
+ const candidate = path.join(overrideRoots[0], 'hooks', script);
627
+ return fs.existsSync(candidate) ? candidate : null;
628
+ }
629
+ if (localHooksDir) {
630
+ const local = path.join(localHooksDir, script);
631
+ if (fs.existsSync(local))
632
+ return local;
633
+ }
634
+ return resolveHookScriptPath(script);
635
+ };
636
+ const managedPrefixes = overrideRoots
637
+ ? [path.join(overrideRoots[0], 'hooks') + path.sep]
638
+ : [
639
+ ...getManagedHookPrefixes(),
640
+ ...(localHooksDir ? [localHooksDir + path.sep] : []),
641
+ ];
556
642
  if (agentId === 'claude') {
557
- return registerHooksForClaude(versionHome, manifest, agentsDir);
643
+ return registerHooksForClaude(versionHome, manifest, resolveScript, managedPrefixes);
558
644
  }
559
645
  if (agentId === 'codex') {
560
- return registerHooksForCodex(versionHome, manifest, agentsDir);
646
+ return registerHooksForCodex(versionHome, manifest, resolveScript, managedPrefixes);
561
647
  }
562
648
  if (agentId === 'gemini') {
563
- return registerHooksForGemini(versionHome, manifest, agentsDir);
649
+ return registerHooksForGemini(versionHome, manifest, resolveScript, managedPrefixes);
564
650
  }
565
651
  return { registered: [], errors: [] };
566
652
  }
@@ -574,7 +660,7 @@ export function registerHooksToSettings(agentId, versionHome, hookManifest, agen
574
660
  const GEMINI_EVENT_MAP = {
575
661
  UserPromptSubmit: 'BeforeAgent',
576
662
  };
577
- function registerHooksForClaude(versionHome, manifest, agentsDir) {
663
+ function registerHooksForClaude(versionHome, manifest, resolveScript, managedPrefixes) {
578
664
  const registered = [];
579
665
  const errors = [];
580
666
  const configDir = path.join(versionHome, '.claude');
@@ -595,14 +681,15 @@ function registerHooksForClaude(versionHome, manifest, agentsDir) {
595
681
  const hooks = config.hooks;
596
682
  // Build set of all command paths the current manifest will register.
597
683
  // Used to garbage-collect stale entries left behind after hook renames.
598
- const managedHooksPrefix = path.join(agentsDir, 'hooks') + path.sep;
599
684
  const currentManifestPaths = new Set();
600
685
  for (const hookDef of Object.values(manifest)) {
601
686
  if (!hookDef.events || hookDef.events.length === 0)
602
687
  continue;
603
- currentManifestPaths.add(path.join(agentsDir, 'hooks', hookDef.script));
688
+ const resolved = resolveScript(hookDef.script);
689
+ if (resolved)
690
+ currentManifestPaths.add(resolved);
604
691
  }
605
- // Remove stale entries: any hook command under ~/.agents/hooks/ that isn't
692
+ // Remove stale entries: any hook command under a managed root that isn't
606
693
  // in the current manifest is a leftover from a renamed/deleted hook script.
607
694
  for (const eventEntries of Object.values(hooks)) {
608
695
  if (!Array.isArray(eventEntries))
@@ -610,7 +697,7 @@ function registerHooksForClaude(versionHome, manifest, agentsDir) {
610
697
  for (const group of eventEntries) {
611
698
  if (!group.hooks)
612
699
  continue;
613
- group.hooks = group.hooks.filter((h) => !h.command.startsWith(managedHooksPrefix) || currentManifestPaths.has(h.command));
700
+ group.hooks = group.hooks.filter((h) => !isManagedHookCommand(h.command, managedPrefixes) || currentManifestPaths.has(h.command));
614
701
  }
615
702
  }
616
703
  // Remove empty matcher groups left after cleanup
@@ -622,9 +709,9 @@ function registerHooksForClaude(versionHome, manifest, agentsDir) {
622
709
  for (const [name, hookDef] of Object.entries(manifest)) {
623
710
  if (!hookDef.events || hookDef.events.length === 0)
624
711
  continue;
625
- const commandPath = path.join(agentsDir, 'hooks', hookDef.script);
626
- if (!fs.existsSync(commandPath)) {
627
- errors.push(`${name}: script not found at ${commandPath}`);
712
+ const commandPath = resolveScript(hookDef.script);
713
+ if (!commandPath) {
714
+ errors.push(`${name}: script not found in user or system hooks dir`);
628
715
  continue;
629
716
  }
630
717
  for (const event of hookDef.events) {
@@ -662,7 +749,7 @@ function registerHooksForClaude(versionHome, manifest, agentsDir) {
662
749
  }
663
750
  return { registered, errors };
664
751
  }
665
- function registerHooksForCodex(versionHome, manifest, agentsDir) {
752
+ function registerHooksForCodex(versionHome, manifest, resolveScript, managedPrefixes) {
666
753
  const registered = [];
667
754
  const errors = [];
668
755
  const configDir = path.join(versionHome, '.codex');
@@ -687,19 +774,20 @@ function registerHooksForCodex(versionHome, manifest, agentsDir) {
687
774
  }
688
775
  }
689
776
  // Build set of current manifest command paths for codex to GC stale entries
690
- const managedHooksPrefix = path.join(agentsDir, 'hooks') + path.sep;
691
777
  const currentManifestPaths = new Set();
692
778
  for (const hookDef of Object.values(manifest)) {
693
779
  if (!hookDef.events || hookDef.events.length === 0)
694
780
  continue;
695
- currentManifestPaths.add(path.join(agentsDir, 'hooks', hookDef.script));
781
+ const resolved = resolveScript(hookDef.script);
782
+ if (resolved)
783
+ currentManifestPaths.add(resolved);
696
784
  }
697
785
  // Remove stale entries from all event groups
698
786
  for (const eventGroups of Object.values(hooksFile.hooks)) {
699
787
  for (const group of eventGroups) {
700
788
  if (!group.hooks)
701
789
  continue;
702
- group.hooks = group.hooks.filter((h) => !h.command.startsWith(managedHooksPrefix) || currentManifestPaths.has(h.command));
790
+ group.hooks = group.hooks.filter((h) => !isManagedHookCommand(h.command, managedPrefixes) || currentManifestPaths.has(h.command));
703
791
  }
704
792
  }
705
793
  for (const [event, eventGroups] of Object.entries(hooksFile.hooks)) {
@@ -708,9 +796,9 @@ function registerHooksForCodex(versionHome, manifest, agentsDir) {
708
796
  for (const [name, hookDef] of Object.entries(manifest)) {
709
797
  if (!hookDef.events || hookDef.events.length === 0)
710
798
  continue;
711
- const commandPath = path.join(agentsDir, 'hooks', hookDef.script);
712
- if (!fs.existsSync(commandPath)) {
713
- errors.push(`${name}: script not found at ${commandPath}`);
799
+ const commandPath = resolveScript(hookDef.script);
800
+ if (!commandPath) {
801
+ errors.push(`${name}: script not found in user or system hooks dir`);
714
802
  continue;
715
803
  }
716
804
  const timeout = hookDef.timeout || 600;
@@ -784,7 +872,7 @@ function registerHooksForCodex(versionHome, manifest, agentsDir) {
784
872
  }
785
873
  return { registered, errors };
786
874
  }
787
- function registerHooksForGemini(versionHome, manifest, agentsDir) {
875
+ function registerHooksForGemini(versionHome, manifest, resolveScript, managedPrefixes) {
788
876
  const registered = [];
789
877
  const errors = [];
790
878
  const settingsPath = path.join(versionHome, '.gemini', 'settings.json');
@@ -795,12 +883,13 @@ function registerHooksForGemini(versionHome, manifest, agentsDir) {
795
883
  config.hooks = {};
796
884
  }
797
885
  const hooks = config.hooks;
798
- const managedHooksPrefix = path.join(agentsDir, 'hooks') + path.sep;
799
886
  const currentManifestPaths = new Set();
800
887
  for (const hookDef of Object.values(manifest)) {
801
888
  if (!hookDef.events || hookDef.events.length === 0)
802
889
  continue;
803
- currentManifestPaths.add(path.join(agentsDir, 'hooks', hookDef.script));
890
+ const resolved = resolveScript(hookDef.script);
891
+ if (resolved)
892
+ currentManifestPaths.add(resolved);
804
893
  }
805
894
  for (const eventEntries of Object.values(hooks)) {
806
895
  if (!Array.isArray(eventEntries))
@@ -808,7 +897,7 @@ function registerHooksForGemini(versionHome, manifest, agentsDir) {
808
897
  for (const group of eventEntries) {
809
898
  if (!group.hooks)
810
899
  continue;
811
- group.hooks = group.hooks.filter((h) => !h.command.startsWith(managedHooksPrefix) || currentManifestPaths.has(h.command));
900
+ group.hooks = group.hooks.filter((h) => !isManagedHookCommand(h.command, managedPrefixes) || currentManifestPaths.has(h.command));
812
901
  }
813
902
  }
814
903
  for (const [event, eventEntries] of Object.entries(hooks)) {
@@ -819,9 +908,9 @@ function registerHooksForGemini(versionHome, manifest, agentsDir) {
819
908
  for (const [name, hookDef] of Object.entries(manifest)) {
820
909
  if (!hookDef.events || hookDef.events.length === 0)
821
910
  continue;
822
- const commandPath = path.join(agentsDir, 'hooks', hookDef.script);
823
- if (!fs.existsSync(commandPath)) {
824
- errors.push(`${name}: script not found at ${commandPath}`);
911
+ const commandPath = resolveScript(hookDef.script);
912
+ if (!commandPath) {
913
+ errors.push(`${name}: script not found in user or system hooks dir`);
825
914
  continue;
826
915
  }
827
916
  const timeoutMs = (hookDef.timeout || 600) * 1000;
@@ -5,4 +5,4 @@
5
5
  * Each migration is guarded by an existence check so re-running is safe.
6
6
  */
7
7
  /** Run all idempotent migrations. Safe to call multiple times. */
8
- export declare function runMigration(): void;
8
+ export declare function runMigration(): Promise<void>;