deepline 0.3.89 → 0.3.91

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 (267) hide show
  1. package/contracts/install-commands.json +29 -0
  2. package/dist/bundling-sources/sdk/src/client.ts +221 -43
  3. package/dist/bundling-sources/sdk/src/index.ts +4 -0
  4. package/dist/bundling-sources/sdk/src/monitor-fleet-contract.ts +2 -556
  5. package/dist/bundling-sources/sdk/src/monitor-fleets.ts +2 -2
  6. package/dist/bundling-sources/sdk/src/pagination.ts +25 -0
  7. package/dist/bundling-sources/sdk/src/plays/bundle-play-file.ts +1 -1
  8. package/dist/bundling-sources/sdk/src/release.ts +11 -9
  9. package/dist/bundling-sources/sdk/src/types.ts +29 -1
  10. package/dist/bundling-sources/shared_libs/integration-contracts/monitor-fleet-contract.ts +549 -0
  11. package/dist/bundling-sources/shared_libs/monitors/analytics-public.ts +10 -0
  12. package/dist/bundling-sources/shared_libs/monitors/fleets/errors.ts +96 -0
  13. package/dist/bundling-sources/shared_libs/monitors/fleets/limits.ts +8 -0
  14. package/dist/bundling-sources/shared_libs/monitors/fleets/plan.ts +320 -0
  15. package/dist/bundling-sources/shared_libs/monitors/fleets/verdict.ts +106 -0
  16. package/dist/bundling-sources/shared_libs/monitors/http-error-response.ts +8 -1
  17. package/dist/bundling-sources/shared_libs/monitors/inbound-queue.ts +4 -4
  18. package/dist/bundling-sources/shared_libs/monitors/inventory-reconciliation.ts +59 -0
  19. package/dist/bundling-sources/shared_libs/monitors/lifecycle-notifications.ts +7 -9
  20. package/dist/bundling-sources/shared_libs/monitors/monitor-fleet-limits.ts +2 -12
  21. package/dist/bundling-sources/shared_libs/monitors/package.json +113 -4
  22. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-batch-operation.ts +56 -9
  23. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-consumer-health.ts +2 -2
  24. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-identity-claims.ts +2 -2
  25. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-public-aliases.ts +1 -1
  26. package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-dead-letter.ts +245 -0
  27. package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-message.ts +38 -0
  28. package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-queue-ack-probe.ts +94 -0
  29. package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-queue-delivery.ts +60 -0
  30. package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-queue.ts +60 -0
  31. package/dist/bundling-sources/shared_libs/monitors/snitcher-install-validation.ts +1 -1
  32. package/dist/bundling-sources/shared_libs/monitors/snitcher-ip2company.ts +2 -2
  33. package/dist/bundling-sources/shared_libs/monitors/snitcher-radar.ts +1 -1
  34. package/dist/bundling-sources/shared_libs/monitors/tracking-provider-integrations.ts +1 -1
  35. package/dist/bundling-sources/shared_libs/observability/build-context.ts +13 -0
  36. package/dist/bundling-sources/shared_libs/observability/log-metadata.ts +160 -0
  37. package/dist/bundling-sources/shared_libs/observability/request-context.ts +68 -0
  38. package/dist/bundling-sources/shared_libs/observability/scheduled-jobs.json +690 -0
  39. package/dist/bundling-sources/shared_libs/observability/scheduled-work-manual.ts +35 -0
  40. package/dist/bundling-sources/shared_libs/observability/scheduled-work.ts +5 -0
  41. package/dist/bundling-sources/shared_libs/play-data-plane/neon-constants.ts +9 -0
  42. package/dist/bundling-sources/shared_libs/play-data-plane/r2.ts +272 -0
  43. package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +46 -1
  44. package/dist/bundling-sources/shared_libs/play-runtime/async-operation.ts +66 -1
  45. package/dist/bundling-sources/shared_libs/play-runtime/async-play-invocation.ts +0 -1
  46. package/dist/bundling-sources/shared_libs/play-runtime/bounceban-batching.ts +137 -0
  47. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +779 -140
  48. package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +46 -0
  49. package/dist/bundling-sources/shared_libs/play-runtime/daytona-payload-contract.ts +68 -0
  50. package/dist/bundling-sources/shared_libs/play-runtime/daytona-sandbox-janitor.ts +103 -0
  51. package/dist/bundling-sources/shared_libs/play-runtime/daytona-sandbox-reaper.ts +725 -0
  52. package/dist/bundling-sources/shared_libs/play-runtime/db-session-lease-store.ts +578 -0
  53. package/dist/bundling-sources/shared_libs/play-runtime/deployment/commands/roll-execution-relay.ts +521 -0
  54. package/dist/bundling-sources/shared_libs/play-runtime/deployment/commands/roll-receipt-gateway.ts +1378 -0
  55. package/dist/bundling-sources/shared_libs/play-runtime/deployment/commands/runtime-topology.ts +1024 -0
  56. package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-gateway-route-probe.ts +193 -0
  57. package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-machine-lifecycle.ts +104 -0
  58. package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-machines.ts +1844 -0
  59. package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-registry.ts +21 -0
  60. package/dist/bundling-sources/shared_libs/play-runtime/deployment/process-tree.ts +40 -0
  61. package/dist/bundling-sources/shared_libs/play-runtime/deployment/runtime-gateway-drain.ts +262 -0
  62. package/dist/bundling-sources/shared_libs/play-runtime/deployment/runtime-surface.ts +98 -0
  63. package/dist/bundling-sources/shared_libs/play-runtime/deployment/runtime-topology.ts +303 -0
  64. package/dist/bundling-sources/shared_libs/play-runtime/deployment/runtime-tuple-publication-guardian.ts +70 -0
  65. package/dist/bundling-sources/shared_libs/play-runtime/deployment/runtime-tuple-recovery.ts +519 -0
  66. package/dist/bundling-sources/shared_libs/play-runtime/deployment/vercel-fly-rollback-alignment.ts +280 -0
  67. package/dist/bundling-sources/shared_libs/play-runtime/deployment/vercel-production-gate.ts +159 -0
  68. package/dist/bundling-sources/shared_libs/play-runtime/durable-call-cache.ts +29 -0
  69. package/dist/bundling-sources/shared_libs/play-runtime/execution-capabilities.ts +23 -0
  70. package/dist/bundling-sources/shared_libs/play-runtime/execution-gateway-invocation-fence.ts +442 -0
  71. package/dist/bundling-sources/shared_libs/play-runtime/execution-protocol.ts +3 -3
  72. package/dist/bundling-sources/shared_libs/play-runtime/fixture-behavior.ts +18 -0
  73. package/dist/bundling-sources/shared_libs/play-runtime/governor/app-runtime-rate-state-backend.ts +9 -0
  74. package/dist/bundling-sources/shared_libs/play-runtime/governor/policy.ts +1 -1
  75. package/dist/bundling-sources/shared_libs/play-runtime/governor/rate-state-backend.ts +1 -1
  76. package/dist/bundling-sources/shared_libs/play-runtime/integration-operation-reader-fence/contracts.ts +66 -0
  77. package/dist/bundling-sources/shared_libs/play-runtime/integration-operation-reader-fence/job.ts +145 -0
  78. package/dist/bundling-sources/shared_libs/play-runtime/integration-operation-reader-fence/memory-store.ts +114 -0
  79. package/dist/bundling-sources/shared_libs/play-runtime/integration-operation-reader-fence/ports.ts +21 -0
  80. package/dist/bundling-sources/shared_libs/play-runtime/integration-operation-reader-fence/postgres-store.ts +170 -0
  81. package/dist/bundling-sources/shared_libs/play-runtime/internal-bootstrap-token.ts +1322 -0
  82. package/dist/bundling-sources/shared_libs/play-runtime/internal-step-ids.ts +2 -2
  83. package/dist/bundling-sources/shared_libs/play-runtime/lane-retirement-gate.ts +1 -1
  84. package/dist/bundling-sources/shared_libs/play-runtime/launch-source-policy.ts +112 -0
  85. package/dist/bundling-sources/shared_libs/play-runtime/map-execution-frame.ts +8 -0
  86. package/dist/bundling-sources/shared_libs/play-runtime/perf-trace.ts +127 -0
  87. package/dist/bundling-sources/shared_libs/play-runtime/play-artifact-runtime-contract.ts +5 -0
  88. package/dist/bundling-sources/shared_libs/play-runtime/play-run-recovery-policy.ts +24 -1
  89. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/admission/contracts.ts +56 -0
  90. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/admission/index.ts +13 -0
  91. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/admission/job.ts +41 -0
  92. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/admission/ports.ts +17 -0
  93. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/admission/postgres-adapter.ts +54 -0
  94. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/contracts.ts +114 -0
  95. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/engine-suspension.ts +108 -0
  96. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/index.ts +36 -0
  97. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/job.ts +97 -0
  98. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/ports.ts +104 -0
  99. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/postgres-fence-adapter.ts +263 -0
  100. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/attempts/worker-terminal-projection.ts +64 -0
  101. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/projection/contracts.ts +29 -0
  102. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/projection/gateway-adapter.ts +56 -0
  103. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/projection/index.ts +15 -0
  104. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/projection/job.ts +65 -0
  105. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/projection/ports.ts +17 -0
  106. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/contracts.ts +42 -0
  107. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/index.ts +17 -0
  108. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/job.ts +142 -0
  109. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/ports.ts +42 -0
  110. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/postgres-adapter.ts +102 -0
  111. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/contracts.ts +60 -0
  112. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/index.ts +16 -0
  113. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/job.ts +78 -0
  114. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/ports.ts +54 -0
  115. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/postgres-adapter.ts +71 -0
  116. package/dist/bundling-sources/shared_libs/play-runtime/play-runtime-batching-registry.ts +4 -0
  117. package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +2 -0
  118. package/dist/bundling-sources/shared_libs/play-runtime/receipt-status.ts +5 -8
  119. package/dist/bundling-sources/shared_libs/play-runtime/run-failure.ts +3 -5
  120. package/dist/bundling-sources/shared_libs/play-runtime/run-identity.ts +168 -0
  121. package/dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts +44 -5
  122. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/child-play-resolver.ts +26 -0
  123. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +3662 -0
  124. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/progress-sidecar.ts +47 -0
  125. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-deadline.ts +84 -0
  126. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-gateway-transport.ts +91 -0
  127. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-heartbeat.ts +424 -0
  128. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-progress-push.ts +321 -0
  129. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-sheet-persistence-retry.ts +110 -0
  130. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-terminal-push.ts +625 -0
  131. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-lifecycle.ts +72 -9
  132. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-payload-transport.ts +6 -12
  133. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +19 -0
  134. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/bundle.ts +0 -1
  135. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/runtime-sandbox-reconciliation.ts +14 -44
  136. package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +103 -208
  137. package/dist/bundling-sources/shared_libs/play-runtime/runtime-authority.ts +201 -0
  138. package/dist/bundling-sources/shared_libs/play-runtime/runtime-env.ts +6 -0
  139. package/dist/bundling-sources/shared_libs/play-runtime/runtime-operation-contract.ts +67 -0
  140. package/dist/bundling-sources/shared_libs/play-runtime/runtime-release-environment.ts +2 -0
  141. package/dist/bundling-sources/shared_libs/play-runtime/runtime-sandbox-contract.ts +68 -0
  142. package/dist/bundling-sources/shared_libs/play-runtime/runtime-scheduler-topology.ts +14 -2
  143. package/dist/bundling-sources/shared_libs/play-runtime/runtime-telemetry.ts +108 -0
  144. package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/contract.ts +4 -0
  145. package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/runner-backend-adapter.ts +3 -0
  146. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backend.ts +7 -0
  147. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-deadline-reconciliation.ts +88 -0
  148. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-play-deploy-task.ts +124 -0
  149. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-play-run-task.ts +68 -0
  150. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-pool.ts +193 -0
  151. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-queue-lifecycle.ts +269 -0
  152. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-queue-suffix.ts +73 -0
  153. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +6642 -0
  154. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-shared.ts +897 -0
  155. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-worker-metrics.ts +120 -0
  156. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-worker-required-env.ts +76 -0
  157. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd.ts +476 -0
  158. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/gateway-heavy-request-admission.ts +47 -0
  159. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/gateway-progress-registry.ts +147 -0
  160. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/index.ts +27 -0
  161. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/lazy.ts +50 -0
  162. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/play-run-recovery.ts +98 -0
  163. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-budget-state.ts +260 -0
  164. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-pool.ts +1416 -0
  165. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-progress.ts +1255 -0
  166. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-rate-state.ts +942 -0
  167. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +14636 -0
  168. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/receipt-gateway.ts +888 -0
  169. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-outbox-recovery.ts +355 -0
  170. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-terminal-transition.ts +46 -0
  171. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runner-push.ts +60 -0
  172. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-api-origin.ts +33 -0
  173. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-receipt-gateway-health.ts +64 -0
  174. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-capacity.ts +835 -0
  175. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-ledger-reconciliation.ts +1218 -0
  176. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-operation.ts +207 -0
  177. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-scheduler-schema.ts +10 -0
  178. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/scheduler-capacity.ts +123 -0
  179. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/scheduler-launch-read-observability.ts +78 -0
  180. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/submit-admission.ts +169 -0
  181. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/terminal-contract.ts +20 -0
  182. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/worker-queue-metrics.ts +34 -0
  183. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/worker-resource-metrics.ts +249 -0
  184. package/dist/bundling-sources/shared_libs/play-runtime/sheet-attempt-sql.ts +7 -0
  185. package/dist/bundling-sources/shared_libs/play-runtime/step-progress.ts +296 -0
  186. package/dist/bundling-sources/shared_libs/play-runtime/tool-call/native-batch.ts +3 -3
  187. package/dist/bundling-sources/shared_libs/play-runtime/tool-call/runtime-step-receipts-adapter.ts +20 -1
  188. package/dist/bundling-sources/shared_libs/play-runtime/tool-execute-retry-policy.ts +60 -15
  189. package/dist/bundling-sources/shared_libs/play-runtime/tool-execution-outcome.ts +20 -0
  190. package/dist/bundling-sources/shared_libs/play-runtime/transient-service-error.ts +12 -0
  191. package/dist/bundling-sources/shared_libs/play-runtime/vercel-protection.ts +14 -1
  192. package/dist/bundling-sources/shared_libs/play-runtime/webhook-receipt-retry.ts +50 -0
  193. package/dist/bundling-sources/shared_libs/play-runtime/work-receipt-storage-contract.ts +165 -0
  194. package/dist/bundling-sources/shared_libs/play-runtime/work-receipts.ts +15 -23
  195. package/dist/bundling-sources/shared_libs/play-runtime/workflow-executor-auth.ts +169 -0
  196. package/dist/bundling-sources/shared_libs/play-runtime/zerobounce-batching.ts +122 -0
  197. package/dist/bundling-sources/shared_libs/plays/artifact-types.ts +2 -0
  198. package/dist/bundling-sources/shared_libs/plays/bundling/repository-adapter.ts +24 -0
  199. package/dist/bundling-sources/shared_libs/plays/child-run-projection.ts +174 -0
  200. package/dist/bundling-sources/shared_libs/plays/contracts.ts +2 -0
  201. package/dist/bundling-sources/shared_libs/plays/deploy/api-client.ts +267 -0
  202. package/dist/bundling-sources/shared_libs/plays/deploy/control-plane-types.ts +73 -0
  203. package/dist/bundling-sources/shared_libs/plays/deploy/manifest.ts +162 -0
  204. package/dist/bundling-sources/shared_libs/plays/deploy/project-serializer.ts +87 -0
  205. package/dist/bundling-sources/shared_libs/plays/deploy/source-file-path.ts +26 -0
  206. package/dist/bundling-sources/shared_libs/plays/deploy/target-paths.ts +36 -0
  207. package/dist/bundling-sources/shared_libs/plays/deployment-status.ts +1 -1
  208. package/dist/bundling-sources/shared_libs/plays/docflow.ts +1 -1
  209. package/dist/bundling-sources/shared_libs/plays/launch/input-contract.ts +400 -0
  210. package/dist/bundling-sources/shared_libs/plays/launch/prepare.ts +96 -0
  211. package/dist/bundling-sources/shared_libs/plays/local-file-discovery.ts +385 -0
  212. package/dist/bundling-sources/shared_libs/plays/play-grep-search.ts +112 -0
  213. package/dist/bundling-sources/shared_libs/plays/play-reference.ts +117 -0
  214. package/dist/bundling-sources/shared_libs/plays/run-input-summary.ts +260 -0
  215. package/dist/bundling-sources/shared_libs/plays/run-summary-types.ts +49 -0
  216. package/dist/bundling-sources/shared_libs/plays/secrets/errors.ts +19 -0
  217. package/dist/bundling-sources/shared_libs/plays/share/copy.ts +271 -0
  218. package/dist/bundling-sources/shared_libs/plays/share/metrics.ts +140 -0
  219. package/dist/bundling-sources/shared_libs/plays/share/public-read-model.ts +86 -0
  220. package/dist/bundling-sources/shared_libs/plays/share/seo-quality.ts +181 -0
  221. package/dist/bundling-sources/shared_libs/plays/share/static-pipeline-summary.ts +658 -0
  222. package/dist/bundling-sources/shared_libs/plays/share/types.ts +197 -0
  223. package/dist/bundling-sources/shared_libs/plays/sheet-filter.ts +347 -0
  224. package/dist/bundling-sources/shared_libs/plays/slack-hitl-timeout-error.ts +37 -0
  225. package/dist/bundling-sources/shared_libs/plays/standard-webhooks.ts +117 -0
  226. package/dist/bundling-sources/shared_libs/plays/static-pipeline.ts +6 -1
  227. package/dist/bundling-sources/shared_libs/plays/status-result.ts +388 -0
  228. package/dist/bundling-sources/shared_libs/plays/tool-result-types.ts +1 -1
  229. package/dist/bundling-sources/shared_libs/plays/transform-factor-structure.ts +377 -0
  230. package/dist/bundling-sources/shared_libs/plays/webhook-payload.ts +113 -0
  231. package/dist/bundling-sources/shared_libs/product-notifications/configuration.ts +7 -1
  232. package/dist/bundling-sources/shared_libs/product-notifications/default-policy.ts +3 -2
  233. package/dist/bundling-sources/shared_libs/product-notifications/overflow.ts +18 -0
  234. package/dist/bundling-sources/shared_libs/product-notifications/rolling-limit.ts +24 -0
  235. package/dist/bundling-sources/shared_libs/product-notifications/slack-delivery.ts +624 -0
  236. package/dist/bundling-sources/shared_libs/product-notifications/slack-payload.ts +140 -0
  237. package/dist/bundling-sources/shared_libs/product-notifications/slack-transport.ts +75 -0
  238. package/dist/bundling-sources/shared_libs/runtime-env.ts +6 -0
  239. package/dist/bundling-sources/shared_libs/security/email-blacklist.ts +42 -0
  240. package/dist/bundling-sources/shared_libs/security/header-safe-env.ts +10 -3
  241. package/dist/bundling-sources/shared_libs/security/slack-sanitize.ts +133 -0
  242. package/dist/cli/getting-started.d.mts +52 -0
  243. package/dist/cli/getting-started.d.ts +52 -0
  244. package/dist/cli/getting-started.js +65 -0
  245. package/dist/cli/getting-started.mjs +36 -0
  246. package/dist/cli/index.d.mts +9 -0
  247. package/dist/cli/index.d.ts +9 -0
  248. package/dist/cli/index.js +895 -407
  249. package/dist/cli/index.mjs +893 -414
  250. package/dist/{compiler-manifest-DsLbQaew.d.mts → compiler-manifest-x14KL83E.d.mts} +4 -2
  251. package/dist/{compiler-manifest-DsLbQaew.d.ts → compiler-manifest-x14KL83E.d.ts} +4 -2
  252. package/dist/index.d.mts +124 -154
  253. package/dist/index.d.ts +124 -154
  254. package/dist/index.js +132 -28
  255. package/dist/index.mjs +132 -28
  256. package/dist/install-integrity.json +182 -2
  257. package/dist/monitor-fleet-contract.d.mts +131 -0
  258. package/dist/monitor-fleet-contract.d.ts +131 -0
  259. package/dist/monitor-fleet-contract.js +406 -0
  260. package/dist/monitor-fleet-contract.mjs +367 -0
  261. package/dist/plays/bundle-play-file.d.mts +2 -2
  262. package/dist/plays/bundle-play-file.d.ts +2 -2
  263. package/dist/release.d.mts +255 -0
  264. package/dist/release.d.ts +255 -0
  265. package/dist/release.js +210 -0
  266. package/dist/release.mjs +183 -0
  267. package/package.json +21 -4
