@entrydesk/cli 2.1.0-beta.4 → 2.2.0-beta

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 (97) hide show
  1. package/README.md +113 -30
  2. package/dist/add-A1EZKhMH.js +10 -0
  3. package/dist/agents-CZzVru0_.js +10 -0
  4. package/dist/billing-DHV0Wfwm.js +10 -0
  5. package/dist/budget-Dvl1Q6_g.js +10 -0
  6. package/dist/build-task-request-config-B_mlDg_c.js +10 -0
  7. package/dist/{commands-DRUlUd-I.js → commands-ghS7KAQr.js} +1 -1
  8. package/dist/commands-qNH4DlB_.js +10 -0
  9. package/dist/config-B3pbK-VP.js +11 -0
  10. package/dist/connectors-Dqa8qg7s.js +11 -0
  11. package/dist/file-upload-CgLvxPGL.js +24 -0
  12. package/dist/format-BaXJBAlk.js +10 -0
  13. package/dist/index.js +40 -25
  14. package/dist/{instruction-DYgn39xF.js → instruction-DaoJgFgE.js} +1 -1
  15. package/dist/login-CVUzJp76.js +10 -0
  16. package/dist/{logout-DnFBlXMZ.js → logout-B6Bb4w2Y.js} +1 -1
  17. package/dist/marketplace-C-7CArF7.js +12 -0
  18. package/dist/mcp-BnFLUTG-.js +11 -0
  19. package/dist/mcp-client-CPFC6TCy.js +10 -0
  20. package/dist/meeting-B5-UQSO3.js +11 -0
  21. package/dist/message-utils-DRHsMlj2.js +15 -0
  22. package/dist/models-pzt8nNX7.js +11 -0
  23. package/dist/notifications-Bo7oPqK5.js +10 -0
  24. package/dist/{paginate-Brd-j5V8.js → paginate-DetNe5nU.js} +1 -1
  25. package/dist/{paths-mBL9tt9p.js → paths-CLGwOhp4.js} +1 -1
  26. package/dist/profile-Cth2_rzi.js +10 -0
  27. package/dist/profile-storage-BVSyHoBn.js +68 -0
  28. package/dist/project-CPKxduou.js +10 -0
  29. package/dist/project-context-D8YawkvR.js +10 -0
  30. package/dist/project-governance-EFbI_Qan.js +10 -0
  31. package/dist/{project-sources-D17oXXhL.js → project-sources-CFgB4loh.js} +1 -1
  32. package/dist/project-sources-write-DUx1voCZ.js +10 -0
  33. package/dist/project-tasks-Bk8-wOyn.js +10 -0
  34. package/dist/{push-CJZLFEdk.js → push-4Y4mjxO7.js} +1 -1
  35. package/dist/recordings-DtgXMjp2.js +11 -0
  36. package/dist/remove-DUFnCuRT.js +10 -0
  37. package/dist/resolve-yAqzT64X.js +14 -0
  38. package/dist/{resource-grants-zAoqe73P.js → resource-grants-DMj0dy5m.js} +1 -1
  39. package/dist/schedules-6T2-994t.js +29 -0
  40. package/dist/skills-C56S2Z62.js +10 -0
  41. package/dist/status-BBvz4l0p.js +10 -0
  42. package/dist/status-DHllWQ7c.js +10 -0
  43. package/dist/task-Hcgf0oDf.js +110 -0
  44. package/dist/{tasks-dv0gJ38_.js → tasks-CLlI3fiV.js} +1 -1
  45. package/dist/tasks-D2CtxbpJ.js +22 -0
  46. package/dist/team-aQszguLF.js +11 -0
  47. package/dist/terminal-text-cBPBiP3x.js +10 -0
  48. package/dist/tool-CASBzR_z.js +17 -0
  49. package/dist/update-CSh9DfHK.js +10 -0
  50. package/dist/usage-BLPq7c6l.js +11 -0
  51. package/dist/usage-audit-BYvZgTJp.js +12 -0
  52. package/dist/{version-Dgsb7T5N.js → version-jPJWKUcc.js} +1 -1
  53. package/dist/webhook-BxPA95wd.js +11 -0
  54. package/dist/workflow-DJkPvmuA.js +14 -0
  55. package/dist/workspaces-CDotU443.js +11 -0
  56. package/package.json +8 -7
  57. package/dist/add-4VqDcbIj.js +0 -10
  58. package/dist/agents-CCOqroYN.js +0 -10
  59. package/dist/billing-BV5kdyQb.js +0 -10
  60. package/dist/budget-CnxbNkne.js +0 -10
  61. package/dist/build-task-request-config-CjKDSNjv.js +0 -10
  62. package/dist/commands-gyHmiEsC.js +0 -10
  63. package/dist/config-CJf4r7wp.js +0 -11
  64. package/dist/connectors-C_Re7e0l.js +0 -11
  65. package/dist/file-upload-D2s_clGk.js +0 -24
  66. package/dist/format-DCvznP70.js +0 -10
  67. package/dist/isRecord-BNZWvqVS.js +0 -10
  68. package/dist/login-C0Zz6tHG.js +0 -10
  69. package/dist/marketplace-DQsEzT6T.js +0 -12
  70. package/dist/mcp-DHXuIFWP.js +0 -11
  71. package/dist/mcp-client-EK-Fh8gM.js +0 -10
  72. package/dist/meeting-C6H_GJB7.js +0 -11
  73. package/dist/message-utils-Cq_Fel5P.js +0 -15
  74. package/dist/models-DT78HZxx.js +0 -11
  75. package/dist/notifications-3UrKbGaT.js +0 -10
  76. package/dist/profile-D4m5ZAG7.js +0 -10
  77. package/dist/profile-storage-CPg61h-2.js +0 -68
  78. package/dist/project-C5_rCWCh.js +0 -10
  79. package/dist/project-context-DnIuy1T0.js +0 -10
  80. package/dist/project-governance-CxDZSThr.js +0 -10
  81. package/dist/project-sources-write-C-W8gjLg.js +0 -10
  82. package/dist/project-tasks-t4HFgEoZ.js +0 -10
  83. package/dist/recordings-DeB1LqiS.js +0 -11
  84. package/dist/remove-ChV-BE95.js +0 -10
  85. package/dist/resolve-Czx_OkYk.js +0 -14
  86. package/dist/schedules-COBaV-Be.js +0 -29
  87. package/dist/skills-OLZywcSs.js +0 -10
  88. package/dist/status-CpfDbB9S.js +0 -10
  89. package/dist/status-Oo8upbyy.js +0 -10
  90. package/dist/task-C8PttINZ.js +0 -108
  91. package/dist/tasks-CAmfAGsn.js +0 -22
  92. package/dist/tool-kEevHrsQ.js +0 -17
  93. package/dist/update-Y9S-P4wG.js +0 -10
  94. package/dist/usage-CHIhyA8S.js +0 -11
  95. package/dist/usage-audit-C1xGe42N.js +0 -12
  96. package/dist/workflow-DWmgcRJ_.js +0 -14
  97. package/dist/workspaces-3PFiXy1I.js +0 -11
package/README.md CHANGED
@@ -200,11 +200,18 @@ equivalent:
200
200
  entrydesk project note 2 -m "Shipped the retry fix"
201
201
  entrydesk project note 2 -f ./summary.md
202
202
  git log -1 | entrydesk project note 2 --title "Fixed the login race"
