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
package/dist/cli/index.js CHANGED
@@ -6,6 +6,10 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
7
  var __getProtoOf = Object.getPrototypeOf;
8
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
9
13
  var __copyProps = (to, from, except, desc) => {
10
14
  if (from && typeof from === "object" || typeof from === "function") {
11
15
  for (let key of __getOwnPropNames(from))
@@ -22,6 +26,14 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
22
26
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
27
  mod
24
28
  ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+
31
+ // src/cli/index.ts
32
+ var cli_exports = {};
33
+ __export(cli_exports, {
34
+ main: () => main
35
+ });
36
+ module.exports = __toCommonJS(cli_exports);
25
37
 
26
38
  // src/cli/proxy-env.ts
27
39
  var import_undici = require("undici");
@@ -186,6 +198,26 @@ var import_node_path29 = require("path");
186
198
  var import_node_os18 = require("os");
187
199
  var import_commander5 = require("commander");
188
200
 
201
+ // src/pagination.ts
202
+ async function* iterateCursorPages(fetchPage) {
203
+ let cursor = null;
204
+ const seen = /* @__PURE__ */ new Set();
205
+ for (; ; ) {
206
+ const page = await fetchPage(cursor);
207
+ if (page.hasMore) {
208
+ if (!page.cursor || seen.has(page.cursor)) {
209
+ throw new Error(
210
+ "Pagination reported more results without an advancing cursor"
211
+ );
212
+ }
213
+ seen.add(page.cursor);
214
+ }
215
+ yield page.items;
216
+ if (!page.hasMore) return;
217
+ cursor = page.cursor;
218
+ }
219
+ }
220
+
189
221
  // src/config.ts
190
222
  var import_node_fs = require("fs");
191
223
  var import_node_os = require("os");
@@ -1265,20 +1297,22 @@ var SDK_RELEASE = {
1265
1297
  // available at toolResponse.rawV2 while toolResponse.raw and all declared
1266
1298
  // getters keep their established compatibility behavior.
1267
1299
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
1268
- version: "0.3.89",
1269
- 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.",
1300
+ // 0.3.90 is the first deliberately versioned SDK release for API v3.
1301
+ version: "0.3.91",
1302
+ 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.",
1270
1303
  packageCapabilities: {
1271
1304
  updatePreferences: 1
1272
1305
  },
1273
1306
  contracts: {
1274
1307
  api: {
1275
1308
  name: "sdk-http-api",
1276
- // API v2 is append-only. A breaking public request/response change needs
1277
- // v3 and an explicit v2 support-window decision, never a patch release.
1278
- currentMajor: 2,
1279
- supportedMajors: [2],
1280
- // Accepted only to bridge SDKs released before X-Deepline-API-Major.
1309
+ // Concise Play grep has the current wire id. Older ids follow the
1310
+ // standard API support window.
1311
+ currentMajor: 3,
1312
+ supportedMajors: [3, 2],
1313
+ // Older ids remain subject to the API support window.
1281
1314
  legacyWireIds: [
1315
+ "2026-09-play-grep-concise-results",
1282
1316
  "2026-07-admin-cli-local-cutover",
1283
1317
  "2026-07-native-monitor-launch-hard-cutover"
1284
1318
  ]
@@ -2527,6 +2561,10 @@ function normalizeProductNotificationEmail(value) {
2527
2561
  const email = typeof value === "string" ? value.trim().toLowerCase() : "";
2528
2562
  return email && email.length <= 320 && PRODUCT_NOTIFICATION_EMAIL_PATTERN.test(email) ? email : null;
2529
2563
  }
2564
+ var DEFAULT_PRODUCT_NOTIFICATION_DELIVERY_TIMING = {
2565
+ mode: "rolling_limit",
2566
+ windowMs: 36e5
2567
+ };
2530
2568
 
2531
2569
  // src/stream-reconnect.ts
2532
2570
  var STREAM_RECONNECT_BASE_DELAY_MS = 500;
@@ -5120,6 +5158,7 @@ var DeeplineClient = class {
5120
5158
  this.runs = {
5121
5159
  get: (runId, options2) => this.getRunStatus(runId, options2),
5122
5160
  list: (options2) => this.listRuns(options2),
5161
+ listPage: (options2) => this.listRunsPage(options2),
5123
5162
  tail: (runId, options2) => this.tailRun(runId, options2),
5124
5163
  logs: (runId, options2) => this.getRunLogs(runId, options2),
5125
5164
  input: (runId) => this.getRunInput(runId),
@@ -5145,9 +5184,19 @@ var DeeplineClient = class {
5145
5184
  targetStatus: () => this.getTargetBillingStatus(),
5146
5185
  autoRecharge: {
5147
5186
  get: () => this.getTargetAutoRecharge(),
5187
+ trigger: (options2) => this.http.post(
5188
+ "/api/v2/billing/auto-recharge/trigger",
5189
+ {},
5190
+ {
5191
+ "Idempotency-Key": requireTargetBillingIdempotencyKey(
5192
+ options2?.idempotencyKey ?? globalThis.crypto.randomUUID()
5193
+ )
5194
+ }
5195
+ ),
5148
5196
  update: (options2) => this.updateTargetAutoRecharge(options2)
5149
5197
  },
5150
5198
  purchaseCredits: (options2) => this.purchaseTargetBillingCredits(options2),
5199
+ recoverCreditPurchase: (options2) => this.recoverTargetBillingCreditPurchase(options2),
5151
5200
  transitionPlan: (options2) => this.transitionTargetBillingPlan(options2),
5152
5201
  portalSession: () => this.createTargetBillingPortalSession()
5153
5202
  };
@@ -5316,6 +5365,14 @@ var DeeplineClient = class {
5316
5365
  if (options.playName !== void 0) params.set("play", options.playName);
5317
5366
  return this.http.get(`/api/v2/secrets?${params.toString()}`);
5318
5367
  }
5368
+ /** Add, replace, or clear the non-sensitive note attached to one secret. */
5369
+ async updateSecretNote(secretId, note) {
5370
+ const response = await this.http.patch(
5371
+ `/api/v2/secrets/${encodeURIComponent(secretId)}`,
5372
+ { note }
5373
+ );
5374
+ return response.secret;
5375
+ }
5319
5376
  // ——————————————————————————————————————————————————————————
5320
5377
  // Tools
5321
5378
  // ——————————————————————————————————————————————————————————
@@ -6333,6 +6390,10 @@ var DeeplineClient = class {
6333
6390
  * ```
6334
6391
  */
6335
6392
  async listRuns(options) {
6393
+ return (await this.listRunsPage(options)).runs;
6394
+ }
6395
+ /** Read one run page without discarding server pagination metadata. */
6396
+ async listRunsPage(options) {
6336
6397
  const playName = options.play?.trim();
6337
6398
  const params = new URLSearchParams();
6338
6399
  if (playName) {
@@ -6363,7 +6424,7 @@ var DeeplineClient = class {
6363
6424
  const response = await this.http.get(
6364
6425
  `/api/v2/runs?${params.toString()}`
6365
6426
  );
6366
- return response.runs ?? [];
6427
+ return { ...response, runs: response.runs ?? [] };
6367
6428
  }
6368
6429
  /**
6369
6430
  * Observe one run's live events. Uses the Convex Run Snapshot subscription
@@ -6758,13 +6819,33 @@ var DeeplineClient = class {
6758
6819
  );
6759
6820
  }
6760
6821
  /**
6761
- * List callable plays visible to the workspace.
6822
+ * List one page of callable plays; grep retains exhaustive matching results.
6823
+ * Use listPlaysPage to retain pagination metadata.
6762
6824
  *
6763
6825
  * Pass `origin: "prebuilt"` for Deepline-managed prebuilts or
6764
6826
  * `origin: "owned"` for org-owned plays.
6765
6827
  */
6766
6828
  async listPlays(options) {
6829
+ if (!options?.grep?.trim()) {
6830
+ return (await this.requestPlaysPage(options, false)).plays;
6831
+ }
6832
+ const plays = [];
6833
+ for await (const items of iterateCursorPages(async (cursor) => {
6834
+ const page = await this.listPlaysPage({ ...options, cursor });
6835
+ return { items: page.plays, cursor: page.cursor, hasMore: page.hasMore };
6836
+ })) {
6837
+ plays.push(...items);
6838
+ }
6839
+ return plays;
6840
+ }
6841
+ /** Read one bounded inventory page; cursor continues the same filters. */
6842
+ async listPlaysPage(options) {
6843
+ return this.requestPlaysPage(options);
6844
+ }
6845
+ async requestPlaysPage(options, paginateInventory = true) {
6767
6846
  const params = new URLSearchParams();
6847
+ if (paginateInventory && !options?.grep?.trim())
6848
+ params.set("inventory_paginated", "1");
6768
6849
  if (options?.origin) params.set("origin", options.origin);
6769
6850
  if (options?.categories) {
6770
6851
  params.set(
@@ -6776,26 +6857,27 @@ var DeeplineClient = class {
6776
6857
  params.set("include_tool_categories", "1");
6777
6858
  }
6778
6859
  if (options?.includeArchived) params.set("include_archived", "1");
6860
+ if (options?.includeCostEstimates) {
6861
+ params.set("include_cost_estimates", "1");
6862
+ }
6779
6863
  if (options?.grep?.trim()) {
6780
6864
  params.set("grep", options.grep.trim());
6781
- params.set("grep_mode", options.grepMode ?? "all");
6782
- params.set("grep_paginated", "1");
6783
6865
  params.set("limit", "60");
6784
6866
  }
6785
- const plays = [];
6786
- let cursor = null;
6787
- let hasMore = true;
6788
- do {
6789
- if (cursor) params.set("cursor", cursor);
6790
- const suffix = params.toString() ? `?${params.toString()}` : "";
6791
- const response = await this.http.get(
6792
- `/api/v2/plays${suffix}`
6793
- );
6794
- plays.push(...response.plays ?? []);
6795
- cursor = response.pagination?.cursor ?? response.cursor ?? null;
6796
- hasMore = Boolean(response.pagination?.hasMore ?? response.hasMore);
6797
- } while (Boolean(options?.grep?.trim()) && hasMore && cursor);
6798
- return plays;
6867
+ if (options?.limit !== void 0) {
6868
+ if (!Number.isSafeInteger(options.limit) || options.limit < 1) {
6869
+ throw new Error("Play page limit must be a positive integer");
6870
+ }
6871
+ params.set("limit", String(options.limit));
6872
+ }
6873
+ if (options?.cursor) params.set("cursor", options.cursor);
6874
+ const suffix = params.size ? `?${params.toString()}` : "";
6875
+ const response = await this.http.get(`/api/v2/plays${suffix}`);
6876
+ return {
6877
+ plays: response.plays ?? [],
6878
+ cursor: response.pagination?.cursor ?? response.cursor ?? null,
6879
+ hasMore: Boolean(response.pagination?.hasMore ?? response.hasMore)
6880
+ };
6799
6881
  }
6800
6882
  /** Set whether an org-owned Play sorts before unpinned Plays. */
6801
6883
  async setPlayPinned(playName, pinned) {
@@ -6929,7 +7011,7 @@ var DeeplineClient = class {
6929
7011
  groupKey,
6930
7012
  name,
6931
7013
  enabled: true,
6932
- deliveryTiming: { mode: "immediate" },
7014
+ deliveryTiming: DEFAULT_PRODUCT_NOTIFICATION_DELIVERY_TIMING,
6933
7015
  source: "workspace",
6934
7016
  configMode: "custom",
6935
7017
  version: 0
@@ -7484,7 +7566,8 @@ var DeeplineClient = class {
7484
7566
  options.enabled ? {
7485
7567
  enabled: true,
7486
7568
  threshold_credits: options.thresholdCredits,
7487
- refill_to_credits: options.refillToCredits
7569
+ refill_to_credits: options.refillToCredits,
7570
+ ...options.purchaseLimitCents !== void 0 ? { purchase_limit_cents: options.purchaseLimitCents } : {}
7488
7571
  } : { enabled: false },
7489
7572
  { "Idempotency-Key": idempotencyKey }
7490
7573
  );
@@ -7505,6 +7588,39 @@ var DeeplineClient = class {
7505
7588
  { maxRetries: 0, exactUrlOnly: true }
7506
7589
  );
7507
7590
  }
7591
+ /** Recover only the original workspace, credit amount, and purchase key; never charge. */
7592
+ async recoverTargetBillingCreditPurchase(options) {
7593
+ if (typeof options.idempotencyKey !== "string") {
7594
+ throw new DeeplineError(
7595
+ "The original billing idempotencyKey is required.",
7596
+ void 0,
7597
+ "INVALID_BILLING_IDEMPOTENCY_KEY"
7598
+ );
7599
+ }
7600
+ const idempotencyKey = requireTargetBillingIdempotencyKey(
7601
+ options.idempotencyKey
7602
+ );
7603
+ if (!Number.isSafeInteger(options.credits) || options.credits <= 0) {
7604
+ throw new DeeplineError(
7605
+ "credits must be a positive safe integer.",
7606
+ void 0,
7607
+ "INVALID_CREDITS"
7608
+ );
7609
+ }
7610
+ if (typeof options.orgId !== "string" || !options.orgId.trim() || options.orgId !== options.orgId.trim()) {
7611
+ throw new DeeplineError(
7612
+ "The original orgId is required without surrounding whitespace.",
7613
+ void 0,
7614
+ "INVALID_ORG_ID"
7615
+ );
7616
+ }
7617
+ return this.http.post(
7618
+ "/api/v2/billing/credit-purchases/recover",
7619
+ { credits: options.credits, org_id: options.orgId },
7620
+ { "Idempotency-Key": idempotencyKey },
7621
+ { maxRetries: 0, exactUrlOnly: true }
7622
+ );
7623
+ }
7508
7624
  /**
7509
7625
  * Start, change, cancel, or restore a target plan through one idempotent
7510
7626
  * commercial operation.
@@ -8145,13 +8261,6 @@ function getAuthedHttpClient() {
8145
8261
  const config = resolveConfig();
8146
8262
  return { config, http: new HttpClient(config) };
8147
8263
  }
8148
- async function writeOutputFile(filename, content) {
8149
- const outputDir = (0, import_node_path4.resolve)(process.cwd(), "deepline", "data");
8150
- await (0, import_promises.mkdir)(outputDir, { recursive: true });
8151
- const fullPath = (0, import_node_path4.join)(outputDir, filename);
8152
- await (0, import_promises.writeFile)(fullPath, content, "utf-8");
8153
- return fullPath;
8154
- }
8155
8264
  function stableOsUserId() {
8156
8265
  try {
8157
8266
  const info = (0, import_node_os4.userInfo)();
@@ -8794,13 +8903,6 @@ function createTimestampedName(prefix, extension) {
8794
8903
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
8795
8904
  return `${prefix}-${timestamp}.${extension}`;
8796
8905
  }
8797
- async function writeCsvRowsFile(prefix, rows) {
8798
- const path = await writeOutputFile(
8799
- createTimestampedName(prefix, "csv"),
8800
- csvStringFromRows(rows)
8801
- );
8802
- return path;
8803
- }
8804
8906
  function clip(value, maxLength) {
8805
8907
  return value.length > maxLength ? `${value.slice(0, maxLength - 1)}\u2026` : value;
8806
8908
  }
@@ -9585,7 +9687,7 @@ Notes:
9585
9687
  workspace. To switch, use deepline org list and deepline org set <org-id>.
9586
9688
  `
9587
9689
  );
9588
- auth.command("workspaces").description("Deprecated. Use deepline org list to see workspaces.").action(() => {
9690
+ auth.command("workspaces", { hidden: true }).description("Deprecated. Use deepline org list to see workspaces.").action(() => {
9589
9691
  console.error(
9590
9692
  "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."
9591
9693
  );
@@ -9682,7 +9784,6 @@ var SUBSCRIPTION_STATUS_NEXT_COMMAND = "deepline billing subscription status --j
9682
9784
  var SUBSCRIPTION_CANCEL_PATH = "/api/v2/billing/subscription/cancel";
9683
9785
  var BILLING_TOP_UP_PATH = "/api/v2/billing/top-up";
9684
9786
  var DEFAULT_BALANCE_RECOVERY_CREDITS = 100;
9685
- var BILLING_HISTORY_EXPORT_LIMIT = 5e3;
9686
9787
  function billingFailureFromError(error, options) {
9687
9788
  if (error instanceof AuthError) {
9688
9789
  return {
@@ -9947,6 +10048,17 @@ async function handleBalance(options) {
9947
10048
  const needsCredits = status === "no_billing" || status === "zero_balance" || status === "payment_method_only";
9948
10049
  const recovery = needsCredits ? balanceRecoveryForCredits() : null;
9949
10050
  const lines = [`Balance: ${payload.balance ?? "(unknown)"} credits`];
10051
+ const temporaryHolds = payload.temporary_hold_credits;
10052
+ if (typeof temporaryHolds === "number" && temporaryHolds > 0) {
10053
+ lines.push(
10054
+ `Temporarily reserved: ${temporaryHolds} credits \u2014 not charged; unused credits are released after final usage is calculated.`
10055
+ );
10056
+ } else if (temporaryHolds === null) {
10057
+ lines.push("Temporary reservation status is temporarily unavailable.");
10058
+ }
10059
+ if (payload.temporary_hold_credits_truncated === true) {
10060
+ lines.push("Temporary reservation total may be incomplete.");
10061
+ }
9950
10062
  if (status === "no_billing") {
9951
10063
  lines.push(
9952
10064
  "Billing: No billing account or payment method set up for this workspace."
@@ -9973,6 +10085,9 @@ async function handleBalance(options) {
9973
10085
  );
9974
10086
  return;
9975
10087
  }
10088
+ function quoteShellArgument(value) {
10089
+ return `'${value.replace(/'/g, `'\\''`)}'`;
10090
+ }
9976
10091
  async function handleUsage(options) {
9977
10092
  const { http } = getAuthedHttpClient();
9978
10093
  const params = new URLSearchParams();
@@ -9989,24 +10104,32 @@ async function handleUsage(options) {
9989
10104
  const recent = payload.recent ?? {};
9990
10105
  const last30Usage = usage.last_30_days_usage_credits ?? usage.month_spent_credits;
9991
10106
  const temporaryHolds = Number(usage.temporary_hold_credits ?? 0);
10107
+ 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;
9992
10108
  const lines = [
9993
10109
  `Balance: ${payload.balance ?? "(unknown)"}`,
9994
10110
  `Last 30 days usage: ${last30Usage ?? "(unknown)"}`,
9995
10111
  ...Number.isFinite(temporaryHolds) && temporaryHolds > 0 ? [`Temporary holds: ${temporaryHolds}`] : [],
9996
- `Monthly limit: ${quota.enabled ? quota.monthly_credits_limit ?? "(unknown)" : "off"}`,
10112
+ `Monthly spend guidance: ${quota.enabled ? quota.monthly_credits_limit ?? "(unknown)" : "off"}`,
9997
10113
  ...options.runId && recent.run_id ? [
9998
10114
  `Run spend: ${(payload.run ?? {}).spent_credits ?? "(unknown)"} Deepline Credits`
9999
10115
  ] : [],
10000
10116
  ...recentUsageLines(
10001
10117
  Array.isArray(recent.entries) ? recent.entries : []
10002
10118
  ),
10003
- ...typeof recent.next_cursor === "string" && recent.next_cursor.length > 0 ? [
10004
- `Next page: deepline billing usage --cursor ${recent.next_cursor}${options.limit ? ` --limit ${options.limit}` : ""}${options.runId ? ` --run-id ${options.runId}` : ""}`
10119
+ ...recent.has_more === true || recent.incomplete === true ? ["List truncated \u2014 more recent calls match this query."] : [],
10120
+ ...nextPage ? [`Next page: ${nextPage}`] : [],
10121
+ ...!nextPage && (recent.has_more === true || recent.incomplete === true) ? [
10122
+ "No continuation is available for this view. Use deepline billing ledger export all --json for the full ledger."
10005
10123
  ] : []
10006
10124
  ];
10007
10125
  printCommandEnvelope(
10008
10126
  {
10009
10127
  ...payload,
10128
+ recent: {
10129
+ ...recent,
10130
+ is_truncated: recent.has_more === true || recent.incomplete === true
10131
+ },
10132
+ next: { page: nextPage },
10010
10133
  render: { sections: [{ title: "billing usage", lines }] }
10011
10134
  },
10012
10135
  { json: options.json }
@@ -10018,9 +10141,9 @@ async function handleLimit(options) {
10018
10141
  "/api/v2/billing/limit"
10019
10142
  );
10020
10143
  const lines = payload.enabled ? [
10021
- `Monthly limit: ${payload.monthly_credits_limit ?? "(unknown)"}`,
10022
- `Remaining before cap: ${payload.remaining_credits ?? "(unknown)"}`
10023
- ] : ["Monthly limit: off"];
10144
+ `Monthly spend guidance: ${payload.monthly_credits_limit ?? "(unknown)"}`,
10145
+ "Enforcement: advisory; available balance remains the exact admission control."
10146
+ ] : ["Monthly spend guidance: off"];
10024
10147
  printCommandEnvelope(
10025
10148
  {
10026
10149
  ...payload,
@@ -10042,7 +10165,7 @@ async function handleSetLimit(credits, options) {
10042
10165
  sections: [
10043
10166
  {
10044
10167
  title: "billing limit",
10045
- lines: [`Monthly billing limit set to ${credits} credits.`]
10168
+ lines: [`Monthly spend guidance set to ${credits} credits.`]
10046
10169
  }
10047
10170
  ]
10048
10171
  }
@@ -10062,7 +10185,7 @@ async function handleLimitOff(options) {
10062
10185
  sections: [
10063
10186
  {
10064
10187
  title: "billing limit",
10065
- lines: ["Monthly billing limit is now off."]
10188
+ lines: ["Monthly spend guidance is now off."]
10066
10189
  }
10067
10190
  ]
10068
10191
  }
@@ -10070,6 +10193,39 @@ async function handleLimitOff(options) {
10070
10193
  { json: options.json }
10071
10194
  );
10072
10195
  }
10196
+ async function exportLedger(http, outputPath, options) {
10197
+ let summary = { row_count: 0, net_delta_credits: 0 };
10198
+ let initialized = false;
10199
+ for await (const entries of iterateCursorPages(async (cursor) => {
10200
+ const params = new URLSearchParams({ limit: "5000" });
10201
+ if (cursor) params.set("cursor", cursor);
10202
+ if (options.sinceAt !== null)
10203
+ params.set("since_at", String(options.sinceAt));
10204
+ if (options.runId) params.set("run_id", options.runId);
10205
+ if (options.operation) params.set("operation", options.operation);
10206
+ const payload = await http.get(
10207
+ `/api/v2/billing/ledger?${params.toString()}`
10208
+ );
10209
+ if (!Array.isArray(payload.entries) || typeof payload.has_more !== "boolean") {
10210
+ throw new Error("Billing ledger response is missing entries");
10211
+ }
10212
+ return {
10213
+ items: payload.entries,
10214
+ hasMore: payload.has_more === true,
10215
+ cursor: typeof payload.next_cursor === "string" ? payload.next_cursor : null
10216
+ };
10217
+ })) {
10218
+ if (!initialized) {
10219
+ await (0, import_promises2.mkdir)((0, import_node_path6.dirname)(outputPath), { recursive: true });
10220
+ await (0, import_promises2.writeFile)(outputPath, ledgerRowsToCsv([], true), "utf-8");
10221
+ initialized = true;
10222
+ }
10223
+ const rows = entries.map(ledgerApiEntryToRow);
10224
+ await (0, import_promises2.appendFile)(outputPath, ledgerRowsToCsv(rows, false), "utf-8");
10225
+ summary = summarizeLedgerRows(summary, rows);
10226
+ }
10227
+ return summary;
10228
+ }
10073
10229
  async function handleHistory(options) {
10074
10230
  const { http } = getAuthedHttpClient();
10075
10231
  const windows = {
@@ -10079,41 +10235,20 @@ async function handleHistory(options) {
10079
10235
  "1y": 31536e3
10080
10236
  };
10081
10237
  const sinceAt = Math.max(0, Math.floor(Date.now() / 1e3) - windows[options.time]) * 1e3;
10082
- const entries = [];
10083
- let cursor = null;
10084
- while (entries.length < BILLING_HISTORY_EXPORT_LIMIT) {
10085
- const params = new URLSearchParams({
10086
- since_at: String(sinceAt),
10087
- limit: String(BILLING_HISTORY_EXPORT_LIMIT - entries.length)
10088
- });
10089
- if (cursor !== null) params.set("cursor", cursor);
10090
- const payload = await http.get(
10091
- `/api/v2/billing/ledger?${params.toString()}`
10092
- );
10093
- if (Array.isArray(payload.entries)) {
10094
- entries.push(
10095
- ...payload.entries.slice(
10096
- 0,
10097
- BILLING_HISTORY_EXPORT_LIMIT - entries.length
10098
- )
10099
- );
10100
- }
10101
- const nextCursor = typeof payload.next_cursor === "string" && payload.next_cursor.length > 0 ? payload.next_cursor : null;
10102
- if (payload.has_more !== true || nextCursor === null) break;
10103
- if (nextCursor === cursor) {
10104
- throw new Error("Billing history pagination cursor did not advance");
10105
- }
10106
- cursor = nextCursor;
10107
- }
10108
- const rows = entries.map(ledgerApiEntryToRow);
10109
- const outputPath = await writeCsvRowsFile(
10110
- `billing-history-${options.time}`,
10111
- rows
10238
+ const outputPath = (0, import_node_path6.resolve)(
10239
+ process.cwd(),
10240
+ "deepline",
10241
+ "data",
10242
+ createTimestampedName(`billing-history-${options.time}`, "csv")
10112
10243
  );
10244
+ const summary = await exportLedger(http, outputPath, { sinceAt });
10113
10245
  printCommandEnvelope(
10114
10246
  {
10115
10247
  output_path: outputPath,
10116
- row_count: rows.length,
10248
+ row_count: summary.row_count,
10249
+ has_more: false,
10250
+ is_truncated: false,
10251
+ next_cursor: null,
10117
10252
  time_window: options.time,
10118
10253
  render: {
10119
10254
  sections: [
@@ -10121,7 +10256,7 @@ async function handleHistory(options) {
10121
10256
  title: "billing history",
10122
10257
  lines: [
10123
10258
  `Billing history written to ${outputPath}`,
10124
- `${rows.length} row(s) exported.`
10259
+ `${summary.row_count} row(s) exported.`
10125
10260
  ]
10126
10261
  }
10127
10262
  ]
@@ -10146,40 +10281,18 @@ async function handleLedgerExportAll(options) {
10146
10281
  }
10147
10282
  const { http } = getAuthedHttpClient();
10148
10283
  const outputPath = options.output ? (0, import_node_path6.resolve)(String(options.output)) : defaultLedgerExportPath();
10149
- let summary = { row_count: 0, net_delta_credits: 0 };
10150
- let cursor = null;
10151
- let initializedOutput = false;
10152
- for (; ; ) {
10153
- const params = new URLSearchParams({ limit: "5000" });
10154
- if (cursor !== null) params.set("cursor", cursor);
10155
- if (options.runId) params.set("run_id", options.runId);
10156
- if (options.operation) params.set("operation", options.operation);
10157
- if (sinceAt !== null) params.set("since_at", String(sinceAt));
10158
- const payload = await http.get(
10159
- `/api/v2/billing/ledger?${params.toString()}`
10160
- );
10161
- const entries = Array.isArray(payload.entries) ? payload.entries : [];
10162
- const rows = entries.map(ledgerApiEntryToRow);
10163
- if (!initializedOutput) {
10164
- await (0, import_promises2.mkdir)((0, import_node_path6.dirname)(outputPath), { recursive: true });
10165
- await (0, import_promises2.writeFile)(outputPath, ledgerRowsToCsv([], true), "utf-8");
10166
- initializedOutput = true;
10167
- }
10168
- if (rows.length > 0) {
10169
- await (0, import_promises2.appendFile)(outputPath, ledgerRowsToCsv(rows, false), "utf-8");
10170
- summary = summarizeLedgerRows(summary, rows);
10171
- }
10172
- const nextCursor = typeof payload.next_cursor === "string" && payload.next_cursor.length > 0 ? payload.next_cursor : null;
10173
- if (payload.has_more !== true || nextCursor === null) {
10174
- break;
10175
- }
10176
- if (nextCursor === cursor) break;
10177
- cursor = nextCursor;
10178
- }
10284
+ const summary = await exportLedger(http, outputPath, {
10285
+ sinceAt,
10286
+ runId: options.runId,
10287
+ operation: options.operation
10288
+ });
10179
10289
  printCommandEnvelope(
10180
10290
  {
10181
10291
  output_path: outputPath,
10182
10292
  row_count: summary.row_count,
10293
+ has_more: false,
10294
+ is_truncated: false,
10295
+ next_cursor: null,
10183
10296
  net_delta_credits: summary.net_delta_credits,
10184
10297
  scope: "workspace",
10185
10298
  ...options.runId ? { run_id: options.runId } : {},
@@ -10208,42 +10321,28 @@ function planPriceText(priceUsd, priceInterval) {
10208
10321
  }
10209
10322
  return `$${priceUsd}${priceInterval ? `/${priceInterval}` : ""}`;
10210
10323
  }
10211
- function planRolloverText(rollover) {
10212
- const mode = rollover?.mode ?? "none";
10213
- if (mode === "none") return "no rollover";
10214
- if (mode === "bounded") {
10215
- return `rollover up to ${rollover?.max_credits ?? "(unknown)"} credits`;
10216
- }
10217
- return `rollover ${mode}`;
10324
+ function targetPlanLine(plan) {
10325
+ 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"}`;
10218
10326
  }
10219
10327
  async function handlePlans(options) {
10220
- const { http } = getAuthedHttpClient();
10221
- const payload = await http.get(
10222
- "/api/v2/billing/catalog/current"
10328
+ const client2 = new DeeplineClient();
10329
+ const payload = await client2.billing.targetPlans();
10330
+ const listedCurrentPlan = payload.plans.find(
10331
+ (plan) => plan.sku === payload.current_plan_sku
10223
10332
  );
10224
- const activePlan = payload.active_plan ?? {};
10225
- const plans = Array.isArray(payload.plans) ? payload.plans : [];
10226
- const meters = Array.isArray(payload.meters) ? payload.meters : Array.isArray(payload.metrics) ? payload.metrics : [];
10333
+ const currentPlan = listedCurrentPlan ?? (await client2.billing.targetStatus()).plan;
10227
10334
  const lines = [
10228
- `Catalog: ${payload.catalog_id ?? "(unknown)"} (version ${payload.catalog_version ?? "(unknown)"})`,
10229
- `Active plan: ${activePlan.public_name ?? "(unknown)"} (${activePlan.plan_version_id ?? "(unknown)"})`,
10230
- `Assigned by: ${activePlan.assigned_by ?? "default"} | subscription: ${activePlan.has_subscription ? "yes" : "no"}`,
10231
- ...plans.length === 0 ? ["Plans: none published"] : [
10232
- "Plans:",
10233
- ...plans.map(
10234
- (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"}`
10235
- )
10236
- ],
10237
- ...meters.length === 0 ? ["Metrics: none"] : [
10238
- "Metrics:",
10239
- ...meters.map(
10240
- (meter) => `${meter.id ?? "(unknown)"} | ${meter.name ?? "(unknown)"}`
10241
- )
10242
- ]
10335
+ `Current plan: ${currentPlan.name} (${currentPlan.sku}) | ${planPriceText(currentPlan.recurring_price_usd, currentPlan.interval)} | ${currentPlan.included_credits ?? "(unknown)"} included credits/month`,
10336
+ `Pending plan: ${payload.pending_plan_sku ?? "none"}`,
10337
+ `Plan changes: ${payload.acquisition_enabled ? "enabled" : "disabled"}`,
10338
+ ...payload.plans.length === 0 ? ["Plans: none available"] : ["Plans:", ...payload.plans.map(targetPlanLine)],
10339
+ "Change plan: deepline billing change-plan <plan_sku> --json"
10243
10340
  ];
10341
+ const legacyPayload = shouldEmitJson(options.json) ? await client2.billing.plans() : null;
10244
10342
  printCommandEnvelope(
10245
10343
  {
10246
- ...payload,
10344
+ ...legacyPayload ?? payload,
10345
+ ...legacyPayload ? { target_billing: payload } : {},
10247
10346
  render: { sections: [{ title: "billing plans", lines }] }
10248
10347
  },
10249
10348
  { json: options.json }
@@ -10618,7 +10717,10 @@ async function handleAutoRechargeStatus(options) {
10618
10717
  const lines = [
10619
10718
  `State: ${state}`,
10620
10719
  ...payload.threshold_credits !== null ? [`Threshold: ${payload.threshold_credits} credits`] : [],
10621
- ...payload.refill_to_credits !== null ? [`Refill balance to: ${payload.refill_to_credits} credits`] : []
10720
+ ...payload.refill_to_credits !== null ? [`Refill balance to: ${payload.refill_to_credits} credits`] : [],
10721
+ ...payload.purchase_limit_cents !== void 0 ? [
10722
+ payload.purchase_limit_cents === null ? "Automatic purchase cap: none" : `Automatic purchase cap: $${(payload.purchase_limit_cents / 100).toFixed(2)} per rolling 30 days`
10723
+ ] : []
10622
10724
  ];
10623
10725
  printCommandEnvelope(
10624
10726
  {
@@ -10632,6 +10734,18 @@ async function handleAutoRechargeStatus(options) {
10632
10734
  async function handleAutoRechargeSet(options) {
10633
10735
  const thresholdCredits = parseTopUpCredits(options.thresholdCredits);
10634
10736
  const refillToCredits = parseTopUpCredits(options.refillToCredits);
10737
+ const rollingLimitCents = options.purchaseLimitCents === void 0 ? void 0 : options.purchaseLimitCents === "none" ? null : Number(options.purchaseLimitCents);
10738
+ if (rollingLimitCents !== void 0 && rollingLimitCents !== null && (!Number.isSafeInteger(rollingLimitCents) || rollingLimitCents <= 0)) {
10739
+ reportBillingFailure(
10740
+ {
10741
+ exitCode: 2,
10742
+ code: "INVALID_AUTO_RECHARGE_CONFIGURATION",
10743
+ message: "--purchase-limit-cents must be a positive whole number of USD cents or none."
10744
+ },
10745
+ options
10746
+ );
10747
+ return;
10748
+ }
10635
10749
  if (thresholdCredits === null || refillToCredits === null || refillToCredits <= thresholdCredits) {
10636
10750
  reportBillingFailure(
10637
10751
  {
@@ -10656,7 +10770,8 @@ async function handleAutoRechargeSet(options) {
10656
10770
  body: {
10657
10771
  enabled: true,
10658
10772
  threshold_credits: thresholdCredits,
10659
- refill_to_credits: refillToCredits
10773
+ refill_to_credits: refillToCredits,
10774
+ ...rollingLimitCents !== void 0 ? { purchase_limit_cents: rollingLimitCents } : {}
10660
10775
  }
10661
10776
  }
10662
10777
  },
@@ -10668,6 +10783,7 @@ async function handleAutoRechargeSet(options) {
10668
10783
  enabled: true,
10669
10784
  thresholdCredits,
10670
10785
  refillToCredits,
10786
+ ...rollingLimitCents !== void 0 ? { purchaseLimitCents: rollingLimitCents } : {},
10671
10787
  idempotencyKey
10672
10788
  });
10673
10789
  printCommandEnvelope(
@@ -10725,6 +10841,60 @@ async function handleBuyCredits(creditsRaw, options) {
10725
10841
  { json: options.json }
10726
10842
  );
10727
10843
  }
10844
+ async function handleTopUpRecover(creditsRaw, options) {
10845
+ const credits = parseTopUpCredits(creditsRaw);
10846
+ if (credits === null) {
10847
+ reportBillingFailure(
10848
+ {
10849
+ exitCode: 2,
10850
+ code: "INVALID_CREDITS",
10851
+ message: "<credits> must be a positive integer."
10852
+ },
10853
+ options
10854
+ );
10855
+ return;
10856
+ }
10857
+ const failure = !options.orgId?.trim() || options.orgId !== options.orgId.trim() ? {
10858
+ code: "INVALID_ORG_ID",
10859
+ message: "--org-id must be the original workspace ID without surrounding whitespace."
10860
+ } : !options.idempotencyKey || options.idempotencyKey.length > 200 || options.idempotencyKey !== options.idempotencyKey.trim() ? {
10861
+ code: "INVALID_BILLING_IDEMPOTENCY_KEY",
10862
+ message: "--idempotency-key must be the original key (1\u2013200 characters without surrounding whitespace)."
10863
+ } : null;
10864
+ if (failure) {
10865
+ reportBillingFailure(
10866
+ {
10867
+ exitCode: 2,
10868
+ ...failure
10869
+ },
10870
+ options
10871
+ );
10872
+ return;
10873
+ }
10874
+ if (options.dryRun) {
10875
+ printCommandEnvelope(
10876
+ {
10877
+ ok: true,
10878
+ dry_run: true,
10879
+ method: "POST",
10880
+ path: "/api/v2/billing/credit-purchases/recover",
10881
+ idempotency_key: options.idempotencyKey,
10882
+ body: { credits, org_id: options.orgId }
10883
+ },
10884
+ { json: options.json }
10885
+ );
10886
+ return;
10887
+ }
10888
+ const payload = await new DeeplineClient().billing.recoverCreditPurchase({
10889
+ credits,
10890
+ orgId: options.orgId,
10891
+ idempotencyKey: options.idempotencyKey
10892
+ });
10893
+ printCommandEnvelope(
10894
+ { ok: true, idempotency_key: options.idempotencyKey, ...payload },
10895
+ { json: options.json }
10896
+ );
10897
+ }
10728
10898
  async function handleTargetPlan(planSku, options) {
10729
10899
  if (planSku !== "payg-v1" && planSku !== "builder-v1" && planSku !== "growth-v1" && planSku !== "growth-canary-v1" && planSku !== "team-v1") {
10730
10900
  reportBillingFailure(
@@ -10842,35 +11012,36 @@ Examples:
10842
11012
  "--cursor <cursor>",
10843
11013
  "Recent-call cursor from the previous response"
10844
11014
  ).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);
10845
- billing.command("limit").description("Show configured monthly limit state.").addHelpText(
11015
+ billing.command("limit").description("Show configured monthly spend guidance.").addHelpText(
10846
11016
  "after",
10847
11017
  `
10848
11018
  Notes:
10849
- Read-only. Shows whether the monthly workspace cap is enabled and how many
10850
- Deepline credits remain before the cap.
11019
+ Read-only. Shows whether monthly workspace spend guidance is enabled.
11020
+ Guidance does not reject funded work; available balance remains exact.
10851
11021
 
10852
11022
  Examples:
10853
11023
  deepline billing limit
10854
11024
  deepline billing limit --json
10855
11025
  `
10856
11026
  ).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleLimit);
10857
- billing.command("set-limit").description("Set monthly credit cap.").addHelpText(
11027
+ billing.command("set-limit").description("Set monthly spend guidance.").addHelpText(
10858
11028
  "after",
10859
11029
  `
10860
11030
  Notes:
10861
11031
  Mutates workspace billing settings. The argument is a Deepline credit amount,
10862
- not dollars and not provider credits.
11032
+ not dollars and not provider credits. Guidance is advisory; it does not
11033
+ replace the exact available-balance admission check.
10863
11034
 
10864
11035
  Examples:
10865
11036
  deepline billing set-limit 500
10866
11037
  deepline billing set-limit 500 --json
10867
11038
  `
10868
11039
  ).argument("<credits>", "Monthly credits limit").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleSetLimit);
10869
- billing.command("off").description("Disable monthly credit cap.").addHelpText(
11040
+ billing.command("off").description("Disable monthly spend guidance.").addHelpText(
10870
11041
  "after",
10871
11042
  `
10872
11043
  Notes:
10873
- Mutates workspace billing settings by removing the monthly Deepline credit cap.
11044
+ Mutates workspace billing settings by removing monthly Deepline spend guidance.
10874
11045
 
10875
11046
  Examples:
10876
11047
  deepline billing off
@@ -10924,7 +11095,9 @@ Examples:
10924
11095
  `
10925
11096
  Notes:
10926
11097
  Read-only server query that writes a local CSV file. With --json, stdout is a
10927
- summary containing the output path and row count.
11098
+ summary containing the output path, row count, and completeness metadata.
11099
+ Exports the complete window using bounded pages. For an exact start timestamp:
11100
+ deepline billing ledger export all --since <ISO-8601> --json
10928
11101
 
10929
11102
  Examples:
10930
11103
  deepline billing history --time 1m
@@ -10966,6 +11139,18 @@ Examples:
10966
11139
  "Stable retry key for the same intended top-up"
10967
11140
  ).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);
10968
11141
  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);
11142
+ billing.command("top-up-recover").description(
11143
+ "Inspect or retire an original top-up intent without starting a payment."
11144
+ ).argument("<credits>", "Original positive integer Deepline credit amount").requiredOption(
11145
+ "--org-id <original-org>",
11146
+ "Original workspace ID (must match the authenticated workspace)"
11147
+ ).requiredOption(
11148
+ "--idempotency-key <original-key>",
11149
+ "Original purchase key; never generates a new key"
11150
+ ).option("--dry-run", "Print the recovery request without changing state").option("--json", "Emit JSON output. Also automatic when stdout is piped").addHelpText(
11151
+ "after",
11152
+ "\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"
11153
+ ).action(handleTopUpRecover);
10969
11154
  billing.command("status").description("Show normalized target billing state.").option("--json", "Emit JSON output").action(handleTargetStatus);
10970
11155
  billing.command("auto-recharge").description("Inspect and manage automatic Deepline credit recharge.").addHelpText(
10971
11156
  "after",
@@ -10986,24 +11171,37 @@ Examples:
10986
11171
  ).requiredOption(
10987
11172
  "--refill-to-credits <credits>",
10988
11173
  "Recharge the balance to this amount"
11174
+ ).option(
11175
+ "--purchase-limit-cents <cents>",
11176
+ "Limit automatic purchases over rolling 30 days (USD cents)"
10989
11177
  ).option("--idempotency-key <key>", "Stable retry key").option("--dry-run", "Print the planned update without applying it").option("--json", "Emit JSON output").action(handleAutoRechargeSet)
10990
11178
  ).addCommand(
10991
11179
  new import_commander.Command("off").description(
10992
11180
  "Disable automatic recharge without clearing saved amounts."
10993
11181
  ).option("--idempotency-key <key>", "Stable retry key").option("--dry-run", "Print the planned update without applying it").option("--json", "Emit JSON output").action(handleAutoRechargeOff)
11182
+ ).addCommand(
11183
+ new import_commander.Command("trigger").description(
11184
+ "Evaluate capped automatic recharge and resume any pending purchase."
11185
+ ).option("--json", "Emit JSON output").action(async (options) => {
11186
+ const result = await new DeeplineClient().billing.autoRecharge.trigger();
11187
+ printCommandEnvelope({ ok: true, ...result }, { json: options.json });
11188
+ })
10994
11189
  );
10995
- 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);
11190
+ billing.command("change-plan").description("Start or change the target billing plan.").argument(
11191
+ "<plan_sku>",
11192
+ "payg-v1, builder-v1, growth-v1, growth-canary-v1, or team-v1"
11193
+ ).option("--idempotency-key <key>", "Stable retry key").option("--json", "Emit JSON output").action(handleTargetPlan);
10996
11194
  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);
10997
11195
  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);
10998
11196
  billing.command("plans").description("Show published plans and the plan you are on.").addHelpText(
10999
11197
  "after",
11000
11198
  `
11001
11199
  Notes:
11002
- Read-only. Answers "what plans exist and what am I on": each plan's price,
11003
- monthly grant credits, rollover policy, and whether it is open for
11004
- subscription, plus the catalog's usage metrics. All amounts are Deepline
11005
- credits and Deepline-facing USD, never raw provider spend. Subscribe to a
11006
- listed plan with: deepline billing subscribe <plan_version_id>
11200
+ Read-only. Shows the current target billing plan, pending plan, and every
11201
+ visible plan's recurring price, included credits, purchased-credit price,
11202
+ and current acquisition availability. All amounts are Deepline credits and
11203
+ Deepline-facing USD, never raw provider spend. Change to an available plan
11204
+ with: deepline billing change-plan <plan_sku>
11007
11205
 
11008
11206
  Examples:
11009
11207
  deepline billing plans
@@ -11025,7 +11223,7 @@ Examples:
11025
11223
  deepline billing subscribe runtime-395-2026-07-v1
11026
11224
  deepline billing subscribe runtime-395-2026-07-v1 --no-open --json
11027
11225
  `
11028
- ).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);
11226
+ ).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);
11029
11227
  billing.command("subscription").description("Inspect and manage subscription state for the workspace.").addHelpText(
11030
11228
  "after",
11031
11229
  `
@@ -11284,6 +11482,7 @@ function mergeCanonicalRowsInfo(left, right) {
11284
11482
  ...right.recoveredReturnPaths ?? []
11285
11483
  ])
11286
11484
  ];
11485
+ const currentTable = left.currentTable || right.currentTable;
11287
11486
  return {
11288
11487
  ...fallback,
11289
11488
  ...preferred,
@@ -11297,6 +11496,7 @@ function mergeCanonicalRowsInfo(left, right) {
11297
11496
  tableNamespace: preferred.tableNamespace ?? fallback.tableNamespace,
11298
11497
  ...left.recovered || right.recovered ? { recovered: true } : {},
11299
11498
  ...recoveredReturnPaths2.length ? { recoveredReturnPaths: recoveredReturnPaths2 } : {},
11499
+ ...currentTable ? { currentTable: true } : {},
11300
11500
  ...exportUnavailableReason ? {
11301
11501
  exportUnavailableReason,
11302
11502
  ...unavailableSource?.exportUnavailableMessage ? {
@@ -11357,6 +11557,11 @@ function isSerializedDataset(value) {
11357
11557
  function isPackagedDatasetOutput(value) {
11358
11558
  return isRecord8(value) && value.kind === "dataset" && isRecord8(value.preview) && Array.isArray(value.preview.rows);
11359
11559
  }
11560
+ function hasCurrentTableExport(value) {
11561
+ if (!isRecord8(value) || !isRecord8(value.actions)) return false;
11562
+ const exportCsv = value.actions.exportCsv;
11563
+ return isRecord8(exportCsv) && isRecord8(exportCsv.scope) && exportCsv.scope.kind === "database" && exportCsv.scope.mutability === "current";
11564
+ }
11360
11565
  function recoveredReturnPaths(value) {
11361
11566
  if (!Array.isArray(value)) return [];
11362
11567
  return [
@@ -11463,6 +11668,7 @@ function canonicalRowsInfoFromCandidate(input2) {
11463
11668
  datasetId: typeof candidate.value.datasetId === "string" ? candidate.value.datasetId : null,
11464
11669
  tableNamespace: typeof candidate.value.tableNamespace === "string" ? candidate.value.tableNamespace : null,
11465
11670
  ...candidate.value.recovered === true ? { recovered: true } : {},
11671
+ ...hasCurrentTableExport(candidate.value) ? { currentTable: true } : {},
11466
11672
  ...recoveredReturnPaths(candidate.value.recoveredReturnPaths).length ? {
11467
11673
  recoveredReturnPaths: recoveredReturnPaths(
11468
11674
  candidate.value.recoveredReturnPaths
@@ -19777,6 +19983,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
19777
19983
  runId: workflowId,
19778
19984
  playName: input2.playName,
19779
19985
  dashboardUrl,
19986
+ inputFieldCount: Object.keys(input2.request.input ?? {}).length,
19780
19987
  jsonOutput: false,
19781
19988
  progress: input2.progress
19782
19989
  });
@@ -20894,11 +21101,15 @@ function formatPackageDatasetActionLines(packaged) {
20894
21101
  ` ${category} dataset ${path}: ${rowCount === null ? "unknown rows" : `${formatInteger(rowCount)} ${rowCount === 1 ? "row" : "rows"}`}`
20895
21102
  );
20896
21103
  }
20897
- const exportCommand = actionToCommand(actions.exportCsv);
21104
+ const exportAction = readRecord(actions.exportCsv);
21105
+ const exportCommand = actionToCommand(exportAction);
21106
+ const exportScope = readRecord(exportAction?.scope);
20898
21107
  const currentQueryCommand = actionToCommand(actions.queryCurrentTable);
20899
21108
  const legacyQueryCommand = actionToCommand(actions.query);
20900
21109
  if (exportCommand) {
20901
- lines.push(` export this run: ${exportCommand}`);
21110
+ lines.push(
21111
+ exportScope?.kind === "database" ? ` export current table (may include other runs): ${exportCommand}` : ` export this run: ${exportCommand}`
21112
+ );
20902
21113
  }
20903
21114
  if (currentQueryCommand) {
20904
21115
  lines.push(` query current table: ${currentQueryCommand}`);
@@ -21307,33 +21518,29 @@ function sqlSafeExportColumnName(id) {
21307
21518
  async function fetchBackingDatasetRows(input2) {
21308
21519
  const playName = extractRunPlayName(input2.status);
21309
21520
  const tableNamespace = input2.rowsInfo.tableNamespace?.trim();
21521
+ const currentTable = input2.rowsInfo.currentTable === true;
21310
21522
  if (!playName || !tableNamespace) {
21311
21523
  return null;
21312
21524
  }
21313
21525
  const sheetRows = [];
21314
21526
  let offset = 0;
21315
- let expectedTotal = input2.rowsInfo.totalRows;
21316
21527
  while (true) {
21317
21528
  const page = await input2.client.runs.exportDatasetRows({
21318
21529
  playName,
21319
21530
  tableNamespace,
21320
- runId: input2.status.runId,
21531
+ ...currentTable ? {} : { runId: input2.status.runId },
21321
21532
  limit: RUN_EXPORT_PAGE_SIZE,
21322
21533
  offset,
21323
21534
  rowMode: "all"
21324
21535
  });
21325
21536
  sheetRows.push(...page.rows);
21326
- const summaryTotal = page.summary?.stats?.total;
21327
- if (typeof summaryTotal === "number" && Number.isFinite(summaryTotal)) {
21328
- expectedTotal = Math.max(expectedTotal, Math.trunc(summaryTotal));
21329
- }
21330
- if (page.rows.length < RUN_EXPORT_PAGE_SIZE || sheetRows.length >= expectedTotal) {
21537
+ if (page.rows.length < RUN_EXPORT_PAGE_SIZE) {
21331
21538
  break;
21332
21539
  }
21333
21540
  offset += page.rows.length;
21334
21541
  }
21335
21542
  const rows = sheetRows.map(exportableSheetRow).filter((row) => Boolean(row));
21336
- if (rows.length < input2.rowsInfo.totalRows) {
21543
+ if (!currentTable && rows.length < input2.rowsInfo.totalRows || currentTable && rows.length === 0 && input2.rowsInfo.totalRows > 0) {
21337
21544
  return null;
21338
21545
  }
21339
21546
  const columns = mergeExportColumns(
@@ -21346,6 +21553,7 @@ async function fetchBackingDatasetRows(input2) {
21346
21553
  columns,
21347
21554
  totalRows: rows.length,
21348
21555
  complete: true,
21556
+ ...currentTable ? { currentTable: true } : {},
21349
21557
  source: `${input2.rowsInfo.source ?? "result.rows"} -> /api/v2/plays/${playName}/sheet?tableNamespace=${tableNamespace}`
21350
21558
  };
21351
21559
  }
@@ -21370,12 +21578,14 @@ function assertDatasetHasExportableRows(input2) {
21370
21578
  if (input2.rowsInfo.rows.length > 0) {
21371
21579
  return input2.rowsInfo;
21372
21580
  }
21581
+ if (input2.rowsInfo.currentTable === true && input2.rowsInfo.totalRows === 0) {
21582
+ return input2.rowsInfo;
21583
+ }
21373
21584
  const datasetLabel = input2.datasetPath ?? input2.rowsInfo.tableNamespace ?? input2.rowsInfo.source ?? "result.rows";
21374
21585
  const available = input2.availableRows.map((info) => info.tableNamespace ?? info.source).filter((name) => typeof name === "string");
21375
21586
  const runStatus = String(input2.status.status ?? "").toLowerCase();
21376
- const failedBeforePersisting = runStatus !== "completed";
21377
21587
  throw new DeeplineError(
21378
- `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."),
21588
+ `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."),
21379
21589
  void 0,
21380
21590
  "RUN_EXPORT_EMPTY",
21381
21591
  {
@@ -21386,23 +21596,6 @@ function assertDatasetHasExportableRows(input2) {
21386
21596
  }
21387
21597
  );
21388
21598
  }
21389
- function assertDatasetExportAvailable(input2) {
21390
- if (input2.rowsInfo.exportUnavailableReason !== "shared_table_namespace") {
21391
- return;
21392
- }
21393
- throw new DeeplineError(
21394
- input2.rowsInfo.exportUnavailableMessage ?? "Run CSV export is unavailable because multiple Dataset Handles share one physical table.",
21395
- void 0,
21396
- "RUN_EXPORT_UNAVAILABLE",
21397
- {
21398
- runId: input2.status.runId,
21399
- dataset: input2.rowsInfo.source,
21400
- datasetId: input2.rowsInfo.datasetId ?? null,
21401
- tableNamespace: input2.rowsInfo.tableNamespace ?? null,
21402
- reason: input2.rowsInfo.exportUnavailableReason
21403
- }
21404
- );
21405
- }
21406
21599
  async function exportPlayStatusRows(client2, status, outPath, options = {}) {
21407
21600
  if (!outPath) {
21408
21601
  return null;
@@ -21481,7 +21674,6 @@ ${commands.join("\n")}`,
21481
21674
  `Run ${status.runId} did not expose a row-shaped final output to export.`
21482
21675
  );
21483
21676
  }
21484
- assertDatasetExportAvailable({ rowsInfo, status });
21485
21677
  const attempts = Math.max(1, Math.trunc(options.attempts ?? 1));
21486
21678
  const retryDelayMs = Math.max(0, Math.trunc(options.retryDelayMs ?? 0));
21487
21679
  for (let attempt = 1; attempt <= attempts; attempt += 1) {
@@ -21496,6 +21688,9 @@ ${commands.join("\n")}`,
21496
21688
  if (error instanceof DeeplineError && error.code === "RUN_EXPORT_SCOPE_MISMATCH") {
21497
21689
  throw error;
21498
21690
  }
21691
+ if (rowsInfo.currentTable) {
21692
+ throw error;
21693
+ }
21499
21694
  if (!rowsInfo.complete) {
21500
21695
  throw error;
21501
21696
  }
@@ -21509,7 +21704,8 @@ ${commands.join("\n")}`,
21509
21704
  });
21510
21705
  return {
21511
21706
  path: RunDataset.from(guarded2).exportCsv(outPath),
21512
- rowsInfo: guarded2
21707
+ rowsInfo: guarded2,
21708
+ currentTable: fetchedRowsInfo.currentTable === true
21513
21709
  };
21514
21710
  }
21515
21711
  if (rowsInfo.complete) {
@@ -21521,7 +21717,8 @@ ${commands.join("\n")}`,
21521
21717
  });
21522
21718
  return {
21523
21719
  path: RunDataset.from(guarded2).exportCsv(outPath),
21524
- rowsInfo: guarded2
21720
+ rowsInfo: guarded2,
21721
+ currentTable: false
21525
21722
  };
21526
21723
  }
21527
21724
  if (attempt < attempts && retryDelayMs > 0) {
@@ -21556,7 +21753,8 @@ ${commands.join("\n")}`,
21556
21753
  });
21557
21754
  return {
21558
21755
  path: RunDataset.from(guarded).exportCsv(outPath),
21559
- rowsInfo: guarded
21756
+ rowsInfo: guarded,
21757
+ currentTable: false
21560
21758
  };
21561
21759
  }
21562
21760
  function extractActiveRunsFromError(error) {
@@ -23420,12 +23618,13 @@ async function handleRunsList(args) {
23420
23618
  return 1;
23421
23619
  }
23422
23620
  const client2 = new DeeplineClient();
23423
- const runs = (await client2.runs.list({
23621
+ const page = await client2.runs.listPage({
23424
23622
  ...playName ? { play: playName } : {},
23425
23623
  ...statusFilter ? { status: statusFilter } : {},
23426
23624
  ...limit !== void 0 ? { limit } : {},
23427
23625
  ...offset !== void 0 ? { offset } : {}
23428
- })).map((run) => ({
23626
+ });
23627
+ const runs = page.runs.map((run) => ({
23429
23628
  runId: run.workflowId,
23430
23629
  // `workflowId` is the legacy SDK name for the same public Deepline run
23431
23630
  // identity. Keep it during the compatibility window, but never label the
@@ -23463,11 +23662,24 @@ async function handleRunsList(args) {
23463
23662
  if (run.rootRunId) lines2.push(` root: ${run.rootRunId}`);
23464
23663
  return lines2.join("\n");
23465
23664
  });
23665
+ const nextOffset = (page.offset ?? offset ?? 0) + runs.length;
23666
+ const nextPage = page.hasMore && playName ? `deepline runs list --play ${shellQuote2(playName)}${statusFilter ? ` --status ${shellQuote2(statusFilter)}` : ""} --limit ${page.limit ?? limit ?? 20} --offset ${nextOffset} --json` : null;
23667
+ if (page.hasMore) {
23668
+ lines.push("List truncated \u2014 more runs match this filter.");
23669
+ lines.push(
23670
+ nextPage ? `Next page: ${nextPage}` : "Narrow with --play <play-name> to page through runs."
23671
+ );
23672
+ }
23466
23673
  printCommandEnvelope(
23467
23674
  {
23468
23675
  runs,
23469
23676
  count: runs.length,
23677
+ ...page.total !== void 0 ? { total: page.total } : {},
23678
+ offset: page.offset ?? offset ?? 0,
23679
+ limit: page.limit ?? limit ?? (playName ? 20 : 100),
23680
+ ...page.hasMore !== void 0 ? { has_more: page.hasMore, is_truncated: page.hasMore } : {},
23470
23681
  next: {
23682
+ page: nextPage,
23471
23683
  get: runs[0]?.runId ? `deepline runs get ${runs[0].runId} --json` : null
23472
23684
  },
23473
23685
  render: { sections: [{ title: "runs", lines }] }
@@ -23893,6 +24105,11 @@ async function handleRunExport(args) {
23893
24105
  datasetPath
23894
24106
  });
23895
24107
  const source = exportResult?.rowsInfo.source ?? datasetPath ?? null;
24108
+ const currentTableNotice = exportResult?.currentTable ? {
24109
+ code: "CURRENT_SHARED_DATASET",
24110
+ message: "This CSV is the current shared dataset and may include writes from another run.",
24111
+ full_run_output_command: `deepline runs get ${status.runId} --full --json`
24112
+ } : null;
23896
24113
  const next = {
23897
24114
  ...buildRunNextCommands(status),
23898
24115
  export: runExportRetryCommand(status.runId, outPath, datasetPath ?? source)
@@ -23904,6 +24121,7 @@ async function handleRunExport(args) {
23904
24121
  source,
23905
24122
  rowCount: exportResult?.rowsInfo.totalRows ?? null,
23906
24123
  columns: exportResult?.rowsInfo.columns ?? [],
24124
+ ...currentTableNotice ? { notice: currentTableNotice } : {},
23907
24125
  ...metadataOutPath ? { metadata_path: metadataOutPath } : {},
23908
24126
  local: { csv_path: exportResult?.path ?? null },
23909
24127
  next,
@@ -23913,6 +24131,10 @@ async function handleRunExport(args) {
23913
24131
  title: "run export",
23914
24132
  lines: [
23915
24133
  `Exported ${status.runId} to ${exportResult?.path ?? outPath}`,
24134
+ ...currentTableNotice ? [
24135
+ "Current shared dataset: this CSV may include writes from another run.",
24136
+ `This run's full returned output: ${currentTableNotice.full_run_output_command}`
24137
+ ] : [],
23916
24138
  ...source ? [`source=${source}`] : []
23917
24139
  ]
23918
24140
  }
@@ -24115,23 +24337,47 @@ async function handlePlayVersions(args) {
24115
24337
  }
24116
24338
  return 0;
24117
24339
  }
24340
+ function formatPlayCostEstimate(estimate) {
24341
+ if (!estimate || estimate.status === "unavailable") {
24342
+ return `unavailable${estimate ? `: ${estimate.message}` : ""}`;
24343
+ }
24344
+ const formatCredits = (value) => value.toLocaleString("en-US", {
24345
+ maximumFractionDigits: value < 1 ? 4 : 2
24346
+ });
24347
+ const credits = estimate.lowCredits === estimate.highCredits ? `${estimate.source === "observed" ? "~" : ""}${formatCredits(estimate.lowCredits)}` : `${formatCredits(estimate.lowCredits)}\u2013${formatCredits(estimate.highCredits)}`;
24348
+ const unit = estimate.unit === "row" ? "output row" : "run";
24349
+ const source = estimate.source === "observed" ? `observed from ${estimate.sampleRunCount} ${estimate.sampleRunCount === 1 ? "run" : "runs"}` : "static estimate";
24350
+ return `${credits} Deepline credits per ${unit} (${source})`;
24351
+ }
24118
24352
  async function handlePlayList(args) {
24119
24353
  const jsonOutput = argsWantJson(args);
24354
+ const showCost = args.includes("--show-cost");
24120
24355
  const client2 = new DeeplineClient();
24121
24356
  const categoriesIndex = args.indexOf("--categories");
24122
24357
  const categories = categoriesIndex >= 0 ? args[categoriesIndex + 1]?.trim() : void 0;
24123
- const plays = await client2.listPlays({
24358
+ const limitIndex = args.indexOf("--limit");
24359
+ const cursorIndex = args.indexOf("--cursor");
24360
+ const limit = limitIndex >= 0 ? Number(args[limitIndex + 1]) : void 0;
24361
+ const cursor = cursorIndex >= 0 ? args[cursorIndex + 1] : void 0;
24362
+ if (limitIndex >= 0 && (!Number.isSafeInteger(limit) || limit < 1) || cursorIndex >= 0 && !cursor?.trim()) {
24363
+ console.error("Pass a positive --limit and a non-empty --cursor.");
24364
+ return 2;
24365
+ }
24366
+ const page = await client2.listPlaysPage({
24124
24367
  categories,
24125
- includeToolCategories: true
24126
- });
24127
- if (jsonOutput) {
24128
- process.stdout.write(`${JSON.stringify(plays)}
24129
- `);
24130
- return 0;
24368
+ includeToolCategories: true,
24369
+ ...showCost ? { includeCostEstimates: true } : {},
24370
+ limit,
24371
+ cursor
24372
+ });
24373
+ const plays = page.plays;
24374
+ 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;
24375
+ if (page.hasMore && !nextPage) {
24376
+ throw new Error(
24377
+ "Play list reported more results without a continuation cursor"
24378
+ );
24131
24379
  }
24132
- process.stdout.write(`${plays.length} plays available:
24133
-
24134
- `);
24380
+ const lines = [`${plays.length} plays in this page:`];
24135
24381
  for (const play of plays) {
24136
24382
  const flags = [
24137
24383
  play.pinned ? "pinned" : null,
@@ -24141,32 +24387,48 @@ async function handlePlayList(args) {
24141
24387
  play.isDraftDirty ? "draft-dirty" : null
24142
24388
  ].filter(Boolean).join(", ");
24143
24389
  const reference = formatPlayListReference(play);
24144
- process.stdout.write(` ${reference}${flags ? ` [${flags}]` : ""}
24145
- `);
24390
+ lines.push(` ${reference}${flags ? ` [${flags}]` : ""}`);
24146
24391
  if (play.inputSchema || play.hasInputSchema) {
24147
- process.stdout.write(" inputSchema: yes\n");
24392
+ lines.push(" inputSchema: yes");
24148
24393
  }
24149
24394
  if (play.triggerStatus?.cron) {
24150
- process.stdout.write(
24151
- ` scheduled execution: ${cronExecutionLabel(play.triggerStatus.cron)}
24152
- `
24395
+ lines.push(
24396
+ ` scheduled execution: ${cronExecutionLabel(play.triggerStatus.cron)}`
24153
24397
  );
24154
24398
  if (play.triggerStatus.blockedReason) {
24155
- process.stdout.write(
24156
- ` schedule issue: ${play.triggerStatus.blockedReason}
24157
- `
24158
- );
24399
+ lines.push(` schedule issue: ${play.triggerStatus.blockedReason}`);
24159
24400
  }
24160
24401
  } else {
24161
- process.stdout.write(" scheduled execution: not configured\n");
24402
+ lines.push(" scheduled execution: not configured");
24162
24403
  }
24163
24404
  if (play.triggerStatus?.webhook) {
24164
- process.stdout.write(` webhook: ${play.triggerStatus.webhook}
24165
- `);
24405
+ lines.push(` webhook: ${play.triggerStatus.webhook}`);
24166
24406
  }
24167
- process.stdout.write(` run: deepline plays run ${reference} --watch
24168
- `);
24407
+ if (showCost) {
24408
+ lines.push(
24409
+ ` cost estimate: ${formatPlayCostEstimate(play.costEstimate)}`
24410
+ );
24411
+ }
24412
+ lines.push(` run: deepline plays run ${reference} --watch`);
24413
+ }
24414
+ if (page.hasMore) {
24415
+ lines.push("List truncated \u2014 more plays are available.");
24416
+ lines.push(`Next page: ${nextPage}`);
24169
24417
  }
24418
+ printCommandEnvelope(
24419
+ {
24420
+ plays,
24421
+ count: plays.length,
24422
+ has_more: page.hasMore,
24423
+ is_truncated: page.hasMore,
24424
+ next_cursor: page.cursor,
24425
+ next: { page: nextPage },
24426
+ render: {
24427
+ sections: [{ title: "plays", lines }]
24428
+ }
24429
+ },
24430
+ { json: jsonOutput }
24431
+ );
24170
24432
  return 0;
24171
24433
  }
24172
24434
  async function handlePlayPin(args, pinned) {
@@ -24330,51 +24592,18 @@ function compactPlaySchema(schema) {
24330
24592
  ).filter((field) => Boolean(field?.name)) : [];
24331
24593
  return fields.length > 0 ? { fields } : schema;
24332
24594
  }
24333
- function playSchemaMetadata(schema, key) {
24334
- if (!schema || typeof schema !== "object" || Array.isArray(schema))
24335
- return null;
24336
- const value = schema[key];
24337
- return value && typeof value === "object" && !Array.isArray(value) ? value : null;
24338
- }
24339
- function playRunCommand(play, options) {
24340
- const target = play.reference || play.name;
24341
- if (options?.csvInput) {
24342
- const inputField = typeof options.csvInput.inputField === "string" && options.csvInput.inputField.trim() ? options.csvInput.inputField.trim() : "csv";
24343
- return `deepline plays run ${target} --input '${JSON.stringify({ [inputField]: "leads.csv" })}' --watch`;
24344
- }
24345
- return `deepline plays run ${target} --input '{...}' --watch`;
24346
- }
24347
- function summarizePlayListItemForCli(play, options) {
24348
- const aliases = play.aliases ?? [];
24349
- const csvInput = playSchemaMetadata(play.inputSchema, "csvInput");
24350
- const rowOutputSchema = playSchemaMetadata(
24351
- play.outputSchema,
24352
- "rowOutputSchema"
24353
- );
24354
- const runCommand2 = playRunCommand(play, { csvInput });
24355
- const cloneEditStarter = buildCloneEditStarter(play);
24595
+ function summarizePlayGrepResult(play) {
24596
+ const reference = formatPlayListReference(play);
24356
24597
  return {
24357
- name: play.name,
24358
- ...play.reference ? { reference: play.reference } : {},
24359
- ...play.displayName ? { displayName: play.displayName } : {},
24360
- pinned: Boolean(play.pinned),
24361
- toolCategories: play.toolCategories ?? [],
24362
- origin: play.origin,
24363
- ownerType: play.ownerType,
24364
- canEdit: play.canEdit,
24365
- canClone: play.canClone,
24366
- aliases,
24367
- inputSchema: options?.compact ? compactPlaySchema(play.inputSchema) : play.inputSchema ?? null,
24368
- outputSchema: options?.compact ? compactPlaySchema(play.outputSchema) : play.outputSchema ?? null,
24369
- ...csvInput ? { csvInput } : {},
24370
- ...rowOutputSchema ? { rowOutputSchema } : {},
24371
- runCommand: runCommand2,
24372
- examples: [runCommand2],
24373
- ...cloneEditStarter ? { cloneEditStarter } : {},
24374
- currentPublishedVersion: play.currentPublishedVersion ?? null,
24375
- isDraftDirty: play.isDraftDirty
24598
+ name: play.displayName?.trim() || play.name,
24599
+ reference,
24600
+ matches: play.matches ?? [],
24601
+ describe: `deepline plays describe ${reference} --json`
24376
24602
  };
24377
24603
  }
24604
+ function formatPlayGrepMatches(matches) {
24605
+ return matches.map((match) => `${match.field}: ${match.terms.join(", ")}`).join("; ");
24606
+ }
24378
24607
  async function handlePlaySearch(args) {
24379
24608
  let options;
24380
24609
  try {
@@ -24430,84 +24659,35 @@ async function handlePlaySearch(args) {
24430
24659
  }
24431
24660
  return 0;
24432
24661
  }
24433
- function normalizePlayGrepText(value) {
24434
- if (value === null || value === void 0) return "";
24435
- if (typeof value === "string") return value.toLowerCase();
24436
- if (typeof value === "number" || typeof value === "boolean") {
24437
- return String(value).toLowerCase();
24438
- }
24439
- if (Array.isArray(value)) return value.map(normalizePlayGrepText).join(" ");
24440
- if (typeof value === "object") {
24441
- return Object.values(value).map(normalizePlayGrepText).join(" ");
24442
- }
24443
- return "";
24444
- }
24445
- function parsePlayGrepTerms(query, mode) {
24446
- const trimmed = query.trim().toLowerCase();
24447
- if (!trimmed) return [];
24448
- if (mode === "phrase") return [trimmed];
24449
- const matches = trimmed.match(/"([^"]+)"|'([^']+)'|\S+/g) ?? [];
24450
- return matches.map((term) => term.replace(/^["']|["']$/g, "").trim()).filter(Boolean);
24451
- }
24452
- function matchesPlayGrepQuery(value, query, mode) {
24453
- const terms = parsePlayGrepTerms(query, mode);
24454
- if (terms.length === 0) return true;
24455
- const haystack = normalizePlayGrepText(value);
24456
- if (mode === "any") return terms.some((term) => haystack.includes(term));
24457
- return terms.every((term) => haystack.includes(term));
24458
- }
24459
24662
  async function handlePlayGrep(args) {
24460
24663
  const query = args[0]?.trim();
24461
24664
  if (!query) {
24462
- console.error(
24463
- "Usage: deepline plays grep <query> [--mode all|any|phrase] [--compact] [--json]"
24464
- );
24665
+ console.error("Usage: deepline plays grep <query> [--json]");
24465
24666
  return 1;
24466
24667
  }
24467
- let mode = "all";
24468
- for (let index = 1; index < args.length; index += 1) {
24469
- const arg = args[index];
24470
- if (arg === "--mode" && args[index + 1]) {
24471
- const rawMode = args[++index].trim().toLowerCase();
24472
- mode = rawMode === "any" || rawMode === "phrase" ? rawMode : "all";
24473
- }
24474
- }
24475
- const compact = args.includes("--compact");
24476
24668
  const client2 = new DeeplineClient();
24477
- const plays = (await client2.listPlays({
24478
- grep: query,
24479
- grepMode: mode
24480
- })).filter(
24481
- (play) => matchesPlayGrepQuery(
24482
- {
24483
- name: play.name,
24484
- reference: play.reference,
24485
- displayName: play.displayName,
24486
- origin: play.origin,
24487
- ownerType: play.ownerType,
24488
- aliases: play.aliases,
24489
- toolCategories: play.toolCategories,
24490
- inputSchema: play.inputSchema,
24491
- outputSchema: play.outputSchema
24492
- },
24493
- query,
24494
- mode
24495
- )
24496
- ).map((play) => summarizePlayListItemForCli(play, { compact }));
24669
+ const results = (await client2.listPlays({ grep: query })).map(
24670
+ summarizePlayGrepResult
24671
+ );
24497
24672
  if (argsWantJson(args)) {
24498
24673
  printCompactJson({
24499
- plays,
24500
- count: plays.length,
24674
+ plays: results,
24675
+ count: results.length,
24501
24676
  query,
24502
- grep: { mode, terms: parsePlayGrepTerms(query, mode) }
24677
+ grep: { query }
24503
24678
  });
24504
24679
  return 0;
24505
24680
  }
24506
- process.stdout.write(`${plays.length} plays found:
24681
+ process.stdout.write(
24682
+ `${results.length} results for ${JSON.stringify(query)}:
24507
24683
 
24508
- `);
24509
- for (const play of plays) {
24510
- printPlayDescription(play);
24684
+ `
24685
+ );
24686
+ for (const result of results) {
24687
+ console.log(result.name);
24688
+ const matches = formatPlayGrepMatches(result.matches);
24689
+ if (matches) console.log(` Matched: ${matches}`);
24690
+ console.log(` Describe: ${result.describe}`);
24511
24691
  console.log("");
24512
24692
  }
24513
24693
  return 0;
@@ -25207,7 +25387,7 @@ Pass-through input flags:
25207
25387
  if (effectiveTarget && passthroughArgs[0] === effectiveTarget) {
25208
25388
  passthroughArgs.shift();
25209
25389
  }
25210
- process.exitCode = await handlePlayRun([
25390
+ const exitCode = await handlePlayRun([
25211
25391
  ...effectiveTarget ? [effectiveTarget] : [],
25212
25392
  ...options.file ? ["--file", options.file] : [],
25213
25393
  ...options.name ? ["--name", options.name] : [],
@@ -25237,6 +25417,11 @@ Pass-through input flags:
25237
25417
  ...options.full ? ["--full"] : [],
25238
25418
  ...passthroughArgs
25239
25419
  ]);
25420
+ recordCliTrace({
25421
+ phase: "cli.play_command_exit",
25422
+ exitCode
25423
+ });
25424
+ process.exitCode = exitCode;
25240
25425
  });
25241
25426
  registerPlayBootstrapCommand(play);
25242
25427
  play.command("get <target>").description(
@@ -25278,17 +25463,22 @@ Examples:
25278
25463
  `
25279
25464
  Notes:
25280
25465
  Inventory command for saved org plays and prebuilt plays. Use search for
25281
- ranked discovery by task or schema.
25466
+ ranked discovery by task or schema. Returns one bounded page with has_more,
25467
+ is_truncated, next_cursor, and a next-page command. Use --limit to choose
25468
+ the page size and --cursor to continue with the same filters.
25282
25469
 
25283
25470
  Examples:
25284
25471
  deepline plays list
25285
25472
  deepline plays search email --json
25286
25473
  `
25287
- ).option("--json", "Emit JSON output. Also automatic when stdout is piped").option(
25474
+ ).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(
25288
25475
  "--categories <categories>",
25289
25476
  "Filter by comma-separated canonical tool categories"
25290
25477
  ).action(async (options) => {
25291
25478
  process.exitCode = await handlePlayList([
25479
+ ...options.limit ? ["--limit", options.limit] : [],
25480
+ ...options.cursor ? ["--cursor", options.cursor] : [],
25481
+ ...options.showCost ? ["--show-cost"] : [],
25292
25482
  ...options.categories ? ["--categories", options.categories] : [],
25293
25483
  ...options.json ? ["--json"] : []
25294
25484
  ]);
@@ -25327,13 +25517,13 @@ Notes:
25327
25517
  because they are trusted, robust plays with maintained contracts. Use describe
25328
25518
  on a result before running it.
25329
25519
  Add --all only when you are specifically looking for a play you created.
25330
- The grep alias is the same ranked retrieval surface with a more literal name
25331
- for agents that are filtering the play registry.
25520
+ Use plays grep to search active org-owned Plays through Convex's indexed
25521
+ authored corpus. It does not search prebuilt or archived Plays.
25332
25522
 
25333
25523
  Examples:
25334
25524
  deepline plays search email
25335
25525
  deepline plays search email --all
25336
- deepline plays grep "linkedin to email" --compact --json
25526
+ deepline plays grep "linkedin to email" --json
25337
25527
  deepline plays describe prebuilt/person-linkedin-to-email --json
25338
25528
  `
25339
25529
  ).option("--compact", "Emit compact schemas").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (query, options) => {
@@ -25346,25 +25536,22 @@ Examples:
25346
25536
  ]);
25347
25537
  });
25348
25538
  addPlaySearchCommand(play.command("search <query>"));
25349
- play.command("grep <query>").description("Literal grep over play names, schemas, and descriptions.").addHelpText(
25539
+ play.command("grep <query>").description(
25540
+ "Search active org-owned Plays through Convex full-text search."
25541
+ ).addHelpText(
25350
25542
  "after",
25351
25543
  `
25352
25544
  Notes:
25353
- Literal registry filtering. Terms are matched case-insensitively against play
25354
- names, references, display names, ownership, and schemas. Use
25355
- --mode phrase for exact phrase matching, --mode any for OR, and the default
25356
- --mode all for AND.
25545
+ Queries use Convex token semantics over the indexed authored Play corpus.
25546
+ Prebuilt and archived Plays are not part of this index.
25357
25547
 
25358
25548
  Examples:
25359
25549
  deepline plays grep email --json
25360
- deepline plays grep "company contact" --mode all --json
25361
25550
  deepline plays describe prebuilt/company-to-contact --json
25362
25551
  `
25363
- ).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) => {
25552
+ ).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (query, options) => {
25364
25553
  process.exitCode = await handlePlayGrep([
25365
25554
  query,
25366
- ...options.compact ? ["--compact"] : [],
25367
- ...options.mode ? ["--mode", options.mode] : [],
25368
25555
  ...options.json ? ["--json"] : []
25369
25556
  ]);
25370
25557
  });
@@ -30962,7 +31149,7 @@ async function compileConfig(input2) {
30962
31149
  })).config;
30963
31150
  }
30964
31151
  function registerEnrichCommand(program) {
30965
- program.command("enrich").allowUnknownOption(true).description("Run v1-style CSV enrichment through the V2 play runner.").configureHelp({
31152
+ program.command("enrich", { hidden: true }).allowUnknownOption(true).description("Run v1-style CSV enrichment through the V2 play runner.").configureHelp({
30966
31153
  optionTerm(option) {
30967
31154
  return option.long === "--timeout" ? "--timeout SECONDS" : option.flags;
30968
31155
  }
@@ -32018,7 +32205,7 @@ function loadViewerAssets() {
32018
32205
  "viewer"
32019
32206
  )
32020
32207
  ] : [],
32021
- (0, import_node_path16.join)(process.cwd(), "src", "lib", "cli", "viewer")
32208
+ (0, import_node_path16.join)(process.cwd(), "packages", "sdk", "assets", "viewer")
32022
32209
  ];
32023
32210
  for (const root of candidateRoots2) {
32024
32211
  try {
@@ -32235,7 +32422,7 @@ function addDeprecatedSubcommand(parent, family, subcommand, description) {
32235
32422
  });
32236
32423
  }
32237
32424
  function registerDeprecatedCommands(program) {
32238
- const session = program.command("session").description("Deprecated legacy session command namespace.").allowUnknownOption(true).allowExcessArguments(true).option("--json", "Emit JSON output").argument("[args...]").addHelpText(
32425
+ 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(
32239
32426
  "after",
32240
32427
  `
32241
32428
  Notes:
@@ -32267,7 +32454,7 @@ Examples:
32267
32454
  `Deprecated legacy "deepline session ${subcommand}" command.`
32268
32455
  );
32269
32456
  }
32270
- const backend = program.command("backend").description("Deprecated legacy local backend command namespace.").allowUnknownOption(true).allowExcessArguments(true).option("--json", "Emit JSON output").argument("[args...]").addHelpText(
32457
+ 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(
32271
32458
  "after",
32272
32459
  `
32273
32460
  Notes:
@@ -32303,7 +32490,7 @@ var import_node_fs15 = require("fs");
32303
32490
  var import_node_path17 = require("path");
32304
32491
  var import_promises8 = require("readline/promises");
32305
32492
 
32306
- // src/monitor-fleet-contract.ts
32493
+ // ../integration-contracts/monitor-fleet-contract.ts
32307
32494
  var MONITOR_FLEET_MAX_MEMBERS = 1e3;
32308
32495
  var MONITOR_FLEET_AUTHORING_CONTRACT_EDITION = 1;
32309
32496
  var SUPPORTED_MONITOR_FLEET_AUTHORING_CONTRACT_EDITIONS = [
@@ -32989,9 +33176,35 @@ function renderMonitorDeployPlan(payload) {
32989
33176
  " Inspect: deepline monitors get <key> --json"
32990
33177
  );
32991
33178
  }
33179
+ const identityConflict = asRecord2(payload.identity_conflict);
33180
+ const identityOwner = identityConflict ? asRecord2(identityConflict.existing_monitor) : null;
33181
+ const identityOwnerKey = identityOwner ? asString(identityOwner.key) : void 0;
33182
+ const identityOwnerStatus = identityOwner ? asString(identityOwner.status) : void 0;
33183
+ if (identityConflict) {
33184
+ if (identityOwnerStatus === "provisioning") {
33185
+ lines.push(
33186
+ "",
33187
+ "An in-progress provider operation owns this upstream identity.",
33188
+ "Do not deploy this key yet. Wait, then rerun this dry run."
33189
+ );
33190
+ } else if (identityOwnerKey) {
33191
+ lines.push(
33192
+ "",
33193
+ `An existing monitor owns this upstream identity: ${identityOwnerKey}.`,
33194
+ `Inspect: deepline monitors get ${identityOwnerKey} --json`,
33195
+ "Do not deploy this key unless that conflict is resolved."
33196
+ );
33197
+ } else {
33198
+ lines.push(
33199
+ "",
33200
+ "An existing monitor owns this upstream identity.",
33201
+ "Do not deploy this key until that conflict is resolved."
33202
+ );
33203
+ }
33204
+ }
32992
33205
  lines.push(
32993
33206
  "",
32994
- valid ? "Deploy for real: re-run this command without --dry-run." : "Fix the definition, then re-run this command."
33207
+ 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."
32995
33208
  );
32996
33209
  return `${lines.join("\n")}
32997
33210
  `;
@@ -33243,11 +33456,12 @@ async function handleMonitorsDeploy(definition, options) {
33243
33456
  dryRun: true
33244
33457
  });
33245
33458
  const valid = payload2.valid !== false;
33459
+ const hasIdentityConflict = Boolean(asRecord2(payload2)?.identity_conflict);
33246
33460
  printCommandEnvelope(
33247
33461
  { dry_run: true, ...payload2 },
33248
33462
  { json: options.json, text: renderMonitorDeployPlan(payload2) }
33249
33463
  );
33250
- if (!valid) {
33464
+ if (!valid || hasIdentityConflict) {
33251
33465
  process.exitCode = 7;
33252
33466
  }
33253
33467
  return;
@@ -34278,11 +34492,13 @@ function monitorHealthLine(health) {
34278
34492
  if (health.refresh?.state === "running") {
34279
34493
  return `refreshing whole scope \xB7 scanned ${health.scanned} so far`;
34280
34494
  }
34495
+ const alignmentRequired = health.alignment_required ?? 0;
34281
34496
  return [
34282
34497
  `converged ${health.converged}/${health.scanned}`,
34283
34498
  `needs_repair ${health.needs_repair}`,
34284
34499
  `missing ${health.observed.missing}`,
34285
34500
  `unaudited ${health.observed.unknown + health.observed.unset}`,
34501
+ ...alignmentRequired > 0 ? [`needs_alignment ${alignmentRequired}`] : [],
34286
34502
  `silent ${health.silent}`
34287
34503
  ].join(" \xB7 ");
34288
34504
  }
@@ -34316,7 +34532,9 @@ async function watchMonitorHealth(input2) {
34316
34532
  let last = await input2.client.monitors.health(scope);
34317
34533
  input2.onProgress(last);
34318
34534
  while (Date.now() < deadlineAt) {
34319
- if (last.refresh?.state !== "running" && last.needs_repair === 0 && last.observed.unknown === 0) {
34535
+ const unresolved = last.observed.unknown + last.observed.unset;
34536
+ const alignmentRequired = last.alignment_required ?? 0;
34537
+ if (last.refresh?.state !== "running" && !last.truncated && last.needs_repair === 0 && (unresolved === 0 || alignmentRequired === unresolved)) {
34320
34538
  return last;
34321
34539
  }
34322
34540
  await new Promise(
@@ -34329,6 +34547,7 @@ async function watchMonitorHealth(input2) {
34329
34547
  }
34330
34548
  function monitorHealthText(health) {
34331
34549
  const partial = health.refresh?.state === "running" ? " (refreshing \u2014 counts below are not final)" : health.truncated ? " (partial \u2014 scope larger than one read)" : "";
34550
+ const unauditedMonitors = health.unaudited_monitors ?? [];
34332
34551
  const lines = [
34333
34552
  `scope: ${health.scope.fleet_id ?? "workspace"}${partial}`,
34334
34553
  monitorHealthLine(health)
@@ -34351,6 +34570,29 @@ function monitorHealthText(health) {
34351
34570
  lines.push(` ${entry.reason} (${entry.count})${how}`);
34352
34571
  }
34353
34572
  }
34573
+ if (unauditedMonitors.length > 0) {
34574
+ const reason = {
34575
+ not_yet_audited: "has not been observed yet",
34576
+ missing_provider_resource_id: "has no stored upstream resource id",
34577
+ provider_observation_unknown: "the provider observation is still unknown"
34578
+ };
34579
+ lines.push("");
34580
+ lines.push("unresolved monitor observations:");
34581
+ for (const entry of unauditedMonitors) {
34582
+ lines.push(
34583
+ ` ${entry.monitor_key} ${entry.tool} \u2014 ${reason[entry.reason]}`
34584
+ );
34585
+ }
34586
+ }
34587
+ if ((health.alignment_required ?? 0) > 0) {
34588
+ lines.push("");
34589
+ lines.push(
34590
+ `${health.alignment_required} monitor(s) need provider identity alignment; normal repair intentionally will not guess or create a paid replacement.`
34591
+ );
34592
+ lines.push(
34593
+ `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`
34594
+ );
34595
+ }
34354
34596
  if (health.worst_offenders.length > 0) {
34355
34597
  lines.push("");
34356
34598
  lines.push(
@@ -34575,9 +34817,8 @@ Exit codes:
34575
34817
 
34576
34818
  Examples:
34577
34819
  deepline monitors status --json
34578
- deepline monitors available --json # compact list by default
34579
- deepline monitors available --full --json # complete catalog
34580
- deepline monitors available deepline_native.company_radar --json
34820
+ deepline tools list --categories monitors --json
34821
+ deepline tools get deepline_native.company_radar --json
34581
34822
  deepline monitors check '{"key":"job-openings","tool":"deepline_native.company_radar","payload":{"domain":"stripe.com","radar_type":"company_job_openings"}}'
34582
34823
  deepline monitors deploy --dry-run --file monitor.json
34583
34824
  deepline monitors deploy --file monitor.json
@@ -34747,7 +34988,7 @@ Examples:
34747
34988
  )
34748
34989
  ).action(monitorsAction(handleMonitorsStatus));
34749
34990
  withJsonOption(
34750
- monitors.command("available [tool-id]").alias("tools").description(
34991
+ monitors.command("available [tool-id]", { hidden: true }).alias("tools").description(
34751
34992
  "List the monitor types you can deploy, or describe one by tool id."
34752
34993
  ).addHelpText(
34753
34994
  "after",
@@ -34864,7 +35105,7 @@ Notes:
34864
35105
  Play delivery. The JSON response reports this validation scope explicitly.
34865
35106
  Provider-specific grammar, precedence, enum applicability, examples, and
34866
35107
  update semantics are returned by the live monitor contract. Inspect it with
34867
- \`deepline monitors available deepline_native.company_radar --json\`.
35108
+ \`deepline tools get deepline_native.company_radar --json\`.
34868
35109
  For a bounded urgent Deepline Native preview, use
34869
35110
  controls.execution_type="priority". Deepline injects the upstream marker;
34870
35111
  do not author custom_fields yourself. Priority is capped at ten upstream or
@@ -34902,6 +35143,10 @@ Notes:
34902
35143
  no separate repair command or retry queue: rerun the same deploy/update.
34903
35144
  Scheduled reconciliation can also finish that exact saved cleanup; it never
34904
35145
  creates another monitor.
35146
+ For TamRadar, deliberately changing payload.updates_since is an explicit
35147
+ historical replay request, including when redeploying a disabled monitor.
35148
+ Deepline preserves that selected boundary; filter-only deploys and ordinary
35149
+ reactivation start from a fresh future-only source boundary instead.
34905
35150
  For a bounded urgent Deepline Native preview, set
34906
35151
  controls.execution_type="priority". Deepline injects the provider custom
34907
35152
  field and enforces a ten-slot per-org cap; do not use it for regular or bulk
@@ -34931,6 +35176,11 @@ positionally, via --file <path>, or from stdin with --file -.
34931
35176
  When <patch> includes payload, its top-level fields are merged with the stored
34932
35177
  payload before validation. This lets you change one filter without resending
34933
35178
  domain or radar_type; nested values and arrays replace atomically.
35179
+ For TamRadar, changing payload.updates_since is an explicit historical replay
35180
+ request. Deepline passes that requested boundary upstream, but previously
35181
+ delivered canonical findings are deduplicated before dispatch and billing; only
35182
+ previously unseen historical findings are chargeable. Filter-only updates,
35183
+ repair, and reactivation instead use a fresh future-only source boundary.
34934
35184
  Use {"controls":{"execution_type":"priority"}} only for a bounded urgent
34935
35185
  Deepline Native preview. The ten-radar priority cap applies on update too.
34936
35186
  Use {"controls":{"execution_type":null}} to release priority without
@@ -35017,7 +35267,7 @@ ${MONITOR_FLEET_HELP_EPILOG}`
35017
35267
  Creates a ready-to-review JSON definition. Fleets always sync ${MONITOR_FLEET_DOCUMENTATION.fixedPolicy.cadence} and retain
35018
35268
  a missing member for ${MONITOR_FLEET_DOCUMENTATION.fixedPolicy.removalGrace} before it is ${MONITOR_FLEET_DOCUMENTATION.fixedPolicy.onRemoved}d; those
35019
35269
  policies are not authored in the file. ${MONITOR_FLEET_DOCUMENTATION.stickyMembership} The payload remains the actual monitor payload for the chosen tool, so use
35020
- \`deepline monitors available\` to discover a tool first.
35270
+ \`deepline tools list --categories monitors\` to discover a tool first.
35021
35271
 
35022
35272
  Example:
35023
35273
  deepline monitors fleets init account-job-openings \\
@@ -36004,7 +36254,7 @@ Examples:
36004
36254
  )
36005
36255
  ).action(handleOrgSwitch);
36006
36256
  addOrgSetOptions(
36007
- org.command("switch [selection]").description(
36257
+ org.command("switch [selection]", { hidden: true }).description(
36008
36258
  "Deprecated alias for org set. Set the organization for the selected auth scope."
36009
36259
  ).addHelpText(
36010
36260
  "after",
@@ -36031,6 +36281,9 @@ Examples:
36031
36281
 
36032
36282
  // src/cli/commands/git.ts
36033
36283
  var GIT_DEPLOY_FEATURE = "github-deploy";
36284
+ function shellQuote3(value) {
36285
+ return `'${value.replace(/'/g, `'\\''`)}'`;
36286
+ }
36034
36287
  function renderProject(project) {
36035
36288
  const root = project.rootDirectory ? ` (${project.rootDirectory})` : "";
36036
36289
  const flags = [
@@ -36069,6 +36322,98 @@ async function handleList(options) {
36069
36322
  { json: options.json }
36070
36323
  );
36071
36324
  }
36325
+ function describeInstallationStatus(installation) {
36326
+ switch (installation.status) {
36327
+ case "active":
36328
+ return [
36329
+ `Connected to ${installation.accountLogin} (installation ${installation.installationId}).`
36330
+ ];
36331
+ case "uninstalled":
36332
+ return [
36333
+ `The Deepline GitHub App was uninstalled from ${installation.accountLogin}${installation.uninstalledAt ? ` at ${new Date(installation.uninstalledAt).toISOString()}` : ""}.`,
36334
+ "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."
36335
+ ];
36336
+ case "suspended":
36337
+ return [
36338
+ `GitHub suspended the Deepline App on ${installation.accountLogin}${installation.suspendedAt ? ` at ${new Date(installation.suspendedAt).toISOString()}` : ""}.`,
36339
+ "Pushes are not delivered while it is suspended; unsuspend it in GitHub settings."
36340
+ ];
36341
+ }
36342
+ }
36343
+ async function handleStatus2(options) {
36344
+ const { http } = getAuthedHttpClient();
36345
+ const payload = await http.get("/api/v2/github/installation");
36346
+ const installation = payload.installation;
36347
+ const others = (payload.installations ?? []).filter(
36348
+ (row) => row.installationId !== installation?.installationId
36349
+ );
36350
+ const lines = installation ? describeInstallationStatus(installation) : [
36351
+ "No GitHub installation is connected to this workspace. Run `deepline git connect`."
36352
+ ];
36353
+ for (const other of others) {
36354
+ lines.push(
36355
+ `Also: ${other.accountLogin} (installation ${other.installationId}) is ${other.status}.`
36356
+ );
36357
+ }
36358
+ const byId = new Map(
36359
+ (payload.installations ?? []).map((row) => [row.installationId, row])
36360
+ );
36361
+ const { projects } = await http.get(
36362
+ "/api/v2/play-projects?includeDisabled=1"
36363
+ );
36364
+ const affected_links = projects.map((project) => {
36365
+ const own = byId.get(project.installationId);
36366
+ const verdict = !own ? "unknown" : own.status === "active" ? null : own.status;
36367
+ return verdict ? {
36368
+ id: project.id,
36369
+ repoId: project.repoId,
36370
+ repoFullName: project.repoFullName,
36371
+ rootDirectory: project.rootDirectory,
36372
+ productionBranch: project.productionBranch,
36373
+ manifestPath: project.manifestPath,
36374
+ checkOnPullRequest: project.checkOnPullRequest,
36375
+ disabled: project.disabled,
36376
+ installationId: project.installationId,
36377
+ installationStatus: verdict
36378
+ } : null;
36379
+ }).filter((row) => row !== null);
36380
+ const activeInstallations = (payload.installations ?? []).filter(
36381
+ (row) => row.status === "active"
36382
+ );
36383
+ const relinkCommand = (link2) => [
36384
+ // The numeric repo id, not the name: a repository renamed while the
36385
+ // App was gone keeps a stale name here, and `git link` accepts the id.
36386
+ `deepline git link ${link2.repoId}`,
36387
+ // Stored values are admin-controlled text and this line is
36388
+ // copy-pasted into a shell by whoever reads it, so every
36389
+ // interpolated value below is quoted.
36390
+ `--branch ${shellQuote3(link2.productionBranch)}`,
36391
+ link2.rootDirectory ? `--root-dir ${shellQuote3(link2.rootDirectory)}` : "",
36392
+ link2.manifestPath && link2.manifestPath !== "deepline.json" ? `--manifest ${shellQuote3(link2.manifestPath)}` : "",
36393
+ link2.checkOnPullRequest ? "" : "--no-pr-checks",
36394
+ // With several active installations no id is guessed: the reader picks.
36395
+ activeInstallations.length > 1 ? "--installation <id>" : ""
36396
+ ].filter(Boolean).join(" ");
36397
+ for (const link2 of affected_links) {
36398
+ const label = `${link2.repoFullName}${link2.rootDirectory ? ` (${link2.rootDirectory})` : ""}`;
36399
+ lines.push(
36400
+ 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(", ")}` : ""}.` : (
36401
+ // A link disabled during the suspension stays disabled; only an
36402
+ // enabled one picks up again on its own when GitHub unsuspends.
36403
+ 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.`
36404
+ )
36405
+ );
36406
+ }
36407
+ printCommandEnvelope(
36408
+ {
36409
+ installation,
36410
+ installations: payload.installations ?? [],
36411
+ affected_links,
36412
+ render: { sections: [{ title: "github installation", lines }] }
36413
+ },
36414
+ { json: options.json }
36415
+ );
36416
+ }
36072
36417
  async function handleRepos(options) {
36073
36418
  const { http } = getAuthedHttpClient();
36074
36419
  const query = options.installation ? `?installationId=${encodeURIComponent(options.installation)}` : "";
@@ -36299,6 +36644,9 @@ Examples:
36299
36644
  `
36300
36645
  );
36301
36646
  git.command("connect").description("Connect a GitHub installation (browser step).").option("--json", "Emit JSON output").action(async (options) => handleConnect(options));
36647
+ git.command("status").description(
36648
+ "Show the workspace's GitHub installation and whether it is still usable."
36649
+ ).option("--json", "Emit JSON output").action(async (options) => handleStatus2(options));
36302
36650
  git.command("repos").description("List repos the workspace's GitHub installation can reach.").option(
36303
36651
  "--installation <id>",
36304
36652
  "GitHub installation id (required when several are connected)"
@@ -36409,7 +36757,7 @@ async function handleQuickstart(options) {
36409
36757
  return 0;
36410
36758
  }
36411
36759
  function registerQuickstartCommands(program) {
36412
- program.command("quickstart").description(
36760
+ program.command("quickstart", { hidden: true }).description(
36413
36761
  "Deprecated compatibility command. Use /deepline-gtm in your agent."
36414
36762
  ).addHelpText(
36415
36763
  "after",
@@ -36441,7 +36789,8 @@ function renderSecret(secret) {
36441
36789
  const added = new Date(secret.createdAt).toISOString();
36442
36790
  const updated = new Date(secret.updatedAt).toISOString();
36443
36791
  const lastUsed = secret.lastUsedAt ? `, last used ${new Date(secret.lastUsedAt).toISOString()}` : ", never used";
36444
- return `${secret.name} (${scope}) - ${secret.status}${secret.hasValue ? ", set" : ", empty"}, added ${added}${updated !== added ? `, updated ${updated}` : ""}${lastUsed}`;
36792
+ const note = secret.note ? `, note ${JSON.stringify(secret.note)}` : "";
36793
+ return `${secret.name} (${scope}) - ${secret.status}${secret.hasValue ? ", set" : ", empty"}${note}, added ${added}${updated !== added ? `, updated ${updated}` : ""}${lastUsed}`;
36445
36794
  }
36446
36795
  async function readHiddenLine(prompt, streams = {}) {
36447
36796
  const inputStream = streams.input ?? import_node_process.stdin;
@@ -36648,7 +36997,8 @@ async function handleSet2(nameInput, forbidden, options) {
36648
36997
  name,
36649
36998
  value,
36650
36999
  scope,
36651
- ...playName ? { playName } : {}
37000
+ ...playName ? { playName } : {},
37001
+ ...options.note !== void 0 ? { note: options.note } : {}
36652
37002
  }
36653
37003
  );
36654
37004
  const secret = response.secret;
@@ -36671,6 +37021,57 @@ async function handleSet2(nameInput, forbidden, options) {
36671
37021
  { json: options.json }
36672
37022
  );
36673
37023
  }
37024
+ async function handleNote(secretId, noteInput, options) {
37025
+ if (options.clear && noteInput !== void 0) {
37026
+ throw new Error("Pass either a note or --clear, not both.");
37027
+ }
37028
+ if (!options.clear && noteInput === void 0) {
37029
+ throw new Error("Provide a note or use --clear.");
37030
+ }
37031
+ const note = options.clear ? "" : noteInput;
37032
+ if (options.dryRun) {
37033
+ printCommandEnvelope(
37034
+ {
37035
+ ok: true,
37036
+ dryRun: true,
37037
+ secretId,
37038
+ note,
37039
+ render: {
37040
+ sections: [
37041
+ {
37042
+ title: "secret note",
37043
+ lines: [
37044
+ options.clear ? `Would clear the note on secret ${secretId}.` : `Would save a note on secret ${secretId}.`
37045
+ ]
37046
+ }
37047
+ ]
37048
+ }
37049
+ },
37050
+ { json: options.json }
37051
+ );
37052
+ return;
37053
+ }
37054
+ const client2 = new DeeplineClient();
37055
+ const secret = await client2.updateSecretNote(secretId, note);
37056
+ printCommandEnvelope(
37057
+ {
37058
+ ok: true,
37059
+ secret,
37060
+ render: {
37061
+ sections: [
37062
+ {
37063
+ title: "secret note saved",
37064
+ lines: [
37065
+ secret.note ? `${secret.name}: note saved.` : `${secret.name}: note cleared.`,
37066
+ renderSecret(secret)
37067
+ ]
37068
+ }
37069
+ ]
37070
+ }
37071
+ },
37072
+ { json: options.json }
37073
+ );
37074
+ }
36674
37075
  function registerSecretsCommands(program) {
36675
37076
  const secrets = program.command("secrets").description("Manage play secrets without revealing values.").addHelpText(
36676
37077
  "after",
@@ -36678,8 +37079,8 @@ function registerSecretsCommands(program) {
36678
37079
  Notes:
36679
37080
  Secret values are never accepted as command arguments. Use the hidden prompt,
36680
37081
  or one explicit non-argv source: --value-stdin, --from-env NAME, or
36681
- --from-file PATH. Values are never printed. secrets list shows only status,
36682
- added, updated, and last-used metadata.
37082
+ --from-file PATH. Values are never printed. secrets list shows only metadata,
37083
+ including any note you intentionally added.
36683
37084
 
36684
37085
  Examples:
36685
37086
  deepline secrets list
@@ -36689,6 +37090,9 @@ Examples:
36689
37090
  printf %s "$HUBSPOT_TOKEN" | deepline secrets set HUBSPOT_TOKEN --value-stdin
36690
37091
  deepline secrets set HUBSPOT_TOKEN --from-env HUBSPOT_TOKEN
36691
37092
  deepline secrets set HUBSPOT_TOKEN --from-file ./hubspot-token.txt
37093
+ deepline secrets set HUBSPOT_TOKEN --note "Chrome extension \u2014 Avery"
37094
+ deepline secrets note <secret-id> "Chrome extension \u2014 Avery"
37095
+ deepline secrets note <secret-id> --clear
36692
37096
  `
36693
37097
  );
36694
37098
  secrets.command("list").description("List secret metadata only.").option("--json", "Emit JSON output").action(async (options) => {
@@ -36702,11 +37106,19 @@ Examples:
36702
37106
  ).option("--json", "Emit JSON output").action(async (name, options) => {
36703
37107
  await handleCheck(name, options);
36704
37108
  });
36705
- 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(
37109
+ 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(
37110
+ "--note <note>",
37111
+ "Optional non-sensitive memo (maximum 500 characters)"
37112
+ ).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(
36706
37113
  async (name, forbidden, options) => {
36707
37114
  await handleSet2(name, forbidden ?? [], options);
36708
37115
  }
36709
37116
  );
37117
+ 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(
37118
+ async (secretId, note, options) => {
37119
+ await handleNote(secretId, note, options);
37120
+ }
37121
+ );
36710
37122
  }
36711
37123
 
36712
37124
  // src/cli/commands/setup.ts
@@ -36843,7 +37255,7 @@ var import_node_fs19 = require("fs");
36843
37255
  var import_node_os12 = require("os");
36844
37256
  var import_node_path21 = require("path");
36845
37257
 
36846
- // ../../shared_libs/cli/install-commands.json
37258
+ // contracts/install-commands.json
36847
37259
  var install_commands_default = {
36848
37260
  skills: {
36849
37261
  index_path: "/.well-known/skills/index.json",
@@ -36951,6 +37363,7 @@ function buildSkillsAddArgs(baseUrl, skillName, options = {}) {
36951
37363
 
36952
37364
  // src/cli/skills-sync.ts
36953
37365
  var import_node_child_process2 = require("child_process");
37366
+ var import_node_crypto10 = require("crypto");
36954
37367
  var import_node_fs18 = require("fs");
36955
37368
  var import_node_path20 = require("path");
36956
37369
 
@@ -37307,6 +37720,7 @@ async function maybeReportSdkCliFailure(input2) {
37307
37720
 
37308
37721
  // src/cli/skills-sync.ts
37309
37722
  var CHECK_TIMEOUT_MS2 = 3e3;
37723
+ var SKILLS_SYNC_CLAIM_MAX_AGE_MS = 60 * 60 * 1e3;
37310
37724
  function shouldSkipSkillsSync() {
37311
37725
  if (detectAgentRuntime() === "claude_cowork") {
37312
37726
  return true;
@@ -37323,6 +37737,60 @@ function failedSkillsSyncPath(baseUrl, agents) {
37323
37737
  `skills-sync-failed-${agents.join("-")}-version`
37324
37738
  );
37325
37739
  }
37740
+ function inProgressSkillsSyncPath(baseUrl, agents) {
37741
+ return (0, import_node_path20.join)(
37742
+ sdkCliStateDirPath(baseUrl),
37743
+ `skills-sync-in-progress-${agents.join("-")}`
37744
+ );
37745
+ }
37746
+ function removeSkillsSyncClaim(path, token) {
37747
+ try {
37748
+ (0, import_node_fs18.unlinkSync)((0, import_node_path20.join)(path, token));
37749
+ (0, import_node_fs18.rmdirSync)(path);
37750
+ } catch {
37751
+ }
37752
+ }
37753
+ function claimSkillsSync(baseUrl, agents) {
37754
+ const path = inProgressSkillsSyncPath(baseUrl, agents);
37755
+ try {
37756
+ (0, import_node_fs18.mkdirSync)((0, import_node_path20.dirname)(path), { recursive: true });
37757
+ } catch {
37758
+ return { status: "unavailable" };
37759
+ }
37760
+ const token = (0, import_node_crypto10.randomUUID)();
37761
+ for (let attempt = 0; attempt < 2; attempt += 1) {
37762
+ const pendingPath = `${path}-pending-${token}`;
37763
+ try {
37764
+ (0, import_node_fs18.mkdirSync)(pendingPath);
37765
+ (0, import_node_fs18.writeFileSync)((0, import_node_path20.join)(pendingPath, token), "", { flag: "wx" });
37766
+ (0, import_node_fs18.renameSync)(pendingPath, path);
37767
+ return { status: "claimed", token };
37768
+ } catch {
37769
+ removeSkillsSyncClaim(pendingPath, token);
37770
+ if (!(0, import_node_fs18.existsSync)(path)) continue;
37771
+ }
37772
+ if (attempt > 0) return { status: "held" };
37773
+ try {
37774
+ if (Date.now() - (0, import_node_fs18.statSync)(path).mtimeMs <= SKILLS_SYNC_CLAIM_MAX_AGE_MS) {
37775
+ return { status: "held" };
37776
+ }
37777
+ const owners = (0, import_node_fs18.readdirSync)(path);
37778
+ if (owners.length === 0) {
37779
+ (0, import_node_fs18.rmdirSync)(path);
37780
+ continue;
37781
+ }
37782
+ if (owners.length !== 1) return { status: "held" };
37783
+ (0, import_node_fs18.renameSync)(path, `${path}-stale-${owners[0]}`);
37784
+ } catch {
37785
+ return { status: "held" };
37786
+ }
37787
+ }
37788
+ return { status: "held" };
37789
+ }
37790
+ function clearSkillsSyncClaim(baseUrl, agents, token) {
37791
+ const path = inProgressSkillsSyncPath(baseUrl, agents);
37792
+ removeSkillsSyncClaim(path, token);
37793
+ }
37326
37794
  function hasMarkedSkillsSyncVersion(path, version) {
37327
37795
  return Boolean(version) && readMarkedSkillsSyncVersion(path) === version;
37328
37796
  }
@@ -37458,7 +37926,7 @@ function hasCommand(command) {
37458
37926
  });
37459
37927
  return result.status === 0;
37460
37928
  }
37461
- function shellQuote3(arg) {
37929
+ function shellQuote4(arg) {
37462
37930
  return `'${arg.replace(/'/g, `'\\''`)}'`;
37463
37931
  }
37464
37932
  function temporarySkillsSyncSkipCommand() {
@@ -37477,7 +37945,7 @@ function resolveSkillsInstallCommands(baseUrl, skillNames = DEFAULT_SDK_SKILL_NA
37477
37945
  commands.push({
37478
37946
  command: "bunx",
37479
37947
  args: bunxArgs,
37480
- manualCommand: `bunx ${bunxArgs.map(shellQuote3).join(" ")}`
37948
+ manualCommand: `bunx ${bunxArgs.map(shellQuote4).join(" ")}`
37481
37949
  });
37482
37950
  }
37483
37951
  if (hasCommand("npx")) {
@@ -37485,7 +37953,7 @@ function resolveSkillsInstallCommands(baseUrl, skillNames = DEFAULT_SDK_SKILL_NA
37485
37953
  commands.push({
37486
37954
  command: "npx",
37487
37955
  args: npxArgs,
37488
- manualCommand: `npx ${npxArgs.map(shellQuote3).join(" ")}`
37956
+ manualCommand: `npx ${npxArgs.map(shellQuote4).join(" ")}`
37489
37957
  });
37490
37958
  }
37491
37959
  return commands;
@@ -37652,30 +38120,43 @@ async function syncSdkSkillsIfNeeded(baseUrl, options = {}) {
37652
38120
  writeUnavailableSkillsNotice(baseUrl, update.remoteVersion, skillNames);
37653
38121
  return;
37654
38122
  }
37655
- writeSdkSkillsStatusLine("Deepline skills changed; syncing agent skills...");
37656
- const installResult = await runSkillsInstall(installs, agents);
37657
- if (!installResult.installed) {
37658
- const markerWritten = markFailedSkillsSync(
37659
- baseUrl,
37660
- update.remoteVersion,
37661
- agents
38123
+ const claim = claimSkillsSync(baseUrl, agents);
38124
+ if (claim.status === "held") return;
38125
+ try {
38126
+ if (hasFailedSkillsSync(baseUrl, update.remoteVersion, agents) || readSdkSkillsLocalVersion(baseUrl) === update.remoteVersion) {
38127
+ return;
38128
+ }
38129
+ writeSdkSkillsStatusLine(
38130
+ "Deepline skills changed; syncing agent skills..."
37662
38131
  );
37663
- void maybeReportAutomaticSkillsSyncFailure({
37664
- baseUrl,
37665
- remoteSkillsVersion: update.remoteVersion,
37666
- agents,
37667
- skillsPackage: SKILLS_NPX_PACKAGE,
37668
- targetSkillCount: skillNames.length,
37669
- markerWritten,
37670
- attempts: installResult.attempts
37671
- });
37672
- return;
38132
+ const installResult = await runSkillsInstall(installs, agents);
38133
+ if (!installResult.installed) {
38134
+ const markerWritten = markFailedSkillsSync(
38135
+ baseUrl,
38136
+ update.remoteVersion,
38137
+ agents
38138
+ );
38139
+ void maybeReportAutomaticSkillsSyncFailure({
38140
+ baseUrl,
38141
+ remoteSkillsVersion: update.remoteVersion,
38142
+ agents,
38143
+ skillsPackage: SKILLS_NPX_PACKAGE,
38144
+ targetSkillCount: skillNames.length,
38145
+ markerWritten,
38146
+ attempts: installResult.attempts
38147
+ });
38148
+ return;
38149
+ }
38150
+ runLegacySkillsCleanup(agents);
38151
+ writeSdkSkillsLocalVersion(baseUrl, update.remoteVersion, agents);
38152
+ clearUnavailableSkillsNotice(baseUrl);
38153
+ clearFailedSkillsSync(baseUrl, agents);
38154
+ writeSdkSkillsStatusLine("Deepline agent skills are up to date.");
38155
+ } finally {
38156
+ if (claim.status === "claimed") {
38157
+ clearSkillsSyncClaim(baseUrl, agents, claim.token);
38158
+ }
37673
38159
  }
37674
- runLegacySkillsCleanup(agents);
37675
- writeSdkSkillsLocalVersion(baseUrl, update.remoteVersion, agents);
37676
- clearUnavailableSkillsNotice(baseUrl);
37677
- clearFailedSkillsSync(baseUrl, agents);
37678
- writeSdkSkillsStatusLine("Deepline agent skills are up to date.");
37679
38160
  }
37680
38161
 
37681
38162
  // src/cli/commands/skills.ts
@@ -39299,14 +39780,14 @@ function posixShellQuote(value) {
39299
39780
  function windowsCmdQuote(value) {
39300
39781
  return `"${value.replace(/"/g, '""')}"`;
39301
39782
  }
39302
- function shellQuote4(value) {
39783
+ function shellQuote5(value) {
39303
39784
  if (process.platform === "win32") {
39304
39785
  return /^[A-Za-z0-9_./:@%+=,-]+$/.test(value) ? value : windowsCmdQuote(value);
39305
39786
  }
39306
39787
  return posixShellQuote(value);
39307
39788
  }
39308
39789
  function buildSourceUpdateCommand(sourceRoot) {
39309
- const quotedRoot = shellQuote4(sourceRoot);
39790
+ const quotedRoot = shellQuote5(sourceRoot);
39310
39791
  const cdCommand = process.platform === "win32" ? `cd /d ${quotedRoot}` : `cd ${quotedRoot}`;
39311
39792
  return `${cdCommand} && git fetch origin main --tags && git merge --ff-only origin/main`;
39312
39793
  }
@@ -39318,7 +39799,7 @@ function buildSidecarProjectConfigCommand(versionDir, nodeBin) {
39318
39799
  "fs.mkdirSync(dir,{recursive:true});",
39319
39800
  `fs.writeFileSync(path.join(dir,'package.json'),${JSON.stringify(NPM_SDK_SIDECAR_PACKAGE_JSON)});`
39320
39801
  ].join("");
39321
- return `${shellQuote4(nodeBin)} -e ${shellQuote4(script)} ${shellQuote4(versionDir)}`;
39802
+ return `${shellQuote5(nodeBin)} -e ${shellQuote5(script)} ${shellQuote5(versionDir)}`;
39322
39803
  }
39323
39804
  function sidecarStateDir(input2) {
39324
39805
  const scope = input2.env.DEEPLINE_CONFIG_SCOPE?.trim();
@@ -39381,7 +39862,7 @@ function resolvePythonSidecarUpdatePlan(options) {
39381
39862
  const npmCommand = "npm";
39382
39863
  const registryUrl = sidecarRegistryUrl(hostUrl);
39383
39864
  const versionDir = (0, import_node_path25.join)(stateDir, "versions", "<version>");
39384
- const manualCommand = `${buildSidecarProjectConfigCommand(versionDir, nodeBin)} && ${npmCommand} install --prefix ${shellQuote4(versionDir)} --registry ${shellQuote4(registryUrl)} ${NPM_SDK_INSTALL_COMMON_FLAGS.map(shellQuote4).join(" ")} ${shellQuote4(packageSpec)}`;
39865
+ const manualCommand = `${buildSidecarProjectConfigCommand(versionDir, nodeBin)} && ${npmCommand} install --prefix ${shellQuote5(versionDir)} --registry ${shellQuote5(registryUrl)} ${NPM_SDK_INSTALL_COMMON_FLAGS.map(shellQuote5).join(" ")} ${shellQuote5(packageSpec)}`;
39385
39866
  return {
39386
39867
  kind: "python-sidecar",
39387
39868
  stateDir,
@@ -39528,7 +40009,7 @@ function resolveUpdatePlan(options = {}) {
39528
40009
  args,
39529
40010
  ...installPrefix ? { installPrefix } : {},
39530
40011
  ...fallbackRegistryUrl ? { fallbackRegistryUrl } : {},
39531
- manualCommand: `${command} ${args.map(shellQuote4).join(" ")}`
40012
+ manualCommand: `${command} ${args.map(shellQuote5).join(" ")}`
39532
40013
  };
39533
40014
  }
39534
40015
  var AUTO_UPDATE_FAILURE_FILE = ".auto-update-failure.json";
@@ -39796,23 +40277,23 @@ function writeSidecarLauncher(input2) {
39796
40277
  input2.path,
39797
40278
  [
39798
40279
  "#!/usr/bin/env sh",
39799
- `export DEEPLINE_HOST_URL=${shellQuote4(input2.hostUrl)}`,
39800
- `export DEEPLINE_CONFIG_SCOPE=${shellQuote4(input2.scope)}`,
39801
- `if ${criticalPaths.map((path) => `[ ! -f ${shellQuote4(path)} ]`).join(" || ")}; then`,
40280
+ `export DEEPLINE_HOST_URL=${shellQuote5(input2.hostUrl)}`,
40281
+ `export DEEPLINE_CONFIG_SCOPE=${shellQuote5(input2.scope)}`,
40282
+ `if ${criticalPaths.map((path) => `[ ! -f ${shellQuote5(path)} ]`).join(" || ")}; then`,
39802
40283
  ' if [ -n "${DEEPLINE_REAL_BINARY:-}" ] && [ -x "$DEEPLINE_REAL_BINARY" ]; then',
39803
40284
  ' exec "$DEEPLINE_REAL_BINARY" --version=v2 "$@"',
39804
40285
  " fi",
39805
40286
  ' printf "%s\\n" "Deepline SDK CLI install is incomplete. Run \\`deepline update\\` to repair it." >&2',
39806
40287
  " exit 1",
39807
40288
  "fi",
39808
- `if ! ${shellQuote4(input2.nodeBin)} -e ${shellQuote4(esbuildProbe)} ${shellQuote4(versionDir)} >/dev/null 2>&1; then`,
40289
+ `if ! ${shellQuote5(input2.nodeBin)} -e ${shellQuote5(esbuildProbe)} ${shellQuote5(versionDir)} >/dev/null 2>&1; then`,
39809
40290
  ' if [ -n "${DEEPLINE_REAL_BINARY:-}" ] && [ -x "$DEEPLINE_REAL_BINARY" ]; then',
39810
40291
  ' exec "$DEEPLINE_REAL_BINARY" --version=v2 "$@"',
39811
40292
  " fi",
39812
40293
  ' printf "%s\\n" "Deepline SDK CLI install is incomplete. Run \\`deepline update\\` to repair it." >&2',
39813
40294
  " exit 1",
39814
40295
  "fi",
39815
- `exec ${shellQuote4(input2.nodeBin)} ${shellQuote4(input2.entryPath)} "$@"`,
40296
+ `exec ${shellQuote5(input2.nodeBin)} ${shellQuote5(input2.entryPath)} "$@"`,
39816
40297
  ""
39817
40298
  ].join("\n"),
39818
40299
  { encoding: "utf8", mode: 493 }
@@ -43070,9 +43551,9 @@ function apifySyncRecoveryNext(rawResponse) {
43070
43551
  const getDatasetItemsTool = stringField2(getDatasetItems, "tool");
43071
43552
  const getDatasetItemsPayload = recordField2(getDatasetItems, "payload");
43072
43553
  return {
43073
- getActorRun: `deepline tools execute ${getActorRunTool} --input ${shellQuote5(JSON.stringify(getActorRunPayload))} --json`,
43554
+ getActorRun: `deepline tools execute ${getActorRunTool} --input ${shellQuote6(JSON.stringify(getActorRunPayload))} --json`,
43074
43555
  ...getDatasetItemsTool && Object.keys(getDatasetItemsPayload).length > 0 ? {
43075
- getDatasetItems: `deepline tools execute ${getDatasetItemsTool} --input ${shellQuote5(JSON.stringify(getDatasetItemsPayload))} --json`
43556
+ getDatasetItems: `deepline tools execute ${getDatasetItemsTool} --input ${shellQuote6(JSON.stringify(getDatasetItemsPayload))} --json`
43076
43557
  } : {}
43077
43558
  };
43078
43559
  }
@@ -43245,7 +43726,7 @@ function parseExecuteOptions(args) {
43245
43726
  function safeFileStem(value) {
43246
43727
  return value.trim().replace(/[^a-zA-Z0-9_-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64) || "tool";
43247
43728
  }
43248
- function shellQuote5(value) {
43729
+ function shellQuote6(value) {
43249
43730
  return `'${value.replace(/'/g, `'\\''`)}'`;
43250
43731
  }
43251
43732
  function powerShellQuote(value) {
@@ -43315,7 +43796,7 @@ export default definePlay(${JSON.stringify(playName)}, async (ctx) => {
43315
43796
  path: scriptPath,
43316
43797
  sourceCode: script,
43317
43798
  projectDir,
43318
- macCopyCommand: `mkdir -p ${shellQuote5(projectDir)} && cp ${shellQuote5(scriptPath)} ${shellQuote5(`${projectDir}/${fileName}`)}`,
43799
+ macCopyCommand: `mkdir -p ${shellQuote6(projectDir)} && cp ${shellQuote6(scriptPath)} ${shellQuote6(`${projectDir}/${fileName}`)}`,
43319
43800
  windowsCopyCommand: `New-Item -ItemType Directory -Force -Path ${powerShellQuote(projectDir.replace(/\//g, "\\"))} | Out-Null; Copy-Item -LiteralPath ${powerShellQuote(scriptPath)} -Destination ${powerShellQuote(`${projectDir.replace(/\//g, "\\")}\\${fileName}`)}`
43320
43801
  };
43321
43802
  }
@@ -43342,7 +43823,7 @@ function buildToolExecuteBaseEnvelope(input2) {
43342
43823
  envelope,
43343
43824
  "output"
43344
43825
  );
43345
- const inspectCommand = `deepline tools execute ${input2.toolId} --input ${shellQuote5(JSON.stringify(input2.params))} --json`;
43826
+ const inspectCommand = `deepline tools execute ${input2.toolId} --input ${shellQuote6(JSON.stringify(input2.params))} --json`;
43346
43827
  const actions = input2.listConversion ? [
43347
43828
  {
43348
43829
  label: "next",
@@ -43738,7 +44219,7 @@ var import_promises10 = require("fs/promises");
43738
44219
  var import_node_path28 = require("path");
43739
44220
 
43740
44221
  // src/cli/workflow-to-play.ts
43741
- var import_node_crypto10 = require("crypto");
44222
+ var import_node_crypto11 = require("crypto");
43742
44223
  var HITL_WAIT_FOR_SIGNAL_TOOL = "deepline_workflow_wait_for_signal";
43743
44224
  var HITL_SLACK_TOOL = "slack_message_with_hitl";
43744
44225
  var SUB_WORKFLOW_TOOL_PREFIX = "deepline_workflow_";
@@ -43844,7 +44325,7 @@ function sanitizePlayNameSegment(value) {
43844
44325
  }
43845
44326
  function deriveWorkflowPlayName(workflowName) {
43846
44327
  const base = sanitizePlayNameSegment(workflowName) || "workflow";
43847
- const suffix = (0, import_node_crypto10.createHash)("sha256").update(workflowName).digest("hex").slice(0, 8);
44328
+ const suffix = (0, import_node_crypto11.createHash)("sha256").update(workflowName).digest("hex").slice(0, 8);
43848
44329
  const reserved = suffix.length + 1;
43849
44330
  const allowedBase = Math.max(1, MAX_PLAY_NAME_LENGTH - reserved);
43850
44331
  let name = `${base.slice(0, allowedBase)}_${suffix}`;
@@ -44162,7 +44643,7 @@ async function handleTail(id, runId, options) {
44162
44643
  }
44163
44644
  }
44164
44645
  function registerWorkflowCommands(program) {
44165
- const workflows = program.command("workflows").description(
44646
+ const workflows = program.command("workflows", { hidden: true }).description(
44166
44647
  "Legacy cloud workflows (now becoming plays). Commands still work; use `workflows transform` to migrate one to a play. " + TRIGGER_REDIRECT
44167
44648
  ).addHelpText(
44168
44649
  "after",
@@ -44982,4 +45463,11 @@ Examples:
44982
45463
  }
44983
45464
  process.exitCode = process.exitCode ?? 0;
44984
45465
  }
44985
- main();
45466
+ var DEV_CLI_AWAIT_MAIN = Symbol.for("@deepline/sdk/dev-cli-await-main");
45467
+ if (globalThis[DEV_CLI_AWAIT_MAIN] !== true) {
45468
+ void main();
45469
+ }
45470
+ // Annotate the CommonJS export names for ESM import in node:
45471
+ 0 && (module.exports = {
45472
+ main
45473
+ });