wizards 0.3.7 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -14
- package/apps/runtime/dist/agents/studio-assistant.js +79 -7
- package/apps/runtime/dist/assistant/runs.js +24 -0
- package/apps/runtime/dist/auth/account.js +36 -4
- package/apps/runtime/dist/auth/device.js +101 -0
- package/apps/runtime/dist/auth/index.js +4 -4
- package/apps/runtime/dist/cli/account.js +289 -0
- package/apps/runtime/dist/cli/install-env.js +33 -0
- package/apps/runtime/dist/cli/main.js +17 -3
- package/apps/runtime/dist/cli/menu.js +19 -5
- package/apps/runtime/dist/cli/setup.js +9 -16
- package/apps/runtime/dist/cli/status.js +4 -1
- package/apps/runtime/dist/cli/ui.js +14 -0
- package/apps/runtime/dist/docs/user/assistant.md +25 -7
- package/apps/runtime/dist/docs/user/command-line.md +3 -2
- package/apps/runtime/dist/docs/user/create-account.md +47 -0
- package/apps/runtime/dist/docs/user/first-start.md +9 -1
- package/apps/runtime/dist/docs/user/index.md +16 -12
- package/apps/runtime/dist/docs/user/install.md +3 -1
- package/apps/runtime/dist/docs/user/local-only.md +38 -0
- package/apps/runtime/dist/docs/user/meta.json +3 -1
- package/apps/runtime/dist/docs/user/models.md +3 -2
- package/apps/runtime/dist/env.js +5 -0
- package/apps/runtime/dist/manage.js +16 -4
- package/apps/runtime/dist/models.js +6 -0
- package/apps/runtime/dist/plugins/pro.js +16 -16
- package/apps/runtime/dist/routes/studio.js +140 -40
- package/apps/runtime/dist/services/assistant-chats.js +49 -6
- package/apps/runtime/dist/services/cloud.js +10 -10
- package/apps/runtime/dist/services/onboarding.js +152 -0
- package/apps/web/dist/assets/{AboutDialog-C0dN86zd.js → AboutDialog-CPQiN7H9.js} +1 -1
- package/apps/web/dist/assets/{ChangelogDialog-Cv81t7tj.js → ChangelogDialog-DynvQuuR.js} +1 -1
- package/apps/web/dist/assets/ChatView-CKo_9IZD.js +10 -0
- package/apps/web/dist/assets/EditorPage-CDIJXC4T.js +3 -0
- package/apps/web/dist/assets/{FlowPreview-D4dp1MWS.js → FlowPreview-BZLnG7GV.js} +1 -1
- package/apps/web/dist/assets/{Harness-v7r0e6vK.js → Harness-CNh3nbB_.js} +2 -2
- package/apps/web/dist/assets/{NewWizardChannels-Be-7VhBi.js → NewWizardChannels-C1Ss9UMY.js} +1 -1
- package/apps/web/dist/assets/{NewWizardPage-C8hPvrK8.js → NewWizardPage-2qLAbvDL.js} +2 -2
- package/apps/web/dist/assets/OnboardingPage-C1FJwEsT.js +1 -0
- package/apps/web/dist/assets/ProjectPage-CGuLUuOs.js +1 -0
- package/apps/web/dist/assets/{PublicRunner-DeCpVfZP.js → PublicRunner-BKw1lOW4.js} +1 -1
- package/apps/web/dist/assets/{ReadOnly-B-UCgnqW.js → ReadOnly-DTjv2Jzm.js} +1 -1
- package/apps/web/dist/assets/RunDrawer-D1I5xqVf.js +4 -0
- package/apps/web/dist/assets/RunnerView-BPPmlv9z.js +1 -0
- package/apps/web/dist/assets/SettingsPage-zbomQfGy.js +1 -0
- package/apps/web/dist/assets/SetupPage-D3F7M6Pz.js +1 -0
- package/apps/web/dist/assets/{SharePage-B778xUFo.js → SharePage-BY49IJgT.js} +1 -1
- package/apps/web/dist/assets/{changelog-DCJo2mbx.js → changelog-DYZC2E6q.js} +1 -1
- package/apps/web/dist/assets/{circle-alert-DLvC9ePT.js → circle-alert-CVOH4wAv.js} +1 -1
- package/apps/web/dist/assets/{esm-BJskogLD.js → esm-BfXdeWaI.js} +1 -1
- package/apps/web/dist/assets/index-B9xVkr2X.css +1 -0
- package/apps/web/dist/assets/index-BH0PYgov.js +15 -0
- package/apps/web/dist/assets/{lock-DR7NakPn.js → lock-DHBh62LA.js} +1 -1
- package/apps/web/dist/assets/{phone-BORh3jfv.js → phone-Bt1cyWpY.js} +1 -1
- package/apps/web/dist/assets/{settings-menu-DV5D91TD.js → settings-menu-ace1vI3i.js} +1 -1
- package/apps/web/dist/assets/{ui-BOCXzzHi.js → ui-D2SqIZeQ.js} +2 -2
- package/apps/web/dist/assets/{upload-B3yv8gsk.js → upload-CCEq88l4.js} +1 -1
- package/apps/web/dist/index.html +3 -3
- package/apps/web/dist/install.sh +17 -7
- package/apps/web/dist/mcp/flow.html +3 -3
- package/node_modules/@engenty-wizards/shared/dist/assistant.d.ts +62 -1
- package/node_modules/@engenty-wizards/shared/dist/assistant.js +10 -0
- package/package.json +1 -1
- package/apps/web/dist/assets/ChatView-uogJ3nht.js +0 -10
- package/apps/web/dist/assets/EditorPage-n8YuTh6j.js +0 -3
- package/apps/web/dist/assets/ProjectPage-B686ArYy.js +0 -1
- package/apps/web/dist/assets/RunDrawer-C6pzi8AJ.js +0 -4
- package/apps/web/dist/assets/RunnerView-Deenymq0.js +0 -1
- package/apps/web/dist/assets/SettingsPage-CK6L0yEe.js +0 -1
- package/apps/web/dist/assets/SetupPage-9CH3qXdH.js +0 -1
- package/apps/web/dist/assets/index-D6hUM8NU.css +0 -1
- package/apps/web/dist/assets/index-Df6UxElH.js +0 -12
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Create an account
|
|
3
|
+
description: Your team, its space and your wizards live in your account at engenty.ai. Sign up with an invitation code, answer four questions, build.
|
|
4
|
+
version: 0.3.4
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
engenty wizards is in a closed beta: a new account needs an invitation code. "Get started" on
|
|
8
|
+
[engenty.ai](https://engenty.ai) takes your e-mail and puts you on the list; the code comes by
|
|
9
|
+
mail as soon as a seat is free. With a code, the same step opens the sign-up.
|
|
10
|
+
|
|
11
|
+
## Sign up
|
|
12
|
+
|
|
13
|
+
1. Type the code at [account.engenty.ai/sign-up](https://account.engenty.ai/sign-up). The link
|
|
14
|
+
in the invitation mail has it filled in.
|
|
15
|
+
2. Sign in with Google, GitHub, or a link by mail. There is no password.
|
|
16
|
+
3. The studio opens at [engenty.ai/studio](https://engenty.ai/studio).
|
|
17
|
+
|
|
18
|
+
Your account is a **team**: it holds your credits, your spaces and, on the Team plan, your
|
|
19
|
+
colleagues. It starts with credits, some of which end on a date; the account pages at
|
|
20
|
+
[account.engenty.ai](https://account.engenty.ai) show them.
|
|
21
|
+
|
|
22
|
+
## The first visit
|
|
23
|
+
|
|
24
|
+
The studio asks four things, one per page. Each but the first can be skipped and changed later.
|
|
25
|
+
|
|
26
|
+
| Page | Asks | Goes to |
|
|
27
|
+
|---|---|---|
|
|
28
|
+
| Who you are | What your team is called: your company, your club, or just your name | The team's name at account.engenty.ai |
|
|
29
|
+
| About you & your brand | Your website. engenty reads your name, what you do, your logo and colours from it; or you write a line about yourself | [Space → Info & brand](./space.md#info--brand) |
|
|
30
|
+
| Knowledge | Documents the wizards may look things up in: price lists, your terms, an FAQ | [Space → Knowledge](./space.md#knowledge) |
|
|
31
|
+
| Your space | Nothing: it explains the space that holds all of this, "Meine Wizards" | — |
|
|
32
|
+
|
|
33
|
+
Then "Build your first wizard" opens the studio's start: describe a task in a sentence, or pick
|
|
34
|
+
a template. See [Build a wizard](./build-a-wizard.md).
|
|
35
|
+
|
|
36
|
+
## What the cloud does
|
|
37
|
+
|
|
38
|
+
- Wizards built here run behind a link that works day and night, on the team's credits.
|
|
39
|
+
- Share links, the tag for your website, QR codes and the channels of [Test and share](./test-and-share.md) work as on an install.
|
|
40
|
+
- What the wizards think with is the team's: [Models and account](./models.md).
|
|
41
|
+
|
|
42
|
+
## Also on your computer
|
|
43
|
+
|
|
44
|
+
The same account works on your own computer: [install](./install.md) engenty wizards there and
|
|
45
|
+
sign in during the setup. It thinks with your Claude, ChatGPT, Gemini or Cursor subscription,
|
|
46
|
+
reads your local files and browses for you; what you publish there runs in the cloud too, behind
|
|
47
|
+
the same links. "Also on your computer" on the studio's start page mails you the command.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: First start
|
|
3
3
|
description: Choose what engenty wizards thinks with. The studio opens once a test call works.
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.4
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
The first page of the studio is the setup, "Choose your Engine". It asks one thing: what should
|
|
@@ -9,10 +9,18 @@ engenty think with?
|
|
|
9
9
|
|
|
10
10
|

|
|
11
11
|
|
|
12
|
+
## Your account
|
|
13
|
+
|
|
14
|
+
Above the engines stands your account: signed in during the [install](./install.md), it shows
|
|
15
|
+
your name, your team and your credits, and your team's space is on this computer. Not signed in
|
|
16
|
+
yet, "Sign in" opens your browser for it; an install that is [local only](./local-only.md)
|
|
17
|
+
shows nothing here.
|
|
18
|
+
|
|
12
19
|
## Choose your engine
|
|
13
20
|
|
|
14
21
|
| Engine | Runs on | Needs |
|
|
15
22
|
|---|---|---|
|
|
23
|
+
| engenty credits | Your account's credits, like in the cloud | An account signed in. Shown only then |
|
|
16
24
|
| Claude Code | Your Claude subscription | The client installed and signed in |
|
|
17
25
|
| Codex | Your ChatGPT subscription | The client installed and signed in |
|
|
18
26
|
| Gemini CLI | Your Google account | The client installed and signed in |
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: User Guide
|
|
3
3
|
description: Install engenty wizards, build a wizard, run and share it.
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.4
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
engenty wizards turns something you do again and again into a wizard: pages that ask what it
|
|
@@ -17,30 +17,34 @@ briefing, an invoice, a quote, a damage report.
|
|
|
17
17
|
| **Describe it** | Say in plain words what the wizard should do. The assistant builds the flow; you see it as a diagram and change any step. |
|
|
18
18
|
| **Let AI steps work** | They research the web, write, draw images, render video, read PDFs, scans and mails, build documents and dashboards, and write into other services. Anything that changes an account asks first. |
|
|
19
19
|
| **Share a link** | Anyone runs the wizard in a browser, on a phone too. Results download as PDF, Word, HTML, Markdown, PNG, MP4, MP3, CSV, Excel or JSON, or go out as a link. |
|
|
20
|
-
| **
|
|
20
|
+
| **In the cloud, or on your computer** | Sign up and build in the browser; links run on your team's credits. Or install it on your computer: it thinks with Codex, Claude Code, Gemini CLI or Cursor Agent on your own subscription, with your own keys, or with a local model, and your files stay with you. |
|
|
21
21
|
|
|
22
22
|
## Where to start
|
|
23
23
|
|
|
24
|
-
1. [
|
|
25
|
-
2.
|
|
26
|
-
3. [
|
|
27
|
-
4. [
|
|
24
|
+
1. [Create an account](./create-account.md) at engenty.ai, with an invitation code.
|
|
25
|
+
2. [Build a wizard](./build-a-wizard.md) from a sentence or a template.
|
|
26
|
+
3. [Test and share](./test-and-share.md) it.
|
|
27
|
+
4. Also on your computer: [install](./install.md) it there, signed in to the same account, and at the [first start](./first-start.md) choose what it thinks with.
|
|
28
28
|
5. Use it from your [AI apps](./ai-apps.md): Claude Desktop, Cursor, Codex and others.
|
|
29
29
|
|
|
30
30
|
## Words used here
|
|
31
31
|
|
|
32
32
|
| Word | Means |
|
|
33
33
|
|---|---|
|
|
34
|
-
|
|
|
34
|
+
| Account | You, signed in at engenty.ai with Google, GitHub or a link by mail |
|
|
35
|
+
| Team | What the sign-up creates: it holds your credits, your spaces and, on the Team plan, your colleagues |
|
|
36
|
+
| Space | What all your wizards know and produce: name, logo, colours, facts, documents, data, results. A team's first one is "Meine Wizards" |
|
|
37
|
+
| Studio | Where you build wizards: engenty.ai/studio, or `/studio` of your install |
|
|
35
38
|
| Wizard | A flow of steps a person walks through on a link |
|
|
36
39
|
| Step | One part of the flow: a page, an AI step, a review, the result |
|
|
37
40
|
| Run | One person going through a wizard once |
|
|
38
|
-
| Space | What all your wizards know: name, logo, colours, facts, documents |
|
|
39
41
|
| Model class | The kind of model a step needs. Which model serves a class is a setting, not part of the wizard |
|
|
40
42
|
|
|
41
43
|
## Two places it runs
|
|
42
44
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
Your team, its space and your wizards live in your account. engenty.ai is the cloud: you build
|
|
46
|
+
there in the browser, and links run day and night on the team's credits. Your computer can join:
|
|
47
|
+
[install](./install.md) engenty wizards there, signed in to the same account, and it thinks with
|
|
48
|
+
the AI clients and keys on that machine; what you publish there runs in the cloud as well
|
|
49
|
+
([Test and share](./test-and-share.md#in-the-cloud)). An install without an account is
|
|
50
|
+
[local only](./local-only.md).
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Install
|
|
3
3
|
description: One command on macOS or Linux. It brings its own Node.js and asks for no password.
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.4
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
## Install
|
|
@@ -18,6 +18,7 @@ command into `~/.local/bin` and then walks you through the rest:
|
|
|
18
18
|
|
|
19
19
|
| Step | What it does |
|
|
20
20
|
|---|---|
|
|
21
|
+
| Your engenty account | Shows a code and opens the browser for the sign-in at account.engenty.ai (no account yet? the page takes an invitation code). Signed in, your team's space comes down to this computer, and what you publish here runs in the cloud too. "Later" skips it: `wizards account sign-in` does it any time. `--local` leaves the account out altogether: [Local only](./local-only.md) |
|
|
21
22
|
| Something to think with | Looks for Codex, Claude Code, Gemini CLI and Cursor Agent and offers to install the ones that are missing. It proposes the one whose app (ChatGPT, Claude, Cursor) is on your Mac first, as that subscription is most likely yours already. You can also use an API key, [Ollama](https://ollama.com) or, on a Mac with Apple silicon and macOS 26, Apple Intelligence: the studio's [first page](./first-start.md) offers them |
|
|
22
23
|
| A browser and ffmpeg | Names the browser for PDF and PNG exports and steps on websites: the first of Chrome, Edge and Chromium it finds (on a Mac also Brave). The app uses that one; [`CHROME_PATH`](./command-line.md#settings) picks another. Says whether there is ffmpeg for MP4 videos of animated widgets; with Homebrew it offers to install it |
|
|
23
24
|
| Start at login (optional) | engenty wizards starts in the background when you log in, so links and AI clients always reach it. A LaunchAgent on a Mac, a systemd user service on Linux |
|
|
@@ -37,6 +38,7 @@ You install once; from then on you use the `wizards` command.
|
|
|
37
38
|
| `wizards stop` | Stops it. Your data is kept |
|
|
38
39
|
| `wizards status` | Whether it runs, and where |
|
|
39
40
|
| `wizards restart` | Stops it and starts it again |
|
|
41
|
+
| `wizards account` | How the install stands to your account; `sign-in` and `sign-out` |
|
|
40
42
|
| `wizards` | A menu with all of it |
|
|
41
43
|
|
|
42
44
|
The studio is at
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Local only
|
|
3
|
+
description: An install without an account. Nothing leaves the computer; links answer on it only. The flag, what it means, and how to connect an account later.
|
|
4
|
+
version: 0.3.4
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
An install normally signs in to your account during the setup: your team's space comes down to
|
|
8
|
+
the computer, and what you publish runs in the cloud too. An install can also stay alone.
|
|
9
|
+
|
|
10
|
+
## The flag
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
curl -fsSL https://engenty.ai/install.sh | bash -s -- --local
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
`--local` skips the account step of the setup and switches the account off for this install.
|
|
17
|
+
On an install that is there already: `wizards setup --local`.
|
|
18
|
+
|
|
19
|
+
## What it means
|
|
20
|
+
|
|
21
|
+
- No account, nothing leaves this computer. Wizards, the space and results stay in
|
|
22
|
+
`~/.engenty/wizards/data` ([Your data](./data.md)).
|
|
23
|
+
- Links answer on this computer only: `http://localhost:24368/w/…`. For others to open them,
|
|
24
|
+
run it [on a server](./server.md) of your own.
|
|
25
|
+
- It thinks with your AI clients, your own keys, Ollama or Apple Intelligence
|
|
26
|
+
([First start](./first-start.md)). Without an account, video and voice need a key of your own.
|
|
27
|
+
- The studio shows no account surfaces: no sign-in offer, no credits, no cloud copy. The feature
|
|
28
|
+
switch `account` is off in the install's `.features` file; `wizards features` lists it.
|
|
29
|
+
|
|
30
|
+
## Connect an account later
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
wizards account sign-in
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The command shows a code and opens the browser for the sign-in; afterwards the install is
|
|
37
|
+
connected, and the switch is on again. `wizards account` says how the install stands,
|
|
38
|
+
`wizards account sign-out` disconnects it. Settings → Account in the studio does the same.
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"title": "User Guide",
|
|
3
|
-
"description": "
|
|
3
|
+
"description": "Create an account, build a wizard, run and share it, install it on your computer.",
|
|
4
4
|
"root": true,
|
|
5
5
|
"icon": "LifeBuoy",
|
|
6
6
|
"pages": [
|
|
7
7
|
"index",
|
|
8
8
|
"---Start---",
|
|
9
|
+
"create-account",
|
|
9
10
|
"install",
|
|
10
11
|
"first-start",
|
|
11
12
|
"---Wizards---",
|
|
@@ -24,6 +25,7 @@
|
|
|
24
25
|
"---Your install---",
|
|
25
26
|
"command-line",
|
|
26
27
|
"data",
|
|
28
|
+
"local-only",
|
|
27
29
|
"server",
|
|
28
30
|
"troubleshooting"
|
|
29
31
|
]
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Models and account
|
|
3
3
|
description: Who does what your wizards ask for — an installed AI client, your own API keys, a local model, or credits.
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.4
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
Settings → Models decides who does what your wizards ask for. On your computer it is yours; on
|
|
@@ -125,7 +125,8 @@ Text & reasoning) picks what builds your wizards in the editor's conversation:
|
|
|
125
125
|
|
|
126
126
|
## Account
|
|
127
127
|
|
|
128
|
-
An account
|
|
128
|
+
An install normally signs in to your account during the setup ([Install](./install.md)); one
|
|
129
|
+
without an account is [local only](./local-only.md). With an account you
|
|
129
130
|
|
|
130
131
|
- use credits instead of your own keys (the editor's note about missing models says so where
|
|
131
132
|
text, image or video models are missing),
|
package/apps/runtime/dist/env.js
CHANGED
|
@@ -152,6 +152,11 @@ export const env = {
|
|
|
152
152
|
/** Encrypts connected accounts and kept browser sessions; falls back to the app secret. */
|
|
153
153
|
storeKey: str("STORE_ENC_KEY"),
|
|
154
154
|
devLogin: process.env.NODE_ENV !== "production" && str("DEV_LOGIN") === "1",
|
|
155
|
+
/**
|
|
156
|
+
* `1`: the studio assistant's developer mode may be switched on here (steps, tools, prompt,
|
|
157
|
+
* the turns' events). A managed runtime offers it to the platform's admins instead.
|
|
158
|
+
*/
|
|
159
|
+
assistantDev: str("ASSISTANT_DEV") === "1",
|
|
155
160
|
/**
|
|
156
161
|
* The Manage-App this runtime belongs to. Set = people sign in there, tenants come from its
|
|
157
162
|
* tokens and model calls go through its gateway. Empty = the runtime runs alone with one tenant.
|
|
@@ -110,15 +110,15 @@ export function tenantMembers(id) {
|
|
|
110
110
|
return call("GET", `/v1/tenants/${encodeURIComponent(id)}/members`);
|
|
111
111
|
}
|
|
112
112
|
const users = new Map();
|
|
113
|
-
/**
|
|
114
|
-
export async function
|
|
113
|
+
/** What the Manage-App says of a person beyond their token; cached a minute. */
|
|
114
|
+
export async function userInfo(userId) {
|
|
115
115
|
const hit = users.get(userId);
|
|
116
116
|
if (hit && Date.now() - hit.at < 60_000) {
|
|
117
117
|
return hit.value;
|
|
118
118
|
}
|
|
119
119
|
const value = await call("GET", `/v1/users/${encodeURIComponent(userId)}`)
|
|
120
|
-
.then((u) => u.features ?? {})
|
|
121
|
-
.catch(() => hit?.value ?? {});
|
|
120
|
+
.then((u) => ({ features: u.features ?? {}, admin: u.admin === true }))
|
|
121
|
+
.catch(() => hit?.value ?? { features: {}, admin: false });
|
|
122
122
|
users.set(userId, { at: Date.now(), value });
|
|
123
123
|
return value;
|
|
124
124
|
}
|
|
@@ -145,6 +145,18 @@ export async function tenantInfo(id, fresh = false) {
|
|
|
145
145
|
export function forgetTenant(id) {
|
|
146
146
|
tenants.delete(id);
|
|
147
147
|
}
|
|
148
|
+
/** Renames the team at the Manage-App; what it answers is the tenant as it stands now. */
|
|
149
|
+
export async function renameTenant(id, name) {
|
|
150
|
+
const value = await call("PATCH", `/v1/tenants/${encodeURIComponent(id)}`, {
|
|
151
|
+
name,
|
|
152
|
+
});
|
|
153
|
+
tenants.set(id, { at: Date.now(), value });
|
|
154
|
+
return value;
|
|
155
|
+
}
|
|
156
|
+
/** The Manage-App mails the install command and the first steps to one of the team's people. */
|
|
157
|
+
export function installMail(email, lang) {
|
|
158
|
+
return call("POST", "/v1/install-mail", { email, lang });
|
|
159
|
+
}
|
|
148
160
|
export function verifyKey(key) {
|
|
149
161
|
return call("POST", "/v1/keys/verify", { key });
|
|
150
162
|
}
|
|
@@ -1013,6 +1013,12 @@ function priceOf(ref) {
|
|
|
1013
1013
|
return (catalog.get(provider === null || provider === "gateway" ? id : `${provider}/${id}`)?.pricing ??
|
|
1014
1014
|
{});
|
|
1015
1015
|
}
|
|
1016
|
+
/** A model's context window in tokens, as the AI Gateway's catalog gives it; null where unknown. */
|
|
1017
|
+
export function contextWindowOf(ref) {
|
|
1018
|
+
const { provider, id } = parse(ref);
|
|
1019
|
+
const entry = catalog.get(provider === null || provider === "gateway" ? id : `${provider}/${id}`);
|
|
1020
|
+
return typeof entry?.context_window === "number" ? entry.context_window : null;
|
|
1021
|
+
}
|
|
1016
1022
|
const n = (v, fallback) => {
|
|
1017
1023
|
const x = Number(v);
|
|
1018
1024
|
return Number.isFinite(x) ? x : fallback;
|
|
@@ -84,7 +84,7 @@ async function call(path, token) {
|
|
|
84
84
|
signal: AbortSignal.timeout(60_000),
|
|
85
85
|
}).catch(() => null);
|
|
86
86
|
if (!res) {
|
|
87
|
-
throw new ProModuleError("
|
|
87
|
+
throw new ProModuleError("Your engenty account is not reachable right now.", 502, "offline");
|
|
88
88
|
}
|
|
89
89
|
return res;
|
|
90
90
|
}
|
|
@@ -109,19 +109,19 @@ export async function refreshPro() {
|
|
|
109
109
|
try {
|
|
110
110
|
const token = await accountToken();
|
|
111
111
|
if (!token) {
|
|
112
|
-
throw new ProModuleError("
|
|
112
|
+
throw new ProModuleError("Your engenty account is not reachable right now.", 502, "offline");
|
|
113
113
|
}
|
|
114
114
|
const res = await call("", token);
|
|
115
115
|
if (res.status === 401) {
|
|
116
|
-
throw new ProModuleError("
|
|
116
|
+
throw new ProModuleError("The engenty account no longer accepts this sign-in.", 403);
|
|
117
117
|
}
|
|
118
118
|
if (!res.ok) {
|
|
119
|
-
throw new ProModuleError(`
|
|
119
|
+
throw new ProModuleError(`The account did not answer as expected (${res.status}).`, 502);
|
|
120
120
|
}
|
|
121
121
|
const answer = (await res.json());
|
|
122
122
|
const claims = await verifySigned(answer.entitlement?.token ?? "", [AUDIENCE], env.local.accountUrl);
|
|
123
123
|
if (!claims || claims.sub !== account.tenantId || !Array.isArray(claims.modules)) {
|
|
124
|
-
throw new ProModuleError("
|
|
124
|
+
throw new ProModuleError("The package's confirmation could not be checked.", 502);
|
|
125
125
|
}
|
|
126
126
|
listing = answer;
|
|
127
127
|
lastError = null;
|
|
@@ -177,7 +177,7 @@ function filesOf(zip) {
|
|
|
177
177
|
files = unzipSync(zip);
|
|
178
178
|
}
|
|
179
179
|
catch {
|
|
180
|
-
throw new ProModuleError("
|
|
180
|
+
throw new ProModuleError("The package is damaged.", 502);
|
|
181
181
|
}
|
|
182
182
|
const out = {};
|
|
183
183
|
for (const [name, data] of Object.entries(files)) {
|
|
@@ -188,7 +188,7 @@ function filesOf(zip) {
|
|
|
188
188
|
const safe = parts.every((p) => p && p !== "." && p !== ".." && !p.includes("\\"));
|
|
189
189
|
const allowed = name === MANIFEST_FILE || PARTS.some((part) => name.startsWith(part));
|
|
190
190
|
if (!(safe && allowed)) {
|
|
191
|
-
throw new ProModuleError(`
|
|
191
|
+
throw new ProModuleError(`The package holds a file it may not: ${name}`, 502);
|
|
192
192
|
}
|
|
193
193
|
out[name] = data;
|
|
194
194
|
}
|
|
@@ -197,28 +197,28 @@ function filesOf(zip) {
|
|
|
197
197
|
/** Fetches one module of the plan, checks it and puts it in place; then it loads. */
|
|
198
198
|
export async function installPro(id) {
|
|
199
199
|
if (managed) {
|
|
200
|
-
throw new ProModuleError("
|
|
200
|
+
throw new ProModuleError("Not available here.", 404, "not_found");
|
|
201
201
|
}
|
|
202
202
|
const token = await accountToken();
|
|
203
203
|
if (!token) {
|
|
204
|
-
throw new ProModuleError("
|
|
204
|
+
throw new ProModuleError("Sign in to your engenty account first (Settings → Account).", 409);
|
|
205
205
|
}
|
|
206
206
|
if (!listing) {
|
|
207
207
|
await refreshPro();
|
|
208
208
|
}
|
|
209
209
|
const entry = listing?.modules.find((m) => m.id === id);
|
|
210
210
|
if (!entry) {
|
|
211
|
-
throw new ProModuleError(`
|
|
211
|
+
throw new ProModuleError(`There is no build of this module for ${runtimeTag()}.`, 404, "not_found");
|
|
212
212
|
}
|
|
213
213
|
if (!entry.included) {
|
|
214
|
-
throw new ProModuleError("
|
|
214
|
+
throw new ProModuleError("This module is not part of your plan.", 403, "plan");
|
|
215
215
|
}
|
|
216
216
|
const res = await call(`/${encodeURIComponent(id)}/package`, token);
|
|
217
217
|
if (!res.ok) {
|
|
218
|
-
throw new ProModuleError(`
|
|
218
|
+
throw new ProModuleError(`The module could not be fetched (${res.status}).`, 502);
|
|
219
219
|
}
|
|
220
220
|
if (Number(res.headers.get("content-length") ?? 0) > MAX_PACKAGE) {
|
|
221
|
-
throw new ProModuleError("
|
|
221
|
+
throw new ProModuleError("The package is too large.", 502);
|
|
222
222
|
}
|
|
223
223
|
const zip = new Uint8Array(await res.arrayBuffer());
|
|
224
224
|
const sha256 = createHash("sha256").update(zip).digest("hex");
|
|
@@ -231,12 +231,12 @@ export async function installPro(id) {
|
|
|
231
231
|
signature: entry.signature,
|
|
232
232
|
});
|
|
233
233
|
if (zip.length > MAX_PACKAGE || !genuine) {
|
|
234
|
-
throw new ProModuleError("
|
|
234
|
+
throw new ProModuleError("The package is not signed by engenty and was discarded.", 502);
|
|
235
235
|
}
|
|
236
236
|
const files = filesOf(zip);
|
|
237
237
|
const manifest = JSON.parse(new TextDecoder().decode(files[MANIFEST_FILE] ?? new Uint8Array()));
|
|
238
238
|
if (manifest?.id !== id) {
|
|
239
|
-
throw new ProModuleError("
|
|
239
|
+
throw new ProModuleError("The package does not belong to this module.", 502);
|
|
240
240
|
}
|
|
241
241
|
const dir = proModulesDir();
|
|
242
242
|
const target = join(dir, id);
|
|
@@ -270,7 +270,7 @@ export async function installPro(id) {
|
|
|
270
270
|
/** Removes an installed module; its tables and what is in them stay. */
|
|
271
271
|
export async function removePro(id) {
|
|
272
272
|
if (managed || !(await installedIds()).includes(id)) {
|
|
273
|
-
throw new ProModuleError("
|
|
273
|
+
throw new ProModuleError("This module is not installed.", 404, "not_found");
|
|
274
274
|
}
|
|
275
275
|
await rm(join(proModulesDir(), id), { recursive: true, force: true });
|
|
276
276
|
await findNewPlugins();
|