@indigoai-us/hq-cli 5.345.170 → 5.345.172
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +84 -0
- package/assets/scaffold/core/scripts/hq-delegate-send.sh +1 -1
- package/dist/command-catalog.generated.d.ts +206 -7
- package/dist/command-catalog.generated.js +252 -8
- package/dist/command-registration-plan.d.ts +7 -0
- package/dist/command-registration-plan.js +1 -0
- package/dist/commands/access.d.ts +32 -1
- package/dist/commands/access.js +112 -3
- package/dist/commands/agent-kit.d.ts +1 -1
- package/dist/commands/agent-kit.js +3 -1
- package/dist/commands/agents.js +2 -1
- package/dist/commands/bot.d.ts +3 -0
- package/dist/commands/bot.js +179 -18
- package/dist/commands/cloud.d.ts +58 -1
- package/dist/commands/cloud.js +228 -10
- package/dist/commands/core-company-index-scope-flag.d.ts +8 -1
- package/dist/commands/core-company-index-scope-flag.js +9 -2
- package/dist/commands/core-delegate-w1b.js +5 -2
- package/dist/commands/core-dm-bind-native.js +19 -4
- package/dist/commands/core-rebuild-index-fast.js +24 -6
- package/dist/commands/core.js +18 -6
- package/dist/commands/daemon.js +16 -1
- package/dist/commands/dm.d.ts +17 -3
- package/dist/commands/dm.js +121 -26
- package/dist/commands/files.d.ts +1 -0
- package/dist/commands/files.js +22 -4
- package/dist/commands/integrations-api.d.ts +4 -0
- package/dist/commands/integrations-api.js +18 -2
- package/dist/commands/integrations-connect.d.ts +10 -3
- package/dist/commands/integrations-connect.js +70 -6
- package/dist/commands/integrations-core.d.ts +23 -0
- package/dist/commands/integrations-core.js +100 -0
- package/dist/commands/integrations-manage.js +8 -1
- package/dist/commands/integrations.js +49 -5
- package/dist/commands/lanes-loop.d.ts +20 -0
- package/dist/commands/lanes-loop.js +69 -11
- package/dist/commands/lanes.js +9 -1
- package/dist/commands/rescue.d.ts +9 -0
- package/dist/commands/rescue.js +31 -0
- package/dist/commands/run.js +115 -40
- package/dist/commands/scan.d.ts +5 -1
- package/dist/commands/scan.js +16 -4
- package/dist/commands/secrets.js +50 -9
- package/dist/commands/sync-core.d.ts +22 -0
- package/dist/commands/sync-core.js +124 -0
- package/dist/hq-cloud-sync-runner/bin/sync-runner.js +2447 -2135
- package/dist/hq-cloud-sync-runner/package.json +1 -1
- package/dist/lib/agent-kit/inbox-state.d.ts +17 -0
- package/dist/lib/agent-kit/inbox-state.js +41 -20
- package/dist/lib/agent-kit/kit-config.d.ts +2 -0
- package/dist/lib/agent-kit/kit-config.js +6 -0
- package/dist/lib/agent-kit/mcp/tools.js +12 -5
- package/dist/lib/agent-kit/run/heartbeat.d.ts +6 -3
- package/dist/lib/agent-kit/run/heartbeat.js +6 -3
- package/dist/lib/agent-kit/run/inbox.d.ts +8 -3
- package/dist/lib/agent-kit/run/inbox.js +42 -10
- package/dist/lib/agent-kit/run/request-timeout.d.ts +26 -0
- package/dist/lib/agent-kit/run/request-timeout.js +51 -0
- package/dist/lib/bot/api.d.ts +1 -1
- package/dist/lib/bot/config.d.ts +10 -0
- package/dist/lib/bot/config.js +17 -1
- package/dist/lib/bot/fleet-local.d.ts +142 -0
- package/dist/lib/bot/fleet-local.js +689 -0
- package/dist/lib/bot/fleet-python.d.ts +47 -0
- package/dist/lib/bot/fleet-python.js +218 -0
- package/dist/lib/bot/index.d.ts +2 -0
- package/dist/lib/bot/index.js +2 -0
- package/dist/lib/bot/local-config.d.ts +3 -2
- package/dist/lib/bot/local-config.js +5 -2
- package/dist/lib/bot/promote.d.ts +10 -0
- package/dist/lib/bot/promote.js +3 -2
- package/dist/lib/bot/prompt.d.ts +6 -1
- package/dist/lib/bot/prompt.js +8 -3
- package/dist/lib/bot/runtime/index.js +8 -4
- package/dist/lib/bot/runtime/scratch-dir.d.ts +24 -0
- package/dist/lib/bot/runtime/scratch-dir.js +41 -0
- package/dist/lib/caller-principal.d.ts +4 -0
- package/dist/lib/caller-principal.js +40 -0
- package/dist/lib/capacity/collectors/grok.js +8 -2
- package/dist/lib/cli-flag-keys.d.ts +2 -0
- package/dist/lib/cli-flag-keys.js +2 -0
- package/dist/lib/daemon/catalog.d.ts +12 -4
- package/dist/lib/daemon/catalog.js +70 -24
- package/dist/lib/daemon/config.d.ts +0 -7
- package/dist/lib/daemon/config.js +0 -32
- package/dist/lib/daemon/run.d.ts +5 -1
- package/dist/lib/daemon/run.js +48 -11
- package/dist/lib/daemon/supervisor.js +3 -1
- package/dist/lib/doctor/checks/release-links.d.ts +62 -1
- package/dist/lib/doctor/checks/release-links.js +188 -2
- package/dist/lib/doctor/fix/apply.js +54 -0
- package/dist/lib/doctor/fix/remediation.d.ts +8 -1
- package/dist/lib/doctor/fix/remediation.js +22 -0
- package/dist/lib/flag-registry-worker-source.generated.d.ts +1 -1
- package/dist/lib/flag-registry-worker-source.generated.js +1 -1
- package/dist/lib/index-render/index.d.ts +9 -0
- package/dist/lib/index-render/index.js +65 -5
- package/dist/lib/index-render/session-scope.d.ts +69 -0
- package/dist/lib/index-render/session-scope.js +279 -0
- package/dist/lib/lanes/admission.js +7 -20
- package/dist/lib/lanes/reconcile.js +13 -15
- package/dist/lib/lanes/stale-lock.d.ts +50 -0
- package/dist/lib/lanes/stale-lock.js +105 -0
- package/dist/lib/lanes/store.js +11 -76
- package/dist/lib/notify-recipient.d.ts +10 -4
- package/dist/lib/notify-recipient.js +16 -4
- package/dist/lib/secret-input-link.d.ts +42 -0
- package/dist/lib/secret-input-link.js +93 -0
- package/dist/lib/secret-scan/range.d.ts +57 -0
- package/dist/lib/secret-scan/range.js +266 -0
- package/dist/lib/secret-scan/repo-config.d.ts +18 -3
- package/dist/lib/secret-scan/repo-config.js +135 -2
- package/dist/lib/sync-core/engine-home.d.ts +44 -0
- package/dist/lib/sync-core/engine-home.js +193 -0
- package/dist/lib/sync-core/flag.d.ts +17 -0
- package/dist/lib/sync-core/flag.js +47 -0
- package/dist/lib/sync-core/reconcile.d.ts +31 -0
- package/dist/lib/sync-core/reconcile.js +196 -0
- package/dist/lib/sync-core/release.d.ts +32 -0
- package/dist/lib/sync-core/release.js +140 -0
- package/dist/lib/sync-core/rollout-state.d.ts +24 -0
- package/dist/lib/sync-core/rollout-state.js +94 -0
- package/dist/lib/vault-sync-switches.d.ts +5 -0
- package/dist/lib/vault-sync-switches.js +43 -0
- package/dist/run/script-bound-schema.d.ts +27 -0
- package/dist/run/script-bound-schema.js +97 -0
- package/dist/secrets-env-action.d.ts +2 -0
- package/dist/secrets-env-action.js +7 -2
- package/dist/utils/cognito-session.d.ts +3 -30
- package/dist/utils/cognito-session.js +2 -100
- package/dist/utils/machine-principal-state.d.ts +38 -0
- package/dist/utils/machine-principal-state.js +110 -0
- package/dist/utils/remote-list-not-converging.d.ts +21 -0
- package/dist/utils/remote-list-not-converging.js +40 -0
- package/dist/utils/safe-link.js +9 -0
- package/dist/utils/script-bound-exec.d.ts +158 -0
- package/dist/utils/script-bound-exec.js +568 -0
- package/dist/utils/sync-watchdog.d.ts +92 -0
- package/dist/utils/sync-watchdog.js +250 -0
- package/package.json +8 -8
- package/dist/lib/daemon/sync-core-canary.d.ts +0 -9
- package/dist/lib/daemon/sync-core-canary.js +0 -56
|
@@ -1252,6 +1252,16 @@ export const COMMAND_CATALOG = [
|
|
|
1252
1252
|
"flags": "--force-scope-shrink",
|
|
1253
1253
|
"description": "When a scope shrink would un-track locally-modified files, proceed anyway. Dirty files are KEPT on disk (only un-tracked); clean out-of-scope files are quarantined under .hq/scope-quarantine/.",
|
|
1254
1254
|
"hidden": false
|
|
1255
|
+
},
|
|
1256
|
+
{
|
|
1257
|
+
"flags": "--max-idle <seconds>",
|
|
1258
|
+
"description": "For scheduled or unattended runs: stop with exit code 124 after this many seconds with no file planned, transferred or skipped. The remote listing and planning phase of a leg reports no progress, so set this longer than your slowest planning phase. Laptop sleep does not count. (default: HQ_SYNC_MAX_IDLE, else off)",
|
|
1259
|
+
"hidden": false
|
|
1260
|
+
},
|
|
1261
|
+
{
|
|
1262
|
+
"flags": "--max-runtime <seconds>",
|
|
1263
|
+
"description": "For scheduled or unattended runs: stop with exit code 124 if the run has not finished after this many seconds, even while it is making progress. Laptop sleep does not count. (default: HQ_SYNC_MAX_RUNTIME, else off)",
|
|
1264
|
+
"hidden": false
|
|
1255
1265
|
}
|
|
1256
1266
|
],
|
|
1257
1267
|
"subcommands": []
|
|
@@ -2750,6 +2760,16 @@ export const COMMAND_CATALOG = [
|
|
|
2750
2760
|
"description": "Token expiry duration (e.g. 24h, 2d, 30m)",
|
|
2751
2761
|
"hidden": false,
|
|
2752
2762
|
"defaultValue": "24h"
|
|
2763
|
+
},
|
|
2764
|
+
{
|
|
2765
|
+
"flags": "--format <format>",
|
|
2766
|
+
"description": "Output format: text (default; OSC-8 hyperlink on a supporting TTY, plain URL otherwise; FORCE_HYPERLINK=1/0 overrides detection on a TTY only), markdown (one Markdown link line on stdout, details on stderr), json",
|
|
2767
|
+
"hidden": false
|
|
2768
|
+
},
|
|
2769
|
+
{
|
|
2770
|
+
"flags": "--json",
|
|
2771
|
+
"description": "Print { url, expiresAt, secretName } as JSON (same as --format json)",
|
|
2772
|
+
"hidden": false
|
|
2753
2773
|
}
|
|
2754
2774
|
],
|
|
2755
2775
|
"subcommands": []
|
|
@@ -3654,7 +3674,7 @@ export const COMMAND_CATALOG = [
|
|
|
3654
3674
|
},
|
|
3655
3675
|
{
|
|
3656
3676
|
"name": "files",
|
|
3657
|
-
"description": "Manage file access controls in HQ vault. A trailing folder slash (foo/) is a private folder; the quoted glob 'foo/*' shares all children.",
|
|
3677
|
+
"description": "Manage file access controls in HQ vault. A trailing folder slash (foo/) is a private folder; the quoted glob 'foo/*' shares all children, and a quoted 'clients/*/reports' shares that folder under every client.",
|
|
3658
3678
|
"aliases": [],
|
|
3659
3679
|
"hidden": false,
|
|
3660
3680
|
"helpOption": true,
|
|
@@ -3672,7 +3692,7 @@ export const COMMAND_CATALOG = [
|
|
|
3672
3692
|
"subcommands": [
|
|
3673
3693
|
{
|
|
3674
3694
|
"name": "share",
|
|
3675
|
-
"description": "Share file paths. foo/ is a private folder (children stay creator-only); quote the shared-folder glob 'foo/*' so the shell passes it literally. Without --with: mint a share-session URL and open it in the browser. With --with: grant access directly to a person, group, or @all.",
|
|
3695
|
+
"description": "Share file paths. foo/ is a private folder (children stay creator-only); quote the shared-folder glob 'foo/*', or a one-folder wildcard such as 'clients/*/reports', so the shell passes it literally. Without --with: mint a share-session URL and open it in the browser. With --with: grant access directly to a person, group, or @all.",
|
|
3676
3696
|
"aliases": [],
|
|
3677
3697
|
"hidden": false,
|
|
3678
3698
|
"helpOption": true,
|
|
@@ -4095,7 +4115,7 @@ export const COMMAND_CATALOG = [
|
|
|
4095
4115
|
"helpText": [
|
|
4096
4116
|
{
|
|
4097
4117
|
"position": "after",
|
|
4098
|
-
"text": "\nExit codes:\n 0 local or not-synced (file exists and you can read it)\n 2 never-existed (the path was never created)\n 3 no-access (the file exists but you cannot read it)\n 4 ambiguous (several keys matched; pick one)\n\nWith several paths, each gets its own result block and the exit code is the\nhighest one across the paths.\n"
|
|
4118
|
+
"text": "\nExit codes:\n 0 local or not-synced (file exists and you can read it)\n 2 never-existed (the path was never created)\n 3 no-access (the file exists but you cannot read it), or\n no-write-access (the file is on disk, not in the vault, and you cannot\n write to it, so a push cannot upload it)\n 4 ambiguous (several keys matched; pick one)\n\nWith several paths, each gets its own result block and the exit code is the\nhighest one across the paths.\n"
|
|
4099
4119
|
}
|
|
4100
4120
|
],
|
|
4101
4121
|
"arguments": [
|
|
@@ -4842,7 +4862,7 @@ export const COMMAND_CATALOG = [
|
|
|
4842
4862
|
},
|
|
4843
4863
|
{
|
|
4844
4864
|
"name": "dm",
|
|
4845
|
-
"description": "Send and read direct messages, and manage connection requests. Messages
|
|
4865
|
+
"description": "Send and read direct messages, and manage connection requests. Messages sent from a person login are always tagged for people. When an agent or bot sends, messages to an agent, a channel or a group are tagged for agents and folded away from people by default. Pass --for-human or --audience human to tag a message for people; --audience agent|both is for agents and bots only.",
|
|
4846
4866
|
"aliases": [],
|
|
4847
4867
|
"hidden": false,
|
|
4848
4868
|
"helpOption": true,
|
|
@@ -4923,7 +4943,7 @@ export const COMMAND_CATALOG = [
|
|
|
4923
4943
|
},
|
|
4924
4944
|
{
|
|
4925
4945
|
"flags": "--audience <human|agent|both>",
|
|
4926
|
-
"description": "Tag who this message is for: human (a person must read it), agent (progress/status, hidden from humans by default), or both. Default: human for a person, agent for an agent, a channel or a group. Wins over --for-human.",
|
|
4946
|
+
"description": "Tag who this message is for: human (a person must read it), agent (progress/status, hidden from humans by default), or both. agent and both are for agents and bots only; a person login always sends human. Default for agents and bots: human for a person, agent for an agent, a channel or a group. Wins over --for-human.",
|
|
4927
4947
|
"hidden": false
|
|
4928
4948
|
},
|
|
4929
4949
|
{
|
|
@@ -6478,6 +6498,11 @@ export const COMMAND_CATALOG = [
|
|
|
6478
6498
|
"description": "Company slug, e.g. indigo",
|
|
6479
6499
|
"hidden": false
|
|
6480
6500
|
},
|
|
6501
|
+
{
|
|
6502
|
+
"flags": "--account <id-or-label>",
|
|
6503
|
+
"description": "Which account of the app: its connection id or account label",
|
|
6504
|
+
"hidden": false
|
|
6505
|
+
},
|
|
6481
6506
|
{
|
|
6482
6507
|
"flags": "--describe <tool>",
|
|
6483
6508
|
"description": "Print the full input schema for one tool",
|
|
@@ -6519,6 +6544,11 @@ export const COMMAND_CATALOG = [
|
|
|
6519
6544
|
"description": "Connection id (acct_…)",
|
|
6520
6545
|
"hidden": false
|
|
6521
6546
|
},
|
|
6547
|
+
{
|
|
6548
|
+
"flags": "--account <id-or-label>",
|
|
6549
|
+
"description": "Which account of the app: its connection id or account label",
|
|
6550
|
+
"hidden": false
|
|
6551
|
+
},
|
|
6522
6552
|
{
|
|
6523
6553
|
"flags": "--company <slug>",
|
|
6524
6554
|
"description": "Company slug, e.g. indigo",
|
|
@@ -6840,6 +6870,16 @@ export const COMMAND_CATALOG = [
|
|
|
6840
6870
|
"description": "Connect again even if this app is already connected",
|
|
6841
6871
|
"hidden": false
|
|
6842
6872
|
},
|
|
6873
|
+
{
|
|
6874
|
+
"flags": "--personal",
|
|
6875
|
+
"description": "Connect it as your own personal connection (not --company <slug>, which picks the company)",
|
|
6876
|
+
"hidden": false
|
|
6877
|
+
},
|
|
6878
|
+
{
|
|
6879
|
+
"flags": "--company-owned",
|
|
6880
|
+
"description": "Connect it as a connection the whole company owns (needs permission to add company apps)",
|
|
6881
|
+
"hidden": false
|
|
6882
|
+
},
|
|
6843
6883
|
{
|
|
6844
6884
|
"flags": "--json",
|
|
6845
6885
|
"description": "Machine-readable output",
|
|
@@ -6926,6 +6966,16 @@ export const COMMAND_CATALOG = [
|
|
|
6926
6966
|
"description": "For a revoked row, run `connect <domain>` to re-add and revive it",
|
|
6927
6967
|
"hidden": false
|
|
6928
6968
|
},
|
|
6969
|
+
{
|
|
6970
|
+
"flags": "--personal",
|
|
6971
|
+
"description": "With --connect: re-add it as your own personal connection",
|
|
6972
|
+
"hidden": false
|
|
6973
|
+
},
|
|
6974
|
+
{
|
|
6975
|
+
"flags": "--company-owned",
|
|
6976
|
+
"description": "With --connect: re-add it as a connection the whole company owns",
|
|
6977
|
+
"hidden": false
|
|
6978
|
+
},
|
|
6929
6979
|
{
|
|
6930
6980
|
"flags": "--json",
|
|
6931
6981
|
"description": "Machine-readable output",
|
|
@@ -7698,7 +7748,7 @@ export const COMMAND_CATALOG = [
|
|
|
7698
7748
|
},
|
|
7699
7749
|
{
|
|
7700
7750
|
"flags": "--repo <dir>",
|
|
7701
|
-
"description": "With files: apply this repo's committed .gitleaks.toml allowlists, matching repo-relative paths",
|
|
7751
|
+
"description": "With files: apply this repo's committed .gitleaks.toml allowlists, matching repo-relative paths. With --range: the repo to scan (default: the current directory)",
|
|
7702
7752
|
"hidden": false
|
|
7703
7753
|
},
|
|
7704
7754
|
{
|
|
@@ -7710,6 +7760,11 @@ export const COMMAND_CATALOG = [
|
|
|
7710
7760
|
"flags": "--allowlist-rev <rev>",
|
|
7711
7761
|
"description": "With --repo: read .gitleaks.toml from this commit instead of HEAD",
|
|
7712
7762
|
"hidden": false
|
|
7763
|
+
},
|
|
7764
|
+
{
|
|
7765
|
+
"flags": "--range <range>",
|
|
7766
|
+
"description": "Scan the lines added in <base>..<head> (head defaults to HEAD), every commit included, with the base's .gitleaks.toml allowlists and the repo's [[rules]]",
|
|
7767
|
+
"hidden": false
|
|
7713
7768
|
}
|
|
7714
7769
|
],
|
|
7715
7770
|
"subcommands": []
|
|
@@ -10370,6 +10425,49 @@ export const COMMAND_CATALOG = [
|
|
|
10370
10425
|
],
|
|
10371
10426
|
"subcommands": []
|
|
10372
10427
|
},
|
|
10428
|
+
{
|
|
10429
|
+
"name": "pull",
|
|
10430
|
+
"description": "Download one file from an Outpost through a short-lived download link (for files too large for exec output). <outpost> is the Outpost id (`primary` for your first box). The remote path must be inside the Outpost user's home or HQ dir; relative and ~ paths start at the home dir. The file is saved to [local-path], or to the remote file name in the current directory.",
|
|
10431
|
+
"aliases": [],
|
|
10432
|
+
"hidden": false,
|
|
10433
|
+
"helpOption": true,
|
|
10434
|
+
"helpCommand": false,
|
|
10435
|
+
"usage": "[options] <outpost> <remote-path> [local-path]",
|
|
10436
|
+
"helpText": [],
|
|
10437
|
+
"arguments": [
|
|
10438
|
+
{
|
|
10439
|
+
"name": "outpost",
|
|
10440
|
+
"required": true,
|
|
10441
|
+
"variadic": false,
|
|
10442
|
+
"description": ""
|
|
10443
|
+
},
|
|
10444
|
+
{
|
|
10445
|
+
"name": "remote-path",
|
|
10446
|
+
"required": true,
|
|
10447
|
+
"variadic": false,
|
|
10448
|
+
"description": ""
|
|
10449
|
+
},
|
|
10450
|
+
{
|
|
10451
|
+
"name": "local-path",
|
|
10452
|
+
"required": false,
|
|
10453
|
+
"variadic": false,
|
|
10454
|
+
"description": ""
|
|
10455
|
+
}
|
|
10456
|
+
],
|
|
10457
|
+
"options": [
|
|
10458
|
+
{
|
|
10459
|
+
"flags": "--force",
|
|
10460
|
+
"description": "Replace the local file if it already exists",
|
|
10461
|
+
"hidden": false
|
|
10462
|
+
},
|
|
10463
|
+
{
|
|
10464
|
+
"flags": "--json",
|
|
10465
|
+
"description": "Emit raw JSON",
|
|
10466
|
+
"hidden": false
|
|
10467
|
+
}
|
|
10468
|
+
],
|
|
10469
|
+
"subcommands": []
|
|
10470
|
+
},
|
|
10373
10471
|
{
|
|
10374
10472
|
"name": "terminal",
|
|
10375
10473
|
"description": "Open an interactive terminal on an Outpost — a real TTY over SSM Session Manager (no SSH, no local AWS credentials). Requires the AWS session-manager-plugin installed locally. With --forward, tunnels a port on the box to your machine instead of opening a shell.",
|
|
@@ -22251,6 +22349,25 @@ export const COMMAND_CATALOG = [
|
|
|
22251
22349
|
"options": [],
|
|
22252
22350
|
"subcommands": []
|
|
22253
22351
|
},
|
|
22352
|
+
{
|
|
22353
|
+
"name": "sync-core-reconcile",
|
|
22354
|
+
"description": "Read each company's new-sync-engine switch and write this machine's engine homes and legacy off-switches",
|
|
22355
|
+
"aliases": [],
|
|
22356
|
+
"hidden": false,
|
|
22357
|
+
"helpOption": true,
|
|
22358
|
+
"helpCommand": false,
|
|
22359
|
+
"usage": "[options]",
|
|
22360
|
+
"helpText": [],
|
|
22361
|
+
"arguments": [],
|
|
22362
|
+
"options": [
|
|
22363
|
+
{
|
|
22364
|
+
"flags": "--hq-root <path>",
|
|
22365
|
+
"description": "HQ folder the engine works against",
|
|
22366
|
+
"hidden": false
|
|
22367
|
+
}
|
|
22368
|
+
],
|
|
22369
|
+
"subcommands": []
|
|
22370
|
+
},
|
|
22254
22371
|
{
|
|
22255
22372
|
"name": "remote-control",
|
|
22256
22373
|
"description": "Keep `claude remote-control` running in a tmux session in the HQ folder",
|
|
@@ -22399,6 +22516,73 @@ export const COMMAND_CATALOG = [
|
|
|
22399
22516
|
}
|
|
22400
22517
|
]
|
|
22401
22518
|
},
|
|
22519
|
+
{
|
|
22520
|
+
"name": "sync-core",
|
|
22521
|
+
"description": "Move this machine's vaults between the current sync and the new sync engine, following each company's switch",
|
|
22522
|
+
"aliases": [],
|
|
22523
|
+
"hidden": true,
|
|
22524
|
+
"helpOption": true,
|
|
22525
|
+
"helpCommand": true,
|
|
22526
|
+
"usage": "[options] [command]",
|
|
22527
|
+
"helpText": [],
|
|
22528
|
+
"arguments": [],
|
|
22529
|
+
"options": [],
|
|
22530
|
+
"subcommands": [
|
|
22531
|
+
{
|
|
22532
|
+
"name": "reconcile",
|
|
22533
|
+
"description": "Read each company's switch, install the engine when needed, and write the engine homes and legacy off-switches",
|
|
22534
|
+
"aliases": [],
|
|
22535
|
+
"hidden": false,
|
|
22536
|
+
"helpOption": true,
|
|
22537
|
+
"helpCommand": false,
|
|
22538
|
+
"usage": "[options]",
|
|
22539
|
+
"helpText": [],
|
|
22540
|
+
"arguments": [],
|
|
22541
|
+
"options": [
|
|
22542
|
+
{
|
|
22543
|
+
"flags": "--hq-root <path>",
|
|
22544
|
+
"description": "HQ folder (default: the daemon's)",
|
|
22545
|
+
"hidden": false
|
|
22546
|
+
},
|
|
22547
|
+
{
|
|
22548
|
+
"flags": "--companies-only",
|
|
22549
|
+
"description": "Never move the personal vault (agent boxes)",
|
|
22550
|
+
"hidden": false
|
|
22551
|
+
},
|
|
22552
|
+
{
|
|
22553
|
+
"flags": "--token-file <path>",
|
|
22554
|
+
"description": "Token file the engine reads (default: this user's hq sign-in)",
|
|
22555
|
+
"hidden": false
|
|
22556
|
+
},
|
|
22557
|
+
{
|
|
22558
|
+
"flags": "--json",
|
|
22559
|
+
"description": "Print the written rollout state as JSON",
|
|
22560
|
+
"hidden": false
|
|
22561
|
+
}
|
|
22562
|
+
],
|
|
22563
|
+
"subcommands": []
|
|
22564
|
+
},
|
|
22565
|
+
{
|
|
22566
|
+
"name": "status",
|
|
22567
|
+
"description": "Show which vaults are on the new sync engine on this machine",
|
|
22568
|
+
"aliases": [],
|
|
22569
|
+
"hidden": false,
|
|
22570
|
+
"helpOption": true,
|
|
22571
|
+
"helpCommand": false,
|
|
22572
|
+
"usage": "[options]",
|
|
22573
|
+
"helpText": [],
|
|
22574
|
+
"arguments": [],
|
|
22575
|
+
"options": [
|
|
22576
|
+
{
|
|
22577
|
+
"flags": "--json",
|
|
22578
|
+
"description": "Print JSON",
|
|
22579
|
+
"hidden": false
|
|
22580
|
+
}
|
|
22581
|
+
],
|
|
22582
|
+
"subcommands": []
|
|
22583
|
+
}
|
|
22584
|
+
]
|
|
22585
|
+
},
|
|
22402
22586
|
{
|
|
22403
22587
|
"name": "bot",
|
|
22404
22588
|
"description": "Personal local bots that run on this computer with your own model login",
|
|
@@ -22596,8 +22780,12 @@ export const COMMAND_CATALOG = [
|
|
|
22596
22780
|
{
|
|
22597
22781
|
"flags": "--runtime <runtime>",
|
|
22598
22782
|
"description": "Model CLI to run the bot with: claude|codex|grok",
|
|
22599
|
-
"hidden": false
|
|
22600
|
-
|
|
22783
|
+
"hidden": false
|
|
22784
|
+
},
|
|
22785
|
+
{
|
|
22786
|
+
"flags": "--hq-fleet-runtime",
|
|
22787
|
+
"description": "Create this personal bot with the local HQ Fleet Runtime",
|
|
22788
|
+
"hidden": false
|
|
22601
22789
|
},
|
|
22602
22790
|
{
|
|
22603
22791
|
"flags": "--model <model>",
|
|
@@ -22933,6 +23121,62 @@ export const COMMAND_CATALOG = [
|
|
|
22933
23121
|
],
|
|
22934
23122
|
"subcommands": []
|
|
22935
23123
|
},
|
|
23124
|
+
{
|
|
23125
|
+
"name": "auth",
|
|
23126
|
+
"description": "Sign a runtime-backed personal bot in to ChatGPT, Grok, Claude, or another supported provider",
|
|
23127
|
+
"aliases": [],
|
|
23128
|
+
"hidden": false,
|
|
23129
|
+
"helpOption": true,
|
|
23130
|
+
"helpCommand": false,
|
|
23131
|
+
"usage": "[options] <name>",
|
|
23132
|
+
"helpText": [],
|
|
23133
|
+
"arguments": [
|
|
23134
|
+
{
|
|
23135
|
+
"name": "name",
|
|
23136
|
+
"required": true,
|
|
23137
|
+
"variadic": false,
|
|
23138
|
+
"description": ""
|
|
23139
|
+
}
|
|
23140
|
+
],
|
|
23141
|
+
"options": [
|
|
23142
|
+
{
|
|
23143
|
+
"flags": "--provider <provider>",
|
|
23144
|
+
"description": "Provider: chatgpt, grok, claude, or a runtime provider id",
|
|
23145
|
+
"hidden": false
|
|
23146
|
+
},
|
|
23147
|
+
{
|
|
23148
|
+
"flags": "--model <model>",
|
|
23149
|
+
"description": "Model id; required for providers without a built-in personal-bot default",
|
|
23150
|
+
"hidden": false
|
|
23151
|
+
},
|
|
23152
|
+
{
|
|
23153
|
+
"flags": "--api-key",
|
|
23154
|
+
"description": "Read an API key from stdin instead of starting device authorization",
|
|
23155
|
+
"hidden": false
|
|
23156
|
+
},
|
|
23157
|
+
{
|
|
23158
|
+
"flags": "--base-url <url>",
|
|
23159
|
+
"description": "Provider API base URL; required for custom runtime providers",
|
|
23160
|
+
"hidden": false
|
|
23161
|
+
},
|
|
23162
|
+
{
|
|
23163
|
+
"flags": "--transport <transport>",
|
|
23164
|
+
"description": "Provider transport: chat_completions, anthropic_messages, or codex_responses",
|
|
23165
|
+
"hidden": false
|
|
23166
|
+
},
|
|
23167
|
+
{
|
|
23168
|
+
"flags": "--no-browser",
|
|
23169
|
+
"description": "Do not open a browser during device authorization",
|
|
23170
|
+
"hidden": false
|
|
23171
|
+
},
|
|
23172
|
+
{
|
|
23173
|
+
"flags": "--json",
|
|
23174
|
+
"description": "Print machine-readable JSON",
|
|
23175
|
+
"hidden": false
|
|
23176
|
+
}
|
|
23177
|
+
],
|
|
23178
|
+
"subcommands": []
|
|
23179
|
+
},
|
|
22936
23180
|
{
|
|
22937
23181
|
"name": "logs",
|
|
22938
23182
|
"description": "Show the bot's log",
|
|
@@ -515,6 +515,13 @@ export declare const REGISTRATION_PLAN: readonly [{
|
|
|
515
515
|
readonly module: "./commands/daemon.js";
|
|
516
516
|
readonly exportName: "registerDaemonCommand";
|
|
517
517
|
readonly hidden: true;
|
|
518
|
+
}, {
|
|
519
|
+
readonly type: "registrar";
|
|
520
|
+
readonly root: "sync-core";
|
|
521
|
+
readonly parent: "program";
|
|
522
|
+
readonly module: "./commands/sync-core.js";
|
|
523
|
+
readonly exportName: "registerSyncCoreCommand";
|
|
524
|
+
readonly hidden: true;
|
|
518
525
|
}, {
|
|
519
526
|
readonly type: "registrar";
|
|
520
527
|
readonly root: "bot";
|
|
@@ -88,6 +88,7 @@ export const REGISTRATION_PLAN = [
|
|
|
88
88
|
{ type: "registrar", root: "lanes", parent: "program", module: "./commands/lanes.js", exportName: "registerLanesCommand" },
|
|
89
89
|
{ type: "registrar", root: "monitor", parent: "program", module: "./commands/monitor.js", exportName: "registerMonitorCommand" },
|
|
90
90
|
{ type: "registrar", root: "daemon", parent: "program", module: "./commands/daemon.js", exportName: "registerDaemonCommand", hidden: true },
|
|
91
|
+
{ type: "registrar", root: "sync-core", parent: "program", module: "./commands/sync-core.js", exportName: "registerSyncCoreCommand", hidden: true },
|
|
91
92
|
{ type: "registrar", root: "bot", parent: "program", module: "./commands/bot.js", exportName: "registerBotCommand" },
|
|
92
93
|
{ type: "registrar", root: "report", parent: "program", module: "./commands/report.js", exportName: "registerReportCommand" },
|
|
93
94
|
{ type: "group", root: "deploy", id: "deploy", name: "deploy", description: "Manage deployments in hq-deploy" },
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
import { Command } from "commander";
|
|
17
17
|
import { type CompanyBrowseClientFactory, type FilesBrowseVaultClient, type RunGetResult } from "./files-browse.js";
|
|
18
18
|
import { type AclLock } from "./acl-lock.js";
|
|
19
|
-
export type AccessOutcome = "never-existed" | "local" | "not-synced" | "no-access" | "ambiguous" | "pending-confirmation";
|
|
19
|
+
export type AccessOutcome = "never-existed" | "local" | "not-synced" | "no-access" | "no-write-access" | "ambiguous" | "pending-confirmation";
|
|
20
20
|
export interface AccessAclTree {
|
|
21
21
|
prefix: string;
|
|
22
22
|
direct: Array<{
|
|
@@ -151,6 +151,15 @@ export interface RunAccessResult {
|
|
|
151
151
|
* grants (including a root `*` company-wide grant) do not apply.
|
|
152
152
|
*/
|
|
153
153
|
lockedBy?: AclLock;
|
|
154
|
+
/**
|
|
155
|
+
* Set with outcome "no-write-access": the ACL row that blocks writes to a
|
|
156
|
+
* path that is on disk but not in the vault, so a push cannot upload it.
|
|
157
|
+
* Anchored as companies/<slug>/<prefix>; absent when only the effective
|
|
158
|
+
* permission is known.
|
|
159
|
+
*/
|
|
160
|
+
writeBlockedBy?: string;
|
|
161
|
+
/** Effective permission on the path when outcome is "no-write-access". */
|
|
162
|
+
permission?: string | null;
|
|
154
163
|
}
|
|
155
164
|
export interface AccessAsResult {
|
|
156
165
|
personUid: string;
|
|
@@ -164,6 +173,28 @@ export interface AccessAsResult {
|
|
|
164
173
|
export declare function outcomeExitCode(outcome: AccessOutcome): 0 | 2 | 3 | 4;
|
|
165
174
|
export declare function formatAccessOutcome(result: RunAccessResult): string;
|
|
166
175
|
export declare function resolveGrantor(tree: AccessAclTree | null, members: AccessMember[]): AccessGrantor | null;
|
|
176
|
+
/**
|
|
177
|
+
* ACL evidence for one key. `tree` is the full acl/tree response (which keeps
|
|
178
|
+
* the deny / no-record distinction and the ACL creator for grantor lookup).
|
|
179
|
+
* `resolved` is a non-null permission from the batch acl/resolve route.
|
|
180
|
+
*/
|
|
181
|
+
export type AclVerdict = {
|
|
182
|
+
kind: "tree";
|
|
183
|
+
tree: AccessAclTree | null;
|
|
184
|
+
} | {
|
|
185
|
+
kind: "resolved";
|
|
186
|
+
permission: string;
|
|
187
|
+
};
|
|
188
|
+
/**
|
|
189
|
+
* Why the caller cannot write `relative`, or null when it can or the ACL says
|
|
190
|
+
* nothing (no record: membership-distributed access decides, which this
|
|
191
|
+
* command cannot see). The tree is fetched when the fast resolve path gave
|
|
192
|
+
* only a permission, so the blocking row can be named.
|
|
193
|
+
*/
|
|
194
|
+
export declare function writeBlocker(verdict: AclVerdict, relative: string, deps: Pick<AccessDeps, "fetchAclTree" | "companySlug">): Promise<{
|
|
195
|
+
permission: string | null;
|
|
196
|
+
blockedBy?: string;
|
|
197
|
+
} | null>;
|
|
167
198
|
export declare function runAccess(input: RunAccessInput): Promise<RunAccessResult>;
|
|
168
199
|
export interface RunAccessBatchInput {
|
|
169
200
|
targets: string[];
|
package/dist/commands/access.js
CHANGED
|
@@ -26,6 +26,7 @@ import { listActiveMembers } from "./members.js";
|
|
|
26
26
|
import { aclLockedBy } from "./acl-lock.js";
|
|
27
27
|
import { buildDmBody } from "./dm.js";
|
|
28
28
|
import { defaultAudienceFor, recipientKindOf } from "../lib/notify-recipient.js";
|
|
29
|
+
import { callerIsMachinePrincipal } from "../lib/caller-principal.js";
|
|
29
30
|
import { peekIdToken } from "../utils/id-token.js";
|
|
30
31
|
import { findRecentAccessRequest, formatTimeAgo, recordAccessRequest, } from "../utils/access-requests.js";
|
|
31
32
|
import { recordAccessOutcome } from "../utils/access-outcomes.js";
|
|
@@ -34,8 +35,11 @@ export function outcomeExitCode(outcome) {
|
|
|
34
35
|
return 0;
|
|
35
36
|
if (outcome === "never-existed")
|
|
36
37
|
return 2;
|
|
37
|
-
if (outcome === "no-access" ||
|
|
38
|
+
if (outcome === "no-access" ||
|
|
39
|
+
outcome === "no-write-access" ||
|
|
40
|
+
outcome === "pending-confirmation") {
|
|
38
41
|
return 3;
|
|
42
|
+
}
|
|
39
43
|
return 4;
|
|
40
44
|
}
|
|
41
45
|
export function formatAccessOutcome(result) {
|
|
@@ -57,6 +61,16 @@ export function formatAccessOutcome(result) {
|
|
|
57
61
|
lines.push(`You do not have read access to this path.`);
|
|
58
62
|
lines.push(result.path);
|
|
59
63
|
break;
|
|
64
|
+
case "no-write-access":
|
|
65
|
+
lines.push(`The file is on this computer but not in the ${result.company} vault, and you cannot write to it, so a push cannot upload it.`);
|
|
66
|
+
lines.push(result.path);
|
|
67
|
+
if (result.writeBlockedBy) {
|
|
68
|
+
lines.push(`Write is blocked by the ACL on ${result.writeBlockedBy} (your permission: ${result.permission ?? "none"}). Ask its creator or a company admin for write access.`);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
lines.push(`Your permission on this path is ${result.permission ?? "none"}. Ask a company admin for write access.`);
|
|
72
|
+
}
|
|
73
|
+
break;
|
|
60
74
|
case "pending-confirmation":
|
|
61
75
|
lines.push(`Ask the grantor for read access to this path.`);
|
|
62
76
|
lines.push(result.path);
|
|
@@ -243,6 +257,69 @@ function startEarly(promise) {
|
|
|
243
257
|
promise.catch(() => undefined);
|
|
244
258
|
return promise;
|
|
245
259
|
}
|
|
260
|
+
const WRITE_PERMISSIONS = new Set(["write", "admin", "owner"]);
|
|
261
|
+
/**
|
|
262
|
+
* Why the caller cannot write `relative`, or null when it can or the ACL says
|
|
263
|
+
* nothing (no record: membership-distributed access decides, which this
|
|
264
|
+
* command cannot see). The tree is fetched when the fast resolve path gave
|
|
265
|
+
* only a permission, so the blocking row can be named.
|
|
266
|
+
*/
|
|
267
|
+
export async function writeBlocker(verdict, relative, deps) {
|
|
268
|
+
const resolvedPermission = verdict.kind === "resolved" ? verdict.permission : undefined;
|
|
269
|
+
if (resolvedPermission && WRITE_PERMISSIONS.has(resolvedPermission))
|
|
270
|
+
return null;
|
|
271
|
+
let tree = verdict.kind === "tree" ? verdict.tree : null;
|
|
272
|
+
if (verdict.kind === "resolved") {
|
|
273
|
+
try {
|
|
274
|
+
tree = await deps.fetchAclTree(relative);
|
|
275
|
+
}
|
|
276
|
+
catch {
|
|
277
|
+
tree = null;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
const permission = resolvedPermission ?? tree?.effectivePermission ?? null;
|
|
281
|
+
if (permission && WRITE_PERMISSIONS.has(permission))
|
|
282
|
+
return null;
|
|
283
|
+
const covering = tree?.coveringAclPath;
|
|
284
|
+
if (typeof covering === "string" && covering !== "") {
|
|
285
|
+
return {
|
|
286
|
+
permission,
|
|
287
|
+
blockedBy: toBucketRelative(covering, deps.companySlug),
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
// A row on the path itself with a known non-write permission blocks it.
|
|
291
|
+
// With no permission reported, nothing proves the path is blocked.
|
|
292
|
+
if (permission && tree?.directRow) {
|
|
293
|
+
return { permission, blockedBy: toBucketRelative(tree.prefix, deps.companySlug) };
|
|
294
|
+
}
|
|
295
|
+
// No ACL row covers the path. A known non-write permission still blocks.
|
|
296
|
+
if (resolvedPermission)
|
|
297
|
+
return { permission };
|
|
298
|
+
return null;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Owners and admins write past ACL rows on the server (role bypass), which
|
|
302
|
+
* the ACL tree does not always show. Treat a lookup failure as no bypass only
|
|
303
|
+
* when the member list loads; if it cannot be read, assume a bypass so the
|
|
304
|
+
* command keeps its old "never-existed" answer instead of a wrong blocker.
|
|
305
|
+
*/
|
|
306
|
+
async function callerHasRoleBypass(deps) {
|
|
307
|
+
try {
|
|
308
|
+
const [members, requester] = await Promise.all([
|
|
309
|
+
deps.listMembers(),
|
|
310
|
+
resolveRequester(deps.requester),
|
|
311
|
+
]);
|
|
312
|
+
const email = (requester.email ?? "").trim().toLowerCase();
|
|
313
|
+
// An unknown caller cannot be matched; keep the old answer.
|
|
314
|
+
if (email === "")
|
|
315
|
+
return true;
|
|
316
|
+
return members.some((m) => (m.personEmail ?? "").trim().toLowerCase() === email &&
|
|
317
|
+
(m.role === "owner" || m.role === "admin"));
|
|
318
|
+
}
|
|
319
|
+
catch {
|
|
320
|
+
return true;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
246
323
|
function verdictDenied(verdict) {
|
|
247
324
|
return verdict.kind === "tree" ? aclDenied(verdict.tree) : false;
|
|
248
325
|
}
|
|
@@ -388,6 +465,31 @@ async function locateTarget(target, deps, ctx) {
|
|
|
388
465
|
},
|
|
389
466
|
};
|
|
390
467
|
}
|
|
468
|
+
// feedback_5baccb9e: a file that is on disk but absent from the vault
|
|
469
|
+
// is usually one a push could not upload. When the ACL blocks writes,
|
|
470
|
+
// say so instead of "never existed".
|
|
471
|
+
if (relative !== "" &&
|
|
472
|
+
fs.existsSync(path.join(deps.hqRoot, "companies", slug, relative))) {
|
|
473
|
+
steps.push("disk: present");
|
|
474
|
+
const blocker = await writeBlocker(verdict, relative, deps);
|
|
475
|
+
if (blocker && !(await callerHasRoleBypass(deps))) {
|
|
476
|
+
steps.push(blocker.blockedBy
|
|
477
|
+
? `acl: write blocked by ${anchored(blocker.blockedBy)} (${blocker.permission ?? "none"})`
|
|
478
|
+
: `acl: no write (${blocker.permission ?? "none"})`);
|
|
479
|
+
return {
|
|
480
|
+
kind: "terminal",
|
|
481
|
+
outcome: "no-write-access",
|
|
482
|
+
fields: {
|
|
483
|
+
path: anchored(relative),
|
|
484
|
+
company: slug,
|
|
485
|
+
exists: false,
|
|
486
|
+
steps,
|
|
487
|
+
permission: blocker.permission,
|
|
488
|
+
...(blocker.blockedBy ? { writeBlockedBy: anchored(blocker.blockedBy) } : {}),
|
|
489
|
+
},
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
}
|
|
391
493
|
return {
|
|
392
494
|
kind: "terminal",
|
|
393
495
|
outcome: "never-existed",
|
|
@@ -857,6 +959,11 @@ function jsonPayload(result) {
|
|
|
857
959
|
payload.alreadyAskedAt = result.alreadyAskedAt;
|
|
858
960
|
if (result.lockedBy)
|
|
859
961
|
payload.lockedBy = result.lockedBy;
|
|
962
|
+
if (result.outcome === "no-write-access") {
|
|
963
|
+
payload.permission = result.permission ?? null;
|
|
964
|
+
if (result.writeBlockedBy)
|
|
965
|
+
payload.writeBlockedBy = result.writeBlockedBy;
|
|
966
|
+
}
|
|
860
967
|
return payload;
|
|
861
968
|
}
|
|
862
969
|
function emit(input, result, log) {
|
|
@@ -933,7 +1040,9 @@ export function registerAccessCommand(program) {
|
|
|
933
1040
|
Exit codes:
|
|
934
1041
|
0 local or not-synced (file exists and you can read it)
|
|
935
1042
|
2 never-existed (the path was never created)
|
|
936
|
-
3 no-access (the file exists but you cannot read it)
|
|
1043
|
+
3 no-access (the file exists but you cannot read it), or
|
|
1044
|
+
no-write-access (the file is on disk, not in the vault, and you cannot
|
|
1045
|
+
write to it, so a push cannot upload it)
|
|
937
1046
|
4 ambiguous (several keys matched; pick one)
|
|
938
1047
|
|
|
939
1048
|
With several paths, each gets its own result block and the exit code is the
|
|
@@ -1161,7 +1270,7 @@ async function buildLiveAccessDeps(slug, hqRoot) {
|
|
|
1161
1270
|
prompt: msg.prompt,
|
|
1162
1271
|
details: msg.details,
|
|
1163
1272
|
now: Date.now(),
|
|
1164
|
-
audience: defaultAudienceFor(recipientKindOf(msg.recipient)),
|
|
1273
|
+
audience: defaultAudienceFor(recipientKindOf(msg.recipient), callerIsMachinePrincipal()),
|
|
1165
1274
|
});
|
|
1166
1275
|
const res = await vaultApiFetch({
|
|
1167
1276
|
token,
|
|
@@ -75,7 +75,7 @@ export interface KitRuntime {
|
|
|
75
75
|
paths: AgentKitPaths;
|
|
76
76
|
creds: ExternalMachineCreds;
|
|
77
77
|
config: KitConfig;
|
|
78
|
-
getToken: () => Promise<string>;
|
|
78
|
+
getToken: (signal?: AbortSignal) => Promise<string>;
|
|
79
79
|
log: KitLogger;
|
|
80
80
|
credsSource?: HeartbeatCredsSource;
|
|
81
81
|
}
|