@dreamlake/dreamlake-cli 0.2.0 → 0.9.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.
package/bin/dreamlake.js CHANGED
@@ -1,33 +1,37 @@
1
1
  #!/usr/bin/env node
2
- // `dreamlake` CLI entry. Picks the compiled JS if present (production
3
- // install), else falls back to running the TS source through tsx
4
- // (workspace dev — no `pnpm build` required).
2
+ "use strict";
3
+ const { spawnSync } = require("node:child_process");
5
4
 
6
- import { existsSync } from "node:fs";
7
- import { fileURLToPath, pathToFileURL } from "node:url";
8
- import path from "node:path";
5
+ function isMusl() {
6
+ if (process.platform !== "linux") return false;
7
+ try {
8
+ return !process.report.getReport().header.glibcVersionRuntime;
9
+ } catch {
10
+ return false;
11
+ }
12
+ }
9
13
 
10
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
11
- const distEntry = path.join(__dirname, "..", "dist", "cli", "index.js");
12
- const srcEntry = path.join(__dirname, "..", "src", "cli", "index.ts");
14
+ const key = process.platform + "-" + process.arch + (isMusl() ? "-musl" : "");
15
+ const pkg = "@dreamlake/dreamlake-cli-" + key;
16
+ const bin = process.platform === "win32" ? "dreamlake.exe" : "dreamlake";
13
17
 
