@entrydesk/cli 2.2.0-beta.2 → 2.2.0-beta.3

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 (67) hide show
  1. package/README.md +72 -3
  2. package/dist/{add-BYupRwo_.js → add-QRCNes33.js} +1 -1
  3. package/dist/{agents-CeXkI4US.js → agents-C6_4nYx3.js} +1 -1
  4. package/dist/{billing-BeaQvLSK.js → billing-B52QpxBo.js} +1 -1
  5. package/dist/{budget-B4SKcu-1.js → budget-CCZUSzQX.js} +1 -1
  6. package/dist/build-task-request-config-D1BoTQ_r.js +10 -0
  7. package/dist/{commands-Bisc9IY0.js → commands-DT40svYr.js} +1 -1
  8. package/dist/{commands-Drf0_Uu8.js → commands-OQF1wQ6Z.js} +1 -1
  9. package/dist/{config-ROg2C1qz.js → config-DRasb4uc.js} +2 -2
  10. package/dist/connectors-CGdm_hGV.js +11 -0
  11. package/dist/{file-upload-ClVCUJp1.js → file-upload-DuXlHqyj.js} +1 -1
  12. package/dist/{format-B6a10P86.js → format-C0MI0rzh.js} +1 -1
  13. package/dist/index.js +43 -23
  14. package/dist/{instruction-D0Sy5WJu.js → instruction-OdStaJMu.js} +1 -1
  15. package/dist/{login-7nuzjqqL.js → login-BJK-C-yF.js} +1 -1
  16. package/dist/{logout-O7uVmxmK.js → logout-b335WkA6.js} +1 -1
  17. package/dist/{marketplace-8V1DNOld.js → marketplace-B5HXnl23.js} +2 -2
  18. package/dist/{mcp-client-DpDabxv9.js → mcp-client-mMhJPPZN.js} +1 -1
  19. package/dist/{mcp-DwMCTWU-.js → mcp-hLbWIery.js} +1 -1
  20. package/dist/{meeting-DCMyPA59.js → meeting-2Z2c7Ppj.js} +1 -1
  21. package/dist/{message-utils-C6JS91tT.js → message-utils-BHtHL44l.js} +7 -7
  22. package/dist/{models-BdxCIBZD.js → models-Cd725_l2.js} +1 -1
  23. package/dist/{notifications-BZxmGqEM.js → notifications-D1-iA_h8.js} +1 -1
  24. package/dist/{paginate-B-nHzQ0j.js → paginate-y3CJuqRW.js} +1 -1
  25. package/dist/{paths-ZPsPG0IC.js → paths-CIj_zxDF.js} +1 -1
  26. package/dist/profile-B1Jui2gr.js +10 -0
  27. package/dist/profile-storage-BPBUFvA6.js +74 -0
  28. package/dist/{project-Ba5LBPMF.js → project-DwR8Pf3y.js} +1 -1
  29. package/dist/project-context-CiI3hHaT.js +10 -0
  30. package/dist/{project-governance-B66BEQxO.js → project-governance-OVpv9LXv.js} +1 -1
  31. package/dist/{project-sources-D4m1oEvu.js → project-sources-CtSvnInR.js} +1 -1
  32. package/dist/{project-sources-write-CCICd6f8.js → project-sources-write-BaWV2jtH.js} +1 -1
  33. package/dist/{project-tasks-ylwpld2n.js → project-tasks-BKdZe3qu.js} +1 -1
  34. package/dist/{push-CNZNGP6D.js → push-CMRb7H6f.js} +1 -1
  35. package/dist/{recordings-DpDUq0iw.js → recordings-Bz6wVqBM.js} +1 -1
  36. package/dist/{remove-CbGljmXk.js → remove-B7p4PV6f.js} +1 -1
  37. package/dist/resolve-DdZsf3QT.js +14 -0
  38. package/dist/resource-grants-HDU2bPhQ.js +10 -0
  39. package/dist/{schedules-CTFIi2SL.js → schedules-DrzGEvSR.js} +2 -2
  40. package/dist/{skills-DbFd9oBS.js → skills-CdcBhRxn.js} +1 -1
  41. package/dist/{status-Br8KI96N.js → status-p4tJRN-I.js} +1 -1
  42. package/dist/status-wTfceoHq.js +10 -0
  43. package/dist/task-CyuwUFin.js +116 -0
  44. package/dist/tasks-B0x5P4UU.js +22 -0
  45. package/dist/{tasks-CNUJbs7w.js → tasks-BpqBNtta.js} +1 -1
  46. package/dist/{team-BfBb-uk2.js → team-R67MPRfp.js} +1 -1
  47. package/dist/{teams-47YS8wYw.js → teams-DvACXgpt.js} +1 -1
  48. package/dist/{token-CvjOXFDB.js → token-Diy_e8pF.js} +1 -1
  49. package/dist/{tool-D_n28XK0.js → tool-CFaX5Q8e.js} +7 -7
  50. package/dist/{update-B8gxXkSO.js → update-CvHLQuTu.js} +1 -1
  51. package/dist/{usage-BPyHU-GL.js → usage-Bv04bmPn.js} +1 -1
  52. package/dist/{usage-audit-STxCfVta.js → usage-audit-D65sU87J.js} +3 -3
  53. package/dist/{version-Ca4arzgb.js → version-BFfQldMJ.js} +1 -1
  54. package/dist/{webhook-B0E0M2EK.js → webhook-h1JuRyJf.js} +1 -1
  55. package/dist/{workflow-B-iN8d5R.js → workflow-CrOwbORs.js} +1 -1
  56. package/dist/{workspaces-DmqtYNX1.js → workspaces-CJP3Q8wV.js} +1 -1
  57. package/package.json +4 -4
  58. package/dist/build-task-request-config-eOeyGAfk.js +0 -10
  59. package/dist/connectors-jktsuWlk.js +0 -11
  60. package/dist/profile-D4jP-vQE.js +0 -10
  61. package/dist/profile-storage--QCh_u_Q.js +0 -73
  62. package/dist/project-context-8lb14kaU.js +0 -10
  63. package/dist/resolve-Di6ohyyF.js +0 -14
  64. package/dist/resource-grants-DojPWFs8.js +0 -10
  65. package/dist/status-DLI2OgMv.js +0 -10
  66. package/dist/task-CRwWxEOf.js +0 -116
  67. package/dist/tasks-VEfTbXVT.js +0 -22
