archal 0.9.18 → 0.9.19

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.
@@ -2982,7 +2982,7 @@ var require_compile2 = __commonJS({
2982
2982
  const schOrFunc = root.refs[ref2];
2983
2983
  if (schOrFunc)
2984
2984
  return schOrFunc;
2985
- let _sch = resolve10.call(this, root, ref2);
2985
+ let _sch = resolve12.call(this, root, ref2);
2986
2986
  if (_sch === void 0) {
2987
2987
  const schema = (_a3 = root.localRefs) === null || _a3 === void 0 ? void 0 : _a3[ref2];
2988
2988
  const { schemaId } = this.opts;
@@ -3009,7 +3009,7 @@ var require_compile2 = __commonJS({
3009
3009
  function sameSchemaEnv(s1, s2) {
3010
3010
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
3011
3011
  }
3012
- function resolve10(root, ref2) {
3012
+ function resolve12(root, ref2) {
3013
3013
  let sch;
3014
3014
  while (typeof (sch = this.refs[ref2]) == "string")
3015
3015
  ref2 = sch;
@@ -3584,55 +3584,55 @@ var require_fast_uri2 = __commonJS({
3584
3584
  }
3585
3585
  return uri;
3586
3586
  }
3587
- function resolve10(baseURI, relativeURI, options) {
3587
+ function resolve12(baseURI, relativeURI, options) {
3588
3588
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
3589
3589
  const resolved = resolveComponent(parse8(baseURI, schemelessOptions), parse8(relativeURI, schemelessOptions), schemelessOptions, true);
3590
3590
  schemelessOptions.skipEscape = true;
3591
3591
  return serialize(resolved, schemelessOptions);
3592
3592
  }
3593
- function resolveComponent(base, relative2, options, skipNormalization) {
3593
+ function resolveComponent(base, relative4, options, skipNormalization) {
3594
3594
  const target = {};
3595
3595
  if (!skipNormalization) {
3596
3596
  base = parse8(serialize(base, options), options);
3597
- relative2 = parse8(serialize(relative2, options), options);
3597
+ relative4 = parse8(serialize(relative4, options), options);
3598
3598
  }
3599
3599
  options = options || {};
3600
- if (!options.tolerant && relative2.scheme) {
3601
- target.scheme = relative2.scheme;
3602
- target.userinfo = relative2.userinfo;
3603
- target.host = relative2.host;
3604
- target.port = relative2.port;
3605
- target.path = removeDotSegments(relative2.path || "");
3606
- target.query = relative2.query;
3600
+ if (!options.tolerant && relative4.scheme) {
3601
+ target.scheme = relative4.scheme;
3602
+ target.userinfo = relative4.userinfo;
3603
+ target.host = relative4.host;
3604
+ target.port = relative4.port;
3605
+ target.path = removeDotSegments(relative4.path || "");
3606
+ target.query = relative4.query;
3607
3607
  } else {
3608
- if (relative2.userinfo !== void 0 || relative2.host !== void 0 || relative2.port !== void 0) {
3609
- target.userinfo = relative2.userinfo;
3610
- target.host = relative2.host;
3611
- target.port = relative2.port;
3612
- target.path = removeDotSegments(relative2.path || "");
3613
- target.query = relative2.query;
3608
+ if (relative4.userinfo !== void 0 || relative4.host !== void 0 || relative4.port !== void 0) {
3609
+ target.userinfo = relative4.userinfo;
3610
+ target.host = relative4.host;
3611
+ target.port = relative4.port;
3612
+ target.path = removeDotSegments(relative4.path || "");
3613
+ target.query = relative4.query;
3614
3614
  } else {
3615
- if (!relative2.path) {
3615
+ if (!relative4.path) {
3616
3616
  target.path = base.path;
3617
- if (relative2.query !== void 0) {
3618
- target.query = relative2.query;
3617
+ if (relative4.query !== void 0) {
3618
+ target.query = relative4.query;
3619
3619
  } else {
3620
3620
  target.query = base.query;
3621
3621
  }
3622
3622
  } else {
3623
- if (relative2.path[0] === "/") {
3624
- target.path = removeDotSegments(relative2.path);
3623
+ if (relative4.path[0] === "/") {
3624
+ target.path = removeDotSegments(relative4.path);
3625
3625
  } else {
3626
3626
  if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) {
3627
- target.path = "/" + relative2.path;
3627
+ target.path = "/" + relative4.path;
3628
3628
  } else if (!base.path) {
3629
- target.path = relative2.path;
3629
+ target.path = relative4.path;
3630
3630
  } else {
3631
- target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative2.path;
3631
+ target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative4.path;
3632
3632
  }
3633
3633
  target.path = removeDotSegments(target.path);
3634
3634
  }
3635
- target.query = relative2.query;
3635
+ target.query = relative4.query;
3636
3636
  }
3637
3637
  target.userinfo = base.userinfo;
3638
3638
  target.host = base.host;
@@ -3640,7 +3640,7 @@ var require_fast_uri2 = __commonJS({
3640
3640
  }
3641
3641
  target.scheme = base.scheme;
3642
3642
  }
3643
- target.fragment = relative2.fragment;
3643
+ target.fragment = relative4.fragment;
3644
3644
  return target;
3645
3645
  }
3646
3646
  function equal(uriA, uriB, options) {
@@ -3811,7 +3811,7 @@ var require_fast_uri2 = __commonJS({
3811
3811
  var fastUri = {
3812
3812
  SCHEMES,
3813
3813
  normalize,
3814
- resolve: resolve10,
3814
+ resolve: resolve12,
3815
3815
  resolveComponent,
3816
3816
  equal,
3817
3817
  serialize,
@@ -6819,7 +6819,7 @@ __export(index_exports, {
6819
6819
  withArchal: () => withArchal
6820
6820
  });
6821
6821
  module.exports = __toCommonJS(index_exports);
6822
- var import_node_path14 = require("path");
6822
+ var import_node_path15 = require("path");
6823
6823
  var import_node_url4 = require("url");
6824
6824
 
6825
6825
  // ../runtime/src/auth-lease.ts
@@ -7390,8 +7390,9 @@ var GENERATED_TWIN_CATALOG = [
7390
7390
  icon: "AP",
7391
7391
  name: "Apify",
7392
7392
  description: "Actors, runs, datasets, key-value stores, and request queues.",
7393
- toolCount: 45,
7394
- transport: "rest"
7393
+ toolCount: 43,
7394
+ transport: "rest",
7395
+ opsCoverage: null
7395
7396
  },
7396
7397
  {
7397
7398
  id: "discord",
@@ -7399,7 +7400,17 @@ var GENERATED_TWIN_CATALOG = [
7399
7400
  name: "Discord",
7400
7401
  description: "Guilds, channels, messages, webhooks, threads, commands, and interaction responses.",
7401
7402
  toolCount: 67,
7402
- transport: "both"
7403
+ transport: "both",
7404
+ opsCoverage: 14
7405
+ },
7406
+ {
7407
+ id: "firecrawl",
7408
+ icon: "FC",
7409
+ name: "Firecrawl",
7410
+ description: "Scraping, crawling, mapping, search, and extraction.",
7411
+ toolCount: 6,
7412
+ transport: "rest",
7413
+ opsCoverage: 77
7403
7414
  },
7404
7415
  {
7405
7416
  id: "github",
@@ -7407,7 +7418,8 @@ var GENERATED_TWIN_CATALOG = [
7407
7418
  name: "GitHub",
7408
7419
  description: "Repos, issues, pull requests, branches, and commits.",
7409
7420
  toolCount: 26,
7410
- transport: "both"
7421
+ transport: "both",
7422
+ opsCoverage: 96
7411
7423
  },
7412
7424
  {
7413
7425
  id: "google-workspace",
@@ -7415,7 +7427,17 @@ var GENERATED_TWIN_CATALOG = [
7415
7427
  name: "Google Workspace",
7416
7428
  description: "Gmail, Calendar, Drive, Sheets, and Contacts.",
7417
7429
  toolCount: 249,
7418
- transport: "both"
7430
+ transport: "both",
7431
+ opsCoverage: 64
7432
+ },
7433
+ {
7434
+ id: "hubspot",
7435
+ icon: "HS",
7436
+ name: "HubSpot",
7437
+ description: "CRM contacts, companies, deals, tickets, and engagements.",
7438
+ toolCount: 45,
7439
+ transport: "rest",
7440
+ opsCoverage: 10
7419
7441
  },
7420
7442
  {
7421
7443
  id: "jira",
@@ -7423,7 +7445,8 @@ var GENERATED_TWIN_CATALOG = [
7423
7445
  name: "Jira",
7424
7446
  description: "Issues, projects, boards, sprints, and versions.",
7425
7447
  toolCount: 49,
7426
- transport: "both"
7448
+ transport: "both",
7449
+ opsCoverage: 80
7427
7450
  },
7428
7451
  {
7429
7452
  id: "linear",
@@ -7431,7 +7454,8 @@ var GENERATED_TWIN_CATALOG = [
7431
7454
  name: "Linear",
7432
7455
  description: "Issues, projects, teams, cycles, and workflows.",
7433
7456
  toolCount: 42,
7434
- transport: "both"
7457
+ transport: "both",
7458
+ opsCoverage: 98
7435
7459
  },
7436
7460
  {
7437
7461
  id: "ramp",
@@ -7439,7 +7463,17 @@ var GENERATED_TWIN_CATALOG = [
7439
7463
  name: "Ramp",
7440
7464
  description: "Cards, funds, expenses, reimbursements, bills, and travel.",
7441
7465
  toolCount: 46,
7442
- transport: "mcp"
7466
+ transport: "mcp",
7467
+ opsCoverage: null
7468
+ },
7469
+ {
7470
+ id: "sendgrid",
7471
+ icon: "SG",
7472
+ name: "SendGrid",
7473
+ description: "Mail send, contacts, lists, templates, and stats.",
7474
+ toolCount: 28,
7475
+ transport: "rest",
7476
+ opsCoverage: 100
7443
7477
  },
7444
7478
  {
7445
7479
  id: "slack",
@@ -7447,7 +7481,8 @@ var GENERATED_TWIN_CATALOG = [
7447
7481
  name: "Slack",
7448
7482
  description: "Channels, messages, threads, users, and reactions.",
7449
7483
  toolCount: 8,
7450
- transport: "both"
7484
+ transport: "both",
7485
+ opsCoverage: 100
7451
7486
  },
7452
7487
  {
7453
7488
  id: "stripe",
@@ -7455,7 +7490,8 @@ var GENERATED_TWIN_CATALOG = [
7455
7490
  name: "Stripe",
7456
7491
  description: "Customers, payments, subscriptions, invoices, and refunds.",
7457
7492
  toolCount: 28,
7458
- transport: "both"
7493
+ transport: "both",
7494
+ opsCoverage: null
7459
7495
  },
7460
7496
  {
7461
7497
  id: "supabase",
@@ -7463,7 +7499,8 @@ var GENERATED_TWIN_CATALOG = [
7463
7499
  name: "Supabase",
7464
7500
  description: "SQL, migrations, logs, branches, and project metadata.",
7465
7501
  toolCount: 29,
7466
- transport: "both"
7502
+ transport: "both",
7503
+ opsCoverage: 100
7467
7504
  },
7468
7505
  {
7469
7506
  id: "tavily",
@@ -7471,7 +7508,35 @@ var GENERATED_TWIN_CATALOG = [
7471
7508
  name: "Tavily",
7472
7509
  description: "Search, extract, crawl, map, research, usage, and API key operations.",
7473
7510
  toolCount: 11,
7474
- transport: "rest"
7511
+ transport: "rest",
7512
+ opsCoverage: 100
7513
+ },
7514
+ {
7515
+ id: "telegram",
7516
+ icon: "TG",
7517
+ name: "Telegram",
7518
+ description: "Bot messages, chats, updates, and webhooks.",
7519
+ toolCount: 32,
7520
+ transport: "both",
7521
+ opsCoverage: null
7522
+ },
7523
+ {
7524
+ id: "twilio",
7525
+ icon: "TW",
7526
+ name: "Twilio",
7527
+ description: "Messages, calls, phone numbers, and verifications.",
7528
+ toolCount: 35,
7529
+ transport: "rest",
7530
+ opsCoverage: 92
7531
+ },
7532
+ {
7533
+ id: "unipile",
7534
+ icon: "UP",
7535
+ name: "Unipile",
7536
+ description: "LinkedIn and email messaging, accounts, and chats.",
7537
+ toolCount: 24,
7538
+ transport: "rest",
7539
+ opsCoverage: 100
7475
7540
  }
7476
7541
  ];
7477
7542
  var GENERATED_STARTABLE_TWIN_IDS = [
@@ -7820,11 +7885,10 @@ function trimEnv(name) {
7820
7885
  }
7821
7886
  function parsePositiveInteger(rawValue, fallback, minimum = 1) {
7822
7887
  if (!rawValue) return fallback;
7823
- const parsed = Number.parseInt(rawValue, 10);
7824
- if (Number.isNaN(parsed) || parsed < minimum) {
7825
- return fallback;
7826
- }
7827
- return parsed;
7888
+ const normalized = rawValue.trim();
7889
+ if (!/^[1-9]\d*$/.test(normalized)) return fallback;
7890
+ const parsed = Number(normalized);
7891
+ return Number.isSafeInteger(parsed) && parsed >= minimum ? parsed : fallback;
7828
7892
  }
7829
7893
  function normalizeApiBaseUrl(value) {
7830
7894
  if (!value) return null;
@@ -7850,7 +7914,7 @@ function resolveHostedWorkspaceHeader() {
7850
7914
  return trimEnv("ARCHAL_WORKSPACE_ID");
7851
7915
  }
7852
7916
  async function sleep(ms) {
7853
- await new Promise((resolve10) => setTimeout(resolve10, ms));
7917
+ await new Promise((resolve12) => setTimeout(resolve12, ms));
7854
7918
  }
7855
7919
  async function readJsonResponse(response) {
7856
7920
  if (response.status === 204) return void 0;
@@ -8563,12 +8627,14 @@ var __toESM2 = (mod, isNodeMode, target) => (target = mod != null ? __create2(__
8563
8627
  mod
8564
8628
  ));
8565
8629
 
8566
- // ../seedgen/dist/chunk-E7QP3UBL.js
8630
+ // ../seedgen/dist/chunk-OUL4HJ5I.js
8567
8631
  var import_stream = require("stream");
8568
8632
  var import_crypto = __toESM(require("crypto"), 1);
8569
8633
  var import_async_hooks = require("async_hooks");
8570
8634
  var import_os = require("os");
8571
8635
  var import_path = require("path");
8636
+ var import_os2 = require("os");
8637
+ var import_path2 = require("path");
8572
8638
  var require_code = __commonJS2({
8573
8639
  "../../node_modules/.pnpm/ajv@8.18.0/node_modules/ajv/dist/compile/codegen/code.js"(exports2) {
8574
8640
  "use strict";
@@ -11479,7 +11545,7 @@ var require_compile = __commonJS2({
11479
11545
  const schOrFunc = root.refs[ref2];
11480
11546
  if (schOrFunc)
11481
11547
  return schOrFunc;
11482
- let _sch = resolve52.call(this, root, ref2);
11548
+ let _sch = resolve62.call(this, root, ref2);
11483
11549
  if (_sch === void 0) {
11484
11550
  const schema = (_a22 = root.localRefs) === null || _a22 === void 0 ? void 0 : _a22[ref2];
11485
11551
  const { schemaId } = this.opts;
@@ -11506,7 +11572,7 @@ var require_compile = __commonJS2({
11506
11572
  function sameSchemaEnv(s1, s2) {
11507
11573
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
11508
11574
  }
11509
- function resolve52(root, ref2) {
11575
+ function resolve62(root, ref2) {
11510
11576
  let sch;
11511
11577
  while (typeof (sch = this.refs[ref2]) == "string")
11512
11578
  ref2 = sch;
@@ -12073,55 +12139,55 @@ var require_fast_uri = __commonJS2({
12073
12139
  }
12074
12140
  return uri;
12075
12141
  }
12076
- function resolve52(baseURI, relativeURI, options) {
12142
+ function resolve62(baseURI, relativeURI, options) {
12077
12143
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
12078
12144
  const resolved = resolveComponent(parse32(baseURI, schemelessOptions), parse32(relativeURI, schemelessOptions), schemelessOptions, true);
12079
12145
  schemelessOptions.skipEscape = true;
12080
12146
  return serialize(resolved, schemelessOptions);
12081
12147
  }
12082
- function resolveComponent(base, relative2, options, skipNormalization) {
12148
+ function resolveComponent(base, relative32, options, skipNormalization) {
12083
12149
  const target = {};
12084
12150
  if (!skipNormalization) {
12085
12151
  base = parse32(serialize(base, options), options);
12086
- relative2 = parse32(serialize(relative2, options), options);
12152
+ relative32 = parse32(serialize(relative32, options), options);
12087
12153
  }
12088
12154
  options = options || {};
12089
- if (!options.tolerant && relative2.scheme) {
12090
- target.scheme = relative2.scheme;
12091
- target.userinfo = relative2.userinfo;
12092
- target.host = relative2.host;
12093
- target.port = relative2.port;
12094
- target.path = removeDotSegments(relative2.path || "");
12095
- target.query = relative2.query;
12155
+ if (!options.tolerant && relative32.scheme) {
12156
+ target.scheme = relative32.scheme;
12157
+ target.userinfo = relative32.userinfo;
12158
+ target.host = relative32.host;
12159
+ target.port = relative32.port;
12160
+ target.path = removeDotSegments(relative32.path || "");
12161
+ target.query = relative32.query;
12096
12162
  } else {
12097
- if (relative2.userinfo !== void 0 || relative2.host !== void 0 || relative2.port !== void 0) {
12098
- target.userinfo = relative2.userinfo;
12099
- target.host = relative2.host;
12100
- target.port = relative2.port;
12101
- target.path = removeDotSegments(relative2.path || "");
12102
- target.query = relative2.query;
12163
+ if (relative32.userinfo !== void 0 || relative32.host !== void 0 || relative32.port !== void 0) {
12164
+ target.userinfo = relative32.userinfo;
12165
+ target.host = relative32.host;
12166
+ target.port = relative32.port;
12167
+ target.path = removeDotSegments(relative32.path || "");
12168
+ target.query = relative32.query;
12103
12169
  } else {
12104
- if (!relative2.path) {
12170
+ if (!relative32.path) {
12105
12171
  target.path = base.path;
12106
- if (relative2.query !== void 0) {
12107
- target.query = relative2.query;
12172
+ if (relative32.query !== void 0) {
12173
+ target.query = relative32.query;
12108
12174
  } else {
12109
12175
  target.query = base.query;
12110
12176
  }
12111
12177
  } else {
12112
- if (relative2.path[0] === "/") {
12113
- target.path = removeDotSegments(relative2.path);
12178
+ if (relative32.path[0] === "/") {
12179
+ target.path = removeDotSegments(relative32.path);
12114
12180
  } else {
12115
12181
  if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) {
12116
- target.path = "/" + relative2.path;
12182
+ target.path = "/" + relative32.path;
12117
12183
  } else if (!base.path) {
12118
- target.path = relative2.path;
12184
+ target.path = relative32.path;
12119
12185
  } else {
12120
- target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative2.path;
12186
+ target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative32.path;
12121
12187
  }
12122
12188
  target.path = removeDotSegments(target.path);
12123
12189
  }
12124
- target.query = relative2.query;
12190
+ target.query = relative32.query;
12125
12191
  }
12126
12192
  target.userinfo = base.userinfo;
12127
12193
  target.host = base.host;
@@ -12129,7 +12195,7 @@ var require_fast_uri = __commonJS2({
12129
12195
  }
12130
12196
  target.scheme = base.scheme;
12131
12197
  }
12132
- target.fragment = relative2.fragment;
12198
+ target.fragment = relative32.fragment;
12133
12199
  return target;
12134
12200
  }
12135
12201
  function equal(uriA, uriB, options) {
@@ -12300,7 +12366,7 @@ var require_fast_uri = __commonJS2({
12300
12366
  var fastUri = {
12301
12367
  SCHEMES,
12302
12368
  normalize,
12303
- resolve: resolve52,
12369
+ resolve: resolve62,
12304
12370
  resolveComponent,
12305
12371
  equal,
12306
12372
  serialize,
@@ -34379,6 +34445,62 @@ var toolSearchInputSchema = external_exports3.object({
34379
34445
  /** Max results. Defaults to 10; capped at 100. */
34380
34446
  limit: external_exports3.number().int().positive().max(TOOL_SEARCH_MAX_LIMIT).optional()
34381
34447
  });
34448
+ var RecordingManifestEntrySchema = external_exports3.object({
34449
+ filename: external_exports3.string(),
34450
+ sha256: external_exports3.string().regex(/^[0-9a-f]{64}$/, "sha256 must be 64 lowercase hex chars"),
34451
+ size: external_exports3.number().optional(),
34452
+ sizeBytes: external_exports3.number().optional(),
34453
+ uploadedAt: external_exports3.string().optional(),
34454
+ // Optional symbolic tags that map fixture-oracle / replay lookups onto this
34455
+ // recording. Lets twins keep tag→file resolution inside the manifest itself
34456
+ // rather than depending on a separate provenance.json (which is excluded
34457
+ // from the in-tree fixture allowlist for graduated twins). Codex P2 on
34458
+ // tavily #3603 — fixture-oracle previously required provenance.json to
34459
+ // resolve `rest-profile:tavily:tavily_search_basic` → filename.
34460
+ tags: external_exports3.array(external_exports3.string()).optional()
34461
+ }).loose();
34462
+ var RecordingManifestSchema = external_exports3.object({
34463
+ service: external_exports3.string().min(1),
34464
+ version: external_exports3.number().int(),
34465
+ container: external_exports3.string().min(1),
34466
+ baseUrl: external_exports3.string().optional(),
34467
+ entries: external_exports3.array(RecordingManifestEntrySchema)
34468
+ }).loose();
34469
+ var DEFAULT_BASE_URL = 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";
34470
+ var DEFAULT_CACHE_ROOT = process.env["ARCHAL_FIXTURE_CACHE_ROOT"] ?? (0, import_path2.resolve)((0, import_os2.homedir)(), ".archal", "forge", "recordings-cache");
34471
+ function warnIfSasExpiresSoon(baseUrl) {
34472
+ if (process.env["ARCHAL_FIXTURE_SAS_WARN"] === "0") return;
34473
+ const queryIdx = baseUrl.indexOf("?");
34474
+ if (queryIdx < 0) return;
34475
+ const query = baseUrl.slice(queryIdx + 1);
34476
+ const seParam = query.split("&").find((p) => p.startsWith("se="));
34477
+ if (!seParam) return;
34478
+ const seValue = decodeURIComponent(seParam.slice(3));
34479
+ const expiresAt = Date.parse(seValue);
34480
+ if (Number.isNaN(expiresAt)) return;
34481
+ const now2 = Date.now();
34482
+ const daysRemaining = Math.floor((expiresAt - now2) / (1e3 * 60 * 60 * 24));
34483
+ if (daysRemaining < 365) {
34484
+ console.warn(
34485
+ `[recording-fetcher] SAS token in ARCHAL_FIXTURE_BASE_URL expires in ${daysRemaining}d (${seValue}). Rotate via scripts/rotate-fixture-sas.mjs before expiry.`
34486
+ );
34487
+ }
34488
+ }
34489
+ warnIfSasExpiresSoon(DEFAULT_BASE_URL);
34490
+ var DEFAULT_CACHE_ROOT2 = process.env["ARCHAL_LEGACY_ASSET_CACHE_ROOT"] ?? (0, import_path.resolve)((0, import_os.homedir)(), ".archal", "forge", "legacy-assets-cache");
34491
+ var LegacyAssetEntrySchema = external_exports3.object({
34492
+ relativePath: external_exports3.string().min(1),
34493
+ sha256: external_exports3.string().regex(/^[0-9a-f]{64}$/, "sha256 must be 64 lowercase hex chars"),
34494
+ sizeBytes: external_exports3.number().optional(),
34495
+ uploadedAt: external_exports3.string().optional()
34496
+ }).loose();
34497
+ var LegacyAssetManifestSchema = external_exports3.object({
34498
+ service: external_exports3.string().min(1),
34499
+ version: external_exports3.number().int(),
34500
+ container: external_exports3.string().min(1),
34501
+ layout: external_exports3.string().optional(),
34502
+ entries: external_exports3.array(LegacyAssetEntrySchema)
34503
+ }).loose();
34382
34504
  var manifest_default = [
34383
34505
  {
34384
34506
  name: "apify",
@@ -34427,6 +34549,12 @@ var manifest_default = [
34427
34549
  package: "@archal/twin-firecrawl",
34428
34550
  path: "twins/firecrawl",
34429
34551
  stage: "internal",
34552
+ display: {
34553
+ icon: "FC",
34554
+ name: "Firecrawl",
34555
+ description: "Scraping, crawling, mapping, search, and extraction.",
34556
+ toolCount: 6
34557
+ },
34430
34558
  transport: "rest",
34431
34559
  hostedRuntime: { enabled: true, requiresDist: true, requiresEmptySeed: true },
34432
34560
  cli: { bundleAssets: false, bundleToolSnapshot: false },
@@ -34494,6 +34622,12 @@ var manifest_default = [
34494
34622
  package: "@archal/twin-hubspot",
34495
34623
  path: "twins/hubspot",
34496
34624
  stage: "internal",
34625
+ display: {
34626
+ icon: "HS",
34627
+ name: "HubSpot",
34628
+ description: "CRM contacts, companies, deals, tickets, and engagements.",
34629
+ toolCount: 45
34630
+ },
34497
34631
  transport: "rest",
34498
34632
  hostedRuntime: { enabled: true, requiresDist: true, requiresEmptySeed: true },
34499
34633
  cli: { bundleAssets: false, bundleToolSnapshot: false },
@@ -34570,6 +34704,12 @@ var manifest_default = [
34570
34704
  package: "@archal/twin-sendgrid",
34571
34705
  path: "twins/sendgrid",
34572
34706
  stage: "internal",
34707
+ display: {
34708
+ icon: "SG",
34709
+ name: "SendGrid",
34710
+ description: "Mail send, contacts, lists, templates, and stats.",
34711
+ toolCount: 28
34712
+ },
34573
34713
  transport: "rest",
34574
34714
  hostedRuntime: { enabled: true, requiresDist: true, requiresEmptySeed: true },
34575
34715
  cli: { bundleAssets: false, bundleToolSnapshot: false },
@@ -34666,6 +34806,12 @@ var manifest_default = [
34666
34806
  package: "@archal/twin-telegram",
34667
34807
  path: "twins/telegram",
34668
34808
  stage: "internal",
34809
+ display: {
34810
+ icon: "TG",
34811
+ name: "Telegram",
34812
+ description: "Bot messages, chats, updates, and webhooks.",
34813
+ toolCount: 32
34814
+ },
34669
34815
  transport: "both",
34670
34816
  hostedRuntime: { enabled: true, requiresDist: true, requiresEmptySeed: true },
34671
34817
  cli: { bundleAssets: false, bundleToolSnapshot: false },
@@ -34678,6 +34824,12 @@ var manifest_default = [
34678
34824
  package: "@archal/twin-twilio",
34679
34825
  path: "twins/twilio",
34680
34826
  stage: "internal",
34827
+ display: {
34828
+ icon: "TW",
34829
+ name: "Twilio",
34830
+ description: "Messages, calls, phone numbers, and verifications.",
34831
+ toolCount: 35
34832
+ },
34681
34833
  transport: "rest",
34682
34834
  hostedRuntime: { enabled: true, requiresDist: true, requiresEmptySeed: true },
34683
34835
  cli: { bundleAssets: false, bundleToolSnapshot: false },
@@ -34690,6 +34842,12 @@ var manifest_default = [
34690
34842
  package: "@archal/twin-unipile",
34691
34843
  path: "twins/unipile",
34692
34844
  stage: "internal",
34845
+ display: {
34846
+ icon: "UP",
34847
+ name: "Unipile",
34848
+ description: "LinkedIn and email messaging, accounts, and chats.",
34849
+ toolCount: 24
34850
+ },
34693
34851
  transport: "rest",
34694
34852
  hostedRuntime: { enabled: true, requiresDist: true, requiresEmptySeed: true },
34695
34853
  cli: { bundleAssets: false, bundleToolSnapshot: false },
@@ -34834,48 +34992,6 @@ var SCENARIO_RISK_RULES = [
34834
34992
  var SCENARIO_RISK_TAXONOMY = SCENARIO_RISK_RULES.map(
34835
34993
  ({ id, label, description }) => ({ id, label, description })
34836
34994
  );
34837
- var RecordingManifestEntrySchema = external_exports3.object({
34838
- filename: external_exports3.string(),
34839
- sha256: external_exports3.string().regex(/^[0-9a-f]{64}$/, "sha256 must be 64 lowercase hex chars"),
34840
- size: external_exports3.number().optional(),
34841
- sizeBytes: external_exports3.number().optional(),
34842
- uploadedAt: external_exports3.string().optional(),
34843
- // Optional symbolic tags that map fixture-oracle / replay lookups onto this
34844
- // recording. Lets twins keep tag→file resolution inside the manifest itself
34845
- // rather than depending on a separate provenance.json (which is excluded
34846
- // from the in-tree fixture allowlist for graduated twins). Codex P2 on
34847
- // tavily #3603 — fixture-oracle previously required provenance.json to
34848
- // resolve `rest-profile:tavily:tavily_search_basic` → filename.
34849
- tags: external_exports3.array(external_exports3.string()).optional()
34850
- }).loose();
34851
- var RecordingManifestSchema = external_exports3.object({
34852
- service: external_exports3.string().min(1),
34853
- version: external_exports3.number().int(),
34854
- container: external_exports3.string().min(1),
34855
- baseUrl: external_exports3.string().optional(),
34856
- entries: external_exports3.array(RecordingManifestEntrySchema)
34857
- }).loose();
34858
- var DEFAULT_BASE_URL = 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";
34859
- var DEFAULT_CACHE_ROOT = process.env["ARCHAL_FIXTURE_CACHE_ROOT"] ?? (0, import_path.resolve)((0, import_os.homedir)(), ".archal", "forge", "recordings-cache");
34860
- function warnIfSasExpiresSoon(baseUrl) {
34861
- if (process.env["ARCHAL_FIXTURE_SAS_WARN"] === "0") return;
34862
- const queryIdx = baseUrl.indexOf("?");
34863
- if (queryIdx < 0) return;
34864
- const query = baseUrl.slice(queryIdx + 1);
34865
- const seParam = query.split("&").find((p) => p.startsWith("se="));
34866
- if (!seParam) return;
34867
- const seValue = decodeURIComponent(seParam.slice(3));
34868
- const expiresAt = Date.parse(seValue);
34869
- if (Number.isNaN(expiresAt)) return;
34870
- const now2 = Date.now();
34871
- const daysRemaining = Math.floor((expiresAt - now2) / (1e3 * 60 * 60 * 24));
34872
- if (daysRemaining < 365) {
34873
- console.warn(
34874
- `[recording-fetcher] SAS token in ARCHAL_FIXTURE_BASE_URL expires in ${daysRemaining}d (${seValue}). Rotate via scripts/rotate-fixture-sas.mjs before expiry.`
34875
- );
34876
- }
34877
- }
34878
- warnIfSasExpiresSoon(DEFAULT_BASE_URL);
34879
34995
 
34880
34996
  // ../../node_modules/.pnpm/acorn@8.16.0/node_modules/acorn/dist/acorn.mjs
34881
34997
  var astralIdentifierCodes = [509, 0, 227, 0, 150, 4, 294, 9, 1368, 2, 2, 1, 6, 3, 41, 2, 5, 0, 166, 1, 574, 3, 9, 9, 7, 9, 32, 4, 318, 1, 78, 5, 71, 10, 50, 3, 123, 2, 54, 14, 32, 10, 3, 1, 11, 3, 46, 10, 8, 0, 46, 9, 7, 2, 37, 13, 2, 9, 6, 1, 45, 0, 13, 2, 49, 13, 9, 3, 2, 11, 83, 11, 7, 0, 3, 0, 158, 11, 6, 9, 7, 3, 56, 1, 2, 6, 3, 1, 3, 2, 10, 0, 11, 1, 3, 6, 4, 4, 68, 8, 2, 0, 3, 0, 2, 3, 2, 4, 2, 0, 15, 1, 83, 17, 10, 9, 5, 0, 82, 19, 13, 9, 214, 6, 3, 8, 28, 1, 83, 16, 16, 9, 82, 12, 9, 9, 7, 19, 58, 14, 5, 9, 243, 14, 166, 9, 71, 5, 2, 1, 3, 3, 2, 0, 2, 1, 13, 9, 120, 6, 3, 6, 4, 0, 29, 9, 41, 6, 2, 3, 9, 0, 10, 10, 47, 15, 199, 7, 137, 9, 54, 7, 2, 7, 17, 9, 57, 21, 2, 13, 123, 5, 4, 0, 2, 1, 2, 6, 2, 0, 9, 9, 49, 4, 2, 1, 2, 4, 9, 9, 55, 9, 266, 3, 10, 1, 2, 0, 49, 6, 4, 4, 14, 10, 5350, 0, 7, 14, 11465, 27, 2343, 9, 87, 9, 39, 4, 60, 6, 26, 9, 535, 9, 470, 0, 2, 54, 8, 3, 82, 0, 12, 1, 19628, 1, 4178, 9, 519, 45, 3, 22, 543, 4, 4, 5, 9, 7, 3, 6, 31, 3, 149, 2, 1418, 49, 513, 54, 5, 49, 9, 0, 15, 0, 23, 4, 2, 14, 1361, 6, 2, 16, 3, 6, 2, 1, 2, 4, 101, 0, 161, 6, 10, 9, 357, 0, 62, 13, 499, 13, 245, 1, 2, 9, 233, 0, 3, 0, 8, 1, 6, 0, 475, 6, 110, 6, 6, 9, 4759, 9, 787719, 239];
@@ -41796,17 +41912,17 @@ function checkStaticSafety(code) {
41796
41912
  return { safe: true, reason: "" };
41797
41913
  }
41798
41914
 
41799
- // ../seedgen/dist/chunk-XI7HKUUF.js
41915
+ // ../seedgen/dist/chunk-CIYCQV32.js
41800
41916
  var import_child_process = require("child_process");
41801
41917
  var import_crypto2 = require("crypto");
41802
41918
  var import_fs = require("fs");
41803
- var import_os2 = require("os");
41804
- var import_path2 = require("path");
41919
+ var import_os3 = require("os");
41920
+ var import_path3 = require("path");
41805
41921
  var import_net = require("net");
41806
41922
  var import_child_process2 = require("child_process");
41807
41923
  var import_fs2 = require("fs");
41808
41924
  var import_url = require("url");
41809
- var import_path3 = __toESM(require("path"), 1);
41925
+ var import_path4 = __toESM(require("path"), 1);
41810
41926
  var CREDENTIALS_FILE2 = "credentials.json";
41811
41927
  var CREDENTIALS_KEY_FILE2 = "credentials.key";
41812
41928
  var AUTH_TOKEN_ENV_VAR2 = "ARCHAL_TOKEN";
@@ -41851,7 +41967,7 @@ function isRunningUnderTests2() {
41851
41967
  return process.env["VITEST"] === "true" || process.env["VITEST_WORKER_ID"] !== void 0 || process.env["JEST_WORKER_ID"] !== void 0 || process.env["NODE_TEST_CONTEXT"] !== void 0;
41852
41968
  }
41853
41969
  function getRealArchalDir2() {
41854
- return (0, import_path2.join)((0, import_os2.homedir)(), ARCHAL_DIR_NAME2);
41970
+ return (0, import_path3.join)((0, import_os3.homedir)(), ARCHAL_DIR_NAME2);
41855
41971
  }
41856
41972
  function normalizeSandboxId2(raw) {
41857
41973
  const trimmed = raw.trim();
@@ -41863,10 +41979,10 @@ function normalizeSandboxId2(raw) {
41863
41979
  function getTestSandboxDir2() {
41864
41980
  const sharedSandboxId = process.env[VITEST_CONFIG_ENV_VAR2]?.trim() || process.env[TEST_SANDBOX_ID_ENV_VAR2]?.trim();
41865
41981
  if (sharedSandboxId) {
41866
- return (0, import_path2.join)((0, import_os2.tmpdir)(), `archal-test-sandbox-${normalizeSandboxId2(sharedSandboxId)}`);
41982
+ return (0, import_path3.join)((0, import_os3.tmpdir)(), `archal-test-sandbox-${normalizeSandboxId2(sharedSandboxId)}`);
41867
41983
  }
41868
41984
  const workerId = process.env["VITEST_WORKER_ID"] ?? process.env["JEST_WORKER_ID"] ?? String(process.pid);
41869
- return (0, import_path2.join)((0, import_os2.tmpdir)(), `archal-test-sandbox-${workerId}-${process.pid}`);
41985
+ return (0, import_path3.join)((0, import_os3.tmpdir)(), `archal-test-sandbox-${workerId}-${process.pid}`);
41870
41986
  }
41871
41987
  function getArchalDir2() {
41872
41988
  const explicit = process.env["ARCHAL_HOME"];
@@ -41879,7 +41995,7 @@ function getArchalDir2() {
41879
41995
  return getRealArchalDir2();
41880
41996
  }
41881
41997
  function getCredentialsPath2() {
41882
- return (0, import_path2.join)(getArchalDir2(), CREDENTIALS_FILE2);
41998
+ return (0, import_path3.join)(getArchalDir2(), CREDENTIALS_FILE2);
41883
41999
  }
41884
42000
  function ensureDir2(dir) {
41885
42001
  if (!(0, import_fs.existsSync)(dir)) {
@@ -41889,7 +42005,7 @@ function ensureDir2(dir) {
41889
42005
  return dir;
41890
42006
  }
41891
42007
  function getCredentialsKeyPathForDir2(dir) {
41892
- return (0, import_path2.join)(dir, CREDENTIALS_KEY_FILE2);
42008
+ return (0, import_path3.join)(dir, CREDENTIALS_KEY_FILE2);
41893
42009
  }
41894
42010
  function readCredentialsKeyFromEnv2() {
41895
42011
  const raw = process.env[CREDENTIALS_MASTER_KEY_ENV_VAR2]?.trim();
@@ -42097,7 +42213,7 @@ function resolveStoredRefreshToken2(parsed, dir = getArchalDir2()) {
42097
42213
  return { refreshToken: "", source: "none" };
42098
42214
  }
42099
42215
  function buildStoredCredentials2(parsed, path2, warn22, options) {
42100
- const dir = (0, import_path2.dirname)(path2);
42216
+ const dir = (0, import_path3.dirname)(path2);
42101
42217
  const { token, source: tokenSource } = resolveStoredToken2(parsed, dir);
42102
42218
  const { refreshToken, source: refreshTokenSource } = resolveStoredRefreshToken2(parsed, dir);
42103
42219
  if (token === null || refreshToken === null || parsed.refreshToken !== void 0 && typeof parsed.refreshToken !== "string" || parsed.refreshTokenEncrypted !== void 0 && typeof parsed.refreshTokenEncrypted !== "string" || !hasValidSelectedTwins2(parsed.selectedTwins)) {
@@ -42233,7 +42349,7 @@ function getStoredCredentials2(options) {
42233
42349
  return isExpired2(creds.expiresAt) ? null : creds;
42234
42350
  }
42235
42351
  function writeCredentialsAtPath2(path2, creds) {
42236
- const dir = (0, import_path2.dirname)(path2);
42352
+ const dir = (0, import_path3.dirname)(path2);
42237
42353
  ensureDir2(dir);
42238
42354
  const payload = {
42239
42355
  email: creds.email,
@@ -42359,8 +42475,9 @@ var GENERATED_TWIN_CATALOG2 = [
42359
42475
  icon: "AP",
42360
42476
  name: "Apify",
42361
42477
  description: "Actors, runs, datasets, key-value stores, and request queues.",
42362
- toolCount: 45,
42363
- transport: "rest"
42478
+ toolCount: 43,
42479
+ transport: "rest",
42480
+ opsCoverage: null
42364
42481
  },
42365
42482
  {
42366
42483
  id: "discord",
@@ -42368,7 +42485,17 @@ var GENERATED_TWIN_CATALOG2 = [
42368
42485
  name: "Discord",
42369
42486
  description: "Guilds, channels, messages, webhooks, threads, commands, and interaction responses.",
42370
42487
  toolCount: 67,
42371
- transport: "both"
42488
+ transport: "both",
42489
+ opsCoverage: 14
42490
+ },
42491
+ {
42492
+ id: "firecrawl",
42493
+ icon: "FC",
42494
+ name: "Firecrawl",
42495
+ description: "Scraping, crawling, mapping, search, and extraction.",
42496
+ toolCount: 6,
42497
+ transport: "rest",
42498
+ opsCoverage: 77
42372
42499
  },
42373
42500
  {
42374
42501
  id: "github",
@@ -42376,7 +42503,8 @@ var GENERATED_TWIN_CATALOG2 = [
42376
42503
  name: "GitHub",
42377
42504
  description: "Repos, issues, pull requests, branches, and commits.",
42378
42505
  toolCount: 26,
42379
- transport: "both"
42506
+ transport: "both",
42507
+ opsCoverage: 96
42380
42508
  },
42381
42509
  {
42382
42510
  id: "google-workspace",
@@ -42384,7 +42512,17 @@ var GENERATED_TWIN_CATALOG2 = [
42384
42512
  name: "Google Workspace",
42385
42513
  description: "Gmail, Calendar, Drive, Sheets, and Contacts.",
42386
42514
  toolCount: 249,
42387
- transport: "both"
42515
+ transport: "both",
42516
+ opsCoverage: 64
42517
+ },
42518
+ {
42519
+ id: "hubspot",
42520
+ icon: "HS",
42521
+ name: "HubSpot",
42522
+ description: "CRM contacts, companies, deals, tickets, and engagements.",
42523
+ toolCount: 45,
42524
+ transport: "rest",
42525
+ opsCoverage: 10
42388
42526
  },
42389
42527
  {
42390
42528
  id: "jira",
@@ -42392,7 +42530,8 @@ var GENERATED_TWIN_CATALOG2 = [
42392
42530
  name: "Jira",
42393
42531
  description: "Issues, projects, boards, sprints, and versions.",
42394
42532
  toolCount: 49,
42395
- transport: "both"
42533
+ transport: "both",
42534
+ opsCoverage: 80
42396
42535
  },
42397
42536
  {
42398
42537
  id: "linear",
@@ -42400,7 +42539,8 @@ var GENERATED_TWIN_CATALOG2 = [
42400
42539
  name: "Linear",
42401
42540
  description: "Issues, projects, teams, cycles, and workflows.",
42402
42541
  toolCount: 42,
42403
- transport: "both"
42542
+ transport: "both",
42543
+ opsCoverage: 98
42404
42544
  },
42405
42545
  {
42406
42546
  id: "ramp",
@@ -42408,7 +42548,17 @@ var GENERATED_TWIN_CATALOG2 = [
42408
42548
  name: "Ramp",
42409
42549
  description: "Cards, funds, expenses, reimbursements, bills, and travel.",
42410
42550
  toolCount: 46,
42411
- transport: "mcp"
42551
+ transport: "mcp",
42552
+ opsCoverage: null
42553
+ },
42554
+ {
42555
+ id: "sendgrid",
42556
+ icon: "SG",
42557
+ name: "SendGrid",
42558
+ description: "Mail send, contacts, lists, templates, and stats.",
42559
+ toolCount: 28,
42560
+ transport: "rest",
42561
+ opsCoverage: 100
42412
42562
  },
42413
42563
  {
42414
42564
  id: "slack",
@@ -42416,7 +42566,8 @@ var GENERATED_TWIN_CATALOG2 = [
42416
42566
  name: "Slack",
42417
42567
  description: "Channels, messages, threads, users, and reactions.",
42418
42568
  toolCount: 8,
42419
- transport: "both"
42569
+ transport: "both",
42570
+ opsCoverage: 100
42420
42571
  },
42421
42572
  {
42422
42573
  id: "stripe",
@@ -42424,7 +42575,8 @@ var GENERATED_TWIN_CATALOG2 = [
42424
42575
  name: "Stripe",
42425
42576
  description: "Customers, payments, subscriptions, invoices, and refunds.",
42426
42577
  toolCount: 28,
42427
- transport: "both"
42578
+ transport: "both",
42579
+ opsCoverage: null
42428
42580
  },
42429
42581
  {
42430
42582
  id: "supabase",
@@ -42432,7 +42584,8 @@ var GENERATED_TWIN_CATALOG2 = [
42432
42584
  name: "Supabase",
42433
42585
  description: "SQL, migrations, logs, branches, and project metadata.",
42434
42586
  toolCount: 29,
42435
- transport: "both"
42587
+ transport: "both",
42588
+ opsCoverage: 100
42436
42589
  },
42437
42590
  {
42438
42591
  id: "tavily",
@@ -42440,7 +42593,35 @@ var GENERATED_TWIN_CATALOG2 = [
42440
42593
  name: "Tavily",
42441
42594
  description: "Search, extract, crawl, map, research, usage, and API key operations.",
42442
42595
  toolCount: 11,
42443
- transport: "rest"
42596
+ transport: "rest",
42597
+ opsCoverage: 100
42598
+ },
42599
+ {
42600
+ id: "telegram",
42601
+ icon: "TG",
42602
+ name: "Telegram",
42603
+ description: "Bot messages, chats, updates, and webhooks.",
42604
+ toolCount: 32,
42605
+ transport: "both",
42606
+ opsCoverage: null
42607
+ },
42608
+ {
42609
+ id: "twilio",
42610
+ icon: "TW",
42611
+ name: "Twilio",
42612
+ description: "Messages, calls, phone numbers, and verifications.",
42613
+ toolCount: 35,
42614
+ transport: "rest",
42615
+ opsCoverage: 92
42616
+ },
42617
+ {
42618
+ id: "unipile",
42619
+ icon: "UP",
42620
+ name: "Unipile",
42621
+ description: "LinkedIn and email messaging, accounts, and chats.",
42622
+ toolCount: 24,
42623
+ transport: "rest",
42624
+ opsCoverage: 100
42444
42625
  }
42445
42626
  ];
42446
42627
  var GENERATED_STARTABLE_TWIN_IDS2 = [
@@ -42586,13 +42767,13 @@ var LLM_PRICING_FAMILY_RATES2 = [
42586
42767
  ];
42587
42768
  var DEFAULT_TIMEOUT_MS = 5e3;
42588
42769
  function resolveWorkerScriptPath() {
42589
- const thisDir = import_path3.default.dirname((0, import_url.fileURLToPath)(__archal_import_meta_url));
42770
+ const thisDir = import_path4.default.dirname((0, import_url.fileURLToPath)(__archal_import_meta_url));
42590
42771
  const candidates = [
42591
42772
  // Source or unbundled output: executor.js and subprocess-worker.js live together.
42592
- import_path3.default.join(thisDir, "subprocess-worker.js"),
42773
+ import_path4.default.join(thisDir, "subprocess-worker.js"),
42593
42774
  // tsup bundles executor into a root chunk while keeping the worker entry
42594
42775
  // at dist/codegen/subprocess-worker.js.
42595
- import_path3.default.join(thisDir, "codegen", "subprocess-worker.js")
42776
+ import_path4.default.join(thisDir, "codegen", "subprocess-worker.js")
42596
42777
  ];
42597
42778
  return candidates.find((candidate) => (0, import_fs2.existsSync)(candidate));
42598
42779
  }
@@ -42611,7 +42792,7 @@ async function executeSeedCodeIsolated(code, twinName, baseSeed, timeoutMs = DEF
42611
42792
  "seedgen: subprocess worker script is unresolvable. Ensure the package is built before use."
42612
42793
  );
42613
42794
  }
42614
- return new Promise((resolve10) => {
42795
+ return new Promise((resolve12) => {
42615
42796
  const child = (0, import_child_process2.fork)(workerScriptPath, {
42616
42797
  // Silent: don't inherit parent stdout/stderr so worker crashes
42617
42798
  // don't pollute the parent's output.
@@ -42636,28 +42817,28 @@ async function executeSeedCodeIsolated(code, twinName, baseSeed, timeoutMs = DEF
42636
42817
  if (!resolved) {
42637
42818
  resolved = true;
42638
42819
  child.kill("SIGKILL");
42639
- resolve10({ ok: false, type: "timeout", message: `Subprocess timed out after ${timeoutMs}ms` });
42820
+ resolve12({ ok: false, type: "timeout", message: `Subprocess timed out after ${timeoutMs}ms` });
42640
42821
  }
42641
42822
  }, timeoutMs + 2e3);
42642
42823
  child.on("message", (msg) => {
42643
42824
  if (!resolved) {
42644
42825
  resolved = true;
42645
42826
  clearTimeout(timer);
42646
- resolve10(msg);
42827
+ resolve12(msg);
42647
42828
  }
42648
42829
  });
42649
42830
  child.on("error", (err) => {
42650
42831
  if (!resolved) {
42651
42832
  resolved = true;
42652
42833
  clearTimeout(timer);
42653
- resolve10({ ok: false, type: "runtime", message: `Worker error: ${errorMessage3(err)}` });
42834
+ resolve12({ ok: false, type: "runtime", message: `Worker error: ${errorMessage3(err)}` });
42654
42835
  }
42655
42836
  });
42656
42837
  child.on("exit", (exitCode) => {
42657
42838
  if (!resolved) {
42658
42839
  resolved = true;
42659
42840
  clearTimeout(timer);
42660
- resolve10({
42841
+ resolve12({
42661
42842
  ok: false,
42662
42843
  type: "runtime",
42663
42844
  message: exitCode ? `Worker exited with code ${exitCode}` : "Worker exited unexpectedly"
@@ -44236,7 +44417,7 @@ var TRANSIENT_AWS_EXCEPTIONS_PATTERN = /ThrottlingException|ServiceUnavailableEx
44236
44417
  var STATUS_CODE_IN_MESSAGE_PATTERN = /\b(429|500|502|503|529)\b/;
44237
44418
  var TRANSIENT_NETWORK_ERRORS_PATTERN = /ECONNRESET|ETIMEDOUT|EAI_AGAIN/i;
44238
44419
  function defaultSleep(backoffMs) {
44239
- return new Promise((resolve10) => setTimeout(resolve10, backoffMs));
44420
+ return new Promise((resolve12) => setTimeout(resolve12, backoffMs));
44240
44421
  }
44241
44422
  function getServerHintedDelayMs(error95) {
44242
44423
  if (error95 instanceof UpstreamApiError && typeof error95.retryAfterMs === "number" && error95.retryAfterMs >= 0) {
@@ -45562,7 +45743,7 @@ function getRunSessionContext() {
45562
45743
  return runSessionContext.getStore();
45563
45744
  }
45564
45745
 
45565
- // ../seedgen/dist/chunk-P6IA2T7T.js
45746
+ // ../seedgen/dist/chunk-JD4OJDYX.js
45566
45747
  async function retryWithCircuitBreaker(fn, opts) {
45567
45748
  let lastError;
45568
45749
  for (let attempt = 1; attempt <= opts.maxAttempts; attempt++) {
@@ -45712,7 +45893,7 @@ async function callCodegenLlm(options, cooldownKey = "__global__", directUsage)
45712
45893
  );
45713
45894
  }
45714
45895
 
45715
- // ../seedgen/dist/chunk-FCZCUWWZ.js
45896
+ // ../seedgen/dist/chunk-GBWN7KZ5.js
45716
45897
  var ENRICH_SYSTEM_PROMPT = `You enrich seed data with scenario-specific values. Given a setup description and a seed with generic placeholder titles/names, replace them with realistic values that match the scenario.
45717
45898
 
45718
45899
  Output ONLY valid JSON:
@@ -51005,7 +51186,7 @@ var FILL_TEMPLATES = {
51005
51186
  }
51006
51187
  };
51007
51188
 
51008
- // ../seedgen/dist/chunk-QYH3SE7W.js
51189
+ // ../seedgen/dist/chunk-52VGGT45.js
51009
51190
  var MAX_ENTITY_TYPES = 50;
51010
51191
  function parseDetails(details) {
51011
51192
  const map3 = /* @__PURE__ */ new Map();
@@ -52916,13 +53097,13 @@ function extractSeedIntent(twinName, setupDescription) {
52916
53097
  }
52917
53098
  }
52918
53099
 
52919
- // ../seedgen/dist/chunk-HL4OTBZD.js
53100
+ // ../seedgen/dist/chunk-KEUOYX5N.js
52920
53101
  var import_crypto5 = require("crypto");
52921
53102
  var import_fs3 = require("fs");
52922
- var import_path4 = require("path");
52923
- var import_os3 = require("os");
53103
+ var import_path5 = require("path");
53104
+ var import_os4 = require("os");
52924
53105
  var SEED_CACHE_VERSION = 6;
52925
- var CACHE_DIR = (0, import_path4.join)((0, import_os3.homedir)(), ".archal", "seed-cache");
53106
+ var CACHE_DIR = (0, import_path5.join)((0, import_os4.homedir)(), ".archal", "seed-cache");
52926
53107
  var MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
52927
53108
  function normalizeSetupText(setupText) {
52928
53109
  return setupText.toLowerCase().replace(/[^a-z0-9\s_/-]/g, " ").replace(/\s+/g, " ").trim();
@@ -52958,7 +53139,7 @@ function cacheFilePathScoped(twinName, baseSeedName, setupText, scope) {
52958
53139
  const key = (0, import_crypto5.createHash)("sha256").update(`${twinName}:${baseSeedName}:${normalizedSetup}:${contextHash}:${baseSeedHash}`).digest("hex").slice(0, 32);
52959
53140
  const intentHash = setupHash(normalizedSetup);
52960
53141
  return {
52961
- path: (0, import_path4.join)(CACHE_DIR, `${key}.json`),
53142
+ path: (0, import_path5.join)(CACHE_DIR, `${key}.json`),
52962
53143
  key,
52963
53144
  normalizedSetup,
52964
53145
  intentHash,
@@ -52977,7 +53158,7 @@ function evictStaleEntries() {
52977
53158
  const now2 = Date.now();
52978
53159
  for (const file3 of (0, import_fs3.readdirSync)(CACHE_DIR)) {
52979
53160
  if (!file3.endsWith(".json")) continue;
52980
- const filePath = (0, import_path4.join)(CACHE_DIR, file3);
53161
+ const filePath = (0, import_path5.join)(CACHE_DIR, file3);
52981
53162
  const stat = (0, import_fs3.lstatSync)(filePath);
52982
53163
  if (stat.isSymbolicLink()) {
52983
53164
  debug3("Skipping symlink during cache eviction", { file: file3 });
@@ -53078,7 +53259,7 @@ function cacheSeed(twinName, baseSeedName, setupText, seed, patch, scope, genera
53078
53259
  }
53079
53260
  }
53080
53261
 
53081
- // ../seedgen/dist/chunk-A25DCP64.js
53262
+ // ../seedgen/dist/chunk-KAB6MOBH.js
53082
53263
  var import_crypto6 = require("crypto");
53083
53264
  var SEED_CODEGEN_MAX_TOKENS = 4096;
53084
53265
  var MAX_CODEGEN_ATTEMPTS = 3;
@@ -53707,7 +53888,7 @@ async function waitForSeedLoad(loadingMarkerPath, loadedMarkerPath, options = {}
53707
53888
  if ((0, import_node_fs4.existsSync)(loadedMarkerPath) || !(0, import_node_fs4.existsSync)(loadingMarkerPath)) {
53708
53889
  return;
53709
53890
  }
53710
- await new Promise((resolve10) => setTimeout(resolve10, 25));
53891
+ await new Promise((resolve12) => setTimeout(resolve12, 25));
53711
53892
  }
53712
53893
  throw new Error("Timed out waiting for another worker to finish loading seed files.");
53713
53894
  }
@@ -54537,6 +54718,7 @@ var slackRouteManifest = {
54537
54718
  exactDomain("slack.com"),
54538
54719
  exactDomain("api.slack.com")
54539
54720
  ],
54721
+ upstreamBasePath: "/api",
54540
54722
  // Block adjacent Slack-owned domains that tests don't need and that can be
54541
54723
  // abused as data-exfiltration channels. hooks.slack.com and files.slack.com
54542
54724
  // in particular are ideal POST targets for a malicious dependency trying to
@@ -55468,7 +55650,7 @@ var ROUTE_RUNTIME_DISPATCHING_ROUTE_KINDS = new Set(ROUTE_RUNTIME_PUBLIC_ROUTE_K
55468
55650
  var stripeCompatibilityProfile = buildServiceCompatibilityProfile(stripeRouteManifest);
55469
55651
 
55470
55652
  // ../route-runtime-core/src/hosted-capabilities.ts
55471
- var import_node_crypto11 = require("crypto");
55653
+ var import_node_crypto12 = require("crypto");
55472
55654
 
55473
55655
  // ../../twins/core/src/control-plane-auth.ts
55474
55656
  var import_node_crypto2 = require("crypto");
@@ -74877,14 +75059,84 @@ var import_node_crypto7 = require("crypto");
74877
75059
  var import_node_perf_hooks = require("perf_hooks");
74878
75060
 
74879
75061
  // ../../twins/core/src/fixture-oracle.ts
74880
- var import_node_fs9 = require("fs");
74881
- var import_node_path9 = require("path");
75062
+ var import_node_fs11 = require("fs");
75063
+ var import_node_path11 = require("path");
74882
75064
  var import_node_url3 = require("url");
74883
75065
 
74884
- // ../../twins/core/src/run-twin-cli.ts
75066
+ // ../../twins/core/src/legacy-asset-cache.ts
75067
+ var import_node_crypto9 = require("crypto");
74885
75068
  var import_node_fs10 = require("fs");
75069
+ var import_node_os5 = require("os");
74886
75070
  var import_node_path10 = require("path");
74887
75071
 
75072
+ // ../../twins/core/src/recording-fetcher.ts
75073
+ var import_node_crypto8 = require("crypto");
75074
+ var import_node_fs9 = require("fs");
75075
+ var import_node_os4 = require("os");
75076
+ var import_node_path9 = require("path");
75077
+ var RecordingManifestEntrySchema2 = external_exports4.object({
75078
+ filename: external_exports4.string(),
75079
+ sha256: external_exports4.string().regex(/^[0-9a-f]{64}$/, "sha256 must be 64 lowercase hex chars"),
75080
+ size: external_exports4.number().optional(),
75081
+ sizeBytes: external_exports4.number().optional(),
75082
+ uploadedAt: external_exports4.string().optional(),
75083
+ // Optional symbolic tags that map fixture-oracle / replay lookups onto this
75084
+ // recording. Lets twins keep tag→file resolution inside the manifest itself
75085
+ // rather than depending on a separate provenance.json (which is excluded
75086
+ // from the in-tree fixture allowlist for graduated twins). Codex P2 on
75087
+ // tavily #3603 — fixture-oracle previously required provenance.json to
75088
+ // resolve `rest-profile:tavily:tavily_search_basic` → filename.
75089
+ tags: external_exports4.array(external_exports4.string()).optional()
75090
+ }).loose();
75091
+ var RecordingManifestSchema2 = external_exports4.object({
75092
+ service: external_exports4.string().min(1),
75093
+ version: external_exports4.number().int(),
75094
+ container: external_exports4.string().min(1),
75095
+ baseUrl: external_exports4.string().optional(),
75096
+ entries: external_exports4.array(RecordingManifestEntrySchema2)
75097
+ }).loose();
75098
+ 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";
75099
+ var DEFAULT_CACHE_ROOT3 = process.env["ARCHAL_FIXTURE_CACHE_ROOT"] ?? (0, import_node_path9.resolve)((0, import_node_os4.homedir)(), ".archal", "forge", "recordings-cache");
75100
+ function warnIfSasExpiresSoon2(baseUrl) {
75101
+ if (process.env["ARCHAL_FIXTURE_SAS_WARN"] === "0") return;
75102
+ const queryIdx = baseUrl.indexOf("?");
75103
+ if (queryIdx < 0) return;
75104
+ const query = baseUrl.slice(queryIdx + 1);
75105
+ const seParam = query.split("&").find((p) => p.startsWith("se="));
75106
+ if (!seParam) return;
75107
+ const seValue = decodeURIComponent(seParam.slice(3));
75108
+ const expiresAt = Date.parse(seValue);
75109
+ if (Number.isNaN(expiresAt)) return;
75110
+ const now2 = Date.now();
75111
+ const daysRemaining = Math.floor((expiresAt - now2) / (1e3 * 60 * 60 * 24));
75112
+ if (daysRemaining < 365) {
75113
+ console.warn(
75114
+ `[recording-fetcher] SAS token in ARCHAL_FIXTURE_BASE_URL expires in ${daysRemaining}d (${seValue}). Rotate via scripts/rotate-fixture-sas.mjs before expiry.`
75115
+ );
75116
+ }
75117
+ }
75118
+ warnIfSasExpiresSoon2(DEFAULT_BASE_URL2);
75119
+
75120
+ // ../../twins/core/src/legacy-asset-cache.ts
75121
+ var DEFAULT_CACHE_ROOT4 = process.env["ARCHAL_LEGACY_ASSET_CACHE_ROOT"] ?? (0, import_node_path10.resolve)((0, import_node_os5.homedir)(), ".archal", "forge", "legacy-assets-cache");
75122
+ var LegacyAssetEntrySchema2 = external_exports4.object({
75123
+ relativePath: external_exports4.string().min(1),
75124
+ sha256: external_exports4.string().regex(/^[0-9a-f]{64}$/, "sha256 must be 64 lowercase hex chars"),
75125
+ sizeBytes: external_exports4.number().optional(),
75126
+ uploadedAt: external_exports4.string().optional()
75127
+ }).loose();
75128
+ var LegacyAssetManifestSchema2 = external_exports4.object({
75129
+ service: external_exports4.string().min(1),
75130
+ version: external_exports4.number().int(),
75131
+ container: external_exports4.string().min(1),
75132
+ layout: external_exports4.string().optional(),
75133
+ entries: external_exports4.array(LegacyAssetEntrySchema2)
75134
+ }).loose();
75135
+
75136
+ // ../../twins/core/src/run-twin-cli.ts
75137
+ var import_node_fs12 = require("fs");
75138
+ var import_node_path12 = require("path");
75139
+
74888
75140
  // ../../twins/manifest.json
74889
75141
  var manifest_default2 = [
74890
75142
  {
@@ -74934,6 +75186,12 @@ var manifest_default2 = [
74934
75186
  package: "@archal/twin-firecrawl",
74935
75187
  path: "twins/firecrawl",
74936
75188
  stage: "internal",
75189
+ display: {
75190
+ icon: "FC",
75191
+ name: "Firecrawl",
75192
+ description: "Scraping, crawling, mapping, search, and extraction.",
75193
+ toolCount: 6
75194
+ },
74937
75195
  transport: "rest",
74938
75196
  hostedRuntime: { enabled: true, requiresDist: true, requiresEmptySeed: true },
74939
75197
  cli: { bundleAssets: false, bundleToolSnapshot: false },
@@ -75001,6 +75259,12 @@ var manifest_default2 = [
75001
75259
  package: "@archal/twin-hubspot",
75002
75260
  path: "twins/hubspot",
75003
75261
  stage: "internal",
75262
+ display: {
75263
+ icon: "HS",
75264
+ name: "HubSpot",
75265
+ description: "CRM contacts, companies, deals, tickets, and engagements.",
75266
+ toolCount: 45
75267
+ },
75004
75268
  transport: "rest",
75005
75269
  hostedRuntime: { enabled: true, requiresDist: true, requiresEmptySeed: true },
75006
75270
  cli: { bundleAssets: false, bundleToolSnapshot: false },
@@ -75077,6 +75341,12 @@ var manifest_default2 = [
75077
75341
  package: "@archal/twin-sendgrid",
75078
75342
  path: "twins/sendgrid",
75079
75343
  stage: "internal",
75344
+ display: {
75345
+ icon: "SG",
75346
+ name: "SendGrid",
75347
+ description: "Mail send, contacts, lists, templates, and stats.",
75348
+ toolCount: 28
75349
+ },
75080
75350
  transport: "rest",
75081
75351
  hostedRuntime: { enabled: true, requiresDist: true, requiresEmptySeed: true },
75082
75352
  cli: { bundleAssets: false, bundleToolSnapshot: false },
@@ -75173,6 +75443,12 @@ var manifest_default2 = [
75173
75443
  package: "@archal/twin-telegram",
75174
75444
  path: "twins/telegram",
75175
75445
  stage: "internal",
75446
+ display: {
75447
+ icon: "TG",
75448
+ name: "Telegram",
75449
+ description: "Bot messages, chats, updates, and webhooks.",
75450
+ toolCount: 32
75451
+ },
75176
75452
  transport: "both",
75177
75453
  hostedRuntime: { enabled: true, requiresDist: true, requiresEmptySeed: true },
75178
75454
  cli: { bundleAssets: false, bundleToolSnapshot: false },
@@ -75185,6 +75461,12 @@ var manifest_default2 = [
75185
75461
  package: "@archal/twin-twilio",
75186
75462
  path: "twins/twilio",
75187
75463
  stage: "internal",
75464
+ display: {
75465
+ icon: "TW",
75466
+ name: "Twilio",
75467
+ description: "Messages, calls, phone numbers, and verifications.",
75468
+ toolCount: 35
75469
+ },
75188
75470
  transport: "rest",
75189
75471
  hostedRuntime: { enabled: true, requiresDist: true, requiresEmptySeed: true },
75190
75472
  cli: { bundleAssets: false, bundleToolSnapshot: false },
@@ -75197,6 +75479,12 @@ var manifest_default2 = [
75197
75479
  package: "@archal/twin-unipile",
75198
75480
  path: "twins/unipile",
75199
75481
  stage: "internal",
75482
+ display: {
75483
+ icon: "UP",
75484
+ name: "Unipile",
75485
+ description: "LinkedIn and email messaging, accounts, and chats.",
75486
+ toolCount: 24
75487
+ },
75200
75488
  transport: "rest",
75201
75489
  hostedRuntime: { enabled: true, requiresDist: true, requiresEmptySeed: true },
75202
75490
  cli: { bundleAssets: false, bundleToolSnapshot: false },
@@ -75215,10 +75503,10 @@ var CLONE_PACKAGES2 = CLONE_MANIFEST2.map((t) => t.package);
75215
75503
  var TWIN_PREFIX_PATTERN2 = new RegExp(`^(${CLONE_NAMES2.join("|")})_`, "i");
75216
75504
 
75217
75505
  // ../../twins/core/src/session-run-id.ts
75218
- var import_node_crypto8 = require("crypto");
75506
+ var import_node_crypto10 = require("crypto");
75219
75507
 
75220
75508
  // ../../twins/core/src/webhook-signing.ts
75221
- var import_node_crypto9 = require("crypto");
75509
+ var import_node_crypto11 = require("crypto");
75222
75510
 
75223
75511
  // ../../twins/core/src/scenario-schemas.ts
75224
75512
  var successCriterionSchema2 = external_exports4.object({
@@ -75356,54 +75644,6 @@ var SCENARIO_RISK_TAXONOMY2 = SCENARIO_RISK_RULES2.map(
75356
75644
  ({ id, label, description }) => ({ id, label, description })
75357
75645
  );
75358
75646
 
75359
- // ../../twins/core/src/recording-fetcher.ts
75360
- var import_node_crypto10 = require("crypto");
75361
- var import_node_fs11 = require("fs");
75362
- var import_node_os4 = require("os");
75363
- var import_node_path11 = require("path");
75364
- var RecordingManifestEntrySchema2 = external_exports4.object({
75365
- filename: external_exports4.string(),
75366
- sha256: external_exports4.string().regex(/^[0-9a-f]{64}$/, "sha256 must be 64 lowercase hex chars"),
75367
- size: external_exports4.number().optional(),
75368
- sizeBytes: external_exports4.number().optional(),
75369
- uploadedAt: external_exports4.string().optional(),
75370
- // Optional symbolic tags that map fixture-oracle / replay lookups onto this
75371
- // recording. Lets twins keep tag→file resolution inside the manifest itself
75372
- // rather than depending on a separate provenance.json (which is excluded
75373
- // from the in-tree fixture allowlist for graduated twins). Codex P2 on
75374
- // tavily #3603 — fixture-oracle previously required provenance.json to
75375
- // resolve `rest-profile:tavily:tavily_search_basic` → filename.
75376
- tags: external_exports4.array(external_exports4.string()).optional()
75377
- }).loose();
75378
- var RecordingManifestSchema2 = external_exports4.object({
75379
- service: external_exports4.string().min(1),
75380
- version: external_exports4.number().int(),
75381
- container: external_exports4.string().min(1),
75382
- baseUrl: external_exports4.string().optional(),
75383
- entries: external_exports4.array(RecordingManifestEntrySchema2)
75384
- }).loose();
75385
- 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";
75386
- var DEFAULT_CACHE_ROOT2 = process.env["ARCHAL_FIXTURE_CACHE_ROOT"] ?? (0, import_node_path11.resolve)((0, import_node_os4.homedir)(), ".archal", "forge", "recordings-cache");
75387
- function warnIfSasExpiresSoon2(baseUrl) {
75388
- if (process.env["ARCHAL_FIXTURE_SAS_WARN"] === "0") return;
75389
- const queryIdx = baseUrl.indexOf("?");
75390
- if (queryIdx < 0) return;
75391
- const query = baseUrl.slice(queryIdx + 1);
75392
- const seParam = query.split("&").find((p) => p.startsWith("se="));
75393
- if (!seParam) return;
75394
- const seValue = decodeURIComponent(seParam.slice(3));
75395
- const expiresAt = Date.parse(seValue);
75396
- if (Number.isNaN(expiresAt)) return;
75397
- const now2 = Date.now();
75398
- const daysRemaining = Math.floor((expiresAt - now2) / (1e3 * 60 * 60 * 24));
75399
- if (daysRemaining < 365) {
75400
- console.warn(
75401
- `[recording-fetcher] SAS token in ARCHAL_FIXTURE_BASE_URL expires in ${daysRemaining}d (${seValue}). Rotate via scripts/rotate-fixture-sas.mjs before expiry.`
75402
- );
75403
- }
75404
- }
75405
- warnIfSasExpiresSoon2(DEFAULT_BASE_URL2);
75406
-
75407
75647
  // src/runtime/service-profiles.ts
75408
75648
  function unsupportedServiceMessage(unsupportedServices) {
75409
75649
  const supportedServices = listSharedRouteManifests().map((manifest) => manifest.service).sort();
@@ -75433,11 +75673,11 @@ function resolveArchalVitestServiceProfiles(services) {
75433
75673
  }
75434
75674
 
75435
75675
  // src/runtime/hosted-session-provider.ts
75436
- var import_node_crypto12 = require("crypto");
75676
+ var import_node_crypto13 = require("crypto");
75437
75677
  var import_node_child_process2 = require("child_process");
75438
- var import_node_fs12 = require("fs");
75439
- var import_node_path12 = require("path");
75440
- var import_node_os5 = require("os");
75678
+ var import_node_fs13 = require("fs");
75679
+ var import_node_path13 = require("path");
75680
+ var import_node_os6 = require("os");
75441
75681
 
75442
75682
  // src/url-resolution.ts
75443
75683
  function readFirstConfiguredApiBaseUrl(envVars) {
@@ -75486,20 +75726,20 @@ function toSafeCoordinatorDirectoryName(sessionKey) {
75486
75726
  return sessionKey;
75487
75727
  }
75488
75728
  const slug2 = sessionKey.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^[.-]+|[.-]+$/g, "").slice(0, 48);
75489
- const hash3 = (0, import_node_crypto12.createHash)("sha256").update(sessionKey).digest("hex").slice(0, 12);
75729
+ const hash3 = (0, import_node_crypto13.createHash)("sha256").update(sessionKey).digest("hex").slice(0, 12);
75490
75730
  return `${slug2 || "session"}-${hash3}`;
75491
75731
  }
75492
75732
  function resolveCoordinatorPaths(config3) {
75493
- const baseDirectory = (0, import_node_path12.resolve)(
75494
- trimEnv("ARCHAL_VITEST_COORDINATOR_DIR") ?? (0, import_node_path12.join)((0, import_node_os5.tmpdir)(), "archal-vitest")
75733
+ const baseDirectory = (0, import_node_path13.resolve)(
75734
+ trimEnv("ARCHAL_VITEST_COORDINATOR_DIR") ?? (0, import_node_path13.join)((0, import_node_os6.tmpdir)(), "archal-vitest")
75495
75735
  );
75496
- const sessionKey = config3.sessionKey ?? `${config3.projectName}-${(0, import_node_crypto12.randomUUID)()}`;
75497
- const directory = (0, import_node_path12.resolve)(baseDirectory, toSafeCoordinatorDirectoryName(sessionKey));
75736
+ const sessionKey = config3.sessionKey ?? `${config3.projectName}-${(0, import_node_crypto13.randomUUID)()}`;
75737
+ const directory = (0, import_node_path13.resolve)(baseDirectory, toSafeCoordinatorDirectoryName(sessionKey));
75498
75738
  return {
75499
75739
  directory,
75500
- lockDirectory: (0, import_node_path12.join)(directory, "lock"),
75501
- statePath: (0, import_node_path12.join)(directory, "state.json"),
75502
- reaperPidPath: (0, import_node_path12.join)(directory, "reaper.pid")
75740
+ lockDirectory: (0, import_node_path13.join)(directory, "lock"),
75741
+ statePath: (0, import_node_path13.join)(directory, "state.json"),
75742
+ reaperPidPath: (0, import_node_path13.join)(directory, "reaper.pid")
75503
75743
  };
75504
75744
  }
75505
75745
  function shouldStopSessionOnRelease() {
@@ -75543,20 +75783,20 @@ async function resolveHostedSessionEnvironment() {
75543
75783
  };
75544
75784
  }
75545
75785
  async function withCoordinatorLock(paths, lockTimeoutMs, action) {
75546
- await import_node_fs12.promises.mkdir(paths.directory, { recursive: true });
75786
+ await import_node_fs13.promises.mkdir(paths.directory, { recursive: true });
75547
75787
  const deadline = Date.now() + resolveCoordinatorLockWaitTimeoutMs(lockTimeoutMs);
75548
75788
  while (true) {
75549
75789
  try {
75550
- await import_node_fs12.promises.mkdir(paths.lockDirectory);
75790
+ await import_node_fs13.promises.mkdir(paths.lockDirectory);
75551
75791
  break;
75552
75792
  } catch (error95) {
75553
75793
  const code = error95 instanceof Error && "code" in error95 ? String(error95.code) : "";
75554
75794
  if (code !== "EEXIST") {
75555
75795
  throw error95;
75556
75796
  }
75557
- const stale = await import_node_fs12.promises.stat(paths.lockDirectory).then((stats) => Date.now() - stats.mtimeMs >= COORDINATOR_STALE_LOCK_MS).catch(() => false);
75797
+ const stale = await import_node_fs13.promises.stat(paths.lockDirectory).then((stats) => Date.now() - stats.mtimeMs >= COORDINATOR_STALE_LOCK_MS).catch(() => false);
75558
75798
  if (stale) {
75559
- await import_node_fs12.promises.rm(paths.lockDirectory, { recursive: true, force: true }).catch(() => {
75799
+ await import_node_fs13.promises.rm(paths.lockDirectory, { recursive: true, force: true }).catch(() => {
75560
75800
  });
75561
75801
  continue;
75562
75802
  }
@@ -75570,7 +75810,7 @@ async function withCoordinatorLock(paths, lockTimeoutMs, action) {
75570
75810
  }
75571
75811
  try {
75572
75812
  const keepalive = setInterval(() => {
75573
- void import_node_fs12.promises.utimes(paths.lockDirectory, /* @__PURE__ */ new Date(), /* @__PURE__ */ new Date()).catch(() => void 0);
75813
+ void import_node_fs13.promises.utimes(paths.lockDirectory, /* @__PURE__ */ new Date(), /* @__PURE__ */ new Date()).catch(() => void 0);
75574
75814
  }, 1e3);
75575
75815
  keepalive.unref();
75576
75816
  try {
@@ -75579,7 +75819,7 @@ async function withCoordinatorLock(paths, lockTimeoutMs, action) {
75579
75819
  clearInterval(keepalive);
75580
75820
  }
75581
75821
  } finally {
75582
- await import_node_fs12.promises.rm(paths.lockDirectory, { recursive: true, force: true });
75822
+ await import_node_fs13.promises.rm(paths.lockDirectory, { recursive: true, force: true });
75583
75823
  }
75584
75824
  }
75585
75825
  function resolveCoordinatorLockWaitTimeoutMs(readyTimeoutMs) {
@@ -75589,11 +75829,11 @@ async function readCoordinatorState(paths) {
75589
75829
  if (!await fileExists(paths.statePath)) {
75590
75830
  return { kind: "missing" };
75591
75831
  }
75592
- const raw = await import_node_fs12.promises.readFile(paths.statePath, "utf8");
75832
+ const raw = await import_node_fs13.promises.readFile(paths.statePath, "utf8");
75593
75833
  try {
75594
75834
  const normalizedState = normalizeCoordinatorState(JSON.parse(raw));
75595
75835
  if (!normalizedState) {
75596
- await import_node_fs12.promises.rm(paths.statePath, { force: true }).catch(() => void 0);
75836
+ await import_node_fs13.promises.rm(paths.statePath, { force: true }).catch(() => void 0);
75597
75837
  return { kind: "corrupt" };
75598
75838
  }
75599
75839
  return {
@@ -75601,7 +75841,7 @@ async function readCoordinatorState(paths) {
75601
75841
  state: normalizedState
75602
75842
  };
75603
75843
  } catch {
75604
- await import_node_fs12.promises.rm(paths.statePath, { force: true }).catch(() => void 0);
75844
+ await import_node_fs13.promises.rm(paths.statePath, { force: true }).catch(() => void 0);
75605
75845
  return { kind: "corrupt" };
75606
75846
  }
75607
75847
  }
@@ -75716,16 +75956,16 @@ function normalizeStringRecord(input) {
75716
75956
  return entries.length === Object.keys(record3).length ? Object.fromEntries(entries) : null;
75717
75957
  }
75718
75958
  async function writeCoordinatorState(paths, state) {
75719
- await import_node_fs12.promises.writeFile(paths.statePath, JSON.stringify(state, null, 2) + "\n", "utf8");
75959
+ await import_node_fs13.promises.writeFile(paths.statePath, JSON.stringify(state, null, 2) + "\n", "utf8");
75720
75960
  }
75721
75961
  async function clearCoordinatorState(paths) {
75722
75962
  await Promise.all([
75723
- import_node_fs12.promises.rm(paths.statePath, { force: true }),
75724
- import_node_fs12.promises.rm(paths.reaperPidPath, { force: true })
75963
+ import_node_fs13.promises.rm(paths.statePath, { force: true }),
75964
+ import_node_fs13.promises.rm(paths.reaperPidPath, { force: true })
75725
75965
  ]);
75726
75966
  }
75727
75967
  async function readRunnerReaperState(paths) {
75728
- const raw = await import_node_fs12.promises.readFile(paths.reaperPidPath, "utf8").catch(() => null);
75968
+ const raw = await import_node_fs13.promises.readFile(paths.reaperPidPath, "utf8").catch(() => null);
75729
75969
  if (!raw) {
75730
75970
  return null;
75731
75971
  }
@@ -75759,12 +75999,12 @@ async function readRunnerReaperState(paths) {
75759
75999
  }
75760
76000
  }
75761
76001
  async function writeRunnerReaperState(paths, state) {
75762
- await import_node_fs12.promises.writeFile(paths.reaperPidPath, JSON.stringify(state) + "\n", "utf8");
76002
+ await import_node_fs13.promises.writeFile(paths.reaperPidPath, JSON.stringify(state) + "\n", "utf8");
75763
76003
  }
75764
76004
  async function stopRunnerReaper(paths) {
75765
76005
  const reaperState = await readRunnerReaperState(paths);
75766
76006
  if (!reaperState) {
75767
- await import_node_fs12.promises.rm(paths.reaperPidPath, { force: true }).catch(() => void 0);
76007
+ await import_node_fs13.promises.rm(paths.reaperPidPath, { force: true }).catch(() => void 0);
75768
76008
  return;
75769
76009
  }
75770
76010
  if (isProcessAlive(reaperState.pid)) {
@@ -75773,7 +76013,7 @@ async function stopRunnerReaper(paths) {
75773
76013
  } catch {
75774
76014
  }
75775
76015
  }
75776
- await import_node_fs12.promises.rm(paths.reaperPidPath, { force: true }).catch(() => void 0);
76016
+ await import_node_fs13.promises.rm(paths.reaperPidPath, { force: true }).catch(() => void 0);
75777
76017
  }
75778
76018
  function pruneLeases(leases) {
75779
76019
  return leases.filter((lease) => isProcessAlive(lease.pid));
@@ -75966,7 +76206,7 @@ var CoordinatedHostedSessionManager = class {
75966
76206
  if (reusableSession && requestedSeedsMatchSession(requestedSeeds, reusableSession)) {
75967
76207
  await this.ensureRunnerReaper(reusableSession.sessionId, runnerPid);
75968
76208
  if (trimEnv("ARCHAL_VITEST_DISABLE_RUNNER_REAPER") === "1") {
75969
- await import_node_fs12.promises.rm(this.paths.reaperPidPath, { force: true }).catch(() => void 0);
76209
+ await import_node_fs13.promises.rm(this.paths.reaperPidPath, { force: true }).catch(() => void 0);
75970
76210
  }
75971
76211
  await writeCoordinatorState(this.paths, {
75972
76212
  session: reusableSession,
@@ -76023,7 +76263,7 @@ var CoordinatedHostedSessionManager = class {
76023
76263
  };
76024
76264
  function buildNoSession() {
76025
76265
  return {
76026
- sessionId: `archal-vitest-${(0, import_node_crypto12.randomUUID)()}`,
76266
+ sessionId: `archal-vitest-${(0, import_node_crypto13.randomUUID)()}`,
76027
76267
  services: [],
76028
76268
  resolvedRuntime: {
76029
76269
  resolvedServices: [],
@@ -76420,11 +76660,11 @@ async function buildRuntimeConfig(scope) {
76420
76660
  };
76421
76661
  scope[GLOBAL_SESSION_KEY] = redactSessionSnapshot(session);
76422
76662
  try {
76423
- const { writeFileSync: writeFileSync8, mkdirSync: mkdirSync7 } = await import("fs");
76424
- const { dirname: dirname10 } = await import("path");
76663
+ const { writeFileSync: writeFileSync9, mkdirSync: mkdirSync8 } = await import("fs");
76664
+ const { dirname: dirname12 } = await import("path");
76425
76665
  const sessionIdPath = getSessionIdFilePath(config3.sessionKey);
76426
- mkdirSync7(dirname10(sessionIdPath), { recursive: true });
76427
- writeFileSync8(sessionIdPath, session.sessionId, "utf-8");
76666
+ mkdirSync8(dirname12(sessionIdPath), { recursive: true });
76667
+ writeFileSync9(sessionIdPath, session.sessionId, "utf-8");
76428
76668
  } catch {
76429
76669
  }
76430
76670
  return {
@@ -76951,11 +77191,11 @@ var ArchalReporter = class {
76951
77191
  }
76952
77192
  }
76953
77193
  async readSessionId(sessionKey) {
76954
- const { readFileSync: readFileSync9, readdirSync: readdirSync4, statSync: statSync3 } = await import("fs");
76955
- const { dirname: dirname10, join: join8 } = await import("path");
77194
+ const { readFileSync: readFileSync10, readdirSync: readdirSync4, statSync: statSync3 } = await import("fs");
77195
+ const { dirname: dirname12, join: join8 } = await import("path");
76956
77196
  if (sessionKey?.trim()) {
76957
77197
  try {
76958
- const keyed = readFileSync9(getSessionIdFilePath(sessionKey), "utf-8").trim();
77198
+ const keyed = readFileSync10(getSessionIdFilePath(sessionKey), "utf-8").trim();
76959
77199
  if (keyed) return keyed;
76960
77200
  } catch {
76961
77201
  }
@@ -76964,7 +77204,7 @@ var ArchalReporter = class {
76964
77204
  return void 0;
76965
77205
  }
76966
77206
  try {
76967
- const sessionsDir = dirname10(getSessionIdFilePath("any"));
77207
+ const sessionsDir = dirname12(getSessionIdFilePath("any"));
76968
77208
  const entries = readdirSync4(sessionsDir);
76969
77209
  let newest;
76970
77210
  for (const name of entries) {
@@ -76979,7 +77219,7 @@ var ArchalReporter = class {
76979
77219
  }
76980
77220
  }
76981
77221
  if (newest) {
76982
- const content = readFileSync9(newest.path, "utf-8").trim();
77222
+ const content = readFileSync10(newest.path, "utf-8").trim();
76983
77223
  if (content) return content;
76984
77224
  }
76985
77225
  } catch {
@@ -76989,14 +77229,14 @@ var ArchalReporter = class {
76989
77229
  };
76990
77230
 
76991
77231
  // src/seed-files.ts
76992
- var import_node_crypto13 = require("crypto");
76993
- var import_node_fs13 = require("fs");
76994
- var import_node_path13 = require("path");
77232
+ var import_node_crypto14 = require("crypto");
77233
+ var import_node_fs14 = require("fs");
77234
+ var import_node_path14 = require("path");
76995
77235
  var MAX_SEED_FILE_BYTES = 256 * 1024;
76996
77236
  function classifySeed(value) {
76997
77237
  const trimmed = value.trim();
76998
77238
  if (trimmed.startsWith("./") || trimmed.startsWith("../") || trimmed.startsWith("/")) {
76999
- const ext = (0, import_node_path13.extname)(trimmed).toLowerCase();
77239
+ const ext = (0, import_node_path14.extname)(trimmed).toLowerCase();
77000
77240
  if (ext === ".json") return { type: "file", path: trimmed, format: "json" };
77001
77241
  if (ext === ".md") return { type: "file", path: trimmed, format: "markdown" };
77002
77242
  throw new Error(
@@ -77006,21 +77246,21 @@ function classifySeed(value) {
77006
77246
  );
77007
77247
  }
77008
77248
  if (trimmed.endsWith(".json") || trimmed.endsWith(".md")) {
77009
- const ext = (0, import_node_path13.extname)(trimmed).toLowerCase();
77249
+ const ext = (0, import_node_path14.extname)(trimmed).toLowerCase();
77010
77250
  const format = ext === ".json" ? "json" : "markdown";
77011
77251
  return { type: "file", path: trimmed, format };
77012
77252
  }
77013
77253
  return { type: "named", name: trimmed };
77014
77254
  }
77015
77255
  function readSeedFile(seedPath, serviceName) {
77016
- const resolved = (0, import_node_path13.resolve)(seedPath);
77017
- if (!(0, import_node_fs13.existsSync)(resolved)) {
77256
+ const resolved = (0, import_node_path14.resolve)(seedPath);
77257
+ if (!(0, import_node_fs14.existsSync)(resolved)) {
77018
77258
  throw new Error(
77019
77259
  `Seed file not found for ${serviceName}: ${resolved}
77020
77260
  Check the path relative to your project root.`
77021
77261
  );
77022
77262
  }
77023
- const content = (0, import_node_fs13.readFileSync)(resolved, "utf-8");
77263
+ const content = (0, import_node_fs14.readFileSync)(resolved, "utf-8");
77024
77264
  if (Buffer.byteLength(content, "utf-8") > MAX_SEED_FILE_BYTES) {
77025
77265
  throw new Error(
77026
77266
  `Seed file for ${serviceName} exceeds ${MAX_SEED_FILE_BYTES / 1024}KB limit: ${resolved}`
@@ -77036,12 +77276,12 @@ function computeStableSessionKey(projectName, services, fileSeedContents, fileSe
77036
77276
  return {
77037
77277
  name,
77038
77278
  mode: svc?.mode,
77039
- seed: fileContent ? (0, import_node_crypto13.createHash)("sha256").update(fileContent).digest("hex").slice(0, 16) : svc?.seed ?? null,
77279
+ seed: fileContent ? (0, import_node_crypto14.createHash)("sha256").update(fileContent).digest("hex").slice(0, 16) : svc?.seed ?? null,
77040
77280
  ...format ? { seedFormat: format } : {}
77041
77281
  };
77042
77282
  });
77043
77283
  const payload = JSON.stringify({ projectName, services: sortedServices });
77044
- return (0, import_node_crypto13.createHash)("sha256").update(payload).digest("hex").slice(0, 16);
77284
+ return (0, import_node_crypto14.createHash)("sha256").update(payload).digest("hex").slice(0, 16);
77045
77285
  }
77046
77286
 
77047
77287
  // src/webhooks.ts
@@ -77101,7 +77341,7 @@ async function waitForArchalWebhook(serviceName, matcher, options = {}) {
77101
77341
  return match;
77102
77342
  }
77103
77343
  if (Date.now() + interval >= deadline) break;
77104
- await new Promise((resolve10) => setTimeout(resolve10, interval));
77344
+ await new Promise((resolve12) => setTimeout(resolve12, interval));
77105
77345
  interval = Math.min(250, Math.round(interval * 1.5));
77106
77346
  }
77107
77347
  const elapsed = Date.now() - startTime;
@@ -77128,8 +77368,8 @@ var DEFAULT_EXCLUDE_PATTERNS = [
77128
77368
  ];
77129
77369
  var ARCHAL_VITEST_WIRING_MARKER_ENV = "ARCHAL_VITEST_WIRING_MARKER";
77130
77370
  var ARCHAL_VITEST_WORKSPACE_REPORTER_MARKER_ENV = "ARCHAL_VITEST_WORKSPACE_REPORTER_MARKER";
77131
- var currentModuleFile = typeof __filename === "string" && (0, import_node_path14.isAbsolute)(__filename) ? __filename : (0, import_node_url4.fileURLToPath)(__archal_import_meta_url);
77132
- var reporterEntryModule = (0, import_node_path14.resolve)((0, import_node_path14.dirname)(currentModuleFile), "../reporter-entry.js");
77371
+ var currentModuleFile = typeof __filename === "string" && (0, import_node_path15.isAbsolute)(__filename) ? __filename : (0, import_node_url4.fileURLToPath)(__archal_import_meta_url);
77372
+ var reporterEntryModule = (0, import_node_path15.resolve)((0, import_node_path15.dirname)(currentModuleFile), "../reporter-entry.js");
77133
77373
  function buildTestConfig(options, testOptions) {
77134
77374
  markHelperCalled();
77135
77375
  assertSupportedArchalVitestServices(options.services);