firedrill-run 2.2.5 → 3.0.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 (392) hide show
  1. package/README.md +178 -22
  2. package/bin/firedrill.mjs +29 -5
  3. package/dist/assembly.json +13 -0
  4. package/dist/cli/runtime/candidate_copy.py +395 -0
  5. package/dist/cli/runtime/source_snapshot.py +391 -0
  6. package/dist/cli/src/administration.js +295 -0
  7. package/dist/cli/src/agent-changes.js +496 -0
  8. package/dist/cli/src/assessment-requests.js +67 -0
  9. package/dist/cli/src/auth.js +465 -0
  10. package/dist/cli/src/billing-commerce-contracts.js +1 -0
  11. package/dist/cli/src/billing-usage.js +227 -0
  12. package/dist/cli/src/billing-wallet-contracts.js +1 -0
  13. package/dist/cli/src/billing.js +170 -0
  14. package/dist/cli/src/bootstrap-process-lock.js +136 -0
  15. package/dist/cli/src/browser-links.js +14 -0
  16. package/dist/cli/src/campaign-controls.js +122 -0
  17. package/dist/cli/src/campaign-diagnoses.js +118 -0
  18. package/dist/cli/src/campaign-reports.js +1215 -0
  19. package/dist/cli/src/campaign-world.js +156 -0
  20. package/dist/cli/src/candidate-copy.js +376 -0
  21. package/dist/cli/src/catalog-contracts.js +1 -0
  22. package/dist/cli/src/ci-access-contracts.js +1 -0
  23. package/dist/cli/src/ci-configuration-contracts.js +1 -0
  24. package/dist/cli/src/ci-coverage.js +64 -0
  25. package/dist/cli/src/ci-delivery-contracts.js +1 -0
  26. package/dist/cli/src/ci-result-contracts.js +1 -0
  27. package/dist/cli/src/ci-run-contracts.js +1 -0
  28. package/dist/cli/src/ci-setup-proposals.js +52 -0
  29. package/dist/cli/src/company-policies.js +229 -0
  30. package/dist/cli/src/completion.js +79 -0
  31. package/dist/cli/src/configuration-intents.js +277 -0
  32. package/dist/cli/src/configuration.js +369 -0
  33. package/dist/cli/src/continuous-simulation.js +277 -0
  34. package/dist/cli/src/coordinated-checkpoints.js +133 -0
  35. package/dist/cli/src/credential-mode.js +139 -0
  36. package/dist/cli/src/credentials.js +331 -0
  37. package/dist/cli/src/credit-format.js +8 -0
  38. package/dist/cli/src/dataset-contracts.js +1 -0
  39. package/dist/cli/src/dataset-export.js +154 -0
  40. package/dist/cli/src/dataset-reads.js +37 -0
  41. package/dist/cli/src/dependency-preparation.js +239 -0
  42. package/dist/cli/src/director-tool-setup.js +104 -0
  43. package/dist/cli/src/driver-review.js +225 -0
  44. package/dist/cli/src/evaluation-authoring.js +315 -0
  45. package/dist/cli/src/evidence-bundles.js +367 -0
  46. package/dist/cli/src/execution-proposals.js +36 -0
  47. package/dist/cli/src/http.js +302 -0
  48. package/dist/cli/src/local-container-boundary.js +38 -0
  49. package/dist/cli/src/local-container-policy.js +201 -0
  50. package/dist/cli/src/local-execution-setup.js +81 -0
  51. package/dist/cli/src/local-source-basis.js +73 -0
  52. package/dist/cli/src/local-source.js +66 -0
  53. package/dist/cli/src/local-value-store.js +91 -0
  54. package/dist/cli/src/local-values.js +163 -0
  55. package/dist/cli/src/login-organizations.js +70 -0
  56. package/dist/cli/src/main.js +1622 -0
  57. package/dist/cli/src/mcp-connection.js +109 -0
  58. package/dist/cli/src/native/bindings.js +137 -0
  59. package/dist/cli/src/native/canonical.js +370 -0
  60. package/dist/cli/src/native/cloud-resources.js +942 -0
  61. package/dist/cli/src/native/companion-channel.js +421 -0
  62. package/dist/cli/src/native/companion-ipc.js +473 -0
  63. package/dist/cli/src/native/contracts.js +218 -0
  64. package/dist/cli/src/native/control-plane.js +1354 -0
  65. package/dist/cli/src/native/credit-approval.js +15 -0
  66. package/dist/cli/src/native/dependency-proxy.js +1006 -0
  67. package/dist/cli/src/native/drill-cleanup.js +115 -0
  68. package/dist/cli/src/native/drill-runner.js +1562 -0
  69. package/dist/cli/src/native/drivers/action-trace.js +210 -0
  70. package/dist/cli/src/native/drivers/function-wrapper.js +152 -0
  71. package/dist/cli/src/native/drivers/http.js +442 -0
  72. package/dist/cli/src/native/drivers/index.js +47 -0
  73. package/dist/cli/src/native/drivers/jsonl-process.js +538 -0
  74. package/dist/cli/src/native/drivers/playwright.js +600 -0
  75. package/dist/cli/src/native/drivers/signed-event.js +244 -0
  76. package/dist/cli/src/native/drivers/types.js +578 -0
  77. package/dist/cli/src/native/evidence-filter.js +255 -0
  78. package/dist/cli/src/native/isolated-access.js +241 -0
  79. package/dist/cli/src/native/library-sharing.js +220 -0
  80. package/dist/cli/src/native/local-run.js +667 -0
  81. package/dist/cli/src/native/local-secrets.js +19 -0
  82. package/dist/cli/src/native/mcp-config.js +123 -0
  83. package/dist/cli/src/native/metadata-requests.js +120 -0
  84. package/dist/cli/src/native/observations.js +1159 -0
  85. package/dist/cli/src/native/owned-groups.js +46 -0
  86. package/dist/cli/src/native/plan.js +594 -0
  87. package/dist/cli/src/native/png.js +159 -0
  88. package/dist/cli/src/native/ports.js +43 -0
  89. package/dist/cli/src/native/readiness.js +139 -0
  90. package/dist/cli/src/native/reassessments.js +206 -0
  91. package/dist/cli/src/native/redaction.js +235 -0
  92. package/dist/cli/src/native/registration.js +155 -0
  93. package/dist/cli/src/native/roots.js +110 -0
  94. package/dist/cli/src/native/run-cleanup.js +199 -0
  95. package/dist/cli/src/native/scratch.js +117 -0
  96. package/dist/cli/src/native/screenshots.js +60 -0
  97. package/dist/cli/src/native/session.js +556 -0
  98. package/dist/cli/src/native/standalone-proxy.js +580 -0
  99. package/dist/cli/src/native/standalone-renewals.js +183 -0
  100. package/dist/cli/src/native/standalone-state.js +193 -0
  101. package/dist/cli/src/native/standalone-tools.js +187 -0
  102. package/dist/cli/src/native/supervisor.js +831 -0
  103. package/dist/cli/src/native/target-auth.js +161 -0
  104. package/dist/cli/src/native/target-state.js +330 -0
  105. package/dist/cli/src/native/tool-reuse.js +364 -0
  106. package/dist/cli/src/native/tool-setups.js +336 -0
  107. package/dist/cli/src/native/world-reuse.js +288 -0
  108. package/dist/cli/src/onboarding.js +23 -0
  109. package/dist/cli/src/priority-requests.js +70 -0
  110. package/dist/cli/src/priority.js +223 -0
  111. package/dist/cli/src/prompts.js +184 -0
  112. package/dist/cli/src/real-operations.js +221 -0
  113. package/dist/cli/src/recipe-intents.js +58 -0
  114. package/dist/cli/src/recorded-context-intents.js +59 -0
  115. package/dist/cli/src/recorded-context.js +248 -0
  116. package/dist/cli/src/recordings.js +69 -0
  117. package/dist/cli/src/registration-guide.js +39 -0
  118. package/dist/cli/src/report-exports.js +213 -0
  119. package/dist/cli/src/request-input.js +47 -0
  120. package/dist/cli/src/resource-lifecycle.js +141 -0
  121. package/dist/cli/src/revision-requests.js +55 -0
  122. package/dist/cli/src/runner-abandon.js +53 -0
  123. package/dist/cli/src/runner-campaign-controls.js +262 -0
  124. package/dist/cli/src/runner-claim-reads.js +36 -0
  125. package/dist/cli/src/runner-completion.js +65 -0
  126. package/dist/cli/src/runner-configuration.js +546 -0
  127. package/dist/cli/src/runner-container.js +794 -0
  128. package/dist/cli/src/runner-evidence-erasure.js +351 -0
  129. package/dist/cli/src/runner-evidence-privacy.js +37 -0
  130. package/dist/cli/src/runner-evidence-retention.js +161 -0
  131. package/dist/cli/src/runner-evidence.js +326 -0
  132. package/dist/cli/src/runner-execute.js +92 -0
  133. package/dist/cli/src/runner-execution-deadline.js +25 -0
  134. package/dist/cli/src/runner-grants.js +307 -0
  135. package/dist/cli/src/runner-identity.js +615 -0
  136. package/dist/cli/src/runner-inputs.js +308 -0
  137. package/dist/cli/src/runner-jobs.js +49 -0
  138. package/dist/cli/src/runner-model-transport.js +392 -0
  139. package/dist/cli/src/runner-ownership.js +332 -0
  140. package/dist/cli/src/runner-process-lock.js +175 -0
  141. package/dist/cli/src/runner-runtime.js +396 -0
  142. package/dist/cli/src/runner-session-channel.js +377 -0
  143. package/dist/cli/src/runner-trial-completion.js +34 -0
  144. package/dist/cli/src/runner-trial-journal.js +358 -0
  145. package/dist/cli/src/runner-trial-live.js +393 -0
  146. package/dist/cli/src/runner-trial-protocol.js +289 -0
  147. package/dist/cli/src/runner-trial-sync.js +110 -0
  148. package/dist/cli/src/runner-trial-transfer.js +107 -0
  149. package/dist/cli/src/runner-voice.js +40 -0
  150. package/dist/cli/src/runner-world-claim.js +21 -0
  151. package/dist/cli/src/runner-world-collector.js +159 -0
  152. package/dist/cli/src/runner-world-command-evidence.js +487 -0
  153. package/dist/cli/src/runner-world-commands.js +268 -0
  154. package/dist/cli/src/runner-world-completion.js +76 -0
  155. package/dist/cli/src/runner-world-erasure.js +95 -0
  156. package/dist/cli/src/runner-world-evidence-sync.js +91 -0
  157. package/dist/cli/src/runner-world-journal.js +510 -0
  158. package/dist/cli/src/runner-world-native-filters.js +134 -0
  159. package/dist/cli/src/runner-world-observations.js +50 -0
  160. package/dist/cli/src/runner-world-session-protocol.js +134 -0
  161. package/dist/cli/src/saved-records.js +40 -0
  162. package/dist/cli/src/scenario-authoring.js +212 -0
  163. package/dist/cli/src/scenario-discovery.js +216 -0
  164. package/dist/cli/src/scenario-paths.js +68 -0
  165. package/dist/cli/src/scenario-requests.js +4 -0
  166. package/dist/cli/src/service-receipts.js +105 -0
  167. package/dist/cli/src/simple/authoring.js +270 -0
  168. package/dist/cli/src/simple/credit-approval.js +16 -0
  169. package/dist/cli/src/simple/help.js +98 -0
  170. package/dist/cli/src/simple/init.js +61 -0
  171. package/dist/cli/src/simple/library-sharing.js +414 -0
  172. package/dist/cli/src/simple/metadata-requests.js +46 -0
  173. package/dist/cli/src/simple/native-report.js +841 -0
  174. package/dist/cli/src/simple/native-tools.js +780 -0
  175. package/dist/cli/src/simple/plan-apply.js +506 -0
  176. package/dist/cli/src/simple/reassessment.js +323 -0
  177. package/dist/cli/src/simple/register.js +123 -0
  178. package/dist/cli/src/simple/run.js +122 -0
  179. package/dist/cli/src/simple/status.js +49 -0
  180. package/dist/cli/src/simple/tool-renewal.js +308 -0
  181. package/dist/cli/src/simple/tool-reuse.js +526 -0
  182. package/dist/cli/src/simple/tool-start-catalog.js +100 -0
  183. package/dist/cli/src/simple/tool-state.js +426 -0
  184. package/dist/cli/src/simple/tools-author.js +222 -0
  185. package/dist/cli/src/simple/watch.js +28 -0
  186. package/dist/cli/src/simple/world-reuse.js +586 -0
  187. package/dist/cli/src/simulation-intents.js +406 -0
  188. package/dist/cli/src/simulation-run.js +1058 -0
  189. package/dist/cli/src/source-batch.js +322 -0
  190. package/dist/cli/src/source-connection.js +451 -0
  191. package/dist/cli/src/source-runtime.js +346 -0
  192. package/dist/cli/src/source-selection-intents.js +75 -0
  193. package/dist/cli/src/source-sets.js +214 -0
  194. package/dist/cli/src/target-models.js +109 -0
  195. package/dist/cli/src/tool-catalog.js +224 -0
  196. package/dist/cli/src/tool-command-contracts.js +1 -0
  197. package/dist/cli/src/tool-command-export.js +245 -0
  198. package/dist/cli/src/tool-connection-contracts.js +1 -0
  199. package/dist/cli/src/tool-connection-reads.js +23 -0
  200. package/dist/cli/src/tool-contributions.js +58 -0
  201. package/dist/cli/src/tool-data.js +116 -0
  202. package/dist/cli/src/tool-datasets.js +176 -0
  203. package/dist/cli/src/tool-group-contracts.js +1 -0
  204. package/dist/cli/src/tool-group-reads.js +26 -0
  205. package/dist/cli/src/tool-group-state.js +147 -0
  206. package/dist/cli/src/tool-groups.js +311 -0
  207. package/dist/cli/src/tool-instances.js +186 -0
  208. package/dist/cli/src/tool-lifecycle-contracts.js +1 -0
  209. package/dist/cli/src/tool-lifecycle-reads.js +30 -0
  210. package/dist/cli/src/tool-lifecycle.js +323 -0
  211. package/dist/cli/src/tool-package-contracts.js +1 -0
  212. package/dist/cli/src/tool-package-reads.js +41 -0
  213. package/dist/cli/src/tool-records.js +53 -0
  214. package/dist/cli/src/tool-runtime.js +96 -0
  215. package/dist/cli/src/tool-state-contracts.js +1 -0
  216. package/dist/cli/src/tool-state-reads.js +31 -0
  217. package/dist/cli/src/tools.js +306 -0
  218. package/dist/cli/src/trial-actions.js +93 -0
  219. package/dist/cli/src/trial-checkpoints.js +133 -0
  220. package/dist/cli/src/trial-checks.js +70 -0
  221. package/dist/cli/src/trial-state.js +197 -0
  222. package/dist/cli/src/vault.js +266 -0
  223. package/dist/cli/src/workspace-registration.js +383 -0
  224. package/dist/cli/src/workspace-team-contracts.js +1 -0
  225. package/dist/cli/src/world-access.js +231 -0
  226. package/dist/cli/src/world-agent.js +4 -0
  227. package/dist/cli/src/world-checkpoint-scopes.js +15 -0
  228. package/dist/cli/src/world-contracts.js +6 -0
  229. package/dist/cli/src/world-creation.js +201 -0
  230. package/dist/cli/src/world-datasets.js +207 -0
  231. package/dist/cli/src/world-inspection.js +257 -0
  232. package/dist/cli/src/world-recipes.js +103 -0
  233. package/dist/cli/src/world-requests.js +241 -0
  234. package/dist/cli/src/world-session-checkpoints.js +196 -0
  235. package/dist/cli/src/world-session-lifecycle.js +207 -0
  236. package/dist/cli/src/world-session-requests.js +215 -0
  237. package/dist/cli/src/world-session-state.js +145 -0
  238. package/dist/cli/src/world-session-voice.js +66 -0
  239. package/dist/cli/src/world-sessions.js +288 -0
  240. package/dist/cli/src/world-stream.js +99 -0
  241. package/dist/cli/src/world-time-report.js +58 -0
  242. package/dist/contracts/agent-change-contracts.js +75 -0
  243. package/dist/contracts/agent-execution-contracts.js +38 -0
  244. package/dist/contracts/application-state-contracts.js +26 -0
  245. package/dist/contracts/assessment-aggregate-contracts.js +15 -0
  246. package/dist/contracts/assessment-contracts.js +74 -0
  247. package/dist/contracts/billing-commerce-contracts.js +107 -0
  248. package/dist/contracts/billing-wallet-contracts.js +43 -0
  249. package/dist/contracts/campaign-lifecycle.js +1 -0
  250. package/dist/contracts/campaign-world-contracts.js +80 -0
  251. package/dist/contracts/catalog-contracts.js +73 -0
  252. package/dist/contracts/ci-access-contracts.js +68 -0
  253. package/dist/contracts/ci-configuration-contracts.js +88 -0
  254. package/dist/contracts/ci-coverage-contracts.js +65 -0
  255. package/dist/contracts/ci-coverage-labels.js +25 -0
  256. package/dist/contracts/ci-delivery-contracts.js +61 -0
  257. package/dist/contracts/ci-result-contracts.js +103 -0
  258. package/dist/contracts/ci-run-contracts.js +51 -0
  259. package/dist/contracts/ci-setup-contracts.js +88 -0
  260. package/dist/contracts/clip-contracts.js +32 -0
  261. package/dist/contracts/comparison-contracts.js +53 -0
  262. package/dist/contracts/composite-contracts.js +34 -0
  263. package/dist/contracts/context-contracts.js +76 -0
  264. package/dist/contracts/continuation-report-contracts.js +1 -0
  265. package/dist/contracts/continuity-requirements.js +8 -0
  266. package/dist/contracts/coordinated-checkpoint-contracts.js +34 -0
  267. package/dist/contracts/dataset-contracts.js +88 -0
  268. package/dist/contracts/dependency-decision-contracts.js +36 -0
  269. package/dist/contracts/dependency-protocol-contracts.js +43 -0
  270. package/dist/contracts/director-execution.js +51 -0
  271. package/dist/contracts/driver-review-contracts.js +99 -0
  272. package/dist/contracts/evidence-contracts.js +65 -0
  273. package/dist/contracts/evidence-coverage-contracts.js +10 -0
  274. package/dist/contracts/export-contracts.js +44 -0
  275. package/dist/contracts/github-directory-contracts.js +96 -0
  276. package/dist/contracts/insight-contracts.js +11 -0
  277. package/dist/contracts/inspection-contracts.js +1 -0
  278. package/dist/contracts/local-claim-contracts.js +39 -0
  279. package/dist/contracts/local-configuration-contracts.js +7 -0
  280. package/dist/contracts/local-evidence-contracts.js +32 -0
  281. package/dist/contracts/local-grant-contracts.js +83 -0
  282. package/dist/contracts/local-input-contracts.js +19 -0
  283. package/dist/contracts/local-runner-contracts.js +42 -0
  284. package/dist/contracts/local-trial-live-contracts.js +16 -0
  285. package/dist/contracts/local-value-source-contracts.js +92 -0
  286. package/dist/contracts/local-world-native-contracts.js +8 -0
  287. package/dist/contracts/mcp-contracts.js +42 -0
  288. package/dist/contracts/media-contracts.js +28 -0
  289. package/dist/contracts/native-check-contracts.js +31 -0
  290. package/dist/contracts/native-identity-contracts.js +52 -0
  291. package/dist/contracts/onboarding-contracts.js +32 -0
  292. package/dist/contracts/performance-contracts.js +85 -0
  293. package/dist/contracts/planning-contracts.js +81 -0
  294. package/dist/contracts/real-operation-contracts.js +30 -0
  295. package/dist/contracts/recommendation-contracts.js +54 -0
  296. package/dist/contracts/report-contracts.js +1 -0
  297. package/dist/contracts/resource-lifecycle-contracts.js +57 -0
  298. package/dist/contracts/revision-contracts.js +12 -0
  299. package/dist/contracts/revision-request-contracts.js +39 -0
  300. package/dist/contracts/saved-record-contracts.js +76 -0
  301. package/dist/contracts/scenario-draft-comparison.js +91 -0
  302. package/dist/contracts/scenario-world-contracts.js +14 -0
  303. package/dist/contracts/service-contracts.js +1 -0
  304. package/dist/contracts/session-command-contracts.js +56 -0
  305. package/dist/contracts/session-contracts.js +65 -0
  306. package/dist/contracts/session-state-contracts.js +67 -0
  307. package/dist/contracts/session-voice-contracts.js +45 -0
  308. package/dist/contracts/source-set-contracts.js +26 -0
  309. package/dist/contracts/source-upload-contracts.js +22 -0
  310. package/dist/contracts/tool-command-contracts.js +57 -0
  311. package/dist/contracts/tool-connection-contracts.js +87 -0
  312. package/dist/contracts/tool-contribution-contracts.js +35 -0
  313. package/dist/contracts/tool-group-contracts.js +53 -0
  314. package/dist/contracts/tool-group-state-contracts.js +63 -0
  315. package/dist/contracts/tool-lifecycle-contracts.js +94 -0
  316. package/dist/contracts/tool-package-contracts.js +91 -0
  317. package/dist/contracts/tool-protocol-contracts.js +71 -0
  318. package/dist/contracts/tool-runtime-billing-contracts.js +28 -0
  319. package/dist/contracts/tool-setup-proposal.js +59 -0
  320. package/dist/contracts/tool-state-contracts.js +79 -0
  321. package/dist/contracts/trial-state-contracts.js +30 -0
  322. package/dist/contracts/typescript/agent-change.js +1 -0
  323. package/dist/contracts/typescript/assessment-aggregate.js +1 -0
  324. package/dist/contracts/typescript/assessment.js +1 -0
  325. package/dist/contracts/typescript/billing-commerce.js +1 -0
  326. package/dist/contracts/typescript/campaigns.js +1 -0
  327. package/dist/contracts/typescript/catalog.js +1 -0
  328. package/dist/contracts/typescript/ci-access.js +1 -0
  329. package/dist/contracts/typescript/ci-configuration.js +1 -0
  330. package/dist/contracts/typescript/ci-delivery.js +1 -0
  331. package/dist/contracts/typescript/ci-result.js +1 -0
  332. package/dist/contracts/typescript/ci-runs.js +1 -0
  333. package/dist/contracts/typescript/clips.js +1 -0
  334. package/dist/contracts/typescript/comparison.js +1 -0
  335. package/dist/contracts/typescript/composite.js +1 -0
  336. package/dist/contracts/typescript/connections.js +1 -0
  337. package/dist/contracts/typescript/context.js +1 -0
  338. package/dist/contracts/typescript/datasets.js +1 -0
  339. package/dist/contracts/typescript/evidence-coverage.js +1 -0
  340. package/dist/contracts/typescript/export.js +1 -0
  341. package/dist/contracts/typescript/github-directory.js +1 -0
  342. package/dist/contracts/typescript/insight.js +1 -0
  343. package/dist/contracts/typescript/inspection.js +1 -0
  344. package/dist/contracts/typescript/intake.js +1 -0
  345. package/dist/contracts/typescript/local-claim.js +1 -0
  346. package/dist/contracts/typescript/local-configuration.js +1 -0
  347. package/dist/contracts/typescript/local-evidence.js +1 -0
  348. package/dist/contracts/typescript/local-grant.js +1 -0
  349. package/dist/contracts/typescript/local-input.js +1 -0
  350. package/dist/contracts/typescript/local-runner.js +1 -0
  351. package/dist/contracts/typescript/local-trial-live.js +1 -0
  352. package/dist/contracts/typescript/local-value-source.js +1 -0
  353. package/dist/contracts/typescript/local-world-native.js +1 -0
  354. package/dist/contracts/typescript/mcp.js +1 -0
  355. package/dist/contracts/typescript/media.js +1 -0
  356. package/dist/contracts/typescript/native-check.js +1 -0
  357. package/dist/contracts/typescript/native-identity.js +1 -0
  358. package/dist/contracts/typescript/onboarding.js +1 -0
  359. package/dist/contracts/typescript/performance.js +1 -0
  360. package/dist/contracts/typescript/planning.js +1 -0
  361. package/dist/contracts/typescript/preparation.js +1 -0
  362. package/dist/contracts/typescript/real-operation.js +1 -0
  363. package/dist/contracts/typescript/recommendation.js +1 -0
  364. package/dist/contracts/typescript/reports.js +1 -0
  365. package/dist/contracts/typescript/resource-lifecycle.js +1 -0
  366. package/dist/contracts/typescript/saved-record.js +1 -0
  367. package/dist/contracts/typescript/scenarios.js +1 -0
  368. package/dist/contracts/typescript/services.js +1 -0
  369. package/dist/contracts/typescript/session-command.js +1 -0
  370. package/dist/contracts/typescript/session-state.js +1 -0
  371. package/dist/contracts/typescript/session-voice.js +1 -0
  372. package/dist/contracts/typescript/session.js +1 -0
  373. package/dist/contracts/typescript/tool-command.js +1 -0
  374. package/dist/contracts/typescript/tool-connection.js +1 -0
  375. package/dist/contracts/typescript/tool-contribution.js +1 -0
  376. package/dist/contracts/typescript/tool-groups.js +1 -0
  377. package/dist/contracts/typescript/tool-lifecycle.js +1 -0
  378. package/dist/contracts/typescript/tool-package.js +1 -0
  379. package/dist/contracts/typescript/tool-state.js +1 -0
  380. package/dist/contracts/typescript/trial-state.js +1 -0
  381. package/dist/contracts/typescript/vault.js +1 -0
  382. package/dist/contracts/typescript/workspace-team.js +1 -0
  383. package/dist/contracts/typescript/world-stream.js +1 -0
  384. package/dist/contracts/workspace-team-contracts.js +55 -0
  385. package/dist/contracts/world-command.js +65 -0
  386. package/dist/contracts/world-lifetime-contracts.js +74 -0
  387. package/dist/contracts/world-recipe-contracts.js +27 -0
  388. package/dist/contracts/world-stream-contracts.js +27 -0
  389. package/dist/package.json +1 -0
  390. package/package.json +16 -16
  391. package/LICENSE.md +0 -23
  392. package/PACKAGING.json +0 -50
