@archal/cli 0.9.7 → 1.0.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.
Files changed (2) hide show
  1. package/dist/index.cjs +665 -473
  2. package/package.json +11 -12
package/dist/index.cjs CHANGED
@@ -1202,7 +1202,7 @@ var require_command = __commonJS({
1202
1202
  "use strict";
1203
1203
  var EventEmitter = require("events").EventEmitter;
1204
1204
  var childProcess = require("child_process");
1205
- var path = require("path");
1205
+ var path2 = require("path");
1206
1206
  var fs = require("fs");
1207
1207
  var process3 = require("process");
1208
1208
  var { Argument: Argument2, humanReadableArgName } = require_argument();
@@ -2215,9 +2215,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
2215
2215
  let launchWithNode = false;
2216
2216
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
2217
2217
  function findFile(baseDir, baseName) {
2218
- const localBin = path.resolve(baseDir, baseName);
2218
+ const localBin = path2.resolve(baseDir, baseName);
2219
2219
  if (fs.existsSync(localBin)) return localBin;
2220
- if (sourceExt.includes(path.extname(baseName))) return void 0;
2220
+ if (sourceExt.includes(path2.extname(baseName))) return void 0;
2221
2221
  const foundExt = sourceExt.find(
2222
2222
  (ext) => fs.existsSync(`${localBin}${ext}`)
2223
2223
  );
@@ -2235,17 +2235,17 @@ Expecting one of '${allowedValues.join("', '")}'`);
2235
2235
  } catch {
2236
2236
  resolvedScriptPath = this._scriptPath;
2237
2237
  }
2238
- executableDir = path.resolve(
2239
- path.dirname(resolvedScriptPath),
2238
+ executableDir = path2.resolve(
2239
+ path2.dirname(resolvedScriptPath),
2240
2240
  executableDir
2241
2241
  );
2242
2242
  }
2243
2243
  if (executableDir) {
2244
2244
  let localFile = findFile(executableDir, executableFile);
2245
2245
  if (!localFile && !subcommand._executableFile && this._scriptPath) {
2246
- const legacyName = path.basename(
2246
+ const legacyName = path2.basename(
2247
2247
  this._scriptPath,
2248
- path.extname(this._scriptPath)
2248
+ path2.extname(this._scriptPath)
2249
2249
  );
2250
2250
  if (legacyName !== this._name) {
2251
2251
  localFile = findFile(
@@ -2256,7 +2256,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2256
2256
  }
2257
2257
  executableFile = localFile || executableFile;
2258
2258
  }
2259
- launchWithNode = sourceExt.includes(path.extname(executableFile));
2259
+ launchWithNode = sourceExt.includes(path2.extname(executableFile));
2260
2260
  let proc;
2261
2261
  if (process3.platform !== "win32") {
2262
2262
  if (launchWithNode) {
@@ -3171,7 +3171,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
3171
3171
  * @return {Command}
3172
3172
  */
3173
3173
  nameFromFilename(filename) {
3174
- this._name = path.basename(filename, path.extname(filename));
3174
+ this._name = path2.basename(filename, path2.extname(filename));
3175
3175
  return this;
3176
3176
  }
3177
3177
  /**
@@ -3185,9 +3185,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
3185
3185
  * @param {string} [path]
3186
3186
  * @return {(string|null|Command)}
3187
3187
  */
3188
- executableDir(path2) {
3189
- if (path2 === void 0) return this._executableDir;
3190
- this._executableDir = path2;
3188
+ executableDir(path3) {
3189
+ if (path3 === void 0) return this._executableDir;
3190
+ this._executableDir = path3;
3191
3191
  return this;
3192
3192
  }
3193
3193
  /**
@@ -4079,8 +4079,8 @@ var init_parseUtil = __esm({
4079
4079
  init_errors();
4080
4080
  init_en();
4081
4081
  makeIssue = (params) => {
4082
- const { data, path, errorMaps, issueData } = params;
4083
- const fullPath = [...path, ...issueData.path || []];
4082
+ const { data, path: path2, errorMaps, issueData } = params;
4083
+ const fullPath = [...path2, ...issueData.path || []];
4084
4084
  const fullIssue = {
4085
4085
  ...issueData,
4086
4086
  path: fullPath
@@ -4363,11 +4363,11 @@ var init_types = __esm({
4363
4363
  init_parseUtil();
4364
4364
  init_util();
4365
4365
  ParseInputLazyPath = class {
4366
- constructor(parent, value, path, key) {
4366
+ constructor(parent, value, path2, key) {
4367
4367
  this._cachedPath = [];
4368
4368
  this.parent = parent;
4369
4369
  this.data = value;
4370
- this._path = path;
4370
+ this._path = path2;
4371
4371
  this._key = key;
4372
4372
  }
4373
4373
  get path() {
@@ -7875,10 +7875,10 @@ function mergeDefs(...defs) {
7875
7875
  function cloneDef(schema) {
7876
7876
  return mergeDefs(schema._zod.def);
7877
7877
  }
7878
- function getElementAtPath(obj, path) {
7879
- if (!path)
7878
+ function getElementAtPath(obj, path2) {
7879
+ if (!path2)
7880
7880
  return obj;
7881
- return path.reduce((acc, key) => acc?.[key], obj);
7881
+ return path2.reduce((acc, key) => acc?.[key], obj);
7882
7882
  }
7883
7883
  function promiseAllObject(promisesObj) {
7884
7884
  const keys = Object.keys(promisesObj);
@@ -8190,11 +8190,11 @@ function aborted(x, startIndex = 0) {
8190
8190
  }
8191
8191
  return false;
8192
8192
  }
8193
- function prefixIssues(path, issues) {
8193
+ function prefixIssues(path2, issues) {
8194
8194
  return issues.map((iss) => {
8195
8195
  var _a2;
8196
8196
  (_a2 = iss).path ?? (_a2.path = []);
8197
- iss.path.unshift(path);
8197
+ iss.path.unshift(path2);
8198
8198
  return iss;
8199
8199
  });
8200
8200
  }
@@ -8437,7 +8437,7 @@ function formatError(error49, mapper = (issue2) => issue2.message) {
8437
8437
  }
8438
8438
  function treeifyError(error49, mapper = (issue2) => issue2.message) {
8439
8439
  const result = { errors: [] };
8440
- const processError = (error50, path = []) => {
8440
+ const processError = (error50, path2 = []) => {
8441
8441
  var _a2, _b;
8442
8442
  for (const issue2 of error50.issues) {
8443
8443
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -8447,7 +8447,7 @@ function treeifyError(error49, mapper = (issue2) => issue2.message) {
8447
8447
  } else if (issue2.code === "invalid_element") {
8448
8448
  processError({ issues: issue2.issues }, issue2.path);
8449
8449
  } else {
8450
- const fullpath = [...path, ...issue2.path];
8450
+ const fullpath = [...path2, ...issue2.path];
8451
8451
  if (fullpath.length === 0) {
8452
8452
  result.errors.push(mapper(issue2));
8453
8453
  continue;
@@ -8479,8 +8479,8 @@ function treeifyError(error49, mapper = (issue2) => issue2.message) {
8479
8479
  }
8480
8480
  function toDotPath(_path) {
8481
8481
  const segs = [];
8482
- const path = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
8483
- for (const seg of path) {
8482
+ const path2 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
8483
+ for (const seg of path2) {
8484
8484
  if (typeof seg === "number")
8485
8485
  segs.push(`[${seg}]`);
8486
8486
  else if (typeof seg === "symbol")
@@ -21323,13 +21323,13 @@ function resolveRef(ref, ctx) {
21323
21323
  if (!ref.startsWith("#")) {
21324
21324
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
21325
21325
  }
21326
- const path = ref.slice(1).split("/").filter(Boolean);
21327
- if (path.length === 0) {
21326
+ const path2 = ref.slice(1).split("/").filter(Boolean);
21327
+ if (path2.length === 0) {
21328
21328
  return ctx.rootSchema;
21329
21329
  }
21330
21330
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
21331
- if (path[0] === defsKey) {
21332
- const key = path[1];
21331
+ if (path2[0] === defsKey) {
21332
+ const key = path2[1];
21333
21333
  if (!key || !ctx.defs[key]) {
21334
21334
  throw new Error(`Reference not found: ${ref}`);
21335
21335
  }
@@ -27200,8 +27200,8 @@ var require_utils = __commonJS({
27200
27200
  }
27201
27201
  return ind;
27202
27202
  }
27203
- function removeDotSegments(path) {
27204
- let input = path;
27203
+ function removeDotSegments(path2) {
27204
+ let input = path2;
27205
27205
  const output = [];
27206
27206
  let nextSlash = -1;
27207
27207
  let len = 0;
@@ -27400,8 +27400,8 @@ var require_schemes = __commonJS({
27400
27400
  wsComponent.secure = void 0;
27401
27401
  }
27402
27402
  if (wsComponent.resourceName) {
27403
- const [path, query] = wsComponent.resourceName.split("?");
27404
- wsComponent.path = path && path !== "/" ? path : void 0;
27403
+ const [path2, query] = wsComponent.resourceName.split("?");
27404
+ wsComponent.path = path2 && path2 !== "/" ? path2 : void 0;
27405
27405
  wsComponent.query = query;
27406
27406
  wsComponent.resourceName = void 0;
27407
27407
  }
@@ -31594,19 +31594,19 @@ function resolveStoredRefreshToken(parsed) {
31594
31594
  }
31595
31595
  return { refreshToken: "", source: "none" };
31596
31596
  }
31597
- function buildStoredCredentials(parsed, path, warn3) {
31597
+ function buildStoredCredentials(parsed, path2, warn3) {
31598
31598
  const { token, source: tokenSource } = resolveStoredToken(parsed);
31599
31599
  const { refreshToken, source: refreshTokenSource } = resolveStoredRefreshToken(parsed);
31600
31600
  if (token === null || refreshToken === null || parsed.refreshToken !== void 0 && typeof parsed.refreshToken !== "string" || parsed.refreshTokenEncrypted !== void 0 && typeof parsed.refreshTokenEncrypted !== "string" || !hasValidSelectedTwins(parsed.selectedTwins)) {
31601
31601
  warn3(
31602
- `Credentials file at ${path} has missing or invalid fields. Run \`archal login\` to re-authenticate.`
31602
+ `Credentials file at ${path2} has missing or invalid fields. Run \`archal login\` to re-authenticate.`
31603
31603
  );
31604
31604
  return null;
31605
31605
  }
31606
31606
  const { email: email3, plan, expiresAt } = parsed;
31607
31607
  if (typeof email3 !== "string" || !isPlan(plan) || typeof expiresAt !== "number") {
31608
31608
  warn3(
31609
- `Credentials file at ${path} has missing or invalid fields. Run \`archal login\` to re-authenticate.`
31609
+ `Credentials file at ${path2} has missing or invalid fields. Run \`archal login\` to re-authenticate.`
31610
31610
  );
31611
31611
  return null;
31612
31612
  }
@@ -31628,18 +31628,18 @@ function buildStoredCredentials(parsed, path, warn3) {
31628
31628
  return creds;
31629
31629
  }
31630
31630
  function readCredentialsFile(options) {
31631
- const path = getCredentialsPath();
31632
- if (!(0, import_fs.existsSync)(path)) {
31631
+ const path2 = getCredentialsPath();
31632
+ if (!(0, import_fs.existsSync)(path2)) {
31633
31633
  return null;
31634
31634
  }
31635
31635
  try {
31636
31636
  const warn3 = getWarn(options);
31637
- const parsed = JSON.parse((0, import_fs.readFileSync)(path, "utf-8"));
31638
- return buildStoredCredentials(parsed, path, warn3);
31637
+ const parsed = JSON.parse((0, import_fs.readFileSync)(path2, "utf-8"));
31638
+ return buildStoredCredentials(parsed, path2, warn3);
31639
31639
  } catch {
31640
31640
  const warn3 = getWarn(options);
31641
31641
  warn3(
31642
- `Credentials file at ${path} exists but could not be parsed. Delete it and run \`archal login\` to re-authenticate.`
31642
+ `Credentials file at ${path2} exists but could not be parsed. Delete it and run \`archal login\` to re-authenticate.`
31643
31643
  );
31644
31644
  return null;
31645
31645
  }
@@ -31716,11 +31716,11 @@ function saveCredentials(creds) {
31716
31716
  (0, import_fs.renameSync)(tmpPath, credPath);
31717
31717
  }
31718
31718
  function deleteCredentials() {
31719
- const path = getCredentialsPath();
31720
- if (!(0, import_fs.existsSync)(path)) {
31719
+ const path2 = getCredentialsPath();
31720
+ if (!(0, import_fs.existsSync)(path2)) {
31721
31721
  return false;
31722
31722
  }
31723
- (0, import_fs.unlinkSync)(path);
31723
+ (0, import_fs.unlinkSync)(path2);
31724
31724
  return true;
31725
31725
  }
31726
31726
  function getWarn2(options) {
@@ -31807,6 +31807,13 @@ function getConfiguredApiBaseUrl(options) {
31807
31807
  }
31808
31808
  return isStrictEndpointModeEnabled() ? null : HOSTED_DEFAULT_API_BASE_URL;
31809
31809
  }
31810
+ function getConfiguredRuntimeBaseUrl(options) {
31811
+ const explicit = readConfiguredUrl(options, "ARCHAL_RUNTIME_URL");
31812
+ if (explicit) {
31813
+ return explicit;
31814
+ }
31815
+ return isStrictEndpointModeEnabled() ? null : HOSTED_DEFAULT_RUNTIME_BASE_URL;
31816
+ }
31810
31817
  function buildAuthRequestHeaders(metadata, includeContentType = false) {
31811
31818
  const headers = {};
31812
31819
  if (includeContentType) {
@@ -32150,7 +32157,7 @@ async function revokeCliSession(refreshToken, metadata) {
32150
32157
  debug2(`Session revoke failed (best-effort): ${errorMessage2(error49)}`);
32151
32158
  }
32152
32159
  }
32153
- var import_child_process, import_crypto2, import_fs, import_os, import_path, CREDENTIALS_FILE, CREDENTIALS_KEY_FILE, AUTH_TOKEN_ENV_VAR, TOKEN_ENCRYPTION_PREFIX, CREDENTIALS_MASTER_KEY_ENV_VAR, KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT, HOSTED_DEFAULT_AUTH_BASE_URL, HOSTED_DEFAULT_API_BASE_URL, STRICT_ENDPOINTS_ENV_VAR, REQUEST_TIMEOUT_MS, ENV_TOKEN_FALLBACK_TTL_SECONDS, AUTH_RETRY_OPTIONS, ExpiredEnvTokenError, KEYCHAIN_COMMAND_TIMEOUT_MS, ARCHAL_DIR_NAME, seededSandboxes;
32160
+ var import_child_process, import_crypto2, import_fs, import_os, import_path, CREDENTIALS_FILE, CREDENTIALS_KEY_FILE, AUTH_TOKEN_ENV_VAR, TOKEN_ENCRYPTION_PREFIX, CREDENTIALS_MASTER_KEY_ENV_VAR, KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT, HOSTED_DEFAULT_AUTH_BASE_URL, HOSTED_DEFAULT_API_BASE_URL, HOSTED_DEFAULT_RUNTIME_BASE_URL, STRICT_ENDPOINTS_ENV_VAR, REQUEST_TIMEOUT_MS, ENV_TOKEN_FALLBACK_TTL_SECONDS, AUTH_RETRY_OPTIONS, ExpiredEnvTokenError, KEYCHAIN_COMMAND_TIMEOUT_MS, ARCHAL_DIR_NAME, seededSandboxes;
32154
32161
  var init_dist3 = __esm({
32155
32162
  "../packages/node-auth/dist/index.js"() {
32156
32163
  "use strict";
@@ -32167,7 +32174,8 @@ var init_dist3 = __esm({
32167
32174
  KEYCHAIN_SERVICE = "archal-cli";
32168
32175
  KEYCHAIN_ACCOUNT = "credentials-master-key";
32169
32176
  HOSTED_DEFAULT_AUTH_BASE_URL = "https://www.archal.ai";
32170
- HOSTED_DEFAULT_API_BASE_URL = "https://www.archal.ai";
32177
+ HOSTED_DEFAULT_API_BASE_URL = "https://api.archal.ai";
32178
+ HOSTED_DEFAULT_RUNTIME_BASE_URL = "https://api.archal.ai";
32171
32179
  STRICT_ENDPOINTS_ENV_VAR = "ARCHAL_STRICT_ENDPOINTS";
32172
32180
  REQUEST_TIMEOUT_MS = 8e3;
32173
32181
  ENV_TOKEN_FALLBACK_TTL_SECONDS = 24 * 60 * 60;
@@ -32377,6 +32385,9 @@ function getConfiguredAuthBaseUrl2() {
32377
32385
  function getConfiguredApiBaseUrl2() {
32378
32386
  return getConfiguredApiBaseUrl(READ_OPTIONS);
32379
32387
  }
32388
+ function getConfiguredRuntimeBaseUrl2() {
32389
+ return getConfiguredRuntimeBaseUrl(READ_OPTIONS);
32390
+ }
32380
32391
  var READ_OPTIONS;
32381
32392
  var init_url_resolver = __esm({
32382
32393
  "src/auth/url-resolver.ts"() {
@@ -32598,6 +32609,7 @@ __export(auth_exports, {
32598
32609
  getArchalDir: () => getArchalDir,
32599
32610
  getConfiguredApiBaseUrl: () => getConfiguredApiBaseUrl2,
32600
32611
  getConfiguredAuthBaseUrl: () => getConfiguredAuthBaseUrl2,
32612
+ getConfiguredRuntimeBaseUrl: () => getConfiguredRuntimeBaseUrl2,
32601
32613
  getCredentials: () => getCredentials2,
32602
32614
  getJwtExpiry: () => getJwtExpiry,
32603
32615
  getStoredCredentials: () => getStoredCredentials2,
@@ -32933,13 +32945,13 @@ function resolveBaseUrl(_path) {
32933
32945
  error: "ARCHAL_API_URL is required for API requests when ARCHAL_STRICT_ENDPOINTS=1. Set ARCHAL_API_URL to your API endpoint, or unset ARCHAL_STRICT_ENDPOINTS."
32934
32946
  };
32935
32947
  }
32936
- function isFinalizeEvidencePath(path) {
32937
- const [pathname] = path.split("?", 1);
32948
+ function isFinalizeEvidencePath(path2) {
32949
+ const [pathname] = path2.split("?", 1);
32938
32950
  if (!pathname) return false;
32939
32951
  return /^\/api\/sessions\/[^/]+\/evidence\/finalize$/.test(pathname);
32940
32952
  }
32941
- function isCreateSessionPath(path) {
32942
- const [pathname] = path.split("?", 1);
32953
+ function isCreateSessionPath(path2) {
32954
+ const [pathname] = path2.split("?", 1);
32943
32955
  if (!pathname) return false;
32944
32956
  return pathname === "/api/sessions";
32945
32957
  }
@@ -32988,9 +33000,9 @@ async function tryRefreshToken() {
32988
33000
  return null;
32989
33001
  }
32990
33002
  }
32991
- async function request(method, path, token, body, timeoutOrOptions) {
33003
+ async function request(method, path2, token, body, timeoutOrOptions) {
32992
33004
  const options = typeof timeoutOrOptions === "number" ? { timeoutMs: timeoutOrOptions } : timeoutOrOptions ?? {};
32993
- const baseUrl = resolveBaseUrl(path);
33005
+ const baseUrl = resolveBaseUrl(path2);
32994
33006
  if (!baseUrl.ok) {
32995
33007
  return {
32996
33008
  ok: false,
@@ -32999,7 +33011,7 @@ async function request(method, path, token, body, timeoutOrOptions) {
32999
33011
  code: baseUrl.code
33000
33012
  };
33001
33013
  }
33002
- const url2 = `${baseUrl.baseUrl}${path}`;
33014
+ const url2 = `${baseUrl.baseUrl}${path2}`;
33003
33015
  const headers = {
33004
33016
  "content-type": "application/json",
33005
33017
  "user-agent": CLI_USER_AGENT,
@@ -33016,8 +33028,8 @@ async function request(method, path, token, body, timeoutOrOptions) {
33016
33028
  if (options.idempotencyKey) {
33017
33029
  headers["x-archal-idempotency-key"] = options.idempotencyKey;
33018
33030
  }
33019
- const isIdempotentFinalize = method === "POST" && isFinalizeEvidencePath(path);
33020
- const isIdempotentCreateSession = method === "POST" && isCreateSessionPath(path) && Boolean(options.idempotentPost && options.idempotencyKey);
33031
+ const isIdempotentFinalize = method === "POST" && isFinalizeEvidencePath(path2);
33032
+ const isIdempotentCreateSession = method === "POST" && isCreateSessionPath(path2) && Boolean(options.idempotentPost && options.idempotencyKey);
33021
33033
  const retriesAllowed = method !== "POST" || isIdempotentFinalize || isIdempotentCreateSession;
33022
33034
  const attempts = retriesAllowed ? getMaxRetries() + 1 : 1;
33023
33035
  let lastError = "request failed";
@@ -33044,7 +33056,7 @@ async function request(method, path, token, body, timeoutOrOptions) {
33044
33056
  }
33045
33057
  if (retriesAllowed && !softAuthRetryAttempted && getMaxRetries() > 0 && token) {
33046
33058
  softAuthRetryAttempted = true;
33047
- debug3(`401 on ${method} ${path}: soft-retrying once after backoff`);
33059
+ debug3(`401 on ${method} ${path2}: soft-retrying once after backoff`);
33048
33060
  await sleep(retryDelayMs(1, response.headers.get("retry-after")));
33049
33061
  attempt -= 1;
33050
33062
  continue;
@@ -34210,7 +34222,7 @@ var init_dist4 = __esm({
34210
34222
  }
34211
34223
  });
34212
34224
 
34213
- // ../packages/seed-codegen-runtime/dist/index.js
34225
+ // ../packages/seed-codegen-runtime/dist/chunk-LOUVSGFM.js
34214
34226
  function getMaxId(entities) {
34215
34227
  let max = 0;
34216
34228
  for (const entity of entities) {
@@ -35137,13 +35149,13 @@ function buildGitHubSandbox(context, collector) {
35137
35149
  const repoId = repoRef?._id ?? findFirstRepoId(collector.seed) ?? 1;
35138
35150
  const nextId = getMaxId(collector.seed["workflows"]) + 1;
35139
35151
  const now = /* @__PURE__ */ new Date();
35140
- const path = opts?.["path"] ?? `.github/workflows/${name.toLowerCase().replace(/\s+/g, "-")}.yml`;
35152
+ const path2 = opts?.["path"] ?? `.github/workflows/${name.toLowerCase().replace(/\s+/g, "-")}.yml`;
35141
35153
  collector.seed["workflows"].push({
35142
35154
  id: nextId,
35143
35155
  repoId,
35144
35156
  nodeId: generateNodeId("W", nextId),
35145
35157
  name,
35146
- path,
35158
+ path: path2,
35147
35159
  state: opts?.["state"] ?? "active",
35148
35160
  htmlUrl: "",
35149
35161
  badgeUrl: "",
@@ -36120,7 +36132,7 @@ function buildGitHubSandbox(context, collector) {
36120
36132
  });
36121
36133
  return makeRef("environments", nextId, name);
36122
36134
  };
36123
- context["createFileEntry"] = (repoRef, path, content, opts) => {
36135
+ context["createFileEntry"] = (repoRef, path2, content, opts) => {
36124
36136
  if (!collector.seed["files"]) collector.seed["files"] = [];
36125
36137
  const repoId = repoRef?._id ?? findFirstRepoId(collector.seed) ?? 1;
36126
36138
  const nextId = getMaxId(collector.seed["files"]) + 1;
@@ -36129,7 +36141,7 @@ function buildGitHubSandbox(context, collector) {
36129
36141
  id: nextId,
36130
36142
  repoId,
36131
36143
  branchName: opts?.["branchName"] ?? "main",
36132
- path,
36144
+ path: path2,
36133
36145
  content,
36134
36146
  encoding: opts?.["encoding"] ?? "utf-8",
36135
36147
  sha: generateSha(),
@@ -36138,7 +36150,7 @@ function buildGitHubSandbox(context, collector) {
36138
36150
  createdAt: now.toISOString(),
36139
36151
  updatedAt: now.toISOString()
36140
36152
  });
36141
- return makeRef("files", nextId, path);
36153
+ return makeRef("files", nextId, path2);
36142
36154
  };
36143
36155
  context["createFollower"] = (userLogin, followerLogin) => {
36144
36156
  if (!collector.seed["followers"]) collector.seed["followers"] = [];
@@ -36726,7 +36738,7 @@ function buildGitHubSandbox(context, collector) {
36726
36738
  });
36727
36739
  return makeRef("projectCards", nextId);
36728
36740
  };
36729
- context["createPullRequestReviewThread"] = (repoRef, pullRequestNumber, path, opts) => {
36741
+ context["createPullRequestReviewThread"] = (repoRef, pullRequestNumber, path2, opts) => {
36730
36742
  if (!collector.seed["pullRequestReviewThreads"]) collector.seed["pullRequestReviewThreads"] = [];
36731
36743
  const repoId = repoRef?._id ?? findFirstRepoId(collector.seed) ?? 1;
36732
36744
  const nextId = getMaxId(collector.seed["pullRequestReviewThreads"]) + 1;
@@ -36745,7 +36757,7 @@ function buildGitHubSandbox(context, collector) {
36745
36757
  startSide: opts?.["startSide"] ?? "RIGHT",
36746
36758
  side: opts?.["side"] ?? "RIGHT",
36747
36759
  diffSide: opts?.["diffSide"] ?? "RIGHT",
36748
- path,
36760
+ path: path2,
36749
36761
  createdAt: now.toISOString(),
36750
36762
  updatedAt: now.toISOString()
36751
36763
  });
@@ -43637,6 +43649,204 @@ function buildSandboxContext(collector, twinName) {
43637
43649
  }
43638
43650
  return context;
43639
43651
  }
43652
+ var MS_PER_DAY, ISSUE_TITLES, ISSUE_BODIES, PR_TITLES, CHANNEL_PURPOSES, MESSAGE_TEXTS, DEFAULT_REACTIONS, MAX_BULK_COUNT, SeedCollector, TWIN_CONTEXT_BUILDERS;
43653
+ var init_chunk_LOUVSGFM = __esm({
43654
+ "../packages/seed-codegen-runtime/dist/chunk-LOUVSGFM.js"() {
43655
+ "use strict";
43656
+ MS_PER_DAY = 864e5;
43657
+ ISSUE_TITLES = [
43658
+ "Fix login redirect loop on Safari",
43659
+ "Add dark mode support to settings page",
43660
+ "Rate limiter returns 500 instead of 429",
43661
+ "Memory leak in WebSocket connection manager",
43662
+ "Dropdown menus do not close on mobile",
43663
+ "Search results do not highlight matching terms",
43664
+ "File upload fails silently for large files",
43665
+ "Add CSV export to analytics dashboard",
43666
+ "Implement bulk actions for notifications",
43667
+ "GraphQL query returns stale cached data",
43668
+ "Table component lacks keyboard navigation",
43669
+ "Create onboarding tutorial for new members",
43670
+ "API response times degrade for large date ranges",
43671
+ "Add two-factor authentication for admin accounts",
43672
+ "Deprecated crypto API warnings in test suite",
43673
+ "Evaluate replacing Moment.js with date-fns",
43674
+ "Broken tooltip positioning on Safari 17",
43675
+ "Login page shows blank screen on slow 3G",
43676
+ "Intermittent 502 errors on reports endpoint",
43677
+ "Tracking: migrate auth from cookies to JWT",
43678
+ "Roadmap: accessibility audit and WCAG compliance",
43679
+ "Upgrade Node.js runtime from 18 to 20 LTS",
43680
+ "Refactor database connection pool configuration",
43681
+ "Add retry logic for third-party API calls",
43682
+ "Improve error messages for form validation",
43683
+ "Pagination breaks when filtering by status",
43684
+ "Email notification templates are not responsive",
43685
+ "CI pipeline takes 45 minutes on large PRs",
43686
+ "Localization support for date and number formats",
43687
+ "Dashboard widgets do not resize on mobile"
43688
+ ];
43689
+ ISSUE_BODIES = [
43690
+ "This has been reported multiple times by users. Needs investigation and a fix.",
43691
+ "No one has started working on this yet. Low priority but would improve UX.",
43692
+ "This is affecting production traffic. We need to address this soon.",
43693
+ "Users have requested this feature multiple times. Would be a nice enhancement.",
43694
+ "This is a long-running tracking issue. Should remain open for visibility.",
43695
+ "Repro steps: 1) Open the app 2) Navigate to settings 3) Observe the issue.",
43696
+ "This blocks other work. Please prioritize.",
43697
+ "Nice to have. Not urgent but would reduce tech debt."
43698
+ ];
43699
+ PR_TITLES = [
43700
+ "Fix null check in JWT validation",
43701
+ "Add pagination to search results",
43702
+ "Refactor database connection pooling",
43703
+ "Update dependencies to latest versions",
43704
+ "Improve error handling in API middleware",
43705
+ "Add unit tests for auth module",
43706
+ "Fix race condition in WebSocket handler",
43707
+ "Migrate CSS to custom properties for theming"
43708
+ ];
43709
+ CHANNEL_PURPOSES = [
43710
+ "General discussion",
43711
+ "Engineering team updates",
43712
+ "Product announcements",
43713
+ "Customer support escalations",
43714
+ "Random fun stuff",
43715
+ "Incident response",
43716
+ "Design feedback",
43717
+ "Deploy notifications"
43718
+ ];
43719
+ MESSAGE_TEXTS = [
43720
+ "Hey team, just a heads up about the deploy today.",
43721
+ "Can someone review my PR? It's been open for a while.",
43722
+ "The CI pipeline is green again after the fix.",
43723
+ "Meeting notes from today's standup are in the doc.",
43724
+ "Has anyone seen this error before? Getting a 502 intermittently.",
43725
+ "Thanks for the quick turnaround on that bug fix!",
43726
+ "Reminder: retro is at 3pm today.",
43727
+ "I pushed a hotfix for the login issue. Please verify."
43728
+ ];
43729
+ DEFAULT_REACTIONS = {
43730
+ totalCount: 0,
43731
+ plusOne: 0,
43732
+ minusOne: 0,
43733
+ laugh: 0,
43734
+ hooray: 0,
43735
+ confused: 0,
43736
+ heart: 0,
43737
+ rocket: 0,
43738
+ eyes: 0
43739
+ };
43740
+ MAX_BULK_COUNT = 1e3;
43741
+ SeedCollector = class {
43742
+ seed;
43743
+ warnings = [];
43744
+ twinName;
43745
+ now;
43746
+ constructor(twinName, baseSeed) {
43747
+ this.seed = structuredClone(baseSeed);
43748
+ this.twinName = twinName;
43749
+ this.now = /* @__PURE__ */ new Date();
43750
+ }
43751
+ /** Create a single identity entity (user, repo, workspace, etc.). */
43752
+ createIdentity(collection, fields) {
43753
+ if (!this.seed[collection]) this.seed[collection] = [];
43754
+ const existing = this.seed[collection].find((entity2) => {
43755
+ for (const [key, value] of Object.entries(fields)) {
43756
+ if (entity2[key] !== value) return false;
43757
+ }
43758
+ return true;
43759
+ });
43760
+ if (existing) {
43761
+ return makeRef(
43762
+ collection,
43763
+ existing["id"],
43764
+ fields["name"] ?? fields["login"]
43765
+ );
43766
+ }
43767
+ const nextId = getMaxId(this.seed[collection]) + 1;
43768
+ const nowStr = this.now.toISOString();
43769
+ const entity = {
43770
+ id: nextId,
43771
+ ...fields,
43772
+ createdAt: nowStr,
43773
+ updatedAt: nowStr
43774
+ };
43775
+ fillDefaults(entity, collection);
43776
+ this.seed[collection].push(entity);
43777
+ return makeRef(collection, nextId, fields["name"] ?? fields["login"]);
43778
+ }
43779
+ /** Create N entities in a collection with shared properties. */
43780
+ createBulk(collection, count, properties) {
43781
+ if (!this.seed[collection]) this.seed[collection] = [];
43782
+ const safeCount = Math.min(count, MAX_BULK_COUNT);
43783
+ if (safeCount < count) {
43784
+ this.warnings.push(
43785
+ `createBulk: count ${count} capped at ${MAX_BULK_COUNT} for "${collection}"`
43786
+ );
43787
+ }
43788
+ for (let i = 0; i < safeCount; i++) {
43789
+ const nextId = getMaxId(this.seed[collection]) + 1;
43790
+ const temporal = resolveTemporalProperties(properties, this.now);
43791
+ const entity = this.buildEntity(collection, nextId, properties, i, temporal);
43792
+ this.seed[collection].push(entity);
43793
+ }
43794
+ }
43795
+ /** Push a single pre-built entity directly into a collection. */
43796
+ pushEntity(collection, entity) {
43797
+ if (!this.seed[collection]) this.seed[collection] = [];
43798
+ const stored = entity["id"] === void 0 ? { id: getMaxId(this.seed[collection]) + 1, ...entity } : entity;
43799
+ this.seed[collection].push(stored);
43800
+ }
43801
+ /** Clear a collection (blueprint-style replacement). */
43802
+ clearCollection(collection) {
43803
+ if (this.seed[collection]) {
43804
+ this.seed[collection] = [];
43805
+ }
43806
+ }
43807
+ buildEntity(collection, id, props, index, temporal) {
43808
+ if (this.twinName === "github")
43809
+ return buildGitHubEntity(collection, id, props, this.seed, index, temporal);
43810
+ if (this.twinName === "slack")
43811
+ return buildSlackEntity(collection, id, props, this.seed, index, temporal);
43812
+ if (this.twinName === "linear")
43813
+ return buildLinearEntity(collection, id, props, this.seed, index, temporal);
43814
+ if (this.twinName === "stripe")
43815
+ return buildStripeEntity(collection, id, props, this.seed, index, temporal);
43816
+ if (this.twinName === "jira")
43817
+ return buildJiraEntity(collection, id, props, this.seed, index, temporal);
43818
+ return { id, ...props, createdAt: temporal.createdAt, updatedAt: temporal.updatedAt };
43819
+ }
43820
+ /** Compute a synthetic patch (add-only) from base → built seed. */
43821
+ computePatch(baseSeed) {
43822
+ const add = {};
43823
+ for (const [collection, entities] of Object.entries(this.seed)) {
43824
+ const baseEntities = baseSeed[collection] ?? [];
43825
+ const baseIds = new Set(baseEntities.map((e) => e["id"]));
43826
+ const newEntities = entities.filter(
43827
+ (e) => !baseIds.has(e["id"])
43828
+ );
43829
+ if (newEntities.length > 0) {
43830
+ add[collection] = newEntities;
43831
+ }
43832
+ }
43833
+ return { add };
43834
+ }
43835
+ };
43836
+ TWIN_CONTEXT_BUILDERS = {
43837
+ github: buildGitHubSandbox,
43838
+ slack: buildSlackSandbox,
43839
+ linear: buildLinearSandbox,
43840
+ stripe: buildStripeSandbox,
43841
+ jira: buildJiraSandbox,
43842
+ supabase: buildSupabaseSandbox,
43843
+ "google-workspace": buildGoogleWorkspaceSandbox,
43844
+ ramp: buildRampSandbox
43845
+ };
43846
+ }
43847
+ });
43848
+
43849
+ // ../packages/seed-codegen-runtime/dist/index.js
43640
43850
  function checkStaticSafety(code) {
43641
43851
  const match = FORBIDDEN_PATTERN.exec(code);
43642
43852
  if (match) {
@@ -44471,204 +44681,18 @@ function augmentPlanFromDescription(plan, description, twinName) {
44471
44681
  planTypes.add(rule.type);
44472
44682
  }
44473
44683
  }
44474
- var import_vm, MS_PER_DAY, ISSUE_TITLES, ISSUE_BODIES, PR_TITLES, CHANNEL_PURPOSES, MESSAGE_TEXTS, DEFAULT_REACTIONS, MAX_BULK_COUNT, SeedCollector, TWIN_CONTEXT_BUILDERS, FORBIDDEN_PATTERN, OBFUSCATION_PATTERNS, DEFAULT_TIMEOUT_MS2, SDK_DECLARATIONS, SDK_EXAMPLES, CODEGEN_SYSTEM_PROMPT, GEMINI_API_BASE_URL2, ANTHROPIC_API_URL2, OPENAI_API_URL2, ANTHROPIC_API_VERSION2, MANAGED_SEED_TIMEOUT_MS, DIRECT_SEED_TIMEOUT_MS, ERROR_BODY_PREVIEW_LENGTH3, RETRYABLE_STATUS_CODES3, MAX_RETRIES2, INITIAL_BACKOFF_MS2, MAX_JITTER_MS2, SeedLlmApiError, PLAN_SYSTEM_PROMPT, ENTITY_TYPE_TO_COLLECTION;
44684
+ var import_url, import_path2, import_vm, import_meta2, FORBIDDEN_PATTERN, OBFUSCATION_PATTERNS, DEFAULT_TIMEOUT_MS2, workerScriptPath, SDK_DECLARATIONS, SDK_EXAMPLES, CODEGEN_SYSTEM_PROMPT, GEMINI_API_BASE_URL2, ANTHROPIC_API_URL2, OPENAI_API_URL2, ANTHROPIC_API_VERSION2, MANAGED_SEED_TIMEOUT_MS, DIRECT_SEED_TIMEOUT_MS, ERROR_BODY_PREVIEW_LENGTH3, RETRYABLE_STATUS_CODES3, MAX_RETRIES2, INITIAL_BACKOFF_MS2, MAX_JITTER_MS2, SeedLlmApiError, PLAN_SYSTEM_PROMPT, ENTITY_TYPE_TO_COLLECTION;
44475
44685
  var init_dist5 = __esm({
44476
44686
  "../packages/seed-codegen-runtime/dist/index.js"() {
44477
44687
  "use strict";
44688
+ init_chunk_LOUVSGFM();
44689
+ import_url = require("url");
44690
+ import_path2 = __toESM(require("path"), 1);
44478
44691
  import_vm = __toESM(require("vm"), 1);
44479
44692
  init_dist2();
44480
44693
  init_dist2();
44481
44694
  init_dist3();
44482
- MS_PER_DAY = 864e5;
44483
- ISSUE_TITLES = [
44484
- "Fix login redirect loop on Safari",
44485
- "Add dark mode support to settings page",
44486
- "Rate limiter returns 500 instead of 429",
44487
- "Memory leak in WebSocket connection manager",
44488
- "Dropdown menus do not close on mobile",
44489
- "Search results do not highlight matching terms",
44490
- "File upload fails silently for large files",
44491
- "Add CSV export to analytics dashboard",
44492
- "Implement bulk actions for notifications",
44493
- "GraphQL query returns stale cached data",
44494
- "Table component lacks keyboard navigation",
44495
- "Create onboarding tutorial for new members",
44496
- "API response times degrade for large date ranges",
44497
- "Add two-factor authentication for admin accounts",
44498
- "Deprecated crypto API warnings in test suite",
44499
- "Evaluate replacing Moment.js with date-fns",
44500
- "Broken tooltip positioning on Safari 17",
44501
- "Login page shows blank screen on slow 3G",
44502
- "Intermittent 502 errors on reports endpoint",
44503
- "Tracking: migrate auth from cookies to JWT",
44504
- "Roadmap: accessibility audit and WCAG compliance",
44505
- "Upgrade Node.js runtime from 18 to 20 LTS",
44506
- "Refactor database connection pool configuration",
44507
- "Add retry logic for third-party API calls",
44508
- "Improve error messages for form validation",
44509
- "Pagination breaks when filtering by status",
44510
- "Email notification templates are not responsive",
44511
- "CI pipeline takes 45 minutes on large PRs",
44512
- "Localization support for date and number formats",
44513
- "Dashboard widgets do not resize on mobile"
44514
- ];
44515
- ISSUE_BODIES = [
44516
- "This has been reported multiple times by users. Needs investigation and a fix.",
44517
- "No one has started working on this yet. Low priority but would improve UX.",
44518
- "This is affecting production traffic. We need to address this soon.",
44519
- "Users have requested this feature multiple times. Would be a nice enhancement.",
44520
- "This is a long-running tracking issue. Should remain open for visibility.",
44521
- "Repro steps: 1) Open the app 2) Navigate to settings 3) Observe the issue.",
44522
- "This blocks other work. Please prioritize.",
44523
- "Nice to have. Not urgent but would reduce tech debt."
44524
- ];
44525
- PR_TITLES = [
44526
- "Fix null check in JWT validation",
44527
- "Add pagination to search results",
44528
- "Refactor database connection pooling",
44529
- "Update dependencies to latest versions",
44530
- "Improve error handling in API middleware",
44531
- "Add unit tests for auth module",
44532
- "Fix race condition in WebSocket handler",
44533
- "Migrate CSS to custom properties for theming"
44534
- ];
44535
- CHANNEL_PURPOSES = [
44536
- "General discussion",
44537
- "Engineering team updates",
44538
- "Product announcements",
44539
- "Customer support escalations",
44540
- "Random fun stuff",
44541
- "Incident response",
44542
- "Design feedback",
44543
- "Deploy notifications"
44544
- ];
44545
- MESSAGE_TEXTS = [
44546
- "Hey team, just a heads up about the deploy today.",
44547
- "Can someone review my PR? It's been open for a while.",
44548
- "The CI pipeline is green again after the fix.",
44549
- "Meeting notes from today's standup are in the doc.",
44550
- "Has anyone seen this error before? Getting a 502 intermittently.",
44551
- "Thanks for the quick turnaround on that bug fix!",
44552
- "Reminder: retro is at 3pm today.",
44553
- "I pushed a hotfix for the login issue. Please verify."
44554
- ];
44555
- DEFAULT_REACTIONS = {
44556
- totalCount: 0,
44557
- plusOne: 0,
44558
- minusOne: 0,
44559
- laugh: 0,
44560
- hooray: 0,
44561
- confused: 0,
44562
- heart: 0,
44563
- rocket: 0,
44564
- eyes: 0
44565
- };
44566
- MAX_BULK_COUNT = 1e3;
44567
- SeedCollector = class {
44568
- seed;
44569
- warnings = [];
44570
- twinName;
44571
- now;
44572
- constructor(twinName, baseSeed) {
44573
- this.seed = structuredClone(baseSeed);
44574
- this.twinName = twinName;
44575
- this.now = /* @__PURE__ */ new Date();
44576
- }
44577
- /** Create a single identity entity (user, repo, workspace, etc.). */
44578
- createIdentity(collection, fields) {
44579
- if (!this.seed[collection]) this.seed[collection] = [];
44580
- const existing = this.seed[collection].find((entity2) => {
44581
- for (const [key, value] of Object.entries(fields)) {
44582
- if (entity2[key] !== value) return false;
44583
- }
44584
- return true;
44585
- });
44586
- if (existing) {
44587
- return makeRef(
44588
- collection,
44589
- existing["id"],
44590
- fields["name"] ?? fields["login"]
44591
- );
44592
- }
44593
- const nextId = getMaxId(this.seed[collection]) + 1;
44594
- const nowStr = this.now.toISOString();
44595
- const entity = {
44596
- id: nextId,
44597
- ...fields,
44598
- createdAt: nowStr,
44599
- updatedAt: nowStr
44600
- };
44601
- fillDefaults(entity, collection);
44602
- this.seed[collection].push(entity);
44603
- return makeRef(collection, nextId, fields["name"] ?? fields["login"]);
44604
- }
44605
- /** Create N entities in a collection with shared properties. */
44606
- createBulk(collection, count, properties) {
44607
- if (!this.seed[collection]) this.seed[collection] = [];
44608
- const safeCount = Math.min(count, MAX_BULK_COUNT);
44609
- if (safeCount < count) {
44610
- this.warnings.push(
44611
- `createBulk: count ${count} capped at ${MAX_BULK_COUNT} for "${collection}"`
44612
- );
44613
- }
44614
- for (let i = 0; i < safeCount; i++) {
44615
- const nextId = getMaxId(this.seed[collection]) + 1;
44616
- const temporal = resolveTemporalProperties(properties, this.now);
44617
- const entity = this.buildEntity(collection, nextId, properties, i, temporal);
44618
- this.seed[collection].push(entity);
44619
- }
44620
- }
44621
- /** Push a single pre-built entity directly into a collection. */
44622
- pushEntity(collection, entity) {
44623
- if (!this.seed[collection]) this.seed[collection] = [];
44624
- const stored = entity["id"] === void 0 ? { id: getMaxId(this.seed[collection]) + 1, ...entity } : entity;
44625
- this.seed[collection].push(stored);
44626
- }
44627
- /** Clear a collection (blueprint-style replacement). */
44628
- clearCollection(collection) {
44629
- if (this.seed[collection]) {
44630
- this.seed[collection] = [];
44631
- }
44632
- }
44633
- buildEntity(collection, id, props, index, temporal) {
44634
- if (this.twinName === "github")
44635
- return buildGitHubEntity(collection, id, props, this.seed, index, temporal);
44636
- if (this.twinName === "slack")
44637
- return buildSlackEntity(collection, id, props, this.seed, index, temporal);
44638
- if (this.twinName === "linear")
44639
- return buildLinearEntity(collection, id, props, this.seed, index, temporal);
44640
- if (this.twinName === "stripe")
44641
- return buildStripeEntity(collection, id, props, this.seed, index, temporal);
44642
- if (this.twinName === "jira")
44643
- return buildJiraEntity(collection, id, props, this.seed, index, temporal);
44644
- return { id, ...props, createdAt: temporal.createdAt, updatedAt: temporal.updatedAt };
44645
- }
44646
- /** Compute a synthetic patch (add-only) from base → built seed. */
44647
- computePatch(baseSeed) {
44648
- const add = {};
44649
- for (const [collection, entities] of Object.entries(this.seed)) {
44650
- const baseEntities = baseSeed[collection] ?? [];
44651
- const baseIds = new Set(baseEntities.map((e) => e["id"]));
44652
- const newEntities = entities.filter(
44653
- (e) => !baseIds.has(e["id"])
44654
- );
44655
- if (newEntities.length > 0) {
44656
- add[collection] = newEntities;
44657
- }
44658
- }
44659
- return { add };
44660
- }
44661
- };
44662
- TWIN_CONTEXT_BUILDERS = {
44663
- github: buildGitHubSandbox,
44664
- slack: buildSlackSandbox,
44665
- linear: buildLinearSandbox,
44666
- stripe: buildStripeSandbox,
44667
- jira: buildJiraSandbox,
44668
- supabase: buildSupabaseSandbox,
44669
- "google-workspace": buildGoogleWorkspaceSandbox,
44670
- ramp: buildRampSandbox
44671
- };
44695
+ import_meta2 = {};
44672
44696
  FORBIDDEN_PATTERN = /\b(require|process|globalThis|eval|Function|constructor|__proto__|Reflect|Proxy|import)\s*[([.`]/;
44673
44697
  OBFUSCATION_PATTERNS = [
44674
44698
  /\[\s*['"`](?:constructor|__proto__|prototype)['"` ]/,
@@ -44685,6 +44709,12 @@ var init_dist5 = __esm({
44685
44709
  // Symbol-based property access
44686
44710
  ];
44687
44711
  DEFAULT_TIMEOUT_MS2 = 5e3;
44712
+ try {
44713
+ const thisDir = import_path2.default.dirname((0, import_url.fileURLToPath)(import_meta2.url));
44714
+ workerScriptPath = import_path2.default.join(thisDir, "subprocess-worker.js");
44715
+ } catch {
44716
+ workerScriptPath = void 0;
44717
+ }
44688
44718
  SDK_DECLARATIONS = {
44689
44719
  github: `// GitHub Seed Builder SDK
44690
44720
  // All functions return opaque Ref handles. Use them to link entities.
@@ -52416,13 +52446,13 @@ function applyEnrichments(seed, response) {
52416
52446
  function buildFewShotExample(twinName) {
52417
52447
  try {
52418
52448
  const fs = require("fs");
52419
- const path = require("path");
52420
- const seedsDir = path.resolve("twins", twinName, "seeds");
52449
+ const path2 = require("path");
52450
+ const seedsDir = path2.resolve("twins", twinName, "seeds");
52421
52451
  if (!fs.existsSync(seedsDir)) return "";
52422
52452
  const files = fs.readdirSync(seedsDir).filter((f) => f.endsWith(".json") && f !== "empty.json");
52423
52453
  if (files.length === 0) return "";
52424
52454
  const firstFile = files[0] ?? "";
52425
- const seedData = JSON.parse(fs.readFileSync(path.join(seedsDir, firstFile), "utf-8"));
52455
+ const seedData = JSON.parse(fs.readFileSync(path2.join(seedsDir, firstFile), "utf-8"));
52426
52456
  for (const [col, entities] of Object.entries(seedData)) {
52427
52457
  if (Array.isArray(entities) && entities.length > 0 && typeof entities[0] === "object") {
52428
52458
  const example = JSON.stringify(entities[0]).slice(0, 500);
@@ -54395,23 +54425,23 @@ __export(dist_exports, {
54395
54425
  function isStringRecord(v) {
54396
54426
  return typeof v === "object" && v !== null && !Array.isArray(v);
54397
54427
  }
54398
- function readPackageJson(path) {
54399
- if (!(0, import_fs2.existsSync)(path)) return void 0;
54400
- const content = (0, import_fs2.readFileSync)(path, "utf-8");
54428
+ function readPackageJson(path2) {
54429
+ if (!(0, import_fs2.existsSync)(path2)) return void 0;
54430
+ const content = (0, import_fs2.readFileSync)(path2, "utf-8");
54401
54431
  let parsed;
54402
54432
  try {
54403
54433
  parsed = JSON.parse(content);
54404
54434
  } catch {
54405
54435
  throw new DockerfileError(
54406
54436
  "invalid_path",
54407
- `Failed to parse ${path.split("/").pop()}: invalid JSON`,
54437
+ `Failed to parse ${path2.split("/").pop()}: invalid JSON`,
54408
54438
  "Fix the JSON syntax error in the file and try again."
54409
54439
  );
54410
54440
  }
54411
54441
  if (typeof parsed !== "object" || parsed === null) {
54412
54442
  throw new DockerfileError(
54413
54443
  "invalid_path",
54414
- `${path.split("/").pop()} is not a JSON object`,
54444
+ `${path2.split("/").pop()} is not a JSON object`,
54415
54445
  "Fix the JSON syntax error in the file and try again."
54416
54446
  );
54417
54447
  }
@@ -54422,7 +54452,7 @@ function readPackageJson(path) {
54422
54452
  };
54423
54453
  }
54424
54454
  function hasFile(repoPath, relativePath) {
54425
- return (0, import_fs2.existsSync)((0, import_path2.join)(repoPath, relativePath));
54455
+ return (0, import_fs2.existsSync)((0, import_path3.join)(repoPath, relativePath));
54426
54456
  }
54427
54457
  function quoteJsonCommand(parts) {
54428
54458
  return `[${parts.map((part) => JSON.stringify(part)).join(", ")}]`;
@@ -54478,7 +54508,7 @@ function resolveNodeLaunchCommand(repoPath, pkg, packageManager) {
54478
54508
  return void 0;
54479
54509
  }
54480
54510
  function maybeGenerateNodeDockerfile(repoPath) {
54481
- const packageJsonPath = (0, import_path2.join)(repoPath, "package.json");
54511
+ const packageJsonPath = (0, import_path3.join)(repoPath, "package.json");
54482
54512
  const pkg = readPackageJson(packageJsonPath);
54483
54513
  if (!pkg) return void 0;
54484
54514
  const packageManager = detectPackageManager(pkg, repoPath);
@@ -54506,12 +54536,12 @@ function maybeGenerateNodeDockerfile(repoPath) {
54506
54536
  };
54507
54537
  }
54508
54538
  function maybeGenerateSharedLibNodeDockerfile(repoPath) {
54509
- const packageJsonPath = (0, import_path2.join)(repoPath, "package.json");
54539
+ const packageJsonPath = (0, import_path3.join)(repoPath, "package.json");
54510
54540
  const pkg = readPackageJson(packageJsonPath);
54511
54541
  if (!pkg) return void 0;
54512
- const harnessDirName = (0, import_path2.basename)(repoPath);
54513
- const parentDir = (0, import_path2.dirname)(repoPath);
54514
- const sharedLibDir = (0, import_path2.join)(parentDir, "_lib");
54542
+ const harnessDirName = (0, import_path3.basename)(repoPath);
54543
+ const parentDir = (0, import_path3.dirname)(repoPath);
54544
+ const sharedLibDir = (0, import_path3.join)(parentDir, "_lib");
54515
54545
  if (!(0, import_fs2.existsSync)(sharedLibDir)) return void 0;
54516
54546
  let hasSharedLibFiles;
54517
54547
  try {
@@ -54626,7 +54656,7 @@ function generateDockerfile(repoPath) {
54626
54656
  }
54627
54657
  function resolveExplicitDockerfile(repoPath, rawPath) {
54628
54658
  const trimmed = rawPath.trim();
54629
- const dockerfilePath = (0, import_path2.resolve)(repoPath, trimmed);
54659
+ const dockerfilePath = (0, import_path3.resolve)(repoPath, trimmed);
54630
54660
  if (!(0, import_fs2.existsSync)(dockerfilePath) || !(0, import_fs2.statSync)(dockerfilePath).isFile()) {
54631
54661
  throw new DockerfileError(
54632
54662
  "invalid_path",
@@ -54637,7 +54667,7 @@ function resolveExplicitDockerfile(repoPath, rawPath) {
54637
54667
  return dockerfilePath;
54638
54668
  }
54639
54669
  function resolveDockerfile(repoPathInput, options) {
54640
- const repoPath = (0, import_path2.resolve)(repoPathInput);
54670
+ const repoPath = (0, import_path3.resolve)(repoPathInput);
54641
54671
  if (options?.explicitDockerfile?.trim()) {
54642
54672
  const dockerfilePath = resolveExplicitDockerfile(repoPath, options.explicitDockerfile);
54643
54673
  return {
@@ -54647,7 +54677,7 @@ function resolveDockerfile(repoPathInput, options) {
54647
54677
  summary: `using explicit Dockerfile ${dockerfilePath}`
54648
54678
  };
54649
54679
  }
54650
- const rootDockerfile = (0, import_path2.join)(repoPath, "Dockerfile");
54680
+ const rootDockerfile = (0, import_path3.join)(repoPath, "Dockerfile");
54651
54681
  if ((0, import_fs2.existsSync)(rootDockerfile) && (0, import_fs2.statSync)(rootDockerfile).isFile()) {
54652
54682
  return {
54653
54683
  source: "existing",
@@ -54671,7 +54701,7 @@ function resolveDockerfile(repoPathInput, options) {
54671
54701
  "Pass a generatedDockerfilePath to resolveDockerfile."
54672
54702
  );
54673
54703
  }
54674
- const generatedPath = (0, import_path2.resolve)(options.generatedDockerfilePath);
54704
+ const generatedPath = (0, import_path3.resolve)(options.generatedDockerfilePath);
54675
54705
  (0, import_fs2.writeFileSync)(generatedPath, generated.contents, "utf-8");
54676
54706
  return {
54677
54707
  source: "generated",
@@ -54687,9 +54717,9 @@ function generateCertAuthority() {
54687
54717
  });
54688
54718
  const certPem = generateSelfSignedCert(publicKey, privateKey, CA_COMMON_NAME, true);
54689
54719
  const keyPem = privateKey.export({ type: "pkcs8", format: "pem" });
54690
- const dir = (0, import_fs4.mkdtempSync)((0, import_path4.join)((0, import_os3.tmpdir)(), "archal-sandbox-ca-"));
54691
- const certPath = (0, import_path4.join)(dir, "ca.crt");
54692
- const keyPath = (0, import_path4.join)(dir, "ca.key");
54720
+ const dir = (0, import_fs4.mkdtempSync)((0, import_path5.join)((0, import_os3.tmpdir)(), "archal-sandbox-ca-"));
54721
+ const certPath = (0, import_path5.join)(dir, "ca.crt");
54722
+ const keyPath = (0, import_path5.join)(dir, "ca.key");
54693
54723
  (0, import_fs4.writeFileSync)(certPath, certPem);
54694
54724
  (0, import_fs4.writeFileSync)(keyPath, keyPem);
54695
54725
  return { certPem, keyPem, certPath, keyPath, dir };
@@ -55402,8 +55432,8 @@ function extractInlineArg(query, name) {
55402
55432
  const match = query.match(regex);
55403
55433
  return match?.[1];
55404
55434
  }
55405
- function forwardToCloudTwin(clientReq, clientRes, targetBaseUrl, path, authHeaders, injectResponseHeaders) {
55406
- const target = resolveForwardTarget(targetBaseUrl, path);
55435
+ function forwardToCloudTwin(clientReq, clientRes, targetBaseUrl, path2, authHeaders, injectResponseHeaders) {
55436
+ const target = resolveForwardTarget(targetBaseUrl, path2);
55407
55437
  const isHttps = target.protocol === "https:";
55408
55438
  const requestFn = isHttps ? import_https.request : import_http.request;
55409
55439
  const headers = {
@@ -55633,27 +55663,27 @@ function formatExecError(err) {
55633
55663
  return String(err);
55634
55664
  }
55635
55665
  function resolveLocalSandboxBuildTarget() {
55636
- const moduleDir = typeof import_meta3?.url === "string" ? (0, import_path5.dirname)((0, import_url.fileURLToPath)(import_meta3.url)) : typeof __dirname === "string" ? __dirname : process.cwd();
55666
+ const moduleDir = typeof import_meta4?.url === "string" ? (0, import_path6.dirname)((0, import_url2.fileURLToPath)(import_meta4.url)) : typeof __dirname === "string" ? __dirname : process.cwd();
55637
55667
  const candidates = [
55638
55668
  {
55639
- dockerfile: (0, import_path5.resolve)(process.cwd(), "packages/sandbox-runtime/docker/sandbox/Dockerfile"),
55640
- contextDir: (0, import_path5.resolve)(process.cwd(), "packages/sandbox-runtime")
55669
+ dockerfile: (0, import_path6.resolve)(process.cwd(), "packages/sandbox-runtime/docker/sandbox/Dockerfile"),
55670
+ contextDir: (0, import_path6.resolve)(process.cwd(), "packages/sandbox-runtime")
55641
55671
  },
55642
55672
  {
55643
- dockerfile: (0, import_path5.resolve)(process.cwd(), "cli/docker/sandbox/Dockerfile"),
55644
- contextDir: (0, import_path5.resolve)(process.cwd(), "cli")
55673
+ dockerfile: (0, import_path6.resolve)(process.cwd(), "cli/docker/sandbox/Dockerfile"),
55674
+ contextDir: (0, import_path6.resolve)(process.cwd(), "cli")
55645
55675
  },
55646
55676
  {
55647
- dockerfile: (0, import_path5.resolve)(process.cwd(), "docker/sandbox/Dockerfile"),
55677
+ dockerfile: (0, import_path6.resolve)(process.cwd(), "docker/sandbox/Dockerfile"),
55648
55678
  contextDir: process.cwd()
55649
55679
  },
55650
55680
  {
55651
- dockerfile: (0, import_path5.resolve)(moduleDir, "../docker/sandbox/Dockerfile"),
55652
- contextDir: (0, import_path5.resolve)(moduleDir, "..")
55681
+ dockerfile: (0, import_path6.resolve)(moduleDir, "../docker/sandbox/Dockerfile"),
55682
+ contextDir: (0, import_path6.resolve)(moduleDir, "..")
55653
55683
  },
55654
55684
  {
55655
- dockerfile: (0, import_path5.resolve)(moduleDir, "../../docker/sandbox/Dockerfile"),
55656
- contextDir: (0, import_path5.resolve)(moduleDir, "../..")
55685
+ dockerfile: (0, import_path6.resolve)(moduleDir, "../../docker/sandbox/Dockerfile"),
55686
+ contextDir: (0, import_path6.resolve)(moduleDir, "../..")
55657
55687
  }
55658
55688
  ];
55659
55689
  return candidates.find((candidate) => (0, import_fs5.existsSync)(candidate.dockerfile));
@@ -55661,15 +55691,15 @@ function resolveLocalSandboxBuildTarget() {
55661
55691
  function getSandboxRuntimeDependencyPaths(target) {
55662
55692
  return [
55663
55693
  target.dockerfile,
55664
- (0, import_path5.resolve)(target.contextDir, "docker/sandbox/entrypoint.sh"),
55665
- (0, import_path5.resolve)(target.contextDir, "src/sandbox/proxy-entry.ts"),
55666
- (0, import_path5.resolve)(target.contextDir, "src/sandbox/proxy.ts"),
55667
- (0, import_path5.resolve)(target.contextDir, "src/sandbox/twins.ts"),
55668
- (0, import_path5.resolve)(target.contextDir, "src/sandbox/certs.ts")
55669
- ].filter((path) => (0, import_fs5.existsSync)(path));
55694
+ (0, import_path6.resolve)(target.contextDir, "docker/sandbox/entrypoint.sh"),
55695
+ (0, import_path6.resolve)(target.contextDir, "src/sandbox/proxy-entry.ts"),
55696
+ (0, import_path6.resolve)(target.contextDir, "src/sandbox/proxy.ts"),
55697
+ (0, import_path6.resolve)(target.contextDir, "src/sandbox/twins.ts"),
55698
+ (0, import_path6.resolve)(target.contextDir, "src/sandbox/certs.ts")
55699
+ ].filter((path2) => (0, import_fs5.existsSync)(path2));
55670
55700
  }
55671
55701
  function getNewestSandboxRuntimeMtimeMs(target) {
55672
- return getSandboxRuntimeDependencyPaths(target).map((path) => (0, import_fs5.statSync)(path).mtimeMs).reduce((max, mtimeMs) => Math.max(max, mtimeMs), 0);
55702
+ return getSandboxRuntimeDependencyPaths(target).map((path2) => (0, import_fs5.statSync)(path2).mtimeMs).reduce((max, mtimeMs) => Math.max(max, mtimeMs), 0);
55673
55703
  }
55674
55704
  function getLocalImageCreatedAtMs(image) {
55675
55705
  try {
@@ -55766,8 +55796,8 @@ async function ensureSandboxImage(image, openclawVersion) {
55766
55796
  }
55767
55797
  function launchSandbox(config2) {
55768
55798
  const image = config2.image ?? DEFAULT_SANDBOX_IMAGE;
55769
- const artifactsDir = (0, import_fs5.mkdtempSync)((0, import_path5.join)((0, import_os4.tmpdir)(), "archal-sandbox-"));
55770
- const proxyEventsHostPath = (0, import_path5.join)(artifactsDir, "proxy-events.ndjson");
55799
+ const artifactsDir = (0, import_fs5.mkdtempSync)((0, import_path6.join)((0, import_os4.tmpdir)(), "archal-sandbox-"));
55800
+ const proxyEventsHostPath = (0, import_path6.join)(artifactsDir, "proxy-events.ndjson");
55771
55801
  const proxyEventsContainerPath = "/archal-artifacts/proxy-events.ndjson";
55772
55802
  const mounts = [];
55773
55803
  mounts.push("-v", `${artifactsDir}:/archal-artifacts`);
@@ -55868,9 +55898,9 @@ function spawnWithTimeout2(command, args, timeoutMs, artifacts) {
55868
55898
  });
55869
55899
  });
55870
55900
  }
55871
- function readProxyEvents(path) {
55901
+ function readProxyEvents(path2) {
55872
55902
  try {
55873
- const raw = (0, import_fs5.readFileSync)(path, "utf8").trim();
55903
+ const raw = (0, import_fs5.readFileSync)(path2, "utf8").trim();
55874
55904
  if (!raw) return [];
55875
55905
  return raw.split("\n").map((line) => {
55876
55906
  try {
@@ -56072,7 +56102,7 @@ function writeMountedConfigFiles(dir, cloudTwinUrls, authToken, caPath) {
56072
56102
  example: 'mcp__github__list_issues -> POST github-url/tools/call with { "name": "list_issues", "arguments": {} }'
56073
56103
  }
56074
56104
  };
56075
- (0, import_fs3.writeFileSync)((0, import_path3.join)(dir, "rest-config.json"), JSON.stringify(restConfig, null, 2) + "\n", "utf-8");
56105
+ (0, import_fs3.writeFileSync)((0, import_path4.join)(dir, "rest-config.json"), JSON.stringify(restConfig, null, 2) + "\n", "utf-8");
56076
56106
  const mcpServers = {};
56077
56107
  for (const [twinName, baseUrl] of Object.entries(cloudTwinUrls)) {
56078
56108
  const trimmed = baseUrl.trim().replace(/\/+$/, "");
@@ -56082,9 +56112,9 @@ function writeMountedConfigFiles(dir, cloudTwinUrls, authToken, caPath) {
56082
56112
  headers: { Authorization: `Bearer ${authToken}` }
56083
56113
  };
56084
56114
  }
56085
- (0, import_fs3.writeFileSync)((0, import_path3.join)(dir, "mcp-config.json"), JSON.stringify({ mcpServers }, null, 2) + "\n", "utf-8");
56086
- (0, import_fs3.writeFileSync)((0, import_path3.join)(dir, "mcp-servers.json"), JSON.stringify(mcpServers), "utf-8");
56087
- (0, import_fs3.writeFileSync)((0, import_path3.join)(dir, "ca.crt"), (0, import_fs3.readFileSync)(caPath, "utf-8"), "utf-8");
56115
+ (0, import_fs3.writeFileSync)((0, import_path4.join)(dir, "mcp-config.json"), JSON.stringify({ mcpServers }, null, 2) + "\n", "utf-8");
56116
+ (0, import_fs3.writeFileSync)((0, import_path4.join)(dir, "mcp-servers.json"), JSON.stringify(mcpServers), "utf-8");
56117
+ (0, import_fs3.writeFileSync)((0, import_path4.join)(dir, "ca.crt"), (0, import_fs3.readFileSync)(caPath, "utf-8"), "utf-8");
56088
56118
  }
56089
56119
  async function ensurePreparedImage(repoPath, dockerfilePath, image, timeoutMs) {
56090
56120
  const buildArgs = ["build", "-f", dockerfilePath, "-t", image, repoPath];
@@ -56107,12 +56137,12 @@ async function cleanupDockerImage(imageName) {
56107
56137
  await runDockerCommand(["image", "rm", "-f", imageName], 1e4);
56108
56138
  }
56109
56139
  async function buildDockerHarnessImage(repoPath, dockerfilePath, timeoutMs) {
56110
- const resolvedRepoPath = (0, import_path3.resolve)(repoPath);
56140
+ const resolvedRepoPath = (0, import_path4.resolve)(repoPath);
56111
56141
  const dockerIdSuffix = `${Date.now().toString(36)}-${process.pid}`;
56112
56142
  const imageName = `archal/harness-${dockerIdSuffix}`;
56113
- const buildDir = (0, import_fs3.mkdtempSync)((0, import_path3.join)((0, import_os2.tmpdir)(), "archal-harness-build-"));
56143
+ const buildDir = (0, import_fs3.mkdtempSync)((0, import_path4.join)((0, import_os2.tmpdir)(), "archal-harness-build-"));
56114
56144
  try {
56115
- const generatedDockerfilePath = (0, import_path3.join)(buildDir, "Dockerfile.generated");
56145
+ const generatedDockerfilePath = (0, import_path4.join)(buildDir, "Dockerfile.generated");
56116
56146
  let dockerfile;
56117
56147
  try {
56118
56148
  dockerfile = resolveDockerfile(resolvedRepoPath, {
@@ -56157,9 +56187,9 @@ async function runDockerHarness(config2) {
56157
56187
  "Install Docker Desktop or Docker Engine before using the Docker harness."
56158
56188
  ));
56159
56189
  }
56160
- const repoPath = (0, import_path3.resolve)(config2.repoPath);
56161
- const runDir = (0, import_fs3.mkdtempSync)((0, import_path3.join)((0, import_os2.tmpdir)(), "archal-harness-"));
56162
- const generatedDockerfilePath = (0, import_path3.join)(runDir, "Dockerfile.generated");
56190
+ const repoPath = (0, import_path4.resolve)(config2.repoPath);
56191
+ const runDir = (0, import_fs3.mkdtempSync)((0, import_path4.join)((0, import_os2.tmpdir)(), "archal-harness-"));
56192
+ const generatedDockerfilePath = (0, import_path4.join)(runDir, "Dockerfile.generated");
56163
56193
  const dockerIdSuffix = `${Date.now().toString(36)}-${process.pid}`;
56164
56194
  const imageName = config2.prebuiltImage ?? `archal/harness-${dockerIdSuffix}`;
56165
56195
  const containerName = `archal-harness-${dockerIdSuffix}`;
@@ -56208,23 +56238,23 @@ async function runDockerHarness(config2) {
56208
56238
  return fail(stageError("Docker harness attach failed", reason));
56209
56239
  }
56210
56240
  try {
56211
- const mountedConfigDir = (0, import_path3.join)(runDir, "out");
56241
+ const mountedConfigDir = (0, import_path4.join)(runDir, "out");
56212
56242
  writeMountedConfigFiles(mountedConfigDir, config2.cloudTwinUrls, config2.authToken, ca.certPath);
56213
56243
  const env = buildContainerEnv(config2, proxy.port);
56214
- env["ARCHAL_MCP_SERVERS"] = (0, import_fs3.readFileSync)((0, import_path3.join)(mountedConfigDir, "mcp-servers.json"), "utf-8");
56244
+ env["ARCHAL_MCP_SERVERS"] = (0, import_fs3.readFileSync)((0, import_path4.join)(mountedConfigDir, "mcp-servers.json"), "utf-8");
56215
56245
  const envFileLines = [];
56216
56246
  let multiLineIdx = 0;
56217
56247
  for (const [key, value] of Object.entries(env)) {
56218
56248
  if (value.includes("\n")) {
56219
56249
  const filename = `_env_${multiLineIdx++}_${key.toLowerCase()}`;
56220
- (0, import_fs3.writeFileSync)((0, import_path3.join)(mountedConfigDir, filename), value, { encoding: "utf-8", mode: 384 });
56250
+ (0, import_fs3.writeFileSync)((0, import_path4.join)(mountedConfigDir, filename), value, { encoding: "utf-8", mode: 384 });
56221
56251
  envFileLines.push(`${key}_FILE=${OUTPUT_DIR_IN_CONTAINER}/${filename}`);
56222
56252
  envFileLines.push(`${key}=${OUTPUT_DIR_IN_CONTAINER}/${filename}`);
56223
56253
  } else {
56224
56254
  envFileLines.push(`${key}=${value}`);
56225
56255
  }
56226
56256
  }
56227
- const envFilePath = (0, import_path3.join)(runDir, ".env");
56257
+ const envFilePath = (0, import_path4.join)(runDir, ".env");
56228
56258
  (0, import_fs3.writeFileSync)(envFilePath, envFileLines.join("\n") + "\n", { encoding: "utf-8", mode: 384 });
56229
56259
  const args = [
56230
56260
  "run",
@@ -56300,7 +56330,7 @@ async function runDockerHarness(config2) {
56300
56330
  } catch {
56301
56331
  }
56302
56332
  }
56303
- const envPath = (0, import_path3.join)(runDir, ".env");
56333
+ const envPath = (0, import_path4.join)(runDir, ".env");
56304
56334
  try {
56305
56335
  if ((0, import_fs3.existsSync)(envPath)) {
56306
56336
  const size = (0, import_fs3.statSync)(envPath).size;
@@ -56352,7 +56382,7 @@ async function runLocalProxy(config2, task, canaryFiles) {
56352
56382
  if (hostsEntries) {
56353
56383
  status("NOTE: For full interception in local mode, add these to /etc/hosts:\n" + hostsEntries);
56354
56384
  }
56355
- const workspace = config2.workspacePath ?? (0, import_path6.join)(process.env["HOME"] ?? "/root", ".openclaw");
56385
+ const workspace = config2.workspacePath ?? (0, import_path7.join)(process.env["HOME"] ?? "/root", ".openclaw");
56356
56386
  const noProxyHosts = "127.0.0.1,localhost,.archal.ai";
56357
56387
  const env = {
56358
56388
  ...process.env,
@@ -56387,13 +56417,13 @@ async function runLocalProxy(config2, task, canaryFiles) {
56387
56417
  }
56388
56418
  }
56389
56419
  function writeCanaryFiles(workspace, canaryFiles) {
56390
- const resolvedWorkspace = (0, import_path6.resolve)(workspace);
56420
+ const resolvedWorkspace = (0, import_path7.resolve)(workspace);
56391
56421
  for (const [relativePath, content] of Object.entries(canaryFiles)) {
56392
- const filePath = (0, import_path6.resolve)(workspace, relativePath);
56393
- if (filePath !== resolvedWorkspace && !filePath.startsWith(resolvedWorkspace + import_path6.sep)) {
56422
+ const filePath = (0, import_path7.resolve)(workspace, relativePath);
56423
+ if (filePath !== resolvedWorkspace && !filePath.startsWith(resolvedWorkspace + import_path7.sep)) {
56394
56424
  throw new Error(`Canary path escapes sandbox root: ${relativePath}`);
56395
56425
  }
56396
- (0, import_fs6.mkdirSync)((0, import_path6.dirname)(filePath), { recursive: true });
56426
+ (0, import_fs6.mkdirSync)((0, import_path7.dirname)(filePath), { recursive: true });
56397
56427
  (0, import_fs6.writeFileSync)(filePath, content);
56398
56428
  }
56399
56429
  }
@@ -56462,9 +56492,9 @@ function spawnAgent(workspace, task, env, timeoutMs) {
56462
56492
  });
56463
56493
  }
56464
56494
  function confinePath(root, relativePath) {
56465
- const resolvedRoot = (0, import_path7.resolve)(root);
56466
- const resolved = (0, import_path7.resolve)(root, relativePath);
56467
- if (resolved !== resolvedRoot && !resolved.startsWith(resolvedRoot + import_path7.sep)) {
56495
+ const resolvedRoot = (0, import_path8.resolve)(root);
56496
+ const resolved = (0, import_path8.resolve)(root, relativePath);
56497
+ if (resolved !== resolvedRoot && !resolved.startsWith(resolvedRoot + import_path8.sep)) {
56468
56498
  throw new Error(`Canary path escapes sandbox root: ${relativePath}`);
56469
56499
  }
56470
56500
  return resolved;
@@ -56727,19 +56757,19 @@ async function runDockerSandbox(config2) {
56727
56757
  error: result.timedOut ? `Sandbox timed out after ${Math.round(config2.timeoutMs / 1e3)}s` : result.exitCode !== 0 ? `Sandbox exited with code ${result.exitCode}` : void 0
56728
56758
  };
56729
56759
  }
56730
- var import_fs2, import_path2, import_fs3, import_os2, import_path3, import_crypto3, import_fs4, import_path4, import_os3, import_http, import_https, import_tls, import_net, import_child_process2, import_fs5, import_os4, import_path5, import_url, import_child_process3, import_child_process4, import_fs6, import_path6, import_path7, import_meta3, DockerfileError, NODE_SCRIPT_PRIORITY, CA_COMMON_NAME, CERT_VALIDITY_DAYS, domainCertCache, REQUEST_BODY_PREVIEW_HEAD_LIMIT, REQUEST_BODY_PREVIEW_TAIL_LIMIT, GITHUB_RESPONSE_HEADERS, PASSTHROUGH_CONNECT_TIMEOUT_MS, TWIN_DOMAINS, DEFAULT_SANDBOX_IMAGE, VERSIONED_SANDBOX_TAG_PREFIX, MAX_OUTPUT_BYTES, KILL_GRACE_MS, MAX_OUTPUT_BYTES2, OUTPUT_DIR_IN_CONTAINER, HOST_GATEWAY_NAME, BUILD_TIMEOUT_CAP_MS, SANDBOX_CANARY_TAG, CANARY_LEAK_ERROR_CODE, CANARY_VALUE_PATTERN, SANDBOX_FILES_BLOCK_PATTERN, SNIPPET_RADIUS, DOCKER_IMAGE_NAME;
56760
+ var import_fs2, import_path3, import_fs3, import_os2, import_path4, import_crypto3, import_fs4, import_path5, import_os3, import_http, import_https, import_tls, import_net, import_child_process2, import_fs5, import_os4, import_path6, import_url2, import_child_process3, import_child_process4, import_fs6, import_path7, import_path8, import_meta4, DockerfileError, NODE_SCRIPT_PRIORITY, CA_COMMON_NAME, CERT_VALIDITY_DAYS, domainCertCache, REQUEST_BODY_PREVIEW_HEAD_LIMIT, REQUEST_BODY_PREVIEW_TAIL_LIMIT, GITHUB_RESPONSE_HEADERS, PASSTHROUGH_CONNECT_TIMEOUT_MS, TWIN_DOMAINS, DEFAULT_SANDBOX_IMAGE, VERSIONED_SANDBOX_TAG_PREFIX, MAX_OUTPUT_BYTES, KILL_GRACE_MS, MAX_OUTPUT_BYTES2, OUTPUT_DIR_IN_CONTAINER, HOST_GATEWAY_NAME, BUILD_TIMEOUT_CAP_MS, SANDBOX_CANARY_TAG, CANARY_LEAK_ERROR_CODE, CANARY_VALUE_PATTERN, SANDBOX_FILES_BLOCK_PATTERN, SNIPPET_RADIUS, DOCKER_IMAGE_NAME;
56731
56761
  var init_dist6 = __esm({
56732
56762
  "../packages/sandbox-runtime/dist/index.js"() {
56733
56763
  "use strict";
56734
56764
  import_fs2 = require("fs");
56735
- import_path2 = require("path");
56765
+ import_path3 = require("path");
56736
56766
  import_fs3 = require("fs");
56737
56767
  import_os2 = require("os");
56738
- import_path3 = require("path");
56768
+ import_path4 = require("path");
56739
56769
  init_dist2();
56740
56770
  import_crypto3 = require("crypto");
56741
56771
  import_fs4 = require("fs");
56742
- import_path4 = require("path");
56772
+ import_path5 = require("path");
56743
56773
  import_os3 = require("os");
56744
56774
  import_http = require("http");
56745
56775
  import_https = require("https");
@@ -56748,15 +56778,15 @@ var init_dist6 = __esm({
56748
56778
  import_child_process2 = require("child_process");
56749
56779
  import_fs5 = require("fs");
56750
56780
  import_os4 = require("os");
56751
- import_path5 = require("path");
56752
- import_url = require("url");
56781
+ import_path6 = require("path");
56782
+ import_url2 = require("url");
56753
56783
  import_child_process3 = require("child_process");
56754
56784
  import_child_process4 = require("child_process");
56755
56785
  import_fs6 = require("fs");
56756
- import_path6 = require("path");
56757
56786
  import_path7 = require("path");
56787
+ import_path8 = require("path");
56758
56788
  init_dist4();
56759
- import_meta3 = {};
56789
+ import_meta4 = {};
56760
56790
  DockerfileError = class extends Error {
56761
56791
  kind;
56762
56792
  suggestion;
@@ -56822,13 +56852,13 @@ __export(archal_file_exports, {
56822
56852
  function loadArchalFile(explicitPath) {
56823
56853
  let filePath;
56824
56854
  if (explicitPath) {
56825
- filePath = (0, import_node_path21.resolve)(explicitPath);
56826
- if (!(0, import_node_fs25.existsSync)(filePath)) throw new Error(`Config file not found: ${filePath}`);
56855
+ filePath = (0, import_node_path22.resolve)(explicitPath);
56856
+ if (!(0, import_node_fs26.existsSync)(filePath)) throw new Error(`Config file not found: ${filePath}`);
56827
56857
  } else {
56828
- filePath = (0, import_node_path21.resolve)(ARCHAL_FILENAME);
56829
- if (!(0, import_node_fs25.existsSync)(filePath)) return null;
56858
+ filePath = (0, import_node_path22.resolve)(ARCHAL_FILENAME);
56859
+ if (!(0, import_node_fs26.existsSync)(filePath)) return null;
56830
56860
  }
56831
- const raw = (0, import_node_fs25.readFileSync)(filePath, "utf-8").trim();
56861
+ const raw = (0, import_node_fs26.readFileSync)(filePath, "utf-8").trim();
56832
56862
  if (!raw) throw new Error(`Config file is empty: ${filePath}`);
56833
56863
  let parsed;
56834
56864
  try {
@@ -56860,14 +56890,14 @@ function loadArchalFile(explicitPath) {
56860
56890
  if (typeof c["model"] === "string") r.model = c["model"].trim() || void 0;
56861
56891
  if (typeof c["runs"] === "number" && Number.isInteger(c["runs"]) && c["runs"] > 0) r.runs = c["runs"];
56862
56892
  if (typeof c["timeout"] === "number" && c["timeout"] > 0) r.timeout = c["timeout"];
56863
- return { config: r, configDir: (0, import_node_path21.dirname)(filePath) };
56893
+ return { config: r, configDir: (0, import_node_path22.dirname)(filePath) };
56864
56894
  }
56865
- var import_node_fs25, import_node_path21, ARCHAL_FILENAME;
56895
+ var import_node_fs26, import_node_path22, ARCHAL_FILENAME;
56866
56896
  var init_archal_file = __esm({
56867
56897
  "src/config/archal-file.ts"() {
56868
56898
  "use strict";
56869
- import_node_fs25 = require("fs");
56870
- import_node_path21 = require("path");
56899
+ import_node_fs26 = require("fs");
56900
+ import_node_path22 = require("path");
56871
56901
  ARCHAL_FILENAME = ".archal.json";
56872
56902
  }
56873
56903
  });
@@ -56926,7 +56956,7 @@ function detectTwinsFromSource(source) {
56926
56956
  function detectTwinsFromPackageJson(packageJsonPath) {
56927
56957
  const twins = /* @__PURE__ */ new Set();
56928
56958
  try {
56929
- const pkg = JSON.parse((0, import_node_fs26.readFileSync)(packageJsonPath, "utf-8"));
56959
+ const pkg = JSON.parse((0, import_node_fs27.readFileSync)(packageJsonPath, "utf-8"));
56930
56960
  for (const depName of Object.keys({ ...pkg.dependencies, ...pkg.devDependencies })) {
56931
56961
  const twinName = PACKAGE_TO_TWIN[depName];
56932
56962
  if (twinName) twins.add(twinName);
@@ -56938,26 +56968,26 @@ function detectTwinsFromPackageJson(packageJsonPath) {
56938
56968
  function detectTwinsFromHarnessDir(harnessDir) {
56939
56969
  const twins = /* @__PURE__ */ new Set();
56940
56970
  for (const candidate of ENTRY_CANDIDATES) {
56941
- const filePath = (0, import_node_path22.resolve)(harnessDir, candidate);
56942
- if (!(0, import_node_fs26.existsSync)(filePath)) continue;
56971
+ const filePath = (0, import_node_path23.resolve)(harnessDir, candidate);
56972
+ if (!(0, import_node_fs27.existsSync)(filePath)) continue;
56943
56973
  try {
56944
- for (const twin of detectTwinsFromSource((0, import_node_fs26.readFileSync)(filePath, "utf-8"))) {
56974
+ for (const twin of detectTwinsFromSource((0, import_node_fs27.readFileSync)(filePath, "utf-8"))) {
56945
56975
  twins.add(twin);
56946
56976
  }
56947
56977
  } catch {
56948
56978
  }
56949
56979
  }
56950
- for (const twin of detectTwinsFromPackageJson((0, import_node_path22.resolve)(harnessDir, "package.json"))) {
56980
+ for (const twin of detectTwinsFromPackageJson((0, import_node_path23.resolve)(harnessDir, "package.json"))) {
56951
56981
  twins.add(twin);
56952
56982
  }
56953
56983
  return [...twins].sort();
56954
56984
  }
56955
- var import_node_fs26, import_node_path22, ENTRY_CANDIDATES, IMPORT_PATTERNS, ENV_VAR_PATTERN;
56985
+ var import_node_fs27, import_node_path23, ENTRY_CANDIDATES, IMPORT_PATTERNS, ENV_VAR_PATTERN;
56956
56986
  var init_harness_import_detector = __esm({
56957
56987
  "src/runner/harness-import-detector.ts"() {
56958
56988
  "use strict";
56959
- import_node_fs26 = require("fs");
56960
- import_node_path22 = require("path");
56989
+ import_node_fs27 = require("fs");
56990
+ import_node_path23 = require("path");
56961
56991
  init_package_twin_map();
56962
56992
  ENTRY_CANDIDATES = [
56963
56993
  "harness.ts",
@@ -56983,7 +57013,7 @@ __export(twins_exports, {
56983
57013
  listTwinCatalog: () => listTwinCatalog
56984
57014
  });
56985
57015
  function hasFidelityBaseline(twinName) {
56986
- return findFirstExistingLocalTwinAssetPath(import_meta4.url, twinName, "fidelity.json") !== null;
57016
+ return findFirstExistingLocalTwinAssetPath(import_meta5.url, twinName, "fidelity.json") !== null;
56987
57017
  }
56988
57018
  function writeLocalTwinCatalogJson() {
56989
57019
  process.stdout.write(JSON.stringify(
@@ -57051,7 +57081,7 @@ async function listTwinCatalog(json2) {
57051
57081
  table(["Name", "Tools", "Description", "Status"], rows);
57052
57082
  success2(twinCatalogSummary(creds));
57053
57083
  }
57054
- var import_meta4, KNOWN_TWINS;
57084
+ var import_meta5, KNOWN_TWINS;
57055
57085
  var init_twins = __esm({
57056
57086
  "src/commands/twins.ts"() {
57057
57087
  "use strict";
@@ -57059,7 +57089,7 @@ var init_twins = __esm({
57059
57089
  init_auth();
57060
57090
  init_api_client();
57061
57091
  init_bundled_assets();
57062
- import_meta4 = {};
57092
+ import_meta5 = {};
57063
57093
  KNOWN_TWINS = [
57064
57094
  { name: "github", description: "GitHub digital twin" },
57065
57095
  { name: "slack", description: "Slack digital twin" },
@@ -57096,8 +57126,8 @@ init_dist2();
57096
57126
  // src/commands/run.ts
57097
57127
  init_dist2();
57098
57128
  var import_node_crypto7 = require("crypto");
57099
- var import_node_fs27 = require("fs");
57100
- var import_node_path23 = require("path");
57129
+ var import_node_fs28 = require("fs");
57130
+ var import_node_path24 = require("path");
57101
57131
 
57102
57132
  // src/commands/task-scenario.ts
57103
57133
  var import_node_fs = require("fs");
@@ -57456,17 +57486,17 @@ function isLoopbackUrl(rawUrl) {
57456
57486
  function isNonLocalEndpoint(rawUrl) {
57457
57487
  return !isLoopbackUrl(rawUrl);
57458
57488
  }
57459
- function parseUrlOverridesFile(path, label) {
57460
- if (!path) return void 0;
57461
- if (!(0, import_node_fs4.existsSync)(path)) {
57462
- throw new Error(`${label.fileNotFound}: ${path}`);
57489
+ function parseUrlOverridesFile(path2, label) {
57490
+ if (!path2) return void 0;
57491
+ if (!(0, import_node_fs4.existsSync)(path2)) {
57492
+ throw new Error(`${label.fileNotFound}: ${path2}`);
57463
57493
  }
57464
- const raw = (0, import_node_fs4.readFileSync)(path, "utf-8");
57494
+ const raw = (0, import_node_fs4.readFileSync)(path2, "utf-8");
57465
57495
  const parsed = JSON.parse(raw);
57466
57496
  const overrides = {};
57467
57497
  for (const [key, value] of Object.entries(parsed)) {
57468
57498
  if (typeof value !== "string" || !value.trim()) {
57469
- throw new Error(`${label.invalidEntry} for "${key}" in ${path}`);
57499
+ throw new Error(`${label.invalidEntry} for "${key}" in ${path2}`);
57470
57500
  }
57471
57501
  const trimmed = value.trim();
57472
57502
  try {
@@ -57475,21 +57505,21 @@ function parseUrlOverridesFile(path, label) {
57475
57505
  throw new Error("missing protocol");
57476
57506
  }
57477
57507
  } catch {
57478
- throw new Error(`${label.invalidUrl} "${key}" in ${path}: ${trimmed}`);
57508
+ throw new Error(`${label.invalidUrl} "${key}" in ${path2}: ${trimmed}`);
57479
57509
  }
57480
57510
  overrides[key] = trimmed;
57481
57511
  }
57482
57512
  return overrides;
57483
57513
  }
57484
- function parseRemoteTwinUrlOverrides(path) {
57485
- return parseUrlOverridesFile(path, {
57514
+ function parseRemoteTwinUrlOverrides(path2) {
57515
+ return parseUrlOverridesFile(path2, {
57486
57516
  fileNotFound: "Twin URL overrides file not found",
57487
57517
  invalidEntry: "Invalid twin URL override",
57488
57518
  invalidUrl: "Invalid URL for twin"
57489
57519
  });
57490
57520
  }
57491
- function parseApiBaseUrlOverrides(path) {
57492
- return parseUrlOverridesFile(path, {
57521
+ function parseApiBaseUrlOverrides(path2) {
57522
+ return parseUrlOverridesFile(path2, {
57493
57523
  fileNotFound: "API base URL overrides file not found",
57494
57524
  invalidEntry: "Invalid API base URL override",
57495
57525
  invalidUrl: "Invalid API base URL for"
@@ -60201,7 +60231,7 @@ var import_node_fs9 = require("fs");
60201
60231
  var import_node_path7 = require("path");
60202
60232
  init_dist2();
60203
60233
  init_bundled_assets();
60204
- var import_meta2 = {};
60234
+ var import_meta3 = {};
60205
60235
  function isIdKeyedCollection(value) {
60206
60236
  if (!Array.isArray(value)) return false;
60207
60237
  if (value.length === 0) return false;
@@ -60439,7 +60469,7 @@ function normalizeSeedState(raw) {
60439
60469
  return Object.keys(normalized).length > 0 ? normalized : null;
60440
60470
  }
60441
60471
  function loadBaseSeedFromDisk(twinName, seedName) {
60442
- for (const seedRoot of resolveLocalTwinAssetCandidates(import_meta2.url, twinName, "seeds")) {
60472
+ for (const seedRoot of resolveLocalTwinAssetCandidates(import_meta3.url, twinName, "seeds")) {
60443
60473
  const seedState = loadSeedStateFromPath(seedRoot, seedName);
60444
60474
  if (seedState) {
60445
60475
  return seedState;
@@ -66385,12 +66415,12 @@ function listCommandCandidates(command) {
66385
66415
  }
66386
66416
  return [...variants];
66387
66417
  }
66388
- function isExecutable(path) {
66418
+ function isExecutable(path2) {
66389
66419
  try {
66390
- (0, import_node_fs18.accessSync)(path, import_node_fs18.constants.X_OK);
66420
+ (0, import_node_fs18.accessSync)(path2, import_node_fs18.constants.X_OK);
66391
66421
  return true;
66392
66422
  } catch {
66393
- return process.platform === "win32" && (0, import_node_fs18.existsSync)(path);
66423
+ return process.platform === "win32" && (0, import_node_fs18.existsSync)(path2);
66394
66424
  }
66395
66425
  }
66396
66426
  function isCommandAvailable(command) {
@@ -66639,6 +66669,83 @@ ${lines.join("\n")}`
66639
66669
  init_cache();
66640
66670
  init_auth();
66641
66671
  init_api_client();
66672
+
66673
+ // src/commands/env-session-reuse.ts
66674
+ var import_node_fs20 = require("fs");
66675
+ var import_node_os7 = require("os");
66676
+ var import_node_path16 = require("path");
66677
+ init_auth();
66678
+ var TWIN_SESSION_FILE = (0, import_node_path16.join)((0, import_node_os7.homedir)(), ".archal", "twin-session.json");
66679
+ var LEGACY_SESSION_FILE = (0, import_node_path16.join)((0, import_node_os7.homedir)(), ".archal", "env-session.json");
66680
+ function loadSession() {
66681
+ let filePath = TWIN_SESSION_FILE;
66682
+ if (!(0, import_node_fs20.existsSync)(filePath)) {
66683
+ if ((0, import_node_fs20.existsSync)(LEGACY_SESSION_FILE)) {
66684
+ filePath = LEGACY_SESSION_FILE;
66685
+ } else {
66686
+ return null;
66687
+ }
66688
+ }
66689
+ try {
66690
+ return JSON.parse((0, import_node_fs20.readFileSync)(filePath, "utf8"));
66691
+ } catch {
66692
+ return null;
66693
+ }
66694
+ }
66695
+ function resolveApiBaseUrl() {
66696
+ return getConfiguredApiBaseUrl2() ?? "https://api.archal.ai";
66697
+ }
66698
+ async function tryReuseEnvSession(requiredTwins, credentials) {
66699
+ try {
66700
+ const session = loadSession();
66701
+ if (!session) {
66702
+ return null;
66703
+ }
66704
+ if (!requiredTwins.every((t) => session.twins.includes(t))) {
66705
+ return null;
66706
+ }
66707
+ const missingEndpoints = requiredTwins.filter(
66708
+ (t) => !session.endpoints[t] && !session.apiBaseUrls[t]
66709
+ );
66710
+ if (missingEndpoints.length > 0) {
66711
+ return null;
66712
+ }
66713
+ let apiBase = resolveApiBaseUrl();
66714
+ if (session.apiBaseUrl) {
66715
+ try {
66716
+ const parsed = new URL(session.apiBaseUrl);
66717
+ const isLocalHttp = parsed.protocol === "http:" && (parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1");
66718
+ if (parsed.protocol === "https:" || isLocalHttp) {
66719
+ apiBase = session.apiBaseUrl;
66720
+ }
66721
+ } catch {
66722
+ }
66723
+ }
66724
+ const response = await fetch(`${apiBase}/api/sessions/${session.sessionId}`, {
66725
+ method: "GET",
66726
+ headers: {
66727
+ "Authorization": `Bearer ${credentials.token}`,
66728
+ "Content-Type": "application/json"
66729
+ }
66730
+ });
66731
+ if (!response.ok) {
66732
+ return null;
66733
+ }
66734
+ const data = await response.json();
66735
+ if (data.status !== "ready") {
66736
+ return null;
66737
+ }
66738
+ return {
66739
+ sessionId: session.sessionId,
66740
+ endpoints: session.endpoints,
66741
+ apiBaseUrls: session.apiBaseUrls
66742
+ };
66743
+ } catch {
66744
+ return null;
66745
+ }
66746
+ }
66747
+
66748
+ // src/commands/run.ts
66642
66749
  init_errors4();
66643
66750
  init_logger();
66644
66751
 
@@ -66675,24 +66782,24 @@ async function runShutdownHooks(signal) {
66675
66782
  init_config();
66676
66783
 
66677
66784
  // src/commands/run-config-resolver.ts
66678
- var import_node_fs21 = require("fs");
66679
- var import_node_path17 = require("path");
66785
+ var import_node_fs22 = require("fs");
66786
+ var import_node_path18 = require("path");
66680
66787
  init_config();
66681
66788
 
66682
66789
  // src/commands/openclaw-shared.ts
66683
- var import_node_fs20 = require("fs");
66684
- var import_node_os7 = require("os");
66685
- var import_node_path16 = require("path");
66790
+ var import_node_fs21 = require("fs");
66791
+ var import_node_os8 = require("os");
66792
+ var import_node_path17 = require("path");
66686
66793
  var OPENCLAW_HARNESS_ALIASES = /* @__PURE__ */ new Set(["openclaw", "oc", "nemoclaw", "nemo"]);
66687
66794
  function isOpenClawHarnessName(name) {
66688
66795
  return OPENCLAW_HARNESS_ALIASES.has(name.trim().toLowerCase());
66689
66796
  }
66690
- function resolveDefaultOpenClawHome(opts, homeDir = (0, import_node_os7.homedir)()) {
66797
+ function resolveDefaultOpenClawHome(opts, homeDir = (0, import_node_os8.homedir)()) {
66691
66798
  if (opts.openclawHome?.trim() || opts.workspace?.trim() || opts.openclawConfig?.trim()) {
66692
66799
  return void 0;
66693
66800
  }
66694
- const defaultHome = (0, import_node_path16.join)(homeDir, ".openclaw");
66695
- return (0, import_node_fs20.existsSync)(defaultHome) ? defaultHome : void 0;
66801
+ const defaultHome = (0, import_node_path17.join)(homeDir, ".openclaw");
66802
+ return (0, import_node_fs21.existsSync)(defaultHome) ? defaultHome : void 0;
66696
66803
  }
66697
66804
  function detectApiKeyProvider(key) {
66698
66805
  if (!key) return "unknown";
@@ -66772,7 +66879,7 @@ function resolveFromCandidates(candidates, fallback) {
66772
66879
  return fallback;
66773
66880
  }
66774
66881
  function loadProjectConfigForScenario(scenarioPath) {
66775
- const root = findNearestProjectRoot((0, import_node_path17.dirname)((0, import_node_path17.resolve)(scenarioPath)), process.cwd());
66882
+ const root = findNearestProjectRoot((0, import_node_path18.dirname)((0, import_node_path18.resolve)(scenarioPath)), process.cwd());
66776
66883
  if (!root) {
66777
66884
  return {
66778
66885
  root: null,
@@ -66782,7 +66889,7 @@ function loadProjectConfigForScenario(scenarioPath) {
66782
66889
  }
66783
66890
  return {
66784
66891
  root,
66785
- configPath: (0, import_node_path17.join)(root, ".archal.json"),
66892
+ configPath: (0, import_node_path18.join)(root, ".archal.json"),
66786
66893
  config: loadProjectConfig(root)
66787
66894
  };
66788
66895
  }
@@ -67203,7 +67310,7 @@ function resolveRunConfigWithSources(scenarioPath, opts, sources, preloaded) {
67203
67310
  { value: void 0, source: "unset", detail: "(not set)" }
67204
67311
  );
67205
67312
  return {
67206
- scenarioPath: (0, import_node_path17.resolve)(scenarioPath),
67313
+ scenarioPath: (0, import_node_path18.resolve)(scenarioPath),
67207
67314
  projectRoot: project.root,
67208
67315
  projectConfigPath: project.configPath,
67209
67316
  invalidExplicitRuns,
@@ -67240,13 +67347,13 @@ function applyResolvedRunConfigToOptions(opts, resolved) {
67240
67347
  function findNearestProjectRoot(...startPaths) {
67241
67348
  for (const start of startPaths) {
67242
67349
  if (!start || !start.trim()) continue;
67243
- let current = (0, import_node_path17.resolve)(start);
67350
+ let current = (0, import_node_path18.resolve)(start);
67244
67351
  while (true) {
67245
- const candidate = (0, import_node_path17.join)(current, ".archal.json");
67246
- if ((0, import_node_fs21.existsSync)(candidate)) {
67352
+ const candidate = (0, import_node_path18.join)(current, ".archal.json");
67353
+ if ((0, import_node_fs22.existsSync)(candidate)) {
67247
67354
  return current;
67248
67355
  }
67249
- const parent = (0, import_node_path17.dirname)(current);
67356
+ const parent = (0, import_node_path18.dirname)(current);
67250
67357
  if (parent === current) break;
67251
67358
  current = parent;
67252
67359
  }
@@ -67255,8 +67362,8 @@ function findNearestProjectRoot(...startPaths) {
67255
67362
  }
67256
67363
 
67257
67364
  // src/commands/run-session.ts
67258
- var import_node_fs22 = require("fs");
67259
- var import_node_path18 = require("path");
67365
+ var import_node_fs23 = require("fs");
67366
+ var import_node_path19 = require("path");
67260
67367
  init_dist2();
67261
67368
  init_api_client();
67262
67369
  init_auth();
@@ -67548,9 +67655,9 @@ function writeManagedRunStatus(patch) {
67548
67655
  if (!statusPath) return;
67549
67656
  try {
67550
67657
  let existing = {};
67551
- if ((0, import_node_fs22.existsSync)(statusPath)) {
67658
+ if ((0, import_node_fs23.existsSync)(statusPath)) {
67552
67659
  try {
67553
- const raw = (0, import_node_fs22.readFileSync)(statusPath, "utf-8");
67660
+ const raw = (0, import_node_fs23.readFileSync)(statusPath, "utf-8");
67554
67661
  const parsed = JSON.parse(raw);
67555
67662
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
67556
67663
  existing = parsed;
@@ -67559,8 +67666,8 @@ function writeManagedRunStatus(patch) {
67559
67666
  }
67560
67667
  }
67561
67668
  const merged = { ...existing, ...patch, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
67562
- (0, import_node_fs22.mkdirSync)((0, import_node_path18.dirname)(statusPath), { recursive: true });
67563
- (0, import_node_fs22.writeFileSync)(statusPath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
67669
+ (0, import_node_fs23.mkdirSync)((0, import_node_path19.dirname)(statusPath), { recursive: true });
67670
+ (0, import_node_fs23.writeFileSync)(statusPath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
67564
67671
  } catch {
67565
67672
  }
67566
67673
  }
@@ -67578,9 +67685,21 @@ function resolveManagedRunProjectMetadata(opts) {
67578
67685
  const description = opts?.runProjectDescription?.trim() || process.env["ARCHAL_WEB_RUN_PROJECT_DESCRIPTION"]?.trim();
67579
67686
  return { id, name, description };
67580
67687
  }
67688
+ function buildRuntimeTwinUrls(sessionId, twins, runtimeBaseUrl) {
67689
+ const base = runtimeBaseUrl.replace(/\/+$/, "");
67690
+ const sessionPath = encodeURIComponent(sessionId);
67691
+ const endpoints = {};
67692
+ const apiBaseUrls = {};
67693
+ for (const twin of twins) {
67694
+ const root = `${base}/runtime/${sessionPath}/${encodeURIComponent(twin)}`;
67695
+ endpoints[twin] = root;
67696
+ apiBaseUrls[twin] = `${root}/api`;
67697
+ }
67698
+ return { endpoints, apiBaseUrls };
67699
+ }
67581
67700
  function writeTempJsonMap(filePath, data, context) {
67582
67701
  try {
67583
- (0, import_node_fs22.writeFileSync)(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
67702
+ (0, import_node_fs23.writeFileSync)(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
67584
67703
  return { ok: true };
67585
67704
  } catch (err) {
67586
67705
  const reason = errorMessage(err);
@@ -67588,17 +67707,17 @@ function writeTempJsonMap(filePath, data, context) {
67588
67707
  }
67589
67708
  }
67590
67709
  function cleanupGeneratedSessionMaps(ctx) {
67591
- if (ctx.generatedTwinUrlMapPath && (0, import_node_fs22.existsSync)(ctx.generatedTwinUrlMapPath)) {
67710
+ if (ctx.generatedTwinUrlMapPath && (0, import_node_fs23.existsSync)(ctx.generatedTwinUrlMapPath)) {
67592
67711
  try {
67593
- (0, import_node_fs22.unlinkSync)(ctx.generatedTwinUrlMapPath);
67712
+ (0, import_node_fs23.unlinkSync)(ctx.generatedTwinUrlMapPath);
67594
67713
  } catch (error49) {
67595
67714
  process.stderr.write(`Warning: failed to remove temp twin URL map: ${errorMessage(error49)}
67596
67715
  `);
67597
67716
  }
67598
67717
  }
67599
- if (ctx.generatedApiBaseUrlMapPath && (0, import_node_fs22.existsSync)(ctx.generatedApiBaseUrlMapPath)) {
67718
+ if (ctx.generatedApiBaseUrlMapPath && (0, import_node_fs23.existsSync)(ctx.generatedApiBaseUrlMapPath)) {
67600
67719
  try {
67601
- (0, import_node_fs22.unlinkSync)(ctx.generatedApiBaseUrlMapPath);
67720
+ (0, import_node_fs23.unlinkSync)(ctx.generatedApiBaseUrlMapPath);
67602
67721
  } catch (error49) {
67603
67722
  process.stderr.write(`Warning: failed to remove temp API base URL map: ${errorMessage(error49)}
67604
67723
  `);
@@ -67607,6 +67726,9 @@ function cleanupGeneratedSessionMaps(ctx) {
67607
67726
  }
67608
67727
  async function cleanupHostedSession(ctx) {
67609
67728
  cleanupGeneratedSessionMaps(ctx);
67729
+ if (ctx.isReusedEnvSession) {
67730
+ return;
67731
+ }
67610
67732
  if (!ctx.backendSessionId && ctx.inFlightSessionStart) {
67611
67733
  try {
67612
67734
  const startResult = await ctx.inFlightSessionStart;
@@ -67689,8 +67811,8 @@ async function cleanupHostedSession(ctx) {
67689
67811
  } catch {
67690
67812
  }
67691
67813
  }
67692
- (0, import_node_fs22.mkdirSync)((0, import_node_path18.dirname)(ctx.evidenceOutputPath), { recursive: true });
67693
- (0, import_node_fs22.writeFileSync)(
67814
+ (0, import_node_fs23.mkdirSync)((0, import_node_path19.dirname)(ctx.evidenceOutputPath), { recursive: true });
67815
+ (0, import_node_fs23.writeFileSync)(
67694
67816
  ctx.evidenceOutputPath,
67695
67817
  JSON.stringify(
67696
67818
  {
@@ -67869,35 +67991,35 @@ function mapSessionStartError(sessionResult) {
67869
67991
  }
67870
67992
 
67871
67993
  // src/commands/run-validation.ts
67872
- var import_node_fs24 = require("fs");
67873
- var import_node_path20 = require("path");
67994
+ var import_node_fs25 = require("fs");
67995
+ var import_node_path21 = require("path");
67874
67996
  init_dist2();
67875
67997
  init_errors4();
67876
67998
  init_auth();
67877
67999
 
67878
68000
  // src/scenarios/catalog.ts
67879
- var import_node_fs23 = require("fs");
67880
- var import_node_path19 = require("path");
68001
+ var import_node_fs24 = require("fs");
68002
+ var import_node_path20 = require("path");
67881
68003
  var SCENARIO_DIR_CANDIDATES = [
67882
- (0, import_node_path19.resolve)("scenarios"),
67883
- (0, import_node_path19.resolve)("scenario"),
67884
- (0, import_node_path19.resolve)("test", "scenarios"),
67885
- (0, import_node_path19.resolve)("tests", "scenarios"),
67886
- (0, import_node_path19.resolve)(".archal", "scenarios")
68004
+ (0, import_node_path20.resolve)("scenarios"),
68005
+ (0, import_node_path20.resolve)("scenario"),
68006
+ (0, import_node_path20.resolve)("test", "scenarios"),
68007
+ (0, import_node_path20.resolve)("tests", "scenarios"),
68008
+ (0, import_node_path20.resolve)(".archal", "scenarios")
67887
68009
  ];
67888
68010
  function findScenarioFiles(dir) {
67889
- if (!(0, import_node_fs23.existsSync)(dir)) {
68011
+ if (!(0, import_node_fs24.existsSync)(dir)) {
67890
68012
  return [];
67891
68013
  }
67892
68014
  const files = [];
67893
- const entries = (0, import_node_fs23.readdirSync)(dir, { withFileTypes: true });
68015
+ const entries = (0, import_node_fs24.readdirSync)(dir, { withFileTypes: true });
67894
68016
  for (const entry of entries) {
67895
- const fullPath = (0, import_node_path19.join)(dir, entry.name);
68017
+ const fullPath = (0, import_node_path20.join)(dir, entry.name);
67896
68018
  if (entry.isDirectory()) {
67897
68019
  files.push(...findScenarioFiles(fullPath));
67898
68020
  continue;
67899
68021
  }
67900
- if (entry.isFile() && (0, import_node_path19.extname)(entry.name) === ".md") {
68022
+ if (entry.isFile() && (0, import_node_path20.extname)(entry.name) === ".md") {
67901
68023
  files.push(fullPath);
67902
68024
  }
67903
68025
  }
@@ -67905,27 +68027,27 @@ function findScenarioFiles(dir) {
67905
68027
  }
67906
68028
  function findLocalScenariosDir() {
67907
68029
  for (const candidate of SCENARIO_DIR_CANDIDATES) {
67908
- if ((0, import_node_fs23.existsSync)(candidate)) {
68030
+ if ((0, import_node_fs24.existsSync)(candidate)) {
67909
68031
  return { dir: candidate, candidates: SCENARIO_DIR_CANDIDATES };
67910
68032
  }
67911
68033
  }
67912
68034
  return {
67913
- dir: (0, import_node_path19.resolve)("scenarios"),
68035
+ dir: (0, import_node_path20.resolve)("scenarios"),
67914
68036
  candidates: SCENARIO_DIR_CANDIDATES
67915
68037
  };
67916
68038
  }
67917
68039
  function resolveLocalScenario(nameOrPath) {
67918
- const directPath = (0, import_node_path19.resolve)(nameOrPath);
67919
- if ((0, import_node_fs23.existsSync)(directPath)) {
68040
+ const directPath = (0, import_node_path20.resolve)(nameOrPath);
68041
+ if ((0, import_node_fs24.existsSync)(directPath)) {
67920
68042
  return directPath;
67921
68043
  }
67922
68044
  const needle = nameOrPath.endsWith(".md") ? nameOrPath : `${nameOrPath}.md`;
67923
68045
  for (const candidate of SCENARIO_DIR_CANDIDATES) {
67924
- if (!(0, import_node_fs23.existsSync)(candidate)) {
68046
+ if (!(0, import_node_fs24.existsSync)(candidate)) {
67925
68047
  continue;
67926
68048
  }
67927
- const rootCandidate = (0, import_node_path19.join)(candidate, needle);
67928
- if ((0, import_node_fs23.existsSync)(rootCandidate)) {
68049
+ const rootCandidate = (0, import_node_path20.join)(candidate, needle);
68050
+ if ((0, import_node_fs24.existsSync)(rootCandidate)) {
67929
68051
  return rootCandidate;
67930
68052
  }
67931
68053
  const nestedMatch = findScenarioFiles(candidate).find(
@@ -68074,8 +68196,8 @@ function parseOpenClawEvalMode(raw, source) {
68074
68196
  );
68075
68197
  }
68076
68198
  function resolveScenarioPath(scenarioArg) {
68077
- let scenarioPath = (0, import_node_path20.resolve)(scenarioArg);
68078
- if (!(0, import_node_fs24.existsSync)(scenarioPath)) {
68199
+ let scenarioPath = (0, import_node_path21.resolve)(scenarioArg);
68200
+ if (!(0, import_node_fs25.existsSync)(scenarioPath)) {
68079
68201
  const localScenario = resolveLocalScenario(scenarioArg);
68080
68202
  if (localScenario) {
68081
68203
  scenarioPath = localScenario;
@@ -68092,7 +68214,7 @@ function resolveScenarioPath(scenarioArg) {
68092
68214
  "Rename the file to use the .md extension, then retry."
68093
68215
  );
68094
68216
  }
68095
- if (!(0, import_node_fs24.readFileSync)(scenarioPath, "utf-8").trim()) {
68217
+ if (!(0, import_node_fs25.readFileSync)(scenarioPath, "utf-8").trim()) {
68096
68218
  validationError(
68097
68219
  `Scenario file is empty: ${scenarioPath}`,
68098
68220
  "Add scenario content (Setup, Prompt, Success Criteria sections), then retry."
@@ -68253,9 +68375,10 @@ function resolveHarnessAndEngine(opts, timeout, resolved) {
68253
68375
  opts.explicitHarnessKind = void 0;
68254
68376
  let inferredRepoHarness = false;
68255
68377
  const dockerExplicitlyRequested = isDockerExplicitlyRequested(opts);
68378
+ const userConfig = loadConfig();
68256
68379
  if (!process.env["ANTHROPIC_API_KEY"] && !process.env["OPENAI_API_KEY"] && !process.env["GEMINI_API_KEY"]) {
68257
68380
  try {
68258
- const cfg = loadConfig();
68381
+ const cfg = userConfig;
68259
68382
  if (cfg.apiKey) {
68260
68383
  if (cfg.apiKey.startsWith("sk-ant-")) {
68261
68384
  process.env["ANTHROPIC_API_KEY"] = cfg.apiKey;
@@ -68312,7 +68435,6 @@ function resolveHarnessAndEngine(opts, timeout, resolved) {
68312
68435
  }
68313
68436
  }
68314
68437
  }
68315
- const userConfig = loadConfig();
68316
68438
  const { resolvedHarness, resolvedAgentModel } = applyConfiguredRunDefaults(opts, resolved, userConfig);
68317
68439
  if (opts.apiKey?.trim()) {
68318
68440
  warnIfKeyLooksInvalid(opts.apiKey.trim(), "--api-key");
@@ -68350,7 +68472,7 @@ function resolveHarnessAndEngine(opts, timeout, resolved) {
68350
68472
  }
68351
68473
  } else {
68352
68474
  const inferredHarness = discoverRepoLocalHarness(
68353
- (0, import_node_path20.dirname)(resolved?.scenarioPath ?? process.cwd()),
68475
+ (0, import_node_path21.dirname)(resolved?.scenarioPath ?? process.cwd()),
68354
68476
  resolved?.projectRoot ?? "",
68355
68477
  process.cwd()
68356
68478
  );
@@ -68740,9 +68862,29 @@ async function executeRunForScenario(scenarioArg, opts, command, configDefaults)
68740
68862
  );
68741
68863
  }
68742
68864
  writeManagedRunStatus({ stage: shouldProvisionHostedSession ? "provisioning" : "running" });
68865
+ let reusedExistingSession = false;
68866
+ if (shouldProvisionHostedSession && credentials) {
68867
+ const reusedSession = await tryReuseEnvSession(scenario.config.twins, credentials);
68868
+ if (reusedSession) {
68869
+ reusedExistingSession = true;
68870
+ ctx.backendSessionId = reusedSession.sessionId;
68871
+ ctx.isReusedEnvSession = true;
68872
+ cloudTwinUrls = reusedSession.endpoints;
68873
+ if (!opts.apiBaseUrls) {
68874
+ hostedApiBaseUrlOverrides = reusedSession.apiBaseUrls;
68875
+ }
68876
+ if (!opts.quiet) {
68877
+ info(`Reusing active twin session ${reusedSession.sessionId}`);
68878
+ }
68879
+ writeManagedRunStatus({
68880
+ stage: "session_ready",
68881
+ sessionId: ctx.backendSessionId
68882
+ });
68883
+ }
68884
+ }
68743
68885
  if (process.env["ARCHAL_LOCAL_TWINS"]) {
68744
68886
  ctx.runFailureMessage = "ARCHAL_LOCAL_TWINS has been removed. Twins are always provisioned in hosted cloud sessions.";
68745
- } else if (shouldProvisionHostedSession) {
68887
+ } else if (!reusedExistingSession && shouldProvisionHostedSession) {
68746
68888
  ctx.inFlightSessionStart = startSession(credentials?.token ?? "", {
68747
68889
  twins: scenario.config.twins,
68748
68890
  scenarioId: scenario.title,
@@ -68772,12 +68914,27 @@ async function executeRunForScenario(scenarioArg, opts, command, configDefaults)
68772
68914
  stage: "provisioning",
68773
68915
  sessionId: ctx.backendSessionId
68774
68916
  });
68775
- const endpointRoots = sessionResult.data.endpoints;
68776
- const apiBaseUrls = sessionResult.data.apiBaseUrls;
68917
+ const serverEndpoints = sessionResult.data.endpoints;
68918
+ const serverApiBaseUrls = sessionResult.data.apiBaseUrls;
68777
68919
  const missingEndpoints = scenario.config.twins.filter((name) => {
68778
- const endpoint = endpointRoots[name];
68920
+ const endpoint = serverEndpoints[name];
68779
68921
  return typeof endpoint !== "string" || endpoint.trim().length === 0;
68780
68922
  });
68923
+ const runtimeBase = getConfiguredRuntimeBaseUrl2();
68924
+ let endpointRoots;
68925
+ let apiBaseUrls;
68926
+ if (runtimeBase && missingEndpoints.length === 0) {
68927
+ const runtimeUrls = buildRuntimeTwinUrls(
68928
+ ctx.backendSessionId,
68929
+ scenario.config.twins,
68930
+ runtimeBase
68931
+ );
68932
+ endpointRoots = runtimeUrls.endpoints;
68933
+ apiBaseUrls = runtimeUrls.apiBaseUrls;
68934
+ } else {
68935
+ endpointRoots = serverEndpoints;
68936
+ apiBaseUrls = serverApiBaseUrls;
68937
+ }
68781
68938
  if (missingEndpoints.length > 0) {
68782
68939
  ctx.runFailureMessage = `Twin provisioning failed for: ${missingEndpoints.join(", ")}. Try again or run: archal doctor`;
68783
68940
  }
@@ -68788,7 +68945,7 @@ async function executeRunForScenario(scenarioArg, opts, command, configDefaults)
68788
68945
  hostedApiBaseUrlOverrides = apiBaseUrls;
68789
68946
  }
68790
68947
  if (!ctx.runFailureMessage && engine.mode === "api" && !engine.twinUrlsPath) {
68791
- ctx.generatedTwinUrlMapPath = (0, import_node_path23.resolve)(
68948
+ ctx.generatedTwinUrlMapPath = (0, import_node_path24.resolve)(
68792
68949
  `.archal-session-${ctx.backendSessionId}-engine-twin-urls.json`
68793
68950
  );
68794
68951
  const result = writeTempJsonMap(ctx.generatedTwinUrlMapPath, endpointRoots, "engine twin URL map");
@@ -68981,8 +69138,8 @@ async function executeRunForScenario(scenarioArg, opts, command, configDefaults)
68981
69138
  process.stderr.write(`Warning: failed to build trace payload: ${errorMessage(traceErr)}
68982
69139
  `);
68983
69140
  }
68984
- (0, import_node_fs27.mkdirSync)((0, import_node_path23.dirname)(ctx.evidenceOutputPath), { recursive: true });
68985
- (0, import_node_fs27.writeFileSync)(
69141
+ (0, import_node_fs28.mkdirSync)((0, import_node_path24.dirname)(ctx.evidenceOutputPath), { recursive: true });
69142
+ (0, import_node_fs28.writeFileSync)(
68986
69143
  ctx.evidenceOutputPath,
68987
69144
  JSON.stringify({
68988
69145
  sessionId: ctx.backendSessionId ?? null,
@@ -69036,7 +69193,23 @@ function createRunCommand() {
69036
69193
  throw new CliUsageError("--twin requires --task.");
69037
69194
  }
69038
69195
  const { loadArchalFile: loadArchalFile2 } = await Promise.resolve().then(() => (init_archal_file(), archal_file_exports));
69039
- const archalFile = loadArchalFile2(opts["config"]);
69196
+ let archalFile = loadArchalFile2(opts["config"]);
69197
+ if (!archalFile && opts.task) {
69198
+ try {
69199
+ const { detectTwinsFromHarnessDir: detectTwinsFromHarnessDir2 } = await Promise.resolve().then(() => (init_harness_import_detector(), harness_import_detector_exports));
69200
+ const detected = detectTwinsFromHarnessDir2(process.cwd());
69201
+ if (detected.length > 0) {
69202
+ const { writeFileSync: writeFileSync_ } = await import("fs");
69203
+ const { resolve: resolvePath } = await import("path");
69204
+ const generatedConfig = { twins: detected };
69205
+ const configPath = resolvePath(process.cwd(), ".archal.json");
69206
+ writeFileSync_(configPath, JSON.stringify(generatedConfig, null, 2) + "\n", "utf-8");
69207
+ info("Created .archal.json with detected twins: " + detected.join(", "));
69208
+ archalFile = loadArchalFile2();
69209
+ }
69210
+ } catch {
69211
+ }
69212
+ }
69040
69213
  const scenariosToRun = scenarioArg?.trim() ? [scenarioArg] : [];
69041
69214
  if (archalFile) {
69042
69215
  const { config: af, configDir } = archalFile;
@@ -69071,7 +69244,7 @@ function createRunCommand() {
69071
69244
  const seedOverrides = {};
69072
69245
  for (const [twinName, seedPath] of Object.entries(af.seeds)) {
69073
69246
  const resolvedSeedPath = resolvePath(configDir, seedPath);
69074
- const seedExt = (0, import_node_path23.extname)(resolvedSeedPath).toLowerCase();
69247
+ const seedExt = (0, import_node_path24.extname)(resolvedSeedPath).toLowerCase();
69075
69248
  if (seedExt === ".json" || seedExt === ".md") {
69076
69249
  fileSeedPaths[twinName] = resolvedSeedPath;
69077
69250
  } else {
@@ -69129,7 +69302,7 @@ function createRunCommand() {
69129
69302
  }
69130
69303
  if (scenariosToRun.length === 0) {
69131
69304
  throw new CliUsageError(
69132
- 'No .archal.json config found and no scenario specified.\n Create .archal.json with your twins: { "twins": ["github"] }\n Or pass a scenario directly: archal run scenario.md'
69305
+ 'No .archal.json config found and no scenario specified.\n Create .archal.json with your twins: { "twins": ["github"] }\n Or pass a scenario directly: archal run scenario.md\n Or run an inline task with a twin: archal run --task "Create an issue" --twin github'
69133
69306
  );
69134
69307
  }
69135
69308
  const tempManifestPath = opts["_tempManifestPath"];
@@ -69593,8 +69766,8 @@ ${CYAN2}${BOLD2}Archal CLI${RESET2} ${DIM2}v${CLI_VERSION}${RESET2}
69593
69766
  }
69594
69767
 
69595
69768
  // src/commands/scenario.ts
69596
- var import_node_fs28 = require("fs");
69597
- var import_node_path24 = require("path");
69769
+ var import_node_fs29 = require("fs");
69770
+ var import_node_path25 = require("path");
69598
69771
  init_logger();
69599
69772
  function listScenarios(opts) {
69600
69773
  const tagFilter = opts.tag?.toLowerCase();
@@ -69603,7 +69776,7 @@ function listScenarios(opts) {
69603
69776
  const rows = [];
69604
69777
  const localResolution = findLocalScenariosDir();
69605
69778
  const localDir = localResolution.dir;
69606
- const localDirExists = (0, import_node_fs28.existsSync)(localDir);
69779
+ const localDirExists = (0, import_node_fs29.existsSync)(localDir);
69607
69780
  if (localDirExists) {
69608
69781
  const localFiles = findScenarioFiles(localDir);
69609
69782
  for (const file2 of localFiles) {
@@ -69614,10 +69787,10 @@ function listScenarios(opts) {
69614
69787
  if (!scenarioTags.includes(tagFilter)) continue;
69615
69788
  }
69616
69789
  if (difficultyFilter && (scenario.config.difficulty ?? "") !== difficultyFilter) continue;
69617
- const slug = (0, import_node_path24.basename)(file2, ".md");
69790
+ const slug = (0, import_node_path25.basename)(file2, ".md");
69618
69791
  rows.push([scenario.title, slug, scenario.config.twins.join(", ") || "(auto)"]);
69619
69792
  } catch {
69620
- const slug = (0, import_node_path24.basename)(file2, ".md");
69793
+ const slug = (0, import_node_path25.basename)(file2, ".md");
69621
69794
  rows.push(["(parse error)", slug, "-"]);
69622
69795
  }
69623
69796
  }
@@ -69658,35 +69831,35 @@ function createScenarioCommand() {
69658
69831
  }
69659
69832
 
69660
69833
  // src/commands/twin.ts
69661
- var import_node_fs30 = require("fs");
69834
+ var import_node_fs31 = require("fs");
69662
69835
  init_auth();
69663
69836
  init_api_client();
69664
69837
  init_errors4();
69665
69838
 
69666
69839
  // src/commands/twin-session-store.ts
69667
- var import_node_fs29 = require("fs");
69668
- var import_node_os8 = require("os");
69669
- var import_node_path25 = require("path");
69670
- var TWIN_SESSION_FILE = (0, import_node_path25.join)((0, import_node_os8.homedir)(), ".archal", "twin-session.json");
69671
- var LEGACY_SESSION_FILE = (0, import_node_path25.join)((0, import_node_os8.homedir)(), ".archal", "env-session.json");
69840
+ var import_node_fs30 = require("fs");
69841
+ var import_node_os9 = require("os");
69842
+ var import_node_path26 = require("path");
69843
+ var TWIN_SESSION_FILE2 = (0, import_node_path26.join)((0, import_node_os9.homedir)(), ".archal", "twin-session.json");
69844
+ var LEGACY_SESSION_FILE2 = (0, import_node_path26.join)((0, import_node_os9.homedir)(), ".archal", "env-session.json");
69672
69845
  function saveSession(session) {
69673
- (0, import_node_fs29.mkdirSync)((0, import_node_path25.join)((0, import_node_os8.homedir)(), ".archal"), { recursive: true });
69674
- (0, import_node_fs29.writeFileSync)(TWIN_SESSION_FILE, JSON.stringify(session, null, 2));
69846
+ (0, import_node_fs30.mkdirSync)((0, import_node_path26.join)((0, import_node_os9.homedir)(), ".archal"), { recursive: true });
69847
+ (0, import_node_fs30.writeFileSync)(TWIN_SESSION_FILE2, JSON.stringify(session, null, 2));
69675
69848
  }
69676
- function loadSession() {
69677
- let filePath = TWIN_SESSION_FILE;
69678
- if (!(0, import_node_fs29.existsSync)(filePath) && (0, import_node_fs29.existsSync)(LEGACY_SESSION_FILE)) {
69679
- filePath = LEGACY_SESSION_FILE;
69849
+ function loadSession2() {
69850
+ let filePath = TWIN_SESSION_FILE2;
69851
+ if (!(0, import_node_fs30.existsSync)(filePath) && (0, import_node_fs30.existsSync)(LEGACY_SESSION_FILE2)) {
69852
+ filePath = LEGACY_SESSION_FILE2;
69680
69853
  }
69681
- if (!(0, import_node_fs29.existsSync)(filePath)) {
69854
+ if (!(0, import_node_fs30.existsSync)(filePath)) {
69682
69855
  return null;
69683
69856
  }
69684
69857
  try {
69685
- const session = JSON.parse((0, import_node_fs29.readFileSync)(filePath, "utf8"));
69686
- if (filePath === LEGACY_SESSION_FILE) {
69858
+ const session = JSON.parse((0, import_node_fs30.readFileSync)(filePath, "utf8"));
69859
+ if (filePath === LEGACY_SESSION_FILE2) {
69687
69860
  saveSession(session);
69688
69861
  try {
69689
- (0, import_node_fs29.rmSync)(LEGACY_SESSION_FILE);
69862
+ (0, import_node_fs30.rmSync)(LEGACY_SESSION_FILE2);
69690
69863
  } catch {
69691
69864
  }
69692
69865
  }
@@ -69697,11 +69870,11 @@ function loadSession() {
69697
69870
  }
69698
69871
  function clearSession() {
69699
69872
  try {
69700
- (0, import_node_fs29.rmSync)(TWIN_SESSION_FILE);
69873
+ (0, import_node_fs30.rmSync)(TWIN_SESSION_FILE2);
69701
69874
  } catch {
69702
69875
  }
69703
69876
  try {
69704
- (0, import_node_fs29.rmSync)(LEGACY_SESSION_FILE);
69877
+ (0, import_node_fs30.rmSync)(LEGACY_SESSION_FILE2);
69705
69878
  } catch {
69706
69879
  }
69707
69880
  }
@@ -69830,11 +70003,19 @@ async function pollUntilReady(sessionId, twins, token) {
69830
70003
  }
69831
70004
  const status = result.data;
69832
70005
  if (status.status === "ready") {
70006
+ const runtimeBase = getConfiguredRuntimeBaseUrl2();
70007
+ let endpoints = status.endpoints ?? {};
70008
+ let apiBaseUrls = status.apiBaseUrls ?? {};
70009
+ if (runtimeBase) {
70010
+ const runtimeUrls = buildRuntimeTwinUrls(sessionId, twins, runtimeBase);
70011
+ endpoints = runtimeUrls.endpoints;
70012
+ apiBaseUrls = runtimeUrls.apiBaseUrls;
70013
+ }
69833
70014
  const saved = {
69834
70015
  sessionId,
69835
70016
  twins,
69836
- endpoints: status.endpoints ?? {},
69837
- apiBaseUrls: status.apiBaseUrls ?? {},
70017
+ endpoints,
70018
+ apiBaseUrls,
69838
70019
  createdAt: status.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
69839
70020
  };
69840
70021
  saveSession(saved);
@@ -69850,7 +70031,7 @@ async function pollUntilReady(sessionId, twins, token) {
69850
70031
  throw new CliRuntimeError("Timed out waiting for twins to start.");
69851
70032
  }
69852
70033
  async function loadSeedFile(session, twin, seedFile, token) {
69853
- const content = (0, import_node_fs30.readFileSync)(seedFile, "utf8");
70034
+ const content = (0, import_node_fs31.readFileSync)(seedFile, "utf8");
69854
70035
  if (content.length > MAX_SETUP_FILE_SIZE) {
69855
70036
  throw new CliUsageError(
69856
70037
  `Seed file too large (${content.length} bytes, max ${MAX_SETUP_FILE_SIZE}). Split the seed or reduce its size.`
@@ -69885,7 +70066,7 @@ async function loadSeedFile(session, twin, seedFile, token) {
69885
70066
  }
69886
70067
  function readSetupFile(filePath) {
69887
70068
  try {
69888
- const content = (0, import_node_fs30.readFileSync)(filePath, "utf-8").trim();
70069
+ const content = (0, import_node_fs31.readFileSync)(filePath, "utf-8").trim();
69889
70070
  if (content.length > MAX_SETUP_FILE_SIZE) {
69890
70071
  throw new CliUsageError(
69891
70072
  `Setup file too large (${content.length} bytes, max ${MAX_SETUP_FILE_SIZE}). Use --seed-file for large seeds.`
@@ -69944,7 +70125,7 @@ function createTwinCommand() {
69944
70125
  await listTwinCatalog2();
69945
70126
  });
69946
70127
  command.command("start").argument("[twins...]", "Twins to start").option("--all", "Start all available twins").option("--seed <seeds...>", "Seeds per twin (for example: stripe:small-business github:rich-org)").option("--setup <description>", "Describe desired state in natural language and seed the first twin after startup").option("--setup-file <path>", "Read setup description from a file and seed the first twin after startup").option("--seed-file <path>", "Load a JSON seed file after the first twin is ready").option("--ttl-seconds <seconds>", "Requested twin lifetime in seconds (capped server-side)").description("Start a persistent hosted twin session with hosted twin APIs").action(async (twins, opts) => {
69947
- const existing = loadSession();
70128
+ const existing = loadSession2();
69948
70129
  if (existing) {
69949
70130
  throw new CliRuntimeError(
69950
70131
  `Active session found: ${existing.sessionId}
@@ -69962,14 +70143,15 @@ Run 'archal twin stop' first, or 'archal twin status' to inspect it.`
69962
70143
  const createResult = await startSession(token, {
69963
70144
  twins: requestedTwins,
69964
70145
  seeds,
69965
- ttlSeconds: opts.ttlSeconds ? toPositiveInteger2(opts.ttlSeconds, "--ttl-seconds") : void 0
70146
+ ttlSeconds: opts.ttlSeconds ? toPositiveInteger2(opts.ttlSeconds, "--ttl-seconds") : void 0,
70147
+ source: "twin-start"
69966
70148
  });
69967
70149
  const response = unwrapApiResult(createResult, "Failed to create twin session");
69968
70150
  process.stderr.write(`${DIM3}Session ${response.sessionId} created. Waiting for twins to start...${RESET3}
69969
70151
  `);
69970
70152
  const ready = await pollUntilReady(response.sessionId, requestedTwins, token);
69971
70153
  if (ready.status === "ready") {
69972
- const saved = loadSession();
70154
+ const saved = loadSession2();
69973
70155
  if (saved) {
69974
70156
  await loadCustomSeedIfRequested(saved, requestedTwins, opts, token);
69975
70157
  }
@@ -69977,7 +70159,7 @@ Run 'archal twin stop' first, or 'archal twin status' to inspect it.`
69977
70159
  });
69978
70160
  command.command("status").option("--json", "Print the raw status payload as JSON").description("Show the active twin session endpoints and status").action(async (opts) => {
69979
70161
  const token = requireToken();
69980
- const saved = loadSession();
70162
+ const saved = loadSession2();
69981
70163
  if (!saved) {
69982
70164
  process.stderr.write(`${DIM3}No active twin session. Run 'archal twin start github' to start one.${RESET3}
69983
70165
  `);
@@ -70028,7 +70210,7 @@ ${BOLD3}Twin Session: ${saved.sessionId}${RESET3}
70028
70210
  process.stderr.write("\n");
70029
70211
  });
70030
70212
  command.command("list").option("--json", "Print twin sessions as JSON").description("List active twin sessions for the current user").action(async (opts) => {
70031
- const saved = loadSession();
70213
+ const saved = loadSession2();
70032
70214
  if (!saved) {
70033
70215
  if (opts.json) {
70034
70216
  process.stdout.write(`${JSON.stringify({ sessions: [] }, null, 2)}
@@ -70072,11 +70254,20 @@ ${BOLD3}Active Twin Sessions${RESET3}
70072
70254
  const token = requireToken();
70073
70255
  const result = await getSessionStatus(token, sessionId);
70074
70256
  const response = unwrapApiResult(result, "Failed to attach twin session");
70257
+ const attachedTwins = response.twinIds ?? [];
70258
+ const runtimeBase = getConfiguredRuntimeBaseUrl2();
70259
+ let attachEndpoints = response.endpoints ?? {};
70260
+ let attachApiBaseUrls = response.apiBaseUrls ?? {};
70261
+ if (runtimeBase && attachedTwins.length > 0) {
70262
+ const runtimeUrls = buildRuntimeTwinUrls(sessionId, attachedTwins, runtimeBase);
70263
+ attachEndpoints = runtimeUrls.endpoints;
70264
+ attachApiBaseUrls = runtimeUrls.apiBaseUrls;
70265
+ }
70075
70266
  saveSession({
70076
70267
  sessionId,
70077
- twins: response.twinIds ?? [],
70078
- endpoints: response.endpoints ?? {},
70079
- apiBaseUrls: response.apiBaseUrls ?? {},
70268
+ twins: attachedTwins,
70269
+ endpoints: attachEndpoints,
70270
+ apiBaseUrls: attachApiBaseUrls,
70080
70271
  createdAt: response.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
70081
70272
  });
70082
70273
  process.stderr.write(`${GREEN2}Attached${RESET3} ${sessionId}
@@ -70084,7 +70275,7 @@ ${BOLD3}Active Twin Sessions${RESET3}
70084
70275
  });
70085
70276
  command.command("renew").argument("[ttl-seconds]", "Requested additional lifetime in seconds").description("Extend the active twin session lifetime").action(async (ttlSeconds) => {
70086
70277
  const token = requireToken();
70087
- const saved = loadSession();
70278
+ const saved = loadSession2();
70088
70279
  if (!saved) {
70089
70280
  throw new CliRuntimeError("No active twin session.");
70090
70281
  }
@@ -70098,7 +70289,7 @@ ${BOLD3}Active Twin Sessions${RESET3}
70098
70289
  });
70099
70290
  command.command("stop").description("Tear down the active twin session").action(async () => {
70100
70291
  const token = requireToken();
70101
- const saved = loadSession();
70292
+ const saved = loadSession2();
70102
70293
  if (!saved) {
70103
70294
  process.stderr.write(`${DIM3}No active twin session.${RESET3}
70104
70295
  `);
@@ -70130,7 +70321,7 @@ ${BOLD3}Active Twin Sessions${RESET3}
70130
70321
  });
70131
70322
  command.command("reset").argument("[twin]", "Twin to reset, or all session twins if omitted").description("Reset twin state to clean").action(async (twin) => {
70132
70323
  const token = requireToken();
70133
- const saved = loadSession();
70324
+ const saved = loadSession2();
70134
70325
  if (!saved) {
70135
70326
  throw new CliRuntimeError("No active twin session.");
70136
70327
  }
@@ -70171,7 +70362,7 @@ ${BOLD3}Active Twin Sessions${RESET3}
70171
70362
  });
70172
70363
  command.command("seed").argument("<twin>", "Twin to seed").argument("[seed-name]", "Named seed to apply").option("--file <path>", "Load a JSON seed file").option("--setup <description>", "Describe desired state in natural language and seed the twin from it").description("Load a seed into a running twin").action(async (twin, seedName, opts) => {
70173
70364
  const token = requireToken();
70174
- const saved = loadSession();
70365
+ const saved = loadSession2();
70175
70366
  if (!saved) {
70176
70367
  throw new CliRuntimeError("No active twin session.");
70177
70368
  }
@@ -70205,8 +70396,9 @@ ${BOLD3}Active Twin Sessions${RESET3}
70205
70396
  // src/commands/trace.ts
70206
70397
  init_dist2();
70207
70398
  init_require_auth();
70399
+ init_auth();
70208
70400
  async function fetchTraces(token, limit = 20) {
70209
- const baseUrl = process.env["ARCHAL_API_URL"] ?? process.env["ARCHAL_AUTH_URL"] ?? "https://www.archal.ai";
70401
+ const baseUrl = getConfiguredApiBaseUrl2() ?? "https://www.archal.ai";
70210
70402
  const res = await fetch(`${baseUrl}/api/traces?limit=${limit}`, {
70211
70403
  headers: { authorization: `Bearer ${token}` }
70212
70404
  });
@@ -70217,7 +70409,7 @@ async function fetchTraces(token, limit = 20) {
70217
70409
  return body.traces ?? [];
70218
70410
  }
70219
70411
  async function fetchTraceDetail(token, rootTraceId) {
70220
- const baseUrl = process.env["ARCHAL_API_URL"] ?? process.env["ARCHAL_AUTH_URL"] ?? "https://www.archal.ai";
70412
+ const baseUrl = getConfiguredApiBaseUrl2() ?? "https://www.archal.ai";
70221
70413
  const res = await fetch(`${baseUrl}/api/traces/${encodeURIComponent(rootTraceId)}`, {
70222
70414
  headers: { authorization: `Bearer ${token}` }
70223
70415
  });