archal 0.9.16 → 0.9.18
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/clone-assets/discord/tools.json +1 -1
- package/dist/cli.cjs +799 -267
- package/dist/index.cjs +1 -1
- package/dist/seed/dynamic-generator.cjs +351 -21
- package/dist/vitest/{chunk-CJJ32YQF.js → chunk-CTSN67QR.js} +18053 -17674
- package/dist/vitest/{chunk-FU2VLK75.js → chunk-IVXSSEYS.js} +9 -6
- package/dist/vitest/index.cjs +30790 -30408
- package/dist/vitest/index.js +2 -2
- package/dist/vitest/runtime/hosted-session-reaper.cjs +11472 -11380
- package/dist/vitest/runtime/hosted-session-reaper.js +1 -1
- package/dist/vitest/runtime/setup-files.js +2 -2
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -33917,7 +33917,7 @@ var init_generated_catalog = __esm({
|
|
|
33917
33917
|
icon: "AP",
|
|
33918
33918
|
name: "Apify",
|
|
33919
33919
|
description: "Actors, runs, datasets, key-value stores, and request queues.",
|
|
33920
|
-
toolCount:
|
|
33920
|
+
toolCount: 45,
|
|
33921
33921
|
transport: "rest"
|
|
33922
33922
|
},
|
|
33923
33923
|
{
|
|
@@ -33925,7 +33925,7 @@ var init_generated_catalog = __esm({
|
|
|
33925
33925
|
icon: "DC",
|
|
33926
33926
|
name: "Discord",
|
|
33927
33927
|
description: "Guilds, channels, messages, webhooks, threads, commands, and interaction responses.",
|
|
33928
|
-
toolCount:
|
|
33928
|
+
toolCount: 67,
|
|
33929
33929
|
transport: "both"
|
|
33930
33930
|
},
|
|
33931
33931
|
{
|
|
@@ -33941,7 +33941,7 @@ var init_generated_catalog = __esm({
|
|
|
33941
33941
|
icon: "GW",
|
|
33942
33942
|
name: "Google Workspace",
|
|
33943
33943
|
description: "Gmail, Calendar, Drive, Sheets, and Contacts.",
|
|
33944
|
-
toolCount:
|
|
33944
|
+
toolCount: 249,
|
|
33945
33945
|
transport: "both"
|
|
33946
33946
|
},
|
|
33947
33947
|
{
|
|
@@ -34038,7 +34038,7 @@ var init_src2 = __esm({
|
|
|
34038
34038
|
function formatMinutesLabel(minutes) {
|
|
34039
34039
|
return minutes.toLocaleString("en-US");
|
|
34040
34040
|
}
|
|
34041
|
-
var PLAN_MONTHLY_TWIN_MINUTE_LIMITS, PLAN_CONCURRENT_SESSION_LIMITS, FREE_WORKSPACE_MEMBER_LIMIT, PRO_PLAN_PRICE_USD, FREE_MINUTES, PRO_MINUTES, PRO_EVALS_PER_SEAT, PRO_SESSION_MINUTES_PER_SEAT, PRO_MAX_SEATS, FREE_EVALS_PER_MONTH, PLAN_DISPLAY, PLAN_MAX_SESSION_TTL_SECONDS, MAX_ABSOLUTE_SESSION_LIFETIME_SECONDS, LIFETIME_PERIOD_RESETS_AT, SCENARIO_USAGE_WINDOW_DAYS, SCENARIO_USAGE_WINDOW_MS, SCENARIO_USAGE_WINDOW_SECONDS;
|
|
34041
|
+
var PLAN_MONTHLY_TWIN_MINUTE_LIMITS, PLAN_CONCURRENT_SESSION_LIMITS, FREE_WORKSPACE_MEMBER_LIMIT, PRO_PLAN_PRICE_USD, FREE_MINUTES, PRO_MINUTES, PRO_EVALS_PER_SEAT, PRO_SESSION_MINUTES_PER_SEAT, PRO_MAX_SEATS, FREE_EVALS_PER_MONTH, PLAN_DISPLAY, PLAN_MAX_SESSION_TTL_SECONDS, MAX_ABSOLUTE_SESSION_LIFETIME_SECONDS, LIFETIME_PERIOD_RESETS_AT, SCENARIO_USAGE_WINDOW_DAYS, SCENARIO_USAGE_WINDOW_MS, SCENARIO_USAGE_WINDOW_SECONDS, LLM_PRICING_USD_PER_M_TOKENS, LLM_PRICING_FAMILY_RATES;
|
|
34042
34042
|
var init_src3 = __esm({
|
|
34043
34043
|
"../packages/billing-constants/src/index.ts"() {
|
|
34044
34044
|
"use strict";
|
|
@@ -34118,6 +34118,51 @@ var init_src3 = __esm({
|
|
|
34118
34118
|
SCENARIO_USAGE_WINDOW_DAYS = 7;
|
|
34119
34119
|
SCENARIO_USAGE_WINDOW_MS = SCENARIO_USAGE_WINDOW_DAYS * 24 * 60 * 60 * 1e3;
|
|
34120
34120
|
SCENARIO_USAGE_WINDOW_SECONDS = SCENARIO_USAGE_WINDOW_DAYS * 24 * 60 * 60;
|
|
34121
|
+
LLM_PRICING_USD_PER_M_TOKENS = {
|
|
34122
|
+
// Google Gemini (verified 2026-05-05, standard tier <=200K input tokens)
|
|
34123
|
+
"gemini-2.5-pro": { input: 1.25, output: 10 },
|
|
34124
|
+
"gemini-2.5-flash": { input: 0.3, output: 2.5 },
|
|
34125
|
+
// OpenAI flagship text models (verified 2026-05-21, standard short-context tier)
|
|
34126
|
+
"gpt-5.5": { input: 5, output: 30 },
|
|
34127
|
+
"gpt-5.5-pro": { input: 30, output: 180 },
|
|
34128
|
+
"gpt-5.4": { input: 2.5, output: 15 },
|
|
34129
|
+
"gpt-5.4-mini": { input: 0.75, output: 4.5 },
|
|
34130
|
+
"gpt-5.4-nano": { input: 0.2, output: 1.25 },
|
|
34131
|
+
"gpt-5.4-pro": { input: 30, output: 180 },
|
|
34132
|
+
"gpt-4o-mini": { input: 0.15, output: 0.6 },
|
|
34133
|
+
"gpt-4o": { input: 2.5, output: 10 },
|
|
34134
|
+
"gpt-4.1-mini": { input: 0.4, output: 1.6 },
|
|
34135
|
+
"gpt-4.1-nano": { input: 0.1, output: 0.4 },
|
|
34136
|
+
"gpt-4.1": { input: 2, output: 8 },
|
|
34137
|
+
// DeepSeek (verified 2026-05-05; legacy names map to v4-flash per vendor)
|
|
34138
|
+
"deepseek-chat": { input: 0.14, output: 0.28 },
|
|
34139
|
+
"deepseek-reasoner": { input: 0.14, output: 0.28 },
|
|
34140
|
+
"deepseek-v4-flash": { input: 0.14, output: 0.28 }
|
|
34141
|
+
};
|
|
34142
|
+
LLM_PRICING_FAMILY_RATES = [
|
|
34143
|
+
{ match: /^gemini-2\.5-pro/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gemini-2.5-pro"] },
|
|
34144
|
+
{ match: /^gemini-2\.5-flash/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gemini-2.5-flash"] },
|
|
34145
|
+
{ match: /^gpt-5\.5-pro/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-5.5-pro"] },
|
|
34146
|
+
{ match: /^gpt-5\.5/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-5.5"] },
|
|
34147
|
+
{ match: /^gpt-5\.4-pro/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-5.4-pro"] },
|
|
34148
|
+
{ match: /^gpt-5\.4-mini/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-5.4-mini"] },
|
|
34149
|
+
{ match: /^gpt-5\.4-nano/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-5.4-nano"] },
|
|
34150
|
+
{ match: /^gpt-5\.4/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-5.4"] },
|
|
34151
|
+
{ match: /^gpt-4o-mini/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-4o-mini"] },
|
|
34152
|
+
{ match: /^gpt-4o(?!-mini)/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-4o"] },
|
|
34153
|
+
{ match: /^gpt-4\.1-mini/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-4.1-mini"] },
|
|
34154
|
+
{ match: /^gpt-4\.1-nano/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-4.1-nano"] },
|
|
34155
|
+
{ match: /^gpt-4\.1(?!-mini|-nano)/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-4.1"] },
|
|
34156
|
+
{ match: /^claude-opus-/i, rate: { input: 15, output: 75 } },
|
|
34157
|
+
{ match: /^claude-haiku-/i, rate: { input: 0.8, output: 4 } },
|
|
34158
|
+
{ match: /^claude-sonnet-/i, rate: { input: 3, output: 15 } },
|
|
34159
|
+
{ match: /^opus-/i, rate: { input: 15, output: 75 } },
|
|
34160
|
+
{ match: /^haiku-/i, rate: { input: 0.8, output: 4 } },
|
|
34161
|
+
{ match: /^sonnet-/i, rate: { input: 3, output: 15 } },
|
|
34162
|
+
{ match: /^deepseek-chat/i, rate: LLM_PRICING_USD_PER_M_TOKENS["deepseek-chat"] },
|
|
34163
|
+
{ match: /^deepseek-reasoner/i, rate: LLM_PRICING_USD_PER_M_TOKENS["deepseek-reasoner"] },
|
|
34164
|
+
{ match: /^deepseek-v4-flash/i, rate: LLM_PRICING_USD_PER_M_TOKENS["deepseek-v4-flash"] }
|
|
34165
|
+
];
|
|
34121
34166
|
}
|
|
34122
34167
|
});
|
|
34123
34168
|
|
|
@@ -41904,7 +41949,7 @@ function buildCodegenUserPrompt(twinName, setupDescription) {
|
|
|
41904
41949
|
const declarations = SDK_DECLARATIONS[twinName];
|
|
41905
41950
|
const example = SDK_EXAMPLES[twinName];
|
|
41906
41951
|
if (!declarations) {
|
|
41907
|
-
return `
|
|
41952
|
+
return `Clone: ${twinName}
|
|
41908
41953
|
|
|
41909
41954
|
Setup:
|
|
41910
41955
|
${setupDescription}
|
|
@@ -41925,7 +41970,7 @@ ${example.code}
|
|
|
41925
41970
|
`;
|
|
41926
41971
|
}
|
|
41927
41972
|
prompt += `## Task
|
|
41928
|
-
|
|
41973
|
+
Clone: ${twinName}
|
|
41929
41974
|
|
|
41930
41975
|
Setup:
|
|
41931
41976
|
${setupDescription}
|
|
@@ -41951,7 +41996,7 @@ ${originalCode}
|
|
|
41951
41996
|
Fix the code and output ONLY the corrected JavaScript. No explanations.`;
|
|
41952
41997
|
}
|
|
41953
41998
|
function buildSimplifiedCodegenPrompt(twinName, setupDescription) {
|
|
41954
|
-
return `Create seed data for the "${twinName}"
|
|
41999
|
+
return `Create seed data for the "${twinName}" clone.
|
|
41955
42000
|
|
|
41956
42001
|
Use ONLY these core functions (they are already defined globally):
|
|
41957
42002
|
createUser(login), createRepo/createProject/createChannel/createCustomer(name),
|
|
@@ -44428,7 +44473,7 @@ var init_seed_llm = __esm({
|
|
|
44428
44473
|
|
|
44429
44474
|
// ../packages/seedgen/src/codegen/seed-plan.ts
|
|
44430
44475
|
function buildPlanPrompt(twinName, setupDescription) {
|
|
44431
|
-
return `
|
|
44476
|
+
return `Clone: ${twinName}
|
|
44432
44477
|
|
|
44433
44478
|
Setup:
|
|
44434
44479
|
${setupDescription}`;
|
|
@@ -50845,6 +50890,222 @@ var init_cache = __esm({
|
|
|
50845
50890
|
});
|
|
50846
50891
|
|
|
50847
50892
|
// ../packages/seedgen/src/runner/seed/supabase-sql-seed.ts
|
|
50893
|
+
function sqlLiteral2(value) {
|
|
50894
|
+
if (value === null || value === void 0) return "NULL";
|
|
50895
|
+
if (typeof value === "number") return Number.isFinite(value) ? String(value) : "NULL";
|
|
50896
|
+
if (typeof value === "boolean") return value ? "TRUE" : "FALSE";
|
|
50897
|
+
return `'${String(value).replace(/'/g, "''")}'`;
|
|
50898
|
+
}
|
|
50899
|
+
function sqlIdent2(value) {
|
|
50900
|
+
if (!value) throw new Error("SQL identifier must not be empty");
|
|
50901
|
+
if (value.includes("\0")) throw new Error("SQL identifier must not contain null bytes");
|
|
50902
|
+
return `"${value.replace(/"/g, '""')}"`;
|
|
50903
|
+
}
|
|
50904
|
+
function sqlValueLiteral(value, columnType) {
|
|
50905
|
+
const type = columnType?.toLowerCase() ?? "";
|
|
50906
|
+
if (Array.isArray(value)) {
|
|
50907
|
+
if (type.includes("[]")) {
|
|
50908
|
+
const baseType = type.replace(/\[\].*$/, "") || "text";
|
|
50909
|
+
if (value.length === 0) return `ARRAY[]::${baseType}[]`;
|
|
50910
|
+
return `ARRAY[${value.map(sqlLiteral2).join(", ")}]`;
|
|
50911
|
+
}
|
|
50912
|
+
const json2 = sqlLiteral2(JSON.stringify(value));
|
|
50913
|
+
if (type.includes("jsonb")) return `${json2}::jsonb`;
|
|
50914
|
+
if (type.includes("json")) return `${json2}::json`;
|
|
50915
|
+
return json2;
|
|
50916
|
+
}
|
|
50917
|
+
if (value && typeof value === "object") {
|
|
50918
|
+
const json2 = sqlLiteral2(JSON.stringify(value));
|
|
50919
|
+
if (type.includes("jsonb")) return `${json2}::jsonb`;
|
|
50920
|
+
if (type.includes("json")) return `${json2}::json`;
|
|
50921
|
+
return json2;
|
|
50922
|
+
}
|
|
50923
|
+
return sqlLiteral2(value);
|
|
50924
|
+
}
|
|
50925
|
+
function splitSqlTopLevel(input, separator) {
|
|
50926
|
+
const parts = [];
|
|
50927
|
+
let depth = 0;
|
|
50928
|
+
let bracketDepth = 0;
|
|
50929
|
+
let inQuote = false;
|
|
50930
|
+
let start = 0;
|
|
50931
|
+
for (let i = 0; i < input.length; i++) {
|
|
50932
|
+
const ch = input[i];
|
|
50933
|
+
if (ch === void 0) continue;
|
|
50934
|
+
const next = i + 1 < input.length ? input[i + 1] : void 0;
|
|
50935
|
+
if (ch === "'") {
|
|
50936
|
+
if (inQuote && next === "'") {
|
|
50937
|
+
i += 1;
|
|
50938
|
+
continue;
|
|
50939
|
+
}
|
|
50940
|
+
inQuote = !inQuote;
|
|
50941
|
+
continue;
|
|
50942
|
+
}
|
|
50943
|
+
if (inQuote) continue;
|
|
50944
|
+
if (ch === "(") depth += 1;
|
|
50945
|
+
else if (ch === ")") depth = Math.max(0, depth - 1);
|
|
50946
|
+
else if (ch === "[") bracketDepth += 1;
|
|
50947
|
+
else if (ch === "]") bracketDepth = Math.max(0, bracketDepth - 1);
|
|
50948
|
+
if (depth === 0 && bracketDepth === 0 && ch === separator) {
|
|
50949
|
+
parts.push(input.slice(start, i).trim());
|
|
50950
|
+
start = i + 1;
|
|
50951
|
+
}
|
|
50952
|
+
}
|
|
50953
|
+
const tail = input.slice(start).trim();
|
|
50954
|
+
if (tail) parts.push(tail);
|
|
50955
|
+
return parts;
|
|
50956
|
+
}
|
|
50957
|
+
function splitSqlStatements(sql) {
|
|
50958
|
+
return splitSqlTopLevel(sql, ";").map((statement) => statement.trim()).filter(Boolean);
|
|
50959
|
+
}
|
|
50960
|
+
function normalizeSqlIdentifier(raw) {
|
|
50961
|
+
const parts = raw.split(".").map((part) => part.trim().replace(/^"|"$/g, "").replace(/""/g, '"')).filter(Boolean);
|
|
50962
|
+
return parts[parts.length - 1] ?? raw.trim();
|
|
50963
|
+
}
|
|
50964
|
+
function collectTableSchemas(sql) {
|
|
50965
|
+
const tableSchemas = /* @__PURE__ */ new Map();
|
|
50966
|
+
for (const statement of splitSqlStatements(sql)) {
|
|
50967
|
+
const match = statement.match(
|
|
50968
|
+
/^CREATE\s+TABLE(?:\s+IF\s+NOT\s+EXISTS)?\s+([^\s(]+)\s*\(([\s\S]*)\)$/i
|
|
50969
|
+
);
|
|
50970
|
+
if (!match?.[1] || !match[2]) continue;
|
|
50971
|
+
const columnTypes = /* @__PURE__ */ new Map();
|
|
50972
|
+
const columnOrder = [];
|
|
50973
|
+
for (const columnDef of splitSqlTopLevel(match[2], ",")) {
|
|
50974
|
+
const columnMatch = columnDef.trim().match(/^("(?:""|[^"])+"|[a-zA-Z_][a-zA-Z0-9_]*)\s+([a-zA-Z0-9_."[\]]+)/);
|
|
50975
|
+
if (!columnMatch?.[1] || !columnMatch[2]) continue;
|
|
50976
|
+
const columnName = normalizeSqlIdentifier(columnMatch[1]);
|
|
50977
|
+
columnTypes.set(columnName, columnMatch[2].toLowerCase());
|
|
50978
|
+
columnOrder.push(columnName);
|
|
50979
|
+
}
|
|
50980
|
+
tableSchemas.set(normalizeSqlIdentifier(match[1]), { columnTypes, columnOrder });
|
|
50981
|
+
}
|
|
50982
|
+
return tableSchemas;
|
|
50983
|
+
}
|
|
50984
|
+
function normalizeJsonArrayLiteral(value, columnType) {
|
|
50985
|
+
const trimmed = value.trim();
|
|
50986
|
+
if (!trimmed.startsWith("[") || !trimmed.endsWith("]")) return value;
|
|
50987
|
+
let parsed;
|
|
50988
|
+
try {
|
|
50989
|
+
parsed = JSON.parse(trimmed);
|
|
50990
|
+
} catch {
|
|
50991
|
+
return value;
|
|
50992
|
+
}
|
|
50993
|
+
if (!Array.isArray(parsed)) return value;
|
|
50994
|
+
const type = columnType?.toLowerCase() ?? "";
|
|
50995
|
+
if (type.includes("[]")) {
|
|
50996
|
+
const baseType = type.replace(/\[\].*$/, "") || "text";
|
|
50997
|
+
if (parsed.length === 0) return `ARRAY[]::${baseType}[]`;
|
|
50998
|
+
return `ARRAY[${parsed.map(sqlLiteral2).join(", ")}]`;
|
|
50999
|
+
}
|
|
51000
|
+
const json2 = sqlLiteral2(JSON.stringify(parsed));
|
|
51001
|
+
if (type.includes("jsonb")) return `${json2}::jsonb`;
|
|
51002
|
+
if (type.includes("json")) return `${json2}::json`;
|
|
51003
|
+
return json2;
|
|
51004
|
+
}
|
|
51005
|
+
function renderStructuredTableSql(value) {
|
|
51006
|
+
const tables = Array.isArray(value) ? value : value && typeof value === "object" && Array.isArray(value["tables"]) ? value["tables"] : null;
|
|
51007
|
+
if (!Array.isArray(tables)) return null;
|
|
51008
|
+
const statements = [];
|
|
51009
|
+
for (const table2 of tables) {
|
|
51010
|
+
if (!table2 || typeof table2 !== "object") return null;
|
|
51011
|
+
const record2 = table2;
|
|
51012
|
+
const tableName = typeof record2["name"] === "string" ? record2["name"] : void 0;
|
|
51013
|
+
const columns = Array.isArray(record2["columns"]) ? record2["columns"] : void 0;
|
|
51014
|
+
if (!tableName || !columns) return null;
|
|
51015
|
+
const columnTypes = /* @__PURE__ */ new Map();
|
|
51016
|
+
const columnDefinitions = columns.map((column) => {
|
|
51017
|
+
if (!column || typeof column !== "object") throw new Error("invalid column");
|
|
51018
|
+
const columnRecord = column;
|
|
51019
|
+
const name = typeof columnRecord["name"] === "string" ? columnRecord["name"] : void 0;
|
|
51020
|
+
const rawType = typeof columnRecord["type"] === "string" ? columnRecord["type"] : "text";
|
|
51021
|
+
if (!name) throw new Error("invalid column name");
|
|
51022
|
+
const isPrimary = columnRecord["is_primary"] === true || columnRecord["primary"] === true;
|
|
51023
|
+
const type = isPrimary && /^(bigint|int|integer|serial|bigserial)$/i.test(rawType) ? "bigserial" : rawType;
|
|
51024
|
+
columnTypes.set(name, type);
|
|
51025
|
+
return `${sqlIdent2(name)} ${type}${isPrimary ? " PRIMARY KEY" : ""}`;
|
|
51026
|
+
});
|
|
51027
|
+
statements.push(`CREATE TABLE IF NOT EXISTS public.${sqlIdent2(tableName)} (${columnDefinitions.join(", ")});`);
|
|
51028
|
+
const rows = Array.isArray(record2["rows"]) ? record2["rows"] : Array.isArray(record2["data"]) ? record2["data"] : [];
|
|
51029
|
+
for (const row of rows) {
|
|
51030
|
+
if (!row || typeof row !== "object") continue;
|
|
51031
|
+
const entries = Object.entries(row).filter(([column]) => columnTypes.has(column));
|
|
51032
|
+
if (entries.length === 0) continue;
|
|
51033
|
+
statements.push(
|
|
51034
|
+
`INSERT INTO public.${sqlIdent2(tableName)} (${entries.map(([column]) => sqlIdent2(column)).join(", ")}) VALUES (${entries.map(([column, rowValue]) => sqlValueLiteral(rowValue, columnTypes.get(column))).join(", ")});`
|
|
51035
|
+
);
|
|
51036
|
+
}
|
|
51037
|
+
}
|
|
51038
|
+
return statements.length > 0 ? statements.join("\n\n") : null;
|
|
51039
|
+
}
|
|
51040
|
+
function normalizeCreateTableStatement(statement) {
|
|
51041
|
+
const match = statement.match(
|
|
51042
|
+
/^(CREATE\s+TABLE(?:\s+IF\s+NOT\s+EXISTS)?\s+[^\s(]+\s*)\(([\s\S]*)\)$/i
|
|
51043
|
+
);
|
|
51044
|
+
if (!match?.[1] || !match[2]) return statement;
|
|
51045
|
+
const columnDefs = splitSqlTopLevel(match[2], ",").map((columnDef) => {
|
|
51046
|
+
const columnMatch = columnDef.trim().match(
|
|
51047
|
+
/^("(?:""|[^"])+"|[a-zA-Z_][a-zA-Z0-9_]*)\s+([a-zA-Z0-9_."[\]]+)([\s\S]*)$/i
|
|
51048
|
+
);
|
|
51049
|
+
if (!columnMatch?.[2] || !columnMatch[3]) return columnDef;
|
|
51050
|
+
const columnType = columnMatch[2].toLowerCase();
|
|
51051
|
+
const rest = columnMatch[3].replace(
|
|
51052
|
+
/\bDEFAULT\s+(\[[\s\S]*?\])(?=\s|,|$)/i,
|
|
51053
|
+
(_full, value) => `DEFAULT ${normalizeJsonArrayLiteral(value, columnType)}`
|
|
51054
|
+
);
|
|
51055
|
+
return `${columnMatch[1]} ${columnMatch[2]}${rest}`;
|
|
51056
|
+
});
|
|
51057
|
+
return `${match[1]}(${columnDefs.join(", ")})`;
|
|
51058
|
+
}
|
|
51059
|
+
function normalizeSupabaseSql(sql) {
|
|
51060
|
+
const tableSchemas = collectTableSchemas(sql);
|
|
51061
|
+
return splitSqlStatements(sql).map((statement) => {
|
|
51062
|
+
if (/^CREATE\s+TABLE/i.test(statement)) return normalizeCreateTableStatement(statement);
|
|
51063
|
+
const match = statement.match(/^INSERT\s+INTO\s+([^\s(]+)\s*\(([^)]+)\)\s*VALUES\s*([\s\S]*)$/i) ?? statement.match(/^INSERT\s+INTO\s+([^\s(]+)\s+VALUES\s*([\s\S]*)$/i);
|
|
51064
|
+
if (!match?.[1]) return statement;
|
|
51065
|
+
const tableName = normalizeSqlIdentifier(match[1]);
|
|
51066
|
+
const hasColumnList = match.length === 4;
|
|
51067
|
+
const valuesSql = hasColumnList ? match[3] : match[2];
|
|
51068
|
+
if (!valuesSql) return statement;
|
|
51069
|
+
const schema = tableSchemas.get(tableName);
|
|
51070
|
+
const columns = hasColumnList ? splitSqlTopLevel(match[2] ?? "", ",").map(normalizeSqlIdentifier) : schema?.columnOrder ?? [];
|
|
51071
|
+
const tuples = [];
|
|
51072
|
+
let depth = 0;
|
|
51073
|
+
let bracketDepth = 0;
|
|
51074
|
+
let inQuote = false;
|
|
51075
|
+
let tupleStart = -1;
|
|
51076
|
+
for (let i = 0; i < valuesSql.length; i++) {
|
|
51077
|
+
const ch = valuesSql[i];
|
|
51078
|
+
if (ch === void 0) continue;
|
|
51079
|
+
const next = i + 1 < valuesSql.length ? valuesSql[i + 1] : void 0;
|
|
51080
|
+
if (ch === "'") {
|
|
51081
|
+
if (inQuote && next === "'") {
|
|
51082
|
+
i += 1;
|
|
51083
|
+
continue;
|
|
51084
|
+
}
|
|
51085
|
+
inQuote = !inQuote;
|
|
51086
|
+
}
|
|
51087
|
+
if (inQuote) continue;
|
|
51088
|
+
if (ch === "[") bracketDepth += 1;
|
|
51089
|
+
else if (ch === "]") bracketDepth = Math.max(0, bracketDepth - 1);
|
|
51090
|
+
else if (ch === "(" && bracketDepth === 0) {
|
|
51091
|
+
if (depth === 0) tupleStart = i + 1;
|
|
51092
|
+
depth += 1;
|
|
51093
|
+
} else if (ch === ")" && bracketDepth === 0) {
|
|
51094
|
+
depth -= 1;
|
|
51095
|
+
if (depth === 0 && tupleStart >= 0) {
|
|
51096
|
+
tuples.push(valuesSql.slice(tupleStart, i));
|
|
51097
|
+
tupleStart = -1;
|
|
51098
|
+
}
|
|
51099
|
+
}
|
|
51100
|
+
}
|
|
51101
|
+
if (tuples.length === 0) return statement;
|
|
51102
|
+
const normalizedTuples = tuples.map((tuple2) => {
|
|
51103
|
+
const values = splitSqlTopLevel(tuple2, ",").map((value, index) => normalizeJsonArrayLiteral(value, schema?.columnTypes.get(columns[index] ?? "")));
|
|
51104
|
+
return `(${values.join(", ")})`;
|
|
51105
|
+
});
|
|
51106
|
+
return hasColumnList ? `INSERT INTO ${match[1]} (${match[2]}) VALUES ${normalizedTuples.join(", ")}` : `INSERT INTO ${match[1]} VALUES ${normalizedTuples.join(", ")}`;
|
|
51107
|
+
}).join(";\n") + ";";
|
|
51108
|
+
}
|
|
50848
51109
|
function extractSupabaseSql(response) {
|
|
50849
51110
|
let sql = response.trim();
|
|
50850
51111
|
if (sql.startsWith("```")) {
|
|
@@ -50853,24 +51114,35 @@ function extractSupabaseSql(response) {
|
|
|
50853
51114
|
if (sql.startsWith("{")) {
|
|
50854
51115
|
try {
|
|
50855
51116
|
const parsed = JSON.parse(sql);
|
|
51117
|
+
const structuredSql = renderStructuredTableSql(parsed);
|
|
51118
|
+
if (structuredSql) return normalizeSupabaseSql(structuredSql);
|
|
50856
51119
|
const extracted = parsed["sql"] ?? parsed["query"] ?? parsed["script"] ?? parsed["content"];
|
|
50857
|
-
if (extracted && typeof extracted === "string") return extracted;
|
|
51120
|
+
if (extracted && typeof extracted === "string") return normalizeSupabaseSql(extracted);
|
|
51121
|
+
} catch {
|
|
51122
|
+
}
|
|
51123
|
+
}
|
|
51124
|
+
if (sql.startsWith('"')) {
|
|
51125
|
+
try {
|
|
51126
|
+
const parsed = JSON.parse(sql);
|
|
51127
|
+
if (typeof parsed === "string") return normalizeSupabaseSql(parsed);
|
|
50858
51128
|
} catch {
|
|
50859
51129
|
}
|
|
50860
51130
|
}
|
|
50861
51131
|
if (sql.startsWith("[")) {
|
|
50862
51132
|
try {
|
|
50863
51133
|
const parsed = JSON.parse(sql);
|
|
51134
|
+
const structuredSql = renderStructuredTableSql(parsed);
|
|
51135
|
+
if (structuredSql) return normalizeSupabaseSql(structuredSql);
|
|
50864
51136
|
const parts = [];
|
|
50865
51137
|
for (const item of parsed) {
|
|
50866
51138
|
const s = item["sql"] ?? item["query"] ?? item["script"];
|
|
50867
51139
|
if (s && typeof s === "string") parts.push(s);
|
|
50868
51140
|
}
|
|
50869
|
-
if (parts.length > 0) return parts.join("\n\n");
|
|
51141
|
+
if (parts.length > 0) return normalizeSupabaseSql(parts.join("\n\n"));
|
|
50870
51142
|
} catch {
|
|
50871
51143
|
}
|
|
50872
51144
|
}
|
|
50873
|
-
return sql;
|
|
51145
|
+
return normalizeSupabaseSql(sql);
|
|
50874
51146
|
}
|
|
50875
51147
|
var SUPABASE_SQL_SYSTEM_PROMPT;
|
|
50876
51148
|
var init_supabase_sql_seed = __esm({
|
|
@@ -50891,6 +51163,8 @@ IMPORTANT CONSTRAINTS:
|
|
|
50891
51163
|
- For RLS policies, use simple expressions like: USING (true) or USING (current_setting('app.user_id')::int = user_id)
|
|
50892
51164
|
- Use serial or bigserial for primary keys, not uuid (unless explicitly asked)
|
|
50893
51165
|
- Use simple types: text, int, boolean, timestamptz
|
|
51166
|
+
- Do NOT use JSON-style array literals like ["a", "b"] in INSERT values.
|
|
51167
|
+
Use ARRAY['a', 'b'] for SQL array columns, or quoted JSON with ::jsonb for jsonb columns.
|
|
50894
51168
|
- Always include INSERT statements with realistic test data
|
|
50895
51169
|
|
|
50896
51170
|
|
|
@@ -51263,7 +51537,7 @@ async function enrichSeedWithLlm(seed, twinName, setupDescription, deadline, coo
|
|
|
51263
51537
|
try {
|
|
51264
51538
|
const response = await callCodegenLlm({
|
|
51265
51539
|
systemPrompt: ENRICH_SYSTEM_PROMPT,
|
|
51266
|
-
userPrompt: `
|
|
51540
|
+
userPrompt: `Clone: ${twinName}
|
|
51267
51541
|
|
|
51268
51542
|
Setup description:
|
|
51269
51543
|
${setupDescription}
|
|
@@ -52473,6 +52747,9 @@ function ensureSlackScenarioChannelAccess(mergedSeed, intent) {
|
|
|
52473
52747
|
}
|
|
52474
52748
|
return mergedSeed;
|
|
52475
52749
|
}
|
|
52750
|
+
function isSyntheticGoogleWorkspaceEmail(email3) {
|
|
52751
|
+
return email3 === GOOGLE_WORKSPACE_SYNTHETIC_EMAIL;
|
|
52752
|
+
}
|
|
52476
52753
|
function googleWorkspaceEmailEntities(intent) {
|
|
52477
52754
|
if (!intent || intent.twinName !== "google-workspace") return [];
|
|
52478
52755
|
return intent.entities.filter((entity) => entity.kind === "email" && entity.key === "address" && typeof entity.value === "string" || entity.kind === "account" && entity.key === "email" && typeof entity.value === "string").map((entity) => normalizedEmail(entity.value)).filter((value) => Boolean(value));
|
|
@@ -52500,6 +52777,32 @@ function googleWorkspaceReferencedEmails(seed) {
|
|
|
52500
52777
|
}
|
|
52501
52778
|
return emails;
|
|
52502
52779
|
}
|
|
52780
|
+
function googleWorkspaceBootstrapEmail(intentEmails, referencedEmails) {
|
|
52781
|
+
return intentEmails.find((email3) => !isSyntheticGoogleWorkspaceEmail(email3)) ?? referencedEmails.find((email3) => !isSyntheticGoogleWorkspaceEmail(email3)) ?? "user@example.com";
|
|
52782
|
+
}
|
|
52783
|
+
function rewriteSyntheticGoogleWorkspaceAccountRefs(seed, email3) {
|
|
52784
|
+
const collections = [
|
|
52785
|
+
"calendars",
|
|
52786
|
+
"calendarEvents",
|
|
52787
|
+
"gmailThreads",
|
|
52788
|
+
"gmailMessages",
|
|
52789
|
+
"gmailDrafts",
|
|
52790
|
+
"gmailAttachments",
|
|
52791
|
+
"gmailHistory",
|
|
52792
|
+
"driveFiles",
|
|
52793
|
+
"contacts",
|
|
52794
|
+
"googleAuthTokens"
|
|
52795
|
+
];
|
|
52796
|
+
for (const collection of collections) {
|
|
52797
|
+
for (const item of seed[collection] ?? []) {
|
|
52798
|
+
const record2 = asRecord(item);
|
|
52799
|
+
if (!record2) continue;
|
|
52800
|
+
if (isSyntheticGoogleWorkspaceEmail(normalizedEmail(record2["accountEmail"]))) {
|
|
52801
|
+
record2["accountEmail"] = email3;
|
|
52802
|
+
}
|
|
52803
|
+
}
|
|
52804
|
+
}
|
|
52805
|
+
}
|
|
52503
52806
|
function googleWorkspaceHasCalendarSurface(intent) {
|
|
52504
52807
|
return intent.extractedSlots["workspace.surface.calendar"] === true || /\b(calendar|event|events|meeting|meetings|invite|invites)\b/i.test(intent.setupSummary);
|
|
52505
52808
|
}
|
|
@@ -52534,6 +52837,15 @@ function ensureGoogleWorkspaceAccount(accounts, email3, primary) {
|
|
|
52534
52837
|
primary
|
|
52535
52838
|
});
|
|
52536
52839
|
}
|
|
52840
|
+
function replaceGoogleWorkspaceAccount(account, email3) {
|
|
52841
|
+
account["accountId"] = "acct_primary";
|
|
52842
|
+
account["email"] = email3;
|
|
52843
|
+
account["displayName"] = "Primary Account";
|
|
52844
|
+
account["givenName"] = "Primary";
|
|
52845
|
+
account["familyName"] = "Account";
|
|
52846
|
+
account["timezone"] = "America/Los_Angeles";
|
|
52847
|
+
account["primary"] = true;
|
|
52848
|
+
}
|
|
52537
52849
|
function ensureGoogleWorkspaceAuthToken(authTokens, email3) {
|
|
52538
52850
|
if (authTokens.some((token) => normalizedEmail(token["accountEmail"]) === email3)) return;
|
|
52539
52851
|
const localPart = email3.split("@")[0] ?? email3;
|
|
@@ -52553,7 +52865,8 @@ function ensureGoogleWorkspaceAuthToken(authTokens, email3) {
|
|
|
52553
52865
|
function ensureGoogleWorkspacePrimaryCalendar(calendars, accountEmail) {
|
|
52554
52866
|
const existingPrimary = calendars.find((calendar) => calendar["calendarId"] === "primary");
|
|
52555
52867
|
if (existingPrimary) {
|
|
52556
|
-
|
|
52868
|
+
const existingEmail = normalizedEmail(existingPrimary["accountEmail"]);
|
|
52869
|
+
existingPrimary["accountEmail"] = !existingEmail || isSyntheticGoogleWorkspaceEmail(existingEmail) ? accountEmail : existingEmail;
|
|
52557
52870
|
existingPrimary["primary"] = true;
|
|
52558
52871
|
return "primary";
|
|
52559
52872
|
}
|
|
@@ -52578,6 +52891,15 @@ function ensureGoogleWorkspaceCalendarRows(mergedSeed) {
|
|
|
52578
52891
|
for (const item of mergedSeed["calendarEvents"] ?? []) {
|
|
52579
52892
|
const event = asRecord(item);
|
|
52580
52893
|
if (!event) continue;
|
|
52894
|
+
if (typeof event["summary"] !== "string") {
|
|
52895
|
+
event["summary"] = "Calendar event";
|
|
52896
|
+
}
|
|
52897
|
+
if (typeof event["description"] !== "string") {
|
|
52898
|
+
event["description"] = "";
|
|
52899
|
+
}
|
|
52900
|
+
if (typeof event["location"] !== "string") {
|
|
52901
|
+
event["location"] = "";
|
|
52902
|
+
}
|
|
52581
52903
|
const calendarId = typeof event["calendarId"] === "string" && event["calendarId"].trim() ? event["calendarId"].trim() : "primary";
|
|
52582
52904
|
const accountEmail = normalizedEmail(event["accountEmail"]) ?? "self@local.invalid";
|
|
52583
52905
|
if (existingCalendarIds.has(calendarId)) continue;
|
|
@@ -52617,21 +52939,28 @@ function ensureGoogleWorkspaceCalendarEvidence(mergedSeed, intent, accountEmail)
|
|
|
52617
52939
|
organizerEmail: accountEmail,
|
|
52618
52940
|
attendeeEmails: [],
|
|
52619
52941
|
conferenceUrl: null,
|
|
52620
|
-
extendedPropertiesShared:
|
|
52942
|
+
extendedPropertiesShared: {}
|
|
52621
52943
|
});
|
|
52622
52944
|
}
|
|
52623
52945
|
function ensureGoogleWorkspaceScenarioAccounts(mergedSeed, intent) {
|
|
52624
52946
|
if (!intent || intent.twinName !== "google-workspace") return mergedSeed;
|
|
52625
52947
|
const accounts = ensureArray(mergedSeed, "accounts");
|
|
52626
52948
|
const authTokens = ensureArray(mergedSeed, "googleAuthTokens");
|
|
52949
|
+
const intentEmails = googleWorkspaceEmailEntities(intent);
|
|
52950
|
+
let referencedEmails = googleWorkspaceReferencedEmails(mergedSeed);
|
|
52951
|
+
const bootstrapEmail = googleWorkspaceBootstrapEmail(intentEmails, referencedEmails);
|
|
52627
52952
|
if (accounts.length === 0) {
|
|
52628
|
-
ensureGoogleWorkspaceAccount(accounts,
|
|
52953
|
+
ensureGoogleWorkspaceAccount(accounts, bootstrapEmail, true);
|
|
52954
|
+
} else if (accounts.length === 1 && isSyntheticGoogleWorkspaceEmail(normalizedEmail(accounts[0]?.["email"]))) {
|
|
52955
|
+
replaceGoogleWorkspaceAccount(accounts[0], bootstrapEmail);
|
|
52629
52956
|
}
|
|
52630
|
-
|
|
52957
|
+
rewriteSyntheticGoogleWorkspaceAccountRefs(mergedSeed, bootstrapEmail);
|
|
52958
|
+
referencedEmails = googleWorkspaceReferencedEmails(mergedSeed);
|
|
52959
|
+
const primaryEmail = normalizedEmail(accounts.find((account) => account["primary"] === true)?.["email"]) ?? normalizedEmail(accounts[0]?.["email"]) ?? GOOGLE_WORKSPACE_SYNTHETIC_EMAIL;
|
|
52631
52960
|
ensureGoogleWorkspaceAuthToken(authTokens, primaryEmail);
|
|
52632
52961
|
const requiredEmails = Array.from(/* @__PURE__ */ new Set([
|
|
52633
|
-
...
|
|
52634
|
-
...
|
|
52962
|
+
...intentEmails,
|
|
52963
|
+
...referencedEmails,
|
|
52635
52964
|
...accounts.map((account) => normalizedEmail(account["email"])).filter((value) => Boolean(value))
|
|
52636
52965
|
]));
|
|
52637
52966
|
for (const email3 of requiredEmails) {
|
|
@@ -52649,7 +52978,7 @@ function applyScenarioCoverageFixups(mergedSeed, intent) {
|
|
|
52649
52978
|
nextSeed = ensureGoogleWorkspaceScenarioAccounts(nextSeed, intent);
|
|
52650
52979
|
return nextSeed;
|
|
52651
52980
|
}
|
|
52652
|
-
var GOOGLE_WORKSPACE_BOOTSTRAP_SCOPES;
|
|
52981
|
+
var GOOGLE_WORKSPACE_BOOTSTRAP_SCOPES, GOOGLE_WORKSPACE_SYNTHETIC_EMAIL;
|
|
52653
52982
|
var init_scenario_coverage_fixups = __esm({
|
|
52654
52983
|
"../packages/seedgen/src/runner/seed/scenario-coverage-fixups.ts"() {
|
|
52655
52984
|
"use strict";
|
|
@@ -52662,6 +52991,7 @@ var init_scenario_coverage_fixups = __esm({
|
|
|
52662
52991
|
"https://www.googleapis.com/auth/drive.readonly",
|
|
52663
52992
|
"https://www.googleapis.com/auth/contacts.readonly"
|
|
52664
52993
|
];
|
|
52994
|
+
GOOGLE_WORKSPACE_SYNTHETIC_EMAIL = "self@local.invalid";
|
|
52665
52995
|
}
|
|
52666
52996
|
});
|
|
52667
52997
|
|
|
@@ -52739,7 +53069,7 @@ var init_seed_postprocessing = __esm({
|
|
|
52739
53069
|
const details = validationErrors.length > 0 ? `:
|
|
52740
53070
|
${validationErrors.map((e) => ` - ${e}`).join("\n")}` : ".";
|
|
52741
53071
|
const suffix = hint ?? "\n\nHint: Run `archal login` and retry. For deterministic reruns, use `--replay-seed <path>` with a previously saved managed seed snapshot.";
|
|
52742
|
-
super(`Dynamic seed generation failed for
|
|
53072
|
+
super(`Dynamic seed generation failed for clone "${twinName}"${details}${suffix}`);
|
|
52743
53073
|
this.name = "DynamicSeedError";
|
|
52744
53074
|
this.twinName = twinName;
|
|
52745
53075
|
this.validationErrors = validationErrors;
|
|
@@ -53275,8 +53605,8 @@ async function generateDynamicSeed(twinName, baseSeedName, baseSeedData, setupDe
|
|
|
53275
53605
|
],
|
|
53276
53606
|
`
|
|
53277
53607
|
|
|
53278
|
-
Hint: Dynamic seed generation failed for the "${twinName}"
|
|
53279
|
-
Use a documented seed name for ${twinName}, or inspect the
|
|
53608
|
+
Hint: Dynamic seed generation failed for the "${twinName}" clone. Try adding a \`seed: <name>\` line to your scenario's Config section to use a pre-built seed instead.
|
|
53609
|
+
Use a documented seed name for ${twinName}, or inspect the bundled clone assets in this repo.`
|
|
53280
53610
|
);
|
|
53281
53611
|
}
|
|
53282
53612
|
var import_node_crypto14, SEED_CODEGEN_MAX_TOKENS, MAX_CODEGEN_ATTEMPTS, SEED_CACHE_PROMPT_TEMPLATE_VERSION, CODEGEN_TOTAL_BUDGET_MS, SYSTEM_PROMPT_HASH;
|
|
@@ -53299,7 +53629,7 @@ var init_dynamic_generator = __esm({
|
|
|
53299
53629
|
init_seed_postprocessing();
|
|
53300
53630
|
SEED_CODEGEN_MAX_TOKENS = 4096;
|
|
53301
53631
|
MAX_CODEGEN_ATTEMPTS = 3;
|
|
53302
|
-
SEED_CACHE_PROMPT_TEMPLATE_VERSION =
|
|
53632
|
+
SEED_CACHE_PROMPT_TEMPLATE_VERSION = 5;
|
|
53303
53633
|
CODEGEN_TOTAL_BUDGET_MS = 12e4;
|
|
53304
53634
|
SYSTEM_PROMPT_HASH = (0, import_node_crypto14.createHash)("sha256").update(buildSeedPromptHashInput()).digest("hex").slice(0, 12);
|
|
53305
53635
|
}
|
|
@@ -55121,7 +55451,7 @@ function computeStateDiff(before, after) {
|
|
|
55121
55451
|
}
|
|
55122
55452
|
return diff;
|
|
55123
55453
|
}
|
|
55124
|
-
function
|
|
55454
|
+
function splitSqlTopLevel2(input, separator) {
|
|
55125
55455
|
const parts = [];
|
|
55126
55456
|
let depth = 0;
|
|
55127
55457
|
let inQuote = false;
|
|
@@ -55150,11 +55480,11 @@ function splitSqlTopLevel(input, separator) {
|
|
|
55150
55480
|
if (tail) parts.push(tail);
|
|
55151
55481
|
return parts;
|
|
55152
55482
|
}
|
|
55153
|
-
function
|
|
55483
|
+
function splitSqlStatements2(sql) {
|
|
55154
55484
|
const stripped = sql.replace(/--.*$/gm, "");
|
|
55155
|
-
return
|
|
55485
|
+
return splitSqlTopLevel2(stripped, ";").map((stmt) => stmt.trim()).filter((stmt) => stmt.length > 0);
|
|
55156
55486
|
}
|
|
55157
|
-
function
|
|
55487
|
+
function normalizeSqlIdentifier2(raw) {
|
|
55158
55488
|
const parts = raw.split(".").map((part) => part.trim().replace(/^"|"$/g, "").replace(/""/g, '"')).filter((part) => part.length > 0);
|
|
55159
55489
|
return parts[parts.length - 1] ?? raw.trim();
|
|
55160
55490
|
}
|
|
@@ -55173,7 +55503,7 @@ function parseSqlSeed(sql) {
|
|
|
55173
55503
|
const seed = {};
|
|
55174
55504
|
const tablesWithNumericId = /* @__PURE__ */ new Set();
|
|
55175
55505
|
const nextIds = /* @__PURE__ */ new Map();
|
|
55176
|
-
const statements =
|
|
55506
|
+
const statements = splitSqlStatements2(sql);
|
|
55177
55507
|
for (const statement of statements) {
|
|
55178
55508
|
const createMatch = statement.match(
|
|
55179
55509
|
/^CREATE\s+TABLE(?:\s+IF\s+NOT\s+EXISTS)?\s+([^\s(]+)\s*\(([\s\S]*)\)$/i
|
|
@@ -55182,7 +55512,7 @@ function parseSqlSeed(sql) {
|
|
|
55182
55512
|
const tableNameCapture2 = createMatch[1];
|
|
55183
55513
|
const schemaBodyCapture = createMatch[2];
|
|
55184
55514
|
if (tableNameCapture2 === void 0 || schemaBodyCapture === void 0) continue;
|
|
55185
|
-
const tableName2 =
|
|
55515
|
+
const tableName2 = normalizeSqlIdentifier2(tableNameCapture2);
|
|
55186
55516
|
const schemaBody = schemaBodyCapture;
|
|
55187
55517
|
if (/\bid\s+(?:serial|bigserial|integer|int|bigint)\b/i.test(schemaBody)) {
|
|
55188
55518
|
tablesWithNumericId.add(tableName2);
|
|
@@ -55198,8 +55528,8 @@ function parseSqlSeed(sql) {
|
|
|
55198
55528
|
const columnsCapture = insertMatch[2];
|
|
55199
55529
|
const tuplesCapture = insertMatch[3];
|
|
55200
55530
|
if (tableNameCapture === void 0 || columnsCapture === void 0 || tuplesCapture === void 0) continue;
|
|
55201
|
-
const tableName =
|
|
55202
|
-
const columns =
|
|
55531
|
+
const tableName = normalizeSqlIdentifier2(tableNameCapture);
|
|
55532
|
+
const columns = splitSqlTopLevel2(columnsCapture, ",").map((column) => normalizeSqlIdentifier2(column));
|
|
55203
55533
|
const tuplesText = tuplesCapture;
|
|
55204
55534
|
const tuples = [];
|
|
55205
55535
|
let depth = 0;
|
|
@@ -55231,7 +55561,7 @@ function parseSqlSeed(sql) {
|
|
|
55231
55561
|
const rows = seed[tableName] ?? [];
|
|
55232
55562
|
let nextId = nextIds.get(tableName) ?? 1;
|
|
55233
55563
|
for (const tuple2 of tuples) {
|
|
55234
|
-
const rawValues =
|
|
55564
|
+
const rawValues = splitSqlTopLevel2(tuple2, ",");
|
|
55235
55565
|
const row = {};
|
|
55236
55566
|
for (let i = 0; i < columns.length; i++) {
|
|
55237
55567
|
const column = columns[i];
|
|
@@ -56141,7 +56471,6 @@ function writeLocalTwinCatalogJson() {
|
|
|
56141
56471
|
process.stdout.write(JSON.stringify(
|
|
56142
56472
|
KNOWN_CLONES.map((twin) => ({
|
|
56143
56473
|
name: twin.name,
|
|
56144
|
-
package: `@archal/twin-${twin.name}`,
|
|
56145
56474
|
description: twin.description,
|
|
56146
56475
|
toolCount: twin.toolCount
|
|
56147
56476
|
})),
|
|
@@ -56179,14 +56508,12 @@ async function listCloneCatalog(json2) {
|
|
|
56179
56508
|
}
|
|
56180
56509
|
const rows2 = KNOWN_CLONES.map((twin) => [
|
|
56181
56510
|
twin.displayName,
|
|
56182
|
-
String(twin.toolCount),
|
|
56183
56511
|
twin.description,
|
|
56184
56512
|
availableTwinStatus()
|
|
56185
56513
|
]);
|
|
56186
|
-
table(["Name", "
|
|
56514
|
+
table(["Name", "Description", "Status"], rows2);
|
|
56187
56515
|
warn("Could not reach server. Showing local clone list.");
|
|
56188
56516
|
info(twinCatalogSummary(creds));
|
|
56189
|
-
info(TOOL_COUNT_FOOTNOTE);
|
|
56190
56517
|
return;
|
|
56191
56518
|
}
|
|
56192
56519
|
if (json2) {
|
|
@@ -56195,15 +56522,12 @@ async function listCloneCatalog(json2) {
|
|
|
56195
56522
|
}
|
|
56196
56523
|
const rows = result.data.map((twin) => [
|
|
56197
56524
|
twin.name,
|
|
56198
|
-
twin.toolCount != null ? String(twin.toolCount) : "-",
|
|
56199
56525
|
twin.description,
|
|
56200
56526
|
availableTwinStatus()
|
|
56201
56527
|
]);
|
|
56202
|
-
table(["Name", "
|
|
56528
|
+
table(["Name", "Description", "Status"], rows);
|
|
56203
56529
|
success2(twinCatalogSummary(creds));
|
|
56204
|
-
info(TOOL_COUNT_FOOTNOTE);
|
|
56205
56530
|
}
|
|
56206
|
-
var TOOL_COUNT_FOOTNOTE;
|
|
56207
56531
|
var init_clones = __esm({
|
|
56208
56532
|
"src/commands/clones.ts"() {
|
|
56209
56533
|
"use strict";
|
|
@@ -56213,7 +56537,6 @@ var init_clones = __esm({
|
|
|
56213
56537
|
init_api_client();
|
|
56214
56538
|
init_clone_catalog();
|
|
56215
56539
|
init_ansi();
|
|
56216
|
-
TOOL_COUNT_FOOTNOTE = "Tool counts shown are static SDK tools. Run 'archal clone tools <clone>' for the full live tool list.";
|
|
56217
56540
|
}
|
|
56218
56541
|
});
|
|
56219
56542
|
|
|
@@ -61445,7 +61768,7 @@ var parseExistenceAssertion = (ctx) => {
|
|
|
61445
61768
|
const noneMatch = lower.match(/^(?:no|zero|none)\s+(.+?)(?:\s+(?:remain|exist|left|present|found))?\s*$/);
|
|
61446
61769
|
if (noneMatch) {
|
|
61447
61770
|
const noneSubject = noneMatch[1]?.trim() ?? "";
|
|
61448
|
-
if (/\b(?:were|was|have|had|are|is|been|being|contains?|includes?|should|would|could)\b/.test(noneSubject)) {
|
|
61771
|
+
if (/\b(?:were|was|have|had|are|is|been|being|contains?|includes?|exceeds?|exceeded|should|would|could)\b/.test(noneSubject)) {
|
|
61449
61772
|
return null;
|
|
61450
61773
|
}
|
|
61451
61774
|
return {
|
|
@@ -61841,11 +62164,16 @@ var parseNegatedCreationAssertion = (ctx) => {
|
|
|
61841
62164
|
const { lower } = ctx;
|
|
61842
62165
|
const noCreatedInMatch = lower.match(/^no\s+(.+?)\s+(?:were|was|have been|had been)\s+(?:created|processed|charged|posted|sent|made|transferred|issued)\s+(?:in|on|to|from|with|for|via)\s+(.+)$/);
|
|
61843
62166
|
if (noCreatedInMatch) {
|
|
62167
|
+
const subject = noCreatedInMatch[1]?.trim() ?? "";
|
|
62168
|
+
const targetService = noCreatedInMatch[2]?.trim();
|
|
62169
|
+
if (/\brefunds?\b/.test(subject) && /^charge\b/.test(targetService ?? "")) {
|
|
62170
|
+
return null;
|
|
62171
|
+
}
|
|
61844
62172
|
return {
|
|
61845
62173
|
type: "exact_count",
|
|
61846
|
-
subject
|
|
62174
|
+
subject,
|
|
61847
62175
|
value: 0,
|
|
61848
|
-
targetService
|
|
62176
|
+
targetService
|
|
61849
62177
|
};
|
|
61850
62178
|
}
|
|
61851
62179
|
return null;
|
|
@@ -62024,6 +62352,23 @@ function parseAssertion(description) {
|
|
|
62024
62352
|
}
|
|
62025
62353
|
|
|
62026
62354
|
// src/runner/scenario-parser.ts
|
|
62355
|
+
var explicitCriterionTag = /* @__PURE__ */ Symbol("explicitCriterionTag");
|
|
62356
|
+
function getExplicitCriterionTag(criterion) {
|
|
62357
|
+
return criterion[explicitCriterionTag];
|
|
62358
|
+
}
|
|
62359
|
+
function isUnsupportedDeterministicRefundAssertion(description) {
|
|
62360
|
+
const normalized = description.replace(/^\s*\[(?:critical|high|medium|low)\]\s*/i, "").replace(/`/g, "").toLowerCase().trim();
|
|
62361
|
+
if (!/\brefund(?:ed|s|ing)?\b/.test(normalized)) {
|
|
62362
|
+
return false;
|
|
62363
|
+
}
|
|
62364
|
+
if (/\brefunds?\b.*\bexceeds?\b.*\boriginal charge amount\b/.test(normalized)) {
|
|
62365
|
+
return true;
|
|
62366
|
+
}
|
|
62367
|
+
if (/\btotal refunded amount\b.*\b(?:on|for)\s+ch_[a-z0-9_]+\b.*\b(?:exactly|equals?|becomes)\b/.test(normalized)) {
|
|
62368
|
+
return true;
|
|
62369
|
+
}
|
|
62370
|
+
return /^no\s+stripe\s+refunds?\s+(?:are|were|was|have been|had been)\s+created\s+for\s+charge\s+ch_[a-z0-9_]+\b/.test(normalized);
|
|
62371
|
+
}
|
|
62027
62372
|
var SECTION_ALIASES = {
|
|
62028
62373
|
setup: "setup",
|
|
62029
62374
|
context: "setup",
|
|
@@ -62099,20 +62444,28 @@ function parseCriterionLine(line, index) {
|
|
|
62099
62444
|
if (!bulletStripped) return null;
|
|
62100
62445
|
let type = "probabilistic";
|
|
62101
62446
|
let description = bulletStripped;
|
|
62447
|
+
let explicitTag;
|
|
62102
62448
|
const tagMatch = description.match(/^\[([DP])]\s*(.*)/i);
|
|
62103
62449
|
if (tagMatch) {
|
|
62104
62450
|
const tag = (tagMatch[1] ?? "").toUpperCase();
|
|
62451
|
+
explicitTag = tag === "D" ? "D" : "P";
|
|
62105
62452
|
type = tag === "D" ? "deterministic" : "probabilistic";
|
|
62106
62453
|
description = tagMatch[2]?.trim() ?? "";
|
|
62107
62454
|
} else {
|
|
62108
62455
|
type = inferCriterionType(description);
|
|
62109
62456
|
}
|
|
62110
62457
|
if (!description) return null;
|
|
62111
|
-
|
|
62458
|
+
const criterion = {
|
|
62112
62459
|
id: `criterion-${index + 1}`,
|
|
62113
62460
|
description,
|
|
62114
62461
|
type
|
|
62115
62462
|
};
|
|
62463
|
+
if (explicitTag) {
|
|
62464
|
+
Object.defineProperty(criterion, explicitCriterionTag, {
|
|
62465
|
+
value: explicitTag
|
|
62466
|
+
});
|
|
62467
|
+
}
|
|
62468
|
+
return criterion;
|
|
62116
62469
|
}
|
|
62117
62470
|
function inferCriterionType(description) {
|
|
62118
62471
|
const deterministicPatterns = [
|
|
@@ -62371,6 +62724,11 @@ function validateScenario(scenario) {
|
|
|
62371
62724
|
if (!criterion.description) {
|
|
62372
62725
|
errors.push(`Criterion ${criterion.id} has an empty description`);
|
|
62373
62726
|
}
|
|
62727
|
+
if (criterion.type === "deterministic" && getExplicitCriterionTag(criterion) === "D" && isUnsupportedDeterministicRefundAssertion(criterion.description) && parseAssertion(criterion.description) === null) {
|
|
62728
|
+
errors.push(
|
|
62729
|
+
`Criterion ${criterion.id} is tagged [D] but is not supported by the deterministic parser: "${criterion.description}"`
|
|
62730
|
+
);
|
|
62731
|
+
}
|
|
62374
62732
|
}
|
|
62375
62733
|
if (scenario.config.twins.length === 0) {
|
|
62376
62734
|
errors.push("Scenario does not reference any known clones. Add `clones:` under ## Config or describe the service in ## Expected Behavior.");
|
|
@@ -63148,6 +63506,34 @@ var EVIDENCE_SENSITIVE_KEY_PARTS = /* @__PURE__ */ new Set([
|
|
|
63148
63506
|
"accesskey"
|
|
63149
63507
|
]);
|
|
63150
63508
|
var EVIDENCE_STRING_PATTERNS = [
|
|
63509
|
+
{
|
|
63510
|
+
pattern: /https?:\/\/[^\s"'<>]+\/runtime\/session\/[^\s"'<>]*/gi,
|
|
63511
|
+
replacement: "[SERVICE_ENDPOINT_REDACTED]"
|
|
63512
|
+
},
|
|
63513
|
+
{
|
|
63514
|
+
pattern: /\/runtime\/session\/[^\s"'<>]*/gi,
|
|
63515
|
+
replacement: "[SERVICE_ENDPOINT_REDACTED]"
|
|
63516
|
+
},
|
|
63517
|
+
{
|
|
63518
|
+
pattern: /\bx-archal-[\w-]+(?::|=)\s*["']?[^"',\s}]+/gi,
|
|
63519
|
+
replacement: "[SERVICE_HEADER_REDACTED]"
|
|
63520
|
+
},
|
|
63521
|
+
{
|
|
63522
|
+
pattern: /\barchal_mcp_servers\b/gi,
|
|
63523
|
+
replacement: "service_tool_servers"
|
|
63524
|
+
},
|
|
63525
|
+
{
|
|
63526
|
+
pattern: /\bARCHAL_(?:CLONE_URLS_PATH|TWIN_URLS_PATH|PROXY_EVENTS_PATH|METRICS_FILE|AGENT_TRACE_FILE|ENABLE_PROVIDER_EGRESS_PROXY)\b/g,
|
|
63527
|
+
replacement: "[SERVICE_RUNTIME_CONFIG_REDACTED]"
|
|
63528
|
+
},
|
|
63529
|
+
{
|
|
63530
|
+
pattern: /\/archal-artifacts\/[^\s"'<>]*/gi,
|
|
63531
|
+
replacement: "[SERVICE_ARTIFACT_PATH_REDACTED]"
|
|
63532
|
+
},
|
|
63533
|
+
{
|
|
63534
|
+
pattern: /\b(?:host\.docker\.internal|localhost|127\.0\.0\.1):9100\b/gi,
|
|
63535
|
+
replacement: "[SERVICE_PROXY_ENDPOINT_REDACTED]"
|
|
63536
|
+
},
|
|
63151
63537
|
{
|
|
63152
63538
|
pattern: /\b(Bearer\s+)[A-Za-z0-9._~+/=-]+\b/gi,
|
|
63153
63539
|
replacement: `$1${EVIDENCE_REDACTED}`
|
|
@@ -63213,7 +63599,7 @@ var EVIDENCE_STRING_PATTERNS = [
|
|
|
63213
63599
|
replacement: `$1${EVIDENCE_REDACTED}`
|
|
63214
63600
|
}
|
|
63215
63601
|
];
|
|
63216
|
-
var EVIDENCE_STRING_REDACTION_HINT = /(bearer\s+|gh[pousr]_|github_pat_|sk_(?:live|test)_|sk-proj-|sk-ant-|sk-|AIza|xox[baprs]-|x(?:app|oxa|oxc|oxp|oxs)-|(?:AKIA|ASIA)|eyJ|private key|(?:^|[?&])(?:token|access_token|refresh_token|client_secret|secret|api_key|apikey|password)=|\b"?(?:authorization|token|access_token|refresh_token|client_secret|secret|api_key|apikey|password|private_key|privatekey)"?\s*[:=]|\b[A-Z0-9_]*(?:API_KEY|SECRET_KEY|ACCESS_KEY|ACCESS_TOKEN|REFRESH_TOKEN|AUTH_TOKEN|BEARER_TOKEN|TOKEN|PASSWORD|SECRET|PRIVATE_KEY)[A-Z0-9_]*\s*[:=])/i;
|
|
63602
|
+
var EVIDENCE_STRING_REDACTION_HINT = /(\/runtime\/session\/|x-archal-|archal_mcp_servers|\bARCHAL_(?:CLONE_URLS_PATH|TWIN_URLS_PATH|PROXY_EVENTS_PATH|METRICS_FILE|AGENT_TRACE_FILE|ENABLE_PROVIDER_EGRESS_PROXY)\b|\/archal-artifacts\/|\b(?:host\.docker\.internal|localhost|127\.0\.0\.1):9100\b|bearer\s+|gh[pousr]_|github_pat_|sk_(?:live|test)_|sk-proj-|sk-ant-|sk-|AIza|xox[baprs]-|x(?:app|oxa|oxc|oxp|oxs)-|(?:AKIA|ASIA)|eyJ|private key|(?:^|[?&])(?:token|access_token|refresh_token|client_secret|secret|api_key|apikey|password)=|\b"?(?:authorization|token|access_token|refresh_token|client_secret|secret|api_key|apikey|password|private_key|privatekey)"?\s*[:=]|\b[A-Z0-9_]*(?:API_KEY|SECRET_KEY|ACCESS_KEY|ACCESS_TOKEN|REFRESH_TOKEN|AUTH_TOKEN|BEARER_TOKEN|TOKEN|PASSWORD|SECRET|PRIVATE_KEY)[A-Z0-9_]*\s*[:=])/i;
|
|
63217
63603
|
function redactEvidenceString(value) {
|
|
63218
63604
|
if (!EVIDENCE_STRING_REDACTION_HINT.test(value)) {
|
|
63219
63605
|
return value;
|
|
@@ -67296,18 +67682,12 @@ var LEGACY_AGENT_CONTRACT_ENV = /* @__PURE__ */ new Set([
|
|
|
67296
67682
|
"ARCHAL_METRICS_FILE",
|
|
67297
67683
|
"ARCHAL_AGENT_TRACE_FILE"
|
|
67298
67684
|
]);
|
|
67299
|
-
var ROUTED_CLONE_ENV_NAMES2 =
|
|
67300
|
-
|
|
67301
|
-
|
|
67302
|
-
|
|
67303
|
-
|
|
67304
|
-
|
|
67305
|
-
"RAMP",
|
|
67306
|
-
"SLACK",
|
|
67307
|
-
"STRIPE",
|
|
67308
|
-
"SUPABASE",
|
|
67309
|
-
"TELEGRAM"
|
|
67310
|
-
]);
|
|
67685
|
+
var ROUTED_CLONE_ENV_NAMES2 = new Set(
|
|
67686
|
+
CLONE_NAMES.flatMap((cloneName) => {
|
|
67687
|
+
const segment = toServiceEnvSegment(cloneName);
|
|
67688
|
+
return segment ? [segment] : [];
|
|
67689
|
+
})
|
|
67690
|
+
);
|
|
67311
67691
|
var ROUTED_CLONE_ENV_SUFFIXES2 = ["_BASE_URL", "_REST_URL", "_MCP_URL", "_URL"];
|
|
67312
67692
|
function routedCloneEnvName2(key) {
|
|
67313
67693
|
if (!key.startsWith("ARCHAL_")) {
|
|
@@ -67368,7 +67748,7 @@ function buildTrustedCloneRoutingEnv(input) {
|
|
|
67368
67748
|
continue;
|
|
67369
67749
|
}
|
|
67370
67750
|
const restUrl = toTwinRestUrl(rawUrl);
|
|
67371
|
-
const mcpUrl = toTwinMcpUrl(rawUrl);
|
|
67751
|
+
const mcpUrl = supportsHostedCloneMcp(cloneName) ? toTwinMcpUrl(rawUrl) : void 0;
|
|
67372
67752
|
restUrls[cloneName] = restUrl;
|
|
67373
67753
|
maybeSetEnv(env, toAgentServiceEnvVarName(cloneName, "BASE_URL"), restUrl);
|
|
67374
67754
|
maybeSetEnv(env, toAgentServiceEnvVarName(cloneName, "URL"), restUrl);
|
|
@@ -71810,7 +72190,8 @@ function resolveLlmProviderKeys(env) {
|
|
|
71810
72190
|
}
|
|
71811
72191
|
|
|
71812
72192
|
// ../packages/sandbox-runtime/src/docker-harness/runner.ts
|
|
71813
|
-
var
|
|
72193
|
+
var AGENT_OUTPUT_DIR_IN_CONTAINER = "/agent-output";
|
|
72194
|
+
var PROXY_CONFIG_DIR_IN_CONTAINER = "/service-runtime";
|
|
71814
72195
|
var PROXY_IMAGE_NAME = "archal/sandbox";
|
|
71815
72196
|
var BUILD_TIMEOUT_CAP_MS = 12e4;
|
|
71816
72197
|
var PROXY_READY_TIMEOUT_MS = 1e4;
|
|
@@ -71842,21 +72223,21 @@ function fail(error49) {
|
|
|
71842
72223
|
return { ok: false, exitCode: 1, stdout: "", stderr: "", timedOut: false, error: error49 };
|
|
71843
72224
|
}
|
|
71844
72225
|
function buildContainerEnv(config2) {
|
|
71845
|
-
const caPath = `${
|
|
72226
|
+
const caPath = `${AGENT_OUTPUT_DIR_IN_CONTAINER}/ca.crt`;
|
|
71846
72227
|
const includeLegacyArchalEnv = shouldExposeLegacyAgentEnv2();
|
|
71847
72228
|
const env = {
|
|
71848
72229
|
[AGENT_RUN_MODE_ENV2]: "local",
|
|
71849
72230
|
[AGENT_TASK_ENV2]: config2.task,
|
|
71850
|
-
[AGENT_METRICS_FILE_ENV2]: `${
|
|
71851
|
-
[AGENT_TRACE_FILE_ENV2]: `${
|
|
72231
|
+
[AGENT_METRICS_FILE_ENV2]: `${AGENT_OUTPUT_DIR_IN_CONTAINER}/metrics.json`,
|
|
72232
|
+
[AGENT_TRACE_FILE_ENV2]: `${AGENT_OUTPUT_DIR_IN_CONTAINER}/agent-trace.json`,
|
|
71852
72233
|
...BOOTSTRAP_SERVICE_CREDENTIALS2,
|
|
71853
72234
|
...buildTlsTrustEnvVars(caPath)
|
|
71854
72235
|
};
|
|
71855
72236
|
if (includeLegacyArchalEnv) {
|
|
71856
72237
|
env["ARCHAL_ENGINE_MODE"] = "local";
|
|
71857
72238
|
env["ARCHAL_ENGINE_TASK"] = config2.task;
|
|
71858
|
-
env["ARCHAL_METRICS_FILE"] = `${
|
|
71859
|
-
env["ARCHAL_AGENT_TRACE_FILE"] = `${
|
|
72239
|
+
env["ARCHAL_METRICS_FILE"] = `${AGENT_OUTPUT_DIR_IN_CONTAINER}/metrics.json`;
|
|
72240
|
+
env["ARCHAL_AGENT_TRACE_FILE"] = `${AGENT_OUTPUT_DIR_IN_CONTAINER}/agent-trace.json`;
|
|
71860
72241
|
}
|
|
71861
72242
|
if (config2.sessionId) {
|
|
71862
72243
|
env[AGENT_SESSION_ID_ENV] = config2.sessionId;
|
|
@@ -71870,11 +72251,24 @@ function buildContainerEnv(config2) {
|
|
|
71870
72251
|
env["ARCHAL_ENGINE_MODEL"] = config2.model.trim();
|
|
71871
72252
|
}
|
|
71872
72253
|
}
|
|
72254
|
+
const providerKeys = resolveLlmProviderKeys(process.env);
|
|
72255
|
+
if (providerKeys.openai) {
|
|
72256
|
+
env["OPENAI_API_KEY"] = SANDBOX_OPENAI_PLACEHOLDER_API_KEY;
|
|
72257
|
+
}
|
|
72258
|
+
if (providerKeys.anthropic) {
|
|
72259
|
+
env["ANTHROPIC_API_KEY"] = SANDBOX_ANTHROPIC_PLACEHOLDER_API_KEY;
|
|
72260
|
+
}
|
|
72261
|
+
if (process.env["GOOGLE_API_KEY"]?.trim()) {
|
|
72262
|
+
env["GOOGLE_API_KEY"] = SANDBOX_GOOGLE_PLACEHOLDER_API_KEY;
|
|
72263
|
+
}
|
|
72264
|
+
if (process.env["GEMINI_API_KEY"]?.trim()) {
|
|
72265
|
+
env["GEMINI_API_KEY"] = SANDBOX_GOOGLE_PLACEHOLDER_API_KEY;
|
|
72266
|
+
}
|
|
72267
|
+
if (providerKeys.openrouter) {
|
|
72268
|
+
env["OPENROUTER_API_KEY"] = SANDBOX_OPENROUTER_PLACEHOLDER_API_KEY;
|
|
72269
|
+
}
|
|
71873
72270
|
const passthroughKeys = [
|
|
71874
72271
|
...includeLegacyArchalEnv ? ["ARCHAL_ENGINE_API_KEY"] : [],
|
|
71875
|
-
"ANTHROPIC_API_KEY",
|
|
71876
|
-
"OPENAI_API_KEY",
|
|
71877
|
-
"GEMINI_API_KEY",
|
|
71878
72272
|
"NODE_ENV"
|
|
71879
72273
|
];
|
|
71880
72274
|
for (const key of passthroughKeys) {
|
|
@@ -72084,15 +72478,16 @@ async function runDockerHarness(config2) {
|
|
|
72084
72478
|
const proxyContainerName = `archal-harness-proxy-${dockerIdSuffix}`;
|
|
72085
72479
|
const networkName = `archal-harness-net-${dockerIdSuffix}`;
|
|
72086
72480
|
const proxyEgressNetworkName = `archal-harness-egress-${dockerIdSuffix}`;
|
|
72087
|
-
const
|
|
72481
|
+
const agentOutputDir = (0, import_node_path27.join)(runDir, "agent-output");
|
|
72482
|
+
const proxyConfigDir = (0, import_node_path27.join)(runDir, "proxy");
|
|
72088
72483
|
const envFilePath = (0, import_node_path27.join)(runDir, ".env");
|
|
72089
72484
|
const proxyEnvFilePath = (0, import_node_path27.join)(runDir, ".proxy.env");
|
|
72090
|
-
const cloneUrlsHostPath = (0, import_node_path27.join)(
|
|
72091
|
-
const cloneUrlsContainerPath = `${
|
|
72092
|
-
const proxyCaPath = (0, import_node_path27.join)(
|
|
72093
|
-
const proxyEventsPath = (0, import_node_path27.join)(
|
|
72094
|
-
const metricsPath = (0, import_node_path27.join)(
|
|
72095
|
-
const agentTracePath = (0, import_node_path27.join)(
|
|
72485
|
+
const cloneUrlsHostPath = (0, import_node_path27.join)(proxyConfigDir, "service-map.json");
|
|
72486
|
+
const cloneUrlsContainerPath = `${PROXY_CONFIG_DIR_IN_CONTAINER}/service-map.json`;
|
|
72487
|
+
const proxyCaPath = (0, import_node_path27.join)(agentOutputDir, "ca.crt");
|
|
72488
|
+
const proxyEventsPath = (0, import_node_path27.join)(proxyConfigDir, "proxy-events.ndjson");
|
|
72489
|
+
const metricsPath = (0, import_node_path27.join)(agentOutputDir, "metrics.json");
|
|
72490
|
+
const agentTracePath = (0, import_node_path27.join)(agentOutputDir, "agent-trace.json");
|
|
72096
72491
|
const ownImage = !config2.prebuiltImage;
|
|
72097
72492
|
let cleanupDocker = false;
|
|
72098
72493
|
const cleanupHandlers = registerDockerCleanupHandlers(containerName, imageName, ownImage, {
|
|
@@ -72128,7 +72523,8 @@ async function runDockerHarness(config2) {
|
|
|
72128
72523
|
if (!proxyImage.ok) {
|
|
72129
72524
|
return fail(stageError("TLS intercept sidecar unavailable", proxyImage.error));
|
|
72130
72525
|
}
|
|
72131
|
-
(0, import_node_fs30.mkdirSync)(
|
|
72526
|
+
(0, import_node_fs30.mkdirSync)(agentOutputDir, { recursive: true });
|
|
72527
|
+
(0, import_node_fs30.mkdirSync)(proxyConfigDir, { recursive: true });
|
|
72132
72528
|
(0, import_node_fs30.writeFileSync)(cloneUrlsHostPath, JSON.stringify(config2.cloudTwinUrls), { encoding: "utf-8", mode: 384 });
|
|
72133
72529
|
const networkResult = await runDockerCommand(["network", "create", "--internal", networkName], 1e4);
|
|
72134
72530
|
if (networkResult.exitCode !== 0) {
|
|
@@ -72143,11 +72539,11 @@ async function runDockerHarness(config2) {
|
|
|
72143
72539
|
ARCHAL_CLONE_URLS_PATH: cloneUrlsContainerPath,
|
|
72144
72540
|
ARCHAL_TWIN_URLS_PATH: cloneUrlsContainerPath,
|
|
72145
72541
|
ARCHAL_TOKEN: config2.authToken,
|
|
72146
|
-
CA_CERT_PATH: `${
|
|
72147
|
-
CA_KEY_PATH: `${
|
|
72542
|
+
CA_CERT_PATH: `${AGENT_OUTPUT_DIR_IN_CONTAINER}/ca.crt`,
|
|
72543
|
+
CA_KEY_PATH: `${PROXY_CONFIG_DIR_IN_CONTAINER}/ca.key`,
|
|
72148
72544
|
PROXY_PORT: "443",
|
|
72149
72545
|
PROXY_HOST: "0.0.0.0",
|
|
72150
|
-
ARCHAL_PROXY_EVENTS_PATH: `${
|
|
72546
|
+
ARCHAL_PROXY_EVENTS_PATH: `${PROXY_CONFIG_DIR_IN_CONTAINER}/proxy-events.ndjson`,
|
|
72151
72547
|
ARCHAL_ENABLE_PROVIDER_EGRESS_PROXY: "1",
|
|
72152
72548
|
ARCHAL_BLOCK_EGRESS: "1",
|
|
72153
72549
|
...proxyLlmEnv
|
|
@@ -72160,7 +72556,9 @@ async function runDockerHarness(config2) {
|
|
|
72160
72556
|
"--network",
|
|
72161
72557
|
networkName,
|
|
72162
72558
|
"-v",
|
|
72163
|
-
`${
|
|
72559
|
+
`${proxyConfigDir}:${PROXY_CONFIG_DIR_IN_CONTAINER}`,
|
|
72560
|
+
"-v",
|
|
72561
|
+
`${agentOutputDir}:${AGENT_OUTPUT_DIR_IN_CONTAINER}`,
|
|
72164
72562
|
"--env-file",
|
|
72165
72563
|
proxyEnvFilePath,
|
|
72166
72564
|
"--entrypoint",
|
|
@@ -72194,7 +72592,7 @@ async function runDockerHarness(config2) {
|
|
|
72194
72592
|
"--network",
|
|
72195
72593
|
networkName,
|
|
72196
72594
|
"-v",
|
|
72197
|
-
`${
|
|
72595
|
+
`${agentOutputDir}:${AGENT_OUTPUT_DIR_IN_CONTAINER}`,
|
|
72198
72596
|
...buildAddHostArgs(config2.cloudTwinUrls, proxyIp, buildProviderDomainsForProxy(proxyLlmEnv)),
|
|
72199
72597
|
...envArgs,
|
|
72200
72598
|
imageName
|
|
@@ -72361,6 +72759,9 @@ function isLikelyModelBackendFailure(text) {
|
|
|
72361
72759
|
if (!text) return false;
|
|
72362
72760
|
return OPENCLAW_BACKEND_FAILURE_PATTERNS.some((pattern) => pattern.test(text));
|
|
72363
72761
|
}
|
|
72762
|
+
function sanitizeOpenClawGatewayDiagnostic(text) {
|
|
72763
|
+
return text.replace(/Authorization:\s*Bearer\s+\S+/gi, "Authorization: Bearer [REDACTED]").replace(/\bBearer\s+[A-Za-z0-9._~+/\-=]+/gi, "Bearer [REDACTED]").replace(/x-archal-[\w-]+(?::|=)\s*["']?[^"',\s}]+/gi, "[service header redacted]").replace(/https?:\/\/[^\s"'<>]+\/runtime\/session\/[^\s"'<>]*/gi, "[service endpoint redacted]").replace(/\/runtime\/session\/[^\s"'<>]*/gi, "[service endpoint redacted]").replace(/\barchal_mcp_servers\b/gi, "service_tool_servers").replace(/\barchal_(?:transport|eval_mode)\b/gi, "service_metadata").replace(/\bArchal\b/gi, "service runtime");
|
|
72764
|
+
}
|
|
72364
72765
|
function buildModelBackendHint() {
|
|
72365
72766
|
return "Hint: OpenClaw gateway could not get a model response. Verify model/provider credentials on the gateway host (e.g. ANTHROPIC_API_KEY / OPENAI_API_KEY / GEMINI_API_KEY), then restart the gateway.";
|
|
72366
72767
|
}
|
|
@@ -72372,7 +72773,7 @@ function buildOpenClawFailureMessage(parsed) {
|
|
|
72372
72773
|
const details = [errorMessage4, outputText].filter((value) => Boolean(value && value.trim())).join(" | ");
|
|
72373
72774
|
if (details) {
|
|
72374
72775
|
message += `
|
|
72375
|
-
Gateway output: ${details.slice(0, 500)}`;
|
|
72776
|
+
Gateway output: ${sanitizeOpenClawGatewayDiagnostic(details).slice(0, 500)}`;
|
|
72376
72777
|
}
|
|
72377
72778
|
if (isLikelyModelBackendFailure(details)) {
|
|
72378
72779
|
message += `
|
|
@@ -72538,12 +72939,13 @@ async function executeOpenClawRemote(remoteConfig, scenario, runId, taskMessage,
|
|
|
72538
72939
|
if (!response.ok) {
|
|
72539
72940
|
const rawBody = await response.text();
|
|
72540
72941
|
const statusLine = `${response.status} ${response.statusText}`.trim();
|
|
72942
|
+
const sanitizedBody = sanitizeOpenClawGatewayDiagnostic(rawBody).slice(0, 500);
|
|
72541
72943
|
const hint = response.status === 401 || response.status === 403 ? "\nHint: If using a raw LLM API (Anthropic, OpenAI), note that --engine-endpoint requires an OpenClaw-compatible gateway, not a direct model API." : "";
|
|
72542
72944
|
return {
|
|
72543
72945
|
exitCode: response.status,
|
|
72544
72946
|
stdout: "",
|
|
72545
|
-
stderr: `OpenClaw request failed: ${statusLine}
|
|
72546
|
-
${
|
|
72947
|
+
stderr: `OpenClaw request failed: ${statusLine}${sanitizedBody ? `
|
|
72948
|
+
${sanitizedBody}` : ""}${hint}`.trim(),
|
|
72547
72949
|
timedOut: false,
|
|
72548
72950
|
durationMs: Date.now() - startedAt
|
|
72549
72951
|
};
|
|
@@ -72559,9 +72961,10 @@ ${rawBody}${hint}`.trim(),
|
|
|
72559
72961
|
try {
|
|
72560
72962
|
parsed = JSON.parse(rawBody);
|
|
72561
72963
|
} catch {
|
|
72964
|
+
const sanitizedBody = sanitizeOpenClawGatewayDiagnostic(rawBody).slice(0, 500);
|
|
72562
72965
|
return {
|
|
72563
72966
|
exitCode: 1,
|
|
72564
|
-
stdout:
|
|
72967
|
+
stdout: sanitizedBody,
|
|
72565
72968
|
stderr: "OpenClaw response was not valid JSON",
|
|
72566
72969
|
timedOut: false,
|
|
72567
72970
|
durationMs: Date.now() - startedAt
|
|
@@ -74112,65 +74515,10 @@ async function runLocalProxy(config2, task, canaryFiles) {
|
|
|
74112
74515
|
"NODE_PATH",
|
|
74113
74516
|
"NODE_OPTIONS"
|
|
74114
74517
|
]);
|
|
74115
|
-
const DENYLIST = /* @__PURE__ */ new Set([
|
|
74116
|
-
"AWS_ACCESS_KEY_ID",
|
|
74117
|
-
"AWS_SECRET_ACCESS_KEY",
|
|
74118
|
-
"AWS_SESSION_TOKEN",
|
|
74119
|
-
"DATABASE_URL",
|
|
74120
|
-
"DATABASE_PASSWORD",
|
|
74121
|
-
"ARCHAL_TOKEN",
|
|
74122
|
-
"ARCHAL_REST_CONFIG",
|
|
74123
|
-
"ARCHAL_TWIN_URLS",
|
|
74124
|
-
"ARCHAL_TWIN_URLS_PATH",
|
|
74125
|
-
"ARCHAL_TWIN_NAMES",
|
|
74126
|
-
"ARCHAL_CLONE_URLS",
|
|
74127
|
-
"ARCHAL_CLONE_URLS_PATH",
|
|
74128
|
-
"ARCHAL_CLONE_NAMES",
|
|
74129
|
-
"ARCHAL_API_BASE_URLS",
|
|
74130
|
-
"ARCHAL_API_PROXY_URL",
|
|
74131
|
-
"ARCHAL_MCP_CONFIG",
|
|
74132
|
-
"ARCHAL_MCP_SERVERS",
|
|
74133
|
-
"MCP_CONFIG_PATH",
|
|
74134
|
-
"HTTP_PROXY",
|
|
74135
|
-
"HTTPS_PROXY",
|
|
74136
|
-
"http_proxy",
|
|
74137
|
-
"https_proxy",
|
|
74138
|
-
"GITHUB_TOKEN",
|
|
74139
|
-
// CI-injected, not for agents
|
|
74140
|
-
"NPM_TOKEN",
|
|
74141
|
-
// Real LLM keys are stripped — the proxy injects them.
|
|
74142
|
-
"OPENAI_API_KEY",
|
|
74143
|
-
"ANTHROPIC_API_KEY",
|
|
74144
|
-
"GOOGLE_API_KEY",
|
|
74145
|
-
"GEMINI_API_KEY",
|
|
74146
|
-
"OPENROUTER_API_KEY"
|
|
74147
|
-
]);
|
|
74148
|
-
const DENYLIST_PREFIXES = ["AWS_"];
|
|
74149
|
-
const ROUTED_TWIN_ENV_NAMES = /* @__PURE__ */ new Set([
|
|
74150
|
-
"DISCORD",
|
|
74151
|
-
"GITHUB",
|
|
74152
|
-
"GOOGLE_WORKSPACE",
|
|
74153
|
-
"JIRA",
|
|
74154
|
-
"LINEAR",
|
|
74155
|
-
"RAMP",
|
|
74156
|
-
"SLACK",
|
|
74157
|
-
"STRIPE",
|
|
74158
|
-
"SUPABASE",
|
|
74159
|
-
"TELEGRAM"
|
|
74160
|
-
]);
|
|
74161
|
-
const ROUTED_TWIN_ENV_SUFFIXES = ["_BASE_URL", "_REST_URL", "_MCP_URL", "_URL"];
|
|
74162
74518
|
const filteredHostEnv = {};
|
|
74163
74519
|
for (const [key, value] of Object.entries(process.env)) {
|
|
74164
74520
|
if (value === void 0) continue;
|
|
74165
|
-
if (
|
|
74166
|
-
if (DENYLIST.has(key)) continue;
|
|
74167
|
-
if (DENYLIST_PREFIXES.some((prefix) => key.startsWith(prefix))) continue;
|
|
74168
|
-
const routedTwinSuffix = key.startsWith("ARCHAL_") ? ROUTED_TWIN_ENV_SUFFIXES.find((suffix) => key.endsWith(suffix)) : void 0;
|
|
74169
|
-
const routedTwinName = routedTwinSuffix ? key.slice("ARCHAL_".length, -routedTwinSuffix.length).replace(/_(API|TWIN|CLONE)$/, "") : void 0;
|
|
74170
|
-
if (routedTwinName && ROUTED_TWIN_ENV_NAMES.has(routedTwinName)) continue;
|
|
74171
|
-
const isInfra = INFRA_ALLOWLIST.has(key);
|
|
74172
|
-
const isApiKey = key.endsWith("_API_KEY") || key.endsWith("_TOKEN");
|
|
74173
|
-
if (isInfra || isApiKey) {
|
|
74521
|
+
if (INFRA_ALLOWLIST.has(key)) {
|
|
74174
74522
|
filteredHostEnv[key] = value;
|
|
74175
74523
|
}
|
|
74176
74524
|
}
|
|
@@ -78775,6 +79123,47 @@ function formatEvaluationErrorSummary(reasons) {
|
|
|
78775
79123
|
}
|
|
78776
79124
|
return "LLM evaluation errors";
|
|
78777
79125
|
}
|
|
79126
|
+
function toLlmEvalErrorReason(reason) {
|
|
79127
|
+
switch (reason) {
|
|
79128
|
+
case "rate_limited":
|
|
79129
|
+
return "rate_limited";
|
|
79130
|
+
case "missing_credentials":
|
|
79131
|
+
return "auth_error";
|
|
79132
|
+
case "provider_error":
|
|
79133
|
+
return "provider_error";
|
|
79134
|
+
case "context_too_large":
|
|
79135
|
+
case void 0:
|
|
79136
|
+
return void 0;
|
|
79137
|
+
default: {
|
|
79138
|
+
const _exhaustive = reason;
|
|
79139
|
+
return _exhaustive;
|
|
79140
|
+
}
|
|
79141
|
+
}
|
|
79142
|
+
}
|
|
79143
|
+
function normalizeFatalLlmFailureResult(result) {
|
|
79144
|
+
if (!result.fallbackFailureReason || !FATAL_LLM_FAILURE_REASONS.has(result.fallbackFailureReason)) {
|
|
79145
|
+
return result;
|
|
79146
|
+
}
|
|
79147
|
+
const errorReason = toLlmEvalErrorReason(result.fallbackFailureReason);
|
|
79148
|
+
return {
|
|
79149
|
+
...result,
|
|
79150
|
+
status: "error",
|
|
79151
|
+
confidence: 0,
|
|
79152
|
+
...errorReason ? { errorReason } : {}
|
|
79153
|
+
};
|
|
79154
|
+
}
|
|
79155
|
+
function buildUnevaluatedDeterministicFallback(criterion, deterministicResult, reason) {
|
|
79156
|
+
const errorReason = toLlmEvalErrorReason(reason);
|
|
79157
|
+
return {
|
|
79158
|
+
criterionId: criterion.id,
|
|
79159
|
+
status: "error",
|
|
79160
|
+
confidence: 0,
|
|
79161
|
+
explanation: `Could not evaluate deterministic criterion because parser fallback was unavailable (${formatFallbackFailureReason(reason)}). Satisfaction is incomplete for this criterion. Original parser result: ${deterministicResult.explanation}`,
|
|
79162
|
+
fallbackRecommended: true,
|
|
79163
|
+
fallbackFailureReason: reason,
|
|
79164
|
+
...errorReason ? { errorReason } : {}
|
|
79165
|
+
};
|
|
79166
|
+
}
|
|
78778
79167
|
function accumulateTokenUsage(total, next) {
|
|
78779
79168
|
if (!next) return total;
|
|
78780
79169
|
if (!total) return next;
|
|
@@ -78821,9 +79210,15 @@ async function evaluateRun(criteria, context, config2) {
|
|
|
78821
79210
|
if (needsFallback) {
|
|
78822
79211
|
if (deterministicFallbackFailureReason) {
|
|
78823
79212
|
warn(
|
|
78824
|
-
`LLM fallback skipped due to cached ${formatFallbackFailureReason(deterministicFallbackFailureReason)} -
|
|
79213
|
+
`LLM fallback skipped due to cached ${formatFallbackFailureReason(deterministicFallbackFailureReason)} - marking deterministic criterion unevaluated for "${criterion.id}"`
|
|
79214
|
+
);
|
|
79215
|
+
evaluations.push(
|
|
79216
|
+
buildUnevaluatedDeterministicFallback(
|
|
79217
|
+
criterion,
|
|
79218
|
+
result,
|
|
79219
|
+
deterministicFallbackFailureReason
|
|
79220
|
+
)
|
|
78825
79221
|
);
|
|
78826
|
-
evaluations.push(result);
|
|
78827
79222
|
continue;
|
|
78828
79223
|
}
|
|
78829
79224
|
warn(
|
|
@@ -78839,9 +79234,11 @@ async function evaluateRun(criteria, context, config2) {
|
|
|
78839
79234
|
if (llmResult.fallbackFailureReason && FATAL_LLM_FAILURE_REASONS.has(llmResult.fallbackFailureReason)) {
|
|
78840
79235
|
deterministicFallbackFailureReason = llmResult.fallbackFailureReason;
|
|
78841
79236
|
warn(
|
|
78842
|
-
`LLM fallback skipped due to ${formatFallbackFailureReason(llmResult.fallbackFailureReason)} -
|
|
79237
|
+
`LLM fallback skipped due to ${formatFallbackFailureReason(llmResult.fallbackFailureReason)} - marking deterministic criterion unevaluated for "${criterion.id}"`
|
|
79238
|
+
);
|
|
79239
|
+
evaluations.push(
|
|
79240
|
+
buildUnevaluatedDeterministicFallback(criterion, result, llmResult.fallbackFailureReason)
|
|
78843
79241
|
);
|
|
78844
|
-
evaluations.push(result);
|
|
78845
79242
|
} else {
|
|
78846
79243
|
evaluations.push(llmResult);
|
|
78847
79244
|
}
|
|
@@ -78855,9 +79252,12 @@ async function evaluateRun(criteria, context, config2) {
|
|
|
78855
79252
|
}
|
|
78856
79253
|
const allDeterministicFailed = deterministicCriteria.length > 0 && !deterministicFallbackFailureReason && evaluations.length > 0 && evaluations.every((e) => e.status === "fail");
|
|
78857
79254
|
if (allDeterministicFailed && probabilisticCriteria.length > 0) {
|
|
78858
|
-
info(
|
|
78859
|
-
|
|
78860
|
-
|
|
79255
|
+
info(
|
|
79256
|
+
"All deterministic criteria failed - skipping probabilistic evaluation to avoid unnecessary judge spend",
|
|
79257
|
+
{
|
|
79258
|
+
skippedCalls: String(probabilisticCriteria.length)
|
|
79259
|
+
}
|
|
79260
|
+
);
|
|
78861
79261
|
for (const criterion of probabilisticCriteria) {
|
|
78862
79262
|
evaluations.push({
|
|
78863
79263
|
criterionId: criterion.id,
|
|
@@ -78879,19 +79279,18 @@ async function evaluateRun(criteria, context, config2) {
|
|
|
78879
79279
|
} else if (!allDeterministicFailed) {
|
|
78880
79280
|
if (deterministicFallbackFailureReason) {
|
|
78881
79281
|
const cachedReason = deterministicFallbackFailureReason;
|
|
78882
|
-
const
|
|
78883
|
-
const errorReason = cachedReason === "rate_limited" ? "rate_limited" : cachedReason === "missing_credentials" ? "auth_error" : cachedReason === "provider_error" ? "provider_error" : void 0;
|
|
79282
|
+
const errorReason = toLlmEvalErrorReason(cachedReason);
|
|
78884
79283
|
for (const criterion of probabilisticCriteria) {
|
|
78885
79284
|
warn(
|
|
78886
79285
|
`Probabilistic evaluation skipped due to cached ${formatFallbackFailureReason(cachedReason)} for "${criterion.id}"`
|
|
78887
79286
|
);
|
|
78888
79287
|
const skipEntry = {
|
|
78889
79288
|
criterionId: criterion.id,
|
|
78890
|
-
status:
|
|
79289
|
+
status: "error",
|
|
78891
79290
|
confidence: 0,
|
|
78892
79291
|
explanation: `Skipped. ${formatFallbackFailureReason(cachedReason)} already detected.`,
|
|
78893
79292
|
fallbackFailureReason: cachedReason,
|
|
78894
|
-
...
|
|
79293
|
+
...errorReason ? { errorReason } : {}
|
|
78895
79294
|
};
|
|
78896
79295
|
evaluations.push(skipEntry);
|
|
78897
79296
|
}
|
|
@@ -78904,11 +79303,12 @@ async function evaluateRun(criteria, context, config2) {
|
|
|
78904
79303
|
);
|
|
78905
79304
|
judgeTokenUsage = accumulateTokenUsage(judgeTokenUsage, tokenUsage);
|
|
78906
79305
|
for (const result of batchResults) {
|
|
78907
|
-
|
|
79306
|
+
const normalizedResult = normalizeFatalLlmFailureResult(result);
|
|
79307
|
+
evaluations.push(normalizedResult);
|
|
78908
79308
|
debug("Probabilistic evaluation (batch)", {
|
|
78909
|
-
criterion:
|
|
78910
|
-
status:
|
|
78911
|
-
confidence:
|
|
79309
|
+
criterion: normalizedResult.criterionId,
|
|
79310
|
+
status: normalizedResult.status,
|
|
79311
|
+
confidence: normalizedResult.confidence.toFixed(2)
|
|
78912
79312
|
});
|
|
78913
79313
|
}
|
|
78914
79314
|
} else if (probabilisticCriteria.length === 1) {
|
|
@@ -78916,11 +79316,12 @@ async function evaluateRun(criteria, context, config2) {
|
|
|
78916
79316
|
progress(`Evaluating [P] ${criterion.description}`);
|
|
78917
79317
|
const { evaluation: result, tokenUsage } = await evaluateWithLlm(criterion, context, config2);
|
|
78918
79318
|
judgeTokenUsage = accumulateTokenUsage(judgeTokenUsage, tokenUsage);
|
|
78919
|
-
|
|
79319
|
+
const normalizedResult = normalizeFatalLlmFailureResult(result);
|
|
79320
|
+
evaluations.push(normalizedResult);
|
|
78920
79321
|
debug("Probabilistic evaluation", {
|
|
78921
79322
|
criterion: criterion.id,
|
|
78922
|
-
status:
|
|
78923
|
-
confidence:
|
|
79323
|
+
status: normalizedResult.status,
|
|
79324
|
+
confidence: normalizedResult.confidence.toFixed(2)
|
|
78924
79325
|
});
|
|
78925
79326
|
}
|
|
78926
79327
|
}
|
|
@@ -79049,7 +79450,7 @@ function trimSnippet(value) {
|
|
|
79049
79450
|
var REAL_SERVICE_HOST_RE = /\b(api\.github\.com|api\.stripe\.com|slack\.com\/api|api\.linear\.app|gmail\.googleapis\.com|www\.googleapis\.com|googleapis\.com|api\.tavily\.com|api\.apify\.com|atlassian\.net|supabase\.co)\b/i;
|
|
79050
79451
|
var AUTH_FAILURE_RE = /\b(401|403|unauthorized|forbidden|bad credentials|requires authentication|invalid token|invalid api key|authentication failed|permission denied)\b/i;
|
|
79051
79452
|
function isHarnessModelAuthFailure(message) {
|
|
79052
|
-
return /Incorrect API key provided|invalid x-api-key|
|
|
79453
|
+
return /Incorrect API key provided|invalid x-api-key|AuthenticationError|OPENAI_API_KEY|ANTHROPIC_API_KEY|GEMINI_API_KEY|401.*(openai|anthropic|gemini|api key)|(?:openai|anthropic|gemini)[\s\S]{0,120}(?:invalid api key|authentication error|api key.*(?:incorrect|invalid))/i.test(message);
|
|
79053
79454
|
}
|
|
79054
79455
|
function isLikelyRealServiceAuthFailure(message) {
|
|
79055
79456
|
return REAL_SERVICE_HOST_RE.test(message) && AUTH_FAILURE_RE.test(message);
|
|
@@ -79070,6 +79471,9 @@ function classifyLocalHarnessFailure(message) {
|
|
|
79070
79471
|
if (/better-sqlite3|NODE_MODULE_VERSION|ERR_DLOPEN_FAILED|compiled against a different Node\.js version|native module/i.test(message)) {
|
|
79071
79472
|
return "native_dependency";
|
|
79072
79473
|
}
|
|
79474
|
+
if (/(?:stripe|github|slack|linear|jira|supabase|discord|apify|tavily|google-workspace|googleapis)[\s\S]{0,160}(?:401|403|unauthorized|forbidden|bad credentials|invalid api key|authentication_error|requires authentication|permission denied)|(?:authentication_error|Invalid API Key provided)[\s\S]{0,160}(?:stripe|github|slack|linear|jira|supabase|discord|apify|tavily|google-workspace|googleapis)/i.test(message)) {
|
|
79475
|
+
return "clone_service_auth";
|
|
79476
|
+
}
|
|
79073
79477
|
if (isHarnessModelAuthFailure(message)) {
|
|
79074
79478
|
return "harness_model_auth";
|
|
79075
79479
|
}
|
|
@@ -79101,6 +79505,10 @@ Fix: rebuild native modules for the Node runtime Archal uses before rerunning.`;
|
|
|
79101
79505
|
Likely issue: the harness reached its model provider, but the configured provider key is missing or invalid.
|
|
79102
79506
|
Fix: provide a valid provider key for the requested agent model before rerunning.
|
|
79103
79507
|
If your harness does not use an LLM, run: archal run <scenario> --agent-model none`;
|
|
79508
|
+
case "clone_service_auth":
|
|
79509
|
+
return `${intro}
|
|
79510
|
+
Likely issue: the harness reached a clone service, but the request used missing or invalid service-shaped credentials.
|
|
79511
|
+
Fix: use the clone URL from AGENT_CLONE_URLS, add AGENT_ROUTE_HEADERS to the request, and keep the service Authorization header/API key from the matching injected credential such as GITHUB_TOKEN, SLACK_TOKEN, STRIPE_API_KEY, or SUPABASE_SERVICE_ROLE_KEY.`;
|
|
79104
79512
|
case "service_bridge":
|
|
79105
79513
|
return `${intro}
|
|
79106
79514
|
Likely issue: the harness booted, but one of its service boundaries is still stubbed or app-only on the headless path.
|
|
@@ -79343,6 +79751,16 @@ function compactFailureExplanation(explanation) {
|
|
|
79343
79751
|
if (firstLine.length <= 600) return firstLine;
|
|
79344
79752
|
return `${firstLine.slice(0, 597)}...`;
|
|
79345
79753
|
}
|
|
79754
|
+
var RESPONSE_ONLY_CRITERION_PATTERN = /\b(?:final\s+answer|agent\s+(?:response|reply|answer)|response\s+text|text\s+response|explains?\s+why|describes?\s+why|refusal|refuses?)\b/i;
|
|
79755
|
+
function hasConfiguredServiceClones(scenario) {
|
|
79756
|
+
return (scenario.config?.twins ?? []).length > 0;
|
|
79757
|
+
}
|
|
79758
|
+
function isExplicitTextResponseOnlyCriterion(criterion) {
|
|
79759
|
+
return RESPONSE_ONLY_CRITERION_PATTERN.test(criterion.description);
|
|
79760
|
+
}
|
|
79761
|
+
function allCriteriaAreExplicitTextResponseOnly(scenario) {
|
|
79762
|
+
return scenario.successCriteria.length > 0 && scenario.successCriteria.every(isExplicitTextResponseOnlyCriterion);
|
|
79763
|
+
}
|
|
79346
79764
|
function buildFailedResult(ctx, fields) {
|
|
79347
79765
|
const stateAfter = fields.stateAfter ?? fields.beforeState;
|
|
79348
79766
|
const trace = annotateExpectedToolErrors(
|
|
@@ -79523,7 +79941,9 @@ function checkTraceViability(ctx, postRun, _startTime, _beforeState, agentLog, _
|
|
|
79523
79941
|
if (agentToolCallCount === 0 && !agentResponseText) {
|
|
79524
79942
|
const explanation = "Agent made no tool calls and produced no parseable response text, so the run has no evidence to evaluate.";
|
|
79525
79943
|
const failureReasonCode = "agent_no_tool_calls";
|
|
79526
|
-
warn(
|
|
79944
|
+
warn(
|
|
79945
|
+
`Run ${ctx.runIndex + 1}: 0 tool calls and no final response. Marking the run incomplete.`
|
|
79946
|
+
);
|
|
79527
79947
|
return buildFailedResult(ctx, {
|
|
79528
79948
|
explanation,
|
|
79529
79949
|
error: `${explanation} (${failureReasonCode})
|
|
@@ -79540,6 +79960,27 @@ Agent log (stderr tail): ${agentLog?.slice(-1e3) || "(none)"}`,
|
|
|
79540
79960
|
failureReasonCode
|
|
79541
79961
|
});
|
|
79542
79962
|
} else if (agentToolCallCount === 0 && agentResponseText) {
|
|
79963
|
+
if (hasConfiguredServiceClones(ctx.scenario) && !allCriteriaAreExplicitTextResponseOnly(ctx.scenario)) {
|
|
79964
|
+
const explanation = "Agent produced a text response but made no clone-observed tool calls. The service clone was not exercised, so clone-backed criteria cannot be scored from response text alone.";
|
|
79965
|
+
const failureReasonCode = "agent_no_tool_calls";
|
|
79966
|
+
warn(
|
|
79967
|
+
`Run ${ctx.runIndex + 1}: 0 clone-observed tool calls with response text for a service-clone scenario. Marking the run incomplete.`
|
|
79968
|
+
);
|
|
79969
|
+
return buildFailedResult(ctx, {
|
|
79970
|
+
explanation,
|
|
79971
|
+
error: `${explanation} (${failureReasonCode})`,
|
|
79972
|
+
outcome: "insufficient_action",
|
|
79973
|
+
startTime: _startTime,
|
|
79974
|
+
beforeState: _beforeState,
|
|
79975
|
+
stateAfter,
|
|
79976
|
+
trace,
|
|
79977
|
+
agentLog,
|
|
79978
|
+
agentTrace: _agentTrace,
|
|
79979
|
+
tokenUsage: _tokenUsage,
|
|
79980
|
+
events,
|
|
79981
|
+
failureReasonCode
|
|
79982
|
+
});
|
|
79983
|
+
}
|
|
79543
79984
|
warn(
|
|
79544
79985
|
"WARN: no clone-observed tool calls were recorded. Scenario was not exercised - score will be meaningful only for text-response checks. Continuing to evaluation because a text response was produced."
|
|
79545
79986
|
);
|
|
@@ -79565,9 +80006,9 @@ async function evaluateAndBuildResult(ctx, evaluatorConfig, postRun, startTime,
|
|
|
79565
80006
|
evaluatorConfig
|
|
79566
80007
|
);
|
|
79567
80008
|
const evals = evaluationResult.evaluations;
|
|
79568
|
-
const
|
|
79569
|
-
const outcome =
|
|
79570
|
-
const failureReasonCode =
|
|
80009
|
+
const hasEvaluatorError = evals.some((e) => e.status === "error");
|
|
80010
|
+
const outcome = hasEvaluatorError ? "degraded" : "completed";
|
|
80011
|
+
const failureReasonCode = hasEvaluatorError ? "evaluator_unavailable" : void 0;
|
|
79571
80012
|
return {
|
|
79572
80013
|
runIndex: ctx.runIndex,
|
|
79573
80014
|
evaluations: evals,
|
|
@@ -79612,7 +80053,7 @@ init_src();
|
|
|
79612
80053
|
|
|
79613
80054
|
// src/runner/mcp/aggregate-stdio-script.ts
|
|
79614
80055
|
var AGGREGATE_MCP_STDIO_SCRIPT = String.raw`
|
|
79615
|
-
const servers = JSON.parse(process.env.
|
|
80056
|
+
const servers = JSON.parse(process.env.SERVICE_MCP_SERVERS || '{}');
|
|
79616
80057
|
const state = { nextId: 1 };
|
|
79617
80058
|
|
|
79618
80059
|
function namespaceToolName(serverName, toolName) {
|
|
@@ -79649,7 +80090,7 @@ async function fetchJson(url, options) {
|
|
|
79649
80090
|
}
|
|
79650
80091
|
}
|
|
79651
80092
|
if (!response.ok) {
|
|
79652
|
-
throw new Error('
|
|
80093
|
+
throw new Error('Service tool request failed.');
|
|
79653
80094
|
}
|
|
79654
80095
|
return body;
|
|
79655
80096
|
}
|
|
@@ -79661,7 +80102,7 @@ async function listTools() {
|
|
|
79661
80102
|
headers: server.headers || {},
|
|
79662
80103
|
});
|
|
79663
80104
|
if (!Array.isArray(list)) {
|
|
79664
|
-
throw new Error('
|
|
80105
|
+
throw new Error('Service tool discovery failed.');
|
|
79665
80106
|
}
|
|
79666
80107
|
for (const tool of list) {
|
|
79667
80108
|
const originalName = String(tool.name || '');
|
|
@@ -79679,7 +80120,7 @@ async function listTools() {
|
|
|
79679
80120
|
async function callTool(params) {
|
|
79680
80121
|
const parsed = parseNamespacedToolName(String(params && params.name || ''));
|
|
79681
80122
|
if (!parsed || !servers[parsed.serverName]) {
|
|
79682
|
-
throw new Error('Unknown
|
|
80123
|
+
throw new Error('Unknown service tool.');
|
|
79683
80124
|
}
|
|
79684
80125
|
const server = servers[parsed.serverName];
|
|
79685
80126
|
return fetchJson(toolApiBaseUrl(server.url) + '/tools/call', {
|
|
@@ -79706,7 +80147,7 @@ async function handle(request) {
|
|
|
79706
80147
|
result: {
|
|
79707
80148
|
protocolVersion: request.params && request.params.protocolVersion || '2024-11-05',
|
|
79708
80149
|
capabilities: { tools: {} },
|
|
79709
|
-
serverInfo: { name: '
|
|
80150
|
+
serverInfo: { name: 'service-tools', version: '1.0.0' },
|
|
79710
80151
|
},
|
|
79711
80152
|
};
|
|
79712
80153
|
}
|
|
@@ -79726,7 +80167,7 @@ async function handle(request) {
|
|
|
79726
80167
|
return {
|
|
79727
80168
|
jsonrpc: '2.0',
|
|
79728
80169
|
id,
|
|
79729
|
-
error: { code: -32000, message: error && error.message ? error.message :
|
|
80170
|
+
error: { code: -32000, message: error && error.message ? error.message : 'Service tool request failed.' },
|
|
79730
80171
|
};
|
|
79731
80172
|
}
|
|
79732
80173
|
}
|
|
@@ -79750,7 +80191,7 @@ process.stdin.on('data', (chunk) => {
|
|
|
79750
80191
|
process.stdout.write(JSON.stringify({
|
|
79751
80192
|
jsonrpc: '2.0',
|
|
79752
80193
|
id: null,
|
|
79753
|
-
error: { code: -32700, message:
|
|
80194
|
+
error: { code: -32700, message: 'Invalid request.' },
|
|
79754
80195
|
}) + '\n');
|
|
79755
80196
|
});
|
|
79756
80197
|
}
|
|
@@ -79765,11 +80206,11 @@ function writeAgentConfigs(runId, cloudCloneUrls, _authToken) {
|
|
|
79765
80206
|
mcpServers[cloneName] = { url: mcpUrl };
|
|
79766
80207
|
}
|
|
79767
80208
|
const aggregateServer = Object.keys(mcpServers).length === 0 ? {} : {
|
|
79768
|
-
|
|
80209
|
+
services: {
|
|
79769
80210
|
command: process.execPath,
|
|
79770
80211
|
args: ["-e", AGGREGATE_MCP_STDIO_SCRIPT],
|
|
79771
80212
|
env: {
|
|
79772
|
-
|
|
80213
|
+
SERVICE_MCP_SERVERS: JSON.stringify(mcpServers)
|
|
79773
80214
|
}
|
|
79774
80215
|
}
|
|
79775
80216
|
};
|
|
@@ -82349,9 +82790,13 @@ async function loadFileSeedsIntoTwins(config2, fetchTwin2, options = {}) {
|
|
|
82349
82790
|
const loadingMarkerPath = getSeedLoadingMarkerPath(sessionKey);
|
|
82350
82791
|
const loadedMarkerPath = getSeedLoadedMarkerPath(sessionKey);
|
|
82351
82792
|
const markerDir = (0, import_node_path36.dirname)(loadedMarkerPath);
|
|
82793
|
+
const forceReload = options.forceReload === true;
|
|
82352
82794
|
(0, import_node_fs38.mkdirSync)(markerDir, { recursive: true, mode: 448 });
|
|
82795
|
+
if (forceReload) {
|
|
82796
|
+
(0, import_node_fs38.rmSync)(loadedMarkerPath, { force: true });
|
|
82797
|
+
}
|
|
82353
82798
|
while (true) {
|
|
82354
|
-
if ((0, import_node_fs38.existsSync)(loadedMarkerPath)) {
|
|
82799
|
+
if (!forceReload && (0, import_node_fs38.existsSync)(loadedMarkerPath)) {
|
|
82355
82800
|
return;
|
|
82356
82801
|
}
|
|
82357
82802
|
try {
|
|
@@ -82542,9 +82987,17 @@ function buildHostedTwinFetcher(cloudCloneUrls, bearerToken) {
|
|
|
82542
82987
|
throw new Error(`Timed out waiting for hosted clone ${serviceName} to accept file seeds.`);
|
|
82543
82988
|
};
|
|
82544
82989
|
}
|
|
82545
|
-
async function loadFileSeedsIntoHostedTwins(fileSeedPaths, cloudCloneUrls, bearerToken, sessionKey) {
|
|
82990
|
+
async function loadFileSeedsIntoHostedTwins(fileSeedPaths, cloudCloneUrls, bearerToken, sessionKey, options = {}) {
|
|
82546
82991
|
const config2 = sessionKey ? buildSerializedSeedConfigWithSessionKey(fileSeedPaths, sessionKey) : buildSerializedSeedConfig(fileSeedPaths);
|
|
82547
|
-
|
|
82992
|
+
const runtimeOptions = {
|
|
82993
|
+
...options.forceReload === true ? { forceReload: true } : {},
|
|
82994
|
+
...options.hostedSessionId ? { hostedSessionId: options.hostedSessionId } : {}
|
|
82995
|
+
};
|
|
82996
|
+
await loadFileSeedsIntoTwins(
|
|
82997
|
+
config2,
|
|
82998
|
+
buildHostedTwinFetcher(cloudCloneUrls, bearerToken),
|
|
82999
|
+
Object.keys(runtimeOptions).length > 0 ? runtimeOptions : void 0
|
|
83000
|
+
);
|
|
82548
83001
|
}
|
|
82549
83002
|
|
|
82550
83003
|
// src/runner/runtime-prereqs.ts
|
|
@@ -87981,6 +88434,18 @@ Run 'archal usage' to inspect the workspace pool, or open https://www.archal.ai/
|
|
|
87981
88434
|
}
|
|
87982
88435
|
|
|
87983
88436
|
// src/runner/hosted-session/readiness.ts
|
|
88437
|
+
var TRANSIENT_READINESS_DETAIL_PATTERNS = [
|
|
88438
|
+
/\btimed?\s*out\b/i,
|
|
88439
|
+
/\btimeout\b/i,
|
|
88440
|
+
/(HTTP |status[=:]\s*)50[234]\b/i,
|
|
88441
|
+
/upstream\s+returned\s+50[234]\b/i,
|
|
88442
|
+
/\bECONNRESET\b/i,
|
|
88443
|
+
/\bECONNREFUSED\b/i,
|
|
88444
|
+
/\bETIMEDOUT\b/i,
|
|
88445
|
+
/\bEAI_AGAIN\b/i,
|
|
88446
|
+
/network\s+(error|failure)/i,
|
|
88447
|
+
/temporarily unavailable/i
|
|
88448
|
+
];
|
|
87984
88449
|
function isHostedSessionRequestError(error49) {
|
|
87985
88450
|
return error49 instanceof HostedSessionRequestError || error49 instanceof Error && typeof error49.method === "string" && typeof error49.path === "string" && typeof error49.status === "number" && typeof error49.detail === "string";
|
|
87986
88451
|
}
|
|
@@ -87988,6 +88453,28 @@ function getHostedSessionErrorDetail(error49) {
|
|
|
87988
88453
|
const internalDetail = typeof error49.getInternalDetailForRetry === "function" ? error49.getInternalDetailForRetry() : void 0;
|
|
87989
88454
|
return internalDetail ?? error49.detail;
|
|
87990
88455
|
}
|
|
88456
|
+
function detailLooksTransient2(detail) {
|
|
88457
|
+
return TRANSIENT_READINESS_DETAIL_PATTERNS.some((pattern) => pattern.test(detail));
|
|
88458
|
+
}
|
|
88459
|
+
function isRetryableReadinessError(error49) {
|
|
88460
|
+
if (isHostedSessionRequestError(error49)) {
|
|
88461
|
+
if (error49.status === 408 || error49.status === 425 || error49.status === 429 || error49.status === 500 || error49.status === 502 || error49.status === 503 || error49.status === 504) {
|
|
88462
|
+
return true;
|
|
88463
|
+
}
|
|
88464
|
+
return detailLooksTransient2(getHostedSessionErrorDetail(error49));
|
|
88465
|
+
}
|
|
88466
|
+
const message = errorMessage(error49);
|
|
88467
|
+
if (message.startsWith("Hosted session timed out waiting for readiness")) {
|
|
88468
|
+
return true;
|
|
88469
|
+
}
|
|
88470
|
+
if (message.startsWith("Hosted session failed:")) {
|
|
88471
|
+
return detailLooksTransient2(message.slice("Hosted session failed:".length).trim());
|
|
88472
|
+
}
|
|
88473
|
+
if (message === "Hosted session failed") {
|
|
88474
|
+
return true;
|
|
88475
|
+
}
|
|
88476
|
+
return false;
|
|
88477
|
+
}
|
|
87991
88478
|
async function waitForSessionReady(opts) {
|
|
87992
88479
|
if (!opts.quiet) process.stderr.write("Starting cloud session...\n");
|
|
87993
88480
|
const startedAt = Date.now();
|
|
@@ -88020,6 +88507,7 @@ async function waitForSessionReady(opts) {
|
|
|
88020
88507
|
}
|
|
88021
88508
|
return {
|
|
88022
88509
|
ready: false,
|
|
88510
|
+
...isRetryableReadinessError(error49) ? { retryable: true } : {},
|
|
88023
88511
|
error: mapSessionStartError({
|
|
88024
88512
|
ok: false,
|
|
88025
88513
|
offline: false,
|
|
@@ -88031,10 +88519,19 @@ async function waitForSessionReady(opts) {
|
|
|
88031
88519
|
};
|
|
88032
88520
|
}
|
|
88033
88521
|
const message = errorMessage(error49);
|
|
88522
|
+
const retryable = isRetryableReadinessError(error49);
|
|
88034
88523
|
if (message.startsWith("Hosted session ")) {
|
|
88035
|
-
return {
|
|
88524
|
+
return {
|
|
88525
|
+
ready: false,
|
|
88526
|
+
...retryable ? { retryable: true } : {},
|
|
88527
|
+
error: `session ${message.slice("Hosted session ".length)}`
|
|
88528
|
+
};
|
|
88036
88529
|
}
|
|
88037
|
-
return {
|
|
88530
|
+
return {
|
|
88531
|
+
ready: false,
|
|
88532
|
+
...retryable ? { retryable: true } : {},
|
|
88533
|
+
error: `session poll failed: ${message}`
|
|
88534
|
+
};
|
|
88038
88535
|
}
|
|
88039
88536
|
const warmupSec = Math.round((Date.now() - startedAt) / 1e3);
|
|
88040
88537
|
if (!opts.quiet) process.stderr.write(`Cloud session ready (${warmupSec}s).
|
|
@@ -88546,6 +89043,7 @@ async function cleanupHostedSession(ctx) {
|
|
|
88546
89043
|
}
|
|
88547
89044
|
|
|
88548
89045
|
// src/runner/hosted-session-provisioning.ts
|
|
89046
|
+
var HOSTED_RUN_READINESS_ATTEMPTS = 2;
|
|
88549
89047
|
function isLegacyRunConfigTimeoutRejection(result) {
|
|
88550
89048
|
if (result.ok || result.status !== 400 || result.code !== "invalid_session_create_request") {
|
|
88551
89049
|
return false;
|
|
@@ -88571,6 +89069,16 @@ function withoutLegacyUnsupportedRunConfig(input) {
|
|
|
88571
89069
|
runConfig: Object.keys(runConfig).length > 0 ? runConfig : void 0
|
|
88572
89070
|
};
|
|
88573
89071
|
}
|
|
89072
|
+
async function bestEffortEndReadinessRetrySession(input) {
|
|
89073
|
+
const token = input.credentials?.token;
|
|
89074
|
+
if (!token || !input.sessionId) {
|
|
89075
|
+
return;
|
|
89076
|
+
}
|
|
89077
|
+
try {
|
|
89078
|
+
await endSession(token, input.sessionId);
|
|
89079
|
+
} catch {
|
|
89080
|
+
}
|
|
89081
|
+
}
|
|
88574
89082
|
function resolveProvisionedSessionConnectionMaps(input) {
|
|
88575
89083
|
const { sessionId, clones, endpoints, apiBaseUrls, runtimeBaseUrl } = input;
|
|
88576
89084
|
const fallbackConnections = runtimeBaseUrl ? buildRuntimeTwinUrls(sessionId, clones, runtimeBaseUrl) : { endpoints: {}, apiBaseUrls: {} };
|
|
@@ -88677,103 +89185,121 @@ async function provisionHostedRunSession(input) {
|
|
|
88677
89185
|
runProject: sessionStartConfig.runProject,
|
|
88678
89186
|
source: "run"
|
|
88679
89187
|
};
|
|
88680
|
-
|
|
88681
|
-
|
|
88682
|
-
|
|
88683
|
-
|
|
88684
|
-
|
|
88685
|
-
|
|
88686
|
-
|
|
88687
|
-
sessionResult = await ctx.inFlightSessionStart;
|
|
88688
|
-
} finally {
|
|
88689
|
-
ctx.inFlightSessionStart = null;
|
|
88690
|
-
}
|
|
88691
|
-
if (!sessionResult.ok && isLegacyRunConfigTimeoutRejection(sessionResult)) {
|
|
89188
|
+
for (let attempt = 0; attempt < HOSTED_RUN_READINESS_ATTEMPTS; attempt += 1) {
|
|
89189
|
+
cloudCloneUrls = void 0;
|
|
89190
|
+
hostedResolvedSeeds = void 0;
|
|
89191
|
+
hostedApiBaseUrlOverrides = void 0;
|
|
89192
|
+
ctx.backendSessionId = void 0;
|
|
89193
|
+
ctx.sessionWorkspaceId = null;
|
|
89194
|
+
const idempotencyKey = attempt === 0 ? sessionCreateIdempotencyKey : `${sessionCreateIdempotencyKey}:readiness-retry:${attempt}`;
|
|
88692
89195
|
ctx.inFlightSessionStart = startSession(
|
|
88693
89196
|
credentials?.token ?? "",
|
|
88694
|
-
|
|
88695
|
-
|
|
89197
|
+
sessionStartRequest,
|
|
89198
|
+
idempotencyKey
|
|
88696
89199
|
);
|
|
89200
|
+
let sessionResult;
|
|
88697
89201
|
try {
|
|
88698
89202
|
sessionResult = await ctx.inFlightSessionStart;
|
|
88699
89203
|
} finally {
|
|
88700
89204
|
ctx.inFlightSessionStart = null;
|
|
88701
89205
|
}
|
|
88702
|
-
|
|
88703
|
-
|
|
88704
|
-
|
|
88705
|
-
|
|
88706
|
-
|
|
88707
|
-
|
|
88708
|
-
|
|
88709
|
-
|
|
88710
|
-
|
|
88711
|
-
|
|
88712
|
-
|
|
88713
|
-
ctx.backendSessionId = sessionResult.data.sessionId;
|
|
88714
|
-
ctx.sessionWorkspaceId = sessionResult.data.workspace?.id ?? null;
|
|
88715
|
-
writeStatus({
|
|
88716
|
-
stage: "provisioning",
|
|
88717
|
-
sessionId: ctx.backendSessionId
|
|
88718
|
-
});
|
|
88719
|
-
emitSessionCreated({
|
|
88720
|
-
scenario,
|
|
88721
|
-
sessionId: ctx.backendSessionId,
|
|
88722
|
-
isReused: false
|
|
88723
|
-
});
|
|
88724
|
-
if (!opts.quiet) {
|
|
88725
|
-
printWorkspaceBreadcrumb({
|
|
88726
|
-
kind: "session-pushed",
|
|
88727
|
-
workspace: sessionResult.data.workspace ?? null
|
|
88728
|
-
});
|
|
88729
|
-
}
|
|
88730
|
-
const serverResolvedSeeds = sessionResult.data.resolvedSeeds ?? {};
|
|
88731
|
-
const { connections, missingClones } = resolveProvisionedSessionConnectionMaps({
|
|
88732
|
-
sessionId: ctx.backendSessionId,
|
|
88733
|
-
clones: scenario.config.twins,
|
|
88734
|
-
endpoints: sessionResult.data.endpoints,
|
|
88735
|
-
apiBaseUrls: sessionResult.data.apiBaseUrls,
|
|
88736
|
-
runtimeBaseUrl: getConfiguredRuntimeBaseUrl2()
|
|
88737
|
-
});
|
|
88738
|
-
if (missingClones.length > 0) {
|
|
88739
|
-
ctx.runFailureMessage = `Clone provisioning failed for: ${missingClones.join(", ")}. Try again or run: archal doctor`;
|
|
88740
|
-
}
|
|
88741
|
-
if (!ctx.runFailureMessage && Object.keys(connections.endpoints).length > 0) {
|
|
88742
|
-
cloudCloneUrls = connections.endpoints;
|
|
88743
|
-
hostedResolvedSeeds = serverResolvedSeeds;
|
|
88744
|
-
}
|
|
88745
|
-
if (!ctx.runFailureMessage && !opts.apiBaseUrls && Object.keys(connections.apiBaseUrls).length > 0) {
|
|
88746
|
-
hostedApiBaseUrlOverrides = connections.apiBaseUrls;
|
|
88747
|
-
}
|
|
88748
|
-
const enginePlan = engine.plan;
|
|
88749
|
-
if (!ctx.runFailureMessage && enginePlan.kind === "api" && !enginePlan.twinUrlsPath) {
|
|
88750
|
-
ctx.generatedTwinUrlMapPath = (0, import_node_path45.resolve)(
|
|
88751
|
-
`.archal-session-${ctx.backendSessionId}-engine-twin-urls.json`
|
|
88752
|
-
);
|
|
88753
|
-
const result = writeTempJsonMap(
|
|
88754
|
-
ctx.generatedTwinUrlMapPath,
|
|
88755
|
-
connections.endpoints,
|
|
88756
|
-
"engine clone URL map"
|
|
88757
|
-
);
|
|
88758
|
-
if (!result.ok) {
|
|
88759
|
-
ctx.runFailureMessage = result.error;
|
|
89206
|
+
if (!sessionResult.ok && isLegacyRunConfigTimeoutRejection(sessionResult)) {
|
|
89207
|
+
ctx.inFlightSessionStart = startSession(
|
|
89208
|
+
credentials?.token ?? "",
|
|
89209
|
+
withoutLegacyUnsupportedRunConfig(sessionStartRequest),
|
|
89210
|
+
idempotencyKey
|
|
89211
|
+
);
|
|
89212
|
+
try {
|
|
89213
|
+
sessionResult = await ctx.inFlightSessionStart;
|
|
89214
|
+
} finally {
|
|
89215
|
+
ctx.inFlightSessionStart = null;
|
|
89216
|
+
}
|
|
88760
89217
|
}
|
|
88761
|
-
|
|
88762
|
-
|
|
88763
|
-
|
|
89218
|
+
if (!sessionResult.ok) {
|
|
89219
|
+
ctx.runFailureMessage = mapSessionStartError(sessionResult);
|
|
89220
|
+
return {
|
|
89221
|
+
credentials,
|
|
89222
|
+
cloudCloneUrls,
|
|
89223
|
+
hostedResolvedSeeds,
|
|
89224
|
+
hostedApiBaseUrlOverrides
|
|
89225
|
+
};
|
|
89226
|
+
}
|
|
89227
|
+
credentials = getCredentials2() ?? credentials;
|
|
89228
|
+
ctx.backendSessionId = sessionResult.data.sessionId;
|
|
89229
|
+
ctx.sessionWorkspaceId = sessionResult.data.workspace?.id ?? null;
|
|
89230
|
+
writeStatus({
|
|
89231
|
+
stage: "provisioning",
|
|
89232
|
+
sessionId: ctx.backendSessionId
|
|
89233
|
+
});
|
|
89234
|
+
emitSessionCreated({
|
|
89235
|
+
scenario,
|
|
88764
89236
|
sessionId: ctx.backendSessionId,
|
|
88765
|
-
|
|
88766
|
-
|
|
88767
|
-
|
|
88768
|
-
|
|
88769
|
-
|
|
88770
|
-
|
|
88771
|
-
stage: "session_ready",
|
|
88772
|
-
sessionId: ctx.backendSessionId
|
|
89237
|
+
isReused: false
|
|
89238
|
+
});
|
|
89239
|
+
if (!opts.quiet) {
|
|
89240
|
+
printWorkspaceBreadcrumb({
|
|
89241
|
+
kind: "session-pushed",
|
|
89242
|
+
workspace: sessionResult.data.workspace ?? null
|
|
88773
89243
|
});
|
|
88774
|
-
} else {
|
|
88775
|
-
ctx.runFailureMessage = readyResult.error;
|
|
88776
89244
|
}
|
|
89245
|
+
const serverResolvedSeeds = sessionResult.data.resolvedSeeds ?? {};
|
|
89246
|
+
const { connections, missingClones } = resolveProvisionedSessionConnectionMaps({
|
|
89247
|
+
sessionId: ctx.backendSessionId,
|
|
89248
|
+
clones: scenario.config.twins,
|
|
89249
|
+
endpoints: sessionResult.data.endpoints,
|
|
89250
|
+
apiBaseUrls: sessionResult.data.apiBaseUrls,
|
|
89251
|
+
runtimeBaseUrl: getConfiguredRuntimeBaseUrl2()
|
|
89252
|
+
});
|
|
89253
|
+
if (missingClones.length > 0) {
|
|
89254
|
+
ctx.runFailureMessage = `Clone provisioning failed for: ${missingClones.join(", ")}. Try again or run: archal doctor`;
|
|
89255
|
+
}
|
|
89256
|
+
if (!ctx.runFailureMessage && Object.keys(connections.endpoints).length > 0) {
|
|
89257
|
+
cloudCloneUrls = connections.endpoints;
|
|
89258
|
+
hostedResolvedSeeds = serverResolvedSeeds;
|
|
89259
|
+
}
|
|
89260
|
+
if (!ctx.runFailureMessage && !opts.apiBaseUrls && Object.keys(connections.apiBaseUrls).length > 0) {
|
|
89261
|
+
hostedApiBaseUrlOverrides = connections.apiBaseUrls;
|
|
89262
|
+
}
|
|
89263
|
+
if (!ctx.runFailureMessage) {
|
|
89264
|
+
const readyResult = await waitForSessionReady({
|
|
89265
|
+
sessionId: ctx.backendSessionId,
|
|
89266
|
+
twins: scenario.config.twins,
|
|
89267
|
+
quiet: opts.quiet,
|
|
89268
|
+
credentials: credentials ?? { token: "" }
|
|
89269
|
+
});
|
|
89270
|
+
if (readyResult.ready) {
|
|
89271
|
+
const enginePlan = engine.plan;
|
|
89272
|
+
if (!ctx.runFailureMessage && enginePlan.kind === "api" && !enginePlan.twinUrlsPath) {
|
|
89273
|
+
ctx.generatedTwinUrlMapPath = (0, import_node_path45.resolve)(
|
|
89274
|
+
`.archal-session-${ctx.backendSessionId}-engine-twin-urls.json`
|
|
89275
|
+
);
|
|
89276
|
+
const result = writeTempJsonMap(
|
|
89277
|
+
ctx.generatedTwinUrlMapPath,
|
|
89278
|
+
connections.endpoints,
|
|
89279
|
+
"engine clone URL map"
|
|
89280
|
+
);
|
|
89281
|
+
if (!result.ok) {
|
|
89282
|
+
ctx.runFailureMessage = result.error;
|
|
89283
|
+
}
|
|
89284
|
+
}
|
|
89285
|
+
if (!ctx.runFailureMessage) {
|
|
89286
|
+
writeStatus({
|
|
89287
|
+
stage: "session_ready",
|
|
89288
|
+
sessionId: ctx.backendSessionId
|
|
89289
|
+
});
|
|
89290
|
+
}
|
|
89291
|
+
} else if (readyResult.retryable && attempt + 1 < HOSTED_RUN_READINESS_ATTEMPTS) {
|
|
89292
|
+
await bestEffortEndReadinessRetrySession({
|
|
89293
|
+
credentials,
|
|
89294
|
+
sessionId: ctx.backendSessionId
|
|
89295
|
+
});
|
|
89296
|
+
writeStatus({ stage: "provisioning" });
|
|
89297
|
+
continue;
|
|
89298
|
+
} else {
|
|
89299
|
+
ctx.runFailureMessage = readyResult.error;
|
|
89300
|
+
}
|
|
89301
|
+
}
|
|
89302
|
+
break;
|
|
88777
89303
|
}
|
|
88778
89304
|
return {
|
|
88779
89305
|
credentials,
|
|
@@ -89272,7 +89798,11 @@ async function executeRunForScenario(scenarioArg, opts, command, configDefaults,
|
|
|
89272
89798
|
fileSeedPaths,
|
|
89273
89799
|
cloudCloneUrls,
|
|
89274
89800
|
credentials?.token,
|
|
89275
|
-
ctx.backendSessionId ?? runId
|
|
89801
|
+
ctx.backendSessionId ?? runId,
|
|
89802
|
+
{
|
|
89803
|
+
forceReload: runOpts.freshSeed === true,
|
|
89804
|
+
...ctx.backendSessionId ? { hostedSessionId: ctx.backendSessionId } : {}
|
|
89805
|
+
}
|
|
89276
89806
|
);
|
|
89277
89807
|
info("File seeds loaded into clones");
|
|
89278
89808
|
} catch (err) {
|
|
@@ -92080,6 +92610,7 @@ init_ansi();
|
|
|
92080
92610
|
|
|
92081
92611
|
// src/commands/clone/shared.ts
|
|
92082
92612
|
init_src2();
|
|
92613
|
+
init_src();
|
|
92083
92614
|
init_auth();
|
|
92084
92615
|
init_api_client();
|
|
92085
92616
|
init_errors6();
|
|
@@ -92215,13 +92746,14 @@ function printReadyBanner(sessionId, twins, apiBaseUrls) {
|
|
|
92215
92746
|
continue;
|
|
92216
92747
|
}
|
|
92217
92748
|
const restUrl = toRestUrl(url2);
|
|
92218
|
-
const mcpUrl = toMcpUrl(url2);
|
|
92219
92749
|
process.stderr.write(`${GREEN}\u2713${RESET} ${BOLD}${twin}${RESET} clone ready
|
|
92220
92750
|
`);
|
|
92221
92751
|
process.stderr.write(` REST: ${CYAN}${restUrl}${RESET}
|
|
92222
92752
|
`);
|
|
92223
|
-
|
|
92753
|
+
if (supportsHostedCloneMcp(twin)) {
|
|
92754
|
+
process.stderr.write(` MCP: ${CYAN}${toMcpUrl(url2)}${RESET}
|
|
92224
92755
|
`);
|
|
92756
|
+
}
|
|
92225
92757
|
process.stderr.write(
|
|
92226
92758
|
` Control auth: ${DIM}x-route-authorization: Bearer $ARCHAL_TOKEN${RESET}
|
|
92227
92759
|
`
|
|
@@ -93917,7 +94449,7 @@ function buildOwnerTraceDetailUrl(baseUrl, rootTraceId) {
|
|
|
93917
94449
|
return `${trimmed}/v1/traces/root/${encodeURIComponent(rootTraceId)}`;
|
|
93918
94450
|
}
|
|
93919
94451
|
function isEvalTrace(trace) {
|
|
93920
|
-
return !trace.rootTraceId.startsWith("twin-session-");
|
|
94452
|
+
return !trace.rootTraceId.startsWith("session-proxy-") && !trace.rootTraceId.startsWith("twin-session-");
|
|
93921
94453
|
}
|
|
93922
94454
|
var LOCAL_RUN_ARTIFACTS_PATH = ".archal/cache/runs/";
|
|
93923
94455
|
var NO_REMOTE_TRACES_MESSAGE = `No remote traces found. If you just ran a scenario without remote trace upload, local run artifacts are under ${LOCAL_RUN_ARTIFACTS_PATH}.`;
|