@dench.com/cli 0.4.2 → 0.4.4

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.
@@ -0,0 +1,102 @@
1
+ // When `./dench` (or `./dench.mjs`) runs through Node from inside the
2
+ // dench.com source tree, Node does not auto-load workspace `.env` files
3
+ // the way Bun does for `bun run`. That made every gateway-backed
4
+ // subcommand (`dench apps`, `dench tool …`, the enrichment helpers,
5
+ // etc.) silently default to production
6
+ // (`https://gateway.merseoriginals.com`), because `cli/tools.ts`
7
+ // resolves the gateway URL purely from `process.env`. A dev-issued
8
+ // `DENCH_API_KEY` then 401'd against prod with `invalid_api_key`.
9
+ //
10
+ // This helper detects the dench.com source tree (via the parent
11
+ // `package.json` name) and loads `.env` then `.env.local` from the repo
12
+ // root. Globally-installed and sandbox-baked CLI installs never see
13
+ // that marker, so this is a no-op there. Existing `process.env` values
14
+ // always win, so explicit shell exports (e.g.
15
+ // `GATEWAY_URL=… ./dench …`) still take precedence over file values.
16
+
17
+ import { existsSync, readFileSync } from "node:fs";
18
+ import { dirname, join } from "node:path";
19
+ import { fileURLToPath } from "node:url";
20
+
21
+ const WORKSPACE_PACKAGE_NAME = "ironclaw-cloud";
22
+ const ENV_FILES = [".env", ".env.local"];
23
+
24
+ export function loadDevEnv(callerUrl) {
25
+ try {
26
+ const here = dirname(fileURLToPath(callerUrl));
27
+ const repoRoot = dirname(here);
28
+ const pkgPath = join(repoRoot, "package.json");
29
+ if (!existsSync(pkgPath)) return;
30
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
31
+ if (pkg?.name !== WORKSPACE_PACKAGE_NAME) return;
32
+
33
+ for (const filename of ENV_FILES) {
34
+ const path = join(repoRoot, filename);
35
+ if (!existsSync(path)) continue;
36
+ const text = readFileSync(path, "utf8");
37
+ for (const [key, value] of parseEnv(text)) {
38
+ if (key in process.env) continue;
39
+ process.env[key] = value;
40
+ }
41
+ }
42
+ } catch {
43
+ // Never break the CLI just because env loading failed.
44
+ }
45
+ }
46
+
47
+ // Minimal `.env` parser: handles `KEY=value`, `KEY="value"`, `KEY='value'`,
48
+ // `export KEY=value`, comments, blank lines, and multi-line double-quoted
49
+ // values (e.g. JWT_PRIVATE_KEY="-----BEGIN ... -----END ..."). Skips lines
50
+ // that don't match the shape rather than throwing.
51
+ function* parseEnv(text) {
52
+ let i = 0;
53
+ while (i < text.length) {
54
+ while (i < text.length && /\s/.test(text[i])) i++;
55
+ if (i >= text.length) break;
56
+ if (text[i] === "#") {
57
+ while (i < text.length && text[i] !== "\n") i++;
58
+ continue;
59
+ }
60
+ if (text.startsWith("export ", i)) i += 7;
61
+ while (i < text.length && (text[i] === " " || text[i] === "\t")) i++;
62
+
63
+ const keyStart = i;
64
+ while (i < text.length && /[A-Za-z0-9_]/.test(text[i])) i++;
65
+ const key = text.slice(keyStart, i);
66
+ if (!key || text[i] !== "=") {
67
+ while (i < text.length && text[i] !== "\n") i++;
68
+ continue;
69
+ }
70
+ i++;
71
+
72
+ let value;
73
+ if (text[i] === '"' || text[i] === "'") {
74
+ const quote = text[i++];
75
+ const valStart = i;
76
+ while (i < text.length && text[i] !== quote) {
77
+ if (quote === '"' && text[i] === "\\" && i + 1 < text.length) {
78
+ i += 2;
79
+ } else {
80
+ i++;
81
+ }
82
+ }
83
+ value = text.slice(valStart, i);
84
+ if (quote === '"') {
85
+ value = value
86
+ .replace(/\\n/g, "\n")
87
+ .replace(/\\r/g, "\r")
88
+ .replace(/\\t/g, "\t")
89
+ .replace(/\\"/g, '"')
90
+ .replace(/\\\\/g, "\\");
91
+ }
92
+ if (text[i] === quote) i++;
93
+ } else {
94
+ const valStart = i;
95
+ while (i < text.length && text[i] !== "\n" && text[i] !== "#") i++;
96
+ value = text.slice(valStart, i).trim();
97
+ }
98
+
99
+ while (i < text.length && text[i] !== "\n") i++;
100
+ yield [key, value];
101
+ }
102
+ }
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "@dench.com/cli",
3
- "version": "0.4.2",
3
+ "version": "0.4.4",
4
4
  "description": "Dench agent workspace CLI.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "dench": "dench",
8
- "dench-fs-daemon": "fs-daemon"
8
+ "dench-fs-daemon": "fs-daemon",
9
+ "dench-home-sync": "home-sync"
9
10
  },
10
11
  "files": [
11
12
  "dench",
@@ -13,7 +14,12 @@
13
14
  "dench.ts",
14
15
  "fs-daemon",
15
16
  "fs-daemon.ts",
17
+ "fs-daemon-binary.ts",
18
+ "fs-daemon-flush.ts",
16
19
  "fs-daemon-mount.ts",
20
+ "home-sync",
21
+ "home-sync.ts",
22
+ "home-sync-lib.ts",
17
23
  "agent.ts",
18
24
  "chat.ts",
19
25
  "chat-spawn.ts",