@entrydesk/cli 2.0.0 → 2.1.0-beta.1

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 (78) hide show
  1. package/README.md +279 -0
  2. package/dist/add-Lh_kLR85.js +2 -0
  3. package/dist/agents-CLcXSbBp.js +2 -0
  4. package/dist/billing-DHrYi0SU.js +2 -0
  5. package/dist/{budget-DcULs51p.js → budget-D_DDPBBb.js} +1 -1
  6. package/dist/build-task-request-config-Y9X2h9Ia.js +2 -0
  7. package/dist/commands-3Yqb38G_.js +2 -0
  8. package/dist/commands-CdnyYMrx.js +2 -0
  9. package/dist/{config-CI3k8CUK.js → config-hGzOCx4u.js} +2 -2
  10. package/dist/connectors-CxzG22No.js +3 -0
  11. package/dist/file-upload-BmP4AJY0.js +16 -0
  12. package/dist/format-C3tQC6LL.js +2 -0
  13. package/dist/index.js +83 -10
  14. package/dist/instruction-CRCyBKQf.js +2 -0
  15. package/dist/{login-y8SlHgZ4.js → login-CwXjzUnO.js} +1 -1
  16. package/dist/{logout-CGGEe0it.js → logout-BYCFpaxh.js} +1 -1
  17. package/dist/{marketplace-CaIuJP0T.js → marketplace-NSEUjhXf.js} +1 -1
  18. package/dist/{mcp-Yz1qXxIb.js → mcp-B7wo_sRO.js} +2 -2
  19. package/dist/mcp-client-DMOEcmul.js +2 -0
  20. package/dist/meeting-yS83In45.js +3 -0
  21. package/dist/models-AN9cWKSj.js +3 -0
  22. package/dist/notifications-QF11-X32.js +2 -0
  23. package/dist/options-D6fCp3Q_.js +2 -0
  24. package/dist/paginate-CfIrho1f.js +2 -0
  25. package/dist/paths-C9BPsZVF.js +2 -0
  26. package/dist/{profile-1uJ5EHdo.js → profile-WtKtO0yp.js} +1 -1
  27. package/dist/profile-storage-Dv0xRb8J.js +58 -0
  28. package/dist/project-BhPYRsaZ.js +2 -0
  29. package/dist/project-context-Cc_Js6n4.js +2 -0
  30. package/dist/project-governance-C7rl6gDW.js +2 -0
  31. package/dist/project-sources-CzylP6oS.js +2 -0
  32. package/dist/project-sources-write-6cBfdUfV.js +2 -0
  33. package/dist/project-tasks-DaGBt4Cp.js +2 -0
  34. package/dist/push-Ce79oiu0.js +2 -0
  35. package/dist/{recordings-C0Ij3tfP.js → recordings-DoExjM1F.js} +1 -1
  36. package/dist/remove-bHAmCTdf.js +2 -0
  37. package/dist/resolve-f238uD6C.js +6 -0
  38. package/dist/schedules-tDaIGaad.js +21 -0
  39. package/dist/{skills-16msznfK.js → skills-CDd-emMc.js} +1 -1
  40. package/dist/status-CDMSNVD8.js +2 -0
  41. package/dist/{status-D6ebFbsw.js → status-gK3MA1oe.js} +1 -1
  42. package/dist/stdin-DzzLUF6W.js +2 -0
  43. package/dist/task-CHnFR-Zp.js +103 -0
  44. package/dist/tasks-D4RIFT8Y.js +14 -0
  45. package/dist/tasks-acCatE6n.js +2 -0
  46. package/dist/{tool-3NEPlGNR.js → tool-BEivzspP.js} +1 -1
  47. package/dist/update-CJlVgq8V.js +2 -0
  48. package/dist/usage-DOI9sowA.js +3 -0
  49. package/dist/{usage-audit-e6kpW0LZ.js → usage-audit-1GZx4VBG.js} +3 -3
  50. package/dist/version-C37EX5li.js +2 -0
  51. package/dist/workflow-DhomAltH.js +6 -0
  52. package/dist/{workspaces-BQiFZ5pV.js → workspaces-D0VOrP2A.js} +1 -1
  53. package/package.json +8 -4
  54. package/dist/add-CDlJBikf.js +0 -2
  55. package/dist/agents-vivPBsWo.js +0 -2
  56. package/dist/billing-BietwbvI.js +0 -2
  57. package/dist/build-task-request-config-Bbffa_rv.js +0 -2
  58. package/dist/commands-BCLJEd6x.js +0 -2
  59. package/dist/commands-CpuinJar.js +0 -2
  60. package/dist/connectors-CbkKDKQQ.js +0 -3
  61. package/dist/custom-connector-CxGNx65S.js +0 -2
  62. package/dist/format-BNEUX5Xv.js +0 -2
  63. package/dist/mcp-client-DdryEToX.js +0 -2
  64. package/dist/meeting-CWv3iUU6.js +0 -3
  65. package/dist/models-DFEIoTPH.js +0 -2
  66. package/dist/notifications-CBLIBZtc.js +0 -2
  67. package/dist/paths-Cqjaa_lJ.js +0 -2
  68. package/dist/profile-storage-DYUIMuP0.js +0 -72
  69. package/dist/push-BBY3QXxO.js +0 -2
  70. package/dist/remove-D-UQJ0IM.js +0 -2
  71. package/dist/schedules-CFjtG3p4.js +0 -21
  72. package/dist/status-kRSNf0Ap.js +0 -2
  73. package/dist/task-DKK82ixE.js +0 -115
  74. package/dist/tasks-DX7CQir8.js +0 -14
  75. package/dist/update-DhNwkiwD.js +0 -2
  76. package/dist/usage-050zvE6Q.js +0 -3
  77. package/dist/version-orM51hu_.js +0 -2
  78. package/dist/workflow-DHTrGTRn.js +0 -6
package/README.md CHANGED
@@ -82,6 +82,285 @@ entrydesk tasks
82
82
  entrydesk tasks 1
