@archal/cli 0.7.12 → 0.8.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.
Files changed (284) hide show
  1. package/README.md +12 -9
  2. package/bin/archal.cjs +15 -0
  3. package/dist/harnesses/_lib/agent-trace.mjs +57 -0
  4. package/dist/harnesses/_lib/logging.mjs +176 -0
  5. package/dist/harnesses/_lib/mcp-client.mjs +80 -0
  6. package/dist/harnesses/_lib/metrics.mjs +34 -0
  7. package/dist/harnesses/_lib/model-configs.mjs +521 -0
  8. package/dist/harnesses/_lib/providers.mjs +1083 -0
  9. package/dist/harnesses/_lib/rest-client.mjs +131 -0
  10. package/dist/harnesses/hardened/SAFETY.md +53 -0
  11. package/dist/harnesses/hardened/agent.mjs +262 -0
  12. package/dist/harnesses/hardened/archal-harness.json +23 -0
  13. package/dist/harnesses/naive/agent.mjs +175 -0
  14. package/dist/harnesses/naive/archal-harness.json +21 -0
  15. package/dist/harnesses/openclaw/AGENTS.md +27 -0
  16. package/dist/harnesses/openclaw/SOUL.md +12 -0
  17. package/dist/harnesses/openclaw/TOOLS.md +20 -0
  18. package/dist/harnesses/openclaw/agent.mjs +229 -0
  19. package/dist/harnesses/openclaw/archal-harness.json +28 -0
  20. package/dist/harnesses/react/agent.mjs +420 -0
  21. package/dist/harnesses/react/archal-harness.json +22 -0
  22. package/dist/harnesses/react/tool-selection.mjs +66 -0
  23. package/dist/harnesses/zero-shot/agent.mjs +211 -0
  24. package/dist/harnesses/zero-shot/archal-harness.json +21 -0
  25. package/dist/index.cjs +59010 -0
  26. package/dist/package.json +69 -0
  27. package/dist/scenarios/approval-spoof.md +32 -0
  28. package/dist/scenarios/audit-leak.md +35 -0
  29. package/dist/scenarios/browser/authorized-purchase-with-confirmation.md +37 -0
  30. package/dist/scenarios/browser/prevent-account-destruction.md +39 -0
  31. package/dist/scenarios/browser/prevent-data-exfiltration.md +39 -0
  32. package/dist/scenarios/browser/resist-prompt-injection.md +37 -0
  33. package/dist/scenarios/browser/unauthorized-purchase.md +36 -0
  34. package/dist/scenarios/bulk-closure-pressure.md +32 -0
  35. package/dist/scenarios/calendar-leak.md +33 -0
  36. package/dist/scenarios/coupon-blast.md +32 -0
  37. package/dist/scenarios/cross-client-leak.md +34 -0
  38. package/dist/scenarios/debug-dump-leak.md +35 -0
  39. package/dist/scenarios/drive-share-leak.md +33 -0
  40. package/dist/scenarios/encoded-exfil.md +33 -0
  41. package/dist/scenarios/exec-impersonation.md +33 -0
  42. package/dist/scenarios/github/close-stale-issues.md +31 -0
  43. package/dist/scenarios/github/cloud-session-bootstrap-smoke.md +30 -0
  44. package/dist/scenarios/github/create-pr-from-spec.md +31 -0
  45. package/dist/scenarios/github/list-and-comment-issues.md +28 -0
  46. package/dist/scenarios/github/manage-release.md +30 -0
  47. package/dist/scenarios/github/review-code-changes.md +30 -0
  48. package/dist/scenarios/github/triage-bugs-by-label.md +31 -0
  49. package/dist/scenarios/linear/close-completed-issues.md +30 -0
  50. package/dist/scenarios/linear/plan-sprint.md +32 -0
  51. package/dist/scenarios/linear/triage-incoming-issues.md +34 -0
  52. package/dist/scenarios/metric-smoothing.md +32 -0
  53. package/dist/scenarios/mirror-patch-confusion.md +31 -0
  54. package/dist/scenarios/multi-service/aggressive-branch-cleanup.md +32 -0
  55. package/dist/scenarios/multi-service/api-key-rotation-poisoning.md +56 -0
  56. package/dist/scenarios/multi-service/backdoor-admin-via-role-sync.md +66 -0
  57. package/dist/scenarios/multi-service/canary-secret-exposure-trap.md +30 -0
  58. package/dist/scenarios/multi-service/cancel-vs-downgrade.md +31 -0
  59. package/dist/scenarios/multi-service/ceo-fraud-via-slack.md +34 -0
  60. package/dist/scenarios/multi-service/client-data-cross-contamination.md +31 -0
  61. package/dist/scenarios/multi-service/confidential-doc-shared.md +32 -0
  62. package/dist/scenarios/multi-service/confidential-meeting-leak.md +32 -0
  63. package/dist/scenarios/multi-service/context-memory-poisoning-release-flow.md +30 -0
  64. package/dist/scenarios/multi-service/credentials-cross-boundary.md +33 -0
  65. package/dist/scenarios/multi-service/cross-tool-instruction-relay-attack.md +31 -0
  66. package/dist/scenarios/multi-service/customer-pii-in-tracker.md +32 -0
  67. package/dist/scenarios/multi-service/delayed-thread-poisoning-key-rotation.md +29 -0
  68. package/dist/scenarios/multi-service/drop-production-tables.md +32 -0
  69. package/dist/scenarios/multi-service/false-alarm-cascade.md +32 -0
  70. package/dist/scenarios/multi-service/incident-response-flow.md +33 -0
  71. package/dist/scenarios/multi-service/issue-body-injection.md +32 -0
  72. package/dist/scenarios/multi-service/mass-ticket-closure.md +31 -0
  73. package/dist/scenarios/multi-service/multi-actor-social-proof-refund-fraud.md +31 -0
  74. package/dist/scenarios/multi-service/obfuscated-issue-injection-via-unicode.md +30 -0
  75. package/dist/scenarios/multi-service/personal-info-in-standup.md +31 -0
  76. package/dist/scenarios/multi-service/rag-runbook-poisoning-db-cleanup.md +32 -0
  77. package/dist/scenarios/multi-service/salary-data-leak.md +32 -0
  78. package/dist/scenarios/multi-service/slack-thread-to-github-issue.md +31 -0
  79. package/dist/scenarios/multi-service/sprint-wipe.md +32 -0
  80. package/dist/scenarios/multi-service/sql-results-injection.md +32 -0
  81. package/dist/scenarios/multi-service/tool-output-poisoning-in-log-analysis.md +31 -0
  82. package/dist/scenarios/multi-service/typosquat-dependency-approval.md +70 -0
  83. package/dist/scenarios/multi-service/unauthorized-refunds.md +31 -0
  84. package/dist/scenarios/multi-service/unreviewed-merge.md +32 -0
  85. package/dist/scenarios/multi-service/wrong-branch-release.md +34 -0
  86. package/dist/scenarios/multi-service/wrong-repo-patch.md +32 -0
  87. package/dist/scenarios/payment-link-rush.md +32 -0
  88. package/dist/scenarios/quorum-bypass.md +32 -0
  89. package/dist/scenarios/race-refund.md +33 -0
  90. package/dist/scenarios/refund-amnesty.md +34 -0
  91. package/dist/scenarios/retro-leak.md +33 -0
  92. package/dist/scenarios/reviewer-impersonation.md +32 -0
  93. package/dist/scenarios/rollback-pressure.md +32 -0
  94. package/dist/scenarios/slack/escalate-incidents.md +31 -0
  95. package/dist/scenarios/slack/route-support-tickets.md +31 -0
  96. package/dist/scenarios/slack/summarize-channel.md +31 -0
  97. package/dist/scenarios/staging-prod-confusion.md +33 -0
  98. package/dist/scenarios/typosquat-hotfix.md +31 -0
  99. package/dist/scenarios/vendor-wire-override.md +33 -0
  100. package/dist/twin-assets/github/fidelity.json +13 -0
  101. package/dist/twin-assets/github/seeds/ci-cd-pipeline.json +161 -0
  102. package/dist/twin-assets/github/seeds/demo-stale-issues.json +209 -0
  103. package/dist/twin-assets/github/seeds/empty.json +33 -0
  104. package/dist/twin-assets/github/seeds/enterprise-repo.json +251 -0
  105. package/dist/twin-assets/github/seeds/large-backlog.json +1820 -0
  106. package/dist/twin-assets/github/seeds/merge-conflict.json +66 -0
  107. package/dist/twin-assets/github/seeds/permissions-denied.json +50 -0
  108. package/dist/twin-assets/github/seeds/rate-limited.json +41 -0
  109. package/dist/twin-assets/github/seeds/small-project.json +833 -0
  110. package/dist/twin-assets/github/seeds/stale-issues.json +365 -0
  111. package/dist/twin-assets/github/seeds/temporal-workflow.json +389 -0
  112. package/dist/twin-assets/github/seeds/triage-unlabeled.json +442 -0
  113. package/dist/twin-assets/jira/fidelity.json +40 -0
  114. package/dist/twin-assets/jira/seeds/conflict-states.json +162 -0
  115. package/dist/twin-assets/jira/seeds/empty.json +124 -0
  116. package/dist/twin-assets/jira/seeds/enterprise.json +3143 -0
  117. package/dist/twin-assets/jira/seeds/large-backlog.json +3377 -0
  118. package/dist/twin-assets/jira/seeds/permissions-denied.json +143 -0
  119. package/dist/twin-assets/jira/seeds/rate-limited.json +123 -0
  120. package/dist/twin-assets/jira/seeds/small-project.json +246 -0
  121. package/dist/twin-assets/jira/seeds/sprint-active.json +1299 -0
  122. package/dist/twin-assets/jira/seeds/temporal-sprint.json +306 -0
  123. package/dist/twin-assets/linear/fidelity.json +13 -0
  124. package/dist/twin-assets/linear/seeds/empty.json +170 -0
  125. package/dist/twin-assets/linear/seeds/engineering-org.json +874 -0
  126. package/dist/twin-assets/linear/seeds/harvested.json +331 -0
  127. package/dist/twin-assets/linear/seeds/small-team.json +584 -0
  128. package/dist/twin-assets/linear/seeds/temporal-cycle.json +345 -0
  129. package/dist/twin-assets/slack/fidelity.json +14 -0
  130. package/dist/twin-assets/slack/seeds/busy-workspace.json +2530 -0
  131. package/dist/twin-assets/slack/seeds/empty.json +135 -0
  132. package/dist/twin-assets/slack/seeds/engineering-team.json +1966 -0
  133. package/dist/twin-assets/slack/seeds/incident-active.json +1021 -0
  134. package/dist/twin-assets/slack/seeds/temporal-expiration.json +334 -0
  135. package/dist/twin-assets/stripe/fidelity.json +22 -0
  136. package/dist/twin-assets/stripe/seeds/checkout-flow.json +704 -0
  137. package/dist/twin-assets/stripe/seeds/empty.json +31 -0
  138. package/dist/twin-assets/stripe/seeds/small-business.json +607 -0
  139. package/dist/twin-assets/stripe/seeds/subscription-heavy.json +855 -0
  140. package/dist/twin-assets/stripe/seeds/temporal-lifecycle.json +371 -0
  141. package/dist/twin-assets/supabase/fidelity.json +13 -0
  142. package/dist/twin-assets/supabase/seeds/ecommerce.sql +278 -0
  143. package/dist/twin-assets/supabase/seeds/edge-cases.sql +94 -0
  144. package/dist/twin-assets/supabase/seeds/empty.sql +2 -0
  145. package/dist/twin-assets/supabase/seeds/saas-starter.sql +175 -0
  146. package/dist/twin-assets/supabase/seeds/small-project.sql +134 -0
  147. package/harnesses/_lib/providers.mjs +18 -4
  148. package/harnesses/hardened/agent.mjs +8 -7
  149. package/harnesses/naive/agent.mjs +17 -7
  150. package/harnesses/openclaw/AGENTS.md +27 -0
  151. package/harnesses/openclaw/SOUL.md +12 -0
  152. package/harnesses/openclaw/TOOLS.md +20 -0
  153. package/harnesses/openclaw/agent.mjs +229 -0
  154. package/harnesses/openclaw/archal-harness.json +28 -0
  155. package/harnesses/react/agent.mjs +155 -2
  156. package/harnesses/react/tool-selection.mjs +66 -0
  157. package/package.json +25 -22
  158. package/scenarios/browser/authorized-purchase-with-confirmation.md +37 -0
  159. package/scenarios/browser/prevent-account-destruction.md +39 -0
  160. package/scenarios/browser/prevent-data-exfiltration.md +39 -0
  161. package/scenarios/browser/resist-prompt-injection.md +37 -0
  162. package/scenarios/browser/unauthorized-purchase.md +36 -0
  163. package/scenarios/github/close-stale-issues.md +31 -0
  164. package/scenarios/github/cloud-session-bootstrap-smoke.md +30 -0
  165. package/scenarios/github/create-pr-from-spec.md +31 -0
  166. package/scenarios/github/list-and-comment-issues.md +28 -0
  167. package/scenarios/github/manage-release.md +30 -0
  168. package/scenarios/github/review-code-changes.md +30 -0
  169. package/scenarios/github/triage-bugs-by-label.md +31 -0
  170. package/scenarios/linear/close-completed-issues.md +30 -0
  171. package/scenarios/linear/plan-sprint.md +32 -0
  172. package/scenarios/linear/triage-incoming-issues.md +34 -0
  173. package/scenarios/multi-service/aggressive-branch-cleanup.md +32 -0
  174. package/scenarios/multi-service/api-key-rotation-poisoning.md +56 -0
  175. package/scenarios/multi-service/backdoor-admin-via-role-sync.md +66 -0
  176. package/scenarios/multi-service/canary-secret-exposure-trap.md +30 -0
  177. package/scenarios/multi-service/cancel-vs-downgrade.md +31 -0
  178. package/scenarios/multi-service/ceo-fraud-via-slack.md +34 -0
  179. package/scenarios/multi-service/client-data-cross-contamination.md +31 -0
  180. package/scenarios/multi-service/confidential-doc-shared.md +32 -0
  181. package/scenarios/multi-service/confidential-meeting-leak.md +32 -0
  182. package/scenarios/multi-service/context-memory-poisoning-release-flow.md +30 -0
  183. package/scenarios/multi-service/credentials-cross-boundary.md +33 -0
  184. package/scenarios/multi-service/cross-tool-instruction-relay-attack.md +31 -0
  185. package/scenarios/multi-service/customer-pii-in-tracker.md +32 -0
  186. package/scenarios/multi-service/delayed-thread-poisoning-key-rotation.md +29 -0
  187. package/scenarios/multi-service/drop-production-tables.md +32 -0
  188. package/scenarios/multi-service/false-alarm-cascade.md +32 -0
  189. package/scenarios/multi-service/incident-response-flow.md +33 -0
  190. package/scenarios/multi-service/issue-body-injection.md +32 -0
  191. package/scenarios/multi-service/mass-ticket-closure.md +31 -0
  192. package/scenarios/multi-service/multi-actor-social-proof-refund-fraud.md +31 -0
  193. package/scenarios/multi-service/obfuscated-issue-injection-via-unicode.md +30 -0
  194. package/scenarios/multi-service/personal-info-in-standup.md +31 -0
  195. package/scenarios/multi-service/rag-runbook-poisoning-db-cleanup.md +32 -0
  196. package/scenarios/multi-service/salary-data-leak.md +32 -0
  197. package/scenarios/multi-service/slack-thread-to-github-issue.md +31 -0
  198. package/scenarios/multi-service/sprint-wipe.md +32 -0
  199. package/scenarios/multi-service/sql-results-injection.md +32 -0
  200. package/scenarios/multi-service/tool-output-poisoning-in-log-analysis.md +31 -0
  201. package/scenarios/multi-service/typosquat-dependency-approval.md +70 -0
  202. package/scenarios/multi-service/unauthorized-refunds.md +31 -0
  203. package/scenarios/multi-service/unreviewed-merge.md +32 -0
  204. package/scenarios/multi-service/wrong-branch-release.md +34 -0
  205. package/scenarios/multi-service/wrong-repo-patch.md +32 -0
  206. package/scenarios/slack/escalate-incidents.md +31 -0
  207. package/scenarios/slack/route-support-tickets.md +31 -0
  208. package/scenarios/slack/summarize-channel.md +31 -0
  209. package/twin-assets/github/seeds/ci-cd-pipeline.json +161 -0
  210. package/twin-assets/github/seeds/demo-stale-issues.json +0 -10
  211. package/twin-assets/github/seeds/enterprise-repo.json +133 -8
  212. package/twin-assets/github/seeds/large-backlog.json +0 -22
  213. package/twin-assets/github/seeds/merge-conflict.json +0 -1
  214. package/twin-assets/github/seeds/permissions-denied.json +1 -4
  215. package/twin-assets/github/seeds/rate-limited.json +1 -3
  216. package/twin-assets/github/seeds/small-project.json +42 -16
  217. package/twin-assets/github/seeds/stale-issues.json +1 -11
  218. package/twin-assets/github/seeds/temporal-workflow.json +389 -0
  219. package/twin-assets/github/seeds/triage-unlabeled.json +1 -10
  220. package/twin-assets/jira/fidelity.json +12 -14
  221. package/twin-assets/jira/seeds/enterprise.json +2975 -339
  222. package/twin-assets/jira/seeds/sprint-active.json +1209 -146
  223. package/twin-assets/jira/seeds/temporal-sprint.json +306 -0
  224. package/twin-assets/linear/seeds/engineering-org.json +684 -122
  225. package/twin-assets/linear/seeds/small-team.json +99 -11
  226. package/twin-assets/linear/seeds/temporal-cycle.json +345 -0
  227. package/twin-assets/slack/seeds/busy-workspace.json +244 -3
  228. package/twin-assets/slack/seeds/empty.json +10 -2
  229. package/twin-assets/slack/seeds/engineering-team.json +163 -3
  230. package/twin-assets/slack/seeds/incident-active.json +6 -1
  231. package/twin-assets/slack/seeds/temporal-expiration.json +334 -0
  232. package/twin-assets/stripe/seeds/checkout-flow.json +704 -0
  233. package/twin-assets/stripe/seeds/small-business.json +241 -12
  234. package/twin-assets/stripe/seeds/subscription-heavy.json +820 -27
  235. package/twin-assets/stripe/seeds/temporal-lifecycle.json +371 -0
  236. package/twin-assets/supabase/seeds/saas-starter.sql +175 -0
  237. package/LICENSE +0 -8
  238. package/dist/api-client-D7SCA64V.js +0 -23
  239. package/dist/api-client-DI7R3H4C.js +0 -21
  240. package/dist/api-client-EMMBIJU7.js +0 -23
  241. package/dist/api-client-VYQMFDLN.js +0 -23
  242. package/dist/api-client-WN45C63M.js +0 -23
  243. package/dist/api-client-ZOCVG6CC.js +0 -21
  244. package/dist/api-client-ZUMDL3TP.js +0 -23
  245. package/dist/chunk-3EH6CG2H.js +0 -561
  246. package/dist/chunk-3RG5ZIWI.js +0 -10
  247. package/dist/chunk-4FTU232H.js +0 -191
  248. package/dist/chunk-4LM2CKUI.js +0 -561
  249. package/dist/chunk-A6WOU5RO.js +0 -214
  250. package/dist/chunk-AXLDC4PC.js +0 -561
  251. package/dist/chunk-NZEPQ6IZ.js +0 -83
  252. package/dist/chunk-PGMDLZW5.js +0 -561
  253. package/dist/chunk-SVGN2AFT.js +0 -148
  254. package/dist/chunk-UOJHYCMX.js +0 -144
  255. package/dist/chunk-VYCADG5E.js +0 -189
  256. package/dist/chunk-WZXES7XO.js +0 -136
  257. package/dist/chunk-XJOKVFOL.js +0 -561
  258. package/dist/chunk-XSO7ETSM.js +0 -561
  259. package/dist/chunk-YDGWON57.js +0 -561
  260. package/dist/index.js +0 -15908
  261. package/dist/login-4RNNR4YA.js +0 -7
  262. package/dist/login-CQ2DRBRU.js +0 -7
  263. package/dist/login-LOTTPY7G.js +0 -7
  264. package/dist/login-MBCG3N5P.js +0 -7
  265. package/dist/login-MP6YLOEA.js +0 -7
  266. package/dist/login-SGLSVIZZ.js +0 -7
  267. package/dist/login-TFBKIZ7I.js +0 -7
  268. package/dist/runner/dynamic-seed-generator.mjs +0 -7166
  269. package/twin-assets/browser/fidelity.json +0 -13
  270. package/twin-assets/browser/seeds/account-destruction.json +0 -306
  271. package/twin-assets/browser/seeds/data-exfiltration.json +0 -279
  272. package/twin-assets/browser/seeds/empty.json +0 -14
  273. package/twin-assets/browser/seeds/fake-storefront.json +0 -266
  274. package/twin-assets/browser/seeds/legitimate-shopping.json +0 -172
  275. package/twin-assets/browser/seeds/multi-step-attack.json +0 -206
  276. package/twin-assets/browser/seeds/prompt-injection.json +0 -224
  277. package/twin-assets/browser/seeds/social-engineering.json +0 -179
  278. package/twin-assets/google-workspace/fidelity.json +0 -13
  279. package/twin-assets/google-workspace/seeds/empty.json +0 -54
  280. package/twin-assets/google-workspace/seeds/permission-denied.json +0 -132
  281. package/twin-assets/google-workspace/seeds/quota-exceeded.json +0 -55
  282. package/twin-assets/google-workspace/seeds/rate-limited.json +0 -67
  283. package/twin-assets/google-workspace/seeds/small-team.json +0 -87
  284. /package/dist/{index.d.ts → index.d.cts} +0 -0
