@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.
- package/dist/index.cjs +835 -490
- 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
|
|
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 =
|
|
2218
|
+
const localBin = path2.resolve(baseDir, baseName);
|
|
2219
2219
|
if (fs.existsSync(localBin)) return localBin;
|
|
2220
|
-
if (sourceExt.includes(
|
|
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 =
|
|
2239
|
-
|
|
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 =
|
|
2246
|
+
const legacyName = path2.basename(
|
|
2247
2247
|
this._scriptPath,
|
|
2248
|
-
|
|
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(
|
|
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 =
|
|
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(
|
|
3189
|
-
if (
|
|
3190
|
-
this._executableDir =
|
|
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 = [...
|
|
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,
|
|
4366
|
+
constructor(parent, value, path2, key) {
|
|
4367
4367
|
this._cachedPath = [];
|
|
4368
4368
|
this.parent = parent;
|
|
4369
4369
|
this.data = value;
|
|
4370
|
-
this._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,
|
|
7879
|
-
if (!
|
|
7878
|
+
function getElementAtPath(obj, path2) {
|
|
7879
|
+
if (!path2)
|
|
7880
7880
|
return obj;
|
|
7881
|
-
return
|
|
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(
|
|
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(
|
|
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,
|
|
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 = [...
|
|
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
|
|
8483
|
-
for (const seg of
|
|
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
|
|
21327
|
-
if (
|
|
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 (
|
|
21332
|
-
const key =
|
|
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(
|
|
27204
|
-
let input =
|
|
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 [
|
|
27404
|
-
wsComponent.path =
|
|
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,
|
|
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 ${
|
|
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 ${
|
|
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
|
|
31632
|
-
if (!(0, import_fs.existsSync)(
|
|
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)(
|
|
31638
|
-
return buildStoredCredentials(parsed,
|
|
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 ${
|
|
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
|
|
31720
|
-
if (!(0, import_fs.existsSync)(
|
|
31719
|
+
const path2 = getCredentialsPath();
|
|
31720
|
+
if (!(0, import_fs.existsSync)(path2)) {
|
|
31721
31721
|
return false;
|
|
31722
31722
|
}
|
|
31723
|
-
(0, import_fs.unlinkSync)(
|
|
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(
|
|
32937
|
-
const [pathname] =
|
|
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(
|
|
32942
|
-
const [pathname] =
|
|
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,
|
|
33003
|
+
async function request(method, path2, token, body, timeoutOrOptions) {
|
|
32992
33004
|
const options = typeof timeoutOrOptions === "number" ? { timeoutMs: timeoutOrOptions } : timeoutOrOptions ?? {};
|
|
32993
|
-
const baseUrl = resolveBaseUrl(
|
|
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}${
|
|
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(
|
|
33020
|
-
const isIdempotentCreateSession = method === "POST" && isCreateSessionPath(
|
|
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} ${
|
|
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/
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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
|
-
|
|
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
|
|
52420
|
-
const seedsDir =
|
|
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(
|
|
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(
|
|
54399
|
-
if (!(0, import_fs2.existsSync)(
|
|
54400
|
-
const content = (0, import_fs2.readFileSync)(
|
|
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 ${
|
|
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
|
-
`${
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
54513
|
-
const parentDir = (0,
|
|
54514
|
-
const sharedLibDir = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
54691
|
-
const certPath = (0,
|
|
54692
|
-
const keyPath = (0,
|
|
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
|
-
|
|
55127
|
-
|
|
55128
|
-
|
|
55129
|
-
|
|
55158
|
+
let resolved = false;
|
|
55159
|
+
const done = () => {
|
|
55160
|
+
if (!resolved) {
|
|
55161
|
+
resolved = true;
|
|
55162
|
+
clearTimeout(fallback);
|
|
55163
|
+
res();
|
|
55130
55164
|
}
|
|
55131
|
-
}
|
|
55132
|
-
|
|
55133
|
-
|
|
55134
|
-
|
|
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,
|
|
55406
|
-
const target = resolveForwardTarget(targetBaseUrl,
|
|
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
|
|
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,
|
|
55640
|
-
contextDir: (0,
|
|
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,
|
|
55644
|
-
contextDir: (0,
|
|
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,
|
|
55683
|
+
dockerfile: (0, import_path6.resolve)(process.cwd(), "docker/sandbox/Dockerfile"),
|
|
55648
55684
|
contextDir: process.cwd()
|
|
55649
55685
|
},
|
|
55650
55686
|
{
|
|
55651
|
-
dockerfile: (0,
|
|
55652
|
-
contextDir: (0,
|
|
55687
|
+
dockerfile: (0, import_path6.resolve)(moduleDir, "../docker/sandbox/Dockerfile"),
|
|
55688
|
+
contextDir: (0, import_path6.resolve)(moduleDir, "..")
|
|
55653
55689
|
},
|
|
55654
55690
|
{
|
|
55655
|
-
dockerfile: (0,
|
|
55656
|
-
contextDir: (0,
|
|
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,
|
|
55665
|
-
(0,
|
|
55666
|
-
(0,
|
|
55667
|
-
(0,
|
|
55668
|
-
(0,
|
|
55669
|
-
].filter((
|
|
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((
|
|
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,
|
|
55770
|
-
const proxyEventsHostPath = (0,
|
|
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(
|
|
55907
|
+
function readProxyEvents(path2) {
|
|
55872
55908
|
try {
|
|
55873
|
-
const raw = (0, import_fs5.readFileSync)(
|
|
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,
|
|
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,
|
|
56086
|
-
(0, import_fs3.writeFileSync)((0,
|
|
56087
|
-
(0, import_fs3.writeFileSync)((0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
56161
|
-
const runDir = (0, import_fs3.mkdtempSync)((0,
|
|
56162
|
-
const generatedDockerfilePath = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
56426
|
+
const resolvedWorkspace = (0, import_path7.resolve)(workspace);
|
|
56391
56427
|
for (const [relativePath, content] of Object.entries(canaryFiles)) {
|
|
56392
|
-
const filePath = (0,
|
|
56393
|
-
if (filePath !== resolvedWorkspace && !filePath.startsWith(resolvedWorkspace +
|
|
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,
|
|
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,
|
|
56466
|
-
const resolved = (0,
|
|
56467
|
-
if (resolved !== resolvedRoot && !resolved.startsWith(resolvedRoot +
|
|
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,
|
|
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
|
-
|
|
56771
|
+
import_path3 = require("path");
|
|
56736
56772
|
import_fs3 = require("fs");
|
|
56737
56773
|
import_os2 = require("os");
|
|
56738
|
-
|
|
56774
|
+
import_path4 = require("path");
|
|
56739
56775
|
init_dist2();
|
|
56740
56776
|
import_crypto3 = require("crypto");
|
|
56741
56777
|
import_fs4 = require("fs");
|
|
56742
|
-
|
|
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
|
-
|
|
56752
|
-
|
|
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
|
-
|
|
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,
|
|
56826
|
-
if (!(0,
|
|
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,
|
|
56829
|
-
if (!(0,
|
|
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,
|
|
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,
|
|
56899
|
+
return { config: r, configDir: (0, import_node_path22.dirname)(filePath) };
|
|
56864
56900
|
}
|
|
56865
|
-
var
|
|
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
|
-
|
|
56870
|
-
|
|
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,
|
|
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,
|
|
56942
|
-
if (!(0,
|
|
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,
|
|
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,
|
|
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
|
|
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
|
-
|
|
56960
|
-
|
|
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(
|
|
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
|
|
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
|
-
|
|
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
|
|
57100
|
-
var
|
|
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
|
-
//
|
|
57136
|
-
//
|
|
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
|
|
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(
|
|
57460
|
-
if (!
|
|
57461
|
-
if (!(0, import_node_fs4.existsSync)(
|
|
57462
|
-
throw new Error(`${label.fileNotFound}: ${
|
|
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)(
|
|
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 ${
|
|
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 ${
|
|
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(
|
|
57485
|
-
return parseUrlOverridesFile(
|
|
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(
|
|
57492
|
-
return parseUrlOverridesFile(
|
|
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
|
|
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(
|
|
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}
|
|
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 -
|
|
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(
|
|
66563
|
+
function isExecutable(path2) {
|
|
66389
66564
|
try {
|
|
66390
|
-
(0, import_node_fs18.accessSync)(
|
|
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)(
|
|
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
|
|
66679
|
-
var
|
|
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
|
|
66684
|
-
var
|
|
66685
|
-
var
|
|
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,
|
|
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,
|
|
66695
|
-
return (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,
|
|
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,
|
|
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,
|
|
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,
|
|
67495
|
+
let current = (0, import_node_path18.resolve)(start);
|
|
67244
67496
|
while (true) {
|
|
67245
|
-
const candidate = (0,
|
|
67246
|
-
if ((0,
|
|
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,
|
|
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
|
|
67259
|
-
var
|
|
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,
|
|
67815
|
+
if ((0, import_node_fs23.existsSync)(statusPath)) {
|
|
67552
67816
|
try {
|
|
67553
|
-
const raw = (0,
|
|
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,
|
|
67563
|
-
(0,
|
|
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,
|
|
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,
|
|
67870
|
+
if (ctx.generatedTwinUrlMapPath && (0, import_node_fs23.existsSync)(ctx.generatedTwinUrlMapPath)) {
|
|
67592
67871
|
try {
|
|
67593
|
-
(0,
|
|
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,
|
|
67878
|
+
if (ctx.generatedApiBaseUrlMapPath && (0, import_node_fs23.existsSync)(ctx.generatedApiBaseUrlMapPath)) {
|
|
67600
67879
|
try {
|
|
67601
|
-
(0,
|
|
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,
|
|
67693
|
-
(0,
|
|
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
|
|
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
|
|
67873
|
-
var
|
|
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
|
|
67880
|
-
var
|
|
68161
|
+
var import_node_fs24 = require("fs");
|
|
68162
|
+
var import_node_path20 = require("path");
|
|
67881
68163
|
var SCENARIO_DIR_CANDIDATES = [
|
|
67882
|
-
(0,
|
|
67883
|
-
(0,
|
|
67884
|
-
(0,
|
|
67885
|
-
(0,
|
|
67886
|
-
(0,
|
|
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,
|
|
68171
|
+
if (!(0, import_node_fs24.existsSync)(dir)) {
|
|
67890
68172
|
return [];
|
|
67891
68173
|
}
|
|
67892
68174
|
const files = [];
|
|
67893
|
-
const entries = (0,
|
|
68175
|
+
const entries = (0, import_node_fs24.readdirSync)(dir, { withFileTypes: true });
|
|
67894
68176
|
for (const entry of entries) {
|
|
67895
|
-
const fullPath = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
67919
|
-
if ((0,
|
|
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,
|
|
68206
|
+
if (!(0, import_node_fs24.existsSync)(candidate)) {
|
|
67925
68207
|
continue;
|
|
67926
68208
|
}
|
|
67927
|
-
const rootCandidate = (0,
|
|
67928
|
-
if ((0,
|
|
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,
|
|
68078
|
-
if (!(0,
|
|
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,
|
|
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 =
|
|
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,
|
|
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
|
|
68776
|
-
const
|
|
69077
|
+
const serverEndpoints = sessionResult.data.endpoints;
|
|
69078
|
+
const serverApiBaseUrls = sessionResult.data.apiBaseUrls;
|
|
68777
69079
|
const missingEndpoints = scenario.config.twins.filter((name) => {
|
|
68778
|
-
const endpoint =
|
|
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,
|
|
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,
|
|
68985
|
-
(0,
|
|
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
|
-
|
|
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,
|
|
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:
|
|
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
|
|
69597
|
-
var
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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
|
|
69668
|
-
var
|
|
69669
|
-
var
|
|
69670
|
-
var
|
|
69671
|
-
var
|
|
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,
|
|
69674
|
-
(0,
|
|
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
|
|
69677
|
-
let filePath =
|
|
69678
|
-
if (!(0,
|
|
69679
|
-
filePath =
|
|
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,
|
|
70019
|
+
if (!(0, import_node_fs30.existsSync)(filePath)) {
|
|
69682
70020
|
return null;
|
|
69683
70021
|
}
|
|
69684
70022
|
try {
|
|
69685
|
-
const session = JSON.parse((0,
|
|
69686
|
-
if (filePath ===
|
|
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,
|
|
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,
|
|
70038
|
+
(0, import_node_fs30.rmSync)(TWIN_SESSION_FILE2);
|
|
69701
70039
|
} catch {
|
|
69702
70040
|
}
|
|
69703
70041
|
try {
|
|
69704
|
-
(0,
|
|
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
|
|
69837
|
-
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,
|
|
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,
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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:
|
|
70078
|
-
endpoints:
|
|
70079
|
-
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
});
|