@dench.com/cli 2.1.4 → 2.1.5

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 (2) hide show
  1. package/dench.ts +58 -6
  2. package/package.json +1 -1
package/dench.ts CHANGED
@@ -2351,6 +2351,7 @@ async function getRuntime() {
2351
2351
  return {
2352
2352
  mode: "session" as const,
2353
2353
  host: resolveApiHost(host),
2354
+ convexUrl: stored.session.convexUrl,
2354
2355
  client: createCliConvexClient(stored.session.convexUrl),
2355
2356
  sessionToken: stored.session.sessionToken,
2356
2357
  organization: stored.session.organization,
@@ -2397,6 +2398,7 @@ async function getRuntime() {
2397
2398
  return {
2398
2399
  mode: "apiKey" as const,
2399
2400
  host: apiHost,
2401
+ convexUrl: sandboxConvexUrl,
2400
2402
  client: createCliConvexClient(sandboxConvexUrl),
2401
2403
  sessionToken: apiKey,
2402
2404
  organization: sandboxOrganization,
@@ -2412,6 +2414,7 @@ async function getRuntime() {
2412
2414
  return {
2413
2415
  mode: "session" as const,
2414
2416
  host: apiHost,
2417
+ convexUrl: sandboxConvexUrl,
2415
2418
  client: createCliConvexClient(sandboxConvexUrl),
2416
2419
  sessionToken: sandboxAgentToken,
2417
2420
  organization: sandboxOrganization,
@@ -2981,13 +2984,44 @@ function suggestedWorkFromArtifacts(artifacts: JsonRecord[]) {
2981
2984
  );
2982
2985
  }
2983
2986
 
2987
+ /**
2988
+ * The fs daemon authenticates purely from `CONVEX_URL` + `DENCH_API_KEY`
2989
+ * env vars (sandboxes bake them in). Local shells running off an OAuth
2990
+ * agent session have neither — resolve the active session and inject
2991
+ * its convexUrl + `dch_agent_*` token. The server-side files functions
2992
+ * accept the agent-session token in the same `apiKey` slot (prefix
2993
+ * dispatch, like `requireCrmAccess`), so the daemon works unchanged.
2994
+ */
2995
+ async function resolveFsDaemonEnv(): Promise<NodeJS.ProcessEnv> {
2996
+ if (process.env.CONVEX_URL?.trim() && process.env.DENCH_API_KEY?.trim()) {
2997
+ return process.env;
2998
+ }
2999
+ try {
3000
+ const runtime = await getRuntime();
3001
+ if (runtime.mode === "session" || runtime.mode === "apiKey") {
3002
+ return {
3003
+ ...process.env,
3004
+ CONVEX_URL: process.env.CONVEX_URL?.trim() || runtime.convexUrl,
3005
+ DENCH_API_KEY:
3006
+ process.env.DENCH_API_KEY?.trim() || runtime.sessionToken,
3007
+ };
3008
+ }
3009
+ } catch {
3010
+ // No saved session / dev env — fall through with the unmodified env;
3011
+ // the daemon prints its own missing-credential error for subcommands
3012
+ // that need Convex access.
3013
+ }
3014
+ return process.env;
3015
+ }
3016
+
2984
3017
  async function runFsCommand() {
2985
3018
  const subArgs = args.slice(args.indexOf("fs") + 1);
2986
3019
  const configuredBinary = process.env.DENCH_FS_DAEMON_BIN?.trim();
2987
3020
  const binary = configuredBinary || "dench-fs-daemon";
3021
+ const daemonEnv = await resolveFsDaemonEnv();
2988
3022
  let exitCode: number;
2989
3023
  try {
2990
- exitCode = await spawnInherited(binary, subArgs);
3024
+ exitCode = await spawnInherited(binary, subArgs, daemonEnv);
2991
3025
  } catch (error) {
2992
3026
  if (configuredBinary || !isCommandNotFound(error)) {
2993
3027
  throw error;
@@ -2995,7 +3029,11 @@ async function runFsCommand() {
2995
3029
  const localDaemon = fileURLToPath(
2996
3030
  new URL("./fs-daemon.ts", import.meta.url),
2997
3031
  );
2998
- exitCode = await spawnInherited("bun", [localDaemon, ...subArgs]);
3032
+ exitCode = await spawnInherited(
3033
+ "bun",
3034
+ [localDaemon, ...subArgs],
3035
+ daemonEnv,
3036
+ );
2999
3037
  }
3000
3038
  if (exitCode !== 0) {
3001
3039
  process.exitCode = exitCode;
@@ -3025,8 +3063,18 @@ async function requireFilesApiKey(
3025
3063
  runtime: Runtime,
3026
3064
  command: string,
3027
3065
  ): Promise<string> {
3028
- const auth = await resolveGatewayCommandAuth(runtime, command);
3029
- return auth.bearerToken;
3066
+ // The Convex files functions accept either a unified Dench API key OR a
3067
+ // `dch_agent_*` OAuth agent-session token in their `apiKey` arg (the
3068
+ // server dispatches on prefix, same as `requireCrmAccess`). So the
3069
+ // runtime's own bearer works directly — no gateway-key exchange, which
3070
+ // used to gate OAuth sessions behind a paid workspace and an extra
3071
+ // host round-trip.
3072
+ if (runtime.mode === "session" || runtime.mode === "apiKey") {
3073
+ return runtime.sessionToken;
3074
+ }
3075
+ const envApiKey = process.env.DENCH_API_KEY?.trim();
3076
+ if (envApiKey) return envApiKey;
3077
+ throw loginRequiredError(command);
3030
3078
  }
3031
3079
 
3032
3080
  type FileTreeRow = {
@@ -3603,11 +3651,15 @@ function sha256HexSync(bytes: Uint8Array): string {
3603
3651
  return createHash("sha256").update(bytes).digest("hex");
3604
3652
  }
3605
3653
 
3606
- async function spawnInherited(binary: string, commandArgs: string[]) {
3654
+ async function spawnInherited(
3655
+ binary: string,
3656
+ commandArgs: string[],
3657
+ env: NodeJS.ProcessEnv = process.env,
3658
+ ) {
3607
3659
  return await new Promise<number>((resolve, reject) => {
3608
3660
  const child = spawn(binary, commandArgs, {
3609
3661
  stdio: "inherit",
3610
- env: process.env,
3662
+ env,
3611
3663
  });
3612
3664
  child.on("error", reject);
3613
3665
  child.on("close", (code) => resolve(code ?? 1));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dench.com/cli",
3
- "version": "2.1.4",
3
+ "version": "2.1.5",
4
4
  "description": "Dench agent workspace CLI. v2 unifies auth behind `dench signin`; the legacy `dench login` / `dench onboard` / `dench setup` / `dench what-can-i-do` / `dench register` commands now error with a redirect.",
5
5
  "type": "module",
6
6
  "bin": {