@archal/cli 0.9.7 → 0.9.8

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 +835 -490
  2. package/package.json +6 -7
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";
@@ -32168,6 +32175,7 @@ var init_dist3 = __esm({
32168
32175
  KEYCHAIN_ACCOUNT = "credentials-master-key";
32169
32176
  HOSTED_DEFAULT_AUTH_BASE_URL = "https://www.archal.ai";
32170
32177
  HOSTED_DEFAULT_API_BASE_URL = "https://www.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 };
@@ -55041,6 +55071,8 @@ function startTlsIntercept(config2) {
55041
55071
  port: assignedPort,
55042
55072
  stop: () => new Promise((res) => {
55043
55073
  tlsServer.close(() => res());
55074
+ const fallback = setTimeout(() => res(), 1e3);
55075
+ fallback.unref();
55044
55076
  })
55045
55077
  });
55046
55078
  });
@@ -55123,16 +55155,20 @@ function startProxy(config2) {
55123
55155
  server,
55124
55156
  port: assignedPort,
55125
55157
  stop: () => new Promise((res) => {
55126
- const stopTimeout = setTimeout(() => {
55127
- try {
55128
- server.closeAllConnections?.();
55129
- } catch {
55158
+ let resolved = false;
55159
+ const done = () => {
55160
+ if (!resolved) {
55161
+ resolved = true;
55162
+ clearTimeout(fallback);
55163
+ res();
55130
55164
  }
55131
- }, 2e3);
55132
- server.close(() => {
55133
- clearTimeout(stopTimeout);
55134
- res();
55135
- });
55165
+ };
55166
+ try {
55167
+ server.closeAllConnections?.();
55168
+ } catch {
55169
+ }
55170
+ server.close(() => done());
55171
+ const fallback = setTimeout(() => done(), 1e3);
55136
55172
  })
55137
55173
  });
55138
55174
  });
@@ -55402,8 +55438,8 @@ function extractInlineArg(query, name) {
55402
55438
  const match = query.match(regex);
55403
55439
  return match?.[1];
55404
55440
  }