package/README.md CHANGED
@@ -95,6 +95,42 @@ entrydesk task -m "Hi" --model <model> --plain
95
95
  entrydesk task -m "Hi" --model <model> --output stream-json
96
96
  ```
97
97
 
98
+ With `--output stream-json`, the last line is `{"event":"done","data":{"taskId":"…","text":"…"}}`: `text` is the final answer, without the progress notes the agent writes between tool calls.
99
+
100
+ Stopping a task:
101
+
102
+ ```bash
103
+ entrydesk tasks stop <taskId> # Or a 1-based index into `entrydesk tasks`
104
+ entrydesk tasks stop 1 --json # {"taskId":"…","status":"stopped"}
105
+ ```
106
+
107
+ A one-shot `entrydesk task` prints its task id before sending: `Task: <id>`
108
+ on stderr, or a first `{"event":"task","data":{"taskId":"…"}}` line under
109
+ `--output stream-json`. Ctrl+C, `SIGTERM` or `SIGHUP` (the terminal closing)
110
+ stops the task on the server and ends the local command it is running, then
111
+ exits with 130, 143 or 129; a second signal exits at once. A signal before the
112
+ message is sent stops nothing. If the stop cannot be confirmed, the CLI prints
113
+ the `entrydesk tasks stop` command to retry. `tasks stop` exits 0 when the task stopped or was not running, and 1
114
+ when the task does not exist or is not yours. Stopping cancels the task's
115
+ active run, so with `-c` it also stops a run of that task started from Hub once
116
+ this message has been sent.
117
+
118
+ A local command ends with everything it started, whether it outlives its
119
+ timeout or the task is stopped: on macOS and Linux the command runs in a
120
+ process group of its own, which gets `SIGTERM` and, two seconds later,
121
+ `SIGKILL`; on Windows `taskkill /T` ends its process tree. A second signal
122
+ skips the two seconds and kills it before the CLI exits. Interactive mode
123
+ (`-i`) does the same on `SIGTERM` or `SIGHUP` (the terminal closing), then
124
+ exits with 143 or 129 without stopping the task on the server. Some processes
125
+ get away, by design:
126
+
127
+ - Work a command leaves in the background after it finished on its own
128
+ (`nohup … &`) keeps running, as it would in your terminal.
129
+ - A process that leaves the group (`setsid`, a double fork) or, on Windows, one
130
+ started with `Start-Process` is out of reach.
131
+ - A command has no terminal, so one that prompts on `/dev/tty` (`sudo`, an ssh
132
+ passphrase) fails instead of waiting for input.
133
+
98
134
  ## Browse Resources
99
135
 
100
136
  ```bash
@@ -106,8 +142,21 @@ entrydesk connectors
106
142
  entrydesk skills
107
143
  entrydesk tasks
108
144
  entrydesk tasks 1