83
83
  ```
84
84
 
85
+ ## Project
86
+
87
+ Projects group **sources** (the files and links you put in one), the **tasks**
88
+ that belong to it, and the **assets** those tasks produce. Its **instruction**
89
+ is the standing brief every task in the project starts from.
90
+
91
+ ```bash
92
+ entrydesk project # List projects you belong to
93
+ entrydesk project list --filter mine # all | mine | shared
94
+ entrydesk project get 1 # …by its number in that list
95
+ entrydesk project get <projectId> # …or by id
96
+ entrydesk project instruction 1 # Plain text, ready to pipe
97
+ entrydesk project edit 1 --name "Q4 Launch" --description "Launch coordination"
98
+ ```
99
+
100
+ A `<project>` number always means a position in a **plain** `project list`. A
101
+ `--filter` or `--all` listing renumbers from 1, so those print no position
102
+ column — pass an id there.
103
+
104
+ The number is resolved against the listing as it stands at that moment, not
105
+ against the one you last looked at, so a project created in between shifts the
106
+ positions — the same trade-off `entrydesk tasks <n>` makes. Numbers are for
107
+ typing by hand; scripts, and anything that has to keep pointing at one project,
108
+ should use the id.
109
+
110
+ The instruction is plain text on stdout with nothing around it, so it pipes and
111
+ redirects cleanly, and a project without one prints nothing and exits 0:
112
+
113
+ ```bash
114
+ entrydesk project instruction 1 > brief.md
115
+ cat brief.md | entrydesk project edit 1 --instruction-file -
116
+ entrydesk project edit 1 --clear-instruction
117
+ ```
118
+
119
+ `--instruction`, `--instruction-file` and `--clear-instruction` are mutually
120
+ exclusive. `--instruction-file -` reads stdin, and stores exactly what it is
121
+ given — leading and trailing whitespace included, the same as a file path — so
122
+ the round-trip above returns the instruction unchanged.
123
+
124
+ Project text that another member wrote (names, descriptions, the instruction as
125
+ `project get` renders it) has terminal control characters stripped before it is
126
+ displayed. `project instruction` writes the raw bytes when its output is piped
127
+ or redirected, and filters them only when it is writing to your terminal.
128
+
129
+ These commands read and edit the project itself; none of them talks to the AI.
130
+
131
+ To work with the AI inside a project, pass `--project` to the task commands.
132
+ `task --project` creates its task in the project, so it starts from the project
133
+ instruction and the AI answers as it always does; `entrydesk project note` is
134
+ the other path, filing a work note with no AI reply. `tasks --project` lists or
135
+ searches only the tasks you can see in that project:
136
+
137
+ ```bash
138
+ entrydesk task --project 2 -m "List the open questions in the spec"
139
+ entrydesk task --project 2 -i # Interactive, same project
140
+ entrydesk tasks --project 2 # Tasks you can see in project 2
141
+ entrydesk tasks --project 2 -q "deploy" # …searched within it
142
+ ```
143
+
144
+ `--project` also decides what the numbers mean. `entrydesk tasks` and a bare
145
+ `-c <n>` never list a project's tasks, so inside a project both count down
146
+ `entrydesk tasks --project <project>` instead:
147
+
148
+ ```bash
149
+ entrydesk tasks --project 2 # 1 is the newest task in project 2
150
+ entrydesk task --project 2 -c 1 -m "Follow up"
151
+ ```
152
+
153
+ The same holds for `/tasks` in an interactive `--project` session: it offers
154
+ that project's tasks only, so picking one cannot move the session out of it.
155
+
156
+ A piped `task` gets both halves of what you gave it: `-m` is your instruction
157
+ and stdin is the material to work on, so this reaches the AI as one turn
158
+ carrying the file and the request.
159
+
160
+ ```bash
161
+ entrydesk project context-read 2 file <id> \
162
+ | entrydesk task --project 2 -m "Turn this into a checklist"
163
+ ```
164
+
165
+ stdin here is content from elsewhere, so it is handed over as material to read
166
+ rather than as instructions to follow, and anything inside it that looks like a
167
+ command is not one. Piped stdin on its own is still the message itself, exactly
168
+ as before, and `-i` never reads stdin.
169
+
170
+ A piped stdin is always read to its end, with or without `-m`, so a producer
171
+ that takes seconds to answer is waited for instead of being dropped:
172
+
173
+ ```bash
174
+ curl -s https://example.com/spec.md | entrydesk task --project 2 -m "列出待辦"
175
+ ```
176
+
177
+ The cost is the other side of the same rule: a command spawned with an stdin it
178
+ inherited but never sends on waits for that pipe to close. Close it explicitly
179
+ when you do not mean to send anything — `entrydesk task -m "…" </dev/null`.
180
+
181
+ ### Work notes
182
+
183
+ A work note is the other direction: writing down what you did without asking
184
+ the AI anything. `project note` creates a task under your name in the project,
185
+ private until you share it, and no AI reply is triggered. The content comes
186
+ from `-m`, then `-f`, then stdin — the first one given wins, and all three are
187
+ equivalent:
188
+
189
+ ```bash
190
+ entrydesk project note 2 -m "Shipped the retry fix"
191
+ entrydesk project note 2 -f ./summary.md
192
+ git log -1 | entrydesk project note 2 --title "Fixed the login race"
193
+ ```
194
+
195
+ It prints the new task's id and a Hub link; `--json` returns
196
+ `{ "taskId", "projectId", "url" }`. Reach for `task --project` above whenever
197
+ you want the AI to answer instead.
198
+
199
+ ### Tasks in a project
200
+
201
+ `project tasks` is the project's own listing — the same tasks `tasks --project`
202
+ shows, printed with their ids so they can be handed to the commands below. The
203
+ other three do what the Hub's task menu does: move a task of yours in or out,
204
+ and share it inside the project. Only the task's owner can do any of this; the
205
+ API refuses everyone else with `Task not found`, the same answer as for a task
206
+ that does not exist.
207
+
208
+ ```bash
209
+ entrydesk project tasks 1 # Tasks you can see in project 1
210
+ entrydesk project tasks 1 -q "deploy" # …searched within it
211
+ entrydesk project task-add 1 <taskId> # Move your task in
212
+ entrydesk project task-add 1 <taskId> --confirm-asset-sharing
213
+ entrydesk project task-remove 1 <taskId> # Move it out; its assets stay
214
+ entrydesk project task-share 1 <taskId> --add-user <userId>
215
+ entrydesk project task-share 1 <taskId> --remove-user <userId>
216
+ entrydesk project task-share 1 <taskId> --visibility project
217
+ entrydesk project task-share 1 <taskId> --visibility self
218
+ ```
219
+
220
+ Moving a task in also files the assets it produced with the project, where every
221
+ member can view and use them. When the task carries assets the project does not
222
+ hold yet, `task-add` stops and says so instead of sharing them on its own —
223
+ re-run it with `--confirm-asset-sharing` to go ahead. Under `--json` that
224
+ refusal is the API's own `asset_sharing_confirmation_required` code on stderr.
225
+ Moving a task out leaves its assets in the project along with their version
226
+ history; only the task moves.
227
+
228
+ `task-share` does one thing per call and never prompts. `--add-user` and
229
+ `--remove-user` name one project member by id (`project get <project> --json`
230
+ lists the members with theirs); `--visibility project` opens the task to every
231
+ member and `--visibility self` closes it again, keeping whoever you named. The
232
+ three flags are mutually exclusive and each needs its value; with none of them
233
+ the command prints the usage and exits 1. A task has to be in the project you
234
+ name — `task-share` and `task-remove` refuse one that is elsewhere rather than
235
+ acting on the project it is actually in.
236
+
237
+ `project tasks` reads with `tasks:read`; the three that write need
238
+ `tasks:write`, and `task-remove` and `task-share` also read the task first with
239
+ `tasks:read`. A project you are not a member of answers `Project not found`
240
+ from all four.
241
+
242
+ ### Sources and context
243
+
244
+ **Sources** are the files and links you put in a project — the same list the
245
+ Hub's Sources tab shows, with each one's retrieval description and, for a link,
246
+ whether its snapshot is `pending`, `ready` or `failed`. **Context** is
247
+ everything the AI knows in the project, so searching and reading across the
248
+ tasks you can see _and_ those sources hangs off that word instead:
249
+
250
+ ```bash
251
+ entrydesk project sources 1
252
+ entrydesk project context-search 1 "login race" --type task --limit 5
253
+ entrydesk project context-read 1 file <fileId> # A file's stored text
254
+ entrydesk project context-read 1 task <taskId> # A task's summary
255
+ entrydesk project context-read 1 task <taskId> --full # …its whole history
256
+ ```
257
+
258
+ `context-search` looks across tasks and sources at once; `--type task`, `--type
259
+ file` or `--type link` narrows it to one kind. Assets are not on this surface —
260
+ view them in the Hub — and asking for one fails the same way every other
261
+ project command fails, JSON on stderr included.
262
+
263
+ `sources` lists what the API serves in one shot, which is the newest 200 files
264
+ and the newest 200 links. A project holding more says so on stderr, and under
265
+ `--json` the payload carries `truncated: true` beside the rows.
266
+
267
+ The `sources-*` commands maintain that list the way the Hub's Sources tab does
268
+ — upload a file, add a link, edit a description, re-fetch a link, remove one.
269
+ `sources-add` takes a local file path, or a link when the argument starts with
270
+ `http://` or `https://`; the file is uploaded and then attached to the project.
271
+ `<file|link>` and `<id>` are exactly what `project sources` prints for a row:
272
+
273
+ ```bash
274
+ entrydesk project sources-add 1 ./brief.pdf --description "The launch brief"
275
+ entrydesk project sources-add 1 https://example.com/spec
276
+ entrydesk project sources-edit 1 file <fileId> --description "Signed-off scope"
277
+ entrydesk project sources-refetch 1 <linkId> # Snapshot goes back to pending
278
+ entrydesk project sources-rm 1 link <linkId>
279
+ ```
280
+
281
+ A link starts fetching its snapshot as soon as it is added, and `sources-refetch`
282
+ starts that over, so both report it as `pending`; `project sources` shows when
283
+ it is `ready`. Re-fetching a link whose fetch is still in flight is refused
284
+ rather than queued twice. Assets are removed in the Hub, so `sources-rm` takes
285
+ only `file` or `link`. `--json` prints the source the API returned with a
286
+ `type` field beside it, and `sources-rm --json` prints `{ "type", "id",
287
+ "removed": true }`.
288
+
289
+ Uploading a file goes through the same route the task commands use, which is
290
+ declared on `tasks:write`; attaching it, and every other `sources-*` call, is
291
+ `projects:write`. A token short of either is told which one it lacks.
292
+
293
+ `context-read` writes the source's text and nothing else to stdout, so it pipes
294
+ straight into a task in the same project:
295
+
296
+ ```bash
297
+ entrydesk project context-read 1 file <fileId> \
298
+ | entrydesk task --project 1 -m "List the work this implies"
299
+ ```
300
+
301
+ Everything that is not text stays off stdout, so a pipe never carries an
302
+ explanation where the content should be: a file with no text to extract, a link
303
+ whose snapshot is still being fetched, and one whose fetch failed each print
304
+ their reason on stderr and exit non-zero. With `--json` that reason is the
305
+ `{ "status": … }` object from the API — `download` with a short-lived
306
+ `downloadUrl`, `pending`, or `failed` with the error — again on stderr.
307
+
308
+ A read that is cut short says so on stderr too, never on stdout, and names the
309
+ `--offset` to resume from where the source can be paged. With `--json` the same
310
+ facts are the `truncated` and `nextOffset` fields of the object on stdout.
311
+ `--offset` implies `--full`, since a summary is not paged and an offset against
312
+ one means nothing — resuming needs only the offset the previous read reported.
313
+
314
+ Both depths are a task's: a file or a link snapshot has one, and the server
315
+ serves its stored text up to a fixed cap whether or not you pass `--full`. That
316
+ is why a truncated one reports no offset to resume from — it says it was cut
317
+ short and there is nothing further to ask for.
318
+
319
+ ### Governance
320
+
321
+ A project can be created, deleted and staffed without opening the Hub, under
322
+ the same rules the Hub applies. Whoever creates it is its owner:
323
+
324
+ ```bash
325
+ entrydesk project create --name "Q4 Launch" --description "Launch coordination"
326
+ cat brief.md | entrydesk project create --name "Q4 Launch" --instruction-file -
327
+ entrydesk project members 1 # Each member, role and id
328
+ entrydesk project member-add 1 <userId> # Takes effect at once
329
+ entrydesk project member-role 1 <userId> --role owner
330
+ entrydesk project member-remove 1 <userId> # Your own id leaves the project
331
+ entrydesk project delete 1 # Lists what goes, then asks
332
+ entrydesk project delete 1 -y # No prompt
333
+ ```
334
+
335
+ `create` prints the new id and its Hub address, and with `--json` the payload
336
+ carries both. `--instruction` and `--instruction-file` are the same options
337
+ `edit` takes, with the same limit.
338
+
339
+ Only an owner can delete a project, add or remove someone else, or change a
340
+ role; a member can leave. A user id is the UUID `project members` prints beside
341
+ each member — a workspace member who is not in the project yet is found in the
342
+ Hub's member picker. The last owner cannot leave or step down to member: promote
343
+ someone else first. Each refusal comes back as its own message, and with
344
+ `--json` under its own code (`project_owner_required`,
345
+ `project_last_owner_required`, `project_member_already_exists`,
346
+ `project_invitee_not_in_workspace`, `project_member_not_found`). A project you
347
+ are not in is `Project not found` for every one of these commands, exactly as
348
+ it is for `get`.
349
+
350
+ Deleting a project detaches its tasks, which return to their owners' main
351
+ lists, and deletes its sources, its assets and every version in their history.
352
+ Without `-y` the command prints those effects for the project in question and
353
+ waits for a `y`; with no terminal to ask on it refuses instead (exit code 1,
354
+ JSON on stderr under `--json`), so a stray id in a script cannot delete
355
+ anything.
356
+
357
+ A project command fails in one of three ways, each with its own message: the
358
+ server has projects turned off, your token predates project support (run
359
+ `entrydesk login` again, or issue a PAT with `projects:read`, `projects:write`,
360
+ `tasks:read` and `tasks:write`), or the project is not one you can see —
361
+ reported as `Project not found` whether it is someone else's or does not exist.
362
+ With `--json` the error is JSON on stderr and the exit code is non-zero.
363
+
85
364
  ## Tools
