@indigoai-us/hq-cli 5.345.169 → 5.345.171
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 +69 -0
- package/assets/scaffold/core/scripts/hq-delegate-send.sh +1 -1
- package/dist/command-catalog.generated.d.ts +181 -9
- package/dist/command-catalog.generated.js +224 -10
- package/dist/commands/access.d.ts +32 -1
- package/dist/commands/access.js +119 -5
- 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 +141 -14
- package/dist/commands/cloud.d.ts +78 -1
- package/dist/commands/cloud.js +274 -9
- 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/dm.d.ts +17 -3
- package/dist/commands/dm.js +121 -26
- package/dist/commands/feedback-triage.d.ts +43 -1
- package/dist/commands/feedback-triage.js +123 -23
- package/dist/commands/feedback.d.ts +40 -1
- package/dist/commands/feedback.js +184 -4
- package/dist/commands/files.d.ts +42 -0
- package/dist/commands/files.js +223 -30
- 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/mesh.js +6 -0
- 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-manifest.d.ts +16 -0
- package/dist/commands/sync-manifest.js +17 -1
- package/dist/hq-cloud-sync-runner/bin/sync-runner.js +2367 -2109
- 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/decisions.d.ts +62 -0
- package/dist/lib/bot/decisions.js +228 -0
- package/dist/lib/bot/fleet-local.d.ts +127 -0
- package/dist/lib/bot/fleet-local.js +638 -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/run.d.ts +7 -0
- package/dist/lib/bot/run.js +104 -1
- 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 +4 -0
- package/dist/lib/daemon/catalog.js +63 -29
- package/dist/lib/daemon/config.d.ts +7 -0
- package/dist/lib/daemon/config.js +32 -0
- package/dist/lib/daemon/run.d.ts +3 -2
- package/dist/lib/daemon/run.js +23 -3
- package/dist/lib/daemon/supervisor.d.ts +1 -0
- package/dist/lib/daemon/supervisor.js +4 -0
- package/dist/lib/daemon/sync-core-canary.d.ts +12 -0
- package/dist/lib/daemon/sync-core-canary.js +61 -0
- 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/checks/sync-health.d.ts +32 -0
- package/dist/lib/doctor/checks/sync-health.js +54 -1
- package/dist/lib/doctor/fix/apply.d.ts +26 -4
- package/dist/lib/doctor/fix/apply.js +149 -11
- package/dist/lib/doctor/fix/remediation.d.ts +8 -1
- package/dist/lib/doctor/fix/remediation.js +22 -0
- package/dist/lib/doctor/types.d.ts +1 -1
- package/dist/lib/doctor/types.js +1 -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/mesh/live/daemon/work-subscribe.js +31 -0
- 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/work-context/organize.d.ts +7 -0
- package/dist/lib/work-context/organize.js +21 -1
- 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/sentry-before-send.js +1 -0
- 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/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
|
@@ -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": []
|
|
@@ -1399,6 +1409,11 @@ export const COMMAND_CATALOG = [
|
|
|
1399
1409
|
"description": "Build and print the chunks as JSON; upload nothing",
|
|
1400
1410
|
"hidden": false
|
|
1401
1411
|
},
|
|
1412
|
+
{
|
|
1413
|
+
"flags": "--json",
|
|
1414
|
+
"description": "Print the pass outcome as one JSON line instead of a summary",
|
|
1415
|
+
"hidden": false
|
|
1416
|
+
},
|
|
1402
1417
|
{
|
|
1403
1418
|
"flags": "--respect-throttle",
|
|
1404
1419
|
"description": "Honour the 24h per-scope upload throttle instead of forcing a pass (for scheduled callers)",
|
|
@@ -2745,6 +2760,16 @@ export const COMMAND_CATALOG = [
|
|
|
2745
2760
|
"description": "Token expiry duration (e.g. 24h, 2d, 30m)",
|
|
2746
2761
|
"hidden": false,
|
|
2747
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
|
|
2748
2773
|
}
|
|
2749
2774
|
],
|
|
2750
2775
|
"subcommands": []
|
|
@@ -3693,6 +3718,11 @@ export const COMMAND_CATALOG = [
|
|
|
3693
3718
|
"description": "Permission level (only with --with): read | write",
|
|
3694
3719
|
"hidden": false
|
|
3695
3720
|
},
|
|
3721
|
+
{
|
|
3722
|
+
"flags": "--exact",
|
|
3723
|
+
"description": "With --with: grant exactly the object named by <prefix>, even when it looks like a folder (by default a bare folder name such as 'knowledge' is granted as the folder glob 'knowledge/*').",
|
|
3724
|
+
"hidden": false
|
|
3725
|
+
},
|
|
3696
3726
|
{
|
|
3697
3727
|
"flags": "--full",
|
|
3698
3728
|
"description": "Grant access to the ENTIRE vault (the '*' wildcard prefix) — no need to quote a glob. Requires --with; defaults to write permission.",
|
|
@@ -3724,7 +3754,7 @@ export const COMMAND_CATALOG = [
|
|
|
3724
3754
|
},
|
|
3725
3755
|
{
|
|
3726
3756
|
"name": "unshare",
|
|
3727
|
-
"description": "Remove a named file access grant, or remove an empty ACL row or grantee-less entries without --with.",
|
|
3757
|
+
"description": "Remove a named file access grant, or remove an empty ACL row or grantee-less entries without --with. With --with, a bare name such as 'knowledge' first removes the exact 'knowledge' grant (rows from older `hq files share` versions) and, when none matches, the folder-glob 'knowledge/*' grant. Without --with, the prefix is used exactly as typed: pass 'knowledge/*' (quoted) to clean up the folder-glob row.",
|
|
3728
3758
|
"aliases": [],
|
|
3729
3759
|
"hidden": false,
|
|
3730
3760
|
"helpOption": true,
|
|
@@ -3744,6 +3774,11 @@ export const COMMAND_CATALOG = [
|
|
|
3744
3774
|
"flags": "--with <principal>",
|
|
3745
3775
|
"description": "Person uid, agent uid, company Outpost id (out_...), email address, group id, or '@all' to remove the grant",
|
|
3746
3776
|
"hidden": false
|
|
3777
|
+
},
|
|
3778
|
+
{
|
|
3779
|
+
"flags": "--exact",
|
|
3780
|
+
"description": "With --with: remove the grant on exactly the object named by <prefix>. By default a bare folder name such as 'knowledge' resolves to the folder glob 'knowledge/*', the same way `hq files share` resolves it.",
|
|
3781
|
+
"hidden": false
|
|
3747
3782
|
}
|
|
3748
3783
|
],
|
|
3749
3784
|
"subcommands": []
|
|
@@ -4080,7 +4115,7 @@ export const COMMAND_CATALOG = [
|
|
|
4080
4115
|
"helpText": [
|
|
4081
4116
|
{
|
|
4082
4117
|
"position": "after",
|
|
4083
|
-
"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"
|
|
4084
4119
|
}
|
|
4085
4120
|
],
|
|
4086
4121
|
"arguments": [
|
|
@@ -4827,7 +4862,7 @@ export const COMMAND_CATALOG = [
|
|
|
4827
4862
|
},
|
|
4828
4863
|
{
|
|
4829
4864
|
"name": "dm",
|
|
4830
|
-
"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.",
|
|
4831
4866
|
"aliases": [],
|
|
4832
4867
|
"hidden": false,
|
|
4833
4868
|
"helpOption": true,
|
|
@@ -4908,7 +4943,7 @@ export const COMMAND_CATALOG = [
|
|
|
4908
4943
|
},
|
|
4909
4944
|
{
|
|
4910
4945
|
"flags": "--audience <human|agent|both>",
|
|
4911
|
-
"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.",
|
|
4912
4947
|
"hidden": false
|
|
4913
4948
|
},
|
|
4914
4949
|
{
|
|
@@ -5529,13 +5564,23 @@ export const COMMAND_CATALOG = [
|
|
|
5529
5564
|
"options": [
|
|
5530
5565
|
{
|
|
5531
5566
|
"flags": "--state <state>",
|
|
5532
|
-
"description": "One of: triaged, in-progress, shipped, verified, resolved",
|
|
5567
|
+
"description": "One of: triaged, in-progress, stalled, shipped, verified, resolved",
|
|
5533
5568
|
"hidden": false
|
|
5534
5569
|
},
|
|
5535
5570
|
{
|
|
5536
5571
|
"flags": "--note <text>",
|
|
5537
5572
|
"description": "What the customer should read (plain text, up to 2000 characters)",
|
|
5538
5573
|
"hidden": false
|
|
5574
|
+
},
|
|
5575
|
+
{
|
|
5576
|
+
"flags": "--pr <url>",
|
|
5577
|
+
"description": "Open pull request for this ticket (required with --state in-progress unless --lane is given)",
|
|
5578
|
+
"hidden": false
|
|
5579
|
+
},
|
|
5580
|
+
{
|
|
5581
|
+
"flags": "--lane <id>",
|
|
5582
|
+
"description": "Live lane working this ticket (required with --state in-progress unless --pr is given)",
|
|
5583
|
+
"hidden": false
|
|
5539
5584
|
}
|
|
5540
5585
|
],
|
|
5541
5586
|
"subcommands": []
|
|
@@ -5613,6 +5658,32 @@ export const COMMAND_CATALOG = [
|
|
|
5613
5658
|
],
|
|
5614
5659
|
"subcommands": []
|
|
5615
5660
|
},
|
|
5661
|
+
{
|
|
5662
|
+
"name": "claim",
|
|
5663
|
+
"description": "Assign a ticket to yourself (sets the assignee only, never the status)",
|
|
5664
|
+
"aliases": [],
|
|
5665
|
+
"hidden": false,
|
|
5666
|
+
"helpOption": true,
|
|
5667
|
+
"helpCommand": false,
|
|
5668
|
+
"usage": "[options] <id>",
|
|
5669
|
+
"helpText": [],
|
|
5670
|
+
"arguments": [
|
|
5671
|
+
{
|
|
5672
|
+
"name": "id",
|
|
5673
|
+
"required": true,
|
|
5674
|
+
"variadic": false,
|
|
5675
|
+
"description": "Feedback id (feedback_<uuid>)"
|
|
5676
|
+
}
|
|
5677
|
+
],
|
|
5678
|
+
"options": [
|
|
5679
|
+
{
|
|
5680
|
+
"flags": "--json",
|
|
5681
|
+
"description": "Print { id, assignee } as JSON",
|
|
5682
|
+
"hidden": false
|
|
5683
|
+
}
|
|
5684
|
+
],
|
|
5685
|
+
"subcommands": []
|
|
5686
|
+
},
|
|
5616
5687
|
{
|
|
5617
5688
|
"name": "list",
|
|
5618
5689
|
"description": "List feedback: untriaged (default), yours, or one person's",
|
|
@@ -5629,6 +5700,11 @@ export const COMMAND_CATALOG = [
|
|
|
5629
5700
|
"description": "Items nobody has triaged yet (the default)",
|
|
5630
5701
|
"hidden": false
|
|
5631
5702
|
},
|
|
5703
|
+
{
|
|
5704
|
+
"flags": "--open",
|
|
5705
|
+
"description": "Every item not resolved, won't-fix or accepted, triaged or not",
|
|
5706
|
+
"hidden": false
|
|
5707
|
+
},
|
|
5632
5708
|
{
|
|
5633
5709
|
"flags": "--mine",
|
|
5634
5710
|
"description": "Items assigned to you",
|
|
@@ -5641,7 +5717,7 @@ export const COMMAND_CATALOG = [
|
|
|
5641
5717
|
},
|
|
5642
5718
|
{
|
|
5643
5719
|
"flags": "--status <status>",
|
|
5644
|
-
"description": "Only items with this status",
|
|
5720
|
+
"description": "Only items with this status (new, triaging, accepted, wont_fix, in_progress, resolved, waiting_on_customer, reopened, stalled, needs_info). Without --untriaged, --mine or --assignee it lists every item in that status",
|
|
5645
5721
|
"hidden": false
|
|
5646
5722
|
},
|
|
5647
5723
|
{
|
|
@@ -5656,7 +5732,7 @@ export const COMMAND_CATALOG = [
|
|
|
5656
5732
|
},
|
|
5657
5733
|
{
|
|
5658
5734
|
"flags": "--json",
|
|
5659
|
-
"description": "Print { items, count } as JSON",
|
|
5735
|
+
"description": "Print { items, count } as JSON, plus truncated: true when more items match",
|
|
5660
5736
|
"hidden": false
|
|
5661
5737
|
}
|
|
5662
5738
|
],
|
|
@@ -6422,6 +6498,11 @@ export const COMMAND_CATALOG = [
|
|
|
6422
6498
|
"description": "Company slug, e.g. indigo",
|
|
6423
6499
|
"hidden": false
|
|
6424
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
|
+
},
|
|
6425
6506
|
{
|
|
6426
6507
|
"flags": "--describe <tool>",
|
|
6427
6508
|
"description": "Print the full input schema for one tool",
|
|
@@ -6463,6 +6544,11 @@ export const COMMAND_CATALOG = [
|
|
|
6463
6544
|
"description": "Connection id (acct_…)",
|
|
6464
6545
|
"hidden": false
|
|
6465
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
|
+
},
|
|
6466
6552
|
{
|
|
6467
6553
|
"flags": "--company <slug>",
|
|
6468
6554
|
"description": "Company slug, e.g. indigo",
|
|
@@ -6784,6 +6870,16 @@ export const COMMAND_CATALOG = [
|
|
|
6784
6870
|
"description": "Connect again even if this app is already connected",
|
|
6785
6871
|
"hidden": false
|
|
6786
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
|
+
},
|
|
6787
6883
|
{
|
|
6788
6884
|
"flags": "--json",
|
|
6789
6885
|
"description": "Machine-readable output",
|
|
@@ -6870,6 +6966,16 @@ export const COMMAND_CATALOG = [
|
|
|
6870
6966
|
"description": "For a revoked row, run `connect <domain>` to re-add and revive it",
|
|
6871
6967
|
"hidden": false
|
|
6872
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
|
+
},
|
|
6873
6979
|
{
|
|
6874
6980
|
"flags": "--json",
|
|
6875
6981
|
"description": "Machine-readable output",
|
|
@@ -7642,7 +7748,7 @@ export const COMMAND_CATALOG = [
|
|
|
7642
7748
|
},
|
|
7643
7749
|
{
|
|
7644
7750
|
"flags": "--repo <dir>",
|
|
7645
|
-
"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)",
|
|
7646
7752
|
"hidden": false
|
|
7647
7753
|
},
|
|
7648
7754
|
{
|
|
@@ -7654,6 +7760,11 @@ export const COMMAND_CATALOG = [
|
|
|
7654
7760
|
"flags": "--allowlist-rev <rev>",
|
|
7655
7761
|
"description": "With --repo: read .gitleaks.toml from this commit instead of HEAD",
|
|
7656
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
|
|
7657
7768
|
}
|
|
7658
7769
|
],
|
|
7659
7770
|
"subcommands": []
|
|
@@ -10314,6 +10425,49 @@ export const COMMAND_CATALOG = [
|
|
|
10314
10425
|
],
|
|
10315
10426
|
"subcommands": []
|
|
10316
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
|
+
},
|
|
10317
10471
|
{
|
|
10318
10472
|
"name": "terminal",
|
|
10319
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.",
|
|
@@ -22540,8 +22694,12 @@ export const COMMAND_CATALOG = [
|
|
|
22540
22694
|
{
|
|
22541
22695
|
"flags": "--runtime <runtime>",
|
|
22542
22696
|
"description": "Model CLI to run the bot with: claude|codex|grok",
|
|
22543
|
-
"hidden": false
|
|
22544
|
-
|
|
22697
|
+
"hidden": false
|
|
22698
|
+
},
|
|
22699
|
+
{
|
|
22700
|
+
"flags": "--hq-fleet-runtime",
|
|
22701
|
+
"description": "Create this personal bot with the local HQ Fleet Runtime",
|
|
22702
|
+
"hidden": false
|
|
22545
22703
|
},
|
|
22546
22704
|
{
|
|
22547
22705
|
"flags": "--model <model>",
|
|
@@ -22877,6 +23035,62 @@ export const COMMAND_CATALOG = [
|
|
|
22877
23035
|
],
|
|
22878
23036
|
"subcommands": []
|
|
22879
23037
|
},
|
|
23038
|
+
{
|
|
23039
|
+
"name": "auth",
|
|
23040
|
+
"description": "Sign a runtime-backed personal bot in to ChatGPT, Grok, Claude, or another supported provider",
|
|
23041
|
+
"aliases": [],
|
|
23042
|
+
"hidden": false,
|
|
23043
|
+
"helpOption": true,
|
|
23044
|
+
"helpCommand": false,
|
|
23045
|
+
"usage": "[options] <name>",
|
|
23046
|
+
"helpText": [],
|
|
23047
|
+
"arguments": [
|
|
23048
|
+
{
|
|
23049
|
+
"name": "name",
|
|
23050
|
+
"required": true,
|
|
23051
|
+
"variadic": false,
|
|
23052
|
+
"description": ""
|
|
23053
|
+
}
|
|
23054
|
+
],
|
|
23055
|
+
"options": [
|
|
23056
|
+
{
|
|
23057
|
+
"flags": "--provider <provider>",
|
|
23058
|
+
"description": "Provider: chatgpt, grok, claude, or a runtime provider id",
|
|
23059
|
+
"hidden": false
|
|
23060
|
+
},
|
|
23061
|
+
{
|
|
23062
|
+
"flags": "--model <model>",
|
|
23063
|
+
"description": "Model id; required for providers without a built-in personal-bot default",
|
|
23064
|
+
"hidden": false
|
|
23065
|
+
},
|
|
23066
|
+
{
|
|
23067
|
+
"flags": "--api-key",
|
|
23068
|
+
"description": "Read an API key from stdin instead of starting device authorization",
|
|
23069
|
+
"hidden": false
|
|
23070
|
+
},
|
|
23071
|
+
{
|
|
23072
|
+
"flags": "--base-url <url>",
|
|
23073
|
+
"description": "Provider API base URL; required for custom runtime providers",
|
|
23074
|
+
"hidden": false
|
|
23075
|
+
},
|
|
23076
|
+
{
|
|
23077
|
+
"flags": "--transport <transport>",
|
|
23078
|
+
"description": "Provider transport: chat_completions, anthropic_messages, or codex_responses",
|
|
23079
|
+
"hidden": false
|
|
23080
|
+
},
|
|
23081
|
+
{
|
|
23082
|
+
"flags": "--no-browser",
|
|
23083
|
+
"description": "Do not open a browser during device authorization",
|
|
23084
|
+
"hidden": false
|
|
23085
|
+
},
|
|
23086
|
+
{
|
|
23087
|
+
"flags": "--json",
|
|
23088
|
+
"description": "Print machine-readable JSON",
|
|
23089
|
+
"hidden": false
|
|
23090
|
+
}
|
|
23091
|
+
],
|
|
23092
|
+
"subcommands": []
|
|
23093
|
+
},
|
|
22880
23094
|
{
|
|
22881
23095
|
"name": "logs",
|
|
22882
23096
|
"description": "Show the bot's log",
|
|
@@ -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",
|
|
@@ -611,7 +713,12 @@ async function completeTarget(input, deps, located) {
|
|
|
611
713
|
}
|
|
612
714
|
else {
|
|
613
715
|
grantor = resolved;
|
|
614
|
-
const
|
|
716
|
+
const contactRole = resolved.source === "acl-creator"
|
|
717
|
+
? "ACL creator"
|
|
718
|
+
: resolved.source === "owner"
|
|
719
|
+
? "company owner fallback"
|
|
720
|
+
: "company admin fallback";
|
|
721
|
+
const grantorLine = `Access contact: ${grantorLabel(resolved)} (${contactRole}; file authorship not verified)`;
|
|
615
722
|
// The recipient is always shown BEFORE any send. Under --json stdout is
|
|
616
723
|
// reserved for the single JSON object, so the line goes to stderr.
|
|
617
724
|
if (json)
|
|
@@ -659,7 +766,7 @@ async function completeTarget(input, deps, located) {
|
|
|
659
766
|
}
|
|
660
767
|
if (approved && outcome === "no-access") {
|
|
661
768
|
const message = `${requester.email} is asking for read access to ${resolvedKey} in ${slug}.`;
|
|
662
|
-
const prompt = `hq files share ${resolvedKey} --with ${requester.email} --permission read --company ${slug}`;
|
|
769
|
+
const prompt = `hq files share ${resolvedKey} --exact --with ${requester.email} --permission read --company ${slug}`;
|
|
663
770
|
const sent = await deps.dm.send({
|
|
664
771
|
recipient: resolved.email,
|
|
665
772
|
message,
|
|
@@ -852,6 +959,11 @@ function jsonPayload(result) {
|
|
|
852
959
|
payload.alreadyAskedAt = result.alreadyAskedAt;
|
|
853
960
|
if (result.lockedBy)
|
|
854
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
|
+
}
|
|
855
967
|
return payload;
|
|
856
968
|
}
|
|
857
969
|
function emit(input, result, log) {
|
|
@@ -928,7 +1040,9 @@ export function registerAccessCommand(program) {
|
|
|
928
1040
|
Exit codes:
|
|
929
1041
|
0 local or not-synced (file exists and you can read it)
|
|
930
1042
|
2 never-existed (the path was never created)
|
|
931
|
-
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)
|
|
932
1046
|
4 ambiguous (several keys matched; pick one)
|
|
933
1047
|
|
|
934
1048
|
With several paths, each gets its own result block and the exit code is the
|
|
@@ -1156,7 +1270,7 @@ async function buildLiveAccessDeps(slug, hqRoot) {
|
|
|
1156
1270
|
prompt: msg.prompt,
|
|
1157
1271
|
details: msg.details,
|
|
1158
1272
|
now: Date.now(),
|
|
1159
|
-
audience: defaultAudienceFor(recipientKindOf(msg.recipient)),
|
|
1273
|
+
audience: defaultAudienceFor(recipientKindOf(msg.recipient), callerIsMachinePrincipal()),
|
|
1160
1274
|
});
|
|
1161
1275
|
const res = await vaultApiFetch({
|
|
1162
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
|
}
|