203
+ entrydesk project note 2 -m "Audit: 3 docs lack an owner" --visibility project
203
204
  ```
204
205
 
206
+ `--visibility project` shares the note with every current project member as it
207
+ is filed and notifies them. The workspace sharing policy and the
208
+ sensitive-content check still apply; if either blocks the share, the note is
209
+ still filed privately and the output says why.
210
+
205
211
  It prints the new task's id and a Hub link; `--json` returns
206
- `{ "taskId", "projectId", "url" }`. Reach for `task --project` above whenever
207
- you want the AI to answer instead.
212
+ `{ "taskId", "projectId", "visibility", "url" }`, plus `shareLink` when the
213
+ note was shared, or `shareFailure` (the server's error code) when it was not.
214
+ Reach for `task --project` above whenever you want the AI to answer instead.
208
215
 
209
216
  ### Tasks in a project
210
217
 
@@ -223,6 +230,8 @@ entrydesk project task-add 1 <taskId> --confirm-asset-sharing
223
230
  entrydesk project task-remove 1 <taskId> # Move it out; its assets stay
224
231
  entrydesk project task-share 1 <taskId> --add-user <userId>
225
232
  entrydesk project task-share 1 <taskId> --remove-user <userId>
233
+ entrydesk project task-share 1 <taskId> --add-team "Design"
234
+ entrydesk project task-share 1 <taskId> --remove-team <teamId>
226
235
  entrydesk project task-share 1 <taskId> --visibility project
227
236
  entrydesk project task-share 1 <taskId> --visibility self
228
237
  ```
@@ -237,17 +246,21 @@ history; only the task moves.
237
246
 
238
247
  `task-share` does one thing per call and never prompts. `--add-user` and
239
248
  `--remove-user` name one project member by id (`project get <project> --json`
240
- lists the members with theirs); `--visibility project` opens the task to every
241
- member and `--visibility self` closes it again, keeping whoever you named. The
242
- three flags are mutually exclusive and each needs its value; with none of them
243
- the command prints the usage and exits 1. A task has to be in the project you
249
+ lists the members with theirs); `--add-team` and `--remove-team` name one team
250
+ that is already in the project, by id or by name (`project members <project>`
251
+ lists them), and everyone in that team can view the task, read-only;
252
+ `--visibility project` opens the task to every member and `--visibility self`
253
+ closes it again, keeping whoever you named. The five flags are mutually
254
+ exclusive and each needs its value; with none of them the command prints the
255
+ usage and exits 1. A task has to be in the project you
244
256
  name — `task-share` and `task-remove` refuse one that is elsewhere rather than
245
257
  acting on the project it is actually in.
246
258
 
247
259
  `project tasks` reads with `tasks:read`; the three that write need
248
260
  `tasks:write`, and `task-remove` and `task-share` also read the task first with
249
- `tasks:read`. A project you are not a member of answers `Project not found`
250
- from all four.
261
+ `tasks:read`. `--add-team` and `--remove-team` also read the project's teams,
262
+ which needs `projects:read`. A project you are not a member of answers
263
+ `Project not found` from all four.
251
264
 
252
265
  ### Sources and context
253
266
 
@@ -286,9 +299,20 @@ entrydesk project sources-add 1 https://example.com/spec
286
299
  entrydesk project sources-edit 1 file <fileId> --description "Signed-off scope"
287
300
  entrydesk project sources-edit 1 file <fileId> --title "Launch brief" # How the AI names it
288
301
  entrydesk project sources-refetch 1 <linkId> # Snapshot goes back to pending
302
+ entrydesk project sources-replace 1 <fileId> ./brief.md --expected-version 3
289
303
  entrydesk project sources-rm 1 link <linkId>
290
304
  ```
291
305
 
306
+ `sources-replace` swaps a file's content in place: its id, title and
307
+ description stay, and its version number goes up by one. Pass the version
308
+ `project sources` showed when you read the file. If someone replaced it since,
309
+ nothing changes: the command exits 1 and names the current version, who saved
310
+ it and a URL to read it from. Under `--json` the error carries
311
+ `code: "project_file_version_conflict"` and the same details under `data`. The
312
+ CLI never retries a replace on its own, so a conflict always means someone
313
+ else's write. Merge your change into that content and replace again with that
314
+ version. The replaced content is kept as an earlier version, up to the latest 20.
315
+
292
316
  A link starts fetching its snapshot as soon as it is added, and `sources-refetch`
293
317
  starts that over, so both report it as `pending`; `project sources` shows when
294
318
  it is `ready`. Re-fetching a link whose fetch is still in flight is refused
@@ -343,10 +367,12 @@ the same rules the Hub applies. Whoever creates it is its owner:
343
367
  ```bash
344
368
  entrydesk project create --name "Q4 Launch" --description "Launch coordination"
345
369
  cat brief.md | entrydesk project create --name "Q4 Launch" --instruction-file -
346
- entrydesk project members 1 # Each member, role and id
370
+ entrydesk project members 1 # Each member, role and id, then each team
347
371
  entrydesk project member-add 1 <userId> # Takes effect at once
348
372
  entrydesk project member-role 1 <userId> --role owner
349
373
  entrydesk project member-remove 1 <userId> # Your own id leaves the project
374
+ entrydesk project team-add 1 --team "Design" # Everyone in the team, now and later
375
+ entrydesk project team-remove 1 --team <teamId>
350
376
  entrydesk project delete 1 # Lists what goes, then asks
351
377
  entrydesk project delete 1 -y # No prompt
352
378
  ```
@@ -366,6 +392,22 @@ someone else first. Each refusal comes back as its own message, and with
366
392
  are not in is `Project not found` for every one of these commands, exactly as
367
393
  it is for `get`.
368
394
 
395
+ A team in a project makes everyone in it a member, and anyone who joins the team
396
+ later too; the team is always a member, never an owner. `project members` lists
397
+ the teams after the members, each with its size, visibility and id, and
398
+ `--json` carries them as `teams[]` beside `members[]`. A hidden team you are not
399
+ in shows as `locked`: its name and size, never who is in it. `team-add` and
400
+ `team-remove` take `--team` as an id or a name. A name has to match exactly,
401
+ case included — team names are unique in a workspace, so an exact name is
402
+ never ambiguous. A name that only matches in a different case is never picked:
403
+ the command fails with `project_team_not_found` and lists the similar names
404
+ with their ids as hints. `team-add` checks the project's own teams first, so a
405
+ name already in the project is `project_team_already_added`. Only an owner can add or remove a
406
+ team, and a hidden team can only be added by one of its own members
407
+ (`project_team_not_found` otherwise, and for a team that is already gone);
408
+ adding one twice is `project_team_already_added`. Both need `projects:write`;
409
+ `team-remove`, and `team-add` given a name, also read with `projects:read`.
410
+
369
411
  Deleting a project detaches its tasks, which return to their owners' main
370
412
  lists, and deletes its sources, its assets and every version in their history.
371
413
  Without `-y` the command prints those effects for the project in question and
@@ -526,6 +568,27 @@ entrydesk schedules pause <scheduleId>
526
568
  entrydesk schedules runs <scheduleId> # Run history
527
569
  ```
528
570
 