55405
- function forwardToCloudTwin(clientReq, clientRes, targetBaseUrl, path, authHeaders, injectResponseHeaders) {
55406
- const target = resolveForwardTarget(targetBaseUrl, path);
55441
+ function forwardToCloudTwin(clientReq, clientRes, targetBaseUrl, path2, authHeaders, injectResponseHeaders) {
55442
+ const target = resolveForwardTarget(targetBaseUrl, path2);
55407
55443
  const isHttps = target.protocol === "https:";
55408
55444
  const requestFn = isHttps ? import_https.request : import_http.request;
55409
55445
  const headers = {
@@ -55577,7 +55613,7 @@ function buildCloudTwinMappings(cloudTwinUrls) {
55577
55613
  for (const entry of TWIN_DOMAINS) {
55578
55614
  const rawUrl = cloudTwinUrls[entry.name];
55579
55615
  if (rawUrl === void 0) continue;
55580
- const targetUrl = normalizeCloudTwinTargetUrl(rawUrl);
55616
+ const targetUrl = normalizeCloudTwinTargetUrl(rawUrl) + "/rest";
55581
55617
  mappings.push({
55582
55618
  domain: entry.domain,
55583
55619
  targetUrl,
@@ -55633,27 +55669,27 @@ function formatExecError(err) {
55633
55669
  return String(err);
55634
55670
  }
55635
55671
  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();
55672
+ 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
55673
  const candidates = [
55638
55674
  {
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")
55675
+ dockerfile: (0, import_path6.resolve)(process.cwd(), "packages/sandbox-runtime/docker/sandbox/Dockerfile"),
55676
+ contextDir: (0, import_path6.resolve)(process.cwd(), "packages/sandbox-runtime")
55641
55677
  },
55642
55678
  {
55643
- dockerfile: (0, import_path5.resolve)(process.cwd(), "cli/docker/sandbox/Dockerfile"),
55644
- contextDir: (0, import_path5.resolve)(process.cwd(), "cli")
55679
+ dockerfile: (0, import_path6.resolve)(process.cwd(), "cli/docker/sandbox/Dockerfile"),
55680
+ contextDir: (0, import_path6.resolve)(process.cwd(), "cli")
55645
55681
  },
55646
55682
  {
55647
- dockerfile: (0, import_path5.resolve)(process.cwd(), "docker/sandbox/Dockerfile"),
55683
+ dockerfile: (0, import_path6.resolve)(process.cwd(), "docker/sandbox/Dockerfile"),
55648
55684
  contextDir: process.cwd()
55649
55685
  },
55650
55686
  {
55651
- dockerfile: (0, import_path5.resolve)(moduleDir, "../docker/sandbox/Dockerfile"),
55652
- contextDir: (0, import_path5.resolve)(moduleDir, "..")
55687
+ dockerfile: (0, import_path6.resolve)(moduleDir, "../docker/sandbox/Dockerfile"),
55688
+ contextDir: (0, import_path6.resolve)(moduleDir, "..")
55653
55689
  },
55654
55690
  {
55655
- dockerfile: (0, import_path5.resolve)(moduleDir, "../../docker/sandbox/Dockerfile"),
55656
- contextDir: (0, import_path5.resolve)(moduleDir, "../..")
55691
+ dockerfile: (0, import_path6.resolve)(moduleDir, "../../docker/sandbox/Dockerfile"),
55692
+ contextDir: (0, import_path6.resolve)(moduleDir, "../..")
55657
55693
  }
55658
55694
  ];
55659
55695
  return candidates.find((candidate) => (0, import_fs5.existsSync)(candidate.dockerfile));
@@ -55661,15 +55697,15 @@ function resolveLocalSandboxBuildTarget() {
55661
55697
  function getSandboxRuntimeDependencyPaths(target) {
55662
55698
  return [
55663
55699
  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));
55700
+ (0, import_path6.resolve)(target.contextDir, "docker/sandbox/entrypoint.sh"),
55701
+ (0, import_path6.resolve)(target.contextDir, "src/sandbox/proxy-entry.ts"),
55702
+ (0, import_path6.resolve)(target.contextDir, "src/sandbox/proxy.ts"),
55703
+ (0, import_path6.resolve)(target.contextDir, "src/sandbox/twins.ts"),
55704
+ (0, import_path6.resolve)(target.contextDir, "src/sandbox/certs.ts")
55705
+ ].filter((path2) => (0, import_fs5.existsSync)(path2));
55670
55706
  }
55671
55707
  function getNewestSandboxRuntimeMtimeMs(target) {
55672
- return getSandboxRuntimeDependencyPaths(target).map((path) => (0, import_fs5.statSync)(path).mtimeMs).reduce((max, mtimeMs) => Math.max(max, mtimeMs), 0);
55708
+ return getSandboxRuntimeDependencyPaths(target).map((path2) => (0, import_fs5.statSync)(path2).mtimeMs).reduce((max, mtimeMs) => Math.max(max, mtimeMs), 0);
55673
55709
  }
55674
55710
  function getLocalImageCreatedAtMs(image) {
55675
55711
  try {
@@ -55766,8 +55802,8 @@ async function ensureSandboxImage(image, openclawVersion) {
55766
55802
  }
55767
55803
  function launchSandbox(config2) {
55768
55804
  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");
55805
+ const artifactsDir = (0, import_fs5.mkdtempSync)((0, import_path6.join)((0, import_os4.tmpdir)(), "archal-sandbox-"));
55806
+ const proxyEventsHostPath = (0, import_path6.join)(artifactsDir, "proxy-events.ndjson");
55771
55807
  const proxyEventsContainerPath = "/archal-artifacts/proxy-events.ndjson";
55772
55808
  const mounts = [];
55773
55809
  mounts.push("-v", `${artifactsDir}:/archal-artifacts`);
@@ -55868,9 +55904,9 @@ function spawnWithTimeout2(command, args, timeoutMs, artifacts) {
55868
55904
  });
55869
55905
  });
55870
55906
  }
55871
- function readProxyEvents(path) {
55907
+ function readProxyEvents(path2) {
55872
55908
  try {
55873
- const raw = (0, import_fs5.readFileSync)(path, "utf8").trim();
55909
+ const raw = (0, import_fs5.readFileSync)(path2, "utf8").trim();
55874
55910
  if (!raw) return [];
55875
55911
  return raw.split("\n").map((line) => {
55876
55912
  try {
@@ -56072,7 +56108,7 @@ function writeMountedConfigFiles(dir, cloudTwinUrls, authToken, caPath) {
56072
56108
  example: 'mcp__github__list_issues -> POST github-url/tools/call with { "name": "list_issues", "arguments": {} }'
56073
56109
  }
56074
56110
  };
56075
- (0, import_fs3.writeFileSync)((0, import_path3.join)(dir, "rest-config.json"), JSON.stringify(restConfig, null, 2) + "\n", "utf-8");
56111
+ (0, import_fs3.writeFileSync)((0, import_path4.join)(dir, "rest-config.json"), JSON.stringify(restConfig, null, 2) + "\n", "utf-8");
56076
56112
  const mcpServers = {};
56077
56113
  for (const [twinName, baseUrl] of Object.entries(cloudTwinUrls)) {
56078
56114
  const trimmed = baseUrl.trim().replace(/\/+$/, "");
@@ -56082,9 +56118,9 @@ function writeMountedConfigFiles(dir, cloudTwinUrls, authToken, caPath) {
56082
56118
  headers: { Authorization: `Bearer ${authToken}` }
56083
56119
  };
56084
56120
  }
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");
56121
+ (0, import_fs3.writeFileSync)((0, import_path4.join)(dir, "mcp-config.json"), JSON.stringify({ mcpServers }, null, 2) + "\n", "utf-8");
56122
+ (0, import_fs3.writeFileSync)((0, import_path4.join)(dir, "mcp-servers.json"), JSON.stringify(mcpServers), "utf-8");
56123
+ (0, import_fs3.writeFileSync)((0, import_path4.join)(dir, "ca.crt"), (0, import_fs3.readFileSync)(caPath, "utf-8"), "utf-8");
56088
56124
  }
56089
56125
  async function ensurePreparedImage(repoPath, dockerfilePath, image, timeoutMs) {
56090
56126
  const buildArgs = ["build", "-f", dockerfilePath, "-t", image, repoPath];
@@ -56107,12 +56143,12 @@ async function cleanupDockerImage(imageName) {
56107
56143
  await runDockerCommand(["image", "rm", "-f", imageName], 1e4);
56108
56144
  }
56109
56145
  async function buildDockerHarnessImage(repoPath, dockerfilePath, timeoutMs) {
56110
- const resolvedRepoPath = (0, import_path3.resolve)(repoPath);
56146
+ const resolvedRepoPath = (0, import_path4.resolve)(repoPath);
56111
56147
  const dockerIdSuffix = `${Date.now().toString(36)}-${process.pid}`;
56112
56148
  const imageName = `archal/harness-${dockerIdSuffix}`;
56113
- const buildDir = (0, import_fs3.mkdtempSync)((0, import_path3.join)((0, import_os2.tmpdir)(), "archal-harness-build-"));
56149
+ const buildDir = (0, import_fs3.mkdtempSync)((0, import_path4.join)((0, import_os2.tmpdir)(), "archal-harness-build-"));
56114
56150
  try {
56115
- const generatedDockerfilePath = (0, import_path3.join)(buildDir, "Dockerfile.generated");
56151
+ const generatedDockerfilePath = (0, import_path4.join)(buildDir, "Dockerfile.generated");
56116
56152
  let dockerfile;
56117
56153
  try {
56118
56154
  dockerfile = resolveDockerfile(resolvedRepoPath, {
@@ -56157,9 +56193,9 @@ async function runDockerHarness(config2) {
56157
56193
  "Install Docker Desktop or Docker Engine before using the Docker harness."
56158
56194
  ));
56159
56195
  }
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");
56196
+ const repoPath = (0, import_path4.resolve)(config2.repoPath);
56197
+ const runDir = (0, import_fs3.mkdtempSync)((0, import_path4.join)((0, import_os2.tmpdir)(), "archal-harness-"));
56198
+ const generatedDockerfilePath = (0, import_path4.join)(runDir, "Dockerfile.generated");
56163
56199
  const dockerIdSuffix = `${Date.now().toString(36)}-${process.pid}`;
56164
56200
  const imageName = config2.prebuiltImage ?? `archal/harness-${dockerIdSuffix}`;
56165
56201
  const containerName = `archal-harness-${dockerIdSuffix}`;
@@ -56208,23 +56244,23 @@ async function runDockerHarness(config2) {
56208
56244
  return fail(stageError("Docker harness attach failed", reason));
56209
56245
  }
56210
56246
  try {
56211
- const mountedConfigDir = (0, import_path3.join)(runDir, "out");
56247
+ const mountedConfigDir = (0, import_path4.join)(runDir, "out");
56212
56248
  writeMountedConfigFiles(mountedConfigDir, config2.cloudTwinUrls, config2.authToken, ca.certPath);
56213
56249
  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");
56250
+ env["ARCHAL_MCP_SERVERS"] = (0, import_fs3.readFileSync)((0, import_path4.join)(mountedConfigDir, "mcp-servers.json"), "utf-8");
56215
56251
  const envFileLines = [];
56216
56252
  let multiLineIdx = 0;
56217
56253
  for (const [key, value] of Object.entries(env)) {
56218
56254
  if (value.includes("\n")) {
56219
56255
  const filename = `_env_${multiLineIdx++}_${key.toLowerCase()}`;
56220
- (0, import_fs3.writeFileSync)((0, import_path3.join)(mountedConfigDir, filename), value, { encoding: "utf-8", mode: 384 });
56256
+ (0, import_fs3.writeFileSync)((0, import_path4.join)(mountedConfigDir, filename), value, { encoding: "utf-8", mode: 384 });
56221
56257
  envFileLines.push(`${key}_FILE=${OUTPUT_DIR_IN_CONTAINER}/${filename}`);
56222
56258
  envFileLines.push(`${key}=${OUTPUT_DIR_IN_CONTAINER}/${filename}`);
56223
56259
  } else {
56224
56260
  envFileLines.push(`${key}=${value}`);
56225
56261
  }
56226
56262
  }
56227
- const envFilePath = (0, import_path3.join)(runDir, ".env");
56263
+ const envFilePath = (0, import_path4.join)(runDir, ".env");
56228
56264
  (0, import_fs3.writeFileSync)(envFilePath, envFileLines.join("\n") + "\n", { encoding: "utf-8", mode: 384 });
56229
56265
  const args = [
56230
56266
  "run",
@@ -56300,7 +56336,7 @@ async function runDockerHarness(config2) {
56300
56336
  } catch {
56301
56337
  }
56302
56338
  }
56303
- const envPath = (0, import_path3.join)(runDir, ".env");
56339
+ const envPath = (0, import_path4.join)(runDir, ".env");
56304
56340
  try {
56305
56341
  if ((0, import_fs3.existsSync)(envPath)) {
56306
56342
  const size = (0, import_fs3.statSync)(envPath).size;
@@ -56352,7 +56388,7 @@ async function runLocalProxy(config2, task, canaryFiles) {
56352
56388
  if (hostsEntries) {
56353
56389
  status("NOTE: For full interception in local mode, add these to /etc/hosts:\n" + hostsEntries);
56354
56390
  }
56355
- const workspace = config2.workspacePath ?? (0, import_path6.join)(process.env["HOME"] ?? "/root", ".openclaw");
56391
+ const workspace = config2.workspacePath ?? (0, import_path7.join)(process.env["HOME"] ?? "/root", ".openclaw");
56356
56392
  const noProxyHosts = "127.0.0.1,localhost,.archal.ai";
56357
56393
  const env = {
56358
56394
  ...process.env,
@@ -56387,13 +56423,13 @@ async function runLocalProxy(config2, task, canaryFiles) {
56387
56423
  }
56388
56424
  }
56389
56425
  function writeCanaryFiles(workspace, canaryFiles) {
56390
- const resolvedWorkspace = (0, import_path6.resolve)(workspace);
56426
+ const resolvedWorkspace = (0, import_path7.resolve)(workspace);
56391
56427
  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)) {
56428
+ const filePath = (0, import_path7.resolve)(workspace, relativePath);
56429
+ if (filePath !== resolvedWorkspace && !filePath.startsWith(resolvedWorkspace + import_path7.sep)) {
56394
56430
  throw new Error(`Canary path escapes sandbox root: ${relativePath}`);
56395
56431
  }
56396
- (0, import_fs6.mkdirSync)((0, import_path6.dirname)(filePath), { recursive: true });
56432
+ (0, import_fs6.mkdirSync)((0, import_path7.dirname)(filePath), { recursive: true });
56397
56433
  (0, import_fs6.writeFileSync)(filePath, content);
56398
56434
  }
56399
56435
  }
@@ -56462,9 +56498,9 @@ function spawnAgent(workspace, task, env, timeoutMs) {
56462
56498
  });
56463
56499
  }
56464
56500
  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)) {
56501
+ const resolvedRoot = (0, import_path8.resolve)(root);
56502
+ const resolved = (0, import_path8.resolve)(root, relativePath);
56503
+ if (resolved !== resolvedRoot && !resolved.startsWith(resolvedRoot + import_path8.sep)) {
56468
56504
  throw new Error(`Canary path escapes sandbox root: ${relativePath}`);
56469
56505
  }
56470
56506
  return resolved;
@@ -56727,19 +56763,19 @@ async function runDockerSandbox(config2) {
56727
56763
  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
56764
  };
56729
56765
  }
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;
56766
+ 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
56767
  var init_dist6 = __esm({
56732
56768
  "../packages/sandbox-runtime/dist/index.js"() {
56733
56769
  "use strict";
56734
56770
  import_fs2 = require("fs");
56735
- import_path2 = require("path");
56771
+ import_path3 = require("path");
56736
56772
  import_fs3 = require("fs");
56737
56773
  import_os2 = require("os");
56738
- import_path3 = require("path");
56774
+ import_path4 = require("path");
56739
56775
  init_dist2();
56740
56776
  import_crypto3 = require("crypto");
56741
56777
  import_fs4 = require("fs");
56742
- import_path4 = require("path");
56778
+ import_path5 = require("path");
56743
56779
  import_os3 = require("os");
56744
56780
  import_http = require("http");
56745
56781
  import_https = require("https");
@@ -56748,15 +56784,15 @@ var init_dist6 = __esm({
56748
56784
  import_child_process2 = require("child_process");
56749
56785
  import_fs5 = require("fs");
56750
56786
  import_os4 = require("os");
56751
- import_path5 = require("path");
56752
- import_url = require("url");
56787
+ import_path6 = require("path");
56788
+ import_url2 = require("url");
56753
56789
  import_child_process3 = require("child_process");
56754
56790
  import_child_process4 = require("child_process");
56755
56791
  import_fs6 = require("fs");
56756
- import_path6 = require("path");
56757
56792
  import_path7 = require("path");
56793
+ import_path8 = require("path");
56758
56794
  init_dist4();
56759
- import_meta3 = {};
56795
+ import_meta4 = {};
56760
56796
  DockerfileError = class extends Error {
56761
56797
  kind;
56762
56798
  suggestion;
@@ -56822,13 +56858,13 @@ __export(archal_file_exports, {
56822
56858
  function loadArchalFile(explicitPath) {
56823
56859
  let filePath;
56824
56860
  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}`);
56861
+ filePath = (0, import_node_path22.resolve)(explicitPath);
56862
+ if (!(0, import_node_fs26.existsSync)(filePath)) throw new Error(`Config file not found: ${filePath}`);
56827
56863
  } else {
56828
- filePath = (0, import_node_path21.resolve)(ARCHAL_FILENAME);
56829
- if (!(0, import_node_fs25.existsSync)(filePath)) return null;
56864
+ filePath = (0, import_node_path22.resolve)(ARCHAL_FILENAME);
56865
+ if (!(0, import_node_fs26.existsSync)(filePath)) return null;
56830
56866
  }
56831
- const raw = (0, import_node_fs25.readFileSync)(filePath, "utf-8").trim();
56867
+ const raw = (0, import_node_fs26.readFileSync)(filePath, "utf-8").trim();
56832
56868
  if (!raw) throw new Error(`Config file is empty: ${filePath}`);
56833
56869
  let parsed;
56834
56870
  try {
@@ -56860,14 +56896,14 @@ function loadArchalFile(explicitPath) {
56860
56896
  if (typeof c["model"] === "string") r.model = c["model"].trim() || void 0;
56861
56897
  if (typeof c["runs"] === "number" && Number.isInteger(c["runs"]) && c["runs"] > 0) r.runs = c["runs"];
56862
56898
  if (typeof c["timeout"] === "number" && c["timeout"] > 0) r.timeout = c["timeout"];
56863
- return { config: r, configDir: (0, import_node_path21.dirname)(filePath) };
56899
+ return { config: r, configDir: (0, import_node_path22.dirname)(filePath) };
56864
56900
  }
56865
- var import_node_fs25, import_node_path21, ARCHAL_FILENAME;
56901
+ var import_node_fs26, import_node_path22, ARCHAL_FILENAME;
56866
56902
  var init_archal_file = __esm({
56867
56903
  "src/config/archal-file.ts"() {
56868
56904
  "use strict";
56869
- import_node_fs25 = require("fs");
56870
- import_node_path21 = require("path");
56905
+ import_node_fs26 = require("fs");
56906
+ import_node_path22 = require("path");
56871
56907
  ARCHAL_FILENAME = ".archal.json";
56872
56908
  }
56873
56909
  });
@@ -56926,7 +56962,7 @@ function detectTwinsFromSource(source) {
56926
56962
  function detectTwinsFromPackageJson(packageJsonPath) {
56927
56963
  const twins = /* @__PURE__ */ new Set();
56928
56964
  try {
56929
- const pkg = JSON.parse((0, import_node_fs26.readFileSync)(packageJsonPath, "utf-8"));
56965
+ const pkg = JSON.parse((0, import_node_fs27.readFileSync)(packageJsonPath, "utf-8"));
56930
56966
  for (const depName of Object.keys({ ...pkg.dependencies, ...pkg.devDependencies })) {
56931
56967
  const twinName = PACKAGE_TO_TWIN[depName];
56932
56968
  if (twinName) twins.add(twinName);
@@ -56938,26 +56974,26 @@ function detectTwinsFromPackageJson(packageJsonPath) {
56938
56974
  function detectTwinsFromHarnessDir(harnessDir) {
56939
56975
  const twins = /* @__PURE__ */ new Set();
56940
56976
  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;
56977
+ const filePath = (0, import_node_path23.resolve)(harnessDir, candidate);
56978
+ if (!(0, import_node_fs27.existsSync)(filePath)) continue;
56943
56979
  try {
56944
- for (const twin of detectTwinsFromSource((0, import_node_fs26.readFileSync)(filePath, "utf-8"))) {
56980
+ for (const twin of detectTwinsFromSource((0, import_node_fs27.readFileSync)(filePath, "utf-8"))) {
56945
56981
  twins.add(twin);
56946
56982
  }
56947
56983
  } catch {
56948
56984
  }
56949
56985
  }
56950
- for (const twin of detectTwinsFromPackageJson((0, import_node_path22.resolve)(harnessDir, "package.json"))) {
56986
+ for (const twin of detectTwinsFromPackageJson((0, import_node_path23.resolve)(harnessDir, "package.json"))) {
56951
56987
  twins.add(twin);
56952
56988
  }
56953
56989
  return [...twins].sort();
56954
56990
  }
56955
- var import_node_fs26, import_node_path22, ENTRY_CANDIDATES, IMPORT_PATTERNS, ENV_VAR_PATTERN;
56991
+ var import_node_fs27, import_node_path23, ENTRY_CANDIDATES, IMPORT_PATTERNS, ENV_VAR_PATTERN;
56956
56992
  var init_harness_import_detector = __esm({
56957
56993
  "src/runner/harness-import-detector.ts"() {
56958
56994
  "use strict";
56959
- import_node_fs26 = require("fs");
56960
- import_node_path22 = require("path");
56995
+ import_node_fs27 = require("fs");
56996
+ import_node_path23 = require("path");
56961
56997
  init_package_twin_map();
56962
56998
  ENTRY_CANDIDATES = [
56963
56999
  "harness.ts",
@@ -56983,7 +57019,7 @@ __export(twins_exports, {
56983
57019
  listTwinCatalog: () => listTwinCatalog
56984
57020
  });
56985
57021
  function hasFidelityBaseline(twinName) {
56986
- return findFirstExistingLocalTwinAssetPath(import_meta4.url, twinName, "fidelity.json") !== null;
57022
+ return findFirstExistingLocalTwinAssetPath(import_meta5.url, twinName, "fidelity.json") !== null;
56987
57023
  }
56988
57024
  function writeLocalTwinCatalogJson() {
56989
57025
  process.stdout.write(JSON.stringify(
@@ -57051,7 +57087,7 @@ async function listTwinCatalog(json2) {
57051
57087
  table(["Name", "Tools", "Description", "Status"], rows);
57052
57088
  success2(twinCatalogSummary(creds));
57053
57089
  }
57054
- var import_meta4, KNOWN_TWINS;
57090
+ var import_meta5, KNOWN_TWINS;
57055
57091
  var init_twins = __esm({
57056
57092
  "src/commands/twins.ts"() {
57057
57093
  "use strict";
@@ -57059,7 +57095,7 @@ var init_twins = __esm({
57059
57095
  init_auth();
57060
57096
  init_api_client();
57061
57097
  init_bundled_assets();
57062
- import_meta4 = {};
57098
+ import_meta5 = {};
57063
57099
  KNOWN_TWINS = [
57064
57100
  { name: "github", description: "GitHub digital twin" },
57065
57101
  { name: "slack", description: "Slack digital twin" },
@@ -57096,8 +57132,8 @@ init_dist2();
57096
57132
  // src/commands/run.ts
57097
57133
  init_dist2();
57098
57134
  var import_node_crypto7 = require("crypto");
57099
- var import_node_fs27 = require("fs");
57100
- var import_node_path23 = require("path");
57135
+ var import_node_fs28 = require("fs");
57136
+ var import_node_path24 = require("path");
57101
57137
 
57102
57138
  // src/commands/task-scenario.ts
57103
57139
  var import_node_fs = require("fs");
@@ -57132,10 +57168,10 @@ function generateTaskScenario(options) {
57132
57168
  "",
57133
57169
  "## Success criteria",
57134
57170
  "",
57135
- // Generic criteria for inline --task mode. The evaluator interprets
57136
- // these broadly based on the task description and agent trace.
57171
+ // Criteria for inline --task mode. The evaluator interprets these
57172
+ // based on the task description, agent trace, and twin state.
57137
57173
  "- The agent attempted to complete the task using available tools",
57138
- "- The agent's actions were appropriate for the task",
57174
+ "- The requested change is reflected in the digital twin's final state. Check the state diff and state after \u2014 the service-side effect described in the task must actually be present, not just attempted. If the agent reported success but the twin state shows no corresponding change, this criterion fails.",
57139
57175
  "",
57140
57176
  "## Config",
57141
57177
  "",
@@ -57456,17 +57492,17 @@ function isLoopbackUrl(rawUrl) {
57456
57492
  function isNonLocalEndpoint(rawUrl) {
57457
57493
  return !isLoopbackUrl(rawUrl);
57458
57494
  }
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}`);
57495
+ function parseUrlOverridesFile(path2, label) {
57496
+ if (!path2) return void 0;
57497
+ if (!(0, import_node_fs4.existsSync)(path2)) {
57498
+ throw new Error(`${label.fileNotFound}: ${path2}`);
57463
57499
  }
57464
- const raw = (0, import_node_fs4.readFileSync)(path, "utf-8");
57500
+ const raw = (0, import_node_fs4.readFileSync)(path2, "utf-8");
57465
57501
  const parsed = JSON.parse(raw);
57466
57502
  const overrides = {};
57467
57503
  for (const [key, value] of Object.entries(parsed)) {
57468
57504
  if (typeof value !== "string" || !value.trim()) {
57469
- throw new Error(`${label.invalidEntry} for "${key}" in ${path}`);
57505
+ throw new Error(`${label.invalidEntry} for "${key}" in ${path2}`);
57470
57506
  }
57471
57507
  const trimmed = value.trim();
57472
57508
  try {
@@ -57475,21 +57511,21 @@ function parseUrlOverridesFile(path, label) {
57475
57511
  throw new Error("missing protocol");
57476
57512
  }
57477
57513
  } catch {
57478
- throw new Error(`${label.invalidUrl} "${key}" in ${path}: ${trimmed}`);
57514
+ throw new Error(`${label.invalidUrl} "${key}" in ${path2}: ${trimmed}`);
57479
57515
  }
57480
57516
  overrides[key] = trimmed;
57481
57517
  }
57482
57518
  return overrides;
57483
57519
  }
57484
- function parseRemoteTwinUrlOverrides(path) {
57485
- return parseUrlOverridesFile(path, {
57520
+ function parseRemoteTwinUrlOverrides(path2) {
57521
+ return parseUrlOverridesFile(path2, {
57486
57522
  fileNotFound: "Twin URL overrides file not found",
57487
57523
  invalidEntry: "Invalid twin URL override",
57488
57524
  invalidUrl: "Invalid URL for twin"
57489
57525
  });
57490
57526
  }
57491
- function parseApiBaseUrlOverrides(path) {
57492
- return parseUrlOverridesFile(path, {
57527
+ function parseApiBaseUrlOverrides(path2) {
57528
+ return parseUrlOverridesFile(path2, {
57493
57529
  fileNotFound: "API base URL overrides file not found",
57494
57530
  invalidEntry: "Invalid API base URL override",
57495
57531
  invalidUrl: "Invalid API base URL for"
@@ -59089,6 +59125,42 @@ function summarizeToolCalls(toolName, entries) {
59089
59125
  }
59090
59126
  return `${toolLabel} \xD7${count}`;
59091
59127
  }
59128
+ var MAX_CONVERSATION_LINES = 6;
59129
+ var MAX_CONVERSATION_TEXT_CHARS = 120;
59130
+ function formatConversationSummary(report) {
59131
+ const lines = [];
59132
+ const representativeRun = report.runs.find((r) => r.agentTrace && r.agentTrace.length > 0);
59133
+ if (!representativeRun?.agentTrace) return lines;
59134
+ const agentTrace = representativeRun.agentTrace;
59135
+ const twinToolNames = new Set(representativeRun.trace.map((e) => e.toolName));
59136
+ const entries = [];
59137
+ for (const step of agentTrace) {
59138
+ if (entries.length >= MAX_CONVERSATION_LINES) break;
59139
+ for (const call of step.toolCalls) {
59140
+ if (entries.length >= MAX_CONVERSATION_LINES) break;
59141
+ if (!twinToolNames.has(call.name)) {
59142
+ let argStr = "";
59143
+ try {
59144
+ const raw = JSON.stringify(call.arguments);
59145
+ argStr = raw.length > MAX_CONVERSATION_TEXT_CHARS ? raw.slice(0, MAX_CONVERSATION_TEXT_CHARS - 1) + "\u2026" : raw;
59146
+ } catch {
59147
+ }
59148
+ entries.push(`${DIM}\u2192${RESET} [${call.name}${argStr ? " \u2192 " + argStr : ""}]`);
59149
+ }
59150
+ }
59151
+ if (step.text && entries.length < MAX_CONVERSATION_LINES) {
59152
+ const flat = step.text.replace(/\s+/g, " ").trim();
59153
+ const preview = flat.length > MAX_CONVERSATION_TEXT_CHARS ? flat.slice(0, MAX_CONVERSATION_TEXT_CHARS - 1) + "\u2026" : flat;
59154
+ entries.push(`${DIM}\u201C${preview}\u201D${RESET}`);
59155
+ }
59156
+ }
59157
+ if (entries.length === 0) return lines;
59158
+ lines.push(` ${DIM}conversation:${RESET}`);
59159
+ for (const entry of entries) {
59160
+ lines.push(` ${entry}`);
59161
+ }
59162
+ return lines;
59163
+ }
59092
59164
  var MAX_DISPLAYED_EVENTS = 10;
59093
59165
  function formatEventsSummary(report) {
59094
59166
  const lines = [];
@@ -59225,6 +59297,11 @@ function formatTerminal(report) {
59225
59297
  lines.push(` ${DIM}${line}${RESET}`);
59226
59298
  }
59227
59299
  }
59300
+ const conversationSummary = formatConversationSummary(report);
59301
+ if (conversationSummary.length > 0) {
59302
+ lines.push("");
59303
+ lines.push(...conversationSummary);
59304
+ }
59228
59305
  const eventsSummary = formatEventsSummary(report);
59229
59306
  if (eventsSummary.length > 0) {
59230
59307
  lines.push("");
@@ -60201,7 +60278,7 @@ var import_node_fs9 = require("fs");
60201
60278
  var import_node_path7 = require("path");
60202
60279
  init_dist2();
60203
60280
  init_bundled_assets();
60204
- var import_meta2 = {};
60281
+ var import_meta3 = {};
60205
60282
  function isIdKeyedCollection(value) {
60206
60283
  if (!Array.isArray(value)) return false;
60207
60284
  if (value.length === 0) return false;
@@ -60439,7 +60516,7 @@ function normalizeSeedState(raw) {
60439
60516
  return Object.keys(normalized).length > 0 ? normalized : null;
60440
60517
  }
60441
60518
  function loadBaseSeedFromDisk(twinName, seedName) {
60442
- for (const seedRoot of resolveLocalTwinAssetCandidates(import_meta2.url, twinName, "seeds")) {
60519
+ for (const seedRoot of resolveLocalTwinAssetCandidates(import_meta3.url, twinName, "seeds")) {
60443
60520
  const seedState = loadSeedStateFromPath(seedRoot, seedName);
60444
60521
  if (seedState) {
60445
60522
  return seedState;
@@ -60551,6 +60628,80 @@ function toTwinUrlEnvKey(name) {
60551
60628
  const normalized = name.trim().toUpperCase().replace(/[^A-Z0-9]+/g, "_").replace(/^_+|_+$/g, "");
60552
60629
  return normalized.length > 0 ? `ARCHAL_${normalized}_URL` : null;
60553
60630
  }
60631
+ function synthesizeAgentTraceFromStderr(stderr) {
60632
+ const lines = stderr.split("\n");
60633
+ const steps = [];
60634
+ let stepNumber = 1;
60635
+ let currentText = [];
60636
+ let currentToolCalls = [];
60637
+ function flushStep() {
60638
+ if (currentText.length === 0 && currentToolCalls.length === 0) return;
60639
+ steps.push({
60640
+ step: stepNumber++,
60641
+ thinking: null,
60642
+ text: currentText.length > 0 ? currentText.join("\n") : null,
60643
+ toolCalls: currentToolCalls,
60644
+ durationMs: 0
60645
+ });
60646
+ currentText = [];
60647
+ currentToolCalls = [];
60648
+ }
60649
+ for (const line of lines) {
60650
+ if (line.startsWith("[agent] ")) {
60651
+ const text = line.slice("[agent] ".length).trim();
60652
+ if (text) {
60653
+ currentText.push(text);
60654
+ }
60655
+ } else if (line.startsWith("[tool] ")) {
60656
+ const toolName = line.slice("[tool] ".length).trim();
60657
+ if (toolName) {
60658
+ flushStep();
60659
+ currentToolCalls.push({ name: toolName, arguments: {} });
60660
+ }
60661
+ } else if (line.includes("[ClaudeAgent:tool_result]")) {
60662
+ let payload = line;
60663
+ try {
60664
+ const outer = JSON.parse(line);
60665
+ if (outer && typeof outer === "object" && "msg" in outer) {
60666
+ const msg = outer["msg"];
60667
+ if (typeof msg === "string") payload = msg;
60668
+ }
60669
+ } catch {
60670
+ }
60671
+ const marker = "[ClaudeAgent:tool_result] ";
60672
+ const markerIdx = payload.indexOf(marker);
60673
+ const jsonStr = markerIdx !== -1 ? payload.slice(markerIdx + marker.length) : payload.slice(payload.indexOf("{"));
60674
+ if (jsonStr) {
60675
+ try {
60676
+ const parsed = JSON.parse(jsonStr);
60677
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
60678
+ const obj = parsed;
60679
+ const toolUseId = typeof obj["tool_use_id"] === "string" ? obj["tool_use_id"] : void 0;
60680
+ const content = Array.isArray(obj["content"]) ? obj["content"] : void 0;
60681
+ const resultText = content ? content.find((b) => b["type"] === "text")?.["text"] : obj["result"] ?? obj["content"];
60682
+ if (toolUseId || resultText) {
60683
+ let resultObj = resultText;
60684
+ if (typeof resultText === "string") {
60685
+ try {
60686
+ resultObj = JSON.parse(resultText);
60687
+ } catch {
60688
+ }
60689
+ }
60690
+ flushStep();
60691
+ currentToolCalls.push({
60692
+ name: "agent_tool_result",
60693
+ arguments: resultObj ?? {}
60694
+ });
60695
+ }
60696
+ }
60697
+ } catch {
60698
+ }
60699
+ }
60700
+ }
60701
+ }
60702
+ flushStep();
60703
+ return steps.length > 0 ? steps : void 0;
60704
+ }
60554
60705
  async function executeAgent(params) {
60555
60706
  const {
60556
60707
  agentConfig,
@@ -60767,6 +60918,12 @@ ${stderrPreview}`);
60767
60918
  }
60768
60919
  }
60769
60920
  }
60921
+ if (!agentTrace) {
60922
+ const combined = [result.stderr, result.stdout].filter(Boolean).join("\n");
60923
+ if (combined.trim()) {
60924
+ agentTrace = synthesizeAgentTraceFromStderr(combined);
60925
+ }
60926
+ }
60770
60927
  return {
60771
60928
  exitCode: result.exitCode,
60772
60929
  stdout: result.stdout,
@@ -65129,10 +65286,27 @@ function buildFailureAnalysisPrompt(input) {
65129
65286
  ${sanitizeForPrompt(logTail, 800)}`);
65130
65287
  }
65131
65288
  }
65132
- sections.push(`## Agent Trace (${input.trace.length} tool calls)`);
65289
+ sections.push(`## Agent Trace \u2014 Twin API Calls (${input.trace.length} calls)`);
65133
65290
  sections.push(
65134
- input.trace.length === 0 ? "(Agent made no tool calls - likely crashed or timed out)" : JSON.stringify(traceFormatted, null, 2)
65291
+ input.trace.length === 0 ? "(Agent made no tool calls to the twin - but may have used built-in tools; see agent-side trace below)" : JSON.stringify(traceFormatted, null, 2)
65135
65292
  );
65293
+ if (input.agentTrace && input.agentTrace.length > 0) {
65294
+ const agentSteps = input.agentTrace.slice(0, 15).map((step) => ({
65295
+ step: step.step,
65296
+ ...step.text ? { text: step.text.slice(0, 300) } : {},
65297
+ ...step.toolCalls.length > 0 ? {
65298
+ toolCalls: step.toolCalls.map((tc) => ({
65299
+ name: tc.name,
65300
+ arguments: tc.arguments
65301
+ }))
65302
+ } : {}
65303
+ }));
65304
+ sections.push(`## Agent-Side Trace (built-in tool calls + text responses)`);
65305
+ sections.push(
65306
+ "These are tool calls handled by the agent's own tools (not the twin). A tool returning success here does NOT mean the twin state was modified \u2014 the agent's tool handler may have silently dropped the operation."
65307
+ );
65308
+ sections.push(JSON.stringify(agentSteps, null, 2));
65309
+ }
65136
65310
  const stateAfterKeys = Object.keys(input.stateAfter);
65137
65311
  if (stateAfterKeys.length > 0) {
65138
65312
  sections.push(`## Final Twin State Summary`);
@@ -66318,7 +66492,8 @@ async function aggregateAndReport(input) {
66318
66492
  stateAfter: representativeRun.stateAfter ?? {},
66319
66493
  satisfactionScore,
66320
66494
  agentLog: representativeRun.agentLog,
66321
- agentError: representativeRun.error
66495
+ agentError: representativeRun.error,
66496
+ agentTrace: representativeRun.agentTrace
66322
66497
  },
66323
66498
  evaluatorConfig
66324
66499
  );
@@ -66385,12 +66560,12 @@ function listCommandCandidates(command) {
66385
66560
  }
66386
66561
  return [...variants];
66387
66562
  }
66388
- function isExecutable(path) {
66563
+ function isExecutable(path2) {
66389
66564
  try {
66390
- (0, import_node_fs18.accessSync)(path, import_node_fs18.constants.X_OK);
66565
+ (0, import_node_fs18.accessSync)(path2, import_node_fs18.constants.X_OK);
66391
66566
  return true;
66392
66567
  } catch {
66393
- return process.platform === "win32" && (0, import_node_fs18.existsSync)(path);
66568
+ return process.platform === "win32" && (0, import_node_fs18.existsSync)(path2);
66394
66569
  }
66395
66570
  }
66396
66571
  function isCommandAvailable(command) {
@@ -66639,6 +66814,83 @@ ${lines.join("\n")}`
66639
66814
  init_cache();
66640
66815
  init_auth();
66641
66816
  init_api_client();
66817
+
66818
+ // src/commands/env-session-reuse.ts
66819
+ var import_node_fs20 = require("fs");
66820
+ var import_node_os7 = require("os");
66821
+ var import_node_path16 = require("path");
66822
+ init_auth();
66823
+ var TWIN_SESSION_FILE = (0, import_node_path16.join)((0, import_node_os7.homedir)(), ".archal", "twin-session.json");
66824
+ var LEGACY_SESSION_FILE = (0, import_node_path16.join)((0, import_node_os7.homedir)(), ".archal", "env-session.json");
66825
+ function loadSession() {
66826
+ let filePath = TWIN_SESSION_FILE;
66827
+ if (!(0, import_node_fs20.existsSync)(filePath)) {
66828
+ if ((0, import_node_fs20.existsSync)(LEGACY_SESSION_FILE)) {
66829
+ filePath = LEGACY_SESSION_FILE;
66830
+ } else {
66831
+ return null;
66832
+ }
66833
+ }
66834
+ try {
66835
+ return JSON.parse((0, import_node_fs20.readFileSync)(filePath, "utf8"));
66836
+ } catch {
66837
+ return null;
66838
+ }
66839
+ }
66840
+ function resolveApiBaseUrl() {
66841
+ return getConfiguredApiBaseUrl2() ?? "https://www.archal.ai";
66842
+ }
66843
+ async function tryReuseEnvSession(requiredTwins, credentials) {
66844
+ try {
66845
+ const session = loadSession();
66846
+ if (!session) {
66847
+ return null;
66848
+ }
66849
+ if (!requiredTwins.every((t) => session.twins.includes(t))) {
66850
+ return null;
66851
+ }
66852
+ const missingEndpoints = requiredTwins.filter(
66853
+ (t) => !session.endpoints[t] && !session.apiBaseUrls[t]
66854
+ );
66855
+ if (missingEndpoints.length > 0) {
66856
+ return null;
66857
+ }
66858
+ let apiBase = resolveApiBaseUrl();
66859
+ if (session.apiBaseUrl) {
66860
+ try {
66861
+ const parsed = new URL(session.apiBaseUrl);
66862
+ const isLocalHttp = parsed.protocol === "http:" && (parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1");
66863
+ if (parsed.protocol === "https:" || isLocalHttp) {
66864
+ apiBase = session.apiBaseUrl;
66865
+ }
66866
+ } catch {
66867
+ }
66868
+ }
66869
+ const response = await fetch(`${apiBase}/api/sessions/${session.sessionId}`, {
66870
+ method: "GET",
66871
+ headers: {
66872
+ "Authorization": `Bearer ${credentials.token}`,
66873
+ "Content-Type": "application/json"
66874
+ }
66875
+ });
66876
+ if (!response.ok) {
66877
+ return null;
66878
+ }
66879
+ const data = await response.json();
66880
+ if (data.status !== "ready") {
66881
+ return null;
66882
+ }
66883
+ return {
66884
+ sessionId: session.sessionId,
66885
+ endpoints: session.endpoints,
66886
+ apiBaseUrls: session.apiBaseUrls
66887
+ };
66888
+ } catch {
66889
+ return null;
66890
+ }
66891
+ }
66892
+
66893
+ // src/commands/run.ts
66642
66894
  init_errors4();
66643
66895
  init_logger();
66644
66896
 
@@ -66675,24 +66927,24 @@ async function runShutdownHooks(signal) {
66675
66927
  init_config();
66676
66928
 
66677
66929
  // src/commands/run-config-resolver.ts
66678
- var import_node_fs21 = require("fs");
66679
- var import_node_path17 = require("path");
66930
+ var import_node_fs22 = require("fs");
66931
+ var import_node_path18 = require("path");
66680
66932
  init_config();
66681
66933
 
66682
66934
  // 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");
66935
+ var import_node_fs21 = require("fs");
66936
+ var import_node_os8 = require("os");
66937
+ var import_node_path17 = require("path");
66686
66938
  var OPENCLAW_HARNESS_ALIASES = /* @__PURE__ */ new Set(["openclaw", "oc", "nemoclaw", "nemo"]);
66687
66939
  function isOpenClawHarnessName(name) {
66688
66940
  return OPENCLAW_HARNESS_ALIASES.has(name.trim().toLowerCase());
66689
66941
  }
66690
- function resolveDefaultOpenClawHome(opts, homeDir = (0, import_node_os7.homedir)()) {
66942
+ function resolveDefaultOpenClawHome(opts, homeDir = (0, import_node_os8.homedir)()) {
66691
66943
  if (opts.openclawHome?.trim() || opts.workspace?.trim() || opts.openclawConfig?.trim()) {
66692
66944
  return void 0;
66693
66945
  }
66694
- const defaultHome = (0, import_node_path16.join)(homeDir, ".openclaw");
66695
- return (0, import_node_fs20.existsSync)(defaultHome) ? defaultHome : void 0;
66946
+ const defaultHome = (0, import_node_path17.join)(homeDir, ".openclaw");
66947
+ return (0, import_node_fs21.existsSync)(defaultHome) ? defaultHome : void 0;
66696
66948
  }
66697
66949
  function detectApiKeyProvider(key) {
66698
66950
  if (!key) return "unknown";
@@ -66772,7 +67024,7 @@ function resolveFromCandidates(candidates, fallback) {
66772
67024
  return fallback;
66773
67025
  }
66774
67026
  function loadProjectConfigForScenario(scenarioPath) {
66775
- const root = findNearestProjectRoot((0, import_node_path17.dirname)((0, import_node_path17.resolve)(scenarioPath)), process.cwd());
67027
+ const root = findNearestProjectRoot((0, import_node_path18.dirname)((0, import_node_path18.resolve)(scenarioPath)), process.cwd());
66776
67028
  if (!root) {
66777
67029
  return {
66778
67030
  root: null,
@@ -66782,7 +67034,7 @@ function loadProjectConfigForScenario(scenarioPath) {
66782
67034
  }
66783
67035
  return {
66784
67036
  root,
66785
- configPath: (0, import_node_path17.join)(root, ".archal.json"),
67037
+ configPath: (0, import_node_path18.join)(root, ".archal.json"),
66786
67038
  config: loadProjectConfig(root)
66787
67039
  };
66788
67040
  }
@@ -67203,7 +67455,7 @@ function resolveRunConfigWithSources(scenarioPath, opts, sources, preloaded) {
67203
67455
  { value: void 0, source: "unset", detail: "(not set)" }
67204
67456
  );
67205
67457
  return {
67206
- scenarioPath: (0, import_node_path17.resolve)(scenarioPath),
67458
+ scenarioPath: (0, import_node_path18.resolve)(scenarioPath),
67207
67459
  projectRoot: project.root,
67208
67460
  projectConfigPath: project.configPath,
67209
67461
  invalidExplicitRuns,
@@ -67240,13 +67492,13 @@ function applyResolvedRunConfigToOptions(opts, resolved) {
67240
67492
  function findNearestProjectRoot(...startPaths) {
67241
67493
  for (const start of startPaths) {
67242
67494
  if (!start || !start.trim()) continue;
67243
- let current = (0, import_node_path17.resolve)(start);
67495
+ let current = (0, import_node_path18.resolve)(start);
67244
67496
  while (true) {
67245
- const candidate = (0, import_node_path17.join)(current, ".archal.json");
67246
- if ((0, import_node_fs21.existsSync)(candidate)) {
67497
+ const candidate = (0, import_node_path18.join)(current, ".archal.json");
67498
+ if ((0, import_node_fs22.existsSync)(candidate)) {
67247
67499
  return current;
67248
67500
  }
67249
- const parent = (0, import_node_path17.dirname)(current);
67501
+ const parent = (0, import_node_path18.dirname)(current);
67250
67502
  if (parent === current) break;
67251
67503
  current = parent;
67252
67504
  }
@@ -67255,8 +67507,8 @@ function findNearestProjectRoot(...startPaths) {
67255
67507
  }
67256
67508
 
67257
67509
  // src/commands/run-session.ts
67258
- var import_node_fs22 = require("fs");
67259
- var import_node_path18 = require("path");
67510
+ var import_node_fs23 = require("fs");
67511
+ var import_node_path19 = require("path");
67260
67512
  init_dist2();
67261
67513
  init_api_client();
67262
67514
  init_auth();
@@ -67462,7 +67714,19 @@ function buildEvidenceArtifacts(report) {
67462
67714
  const reportRuns = report.runs ?? [];
67463
67715
  const traceEntries = reportRuns.flatMap((run) => buildToolTraceEntries(run));
67464
67716
  const thinkingTraceEntries = [];
67465
- const agentTraces = [];
67717
+ const agentTraces = reportRuns.filter((run) => run.agentTrace && run.agentTrace.length > 0).map((run) => ({
67718
+ runIndex: run.runIndex,
67719
+ steps: run.agentTrace.map((step) => ({
67720
+ step: step.step,
67721
+ thinking: previewForEvidence(step.thinking, 800),
67722
+ text: previewForEvidence(step.text, 1200),
67723
+ toolCalls: step.toolCalls.map((tc) => ({
67724
+ name: tc.name,
67725
+ arguments: previewForEvidence(tc.arguments)
67726
+ })),
67727
+ durationMs: step.durationMs
67728
+ }))
67729
+ }));
67466
67730
  const evaluations = reportRuns.flatMap(
67467
67731
  (run) => (run.evaluations ?? []).map((ev) => ({
67468
67732
  runIndex: run.runIndex,
@@ -67548,9 +67812,9 @@ function writeManagedRunStatus(patch) {
67548
67812
  if (!statusPath) return;
67549
67813
  try {
67550
67814
  let existing = {};
67551
- if ((0, import_node_fs22.existsSync)(statusPath)) {
67815
+ if ((0, import_node_fs23.existsSync)(statusPath)) {
67552
67816
  try {
67553
- const raw = (0, import_node_fs22.readFileSync)(statusPath, "utf-8");
67817
+ const raw = (0, import_node_fs23.readFileSync)(statusPath, "utf-8");
67554
67818
  const parsed = JSON.parse(raw);
67555
67819
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
67556
67820
  existing = parsed;
@@ -67559,8 +67823,8 @@ function writeManagedRunStatus(patch) {
67559
67823
  }
67560
67824
  }
67561
67825
  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");
67826
+ (0, import_node_fs23.mkdirSync)((0, import_node_path19.dirname)(statusPath), { recursive: true });
67827
+ (0, import_node_fs23.writeFileSync)(statusPath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
67564
67828
  } catch {
67565
67829
  }
67566
67830
  }
@@ -67578,27 +67842,42 @@ function resolveManagedRunProjectMetadata(opts) {
67578
67842
  const description = opts?.runProjectDescription?.trim() || process.env["ARCHAL_WEB_RUN_PROJECT_DESCRIPTION"]?.trim();
67579
67843
  return { id, name, description };
67580
67844
  }
67845
+ function buildRuntimeTwinUrls(sessionId, twins, runtimeBaseUrl) {
67846
+ const base = runtimeBaseUrl.replace(/\/+$/, "");
67847
+ const sessionPath = encodeURIComponent(sessionId);
67848
+ const endpoints = {};
67849
+ const apiBaseUrls = {};
67850
+ for (const twin of twins) {
67851
+ const root = `${base}/runtime/${sessionPath}/${encodeURIComponent(twin)}`;
67852
+ endpoints[twin] = root;
67853
+ apiBaseUrls[twin] = `${root}/api`;
67854
+ }
67855
+ return { endpoints, apiBaseUrls };
67856
+ }
67581
67857
  function writeTempJsonMap(filePath, data, context) {
67582
67858
  try {
67583
- (0, import_node_fs22.writeFileSync)(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
67859
+ (0, import_node_fs23.writeFileSync)(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
67584
67860
  return { ok: true };
67585
67861
  } catch (err) {
67586
67862
  const reason = errorMessage(err);
67587
67863
  return { ok: false, error: `failed to write ${context} (${filePath}): ${reason}` };
67588
67864
  }
67589
67865
  }
67866
+ function isTerminalHostedSessionStatus(status) {
67867
+ return status === "failed" || status === "expired" || status === "completed" || status === "ended" || status === "tearing_down";
67868
+ }
67590
67869
  function cleanupGeneratedSessionMaps(ctx) {
67591
- if (ctx.generatedTwinUrlMapPath && (0, import_node_fs22.existsSync)(ctx.generatedTwinUrlMapPath)) {
67870
+ if (ctx.generatedTwinUrlMapPath && (0, import_node_fs23.existsSync)(ctx.generatedTwinUrlMapPath)) {
67592
67871
  try {
67593
- (0, import_node_fs22.unlinkSync)(ctx.generatedTwinUrlMapPath);
67872
+ (0, import_node_fs23.unlinkSync)(ctx.generatedTwinUrlMapPath);
67594
67873
  } catch (error49) {
67595
67874
  process.stderr.write(`Warning: failed to remove temp twin URL map: ${errorMessage(error49)}
67596
67875
  `);
67597
67876
  }
67598
67877
  }
67599
- if (ctx.generatedApiBaseUrlMapPath && (0, import_node_fs22.existsSync)(ctx.generatedApiBaseUrlMapPath)) {
67878
+ if (ctx.generatedApiBaseUrlMapPath && (0, import_node_fs23.existsSync)(ctx.generatedApiBaseUrlMapPath)) {
67600
67879
  try {
67601
- (0, import_node_fs22.unlinkSync)(ctx.generatedApiBaseUrlMapPath);
67880
+ (0, import_node_fs23.unlinkSync)(ctx.generatedApiBaseUrlMapPath);
67602
67881
  } catch (error49) {
67603
67882
  process.stderr.write(`Warning: failed to remove temp API base URL map: ${errorMessage(error49)}
67604
67883
  `);
@@ -67607,6 +67886,9 @@ function cleanupGeneratedSessionMaps(ctx) {
67607
67886
  }
67608
67887
  async function cleanupHostedSession(ctx) {
67609
67888
  cleanupGeneratedSessionMaps(ctx);
67889
+ if (ctx.isReusedEnvSession) {
67890
+ return;
67891
+ }
67610
67892
  if (!ctx.backendSessionId && ctx.inFlightSessionStart) {
67611
67893
  try {
67612
67894
  const startResult = await ctx.inFlightSessionStart;
@@ -67689,8 +67971,8 @@ async function cleanupHostedSession(ctx) {
67689
67971
  } catch {
67690
67972
  }
67691
67973
  }
67692
- (0, import_node_fs22.mkdirSync)((0, import_node_path18.dirname)(ctx.evidenceOutputPath), { recursive: true });
67693
- (0, import_node_fs22.writeFileSync)(
67974
+ (0, import_node_fs23.mkdirSync)((0, import_node_path19.dirname)(ctx.evidenceOutputPath), { recursive: true });
67975
+ (0, import_node_fs23.writeFileSync)(
67694
67976
  ctx.evidenceOutputPath,
67695
67977
  JSON.stringify(
67696
67978
  {
@@ -67805,7 +68087,7 @@ async function waitForSessionReady(opts) {
67805
68087
  return { ready: false, error: `session health check failed (${healthResult.error})` };
67806
68088
  }
67807
68089
  const status = statusResult.data.status;
67808
- if (status === "failed" || status === "expired" || status === "completed") {
68090
+ if (isTerminalHostedSessionStatus(status)) {
67809
68091
  return { ready: false, error: `session ${status}` };
67810
68092
  }
67811
68093
  const healthAlive = healthResult.ok && healthResult.data.alive;
@@ -67869,35 +68151,35 @@ function mapSessionStartError(sessionResult) {
67869
68151
  }
67870
68152
 
67871
68153
  // src/commands/run-validation.ts
67872
- var import_node_fs24 = require("fs");
67873
- var import_node_path20 = require("path");
68154
+ var import_node_fs25 = require("fs");
68155
+ var import_node_path21 = require("path");
67874
68156
  init_dist2();
67875
68157
  init_errors4();
67876
68158
  init_auth();
67877
68159
 
67878
68160
  // src/scenarios/catalog.ts
67879
- var import_node_fs23 = require("fs");
67880
- var import_node_path19 = require("path");
68161
+ var import_node_fs24 = require("fs");
68162
+ var import_node_path20 = require("path");
67881
68163
  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")
68164
+ (0, import_node_path20.resolve)("scenarios"),
68165
+ (0, import_node_path20.resolve)("scenario"),
68166
+ (0, import_node_path20.resolve)("test", "scenarios"),
68167
+ (0, import_node_path20.resolve)("tests", "scenarios"),
68168
+ (0, import_node_path20.resolve)(".archal", "scenarios")
67887
68169
  ];
67888
68170
  function findScenarioFiles(dir) {
67889
- if (!(0, import_node_fs23.existsSync)(dir)) {
68171
+ if (!(0, import_node_fs24.existsSync)(dir)) {
67890
68172
  return [];
67891
68173
  }
67892
68174
  const files = [];
67893
- const entries = (0, import_node_fs23.readdirSync)(dir, { withFileTypes: true });
68175
+ const entries = (0, import_node_fs24.readdirSync)(dir, { withFileTypes: true });
67894
68176
  for (const entry of entries) {
67895
- const fullPath = (0, import_node_path19.join)(dir, entry.name);
68177
+ const fullPath = (0, import_node_path20.join)(dir, entry.name);
67896
68178
  if (entry.isDirectory()) {
67897
68179
  files.push(...findScenarioFiles(fullPath));
67898
68180
  continue;
67899
68181
  }
67900
- if (entry.isFile() && (0, import_node_path19.extname)(entry.name) === ".md") {
68182
+ if (entry.isFile() && (0, import_node_path20.extname)(entry.name) === ".md") {
67901
68183
  files.push(fullPath);
67902
68184
  }
67903
68185
  }
@@ -67905,27 +68187,27 @@ function findScenarioFiles(dir) {
67905
68187
  }
67906
68188
  function findLocalScenariosDir() {
67907
68189
  for (const candidate of SCENARIO_DIR_CANDIDATES) {
67908
- if ((0, import_node_fs23.existsSync)(candidate)) {
68190
+ if ((0, import_node_fs24.existsSync)(candidate)) {
67909
68191
  return { dir: candidate, candidates: SCENARIO_DIR_CANDIDATES };
67910
68192
  }
67911
68193
  }
67912
68194
  return {
67913
- dir: (0, import_node_path19.resolve)("scenarios"),
68195
+ dir: (0, import_node_path20.resolve)("scenarios"),
67914
68196
  candidates: SCENARIO_DIR_CANDIDATES
67915
68197
  };
67916
68198
  }
67917
68199
  function resolveLocalScenario(nameOrPath) {
67918
- const directPath = (0, import_node_path19.resolve)(nameOrPath);
67919
- if ((0, import_node_fs23.existsSync)(directPath)) {
68200
+ const directPath = (0, import_node_path20.resolve)(nameOrPath);
68201
+ if ((0, import_node_fs24.existsSync)(directPath)) {
67920
68202
  return directPath;
67921
68203
  }
67922
68204
  const needle = nameOrPath.endsWith(".md") ? nameOrPath : `${nameOrPath}.md`;
67923
68205
  for (const candidate of SCENARIO_DIR_CANDIDATES) {
67924
- if (!(0, import_node_fs23.existsSync)(candidate)) {
68206
+ if (!(0, import_node_fs24.existsSync)(candidate)) {
67925
68207
  continue;
67926
68208
  }
67927
- const rootCandidate = (0, import_node_path19.join)(candidate, needle);
67928
- if ((0, import_node_fs23.existsSync)(rootCandidate)) {
68209
+ const rootCandidate = (0, import_node_path20.join)(candidate, needle);
68210
+ if ((0, import_node_fs24.existsSync)(rootCandidate)) {
67929
68211
  return rootCandidate;
67930
68212
  }
67931
68213
  const nestedMatch = findScenarioFiles(candidate).find(
@@ -68074,8 +68356,8 @@ function parseOpenClawEvalMode(raw, source) {
68074
68356
  );
68075
68357
  }
68076
68358
  function resolveScenarioPath(scenarioArg) {
68077
- let scenarioPath = (0, import_node_path20.resolve)(scenarioArg);
68078
- if (!(0, import_node_fs24.existsSync)(scenarioPath)) {
68359
+ let scenarioPath = (0, import_node_path21.resolve)(scenarioArg);
68360
+ if (!(0, import_node_fs25.existsSync)(scenarioPath)) {
68079
68361
  const localScenario = resolveLocalScenario(scenarioArg);
68080
68362
  if (localScenario) {
68081
68363
  scenarioPath = localScenario;
@@ -68092,7 +68374,7 @@ function resolveScenarioPath(scenarioArg) {
68092
68374
  "Rename the file to use the .md extension, then retry."
68093
68375
  );
68094
68376
  }
68095
- if (!(0, import_node_fs24.readFileSync)(scenarioPath, "utf-8").trim()) {
68377
+ if (!(0, import_node_fs25.readFileSync)(scenarioPath, "utf-8").trim()) {
68096
68378
  validationError(
68097
68379
  `Scenario file is empty: ${scenarioPath}`,
68098
68380
  "Add scenario content (Setup, Prompt, Success Criteria sections), then retry."
@@ -68253,9 +68535,10 @@ function resolveHarnessAndEngine(opts, timeout, resolved) {
68253
68535
  opts.explicitHarnessKind = void 0;
68254
68536
  let inferredRepoHarness = false;
68255
68537
  const dockerExplicitlyRequested = isDockerExplicitlyRequested(opts);
68538
+ const userConfig = loadConfig();
68256
68539
  if (!process.env["ANTHROPIC_API_KEY"] && !process.env["OPENAI_API_KEY"] && !process.env["GEMINI_API_KEY"]) {
68257
68540
  try {
68258
- const cfg = loadConfig();
68541
+ const cfg = userConfig;
68259
68542
  if (cfg.apiKey) {
68260
68543
  if (cfg.apiKey.startsWith("sk-ant-")) {
68261
68544
  process.env["ANTHROPIC_API_KEY"] = cfg.apiKey;
@@ -68312,7 +68595,6 @@ function resolveHarnessAndEngine(opts, timeout, resolved) {
68312
68595
  }
68313
68596
  }
68314
68597
  }
68315
- const userConfig = loadConfig();
68316
68598
  const { resolvedHarness, resolvedAgentModel } = applyConfiguredRunDefaults(opts, resolved, userConfig);
68317
68599
  if (opts.apiKey?.trim()) {
68318
68600
  warnIfKeyLooksInvalid(opts.apiKey.trim(), "--api-key");
@@ -68350,7 +68632,7 @@ function resolveHarnessAndEngine(opts, timeout, resolved) {
68350
68632
  }
68351
68633
  } else {
68352
68634
  const inferredHarness = discoverRepoLocalHarness(
68353
- (0, import_node_path20.dirname)(resolved?.scenarioPath ?? process.cwd()),
68635
+ (0, import_node_path21.dirname)(resolved?.scenarioPath ?? process.cwd()),
68354
68636
  resolved?.projectRoot ?? "",
68355
68637
  process.cwd()
68356
68638
  );
@@ -68740,9 +69022,29 @@ async function executeRunForScenario(scenarioArg, opts, command, configDefaults)
68740
69022
  );
68741
69023
  }
68742
69024
  writeManagedRunStatus({ stage: shouldProvisionHostedSession ? "provisioning" : "running" });
69025
+ let reusedExistingSession = false;
69026
+ if (shouldProvisionHostedSession && credentials) {
69027
+ const reusedSession = await tryReuseEnvSession(scenario.config.twins, credentials);
69028
+ if (reusedSession) {
69029
+ reusedExistingSession = true;
69030
+ ctx.backendSessionId = reusedSession.sessionId;
69031
+ ctx.isReusedEnvSession = true;
69032
+ cloudTwinUrls = reusedSession.endpoints;
69033
+ if (!opts.apiBaseUrls) {
69034
+ hostedApiBaseUrlOverrides = reusedSession.apiBaseUrls;
69035
+ }
69036
+ if (!opts.quiet) {
69037
+ info(`Reusing active twin session ${reusedSession.sessionId}`);
69038
+ }
69039
+ writeManagedRunStatus({
69040
+ stage: "session_ready",
69041
+ sessionId: ctx.backendSessionId
69042
+ });
69043
+ }
69044
+ }
68743
69045
  if (process.env["ARCHAL_LOCAL_TWINS"]) {
68744
69046
  ctx.runFailureMessage = "ARCHAL_LOCAL_TWINS has been removed. Twins are always provisioned in hosted cloud sessions.";
68745
- } else if (shouldProvisionHostedSession) {
69047
+ } else if (!reusedExistingSession && shouldProvisionHostedSession) {
68746
69048
  ctx.inFlightSessionStart = startSession(credentials?.token ?? "", {
68747
69049
  twins: scenario.config.twins,
68748
69050
  scenarioId: scenario.title,
@@ -68772,12 +69074,32 @@ async function executeRunForScenario(scenarioArg, opts, command, configDefaults)
68772
69074
  stage: "provisioning",
68773
69075
  sessionId: ctx.backendSessionId
68774
69076
  });
68775
- const endpointRoots = sessionResult.data.endpoints;
68776
- const apiBaseUrls = sessionResult.data.apiBaseUrls;
69077
+ const serverEndpoints = sessionResult.data.endpoints;
69078
+ const serverApiBaseUrls = sessionResult.data.apiBaseUrls;
68777
69079
  const missingEndpoints = scenario.config.twins.filter((name) => {
68778
- const endpoint = endpointRoots[name];
69080
+ const endpoint = serverEndpoints[name];
68779
69081
  return typeof endpoint !== "string" || endpoint.trim().length === 0;
68780
69082
  });
69083
+ let endpointRoots;
69084
+ let apiBaseUrls;
69085
+ if (missingEndpoints.length === 0) {
69086
+ endpointRoots = serverEndpoints;
69087
+ apiBaseUrls = serverApiBaseUrls;
69088
+ } else {
69089
+ const runtimeBase = getConfiguredRuntimeBaseUrl2();
69090
+ if (runtimeBase) {
69091
+ const runtimeUrls = buildRuntimeTwinUrls(
69092
+ ctx.backendSessionId,
69093
+ scenario.config.twins,
69094
+ runtimeBase
69095
+ );
69096
+ endpointRoots = runtimeUrls.endpoints;
69097
+ apiBaseUrls = runtimeUrls.apiBaseUrls;
69098
+ } else {
69099
+ endpointRoots = serverEndpoints;
69100
+ apiBaseUrls = serverApiBaseUrls;
69101
+ }
69102
+ }
68781
69103
  if (missingEndpoints.length > 0) {
68782
69104
  ctx.runFailureMessage = `Twin provisioning failed for: ${missingEndpoints.join(", ")}. Try again or run: archal doctor`;
68783
69105
  }
@@ -68788,7 +69110,7 @@ async function executeRunForScenario(scenarioArg, opts, command, configDefaults)
68788
69110
  hostedApiBaseUrlOverrides = apiBaseUrls;
68789
69111
  }
68790
69112
  if (!ctx.runFailureMessage && engine.mode === "api" && !engine.twinUrlsPath) {
68791
- ctx.generatedTwinUrlMapPath = (0, import_node_path23.resolve)(
69113
+ ctx.generatedTwinUrlMapPath = (0, import_node_path24.resolve)(
68792
69114
  `.archal-session-${ctx.backendSessionId}-engine-twin-urls.json`
68793
69115
  );
68794
69116
  const result = writeTempJsonMap(ctx.generatedTwinUrlMapPath, endpointRoots, "engine twin URL map");
@@ -68981,8 +69303,8 @@ async function executeRunForScenario(scenarioArg, opts, command, configDefaults)
68981
69303
  process.stderr.write(`Warning: failed to build trace payload: ${errorMessage(traceErr)}
68982
69304
  `);
68983
69305
  }
68984
- (0, import_node_fs27.mkdirSync)((0, import_node_path23.dirname)(ctx.evidenceOutputPath), { recursive: true });
68985
- (0, import_node_fs27.writeFileSync)(
69306
+ (0, import_node_fs28.mkdirSync)((0, import_node_path24.dirname)(ctx.evidenceOutputPath), { recursive: true });
69307
+ (0, import_node_fs28.writeFileSync)(
68986
69308
  ctx.evidenceOutputPath,
68987
69309
  JSON.stringify({
68988
69310
  sessionId: ctx.backendSessionId ?? null,
@@ -69036,7 +69358,23 @@ function createRunCommand() {
69036
69358
  throw new CliUsageError("--twin requires --task.");
69037
69359
  }
69038
69360
  const { loadArchalFile: loadArchalFile2 } = await Promise.resolve().then(() => (init_archal_file(), archal_file_exports));
69039
- const archalFile = loadArchalFile2(opts["config"]);
69361
+ let archalFile = loadArchalFile2(opts["config"]);
69362
+ if (!archalFile && opts.task) {
69363
+ try {
69364
+ const { detectTwinsFromHarnessDir: detectTwinsFromHarnessDir2 } = await Promise.resolve().then(() => (init_harness_import_detector(), harness_import_detector_exports));
69365
+ const detected = detectTwinsFromHarnessDir2(process.cwd());
69366
+ if (detected.length > 0) {
69367
+ const { writeFileSync: writeFileSync_ } = await import("fs");
69368
+ const { resolve: resolvePath } = await import("path");
69369
+ const generatedConfig = { twins: detected };
69370
+ const configPath = resolvePath(process.cwd(), ".archal.json");
69371
+ writeFileSync_(configPath, JSON.stringify(generatedConfig, null, 2) + "\n", "utf-8");
69372
+ info("Created .archal.json with detected twins: " + detected.join(", "));
69373
+ archalFile = loadArchalFile2();
69374
+ }
69375
+ } catch {
69376
+ }
69377
+ }
69040
69378
  const scenariosToRun = scenarioArg?.trim() ? [scenarioArg] : [];
69041
69379
  if (archalFile) {
69042
69380
  const { config: af, configDir } = archalFile;
@@ -69071,7 +69409,7 @@ function createRunCommand() {
69071
69409
  const seedOverrides = {};
69072
69410
  for (const [twinName, seedPath] of Object.entries(af.seeds)) {
69073
69411
  const resolvedSeedPath = resolvePath(configDir, seedPath);
69074
- const seedExt = (0, import_node_path23.extname)(resolvedSeedPath).toLowerCase();
69412
+ const seedExt = (0, import_node_path24.extname)(resolvedSeedPath).toLowerCase();
69075
69413
  if (seedExt === ".json" || seedExt === ".md") {
69076
69414
  fileSeedPaths[twinName] = resolvedSeedPath;
69077
69415
  } else {
@@ -69129,7 +69467,7 @@ function createRunCommand() {
69129
69467
  }
69130
69468
  if (scenariosToRun.length === 0) {
69131
69469
  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'
69470
+ '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
69471
  );
69134
69472
  }
69135
69473
  const tempManifestPath = opts["_tempManifestPath"];
@@ -69593,8 +69931,8 @@ ${CYAN2}${BOLD2}Archal CLI${RESET2} ${DIM2}v${CLI_VERSION}${RESET2}
69593
69931
  }
69594
69932
 
69595
69933
  // src/commands/scenario.ts
69596
- var import_node_fs28 = require("fs");
69597
- var import_node_path24 = require("path");
69934
+ var import_node_fs29 = require("fs");
69935
+ var import_node_path25 = require("path");
69598
69936
  init_logger();
69599
69937
  function listScenarios(opts) {
69600
69938
  const tagFilter = opts.tag?.toLowerCase();
@@ -69603,7 +69941,7 @@ function listScenarios(opts) {
69603
69941
  const rows = [];
69604
69942
  const localResolution = findLocalScenariosDir();
69605
69943
  const localDir = localResolution.dir;
69606
- const localDirExists = (0, import_node_fs28.existsSync)(localDir);
69944
+ const localDirExists = (0, import_node_fs29.existsSync)(localDir);
69607
69945
  if (localDirExists) {
69608
69946
  const localFiles = findScenarioFiles(localDir);
69609
69947
  for (const file2 of localFiles) {
@@ -69614,10 +69952,10 @@ function listScenarios(opts) {
69614
69952
  if (!scenarioTags.includes(tagFilter)) continue;
69615
69953
  }
69616
69954
  if (difficultyFilter && (scenario.config.difficulty ?? "") !== difficultyFilter) continue;
69617
- const slug = (0, import_node_path24.basename)(file2, ".md");
69955
+ const slug = (0, import_node_path25.basename)(file2, ".md");
69618
69956
  rows.push([scenario.title, slug, scenario.config.twins.join(", ") || "(auto)"]);
69619
69957
  } catch {
69620
- const slug = (0, import_node_path24.basename)(file2, ".md");
69958
+ const slug = (0, import_node_path25.basename)(file2, ".md");
69621
69959
  rows.push(["(parse error)", slug, "-"]);
69622
69960
  }
69623
69961
  }
@@ -69658,35 +69996,35 @@ function createScenarioCommand() {
69658
69996
  }
69659
69997
 
69660
69998
  // src/commands/twin.ts
69661
- var import_node_fs30 = require("fs");
69999
+ var import_node_fs31 = require("fs");
69662
70000
  init_auth();
69663
70001
  init_api_client();
69664
70002
  init_errors4();
69665
70003
 
69666
70004
  // 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");
70005
+ var import_node_fs30 = require("fs");
70006
+ var import_node_os9 = require("os");
70007
+ var import_node_path26 = require("path");
70008
+ var TWIN_SESSION_FILE2 = (0, import_node_path26.join)((0, import_node_os9.homedir)(), ".archal", "twin-session.json");
70009
+ var LEGACY_SESSION_FILE2 = (0, import_node_path26.join)((0, import_node_os9.homedir)(), ".archal", "env-session.json");
69672
70010
  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));
70011
+ (0, import_node_fs30.mkdirSync)((0, import_node_path26.join)((0, import_node_os9.homedir)(), ".archal"), { recursive: true });
70012
+ (0, import_node_fs30.writeFileSync)(TWIN_SESSION_FILE2, JSON.stringify(session, null, 2));
69675
70013
  }
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;
70014
+ function loadSession2() {
70015
+ let filePath = TWIN_SESSION_FILE2;
70016
+ if (!(0, import_node_fs30.existsSync)(filePath) && (0, import_node_fs30.existsSync)(LEGACY_SESSION_FILE2)) {
70017
+ filePath = LEGACY_SESSION_FILE2;
69680
70018
  }
69681
- if (!(0, import_node_fs29.existsSync)(filePath)) {
70019
+ if (!(0, import_node_fs30.existsSync)(filePath)) {
69682
70020
  return null;
69683
70021
  }
69684
70022
  try {
69685
- const session = JSON.parse((0, import_node_fs29.readFileSync)(filePath, "utf8"));
69686
- if (filePath === LEGACY_SESSION_FILE) {
70023
+ const session = JSON.parse((0, import_node_fs30.readFileSync)(filePath, "utf8"));
70024
+ if (filePath === LEGACY_SESSION_FILE2) {
69687
70025
  saveSession(session);
69688
70026
  try {
69689
- (0, import_node_fs29.rmSync)(LEGACY_SESSION_FILE);
70027
+ (0, import_node_fs30.rmSync)(LEGACY_SESSION_FILE2);
69690
70028
  } catch {
69691
70029
  }
69692
70030
  }
@@ -69697,11 +70035,11 @@ function loadSession() {
69697
70035
  }
69698
70036
  function clearSession() {
69699
70037
  try {
69700
- (0, import_node_fs29.rmSync)(TWIN_SESSION_FILE);
70038
+ (0, import_node_fs30.rmSync)(TWIN_SESSION_FILE2);
69701
70039
  } catch {
69702
70040
  }
69703
70041
  try {
69704
- (0, import_node_fs29.rmSync)(LEGACY_SESSION_FILE);
70042
+ (0, import_node_fs30.rmSync)(LEGACY_SESSION_FILE2);
69705
70043
  } catch {
69706
70044
  }
69707
70045
  }
@@ -69830,11 +70168,13 @@ async function pollUntilReady(sessionId, twins, token) {
69830
70168
  }
69831
70169
  const status = result.data;
69832
70170
  if (status.status === "ready") {
70171
+ const endpoints = status.endpoints ?? {};
70172
+ const apiBaseUrls = status.apiBaseUrls ?? {};
69833
70173
  const saved = {
69834
70174
  sessionId,
69835
70175
  twins,
69836
- endpoints: status.endpoints ?? {},
69837
- apiBaseUrls: status.apiBaseUrls ?? {},
70176
+ endpoints,
70177
+ apiBaseUrls,
69838
70178
  createdAt: status.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
69839
70179
  };
69840
70180
  saveSession(saved);
@@ -69850,7 +70190,7 @@ async function pollUntilReady(sessionId, twins, token) {
69850
70190
  throw new CliRuntimeError("Timed out waiting for twins to start.");
69851
70191
  }
69852
70192
  async function loadSeedFile(session, twin, seedFile, token) {
69853
- const content = (0, import_node_fs30.readFileSync)(seedFile, "utf8");
70193
+ const content = (0, import_node_fs31.readFileSync)(seedFile, "utf8");
69854
70194
  if (content.length > MAX_SETUP_FILE_SIZE) {
69855
70195
  throw new CliUsageError(
69856
70196
  `Seed file too large (${content.length} bytes, max ${MAX_SETUP_FILE_SIZE}). Split the seed or reduce its size.`
@@ -69885,7 +70225,7 @@ async function loadSeedFile(session, twin, seedFile, token) {
69885
70225
  }
69886
70226
  function readSetupFile(filePath) {
69887
70227
  try {
69888
- const content = (0, import_node_fs30.readFileSync)(filePath, "utf-8").trim();
70228
+ const content = (0, import_node_fs31.readFileSync)(filePath, "utf-8").trim();
69889
70229
  if (content.length > MAX_SETUP_FILE_SIZE) {
69890
70230
  throw new CliUsageError(
69891
70231
  `Setup file too large (${content.length} bytes, max ${MAX_SETUP_FILE_SIZE}). Use --seed-file for large seeds.`
@@ -69944,7 +70284,7 @@ function createTwinCommand() {
69944
70284
  await listTwinCatalog2();
69945
70285
  });
69946
70286
  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();
70287
+ const existing = loadSession2();
69948
70288
  if (existing) {
69949
70289
  throw new CliRuntimeError(
69950
70290
  `Active session found: ${existing.sessionId}
@@ -69962,14 +70302,15 @@ Run 'archal twin stop' first, or 'archal twin status' to inspect it.`
69962
70302
  const createResult = await startSession(token, {
69963
70303
  twins: requestedTwins,
69964
70304
  seeds,
69965
- ttlSeconds: opts.ttlSeconds ? toPositiveInteger2(opts.ttlSeconds, "--ttl-seconds") : void 0
70305
+ ttlSeconds: opts.ttlSeconds ? toPositiveInteger2(opts.ttlSeconds, "--ttl-seconds") : void 0,
70306
+ source: "twin-start"
69966
70307
  });
69967
70308
  const response = unwrapApiResult(createResult, "Failed to create twin session");
69968
70309
  process.stderr.write(`${DIM3}Session ${response.sessionId} created. Waiting for twins to start...${RESET3}
69969
70310
  `);
69970
70311
  const ready = await pollUntilReady(response.sessionId, requestedTwins, token);
69971
70312
  if (ready.status === "ready") {
69972
- const saved = loadSession();
70313
+ const saved = loadSession2();
69973
70314
  if (saved) {
69974
70315
  await loadCustomSeedIfRequested(saved, requestedTwins, opts, token);
69975
70316
  }
@@ -69977,7 +70318,7 @@ Run 'archal twin stop' first, or 'archal twin status' to inspect it.`
69977
70318
  });
69978
70319
  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
70320
  const token = requireToken();
69980
- const saved = loadSession();
70321
+ const saved = loadSession2();
69981
70322
  if (!saved) {
69982
70323
  process.stderr.write(`${DIM3}No active twin session. Run 'archal twin start github' to start one.${RESET3}
69983
70324
  `);
@@ -70028,7 +70369,7 @@ ${BOLD3}Twin Session: ${saved.sessionId}${RESET3}
70028
70369
  process.stderr.write("\n");
70029
70370
  });
70030
70371
  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();
70372
+ const saved = loadSession2();
70032
70373
  if (!saved) {
70033
70374
  if (opts.json) {
70034
70375
  process.stdout.write(`${JSON.stringify({ sessions: [] }, null, 2)}
@@ -70072,11 +70413,14 @@ ${BOLD3}Active Twin Sessions${RESET3}
70072
70413
  const token = requireToken();
70073
70414
  const result = await getSessionStatus(token, sessionId);
70074
70415
  const response = unwrapApiResult(result, "Failed to attach twin session");
70416
+ const attachedTwins = response.twinIds ?? [];
70417
+ const attachEndpoints = response.endpoints ?? {};
70418
+ const attachApiBaseUrls = response.apiBaseUrls ?? {};
70075
70419
  saveSession({
70076
70420
  sessionId,
70077
- twins: response.twinIds ?? [],
70078
- endpoints: response.endpoints ?? {},
70079
- apiBaseUrls: response.apiBaseUrls ?? {},
70421
+ twins: attachedTwins,
70422
+ endpoints: attachEndpoints,
70423
+ apiBaseUrls: attachApiBaseUrls,
70080
70424
  createdAt: response.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
70081
70425
  });
70082
70426
  process.stderr.write(`${GREEN2}Attached${RESET3} ${sessionId}
@@ -70084,7 +70428,7 @@ ${BOLD3}Active Twin Sessions${RESET3}
70084
70428
  });
70085
70429
  command.command("renew").argument("[ttl-seconds]", "Requested additional lifetime in seconds").description("Extend the active twin session lifetime").action(async (ttlSeconds) => {
70086
70430
  const token = requireToken();
70087
- const saved = loadSession();
70431
+ const saved = loadSession2();
70088
70432
  if (!saved) {
70089
70433
  throw new CliRuntimeError("No active twin session.");
70090
70434
  }
@@ -70098,7 +70442,7 @@ ${BOLD3}Active Twin Sessions${RESET3}
70098
70442
  });
70099
70443
  command.command("stop").description("Tear down the active twin session").action(async () => {
70100
70444
  const token = requireToken();
70101
- const saved = loadSession();
70445
+ const saved = loadSession2();
70102
70446
  if (!saved) {
70103
70447
  process.stderr.write(`${DIM3}No active twin session.${RESET3}
70104
70448
  `);
@@ -70130,7 +70474,7 @@ ${BOLD3}Active Twin Sessions${RESET3}
70130
70474
  });
70131
70475
  command.command("reset").argument("[twin]", "Twin to reset, or all session twins if omitted").description("Reset twin state to clean").action(async (twin) => {
70132
70476
  const token = requireToken();
70133
- const saved = loadSession();
70477
+ const saved = loadSession2();
70134
70478
  if (!saved) {
70135
70479
  throw new CliRuntimeError("No active twin session.");
70136
70480
  }
@@ -70171,7 +70515,7 @@ ${BOLD3}Active Twin Sessions${RESET3}
70171
70515
  });
70172
70516
  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
70517
  const token = requireToken();
70174
- const saved = loadSession();
70518
+ const saved = loadSession2();
70175
70519
  if (!saved) {
70176
70520
  throw new CliRuntimeError("No active twin session.");
70177
70521
  }
@@ -70205,8 +70549,9 @@ ${BOLD3}Active Twin Sessions${RESET3}
70205
70549
  // src/commands/trace.ts
70206
70550
  init_dist2();
70207
70551
  init_require_auth();
70552
+ init_auth();
70208
70553
  async function fetchTraces(token, limit = 20) {
70209
- const baseUrl = process.env["ARCHAL_API_URL"] ?? process.env["ARCHAL_AUTH_URL"] ?? "https://www.archal.ai";
70554
+ const baseUrl = getConfiguredApiBaseUrl2() ?? "https://www.archal.ai";
70210
70555
  const res = await fetch(`${baseUrl}/api/traces?limit=${limit}`, {
70211
70556
  headers: { authorization: `Bearer ${token}` }
70212
70557
  });
@@ -70217,7 +70562,7 @@ async function fetchTraces(token, limit = 20) {
70217
70562
  return body.traces ?? [];
70218
70563
  }
70219
70564
  async function fetchTraceDetail(token, rootTraceId) {
70220
- const baseUrl = process.env["ARCHAL_API_URL"] ?? process.env["ARCHAL_AUTH_URL"] ?? "https://www.archal.ai";
70565
+ const baseUrl = getConfiguredApiBaseUrl2() ?? "https://www.archal.ai";
70221
70566
  const res = await fetch(`${baseUrl}/api/traces/${encodeURIComponent(rootTraceId)}`, {
70222
70567
  headers: { authorization: `Bearer ${token}` }
70223
70568
  });