@@ -0,0 +1,57 @@
1
+ import { sessionStateCounter } from './session-state-contracts.js';
2
+ const uuid = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/;
3
+ const states = ['queued', 'publishing', 'accepted', 'observed', 'not_dispatched', 'unknown'];
4
+ const positive = (value) => sessionStateCounter(value) !== null && value !== '0';
5
+ function fileMatches(value, available, maximum) {
6
+ if (!available)
7
+ return value === null;
8
+ if (!value || typeof value !== 'object' || Array.isArray(value))
9
+ return false;
10
+ const file = value;
11
+ return Object.keys(file).sort().join(',') === 'sha256,size' && typeof file.size === 'number'
12
+ && Number.isSafeInteger(file.size) && file.size >= 0 && file.size <= maximum
13
+ && typeof file.sha256 === 'string' && /^[a-f0-9]{64}$/.test(file.sha256);
14
+ }
15
+ export function toolCommandRead(value, matches) {
16
+ if (!matches)
17
+ throw new Error('The operation response did not match this instance or original request. Inspect its retained activity.');
18
+ return value;
19
+ }
20
+ export function toolCommandScope(base, actor) {
21
+ const parts = base.split('/');
22
+ return parts.length === 7 && parts[0] === '' && parts[1] === 'api' && parts[2] === 'workspaces'
23
+ && parts[4] === 'tools' && parts[5] === 'instances' && [parts[3], parts[6]].every(one => uuid.test(one ?? ''))
24
+ ? { workspace: parts[3], instance: parts[6], ...(actor ? { actor } : {}) } : null;
25
+ }
26
+ export function toolCommandMatches(value, scope, selected = {}) {
27
+ return !!value && value.workspace_id === scope.workspace && value.instance_id === scope.instance
28
+ && [scope.workspace, scope.instance, value.id, value.actor_id, value.request_key].every(one => uuid.test(one))
29
+ && /^[a-f0-9]{64}$/.test(value.request_digest) && (!selected.digest || value.request_digest === selected.digest)
30
+ && positive(value.sequence) && positive(value.state_epoch) && states.includes(value.state)
31
+ && ['operation', 'surface_open', 'surface_action'].includes(value.kind)
32
+ && (value.kind === 'operation' ? value.surface_id === null : !!value.surface_id && uuid.test(value.surface_id))
33
+ && (!selected.id || value.id === selected.id) && (!selected.key || value.request_key === selected.key && value.actor_id === scope.actor)
34
+ && (!selected.service || value.service_key === selected.service && value.kind === 'operation')
35
+ && (!selected.operation || value.operation_name === selected.operation && value.kind === 'operation')
36
+ && (value.state === 'observed' ? !!value.response : value.response === null)
37
+ && typeof value.request_available === 'boolean' && typeof value.response_available === 'boolean'
38
+ && typeof value.response_withheld === 'boolean'
39
+ && fileMatches(value.request_file, value.request_available, 8 * 1024 ** 2)
40
+ && fileMatches(value.response_file, value.response_available, 16 * 1024 ** 2)
41
+ && (!value.response_file || value.response_file.size === value.response?.body_size)
42
+ && (!value.response_withheld || !value.response_available)
43
+ && (!value.response_withheld || value.response?.transport !== 'http' || value.response.headers === undefined)
44
+ && (!value.response || Number.isSafeInteger(value.response.body_size) && value.response.body_size >= 0
45
+ && value.response.body_size <= 16 * 1024 ** 2 && (value.kind === 'operation'
46
+ ? value.response.transport === 'http' || value.response.transport === 'mcp' : value.response.transport === 'surface'));
47
+ }
48
+ export function toolCommandsMatch(value, scope, selected = {}) {
49
+ if (!value || value.workspace_id !== scope.workspace || value.instance_id !== scope.instance
50
+ || value.query !== (selected.query ?? '').trim() || value.outcome !== (selected.outcome ?? '')
51
+ || selected.anchor !== undefined && value.anchor !== selected.anchor || sessionStateCounter(value.anchor) === null
52
+ || !Number.isSafeInteger(value.limit) || value.limit < 1 || value.limit > 100 || value.results.length > value.limit
53
+ || [value.next_before, value.previous_after].some(one => one !== null && (!positive(one) || BigInt(one) > BigInt(value.anchor))))
54
+ return false;
55
+ return value.results.every((row, index) => toolCommandMatches(row, scope) && BigInt(row.sequence) <= BigInt(value.anchor)
56
+ && (!index || BigInt(value.results[index - 1].sequence) > BigInt(row.sequence)) && (!value.outcome || row.state === value.outcome));
57
+ }
@@ -0,0 +1,87 @@
1
+ import { sessionStateCounter } from './session-state-contracts.js';
2
+ const uuid = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/;
3
+ const serviceKey = /^[a-z][a-z0-9_-]{0,79}$/;
4
+ const operationName = /^[A-Za-z][A-Za-z0-9_.-]{0,127}$/;
5
+ const pair = (one) => JSON.stringify([one.service_key, one.operation_name]);
6
+ export function toolConnectionRead(value, matches) {
7
+ if (!matches)
8
+ throw new Error('The connection response did not match this instance or original permission. Inspect and revoke the original connection before replacing it.');
9
+ return value;
10
+ }
11
+ function protocols(value) {
12
+ return value.length >= 1 && value.length <= 2 && new Set(value).size === value.length && value.every(one => one === 'http' || one === 'mcp');
13
+ }
14
+ function permissions(value) {
15
+ return value.length >= 1 && new Set(value.map(pair)).size === value.length
16
+ && value.every(one => serviceKey.test(one.service_key) && operationName.test(one.operation_name));
17
+ }
18
+ function scopeMatches(value, scope) {
19
+ return !!value && uuid.test(scope.workspace) && uuid.test(scope.instance) && value.workspace_id === scope.workspace && value.instance_id === scope.instance;
20
+ }
21
+ function epochMatches(value, scope) {
22
+ return sessionStateCounter(value) !== null && value !== '0' && (!scope.epoch || scope.epoch === value);
23
+ }
24
+ function audienceMatches(value, instance) {
25
+ try {
26
+ const url = new URL(value);
27
+ return url.protocol === 'https:' && !url.username && !url.password && !url.port && !url.search && !url.hash
28
+ && url.pathname === `/tools/serve/${instance}` && url.origin + url.pathname === value;
29
+ }
30
+ catch {
31
+ return false;
32
+ }
33
+ }
34
+ function pageMatches(value, page) {
35
+ return Number.isSafeInteger(value.page) && value.page >= 1 && (!page || page === value.page) && Number.isSafeInteger(value.page_size)
36
+ && value.page_size >= 1 && value.page_size <= 100 && Number.isSafeInteger(value.count) && value.count >= 0 && value.results.length <= value.page_size;
37
+ }
38
+ export function toolConnectionMatches(value, scope, selected = {}) {
39
+ return scopeMatches(value, scope) && [value.id, value.actor_id, value.request_key].every(one => uuid.test(one))
40
+ && (!selected.id || selected.id === value.id) && (!selected.key || value.request_key === selected.key && value.actor_id === scope.actor)
41
+ && /^[a-f0-9]{64}$/.test(value.request_digest) && (!selected.digest || selected.digest === value.request_digest)
42
+ && epochMatches(value.state_epoch, scope) && permissions(value.operations) && protocols(value.protocols)
43
+ && audienceMatches(value.audience, scope.instance)
44
+ && value.http_url === (value.protocols.includes('http') ? value.audience + '/operations' : null)
45
+ && value.mcp_url === (value.protocols.includes('mcp') ? value.audience + '/mcp' : null)
46
+ && value.http_result_url === (value.http_services.length ? value.audience + '/http-requests/{request_id}' : null)
47
+ && (value.protocols.includes('http') || value.http_services.length === 0) && (!selected.revoked || !!value.revoked_at)
48
+ && new Set(value.http_services.map(one => one.service_key)).size === value.http_services.length
49
+ && value.http_services.every(service => serviceKey.test(service.service_key) && service.base_url === value.audience + '/http/' + service.service_key
50
+ && service.operations.every(operation => operationName.test(operation.name)
51
+ && value.operations.some(one => one.service_key === service.service_key && one.operation_name === operation.name)
52
+ && ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD'].includes(operation.method) && operation.path.startsWith('/')
53
+ && ['uuid_request', 'declared_vendor_key'].includes(operation.idempotency_key_mode)
54
+ && !operation.path.startsWith('//') && !/[\\?#%\u0000-\u0020\u007f]/.test(operation.path)));
55
+ }
56
+ export async function toolConnectionAccepted(value, scope, key, input, selected = {}) {
57
+ if (!toolConnectionMatches(value, scope, { ...selected, key }) || !permissions(input.operations) || !protocols(input.protocols)
58
+ || !Number.isSafeInteger(input.duration_seconds) || input.duration_seconds < 60)
59
+ return false;
60
+ const operations = input.operations.map(one => ({ operation_name: one.operation_name, service_key: one.service_key }))
61
+ .sort((left, right) => left.service_key < right.service_key ? -1 : left.service_key > right.service_key ? 1
62
+ : left.operation_name < right.operation_name ? -1 : left.operation_name > right.operation_name ? 1 : 0);
63
+ const sorted = [...input.protocols].sort();
64
+ if (JSON.stringify(value.operations.map(pair)) !== JSON.stringify(operations.map(pair)) || JSON.stringify(value.protocols) !== JSON.stringify(sorted))
65
+ return false;
66
+ const bytes = await globalThis.crypto.subtle.digest('SHA-256', new TextEncoder().encode(JSON.stringify({
67
+ duration_seconds: input.duration_seconds, operations, protocols: sorted
68
+ })));
69
+ return value.request_digest === Array.from(new Uint8Array(bytes), one => one.toString(16).padStart(2, '0')).join('');
70
+ }
71
+ export function toolConnectionTokenMatches(value) {
72
+ return value.token_available_once ? typeof value.token === 'string' && /^fd_tool_[a-f0-9-]{36}\.[A-Za-z0-9_-]{64}$/.test(value.token)
73
+ && value.token.startsWith('fd_tool_' + value.id + '.') : value.token === null;
74
+ }
75
+ export function toolConnectionsMatch(value, scope, query = '', page) {
76
+ return scopeMatches(value, scope) && value.query === query.trim() && pageMatches(value, page)
77
+ && value.results.every(row => toolConnectionMatches(row, scope));
78
+ }
79
+ export function toolConnectionOptionsMatch(value, scope, query = '', page) {
80
+ if (!scopeMatches(value, scope) || value.query !== query.trim() || !pageMatches(value, page) || !epochMatches(value.state_epoch, scope)
81
+ || !protocols(value.protocols) || !Number.isSafeInteger(value.duration_seconds) || value.duration_seconds < 0
82
+ || !audienceMatches(value.http_url.replace(/\/operations$/, ''), scope.instance)
83
+ || value.mcp_url !== value.http_url.replace(/\/operations$/, '/mcp'))
84
+ return false;
85
+ return value.results.every(one => serviceKey.test(one.service_key) && operationName.test(one.operation_name)
86
+ && ['none', 'read', 'write', 'mixed'].includes(one.effect));
87
+ }
@@ -0,0 +1,35 @@
1
+ const uuid = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/;
2
+ const digest = /^[a-f0-9]{64}$/;
3
+ const states = ['submitted', 'reviewed', 'rejected', 'withdrawn', 'published'];
4
+ export function contributionRead(value, scope, selected = {}) {
5
+ if (!value || value.workspace_id !== scope.workspace || value.actor_id !== scope.actor
6
+ || ![value.id, value.workspace_id, value.actor_id, value.request_key, value.implementation_id].every(one => uuid.test(one))
7
+ || selected.key !== undefined && value.request_key !== selected.key || selected.implementation !== undefined && value.implementation_id !== selected.implementation
8
+ || !digest.test(value.archive_sha256) || !digest.test(value.contract_digest) || !['Apache-2.0', 'MIT'].includes(value.license)
9
+ || value.consent_version !== '2026-11-05' || !states.includes(value.state) || value.automatically_shared !== false
10
+ || typeof value.can_withdraw !== 'boolean' || !Number.isFinite(Date.parse(value.submitted_at))
11
+ || !['', 'clean_native_version', 'rights_unclear', 'private_material', 'native_rework', 'out_of_scope'].includes(value.review_code)
12
+ || [value.reviewed_at, value.withdrawn_at].some(one => one !== null && !Number.isFinite(Date.parse(one)))
13
+ || value.release_id !== null && !uuid.test(value.release_id)
14
+ || value.state === 'published' && (!value.release_id || value.can_withdraw)
15
+ || value.state === 'withdrawn' && (!value.withdrawn_at || value.can_withdraw)
16
+ || value.can_withdraw && !['submitted', 'reviewed', 'rejected'].includes(value.state)
17
+ || selected.input && ['implementation_id', 'archive_sha256', 'contract_digest', 'license', 'consent_version'].some(field => value[field] !== selected.input[field])) {
18
+ throw new Error('The contribution response did not match this exact version and original review. Recover its status before another action.');
19
+ }
20
+ return value;
21
+ }
22
+ export function contributionPageRead(value, scope, selected) {
23
+ if (!value || value.workspace_id !== scope.workspace || value.actor_id !== scope.actor || value.page !== selected.page
24
+ || typeof value.can_nominate !== 'boolean'
25
+ || value.implementation_id !== (selected.implementation ?? null) || value.state_filter !== (selected.state ?? 'all')
26
+ || !Number.isSafeInteger(value.count) || value.count < 0 || !Number.isSafeInteger(value.page_size) || value.page_size < 1 || value.page_size > 100
27
+ || !Array.isArray(value.results) || value.results.length > value.page_size)
28
+ throw new Error('The private contribution history changed. Reload it before continuing.');
29
+ value.results.forEach(row => {
30
+ contributionRead(row, scope, selected);
31
+ if (selected.state && selected.state !== 'all' && row.state !== selected.state)
32
+ throw new Error('The private contribution history did not match its selected state.');
33
+ });
34
+ return value;
35
+ }
@@ -0,0 +1,53 @@
1
+ const uuid = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/;
2
+ const optionalId = (value) => value === null || uuid.test(value);
3
+ export function toolGroupRead(value, matches) {
4
+ if (!matches)
5
+ throw new Error('The tool setup response did not match this workspace or original request. Inspect its retained setup history.');
6
+ return value;
7
+ }
8
+ export function toolGroupMatches(value, scope, selected = {}) {
9
+ if (!value || value.workspace_id !== scope.workspace || ![value.id, value.workspace_id, value.actor_id, value.request_key].every(one => uuid.test(one))
10
+ || !/^[a-f0-9]{64}$/.test(value.request_digest) || selected.id !== undefined && selected.id !== value.id
11
+ || selected.key !== undefined && (selected.key !== value.request_key || scope.actor !== value.actor_id)
12
+ || selected.digest !== undefined && selected.digest !== value.request_digest || selected.stopped && !value.stop_requested_at
13
+ || !Number.isSafeInteger(value.duration_seconds) || value.duration_seconds < 60
14
+ || !value.counts || Object.values(value.counts).some(one => !Number.isSafeInteger(one) || one < 0) || value.counts.selected < 1)
15
+ return false;
16
+ const counts = value.counts;
17
+ return counts.selected === counts.pending + counts.refused + counts.canceled + counts.created
18
+ && ['running', 'closing', 'failed', 'closed'].every(key => counts[key] <= counts.created)
19
+ && value.dispatch_complete === (counts.pending === 0) && value.all_closed === (counts.pending === 0 && counts.closed === counts.created)
20
+ && (!value.stop_requested_at || counts.running === 0);
21
+ }
22
+ export async function toolGroupAccepted(value, scope, key, input, selected = {}) {
23
+ if (!toolGroupMatches(value, scope, { ...selected, key }) || value.name !== input.name || value.duration_seconds !== input.duration_seconds
24
+ || input.start_consent !== true || value.counts.selected !== input.selections.length)
25
+ return false;
26
+ const selections = input.selections.map(one => 'implementation_id' in one
27
+ ? { dataset_id: one.dataset_id, implementation_id: one.implementation_id, usage_quote_id: one.usage_quote_id } : { dataset_id: null, release_id: one.release_id, usage_quote_id: one.usage_quote_id });
28
+ const bytes = await globalThis.crypto.subtle.digest('SHA-256', new TextEncoder().encode(JSON.stringify({
29
+ duration_seconds: input.duration_seconds, name: input.name, selections, start_consent: true
30
+ })));
31
+ return value.request_digest === Array.from(new Uint8Array(bytes), one => one.toString(16).padStart(2, '0')).join('');
32
+ }
33
+ function pageMatches(value, page) {
34
+ return Number.isSafeInteger(value.page) && value.page >= 1 && (!page || page === value.page) && Number.isSafeInteger(value.page_size)
35
+ && value.page_size >= 1 && value.page_size <= 100 && Number.isSafeInteger(value.count) && value.count >= 0 && value.results.length <= value.page_size;
36
+ }
37
+ export function toolGroupsMatch(value, scope, query = '', page) {
38
+ return !!value && value.workspace_id === scope.workspace && value.query === query.trim() && pageMatches(value, page)
39
+ && value.results.every(row => toolGroupMatches(row, scope));
40
+ }
41
+ export function toolGroupMembersMatch(value, scope, group, query = '', page) {
42
+ return !!value && uuid.test(group) && value.workspace_id === scope.workspace && value.group_id === group
43
+ && value.query === query.trim() && pageMatches(value, page) && value.results.every((row, index) => {
44
+ if (row.workspace_id !== scope.workspace || row.group_id !== group || !uuid.test(row.id) || !Number.isSafeInteger(row.position) || row.position < 0
45
+ || index > 0 && row.position <= value.results[index - 1].position || !optionalId(row.release_id) || !optionalId(row.implementation_id)
46
+ || !optionalId(row.catalog_request_key) || row.release_id === null && row.implementation_id === null
47
+ || !['pending', 'preparing', 'created', 'failed', 'canceled'].includes(row.state)
48
+ || row.dataset && (!uuid.test(row.dataset.id) || !Number.isSafeInteger(row.dataset.version) || row.dataset.version < 1))
49
+ return false;
50
+ return !row.instance || uuid.test(row.instance.id) && ['queued', 'starting', 'active', 'closing', 'reconciling', 'stopped', 'failed', 'canceled'].includes(row.instance.state)
51
+ && (!row.instance.observation_current || row.instance.state === 'active' && row.instance.terminal_at === null && row.instance.removal === null);
52
+ });
53
+ }
@@ -0,0 +1,63 @@
1
+ import { toolAllocationQuoteMatches } from './tool-runtime-billing-contracts.js';
2
+ const id = /^[a-f0-9]{8}(?:-[a-f0-9]{4}){3}-[a-f0-9]{12}$/;
3
+ const date = (value) => typeof value === 'string' && Number.isFinite(Date.parse(value));
4
+ export function groupStateInputMatches(value) {
5
+ const row = value;
6
+ return !!row && typeof row === 'object' && !Array.isArray(row)
7
+ && Object.keys(row).sort().join(',') === 'action,duration_seconds,member_quotes,name,source_operation_id,state_consent'
8
+ && ['capture', 'reset', 'fork'].includes(row.action) && typeof row.name === 'string'
9
+ && row.name.trim().length > 0 && row.name.trim().length <= 120 && !/[\u0000-\u001f\u007f]/.test(row.name) && row.state_consent === true
10
+ && Array.isArray(row.member_quotes) && new Set(row.member_quotes.map(one => one?.position)).size === row.member_quotes.length
11
+ && row.member_quotes.every(one => !!one && Object.keys(one).sort().join(',') === 'position,usage_quote_id'
12
+ && Number.isSafeInteger(one.position) && one.position >= 0 && typeof one.usage_quote_id === 'string' && id.test(one.usage_quote_id))
13
+ && (row.action === 'capture' ? row.source_operation_id === null && row.duration_seconds === null && row.member_quotes.length === 0
14
+ : typeof row.source_operation_id === 'string' && id.test(row.source_operation_id) && Number.isSafeInteger(row.duration_seconds)
15
+ && row.duration_seconds >= 60 && row.member_quotes.length > 0);
16
+ }
17
+ export function groupStateInputsEqual(left, right) {
18
+ return groupStateInputMatches(left) && groupStateInputMatches(right) && left.action === right.action && left.name === right.name
19
+ && left.source_operation_id === right.source_operation_id && left.duration_seconds === right.duration_seconds
20
+ && left.member_quotes.length === right.member_quotes.length && left.member_quotes.every((one, index) => one.position === right.member_quotes[index].position && one.usage_quote_id === right.member_quotes[index].usage_quote_id);
21
+ }
22
+ export function groupStateMatches(value, workspace, group, actor, key) {
23
+ return !!value && id.test(value.id) && value.workspace_id === workspace && value.group_id === group
24
+ && id.test(value.actor_id) && id.test(value.request_key) && (!actor || value.actor_id === actor) && (!key || value.request_key === key)
25
+ && groupStateInputMatches(value.request) && value.action === value.request.action && value.name === value.request.name.trim()
26
+ && value.source_operation_id === value.request.source_operation_id && date(value.created_at) && (value.finished_at === null || date(value.finished_at))
27
+ && ['preparing', 'holding', 'capturing', 'stopping', 'starting', 'releasing', 'recovery', 'completed', 'failed'].includes(value.state)
28
+ && !!value.counts && Object.keys(value.counts).sort().join(',') === 'held,ready,released,saved,total' && Number.isSafeInteger(value.counts.total)
29
+ && value.counts.total > 0 && Object.values(value.counts).every(one => Number.isSafeInteger(one) && one >= 0 && one <= value.counts.total)
30
+ && value.process_memory_included === false && value.external_state_included === false
31
+ && value.coordinated === (value.action === 'capture' && value.state === 'completed');
32
+ }
33
+ export function groupStatePageMatches(value, workspace, group, page) {
34
+ return !!value && value.page === page && Number.isSafeInteger(value.count) && value.count >= 0
35
+ && Number.isSafeInteger(value.page_size) && value.page_size > 0 && value.page_size <= 100
36
+ && Array.isArray(value.results) && value.results.length <= value.page_size && value.results.length <= value.count
37
+ && value.results.every(one => groupStateMatches(one, workspace, group)) && new Set(value.results.map(one => one.id)).size === value.results.length;
38
+ }
39
+ export function groupStateMemberPageMatches(value, page) {
40
+ return !!value && value.page === page && Number.isSafeInteger(value.count) && value.count >= 0
41
+ && Number.isSafeInteger(value.page_size) && value.page_size > 0 && value.page_size <= 100
42
+ && Array.isArray(value.results) && value.results.length <= value.page_size && value.results.length <= value.count
43
+ && new Set(value.results.map(one => one?.id)).size === value.results.length
44
+ && new Set(value.results.map(one => one?.position)).size === value.results.length
45
+ && value.results.every(one => !!one && id.test(one.id) && id.test(one.instance_id) && typeof one.name === 'string'
46
+ && Number.isSafeInteger(one.position) && one.position >= 0 && /^[1-9][0-9]{0,18}$/.test(one.state_epoch)
47
+ && (one.checkpoint_id === null || id.test(one.checkpoint_id)) && (one.successor_id === null || id.test(one.successor_id))
48
+ && (one.checkpoint_sha256 === null || /^[a-f0-9]{64}$/.test(one.checkpoint_sha256))
49
+ && [one.held_at, one.released_at, one.captured_at].every(at => at === null || date(at))
50
+ && (one.event_watermark === null || /^(0|[1-9][0-9]{0,18})$/.test(one.event_watermark)));
51
+ }
52
+ export function groupStateQuoteMatches(value, workspace, group, key, selected) {
53
+ return !!value && value.group_id === group && value.operation_request_key === key && value.action === selected.action
54
+ && value.source_operation_id === selected.source_operation_id && value.duration_seconds === selected.duration_seconds
55
+ && Array.isArray(value.members) && value.members.length > 0 && new Set(value.members.map(one => one?.position)).size === value.members.length
56
+ && new Set(value.members.map(one => one?.quote?.id)).size === value.members.length && value.members.every(one => !!one
57
+ && Number.isSafeInteger(one.position) && one.position >= 0 && typeof one.name === 'string' && !!one.selection
58
+ && one.selection.release_id === null && one.selection.dataset_id === null && one.selection.duration_seconds === selected.duration_seconds
59
+ && id.test(one.selection.implementation_id ?? '') && id.test(one.selection.launch_request_key)
60
+ && id.test(one.selection.restore?.instance_id ?? '') && id.test(one.selection.restore?.checkpoint_id ?? '')
61
+ && one.selection.restore?.action === (selected.action === 'fork' ? 'fork' : 'restore')
62
+ && toolAllocationQuoteMatches(one.quote, workspace, one.selection) && Date.parse(one.quote.expires_at) > Date.now());
63
+ }
@@ -0,0 +1,94 @@
1
+ import { sessionStateCounter } from './session-state-contracts.js';
2
+ const uuid = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/;
3
+ const digest = /^[a-f0-9]{64}$/;
4
+ const states = ['queued', 'starting', 'active', 'closing', 'reconciling', 'stopped', 'failed', 'canceled'];
5
+ const terminal = ['stopped', 'failed', 'canceled'];
6
+ const optionalId = (value) => value === null || uuid.test(value);
7
+ export function toolLifecycleRead(value, matches) {
8
+ if (!matches)
9
+ throw new Error('The instance response did not match this selection. Inspect the original instance or request.');
10
+ return value;
11
+ }
12
+ export function toolInstanceMatches(value, workspace, selected = {}) {
13
+ return !!value && value.workspace_id === workspace && [workspace, value.id, value.actor_id, value.request_key, value.implementation_id].every(one => uuid.test(one))
14
+ && (!selected.id || value.id === selected.id) && (!selected.key || value.request_key === selected.key && value.actor_id === selected.actor)
15
+ && typeof value.tool_key === 'string' && value.tool_key.length > 0 && value.tool_key.length <= 160
16
+ && digest.test(value.request_digest) && sessionStateCounter(value.state_epoch) !== null && value.state_epoch !== '0'
17
+ && states.includes(value.state) && (terminal.includes(value.state) ? !!value.terminal_at : value.terminal_at === null)
18
+ && (!value.observation_current || value.state === 'active' && !value.terminal_at && !!value.last_observed_at)
19
+ && (!value.removal || uuid.test(value.removal.request_key) && (!value.removal.completed_at || !!value.terminal_at));
20
+ }
21
+ export function toolInstanceDetailMatches(value, workspace, selected = {}) {
22
+ return toolInstanceMatches(value, workspace, selected) && [value.parent_instance_id, value.restored_checkpoint_id, value.dataset_id].every(optionalId)
23
+ && ['declared_stateless', 'stored_data', 'unspecified'].includes(value.data_mode)
24
+ && value.visual_interfaces.every(one => /^[a-z][a-z0-9_-]{0,79}$/.test(one.service_key))
25
+ && !!value.lifetime && ['standalone', 'setup_member'].includes(value.lifetime.owner)
26
+ && value.lifetime.expires_at === value.expires_at && sessionStateCounter(value.lifetime.revision) !== null
27
+ && Number.isSafeInteger(value.lifetime.idle_timeout_seconds) && value.lifetime.idle_timeout_seconds >= 0
28
+ && Number.isSafeInteger(value.lifetime.maximum_extension_seconds) && value.lifetime.maximum_extension_seconds >= 60
29
+ && typeof value.lifetime.can_extend === 'boolean' && (!value.lifetime.can_extend || !value.terminal_at && value.state === 'active')
30
+ && ['supported_data_only', 'not_available', 'declared_stateless'].includes(value.lifetime.saved_state);
31
+ }
32
+ export function toolExtensionMatches(value, scope, selected = {}) {
33
+ if (!value || value.workspace_id !== scope.workspace || value.instance_id !== scope.instance
34
+ || ![value.id, value.workspace_id, value.instance_id, value.actor_id, value.request_key].every(one => typeof one === 'string' && uuid.test(one))
35
+ || !digest.test(value.request_digest) || sessionStateCounter(value.state_epoch) === null || value.state_epoch === '0'
36
+ || value.usage_quote_id !== null && !uuid.test(value.usage_quote_id)
37
+ || sessionStateCounter(value.revision) === null || value.revision === '0'
38
+ || !['queued', 'publishing', 'accepted', 'confirmed', 'failed'].includes(value.state)
39
+ || !Number.isSafeInteger(value.idle_timeout_seconds) || value.idle_timeout_seconds < 0
40
+ || !Number.isFinite(Date.parse(value.expected_expires_at)) || !Number.isFinite(Date.parse(value.requested_expires_at))
41
+ || Date.parse(value.requested_expires_at) <= Date.parse(value.expected_expires_at)
42
+ || (['confirmed', 'failed'].includes(value.state) ? !value.finished_at : value.finished_at !== null)
43
+ || (value.state === 'confirmed' ? value.confirmed_expires_at !== value.requested_expires_at : value.confirmed_expires_at !== null)
44
+ || selected.key && (value.request_key !== selected.key || value.actor_id !== scope.actor))
45
+ return false;
46
+ const input = selected.input;
47
+ return !input || value.usage_quote_id === input.usage_quote_id && value.state_epoch === input.state_epoch && value.idle_timeout_seconds === input.idle_timeout_seconds
48
+ && Date.parse(value.expected_expires_at) === Date.parse(input.expected_expires_at)
49
+ && Date.parse(value.requested_expires_at) === Date.parse(input.expected_expires_at) + input.additional_seconds * 1000;
50
+ }
51
+ export function toolExtensionPageMatches(value, scope, page) {
52
+ return !!value && value.workspace_id === scope.workspace && value.instance_id === scope.instance && value.page === page
53
+ && Number.isSafeInteger(value.page_size) && value.page_size >= 1 && value.page_size <= 100
54
+ && Number.isSafeInteger(value.count) && value.count >= 0 && Array.isArray(value.results) && value.results.length <= value.page_size
55
+ && value.results.every(one => toolExtensionMatches(one, scope));
56
+ }
57
+ export function toolRuntimeQuoteMatches(value, tool, input) {
58
+ return !!value && uuid.test(value.id) && value.workspace_id === tool.workspace_id && value.activity === 'tool_runtime'
59
+ && value.execution_location === 'managed' && digest.test(value.scope_digest) && digest.test(value.tariff_digest)
60
+ && Number.isSafeInteger(value.credit_scale) && value.credit_scale >= 1
61
+ && Number.isSafeInteger(value.estimated_units) && value.estimated_units >= 0
62
+ && Number.isSafeInteger(value.maximum_units) && value.maximum_units >= value.estimated_units
63
+ && Number.isFinite(Date.parse(value.expires_at)) && value.scope?.instance_id === tool.id
64
+ && value.scope.state_epoch === input.state_epoch && value.scope.idle_timeout_seconds === input.idle_timeout_seconds
65
+ && Date.parse(String(value.scope.expected_expires_at)) === Date.parse(input.expected_expires_at)
66
+ && Date.parse(String(value.scope.requested_expires_at)) === Date.parse(input.expected_expires_at) + input.additional_seconds * 1000;
67
+ }
68
+ export function toolInstancePageMatches(value, workspace, query = '', state = 'all', selectedPage) {
69
+ return !!value && value.workspace_id === workspace && value.query === query.trim() && value.state_filter === state
70
+ && Number.isSafeInteger(value.page) && value.page >= 1 && (!selectedPage || value.page === selectedPage)
71
+ && Number.isSafeInteger(value.count) && value.count >= 0 && Number.isSafeInteger(value.page_size) && value.page_size >= 1 && value.page_size <= 100
72
+ && value.results.length <= value.page_size && value.results.every(row => toolInstanceMatches(row, workspace) && row.details_included === false
73
+ && (state === 'removed' ? !!row.removal?.completed_at : !row.removal?.completed_at)
74
+ && (state === 'active' ? !row.terminal_at : state === 'closed' ? !!row.terminal_at : true))
75
+ && value.setup.default_duration_seconds >= 60 && value.setup.default_duration_seconds <= value.setup.maximum_duration_seconds
76
+ && Number.isSafeInteger(value.setup.maximum_tools) && value.setup.maximum_tools >= 1;
77
+ }
78
+ export async function toolStartReceiptMatches(value, scope, key, input) {
79
+ if (!toolInstanceDetailMatches(value, scope.workspace, { key, actor: scope.actor }) || value.implementation_id !== input.implementation_id
80
+ || value.dataset_id !== input.dataset_id)
81
+ return false;
82
+ // The server retains a digest, not a guessed duration derived from timestamps.
83
+ // These fixed keys are Python canonical_digest's sorted original input shape.
84
+ const original = JSON.stringify({ checkpoint_id: null, dataset_id: input.dataset_id, duration_seconds: input.duration_seconds,
85
+ generation_kind: '', implementation_id: input.implementation_id, parent_instance_id: null, usage_quote_id: input.usage_quote_id });
86
+ const bytes = await globalThis.crypto.subtle.digest('SHA-256', new TextEncoder().encode(original));
87
+ return value.request_digest === Array.from(new Uint8Array(bytes), one => one.toString(16).padStart(2, '0')).join('');
88
+ }
89
+ export function toolRemovalMatches(value, scope, selected = {}) {
90
+ return !!value && value.workspace_id === scope.workspace && [value.id, value.workspace_id, value.actor_id, value.instance_id, value.request_key].every(one => uuid.test(one))
91
+ && (!selected.instance || value.instance_id === selected.instance) && (!selected.id || value.id === selected.id)
92
+ && (!selected.key || value.request_key === selected.key && value.actor_id === scope.actor)
93
+ && value.retains_saved_data === true && (value.completed_at ? value.state === 'removed' : value.state === 'removing');
94
+ }
@@ -0,0 +1,91 @@
1
+ import { toolProtocolMetadataMatches } from './tool-protocol-contracts.js';
2
+ const uuid = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/;
3
+ const digest = /^[a-f0-9]{64}$/;
4
+ const serviceKey = /^[a-z][a-z0-9_-]{0,79}$/;
5
+ const operationName = /^[A-Za-z][A-Za-z0-9_.-]{0,127}$/;
6
+ export function packageRead(value, matches) {
7
+ if (!matches)
8
+ throw new Error('The tool package response did not match this selection. Inspect the original version or request.');
9
+ return value;
10
+ }
11
+ function page(value, selected) {
12
+ return Number.isSafeInteger(value.page) && value.page >= 1 && (!selected || value.page === selected)
13
+ && Number.isSafeInteger(value.page_size) && value.page_size >= 1 && value.page_size <= 100
14
+ && Number.isSafeInteger(value.count) && value.count >= 0 && value.results.length <= value.page_size;
15
+ }
16
+ export function toolVersionMatches(value, workspace, id) {
17
+ return !!value && uuid.test(workspace) && value.workspace_id === workspace && [value.id, value.tool_id].every(one => uuid.test(one))
18
+ && (!id || value.id === id) && ['inspected', 'revoked', 'unavailable'].includes(value.state) && value.runtime_started === false
19
+ && digest.test(value.archive_sha256) && digest.test(value.contract_digest)
20
+ && [value.service_count, value.operation_count].every(one => one === null || Number.isSafeInteger(one) && one >= 1)
21
+ && value.interfaces.every(one => one === 'http' || one === 'mcp');
22
+ }
23
+ export function toolVersionPageMatches(value, workspace, selected = {}) {
24
+ return !!value && value.workspace_id === workspace && value.query === (selected.query ?? '').trim()
25
+ && value.state_filter === (selected.state ?? 'inspected') && value.single_service === (selected.single ?? false) && page(value, selected.page)
26
+ && value.results.every(row => toolVersionMatches(row, workspace) && (value.state_filter === 'all'
27
+ || row.state === value.state_filter || value.state_filter === 'inspected' && row.state === 'unavailable'))
28
+ && Number.isSafeInteger(value.package_capacity.upload_bytes) && value.package_capacity.upload_bytes >= 1
29
+ && Number.isSafeInteger(value.package_capacity.contract_bytes) && value.package_capacity.contract_bytes >= 1;
30
+ }
31
+ function selection(value, version) {
32
+ return value.workspace_id === version.workspace_id && value.implementation_id === version.id && value.contract_digest === version.contract_digest;
33
+ }
34
+ export function toolServiceMatches(value, version, key) {
35
+ return !!value && selection(value, version) && serviceKey.test(key) && value.id === key && value.key === key;
36
+ }
37
+ export function toolServicesMatch(value, version, query = '', selectedPage) {
38
+ return !!value && selection(value, version) && value.query === query.trim() && page(value, selectedPage)
39
+ && value.results.every(row => row.id === row.key && serviceKey.test(row.key) && Number.isSafeInteger(row.operation_count) && row.operation_count >= 1);
40
+ }
41
+ export function toolOperationsMatch(value, version, service, query = '', selectedPage) {
42
+ return !!value && selection(value, version) && serviceKey.test(service) && value.service_key === service
43
+ && value.query === query.trim() && page(value, selectedPage) && value.results.every(row => operationName.test(row.name)
44
+ && toolProtocolMetadataMatches(row)
45
+ && ['http', 'mcp'].includes(row.transport.kind) && ['none', 'read', 'write', 'mixed'].includes(row.effect));
46
+ }
47
+ export function toolOperationMatches(value, version, service, name) {
48
+ return !!value && selection(value, version) && serviceKey.test(service) && value.service_key === service && value.name === name
49
+ && operationName.test(name) && !!value.input_schema && (value.output_schema !== null
50
+ || value.transport.kind === 'http' && value.transport.response_encoding !== undefined && value.transport.response_encoding !== 'json')
51
+ && toolProtocolMetadataMatches(value);
52
+ }
53
+ export function toolPackageMatches(value, scope, selected = {}) {
54
+ const input = selected.input;
55
+ return !!value && value.workspace_id === scope.workspace && value.actor_id === scope.actor
56
+ && [scope.workspace, scope.actor, value.id, value.request_key].every(one => uuid.test(one))
57
+ && (!selected.key || value.request_key === selected.key) && (!selected.id || value.id === selected.id)
58
+ && (!input || value.filename === input.filename && value.size === input.size && value.sha256 === input.sha256)
59
+ && Number.isSafeInteger(value.size) && value.size >= 1 && digest.test(value.sha256)
60
+ && ['uploading', 'inspecting', 'inspected', 'rejected', 'withdrawn'].includes(value.state)
61
+ && (value.implementation_id === null || uuid.test(value.implementation_id))
62
+ && (value.state !== 'inspected' || value.implementation_id !== null && value.finished_at !== null)
63
+ && (value.catalog_setup_id === null && value.catalog_setup_request_key === null
64
+ || !!value.catalog_setup_id && !!value.catalog_setup_request_key && uuid.test(value.catalog_setup_id) && uuid.test(value.catalog_setup_request_key))
65
+ && (!value.can_upload || value.state === 'uploading' && !value.withdrawn_at && !value.catalog_setup_id)
66
+ && (!value.can_withdraw || ['uploading', 'inspecting'].includes(value.state) && !value.finished_at && !value.withdrawn_at);
67
+ }
68
+ export function toolPackagePageMatches(value, scope, query = '', state = 'all', selectedPage) {
69
+ return !!value && value.workspace_id === scope.workspace && value.actor_id === scope.actor && value.query === query.trim()
70
+ && value.state_filter === state && page(value, selectedPage)
71
+ && value.results.every(row => toolPackageMatches(row, scope) && (state === 'all' || row.state === state));
72
+ }
73
+ export function toolPackageUploadDestination(value, scope, request) {
74
+ let url;
75
+ try {
76
+ url = new URL(value.upload_url);
77
+ }
78
+ catch {
79
+ throw new Error('Package upload access could not be confirmed.');
80
+ }
81
+ const parts = url.pathname.split('/');
82
+ packageRead(value, toolPackageMatches(request, scope) && request.can_upload
83
+ && value.workspace_id === scope.workspace && value.actor_id === scope.actor && value.id === request.id
84
+ && value.request_key === request.request_key && value.size === request.size && value.sha256 === request.sha256
85
+ && url.origin === 'https://storage.googleapis.com' && !url.username && !url.password && !url.hash && value.method === 'PUT'
86
+ && parts.length === 7 && !!parts[1] && parts[2] === 'private' && uuid.test(parts[3] ?? '') && parts[4] === scope.workspace
87
+ && parts[5] === 'tool-uploads' && parts[6] === `${request.id}.zip`
88
+ && Object.keys(value.headers).sort().join(',') === 'Content-Type,x-goog-if-generation-match'
89
+ && value.headers['Content-Type'] === 'application/zip' && value.headers['x-goog-if-generation-match'] === '0');
90
+ return url;
91
+ }
@@ -0,0 +1,71 @@
1
+ const names = /^[A-Za-z_][A-Za-z0-9_.-]{0,127}$/;
2
+ const field = /^[A-Za-z_][A-Za-z0-9_]{0,79}$/;
3
+ const headers = new Set(['notion-version', 'stripe-version', 'stripe-account', 'x-goog-api-client']);
4
+ export function toolProtocolMetadataMatches(value) {
5
+ if (!value || !value.transport || typeof value.transport !== 'object' || Array.isArray(value.transport)
6
+ || !['http', 'mcp'].includes(value.transport.kind))
7
+ return false;
8
+ if (value.mcp_aliases !== undefined && (!Array.isArray(value.mcp_aliases) || value.mcp_aliases.length > 16
9
+ || value.mcp_aliases.some(name => typeof name !== 'string' || !names.test(name))
10
+ || new Set(value.mcp_aliases).size !== value.mcp_aliases.length))
11
+ return false;
12
+ if (value.transport.kind !== 'http')
13
+ return value.transport.idempotency === undefined && value.transport.ignored_headers === undefined
14
+ && value.transport.content_type_argument === undefined && value.transport.parts === undefined;
15
+ const metadata = value.transport;
16
+ if (metadata.content_type_argument !== undefined && (typeof metadata.content_type_argument !== 'string'
17
+ || !field.test(metadata.content_type_argument) || !['text', 'base64'].includes(String(metadata.encoding))
18
+ || metadata.content_type_argument === metadata.body))
19
+ return false;
20
+ if (metadata.idempotency !== undefined) {
21
+ if (!metadata.idempotency || typeof metadata.idempotency !== 'object' || Array.isArray(metadata.idempotency))
22
+ return false;
23
+ const mapping = metadata.idempotency;
24
+ if (Object.keys(mapping).sort().join(',') !== 'argument,header' || mapping.header !== 'Idempotency-Key'
25
+ || typeof mapping.argument !== 'string' || !field.test(mapping.argument))
26
+ return false;
27
+ }
28
+ if (metadata.encoding === 'multipart' || metadata.parts !== undefined) {
29
+ if (metadata.encoding !== 'multipart' || !metadata.parts || typeof metadata.parts !== 'object' || Array.isArray(metadata.parts)
30
+ || metadata.body !== undefined || metadata.content_type !== undefined || metadata.content_type_argument !== undefined)
31
+ return false;
32
+ const parts = Object.entries(metadata.parts), argumentsUsed = new Set();
33
+ if (parts.length < 1 || parts.length > 100)
34
+ return false;
35
+ for (const [name, descriptor] of parts) {
36
+ if (!/^[A-Za-z_][A-Za-z0-9_.-]{0,99}$/.test(name) || !descriptor || typeof descriptor !== 'object' || Array.isArray(descriptor))
37
+ return false;
38
+ const part = descriptor;
39
+ if (Object.keys(part).some(key => !['argument', 'encoding', 'filename_argument', 'content_type_argument', 'content_type'].includes(key))
40
+ || !['text', 'json', 'base64'].includes(String(part.encoding)) || typeof part.argument !== 'string' || !field.test(part.argument)
41
+ || part.encoding !== 'base64' && ['filename_argument', 'content_type_argument', 'content_type'].some(key => key in part))
42
+ return false;
43
+ for (const key of ['argument', 'filename_argument', 'content_type_argument']) {
44
+ if (!(key in part))
45
+ continue;
46
+ const argument = part[key];
47
+ if (typeof argument !== 'string' || !field.test(argument) || argumentsUsed.has(argument))
48
+ return false;
49
+ argumentsUsed.add(argument);
50
+ }
51
+ if (part.content_type !== undefined && (typeof part.content_type !== 'string' || part.content_type.length > 128
52
+ || !/^[A-Za-z0-9!#$&^_.+-]+\/[A-Za-z0-9!#$&^_.+-]+(?:;\s*charset=utf-8)?$/i.test(part.content_type)))
53
+ return false;
54
+ }
55
+ const idempotency = metadata.idempotency;
56
+ if (idempotency && argumentsUsed.has(idempotency.argument))
57
+ return false;
58
+ }
59
+ if (metadata.ignored_headers !== undefined && (!Array.isArray(metadata.ignored_headers) || metadata.ignored_headers.length > 4
60
+ || metadata.ignored_headers.some(name => typeof name !== 'string' || !headers.has(name.toLowerCase()))
61
+ || new Set(metadata.ignored_headers.map(name => String(name).toLowerCase())).size !== metadata.ignored_headers.length))
62
+ return false;
63
+ if (Array.isArray(metadata.ignored_headers) && metadata.headers !== undefined) {
64
+ if (!metadata.headers || typeof metadata.headers !== 'object' || Array.isArray(metadata.headers))
65
+ return false;
66
+ const mapped = new Set(Object.keys(metadata.headers).map(name => name.toLowerCase()));
67
+ if (metadata.ignored_headers.some(name => mapped.has(String(name).toLowerCase())))
68
+ return false;
69
+ }
70
+ return true;
71
+ }
@@ -0,0 +1,28 @@
1
+ const id = /^[a-f0-9]{8}(?:-[a-f0-9]{4}){3}-[a-f0-9]{12}$/, digest = /^[a-f0-9]{64}$/;
2
+ export function toolAllocationQuoteMatches(value, workspace, selected) {
3
+ const scope = value?.scope, source = scope?.source;
4
+ return !!value && value.workspace_id === workspace && id.test(value.id) && value.activity === 'tool_runtime' && value.execution_location === 'managed'
5
+ && digest.test(value.scope_digest) && digest.test(value.tariff_digest) && typeof value.tariff_version === 'string' && value.tariff_version.length > 0
6
+ && Number.isSafeInteger(value.credit_scale) && value.credit_scale > 0 && /^10*$/.test(String(value.credit_scale))
7
+ && typeof value.denomination === 'string' && /^[a-zA-Z0-9][a-zA-Z0-9_.:-]{0,31}$/.test(value.denomination)
8
+ && Number.isSafeInteger(value.estimated_units) && value.estimated_units >= 0
9
+ && Number.isSafeInteger(value.maximum_units) && value.maximum_units >= value.estimated_units && Number.isFinite(Date.parse(value.expires_at))
10
+ && scope?.schema === 'firedrill.tool-runtime-budget.v1' && scope.launch_request_key === selected.launch_request_key
11
+ && scope.duration_seconds === selected.duration_seconds && source?.id === (selected.release_id ?? selected.implementation_id)
12
+ && source.kind === (selected.release_id ? 'catalog' : 'version') && [source.digest, source.contract_digest].every(one => digest.test(one)) && /^sha256:[a-f0-9]{64}$/.test(source.bundle_digest)
13
+ && (scope.dataset?.id ?? null) === selected.dataset_id
14
+ && (selected.restore === null ? scope.restore === null : !!scope.restore && scope.restore.instance_id === selected.restore.instance_id
15
+ && (selected.restore.checkpoint_id === null ? id.test(scope.restore.checkpoint_id) : scope.restore.checkpoint_id === selected.restore.checkpoint_id) && scope.restore.action === selected.restore.action)
16
+ && !!scope.resources && Object.values(scope.resources).every(one => Number.isSafeInteger(one) && one > 0);
17
+ }
18
+ export function allocationCredits(value, kind = 'maximum') {
19
+ const units = kind === 'estimated' ? value.estimated_units : value.maximum_units;
20
+ if (!Number.isSafeInteger(units) || units < 0 || !Number.isSafeInteger(value.credit_scale) || value.credit_scale < 1
21
+ || !/^10*$/.test(String(value.credit_scale)))
22
+ return 'Not available';
23
+ const exact = BigInt(units), scale = BigInt(value.credit_scale);
24
+ const whole = new Intl.NumberFormat(undefined, { maximumFractionDigits: 0 }).format(exact / scale);
25
+ const fraction = (exact % scale).toString().padStart(scale.toString().length - 1, '0').replace(/0+$/, '');
26
+ const separator = new Intl.NumberFormat().formatToParts(1.1).find(one => one.type === 'decimal')?.value ?? '.';
27
+ return whole + (fraction ? separator + fraction : '');
28
+ }