571
+ ## Webhooks
572
+
573
+ Outgoing webhook destinations, for environments where an operator has enabled them. Managing them needs the Manage workspace permission.
574
+
575
+ ```bash
576
+ entrydesk webhook # List destinations
577
+ entrydesk webhook event-types # Event types you can subscribe to
578
+ entrydesk webhook create --url https://hooks.example.com/entrydesk --name BPM \
579
+ --events budget.limit_reached,budget.threshold_reached # or --all-events
580
+ entrydesk webhook test <id> # Send destination.test_sent now
581
+ entrydesk webhook deliveries <id> --status failed
582
+ entrydesk webhook delivery <id> <deliveryId>
583
+ entrydesk webhook resend <id> <deliveryId>
584
+ entrydesk webhook rotate-secret <id> --expire-previous 24h # or now
585
+ entrydesk webhook update <id> --name "BPM (prod)"
586
+ entrydesk webhook disable <id> # enable <id> resumes
587
+ entrydesk webhook delete <id> --yes
588
+ ```
589
+
590
+ Write commands need the `workspaces:write` scope; a session from before this release lacks it, so run `entrydesk login` once. `create` and `rotate-secret` print the signing secret only once. Each request carries `X-ED-Timestamp` and `X-ED-Signature: v1=<hex>`, where the hex is HMAC-SHA256 of `"{X-ED-Timestamp}.{raw body}"`.
591
+
529
592
  ## Notifications
530
593
 
531
594
  ```bash
@@ -561,31 +624,47 @@ Billing endpoints require an interactive login — a workspace PAT
561
624
 
562
625
  ## Configuration
563
626
 
564
- ```bash
565
- entrydesk config
566
- entrydesk config set apiUrl http://localhost:3200
567
- entrydesk config set hubUrl http://localhost:3000
568
- entrydesk config unset apiUrl
569
- ```
627
+ Server URLs live in the profile. `profile set` writes the current profile;
628
+ add `--profile <name>` to write another one without switching. The older
629
+ `entrydesk config list|get|set|unset` still works but is deprecated: it prints a
630
+ warning naming the `profile` command to use and will be removed in a future
631
+ release.
632
+
633
+ ```bash
634
+ entrydesk profile show
635
+ entrydesk profile set apiUrl http://localhost:3200
636
+ entrydesk profile set hubUrl http://localhost:3000 --profile local
637
+ entrydesk profile get apiUrl
638
+ entrydesk profile unset apiUrl
639
+ ```
640
+
641
+ When only `hubUrl` is set, the CLI asks that Hub where its API lives
642
+ (`GET <hubUrl>/.well-known/entrydesk/client`) the first time a command sends an
643
+ API request, and caches the answer per Hub in `~/.entrydesk/hub-discovery.json`
644
+ for five minutes; the profile config is left untouched. Commands that never
645
+ call the API (`profile`, `config`, `version`) do not contact the Hub, and
646
+ `entrydesk status` shows the API as resolved on first request until then.
647
+ `entrydesk logout` does reach the API to revoke the session, so it resolves
648
+ the URL, and it clears the local credentials either way.
649
+ `ENTRYDESK_API_URL` and a configured `apiUrl` both take precedence and skip
650
+ discovery. If a Hub has no discovery endpoint, the CLI falls back to the
651
+ matching API for `app.entrydesk.com`, `entrydesk.dcard.io` and `stage.gntc.io`,
652
+ and fails the request with an error for any other Hub instead of sending it to
653
+ the production API — set `apiUrl` explicitly in that case. With neither URL
654
+ set, the CLI uses `https://app.entrydesk.com` and `https://api.entrydesk.com`.
570
655
 
571
656
  ### Running Against a Local API
572
657
 
573
- Point the CLI at a locally running API for one command, or persist it in the
574
- active profile:
658
+ Point the CLI at a locally running API for one command, or create a profile
659
+ for it. A profile of its own keeps local credentials apart from the ones you
660
+ use against production, and `create` switches to it and logs in in one go:
575
661
 
576
662
  ```bash
577
663
  ENTRYDESK_API_URL=http://localhost:3200 entrydesk status # one invocation
578
- entrydesk config set apiUrl http://localhost:3200 # persist
579
- entrydesk config set hubUrl http://localhost:3000 # login opens this Hub
580
- entrydesk login
581
- ```
582
-
583
- Keep local work in its own profile so it cannot overwrite the credentials you
584
- use against production:
585
-
586
- ```bash
587
- entrydesk profile create local
588
- entrydesk profile use local
664
+ entrydesk profile create local \
665
+ --api-url http://localhost:3200 \
666
+ --hub-url http://localhost:3000 \
667
+ --login
589
668
  ```
590
669
 
591
670
  If the local API serves a self-signed certificate, add
@@ -655,9 +734,13 @@ scope together, and refuse with the missing ones named otherwise.
655
734
 
