archal 0.9.15 → 0.9.16

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.
@@ -6819,7 +6819,7 @@ __export(index_exports, {
6819
6819
  withArchal: () => withArchal
6820
6820
  });
6821
6821
  module.exports = __toCommonJS(index_exports);
6822
- var import_node_path13 = require("path");
6822
+ var import_node_path14 = require("path");
6823
6823
  var import_node_url4 = require("url");
6824
6824
 
6825
6825
  // ../runtime/src/auth-lease.ts
@@ -7736,16 +7736,37 @@ var SESSION_STOP_CONFIRM_MAX_ATTEMPTS = 40;
7736
7736
  var ARCHAL_WORKSPACE_HEADER = "x-archal-workspace";
7737
7737
  var SESSION_RESPONSE_SCOPE_HEADER = "x-archal-session-response";
7738
7738
  var CLI_SESSION_TRANSPORT_SCOPE = "cli-transport";
7739
+ var INFRASTRUCTURE_DETAIL_PATTERN = /(?:archal[-_\s]?(?:proxy|runtime|control[-_\s]?plane|service[-_\s]?gateway|openclaw[-_\s]?gateway)|control[-_\s]?plane|CLI_JWT_SECRET|CONTROL_PLANE|JWT_SECRET|ARCHAL_|runtime provider|runtime\/session|worker[-_\s]?endpoint|x[-_]?archal|service[-_\s]?gateway|service[-_\s]?runtime|provider[-_\s]?gateway|graphql[-_\s]?gateway|workflow[-_\s]?(?:runtime|harness|session)|harness[-_\s]?bootstrap|service_mcp_servers|\/service-gateway|tls intercept|sidecar|openclaw[-_\s]?gateway|credential_issuance_seed|hosted\s+clone|cloud(?:Clone|Twin)Urls|(?:clone|twin)[-_]access[-_]denied|twin[-_]not[-_]in[-_]catalog|pre[-_\s]?migration|stale[-_\s]?data)/i;
7740
+ function publicHostedSessionDetail(detail) {
7741
+ if (!detail?.trim()) {
7742
+ return "";
7743
+ }
7744
+ return INFRASTRUCTURE_DETAIL_PATTERN.test(detail) ? "service routing failed to prepare the requested services." : detail;
7745
+ }
7746
+ function hostedSessionRequestErrorMessage(method, path2, status, detail) {
7747
+ const publicDetail = publicHostedSessionDetail(detail);
7748
+ return `Hosted session request failed (${method} ${path2}, HTTP ${status}${publicDetail ? `: ${publicDetail}` : ""}).`;
7749
+ }
7739
7750
  var HostedSessionRequestError = class extends Error {
7740
7751
  constructor(method, path2, status, detail) {
7741
- super(
7742
- `Hosted session request failed (${method} ${path2}, HTTP ${status}${detail ? `: ${detail}` : ""}).`
7743
- );
7752
+ super(hostedSessionRequestErrorMessage(method, path2, status, detail));
7744
7753
  this.method = method;
7745
7754
  this.path = path2;
7746
7755
  this.status = status;
7747
- this.detail = detail;
7748
7756
  this.name = "HostedSessionRequestError";
7757
+ this.detail = publicHostedSessionDetail(detail);
7758
+ Object.defineProperty(this, "internalDetail", {
7759
+ value: detail,
7760
+ enumerable: false,
7761
+ configurable: false,
7762
+ writable: false
7763
+ });
7764
+ }
7765
+ detail;
7766
+ internalDetail;
7767
+ /** @internal */
7768
+ getInternalDetailForRetry() {
7769
+ return this.internalDetail;
7749
7770
  }
7750
7771
  };
