archal 0.9.20 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +59 -159
- package/agents/openclaw/Dockerfile +2 -1
- package/agents/openclaw/README.md +10 -17
- package/agents/openclaw/drive.mjs +21 -31
- package/agents/openclaw/extract-openclaw-response-text.mjs +49 -0
- package/agents/openclaw/scenarios/acceptance/github-escalation-and-cleanup.md +43 -0
- package/agents/openclaw/scenarios/acceptance/jira-linear-release-triage.md +39 -0
- package/agents/openclaw/scenarios/acceptance/multi-clone-customer-risk-review.md +45 -0
- package/agents/openclaw/scenarios/acceptance/slack-incident-handoff.md +42 -0
- package/agents/openclaw/scenarios/acceptance/stripe-dunning-remediation.md +40 -0
- package/agents/openclaw/scenarios/close-stale-issues.md +35 -0
- package/agents/openclaw/workspace/TOOLS.md +19 -0
- package/clone-assets/calcom/tools.json +1705 -153
- package/clone-assets/clickup/tools.json +2528 -541
- package/clone-assets/customerio/tools.json +2108 -144
- package/clone-assets/github/tools.json +1 -2
- package/clone-assets/gitlab/tools.json +10087 -398
- package/clone-assets/hubspot/tools.json +198 -0
- package/clone-assets/linear/tools.json +41 -1
- package/clone-assets/sentry/tools.json +2264 -188
- package/clone-assets/stripe/tools.json +114 -0
- package/clone-assets/webflow/tools.json +1895 -125
- package/dist/{autoloop-worker-types-BEb_E44z.d.cts → autoloop-worker-types-CHaclqtD.d.cts} +23 -59
- package/dist/cli.cjs +107175 -126959
- package/dist/commands/{autoloop-hosted-worker.cjs → autoloop-hosted-control-plane-client.cjs} +25657 -42736
- package/dist/commands/{autoloop-hosted-worker.d.cts → autoloop-hosted-control-plane-client.d.cts} +32 -42
- package/dist/commands/autoloop-pr-verification.cjs +607 -522
- package/dist/commands/autoloop-pr-verification.d.cts +3 -1
- package/dist/commands/autoloop-result-parser.cjs +2474 -2373
- package/dist/commands/autoloop-result-parser.d.cts +159 -2
- package/dist/commands/autoloop-worker.cjs +14565 -12240
- package/dist/commands/autoloop-worker.d.cts +10 -5
- package/dist/eval-shim.mjs +216 -0
- package/dist/index.cjs +15 -2
- package/dist/index.d.cts +3 -1
- package/dist/layer-1-ziaLpfLr.d.cts +62 -0
- package/dist/metafile-cjs.json +1 -0
- package/dist/reporter-entry.js +3 -0
- package/dist/{replay.cjs → sdk/index.cjs} +42979 -40973
- package/dist/sdk/index.d.cts +626 -0
- package/dist/vitest/{chunk-6CBYFCFK.js → chunk-2PDHTPZC.js} +289 -89
- package/dist/vitest/{chunk-ARVS45PP.js → chunk-7L4BBB6M.js} +123 -274
- package/dist/vitest/index.cjs +500 -816
- package/dist/vitest/index.d.ts +16 -81
- package/dist/vitest/index.js +40 -409
- package/dist/vitest/runtime/hosted-session-reaper.cjs +143 -293
- package/dist/vitest/runtime/hosted-session-reaper.js +1 -1
- package/dist/vitest/runtime/setup-files.js +2 -2
- package/manifest.json +9 -0
- package/package.json +14 -13
- package/skills/archal-agent/SKILL.md +0 -1
- package/skills/autoloop/SKILL.md +288 -273
- package/skills/autoloop/references/hosted-sources.md +49 -17
- package/skills/autoloop/references/trace-schema-mapping.md +83 -52
- package/skills/eval/SKILL.md +16 -48
- package/skills/free-account/SKILL.md +103 -0
- package/skills/install-agent/SKILL.md +16 -35
- package/skills/onboard/SKILL.md +13 -70
- package/skills/scenario/SKILL.md +30 -27
- package/skills/seed/SKILL.md +7 -6
- package/skills/vitest/SKILL.md +3 -2
- package/agents/github-octokit/.archal.json +0 -8
- package/agents/github-octokit/Dockerfile +0 -8
- package/agents/github-octokit/README.md +0 -113
- package/agents/github-octokit/agent.mjs +0 -54
- package/agents/github-octokit/package.json +0 -9
- package/agents/github-octokit/scenarios/test-repo-access.md +0 -27
- package/agents/google-workspace-local-tools/Dockerfile +0 -6
- package/agents/google-workspace-local-tools/README.md +0 -58
- package/agents/google-workspace-local-tools/agent.mjs +0 -196
- package/agents/google-workspace-local-tools/archal-harness.json +0 -7
- package/agents/google-workspace-local-tools/run-input.yaml +0 -16
- package/agents/google-workspace-local-tools/scenario.md +0 -29
- package/agents/hermes/.archal.json +0 -8
- package/agents/hermes/Dockerfile +0 -46
- package/agents/hermes/README.md +0 -87
- package/agents/hermes/SOUL.md +0 -27
- package/agents/hermes/config.yaml +0 -34
- package/agents/hermes/drive.mjs +0 -113
- package/agents/hermes/scenarios/stripe-customers-read-only.md +0 -32
- package/agents/pagination-test/README.md +0 -24
- package/agents/pagination-test/scenario.md +0 -24
- package/agents/replay-capsule-harness/README.md +0 -29
- package/agents/replay-capsule-harness/observability-install-offline-e2e.mts +0 -1517
- package/agents/replay-capsule-harness/replay-capsule-e2e.mjs +0 -104
- package/dist/harness.cjs +0 -63
- package/dist/harness.d.cts +0 -20
- package/dist/replay.d.cts +0 -4625
- package/dist/scenarios.cjs +0 -80343
- package/dist/scenarios.d.cts +0 -562
|
@@ -14,6 +14,7 @@ var CREDENTIALS_MASTER_KEY_ENV_VAR = "ARCHAL_CREDENTIALS_MASTER_KEY";
|
|
|
14
14
|
var KEYCHAIN_SERVICE = "archal-cli";
|
|
15
15
|
var KEYCHAIN_ACCOUNT = "credentials-master-key";
|
|
16
16
|
var HOSTED_DEFAULT_AUTH_BASE_URL = "https://www.archal.ai";
|
|
17
|
+
var WORKSPACE_API_KEY_PREFIX = "archal_ws_";
|
|
17
18
|
var STRICT_ENDPOINTS_ENV_VAR = "ARCHAL_STRICT_ENDPOINTS";
|
|
18
19
|
var REQUEST_TIMEOUT_MS = 8e3;
|
|
19
20
|
var ENV_TOKEN_FALLBACK_TTL_SECONDS = 24 * 60 * 60;
|
|
@@ -23,11 +24,6 @@ function isPlan(value) {
|
|
|
23
24
|
return value === "free" || value === "pro" || value === "enterprise";
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
// ../node-auth/src/errors.ts
|
|
27
|
-
function errorMessage(error) {
|
|
28
|
-
return error instanceof Error ? error.message : String(error);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
27
|
// ../node-auth/src/credential-store.ts
|
|
32
28
|
var import_node_child_process = require("child_process");
|
|
33
29
|
var import_node_crypto = require("crypto");
|
|
@@ -60,7 +56,7 @@ var GENERATED_CLONE_CATALOG = [
|
|
|
60
56
|
name: "Cal.com",
|
|
61
57
|
description: "Event types, schedules, availability slots, bookings, calendars, and webhooks.",
|
|
62
58
|
stage: "preview",
|
|
63
|
-
toolCount:
|
|
59
|
+
toolCount: 35,
|
|
64
60
|
transport: "both",
|
|
65
61
|
architectureClass: "domain-simulator",
|
|
66
62
|
domainPrimitives: [
|
|
@@ -78,7 +74,7 @@ var GENERATED_CLONE_CATALOG = [
|
|
|
78
74
|
name: "ClickUp",
|
|
79
75
|
description: "Teams, spaces, folders, lists, tasks, comments, tags, time tracking, and checklists.",
|
|
80
76
|
stage: "preview",
|
|
81
|
-
toolCount:
|
|
77
|
+
toolCount: 123,
|
|
82
78
|
transport: "both",
|
|
83
79
|
architectureClass: "standard-core",
|
|
84
80
|
domainPrimitives: [],
|
|
@@ -91,7 +87,7 @@ var GENERATED_CLONE_CATALOG = [
|
|
|
91
87
|
name: "Customer.io",
|
|
92
88
|
description: "Messaging automation across campaigns, broadcasts, transactional email, segments, customers, and message delivery.",
|
|
93
89
|
stage: "preview",
|
|
94
|
-
toolCount:
|
|
90
|
+
toolCount: 129,
|
|
95
91
|
transport: "rest",
|
|
96
92
|
architectureClass: "standard-core",
|
|
97
93
|
domainPrimitives: [],
|
|
@@ -156,7 +152,7 @@ var GENERATED_CLONE_CATALOG = [
|
|
|
156
152
|
name: "GitLab",
|
|
157
153
|
description: "Projects, branches, commits, issues, merge requests, pipelines, labels, milestones, releases, and webhooks.",
|
|
158
154
|
stage: "preview",
|
|
159
|
-
toolCount:
|
|
155
|
+
toolCount: 559,
|
|
160
156
|
transport: "both",
|
|
161
157
|
architectureClass: "domain-simulator",
|
|
162
158
|
domainPrimitives: [
|
|
@@ -191,7 +187,7 @@ var GENERATED_CLONE_CATALOG = [
|
|
|
191
187
|
name: "HubSpot",
|
|
192
188
|
description: "CRM contacts, companies, deals, tickets, and engagements.",
|
|
193
189
|
stage: "preview",
|
|
194
|
-
toolCount:
|
|
190
|
+
toolCount: 44,
|
|
195
191
|
transport: "rest",
|
|
196
192
|
architectureClass: "replay-shell",
|
|
197
193
|
domainPrimitives: [
|
|
@@ -226,7 +222,7 @@ var GENERATED_CLONE_CATALOG = [
|
|
|
226
222
|
name: "Linear",
|
|
227
223
|
description: "Issues, projects, teams, cycles, and workflows.",
|
|
228
224
|
stage: "public",
|
|
229
|
-
toolCount:
|
|
225
|
+
toolCount: 53,
|
|
230
226
|
transport: "both",
|
|
231
227
|
architectureClass: "domain-simulator",
|
|
232
228
|
domainPrimitives: [
|
|
@@ -295,7 +291,7 @@ var GENERATED_CLONE_CATALOG = [
|
|
|
295
291
|
name: "Sentry",
|
|
296
292
|
description: "Error monitoring across organizations, projects, teams, issues, events, releases, and DSN keys.",
|
|
297
293
|
stage: "preview",
|
|
298
|
-
toolCount:
|
|
294
|
+
toolCount: 34,
|
|
299
295
|
transport: "rest",
|
|
300
296
|
architectureClass: "domain-simulator",
|
|
301
297
|
domainPrimitives: [
|
|
@@ -397,14 +393,10 @@ var GENERATED_CLONE_CATALOG = [
|
|
|
397
393
|
name: "Webflow",
|
|
398
394
|
description: "Sites, pages, CMS collections, items, assets, forms, and webhooks.",
|
|
399
395
|
stage: "preview",
|
|
400
|
-
toolCount:
|
|
401
|
-
transport: "
|
|
402
|
-
architectureClass: "
|
|
403
|
-
domainPrimitives: [
|
|
404
|
-
"recording replay cursor",
|
|
405
|
-
"CMS collection/item overlays",
|
|
406
|
-
"publish lifecycle captures"
|
|
407
|
-
],
|
|
396
|
+
toolCount: 104,
|
|
397
|
+
transport: "both",
|
|
398
|
+
architectureClass: "standard-core",
|
|
399
|
+
domainPrimitives: [],
|
|
408
400
|
behaviorOwner: null,
|
|
409
401
|
opsCoverage: 100
|
|
410
402
|
}
|
|
@@ -500,142 +492,11 @@ var STARTABLE_CLONE_CATALOG = CLONE_CATALOG.filter(
|
|
|
500
492
|
(entry) => STARTABLE_CLONE_ID_SET.has(entry.id)
|
|
501
493
|
);
|
|
502
494
|
|
|
503
|
-
// ../
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
);
|
|
508
|
-
|
|
509
|
-
// ../billing-constants/src/index.ts
|
|
510
|
-
var PLAN_MONTHLY_TWIN_MINUTE_LIMITS = {
|
|
511
|
-
free: 500,
|
|
512
|
-
pro: 5e3,
|
|
513
|
-
enterprise: null
|
|
514
|
-
};
|
|
515
|
-
var PLAN_CONCURRENT_SESSION_LIMITS = {
|
|
516
|
-
free: 3,
|
|
517
|
-
pro: 10,
|
|
518
|
-
enterprise: 50
|
|
519
|
-
};
|
|
520
|
-
var FREE_WORKSPACE_MEMBER_LIMIT = 2;
|
|
521
|
-
var PRO_PLAN_PRICE_USD = 199;
|
|
522
|
-
function formatMinutesLabel(minutes) {
|
|
523
|
-
return minutes.toLocaleString("en-US");
|
|
524
|
-
}
|
|
525
|
-
var FREE_MINUTES = PLAN_MONTHLY_TWIN_MINUTE_LIMITS.free;
|
|
526
|
-
var PRO_MINUTES = PLAN_MONTHLY_TWIN_MINUTE_LIMITS.pro;
|
|
527
|
-
if (FREE_MINUTES == null || PRO_MINUTES == null) {
|
|
528
|
-
throw new Error("PLAN_MONTHLY_TWIN_MINUTE_LIMITS: free and pro must be non-null");
|
|
529
|
-
}
|
|
530
|
-
var PRO_EVALS_PER_SEAT = 500;
|
|
531
|
-
var PRO_SESSION_MINUTES_PER_SEAT = 5e3;
|
|
532
|
-
var PRO_MAX_SEATS = 5;
|
|
533
|
-
var FREE_EVALS_PER_MONTH = 100;
|
|
534
|
-
var PLAN_DISPLAY = {
|
|
535
|
-
free: {
|
|
536
|
-
tag: "Free",
|
|
537
|
-
priceLabel: "$0",
|
|
538
|
-
periodLabel: "",
|
|
539
|
-
included: [
|
|
540
|
-
`${formatMinutesLabel(FREE_MINUTES)} session-minutes / account`,
|
|
541
|
-
`${FREE_EVALS_PER_MONTH} evals / account`,
|
|
542
|
-
`1 workspace (${FREE_WORKSPACE_MEMBER_LIMIT} users max)`,
|
|
543
|
-
`${PLAN_CONCURRENT_SESSION_LIMITS.free} concurrent sessions / workspace`,
|
|
544
|
-
"All clones included"
|
|
545
|
-
]
|
|
546
|
-
},
|
|
547
|
-
pro: {
|
|
548
|
-
tag: "Pro",
|
|
549
|
-
priceLabel: `$${PRO_PLAN_PRICE_USD}`,
|
|
550
|
-
periodLabel: "/mo per seat",
|
|
551
|
-
included: [
|
|
552
|
-
`${formatMinutesLabel(PRO_SESSION_MINUTES_PER_SEAT)} session-minutes / seat / month`,
|
|
553
|
-
`${PRO_EVALS_PER_SEAT} evals / seat / month`,
|
|
554
|
-
"All clones included",
|
|
555
|
-
`${PLAN_CONCURRENT_SESSION_LIMITS.pro} concurrent sessions / workspace`,
|
|
556
|
-
`1 workspace, up to ${PRO_MAX_SEATS} seats with pooled usage`
|
|
557
|
-
]
|
|
558
|
-
},
|
|
559
|
-
enterprise: {
|
|
560
|
-
tag: "Enterprise",
|
|
561
|
-
priceLabel: "Contact us",
|
|
562
|
-
periodLabel: "",
|
|
563
|
-
included: [
|
|
564
|
-
"Unlimited session-minutes",
|
|
565
|
-
"Unlimited seats per workspace",
|
|
566
|
-
"Unlimited workspaces",
|
|
567
|
-
`${PLAN_CONCURRENT_SESSION_LIMITS.enterprise} concurrent sessions / workspace`,
|
|
568
|
-
"SSO / SAML",
|
|
569
|
-
"SOC 2 (in progress)",
|
|
570
|
-
"Custom clones & eval support",
|
|
571
|
-
"Dedicated onboarding & support"
|
|
572
|
-
]
|
|
573
|
-
}
|
|
574
|
-
};
|
|
575
|
-
var PLAN_MAX_SESSION_TTL_SECONDS = {
|
|
576
|
-
free: 30 * 60,
|
|
577
|
-
// 30 minutes
|
|
578
|
-
pro: 60 * 60,
|
|
579
|
-
// 60 minutes
|
|
580
|
-
enterprise: 90 * 60
|
|
581
|
-
// 90 minutes
|
|
582
|
-
};
|
|
583
|
-
var MAX_ABSOLUTE_SESSION_LIFETIME_SECONDS = 4 * 60 * 60;
|
|
584
|
-
var LIFETIME_PERIOD_RESETS_AT = new Date(Date.UTC(9999, 11, 31));
|
|
585
|
-
var ALL_ENTITLED_CLONES = ALL_STARTABLE_CLONE_IDS;
|
|
586
|
-
var SCENARIO_USAGE_WINDOW_DAYS = 7;
|
|
587
|
-
var SCENARIO_USAGE_WINDOW_MS = SCENARIO_USAGE_WINDOW_DAYS * 24 * 60 * 60 * 1e3;
|
|
588
|
-
var SCENARIO_USAGE_WINDOW_SECONDS = SCENARIO_USAGE_WINDOW_DAYS * 24 * 60 * 60;
|
|
589
|
-
var LLM_PRICING_USD_PER_M_TOKENS = {
|
|
590
|
-
// Google Gemini (verified 2026-05-05, standard tier <=200K input tokens)
|
|
591
|
-
"gemini-2.5-pro": { input: 1.25, output: 10 },
|
|
592
|
-
"gemini-2.5-flash": { input: 0.3, output: 2.5 },
|
|
593
|
-
// OpenAI flagship text models (verified 2026-05-21, standard short-context tier)
|
|
594
|
-
"gpt-5.5": { input: 5, output: 30 },
|
|
595
|
-
"gpt-5.5-pro": { input: 30, output: 180 },
|
|
596
|
-
"gpt-5.4": { input: 2.5, output: 15 },
|
|
597
|
-
"gpt-5.4-mini": { input: 0.75, output: 4.5 },
|
|
598
|
-
"gpt-5.4-nano": { input: 0.2, output: 1.25 },
|
|
599
|
-
"gpt-5.4-pro": { input: 30, output: 180 },
|
|
600
|
-
"gpt-4o-mini": { input: 0.15, output: 0.6 },
|
|
601
|
-
"gpt-4o": { input: 2.5, output: 10 },
|
|
602
|
-
"gpt-4.1-mini": { input: 0.4, output: 1.6 },
|
|
603
|
-
"gpt-4.1-nano": { input: 0.1, output: 0.4 },
|
|
604
|
-
"gpt-4.1": { input: 2, output: 8 },
|
|
605
|
-
// DeepSeek (verified 2026-05-05; legacy names map to v4-flash per vendor)
|
|
606
|
-
"deepseek-chat": { input: 0.14, output: 0.28 },
|
|
607
|
-
"deepseek-reasoner": { input: 0.14, output: 0.28 },
|
|
608
|
-
"deepseek-v4-flash": { input: 0.14, output: 0.28 }
|
|
609
|
-
};
|
|
610
|
-
var LLM_PRICING_FAMILY_RATES = [
|
|
611
|
-
{ match: /^gemini-2\.5-pro/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gemini-2.5-pro"] },
|
|
612
|
-
{ match: /^gemini-2\.5-flash/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gemini-2.5-flash"] },
|
|
613
|
-
{ match: /^gpt-5\.5-pro/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-5.5-pro"] },
|
|
614
|
-
{ match: /^gpt-5\.5/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-5.5"] },
|
|
615
|
-
{ match: /^gpt-5\.4-pro/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-5.4-pro"] },
|
|
616
|
-
{ match: /^gpt-5\.4-mini/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-5.4-mini"] },
|
|
617
|
-
{ match: /^gpt-5\.4-nano/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-5.4-nano"] },
|
|
618
|
-
{ match: /^gpt-5\.4/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-5.4"] },
|
|
619
|
-
{ match: /^gpt-4o-mini/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-4o-mini"] },
|
|
620
|
-
{ match: /^gpt-4o(?!-mini)/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-4o"] },
|
|
621
|
-
{ match: /^gpt-4\.1-mini/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-4.1-mini"] },
|
|
622
|
-
{ match: /^gpt-4\.1-nano/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-4.1-nano"] },
|
|
623
|
-
{ match: /^gpt-4\.1(?!-mini|-nano)/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-4.1"] },
|
|
624
|
-
// Anthropic Claude 4.x list prices (verified 2026): Opus $5/$25, Sonnet
|
|
625
|
-
// $3/$15, Haiku 4.5 $1/$5 per 1M tokens (input/output).
|
|
626
|
-
{ match: /^claude-opus-/i, rate: { input: 5, output: 25 } },
|
|
627
|
-
{ match: /^claude-haiku-/i, rate: { input: 1, output: 5 } },
|
|
628
|
-
{ match: /^claude-sonnet-/i, rate: { input: 3, output: 15 } },
|
|
629
|
-
{ match: /^opus-/i, rate: { input: 5, output: 25 } },
|
|
630
|
-
{ match: /^haiku-/i, rate: { input: 1, output: 5 } },
|
|
631
|
-
{ match: /^sonnet-/i, rate: { input: 3, output: 15 } },
|
|
632
|
-
{ match: /^deepseek-chat/i, rate: LLM_PRICING_USD_PER_M_TOKENS["deepseek-chat"] },
|
|
633
|
-
{ match: /^deepseek-reasoner/i, rate: LLM_PRICING_USD_PER_M_TOKENS["deepseek-reasoner"] },
|
|
634
|
-
{ match: /^deepseek-v4-flash/i, rate: LLM_PRICING_USD_PER_M_TOKENS["deepseek-v4-flash"] }
|
|
635
|
-
];
|
|
636
|
-
|
|
637
|
-
// ../node-auth/src/clone-entitlements.ts
|
|
638
|
-
var ENTITLED_CLONE_SET = new Set(ALL_ENTITLED_CLONES);
|
|
495
|
+
// ../node-auth/src/credential-store.ts
|
|
496
|
+
function errorMessage(error) {
|
|
497
|
+
return error instanceof Error ? error.message : String(error);
|
|
498
|
+
}
|
|
499
|
+
var ENTITLED_CLONE_SET = new Set(ALL_STARTABLE_CLONE_IDS);
|
|
639
500
|
function normalizeEntitledCloneIds(cloneIds) {
|
|
640
501
|
if (!cloneIds) {
|
|
641
502
|
return [];
|
|
@@ -652,8 +513,6 @@ function normalizeEntitledCloneIds(cloneIds) {
|
|
|
652
513
|
}
|
|
653
514
|
return [...normalized];
|
|
654
515
|
}
|
|
655
|
-
|
|
656
|
-
// ../node-auth/src/credential-store.ts
|
|
657
516
|
var KEYCHAIN_COMMAND_TIMEOUT_MS = 1500;
|
|
658
517
|
var ARCHAL_DIR_NAME = ".archal";
|
|
659
518
|
var TEST_SANDBOX_ID_ENV_VAR = "ARCHAL_TEST_SANDBOX_ID";
|
|
@@ -725,7 +584,7 @@ function seedSandboxFromRealHomeOnce(sandboxDir) {
|
|
|
725
584
|
}
|
|
726
585
|
}
|
|
727
586
|
function getArchalDir() {
|
|
728
|
-
const explicit = process.env["ARCHAL_HOME"];
|
|
587
|
+
const explicit = process.env["ARCHAL_HOME"]?.trim();
|
|
729
588
|
if (explicit) {
|
|
730
589
|
return explicit;
|
|
731
590
|
}
|
|
@@ -1009,7 +868,66 @@ function readCredentialsFile(options) {
|
|
|
1009
868
|
return readCredentialsFileAtPath(getCredentialsPath(), options);
|
|
1010
869
|
}
|
|
1011
870
|
function isWorkspaceApiKey(token) {
|
|
1012
|
-
return token.startsWith(
|
|
871
|
+
return token.startsWith(WORKSPACE_API_KEY_PREFIX) || token.startsWith("archal_") && !token.includes(".");
|
|
872
|
+
}
|
|
873
|
+
var WORKSPACE_API_KEY_EXPIRES_SECONDS = 365 * 24 * 60 * 60;
|
|
874
|
+
function parseEnvToken(token, envName = AUTH_TOKEN_ENV_VAR, nowSeconds = Math.floor(Date.now() / 1e3)) {
|
|
875
|
+
const trimmed = token.trim();
|
|
876
|
+
if (!trimmed) {
|
|
877
|
+
return { status: "invalid", message: `${envName} is empty.` };
|
|
878
|
+
}
|
|
879
|
+
if (isWorkspaceApiKey(trimmed)) {
|
|
880
|
+
return {
|
|
881
|
+
status: "ok",
|
|
882
|
+
credentials: {
|
|
883
|
+
token: trimmed,
|
|
884
|
+
refreshToken: "",
|
|
885
|
+
email: "(workspace-api-key)",
|
|
886
|
+
plan: "pro",
|
|
887
|
+
selectedCloneIds: [],
|
|
888
|
+
expiresAt: nowSeconds + WORKSPACE_API_KEY_EXPIRES_SECONDS
|
|
889
|
+
}
|
|
890
|
+
};
|
|
891
|
+
}
|
|
892
|
+
const claims = decodeJwtPayload(trimmed);
|
|
893
|
+
if (claims === null) {
|
|
894
|
+
return {
|
|
895
|
+
status: "invalid",
|
|
896
|
+
message: `${envName} must be a JWT with valid plan and exp claims or a workspace API key (archal_ws_...).`
|
|
897
|
+
};
|
|
898
|
+
}
|
|
899
|
+
const email = typeof claims["email"] === "string" ? claims["email"] : `(from ${envName})`;
|
|
900
|
+
if (!isPlan(claims["plan"])) {
|
|
901
|
+
return {
|
|
902
|
+
status: "invalid",
|
|
903
|
+
message: `${envName} JWT does not contain a valid plan claim.`
|
|
904
|
+
};
|
|
905
|
+
}
|
|
906
|
+
const plan = claims["plan"];
|
|
907
|
+
if (typeof claims["exp"] !== "number" || !Number.isFinite(claims["exp"])) {
|
|
908
|
+
return {
|
|
909
|
+
status: "invalid",
|
|
910
|
+
message: `${envName} JWT does not contain a valid exp claim.`
|
|
911
|
+
};
|
|
912
|
+
}
|
|
913
|
+
const expiresAt = claims["exp"];
|
|
914
|
+
if (expiresAt <= nowSeconds) {
|
|
915
|
+
return {
|
|
916
|
+
status: "expired",
|
|
917
|
+
message: `${envName} is expired. Remove it or replace it with a valid token.`
|
|
918
|
+
};
|
|
919
|
+
}
|
|
920
|
+
return {
|
|
921
|
+
status: "ok",
|
|
922
|
+
credentials: {
|
|
923
|
+
token: trimmed,
|
|
924
|
+
refreshToken: "",
|
|
925
|
+
email,
|
|
926
|
+
plan,
|
|
927
|
+
selectedCloneIds: [],
|
|
928
|
+
expiresAt
|
|
929
|
+
}
|
|
930
|
+
};
|
|
1013
931
|
}
|
|
1014
932
|
function getStoredCredentials(options) {
|
|
1015
933
|
const creds = readCredentialsFile(options);
|
|
@@ -1166,8 +1084,59 @@ function getConfiguredAuthBaseUrl(options) {
|
|
|
1166
1084
|
}
|
|
1167
1085
|
return isStrictEndpointModeEnabled() ? null : HOSTED_DEFAULT_AUTH_BASE_URL;
|
|
1168
1086
|
}
|
|
1087
|
+
function readConfiguredUrlFromEnvChain(envVarNames, options) {
|
|
1088
|
+
const uniqueEnvVars = [...new Set(envVarNames)];
|
|
1089
|
+
return readConfiguredUrl(options, ...uniqueEnvVars);
|
|
1090
|
+
}
|
|
1091
|
+
function getConfiguredAuthValidationBaseUrl(options = {}) {
|
|
1092
|
+
const apiUrlEnvVar = options.apiUrlEnvVar ?? "ARCHAL_API_URL";
|
|
1093
|
+
const authUrlEnvVar = options.authUrlEnvVar ?? "ARCHAL_AUTH_URL";
|
|
1094
|
+
const resolved = readConfiguredUrlFromEnvChain([
|
|
1095
|
+
apiUrlEnvVar,
|
|
1096
|
+
authUrlEnvVar,
|
|
1097
|
+
"ARCHAL_AUTH_URL",
|
|
1098
|
+
"ARCHAL_AUTH_BASE_URL",
|
|
1099
|
+
"ARCHAL_API_URL",
|
|
1100
|
+
"ARCHAL_API_BASE_URL"
|
|
1101
|
+
], options);
|
|
1102
|
+
if (resolved) {
|
|
1103
|
+
return resolved;
|
|
1104
|
+
}
|
|
1105
|
+
return isStrictEndpointModeEnabled() ? null : HOSTED_DEFAULT_AUTH_BASE_URL;
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
// ../retry/dist/index.js
|
|
1109
|
+
function abortReason(signal) {
|
|
1110
|
+
return signal.reason instanceof Error ? signal.reason : new DOMException("The operation was aborted.", "AbortError");
|
|
1111
|
+
}
|
|
1112
|
+
function sleep(ms, options) {
|
|
1113
|
+
const signal = options?.signal;
|
|
1114
|
+
if (signal?.aborted) {
|
|
1115
|
+
return Promise.reject(abortReason(signal));
|
|
1116
|
+
}
|
|
1117
|
+
if (ms <= 0) {
|
|
1118
|
+
return Promise.resolve();
|
|
1119
|
+
}
|
|
1120
|
+
if (!signal) {
|
|
1121
|
+
return new Promise((resolve) => {
|
|
1122
|
+
setTimeout(resolve, ms);
|
|
1123
|
+
});
|
|
1124
|
+
}
|
|
1125
|
+
const abortSignal = signal;
|
|
1126
|
+
return new Promise((resolve, reject) => {
|
|
1127
|
+
const timeout = setTimeout(() => {
|
|
1128
|
+
abortSignal.removeEventListener("abort", onAbort);
|
|
1129
|
+
resolve();
|
|
1130
|
+
}, ms);
|
|
1131
|
+
function onAbort() {
|
|
1132
|
+
clearTimeout(timeout);
|
|
1133
|
+
reject(abortReason(abortSignal));
|
|
1134
|
+
}
|
|
1135
|
+
abortSignal.addEventListener("abort", onAbort, { once: true });
|
|
1136
|
+
});
|
|
1137
|
+
}
|
|
1169
1138
|
|
|
1170
|
-
// ../node-auth/src/
|
|
1139
|
+
// ../node-auth/src/token-exchange.ts
|
|
1171
1140
|
function buildAuthRequestHeaders(metadata, includeContentType = false) {
|
|
1172
1141
|
const headers = {};
|
|
1173
1142
|
if (includeContentType) {
|
|
@@ -1288,37 +1257,6 @@ async function validateAuthWithServerResult(creds, metadata) {
|
|
|
1288
1257
|
};
|
|
1289
1258
|
}
|
|
1290
1259
|
|
|
1291
|
-
// ../retry/dist/index.js
|
|
1292
|
-
function abortReason(signal) {
|
|
1293
|
-
return signal.reason instanceof Error ? signal.reason : new DOMException("The operation was aborted.", "AbortError");
|
|
1294
|
-
}
|
|
1295
|
-
function sleep(ms, options) {
|
|
1296
|
-
const signal = options?.signal;
|
|
1297
|
-
if (signal?.aborted) {
|
|
1298
|
-
return Promise.reject(abortReason(signal));
|
|
1299
|
-
}
|
|
1300
|
-
if (ms <= 0) {
|
|
1301
|
-
return Promise.resolve();
|
|
1302
|
-
}
|
|
1303
|
-
if (!signal) {
|
|
1304
|
-
return new Promise((resolve) => {
|
|
1305
|
-
setTimeout(resolve, ms);
|
|
1306
|
-
});
|
|
1307
|
-
}
|
|
1308
|
-
const abortSignal = signal;
|
|
1309
|
-
return new Promise((resolve, reject) => {
|
|
1310
|
-
const timeout = setTimeout(() => {
|
|
1311
|
-
abortSignal.removeEventListener("abort", onAbort);
|
|
1312
|
-
resolve();
|
|
1313
|
-
}, ms);
|
|
1314
|
-
function onAbort() {
|
|
1315
|
-
clearTimeout(timeout);
|
|
1316
|
-
reject(abortReason(abortSignal));
|
|
1317
|
-
}
|
|
1318
|
-
abortSignal.addEventListener("abort", onAbort, { once: true });
|
|
1319
|
-
});
|
|
1320
|
-
}
|
|
1321
|
-
|
|
1322
1260
|
// ../node-auth/src/secure-token.ts
|
|
1323
1261
|
var import_node_crypto2 = require("crypto");
|
|
1324
1262
|
|
|
@@ -1377,59 +1315,11 @@ function parsePositiveInteger(rawValue, fallback, minimum = 1) {
|
|
|
1377
1315
|
const parsed = Number(normalized);
|
|
1378
1316
|
return Number.isSafeInteger(parsed) && parsed >= minimum ? parsed : fallback;
|
|
1379
1317
|
}
|
|
1380
|
-
function normalizeApiBaseUrl(value) {
|
|
1381
|
-
if (!value) return null;
|
|
1382
|
-
const normalized = value.trim().replace(/\/+$/, "");
|
|
1383
|
-
if (!normalized) return null;
|
|
1384
|
-
let parsed;
|
|
1385
|
-
try {
|
|
1386
|
-
parsed = new URL(normalized);
|
|
1387
|
-
} catch {
|
|
1388
|
-
throw new Error(`Invalid ARCHAL_API_URL: "${normalized}" is not a valid URL`);
|
|
1389
|
-
}
|
|
1390
|
-
const isLocalhostHttp = parsed.protocol === "http:" && (parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1");
|
|
1391
|
-
if (parsed.protocol !== "https:" && !isLocalhostHttp) {
|
|
1392
|
-
throw new Error(`Hosted API URL must use HTTPS (or localhost HTTP). Received ${normalized}.`);
|
|
1393
|
-
}
|
|
1394
|
-
const pathname = parsed.pathname.replace(/\/+$/, "");
|
|
1395
|
-
parsed.pathname = pathname.endsWith("/api") ? pathname.slice(0, -4) || "/" : pathname || "/";
|
|
1396
|
-
parsed.search = "";
|
|
1397
|
-
parsed.hash = "";
|
|
1398
|
-
return parsed.toString().replace(/\/$/, "");
|
|
1399
|
-
}
|
|
1400
1318
|
|
|
1401
1319
|
// ../runtime/src/auth-lease.ts
|
|
1402
1320
|
var STORED_CREDENTIALS_LOCK_TIMEOUT_MS = 3e4;
|
|
1403
1321
|
var STORED_CREDENTIALS_STALE_LOCK_MS = STORED_CREDENTIALS_LOCK_TIMEOUT_MS;
|
|
1404
1322
|
var STORED_CREDENTIALS_LOCK_POLL_INTERVAL_MS = 50;
|
|
1405
|
-
var DEFAULT_AUTH_BASE_URL = "https://www.archal.ai";
|
|
1406
|
-
var WORKSPACE_API_KEY_EXPIRES_SECONDS = 365 * 24 * 60 * 60;
|
|
1407
|
-
function readFirstConfiguredBaseUrl(envVars) {
|
|
1408
|
-
for (const envVar of envVars) {
|
|
1409
|
-
const configured = trimEnv(envVar);
|
|
1410
|
-
if (!configured) {
|
|
1411
|
-
continue;
|
|
1412
|
-
}
|
|
1413
|
-
const normalized = normalizeApiBaseUrl(configured);
|
|
1414
|
-
if (normalized) {
|
|
1415
|
-
return normalized;
|
|
1416
|
-
}
|
|
1417
|
-
}
|
|
1418
|
-
return null;
|
|
1419
|
-
}
|
|
1420
|
-
function resolveHostedAuthBaseUrl(options) {
|
|
1421
|
-
const authUrlEnvVar = options.authUrlEnvVar ?? "ARCHAL_AUTH_URL";
|
|
1422
|
-
const apiUrlEnvVar = options.apiUrlEnvVar ?? "ARCHAL_API_URL";
|
|
1423
|
-
const envVars = [.../* @__PURE__ */ new Set([
|
|
1424
|
-
apiUrlEnvVar,
|
|
1425
|
-
authUrlEnvVar,
|
|
1426
|
-
"ARCHAL_AUTH_URL",
|
|
1427
|
-
"ARCHAL_AUTH_BASE_URL",
|
|
1428
|
-
"ARCHAL_API_URL",
|
|
1429
|
-
"ARCHAL_API_BASE_URL"
|
|
1430
|
-
])];
|
|
1431
|
-
return readFirstConfiguredBaseUrl(envVars) ?? DEFAULT_AUTH_BASE_URL;
|
|
1432
|
-
}
|
|
1433
1323
|
function isImplicitTestSandboxFlow() {
|
|
1434
1324
|
if (trimEnv("ARCHAL_HOME")) {
|
|
1435
1325
|
return false;
|
|
@@ -1446,59 +1336,11 @@ function readExplicitEnvCredentials(envName) {
|
|
|
1446
1336
|
if (!token) {
|
|
1447
1337
|
return { kind: "missing" };
|
|
1448
1338
|
}
|
|
1449
|
-
const
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
if (isWorkspaceApiKey(token)) {
|
|
1453
|
-
return {
|
|
1454
|
-
kind: "valid",
|
|
1455
|
-
credentials: {
|
|
1456
|
-
token,
|
|
1457
|
-
refreshToken: "",
|
|
1458
|
-
email: "(workspace-api-key)",
|
|
1459
|
-
plan: "pro",
|
|
1460
|
-
selectedCloneIds: [],
|
|
1461
|
-
expiresAt: nowSeconds + WORKSPACE_API_KEY_EXPIRES_SECONDS
|
|
1462
|
-
}
|
|
1463
|
-
};
|
|
1464
|
-
}
|
|
1465
|
-
return {
|
|
1466
|
-
kind: "invalid",
|
|
1467
|
-
message: `${envName} must be a JWT with valid plan and exp claims or a workspace API key (archal_ws_...).`
|
|
1468
|
-
};
|
|
1469
|
-
}
|
|
1470
|
-
const email = typeof claims["email"] === "string" ? claims["email"] : `(from ${envName})`;
|
|
1471
|
-
if (!isPlan(claims["plan"])) {
|
|
1472
|
-
return {
|
|
1473
|
-
kind: "invalid",
|
|
1474
|
-
message: `${envName} JWT does not contain a valid plan claim.`
|
|
1475
|
-
};
|
|
1339
|
+
const parsed = parseEnvToken(token, envName);
|
|
1340
|
+
if (parsed.status !== "ok") {
|
|
1341
|
+
return { kind: "invalid", message: parsed.message };
|
|
1476
1342
|
}
|
|
1477
|
-
|
|
1478
|
-
if (typeof claims["exp"] !== "number" || !Number.isFinite(claims["exp"])) {
|
|
1479
|
-
return {
|
|
1480
|
-
kind: "invalid",
|
|
1481
|
-
message: `${envName} JWT does not contain a valid exp claim.`
|
|
1482
|
-
};
|
|
1483
|
-
}
|
|
1484
|
-
const expiresAt = claims["exp"];
|
|
1485
|
-
if (expiresAt <= nowSeconds) {
|
|
1486
|
-
return {
|
|
1487
|
-
kind: "invalid",
|
|
1488
|
-
message: `${envName} is expired. Remove it or replace it with a valid token.`
|
|
1489
|
-
};
|
|
1490
|
-
}
|
|
1491
|
-
return {
|
|
1492
|
-
kind: "valid",
|
|
1493
|
-
credentials: {
|
|
1494
|
-
token,
|
|
1495
|
-
refreshToken: "",
|
|
1496
|
-
email,
|
|
1497
|
-
plan,
|
|
1498
|
-
selectedCloneIds: [],
|
|
1499
|
-
expiresAt
|
|
1500
|
-
}
|
|
1501
|
-
};
|
|
1343
|
+
return { kind: "valid", credentials: parsed.credentials };
|
|
1502
1344
|
}
|
|
1503
1345
|
function readStoredCredentials(includeExpired = false) {
|
|
1504
1346
|
prepareStoredCredentialSources();
|
|
@@ -1615,7 +1457,15 @@ async function resolveCurrentCredentials(credentials, source, forceValidation, a
|
|
|
1615
1457
|
}
|
|
1616
1458
|
async function createHostedAuthLease(options = {}) {
|
|
1617
1459
|
const tokenEnvVar = options.tokenEnvVar ?? "ARCHAL_TOKEN";
|
|
1618
|
-
const authBaseUrl =
|
|
1460
|
+
const authBaseUrl = getConfiguredAuthValidationBaseUrl({
|
|
1461
|
+
apiUrlEnvVar: options.apiUrlEnvVar,
|
|
1462
|
+
authUrlEnvVar: options.authUrlEnvVar
|
|
1463
|
+
});
|
|
1464
|
+
if (!authBaseUrl) {
|
|
1465
|
+
throw new Error(
|
|
1466
|
+
"Hosted auth validation requires ARCHAL_AUTH_URL or ARCHAL_API_URL when ARCHAL_STRICT_ENDPOINTS=1."
|
|
1467
|
+
);
|
|
1468
|
+
}
|
|
1619
1469
|
const resolved = resolveCredentialsWithSource(tokenEnvVar, true);
|
|
1620
1470
|
if (!resolved) {
|
|
1621
1471
|
const tokenSources = Array.from(/* @__PURE__ */ new Set([tokenEnvVar, "ARCHAL_TOKEN"])).join(", ");
|
package/manifest.json
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "archal",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Test your agents & integrations against service clones",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -13,12 +13,10 @@
|
|
|
13
13
|
"types": "./dist/index.d.cts",
|
|
14
14
|
"default": "./dist/index.cjs"
|
|
15
15
|
},
|
|
16
|
-
"./harness": {
|
|
17
|
-
"types": "./dist/harness.d.cts",
|
|
18
|
-
"default": "./dist/harness.cjs"
|
|
19
|
-
},
|
|
20
16
|
"./scenarios": {
|
|
21
17
|
"types": "./dist/scenarios.d.cts",
|
|
18
|
+
"import": "./dist/scenarios.cjs",
|
|
19
|
+
"require": "./dist/scenarios.cjs",
|
|
22
20
|
"default": "./dist/scenarios.cjs"
|
|
23
21
|
},
|
|
24
22
|
"./vitest": {
|
|
@@ -49,13 +47,21 @@
|
|
|
49
47
|
"files": [
|
|
50
48
|
"bin",
|
|
51
49
|
"dist",
|
|
50
|
+
"manifest.json",
|
|
52
51
|
"skills",
|
|
53
52
|
"clone-assets",
|
|
54
53
|
"agents",
|
|
55
54
|
"LICENSE"
|
|
56
55
|
],
|
|
56
|
+
"scripts": {
|
|
57
|
+
"verify:artifacts": "node scripts/assert-artifacts.mjs",
|
|
58
|
+
"prepack": "node scripts/assert-artifacts.mjs",
|
|
59
|
+
"prepare": "node scripts/prepare.cjs",
|
|
60
|
+
"typecheck:raw": "node --check bin/archal.cjs && node --check scripts/assert-artifacts.mjs && node --check scripts/prepare.cjs",
|
|
61
|
+
"typecheck": "pnpm run typecheck:raw"
|
|
62
|
+
},
|
|
57
63
|
"peerDependencies": {
|
|
58
|
-
"vitest": ">=2.1.0"
|
|
64
|
+
"vitest": ">=2.1.0 <3"
|
|
59
65
|
},
|
|
60
66
|
"peerDependenciesMeta": {
|
|
61
67
|
"vitest": {
|
|
@@ -65,11 +71,6 @@
|
|
|
65
71
|
"dependencies": {
|
|
66
72
|
"@aws-sdk/client-secrets-manager": "^3.1065.0",
|
|
67
73
|
"e2b": "^2.28.2",
|
|
68
|
-
"
|
|
69
|
-
},
|
|
70
|
-
"scripts": {
|
|
71
|
-
"verify:artifacts": "node scripts/assert-artifacts.mjs",
|
|
72
|
-
"typecheck:raw": "node --check bin/archal.cjs && node --check scripts/assert-artifacts.mjs && node --check scripts/prepare.cjs",
|
|
73
|
-
"typecheck": "pnpm run typecheck:raw"
|
|
74
|
+
"tsx": "^4.19.0"
|
|
74
75
|
}
|
|
75
|
-
}
|
|
76
|
+
}
|
|
@@ -76,7 +76,6 @@ deeper flow.
|
|
|
76
76
|
|
|
77
77
|
The Archal copilot is not locked to one model. When autofix reproduces a failure
|
|
78
78
|
and writes a fix, the user can drive that remediation with their own agent —
|
|
79
|
-
`archal preprod` exposes `--remediation-agent auto|codex|claude|cursor` so the
|
|
80
79
|
fix is written by their Claude Code, Cursor, or Codex — or let Archal's managed
|
|
81
80
|
agent do it. Mention this when the user asks who writes the fix or wants to use
|
|
82
81
|
their own coding agent, then route to `autoloop`.
|