656
735
  ```bash
657
736
  entrydesk profile # List profiles
658
- entrydesk profile create staging # Create a profile
737
+ entrydesk profile create staging # Create a profile and switch to it
738
+ entrydesk profile create staging --hub-url https://stage.gntc.io --login
739
+ entrydesk profile create staging --no-use # Create without switching
740
+ entrydesk profile create staging --no-use --login # Log in to it, stay on the current one
659
741
  entrydesk profile use staging # Switch active profile
660
- entrydesk profile show staging # Show profile details
742
+ entrydesk profile show staging # Show profile details (URLs, model, login)
743
+ entrydesk profile set apiUrl <url> # Set a value on the current profile
661
744
  entrydesk profile clone default staging # Clone config defaults (no credentials)
662
745
  entrydesk profile rename staging qa # Rename a profile (credentials follow)
663
746
  entrydesk profile delete staging
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ var __entrydeskNodeFloor = 24;
3
+ if (parseInt(process.versions.node, 10) < __entrydeskNodeFloor) {
4
+ process.stderr.write(
5
+ 'entrydesk: Node.js ' + __entrydeskNodeFloor + ' or newer is required, but this is Node ' + process.versions.node + '.\n' +
6
+ 'Upgrade Node (https://nodejs.org/en/download), then reinstall @entrydesk/cli.\n'
7
+ );
8
+ process.exit(1);
9
+ }
10
+ import{N as e}from"./profile-storage-BVSyHoBn.js";import{t}from"./terminal-text-cBPBiP3x.js";import{a as n,d as r,f as i,g as a,i as o,r as s}from"./paths-CLGwOhp4.js";import{t as c}from"./hash-CnSb1n2t.js";import{r as l}from"./installer-CKB3jBE-.js";import{t as u}from"./remote-D3JMUBbh.js";import d from"node:fs";import f from"node:os";import p from"node:path";import m from"cross-spawn";function h(e,t){let n=p.dirname(e);d.mkdirSync(n,{recursive:!0});let r=d.mkdtempSync(p.join(n,`.${p.basename(e)}.tmp-`)),i=p.join(r,`next`),a=p.join(r,`prev`);d.mkdirSync(i,{recursive:!0});let o=!1;try{t(i),d.existsSync(e)&&(d.renameSync(e,a),o=!0),d.renameSync(i,e)}catch(t){throw o&&!d.existsSync(e)&&d.renameSync(a,e),t}finally{d.rmSync(r,{recursive:!0,force:!0})}}const g=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/iu,_=/^([\w.-]+)\/([\w.-]+)(?:\/(.+))?$/u;function v(e){return e===`~`?f.homedir():e.startsWith(`~/`)||e.startsWith(`~\\`)?p.join(f.homedir(),e.slice(2)):e}function y(e){return e.startsWith(`./`)||e.startsWith(`../`)||e.startsWith(`/`)||e.startsWith(`~`)||e.startsWith(`.\\`)||/^[a-zA-Z]:[\\/]/u.test(e)}function b(e){let t=/^https?:\/\/github\.com\/([\w.-]+)\/([\w.-]+?)(?:\.git)?(?:\/tree\/([^/]+)(?:\/(.+))?)?\/?$/u.exec(e);return t?{type:`github`,owner:t[1],repo:t[2],gitRef:t[3],subpath:t[4],url:`https://github.com/${t[1]}/${t[2]}`}:null}function x(e){let t=e.trim();if(y(t))return{type:`local`,path:p.resolve(v(t))};if(t.startsWith(`ed:`)){let e=t.slice(3);return{type:`entrydesk`,ref:e,isId:g.test(e)}}if(g.test(t))return{type:`entrydesk`,ref:t,isId:!0};if(t.startsWith(`git@`)||t.endsWith(`.git`))return{type:`git`,url:t};let n=b(t);if(n)return n;if(/^https?:\/\//u.test(t))return{type:`git`,url:t};let r=_.exec(t);return r?{type:`github`,owner:r[1],repo:r[2],subpath:r[3],url:`https://github.com/${r[1]}/${r[2]}`}:{type:`entrydesk`,ref:t,isId:!1}}function S(e){return e.type===`github`?`github`:e.type}const C=new Set([`.git`,`node_modules`,`__pycache__`,`.DS_Store`,`.entrydesk`]);function w(e,t){if(!d.existsSync(p.join(e,`SKILL.md`)))throw Error(`No SKILL.md found at ${e}`);let n=d.realpathSync(e);if(n===(d.existsSync(t)?d.realpathSync(t):p.resolve(t)))return;let r=d.mkdtempSync(p.join(f.tmpdir(),`ed-local-skill-`)),i=p.join(r,`skill`);try{d.cpSync(n,i,{recursive:!0,filter:e=>!C.has(p.basename(e))}),h(t,e=>{d.cpSync(i,e,{recursive:!0})})}finally{d.rmSync(r,{recursive:!0,force:!0})}}function T(e){try{let t=d.readFileSync(p.join(e,`SKILL.md`),`utf8`),n=/^name:\s*(.+?)\s*$/mu.exec(t.split(/^---\s*$/mu)[1]??``);if(n?.[1])return n[1].replace(/^['"]|['"]$/gu,``)}catch{}return p.basename(e)}async function E(e,t){let{default:n}=await import(`adm-zip`),r=new n(e);h(t,e=>{let t=p.resolve(e)+p.sep;for(let n of r.getEntries()){if(n.isDirectory)continue;let r=p.resolve(e,n.entryName);if(!r.startsWith(t))throw Error(`Zip entry contains path traversal: ${n.entryName}`);d.mkdirSync(p.dirname(r),{recursive:!0}),d.writeFileSync(r,n.getData())}})}async function D(e,t){if(t.isId)return t.ref;let n=(await u(e.client,e.accessToken,e.workspaceId)).find(e=>e.name===t.ref||e.id===t.ref);if(!n)throw Error(`Skill not found in workspace: ${t.ref}`);return n.id}function O(e,t,n){let r=d.mkdtempSync(p.join(f.tmpdir(),`ed-npx-skills-`)),i=[`-y`,`skills@1.5.12`,`add`,e,`--copy`,`--yes`];try{let e=m.sync(`npx`,i,{cwd:r,stdio:n?[`ignore`,`pipe`,`pipe`]:`inherit`});if(e.error)throw e.error;if(e.status!==0){let t=e.stderr?.toString().trim();throw Error(`npx exited with code ${e.status??`null`}${t?`: ${t}`:``}`)}}catch(t){throw d.rmSync(r,{recursive:!0,force:!0}),Error(`npx skills failed for ${e}. Ensure npx + network are available. (${t instanceof Error?t.message:String(t)})`,{cause:t})}let a=p.join(r,`.agents`,`skills`);if(!d.existsSync(a))throw d.rmSync(r,{recursive:!0,force:!0}),Error(`npx skills produced no skills under ${a}`);let o=d.readdirSync(a,{withFileTypes:!0}).filter(e=>e.isDirectory());if(o.length===0)throw d.rmSync(r,{recursive:!0,force:!0}),Error(`npx skills installed no skill directory`);let s=o[0];if(o.length>1){let e=t.type===`github`&&t.subpath?p.basename(t.subpath):void 0,n=e?o.find(t=>t.name===e):void 0;if(!n)throw d.rmSync(r,{recursive:!0,force:!0}),Error(`npx skills installed [${o.map(e=>e.name).join(`, `)}]; ${e?`none matched the subpath "${e}"`:`specify a subpath to pick one`}.`);s=n}return{dir:p.join(a,s.name),tmpRoot:r}}async function k(u,f,p){let m=x(u),h=!!f.global,g=await o(h,p.workspaceId),_=g.rootDir,v={...p,workspaceId:g.workspaceId};if(!g.linked){let t={workspaceId:p.workspaceId,apiUrl:await e()};n(),h?r(t):i(process.cwd(),t)}let y,b,C;if(m.type===`entrydesk`){b=await D(v,m);let e=await v.client.downloadSkillCurrent(v.accessToken,v.workspaceId,b);y=e.name,C=s(_,y);let t=await fetch(e.url);if(!t.ok)throw Error(`Failed to download ${y}: ${t.status}`);await E(Buffer.from(await t.arrayBuffer()),C)}else if(m.type===`local`)y=T(m.path),C=s(_,y),w(m.path,C);else{let{dir:e,tmpRoot:t}=O(u,m,!!f.json);try{y=T(e),C=s(_,y),w(e,C)}finally{d.rmSync(t,{recursive:!0,force:!0})}}let k=c(C),A={source:u,sourceType:S(m),skillId:b,localHash:k,lastPulledHash:m.type===`entrydesk`?k:``,mode:`symlink`,...m.type===`github`?{sourceUrl:m.url,ref:m.gitRef,subpath:m.subpath}:{},...m.type===`git`?{sourceUrl:m.url}:{}};a(_,y,A);let j=l(C,y,_,`symlink`,f.agent);f.json?console.info(t({name:y,sourceType:S(m),hash:k},2)):console.info(`✓ added ${y} (${m.type}, ${k.slice(0,12)}) → agents: ${j.map(e=>e.agentId).join(`, `)}`)}export{k as runSkillsAdd};
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ var __entrydeskNodeFloor = 24;
3
+ if (parseInt(process.versions.node, 10) < __entrydeskNodeFloor) {
4
+ process.stderr.write(
5
+ 'entrydesk: Node.js ' + __entrydeskNodeFloor + ' or newer is required, but this is Node ' + process.versions.node + '.\n' +
6
+ 'Upgrade Node (https://nodejs.org/en/download), then reinstall @entrydesk/cli.\n'
7
+ );
8
+ process.exit(1);
9
+ }
10
+ import{Jt as e,Wt as t,d as n,qt as r,ut as i,x as a}from"./profile-storage-BVSyHoBn.js";import{t as o}from"./resource-grants-DMj0dy5m.js";import{t as s}from"./terminal-text-cBPBiP3x.js";function c(n){return n?e([...new Set(n)]):t}function l(e){console.log(`Available agents (${e.length}):\n`);for(let t of e){if(console.log(` ${t.name} (${t.visibility})`),t.description){let e=t.description.length>80?`${t.description.slice(0,80)}…`:t.description;console.log(` ${e}`)}console.log(` ID: ${t.id}`),console.log(``)}}function u(e){console.log(`My agents (${e.length}):\n`);for(let t of e){let e=[];t.latestVersionNumber!=null&&e.push(`v${t.latestVersionNumber}`),t.hasUnpublishedChanges&&e.push(`unpublished changes`);let n=e.length>0?` (${e.join(` · `)})`:``;if(console.log(` ${t.name}${n}`),t.description){let e=t.description.length>80?`${t.description.slice(0,80)}…`:t.description;console.log(` ${e}`)}console.log(` ${t.myRole??`no-role`} · ID: ${t.id}`),console.log(``)}}function d(e){if(console.log(`${e.name}\n`),console.log(` ID: ${e.id}`),e.visibility&&console.log(` Visibility: ${e.visibility}`),e.model&&console.log(` Model: ${e.model.name}`),e.author&&console.log(` Author: ${e.author.name}${e.author.isMe?` (you)`:``}`),e.description&&console.log(` Description: ${e.description}`),e.capabilities){let t=r(e.capabilities).map(e=>i(e));t.length>0&&console.log(` Capabilities: ${t.join(`, `)}`)}e.connectors&&e.connectors.length>0&&console.log(` Connectors: ${e.connectors.map(e=>e.name).join(`, `)}`),e.tools&&e.tools.length>0&&console.log(` Tools: ${e.tools.length}`),e.conversationStarters&&e.conversationStarters.length>0&&console.log(` Starters: ${e.conversationStarters.length}`),e.systemPrompt&&console.log(`\n System prompt:\n${e.systemPrompt}`)}async function f(e){let{accessToken:t,workspaceId:r}=await n(),i=new a;if(e.mine){let n=[],a=e.all?void 0:e.nextKey;for(let o=0;;o++){o>=100&&(console.error(`Reached maximum page limit (100). Use --limit and --next-key for manual pagination.`),process.exit(1));let s=await i.getMyAgents(t,r,{limit:e.limit,nextKey:a});if(n.push(...s.agents),a=s.nextKey,!e.all||!a)break}if(e.json){console.log(s({agents:n,nextKey:a}));return}if(n.length===0){console.log("You own no agents in this workspace. Create one with `entrydesk agents create --name <name> …`, or browse `entrydesk marketplace`.");return}u(n),!e.all&&a&&console.log(`Next page: --next-key ${a}`);return}if(e.all){let n=[],a;for(let o=0;;o++){o>=100&&(console.error(`Reached maximum page limit (100). Use --limit and --next-key for manual pagination.`),process.exit(1));let s=await i.getAgents(t,r,{limit:e.limit??100,nextKey:a});if(n.push(...s.agents),a=s.nextKey,!a)break}if(e.json){console.log(s({agents:n}));return}if(n.length===0){console.log("No agents in this workspace yet. Create one with `entrydesk agents create`, or browse `entrydesk marketplace`.");return}l(n);return}let{agents:o,nextKey:c}=await i.getAgents(t,r,{limit:e.limit,nextKey:e.nextKey});if(e.json){console.log(s({agents:o,nextKey:c}));return}if(o.length===0){console.log("No agents in this workspace yet. Create one with `entrydesk agents create`, or browse `entrydesk marketplace`.");return}l(o),c&&console.log(`Next page: --next-key ${c}`)}async function p(e,t){let{accessToken:r,workspaceId:i}=await n(),o=await new a().getAgent(r,i,e);if(t.json){console.log(s(o));return}d(o)}async function m(e){let{accessToken:t,workspaceId:r}=await n(),i=await new a().createAgent(t,r,{name:e.name,description:e.description,systemPrompt:e.systemPrompt,modelId:e.modelId,connectorIds:e.connectorIds??[],capabilities:c(e.capabilities),conversationStarters:e.conversationStarters??[],tools:e.tools,iconId:e.iconId});if(e.json){console.log(s(i));return}console.log(`Created agent: ${i.name}`),console.log(` ID: ${i.id}`)}async function h(e,t){let{accessToken:r,workspaceId:i}=await n(),o=new a,s=await o.getAgent(r,i,e),l={name:t.name??s.name,description:t.description??s.description,systemPrompt:t.systemPrompt??s.systemPrompt??``,modelId:t.modelId??s.model?.id??``,connectorIds:t.connectorIds??s.connectors?.map(e=>e.id)??[],capabilities:t.capabilities?c(t.capabilities):s.capabilities??{},conversationStarters:t.conversationStarters??s.conversationStarters??[],tools:t.tools??s.tools??[],iconId:t.iconId??s.iconId};await o.updateAgent(r,i,e,l),console.log(`Updated agent: ${e}`)}async function g(e){let{accessToken:t,workspaceId:r}=await n();await new a().deleteAgent(t,r,e),console.log(`Deleted agent: ${e}`)}async function _(e,t){let{accessToken:r,workspaceId:i}=await n();if(await new a().publishAgent(r,i,e),t.json){console.log(s({id:e,published:!0}));return}console.log(`Published agent to the workspace: ${e}`)}async function v(e,t){let{accessToken:r,workspaceId:i}=await n(),c=new a;if(t.addUser){let n=await c.upsertAgentGrant(r,i,e,t.addUser,t.role);if(t.json){console.log(s(n));return}console.log(`Granted ${t.role} to user ${t.addUser}`);return}if(t.removeUser){if(await c.removeAgentGrant(r,i,e,t.removeUser),t.json){console.log(s({userId:t.removeUser,removed:!0}));return}console.log(`Revoked access for user ${t.removeUser}`);return}let l=await c.getAgentGrants(r,i,e);if(t.json){console.log(s(l));return}o(l)}export{m as createAgent,g as deleteAgent,f as listAgents,_ as publishAgent,v as shareAgent,p as showAgent,h as updateAgent};
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ var __entrydeskNodeFloor = 24;
3
+ if (parseInt(process.versions.node, 10) < __entrydeskNodeFloor) {
4
+ process.stderr.write(
5
+ 'entrydesk: Node.js ' + __entrydeskNodeFloor + ' or newer is required, but this is Node ' + process.versions.node + '.\n' +
6
+ 'Upgrade Node (https://nodejs.org/en/download), then reinstall @entrydesk/cli.\n'
7
+ );
8
+ process.exit(1);
9
+ }
10
+ import{d as e,x as t,y as n}from"./profile-storage-BVSyHoBn.js";import{t as r}from"./terminal-text-cBPBiP3x.js";import{i,n as a}from"./format-BaXJBAlk.js";import{t as o}from"./paginate-DetNe5nU.js";function s(e){if(console.log(`Billing status: ${e.lifecycle.kind}`),e.subscription){let t=e.subscription,n=t.nextInvoiceDueAt?` · next invoice ${new Date(t.nextInvoiceDueAt).toLocaleDateString()}`:``;console.log(` Plan: ${t.planName} · ~${i(t.estimatedMonthlyChargeUsd)}/month${n}`)}else console.log(` Plan: (no active subscription)`);let t=e.seats;console.log(` Seats: pro ${t.assigned.pro}/${t.purchased.pro}, premium ${t.assigned.premium}/${t.purchased.premium} (assigned/purchased)`);let n=e.extraUsage;console.log(` Balance: ${i(n.balanceUsd)} extra usage`),console.log(` Spent: ${a(n.currentSpentUsd)} this period`),n.monthlyExtraUsageLimitUsd!=null&&console.log(` Limit: ${i(n.monthlyExtraUsageLimitUsd)} / month`)}function c(e){console.log(`Invoices (${e.length}):\n`);for(let t of e){let e=new Date(t.billingDate).toLocaleDateString();console.log(` ${e} · ${t.type} · ${t.status} · ${i(t.totalUsd)}`),t.hostedInvoiceUrl&&console.log(` ${t.hostedInvoiceUrl}`),console.log(` ID: ${t.id}`),console.log(``)}}async function l(){return n()&&(console.error("Billing requires an interactive login. A workspace PAT (ENTRYDESK_TOKEN) cannot read billing — run `entrydesk login`."),process.exit(1)),e()}async function u(e){let{accessToken:n,workspaceId:i}=await l(),a=await new t().getBillingOverview(n,i);if(e.json){console.log(r(a));return}s(a)}async function d(e){let{accessToken:n,workspaceId:i}=await l(),a=new t;if(e.all){let t=await o(async t=>{let r=await a.getBillingInvoices(n,i,{limit:e.limit??20,nextKey:t});return{items:r.invoices,nextKey:r.nextKey}});if(e.json){console.log(r({invoices:t}));return}if(t.length===0){console.log(`No invoices.`);return}c(t);return}let{invoices:s,nextKey:u}=await a.getBillingInvoices(n,i,{limit:e.limit,nextKey:e.nextKey});if(e.json){console.log(r({invoices:s,nextKey:u}));return}if(s.length===0){console.log(`No invoices.`);return}c(s),u&&console.log(`Next page: --next-key ${u}`)}export{d as listInvoices,u as showBillingStatus};
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ var __entrydeskNodeFloor = 24;
3
+ if (parseInt(process.versions.node, 10) < __entrydeskNodeFloor) {
4
+ process.stderr.write(
5
+ 'entrydesk: Node.js ' + __entrydeskNodeFloor + ' or newer is required, but this is Node ' + process.versions.node + '.\n' +
6
+ 'Upgrade Node (https://nodejs.org/en/download), then reinstall @entrydesk/cli.\n'
7
+ );
8
+ process.exit(1);
9
+ }
10
+ import{d as e,x as t}from"./profile-storage-BVSyHoBn.js";import{t as n}from"./terminal-text-cBPBiP3x.js";async function r(r){let{accessToken:i,workspaceId:a}=await e(),o=await new t().getBudget(i,a);if(r.json){console.log(n(o));return}if(o.budget===null){console.log(`No budget set for this workspace.`);return}console.log(`Current workspace budget: $${o.budget}`)}async function i(r,i){let{accessToken:a,workspaceId:o}=await e(),s=new t;if(await s.updateBudget(a,o,r),i.json){console.log(n(await s.getBudget(a,o)));return}console.log(`Budget updated: $${r}`)}async function a(r){let{accessToken:i,workspaceId:a}=await e(),o=new t;if(await o.updateBudget(i,a,null),r.json){console.log(n(await o.getBudget(i,a)));return}console.log(`Budget cleared.`)}export{a as clearBudget,i as setBudget,r as showBudget};
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ var __entrydeskNodeFloor = 24;
3
+ if (parseInt(process.versions.node, 10) < __entrydeskNodeFloor) {
4
+ process.stderr.write(
5
+ 'entrydesk: Node.js ' + __entrydeskNodeFloor + ' or newer is required, but this is Node ' + process.versions.node + '.\n' +
6
+ 'Upgrade Node (https://nodejs.org/en/download), then reinstall @entrydesk/cli.\n'
7
+ );
8
+ process.exit(1);
9
+ }
10
+ import{Ht as e,Vt as t,ft as n,pt as r}from"./profile-storage-BVSyHoBn.js";function i({allowedTools:e,disallowedTools:t}){if(!(!e?.length&&!t?.length))return[...r(e?.map(e=>({toolName:e,policy:n.ALWAYS_ALLOW})),t?.map(e=>({toolName:e,policy:n.BLOCK})))].map(([e,t])=>({toolName:e,policy:t}))}function a(e,t){let i=[...t].map(e=>({toolName:e,policy:n.ALWAYS_ALLOW}));return i.length===0?e:[...r(e,i)].map(([e,t])=>({toolName:e,policy:t}))}function o({agentId:n,model:r,projectId:i,connectorIds:a,clientTools:o,clientToolSystemPrompt:s,toolApprovalMode:c,toolPolicies:l}){return{...i?{projectId:i}:{},...n?{agentId:n}:{...r?{model:r}:{},...a?.length?{connectorIds:a}:{}},...o?{clientTools:e(o,t.DIRECT)}:{},...s?{clientToolSystemPrompt:s}:{},...c?{toolApprovalMode:c}:{},...l?.length?{toolPolicies:l}:{}}}export{i as n,a as r,o as t};
@@ -7,4 +7,4 @@ if (parseInt(process.versions.node, 10) < __entrydeskNodeFloor) {
7
7
  );
