deepline 0.1.32 → 0.1.33

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/dist/index.d.mts CHANGED
@@ -186,7 +186,7 @@ type PlayCompilerManifest = {
186
186
  interface DeeplineClientOptions {
187
187
  /** API key. Overrides `DEEPLINE_API_KEY` env var and CLI-stored keys. */
188
188
  apiKey?: string;
189
- /** Base URL of the Deepline API. Overrides `DEEPLINE_ORIGIN_URL` / `DEEPLINE_API_BASE_URL`. */
189
+ /** Base URL of the Deepline API. Overrides `DEEPLINE_HOST_URL`. */
190
190
  baseUrl?: string;
191
191
  /** Per-request timeout in milliseconds. Default: `60_000` (60 seconds). */
192
192
  timeout?: number;
@@ -393,6 +393,8 @@ interface PlayStatus {
393
393
  name?: string;
394
394
  /** Alias for `name` used by run/result APIs. */
395
395
  playName?: string;
396
+ /** Dashboard URL for inspecting the play and its run output in the app. */
397
+ dashboardUrl?: string;
396
398
  /** Product-level play-run state. */
397
399
  status: 'queued' | 'running' | 'waiting' | 'completed' | 'failed' | 'cancelled';
398
400
  /** Execution progress with logs and error details. */
@@ -1438,8 +1440,8 @@ declare class DeeplineClient {
1438
1440
  }>;
1439
1441
  }
1440
1442
 
1441
- declare const SDK_VERSION = "0.1.32";
1442
- declare const SDK_API_CONTRACT = "2026-05-generic-play-input-flags";
1443
+ declare const SDK_VERSION = "0.1.33";
1444
+ declare const SDK_API_CONTRACT = "2026-05-host-env-generic-play-input-flags";
1443
1445
 
1444
1446
  /**
1445
1447
  * Base error class for all Deepline SDK errors.
@@ -1557,27 +1559,7 @@ declare class ConfigError extends DeeplineError {
1557
1559
  /** Production API base URL. */
1558
1560
  declare const PROD_URL = "https://code.deepline.com";
1559
1561
  /**
1560
- * Resolve SDK configuration from all available sources.
1561
- *
1562
- * Merges explicit options, environment variables, and CLI-managed config files
1563
- * into a fully validated {@link ResolvedConfig}. See the module-level docs for
1564
- * the complete resolution order.
1565
- *
1566
- * @param options - Optional overrides (highest priority)
1567
- * @returns Fully resolved configuration with all fields populated
1568
- * @throws {@link ConfigError} if no API key can be found from any source
1569
- *
1570
- * @example
1571
- * ```typescript
1572
- * import { resolveConfig } from 'deepline';
1573
- *
1574
- * // Auto-resolve everything:
1575
- * const config = resolveConfig();
1576
- * console.log(config.baseUrl); // "http://localhost:3000" or "https://code.deepline.com"
1577
- *
1578
- * // Override specific values:
1579
- * const config2 = resolveConfig({ baseUrl: 'http://localhost:4000', timeout: 10_000 });
1580
- * ```
1562
+ * Resolve SDK configuration from the public SDK CLI env contract.
1581
1563
  */
1582
1564
  declare function resolveConfig(options?: DeeplineClientOptions): ResolvedConfig;
1583
1565
 
package/dist/index.d.ts CHANGED
@@ -186,7 +186,7 @@ type PlayCompilerManifest = {
186
186
  interface DeeplineClientOptions {
187
187
  /** API key. Overrides `DEEPLINE_API_KEY` env var and CLI-stored keys. */
188
188
  apiKey?: string;
189
- /** Base URL of the Deepline API. Overrides `DEEPLINE_ORIGIN_URL` / `DEEPLINE_API_BASE_URL`. */
189
+ /** Base URL of the Deepline API. Overrides `DEEPLINE_HOST_URL`. */
190
190
  baseUrl?: string;
191
191
  /** Per-request timeout in milliseconds. Default: `60_000` (60 seconds). */
192
192
  timeout?: number;
@@ -393,6 +393,8 @@ interface PlayStatus {
393
393
  name?: string;
394
394
  /** Alias for `name` used by run/result APIs. */
395
395
  playName?: string;
396
+ /** Dashboard URL for inspecting the play and its run output in the app. */
397
+ dashboardUrl?: string;
396
398
  /** Product-level play-run state. */
397
399
  status: 'queued' | 'running' | 'waiting' | 'completed' | 'failed' | 'cancelled';
398
400
  /** Execution progress with logs and error details. */
@@ -1438,8 +1440,8 @@ declare class DeeplineClient {
1438
1440
  }>;
1439
1441
  }
1440
1442
 
1441
- declare const SDK_VERSION = "0.1.32";
1442
- declare const SDK_API_CONTRACT = "2026-05-generic-play-input-flags";
1443
+ declare const SDK_VERSION = "0.1.33";
1444
+ declare const SDK_API_CONTRACT = "2026-05-host-env-generic-play-input-flags";
1443
1445
 
1444
1446
  /**
1445
1447
  * Base error class for all Deepline SDK errors.
@@ -1557,27 +1559,7 @@ declare class ConfigError extends DeeplineError {
1557
1559
  /** Production API base URL. */
1558
1560
  declare const PROD_URL = "https://code.deepline.com";
1559
1561
  /**
1560
- * Resolve SDK configuration from all available sources.
1561
- *
1562
- * Merges explicit options, environment variables, and CLI-managed config files
1563
- * into a fully validated {@link ResolvedConfig}. See the module-level docs for
1564
- * the complete resolution order.
1565
- *
1566
- * @param options - Optional overrides (highest priority)
1567
- * @returns Fully resolved configuration with all fields populated
1568
- * @throws {@link ConfigError} if no API key can be found from any source
1569
- *
1570
- * @example
1571
- * ```typescript
1572
- * import { resolveConfig } from 'deepline';
1573
- *
1574
- * // Auto-resolve everything:
1575
- * const config = resolveConfig();
1576
- * console.log(config.baseUrl); // "http://localhost:3000" or "https://code.deepline.com"
1577
- *
1578
- * // Override specific values:
1579
- * const config2 = resolveConfig({ baseUrl: 'http://localhost:4000', timeout: 10_000 });
1580
- * ```
1562
+ * Resolve SDK configuration from the public SDK CLI env contract.
1581
1563
  */
1582
1564
  declare function resolveConfig(options?: DeeplineClientOptions): ResolvedConfig;
1583
1565
 
package/dist/index.js CHANGED
@@ -85,13 +85,12 @@ var ConfigError = class extends DeeplineError {
85
85
  };
86
86
 
87
87
  // src/config.ts
88
+ var HOST_URL_ENV = "DEEPLINE_HOST_URL";
89
+ var API_KEY_ENV = "DEEPLINE_API_KEY";
88
90
  var PROD_URL = "https://code.deepline.com";
89
91
  var DEFAULT_TIMEOUT = 6e4;
90
92
  var DEFAULT_MAX_RETRIES = 3;
91
- var ACTIVE_DEEPLINE_ENV_FILE = ".env.deepline";
92
- function projectEnvStartDir() {
93
- return process.env.DEEPLINE_PROJECT_ENV_DIR?.trim() || process.cwd();
94
- }
93
+ var PROJECT_DEEPLINE_ENV_FILE = ".env.deepline";
95
94
  function baseUrlSlug(baseUrl) {
96
95
  let url;
97
96
  try {
@@ -100,7 +99,7 @@ function baseUrlSlug(baseUrl) {
100
99
  return "unknown";
101
100
  }
102
101
  const host = url.hostname || "unknown";
103
- const port = url.port ? parseInt(url.port, 10) : null;
102
+ const port = url.port ? Number.parseInt(url.port, 10) : null;
104
103
  let slug = host.replace(/[^a-zA-Z0-9]/g, "-");
105
104
  if (port && port !== 80 && port !== 443) {
106
105
  slug = `${slug}-${port}`;
@@ -127,109 +126,84 @@ function parseEnvFile(filePath) {
127
126
  }
128
127
  return env;
129
128
  }
130
- function findNearestEnvFile(names, startDir = process.cwd()) {
129
+ function findNearestEnvFile(name, startDir = process.cwd()) {
131
130
  let current = (0, import_node_path.resolve)(startDir);
132
131
  while (true) {
133
- for (const name of names) {
134
- const filePath = (0, import_node_path.join)(current, name);
135
- if ((0, import_node_fs.existsSync)(filePath)) return filePath;
136
- }
132
+ const filePath = (0, import_node_path.join)(current, name);
133
+ if ((0, import_node_fs.existsSync)(filePath)) return filePath;
137
134
  const parent = (0, import_node_path.dirname)(current);
138
135
  if (parent === current) return null;
139
136
  current = parent;
140
137
  }
141
138
  }
142
- function findNearestEnv(names, startDir = process.cwd()) {
143
- const filePath = findNearestEnvFile(names, startDir);
139
+ function loadProjectDeeplineEnv(startDir = process.cwd()) {
140
+ const filePath = findNearestEnvFile(PROJECT_DEEPLINE_ENV_FILE, startDir);
144
141
  return filePath ? parseEnvFile(filePath) : {};
145
142
  }
146
- function findNearestWorktreeEnv(startDir = process.cwd()) {
147
- return findNearestEnv([".env.worktree"], startDir);
148
- }
149
- function resolveProfileEnvFileNames() {
150
- const explicitProfile = process.env.DEEPLINE_ENV_PROFILE?.trim() || process.env.DEEPLINE_PROFILE?.trim() || "";
151
- const names = [];
152
- if (explicitProfile) names.push(`.env.deepline.${explicitProfile}`);
153
- const nodeEnv = process.env.NODE_ENV?.trim();
154
- if (nodeEnv === "production") names.push(".env.deepline.prod");
155
- else if (nodeEnv === "staging") names.push(".env.deepline.staging");
156
- names.push(ACTIVE_DEEPLINE_ENV_FILE);
157
- return names;
158
- }
159
- function resolveProjectAppEnvFileNames() {
160
- const nodeEnv = process.env.NODE_ENV?.trim();
161
- const names = [];
162
- if (nodeEnv === "production") names.push(".env.prod");
163
- if (nodeEnv === "staging") names.push(".env.staging");
164
- names.push(".env.local", ".env");
165
- return names;
166
- }
167
- function resolveBaseUrlFromEnvValues(env) {
168
- return env.DEEPLINE_ORIGIN_URL?.trim() || env.DEEPLINE_API_BASE_URL?.trim() || "";
169
- }
170
- function loadProjectDeeplineEnv() {
171
- return findNearestEnv(resolveProfileEnvFileNames(), projectEnvStartDir());
172
- }
173
- function loadProjectAppEnv() {
174
- return findNearestEnv(resolveProjectAppEnvFileNames(), projectEnvStartDir());
175
- }
176
- function normalizeWorktreeBaseUrl(baseUrl, worktreeEnv = findNearestWorktreeEnv()) {
177
- const trimmed = baseUrl.trim().replace(/\/$/, "");
178
- if (!trimmed) return trimmed;
143
+ function normalizeBaseUrl(baseUrl) {
144
+ const trimmed = baseUrl.trim().replace(/\/+$/, "");
145
+ if (!trimmed) return "";
179
146
  try {
180
147
  const parsed = new URL(trimmed);
181
- if (parsed.hostname.endsWith(".localhost") && parsed.port === "1355") {
182
- const port = worktreeEnv.WORKTREE_APP_PORT || worktreeEnv.PORT;
183
- if (port) return `${parsed.protocol}//localhost:${port}`;
148
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
149
+ return "";
184
150
  }
151
+ return parsed.toString().replace(/\/+$/, "");
185
152
  } catch {
153
+ return "";
154
+ }
155
+ }
156
+ function firstNonEmpty(...values) {
157
+ for (const value of values) {
158
+ const trimmed = value?.trim();
159
+ if (trimmed) return trimmed;
186
160
  }
187
- return trimmed;
161
+ return "";
188
162
  }
189
- function resolveWorktreeBaseUrl() {
190
- const worktreeEnv = findNearestWorktreeEnv();
191
- const declared = worktreeEnv.DEEPLINE_API_BASE_URL || worktreeEnv.WORKTREE_PUBLIC_APP_URL || worktreeEnv.APP_URL || "";
192
- if (declared) return normalizeWorktreeBaseUrl(declared, worktreeEnv);
193
- const port = worktreeEnv.WORKTREE_APP_PORT || worktreeEnv.PORT || "";
194
- return port ? `http://localhost:${port}` : "";
163
+ function sdkCliConfigDir(baseUrl) {
164
+ const home = process.env.HOME?.trim() || (0, import_node_os.homedir)();
165
+ return (0, import_node_path.join)(home, ".local", "deepline", baseUrlSlug(baseUrl || PROD_URL));
195
166
  }
196
167
  function sdkCliEnvFilePath(baseUrl) {
197
- const home = process.env.HOME?.trim() || (0, import_node_os.homedir)();
198
- return (0, import_node_path.join)(home, ".local", "deepline", baseUrlSlug(baseUrl || PROD_URL), ".env");
168
+ return (0, import_node_path.join)(sdkCliConfigDir(baseUrl), ".env");
199
169
  }
200
170
  function loadCliEnv(baseUrl = PROD_URL) {
201
- const envPath = sdkCliEnvFilePath(baseUrl);
202
- return parseEnvFile(envPath);
171
+ return parseEnvFile(sdkCliEnvFilePath(baseUrl));
203
172
  }
204
173
  function loadGlobalCliEnv() {
205
174
  return loadCliEnv(PROD_URL);
206
175
  }
207
176
  function autoDetectBaseUrl() {
208
- const envOrigin = process.env.DEEPLINE_ORIGIN_URL?.trim();
209
- if (envOrigin) return normalizeWorktreeBaseUrl(envOrigin);
210
- const envBase = process.env.DEEPLINE_API_BASE_URL?.trim();
211
- if (envBase) return normalizeWorktreeBaseUrl(envBase);
212
- const projectDeeplineBaseUrl = resolveBaseUrlFromEnvValues(loadProjectDeeplineEnv());
213
- if (projectDeeplineBaseUrl) return normalizeWorktreeBaseUrl(projectDeeplineBaseUrl);
214
- const projectAppBaseUrl = resolveBaseUrlFromEnvValues(loadProjectAppEnv());
215
- if (projectAppBaseUrl) return normalizeWorktreeBaseUrl(projectAppBaseUrl);
216
- const worktreeBaseUrl = resolveWorktreeBaseUrl();
217
- if (worktreeBaseUrl) return worktreeBaseUrl;
177
+ const projectEnv = loadProjectDeeplineEnv();
218
178
  const globalEnv = loadGlobalCliEnv();
219
- const globalOrigin = globalEnv.DEEPLINE_ORIGIN_URL?.trim();
220
- if (globalOrigin) return normalizeWorktreeBaseUrl(globalOrigin);
221
- return PROD_URL;
179
+ return normalizeBaseUrl(process.env[HOST_URL_ENV] ?? "") || normalizeBaseUrl(projectEnv[HOST_URL_ENV] ?? "") || normalizeBaseUrl(globalEnv[HOST_URL_ENV] ?? "") || PROD_URL;
180
+ }
181
+ function resolveApiKeyForBaseUrl(baseUrl, explicitApiKey) {
182
+ const normalizedBaseUrl = normalizeBaseUrl(baseUrl);
183
+ const projectEnv = loadProjectDeeplineEnv();
184
+ const cliEnv = loadCliEnv(normalizedBaseUrl || baseUrl);
185
+ const projectBaseUrl = normalizeBaseUrl(projectEnv[HOST_URL_ENV] ?? "");
186
+ const projectKeyApplies = projectBaseUrl === normalizedBaseUrl;
187
+ return firstNonEmpty(
188
+ explicitApiKey,
189
+ process.env[API_KEY_ENV],
190
+ projectKeyApplies ? projectEnv[API_KEY_ENV] : "",
191
+ cliEnv[API_KEY_ENV]
192
+ );
222
193
  }
223
194
  function resolveConfig(options) {
224
- const requestedBaseUrl = options?.baseUrl?.trim() || autoDetectBaseUrl();
225
- const baseUrl = normalizeWorktreeBaseUrl(requestedBaseUrl);
226
- const cliEnv = loadCliEnv(baseUrl);
227
- const projectDeeplineEnv = loadProjectDeeplineEnv();
228
- const projectAppEnv = loadProjectAppEnv();
229
- const apiKey = options?.apiKey?.trim() || process.env.DEEPLINE_API_KEY?.trim() || projectDeeplineEnv.DEEPLINE_API_KEY || projectAppEnv.DEEPLINE_API_KEY || cliEnv.DEEPLINE_API_KEY || "";
195
+ const baseUrl = normalizeBaseUrl(
196
+ options?.baseUrl?.trim() || autoDetectBaseUrl()
197
+ );
198
+ if (!baseUrl) {
199
+ throw new ConfigError(
200
+ `Invalid ${HOST_URL_ENV}. Expected an http(s) URL such as https://code.deepline.com.`
201
+ );
202
+ }
203
+ const apiKey = resolveApiKeyForBaseUrl(baseUrl, options?.apiKey);
230
204
  if (!apiKey) {
231
205
  throw new ConfigError(
232
- `No API key found. Set DEEPLINE_API_KEY env var, pass apiKey option, or run: deepline auth register`
206
+ `No API key found. Set ${API_KEY_ENV}, add it to .env.deepline, or run: deepline auth register`
233
207
  );
234
208
  }
235
209
  return {
@@ -241,8 +215,8 @@ function resolveConfig(options) {
241
215
  }
242
216
 
243
217
  // src/version.ts
244
- var SDK_VERSION = "0.1.32";
245
- var SDK_API_CONTRACT = "2026-05-generic-play-input-flags";
218
+ var SDK_VERSION = "0.1.33";
219
+ var SDK_API_CONTRACT = "2026-05-host-env-generic-play-input-flags";
246
220
 
247
221
  // ../shared_libs/play-runtime/coordinator-headers.ts
248
222
  var COORDINATOR_INTERNAL_TOKEN_HEADER = "x-deepline-internal-token";
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/config.ts
2
- import { readFileSync, existsSync, mkdirSync, writeFileSync } from "fs";
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
3
3
  import { homedir } from "os";
4
4
  import { dirname, join, resolve } from "path";
5
5
 
@@ -39,13 +39,12 @@ var ConfigError = class extends DeeplineError {
39
39
  };
40
40
 
41
41
  // src/config.ts
42
+ var HOST_URL_ENV = "DEEPLINE_HOST_URL";
43
+ var API_KEY_ENV = "DEEPLINE_API_KEY";
42
44
  var PROD_URL = "https://code.deepline.com";
43
45
  var DEFAULT_TIMEOUT = 6e4;
44
46
  var DEFAULT_MAX_RETRIES = 3;
45
- var ACTIVE_DEEPLINE_ENV_FILE = ".env.deepline";
46
- function projectEnvStartDir() {
47
- return process.env.DEEPLINE_PROJECT_ENV_DIR?.trim() || process.cwd();
48
- }
47
+ var PROJECT_DEEPLINE_ENV_FILE = ".env.deepline";
49
48
  function baseUrlSlug(baseUrl) {
50
49
  let url;
51
50
  try {
@@ -54,7 +53,7 @@ function baseUrlSlug(baseUrl) {
54
53
  return "unknown";
55
54
  }
56
55
  const host = url.hostname || "unknown";
57
- const port = url.port ? parseInt(url.port, 10) : null;
56
+ const port = url.port ? Number.parseInt(url.port, 10) : null;
58
57
  let slug = host.replace(/[^a-zA-Z0-9]/g, "-");
59
58
  if (port && port !== 80 && port !== 443) {
60
59
  slug = `${slug}-${port}`;
@@ -81,109 +80,84 @@ function parseEnvFile(filePath) {
81
80
  }
82
81
  return env;
83
82
  }
84
- function findNearestEnvFile(names, startDir = process.cwd()) {
83
+ function findNearestEnvFile(name, startDir = process.cwd()) {
85
84
  let current = resolve(startDir);
86
85
  while (true) {
87
- for (const name of names) {
88
- const filePath = join(current, name);
89
- if (existsSync(filePath)) return filePath;
90
- }
86
+ const filePath = join(current, name);
87
+ if (existsSync(filePath)) return filePath;
91
88
  const parent = dirname(current);
92
89
  if (parent === current) return null;
93
90
  current = parent;
94
91
  }
95
92
  }
96
- function findNearestEnv(names, startDir = process.cwd()) {
97
- const filePath = findNearestEnvFile(names, startDir);
93
+ function loadProjectDeeplineEnv(startDir = process.cwd()) {
94
+ const filePath = findNearestEnvFile(PROJECT_DEEPLINE_ENV_FILE, startDir);
98
95
  return filePath ? parseEnvFile(filePath) : {};
99
96
  }
100
- function findNearestWorktreeEnv(startDir = process.cwd()) {
101
- return findNearestEnv([".env.worktree"], startDir);
102
- }
103
- function resolveProfileEnvFileNames() {
104
- const explicitProfile = process.env.DEEPLINE_ENV_PROFILE?.trim() || process.env.DEEPLINE_PROFILE?.trim() || "";
105
- const names = [];
106
- if (explicitProfile) names.push(`.env.deepline.${explicitProfile}`);
107
- const nodeEnv = process.env.NODE_ENV?.trim();
108
- if (nodeEnv === "production") names.push(".env.deepline.prod");
109
- else if (nodeEnv === "staging") names.push(".env.deepline.staging");
110
- names.push(ACTIVE_DEEPLINE_ENV_FILE);
111
- return names;
112
- }
113
- function resolveProjectAppEnvFileNames() {
114
- const nodeEnv = process.env.NODE_ENV?.trim();
115
- const names = [];
116
- if (nodeEnv === "production") names.push(".env.prod");
117
- if (nodeEnv === "staging") names.push(".env.staging");
118
- names.push(".env.local", ".env");
119
- return names;
120
- }
121
- function resolveBaseUrlFromEnvValues(env) {
122
- return env.DEEPLINE_ORIGIN_URL?.trim() || env.DEEPLINE_API_BASE_URL?.trim() || "";
123
- }
124
- function loadProjectDeeplineEnv() {
125
- return findNearestEnv(resolveProfileEnvFileNames(), projectEnvStartDir());
126
- }
127
- function loadProjectAppEnv() {
128
- return findNearestEnv(resolveProjectAppEnvFileNames(), projectEnvStartDir());
129
- }
130
- function normalizeWorktreeBaseUrl(baseUrl, worktreeEnv = findNearestWorktreeEnv()) {
131
- const trimmed = baseUrl.trim().replace(/\/$/, "");
132
- if (!trimmed) return trimmed;
97
+ function normalizeBaseUrl(baseUrl) {
98
+ const trimmed = baseUrl.trim().replace(/\/+$/, "");
99
+ if (!trimmed) return "";
133
100
  try {
134
101
  const parsed = new URL(trimmed);
135
- if (parsed.hostname.endsWith(".localhost") && parsed.port === "1355") {
136
- const port = worktreeEnv.WORKTREE_APP_PORT || worktreeEnv.PORT;
137
- if (port) return `${parsed.protocol}//localhost:${port}`;
102
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
103
+ return "";
138
104
  }
105
+ return parsed.toString().replace(/\/+$/, "");
139
106
  } catch {
107
+ return "";
108
+ }
109
+ }
110
+ function firstNonEmpty(...values) {
111
+ for (const value of values) {
112
+ const trimmed = value?.trim();
113
+ if (trimmed) return trimmed;
140
114
  }
141
- return trimmed;
115
+ return "";
142
116
  }
143
- function resolveWorktreeBaseUrl() {
144
- const worktreeEnv = findNearestWorktreeEnv();
145
- const declared = worktreeEnv.DEEPLINE_API_BASE_URL || worktreeEnv.WORKTREE_PUBLIC_APP_URL || worktreeEnv.APP_URL || "";
146
- if (declared) return normalizeWorktreeBaseUrl(declared, worktreeEnv);
147
- const port = worktreeEnv.WORKTREE_APP_PORT || worktreeEnv.PORT || "";
148
- return port ? `http://localhost:${port}` : "";
117
+ function sdkCliConfigDir(baseUrl) {
118
+ const home = process.env.HOME?.trim() || homedir();
119
+ return join(home, ".local", "deepline", baseUrlSlug(baseUrl || PROD_URL));
149
120
  }
150
121
  function sdkCliEnvFilePath(baseUrl) {
151
- const home = process.env.HOME?.trim() || homedir();
152
- return join(home, ".local", "deepline", baseUrlSlug(baseUrl || PROD_URL), ".env");
122
+ return join(sdkCliConfigDir(baseUrl), ".env");
153
123
  }
154
124
  function loadCliEnv(baseUrl = PROD_URL) {
155
- const envPath = sdkCliEnvFilePath(baseUrl);
156
- return parseEnvFile(envPath);
125
+ return parseEnvFile(sdkCliEnvFilePath(baseUrl));
157
126
  }
158
127
  function loadGlobalCliEnv() {
159
128
  return loadCliEnv(PROD_URL);
160
129
  }
161
130
  function autoDetectBaseUrl() {
162
- const envOrigin = process.env.DEEPLINE_ORIGIN_URL?.trim();
163
- if (envOrigin) return normalizeWorktreeBaseUrl(envOrigin);
164
- const envBase = process.env.DEEPLINE_API_BASE_URL?.trim();
165
- if (envBase) return normalizeWorktreeBaseUrl(envBase);
166
- const projectDeeplineBaseUrl = resolveBaseUrlFromEnvValues(loadProjectDeeplineEnv());
167
- if (projectDeeplineBaseUrl) return normalizeWorktreeBaseUrl(projectDeeplineBaseUrl);
168
- const projectAppBaseUrl = resolveBaseUrlFromEnvValues(loadProjectAppEnv());
169
- if (projectAppBaseUrl) return normalizeWorktreeBaseUrl(projectAppBaseUrl);
170
- const worktreeBaseUrl = resolveWorktreeBaseUrl();
171
- if (worktreeBaseUrl) return worktreeBaseUrl;
131
+ const projectEnv = loadProjectDeeplineEnv();
172
132
  const globalEnv = loadGlobalCliEnv();
173
- const globalOrigin = globalEnv.DEEPLINE_ORIGIN_URL?.trim();
174
- if (globalOrigin) return normalizeWorktreeBaseUrl(globalOrigin);
175
- return PROD_URL;
133
+ return normalizeBaseUrl(process.env[HOST_URL_ENV] ?? "") || normalizeBaseUrl(projectEnv[HOST_URL_ENV] ?? "") || normalizeBaseUrl(globalEnv[HOST_URL_ENV] ?? "") || PROD_URL;
134
+ }
135
+ function resolveApiKeyForBaseUrl(baseUrl, explicitApiKey) {
136
+ const normalizedBaseUrl = normalizeBaseUrl(baseUrl);
137
+ const projectEnv = loadProjectDeeplineEnv();
138
+ const cliEnv = loadCliEnv(normalizedBaseUrl || baseUrl);
139
+ const projectBaseUrl = normalizeBaseUrl(projectEnv[HOST_URL_ENV] ?? "");
140
+ const projectKeyApplies = projectBaseUrl === normalizedBaseUrl;
141
+ return firstNonEmpty(
142
+ explicitApiKey,
143
+ process.env[API_KEY_ENV],
144
+ projectKeyApplies ? projectEnv[API_KEY_ENV] : "",
145
+ cliEnv[API_KEY_ENV]
146
+ );
176
147
  }
177
148
  function resolveConfig(options) {
178
- const requestedBaseUrl = options?.baseUrl?.trim() || autoDetectBaseUrl();
179
- const baseUrl = normalizeWorktreeBaseUrl(requestedBaseUrl);
180
- const cliEnv = loadCliEnv(baseUrl);
181
- const projectDeeplineEnv = loadProjectDeeplineEnv();
182
- const projectAppEnv = loadProjectAppEnv();
183
- const apiKey = options?.apiKey?.trim() || process.env.DEEPLINE_API_KEY?.trim() || projectDeeplineEnv.DEEPLINE_API_KEY || projectAppEnv.DEEPLINE_API_KEY || cliEnv.DEEPLINE_API_KEY || "";
149
+ const baseUrl = normalizeBaseUrl(
150
+ options?.baseUrl?.trim() || autoDetectBaseUrl()
151
+ );
152
+ if (!baseUrl) {
153
+ throw new ConfigError(
154
+ `Invalid ${HOST_URL_ENV}. Expected an http(s) URL such as https://code.deepline.com.`
155
+ );
156
+ }
157
+ const apiKey = resolveApiKeyForBaseUrl(baseUrl, options?.apiKey);
184
158
  if (!apiKey) {
185
159
  throw new ConfigError(
186
- `No API key found. Set DEEPLINE_API_KEY env var, pass apiKey option, or run: deepline auth register`
160
+ `No API key found. Set ${API_KEY_ENV}, add it to .env.deepline, or run: deepline auth register`
187
161
  );
188
162
  }
189
163
  return {
@@ -195,8 +169,8 @@ function resolveConfig(options) {
195
169
  }
196
170
 
197
171
  // src/version.ts
198
- var SDK_VERSION = "0.1.32";
199
- var SDK_API_CONTRACT = "2026-05-generic-play-input-flags";
172
+ var SDK_VERSION = "0.1.33";
173
+ var SDK_API_CONTRACT = "2026-05-host-env-generic-play-input-flags";
200
174
 
201
175
  // ../shared_libs/play-runtime/coordinator-headers.ts
202
176
  var COORDINATOR_INTERNAL_TOKEN_HEADER = "x-deepline-internal-token";