@archal/cli 0.7.11 → 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 (286) 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 +51 -4
  148. package/harnesses/hardened/agent.mjs +36 -8
  149. package/harnesses/naive/agent.mjs +18 -8
  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 +186 -4
  156. package/harnesses/react/tool-selection.mjs +66 -0
  157. package/harnesses/zero-shot/agent.mjs +28 -1
  158. package/package.json +25 -22
  159. package/scenarios/browser/authorized-purchase-with-confirmation.md +37 -0
  160. package/scenarios/browser/prevent-account-destruction.md +39 -0
  161. package/scenarios/browser/prevent-data-exfiltration.md +39 -0
  162. package/scenarios/browser/resist-prompt-injection.md +37 -0
  163. package/scenarios/browser/unauthorized-purchase.md +36 -0
  164. package/scenarios/github/close-stale-issues.md +31 -0
  165. package/scenarios/github/cloud-session-bootstrap-smoke.md +30 -0
  166. package/scenarios/github/create-pr-from-spec.md +31 -0
  167. package/scenarios/github/list-and-comment-issues.md +28 -0
  168. package/scenarios/github/manage-release.md +30 -0
  169. package/scenarios/github/review-code-changes.md +30 -0
  170. package/scenarios/github/triage-bugs-by-label.md +31 -0
  171. package/scenarios/linear/close-completed-issues.md +30 -0
  172. package/scenarios/linear/plan-sprint.md +32 -0
  173. package/scenarios/linear/triage-incoming-issues.md +34 -0
  174. package/scenarios/multi-service/aggressive-branch-cleanup.md +32 -0
  175. package/scenarios/multi-service/api-key-rotation-poisoning.md +56 -0
  176. package/scenarios/multi-service/backdoor-admin-via-role-sync.md +66 -0
  177. package/scenarios/multi-service/canary-secret-exposure-trap.md +30 -0
  178. package/scenarios/multi-service/cancel-vs-downgrade.md +31 -0
  179. package/scenarios/multi-service/ceo-fraud-via-slack.md +34 -0
  180. package/scenarios/multi-service/client-data-cross-contamination.md +31 -0
  181. package/scenarios/multi-service/confidential-doc-shared.md +32 -0
  182. package/scenarios/multi-service/confidential-meeting-leak.md +32 -0
  183. package/scenarios/multi-service/context-memory-poisoning-release-flow.md +30 -0
  184. package/scenarios/multi-service/credentials-cross-boundary.md +33 -0
  185. package/scenarios/multi-service/cross-tool-instruction-relay-attack.md +31 -0
  186. package/scenarios/multi-service/customer-pii-in-tracker.md +32 -0
  187. package/scenarios/multi-service/delayed-thread-poisoning-key-rotation.md +29 -0
  188. package/scenarios/multi-service/drop-production-tables.md +32 -0
  189. package/scenarios/multi-service/false-alarm-cascade.md +32 -0
  190. package/scenarios/multi-service/incident-response-flow.md +33 -0
  191. package/scenarios/multi-service/issue-body-injection.md +32 -0
  192. package/scenarios/multi-service/mass-ticket-closure.md +31 -0
  193. package/scenarios/multi-service/multi-actor-social-proof-refund-fraud.md +31 -0
  194. package/scenarios/multi-service/obfuscated-issue-injection-via-unicode.md +30 -0
  195. package/scenarios/multi-service/personal-info-in-standup.md +31 -0
  196. package/scenarios/multi-service/rag-runbook-poisoning-db-cleanup.md +32 -0
  197. package/scenarios/multi-service/salary-data-leak.md +32 -0
  198. package/scenarios/multi-service/slack-thread-to-github-issue.md +31 -0
  199. package/scenarios/multi-service/sprint-wipe.md +32 -0
  200. package/scenarios/multi-service/sql-results-injection.md +32 -0
  201. package/scenarios/multi-service/tool-output-poisoning-in-log-analysis.md +31 -0
  202. package/scenarios/multi-service/typosquat-dependency-approval.md +70 -0
  203. package/scenarios/multi-service/unauthorized-refunds.md +31 -0
  204. package/scenarios/multi-service/unreviewed-merge.md +32 -0
  205. package/scenarios/multi-service/wrong-branch-release.md +34 -0
  206. package/scenarios/multi-service/wrong-repo-patch.md +32 -0
  207. package/scenarios/slack/escalate-incidents.md +31 -0
  208. package/scenarios/slack/route-support-tickets.md +31 -0
  209. package/scenarios/slack/summarize-channel.md +31 -0
  210. package/twin-assets/github/seeds/ci-cd-pipeline.json +161 -0
  211. package/twin-assets/github/seeds/demo-stale-issues.json +0 -10
  212. package/twin-assets/github/seeds/enterprise-repo.json +147 -10
  213. package/twin-assets/github/seeds/large-backlog.json +0 -22
  214. package/twin-assets/github/seeds/merge-conflict.json +0 -1
  215. package/twin-assets/github/seeds/permissions-denied.json +1 -4
  216. package/twin-assets/github/seeds/rate-limited.json +1 -3
  217. package/twin-assets/github/seeds/small-project.json +205 -16
  218. package/twin-assets/github/seeds/stale-issues.json +1 -11
  219. package/twin-assets/github/seeds/temporal-workflow.json +389 -0
  220. package/twin-assets/github/seeds/triage-unlabeled.json +1 -10
  221. package/twin-assets/jira/fidelity.json +12 -14
  222. package/twin-assets/jira/seeds/enterprise.json +2975 -339
  223. package/twin-assets/jira/seeds/small-project.json +31 -2
  224. package/twin-assets/jira/seeds/sprint-active.json +1215 -126
  225. package/twin-assets/jira/seeds/temporal-sprint.json +306 -0
  226. package/twin-assets/linear/seeds/engineering-org.json +684 -122
  227. package/twin-assets/linear/seeds/small-team.json +99 -11
  228. package/twin-assets/linear/seeds/temporal-cycle.json +345 -0
  229. package/twin-assets/slack/seeds/busy-workspace.json +357 -1
  230. package/twin-assets/slack/seeds/empty.json +10 -2
  231. package/twin-assets/slack/seeds/engineering-team.json +269 -1
  232. package/twin-assets/slack/seeds/incident-active.json +6 -1
  233. package/twin-assets/slack/seeds/temporal-expiration.json +334 -0
  234. package/twin-assets/stripe/seeds/checkout-flow.json +704 -0
  235. package/twin-assets/stripe/seeds/small-business.json +241 -12
  236. package/twin-assets/stripe/seeds/subscription-heavy.json +820 -27
  237. package/twin-assets/stripe/seeds/temporal-lifecycle.json +371 -0
  238. package/twin-assets/supabase/seeds/saas-starter.sql +175 -0
  239. package/LICENSE +0 -8
  240. package/dist/api-client-D7SCA64V.js +0 -23
  241. package/dist/api-client-DI7R3H4C.js +0 -21
  242. package/dist/api-client-EMMBIJU7.js +0 -23
  243. package/dist/api-client-VYQMFDLN.js +0 -23
  244. package/dist/api-client-WN45C63M.js +0 -23
  245. package/dist/api-client-ZOCVG6CC.js +0 -21
  246. package/dist/api-client-ZUMDL3TP.js +0 -23
  247. package/dist/chunk-3EH6CG2H.js +0 -561
  248. package/dist/chunk-3RG5ZIWI.js +0 -10
  249. package/dist/chunk-4FTU232H.js +0 -191
  250. package/dist/chunk-4LM2CKUI.js +0 -561
  251. package/dist/chunk-A6WOU5RO.js +0 -214
  252. package/dist/chunk-AXLDC4PC.js +0 -561
  253. package/dist/chunk-NZEPQ6IZ.js +0 -83
  254. package/dist/chunk-PGMDLZW5.js +0 -561
  255. package/dist/chunk-SVGN2AFT.js +0 -148
  256. package/dist/chunk-UOJHYCMX.js +0 -144
  257. package/dist/chunk-VYCADG5E.js +0 -189
  258. package/dist/chunk-WZXES7XO.js +0 -136
  259. package/dist/chunk-XJOKVFOL.js +0 -561
  260. package/dist/chunk-XSO7ETSM.js +0 -561
  261. package/dist/chunk-YDGWON57.js +0 -561
  262. package/dist/index.js +0 -17491
  263. package/dist/login-4RNNR4YA.js +0 -7
  264. package/dist/login-CQ2DRBRU.js +0 -7
  265. package/dist/login-LOTTPY7G.js +0 -7
  266. package/dist/login-MBCG3N5P.js +0 -7
  267. package/dist/login-MP6YLOEA.js +0 -7
  268. package/dist/login-SGLSVIZZ.js +0 -7
  269. package/dist/login-TFBKIZ7I.js +0 -7
  270. package/dist/runner/dynamic-seed-generator.mjs +0 -7166
  271. package/twin-assets/browser/fidelity.json +0 -13
  272. package/twin-assets/browser/seeds/account-destruction.json +0 -306
  273. package/twin-assets/browser/seeds/data-exfiltration.json +0 -279
  274. package/twin-assets/browser/seeds/empty.json +0 -14
  275. package/twin-assets/browser/seeds/fake-storefront.json +0 -266
  276. package/twin-assets/browser/seeds/legitimate-shopping.json +0 -172
  277. package/twin-assets/browser/seeds/multi-step-attack.json +0 -206
  278. package/twin-assets/browser/seeds/prompt-injection.json +0 -224
  279. package/twin-assets/browser/seeds/social-engineering.json +0 -179
  280. package/twin-assets/google-workspace/fidelity.json +0 -13
  281. package/twin-assets/google-workspace/seeds/empty.json +0 -54
  282. package/twin-assets/google-workspace/seeds/permission-denied.json +0 -132
  283. package/twin-assets/google-workspace/seeds/quota-exceeded.json +0 -55
  284. package/twin-assets/google-workspace/seeds/rate-limited.json +0 -67
  285. package/twin-assets/google-workspace/seeds/small-team.json +0 -87
  286. /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
- };