8
8
  process.exit(1);
9
9
  }
10
- import{r as e}from"./commands-gyHmiEsC.js";export{e as runSkillsUnlink};
10
+ import{r as e}from"./commands-qNH4DlB_.js";export{e as runSkillsUnlink};
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ var __entrydeskNodeFloor = 24;
3
+ if (parseInt(process.versions.node, 10) < __entrydeskNodeFloor) {
4
+ process.stderr.write(
5
+ 'entrydesk: Node.js ' + __entrydeskNodeFloor + ' or newer is required, but this is Node ' + process.versions.node + '.\n' +
6
+ 'Upgrade Node (https://nodejs.org/en/download), then reinstall @entrydesk/cli.\n'
7
+ );
8
+ process.exit(1);
9
+ }
10
+ import{N as e}from"./profile-storage-BVSyHoBn.js";import{t}from"./terminal-text-cBPBiP3x.js";import{a as n,c as r,d as i,f as a,g as o,i as s,l as c,m as l,o as u,r as d,s as f,u as p}from"./paths-CLGwOhp4.js";import{t as m}from"./hash-CnSb1n2t.js";import{r as h}from"./installer-CKB3jBE-.js";import g from"node:path";import _ from"node:fs/promises";const v=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/iu;async function y(t,o,s){let c=t&&v.test(t)?t:s.workspaceId,l={workspaceId:c,apiUrl:await e()};if(n(),o.global)i(l),console.info(`Linked ${f()} → workspace ${c}`);else{let e=process.cwd();a(e,l),console.info(`Linked ${r(e)} → workspace ${c}`)}}function b(e){if(e.global){c()?console.info(`Unlinked ${f()}`):console.info(`No global link found.`);return}let t=u(process.cwd());t&&p(t)?console.info(`Unlinked ${r(t)}`):console.info(`No project link found.`)}async function x(e,t,n,r,i){let a=n.skillId;if(!a){let{skills:t}=await e.client.listAvailableSkills(e.accessToken,e.workspaceId),r=t.find(e=>e.name===n.name);if(!r)throw Error(`Skill not found in workspace: ${n.name}`);a=r.id}let{url:s,name:c}=await e.client.downloadSkillCurrent(e.accessToken,e.workspaceId,a),l=await fetch(s);if(!l.ok)throw Error(`Failed to download ${c}: ${l.status}`);let u=Buffer.from(await l.arrayBuffer()),f=d(t,c);await _.rm(f,{recursive:!0,force:!0}),await _.mkdir(f,{recursive:!0});let{default:p}=await import(`adm-zip`),v=g.resolve(f)+g.sep;for(let e of new p(u).getEntries()){if(e.isDirectory)continue;let t=g.resolve(f,e.entryName);if(!t.startsWith(v))throw Error(`Zip entry contains path traversal: ${e.entryName}`);await _.mkdir(g.dirname(t),{recursive:!0}),await _.writeFile(t,e.getData())}let y=m(f);o(t,c,{source:a,sourceType:`entrydesk`,skillId:a,localHash:y,lastPulledHash:y,mode:`symlink`});let b=h(f,c,t,`symlink`,i);return r||console.info(`✓ pulled ${c} (${y.slice(0,12)}) → agents: ${b.map(e=>e.agentId).join(`, `)}`),{name:c,hash:y}}async function S(e,n,r){let{rootDir:i,workspaceId:a}=await s(!!n.global,r.workspaceId),o={...r,workspaceId:a},c=!!n.json,u=[];if(e)u.push(v.test(e)?{skillId:e}:{name:e});else{let e=l(i).skills;for(let[t,n]of Object.entries(e))u.push({skillId:n.skillId,name:t});if(u.length===0){console.info(`Nothing to pull — no tracked skills. Try: entrydesk skills pull <name>`);return}}let d=[];for(let e of u)d.push(await x(o,i,e,c,n.agent));c&&console.info(t(d,2))}export{S as n,b as r,y as t};
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ var __entrydeskNodeFloor = 24;
3
+ if (parseInt(process.versions.node, 10) < __entrydeskNodeFloor) {
4
+ process.stderr.write(
5
+ 'entrydesk: Node.js ' + __entrydeskNodeFloor + ' or newer is required, but this is Node ' + process.versions.node + '.\n' +
6
+ 'Upgrade Node (https://nodejs.org/en/download), then reinstall @entrydesk/cli.\n'
7
+ );
8
+ process.exit(1);
9
+ }
10
+ import{F as e,I as t,t as n}from"./profile-storage-BVSyHoBn.js";import{t as r}from"./terminal-text-cBPBiP3x.js";function i(i){let a=t.getAll();if(i.json){console.log(r(a));return}let o=Object.entries(a);if(console.log(`Profile: ${n.getEffectiveProfileName()}`),o.length===0){console.log(`No configuration set.`),console.log(`Available keys: ${e.join(`, `)}`);return}console.log(`Configuration:
11
+ `);for(let[e,t]of o)console.log(` ${e}=${t}`);console.log(`\nAvailable keys: ${e.join(`, `)}`)}export{i as listConfig};
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ var __entrydeskNodeFloor = 24;
3
+ if (parseInt(process.versions.node, 10) < __entrydeskNodeFloor) {
4
+ process.stderr.write(
5
+ 'entrydesk: Node.js ' + __entrydeskNodeFloor + ' or newer is required, but this is Node ' + process.versions.node + '.\n' +
6
+ 'Upgrade Node (https://nodejs.org/en/download), then reinstall @entrydesk/cli.\n'
7
+ );
8
+ process.exit(1);
9
+ }
10
+ import{Ft as e,It as t,Lt as n,d as r,jt as i,kt as a,x as o}from"./profile-storage-BVSyHoBn.js";import{t as s}from"./terminal-text-cBPBiP3x.js";import{t as c}from"./confirm-Ct432t3K.js";function l(t,n){return n?e(n)?`Next: entrydesk connectors connect ${t} --oauth`:n===`credentials`?`Next: entrydesk connectors connect ${t} --username <username> --password <password>`:`Next: entrydesk connectors connect ${t} --token <token>`:`This connector needs no authorization — there is no connect step.`}async function u(e){let{accessToken:t,workspaceId:n}=await r(),{connectors:i,nextKey:a}=await new o().getConnectors(t,n,{connectionStatus:e.all?`all`:`connected`,search:e.search,limit:e.limit,nextKey:e.nextKey});if(e.json){console.log(s({connectors:i,nextKey:a}));return}if(i.length===0){console.log(e.all?`No connectors found.`:`No connected connectors. Use --all to browse connectable ones.`);return}let c=e.all?`Connectors`:`Connected connectors`;console.log(`${c} (${i.length}):\n`);for(let e of i){let t=e.connected?`connected`:`not connected`;console.log(` ${e.name} (${t})`),console.log(` Provider: ${e.provider}`),console.log(` ID: ${e.id}`),e.authorization?.type&&console.log(` Auth: ${e.authorization.type}`),console.log(``)}a&&console.log(`More results: --next-key ${a}`)}async function d(e,t){let{accessToken:n,workspaceId:i}=await r(),{tools:a}=await new o().getConnectorTools(n,i,e);if(t.json){console.log(s({tools:a}));return}if(a.length===0){console.log(`This connector exposes no tools.`);return}console.log(`Tools (${a.length}):\n`);for(let e of a)console.log(` ${e.name} [${e.policy}]`),e.description&&console.log(` ${e.description}`)}async function f(e,t){let{accessToken:n,workspaceId:i}=await r();await new o().syncConnectorTools(n,i,e),console.log(t.json?s({id:e,synced:!0}):`Synced tools for connector ${e}.`)}async function p(e,t){let{accessToken:n,workspaceId:i}=await r(),a=new o;if(t.oauth){let{url:r}=await a.getConnectorAuthUrl(n,i,e);if(t.json){console.log(s({url:r}));return}console.log(`Open this URL in your browser to authorize the connector:`),console.log(` ${r}`),console.log(`
11
+ After you approve, the connection is saved automatically — re-run`),console.log("`entrydesk connectors` to confirm it shows as connected.");return}let c;t.token?c={token:t.token}:t.username&&t.password?c={username:t.username,password:t.password}:(console.error(`Provide --token, or --username and --password, or --oauth to connect.`),process.exit(1)),await a.connectConnectorToken(n,i,e,c),console.log(t.json?s({id:e,connected:!0}):`Connected connector ${e}.`)}function m(e){let t=e.auth===`oauth`||e.auth===`google-iap`;if(t&&(!e.provider||!e.scope?.length)&&(console.error(`--auth ${e.auth} needs --provider and at least one --scope.`),process.exit(1)),!t&&(e.provider||e.scope?.length)&&(console.error(e.auth?`--provider and --scope apply only to --auth oauth and --auth google-iap, not --auth ${e.auth}.`:`--provider and --scope need --auth oauth or --auth google-iap.`),process.exit(1)),e.auth!==void 0)return e.auth===!1?null:{type:e.auth,...e.provider?{provider:e.provider}:{},...e.scope?.length?{scopes:e.scope}:{}}}async function h(e){let c=m(e),u=e.toolNamespace??e.toolPrefix,d=u??t(e.name),f=i(d);if(f){let e=a[f];console.error(u?`--tool-namespace ${e}.`:`The tool namespace derived from --name ("${d}") ${e}. Pass --tool-namespace explicitly.`),process.exit(1)}let{accessToken:p,workspaceId:h}=await r(),g=await new o().createCustomConnector(p,h,{type:n.CUSTOM_REMOTE_URL,name:e.name,description:e.description,transport:e.transport,url:e.url,toolNamespace:d,...c?{authorization:c}:{}});if(e.json){console.log(s(g));return}console.log(`Created connector ${g.name}.`),console.log(` ID: ${g.id}`),console.log(` URL: ${g.url}`),console.log(` Tool namespace: ${g.toolNamespace}`),console.log(`\n${l(g.id,e.auth)}`)}function g(e,t){return t===void 0?e:t===null||t.type!==e?.type?t:{...e,...t}}async function _(e,t){[t.name,t.url,t.description,t.transport,t.toolNamespace,t.auth,t.provider,t.scope].every(e=>e===void 0)&&(console.error(`Nothing to update. Pass at least one of --name, --url, --description, --transport, --tool-namespace, --auth or --no-auth.`),process.exit(1));let i=m(t),{accessToken:a,workspaceId:c}=await r(),l=new o,u=await l.getCustomConnector(a,c,e),d=await l.updateCustomConnector(a,c,e,{type:n.CUSTOM_REMOTE_URL,name:t.name??u.name,description:t.description??u.description,transport:t.transport??u.transport,url:t.url??u.url,toolNamespace:t.toolNamespace??u.toolNamespace,authorization:g(u.authorization,i)});if(t.json){console.log(s(d));return}console.log(`Updated connector ${d.name}.`),console.log(` ID: ${d.id}`),console.log(` URL: ${d.url}`),console.log(` Tool namespace: ${d.toolNamespace}`)}async function v(e,t){let{accessToken:n,workspaceId:i}=await r();if(!t.yes&&(process.stdin.isTTY||(console.error(`Disconnecting connector ${e} needs confirmation. Re-run with --yes.`),process.exit(1)),!await c(`Disconnect connector ${e}?`))){console.log(`Aborted.`);return}await new o().disconnectConnector(n,i,e),console.log(t.json?s({id:e,disconnected:!0}):`Disconnected connector ${e}.`)}export{p as connectConnector,h as createConnector,v as disconnectConnector,d as listConnectorTools,u as listConnectors,f as syncConnectorTools,_ as updateConnector};
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env node
2
+ var __entrydeskNodeFloor = 24;
3
+ if (parseInt(process.versions.node, 10) < __entrydeskNodeFloor) {
4
+ process.stderr.write(
5
+ 'entrydesk: Node.js ' + __entrydeskNodeFloor + ' or newer is required, but this is Node ' + process.versions.node + '.\n' +
6
+ 'Upgrade Node (https://nodejs.org/en/download), then reinstall @entrydesk/cli.\n'
7
+ );
8
+ process.exit(1);
9
+ }
10
+ import e,{promises as t}from"node:fs";import n from"node:os";import r from"node:path";import{execFile as i}from"node:child_process";import a from"node:fs/promises";import{promisify as o}from"node:util";const s=o(i);async function c(){let t=r.join(n.tmpdir(),`entrydesk-clipboard-${Date.now()}.png`);try{let e=`
11
+ set imageData to the clipboard as "PNGf"
12
+ set fileRef to open for access POSIX file "${t}" with write permission
13
+ set eof fileRef to 0
14
+ write imageData to fileRef
15
+ close access fileRef
16
+ `;return await s(`osascript`,[`-e`,e]),(await a.stat(t)).size===0?void 0:{buffer:await a.readFile(t),mime:`image/png`}}catch{return}finally{try{e.existsSync(t)&&await a.unlink(t)}catch{}}}async function l(){try{let{stdout:e}=await s(`powershell.exe`,[`-command`,`
17
+ Add-Type -AssemblyName System.Windows.Forms
18
+ $img = [System.Windows.Forms.Clipboard]::GetImage()
19
+ if ($img) {
20
+ $ms = New-Object System.IO.MemoryStream
21
+ $img.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png)
22
+ [System.Convert]::ToBase64String($ms.ToArray())
23
+ }
24
+ `]),t=e.trim();if(!t)return;let n=Buffer.from(t,`base64`);return n.length===0?void 0:{buffer:n,mime:`image/png`}}catch{return}}async function u(){try{let{stdout:e}=await s(`wl-paste`,[`-t`,`image/png`],{encoding:`buffer`,maxBuffer:50*1024*1024});if(e.length>0)return{buffer:e,mime:`image/png`}}catch{}try{let{stdout:e}=await s(`xclip`,[`-selection`,`clipboard`,`-t`,`image/png`,`-o`],{encoding:`buffer`,maxBuffer:50*1024*1024});if(e.length>0)return{buffer:e,mime:`image/png`}}catch{}}async function d(){let e=n.platform();if(e===`darwin`)return c();if(e===`win32`)return l();if(e===`linux`)return u()}const f=new Set(`.png,.jpg,.jpeg,.gif,.webp,.bmp,.ico,.heic,.heif,.pdf,.txt,.md,.rtf,.csv,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.key,.pages,.numbers,.odt,.ods,.odp,.json,.xml,.yaml,.yml`.split(`,`));function p(e){let t=r.extname(e).toLowerCase();return f.has(t)}function m(e){return{".png":`image/png`,".jpg":`image/jpeg`,".jpeg":`image/jpeg`,".gif":`image/gif`,".webp":`image/webp`,".bmp":`image/bmp`,".ico":`image/x-icon`,".heic":`image/heic`,".heif":`image/heif`,".txt":`text/plain`,".md":`text/markdown`,".pdf":`application/pdf`,".csv":`text/csv`,".rtf":`application/rtf`,".doc":`application/msword`,".docx":`application/vnd.openxmlformats-officedocument.wordprocessingml.document`,".xls":`application/vnd.ms-excel`,".xlsx":`application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`,".ppt":`application/vnd.ms-powerpoint`,".pptx":`application/vnd.openxmlformats-officedocument.presentationml.presentation`,".key":`application/vnd.apple.keynote`,".pages":`application/vnd.apple.pages`,".numbers":`application/vnd.apple.numbers`,".odt":`application/vnd.oasis.opendocument.text`,".ods":`application/vnd.oasis.opendocument.spreadsheet`,".odp":`application/vnd.oasis.opendocument.presentation`,".json":`application/json`,".xml":`application/xml`,".yaml":`text/yaml`,".yml":`text/yaml`}[r.extname(e).toLowerCase()]||`application/octet-stream`}function h(e){let t=e.trim();return t.startsWith(`file://`)&&(t=decodeURIComponent(t.slice(7))),(t.startsWith(`'`)&&t.endsWith(`'`)||t.startsWith(`"`)&&t.endsWith(`"`))&&(t=t.slice(1,-1)),t=t.replace(/\\(.)/g,`$1`),t}async function g(e){let t=h(e);if(/^https?:\/\//.test(t))return!1;try{return await a.access(t),!0}catch{return!1}}var _=class extends Error{problem;filePath;constructor(e,t){super(`${e}: ${t}`),this.problem=e,this.filePath=t,this.name=`LocalFileError`}};function v(e){return e instanceof Error&&`code`in e}function y(e){if(v(e)){if(e.code===`ENOENT`||e.code===`ENOTDIR`)return`missing`;if(e.code===`EISDIR`)return`not_a_file`}return`unreadable`}async function b(e){try{if(!(await t.stat(e)).isFile())throw new _(`not_a_file`,e);return{buffer:await t.readFile(e),filename:r.basename(e),mimeType:m(e)}}catch(t){throw t instanceof _?t:new _(y(t),e)}}export{h as a,g as i,b as n,d as o,p as r,_ as t};
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ var __entrydeskNodeFloor = 24;
3
+ if (parseInt(process.versions.node, 10) < __entrydeskNodeFloor) {
4
+ process.stderr.write(
5
+ 'entrydesk: Node.js ' + __entrydeskNodeFloor + ' or newer is required, but this is Node ' + process.versions.node + '.\n' +
6
+ 'Upgrade Node (https://nodejs.org/en/download), then reinstall @entrydesk/cli.\n'
7
+ );
8
+ process.exit(1);
9
+ }
10
+ import{K as e}from"./profile-storage-BVSyHoBn.js";function t(e){return`$${e.toFixed(2)}`}function n(t){return`$${e(t)}`}function r(e){if(e==null)return`—`;let t=Math.round(e),n=Math.floor(t/3600),r=Math.floor(t%3600/60),i=t%60,a=String(r).padStart(2,`0`),o=String(i).padStart(2,`0`);return n>0?`${n}:${a}:${o}`:`${r}:${o}`}function i(e){if(!e)return``;let t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleString()}function a(e,t){return`${e} ${t}${e===1?``:`s`}`}export{a,t as i,n,i as r,r as t};