@@ -163,6 +163,26 @@ import { join as join24 } from "path";
163
163
  import { tmpdir as tmpdir6 } from "os";
164
164
  import { Command as Command5 } from "commander";
165
165
 
166
+ // src/pagination.ts
167
+ async function* iterateCursorPages(fetchPage) {
168
+ let cursor = null;
169
+ const seen = /* @__PURE__ */ new Set();
170
+ for (; ; ) {
171
+ const page = await fetchPage(cursor);
172
+ if (page.hasMore) {
173
+ if (!page.cursor || seen.has(page.cursor)) {
174
+ throw new Error(
175
+ "Pagination reported more results without an advancing cursor"
176
+ );
177
+ }
178
+ seen.add(page.cursor);
179
+ }
180
+ yield page.items;
181
+ if (!page.hasMore) return;
182
+ cursor = page.cursor;
183
+ }
184
+ }
185
+
166
186
  // src/config.ts
167
187
  import {
168
188
  existsSync,
@@ -1250,20 +1270,22 @@ var SDK_RELEASE = {
1250
1270
  // available at toolResponse.rawV2 while toolResponse.raw and all declared
1251
1271
  // getters keep their established compatibility behavior.
1252
1272
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
1253
- version: "0.3.89",
1254
- updateSummary: "Automatic CLI updates are now enabled by default. To opt out, run `deepline settings autoupdate off`; use `deepline settings autoupdate on` to re-enable updates or `deepline settings autoupdate pin <version>` to hold an exact release. This release also adds raw-v2 tool responses at toolResponse.rawV2 while preserving existing toolResponse.raw and declared getters.",
1273
+ // 0.3.90 is the first deliberately versioned SDK release for API v3.
1274
+ version: "0.3.91",
1275
+ updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.",
1255
1276
  packageCapabilities: {
1256
1277
  updatePreferences: 1
1257
1278
  },
1258
1279
  contracts: {
1259
1280
  api: {
1260
1281
  name: "sdk-http-api",
1261
- // API v2 is append-only. A breaking public request/response change needs
1262
- // v3 and an explicit v2 support-window decision, never a patch release.
1263
- currentMajor: 2,
1264
- supportedMajors: [2],
1265
- // Accepted only to bridge SDKs released before X-Deepline-API-Major.
1282
+ // Concise Play grep has the current wire id. Older ids follow the
1283
+ // standard API support window.
1284
+ currentMajor: 3,
1285
+ supportedMajors: [3, 2],
1286
+ // Older ids remain subject to the API support window.
1266
1287
  legacyWireIds: [
1288
+ "2026-09-play-grep-concise-results",
1267
1289
  "2026-07-admin-cli-local-cutover",
1268
1290
  "2026-07-native-monitor-launch-hard-cutover"
1269
1291
  ]
@@ -2512,6 +2534,10 @@ function normalizeProductNotificationEmail(value) {
2512
2534
  const email = typeof value === "string" ? value.trim().toLowerCase() : "";
2513
2535
  return email && email.length <= 320 && PRODUCT_NOTIFICATION_EMAIL_PATTERN.test(email) ? email : null;
2514
2536
  }
2537
+ var DEFAULT_PRODUCT_NOTIFICATION_DELIVERY_TIMING = {
2538
+ mode: "rolling_limit",
2539
+ windowMs: 36e5
2540
+ };
2515
2541
 
2516
2542
  // src/stream-reconnect.ts
2517
2543
  var STREAM_RECONNECT_BASE_DELAY_MS = 500;
@@ -5105,6 +5131,7 @@ var DeeplineClient = class {
5105
5131
  this.runs = {
5106
5132
  get: (runId, options2) => this.getRunStatus(runId, options2),
5107
5133
  list: (options2) => this.listRuns(options2),
5134
+ listPage: (options2) => this.listRunsPage(options2),
5108
5135
  tail: (runId, options2) => this.tailRun(runId, options2),
5109
5136
  logs: (runId, options2) => this.getRunLogs(runId, options2),
5110
5137
  input: (runId) => this.getRunInput(runId),
@@ -5130,9 +5157,19 @@ var DeeplineClient = class {
5130
5157
  targetStatus: () => this.getTargetBillingStatus(),
5131
5158
  autoRecharge: {
5132
5159
  get: () => this.getTargetAutoRecharge(),
5160
+ trigger: (options2) => this.http.post(
5161
+ "/api/v2/billing/auto-recharge/trigger",
5162
+ {},
5163
+ {
5164
+ "Idempotency-Key": requireTargetBillingIdempotencyKey(
5165
+ options2?.idempotencyKey ?? globalThis.crypto.randomUUID()
5166
+ )
5167
+ }
5168
+ ),
5133
5169
  update: (options2) => this.updateTargetAutoRecharge(options2)
5134
5170
  },
5135
5171
  purchaseCredits: (options2) => this.purchaseTargetBillingCredits(options2),
5172
+ recoverCreditPurchase: (options2) => this.recoverTargetBillingCreditPurchase(options2),
5136
5173
  transitionPlan: (options2) => this.transitionTargetBillingPlan(options2),
5137
5174
  portalSession: () => this.createTargetBillingPortalSession()
5138
5175
  };
@@ -5301,6 +5338,14 @@ var DeeplineClient = class {
5301
5338
  if (options.playName !== void 0) params.set("play", options.playName);
5302
5339
  return this.http.get(`/api/v2/secrets?${params.toString()}`);
5303
5340
  }
5341
+ /** Add, replace, or clear the non-sensitive note attached to one secret. */
5342
+ async updateSecretNote(secretId, note) {
5343
+ const response = await this.http.patch(
5344
+ `/api/v2/secrets/${encodeURIComponent(secretId)}`,
5345
+ { note }
5346
+ );
5347
+ return response.secret;
5348
+ }
5304
5349
  // ——————————————————————————————————————————————————————————
5305
5350
  // Tools
5306
5351
  // ——————————————————————————————————————————————————————————
@@ -6318,6 +6363,10 @@ var DeeplineClient = class {
6318
6363
  * ```
6319
6364
  */
6320
6365
  async listRuns(options) {
6366
+ return (await this.listRunsPage(options)).runs;
6367
+ }
6368
+ /** Read one run page without discarding server pagination metadata. */
6369
+ async listRunsPage(options) {
6321
6370
  const playName = options.play?.trim();
6322
6371
  const params = new URLSearchParams();
6323
6372
  if (playName) {
@@ -6348,7 +6397,7 @@ var DeeplineClient = class {
6348
6397
  const response = await this.http.get(
6349
6398
  `/api/v2/runs?${params.toString()}`
6350
6399
  );
6351
- return response.runs ?? [];
6400
+ return { ...response, runs: response.runs ?? [] };
6352
6401
  }
6353
6402
  /**
6354
6403
  * Observe one run's live events. Uses the Convex Run Snapshot subscription
@@ -6743,13 +6792,33 @@ var DeeplineClient = class {
6743
6792
  );
6744
6793
  }
6745
6794
  /**
6746
- * List callable plays visible to the workspace.
6795
+ * List one page of callable plays; grep retains exhaustive matching results.
6796
+ * Use listPlaysPage to retain pagination metadata.
6747
6797
  *
6748
6798
  * Pass `origin: "prebuilt"` for Deepline-managed prebuilts or
6749
6799
  * `origin: "owned"` for org-owned plays.
6750
6800
  */
6751
6801
  async listPlays(options) {
6802
+ if (!options?.grep?.trim()) {
6803
+ return (await this.requestPlaysPage(options, false)).plays;
6804
+ }
6805
+ const plays = [];
6806
+ for await (const items of iterateCursorPages(async (cursor) => {
6807
+ const page = await this.listPlaysPage({ ...options, cursor });
6808
+ return { items: page.plays, cursor: page.cursor, hasMore: page.hasMore };
6809
+ })) {
6810
+ plays.push(...items);
6811
+ }
6812
+ return plays;
6813
+ }
6814
+ /** Read one bounded inventory page; cursor continues the same filters. */
6815
+ async listPlaysPage(options) {
6816
+ return this.requestPlaysPage(options);
6817
+ }
6818
+ async requestPlaysPage(options, paginateInventory = true) {
6752
6819
  const params = new URLSearchParams();
6820
+ if (paginateInventory && !options?.grep?.trim())
6821
+ params.set("inventory_paginated", "1");
6753
6822
  if (options?.origin) params.set("origin", options.origin);
6754
6823
  if (options?.categories) {
6755
6824
  params.set(
@@ -6761,26 +6830,27 @@ var DeeplineClient = class {
6761
6830
  params.set("include_tool_categories", "1");
6762
6831
  }
6763
6832
  if (options?.includeArchived) params.set("include_archived", "1");
6833
+ if (options?.includeCostEstimates) {
6834
+ params.set("include_cost_estimates", "1");
6835
+ }
6764
6836
  if (options?.grep?.trim()) {
6765
6837
  params.set("grep", options.grep.trim());
6766
- params.set("grep_mode", options.grepMode ?? "all");
6767
- params.set("grep_paginated", "1");
6768
6838
  params.set("limit", "60");
6769
6839
  }
6770
- const plays = [];
6771
- let cursor = null;
6772
- let hasMore = true;
6773
- do {
6774
- if (cursor) params.set("cursor", cursor);
6775
- const suffix = params.toString() ? `?${params.toString()}` : "";
6776
- const response = await this.http.get(
6777
- `/api/v2/plays${suffix}`
6778
- );
6779
- plays.push(...response.plays ?? []);
6780
- cursor = response.pagination?.cursor ?? response.cursor ?? null;
6781
- hasMore = Boolean(response.pagination?.hasMore ?? response.hasMore);
6782
- } while (Boolean(options?.grep?.trim()) && hasMore && cursor);
6783
- return plays;
6840
+ if (options?.limit !== void 0) {
6841
+ if (!Number.isSafeInteger(options.limit) || options.limit < 1) {
6842
+ throw new Error("Play page limit must be a positive integer");
6843
+ }
6844
+ params.set("limit", String(options.limit));
6845
+ }
6846
+ if (options?.cursor) params.set("cursor", options.cursor);
6847
+ const suffix = params.size ? `?${params.toString()}` : "";
6848
+ const response = await this.http.get(`/api/v2/plays${suffix}`);
6849
+ return {
6850
+ plays: response.plays ?? [],
6851
+ cursor: response.pagination?.cursor ?? response.cursor ?? null,
6852
+ hasMore: Boolean(response.pagination?.hasMore ?? response.hasMore)
6853
+ };
6784
6854
  }
6785
6855
  /** Set whether an org-owned Play sorts before unpinned Plays. */
6786
6856
  async setPlayPinned(playName, pinned) {
@@ -6914,7 +6984,7 @@ var DeeplineClient = class {
6914
6984
  groupKey,
6915
6985
  name,
6916
6986
  enabled: true,
6917
- deliveryTiming: { mode: "immediate" },
6987
+ deliveryTiming: DEFAULT_PRODUCT_NOTIFICATION_DELIVERY_TIMING,
6918
6988
  source: "workspace",
6919
6989
  configMode: "custom",
6920
6990
  version: 0
@@ -7469,7 +7539,8 @@ var DeeplineClient = class {
7469
7539
  options.enabled ? {
7470
7540
  enabled: true,
7471
7541
  threshold_credits: options.thresholdCredits,
7472
- refill_to_credits: options.refillToCredits
7542
+ refill_to_credits: options.refillToCredits,
7543
+ ...options.purchaseLimitCents !== void 0 ? { purchase_limit_cents: options.purchaseLimitCents } : {}
7473
7544
  } : { enabled: false },
7474
7545
  { "Idempotency-Key": idempotencyKey }
7475
7546
  );
@@ -7490,6 +7561,39 @@ var DeeplineClient = class {
7490
7561
  { maxRetries: 0, exactUrlOnly: true }
7491
7562
  );
7492
7563
  }
7564
+ /** Recover only the original workspace, credit amount, and purchase key; never charge. */
7565
+ async recoverTargetBillingCreditPurchase(options) {
7566
+ if (typeof options.idempotencyKey !== "string") {
7567
+ throw new DeeplineError(
7568
+ "The original billing idempotencyKey is required.",
7569
+ void 0,
7570
+ "INVALID_BILLING_IDEMPOTENCY_KEY"
7571
+ );
7572
+ }
7573
+ const idempotencyKey = requireTargetBillingIdempotencyKey(
7574
+ options.idempotencyKey
7575
+ );
7576
+ if (!Number.isSafeInteger(options.credits) || options.credits <= 0) {
7577
+ throw new DeeplineError(
7578
+ "credits must be a positive safe integer.",
7579
+ void 0,
7580
+ "INVALID_CREDITS"
7581
+ );
7582
+ }
7583
+ if (typeof options.orgId !== "string" || !options.orgId.trim() || options.orgId !== options.orgId.trim()) {
7584
+ throw new DeeplineError(
7585
+ "The original orgId is required without surrounding whitespace.",
7586
+ void 0,
7587
+ "INVALID_ORG_ID"
7588
+ );
7589
+ }
7590
+ return this.http.post(
7591
+ "/api/v2/billing/credit-purchases/recover",
7592
+ { credits: options.credits, org_id: options.orgId },
7593
+ { "Idempotency-Key": idempotencyKey },
7594
+ { maxRetries: 0, exactUrlOnly: true }
7595
+ );
7596
+ }
7493
7597
  /**
7494
7598
  * Start, change, cancel, or restore a target plan through one idempotent
7495
7599
  * commercial operation.
@@ -8142,13 +8246,6 @@ function getAuthedHttpClient() {
8142
8246
  const config = resolveConfig();
8143
8247
  return { config, http: new HttpClient(config) };
8144
8248
  }
8145
- async function writeOutputFile(filename, content) {
8146
- const outputDir = resolve2(process.cwd(), "deepline", "data");
8147
- await mkdir(outputDir, { recursive: true });
8148
- const fullPath = join4(outputDir, filename);
8149
- await writeFile(fullPath, content, "utf-8");
8150
- return fullPath;
8151
- }
8152
8249
  function stableOsUserId() {
8153
8250
  try {
8154
8251
  const info = userInfo();
@@ -8791,13 +8888,6 @@ function createTimestampedName(prefix, extension) {
8791
8888
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
8792
8889
  return `${prefix}-${timestamp}.${extension}`;
8793
8890
  }
8794
- async function writeCsvRowsFile(prefix, rows) {
8795
- const path = await writeOutputFile(
8796
- createTimestampedName(prefix, "csv"),
8797
- csvStringFromRows(rows)
8798
- );
8799
- return path;
8800
- }
8801
8891
  function clip(value, maxLength) {
8802
8892
  return value.length > maxLength ? `${value.slice(0, maxLength - 1)}\u2026` : value;
8803
8893
  }
@@ -9582,7 +9672,7 @@ Notes:
9582
9672
  workspace. To switch, use deepline org list and deepline org set <org-id>.
9583
9673
  `
9584
9674
  );
9585
- auth.command("workspaces").description("Deprecated. Use deepline org list to see workspaces.").action(() => {
9675
+ auth.command("workspaces", { hidden: true }).description("Deprecated. Use deepline org list to see workspaces.").action(() => {
9586
9676
  console.error(
9587
9677
  "Workspaces live under `deepline org`.\n List: deepline org list\n Switch: deepline org set <org-id>\n`deepline auth register` re-approves this device; it does not change the active workspace."
9588
9678
  );
@@ -9679,7 +9769,6 @@ var SUBSCRIPTION_STATUS_NEXT_COMMAND = "deepline billing subscription status --j
9679
9769
  var SUBSCRIPTION_CANCEL_PATH = "/api/v2/billing/subscription/cancel";
9680
9770
  var BILLING_TOP_UP_PATH = "/api/v2/billing/top-up";
9681
9771
  var DEFAULT_BALANCE_RECOVERY_CREDITS = 100;
9682
- var BILLING_HISTORY_EXPORT_LIMIT = 5e3;
9683
9772
  function billingFailureFromError(error, options) {
9684
9773
  if (error instanceof AuthError) {
9685
9774
  return {
@@ -9944,6 +10033,17 @@ async function handleBalance(options) {
9944
10033
  const needsCredits = status === "no_billing" || status === "zero_balance" || status === "payment_method_only";
9945
10034
  const recovery = needsCredits ? balanceRecoveryForCredits() : null;
9946
10035
  const lines = [`Balance: ${payload.balance ?? "(unknown)"} credits`];
10036
+ const temporaryHolds = payload.temporary_hold_credits;
10037
+ if (typeof temporaryHolds === "number" && temporaryHolds > 0) {
10038
+ lines.push(
10039
+ `Temporarily reserved: ${temporaryHolds} credits \u2014 not charged; unused credits are released after final usage is calculated.`
10040
+ );
10041
+ } else if (temporaryHolds === null) {
10042
+ lines.push("Temporary reservation status is temporarily unavailable.");
10043
+ }
10044
+ if (payload.temporary_hold_credits_truncated === true) {
10045
+ lines.push("Temporary reservation total may be incomplete.");
10046
+ }
9947
10047
  if (status === "no_billing") {
9948
10048
  lines.push(
9949
10049
  "Billing: No billing account or payment method set up for this workspace."
@@ -9970,6 +10070,9 @@ async function handleBalance(options) {
9970
10070
  );
9971
10071
  return;
9972
10072
  }
10073
+ function quoteShellArgument(value) {
10074
+ return `'${value.replace(/'/g, `'\\''`)}'`;
10075
+ }
9973
10076
  async function handleUsage(options) {
9974
10077
  const { http } = getAuthedHttpClient();
9975
10078
  const params = new URLSearchParams();
@@ -9986,24 +10089,32 @@ async function handleUsage(options) {
9986
10089
  const recent = payload.recent ?? {};
9987
10090
  const last30Usage = usage.last_30_days_usage_credits ?? usage.month_spent_credits;
9988
10091
  const temporaryHolds = Number(usage.temporary_hold_credits ?? 0);
10092
+ const nextPage = typeof recent.next_cursor === "string" && recent.next_cursor.length > 0 ? `deepline billing usage --cursor ${quoteShellArgument(recent.next_cursor)}${options.limit ? ` --limit ${options.limit}` : ""}${options.runId ? ` --run-id ${quoteShellArgument(options.runId)}` : ""} --json` : null;
9989
10093
  const lines = [
9990
10094
  `Balance: ${payload.balance ?? "(unknown)"}`,
9991
10095
  `Last 30 days usage: ${last30Usage ?? "(unknown)"}`,
9992
10096
  ...Number.isFinite(temporaryHolds) && temporaryHolds > 0 ? [`Temporary holds: ${temporaryHolds}`] : [],
9993
- `Monthly limit: ${quota.enabled ? quota.monthly_credits_limit ?? "(unknown)" : "off"}`,
10097
+ `Monthly spend guidance: ${quota.enabled ? quota.monthly_credits_limit ?? "(unknown)" : "off"}`,
9994
10098
  ...options.runId && recent.run_id ? [
9995
10099
  `Run spend: ${(payload.run ?? {}).spent_credits ?? "(unknown)"} Deepline Credits`
9996
10100
  ] : [],
9997
10101
  ...recentUsageLines(
9998
10102
  Array.isArray(recent.entries) ? recent.entries : []
9999
10103
  ),
10000
- ...typeof recent.next_cursor === "string" && recent.next_cursor.length > 0 ? [
10001
- `Next page: deepline billing usage --cursor ${recent.next_cursor}${options.limit ? ` --limit ${options.limit}` : ""}${options.runId ? ` --run-id ${options.runId}` : ""}`
10104
+ ...recent.has_more === true || recent.incomplete === true ? ["List truncated \u2014 more recent calls match this query."] : [],
10105
+ ...nextPage ? [`Next page: ${nextPage}`] : [],
10106
+ ...!nextPage && (recent.has_more === true || recent.incomplete === true) ? [
10107
+ "No continuation is available for this view. Use deepline billing ledger export all --json for the full ledger."
10002
10108
  ] : []
10003
10109
  ];
10004
10110
  printCommandEnvelope(
10005
10111
  {
10006
10112
  ...payload,
10113
+ recent: {
10114
+ ...recent,
10115
+ is_truncated: recent.has_more === true || recent.incomplete === true
10116
+ },
10117
+ next: { page: nextPage },
10007
10118
  render: { sections: [{ title: "billing usage", lines }] }
10008
10119
  },
10009
10120
  { json: options.json }
@@ -10015,9 +10126,9 @@ async function handleLimit(options) {
10015
10126
  "/api/v2/billing/limit"
10016
10127
  );
10017
10128
  const lines = payload.enabled ? [
10018
- `Monthly limit: ${payload.monthly_credits_limit ?? "(unknown)"}`,
10019
- `Remaining before cap: ${payload.remaining_credits ?? "(unknown)"}`
10020
- ] : ["Monthly limit: off"];
10129
+ `Monthly spend guidance: ${payload.monthly_credits_limit ?? "(unknown)"}`,
10130
+ "Enforcement: advisory; available balance remains the exact admission control."
10131
+ ] : ["Monthly spend guidance: off"];
10021
10132
  printCommandEnvelope(
10022
10133
  {
10023
10134
  ...payload,
@@ -10039,7 +10150,7 @@ async function handleSetLimit(credits, options) {
10039
10150
  sections: [
10040
10151
  {
10041
10152
  title: "billing limit",
10042
- lines: [`Monthly billing limit set to ${credits} credits.`]
10153
+ lines: [`Monthly spend guidance set to ${credits} credits.`]
10043
10154
  }
10044
10155
  ]
10045
10156
  }
@@ -10059,7 +10170,7 @@ async function handleLimitOff(options) {
10059
10170
  sections: [
10060
10171
  {
10061
10172
  title: "billing limit",
10062
- lines: ["Monthly billing limit is now off."]
10173
+ lines: ["Monthly spend guidance is now off."]
10063
10174
  }
10064
10175
  ]
10065
10176
  }
@@ -10067,6 +10178,39 @@ async function handleLimitOff(options) {
10067
10178
  { json: options.json }
10068
10179
  );
10069
10180
  }
10181
+ async function exportLedger(http, outputPath, options) {
10182
+ let summary = { row_count: 0, net_delta_credits: 0 };
10183
+ let initialized = false;
10184
+ for await (const entries of iterateCursorPages(async (cursor) => {
10185
+ const params = new URLSearchParams({ limit: "5000" });
10186
+ if (cursor) params.set("cursor", cursor);
10187
+ if (options.sinceAt !== null)
10188
+ params.set("since_at", String(options.sinceAt));
10189
+ if (options.runId) params.set("run_id", options.runId);
10190
+ if (options.operation) params.set("operation", options.operation);
10191
+ const payload = await http.get(
10192
+ `/api/v2/billing/ledger?${params.toString()}`
10193
+ );
10194
+ if (!Array.isArray(payload.entries) || typeof payload.has_more !== "boolean") {
10195
+ throw new Error("Billing ledger response is missing entries");
10196
+ }
10197
+ return {
10198
+ items: payload.entries,
10199
+ hasMore: payload.has_more === true,
10200
+ cursor: typeof payload.next_cursor === "string" ? payload.next_cursor : null
10201
+ };
10202
+ })) {
10203
+ if (!initialized) {
10204
+ await mkdir2(dirname6(outputPath), { recursive: true });
10205
+ await writeFile2(outputPath, ledgerRowsToCsv([], true), "utf-8");
10206
+ initialized = true;
10207
+ }
10208
+ const rows = entries.map(ledgerApiEntryToRow);
10209
+ await appendFile(outputPath, ledgerRowsToCsv(rows, false), "utf-8");
10210
+ summary = summarizeLedgerRows(summary, rows);
10211
+ }
10212
+ return summary;
10213
+ }
10070
10214
  async function handleHistory(options) {
10071
10215
  const { http } = getAuthedHttpClient();
10072
10216
  const windows = {
@@ -10076,41 +10220,20 @@ async function handleHistory(options) {
10076
10220
  "1y": 31536e3
10077
10221
  };
10078
10222
  const sinceAt = Math.max(0, Math.floor(Date.now() / 1e3) - windows[options.time]) * 1e3;
10079
- const entries = [];
10080
- let cursor = null;
10081
- while (entries.length < BILLING_HISTORY_EXPORT_LIMIT) {
10082
- const params = new URLSearchParams({
10083
- since_at: String(sinceAt),
10084
- limit: String(BILLING_HISTORY_EXPORT_LIMIT - entries.length)
10085
- });
10086
- if (cursor !== null) params.set("cursor", cursor);
10087
- const payload = await http.get(
10088
- `/api/v2/billing/ledger?${params.toString()}`
10089
- );
10090
- if (Array.isArray(payload.entries)) {
10091
- entries.push(
10092
- ...payload.entries.slice(
10093
- 0,
10094
- BILLING_HISTORY_EXPORT_LIMIT - entries.length
10095
- )
10096
- );
10097
- }
10098
- const nextCursor = typeof payload.next_cursor === "string" && payload.next_cursor.length > 0 ? payload.next_cursor : null;
10099
- if (payload.has_more !== true || nextCursor === null) break;
10100
- if (nextCursor === cursor) {
10101
- throw new Error("Billing history pagination cursor did not advance");
10102
- }
10103
- cursor = nextCursor;
10104
- }
10105
- const rows = entries.map(ledgerApiEntryToRow);
10106
- const outputPath = await writeCsvRowsFile(
10107
- `billing-history-${options.time}`,
10108
- rows
10223
+ const outputPath = resolve3(
10224
+ process.cwd(),
10225
+ "deepline",
10226
+ "data",
10227
+ createTimestampedName(`billing-history-${options.time}`, "csv")
10109
10228
  );
10229
+ const summary = await exportLedger(http, outputPath, { sinceAt });
10110
10230
  printCommandEnvelope(
10111
10231
  {
10112
10232
  output_path: outputPath,
10113
- row_count: rows.length,
10233
+ row_count: summary.row_count,
10234
+ has_more: false,
10235
+ is_truncated: false,
10236
+ next_cursor: null,
10114
10237
  time_window: options.time,
10115
10238
  render: {
10116
10239
  sections: [
@@ -10118,7 +10241,7 @@ async function handleHistory(options) {
10118
10241
  title: "billing history",
10119
10242
  lines: [
10120
10243
  `Billing history written to ${outputPath}`,
10121
- `${rows.length} row(s) exported.`
10244
+ `${summary.row_count} row(s) exported.`
10122
10245
  ]
10123
10246
  }
10124
10247
  ]
@@ -10143,40 +10266,18 @@ async function handleLedgerExportAll(options) {
10143
10266
  }
10144
10267
  const { http } = getAuthedHttpClient();
10145
10268
  const outputPath = options.output ? resolve3(String(options.output)) : defaultLedgerExportPath();
10146
- let summary = { row_count: 0, net_delta_credits: 0 };
10147
- let cursor = null;
10148
- let initializedOutput = false;
10149
- for (; ; ) {
10150
- const params = new URLSearchParams({ limit: "5000" });
10151
- if (cursor !== null) params.set("cursor", cursor);
10152
- if (options.runId) params.set("run_id", options.runId);
10153
- if (options.operation) params.set("operation", options.operation);
10154
- if (sinceAt !== null) params.set("since_at", String(sinceAt));
10155
- const payload = await http.get(
10156
- `/api/v2/billing/ledger?${params.toString()}`
10157
- );
10158
- const entries = Array.isArray(payload.entries) ? payload.entries : [];
10159
- const rows = entries.map(ledgerApiEntryToRow);
10160
- if (!initializedOutput) {
10161
- await mkdir2(dirname6(outputPath), { recursive: true });
10162
- await writeFile2(outputPath, ledgerRowsToCsv([], true), "utf-8");
10163
- initializedOutput = true;
10164
- }
10165
- if (rows.length > 0) {
10166
- await appendFile(outputPath, ledgerRowsToCsv(rows, false), "utf-8");
10167
- summary = summarizeLedgerRows(summary, rows);
10168
- }
10169
- const nextCursor = typeof payload.next_cursor === "string" && payload.next_cursor.length > 0 ? payload.next_cursor : null;
10170
- if (payload.has_more !== true || nextCursor === null) {
10171
- break;
10172
- }
10173
- if (nextCursor === cursor) break;
10174
- cursor = nextCursor;
10175
- }
10269
+ const summary = await exportLedger(http, outputPath, {
10270
+ sinceAt,
10271
+ runId: options.runId,
10272
+ operation: options.operation
10273
+ });
10176
10274
  printCommandEnvelope(
10177
10275
  {
10178
10276
  output_path: outputPath,
10179
10277
  row_count: summary.row_count,
10278
+ has_more: false,
10279
+ is_truncated: false,
10280
+ next_cursor: null,
10180
10281
  net_delta_credits: summary.net_delta_credits,
10181
10282
  scope: "workspace",
10182
10283
  ...options.runId ? { run_id: options.runId } : {},
@@ -10205,42 +10306,28 @@ function planPriceText(priceUsd, priceInterval) {
10205
10306
  }
10206
10307
  return `$${priceUsd}${priceInterval ? `/${priceInterval}` : ""}`;
10207
10308
  }
10208
- function planRolloverText(rollover) {
10209
- const mode = rollover?.mode ?? "none";
10210
- if (mode === "none") return "no rollover";
10211
- if (mode === "bounded") {
10212
- return `rollover up to ${rollover?.max_credits ?? "(unknown)"} credits`;
10213
- }
10214
- return `rollover ${mode}`;
10309
+ function targetPlanLine(plan) {
10310
+ return `${plan.name} (${plan.sku}) | ${planPriceText(plan.recurring_price_usd, plan.interval)} | ${plan.included_credits} included credits/month | $${plan.purchased_credit_price_usd}/purchased credit | ${plan.acquisition_enabled ? "available" : "unavailable"}`;
10215
10311
  }
10216
10312
  async function handlePlans(options) {
10217
- const { http } = getAuthedHttpClient();
10218
- const payload = await http.get(
10219
- "/api/v2/billing/catalog/current"
10313
+ const client2 = new DeeplineClient();
10314
+ const payload = await client2.billing.targetPlans();
10315
+ const listedCurrentPlan = payload.plans.find(
10316
+ (plan) => plan.sku === payload.current_plan_sku
10220
10317
  );
10221
- const activePlan = payload.active_plan ?? {};
10222
- const plans = Array.isArray(payload.plans) ? payload.plans : [];
10223
- const meters = Array.isArray(payload.meters) ? payload.meters : Array.isArray(payload.metrics) ? payload.metrics : [];
10318
+ const currentPlan = listedCurrentPlan ?? (await client2.billing.targetStatus()).plan;
10224
10319
  const lines = [
10225
- `Catalog: ${payload.catalog_id ?? "(unknown)"} (version ${payload.catalog_version ?? "(unknown)"})`,
10226
- `Active plan: ${activePlan.public_name ?? "(unknown)"} (${activePlan.plan_version_id ?? "(unknown)"})`,
10227
- `Assigned by: ${activePlan.assigned_by ?? "default"} | subscription: ${activePlan.has_subscription ? "yes" : "no"}`,
10228
- ...plans.length === 0 ? ["Plans: none published"] : [
10229
- "Plans:",
10230
- ...plans.map(
10231
- (plan) => `${plan.public_name ?? "(unknown)"} (${plan.plan_version_id ?? "(unknown)"}) | ${planPriceText(plan.price_usd, plan.price_interval)} | ${plan.monthly_grant_credits ?? 0} credits/cycle | ${planRolloverText(plan.rollover)} | ${plan.acquirable ? "acquirable" : "not acquirable"}`
10232
- )
10233
- ],
10234
- ...meters.length === 0 ? ["Metrics: none"] : [
10235
- "Metrics:",
10236
- ...meters.map(
10237
- (meter) => `${meter.id ?? "(unknown)"} | ${meter.name ?? "(unknown)"}`
10238
- )
10239
- ]
10320
+ `Current plan: ${currentPlan.name} (${currentPlan.sku}) | ${planPriceText(currentPlan.recurring_price_usd, currentPlan.interval)} | ${currentPlan.included_credits ?? "(unknown)"} included credits/month`,
10321
+ `Pending plan: ${payload.pending_plan_sku ?? "none"}`,
10322
+ `Plan changes: ${payload.acquisition_enabled ? "enabled" : "disabled"}`,
10323
+ ...payload.plans.length === 0 ? ["Plans: none available"] : ["Plans:", ...payload.plans.map(targetPlanLine)],
10324
+ "Change plan: deepline billing change-plan <plan_sku> --json"
10240
10325
  ];
10326
+ const legacyPayload = shouldEmitJson(options.json) ? await client2.billing.plans() : null;
10241
10327
  printCommandEnvelope(
10242
10328
  {
10243
- ...payload,
10329
+ ...legacyPayload ?? payload,
10330
+ ...legacyPayload ? { target_billing: payload } : {},
10244
10331
  render: { sections: [{ title: "billing plans", lines }] }
10245
10332
  },
10246
10333
  { json: options.json }
@@ -10615,7 +10702,10 @@ async function handleAutoRechargeStatus(options) {
10615
10702
  const lines = [
10616
10703
  `State: ${state}`,
10617
10704
  ...payload.threshold_credits !== null ? [`Threshold: ${payload.threshold_credits} credits`] : [],
10618
- ...payload.refill_to_credits !== null ? [`Refill balance to: ${payload.refill_to_credits} credits`] : []
10705
+ ...payload.refill_to_credits !== null ? [`Refill balance to: ${payload.refill_to_credits} credits`] : [],
10706
+ ...payload.purchase_limit_cents !== void 0 ? [
10707
+ payload.purchase_limit_cents === null ? "Automatic purchase cap: none" : `Automatic purchase cap: $${(payload.purchase_limit_cents / 100).toFixed(2)} per rolling 30 days`
10708
+ ] : []
10619
10709
  ];
10620
10710
  printCommandEnvelope(
10621
10711
  {
@@ -10629,6 +10719,18 @@ async function handleAutoRechargeStatus(options) {
10629
10719
  async function handleAutoRechargeSet(options) {
10630
10720
  const thresholdCredits = parseTopUpCredits(options.thresholdCredits);
10631
10721
  const refillToCredits = parseTopUpCredits(options.refillToCredits);
10722
+ const rollingLimitCents = options.purchaseLimitCents === void 0 ? void 0 : options.purchaseLimitCents === "none" ? null : Number(options.purchaseLimitCents);
10723
+ if (rollingLimitCents !== void 0 && rollingLimitCents !== null && (!Number.isSafeInteger(rollingLimitCents) || rollingLimitCents <= 0)) {
10724
+ reportBillingFailure(
10725
+ {
10726
+ exitCode: 2,
10727
+ code: "INVALID_AUTO_RECHARGE_CONFIGURATION",
10728
+ message: "--purchase-limit-cents must be a positive whole number of USD cents or none."
10729
+ },
10730
+ options
10731
+ );
10732
+ return;
10733
+ }
10632
10734
  if (thresholdCredits === null || refillToCredits === null || refillToCredits <= thresholdCredits) {
10633
10735
  reportBillingFailure(
10634
10736
  {
@@ -10653,7 +10755,8 @@ async function handleAutoRechargeSet(options) {
10653
10755
  body: {
10654
10756
  enabled: true,
10655
10757
  threshold_credits: thresholdCredits,
10656
- refill_to_credits: refillToCredits
10758
+ refill_to_credits: refillToCredits,
10759
+ ...rollingLimitCents !== void 0 ? { purchase_limit_cents: rollingLimitCents } : {}
10657
10760
  }
10658
10761
  }
10659
10762
  },
@@ -10665,6 +10768,7 @@ async function handleAutoRechargeSet(options) {
10665
10768
  enabled: true,
10666
10769
  thresholdCredits,
10667
10770
  refillToCredits,
10771
+ ...rollingLimitCents !== void 0 ? { purchaseLimitCents: rollingLimitCents } : {},
10668
10772
  idempotencyKey
10669
10773
  });
10670
10774
  printCommandEnvelope(
@@ -10722,6 +10826,60 @@ async function handleBuyCredits(creditsRaw, options) {
10722
10826
  { json: options.json }
10723
10827
  );
10724
10828
  }
10829
+ async function handleTopUpRecover(creditsRaw, options) {
10830
+ const credits = parseTopUpCredits(creditsRaw);
10831
+ if (credits === null) {
10832
+ reportBillingFailure(
10833
+ {
10834
+ exitCode: 2,
10835
+ code: "INVALID_CREDITS",
10836
+ message: "<credits> must be a positive integer."
10837
+ },
10838
+ options
10839
+ );
10840
+ return;
10841
+ }
10842
+ const failure = !options.orgId?.trim() || options.orgId !== options.orgId.trim() ? {
10843
+ code: "INVALID_ORG_ID",
10844
+ message: "--org-id must be the original workspace ID without surrounding whitespace."
10845
+ } : !options.idempotencyKey || options.idempotencyKey.length > 200 || options.idempotencyKey !== options.idempotencyKey.trim() ? {
10846
+ code: "INVALID_BILLING_IDEMPOTENCY_KEY",
10847
+ message: "--idempotency-key must be the original key (1\u2013200 characters without surrounding whitespace)."
10848
+ } : null;
10849
+ if (failure) {
10850
+ reportBillingFailure(
10851
+ {
10852
+ exitCode: 2,
10853
+ ...failure
10854
+ },
10855
+ options
10856
+ );
10857
+ return;
10858
+ }
10859
+ if (options.dryRun) {
10860
+ printCommandEnvelope(
10861
+ {
10862
+ ok: true,
10863
+ dry_run: true,
10864
+ method: "POST",
10865
+ path: "/api/v2/billing/credit-purchases/recover",
10866
+ idempotency_key: options.idempotencyKey,
10867
+ body: { credits, org_id: options.orgId }
10868
+ },
10869
+ { json: options.json }
10870
+ );
10871
+ return;
10872
+ }
10873
+ const payload = await new DeeplineClient().billing.recoverCreditPurchase({
10874
+ credits,
10875
+ orgId: options.orgId,
10876
+ idempotencyKey: options.idempotencyKey
10877
+ });
10878
+ printCommandEnvelope(
10879
+ { ok: true, idempotency_key: options.idempotencyKey, ...payload },
10880
+ { json: options.json }
10881
+ );
10882
+ }
10725
10883
  async function handleTargetPlan(planSku, options) {
10726
10884
  if (planSku !== "payg-v1" && planSku !== "builder-v1" && planSku !== "growth-v1" && planSku !== "growth-canary-v1" && planSku !== "team-v1") {
10727
10885
  reportBillingFailure(
@@ -10839,35 +10997,36 @@ Examples:
10839
10997
  "--cursor <cursor>",
10840
10998
  "Recent-call cursor from the previous response"
10841
10999
  ).option("--run-id <run_id>", "Show recent usage for one play run").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleUsage);
10842
- billing.command("limit").description("Show configured monthly limit state.").addHelpText(
11000
+ billing.command("limit").description("Show configured monthly spend guidance.").addHelpText(
10843
11001
  "after",
10844
11002
  `
10845
11003
  Notes:
10846
- Read-only. Shows whether the monthly workspace cap is enabled and how many
10847
- Deepline credits remain before the cap.
11004
+ Read-only. Shows whether monthly workspace spend guidance is enabled.
11005
+ Guidance does not reject funded work; available balance remains exact.
10848
11006
 
10849
11007
  Examples:
10850
11008
  deepline billing limit
10851
11009
  deepline billing limit --json
10852
11010
  `
10853
11011
  ).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleLimit);
10854
- billing.command("set-limit").description("Set monthly credit cap.").addHelpText(
11012
+ billing.command("set-limit").description("Set monthly spend guidance.").addHelpText(
10855
11013
  "after",
10856
11014
  `
10857
11015
  Notes:
10858
11016
  Mutates workspace billing settings. The argument is a Deepline credit amount,
10859
- not dollars and not provider credits.
11017
+ not dollars and not provider credits. Guidance is advisory; it does not
11018
+ replace the exact available-balance admission check.
10860
11019
 
10861
11020
  Examples:
10862
11021
  deepline billing set-limit 500
10863
11022
  deepline billing set-limit 500 --json
10864
11023
  `
10865
11024
  ).argument("<credits>", "Monthly credits limit").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleSetLimit);
10866
- billing.command("off").description("Disable monthly credit cap.").addHelpText(
11025
+ billing.command("off").description("Disable monthly spend guidance.").addHelpText(
10867
11026
  "after",
10868
11027
  `
10869
11028
  Notes:
10870
- Mutates workspace billing settings by removing the monthly Deepline credit cap.
11029
+ Mutates workspace billing settings by removing monthly Deepline spend guidance.
10871
11030
 
10872
11031
  Examples:
10873
11032
  deepline billing off
@@ -10921,7 +11080,9 @@ Examples:
10921
11080
  `
10922
11081
  Notes:
10923
11082
  Read-only server query that writes a local CSV file. With --json, stdout is a
10924
- summary containing the output path and row count.
11083
+ summary containing the output path, row count, and completeness metadata.
11084
+ Exports the complete window using bounded pages. For an exact start timestamp:
11085
+ deepline billing ledger export all --since <ISO-8601> --json
10925
11086
 
10926
11087
  Examples:
10927
11088
  deepline billing history --time 1m
@@ -10963,6 +11124,18 @@ Examples:
10963
11124
  "Stable retry key for the same intended top-up"
10964
11125
  ).option("--dry-run", "Print the planned top-up without charging").option("--compact", "Keep only high-signal fields in JSON output").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleTopUp);
10965
11126
  billing.command("buy").description("Buy credits through the target billing contract.").argument("<credits>", "Positive integer Deepline credit amount").option("--idempotency-key <key>", "Stable retry key").option("--json", "Emit JSON output").action(handleBuyCredits);
11127
+ billing.command("top-up-recover").description(
11128
+ "Inspect or retire an original top-up intent without starting a payment."
11129
+ ).argument("<credits>", "Original positive integer Deepline credit amount").requiredOption(
11130
+ "--org-id <original-org>",
11131
+ "Original workspace ID (must match the authenticated workspace)"
11132
+ ).requiredOption(
11133
+ "--idempotency-key <original-key>",
11134
+ "Original purchase key; never generates a new key"
11135
+ ).option("--dry-run", "Print the recovery request without changing state").option("--json", "Emit JSON output. Also automatic when stdout is piped").addHelpText(
11136
+ "after",
11137
+ "\nAn absent intent is durably retired; an existing operation is returned unchanged.\nThis command never starts a payment. Use the original amount, workspace, and key.\nExample:\n deepline billing top-up-recover 1000 --org-id org_original --idempotency-key original-purchase-key --json\n"
11138
+ ).action(handleTopUpRecover);
10966
11139
  billing.command("status").description("Show normalized target billing state.").option("--json", "Emit JSON output").action(handleTargetStatus);
10967
11140
  billing.command("auto-recharge").description("Inspect and manage automatic Deepline credit recharge.").addHelpText(
10968
11141
  "after",
@@ -10983,24 +11156,37 @@ Examples:
10983
11156
  ).requiredOption(
10984
11157
  "--refill-to-credits <credits>",
10985
11158
  "Recharge the balance to this amount"
11159
+ ).option(
11160
+ "--purchase-limit-cents <cents>",
11161
+ "Limit automatic purchases over rolling 30 days (USD cents)"
10986
11162
  ).option("--idempotency-key <key>", "Stable retry key").option("--dry-run", "Print the planned update without applying it").option("--json", "Emit JSON output").action(handleAutoRechargeSet)
10987
11163
  ).addCommand(
10988
11164
  new Command("off").description(
10989
11165
  "Disable automatic recharge without clearing saved amounts."
10990
11166
  ).option("--idempotency-key <key>", "Stable retry key").option("--dry-run", "Print the planned update without applying it").option("--json", "Emit JSON output").action(handleAutoRechargeOff)
11167
+ ).addCommand(
11168
+ new Command("trigger").description(
11169
+ "Evaluate capped automatic recharge and resume any pending purchase."
11170
+ ).option("--json", "Emit JSON output").action(async (options) => {
11171
+ const result = await new DeeplineClient().billing.autoRecharge.trigger();
11172
+ printCommandEnvelope({ ok: true, ...result }, { json: options.json });
11173
+ })
10991
11174
  );
10992
- billing.command("change-plan").description("Start or change the target billing plan.").argument("<plan_sku>", "payg-v1, builder-v1, growth-v1, growth-canary-v1, or team-v1").option("--idempotency-key <key>", "Stable retry key").option("--json", "Emit JSON output").action(handleTargetPlan);
11175
+ billing.command("change-plan").description("Start or change the target billing plan.").argument(
11176
+ "<plan_sku>",
11177
+ "payg-v1, builder-v1, growth-v1, growth-canary-v1, or team-v1"
11178
+ ).option("--idempotency-key <key>", "Stable retry key").option("--json", "Emit JSON output").action(handleTargetPlan);
10993
11179
  billing.command("cancel-plan").description("Cancel a target subscription at period end, or undo it.").option("--undo", "Undo a pending period-end cancellation").option("--idempotency-key <key>", "Stable retry key").option("--json", "Emit JSON output").action(handleTargetPlanCancellation);
10994
11180
  billing.command("portal").description("Open the Stripe-hosted billing recovery portal.").option("--no-open", "Print the URL without opening a browser").option("--json", "Emit JSON output").action(handleTargetPortal);
10995
11181
  billing.command("plans").description("Show published plans and the plan you are on.").addHelpText(
10996
11182
  "after",
10997
11183
  `
10998
11184
  Notes:
10999
- Read-only. Answers "what plans exist and what am I on": each plan's price,
11000
- monthly grant credits, rollover policy, and whether it is open for
11001
- subscription, plus the catalog's usage metrics. All amounts are Deepline
11002
- credits and Deepline-facing USD, never raw provider spend. Subscribe to a
11003
- listed plan with: deepline billing subscribe <plan_version_id>
11185
+ Read-only. Shows the current target billing plan, pending plan, and every
11186
+ visible plan's recurring price, included credits, purchased-credit price,
11187
+ and current acquisition availability. All amounts are Deepline credits and
11188
+ Deepline-facing USD, never raw provider spend. Change to an available plan
11189
+ with: deepline billing change-plan <plan_sku>
11004
11190
 
11005
11191
  Examples:
11006
11192
  deepline billing plans
@@ -11022,7 +11208,7 @@ Examples:
11022
11208
  deepline billing subscribe runtime-395-2026-07-v1
11023
11209
  deepline billing subscribe runtime-395-2026-07-v1 --no-open --json
11024
11210
  `
11025
- ).argument("<plan_version_id>", "Plan version id from `billing plans`").option("--no-open", "Print the checkout URL without opening a browser").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleSubscribe);
11211
+ ).argument("<plan_version_id>", "Legacy billing plan version id").option("--no-open", "Print the checkout URL without opening a browser").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleSubscribe);
11026
11212
  billing.command("subscription").description("Inspect and manage subscription state for the workspace.").addHelpText(
11027
11213
  "after",
11028
11214
  `
@@ -11289,6 +11475,7 @@ function mergeCanonicalRowsInfo(left, right) {
11289
11475
  ...right.recoveredReturnPaths ?? []
11290
11476
  ])
11291
11477
  ];
11478
+ const currentTable = left.currentTable || right.currentTable;
11292
11479
  return {
11293
11480
  ...fallback,
11294
11481
  ...preferred,
@@ -11302,6 +11489,7 @@ function mergeCanonicalRowsInfo(left, right) {
11302
11489
  tableNamespace: preferred.tableNamespace ?? fallback.tableNamespace,
11303
11490
  ...left.recovered || right.recovered ? { recovered: true } : {},
11304
11491
  ...recoveredReturnPaths2.length ? { recoveredReturnPaths: recoveredReturnPaths2 } : {},
11492
+ ...currentTable ? { currentTable: true } : {},
11305
11493
  ...exportUnavailableReason ? {
11306
11494
  exportUnavailableReason,
11307
11495
  ...unavailableSource?.exportUnavailableMessage ? {
@@ -11362,6 +11550,11 @@ function isSerializedDataset(value) {
11362
11550
  function isPackagedDatasetOutput(value) {
11363
11551
  return isRecord8(value) && value.kind === "dataset" && isRecord8(value.preview) && Array.isArray(value.preview.rows);
11364
11552
  }
11553
+ function hasCurrentTableExport(value) {
11554
+ if (!isRecord8(value) || !isRecord8(value.actions)) return false;
11555
+ const exportCsv = value.actions.exportCsv;
11556
+ return isRecord8(exportCsv) && isRecord8(exportCsv.scope) && exportCsv.scope.kind === "database" && exportCsv.scope.mutability === "current";
11557
+ }
11365
11558
  function recoveredReturnPaths(value) {
11366
11559
  if (!Array.isArray(value)) return [];
11367
11560
  return [
@@ -11468,6 +11661,7 @@ function canonicalRowsInfoFromCandidate(input2) {
11468
11661
  datasetId: typeof candidate.value.datasetId === "string" ? candidate.value.datasetId : null,
11469
11662
  tableNamespace: typeof candidate.value.tableNamespace === "string" ? candidate.value.tableNamespace : null,
11470
11663
  ...candidate.value.recovered === true ? { recovered: true } : {},
11664
+ ...hasCurrentTableExport(candidate.value) ? { currentTable: true } : {},
11471
11665
  ...recoveredReturnPaths(candidate.value.recoveredReturnPaths).length ? {
11472
11666
  recoveredReturnPaths: recoveredReturnPaths(
11473
11667
  candidate.value.recoveredReturnPaths
@@ -19839,6 +20033,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
19839
20033
  runId: workflowId,
19840
20034
  playName: input2.playName,
19841
20035
  dashboardUrl,
20036
+ inputFieldCount: Object.keys(input2.request.input ?? {}).length,
19842
20037
  jsonOutput: false,
19843
20038
  progress: input2.progress
19844
20039
  });
@@ -20956,11 +21151,15 @@ function formatPackageDatasetActionLines(packaged) {
20956
21151
  ` ${category} dataset ${path}: ${rowCount === null ? "unknown rows" : `${formatInteger(rowCount)} ${rowCount === 1 ? "row" : "rows"}`}`
20957
21152
  );
20958
21153
  }
20959
- const exportCommand = actionToCommand(actions.exportCsv);
21154
+ const exportAction = readRecord(actions.exportCsv);
21155
+ const exportCommand = actionToCommand(exportAction);
21156
+ const exportScope = readRecord(exportAction?.scope);
20960
21157
  const currentQueryCommand = actionToCommand(actions.queryCurrentTable);
20961
21158
  const legacyQueryCommand = actionToCommand(actions.query);
20962
21159
  if (exportCommand) {
20963
- lines.push(` export this run: ${exportCommand}`);
21160
+ lines.push(
21161
+ exportScope?.kind === "database" ? ` export current table (may include other runs): ${exportCommand}` : ` export this run: ${exportCommand}`
21162
+ );
20964
21163
  }
20965
21164
  if (currentQueryCommand) {
20966
21165
  lines.push(` query current table: ${currentQueryCommand}`);
@@ -21369,33 +21568,29 @@ function sqlSafeExportColumnName(id) {
21369
21568
  async function fetchBackingDatasetRows(input2) {
21370
21569
  const playName = extractRunPlayName(input2.status);
21371
21570
  const tableNamespace = input2.rowsInfo.tableNamespace?.trim();
21571
+ const currentTable = input2.rowsInfo.currentTable === true;
21372
21572
  if (!playName || !tableNamespace) {
21373
21573
  return null;
21374
21574
  }
21375
21575
  const sheetRows = [];
21376
21576
  let offset = 0;
21377
- let expectedTotal = input2.rowsInfo.totalRows;
21378
21577
  while (true) {
21379
21578
  const page = await input2.client.runs.exportDatasetRows({
21380
21579
  playName,
21381
21580
  tableNamespace,
21382
- runId: input2.status.runId,
21581
+ ...currentTable ? {} : { runId: input2.status.runId },
21383
21582
  limit: RUN_EXPORT_PAGE_SIZE,
21384
21583
  offset,
21385
21584
  rowMode: "all"
21386
21585
  });
21387
21586
  sheetRows.push(...page.rows);
21388
- const summaryTotal = page.summary?.stats?.total;
21389
- if (typeof summaryTotal === "number" && Number.isFinite(summaryTotal)) {
21390
- expectedTotal = Math.max(expectedTotal, Math.trunc(summaryTotal));
21391
- }
21392
- if (page.rows.length < RUN_EXPORT_PAGE_SIZE || sheetRows.length >= expectedTotal) {
21587
+ if (page.rows.length < RUN_EXPORT_PAGE_SIZE) {
21393
21588
  break;
21394
21589
  }
21395
21590
  offset += page.rows.length;
21396
21591
  }
21397
21592
  const rows = sheetRows.map(exportableSheetRow).filter((row) => Boolean(row));
21398
- if (rows.length < input2.rowsInfo.totalRows) {
21593
+ if (!currentTable && rows.length < input2.rowsInfo.totalRows || currentTable && rows.length === 0 && input2.rowsInfo.totalRows > 0) {
21399
21594
  return null;
21400
21595
  }
21401
21596
  const columns = mergeExportColumns(
@@ -21408,6 +21603,7 @@ async function fetchBackingDatasetRows(input2) {
21408
21603
  columns,
21409
21604
  totalRows: rows.length,
21410
21605
  complete: true,
21606
+ ...currentTable ? { currentTable: true } : {},
21411
21607
  source: `${input2.rowsInfo.source ?? "result.rows"} -> /api/v2/plays/${playName}/sheet?tableNamespace=${tableNamespace}`
21412
21608
  };
21413
21609
  }
@@ -21432,12 +21628,14 @@ function assertDatasetHasExportableRows(input2) {
21432
21628
  if (input2.rowsInfo.rows.length > 0) {
21433
21629
  return input2.rowsInfo;
21434
21630
  }
21631
+ if (input2.rowsInfo.currentTable === true && input2.rowsInfo.totalRows === 0) {
21632
+ return input2.rowsInfo;
21633
+ }
21435
21634
  const datasetLabel = input2.datasetPath ?? input2.rowsInfo.tableNamespace ?? input2.rowsInfo.source ?? "result.rows";
21436
21635
  const available = input2.availableRows.map((info) => info.tableNamespace ?? info.source).filter((name) => typeof name === "string");
21437
21636
  const runStatus = String(input2.status.status ?? "").toLowerCase();
21438
- const failedBeforePersisting = runStatus !== "completed";
21439
21637
  throw new DeeplineError(
21440
- `Run ${input2.status.runId} has zero rows to export from dataset '${datasetLabel}'.` + (failedBeforePersisting ? ` The run status is '${runStatus || "unknown"}', so it likely failed before persisting rows to this dataset \u2014 provider calls may have been billed without a durable row. Fix the run's failure cause and re-run to resume.` : " The run completed but this dataset materialized no rows.") + (available.length > 0 ? ` Available datasets: ${available.join(", ")}.` : " No datasets were materialized for this run."),
21638
+ `Run ${input2.status.runId} has zero rows to export from dataset '${datasetLabel}'. The run status is '${runStatus || "unknown"}', so it likely failed before persisting rows to this dataset \u2014 provider calls may have been billed without a durable row. Fix the run's failure cause and re-run to resume.` + (available.length > 0 ? ` Available datasets: ${available.join(", ")}.` : " No datasets were materialized for this run."),
21441
21639
  void 0,
21442
21640
  "RUN_EXPORT_EMPTY",
21443
21641
  {
@@ -21448,23 +21646,6 @@ function assertDatasetHasExportableRows(input2) {
21448
21646
  }
21449
21647
  );
21450
21648
  }
21451
- function assertDatasetExportAvailable(input2) {
21452
- if (input2.rowsInfo.exportUnavailableReason !== "shared_table_namespace") {
21453
- return;
21454
- }
21455
- throw new DeeplineError(
21456
- input2.rowsInfo.exportUnavailableMessage ?? "Run CSV export is unavailable because multiple Dataset Handles share one physical table.",
21457
- void 0,
21458
- "RUN_EXPORT_UNAVAILABLE",
21459
- {
21460
- runId: input2.status.runId,
21461
- dataset: input2.rowsInfo.source,
21462
- datasetId: input2.rowsInfo.datasetId ?? null,
21463
- tableNamespace: input2.rowsInfo.tableNamespace ?? null,
21464
- reason: input2.rowsInfo.exportUnavailableReason
21465
- }
21466
- );
21467
- }
21468
21649
  async function exportPlayStatusRows(client2, status, outPath, options = {}) {
21469
21650
  if (!outPath) {
21470
21651
  return null;
@@ -21543,7 +21724,6 @@ ${commands.join("\n")}`,
21543
21724
  `Run ${status.runId} did not expose a row-shaped final output to export.`
21544
21725
  );
21545
21726
  }
21546
- assertDatasetExportAvailable({ rowsInfo, status });
21547
21727
  const attempts = Math.max(1, Math.trunc(options.attempts ?? 1));
21548
21728
  const retryDelayMs = Math.max(0, Math.trunc(options.retryDelayMs ?? 0));
21549
21729
  for (let attempt = 1; attempt <= attempts; attempt += 1) {
@@ -21558,6 +21738,9 @@ ${commands.join("\n")}`,
21558
21738
  if (error instanceof DeeplineError && error.code === "RUN_EXPORT_SCOPE_MISMATCH") {
21559
21739
  throw error;
21560
21740
  }
21741
+ if (rowsInfo.currentTable) {
21742
+ throw error;
21743
+ }
21561
21744
  if (!rowsInfo.complete) {
21562
21745
  throw error;
21563
21746
  }
@@ -21571,7 +21754,8 @@ ${commands.join("\n")}`,
21571
21754
  });
21572
21755
  return {
21573
21756
  path: RunDataset.from(guarded2).exportCsv(outPath),
21574
- rowsInfo: guarded2
21757
+ rowsInfo: guarded2,
21758
+ currentTable: fetchedRowsInfo.currentTable === true
21575
21759
  };
21576
21760
  }
21577
21761
  if (rowsInfo.complete) {
@@ -21583,7 +21767,8 @@ ${commands.join("\n")}`,
21583
21767
  });
21584
21768
  return {
21585
21769
  path: RunDataset.from(guarded2).exportCsv(outPath),
21586
- rowsInfo: guarded2
21770
+ rowsInfo: guarded2,
21771
+ currentTable: false
21587
21772
  };
21588
21773
  }
21589
21774
  if (attempt < attempts && retryDelayMs > 0) {
@@ -21618,7 +21803,8 @@ ${commands.join("\n")}`,
21618
21803
  });
21619
21804
  return {
21620
21805
  path: RunDataset.from(guarded).exportCsv(outPath),
21621
- rowsInfo: guarded
21806
+ rowsInfo: guarded,
21807
+ currentTable: false
21622
21808
  };
21623
21809
  }
21624
21810
  function extractActiveRunsFromError(error) {
@@ -23482,12 +23668,13 @@ async function handleRunsList(args) {
23482
23668
  return 1;
23483
23669
  }
23484
23670
  const client2 = new DeeplineClient();
23485
- const runs = (await client2.runs.list({
23671
+ const page = await client2.runs.listPage({
23486
23672
  ...playName ? { play: playName } : {},
23487
23673
  ...statusFilter ? { status: statusFilter } : {},
23488
23674
  ...limit !== void 0 ? { limit } : {},
23489
23675
  ...offset !== void 0 ? { offset } : {}
23490
- })).map((run) => ({
23676
+ });
23677
+ const runs = page.runs.map((run) => ({
23491
23678
  runId: run.workflowId,
23492
23679
  // `workflowId` is the legacy SDK name for the same public Deepline run
23493
23680
  // identity. Keep it during the compatibility window, but never label the
@@ -23525,11 +23712,24 @@ async function handleRunsList(args) {
23525
23712
  if (run.rootRunId) lines2.push(` root: ${run.rootRunId}`);
23526
23713
  return lines2.join("\n");
23527
23714
  });
23715
+ const nextOffset = (page.offset ?? offset ?? 0) + runs.length;
23716
+ const nextPage = page.hasMore && playName ? `deepline runs list --play ${shellQuote2(playName)}${statusFilter ? ` --status ${shellQuote2(statusFilter)}` : ""} --limit ${page.limit ?? limit ?? 20} --offset ${nextOffset} --json` : null;
23717
+ if (page.hasMore) {
23718
+ lines.push("List truncated \u2014 more runs match this filter.");
23719
+ lines.push(
23720
+ nextPage ? `Next page: ${nextPage}` : "Narrow with --play <play-name> to page through runs."
23721
+ );
23722
+ }
23528
23723
  printCommandEnvelope(
23529
23724
  {
23530
23725
  runs,
23531
23726
  count: runs.length,
23727
+ ...page.total !== void 0 ? { total: page.total } : {},
23728
+ offset: page.offset ?? offset ?? 0,
23729
+ limit: page.limit ?? limit ?? (playName ? 20 : 100),
23730
+ ...page.hasMore !== void 0 ? { has_more: page.hasMore, is_truncated: page.hasMore } : {},
23532
23731
  next: {
23732
+ page: nextPage,
23533
23733
  get: runs[0]?.runId ? `deepline runs get ${runs[0].runId} --json` : null
23534
23734
  },
23535
23735
  render: { sections: [{ title: "runs", lines }] }
@@ -23955,6 +24155,11 @@ async function handleRunExport(args) {
23955
24155
  datasetPath
23956
24156
  });
23957
24157
  const source = exportResult?.rowsInfo.source ?? datasetPath ?? null;
24158
+ const currentTableNotice = exportResult?.currentTable ? {
24159
+ code: "CURRENT_SHARED_DATASET",
24160
+ message: "This CSV is the current shared dataset and may include writes from another run.",
24161
+ full_run_output_command: `deepline runs get ${status.runId} --full --json`
24162
+ } : null;
23958
24163
  const next = {
23959
24164
  ...buildRunNextCommands(status),
23960
24165
  export: runExportRetryCommand(status.runId, outPath, datasetPath ?? source)
@@ -23966,6 +24171,7 @@ async function handleRunExport(args) {
23966
24171
  source,
23967
24172
  rowCount: exportResult?.rowsInfo.totalRows ?? null,
23968
24173
  columns: exportResult?.rowsInfo.columns ?? [],
24174
+ ...currentTableNotice ? { notice: currentTableNotice } : {},
23969
24175
  ...metadataOutPath ? { metadata_path: metadataOutPath } : {},
23970
24176
  local: { csv_path: exportResult?.path ?? null },
23971
24177
  next,
@@ -23975,6 +24181,10 @@ async function handleRunExport(args) {
23975
24181
  title: "run export",
23976
24182
  lines: [
23977
24183
  `Exported ${status.runId} to ${exportResult?.path ?? outPath}`,
24184
+ ...currentTableNotice ? [
24185
+ "Current shared dataset: this CSV may include writes from another run.",
24186
+ `This run's full returned output: ${currentTableNotice.full_run_output_command}`
24187
+ ] : [],
23978
24188
  ...source ? [`source=${source}`] : []
23979
24189
  ]
23980
24190
  }
@@ -24177,23 +24387,47 @@ async function handlePlayVersions(args) {
24177
24387
  }
24178
24388
  return 0;
24179
24389
  }
24390
+ function formatPlayCostEstimate(estimate) {
24391
+ if (!estimate || estimate.status === "unavailable") {
24392
+ return `unavailable${estimate ? `: ${estimate.message}` : ""}`;
24393
+ }
24394
+ const formatCredits = (value) => value.toLocaleString("en-US", {
24395
+ maximumFractionDigits: value < 1 ? 4 : 2
24396
+ });
24397
+ const credits = estimate.lowCredits === estimate.highCredits ? `${estimate.source === "observed" ? "~" : ""}${formatCredits(estimate.lowCredits)}` : `${formatCredits(estimate.lowCredits)}\u2013${formatCredits(estimate.highCredits)}`;
24398
+ const unit = estimate.unit === "row" ? "output row" : "run";
24399
+ const source = estimate.source === "observed" ? `observed from ${estimate.sampleRunCount} ${estimate.sampleRunCount === 1 ? "run" : "runs"}` : "static estimate";
24400
+ return `${credits} Deepline credits per ${unit} (${source})`;
24401
+ }
24180
24402
  async function handlePlayList(args) {
24181
24403
  const jsonOutput = argsWantJson(args);
24404
+ const showCost = args.includes("--show-cost");
24182
24405
  const client2 = new DeeplineClient();
24183
24406
  const categoriesIndex = args.indexOf("--categories");
24184
24407
  const categories = categoriesIndex >= 0 ? args[categoriesIndex + 1]?.trim() : void 0;
24185
- const plays = await client2.listPlays({
24408
+ const limitIndex = args.indexOf("--limit");
24409
+ const cursorIndex = args.indexOf("--cursor");
24410
+ const limit = limitIndex >= 0 ? Number(args[limitIndex + 1]) : void 0;
24411
+ const cursor = cursorIndex >= 0 ? args[cursorIndex + 1] : void 0;
24412
+ if (limitIndex >= 0 && (!Number.isSafeInteger(limit) || limit < 1) || cursorIndex >= 0 && !cursor?.trim()) {
24413
+ console.error("Pass a positive --limit and a non-empty --cursor.");
24414
+ return 2;
24415
+ }
24416
+ const page = await client2.listPlaysPage({
24186
24417
  categories,
24187
- includeToolCategories: true
24188
- });
24189
- if (jsonOutput) {
24190
- process.stdout.write(`${JSON.stringify(plays)}
24191
- `);
24192
- return 0;
24418
+ includeToolCategories: true,
24419
+ ...showCost ? { includeCostEstimates: true } : {},
24420
+ limit,
24421
+ cursor
24422
+ });
24423
+ const plays = page.plays;
24424
+ const nextPage = page.hasMore && page.cursor ? `deepline plays list${categories ? ` --categories ${shellQuote2(categories)}` : ""}${limit ? ` --limit ${limit}` : ""}${showCost ? " --show-cost" : ""} --cursor ${shellQuote2(page.cursor)} --json` : null;
24425
+ if (page.hasMore && !nextPage) {
24426
+ throw new Error(
24427
+ "Play list reported more results without a continuation cursor"
24428
+ );
24193
24429
  }
24194
- process.stdout.write(`${plays.length} plays available:
24195
-
24196
- `);
24430
+ const lines = [`${plays.length} plays in this page:`];
24197
24431
  for (const play of plays) {
24198
24432
  const flags = [
24199
24433
  play.pinned ? "pinned" : null,
@@ -24203,32 +24437,48 @@ async function handlePlayList(args) {
24203
24437
  play.isDraftDirty ? "draft-dirty" : null
24204
24438
  ].filter(Boolean).join(", ");
24205
24439
  const reference = formatPlayListReference(play);
24206
- process.stdout.write(` ${reference}${flags ? ` [${flags}]` : ""}
24207
- `);
24440
+ lines.push(` ${reference}${flags ? ` [${flags}]` : ""}`);
24208
24441
  if (play.inputSchema || play.hasInputSchema) {
24209
- process.stdout.write(" inputSchema: yes\n");
24442
+ lines.push(" inputSchema: yes");
24210
24443
  }
24211
24444
  if (play.triggerStatus?.cron) {
24212
- process.stdout.write(
24213
- ` scheduled execution: ${cronExecutionLabel(play.triggerStatus.cron)}
24214
- `
24445
+ lines.push(
24446
+ ` scheduled execution: ${cronExecutionLabel(play.triggerStatus.cron)}`
24215
24447
  );
24216
24448
  if (play.triggerStatus.blockedReason) {
24217
- process.stdout.write(
24218
- ` schedule issue: ${play.triggerStatus.blockedReason}
24219
- `
24220
- );
24449
+ lines.push(` schedule issue: ${play.triggerStatus.blockedReason}`);
24221
24450
  }
24222
24451
  } else {
24223
- process.stdout.write(" scheduled execution: not configured\n");
24452
+ lines.push(" scheduled execution: not configured");
24224
24453
  }
24225
24454
  if (play.triggerStatus?.webhook) {
24226
- process.stdout.write(` webhook: ${play.triggerStatus.webhook}
24227
- `);
24455
+ lines.push(` webhook: ${play.triggerStatus.webhook}`);
24228
24456
  }
24229
- process.stdout.write(` run: deepline plays run ${reference} --watch
24230
- `);
24457
+ if (showCost) {
24458
+ lines.push(
24459
+ ` cost estimate: ${formatPlayCostEstimate(play.costEstimate)}`
24460
+ );
24461
+ }
24462
+ lines.push(` run: deepline plays run ${reference} --watch`);
24463
+ }
24464
+ if (page.hasMore) {
24465
+ lines.push("List truncated \u2014 more plays are available.");
24466
+ lines.push(`Next page: ${nextPage}`);
24231
24467
  }
24468
+ printCommandEnvelope(
24469
+ {
24470
+ plays,
24471
+ count: plays.length,
24472
+ has_more: page.hasMore,
24473
+ is_truncated: page.hasMore,
24474
+ next_cursor: page.cursor,
24475
+ next: { page: nextPage },
24476
+ render: {
24477
+ sections: [{ title: "plays", lines }]
24478
+ }
24479
+ },
24480
+ { json: jsonOutput }
24481
+ );
24232
24482
  return 0;
24233
24483
  }
24234
24484
  async function handlePlayPin(args, pinned) {
@@ -24392,51 +24642,18 @@ function compactPlaySchema(schema) {
24392
24642
  ).filter((field) => Boolean(field?.name)) : [];
24393
24643
  return fields.length > 0 ? { fields } : schema;
24394
24644
  }
24395
- function playSchemaMetadata(schema, key) {
24396
- if (!schema || typeof schema !== "object" || Array.isArray(schema))
24397
- return null;
24398
- const value = schema[key];
24399
- return value && typeof value === "object" && !Array.isArray(value) ? value : null;
24400
- }
24401
- function playRunCommand(play, options) {
24402
- const target = play.reference || play.name;
24403
- if (options?.csvInput) {
24404
- const inputField = typeof options.csvInput.inputField === "string" && options.csvInput.inputField.trim() ? options.csvInput.inputField.trim() : "csv";
24405
- return `deepline plays run ${target} --input '${JSON.stringify({ [inputField]: "leads.csv" })}' --watch`;
24406
- }
24407
- return `deepline plays run ${target} --input '{...}' --watch`;
24408
- }
24409
- function summarizePlayListItemForCli(play, options) {
24410
- const aliases = play.aliases ?? [];
24411
- const csvInput = playSchemaMetadata(play.inputSchema, "csvInput");
24412
- const rowOutputSchema = playSchemaMetadata(
24413
- play.outputSchema,
24414
- "rowOutputSchema"
24415
- );
24416
- const runCommand2 = playRunCommand(play, { csvInput });
24417
- const cloneEditStarter = buildCloneEditStarter(play);
24645
+ function summarizePlayGrepResult(play) {
24646
+ const reference = formatPlayListReference(play);
24418
24647
  return {
24419
- name: play.name,
24420
- ...play.reference ? { reference: play.reference } : {},
24421
- ...play.displayName ? { displayName: play.displayName } : {},
24422
- pinned: Boolean(play.pinned),
24423
- toolCategories: play.toolCategories ?? [],
24424
- origin: play.origin,
24425
- ownerType: play.ownerType,
24426
- canEdit: play.canEdit,
24427
- canClone: play.canClone,
24428
- aliases,
24429
- inputSchema: options?.compact ? compactPlaySchema(play.inputSchema) : play.inputSchema ?? null,
24430
- outputSchema: options?.compact ? compactPlaySchema(play.outputSchema) : play.outputSchema ?? null,
24431
- ...csvInput ? { csvInput } : {},
24432
- ...rowOutputSchema ? { rowOutputSchema } : {},
24433
- runCommand: runCommand2,
24434
- examples: [runCommand2],
24435
- ...cloneEditStarter ? { cloneEditStarter } : {},
24436
- currentPublishedVersion: play.currentPublishedVersion ?? null,
24437
- isDraftDirty: play.isDraftDirty
24648
+ name: play.displayName?.trim() || play.name,
24649
+ reference,
24650
+ matches: play.matches ?? [],
24651
+ describe: `deepline plays describe ${reference} --json`
24438
24652
  };
24439
24653
  }
24654
+ function formatPlayGrepMatches(matches) {
24655
+ return matches.map((match) => `${match.field}: ${match.terms.join(", ")}`).join("; ");
24656
+ }
24440
24657
  async function handlePlaySearch(args) {
24441
24658
  let options;
24442
24659
  try {
@@ -24492,84 +24709,35 @@ async function handlePlaySearch(args) {
24492
24709
  }
24493
24710
  return 0;
24494
24711
  }
24495
- function normalizePlayGrepText(value) {
24496
- if (value === null || value === void 0) return "";
24497
- if (typeof value === "string") return value.toLowerCase();
24498
- if (typeof value === "number" || typeof value === "boolean") {
24499
- return String(value).toLowerCase();
24500
- }
24501
- if (Array.isArray(value)) return value.map(normalizePlayGrepText).join(" ");
24502
- if (typeof value === "object") {
24503
- return Object.values(value).map(normalizePlayGrepText).join(" ");
24504
- }
24505
- return "";
24506
- }
24507
- function parsePlayGrepTerms(query, mode) {
24508
- const trimmed = query.trim().toLowerCase();
24509
- if (!trimmed) return [];
24510
- if (mode === "phrase") return [trimmed];
24511
- const matches = trimmed.match(/"([^"]+)"|'([^']+)'|\S+/g) ?? [];
24512
- return matches.map((term) => term.replace(/^["']|["']$/g, "").trim()).filter(Boolean);
24513
- }
24514
- function matchesPlayGrepQuery(value, query, mode) {
24515
- const terms = parsePlayGrepTerms(query, mode);
24516
- if (terms.length === 0) return true;
24517
- const haystack = normalizePlayGrepText(value);
24518
- if (mode === "any") return terms.some((term) => haystack.includes(term));
24519
- return terms.every((term) => haystack.includes(term));
24520
- }
24521
24712
  async function handlePlayGrep(args) {
24522
24713
  const query = args[0]?.trim();
24523
24714
  if (!query) {
24524
- console.error(
24525
- "Usage: deepline plays grep <query> [--mode all|any|phrase] [--compact] [--json]"
24526
- );
24715
+ console.error("Usage: deepline plays grep <query> [--json]");
24527
24716
  return 1;
24528
24717
  }
24529
- let mode = "all";
24530
- for (let index = 1; index < args.length; index += 1) {
24531
- const arg = args[index];
24532
- if (arg === "--mode" && args[index + 1]) {
24533
- const rawMode = args[++index].trim().toLowerCase();
24534
- mode = rawMode === "any" || rawMode === "phrase" ? rawMode : "all";
24535
- }
24536
- }
24537
- const compact = args.includes("--compact");
24538
24718
  const client2 = new DeeplineClient();
24539
- const plays = (await client2.listPlays({
24540
- grep: query,
24541
- grepMode: mode
24542
- })).filter(
24543
- (play) => matchesPlayGrepQuery(
24544
- {
24545
- name: play.name,
24546
- reference: play.reference,
24547
- displayName: play.displayName,
24548
- origin: play.origin,
24549
- ownerType: play.ownerType,
24550
- aliases: play.aliases,
24551
- toolCategories: play.toolCategories,
24552
- inputSchema: play.inputSchema,
24553
- outputSchema: play.outputSchema
24554
- },
24555
- query,
24556
- mode
24557
- )
24558
- ).map((play) => summarizePlayListItemForCli(play, { compact }));
24719
+ const results = (await client2.listPlays({ grep: query })).map(
24720
+ summarizePlayGrepResult
24721
+ );
24559
24722
  if (argsWantJson(args)) {
24560
24723
  printCompactJson({
24561
- plays,
24562
- count: plays.length,
24724
+ plays: results,
24725
+ count: results.length,
24563
24726
  query,
24564
- grep: { mode, terms: parsePlayGrepTerms(query, mode) }
24727
+ grep: { query }
24565
24728
  });
24566
24729
  return 0;
24567
24730
  }
24568
- process.stdout.write(`${plays.length} plays found:
24731
+ process.stdout.write(
24732
+ `${results.length} results for ${JSON.stringify(query)}:
24569
24733
 
24570
- `);
24571
- for (const play of plays) {
24572
- printPlayDescription(play);
24734
+ `
24735
+ );
24736
+ for (const result of results) {
24737
+ console.log(result.name);
24738
+ const matches = formatPlayGrepMatches(result.matches);
24739
+ if (matches) console.log(` Matched: ${matches}`);
24740
+ console.log(` Describe: ${result.describe}`);
24573
24741
  console.log("");
24574
24742
  }
24575
24743
  return 0;
@@ -25269,7 +25437,7 @@ Pass-through input flags:
25269
25437
  if (effectiveTarget && passthroughArgs[0] === effectiveTarget) {
25270
25438
  passthroughArgs.shift();
25271
25439
  }
25272
- process.exitCode = await handlePlayRun([
25440
+ const exitCode = await handlePlayRun([
25273
25441
  ...effectiveTarget ? [effectiveTarget] : [],
25274
25442
  ...options.file ? ["--file", options.file] : [],
25275
25443
  ...options.name ? ["--name", options.name] : [],
@@ -25299,6 +25467,11 @@ Pass-through input flags:
25299
25467
  ...options.full ? ["--full"] : [],
25300
25468
  ...passthroughArgs
25301
25469
  ]);
25470
+ recordCliTrace({
25471
+ phase: "cli.play_command_exit",
25472
+ exitCode
25473
+ });
25474
+ process.exitCode = exitCode;
25302
25475
  });
25303
25476
  registerPlayBootstrapCommand(play);
25304
25477
  play.command("get <target>").description(
@@ -25340,17 +25513,22 @@ Examples:
25340
25513
  `
25341
25514
  Notes:
25342
25515
  Inventory command for saved org plays and prebuilt plays. Use search for
25343
- ranked discovery by task or schema.
25516
+ ranked discovery by task or schema. Returns one bounded page with has_more,
25517
+ is_truncated, next_cursor, and a next-page command. Use --limit to choose
25518
+ the page size and --cursor to continue with the same filters.
25344
25519
 
25345
25520
  Examples:
25346
25521
  deepline plays list
25347
25522
  deepline plays search email --json
25348
25523
  `
25349
- ).option("--json", "Emit JSON output. Also automatic when stdout is piped").option(
25524
+ ).option("--limit <count>", "Page size").option("--cursor <cursor>", "Continue a previous page").option("--show-cost", "Include the per-row or per-run cost estimate").option("--json", "Emit JSON output. Also automatic when stdout is piped").option(
25350
25525
  "--categories <categories>",
25351
25526
  "Filter by comma-separated canonical tool categories"
25352
25527
  ).action(async (options) => {
25353
25528
  process.exitCode = await handlePlayList([
25529
+ ...options.limit ? ["--limit", options.limit] : [],
25530
+ ...options.cursor ? ["--cursor", options.cursor] : [],
25531
+ ...options.showCost ? ["--show-cost"] : [],
25354
25532
  ...options.categories ? ["--categories", options.categories] : [],
25355
25533
  ...options.json ? ["--json"] : []
25356
25534
  ]);
@@ -25389,13 +25567,13 @@ Notes:
25389
25567
  because they are trusted, robust plays with maintained contracts. Use describe
25390
25568
  on a result before running it.
25391
25569
  Add --all only when you are specifically looking for a play you created.
25392
- The grep alias is the same ranked retrieval surface with a more literal name
25393
- for agents that are filtering the play registry.
25570
+ Use plays grep to search active org-owned Plays through Convex's indexed
25571
+ authored corpus. It does not search prebuilt or archived Plays.
25394
25572
 
25395
25573
  Examples:
25396
25574
  deepline plays search email
25397
25575
  deepline plays search email --all
25398
- deepline plays grep "linkedin to email" --compact --json
25576
+ deepline plays grep "linkedin to email" --json
25399
25577
  deepline plays describe prebuilt/person-linkedin-to-email --json
25400
25578
  `
25401
25579
  ).option("--compact", "Emit compact schemas").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (query, options) => {
@@ -25408,25 +25586,22 @@ Examples:
25408
25586
  ]);
25409
25587
  });
25410
25588
  addPlaySearchCommand(play.command("search <query>"));
25411
- play.command("grep <query>").description("Literal grep over play names, schemas, and descriptions.").addHelpText(
25589
+ play.command("grep <query>").description(
25590
+ "Search active org-owned Plays through Convex full-text search."
25591
+ ).addHelpText(
25412
25592
  "after",
25413
25593
  `
25414
25594
  Notes:
25415
- Literal registry filtering. Terms are matched case-insensitively against play
25416
- names, references, display names, ownership, and schemas. Use
25417
- --mode phrase for exact phrase matching, --mode any for OR, and the default
25418
- --mode all for AND.
25595
+ Queries use Convex token semantics over the indexed authored Play corpus.
25596
+ Prebuilt and archived Plays are not part of this index.
25419
25597
 
25420
25598
  Examples:
25421
25599
  deepline plays grep email --json
25422
- deepline plays grep "company contact" --mode all --json
25423
25600
  deepline plays describe prebuilt/company-to-contact --json
25424
25601
  `
25425
- ).option("--compact", "Emit compact schemas").option("--mode <mode>", "Grep matching mode: all, any, or phrase").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (query, options) => {
25602
+ ).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (query, options) => {
25426
25603
  process.exitCode = await handlePlayGrep([
25427
25604
  query,
25428
- ...options.compact ? ["--compact"] : [],
25429
- ...options.mode ? ["--mode", options.mode] : [],
25430
25605
  ...options.json ? ["--json"] : []
25431
25606
  ]);
25432
25607
  });
@@ -31024,7 +31199,7 @@ async function compileConfig(input2) {
31024
31199
  })).config;
31025
31200
  }
31026
31201
  function registerEnrichCommand(program) {
31027
- program.command("enrich").allowUnknownOption(true).description("Run v1-style CSV enrichment through the V2 play runner.").configureHelp({
31202
+ program.command("enrich", { hidden: true }).allowUnknownOption(true).description("Run v1-style CSV enrichment through the V2 play runner.").configureHelp({
31028
31203
  optionTerm(option) {
31029
31204
  return option.long === "--timeout" ? "--timeout SECONDS" : option.flags;
31030
31205
  }
@@ -32087,7 +32262,7 @@ function loadViewerAssets() {
32087
32262
  "viewer"
32088
32263
  )
32089
32264
  ] : [],
32090
- join12(process.cwd(), "src", "lib", "cli", "viewer")
32265
+ join12(process.cwd(), "packages", "sdk", "assets", "viewer")
32091
32266
  ];
32092
32267
  for (const root of candidateRoots2) {
32093
32268
  try {
@@ -32304,7 +32479,7 @@ function addDeprecatedSubcommand(parent, family, subcommand, description) {
32304
32479
  });
32305
32480
  }
32306
32481
  function registerDeprecatedCommands(program) {
32307
- const session = program.command("session").description("Deprecated legacy session command namespace.").allowUnknownOption(true).allowExcessArguments(true).option("--json", "Emit JSON output").argument("[args...]").addHelpText(
32482
+ const session = program.command("session", { hidden: true }).description("Deprecated legacy session command namespace.").allowUnknownOption(true).allowExcessArguments(true).option("--json", "Emit JSON output").argument("[args...]").addHelpText(
32308
32483
  "after",
32309
32484
  `
32310
32485
  Notes:
@@ -32336,7 +32511,7 @@ Examples:
32336
32511
  `Deprecated legacy "deepline session ${subcommand}" command.`
32337
32512
  );
32338
32513
  }
32339
- const backend = program.command("backend").description("Deprecated legacy local backend command namespace.").allowUnknownOption(true).allowExcessArguments(true).option("--json", "Emit JSON output").argument("[args...]").addHelpText(
32514
+ const backend = program.command("backend", { hidden: true }).description("Deprecated legacy local backend command namespace.").allowUnknownOption(true).allowExcessArguments(true).option("--json", "Emit JSON output").argument("[args...]").addHelpText(
32340
32515
  "after",
32341
32516
  `
32342
32517
  Notes:
@@ -32372,7 +32547,7 @@ import { readFileSync as readFileSync11, writeFileSync as writeFileSync12 } from
32372
32547
  import { resolve as resolve14 } from "path";
32373
32548
  import { createInterface } from "readline/promises";
32374
32549
 
32375
- // src/monitor-fleet-contract.ts
32550
+ // ../integration-contracts/monitor-fleet-contract.ts
32376
32551
  var MONITOR_FLEET_MAX_MEMBERS = 1e3;
32377
32552
  var MONITOR_FLEET_AUTHORING_CONTRACT_EDITION = 1;
32378
32553
  var SUPPORTED_MONITOR_FLEET_AUTHORING_CONTRACT_EDITIONS = [
@@ -33058,9 +33233,35 @@ function renderMonitorDeployPlan(payload) {
33058
33233
  " Inspect: deepline monitors get <key> --json"
33059
33234
  );
33060
33235
  }
33236
+ const identityConflict = asRecord2(payload.identity_conflict);
33237
+ const identityOwner = identityConflict ? asRecord2(identityConflict.existing_monitor) : null;
33238
+ const identityOwnerKey = identityOwner ? asString(identityOwner.key) : void 0;
33239
+ const identityOwnerStatus = identityOwner ? asString(identityOwner.status) : void 0;
33240
+ if (identityConflict) {
33241
+ if (identityOwnerStatus === "provisioning") {
33242
+ lines.push(
33243
+ "",
33244
+ "An in-progress provider operation owns this upstream identity.",
33245
+ "Do not deploy this key yet. Wait, then rerun this dry run."
33246
+ );
33247
+ } else if (identityOwnerKey) {
33248
+ lines.push(
33249
+ "",
33250
+ `An existing monitor owns this upstream identity: ${identityOwnerKey}.`,
33251
+ `Inspect: deepline monitors get ${identityOwnerKey} --json`,
33252
+ "Do not deploy this key unless that conflict is resolved."
33253
+ );
33254
+ } else {
33255
+ lines.push(
33256
+ "",
33257
+ "An existing monitor owns this upstream identity.",
33258
+ "Do not deploy this key until that conflict is resolved."
33259
+ );
33260
+ }
33261
+ }
33061
33262
  lines.push(
33062
33263
  "",
33063
- valid ? "Deploy for real: re-run this command without --dry-run." : "Fix the definition, then re-run this command."
33264
+ identityConflict ? "Do not deploy for real until this identity conflict clears." : valid ? "Deploy for real: re-run this command without --dry-run." : "Fix the definition, then re-run this command."
33064
33265
  );
33065
33266
  return `${lines.join("\n")}
33066
33267
  `;
@@ -33312,11 +33513,12 @@ async function handleMonitorsDeploy(definition, options) {
33312
33513
  dryRun: true
33313
33514
  });
33314
33515
  const valid = payload2.valid !== false;
33516
+ const hasIdentityConflict = Boolean(asRecord2(payload2)?.identity_conflict);
33315
33517
  printCommandEnvelope(
33316
33518
  { dry_run: true, ...payload2 },
33317
33519
  { json: options.json, text: renderMonitorDeployPlan(payload2) }
33318
33520
  );
33319
- if (!valid) {
33521
+ if (!valid || hasIdentityConflict) {
33320
33522
  process.exitCode = 7;
33321
33523
  }
33322
33524
  return;
@@ -34347,11 +34549,13 @@ function monitorHealthLine(health) {
34347
34549
  if (health.refresh?.state === "running") {
34348
34550
  return `refreshing whole scope \xB7 scanned ${health.scanned} so far`;
34349
34551
  }
34552
+ const alignmentRequired = health.alignment_required ?? 0;
34350
34553
  return [
34351
34554
  `converged ${health.converged}/${health.scanned}`,
34352
34555
  `needs_repair ${health.needs_repair}`,
34353
34556
  `missing ${health.observed.missing}`,
34354
34557
  `unaudited ${health.observed.unknown + health.observed.unset}`,
34558
+ ...alignmentRequired > 0 ? [`needs_alignment ${alignmentRequired}`] : [],
34355
34559
  `silent ${health.silent}`
34356
34560
  ].join(" \xB7 ");
34357
34561
  }
@@ -34385,7 +34589,9 @@ async function watchMonitorHealth(input2) {
34385
34589
  let last = await input2.client.monitors.health(scope);
34386
34590
  input2.onProgress(last);
34387
34591
  while (Date.now() < deadlineAt) {
34388
- if (last.refresh?.state !== "running" && last.needs_repair === 0 && last.observed.unknown === 0) {
34592
+ const unresolved = last.observed.unknown + last.observed.unset;
34593
+ const alignmentRequired = last.alignment_required ?? 0;
34594
+ if (last.refresh?.state !== "running" && !last.truncated && last.needs_repair === 0 && (unresolved === 0 || alignmentRequired === unresolved)) {
34389
34595
  return last;
34390
34596
  }
34391
34597
  await new Promise(
@@ -34398,6 +34604,7 @@ async function watchMonitorHealth(input2) {
34398
34604
  }
34399
34605
  function monitorHealthText(health) {
34400
34606
  const partial = health.refresh?.state === "running" ? " (refreshing \u2014 counts below are not final)" : health.truncated ? " (partial \u2014 scope larger than one read)" : "";
34607
+ const unauditedMonitors = health.unaudited_monitors ?? [];
34401
34608
  const lines = [
34402
34609
  `scope: ${health.scope.fleet_id ?? "workspace"}${partial}`,
34403
34610
  monitorHealthLine(health)
@@ -34420,6 +34627,29 @@ function monitorHealthText(health) {
34420
34627
  lines.push(` ${entry.reason} (${entry.count})${how}`);
34421
34628
  }
34422
34629
  }
34630
+ if (unauditedMonitors.length > 0) {
34631
+ const reason = {
34632
+ not_yet_audited: "has not been observed yet",
34633
+ missing_provider_resource_id: "has no stored upstream resource id",
34634
+ provider_observation_unknown: "the provider observation is still unknown"
34635
+ };
34636
+ lines.push("");
34637
+ lines.push("unresolved monitor observations:");
34638
+ for (const entry of unauditedMonitors) {
34639
+ lines.push(
34640
+ ` ${entry.monitor_key} ${entry.tool} \u2014 ${reason[entry.reason]}`
34641
+ );
34642
+ }
34643
+ }
34644
+ if ((health.alignment_required ?? 0) > 0) {
34645
+ lines.push("");
34646
+ lines.push(
34647
+ `${health.alignment_required} monitor(s) need provider identity alignment; normal repair intentionally will not guess or create a paid replacement.`
34648
+ );
34649
+ lines.push(
34650
+ `Run the exact inventory audit, then review one safe adoption candidate: deepline-admin monitors reconcile ${health.scope.org_id} --monitor <monitor-key> --environment production --json`
34651
+ );
34652
+ }
34423
34653
  if (health.worst_offenders.length > 0) {
34424
34654
  lines.push("");
34425
34655
  lines.push(
@@ -34644,9 +34874,8 @@ Exit codes:
34644
34874
 
34645
34875
  Examples:
34646
34876
  deepline monitors status --json
34647
- deepline monitors available --json # compact list by default
34648
- deepline monitors available --full --json # complete catalog
34649
- deepline monitors available deepline_native.company_radar --json
34877
+ deepline tools list --categories monitors --json
34878
+ deepline tools get deepline_native.company_radar --json
34650
34879
  deepline monitors check '{"key":"job-openings","tool":"deepline_native.company_radar","payload":{"domain":"stripe.com","radar_type":"company_job_openings"}}'
34651
34880
  deepline monitors deploy --dry-run --file monitor.json
34652
34881
  deepline monitors deploy --file monitor.json
@@ -34816,7 +35045,7 @@ Examples:
34816
35045
  )
34817
35046
  ).action(monitorsAction(handleMonitorsStatus));
34818
35047
  withJsonOption(
34819
- monitors.command("available [tool-id]").alias("tools").description(
35048
+ monitors.command("available [tool-id]", { hidden: true }).alias("tools").description(
34820
35049
  "List the monitor types you can deploy, or describe one by tool id."
34821
35050
  ).addHelpText(
34822
35051
  "after",
@@ -34933,7 +35162,7 @@ Notes:
34933
35162
  Play delivery. The JSON response reports this validation scope explicitly.
34934
35163
  Provider-specific grammar, precedence, enum applicability, examples, and
34935
35164
  update semantics are returned by the live monitor contract. Inspect it with
34936
- \`deepline monitors available deepline_native.company_radar --json\`.
35165
+ \`deepline tools get deepline_native.company_radar --json\`.
34937
35166
  For a bounded urgent Deepline Native preview, use
34938
35167
  controls.execution_type="priority". Deepline injects the upstream marker;
34939
35168
  do not author custom_fields yourself. Priority is capped at ten upstream or
@@ -34971,6 +35200,10 @@ Notes:
34971
35200
  no separate repair command or retry queue: rerun the same deploy/update.
34972
35201
  Scheduled reconciliation can also finish that exact saved cleanup; it never
34973
35202
  creates another monitor.
35203
+ For TamRadar, deliberately changing payload.updates_since is an explicit
35204
+ historical replay request, including when redeploying a disabled monitor.
35205
+ Deepline preserves that selected boundary; filter-only deploys and ordinary
35206
+ reactivation start from a fresh future-only source boundary instead.
34974
35207
  For a bounded urgent Deepline Native preview, set
34975
35208
  controls.execution_type="priority". Deepline injects the provider custom
34976
35209
  field and enforces a ten-slot per-org cap; do not use it for regular or bulk
@@ -35000,6 +35233,11 @@ positionally, via --file <path>, or from stdin with --file -.
35000
35233
  When <patch> includes payload, its top-level fields are merged with the stored
35001
35234
  payload before validation. This lets you change one filter without resending
35002
35235
  domain or radar_type; nested values and arrays replace atomically.
35236
+ For TamRadar, changing payload.updates_since is an explicit historical replay
35237
+ request. Deepline passes that requested boundary upstream, but previously
35238
+ delivered canonical findings are deduplicated before dispatch and billing; only
35239
+ previously unseen historical findings are chargeable. Filter-only updates,
35240
+ repair, and reactivation instead use a fresh future-only source boundary.
35003
35241
  Use {"controls":{"execution_type":"priority"}} only for a bounded urgent
35004
35242
  Deepline Native preview. The ten-radar priority cap applies on update too.
35005
35243
  Use {"controls":{"execution_type":null}} to release priority without
@@ -35086,7 +35324,7 @@ ${MONITOR_FLEET_HELP_EPILOG}`
35086
35324
  Creates a ready-to-review JSON definition. Fleets always sync ${MONITOR_FLEET_DOCUMENTATION.fixedPolicy.cadence} and retain
35087
35325
  a missing member for ${MONITOR_FLEET_DOCUMENTATION.fixedPolicy.removalGrace} before it is ${MONITOR_FLEET_DOCUMENTATION.fixedPolicy.onRemoved}d; those
35088
35326
  policies are not authored in the file. ${MONITOR_FLEET_DOCUMENTATION.stickyMembership} The payload remains the actual monitor payload for the chosen tool, so use
35089
- \`deepline monitors available\` to discover a tool first.
35327
+ \`deepline tools list --categories monitors\` to discover a tool first.
35090
35328
 
35091
35329
  Example:
35092
35330
  deepline monitors fleets init account-job-openings \\
@@ -36079,7 +36317,7 @@ Examples:
36079
36317
  )
36080
36318
  ).action(handleOrgSwitch);
36081
36319
  addOrgSetOptions(
36082
- org.command("switch [selection]").description(
36320
+ org.command("switch [selection]", { hidden: true }).description(
36083
36321
  "Deprecated alias for org set. Set the organization for the selected auth scope."
36084
36322
  ).addHelpText(
36085
36323
  "after",
@@ -36106,6 +36344,9 @@ Examples:
36106
36344
 
36107
36345
  // src/cli/commands/git.ts
36108
36346
  var GIT_DEPLOY_FEATURE = "github-deploy";
36347
+ function shellQuote3(value) {
36348
+ return `'${value.replace(/'/g, `'\\''`)}'`;
36349
+ }
36109
36350
  function renderProject(project) {
36110
36351
  const root = project.rootDirectory ? ` (${project.rootDirectory})` : "";
36111
36352
  const flags = [
@@ -36144,6 +36385,98 @@ async function handleList(options) {
36144
36385
  { json: options.json }
36145
36386
  );
36146
36387
  }
36388
+ function describeInstallationStatus(installation) {
36389
+ switch (installation.status) {
36390
+ case "active":
36391
+ return [
36392
+ `Connected to ${installation.accountLogin} (installation ${installation.installationId}).`
36393
+ ];
36394
+ case "uninstalled":
36395
+ return [
36396
+ `The Deepline GitHub App was uninstalled from ${installation.accountLogin}${installation.uninstalledAt ? ` at ${new Date(installation.uninstalledAt).toISOString()}` : ""}.`,
36397
+ "Deploys are paused for every linked repository. Run `deepline git connect`, then `deepline git link <owner/repo>` again for each repository; links from the old installation cannot be resumed."
36398
+ ];
36399
+ case "suspended":
36400
+ return [
36401
+ `GitHub suspended the Deepline App on ${installation.accountLogin}${installation.suspendedAt ? ` at ${new Date(installation.suspendedAt).toISOString()}` : ""}.`,
36402
+ "Pushes are not delivered while it is suspended; unsuspend it in GitHub settings."
36403
+ ];
36404
+ }
36405
+ }
36406
+ async function handleStatus2(options) {
36407
+ const { http } = getAuthedHttpClient();
36408
+ const payload = await http.get("/api/v2/github/installation");
36409
+ const installation = payload.installation;
36410
+ const others = (payload.installations ?? []).filter(
36411
+ (row) => row.installationId !== installation?.installationId
36412
+ );
36413
+ const lines = installation ? describeInstallationStatus(installation) : [
36414
+ "No GitHub installation is connected to this workspace. Run `deepline git connect`."
36415
+ ];
36416
+ for (const other of others) {
36417
+ lines.push(
36418
+ `Also: ${other.accountLogin} (installation ${other.installationId}) is ${other.status}.`
36419
+ );
36420
+ }
36421
+ const byId = new Map(
36422
+ (payload.installations ?? []).map((row) => [row.installationId, row])
36423
+ );
36424
+ const { projects } = await http.get(
36425
+ "/api/v2/play-projects?includeDisabled=1"
36426
+ );
36427
+ const affected_links = projects.map((project) => {
36428
+ const own = byId.get(project.installationId);
36429
+ const verdict = !own ? "unknown" : own.status === "active" ? null : own.status;
36430
+ return verdict ? {
36431
+ id: project.id,
36432
+ repoId: project.repoId,
36433
+ repoFullName: project.repoFullName,
36434
+ rootDirectory: project.rootDirectory,
36435
+ productionBranch: project.productionBranch,
36436
+ manifestPath: project.manifestPath,
36437
+ checkOnPullRequest: project.checkOnPullRequest,
36438
+ disabled: project.disabled,
36439
+ installationId: project.installationId,
36440
+ installationStatus: verdict
36441
+ } : null;
36442
+ }).filter((row) => row !== null);
36443
+ const activeInstallations = (payload.installations ?? []).filter(
36444
+ (row) => row.status === "active"
36445
+ );
36446
+ const relinkCommand = (link2) => [
36447
+ // The numeric repo id, not the name: a repository renamed while the
36448
+ // App was gone keeps a stale name here, and `git link` accepts the id.
36449
+ `deepline git link ${link2.repoId}`,
36450
+ // Stored values are admin-controlled text and this line is
36451
+ // copy-pasted into a shell by whoever reads it, so every
36452
+ // interpolated value below is quoted.
36453
+ `--branch ${shellQuote3(link2.productionBranch)}`,
36454
+ link2.rootDirectory ? `--root-dir ${shellQuote3(link2.rootDirectory)}` : "",
36455
+ link2.manifestPath && link2.manifestPath !== "deepline.json" ? `--manifest ${shellQuote3(link2.manifestPath)}` : "",
36456
+ link2.checkOnPullRequest ? "" : "--no-pr-checks",
36457
+ // With several active installations no id is guessed: the reader picks.
36458
+ activeInstallations.length > 1 ? "--installation <id>" : ""
36459
+ ].filter(Boolean).join(" ");
36460
+ for (const link2 of affected_links) {
36461
+ const label = `${link2.repoFullName}${link2.rootDirectory ? ` (${link2.rootDirectory})` : ""}`;
36462
+ lines.push(
36463
+ link2.installationStatus !== "suspended" ? `Link again: ${label} \u2014 its installation ${link2.installationId} is ${link2.installationStatus}; run \`${relinkCommand(link2)}\`${activeInstallations.length > 1 ? ` with <id> being the installation that reaches this repo: ${activeInstallations.map((row) => `${row.installationId} (${row.accountLogin})`).join(", ")}` : ""}.` : (
36464
+ // A link disabled during the suspension stays disabled; only an
36465
+ // enabled one picks up again on its own when GitHub unsuspends.
36466
+ link2.disabled ? `Paused and disabled: ${label} \u2014 its installation is suspended, and the link stays disabled after GitHub unsuspends it until you run \`deepline git set ${link2.id} --enabled\`.` : `Paused: ${label} \u2014 its installation is suspended; pushes resume when GitHub unsuspends it.`
36467
+ )
36468
+ );
36469
+ }
36470
+ printCommandEnvelope(
36471
+ {
36472
+ installation,
36473
+ installations: payload.installations ?? [],
36474
+ affected_links,
36475
+ render: { sections: [{ title: "github installation", lines }] }
36476
+ },
36477
+ { json: options.json }
36478
+ );
36479
+ }
36147
36480
  async function handleRepos(options) {
36148
36481
  const { http } = getAuthedHttpClient();
36149
36482
  const query = options.installation ? `?installationId=${encodeURIComponent(options.installation)}` : "";
@@ -36374,6 +36707,9 @@ Examples:
36374
36707
  `
36375
36708
  );
36376
36709
  git.command("connect").description("Connect a GitHub installation (browser step).").option("--json", "Emit JSON output").action(async (options) => handleConnect(options));
36710
+ git.command("status").description(
36711
+ "Show the workspace's GitHub installation and whether it is still usable."
36712
+ ).option("--json", "Emit JSON output").action(async (options) => handleStatus2(options));
36377
36713
  git.command("repos").description("List repos the workspace's GitHub installation can reach.").option(
36378
36714
  "--installation <id>",
36379
36715
  "GitHub installation id (required when several are connected)"
@@ -36484,7 +36820,7 @@ async function handleQuickstart(options) {
36484
36820
  return 0;
36485
36821
  }
36486
36822
  function registerQuickstartCommands(program) {
36487
- program.command("quickstart").description(
36823
+ program.command("quickstart", { hidden: true }).description(
36488
36824
  "Deprecated compatibility command. Use /deepline-gtm in your agent."
36489
36825
  ).addHelpText(
36490
36826
  "after",
@@ -36516,7 +36852,8 @@ function renderSecret(secret) {
36516
36852
  const added = new Date(secret.createdAt).toISOString();
36517
36853
  const updated = new Date(secret.updatedAt).toISOString();
36518
36854
  const lastUsed = secret.lastUsedAt ? `, last used ${new Date(secret.lastUsedAt).toISOString()}` : ", never used";
36519
- return `${secret.name} (${scope}) - ${secret.status}${secret.hasValue ? ", set" : ", empty"}, added ${added}${updated !== added ? `, updated ${updated}` : ""}${lastUsed}`;
36855
+ const note = secret.note ? `, note ${JSON.stringify(secret.note)}` : "";
36856
+ return `${secret.name} (${scope}) - ${secret.status}${secret.hasValue ? ", set" : ", empty"}${note}, added ${added}${updated !== added ? `, updated ${updated}` : ""}${lastUsed}`;
36520
36857
  }
36521
36858
  async function readHiddenLine(prompt, streams = {}) {
36522
36859
  const inputStream = streams.input ?? input;
@@ -36723,7 +37060,8 @@ async function handleSet2(nameInput, forbidden, options) {
36723
37060
  name,
36724
37061
  value,
36725
37062
  scope,
36726
- ...playName ? { playName } : {}
37063
+ ...playName ? { playName } : {},
37064
+ ...options.note !== void 0 ? { note: options.note } : {}
36727
37065
  }
36728
37066
  );
36729
37067
  const secret = response.secret;
@@ -36746,6 +37084,57 @@ async function handleSet2(nameInput, forbidden, options) {
36746
37084
  { json: options.json }
36747
37085
  );
36748
37086
  }
37087
+ async function handleNote(secretId, noteInput, options) {
37088
+ if (options.clear && noteInput !== void 0) {
37089
+ throw new Error("Pass either a note or --clear, not both.");
37090
+ }
37091
+ if (!options.clear && noteInput === void 0) {
37092
+ throw new Error("Provide a note or use --clear.");
37093
+ }
37094
+ const note = options.clear ? "" : noteInput;
37095
+ if (options.dryRun) {
37096
+ printCommandEnvelope(
37097
+ {
37098
+ ok: true,
37099
+ dryRun: true,
37100
+ secretId,
37101
+ note,
37102
+ render: {
37103
+ sections: [
37104
+ {
37105
+ title: "secret note",
37106
+ lines: [
37107
+ options.clear ? `Would clear the note on secret ${secretId}.` : `Would save a note on secret ${secretId}.`
37108
+ ]
37109
+ }
37110
+ ]
37111
+ }
37112
+ },
37113
+ { json: options.json }
37114
+ );
37115
+ return;
37116
+ }
37117
+ const client2 = new DeeplineClient();
37118
+ const secret = await client2.updateSecretNote(secretId, note);
37119
+ printCommandEnvelope(
37120
+ {
37121
+ ok: true,
37122
+ secret,
37123
+ render: {
37124
+ sections: [
37125
+ {
37126
+ title: "secret note saved",
37127
+ lines: [
37128
+ secret.note ? `${secret.name}: note saved.` : `${secret.name}: note cleared.`,
37129
+ renderSecret(secret)
37130
+ ]
37131
+ }
37132
+ ]
37133
+ }
37134
+ },
37135
+ { json: options.json }
37136
+ );
37137
+ }
36749
37138
  function registerSecretsCommands(program) {
36750
37139
  const secrets = program.command("secrets").description("Manage play secrets without revealing values.").addHelpText(
36751
37140
  "after",
@@ -36753,8 +37142,8 @@ function registerSecretsCommands(program) {
36753
37142
  Notes:
36754
37143
  Secret values are never accepted as command arguments. Use the hidden prompt,
36755
37144
  or one explicit non-argv source: --value-stdin, --from-env NAME, or
36756
- --from-file PATH. Values are never printed. secrets list shows only status,
36757
- added, updated, and last-used metadata.
37145
+ --from-file PATH. Values are never printed. secrets list shows only metadata,
37146
+ including any note you intentionally added.
36758
37147
 
36759
37148
  Examples:
36760
37149
  deepline secrets list
@@ -36764,6 +37153,9 @@ Examples:
36764
37153
  printf %s "$HUBSPOT_TOKEN" | deepline secrets set HUBSPOT_TOKEN --value-stdin
36765
37154
  deepline secrets set HUBSPOT_TOKEN --from-env HUBSPOT_TOKEN
36766
37155
  deepline secrets set HUBSPOT_TOKEN --from-file ./hubspot-token.txt
37156
+ deepline secrets set HUBSPOT_TOKEN --note "Chrome extension \u2014 Avery"
37157
+ deepline secrets note <secret-id> "Chrome extension \u2014 Avery"
37158
+ deepline secrets note <secret-id> --clear
36767
37159
  `
36768
37160
  );
36769
37161
  secrets.command("list").description("List secret metadata only.").option("--json", "Emit JSON output").action(async (options) => {
@@ -36777,11 +37169,19 @@ Examples:
36777
37169
  ).option("--json", "Emit JSON output").action(async (name, options) => {
36778
37170
  await handleCheck(name, options);
36779
37171
  });
36780
- secrets.command("set").description("Set or rotate a secret without exposing its value in argv.").argument("<name>", "Secret name").argument("[forbidden...]", "Do not pass secret values here").option("--json", "Emit JSON output").option("--scope <scope>", "Secret scope: org or play", "org").option("--play <name>", "Play name for play-scoped secrets").option("--value-stdin", "Read the value from piped stdin").option("--from-env <name>", "Read the value from an environment variable").option("--from-file <path>", "Read the value from a file").action(
37172
+ secrets.command("set").description("Set or rotate a secret without exposing its value in argv.").argument("<name>", "Secret name").argument("[forbidden...]", "Do not pass secret values here").option("--json", "Emit JSON output").option("--scope <scope>", "Secret scope: org or play", "org").option("--play <name>", "Play name for play-scoped secrets").option(
37173
+ "--note <note>",
37174
+ "Optional non-sensitive memo (maximum 500 characters)"
37175
+ ).option("--value-stdin", "Read the value from piped stdin").option("--from-env <name>", "Read the value from an environment variable").option("--from-file <path>", "Read the value from a file").action(
36781
37176
  async (name, forbidden, options) => {
36782
37177
  await handleSet2(name, forbidden ?? [], options);
36783
37178
  }
36784
37179
  );
37180
+ secrets.command("note").description("Add, replace, or clear a non-sensitive note on one secret.").argument("<secret-id>", "Secret ID from `deepline secrets list --json`").argument("[note]", "Note text (maximum 500 characters)").option("--clear", "Clear the existing note").option("--dry-run", "Show the note change without saving it").option("--json", "Emit JSON output").action(
37181
+ async (secretId, note, options) => {
37182
+ await handleNote(secretId, note, options);
37183
+ }
37184
+ );
36785
37185
  }
36786
37186
 
36787
37187
  // src/cli/commands/setup.ts
@@ -36931,7 +37331,7 @@ import { existsSync as existsSync14, mkdirSync as mkdirSync11, readFileSync as r
36931
37331
  import { homedir as homedir8 } from "os";
36932
37332
  import { dirname as dirname15, join as join16 } from "path";
36933
37333
 
36934
- // ../../shared_libs/cli/install-commands.json
37334
+ // contracts/install-commands.json
36935
37335
  var install_commands_default = {
36936
37336
  skills: {
36937
37337
  index_path: "/.well-known/skills/index.json",
@@ -37039,10 +37439,15 @@ function buildSkillsAddArgs(baseUrl, skillName, options = {}) {
37039
37439
 
37040
37440
  // src/cli/skills-sync.ts
37041
37441
  import { spawn as spawn2, spawnSync } from "child_process";
37442
+ import { randomUUID as randomUUID7 } from "crypto";
37042
37443
  import {
37043
37444
  existsSync as existsSync13,
37044
37445
  mkdirSync as mkdirSync10,
37446
+ readdirSync as readdirSync4,
37045
37447
  readFileSync as readFileSync14,
37448
+ renameSync,
37449
+ rmdirSync,
37450
+ statSync as statSync5,
37046
37451
  unlinkSync as unlinkSync2,
37047
37452
  writeFileSync as writeFileSync14
37048
37453
  } from "fs";
@@ -37401,6 +37806,7 @@ async function maybeReportSdkCliFailure(input2) {
37401
37806
 
37402
37807
  // src/cli/skills-sync.ts
37403
37808
  var CHECK_TIMEOUT_MS2 = 3e3;
37809
+ var SKILLS_SYNC_CLAIM_MAX_AGE_MS = 60 * 60 * 1e3;
37404
37810
  function shouldSkipSkillsSync() {
37405
37811
  if (detectAgentRuntime() === "claude_cowork") {
37406
37812
  return true;
@@ -37417,6 +37823,60 @@ function failedSkillsSyncPath(baseUrl, agents) {
37417
37823
  `skills-sync-failed-${agents.join("-")}-version`
37418
37824
  );
37419
37825
  }
37826
+ function inProgressSkillsSyncPath(baseUrl, agents) {
37827
+ return join15(
37828
+ sdkCliStateDirPath(baseUrl),
37829
+ `skills-sync-in-progress-${agents.join("-")}`
37830
+ );
37831
+ }
37832
+ function removeSkillsSyncClaim(path, token) {
37833
+ try {
37834
+ unlinkSync2(join15(path, token));
37835
+ rmdirSync(path);
37836
+ } catch {
37837
+ }
37838
+ }
37839
+ function claimSkillsSync(baseUrl, agents) {
37840
+ const path = inProgressSkillsSyncPath(baseUrl, agents);
37841
+ try {
37842
+ mkdirSync10(dirname14(path), { recursive: true });
37843
+ } catch {
37844
+ return { status: "unavailable" };
37845
+ }
37846
+ const token = randomUUID7();
37847
+ for (let attempt = 0; attempt < 2; attempt += 1) {
37848
+ const pendingPath = `${path}-pending-${token}`;
37849
+ try {
37850
+ mkdirSync10(pendingPath);
37851
+ writeFileSync14(join15(pendingPath, token), "", { flag: "wx" });
37852
+ renameSync(pendingPath, path);
37853
+ return { status: "claimed", token };
37854
+ } catch {
37855
+ removeSkillsSyncClaim(pendingPath, token);
37856
+ if (!existsSync13(path)) continue;
37857
+ }
37858
+ if (attempt > 0) return { status: "held" };
37859
+ try {
37860
+ if (Date.now() - statSync5(path).mtimeMs <= SKILLS_SYNC_CLAIM_MAX_AGE_MS) {
37861
+ return { status: "held" };
37862
+ }
37863
+ const owners = readdirSync4(path);
37864
+ if (owners.length === 0) {
37865
+ rmdirSync(path);
37866
+ continue;
37867
+ }
37868
+ if (owners.length !== 1) return { status: "held" };
37869
+ renameSync(path, `${path}-stale-${owners[0]}`);
37870
+ } catch {
37871
+ return { status: "held" };
37872
+ }
37873
+ }
37874
+ return { status: "held" };
37875
+ }
37876
+ function clearSkillsSyncClaim(baseUrl, agents, token) {
37877
+ const path = inProgressSkillsSyncPath(baseUrl, agents);
37878
+ removeSkillsSyncClaim(path, token);
37879
+ }
37420
37880
  function hasMarkedSkillsSyncVersion(path, version) {
37421
37881
  return Boolean(version) && readMarkedSkillsSyncVersion(path) === version;
37422
37882
  }
@@ -37552,7 +38012,7 @@ function hasCommand(command) {
37552
38012
  });
37553
38013
  return result.status === 0;
37554
38014
  }
37555
- function shellQuote3(arg) {
38015
+ function shellQuote4(arg) {
37556
38016
  return `'${arg.replace(/'/g, `'\\''`)}'`;
37557
38017
  }
37558
38018
  function temporarySkillsSyncSkipCommand() {
@@ -37571,7 +38031,7 @@ function resolveSkillsInstallCommands(baseUrl, skillNames = DEFAULT_SDK_SKILL_NA
37571
38031
  commands.push({
37572
38032
  command: "bunx",
37573
38033
  args: bunxArgs,
37574
- manualCommand: `bunx ${bunxArgs.map(shellQuote3).join(" ")}`
38034
+ manualCommand: `bunx ${bunxArgs.map(shellQuote4).join(" ")}`
37575
38035
  });
37576
38036
  }
37577
38037
  if (hasCommand("npx")) {
@@ -37579,7 +38039,7 @@ function resolveSkillsInstallCommands(baseUrl, skillNames = DEFAULT_SDK_SKILL_NA
37579
38039
  commands.push({
37580
38040
  command: "npx",
37581
38041
  args: npxArgs,
37582
- manualCommand: `npx ${npxArgs.map(shellQuote3).join(" ")}`
38042
+ manualCommand: `npx ${npxArgs.map(shellQuote4).join(" ")}`
37583
38043
  });
37584
38044
  }
37585
38045
  return commands;
@@ -37746,30 +38206,43 @@ async function syncSdkSkillsIfNeeded(baseUrl, options = {}) {
37746
38206
  writeUnavailableSkillsNotice(baseUrl, update.remoteVersion, skillNames);
37747
38207
  return;
37748
38208
  }
37749
- writeSdkSkillsStatusLine("Deepline skills changed; syncing agent skills...");
37750
- const installResult = await runSkillsInstall(installs, agents);
37751
- if (!installResult.installed) {
37752
- const markerWritten = markFailedSkillsSync(
37753
- baseUrl,
37754
- update.remoteVersion,
37755
- agents
38209
+ const claim = claimSkillsSync(baseUrl, agents);
38210
+ if (claim.status === "held") return;
38211
+ try {
38212
+ if (hasFailedSkillsSync(baseUrl, update.remoteVersion, agents) || readSdkSkillsLocalVersion(baseUrl) === update.remoteVersion) {
38213
+ return;
38214
+ }
38215
+ writeSdkSkillsStatusLine(
38216
+ "Deepline skills changed; syncing agent skills..."
37756
38217
  );
37757
- void maybeReportAutomaticSkillsSyncFailure({
37758
- baseUrl,
37759
- remoteSkillsVersion: update.remoteVersion,
37760
- agents,
37761
- skillsPackage: SKILLS_NPX_PACKAGE,
37762
- targetSkillCount: skillNames.length,
37763
- markerWritten,
37764
- attempts: installResult.attempts
37765
- });
37766
- return;
38218
+ const installResult = await runSkillsInstall(installs, agents);
38219
+ if (!installResult.installed) {
38220
+ const markerWritten = markFailedSkillsSync(
38221
+ baseUrl,
38222
+ update.remoteVersion,
38223
+ agents
38224
+ );
38225
+ void maybeReportAutomaticSkillsSyncFailure({
38226
+ baseUrl,
38227
+ remoteSkillsVersion: update.remoteVersion,
38228
+ agents,
38229
+ skillsPackage: SKILLS_NPX_PACKAGE,
38230
+ targetSkillCount: skillNames.length,
38231
+ markerWritten,
38232
+ attempts: installResult.attempts
38233
+ });
38234
+ return;
38235
+ }
38236
+ runLegacySkillsCleanup(agents);
38237
+ writeSdkSkillsLocalVersion(baseUrl, update.remoteVersion, agents);
38238
+ clearUnavailableSkillsNotice(baseUrl);
38239
+ clearFailedSkillsSync(baseUrl, agents);
38240
+ writeSdkSkillsStatusLine("Deepline agent skills are up to date.");
38241
+ } finally {
38242
+ if (claim.status === "claimed") {
38243
+ clearSkillsSyncClaim(baseUrl, agents, claim.token);
38244
+ }
37767
38245
  }
37768
- runLegacySkillsCleanup(agents);
37769
- writeSdkSkillsLocalVersion(baseUrl, update.remoteVersion, agents);
37770
- clearUnavailableSkillsNotice(baseUrl);
37771
- clearFailedSkillsSync(baseUrl, agents);
37772
- writeSdkSkillsStatusLine("Deepline agent skills are up to date.");
37773
38246
  }
37774
38247
 
37775
38248
  // src/cli/commands/skills.ts
@@ -39086,7 +39559,7 @@ import {
39086
39559
  existsSync as existsSync16,
39087
39560
  mkdirSync as mkdirSync13,
39088
39561
  readFileSync as readFileSync17,
39089
- renameSync,
39562
+ renameSync as renameSync2,
39090
39563
  rmSync as rmSync5,
39091
39564
  writeFileSync as writeFileSync17
39092
39565
  } from "fs";
@@ -39155,7 +39628,7 @@ function writeCliUpdatePreferences(preferences, homeDir2 = homedir10()) {
39155
39628
  encoding: "utf8",
39156
39629
  mode: 384
39157
39630
  });
39158
- renameSync(tempPath, path);
39631
+ renameSync2(tempPath, path);
39159
39632
  } finally {
39160
39633
  rmSync5(tempPath, { force: true });
39161
39634
  }
@@ -39212,7 +39685,7 @@ import {
39212
39685
  mkdirSync as mkdirSync14,
39213
39686
  realpathSync as realpathSync5,
39214
39687
  readFileSync as readFileSync19,
39215
- renameSync as renameSync2,
39688
+ renameSync as renameSync3,
39216
39689
  rmSync as rmSync6,
39217
39690
  unlinkSync as unlinkSync3,
39218
39691
  writeFileSync as writeFileSync18
@@ -39229,7 +39702,7 @@ import {
39229
39702
 
39230
39703
  // src/cli/install-integrity.ts
39231
39704
  import { createRequire } from "module";
39232
- import { existsSync as existsSync17, readFileSync as readFileSync18, statSync as statSync5 } from "fs";
39705
+ import { existsSync as existsSync17, readFileSync as readFileSync18, statSync as statSync6 } from "fs";
39233
39706
  import { isAbsolute as isAbsolute6, join as join19, relative as relative6, resolve as resolve17 } from "path";
39234
39707
  var SDK_SIDECAR_CRITICAL_PACKAGE_FILES = [
39235
39708
  "dist/cli/index.mjs",
@@ -39269,7 +39742,7 @@ function parseJson(path) {
39269
39742
  }
39270
39743
  function isFile(path) {
39271
39744
  try {
39272
- return statSync5(path).isFile();
39745
+ return statSync6(path).isFile();
39273
39746
  } catch {
39274
39747
  return false;
39275
39748
  }
@@ -39416,14 +39889,14 @@ function posixShellQuote(value) {
39416
39889
  function windowsCmdQuote(value) {
39417
39890
  return `"${value.replace(/"/g, '""')}"`;
39418
39891
  }
39419
- function shellQuote4(value) {
39892
+ function shellQuote5(value) {
39420
39893
  if (process.platform === "win32") {
39421
39894
  return /^[A-Za-z0-9_./:@%+=,-]+$/.test(value) ? value : windowsCmdQuote(value);
39422
39895
  }
39423
39896
  return posixShellQuote(value);
39424
39897
  }
39425
39898
  function buildSourceUpdateCommand(sourceRoot) {
39426
- const quotedRoot = shellQuote4(sourceRoot);
39899
+ const quotedRoot = shellQuote5(sourceRoot);
39427
39900
  const cdCommand = process.platform === "win32" ? `cd /d ${quotedRoot}` : `cd ${quotedRoot}`;
39428
39901
  return `${cdCommand} && git fetch origin main --tags && git merge --ff-only origin/main`;
39429
39902
  }
@@ -39435,7 +39908,7 @@ function buildSidecarProjectConfigCommand(versionDir, nodeBin) {
39435
39908
  "fs.mkdirSync(dir,{recursive:true});",
39436
39909
  `fs.writeFileSync(path.join(dir,'package.json'),${JSON.stringify(NPM_SDK_SIDECAR_PACKAGE_JSON)});`
39437
39910
  ].join("");
39438
- return `${shellQuote4(nodeBin)} -e ${shellQuote4(script)} ${shellQuote4(versionDir)}`;
39911
+ return `${shellQuote5(nodeBin)} -e ${shellQuote5(script)} ${shellQuote5(versionDir)}`;
39439
39912
  }
39440
39913
  function sidecarStateDir(input2) {
39441
39914
  const scope = input2.env.DEEPLINE_CONFIG_SCOPE?.trim();
@@ -39498,7 +39971,7 @@ function resolvePythonSidecarUpdatePlan(options) {
39498
39971
  const npmCommand = "npm";
39499
39972
  const registryUrl = sidecarRegistryUrl(hostUrl);
39500
39973
  const versionDir = join20(stateDir, "versions", "<version>");
39501
- const manualCommand = `${buildSidecarProjectConfigCommand(versionDir, nodeBin)} && ${npmCommand} install --prefix ${shellQuote4(versionDir)} --registry ${shellQuote4(registryUrl)} ${NPM_SDK_INSTALL_COMMON_FLAGS.map(shellQuote4).join(" ")} ${shellQuote4(packageSpec)}`;
39974
+ const manualCommand = `${buildSidecarProjectConfigCommand(versionDir, nodeBin)} && ${npmCommand} install --prefix ${shellQuote5(versionDir)} --registry ${shellQuote5(registryUrl)} ${NPM_SDK_INSTALL_COMMON_FLAGS.map(shellQuote5).join(" ")} ${shellQuote5(packageSpec)}`;
39502
39975
  return {
39503
39976
  kind: "python-sidecar",
39504
39977
  stateDir,
@@ -39645,7 +40118,7 @@ function resolveUpdatePlan(options = {}) {
39645
40118
  args,
39646
40119
  ...installPrefix ? { installPrefix } : {},
39647
40120
  ...fallbackRegistryUrl ? { fallbackRegistryUrl } : {},
39648
- manualCommand: `${command} ${args.map(shellQuote4).join(" ")}`
40121
+ manualCommand: `${command} ${args.map(shellQuote5).join(" ")}`
39649
40122
  };
39650
40123
  }
39651
40124
  var AUTO_UPDATE_FAILURE_FILE = ".auto-update-failure.json";
@@ -39913,23 +40386,23 @@ function writeSidecarLauncher(input2) {
39913
40386
  input2.path,
39914
40387
  [
39915
40388
  "#!/usr/bin/env sh",
39916
- `export DEEPLINE_HOST_URL=${shellQuote4(input2.hostUrl)}`,
39917
- `export DEEPLINE_CONFIG_SCOPE=${shellQuote4(input2.scope)}`,
39918
- `if ${criticalPaths.map((path) => `[ ! -f ${shellQuote4(path)} ]`).join(" || ")}; then`,
40389
+ `export DEEPLINE_HOST_URL=${shellQuote5(input2.hostUrl)}`,
40390
+ `export DEEPLINE_CONFIG_SCOPE=${shellQuote5(input2.scope)}`,
40391
+ `if ${criticalPaths.map((path) => `[ ! -f ${shellQuote5(path)} ]`).join(" || ")}; then`,
39919
40392
  ' if [ -n "${DEEPLINE_REAL_BINARY:-}" ] && [ -x "$DEEPLINE_REAL_BINARY" ]; then',
39920
40393
  ' exec "$DEEPLINE_REAL_BINARY" --version=v2 "$@"',
39921
40394
  " fi",
39922
40395
  ' printf "%s\\n" "Deepline SDK CLI install is incomplete. Run \\`deepline update\\` to repair it." >&2',
39923
40396
  " exit 1",
39924
40397
  "fi",
39925
- `if ! ${shellQuote4(input2.nodeBin)} -e ${shellQuote4(esbuildProbe)} ${shellQuote4(versionDir)} >/dev/null 2>&1; then`,
40398
+ `if ! ${shellQuote5(input2.nodeBin)} -e ${shellQuote5(esbuildProbe)} ${shellQuote5(versionDir)} >/dev/null 2>&1; then`,
39926
40399
  ' if [ -n "${DEEPLINE_REAL_BINARY:-}" ] && [ -x "$DEEPLINE_REAL_BINARY" ]; then',
39927
40400
  ' exec "$DEEPLINE_REAL_BINARY" --version=v2 "$@"',
39928
40401
  " fi",
39929
40402
  ' printf "%s\\n" "Deepline SDK CLI install is incomplete. Run \\`deepline update\\` to repair it." >&2',
39930
40403
  " exit 1",
39931
40404
  "fi",
39932
- `exec ${shellQuote4(input2.nodeBin)} ${shellQuote4(input2.entryPath)} "$@"`,
40405
+ `exec ${shellQuote5(input2.nodeBin)} ${shellQuote5(input2.entryPath)} "$@"`,
39933
40406
  ""
39934
40407
  ].join("\n"),
39935
40408
  { encoding: "utf8", mode: 493 }
@@ -39997,7 +40470,7 @@ async function runPythonSidecarUpdatePlan(plan) {
39997
40470
  `.backup-${installedVersion}-${process.pid}-${Date.now()}`
39998
40471
  );
39999
40472
  try {
40000
- renameSync2(finalDir, backupDir);
40473
+ renameSync3(finalDir, backupDir);
40001
40474
  } catch (error) {
40002
40475
  const concurrentlyPublishedFailure = sidecarInstallFailure(finalDir);
40003
40476
  if (!concurrentlyPublishedFailure) {
@@ -40016,7 +40489,7 @@ async function runPythonSidecarUpdatePlan(plan) {
40016
40489
  }
40017
40490
  if (shouldPublishTemp) {
40018
40491
  try {
40019
- renameSync2(tempDir, finalDir);
40492
+ renameSync3(tempDir, finalDir);
40020
40493
  } catch (error) {
40021
40494
  rmSync6(tempDir, { recursive: true, force: true });
40022
40495
  const concurrentlyPublishedFailure = sidecarInstallFailure(finalDir);
@@ -40027,7 +40500,7 @@ async function runPythonSidecarUpdatePlan(plan) {
40027
40500
  let restoreFailure = "";
40028
40501
  if (backupDir && existsSync18(backupDir) && !existsSync18(finalDir)) {
40029
40502
  try {
40030
- renameSync2(backupDir, finalDir);
40503
+ renameSync3(backupDir, finalDir);
40031
40504
  backupDir = null;
40032
40505
  } catch (restoreError) {
40033
40506
  restoreFailure = `; failed to restore previous install: ${restoreError.message}`;
@@ -40047,7 +40520,7 @@ async function runPythonSidecarUpdatePlan(plan) {
40047
40520
  if (backupDir && existsSync18(backupDir)) {
40048
40521
  rmSync6(finalDir, { recursive: true, force: true });
40049
40522
  try {
40050
- renameSync2(backupDir, finalDir);
40523
+ renameSync3(backupDir, finalDir);
40051
40524
  backupDir = null;
40052
40525
  } catch {
40053
40526
  }
@@ -43199,9 +43672,9 @@ function apifySyncRecoveryNext(rawResponse) {
43199
43672
  const getDatasetItemsTool = stringField2(getDatasetItems, "tool");
43200
43673
  const getDatasetItemsPayload = recordField2(getDatasetItems, "payload");
43201
43674
  return {
43202
- getActorRun: `deepline tools execute ${getActorRunTool} --input ${shellQuote5(JSON.stringify(getActorRunPayload))} --json`,
43675
+ getActorRun: `deepline tools execute ${getActorRunTool} --input ${shellQuote6(JSON.stringify(getActorRunPayload))} --json`,
43203
43676
  ...getDatasetItemsTool && Object.keys(getDatasetItemsPayload).length > 0 ? {
43204
- getDatasetItems: `deepline tools execute ${getDatasetItemsTool} --input ${shellQuote5(JSON.stringify(getDatasetItemsPayload))} --json`
43677
+ getDatasetItems: `deepline tools execute ${getDatasetItemsTool} --input ${shellQuote6(JSON.stringify(getDatasetItemsPayload))} --json`
43205
43678
  } : {}
43206
43679
  };
43207
43680
  }
@@ -43374,7 +43847,7 @@ function parseExecuteOptions(args) {
43374
43847
  function safeFileStem(value) {
43375
43848
  return value.trim().replace(/[^a-zA-Z0-9_-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64) || "tool";
43376
43849
  }
43377
- function shellQuote5(value) {
43850
+ function shellQuote6(value) {
43378
43851
  return `'${value.replace(/'/g, `'\\''`)}'`;
43379
43852
  }
43380
43853
  function powerShellQuote(value) {
@@ -43444,7 +43917,7 @@ export default definePlay(${JSON.stringify(playName)}, async (ctx) => {
43444
43917
  path: scriptPath,
43445
43918
  sourceCode: script,
43446
43919
  projectDir,
43447
- macCopyCommand: `mkdir -p ${shellQuote5(projectDir)} && cp ${shellQuote5(scriptPath)} ${shellQuote5(`${projectDir}/${fileName}`)}`,
43920
+ macCopyCommand: `mkdir -p ${shellQuote6(projectDir)} && cp ${shellQuote6(scriptPath)} ${shellQuote6(`${projectDir}/${fileName}`)}`,
43448
43921
  windowsCopyCommand: `New-Item -ItemType Directory -Force -Path ${powerShellQuote(projectDir.replace(/\//g, "\\"))} | Out-Null; Copy-Item -LiteralPath ${powerShellQuote(scriptPath)} -Destination ${powerShellQuote(`${projectDir.replace(/\//g, "\\")}\\${fileName}`)}`
43449
43922
  };
43450
43923
  }
@@ -43471,7 +43944,7 @@ function buildToolExecuteBaseEnvelope(input2) {
43471
43944
  envelope,
43472
43945
  "output"
43473
43946
  );
43474
- const inspectCommand = `deepline tools execute ${input2.toolId} --input ${shellQuote5(JSON.stringify(input2.params))} --json`;
43947
+ const inspectCommand = `deepline tools execute ${input2.toolId} --input ${shellQuote6(JSON.stringify(input2.params))} --json`;
43475
43948
  const actions = input2.listConversion ? [
43476
43949
  {
43477
43950
  label: "next",
@@ -44291,7 +44764,7 @@ async function handleTail(id, runId, options) {
44291
44764
  }
44292
44765
  }
44293
44766
  function registerWorkflowCommands(program) {
44294
- const workflows = program.command("workflows").description(
44767
+ const workflows = program.command("workflows", { hidden: true }).description(
44295
44768
  "Legacy cloud workflows (now becoming plays). Commands still work; use `workflows transform` to migrate one to a play. " + TRIGGER_REDIRECT
44296
44769
  ).addHelpText(
44297
44770
  "after",
@@ -45111,4 +45584,10 @@ Examples:
45111
45584
  }
45112
45585
  process.exitCode = process.exitCode ?? 0;
45113
45586
  }
45114
- main();
45587
+ var DEV_CLI_AWAIT_MAIN = Symbol.for("@deepline/sdk/dev-cli-await-main");
45588
+ if (globalThis[DEV_CLI_AWAIT_MAIN] !== true) {
45589
+ void main();
45590
+ }
45591
+ export {
45592
+ main
45593
+ };