86
365
 
87
366
  ```bash
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import{E as e}from"./profile-storage-Dv0xRb8J.js";import{a as t,d as n,f as r,g as i,i as a,r as o}from"./paths-C9BPsZVF.js";import{t as s}from"./hash-Ddmw8YE4.js";import{r as c}from"./installer-iaoPJQn3.js";import{t as l}from"./remote-nEFOyIM2.js";import u from"node:fs";import d from"node:os";import f from"node:path";import p from"cross-spawn";function m(e,t){let n=f.dirname(e);u.mkdirSync(n,{recursive:!0});let r=u.mkdtempSync(f.join(n,`.${f.basename(e)}.tmp-`)),i=f.join(r,`next`),a=f.join(r,`prev`);u.mkdirSync(i,{recursive:!0});let o=!1;try{t(i),u.existsSync(e)&&(u.renameSync(e,a),o=!0),u.renameSync(i,e)}catch(t){throw o&&!u.existsSync(e)&&u.renameSync(a,e),t}finally{u.rmSync(r,{recursive:!0,force:!0})}}const h=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/iu,g=/^([\w.-]+)\/([\w.-]+)(?:\/(.+))?$/u;function _(e){return e===`~`?d.homedir():e.startsWith(`~/`)||e.startsWith(`~\\`)?f.join(d.homedir(),e.slice(2)):e}function v(e){return e.startsWith(`./`)||e.startsWith(`../`)||e.startsWith(`/`)||e.startsWith(`~`)||e.startsWith(`.\\`)||/^[a-zA-Z]:[\\/]/u.test(e)}function y(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 b(e){let t=e.trim();if(v(t))return{type:`local`,path:f.resolve(_(t))};if(t.startsWith(`ed:`)){let e=t.slice(3);return{type:`entrydesk`,ref:e,isId:h.test(e)}}if(h.test(t))return{type:`entrydesk`,ref:t,isId:!0};if(t.startsWith(`git@`)||t.endsWith(`.git`))return{type:`git`,url:t};let n=y(t);if(n)return n;if(/^https?:\/\//u.test(t))return{type:`git`,url:t};let r=g.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 x(e){return e.type===`github`?`github`:e.type}const S=new Set([`.git`,`node_modules`,`__pycache__`,`.DS_Store`,`.entrydesk`]);function C(e,t){if(!u.existsSync(f.join(e,`SKILL.md`)))throw Error(`No SKILL.md found at ${e}`);let n=u.realpathSync(e);if(n===(u.existsSync(t)?u.realpathSync(t):f.resolve(t)))return;let r=u.mkdtempSync(f.join(d.tmpdir(),`ed-local-skill-`)),i=f.join(r,`skill`);try{u.cpSync(n,i,{recursive:!0,filter:e=>!S.has(f.basename(e))}),m(t,e=>{u.cpSync(i,e,{recursive:!0})})}finally{u.rmSync(r,{recursive:!0,force:!0})}}function w(e){try{let t=u.readFileSync(f.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 f.basename(e)}async function T(e,t){let{default:n}=await import(`adm-zip`),r=new n(e);m(t,e=>{let t=f.resolve(e)+f.sep;for(let n of r.getEntries()){if(n.isDirectory)continue;let r=f.resolve(e,n.entryName);if(!r.startsWith(t))throw Error(`Zip entry contains path traversal: ${n.entryName}`);u.mkdirSync(f.dirname(r),{recursive:!0}),u.writeFileSync(r,n.getData())}})}async function E(e,t){if(t.isId)return t.ref;let n=(await l(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 D(e,t,n){let r=u.mkdtempSync(f.join(d.tmpdir(),`ed-npx-skills-`)),i=[`-y`,`skills@1.5.12`,`add`,e,`--copy`,`--yes`];try{let e=p.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 u.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=f.join(r,`.agents`,`skills`);if(!u.existsSync(a))throw u.rmSync(r,{recursive:!0,force:!0}),Error(`npx skills produced no skills under ${a}`);let o=u.readdirSync(a,{withFileTypes:!0}).filter(e=>e.isDirectory());if(o.length===0)throw u.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?f.basename(t.subpath):void 0,n=e?o.find(t=>t.name===e):void 0;if(!n)throw u.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:f.join(a,s.name),tmpRoot:r}}async function O(l,d,f){let p=b(l),m=!!d.global,h=a(m,f.workspaceId),g=h.rootDir,_={...f,workspaceId:h.workspaceId};if(!h.linked){let i={workspaceId:f.workspaceId,apiUrl:e()};t(),m?n(i):r(process.cwd(),i)}let v,y,S;if(p.type===`entrydesk`){y=await E(_,p);let e=await _.client.downloadSkillCurrent(_.accessToken,_.workspaceId,y);v=e.name,S=o(g,v);let t=await fetch(e.url);if(!t.ok)throw Error(`Failed to download ${v}: ${t.status}`);await T(Buffer.from(await t.arrayBuffer()),S)}else if(p.type===`local`)v=w(p.path),S=o(g,v),C(p.path,S);else{let{dir:e,tmpRoot:t}=D(l,p,!!d.json);try{v=w(e),S=o(g,v),C(e,S)}finally{u.rmSync(t,{recursive:!0,force:!0})}}let O=s(S),k={source:l,sourceType:x(p),skillId:y,localHash:O,lastPulledHash:p.type===`entrydesk`?O:``,mode:`symlink`,...p.type===`github`?{sourceUrl:p.url,ref:p.gitRef,subpath:p.subpath}:{},...p.type===`git`?{sourceUrl:p.url}:{}};i(g,v,k);let A=c(S,v,g,`symlink`,d.agent);d.json?console.info(JSON.stringify({name:v,sourceType:x(p),hash:O},null,2)):console.info(`✓ added ${v} (${p.type}, ${O.slice(0,12)}) → agents: ${A.map(e=>e.agentId).join(`, `)}`)}export{O as runSkillsAdd};
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import{At as e,Dt as t,F as n,b as r,it as i,jt as a,u as o}from"./profile-storage-Dv0xRb8J.js";function s(e){return e?a([...new Set(e)]):t}function c(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 l(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 u(t){if(console.log(`${t.name}\n`),console.log(` ID: ${t.id}`),t.visibility&&console.log(` Visibility: ${t.visibility}`),t.model&&console.log(` Model: ${t.model.name}`),t.author&&console.log(` Author: ${t.author.name}${t.author.isMe?` (you)`:``}`),t.description&&console.log(` Description: ${t.description}`),t.capabilities){let n=e(t.capabilities).map(e=>i(e));n.length>0&&console.log(` Capabilities: ${n.join(`, `)}`)}t.connectors&&t.connectors.length>0&&console.log(` Connectors: ${t.connectors.map(e=>e.name).join(`, `)}`),t.tools&&t.tools.length>0&&console.log(` Tools: ${t.tools.length}`),t.conversationStarters&&t.conversationStarters.length>0&&console.log(` Starters: ${t.conversationStarters.length}`),t.systemPrompt&&console.log(`\n System prompt:\n${t.systemPrompt}`)}function d(e){let t=n(e);if(console.log(`User grants (${t.length}):`),t.length===0){console.log(` (none)`);return}for(let e of t)console.log(` - ${e.user.name} <${e.user.email}> · ${e.role}`),console.log(` ID: ${e.userId}`)}async function f(e){let{accessToken:t,workspaceId:n}=await o(),i=new r;if(e.mine){let r=[],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,n,{limit:e.limit,nextKey:a});if(r.push(...s.agents),a=s.nextKey,!e.all||!a)break}if(e.json){console.log(JSON.stringify({agents:r,nextKey:a}));return}if(r.length===0){console.log("You own no agents in this workspace. Create one with `entrydesk agents create --name <name> …`, or browse `entrydesk marketplace`.");return}l(r),!e.all&&a&&console.log(`Next page: --next-key ${a}`);return}if(e.all){let r=[],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,n,{limit:e.limit??100,nextKey:a});if(r.push(...s.agents),a=s.nextKey,!a)break}if(e.json){console.log(JSON.stringify({agents:r}));return}if(r.length===0){console.log("No agents in this workspace yet. Create one with `entrydesk agents create`, or browse `entrydesk marketplace`.");return}c(r);return}let{agents:a,nextKey:s}=await i.getAgents(t,n,{limit:e.limit,nextKey:e.nextKey});if(e.json){console.log(JSON.stringify({agents:a,nextKey:s}));return}if(a.length===0){console.log("No agents in this workspace yet. Create one with `entrydesk agents create`, or browse `entrydesk marketplace`.");return}c(a),s&&console.log(`Next page: --next-key ${s}`)}async function p(e,t){let{accessToken:n,workspaceId:i}=await o(),a=await new r().getAgent(n,i,e);if(t.json){console.log(JSON.stringify(a));return}u(a)}async function m(e){let{accessToken:t,workspaceId:n}=await o(),i=await new r().createAgent(t,n,{name:e.name,description:e.description,systemPrompt:e.systemPrompt,modelId:e.modelId,connectorIds:e.connectorIds??[],capabilities:s(e.capabilities),conversationStarters:e.conversationStarters??[],tools:e.tools,iconId:e.iconId});if(e.json){console.log(JSON.stringify(i));return}console.log(`Created agent: ${i.name}`),console.log(` ID: ${i.id}`)}async function h(e,t){let{accessToken:n,workspaceId:i}=await o(),a=new r,c=await a.getAgent(n,i,e),l={name:t.name??c.name,description:t.description??c.description,systemPrompt:t.systemPrompt??c.systemPrompt??``,modelId:t.modelId??c.model?.id??``,connectorIds:t.connectorIds??c.connectors?.map(e=>e.id)??[],capabilities:t.capabilities?s(t.capabilities):c.capabilities??{},conversationStarters:t.conversationStarters??c.conversationStarters??[],tools:t.tools??c.tools??[],iconId:t.iconId??c.iconId};await a.updateAgent(n,i,e,l),console.log(`Updated agent: ${e}`)}async function g(e){let{accessToken:t,workspaceId:n}=await o();await new r().deleteAgent(t,n,e),console.log(`Deleted agent: ${e}`)}async function _(e,t){let{accessToken:n,workspaceId:i}=await o();if(await new r().publishAgent(n,i,e),t.json){console.log(JSON.stringify({id:e,published:!0}));return}console.log(`Published agent to the workspace: ${e}`)}async function v(e,t){let{accessToken:n,workspaceId:i}=await o(),a=new r;if(t.addUser){let r=await a.upsertAgentGrant(n,i,e,t.addUser,t.role);if(t.json){console.log(JSON.stringify(r));return}console.log(`Granted ${t.role} to user ${t.addUser}`);return}if(t.removeUser){if(await a.removeAgentGrant(n,i,e,t.removeUser),t.json){console.log(JSON.stringify({userId:t.removeUser,removed:!0}));return}console.log(`Revoked access for user ${t.removeUser}`);return}let s=await a.getAgentGrants(n,i,e);if(t.json){console.log(JSON.stringify(s));return}d(s)}export{m as createAgent,g as deleteAgent,f as listAgents,_ as publishAgent,v as shareAgent,p as showAgent,h as updateAgent};
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import{b as e,u as t,v as n}from"./profile-storage-Dv0xRb8J.js";import{r}from"./format-C3tQC6LL.js";import{t as i}from"./paginate-CfIrho1f.js";function a(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} · ~${r(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: ${r(n.balanceUsd)} extra usage`),console.log(` Spent: ${r(n.currentSpentUsd)} this period`),n.monthlyExtraUsageLimitUsd!=null&&console.log(` Limit: ${r(n.monthlyExtraUsageLimitUsd)} / month`)}function o(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} · ${r(t.totalUsd)}`),t.hostedInvoiceUrl&&console.log(` ${t.hostedInvoiceUrl}`),console.log(` ID: ${t.id}`),console.log(``)}}async function s(){return n()&&(console.error("Billing requires an interactive login. A workspace PAT (ENTRYDESK_TOKEN) cannot read billing — run `entrydesk login`."),process.exit(1)),t()}async function c(t){let{accessToken:n,workspaceId:r}=await s(),i=await new e().getBillingOverview(n,r);if(t.json){console.log(JSON.stringify(i));return}a(i)}async function l(t){let{accessToken:n,workspaceId:r}=await s(),a=new e;if(t.all){let e=await i(async e=>{let i=await a.getBillingInvoices(n,r,{limit:t.limit??20,nextKey:e});return{items:i.invoices,nextKey:i.nextKey}});if(t.json){console.log(JSON.stringify({invoices:e}));return}if(e.length===0){console.log(`No invoices.`);return}o(e);return}let{invoices:c,nextKey:l}=await a.getBillingInvoices(n,r,{limit:t.limit,nextKey:t.nextKey});if(t.json){console.log(JSON.stringify({invoices:c,nextKey:l}));return}if(c.length===0){console.log(`No invoices.`);return}o(c),l&&console.log(`Next page: --next-key ${l}`)}export{l as listInvoices,c as showBillingStatus};
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import{b as e,l as t}from"./profile-storage-DYUIMuP0.js";async function n(n){let{accessToken:r,workspaceId:i}=await t(),a=await new e().getBudget(r,i);if(n.json){console.log(JSON.stringify(a));return}if(a.budget===null){console.log(`No budget set for this workspace.`);return}console.log(`Current workspace budget: $${a.budget}`)}async function r(n,r){let{accessToken:i,workspaceId:a}=await t(),o=new e;if(await o.updateBudget(i,a,n),r.json){console.log(JSON.stringify(await o.getBudget(i,a)));return}console.log(`Budget updated: $${n}`)}async function i(n){let{accessToken:r,workspaceId:i}=await t(),a=new e;if(await a.updateBudget(r,i,null),n.json){console.log(JSON.stringify(await a.getBudget(r,i)));return}console.log(`Budget cleared.`)}export{i as clearBudget,r as setBudget,n as showBudget};
2
+ import{b as e,u as t}from"./profile-storage-Dv0xRb8J.js";async function n(n){let{accessToken:r,workspaceId:i}=await t(),a=await new e().getBudget(r,i);if(n.json){console.log(JSON.stringify(a));return}if(a.budget===null){console.log(`No budget set for this workspace.`);return}console.log(`Current workspace budget: $${a.budget}`)}async function r(n,r){let{accessToken:i,workspaceId:a}=await t(),o=new e;if(await o.updateBudget(i,a,n),r.json){console.log(JSON.stringify(await o.getBudget(i,a)));return}console.log(`Budget updated: $${n}`)}async function i(n){let{accessToken:r,workspaceId:i}=await t(),a=new e;if(await a.updateBudget(r,i,null),n.json){console.log(JSON.stringify(await a.getBudget(r,i)));return}console.log(`Budget cleared.`)}export{i as clearBudget,r as setBudget,n as showBudget};
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import{nt as e,ot as t,rt as n,st as r}from"./profile-storage-Dv0xRb8J.js";function i({allowedTools:e,disallowedTools:n}){if(!(!e?.length&&!n?.length))return[...r(e?.map(e=>({toolName:e,policy:t.ALWAYS_ALLOW})),n?.map(e=>({toolName:e,policy:t.BLOCK})))].map(([e,t])=>({toolName:e,policy:t}))}function a({agentId:t,model:r,projectId:i,connectorIds:a,clientTools:o,clientToolSystemPrompt:s,toolApprovalMode:c,toolPolicies:l}){return{...i?{projectId:i}:{},...t?{agentId:t}:{...r?{model:r}:{},...a?.length?{connectorIds:a}:{}},...o?{clientTools:n(o,e.DIRECT)}:{},...s?{clientToolSystemPrompt:s}:{},...c?{toolApprovalMode:c}:{},...l?.length?{toolPolicies:l}:{}}}export{i as n,a as t};
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import{E as e}from"./profile-storage-Dv0xRb8J.js";import{a as t,c as n,d as r,f as i,g as a,i as o,l as s,m as c,o as l,r as u,s as d,u as f}from"./paths-C9BPsZVF.js";import{t as p}from"./hash-Ddmw8YE4.js";import{r as m}from"./installer-iaoPJQn3.js";import h from"node:path";import g from"node:fs/promises";const _=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/iu;function v(a,o,s){let c=a&&_.test(a)?a:s.workspaceId,l={workspaceId:c,apiUrl:e()};if(t(),o.global)r(l),console.info(`Linked ${d()} → workspace ${c}`);else{let e=process.cwd();i(e,l),console.info(`Linked ${n(e)} → workspace ${c}`)}}function y(e){if(e.global){s()?console.info(`Unlinked ${d()}`):console.info(`No global link found.`);return}let t=l(process.cwd());t&&f(t)?console.info(`Unlinked ${n(t)}`):console.info(`No project link found.`)}async function b(e,t,n,r,i){let o=n.skillId;if(!o){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}`);o=r.id}let{url:s,name:c}=await e.client.downloadSkillCurrent(e.accessToken,e.workspaceId,o),l=await fetch(s);if(!l.ok)throw Error(`Failed to download ${c}: ${l.status}`);let d=Buffer.from(await l.arrayBuffer()),f=u(t,c);await g.rm(f,{recursive:!0,force:!0}),await g.mkdir(f,{recursive:!0});let{default:_}=await import(`adm-zip`),v=h.resolve(f)+h.sep;for(let e of new _(d).getEntries()){if(e.isDirectory)continue;let t=h.resolve(f,e.entryName);if(!t.startsWith(v))throw Error(`Zip entry contains path traversal: ${e.entryName}`);await g.mkdir(h.dirname(t),{recursive:!0}),await g.writeFile(t,e.getData())}let y=p(f);a(t,c,{source:o,sourceType:`entrydesk`,skillId:o,localHash:y,lastPulledHash:y,mode:`symlink`});let b=m(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 x(e,t,n){let{rootDir:r,workspaceId:i}=o(!!t.global,n.workspaceId),a={...n,workspaceId:i},s=!!t.json,l=[];if(e)l.push(_.test(e)?{skillId:e}:{name:e});else{let e=c(r).skills;for(let[t,n]of Object.entries(e))l.push({skillId:n.skillId,name:t});if(l.length===0){console.info(`Nothing to pull — no tracked skills. Try: entrydesk skills pull <name>`);return}}let u=[];for(let e of l)u.push(await b(a,r,e,s,t.agent));s&&console.info(JSON.stringify(u,null,2))}export{x as n,y as r,v as t};
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import{r as e}from"./commands-3Yqb38G_.js";export{e as runSkillsUnlink};
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import{D as e,O as t,t as n}from"./profile-storage-DYUIMuP0.js";function r(e){try{let{pathname:t}=new URL(e);return t.replace(/\/+$/u,``).endsWith(`/api`)}catch{return!1}}function i(r){let i=t.getAll();if(r.json){console.log(JSON.stringify(i));return}let a=Object.entries(i);if(console.log(`Profile: ${n.getEffectiveProfileName()}`),a.length===0){console.log(`No configuration set.`),console.log(`Available keys: ${e.join(`, `)}`);return}console.log(`Configuration:
3
- `);for(let[e,t]of a)console.log(` ${e}=${t}`);console.log(`\nAvailable keys: ${e.join(`, `)}`)}function a(e,n){let r=t.get(e);n.json?console.log(JSON.stringify({[e]:r??null})):console.log(r||`Not set`)}function o(e,i){t.set(e,i),console.log(`Set ${e}=${i}`),console.error(`(profile: ${n.getEffectiveProfileName()})`),e===`apiUrl`&&r(i)&&console.error(`Warning: ${i} looks like a web app's "/api" browser proxy path. Such proxies usually strip the Authorization header, so CLI requests will fail with 401 missing_token — prefer the API server's own URL unless you know this proxy forwards Authorization.`)}function s(e){t.unset(e),console.log(`Unset ${e}`),console.error(`(profile: ${n.getEffectiveProfileName()})`)}export{a as getConfigValue,i as listConfig,o as setConfigValue,s as unsetConfigValue};
2
+ import{M as e,j as t,t as n}from"./profile-storage-Dv0xRb8J.js";function r(e){try{let{pathname:t}=new URL(e);return t.replace(/\/+$/u,``).endsWith(`/api`)}catch{return!1}}function i(r){let i=e.getAll();if(r.json){console.log(JSON.stringify(i));return}let a=Object.entries(i);if(console.log(`Profile: ${n.getEffectiveProfileName()}`),a.length===0){console.log(`No configuration set.`),console.log(`Available keys: ${t.join(`, `)}`);return}console.log(`Configuration:
3
+ `);for(let[e,t]of a)console.log(` ${e}=${t}`);console.log(`\nAvailable keys: ${t.join(`, `)}`)}function a(t,n){let r=e.get(t);n.json?console.log(JSON.stringify({[t]:r??null})):console.log(r||`Not set`)}function o(t,i){e.set(t,i),console.log(`Set ${t}=${i}`),console.error(`(profile: ${n.getEffectiveProfileName()})`),t===`apiUrl`&&r(i)&&console.error(`Warning: ${i} looks like a web app's "/api" browser proxy path. Such proxies usually strip the Authorization header, so CLI requests will fail with 401 missing_token — prefer the API server's own URL unless you know this proxy forwards Authorization.`)}function s(t){e.unset(t),console.log(`Unset ${t}`),console.error(`(profile: ${n.getEffectiveProfileName()})`)}export{a as getConfigValue,i as listConfig,o as setConfigValue,s as unsetConfigValue};
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import{Et as e,K as t,U as n,V as r,b as i,q as a,u as o}from"./profile-storage-Dv0xRb8J.js";import{t as s}from"./confirm-BrJZbaxf.js";function c(e,n){return n?t(n)?`Next: entrydesk connectors connect ${e} --oauth`:n===`credentials`?`Next: entrydesk connectors connect ${e} --username <username> --password <password>`:`Next: entrydesk connectors connect ${e} --token <token>`:`This connector needs no authorization — there is no connect step.`}async function l(e){let{accessToken:t,workspaceId:n}=await o(),{connectors:r,nextKey:a}=await new i().getConnectors(t,n,{connectionStatus:e.all?`all`:`connected`,search:e.search,limit:e.limit,nextKey:e.nextKey});if(e.json){console.log(JSON.stringify({connectors:r,nextKey:a}));return}if(r.length===0){console.log(e.all?`No connectors found.`:`No connected connectors. Use --all to browse connectable ones.`);return}let s=e.all?`Connectors`:`Connected connectors`;console.log(`${s} (${r.length}):\n`);for(let e of r){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 u(e,t){let{accessToken:n,workspaceId:r}=await o(),{tools:a}=await new i().getConnectorTools(n,r,e);if(t.json){console.log(JSON.stringify({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 d(e,t){let{accessToken:n,workspaceId:r}=await o(),a=new i;if(t.oauth){let{url:i}=await a.getConnectorAuthUrl(n,r,e);if(t.json){console.log(JSON.stringify({url:i}));return}console.log(`Open this URL in your browser to authorize the connector:`),console.log(` ${i}`),console.log(`
3
+ After you approve, the connection is saved automatically — re-run`),console.log("`entrydesk connectors` to confirm it shows as connected.");return}let s;t.token?s={token:t.token}:t.username&&t.password?s={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,r,e,s),console.log(t.json?JSON.stringify({id:e,connected:!0}):`Connected connector ${e}.`)}async function f(t){let s=t.auth===`oauth`||t.auth===`google-iap`;s&&(!t.provider||!t.scope?.length)&&(console.error(`--auth ${t.auth} needs --provider and at least one --scope.`),process.exit(1)),!s&&(t.provider||t.scope?.length)&&(console.error(t.auth?`--provider and --scope apply only to --auth oauth and --auth google-iap, not --auth ${t.auth}.`:`--provider and --scope need --auth oauth or --auth google-iap.`),process.exit(1));let l=t.toolPrefix??a(t.name),u=n(l);if(u){let e=r[u];console.error(t.toolPrefix?`--tool-prefix ${e}.`:`The tool prefix derived from --name ("${l}") ${e}. Pass --tool-prefix explicitly.`),process.exit(1)}let{accessToken:d,workspaceId:f}=await o(),p=t.auth?{type:t.auth,...t.provider?{provider:t.provider}:{},...t.scope?.length?{scopes:t.scope}:{}}:void 0,m=await new i().createCustomConnector(d,f,{type:e.CUSTOM_REMOTE_URL,name:t.name,description:t.description,transport:t.transport,url:t.url,toolPrefix:l,...p?{authorization:p}:{}});if(t.json){console.log(JSON.stringify(m));return}console.log(`Created connector ${m.name}.`),console.log(` ID: ${m.id}`),console.log(` URL: ${m.url}`),console.log(` Tool prefix: ${m.toolPrefix}`),console.log(`\n${c(m.id,t.auth)}`)}async function p(e,t){let{accessToken:n,workspaceId:r}=await o();if(!t.yes&&(process.stdin.isTTY||(console.error(`Disconnecting connector ${e} needs confirmation. Re-run with --yes.`),process.exit(1)),!await s(`Disconnect connector ${e}?`))){console.log(`Aborted.`);return}await new i().disconnectConnector(n,r,e),console.log(t.json?JSON.stringify({id:e,disconnected:!0}):`Disconnected connector ${e}.`)}export{d as connectConnector,f as createConnector,p as disconnectConnector,u as listConnectorTools,l as listConnectors};
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+ 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=`
3
+ set imageData to the clipboard as "PNGf"
4
+ set fileRef to open for access POSIX file "${t}" with write permission
5
+ set eof fileRef to 0
6
+ write imageData to fileRef
7
+ close access fileRef
8
+ `;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`,`
9
+ Add-Type -AssemblyName System.Windows.Forms
10
+ $img = [System.Windows.Forms.Clipboard]::GetImage()
11
+ if ($img) {
12
+ $ms = New-Object System.IO.MemoryStream
13
+ $img.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png)
14
+ [System.Convert]::ToBase64String($ms.ToArray())
15
+ }
16
+ `]),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&&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&&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,2 @@
1
+ #!/usr/bin/env node
2
+ function e(e){return`$${e.toFixed(2)}`}function t(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 n(e){if(!e)return``;let t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleString()}function r(e,t){return`${e} ${t}${e===1?``:`s`}`}export{r as i,n,e as r,t};