7751
7772
  function trimEnv(name) {
@@ -7857,7 +7878,7 @@ function isTransientHostedSessionStartError(error95) {
7857
7878
  if (error95.status === 401 || error95.status === 429 || error95.status === 500 || error95.status === 502 || error95.status === 503 || error95.status === 504) {
7858
7879
  return true;
7859
7880
  }
7860
- return detailLooksTransient(error95.detail);
7881
+ return detailLooksTransient(error95.getInternalDetailForRetry());
7861
7882
  }
7862
7883
  if (error95 instanceof Error) {
7863
7884
  if (error95.message.startsWith("Hosted session timed out waiting for readiness")) {
@@ -53414,7 +53435,7 @@ function resolveRuntimeModuleFromFile(currentModuleFile2, relativePath, buildExt
53414
53435
  return (0, import_node_path5.resolve)((0, import_node_path5.dirname)(currentModuleFile2), relativePath.replace(/\.js$/, resolvedExtension));
53415
53436
  }
53416
53437
  function resolveRuntimeModule(relativePath, buildExtension) {
53417
- const currentModuleFile2 = typeof __filename === "string" ? __filename : (0, import_node_url.fileURLToPath)(__archal_import_meta_url);
53438
+ const currentModuleFile2 = typeof __filename === "string" && (0, import_node_path5.isAbsolute)(__filename) ? __filename : (0, import_node_url.fileURLToPath)(__archal_import_meta_url);
53418
53439
  return resolveRuntimeModuleFromFile(currentModuleFile2, relativePath, buildExtension);
53419
53440
  }
53420
53441
 
@@ -53700,6 +53721,7 @@ var RouteRuntimePolicyError = class extends Error {
53700
53721
 
53701
53722
  // ../route-runtime-core/src/runtime.ts
53702
53723
  var import_node_module = require("module");
53724
+ var import_node_path7 = require("path");
53703
53725
 
53704
53726
  // ../../twins/core/src/errors.ts
53705
53727
  function errorMessage4(error95) {
@@ -53951,7 +53973,7 @@ var discordRouteManifest = {
53951
53973
  ],
53952
53974
  diagnostics: {
53953
53975
  undeclared: ({ url: url3 }) => `Blocked Discord traffic to ${url3}. Declare discord in archalVitestProject({ services: { discord: { mode: "route" } } }) before calling the Discord REST API in Vitest.`,
53954
- declaredEscape: ({ url: url3, configuredBaseUrl }) => `Blocked Discord escape to ${url3}. Discord route mode is configured, but this domain is outside the approved Discord REST route surface. Configured twin base URL: ${configuredBaseUrl ?? "unknown"}.`,
53976
+ declaredEscape: ({ url: url3 }) => `Blocked Discord escape to ${url3}. Discord route mode is configured, but this domain is outside the approved Discord REST route surface.`,
53955
53977
  warning: ({ url: url3 }) => `Observed adjacent Discord domain ${url3}. Archal did not reroute this request because it is outside the approved Discord REST route surface.`
53956
53978
  },
53957
53979
  sdkIdentifiers: ["discord.js", "@discordjs/rest"],
@@ -53999,7 +54021,7 @@ var githubRouteManifest = {
53999
54021
  ],
54000
54022
  diagnostics: {
54001
54023
  undeclared: ({ url: url3 }) => `Blocked GitHub traffic to ${url3}. Declare github in archalVitestProject({ services: { github: { mode: "route" } } }) before using the official GitHub SDK.`,
54002
- declaredEscape: ({ url: url3, configuredBaseUrl }) => `Blocked GitHub escape to ${url3}. GitHub route mode is configured, but this domain is outside the primary routed GitHub surface. Configured twin base URL: ${configuredBaseUrl ?? "unknown"}.`,
54024
+ declaredEscape: ({ url: url3 }) => `Blocked GitHub escape to ${url3}. GitHub route mode is configured, but this domain is outside the primary routed GitHub surface.`,
54003
54025
  warning: ({ url: url3 }) => `Observed adjacent GitHub domain ${url3}. Archal did not reroute this request because it is outside the primary GitHub API route surface.`
54004
54026
  },
54005
54027
  sdkIdentifiers: ["@octokit/rest"],
@@ -54027,7 +54049,7 @@ var googleWorkspaceRouteManifest = {
54027
54049
  ],
54028
54050
  diagnostics: {
54029
54051
  undeclared: ({ url: url3 }) => `Blocked Google Workspace traffic to ${url3}. Declare google-workspace in archalVitestProject({ services: { 'google-workspace': { mode: "route" } } }) before using the official Google client.`,
54030
- declaredEscape: ({ url: url3, configuredBaseUrl }) => `Blocked Google Workspace escape to ${url3}. Google Workspace route mode is configured, but this domain is outside the primary routed surface. Configured twin base URL: ${configuredBaseUrl ?? "unknown"}.`,
54052
+ declaredEscape: ({ url: url3 }) => `Blocked Google Workspace escape to ${url3}. Google Workspace route mode is configured, but this domain is outside the primary routed surface.`,
54031
54053
  warning: ({ url: url3 }) => `Observed adjacent Google Workspace domain ${url3}. Archal did not reroute this request because it is outside the primary Google Workspace API route surface.`
54032
54054
  },
54033
54055
  sdkIdentifiers: ["googleapis"],
@@ -54049,7 +54071,7 @@ var apifyRouteManifest = {
54049
54071
  ],
54050
54072
  diagnostics: {
54051
54073
  undeclared: ({ url: url3 }) => `Blocked Apify traffic to ${url3}. Declare apify before using the official Apify client.`,
54052
- declaredEscape: ({ url: url3, configuredBaseUrl }) => `Blocked Apify escape to ${url3}. Apify route mode is configured, but this domain is outside the primary routed Apify API surface. Configured clone base URL: ${configuredBaseUrl ?? "unknown"}.`,
54074
+ declaredEscape: ({ url: url3 }) => `Blocked Apify escape to ${url3}. Apify route mode is configured, but this domain is outside the primary routed Apify API surface.`,
54053
54075
  warning: ({ url: url3 }) => `Observed adjacent Apify domain ${url3}. Archal did not reroute this request because it is outside the primary Apify API route surface.`
54054
54076
  },
54055
54077
  sdkIdentifiers: ["apify-client", "apify"],
@@ -54074,7 +54096,7 @@ var jiraRouteManifest = {
54074
54096
  ],
54075
54097
  diagnostics: {
54076
54098
  undeclared: ({ url: url3 }) => `Blocked Jira traffic to ${url3}. Declare jira in archalVitestProject({ services: { jira: { mode: "route" } } }) before using the official Jira SDK.`,
54077
- declaredEscape: ({ url: url3, configuredBaseUrl }) => `Blocked Jira escape to ${url3}. Jira route mode is configured, but this domain is outside the primary routed Jira surface. Configured twin base URL: ${configuredBaseUrl ?? "unknown"}.`,
54099
+ declaredEscape: ({ url: url3 }) => `Blocked Jira escape to ${url3}. Jira route mode is configured, but this domain is outside the primary routed Jira surface.`,
54078
54100
  warning: ({ url: url3 }) => `Observed adjacent Jira domain ${url3}. Archal did not reroute this request because it is outside the primary Jira route surface.`
54079
54101
  },
54080
54102
  sdkIdentifiers: ["jira.js"],
@@ -54095,7 +54117,7 @@ var linearRouteManifest = {
54095
54117
  ],
54096
54118
  diagnostics: {
54097
54119
  undeclared: ({ url: url3 }) => `Blocked Linear traffic to ${url3}. Declare linear in archalVitestProject({ services: { linear: { mode: "route" } } }) before using the official Linear SDK.`,
54098
- declaredEscape: ({ url: url3, configuredBaseUrl }) => `Blocked Linear escape to ${url3}. Linear route mode is configured, but this domain is outside the primary routed Linear API surface. Configured twin base URL: ${configuredBaseUrl ?? "unknown"}.`,
54120
+ declaredEscape: ({ url: url3 }) => `Blocked Linear escape to ${url3}. Linear route mode is configured, but this domain is outside the primary routed Linear API surface.`,
54099
54121
  warning: ({ url: url3 }) => `Observed adjacent Linear domain ${url3}. Archal did not reroute this request because it is outside the primary Linear API route surface.`
54100
54122
  },
54101
54123
  sdkIdentifiers: ["@linear/sdk"],
@@ -54117,7 +54139,7 @@ var rampRouteManifest = {
54117
54139
  ],
54118
54140
  diagnostics: {
54119
54141
  undeclared: ({ url: url3 }) => `Blocked Ramp traffic to ${url3}. Declare ramp in archalVitestProject({ services: { ramp: { mode: "route" } } }) before using the official Ramp client.`,
54120
- declaredEscape: ({ url: url3, configuredBaseUrl }) => `Blocked Ramp escape to ${url3}. Ramp route mode is configured, but this domain is outside the primary routed Ramp API surface. Configured twin base URL: ${configuredBaseUrl ?? "unknown"}.`,
54142
+ declaredEscape: ({ url: url3 }) => `Blocked Ramp escape to ${url3}. Ramp route mode is configured, but this domain is outside the primary routed Ramp API surface.`,
54121
54143
  warning: ({ url: url3 }) => `Observed adjacent Ramp domain ${url3}. Archal did not reroute this request because it is outside the primary Ramp API route surface.`
54122
54144
  },
54123
54145
  sdkIdentifiers: ["ramp"],
@@ -54150,7 +54172,7 @@ var slackRouteManifest = {
54150
54172
  ],
54151
54173
  diagnostics: {
54152
54174
  undeclared: ({ url: url3 }) => `Blocked Slack traffic to ${url3}. Declare slack in archalVitestProject({ services: { slack: { mode: "route" } } }) before using the official Slack SDK.`,
54153
- declaredEscape: ({ url: url3, configuredBaseUrl }) => `Blocked Slack escape to ${url3}. Slack route mode is configured, but this domain is outside the primary routed Slack surface. Configured twin base URL: ${configuredBaseUrl ?? "unknown"}.`,
54175
+ declaredEscape: ({ url: url3 }) => `Blocked Slack escape to ${url3}. Slack route mode is configured, but this domain is outside the primary routed Slack surface.`,
54154
54176
  warning: ({ url: url3 }) => `Observed adjacent Slack domain ${url3}. Archal did not reroute this request because it is outside the primary Slack API route surface.`
54155
54177
  },
54156
54178
  sdkIdentifiers: ["@slack/web-api"],
@@ -54218,7 +54240,7 @@ var stripeRouteManifest = {
54218
54240
  ],
54219
54241
  diagnostics: {
54220
54242
  undeclared: ({ url: url3 }) => `Blocked Stripe traffic to ${url3}. Declare stripe in archalVitestProject({ services: { stripe: { mode: "route" } } }) before using the official Stripe SDK.`,
54221
- declaredEscape: ({ url: url3, configuredBaseUrl }) => `Blocked Stripe escape to ${url3}. Stripe route mode is configured, but this Stripe-owned domain is outside the current routed surface. Configured twin base URL: ${configuredBaseUrl ?? "unknown"}.`,
54243
+ declaredEscape: ({ url: url3 }) => `Blocked Stripe escape to ${url3}. Stripe route mode is configured, but this Stripe-owned domain is outside the current routed surface.`,
54222
54244
  warning: ({ url: url3 }) => `Observed adjacent Stripe domain ${url3}. Archal did not reroute this request because it is outside the primary Stripe API route surface.`
54223
54245
  },
54224
54246
  runtimeSurface: stripeRuntimeSurface,
@@ -54241,7 +54263,7 @@ var supabaseRouteManifest = {
54241
54263
  ],
54242
54264
  diagnostics: {
54243
54265
  undeclared: ({ url: url3 }) => `Blocked Supabase traffic to ${url3}. Declare supabase in archalVitestProject({ services: { supabase: { mode: "route" } } }) before using the official Supabase SDK.`,
54244
- declaredEscape: ({ url: url3, configuredBaseUrl }) => `Blocked Supabase escape to ${url3}. Supabase route mode is configured, but this domain is outside the primary routed Supabase surface. Configured twin base URL: ${configuredBaseUrl ?? "unknown"}.`,
54266
+ declaredEscape: ({ url: url3 }) => `Blocked Supabase escape to ${url3}. Supabase route mode is configured, but this domain is outside the primary routed Supabase surface.`,
54245
54267
  warning: ({ url: url3 }) => `Observed adjacent Supabase domain ${url3}. Archal did not reroute this request because it is outside the primary Supabase route surface.`
54246
54268
  },
54247
54269
  sdkIdentifiers: ["@supabase/supabase-js"],
@@ -54263,7 +54285,7 @@ var tavilyRouteManifest = {
54263
54285
  ],
54264
54286
  diagnostics: {
54265
54287
  undeclared: ({ url: url3 }) => `Blocked Tavily traffic to ${url3}. Declare tavily before using the official Tavily client.`,
54266
- declaredEscape: ({ url: url3, configuredBaseUrl }) => `Blocked Tavily escape to ${url3}. Tavily route mode is configured, but this domain is outside the primary routed Tavily API surface. Configured clone base URL: ${configuredBaseUrl ?? "unknown"}.`,
54288
+ declaredEscape: ({ url: url3 }) => `Blocked Tavily escape to ${url3}. Tavily route mode is configured, but this domain is outside the primary routed Tavily API surface.`,
54267
54289
  warning: ({ url: url3 }) => `Observed adjacent Tavily domain ${url3}. Archal did not reroute this request because it is outside the primary Tavily API route surface.`
54268
54290
  },
54269
54291
  sdkIdentifiers: ["@tavily/core", "tavily"],
@@ -54307,10 +54329,25 @@ function buildServiceCompatibilityProfile(manifest) {
54307
54329
  }
54308
54330
 
54309
54331
  // ../route-runtime-core/src/runtime.ts
54310
- var require2 = (0, import_node_module.createRequire)(typeof __filename === "string" ? __filename : __archal_import_meta_url);
54332
+ var require2 = (0, import_node_module.createRequire)(
54333
+ typeof __filename === "string" && (0, import_node_path7.isAbsolute)(__filename) ? __filename : __archal_import_meta_url
54334
+ );
54311
54335
  var httpModule = require2("node:http");
54312
54336
  var httpsModule = require2("node:https");
54313
54337
  var SHARED_SERVICE_PROFILES = listSharedRouteManifests().map(buildServiceCompatibilityProfile);
54338
+ var CLIENT_VISIBLE_BLOCKED_REQUEST_MESSAGE = "Network request failed";
54339
+ function createClientVisibleNetworkError() {
54340
+ return new TypeError(CLIENT_VISIBLE_BLOCKED_REQUEST_MESSAGE);
54341
+ }
54342
+ function sanitizeClientVisibleNetworkError(error95) {
54343
+ const visibleError = error95;
54344
+ for (const key of Reflect.ownKeys(error95)) {
54345
+ delete visibleError[key];
54346
+ }
54347
+ error95.name = "TypeError";
54348
+ error95.message = CLIENT_VISIBLE_BLOCKED_REQUEST_MESSAGE;
54349
+ error95.stack = `${error95.name}: ${error95.message}`;
54350
+ }
54314
54351
  function now() {
54315
54352
  return (/* @__PURE__ */ new Date()).toISOString();
54316
54353
  }
@@ -54514,7 +54551,7 @@ var NodeRouteRuntime = class {
54514
54551
  response3 = await this.originalFetch(
54515
54552
  buildRoutedFetchRequest(originalRequest, decision.targetUrl, service, init)
54516
54553
  );
54517
- } catch (error95) {
54554
+ } catch {
54518
54555
  this.traceRequest({
54519
54556
  method,
54520
54557
  sourceUrl: sourceUrl.toString(),
@@ -54524,9 +54561,9 @@ var NodeRouteRuntime = class {
54524
54561
  outcome: "failed",
54525
54562
  reason: "network_error",
54526
54563
  targetUrl,
54527
- error: errorMessage4(error95)
54564
+ error: CLIENT_VISIBLE_BLOCKED_REQUEST_MESSAGE
54528
54565
  });
54529
- throw error95;
54566
+ throw createClientVisibleNetworkError();
54530
54567
  }
54531
54568
  this.traceRequest({
54532
54569
  method,
@@ -54550,7 +54587,7 @@ var NodeRouteRuntime = class {
54550
54587
  ...init,
54551
54588
  headers
54552
54589
  });
54553
- } catch (error95) {
54590
+ } catch {
54554
54591
  this.traceRequest({
54555
54592
  method,
54556
54593
  sourceUrl: sourceUrl.toString(),
@@ -54560,9 +54597,9 @@ var NodeRouteRuntime = class {
54560
54597
  outcome: "failed",
54561
54598
  reason: "network_error",
54562
54599
  targetUrl,
54563
- error: errorMessage4(error95)
54600
+ error: CLIENT_VISIBLE_BLOCKED_REQUEST_MESSAGE
54564
54601
  });
54565
- throw error95;
54602
+ throw createClientVisibleNetworkError();
54566
54603
  }
54567
54604
  this.traceRequest({
54568
54605
  method,
@@ -54972,28 +55009,29 @@ var NodeRouteRuntime = class {
54972
55009
  if (record3.target === "twin") {
54973
55010
  request.once("response", sanitizeIncomingResponseHeaders);
54974
55011
  }
54975
- if (!this.traceEnabled) {
54976
- return request;
54977
- }
54978
55012
  let settled = false;
54979
- request.once("response", (response) => {
54980
- settled = true;
54981
- this.traceRequest({
54982
- ...record3,
54983
- statusCode: response.statusCode,
54984
- statusText: response.statusMessage
55013
+ if (this.traceEnabled) {
55014
+ request.once("response", (response) => {
55015
+ settled = true;
55016
+ this.traceRequest({
55017
+ ...record3,
55018
+ statusCode: response.statusCode,
55019
+ statusText: response.statusMessage
55020
+ });
54985
55021
  });
54986
- });
55022
+ }
54987
55023
  request.once("error", (error95) => {
54988
- if (settled) {
54989
- return;
55024
+ if (this.traceEnabled && !settled) {
55025
+ this.traceRequest({
55026
+ ...record3,
55027
+ outcome: "failed",
55028
+ reason: "network_error",
55029
+ error: record3.target === "twin" ? CLIENT_VISIBLE_BLOCKED_REQUEST_MESSAGE : error95.message
55030
+ });
55031
+ }
55032
+ if (record3.target === "twin") {
55033
+ sanitizeClientVisibleNetworkError(error95);
54990
55034
  }
54991
- this.traceRequest({
54992
- ...record3,
54993
- outcome: "failed",
54994
- reason: "network_error",
54995
- error: error95.message
54996
- });
54997
55035
  });
54998
55036
  return request;
54999
55037
  }
@@ -74449,7 +74487,7 @@ var import_node_fs8 = require("fs");
74449
74487
  // ../../twins/core/src/seed-loader.ts
74450
74488
  var import_promises = require("fs/promises");
74451
74489
  var import_node_fs7 = require("fs");
74452
- var import_node_path7 = require("path");
74490
+ var import_node_path8 = require("path");
74453
74491
  var import_node_url2 = require("url");
74454
74492
 
74455
74493
  // ../../twins/core/src/mcp/mcp-handler-runtime.ts
@@ -74458,12 +74496,12 @@ var import_node_perf_hooks = require("perf_hooks");
74458
74496
 
74459
74497
  // ../../twins/core/src/fixture-oracle.ts
74460
74498
  var import_node_fs9 = require("fs");
74461
- var import_node_path8 = require("path");
74499
+ var import_node_path9 = require("path");
74462
74500
  var import_node_url3 = require("url");
74463
74501
 
74464
74502
  // ../../twins/core/src/run-twin-cli.ts
74465
74503
  var import_node_fs10 = require("fs");
74466
- var import_node_path9 = require("path");
74504
+ var import_node_path10 = require("path");
74467
74505
 
74468
74506
  // ../../twins/manifest.json
74469
74507
  var manifest_default2 = [
@@ -74940,7 +74978,7 @@ var SCENARIO_RISK_TAXONOMY2 = SCENARIO_RISK_RULES2.map(
74940
74978
  var import_node_crypto10 = require("crypto");
74941
74979
  var import_node_fs11 = require("fs");
74942
74980
  var import_node_os4 = require("os");
74943
- var import_node_path10 = require("path");
74981
+ var import_node_path11 = require("path");
74944
74982
  var RecordingManifestEntrySchema2 = external_exports4.object({
74945
74983
  filename: external_exports4.string(),
74946
74984
  sha256: external_exports4.string().regex(/^[0-9a-f]{64}$/, "sha256 must be 64 lowercase hex chars"),
@@ -74963,7 +75001,7 @@ var RecordingManifestSchema2 = external_exports4.object({
74963
75001
  entries: external_exports4.array(RecordingManifestEntrySchema2)
74964
75002
  }).loose();
74965
75003
  var DEFAULT_BASE_URL2 = process.env["ARCHAL_FIXTURE_BASE_URL"] ?? "https://archalforge8f96908966.blob.core.windows.net/archal-fixture-artifacts?sv=2023-11-03&spr=https&se=2031-05-10T00%3A00%3A00Z&sr=c&sp=rl&sig=r3%2FC3EwzilSHls8z3Pn5ZR%2BkinwQw1C6%2BDKObIZSIu0%3D";
74966
- var DEFAULT_CACHE_ROOT2 = process.env["ARCHAL_FIXTURE_CACHE_ROOT"] ?? (0, import_node_path10.resolve)((0, import_node_os4.homedir)(), ".archal", "forge", "recordings-cache");
75004
+ var DEFAULT_CACHE_ROOT2 = process.env["ARCHAL_FIXTURE_CACHE_ROOT"] ?? (0, import_node_path11.resolve)((0, import_node_os4.homedir)(), ".archal", "forge", "recordings-cache");
74967
75005
  function warnIfSasExpiresSoon2(baseUrl) {
74968
75006
  if (process.env["ARCHAL_FIXTURE_SAS_WARN"] === "0") return;
74969
75007
  const queryIdx = baseUrl.indexOf("?");
@@ -75016,7 +75054,7 @@ function resolveArchalVitestServiceProfiles(services) {
75016
75054
  var import_node_crypto12 = require("crypto");
75017
75055
  var import_node_child_process2 = require("child_process");
75018
75056
  var import_node_fs12 = require("fs");
75019
- var import_node_path11 = require("path");
75057
+ var import_node_path12 = require("path");
75020
75058
  var import_node_os5 = require("os");
75021
75059
 
75022
75060
  // src/url-resolution.ts
@@ -75070,16 +75108,16 @@ function toSafeCoordinatorDirectoryName(sessionKey) {
75070
75108
  return `${slug2 || "session"}-${hash3}`;
75071
75109
  }
75072
75110
  function resolveCoordinatorPaths(config3) {
75073
- const baseDirectory = (0, import_node_path11.resolve)(
75074
- trimEnv("ARCHAL_VITEST_COORDINATOR_DIR") ?? (0, import_node_path11.join)((0, import_node_os5.tmpdir)(), "archal-vitest")
75111
+ const baseDirectory = (0, import_node_path12.resolve)(
75112
+ trimEnv("ARCHAL_VITEST_COORDINATOR_DIR") ?? (0, import_node_path12.join)((0, import_node_os5.tmpdir)(), "archal-vitest")
75075
75113
  );
75076
75114
  const sessionKey = config3.sessionKey ?? `${config3.projectName}-${(0, import_node_crypto12.randomUUID)()}`;
75077
- const directory = (0, import_node_path11.resolve)(baseDirectory, toSafeCoordinatorDirectoryName(sessionKey));
75115
+ const directory = (0, import_node_path12.resolve)(baseDirectory, toSafeCoordinatorDirectoryName(sessionKey));
75078
75116
  return {
75079
75117
  directory,
75080
- lockDirectory: (0, import_node_path11.join)(directory, "lock"),
75081
- statePath: (0, import_node_path11.join)(directory, "state.json"),
75082
- reaperPidPath: (0, import_node_path11.join)(directory, "reaper.pid")
75118
+ lockDirectory: (0, import_node_path12.join)(directory, "lock"),
75119
+ statePath: (0, import_node_path12.join)(directory, "state.json"),
75120
+ reaperPidPath: (0, import_node_path12.join)(directory, "reaper.pid")
75083
75121
  };
75084
75122
  }
75085
75123
  function shouldStopSessionOnRelease() {
@@ -75935,7 +75973,7 @@ function isTruthyEnv(value) {
75935
75973
  }
75936
75974
  function formatTraceRecord(record3) {
75937
75975
  const manifestStatus = record3.manifestMatched ? `matched ${record3.service ?? "manifest"}` : "no manifest match";
75938
- const destination = record3.target === "twin" ? `twin${record3.targetUrl ? ` ${record3.targetUrl}` : ""}` : record3.target === "upstream" ? "real upstream" : "blocked";
75976
+ const destination = record3.target === "twin" ? "service endpoint" : record3.target === "upstream" ? "real upstream" : "blocked";
75939
75977
  const status = record3.statusCode === void 0 ? record3.error ? `error=${record3.error}` : "no status" : `${record3.statusCode}${record3.statusText ? ` ${record3.statusText}` : ""}`;
75940
75978
  return `\x1B[2m[archal:route] ${record3.method} ${record3.sourceUrl} | ${manifestStatus} | ${record3.outcome} -> ${destination} | ${status}\x1B[0m
75941
75979
  `;
@@ -76571,12 +76609,12 @@ var ArchalReporter = class {
76571
76609
  // src/seed-files.ts
76572
76610
  var import_node_crypto13 = require("crypto");
76573
76611
  var import_node_fs13 = require("fs");
76574
- var import_node_path12 = require("path");
76612
+ var import_node_path13 = require("path");
76575
76613
  var MAX_SEED_FILE_BYTES = 256 * 1024;
76576
76614
  function classifySeed(value) {
76577
76615
  const trimmed = value.trim();
76578
76616
  if (trimmed.startsWith("./") || trimmed.startsWith("../") || trimmed.startsWith("/")) {
76579
- const ext = (0, import_node_path12.extname)(trimmed).toLowerCase();
76617
+ const ext = (0, import_node_path13.extname)(trimmed).toLowerCase();
76580
76618
  if (ext === ".json") return { type: "file", path: trimmed, format: "json" };
76581
76619
  if (ext === ".md") return { type: "file", path: trimmed, format: "markdown" };
76582
76620
  throw new Error(
@@ -76586,14 +76624,14 @@ function classifySeed(value) {
76586
76624
  );
76587
76625
  }
76588
76626
  if (trimmed.endsWith(".json") || trimmed.endsWith(".md")) {
76589
- const ext = (0, import_node_path12.extname)(trimmed).toLowerCase();
76627
+ const ext = (0, import_node_path13.extname)(trimmed).toLowerCase();
76590
76628
  const format = ext === ".json" ? "json" : "markdown";
76591
76629
  return { type: "file", path: trimmed, format };
76592
76630
  }
76593
76631
  return { type: "named", name: trimmed };
76594
76632
  }
76595
76633
  function readSeedFile(seedPath, serviceName) {
76596
- const resolved = (0, import_node_path12.resolve)(seedPath);
76634
+ const resolved = (0, import_node_path13.resolve)(seedPath);
76597
76635
  if (!(0, import_node_fs13.existsSync)(resolved)) {
76598
76636
  throw new Error(
76599
76637
  `Seed file not found for ${serviceName}: ${resolved}
@@ -76708,8 +76746,8 @@ var DEFAULT_EXCLUDE_PATTERNS = [
76708
76746
  ];
76709
76747
  var ARCHAL_VITEST_WIRING_MARKER_ENV = "ARCHAL_VITEST_WIRING_MARKER";
76710
76748
  var ARCHAL_VITEST_WORKSPACE_REPORTER_MARKER_ENV = "ARCHAL_VITEST_WORKSPACE_REPORTER_MARKER";
76711
- var currentModuleFile = typeof __filename === "string" ? __filename : (0, import_node_url4.fileURLToPath)(__archal_import_meta_url);
76712
- var reporterEntryModule = (0, import_node_path13.resolve)((0, import_node_path13.dirname)(currentModuleFile), "../reporter-entry.js");
76749
+ var currentModuleFile = typeof __filename === "string" && (0, import_node_path14.isAbsolute)(__filename) ? __filename : (0, import_node_url4.fileURLToPath)(__archal_import_meta_url);
76750
+ var reporterEntryModule = (0, import_node_path14.resolve)((0, import_node_path14.dirname)(currentModuleFile), "../reporter-entry.js");
76713
76751
  function buildTestConfig(options, testOptions) {
76714
76752
  markHelperCalled();
76715
76753
  assertSupportedArchalVitestServices(options.services);
@@ -54,7 +54,7 @@ interface ArchalRuntime {
54
54
  * can impersonate the developer for the life of the token.
55
55
  *
56
56
  * Userland should never need the auth header — the route-mode runtime
57
- * injects it directly into outbound twin requests without routing through
57
+ * injects it directly into outbound clone requests without routing through
58
58
  * userland code. The redacted snapshot exposes just the metadata tests
59
59
  * legitimately need: session id, service names, base URLs, resolved seeds,
60
60
  * manifest versions.
@@ -8,15 +8,15 @@ import {
8
8
  readArchalVitestConfig,
9
9
  resetArchalClones,
10
10
  resolveRuntimeModule
11
- } from "./chunk-2GY4SFKE.js";
11
+ } from "./chunk-FU2VLK75.js";
12
12
  import {
13
13
  encodeConfig,
14
14
  getCredentials,
15
15
  getSessionIdFilePath
16
- } from "./chunk-WVRVNHAX.js";
16
+ } from "./chunk-CJJ32YQF.js";
17
17
 
18
18
  // src/index.ts
19
- import { dirname, resolve as resolve2 } from "path";
19
+ import { dirname, isAbsolute, resolve as resolve2 } from "path";
20
20
  import { fileURLToPath } from "url";
21
21
  import { defineProject } from "vitest/config";
22
22
 
@@ -865,7 +865,7 @@ var DEFAULT_EXCLUDE_PATTERNS = [
865
865
  ];
866
866
  var ARCHAL_VITEST_WIRING_MARKER_ENV = "ARCHAL_VITEST_WIRING_MARKER";
867
867
  var ARCHAL_VITEST_WORKSPACE_REPORTER_MARKER_ENV = "ARCHAL_VITEST_WORKSPACE_REPORTER_MARKER";
868
- var currentModuleFile = typeof __filename === "string" ? __filename : fileURLToPath(import.meta.url);
868
+ var currentModuleFile = typeof __filename === "string" && isAbsolute(__filename) ? __filename : fileURLToPath(import.meta.url);
869
869
  var reporterEntryModule = resolve2(dirname(currentModuleFile), "../reporter-entry.js");
870
870
  function buildTestConfig(options, testOptions) {
871
871
  markHelperCalled();
@@ -4,7 +4,7 @@ import {
4
4
  createHostedAuthLease,
5
5
  parsePositiveInteger,
6
6
  runHostedSessionReaper
7
- } from "../chunk-WVRVNHAX.js";
7
+ } from "../chunk-CJJ32YQF.js";
8
8
 
9
9
  // src/runtime/hosted-session-reaper.ts
10
10
  var VITEST_AUTH_LEASE_OPTIONS = {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  bootstrapArchalVitestRouting
3
- } from "../chunk-2GY4SFKE.js";
4
- import "../chunk-WVRVNHAX.js";
3
+ } from "../chunk-FU2VLK75.js";
4
+ import "../chunk-CJJ32YQF.js";
5
5
 
6
6
  // src/runtime/setup-files.ts
7
7
  import { existsSync, rmSync } from "fs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "archal",
3
- "version": "0.9.15",
3
+ "version": "0.9.16",
4
4
  "description": "Test your agents & integrations against service clones",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -40,7 +40,7 @@
40
40
  "vitest"
41
41
  ],
42
42
  "engines": {
43
- "node": ">=22"
43
+ "node": ">=20.20"
44
44
  },
45
45
  "files": [
46
46
  "bin",
@@ -28,7 +28,7 @@ AGENT_TASK="Reply with OK and do not use tools." node ./.archal/harness.mjs
28
28
 
29
29
  A wired harness that exits cleanly with no service calls is ready. If it says the starter harness is still a stub, edit `.archal/harness.mjs` to call the user's Cursor, Codex, Claude Code, or custom agent first. Other failures catch: no runnable entrypoint, UI-boot assumptions, missing provider keys, service bridge misconfig.
30
30
 
31
- If a local harness returns text but records zero clone-observed calls, check for real-service auth signals such as `api.github.com` plus `401`/`Bad credentials`. That means the harness did not reach the clone. Fix by running the SDK under sandbox/Docker routing, or by wiring the SDK to the clone REST URL pattern shown by `archal clone start <service>` / `archal clone status` and authenticating with `ARCHAL_TOKEN`.
31
+ If a local harness returns text but records zero clone-observed calls, check for real-service auth signals such as `api.github.com` plus `401`/`Bad credentials`. That means the harness did not reach the clone. Fix by running the SDK under sandbox/Docker routing, or by reading `AGENT_CLONE_URLS` for clone REST URLs and adding the JSON headers from `AGENT_ROUTE_HEADERS` to clone requests.
32
32
 
33
33
  ## Running
34
34
 
@@ -85,7 +85,7 @@ Confirm detected clones, then ask which of these the user wants. Each delegates
85
85
  - `"agent": { "command": "node", "args": ["./agent.js"] }` - plain Node script
86
86
  - `"agent": { "command": "python", "args": ["agent.py"] }` - Python agent
87
87
 
88
- If the user doesn't have a harness yet, prefer `npx archal init`; it creates `./.archal/harness.mjs`, points `.archal.json` at it, and adds a starter scenario without overwriting existing files. The generated harness is a guarded stub: Archal refuses to score it until the user edits it to call their Cursor, Codex, Claude Code, or custom agent. A custom harness should read `AGENT_TASK` from env, call the agent runtime, print `{ "text": "..." }` to stdout, and call `reportAgentMetrics()` from `archal/harness` with accumulated `{ inputTokens, outputTokens, llmCallCount }` before exit. Service clients need one explicit routing mode: use sandbox/Docker routing when the harness calls normal service URLs such as `https://api.github.com`, or configure SDK base URLs to the clone REST URL pattern shown by `archal clone start <service>` / `archal clone status` and authenticate those requests with `ARCHAL_TOKEN`. Alternative: skip `agent` in `.archal.json` and pass `--harness <path>` per-run.
88
+ If the user doesn't have a harness yet, prefer `npx archal init`; it creates `./.archal/harness.mjs`, points `.archal.json` at it, and adds a starter scenario without overwriting existing files. The generated harness is a guarded stub: Archal refuses to score it until the user edits it to call their Cursor, Codex, Claude Code, or custom agent. A custom harness should read `AGENT_TASK` from env, call the agent runtime, print `{ "text": "..." }` to stdout, and call `reportAgentMetrics()` from `archal/harness` with accumulated `{ inputTokens, outputTokens, llmCallCount }` before exit. Service clients need one explicit routing mode: use sandbox/Docker routing when the harness calls normal service URLs such as `https://api.github.com`, or configure SDK base URLs from `AGENT_CLONE_URLS` and add the JSON headers from `AGENT_ROUTE_HEADERS` to those clone requests. Alternative: skip `agent` in `.archal.json` and pass `--harness <path>` per-run.
89
89
 
90
90
  ### Option A - Evaluate an agent with scenarios
91
91