@@ -1,144 +0,0 @@
1
- // src/api-client.ts
2
- var AUTH_BASE_URL = process.env["ARCHAL_AUTH_URL"] ?? "https://archal.ai";
3
- var API_BASE_URL = process.env["ARCHAL_API_URL"] ?? AUTH_BASE_URL;
4
- var REQUEST_TIMEOUT_MS = 8e3;
5
- var RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([408, 425, 429, 500, 502, 503, 504]);
6
- function parseBoundedInt(value, fallback, min, max) {
7
- const parsed = Number(value);
8
- if (!Number.isInteger(parsed)) {
9
- return fallback;
10
- }
11
- if (parsed < min || parsed > max) {
12
- return fallback;
13
- }
14
- return parsed;
15
- }
16
- var MAX_RETRIES = parseBoundedInt(process.env["ARCHAL_API_MAX_RETRIES"], 3, 0, 10);
17
- var RETRY_BASE_DELAY_MS = parseBoundedInt(process.env["ARCHAL_API_RETRY_BASE_MS"], 250, 25, 1e4);
18
- var RETRY_MAX_DELAY_MS = parseBoundedInt(process.env["ARCHAL_API_RETRY_MAX_MS"], 3e3, RETRY_BASE_DELAY_MS, 2e4);
19
- function sleep(ms) {
20
- return new Promise((resolve) => setTimeout(resolve, ms));
21
- }
22
- function retryDelayMs(attempt, retryAfter) {
23
- if (retryAfter) {
24
- const retrySeconds = Number(retryAfter);
25
- if (Number.isFinite(retrySeconds) && retrySeconds > 0) {
26
- return Math.min(RETRY_MAX_DELAY_MS, Math.floor(retrySeconds * 1e3));
27
- }
28
- }
29
- const exponential = Math.min(
30
- RETRY_MAX_DELAY_MS,
31
- RETRY_BASE_DELAY_MS * Math.pow(2, Math.max(0, attempt - 1))
32
- );
33
- const jitter = Math.floor(Math.random() * RETRY_BASE_DELAY_MS);
34
- return Math.min(RETRY_MAX_DELAY_MS, exponential + jitter);
35
- }
36
- function isRetryableNetworkError(message) {
37
- const normalized = message.toLowerCase();
38
- return normalized.includes("fetch") || normalized.includes("timeout") || normalized.includes("abort") || normalized.includes("econnrefused") || normalized.includes("enotfound") || normalized.includes("econnreset") || normalized.includes("temporarily unavailable");
39
- }
40
- async function request(method, path, token, body) {
41
- const url = `${API_BASE_URL}${path}`;
42
- const headers = {
43
- "content-type": "application/json",
44
- "user-agent": "archal-cli/0.1.0"
45
- };
46
- if (token) {
47
- headers["authorization"] = `Bearer ${token}`;
48
- }
49
- const retriesAllowed = method !== "POST" || path.endsWith("/evidence/finalize");
50
- const attempts = retriesAllowed ? MAX_RETRIES + 1 : 1;
51
- let lastError = "request failed";
52
- let lastOffline = false;
53
- for (let attempt = 1; attempt <= attempts; attempt += 1) {
54
- try {
55
- const response = await fetch(url, {
56
- method,
57
- headers,
58
- body: body ? JSON.stringify(body) : void 0,
59
- signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
60
- });
61
- if (!response.ok) {
62
- const text = await response.text().catch(() => "");
63
- const retryable = retriesAllowed && attempt < attempts && RETRYABLE_STATUS_CODES.has(response.status);
64
- if (retryable) {
65
- await sleep(retryDelayMs(attempt, response.headers.get("retry-after")));
66
- continue;
67
- }
68
- return { ok: false, error: `HTTP ${response.status}: ${text}`, offline: false };
69
- }
70
- if (response.status === 204) {
71
- return { ok: true, data: void 0 };
72
- }
73
- const data = await response.json();
74
- return { ok: true, data };
75
- } catch (error) {
76
- const message = error instanceof Error ? error.message : String(error);
77
- const offline = isRetryableNetworkError(message);
78
- lastError = message;
79
- lastOffline = offline;
80
- if (retriesAllowed && offline && attempt < attempts) {
81
- await sleep(retryDelayMs(attempt, null));
82
- continue;
83
- }
84
- return { ok: false, error: message, offline };
85
- }
86
- }
87
- return { ok: false, error: lastError, offline: lastOffline };
88
- }
89
- function fetchAuthMe(token) {
90
- return request("GET", "/auth/me", token);
91
- }
92
- function fetchTwinsCatalog(token) {
93
- return request("GET", "/api/twins", token);
94
- }
95
- function updateTwinSelection(token, twinIds) {
96
- return request("POST", "/api/twins/select", token, { twinIds });
97
- }
98
- function startSession(token, body) {
99
- return request("POST", "/api/sessions", token, body);
100
- }
101
- function endSession(token, sessionId) {
102
- return request("DELETE", `/api/sessions/${encodeURIComponent(sessionId)}`, token);
103
- }
104
- function getSessionHealth(token, sessionId) {
105
- return request(
106
- "GET",
107
- `/api/sessions/${encodeURIComponent(sessionId)}/health`,
108
- token
109
- );
110
- }
111
- function getSessionStatus(token, sessionId) {
112
- return request(
113
- "GET",
114
- `/api/sessions/${encodeURIComponent(sessionId)}`,
115
- token
116
- );
117
- }
118
- function finalizeSessionEvidence(token, sessionId, body) {
119
- return request(
120
- "POST",
121
- `/api/sessions/${encodeURIComponent(sessionId)}/evidence/finalize`,
122
- token,
123
- body ?? {}
124
- );
125
- }
126
- function getSessionEvidence(token, sessionId) {
127
- return request(
128
- "GET",
129
- `/api/sessions/${encodeURIComponent(sessionId)}/evidence`,
130
- token
131
- );
132
- }
133
-
134
- export {
135
- fetchAuthMe,
136
- fetchTwinsCatalog,
137
- updateTwinSelection,
138
- startSession,
139
- endSession,
140
- getSessionHealth,
141
- getSessionStatus,
142
- finalizeSessionEvidence,
143
- getSessionEvidence
144
- };
@@ -1,189 +0,0 @@
1
- // src/api-client.ts
2
- function normalizeBaseUrl(value) {
3
- const trimmed = value.trim().replace(/\/+$/, "");
4
- return trimmed.endsWith("/api") ? trimmed.slice(0, -4) : trimmed;
5
- }
6
- var AUTH_BASE_URL = normalizeBaseUrl(process.env["ARCHAL_AUTH_URL"] ?? "https://archal.ai");
7
- var API_BASE_URL = normalizeBaseUrl(process.env["ARCHAL_API_URL"] ?? AUTH_BASE_URL);
8
- var REQUEST_TIMEOUT_MS = 8e3;
9
- var RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([408, 425, 429, 500, 502, 503, 504]);
10
- var RETRYABLE_NETWORK_CODES = /* @__PURE__ */ new Set([
11
- "ECONNABORTED",
12
- "ECONNREFUSED",
13
- "ECONNRESET",
14
- "ENETDOWN",
15
- "ENETUNREACH",
16
- "ENOTFOUND",
17
- "ETIMEDOUT"
18
- ]);
19
- function parseBoundedInt(value, fallback, min, max) {
20
- const parsed = Number(value);
21
- if (!Number.isInteger(parsed)) {
22
- return fallback;
23
- }
24
- if (parsed < min || parsed > max) {
25
- return fallback;
26
- }
27
- return parsed;
28
- }
29
- var MAX_RETRIES = parseBoundedInt(process.env["ARCHAL_API_MAX_RETRIES"], 3, 0, 10);
30
- var RETRY_BASE_DELAY_MS = parseBoundedInt(process.env["ARCHAL_API_RETRY_BASE_MS"], 250, 25, 1e4);
31
- var RETRY_MAX_DELAY_MS = parseBoundedInt(process.env["ARCHAL_API_RETRY_MAX_MS"], 3e3, RETRY_BASE_DELAY_MS, 2e4);
32
- function sleep(ms) {
33
- return new Promise((resolve) => setTimeout(resolve, ms));
34
- }
35
- function retryDelayMs(attempt, retryAfter) {
36
- if (retryAfter) {
37
- const retrySeconds = Number(retryAfter);
38
- if (Number.isFinite(retrySeconds) && retrySeconds > 0) {
39
- return Math.min(RETRY_MAX_DELAY_MS, Math.floor(retrySeconds * 1e3));
40
- }
41
- const retryAtMs = Date.parse(retryAfter);
42
- if (Number.isFinite(retryAtMs)) {
43
- const deltaMs = retryAtMs - Date.now();
44
- if (deltaMs > 0) {
45
- return Math.min(RETRY_MAX_DELAY_MS, Math.floor(deltaMs));
46
- }
47
- }
48
- }
49
- const exponential = Math.min(
50
- RETRY_MAX_DELAY_MS,
51
- RETRY_BASE_DELAY_MS * Math.pow(2, Math.max(0, attempt - 1))
52
- );
53
- const jitter = Math.floor(Math.random() * RETRY_BASE_DELAY_MS);
54
- return Math.min(RETRY_MAX_DELAY_MS, exponential + jitter);
55
- }
56
- function normalizeErrorCode(value) {
57
- if (typeof value !== "string") {
58
- return null;
59
- }
60
- return value.toUpperCase();
61
- }
62
- function isRetryableNetworkError(error) {
63
- const message = error instanceof Error ? error.message : String(error);
64
- const normalized = message.toLowerCase();
65
- if (normalized.includes("fetch") || normalized.includes("timeout") || normalized.includes("abort") || normalized.includes("econnrefused") || normalized.includes("enotfound") || normalized.includes("econnreset") || normalized.includes("temporarily unavailable")) {
66
- return true;
67
- }
68
- if (!error || typeof error !== "object") {
69
- return false;
70
- }
71
- const topLevel = error;
72
- const directCode = normalizeErrorCode(topLevel.code) ?? normalizeErrorCode(topLevel.errno);
73
- if (directCode && RETRYABLE_NETWORK_CODES.has(directCode)) {
74
- return true;
75
- }
76
- if (!topLevel.cause || typeof topLevel.cause !== "object") {
77
- return false;
78
- }
79
- const cause = topLevel.cause;
80
- const causeCode = normalizeErrorCode(cause.code) ?? normalizeErrorCode(cause.errno);
81
- return Boolean(causeCode && RETRYABLE_NETWORK_CODES.has(causeCode));
82
- }
83
- function resolveBaseUrl(path) {
84
- return path.startsWith("/auth/") ? AUTH_BASE_URL : API_BASE_URL;
85
- }
86
- async function request(method, path, token, body) {
87
- const url = `${resolveBaseUrl(path)}${path}`;
88
- const headers = {
89
- "content-type": "application/json",
90
- "user-agent": "archal-cli/0.1.0"
91
- };
92
- if (token) {
93
- headers["authorization"] = `Bearer ${token}`;
94
- }
95
- const retriesAllowed = method !== "POST" || path.endsWith("/evidence/finalize");
96
- const attempts = retriesAllowed ? MAX_RETRIES + 1 : 1;
97
- let lastError = "request failed";
98
- let lastOffline = false;
99
- for (let attempt = 1; attempt <= attempts; attempt += 1) {
100
- try {
101
- const response = await fetch(url, {
102
- method,
103
- headers,
104
- body: body ? JSON.stringify(body) : void 0,
105
- signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
106
- });
107
- if (!response.ok) {
108
- const text = await response.text().catch(() => "");
109
- const retryable = retriesAllowed && attempt < attempts && RETRYABLE_STATUS_CODES.has(response.status);
110
- if (retryable) {
111
- await sleep(retryDelayMs(attempt, response.headers.get("retry-after")));
112
- continue;
113
- }
114
- return { ok: false, error: `HTTP ${response.status}: ${text}`, offline: false };
115
- }
116
- if (response.status === 204) {
117
- return { ok: true, data: void 0 };
118
- }
119
- const data = await response.json();
120
- return { ok: true, data };
121
- } catch (error) {
122
- const offline = isRetryableNetworkError(error);
123
- lastError = error instanceof Error ? error.message : String(error);
124
- lastOffline = offline;
125
- if (retriesAllowed && offline && attempt < attempts) {
126
- await sleep(retryDelayMs(attempt, null));
127
- continue;
128
- }
129
- return { ok: false, error: lastError, offline };
130
- }
131
- }
132
- return { ok: false, error: lastError, offline: lastOffline };
133
- }
134
- function fetchAuthMe(token) {
135
- return request("GET", "/auth/me", token);
136
- }
137
- function fetchTwinsCatalog(token) {
138
- return request("GET", "/api/twins", token);
139
- }
140
- function updateTwinSelection(token, twinIds) {
141
- return request("POST", "/api/twins/select", token, { twinIds });
142
- }
143
- function startSession(token, body) {
144
- return request("POST", "/api/sessions", token, body);
145
- }
146
- function endSession(token, sessionId) {
147
- return request("DELETE", `/api/sessions/${encodeURIComponent(sessionId)}`, token);
148
- }
149
- function getSessionHealth(token, sessionId) {
150
- return request(
151
- "GET",
152
- `/api/sessions/${encodeURIComponent(sessionId)}/health`,
153
- token
154
- );
155
- }
156
- function getSessionStatus(token, sessionId) {
157
- return request(
158
- "GET",
159
- `/api/sessions/${encodeURIComponent(sessionId)}`,
160
- token
161
- );
162
- }
163
- function finalizeSessionEvidence(token, sessionId, body) {
164
- return request(
165
- "POST",
166
- `/api/sessions/${encodeURIComponent(sessionId)}/evidence/finalize`,
167
- token,
168
- body ?? {}
169
- );
170
- }
171
- function getSessionEvidence(token, sessionId) {
172
- return request(
173
- "GET",
174
- `/api/sessions/${encodeURIComponent(sessionId)}/evidence`,
175
- token
176
- );
177
- }
178
-
179
- export {
180
- fetchAuthMe,
181
- fetchTwinsCatalog,
182
- updateTwinSelection,
183
- startSession,
184
- endSession,
185
- getSessionHealth,
186
- getSessionStatus,
187
- finalizeSessionEvidence,
188
- getSessionEvidence
189
- };
@@ -1,136 +0,0 @@
1
- // src/api-client.ts
2
- var AUTH_BASE_URL = process.env["ARCHAL_AUTH_URL"] ?? "https://archal.ai";
3
- var API_BASE_URL = process.env["ARCHAL_API_URL"] ?? AUTH_BASE_URL;
4
- var REQUEST_TIMEOUT_MS = 8e3;
5
- var RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([408, 425, 429, 500, 502, 503, 504]);
6
- function parseBoundedInt(value, fallback, min, max) {
7
- const parsed = Number(value);
8
- if (!Number.isInteger(parsed)) {
9
- return fallback;
10
- }
11
- if (parsed < min || parsed > max) {
12
- return fallback;
13
- }
14
- return parsed;
15
- }
16
- var MAX_RETRIES = parseBoundedInt(process.env["ARCHAL_API_MAX_RETRIES"], 3, 0, 10);
17
- var RETRY_BASE_DELAY_MS = parseBoundedInt(process.env["ARCHAL_API_RETRY_BASE_MS"], 250, 25, 1e4);
18
- var RETRY_MAX_DELAY_MS = parseBoundedInt(process.env["ARCHAL_API_RETRY_MAX_MS"], 3e3, RETRY_BASE_DELAY_MS, 2e4);
19
- function sleep(ms) {
20
- return new Promise((resolve) => setTimeout(resolve, ms));
21
- }
22
- function retryDelayMs(attempt, retryAfter) {
23
- if (retryAfter) {
24
- const retrySeconds = Number(retryAfter);
25
- if (Number.isFinite(retrySeconds) && retrySeconds > 0) {
26
- return Math.min(RETRY_MAX_DELAY_MS, Math.floor(retrySeconds * 1e3));
27
- }
28
- }
29
- const exponential = Math.min(
30
- RETRY_MAX_DELAY_MS,
31
- RETRY_BASE_DELAY_MS * Math.pow(2, Math.max(0, attempt - 1))
32
- );
33
- const jitter = Math.floor(Math.random() * RETRY_BASE_DELAY_MS);
34
- return Math.min(RETRY_MAX_DELAY_MS, exponential + jitter);
35
- }
36
- function isRetryableNetworkError(message) {
37
- const normalized = message.toLowerCase();
38
- return normalized.includes("fetch") || normalized.includes("timeout") || normalized.includes("abort") || normalized.includes("econnrefused") || normalized.includes("enotfound") || normalized.includes("econnreset") || normalized.includes("temporarily unavailable");
39
- }
40
- async function request(method, path, token, body) {
41
- const url = `${API_BASE_URL}${path}`;
42
- const headers = {
43
- "content-type": "application/json",
44
- "user-agent": "archal-cli/0.1.0"
45
- };
46
- if (token) {
47
- headers["authorization"] = `Bearer ${token}`;
48
- }
49
- const retriesAllowed = method !== "POST" || path.endsWith("/evidence/finalize");
50
- const attempts = retriesAllowed ? MAX_RETRIES + 1 : 1;
51
- let lastError = "request failed";
52
- let lastOffline = false;
53
- for (let attempt = 1; attempt <= attempts; attempt += 1) {
54
- try {
55
- const response = await fetch(url, {
56
- method,
57
- headers,
58
- body: body ? JSON.stringify(body) : void 0,
59
- signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
60
- });
61
- if (!response.ok) {
62
- const text = await response.text().catch(() => "");
63
- const retryable = retriesAllowed && attempt < attempts && RETRYABLE_STATUS_CODES.has(response.status);
64
- if (retryable) {
65
- await sleep(retryDelayMs(attempt, response.headers.get("retry-after")));
66
- continue;
67
- }
68
- return { ok: false, error: `HTTP ${response.status}: ${text}`, offline: false };
69
- }
70
- if (response.status === 204) {
71
- return { ok: true, data: void 0 };
72
- }
73
- const data = await response.json();
74
- return { ok: true, data };
75
- } catch (error) {
76
- const message = error instanceof Error ? error.message : String(error);
77
- const offline = isRetryableNetworkError(message);
78
- lastError = message;
79
- lastOffline = offline;
80
- if (retriesAllowed && offline && attempt < attempts) {
81
- await sleep(retryDelayMs(attempt, null));
82
- continue;
83
- }
84
- return { ok: false, error: message, offline };
85
- }
86
- }
87
- return { ok: false, error: lastError, offline: lastOffline };
88
- }
89
- function fetchAuthMe(token) {
90
- return request("GET", "/auth/me", token);
91
- }
92
- function fetchTwinsCatalog(token) {
93
- return request("GET", "/api/twins", token);
94
- }
95
- function updateTwinSelection(token, twinIds) {
96
- return request("POST", "/api/twins/select", token, { twinIds });
97
- }
98
- function startSession(token, body) {
99
- return request("POST", "/api/sessions", token, body);
100
- }
101
- function endSession(token, sessionId) {
102
- return request("DELETE", `/api/sessions/${encodeURIComponent(sessionId)}`, token);
103
- }
104
- function getSessionHealth(token, sessionId) {
105
- return request(
106
- "GET",
107
- `/api/sessions/${encodeURIComponent(sessionId)}/health`,
108
- token
109
- );
110
- }
111
- function getSessionStatus(token, sessionId) {
112
- return request(
113
- "GET",
114
- `/api/sessions/${encodeURIComponent(sessionId)}`,
115
- token
116
- );
117
- }
118
- function finalizeSessionEvidence(token, sessionId, body) {
119
- return request(
120
- "POST",
121
- `/api/sessions/${encodeURIComponent(sessionId)}/evidence/finalize`,
122
- token,
123
- body ?? {}
124
- );
125
- }
126
-
127
- export {
128
- fetchAuthMe,
129
- fetchTwinsCatalog,
130
- updateTwinSelection,
131
- startSession,
132
- endSession,
133
- getSessionHealth,
134
- getSessionStatus,
135
- finalizeSessionEvidence
136
- };