145
+ entrydesk tasks <taskId> --limit 20 --next-key <cursor> # An older page of its messages
109
146
  ```
110
147
 
148
+ The task list (`tasks --json` and `project tasks --json`, without `--search`)
149
+ prints `{ "tasks": [...], "nextKey": "..." }`, `tasks --search <query> --json`
150
+ prints `{ "results": [...], "nextKey": "..." }`, and `tasks <id> --json` prints
151
+ `{ "messages": [...], "nextKey": "..." }`; pass `nextKey` back as `--next-key`
152
+ for the next page. Under `--output stream-json` the closing `done` event carries
153
+ it instead, as `{ "event": "done", "data": { "nextKey": "..." } }`, and has no
154
+ `data` on the last page. Viewing a task reads its newest 50 messages unless
155
+ `--limit` says otherwise, and names the command for older ones when there are
156
+ more. That command uses the task's id even when you opened it as `tasks 1`: the
157
+ recent list can shift between calls, and a cursor read against another task
158
+ returns the wrong messages.
159
+
111
160
  ## Project
112
161
 
113
162
  Projects group **sources** (the files and links you put in one), the **tasks**
@@ -286,8 +335,12 @@ which needs `projects:read`. A project you are not a member of answers
286
335
  ### Sources and context
287
336
 
288
337
  **Sources** are the files and links you put in a project — the same list the
289
- Hub's Sources tab shows, with each one's retrieval description and, for a link,
290
- whether its snapshot is `pending`, `ready` or `failed`. **Context** is
338
+ Hub's Sources tab shows, with each one's retrieval description and whether it
339
+ can be searched: `processing` while it is being indexed, `ready`, `partial`
340
+ with the pages, slides or rows that could not be indexed (`missingUnits`), or
341
+ `failed` with the reason (`knowledgeIssue`). A link reports its snapshot first —
342
+ `pending` while it is being fetched, `failed` with the fetch error — and its
343
+ index status once the snapshot is in. **Context** is
291
344
  everything the AI knows in the project, so searching and reading across the
292
345
  tasks you can see _and_ those sources hangs off that word instead:
293
346
 
@@ -297,6 +350,8 @@ entrydesk project context-search 1 "login race" --type task --limit 5
297
350
  entrydesk project context-read 1 file <fileId> # A file's stored text
298
351
  entrydesk project context-read 1 task <taskId> # A task's summary
299
352
  entrydesk project context-read 1 task <taskId> --full # …its whole history
353
+ entrydesk project context-read 1 file <fileId> --evidence <evidenceId> # One search hit
354
+ entrydesk project context-read 1 file <fileId> --start 12 --end 14 # Pages 12-14
300
355
  ```
301
356
 
302
357
  `context-search` looks across tasks and sources at once; `--type task`, `--type
@@ -355,7 +410,9 @@ entrydesk project context-read 1 file <fileId> \
355
410
  ```
356
411
 
357
412
  Everything that is not text stays off stdout, so a pipe never carries an
358
- explanation where the content should be: a file with no text to extract, a link
413
+ explanation where the content should be: a file whose text has not been
414
+ extracted (still processing, unsupported or failed — a PDF, slide deck,
415
+ spreadsheet or image with extracted text reads like any text file), a link
359
416
  whose snapshot is still being fetched, and one whose fetch failed each print
360
417
  their reason on stderr and exit non-zero. With `--json` that reason is the
361
418
  `{ "status": … }` object from the API — `download` with a short-lived
@@ -380,6 +437,18 @@ naming the stored text it was measured against: a snapshot refetched between
380
437
  two pages fails the next read instead of quietly serving new bytes at the old
381
438
  offset, so start again from the beginning when that happens.
382
439
 
440
+ A file or a link can also be read by its indexed passages instead of its
441
+ stored text. Each `context-search` hit on a source prints its `Evidence` id and
442
+ its location; `--evidence <id>` reads that passage with the ones around it, and
443
+ `--start <n>` / `--end <n>` read the passages overlapping a page, slide or row
444
+ range (1-based, inclusive). The text still goes to stdout alone; stderr lists
445
+ each passage's evidence id and location, and a range cut short names the
446
+ `--start` to continue from — `passages` and `nextStart` under `--json`.
447
+ `--evidence` and a range cannot be combined, neither works with `--offset` or
448
+ `--revision`, and tasks have no passages; the CLI refuses those before sending
449
+ a request. An evidence id lasts until its source is re-indexed, so search again
450
+ when a read says it is gone.
451
+
383
452
  ### Governance
384
453
 
385
454
  A project can be created, deleted and staffed without opening the Hub, under
@@ -7,4 +7,4 @@ if (parseInt(process.versions.node, 10) < __entrydeskNodeFloor) {
7
7
  );
8
8
  process.exit(1);
9
9
  }
10
- import{I as e}from"./profile-storage--QCh_u_Q.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-ZPsPG0IC.js";import{t as c}from"./hash-92fWniGT.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,n,r,i]=/^https?:\/\/github\.com\/([\w.-]+)\/([\w.-]+?)(?:\.git)?(?:\/tree\/([^/]+)(?:\/(.+))?)?\/?$/u.exec(e)??[];return t===void 0||n===void 0?null:{type:`github`,owner:t,repo:n,gitRef:r,subpath:i,url:`https://github.com/${t}/${n}`}}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,i,a]=_.exec(t)??[];return r!==void 0&&i!==void 0?{type:`github`,owner:r,repo:i,subpath:a,url:`https://github.com/${r}/${i}`}:{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()),[s]=o;if(s===void 0)throw d.rmSync(r,{recursive:!0,force:!0}),Error(`npx skills installed no skill directory`);let c=s;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`}.`);c=n}return{dir:p.join(a,c.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};
10
+ import{L as e}from"./profile-storage-BPBUFvA6.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-CIj_zxDF.js";import{t as c}from"./hash-92fWniGT.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,n,r,i]=/^https?:\/\/github\.com\/([\w.-]+)\/([\w.-]+?)(?:\.git)?(?:\/tree\/([^/]+)(?:\/(.+))?)?\/?$/u.exec(e)??[];return t===void 0||n===void 0?null:{type:`github`,owner:t,repo:n,gitRef:r,subpath:i,url:`https://github.com/${t}/${n}`}}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,i,a]=_.exec(t)??[];return r!==void 0&&i!==void 0?{type:`github`,owner:r,repo:i,subpath:a,url:`https://github.com/${r}/${i}`}:{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()),[s]=o;if(s===void 0)throw d.rmSync(r,{recursive:!0,force:!0}),Error(`npx skills installed no skill directory`);let c=s;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`}.`);c=n}return{dir:p.join(a,c.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};
@@ -7,4 +7,4 @@ if (parseInt(process.versions.node, 10) < __entrydeskNodeFloor) {
7
7
  );