14
- async function run() {
15
- if (existsSync(distEntry)) {
16
- await import(pathToFileURL(distEntry).href);
17
- return;
18
- }
19
- if (existsSync(srcEntry)) {
20
- // Register tsx as a module loader, then import the TS source.
21
- const tsx = await import("tsx/esm/api");
22
- tsx.register();
23
- await import(pathToFileURL(srcEntry).href);
24
- return;
25
- }
26
- console.error("dreamlake: neither dist/cli/index.js nor src/cli/index.ts found");
27
- process.exit(2);
18
+ let binPath;
19
+ try {
20
+ binPath = require.resolve(pkg + "/" + bin);
21
+ } catch {
22
+ process.stderr.write(
23
+ "dreamlake: no binary for " + key + ".\n" +
24
+ "The platform package " + pkg + " is not installed. npm skips it when\n" +
25
+ "os/cpu do not match, and --no-optional skips it always. Reinstall without\n" +
26
+ "--no-optional, or use the native installer:\n" +
27
+ " curl -fsSL https://dl.dreamlake.ai/install.sh | sh\n",
28
+ );
29
+ process.exit(1);
28
30
  }
29
31
 
30
- run().catch((err) => {
31
- console.error(err?.stack ?? err);
32
+ const r = spawnSync(binPath, process.argv.slice(2), { stdio: "inherit" });
33
+ if (r.error) {
34
+ process.stderr.write("dreamlake: " + r.error.message + "\n");
32
35
  process.exit(1);
33
- });
36
+ }
37
+ process.exit(r.status === null ? 1 : r.status);
package/package.json CHANGED
@@ -1,37 +1,29 @@
1
1
  {
2
2
  "name": "@dreamlake/dreamlake-cli",
3
- "version": "0.2.0",
4
- "description": "dreamlake — data-warehouse CLI. The `dreamlake` command uploads/downloads assets and manages episodes, bindrs, and datasets against a DreamLake server + BSS.",
5
- "private": false,
6
- "type": "module",
7
- "main": "dist/cli/index.js",
3
+ "version": "0.9.1",
4
+ "repository": {
5
+ "type": "git",
6
+ "url": "git+https://github.com/dreamlake-ai/dreamlake-cli.git"
7
+ },
8
+ "homepage": "https://cli.dreamlake.ai",
9
+ "description": "dreamlake — data-warehouse CLI. The `dreamlake` command uploads/downloads assets, manages episodes, bindrs, datasets, organizations and teams, and versions artifacts, workflow specs and pipelines against a DreamLake server + BSS.",
8
10
  "bin": {
9
11
  "dreamlake": "bin/dreamlake.js"
10
12
  },
11
13
  "files": [
12
- "bin",
13
- "dist",
14
- "!dist/**/*.map"
14
+ "bin"
15
15
  ],
16
- "publishConfig": {
17
- "access": "public"
18
- },
19
- "scripts": {
20
- "build": "tsc",
21
- "cli": "tsx src/cli/index.ts",
22
- "test": "tsc -p tsconfig.json --noEmit && node --import tsx --test src/cli/__tests__/*.test.ts",
23
- "docs:dev": "pnpm -C docs dev",
24
- "docs:build": "pnpm -C docs build",
25
- "docs:preview": "pnpm -C docs preview"
26
- },
27
- "devDependencies": {
28
- "@types/node": "^22.10.0",
29
- "tsx": "^4.19.0",
30
- "typescript": "^5.7.0"
16
+ "engines": {
17
+ "node": ">=18"
31
18
  },
32
- "dependencies": {
33
- "@inquirer/prompts": "^8.4.3",
34
- "commander": "^12.1.0",
35
- "yaml": "^2.6.1"
19
+ "optionalDependencies": {
20
+ "@dreamlake/dreamlake-cli-darwin-arm64": "0.9.1",
21
+ "@dreamlake/dreamlake-cli-darwin-x64": "0.9.1",
22
+ "@dreamlake/dreamlake-cli-linux-x64": "0.9.1",
23
+ "@dreamlake/dreamlake-cli-linux-arm64": "0.9.1",
24
+ "@dreamlake/dreamlake-cli-linux-x64-musl": "0.9.1",
25
+ "@dreamlake/dreamlake-cli-linux-arm64-musl": "0.9.1",
26
+ "@dreamlake/dreamlake-cli-win32-x64": "0.9.1",
27
+ "@dreamlake/dreamlake-cli-win32-arm64": "0.9.1"
36
28
  }
37
29
  }
package/README.md DELETED
@@ -1,171 +0,0 @@
1
- # dreamlake-cli
2
-
3
- `dreamlake` — a data-warehouse CLI for DreamLake. Uploads/downloads assets and
4
- manages episodes, bindrs, and datasets against a DreamLake server + BSS
5
- (big-streaming-server).
6
-
7
- It is a TypeScript port of the CLI shipped in
8
- [`dreamlake-py`](../dreamlake-workspace/dreamlake-py) (`dreamlake.cli`), built
9
- on the [`lakeshore`](../lakeshore) conventions (Commander + native `fetch`,
10
- pure ESM, token saved to a flat YAML file instead of the system keyring).
11
-
12
- > The compiled `dreamlake` binary shares its name with the Python `dreamlake`
13
- > entry point — this CLI is the TypeScript replacement. When both are on a
14
- > machine, `PATH` order decides which one runs.
15
-
16
- ## Install / run
17
-
18
- ```bash
19
- pnpm install
20
- pnpm cli --help # dev — runs the TS source through tsx
21
- pnpm build # emit dist/
22
- node bin/dreamlake.js … # prod — runs compiled dist/ (falls back to tsx in dev)
23
- ```
24
-
25
- ## Auth & environments
26
-
27
- The CLI knows two built-in environments — **`staging`** and **`prod`** — so you
28
- never type their URLs. Each environment keeps its own token; switch between them
29
- with one command.
30
-
31
- ```bash
32
- dreamlake login --env staging # device-authorization flow (opens browser)
33
- dreamlake login --env prod # built-in URLs; no --url/--bss needed
34
- dreamlake login # re-auth the active env (or staging if none)
35
-
36
- dreamlake env list # show logged-in envs (* = active)
37
- dreamlake env use prod # switch active env — no URLs, no re-login
38
- dreamlake env remove staging # forget a saved env
39
-
40
- dreamlake profile # current user (shows [env: ...])
41
- dreamlake logout # log out of the active env only
42
- ```
43
-
44
- Custom / self-hosted environments — define once, then switch by name forever:
45
-
46
- ```bash
47
- dreamlake login --env dev --url https://dev-api.example.com --bss https://dev-bss.example.com
48
- dreamlake env use dev
49
- ```
50
-
51
- Flags / env vars (`DREAMLAKE_REMOTE`, `DREAMLAKE_BSS_URL`, `DREAMLAKE_API_KEY`)
52
- still override the active environment for one-off commands. `--token <jwt>` saves
53
- a token directly (skip the device flow). `--auth <url>` overrides the vuer-auth
54
- server (built-ins set this automatically; staging needs `staging-auth.vuer.ai`).
55
-
56
- Credentials live in `~/.config/dreamlake/auth.yml`
57
- (`$XDG_CONFIG_HOME/dreamlake/auth.yml`, `chmod 600`) as a multi-environment file:
58
-
59
- ```yaml
60
- current: prod
61
- envs:
62
- staging: { server, bss, auth, namespace, token }
63
- prod: { server, bss, auth, namespace, token }
64
- ```
65
-
66
- ## Targets
67
-
68
- Most commands take a target string:
69
-
70
- ```
71
- --episode space[@namespace][:episode] # e.g. robotics@alice:2026/q1/run-042
72
- --project space[@namespace] # e.g. robotics@alice
73
- ```
74
-
75
- When `@namespace` is omitted it is resolved from your token (`/auth/me`).
76
-
77
- ## Commands
78
-
79
- ```bash
80
- # Upload — single file, or a flat directory (resumable). Type auto-detected.
81
- dreamlake upload ./mic.wav --episode robotics@alice:run-042 --to /microphone/front
82
- dreamlake upload ./clip.mp4 --episode robotics:run-042 --to /camera/front --bindr cam-set
83
- dreamlake upload ./capture/ --episode robotics@alice:run-042 --to /sensors --yes
84
-
85
- # Download — a single file, or a whole folder/episode recursively.
86
- dreamlake download --episode robotics@alice:run-042 --from /camera/front/clip.mp4 -o ./clip.mp4
87
- dreamlake download --episode robotics@alice:run-042 --from /camera -o ./out/
88
-
89
- # Projects. Private by default — pass --public (or --visibility public) to share.
90
- dreamlake create project my-robots --description "robot captures" # private
91
- dreamlake create project shared-set --public # public
92
- dreamlake update project my-robots --public # flip visibility later
93
- dreamlake list project
94
- dreamlake delete project my-robots # HARD-deletes the whole subtree
95
-
96
- # List — assets (default), or projects / bindrs / datasets / episodes.
97
- dreamlake list --episode robotics@alice:run-042 --type video
98
- dreamlake list project
99
- dreamlake list bindr --project robotics@alice
100
- dreamlake list dataset --project robotics@alice --json
101
- dreamlake list episode --project robotics@alice
102
-
103
- # Delete uploaded data (all HARD deletes — confirm prompt unless --yes).
104
- dreamlake delete file /camera/front/clip.mp4 --episode robotics@alice:run-042
105
- dreamlake delete episode run-042 --project robotics@alice
106
-
107
- # Bindrs (members are episodes, matched by node-path glob).
108
- dreamlake create bindr front-cam --project robotics@alice --episode "camera/front/*"
109
- dreamlake update bindr front-cam --project robotics@alice --add "2026/04/*"
110
- dreamlake delete bindr front-cam --project robotics@alice
111
-
112
- # Datasets (members are bindrs, matched by name glob).
113
- dreamlake create dataset train-v1 --project robotics@alice --tags robotics,training
114
- dreamlake update dataset train-v1 --project robotics@alice --add "front-*"
115
- dreamlake delete dataset train-v1 --project robotics@alice
116
- ```
117
-
118
- > Videos are just files — upload/list/download them with `upload` / `list --type video`
119
- > / `download`, no dedicated `video` command needed.
120
-
121
- ```bash
122
- # Organizations (GraphQL-backed; same token). Members resolve by email/name.
123
- dreamlake org list
124
- dreamlake org show my-org
125
- dreamlake org create my-org --name "My Org" --description "..." # you become OWNER + a namespace is created
126
- dreamlake org update my-org --description "..."
127
- dreamlake org delete my-org # must have no remaining projects
128
- dreamlake org leave my-org
129
- dreamlake org member list my-org
130
- dreamlake org member add my-org alice@example.com --role member
131
- dreamlake org member role my-org alice@example.com --role owner
132
- dreamlake org member remove my-org alice@example.com
133
-
134
- # Teams (scoped to an org; nestable via --parent; visible|secret).
135
- dreamlake team list # all teams you belong to
136
- dreamlake team list my-org # teams in one org
137
- dreamlake team show my-org backend
138
- dreamlake team create my-org backend --name "Backend" --visibility secret
139
- dreamlake team create my-org api --parent backend # nested team
140
- dreamlake team update my-org backend --visibility visible
141
- dreamlake team delete my-org backend # must have no child teams
142
- dreamlake team leave my-org backend
143
- dreamlake team member list my-org backend
144
- dreamlake team member add my-org backend alice@example.com --role maintainer
145
- dreamlake team member role my-org backend alice@example.com --role member
146
- dreamlake team member remove my-org backend alice@example.com
147
- ```
148
-
149
- ## Configuration
150
-
151
- Resolution precedence (high → low): flag → env var → saved `auth.yml` → default.
152
-
153
- | Setting | Env var | Default |
154
- | --- | --- | --- |
155
- | DreamLake server | `DREAMLAKE_REMOTE` | `http://localhost:10334` |
156
- | BSS server | `DREAMLAKE_BSS_URL` | `http://localhost:10234` |
157
- | Token | `DREAMLAKE_API_KEY` | (from `auth.yml`) |
158
-
159
- ## Not implemented
160
-
161
- By design, the CLI excludes the parts of `dreamlake-py` that aren't
162
- command-line-shaped: `vectorize` (CLIP/LLaVA inference + Zaku + Qdrant), the
163
- SDK-only rich types (`Video`/`TextTrack`/`VectorIndex`), and the deprecated
164
- Episode-tracking stack.
165
-
166
- ## Development
167
-
168
- ```bash
169
- pnpm test # tsc --noEmit + node --test (target/glob/kinds/credentials)
170
- pnpm build # tsc → dist/
171
- ```
@@ -1,240 +0,0 @@
1
- // `dreamlake login | logout | profile`.
2
- //
3
- // login: runs the device-authorization flow (default) or saves a token
4
- // passed via --token (lakeshore-style escape hatch). On success the
5
- // dreamlake token + resolved server/bss/namespace are written to
6
- // ~/.config/dreamlake/auth.yml (NOT the system keyring — see credentials.ts).
7
- //
8
- // profile: hits GET /auth/me, falling back to a local JWT decode when the
9
- // server is unreachable. logout: deletes the auth file.
10
- import { spawn } from "node:child_process";
11
- import { resolveRemote, resolveToken, decodeJwtPayload } from "../config.js";
12
- import { emitJson, renderTable } from "../helpers.js";
13
- import { authFilePath, builtinEnv, BUILTIN_ENVS, currentEnvName, listEnvs, removeEnv, saveEnv, useEnv, } from "./credentials.js";
14
- import { getOrCreateDeviceSecret } from "./device-secret.js";
15
- import { AuthorizationDeniedError, DeviceCodeExpiredError, DeviceFlowClient, TokenExchangeError, } from "./device-flow.js";
16
- async function fetchAuthMe(remote, token) {
17
- try {
18
- const res = await fetch(`${remote}/auth/me`, {
19
- headers: { Authorization: `Bearer ${token}` },
20
- signal: AbortSignal.timeout(5000),
21
- });
22
- if (res.ok)
23
- return (await res.json());
24
- }
25
- catch {
26
- // unreachable
27
- }
28
- return null;
29
- }
30
- function openBrowser(url) {
31
- const cmd = process.platform === "darwin"
32
- ? "open"
33
- : process.platform === "win32"
34
- ? "start"
35
- : "xdg-open";
36
- try {
37
- const child = spawn(cmd, [url], { stdio: "ignore", detached: true });
38
- child.on("error", () => { });
39
- child.unref();
40
- }
41
- catch {
42
- // best-effort
43
- }
44
- }
45
- export async function runLogin(args) {
46
- // Resolve which environment we're logging into and its URLs.
47
- const envName = args.env ?? currentEnvName() ?? "staging";
48
- const builtin = builtinEnv(envName);
49
- const remote = (args.url ?? builtin?.server)?.replace(/\/+$/, "");
50
- const bss = (args.bss ?? builtin?.bss)?.replace(/\/+$/, "");
51
- const auth = args.auth ?? builtin?.auth;
52
- if (!remote || !bss) {
53
- process.stderr.write(`✗ unknown environment '${envName}'. Either use a built-in (${Object.keys(BUILTIN_ENVS).join(", ")}) ` +
54
- `or define one: dreamlake login --env ${envName} --url <api> --bss <bss>\n`);
55
- return 1;
56
- }
57
- process.stderr.write(`Logging into environment '${envName}' (${remote})\n`);
58
- // ── Escape hatch: direct token (lakeshore style) ──────────────────
59
- if (args.token) {
60
- const me = await fetchAuthMe(remote, args.token);
61
- if (!me) {
62
- process.stderr.write(`✗ token validation failed against ${remote}/auth/me\n`);
63
- return 1;
64
- }
65
- const namespace = me.namespace?.slug ?? "";
66
- const p = saveEnv(envName, { server: remote, bss, auth, namespace, token: args.token });
67
- process.stdout.write(`✓ Saved env '${envName}' to ${p}\n` +
68
- ` server: ${remote}\n` +
69
- ` bss: ${bss}\n` +
70
- ` namespace: ${namespace || "(none)"}\n`);
71
- return 0;
72
- }
73
- // ── Device authorization flow ─────────────────────────────────────
74
- const deviceSecret = getOrCreateDeviceSecret();
75
- const client = new DeviceFlowClient(deviceSecret, remote, auth);
76
- let flow;
77
- try {
78
- process.stderr.write("Initializing device authorization...\n\n");
79
- flow = await client.startDeviceFlow();
80
- }
81
- catch (err) {
82
- process.stderr.write(`✗ ${err.message}\n`);
83
- return 1;
84
- }
85
- process.stdout.write(`DEVICE AUTHORIZATION REQUIRED\n\n` +
86
- ` 1. Visit: ${flow.verificationUri}\n` +
87
- ` 2. Enter code: ${flow.userCode}\n\n` +
88
- ` (code expires in ${Math.floor(flow.expiresIn / 60)} minutes)\n\n`);
89
- if (!args.noBrowser) {
90
- openBrowser(flow.verificationUriComplete);
91
- }
92
- process.stderr.write("Waiting for authorization...\n");
93
- let vuerToken;
94
- try {
95
- vuerToken = await client.pollForToken(120, (elapsed) => {
96
- if (process.stderr.isTTY) {
97
- process.stderr.write(`\r waiting (${elapsed}s)`);
98
- }
99
- });
100
- if (process.stderr.isTTY)
101
- process.stderr.write("\n");
102
- }
103
- catch (err) {
104
- if (process.stderr.isTTY)
105
- process.stderr.write("\n");
106
- if (err instanceof DeviceCodeExpiredError) {
107
- process.stderr.write("✗ Device code expired. Run 'dreamlake login' again.\n");
108
- }
109
- else if (err instanceof AuthorizationDeniedError) {
110
- process.stderr.write("✗ Authorization denied.\n");
111
- }
112
- else {
113
- process.stderr.write(`✗ ${err.message}\n`);
114
- }
115
- return 1;
116
- }
117
- let token;
118
- try {
119
- process.stderr.write("Exchanging token with DreamLake server...\n");
120
- token = await client.exchangeToken(vuerToken);
121
- }
122
- catch (err) {
123
- const msg = err instanceof TokenExchangeError ? err.message : err.message;
124
- process.stderr.write(`✗ ${msg}\n`);
125
- return 1;
126
- }
127
- const me = await fetchAuthMe(remote, token);
128
- const namespace = me?.namespace?.slug ?? "";
129
- saveEnv(envName, { server: remote, bss, auth, namespace, token });
130
- process.stdout.write(`✓ Logged in to '${envName}' (now active)\n` +
131
- ` server: ${remote}\n` +
132
- ` bss: ${bss}\n` +
133
- ` namespace: ${namespace || "(none)"}\n`);
134
- return 0;
135
- }
136
- // ─── logout ──────────────────────────────────────────────────────────
137
- export async function runLogout() {
138
- const name = currentEnvName();
139
- if (!name) {
140
- process.stdout.write(`No active environment (${authFilePath()})\n`);
141
- return 0;
142
- }
143
- removeEnv(name);
144
- const next = currentEnvName();
145
- process.stdout.write(`✓ Logged out of '${name}'.` +
146
- (next ? ` Active environment is now '${next}'.\n` : " No environments left.\n"));
147
- return 0;
148
- }
149
- // ─── env (environment switching) ──────────────────────────────────────
150
- export async function runEnvList(opts) {
151
- const envs = listEnvs();
152
- if (opts.json) {
153
- emitJson(envs.map((e) => ({
154
- name: e.name,
155
- current: e.current,
156
- server: e.env.server,
157
- bss: e.env.bss,
158
- namespace: e.env.namespace,
159
- })));
160
- return 0;
161
- }
162
- process.stdout.write("Environments\n\n");
163
- if (envs.length === 0) {
164
- process.stdout.write(` (none logged in)\n hint: dreamlake login --env staging (built-in: ${Object.keys(BUILTIN_ENVS).join(", ")})\n`);
165
- return 0;
166
- }
167
- const rows = envs.map((e) => ({
168
- "": e.current ? "*" : "",
169
- name: e.name,
170
- server: e.env.server,
171
- namespace: e.env.namespace || "(none)",
172
- }));
173
- process.stdout.write(renderTable(rows, ["", "name", "server", "namespace"]));
174
- return 0;
175
- }
176
- export async function runEnvUse(name) {
177
- if (useEnv(name)) {
178
- process.stdout.write(`✓ Active environment is now '${name}'\n`);
179
- return 0;
180
- }
181
- const known = listEnvs().map((e) => e.name);
182
- process.stderr.write(`✗ environment '${name}' is not logged in.\n` +
183
- (known.length ? ` logged in: ${known.join(", ")}\n` : "") +
184
- ` log in with: dreamlake login --env ${name}\n`);
185
- return 1;
186
- }
187
- export async function runEnvRemove(name) {
188
- if (removeEnv(name)) {
189
- process.stdout.write(`✓ Removed environment '${name}'\n`);
190
- return 0;
191
- }
192
- process.stderr.write(`✗ environment '${name}' not found\n`);
193
- return 1;
194
- }
195
- export async function runProfile(args) {
196
- const token = resolveToken();
197
- if (!token) {
198
- process.stdout.write("Not logged in. Run: dreamlake login\n");
199
- return 1;
200
- }
201
- const remote = resolveRemote(args.url);
202
- const me = await fetchAuthMe(remote, token);
203
- if (me) {
204
- const envName = currentEnvName();
205
- process.stdout.write(`Current DreamLake user${envName ? ` [env: ${envName}]` : ""}\n`);
206
- for (const field of ["id", "sub", "username", "name", "email"]) {
207
- if (me[field] != null)
208
- process.stdout.write(` ${field}: ${me[field]}\n`);
209
- }
210
- if (me.namespace?.slug) {
211
- process.stdout.write(` namespace: ${me.namespace.slug} (id: ${me.namespace.id ?? "?"})\n`);
212
- }
213
- if (me.createdAt) {
214
- process.stdout.write(` member since: ${String(me.createdAt).slice(0, 10)}\n`);
215
- }
216
- return 0;
217
- }
218
- // Fallback: decode JWT locally.
219
- process.stderr.write("⚠ could not reach server, showing local token info.\n");
220
- const payload = decodeJwtPayload(token);
221
- if (Object.keys(payload).length === 0) {
222
- process.stdout.write("Failed to decode token. Please log in again.\n");
223
- return 1;
224
- }
225
- process.stdout.write("Current DreamLake user (from token)\n");
226
- for (const field of ["sub", "username", "name", "email"]) {
227
- if (payload[field] != null) {
228
- process.stdout.write(` ${field}: ${payload[field]}\n`);
229
- }
230
- }
231
- const exp = payload.exp;
232
- if (typeof exp === "number") {
233
- const expired = exp < Date.now() / 1000;
234
- process.stdout.write(` expires: ${new Date(exp * 1000).toISOString()}${expired ? " (EXPIRED)" : ""}\n`);
235
- }
236
- else {
237
- process.stdout.write(" expires: never (long-lived token)\n");
238
- }
239
- return 0;
240
- }
@@ -1,16 +0,0 @@
1
- // Authentication constants — port of dreamlake-py's auth/constants.py.
2
- /**
3
- * Vuer-auth server URL (device-flow provider). Resolved lazily so a
4
- * `--auth` flag / late env assignment can override it. NOTE: this must
5
- * match the auth server the TARGET dreamlake-server trusts — e.g.
6
- * staging-api.dreamlake.ai validates tokens from staging-auth.vuer.ai,
7
- * not the production auth.vuer.ai (mismatched keys → "No matching key
8
- * found in JWKS").
9
- */
10
- export function vuerAuthUrl(override) {
11
- return (override || process.env.VUER_AUTH_URL || "https://auth.vuer.ai").replace(/\/+$/, "");
12
- }
13
- /** OAuth client ID for dreamlake. */
14
- export const CLIENT_ID = "dreamlake-client";
15
- /** Default OAuth scopes. */
16
- export const DEFAULT_SCOPE = "openid profile email";