8
8
  process.exit(1);
9
9
  }
10
- import{$t as e,C as t,D as n,Gt as r,Jt as i,O as a,Qt as o,Yt as s,bt as c,p as l,r as u,yt as d}from"./profile-storage--QCh_u_Q.js";import{n as f,t as p}from"./file-upload-ClVCUJp1.js";import{n as m,t as h}from"./terminal-text-cBPBiP3x.js";import{t as g}from"./resource-grants-DojPWFs8.js";import{HTTPError as _}from"ky";const v=new Set([`image/png`,`image/jpeg`,`image/gif`,`image/webp`]);function y(t){return t?e([...new Set(t)]):s}function b(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 x(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 S(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=o(e.capabilities).map(e=>c(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 C(e){let{accessToken:n,workspaceId:r}=await l(),i=new t;if(e.mine){let t=[],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(n,r,{limit:e.limit,nextKey:a});if(t.push(...s.agents),a=s.nextKey,!e.all||!a)break}if(e.json){console.log(h({agents:t,nextKey:a}));return}if(t.length===0){console.log("You own no agents in this workspace. Create one with `entrydesk agents create --name <name> …`, or browse `entrydesk marketplace`.");return}x(t),!e.all&&a&&console.log(`Next page: --next-key ${a}`);return}if(e.all){let t=[],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(n,r,{limit:e.limit??100,nextKey:a});if(t.push(...s.agents),a=s.nextKey,!a)break}if(e.json){console.log(h({agents:t}));return}if(t.length===0){console.log("No agents in this workspace yet. Create one with `entrydesk agents create`, or browse `entrydesk marketplace`.");return}b(t);return}let{agents:a,nextKey:o}=await i.getAgents(n,r,{limit:e.limit,nextKey:e.nextKey});if(e.json){console.log(h({agents:a,nextKey:o}));return}if(a.length===0){console.log("No agents in this workspace yet. Create one with `entrydesk agents create`, or browse `entrydesk marketplace`.");return}b(a),o&&console.log(`Next page: --next-key ${o}`)}async function w(e,n){let{accessToken:r,workspaceId:i}=await l(),a=await new t().getAgent(r,i,e);if(n.json){console.log(h(a));return}S(a)}async function T(e){let{accessToken:n,workspaceId:r}=await l(),i=await new t().createAgent(n,r,{name:e.name,description:e.description,systemPrompt:e.systemPrompt,modelId:e.modelId,connectorIds:e.connectorIds??[],capabilities:y(e.capabilities),conversationStarters:e.conversationStarters??[],tools:e.tools,iconId:e.iconId});if(e.json){console.log(h(i));return}console.log(`Created agent: ${i.name}`),console.log(` ID: ${i.id}`)}function E(e,t){return{name:t.name??e.name,description:t.description??e.description,systemPrompt:t.systemPrompt??e.systemPrompt??``,modelId:t.modelId??e.model?.id??``,connectorIds:t.connectorIds??e.connectors?.map(e=>e.id)??[],capabilities:t.capabilities?y(t.capabilities):e.capabilities??{},conversationStarters:t.conversationStarters??e.conversationStarters??[],tools:t.tools??e.tools??[],iconId:t.iconId??e.iconId}}async function D(e,n){let{accessToken:r,workspaceId:i}=await l(),a=new t,o=await a.getAgent(r,i,e);await a.updateAgent(r,i,e,E(o,n)),console.log(`Updated agent: ${e}`)}async function O(e){let t=a(e),n;try{n=await f(e,{maxBytes:d})}catch(e){if(!(e instanceof p))throw e;switch(e.problem){case`missing`:throw new u(`No file at ${t}.`);case`not_a_file`:throw new u(`${t} is not a regular file.`);case`too_large`:throw new u(`${t} is larger than ${d/1024/1024}MB, the agent icon limit.`);case`unreadable`:throw new u(`Could not read ${t}. Check its permissions.`)}}if(!v.has(n.mimeType))throw new u(`${t} is not a supported icon image. Use a PNG, JPEG, GIF, or WebP file (.png, .jpg, .jpeg, .gif, .webp).`);return n}async function k(e){let{accessToken:n,workspaceId:r}=await l(),i=new t;return{client:i,accessToken:n,workspaceId:r,agent:e?await i.getAgent(n,r,e):void 0}}async function A({client:e,accessToken:t,workspaceId:r},i,a){let o=await e.getAgentHeadVersionId(t,r,i),s=await e.getAgent(t,r,i);try{await e.updateAgent(t,r,i,{...E(s,{iconId:a}),expectedHeadVersionId:o})}catch(e){throw e instanceof _&&n(e.data)===`agent_version_conflict`?new u(`Agent ${i} was changed by someone else while the icon was being made, so it was not applied. Apply it with \`entrydesk agents update ${i} --icon-id ${a}\`.`):e}}async function j(e,t,n){let{agent:r}=e;if(r&&await A(e,r.id,t.iconId),n.json){console.log(h({...t,agentId:r?.id}));return}if(console.log(`Icon ID: ${t.iconId}`),console.log(`URL: ${m(t.url)}`),r){console.log(`\nApplied the icon to agent: ${m(r.name)} (${r.id})`);return}console.log(`\nApply it with \`entrydesk agents update <agentId> --icon-id ${t.iconId}\`.`)}async function M(e,t){if(!e&&(!t.name?.trim()||!t.description?.trim()))throw new u(`Pass --name and --description, or an agentId to generate the icon from that agent.`);let n=await k(e),r=t.name??n.agent?.name??``,i=t.description??(n.agent?.description.trim()?n.agent.description:n.agent?.systemPrompt??``);if(!r.trim()||!i.trim())throw new u(`Agent ${e} has no ${r.trim()?`description or system prompt`:`name`} to generate an icon from. Pass --name and --description.`);await j(n,await n.client.generateAgentIcon(n.accessToken,n.workspaceId,{name:r,description:i}),t)}async function N(e,t,n){let r=await O(e),i=await k(t);await j(i,await i.client.uploadAgentIcon(i.accessToken,i.workspaceId,r),n)}async function P(e){let{accessToken:n,workspaceId:r}=await l();await new t().deleteAgent(n,r,e),console.log(`Deleted agent: ${e}`)}async function F(e,t,n,r){let i;do{let a=await e.getMyAgents(t,n,{nextKey:i}),o=a.agents.find(e=>e.id===r);if(o)return o;i=a.nextKey}while(i)}function I(e){return{resource:{collection:`agents`,id:e},label:`agent`,publishResourceType:i.AGENT,findEditable:(t,n,r)=>F(t,n,r,e)}}async function L(e,t){await g(I(e),{...t,addWorkspace:!0,role:r.VIEWER})}async function R(e,t){await g(I(e),t)}export{T as createAgent,P as deleteAgent,M as generateAgentIcon,C as listAgents,L as publishAgent,R as shareAgent,w as showAgent,D as updateAgent,N as uploadAgentIcon};
10
+ import{$t as e,C as t,O as n,Qt as r,St as i,Yt as a,k as o,nn as s,p as c,r as l,rn as u,xt as d}from"./profile-storage-BPBUFvA6.js";import{n as f,t as p}from"./file-upload-DuXlHqyj.js";import{n as m,t as h}from"./terminal-text-cBPBiP3x.js";import{t as g}from"./resource-grants-HDU2bPhQ.js";import{HTTPError as _}from"ky";const v=new Set([`image/png`,`image/jpeg`,`image/gif`,`image/webp`]);function y(t){return t?u([...new Set(t)]):e}function b(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 x(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 S(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=s(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 C(e){let{accessToken:n,workspaceId:r}=await c(),i=new t;if(e.mine){let t=[],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(n,r,{limit:e.limit,nextKey:a});if(t.push(...s.agents),a=s.nextKey,!e.all||!a)break}if(e.json){console.log(h({agents:t,nextKey:a}));return}if(t.length===0){console.log("You own no agents in this workspace. Create one with `entrydesk agents create --name <name> …`, or browse `entrydesk marketplace`.");return}x(t),!e.all&&a&&console.log(`Next page: --next-key ${a}`);return}if(e.all){let t=[],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(n,r,{limit:e.limit??100,nextKey:a});if(t.push(...s.agents),a=s.nextKey,!a)break}if(e.json){console.log(h({agents:t}));return}if(t.length===0){console.log("No agents in this workspace yet. Create one with `entrydesk agents create`, or browse `entrydesk marketplace`.");return}b(t);return}let{agents:a,nextKey:o}=await i.getAgents(n,r,{limit:e.limit,nextKey:e.nextKey});if(e.json){console.log(h({agents:a,nextKey:o}));return}if(a.length===0){console.log("No agents in this workspace yet. Create one with `entrydesk agents create`, or browse `entrydesk marketplace`.");return}b(a),o&&console.log(`Next page: --next-key ${o}`)}async function w(e,n){let{accessToken:r,workspaceId:i}=await c(),a=await new t().getAgent(r,i,e);if(n.json){console.log(h(a));return}S(a)}async function T(e){let{accessToken:n,workspaceId:r}=await c(),i=await new t().createAgent(n,r,{name:e.name,description:e.description,systemPrompt:e.systemPrompt,modelId:e.modelId,connectorIds:e.connectorIds??[],capabilities:y(e.capabilities),conversationStarters:e.conversationStarters??[],tools:e.tools,iconId:e.iconId});if(e.json){console.log(h(i));return}console.log(`Created agent: ${i.name}`),console.log(` ID: ${i.id}`)}function E(e,t){return{name:t.name??e.name,description:t.description??e.description,systemPrompt:t.systemPrompt??e.systemPrompt??``,modelId:t.modelId??e.model?.id??``,connectorIds:t.connectorIds??e.connectors?.map(e=>e.id)??[],capabilities:t.capabilities?y(t.capabilities):e.capabilities??{},conversationStarters:t.conversationStarters??e.conversationStarters??[],tools:t.tools??e.tools??[],iconId:t.iconId??e.iconId}}async function D(e,n){let{accessToken:r,workspaceId:i}=await c(),a=new t,o=await a.getAgent(r,i,e);await a.updateAgent(r,i,e,E(o,n)),console.log(`Updated agent: ${e}`)}async function O(e){let t=o(e),n;try{n=await f(e,{maxBytes:d})}catch(e){if(!(e instanceof p))throw e;switch(e.problem){case`missing`:throw new l(`No file at ${t}.`);case`not_a_file`:throw new l(`${t} is not a regular file.`);case`too_large`:throw new l(`${t} is larger than ${d/1024/1024}MB, the agent icon limit.`);case`unreadable`:throw new l(`Could not read ${t}. Check its permissions.`)}}if(!v.has(n.mimeType))throw new l(`${t} is not a supported icon image. Use a PNG, JPEG, GIF, or WebP file (.png, .jpg, .jpeg, .gif, .webp).`);return n}async function k(e){let{accessToken:n,workspaceId:r}=await c(),i=new t;return{client:i,accessToken:n,workspaceId:r,agent:e?await i.getAgent(n,r,e):void 0}}async function A({client:e,accessToken:t,workspaceId:r},i,a){let o=await e.getAgentHeadVersionId(t,r,i),s=await e.getAgent(t,r,i);try{await e.updateAgent(t,r,i,{...E(s,{iconId:a}),expectedHeadVersionId:o})}catch(e){throw e instanceof _&&n(e.data)===`agent_version_conflict`?new l(`Agent ${i} was changed by someone else while the icon was being made, so it was not applied. Apply it with \`entrydesk agents update ${i} --icon-id ${a}\`.`):e}}async function j(e,t,n){let{agent:r}=e;if(r&&await A(e,r.id,t.iconId),n.json){console.log(h({...t,agentId:r?.id}));return}if(console.log(`Icon ID: ${t.iconId}`),console.log(`URL: ${m(t.url)}`),r){console.log(`\nApplied the icon to agent: ${m(r.name)} (${r.id})`);return}console.log(`\nApply it with \`entrydesk agents update <agentId> --icon-id ${t.iconId}\`.`)}async function M(e,t){if(!e&&(!t.name?.trim()||!t.description?.trim()))throw new l(`Pass --name and --description, or an agentId to generate the icon from that agent.`);let n=await k(e),r=t.name??n.agent?.name??``,i=t.description??(n.agent?.description.trim()?n.agent.description:n.agent?.systemPrompt??``);if(!r.trim()||!i.trim())throw new l(`Agent ${e} has no ${r.trim()?`description or system prompt`:`name`} to generate an icon from. Pass --name and --description.`);await j(n,await n.client.generateAgentIcon(n.accessToken,n.workspaceId,{name:r,description:i}),t)}async function N(e,t,n){let r=await O(e),i=await k(t);await j(i,await i.client.uploadAgentIcon(i.accessToken,i.workspaceId,r),n)}async function P(e){let{accessToken:n,workspaceId:r}=await c();await new t().deleteAgent(n,r,e),console.log(`Deleted agent: ${e}`)}async function F(e,t,n,r){let i;do{let a=await e.getMyAgents(t,n,{nextKey:i}),o=a.agents.find(e=>e.id===r);if(o)return o;i=a.nextKey}while(i)}function I(e){return{resource:{collection:`agents`,id:e},label:`agent`,publishResourceType:r.AGENT,findEditable:(t,n,r)=>F(t,n,r,e)}}async function L(e,t){await g(I(e),{...t,addWorkspace:!0,role:a.VIEWER})}async function R(e,t){await g(I(e),t)}export{T as createAgent,P as deleteAgent,M as generateAgentIcon,C as listAgents,L as publishAgent,R as shareAgent,w as showAgent,D as updateAgent,N as uploadAgentIcon};
@@ -7,4 +7,4 @@ if (parseInt(process.versions.node, 10) < __entrydeskNodeFloor) {
7
7
  );
8
8
  process.exit(1);
9
9
  }
10
- import{C as e,p as t,x as n}from"./profile-storage--QCh_u_Q.js";import{t as r}from"./terminal-text-cBPBiP3x.js";import{i,n as a}from"./format-B6a10P86.js";import{t as o}from"./paginate-B-nHzQ0j.js";function s(e,t){let n=e.purchased[t]+e.granted[t];return`${t} ${e.assigned[t]}/${n}`}function c(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: ${s(t,`pro`)}, ${s(t,`premium`)} (assigned/capacity)`),t.totalGranted>0&&console.log(` Granted: pro ${t.granted.pro}, premium ${t.granted.premium} (not billed)`);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 l(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 u(){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 d(t){let{accessToken:n,workspaceId:i}=await u(),a=await new e().getBillingOverview(n,i);if(t.json){console.log(r(a));return}c(a)}async function f(t){let{accessToken:n,workspaceId:i}=await u(),a=new e;if(t.all){let e=await o(async e=>{let r=await a.getBillingInvoices(n,i,{limit:t.limit??20,nextKey:e});return{items:r.invoices,nextKey:r.nextKey}});if(t.json){console.log(r({invoices:e}));return}if(e.length===0){console.log(`No invoices.`);return}l(e);return}let{invoices:s,nextKey:c}=await a.getBillingInvoices(n,i,{limit:t.limit,nextKey:t.nextKey});if(t.json){console.log(r({invoices:s,nextKey:c}));return}if(s.length===0){console.log(`No invoices.`);return}l(s),c&&console.log(`Next page: --next-key ${c}`)}export{f as listInvoices,d as showBillingStatus};
10
+ import{C as e,p as t,x as n}from"./profile-storage-BPBUFvA6.js";import{t as r}from"./terminal-text-cBPBiP3x.js";import{i,n as a}from"./format-C0MI0rzh.js";import{t as o}from"./paginate-y3CJuqRW.js";function s(e,t){let n=e.purchased[t]+e.granted[t];return`${t} ${e.assigned[t]}/${n}`}function c(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: ${s(t,`pro`)}, ${s(t,`premium`)} (assigned/capacity)`),t.totalGranted>0&&console.log(` Granted: pro ${t.granted.pro}, premium ${t.granted.premium} (not billed)`);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 l(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 u(){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 d(t){let{accessToken:n,workspaceId:i}=await u(),a=await new e().getBillingOverview(n,i);if(t.json){console.log(r(a));return}c(a)}async function f(t){let{accessToken:n,workspaceId:i}=await u(),a=new e;if(t.all){let e=await o(async e=>{let r=await a.getBillingInvoices(n,i,{limit:t.limit??20,nextKey:e});return{items:r.invoices,nextKey:r.nextKey}});if(t.json){console.log(r({invoices:e}));return}if(e.length===0){console.log(`No invoices.`);return}l(e);return}let{invoices:s,nextKey:c}=await a.getBillingInvoices(n,i,{limit:t.limit,nextKey:t.nextKey});if(t.json){console.log(r({invoices:s,nextKey:c}));return}if(s.length===0){console.log(`No invoices.`);return}l(s),c&&console.log(`Next page: --next-key ${c}`)}export{f as listInvoices,d as showBillingStatus};
@@ -7,4 +7,4 @@ if (parseInt(process.versions.node, 10) < __entrydeskNodeFloor) {
7
7
  );
8
8
  process.exit(1);
9
9
  }
10
- import{C as e,p as t}from"./profile-storage--QCh_u_Q.js";import{t as n}from"./terminal-text-cBPBiP3x.js";async function r(r){let{accessToken:i,workspaceId:a}=await t(),o=await new e().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 t(),s=new e;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 t(),o=new e;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};
10
+ import{C as e,p as t}from"./profile-storage-BPBUFvA6.js";import{t as n}from"./terminal-text-cBPBiP3x.js";async function r(r){let{accessToken:i,workspaceId:a}=await t(),o=await new e().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 t(),s=new e;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 t(),o=new e;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{Kt as e,Tt as t,qt as n,wt as r}from"./profile-storage-BPBUFvA6.js";function i({allowedTools:e,disallowedTools:n}){if(!(!e?.length&&!n?.length))return[...t(e?.map(e=>({toolName:e,policy:r.ALWAYS_ALLOW})),n?.map(e=>({toolName:e,policy:r.BLOCK})))].map(([e,t])=>({toolName:e,policy:t}))}function a(e,n){let i=[...n].map(e=>({toolName:e,policy:r.ALWAYS_ALLOW}));return i.length===0?e:[...t(e,i)].map(([e,t])=>({toolName:e,policy:t}))}function o({agentId:t,model:r,projectId:i,pinnedConnectorIds:a,clientTools:o,clientToolSystemPrompt:s,toolApprovalMode:c,toolPolicies:l}){return{...i?{projectId:i}:{},...t?{agentId:t}:{...r?{model:r}:{},...a?.length?{pinnedConnectorIds:a}:{}},...o?{clientTools:n(o,e.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{I as e}from"./profile-storage--QCh_u_Q.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-ZPsPG0IC.js";import{t as m}from"./hash-92fWniGT.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};
10
+ import{L as e}from"./profile-storage-BPBUFvA6.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-CIj_zxDF.js";import{t as m}from"./hash-92fWniGT.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};
@@ -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-Bisc9IY0.js";export{e as runSkillsUnlink};
10
+ import{r as e}from"./commands-DT40svYr.js";export{e as runSkillsUnlink};
@@ -7,5 +7,5 @@ if (parseInt(process.versions.node, 10) < __entrydeskNodeFloor) {
7
7
  );
8
8
  process.exit(1);
9
9
  }
10
- import{R as e,t,z as n}from"./profile-storage--QCh_u_Q.js";import{t as r}from"./terminal-text-cBPBiP3x.js";function i(i){let a=n.getAll();if(i.json){console.log(r(a));return}let o=Object.entries(a);if(console.log(`Profile: ${t.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};
10
+ import{B as e,t,z as n}from"./profile-storage-BPBUFvA6.js";import{t as r}from"./terminal-text-cBPBiP3x.js";function i(i){let a=e.getAll();if(i.json){console.log(r(a));return}let o=Object.entries(a);if(console.log(`Profile: ${t.getEffectiveProfileName()}`),o.length===0){console.log(`No configuration set.`),console.log(`Available keys: ${n.join(`, `)}`);return}console.log(`Configuration:
11
+ `);for(let[e,t]of o)console.log(` ${e}=${t}`);console.log(`\nAvailable keys: ${n.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{Bt as e,C as t,Ft as n,Nt as r,Vt as i,p as a,zt as o}from"./profile-storage-BPBUFvA6.js";import{t as s}from"./terminal-text-cBPBiP3x.js";import{t as c}from"./confirm-Ct432t3K.js";function l(e,t){return t?o(t)?`Next: entrydesk connectors connect ${e} --oauth`:t===`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 u(e){let{accessToken:n,workspaceId:r}=await a(),{connectors:i,nextKey:o}=await new t().getConnectors(n,r,{connectionStatus:e.all?`all`:`connected`,search:e.search,limit:e.limit,nextKey:e.nextKey});if(e.json){console.log(s({connectors:i,nextKey:o}));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(``)}o&&console.log(`More results: --next-key ${o}`)}async function d(e,n){let{accessToken:r,workspaceId:i}=await a(),{tools:o}=await new t().getConnectorTools(r,i,e);if(n.json){console.log(s({tools:o}));return}if(o.length===0){console.log(`This connector exposes no tools.`);return}console.log(`Tools (${o.length}):\n`);for(let e of o)console.log(` ${e.name} [${e.policy}]`),e.description&&console.log(` ${e.description}`)}async function f(e,n){let{accessToken:r,workspaceId:i}=await a();await new t().syncConnectorTools(r,i,e),console.log(n.json?s({id:e,synced:!0}):`Synced tools for connector ${e}.`)}async function p(e,n){let{accessToken:r,workspaceId:i}=await a(),o=new t;if(n.oauth){let{url:t}=await o.getConnectorAuthUrl(r,i,e);if(n.json){console.log(s({url:t}));return}console.log(`Open this URL in your browser to authorize the connector:`),console.log(` ${t}`),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;n.token?c={token:n.token}:n.username&&n.password?c={username:n.username,password:n.password}:(console.error(`Provide --token, or --username and --password, or --oauth to connect.`),process.exit(1)),await o.connectConnectorToken(r,i,e,c),console.log(n.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(o){let c=m(o),u=o.toolNamespace??o.toolPrefix,d=u??e(o.name),f=n(d);if(f){let e=r[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 a(),g=await new t().createCustomConnector(p,h,{type:i.CUSTOM_REMOTE_URL,name:o.name,description:o.description,transport:o.transport,url:o.url,toolNamespace:d,...c?{authorization:c}:{}});if(o.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,o.auth)}`)}function g(e,t){return t===void 0?e:t===null||t.type!==e?.type?t:{...e,...t}}async function _(e,n){[n.name,n.url,n.description,n.transport,n.toolNamespace,n.auth,n.provider,n.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 r=m(n),{accessToken:o,workspaceId:c}=await a(),l=new t,u=await l.getCustomConnector(o,c,e),d=await l.updateCustomConnector(o,c,e,{type:i.CUSTOM_REMOTE_URL,name:n.name??u.name,description:n.description??u.description,transport:n.transport??u.transport,url:n.url??u.url,toolNamespace:n.toolNamespace??u.toolNamespace,authorization:g(u.authorization,r)});if(n.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,n){let{accessToken:r,workspaceId:i}=await a();if(!n.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 t().disconnectConnector(r,i,e),console.log(n.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};
@@ -7,7 +7,7 @@ if (parseInt(process.versions.node, 10) < __entrydeskNodeFloor) {
7
7
  );
8
8
  process.exit(1);
9
9
  }
10
- import"./profile-storage--QCh_u_Q.js";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";function s(e){return e instanceof Error&&`code`in e}const c=o(i);async function l(){let t=r.join(n.tmpdir(),`entrydesk-clipboard-${Date.now()}.png`);try{let e=`
10
+ import"./profile-storage-BPBUFvA6.js";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";function s(e){return e instanceof Error&&`code`in e}const c=o(i);async function l(){let t=r.join(n.tmpdir(),`entrydesk-clipboard-${Date.now()}.png`);try{let e=`
11
11
  set imageData to the clipboard as "PNGf"
12
12
  set fileRef to open for access POSIX file "${t}" with write permission
13
13
  set eof fileRef to 0
@@ -7,4 +7,4 @@ if (parseInt(process.versions.node, 10) < __entrydeskNodeFloor) {
7
7
  );
8
8
  process.exit(1);
9
9
  }
10
- import{Q as e}from"./profile-storage--QCh_u_Q.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};
10
+ import{$ as e}from"./profile-storage-BPBUFvA6.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};