deepline 0.3.461 → 0.3.463
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.
- package/dist/bundling-sources/sdk/src/client-core.ts +7593 -0
- package/dist/bundling-sources/sdk/src/client.ts +8 -7366
- package/dist/bundling-sources/sdk/src/http-core.ts +1239 -0
- package/dist/bundling-sources/sdk/src/http.ts +6 -1231
- package/dist/bundling-sources/sdk/src/index.ts +4 -1
- package/dist/bundling-sources/sdk/src/play.ts +5 -5
- package/dist/bundling-sources/sdk/src/plays/client-core.ts +437 -0
- package/dist/bundling-sources/sdk/src/plays/client.ts +4 -421
- package/dist/bundling-sources/sdk/src/plays/input-example.ts +3 -4
- package/dist/bundling-sources/sdk/src/plays/play-description.ts +1 -1
- package/dist/bundling-sources/sdk/src/plays/run-request.ts +1 -1
- package/dist/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/sdk/src/server.ts +43 -0
- package/dist/bundling-sources/sdk/src/types.ts +15 -5
- package/dist/bundling-sources/shared_libs/integration-contracts/billing-entitlements.ts +15 -0
- package/dist/bundling-sources/shared_libs/monitors/billing/tamradar.ts +17 -17
- package/dist/bundling-sources/shared_libs/monitors/callback-security.ts +0 -307
- package/dist/bundling-sources/shared_libs/monitors/http-error-response.ts +3 -0
- package/dist/bundling-sources/shared_libs/monitors/lifecycle-notifications.ts +3 -2
- package/dist/bundling-sources/shared_libs/monitors/package.json +2 -0
- package/dist/bundling-sources/shared_libs/monitors/provider-callback-verification.ts +34 -0
- package/dist/bundling-sources/shared_libs/monitors/provider-monitor-batch-operation.ts +61 -0
- package/dist/bundling-sources/shared_libs/monitors/provider-monitor-upstream-identity.ts +122 -2
- package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-dead-letter.ts +11 -1
- package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-failure-codes.ts +24 -0
- package/dist/bundling-sources/shared_libs/observability/dlq.ts +32 -0
- package/dist/bundling-sources/shared_libs/observability/scheduled-jobs.json +57 -3
- package/dist/bundling-sources/shared_libs/observability/scheduled-work.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-data-plane/r2.ts +66 -1
- package/dist/bundling-sources/shared_libs/play-data-plane/sheet-column-storage.ts +36 -7
- package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +250 -11
- package/dist/bundling-sources/shared_libs/play-runtime/array-input-store.ts +319 -0
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +991 -359
- package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +17 -0
- package/dist/bundling-sources/shared_libs/play-runtime/daytona-sandbox-janitor.ts +13 -0
- package/dist/bundling-sources/shared_libs/play-runtime/daytona-sandbox-reaper.ts +110 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-machines.ts +155 -6
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-registry.ts +110 -6
- package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +127 -13
- package/dist/bundling-sources/shared_libs/play-runtime/execution-capabilities.ts +14 -1
- package/dist/bundling-sources/shared_libs/play-runtime/fixture-behavior.ts +57 -1
- package/dist/bundling-sources/shared_libs/play-runtime/free-company-lookup-batching.ts +218 -0
- package/dist/bundling-sources/shared_libs/play-runtime/gateway-postgres-admission.ts +42 -5
- package/dist/bundling-sources/shared_libs/play-runtime/governor/app-runtime-budget-state-backend.ts +6 -1
- package/dist/bundling-sources/shared_libs/play-runtime/governor/app-runtime-rate-state-backend.ts +92 -31
- package/dist/bundling-sources/shared_libs/play-runtime/governor/block-reserving-budget-state-backend.ts +69 -14
- package/dist/bundling-sources/shared_libs/play-runtime/governor/governor.ts +93 -23
- package/dist/bundling-sources/shared_libs/play-runtime/governor/in-memory-rate-state-backend.ts +15 -4
- package/dist/bundling-sources/shared_libs/play-runtime/governor/policy.ts +22 -18
- package/dist/bundling-sources/shared_libs/play-runtime/governor/rate-state-backend.ts +5 -0
- package/dist/bundling-sources/shared_libs/play-runtime/launch-identity.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/map-memory-limits.ts +190 -14
- package/dist/bundling-sources/shared_libs/play-runtime/memory-ledger.ts +131 -0
- package/dist/bundling-sources/shared_libs/play-runtime/modal-runtime-config.ts +77 -2
- package/dist/bundling-sources/shared_libs/play-runtime/output-size-limits.ts +271 -2
- package/dist/bundling-sources/shared_libs/play-runtime/play-run-recovery-policy.ts +51 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/contracts.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/job.ts +27 -1
- package/dist/bundling-sources/shared_libs/play-runtime/play-runtime-batching-registry.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +3 -0
- package/dist/bundling-sources/shared_libs/play-runtime/provider-text-for-log.ts +63 -0
- package/dist/bundling-sources/shared_libs/play-runtime/resource-governor.ts +19 -0
- package/dist/bundling-sources/shared_libs/play-runtime/run-ledger-event-transport.ts +112 -16
- package/dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts +104 -2
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +265 -151
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-gateway-transport.ts +17 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-progress-push.ts +35 -14
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-sheet-persistence-retry.ts +12 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-control-transport.ts +4 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-labels.ts +36 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-launch-transport.ts +136 -70
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-lifecycle.ts +237 -36
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-runtime-watchdog.ts +148 -4
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-session-execution.ts +6 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +285 -32
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/modal.ts +251 -56
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/runtime-sandbox-reconciliation.ts +29 -4
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/sandbox-create-outcome.ts +27 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/types.ts +22 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +1397 -382
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-array-input-receipts.ts +920 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-constants.ts +16 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-environment.ts +38 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-flow.ts +6 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-incident-drills.ts +26 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-operation-contract.ts +30 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-receipt-store-adapter.ts +14 -3
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-receipt-writer.ts +31 -4
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-sheet-row-transition.ts +47 -0
- package/dist/bundling-sources/shared_libs/play-runtime/sandbox-compute-usage.ts +20 -7
- package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/contract.ts +12 -0
- package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/index.ts +9 -0
- package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/runner-backend-adapter.ts +10 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backend.ts +4 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +1496 -320
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-worker-required-env.ts +31 -1
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +1389 -129
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/receipt-gateway.ts +36 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-dispatch-authority.ts +4 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-outbox-recovery.ts +162 -23
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-event-search.ts +499 -115
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-capacity.ts +377 -9
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-ledger-reconciliation.ts +117 -8
- package/dist/bundling-sources/shared_libs/play-runtime/secret-resolution-retry-policy.ts +25 -0
- package/dist/bundling-sources/shared_libs/play-runtime/terminal-runtime-performance.ts +391 -0
- package/dist/bundling-sources/shared_libs/play-runtime/test-runtime-seams.ts +40 -0
- package/dist/bundling-sources/shared_libs/play-runtime/tool-call/index.ts +6 -0
- package/dist/bundling-sources/shared_libs/play-runtime/tool-call/mapped-calls.ts +171 -0
- package/dist/bundling-sources/shared_libs/play-runtime/tool-call/receipt-cohort.ts +16 -1
- package/dist/bundling-sources/shared_libs/play-runtime/tool-execute-retry-policy.ts +38 -12
- package/dist/bundling-sources/shared_libs/play-runtime/tool-result.ts +33 -9
- package/dist/bundling-sources/shared_libs/play-runtime/transport-error-diagnostics.ts +28 -0
- package/dist/bundling-sources/shared_libs/play-runtime/work-receipt-storage-contract.ts +55 -5
- package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +41 -1
- package/dist/bundling-sources/shared_libs/plays/contracts.ts +4 -0
- package/dist/bundling-sources/shared_libs/plays/dataset.ts +9 -3
- package/dist/bundling-sources/shared_libs/plays/deploy/manifest-contract.ts +2 -0
- package/dist/bundling-sources/shared_libs/plays/deploy/manifest.ts +3 -2
- package/dist/bundling-sources/shared_libs/plays/deploy/project-serializer.ts +2 -2
- package/dist/bundling-sources/shared_libs/plays/run-output-summary.ts +66 -0
- package/dist/bundling-sources/shared_libs/plays/script-entry.ts +1 -1
- package/dist/bundling-sources/shared_libs/product-notifications/catalog.ts +43 -1
- package/dist/bundling-sources/shared_libs/product-notifications/content.ts +9 -0
- package/dist/bundling-sources/shared_libs/product-notifications/email.ts +91 -13
- package/dist/bundling-sources/shared_libs/product-notifications/events.ts +3 -0
- package/dist/bundling-sources/shared_libs/product-notifications/slack-delivery.ts +41 -24
- package/dist/bundling-sources/shared_libs/security/attested-client-ip.ts +91 -0
- package/dist/bundling-sources/shared_libs/security/internal-actor.ts +0 -11
- package/dist/cli/{auth-6HJXNWUG.mjs → auth-LZLBR4C3.mjs} +5 -4
- package/dist/cli/auth-XPGKBJKB.js +41 -0
- package/dist/cli/{billing-6P5HO6QG.js → billing-6TJPNJQD.js} +152 -78
- package/dist/cli/{billing-MJ42N7YF.mjs → billing-OTOP5RE4.mjs} +84 -10
- package/dist/cli/{chunk-FCAZQ7WV.js → chunk-2NISBXMN.js} +52 -50
- package/dist/cli/{chunk-PNATXKLP.js → chunk-2ZIRCBYG.js} +6 -6
- package/dist/cli/{chunk-5FDKJQZE.js → chunk-3BOIOCNX.js} +1 -1
- package/dist/cli/chunk-3BVLLJ3H.mjs +1038 -0
- package/dist/cli/{chunk-FJZILBL7.mjs → chunk-3U5EAP6E.mjs} +5 -5
- package/dist/cli/{describe-FRAVCY5F.mjs → chunk-4YZKBBLZ.mjs} +19 -36
- package/dist/cli/{chunk-QWRHGGUH.js → chunk-5DRNNC72.js} +20 -2
- package/dist/cli/{chunk-Z2GUFYT6.js → chunk-5LEAXRHV.js} +11 -11
- package/dist/cli/{chunk-5MDIZX7M.js → chunk-5LHXOIPT.js} +8 -6
- package/dist/cli/{chunk-NMJ4D2WO.js → chunk-6PMCRYDA.js} +216 -91
- package/dist/cli/{chunk-EBU7LQ64.js → chunk-6V7KVRR5.js} +3 -3
- package/dist/cli/{chunk-MGXEUZHL.mjs → chunk-7D6X7IXW.mjs} +7 -5
- package/dist/cli/{chunk-SAZFZQRI.js → chunk-7FCYPAPP.js} +2 -2
- package/dist/cli/{chunk-ACCR7POB.js → chunk-7XYDDCQ2.js} +27 -27
- package/dist/cli/{chunk-5IYOUBFZ.js → chunk-ALZBANZI.js} +28 -54
- package/dist/cli/{chunk-3DNKFH2G.mjs → chunk-BAPTQDLF.mjs} +19 -1
- package/dist/cli/chunk-BGNWI3KH.js +827 -0
- package/dist/cli/{chunk-V7REJRDZ.mjs → chunk-C25QE4CH.mjs} +1 -1
- package/dist/cli/{chunk-FGMX4HUZ.js → chunk-CBZP6J3V.js} +29 -27
- package/dist/cli/{chunk-QEYHTIV4.mjs → chunk-CTQ56DXP.mjs} +10 -1
- package/dist/cli/{chunk-IHHLTHE7.mjs → chunk-CVQ7N5CV.mjs} +267 -38
- package/dist/cli/{chunk-7DH2FD7Y.mjs → chunk-D464JW3N.mjs} +5 -85
- package/dist/cli/{chunk-MEAIOXJL.mjs → chunk-DHXCBITQ.mjs} +7 -5
- package/dist/cli/chunk-F2RHUPVH.mjs +827 -0
- package/dist/cli/chunk-F6QV42MC.mjs +91 -0
- package/dist/cli/{chunk-OZBWRICM.js → chunk-FK2HNDCN.js} +2 -2
- package/dist/cli/{chunk-BGY2PLP7.mjs → chunk-GUT7CLOL.mjs} +23 -49
- package/dist/cli/{chunk-RY4IVOU3.mjs → chunk-I624J4H5.mjs} +16 -806
- package/dist/cli/{chunk-Z2XUZC34.js → chunk-IAYSWZDJ.js} +188 -76
- package/dist/cli/{chunk-FGLKOWSC.mjs → chunk-IKWRUNAP.mjs} +1 -1
- package/dist/cli/{chunk-KCCOQ5G5.js → chunk-JVDKZJUH.js} +511 -282
- package/dist/cli/{chunk-HDFRJ4IT.mjs → chunk-JVHOS3K3.mjs} +177 -65
- package/dist/cli/chunk-LYFKBLJI.mjs +1039 -0
- package/dist/cli/{chunk-SLEUWLJE.mjs → chunk-MSY22NQW.mjs} +5 -5
- package/dist/cli/{chunk-5FY72YOV.js → chunk-NAPTMYTY.js} +8 -8
- package/dist/cli/{chunk-O6QOMHCH.js → chunk-NDHJR2WZ.js} +37 -35
- package/dist/cli/{chunk-KXMNM4AQ.js → chunk-NMU3VR5U.js} +4 -5
- package/dist/cli/chunk-NTLI6P6Y.mjs +19 -0
- package/dist/cli/{chunk-RFONC4WJ.mjs → chunk-O3BJYD6D.mjs} +3 -3
- package/dist/cli/{describe-2WQY7ZCY.js → chunk-PVY4DPPF.js} +27 -44
- package/dist/cli/{chunk-WIYWSYDS.mjs → chunk-Q2EIZKVX.mjs} +3 -3
- package/dist/cli/{chunk-VZBCEA5S.mjs → chunk-RD6IQ2JY.mjs} +223 -92
- package/dist/cli/chunk-RGOUCIIZ.js +1039 -0
- package/dist/cli/{chunk-EIMG75BT.mjs → chunk-S3A4IXBQ.mjs} +4 -5
- package/dist/cli/{chunk-QIW7TVV6.mjs → chunk-S4XQCFES.mjs} +14 -12
- package/dist/cli/chunk-SKU6ECIY.js +19 -0
- package/dist/cli/{chunk-CRYOUPEB.js → chunk-TIRBDQ3W.js} +16 -16
- package/dist/cli/{chunk-G7L27KZB.mjs → chunk-TKAQR3IB.mjs} +31 -21
- package/dist/cli/{chunk-MDJPEGVN.js → chunk-UC4SFYNU.js} +392 -261
- package/dist/cli/{chunk-3BMLICF7.mjs → chunk-UIURR26V.mjs} +13 -8
- package/dist/cli/{chunk-TNMBPMMC.js → chunk-UROQDCVW.js} +13 -4
- package/dist/cli/{chunk-R64BGGRQ.mjs → chunk-VDGTTH7K.mjs} +2 -2
- package/dist/cli/chunk-VLEVVDWG.js +91 -0
- package/dist/cli/{chunk-R2GLGLDR.mjs → chunk-VPHN2HAL.mjs} +216 -91
- package/dist/cli/chunk-VY2GBNTX.js +1038 -0
- package/dist/cli/{chunk-CFUTOWE4.js → chunk-WG3KGAII.js} +8 -88
- package/dist/cli/{chunk-QAJAJPKK.mjs → chunk-WUMIYOXQ.mjs} +4 -2
- package/dist/cli/{chunk-SCIR5JXW.js → chunk-WUZS2HK6.js} +56 -51
- package/dist/cli/{chunk-T3MVIPHG.mjs → chunk-XDWS2JJT.mjs} +1 -1
- package/dist/cli/{chunk-KGQNIA37.js → chunk-XQCTG5OO.js} +44 -34
- package/dist/cli/{chunk-KVJ5VHW5.mjs → chunk-XW2JIYG7.mjs} +2 -2
- package/dist/cli/chunk-YGGIZ3VT.js +920 -0
- package/dist/cli/command-docs.d.mts +5 -0
- package/dist/cli/command-docs.d.ts +5 -0
- package/dist/cli/command-docs.js +2 -2
- package/dist/cli/command-docs.mjs +1 -1
- package/dist/cli/{csv-NX7NO3O6.js → csv-EH5QWR4O.js} +13 -12
- package/dist/cli/{csv-DQ6GW5B5.mjs → csv-OK45Z5XQ.mjs} +4 -3
- package/dist/cli/{db-R72DFMP6.js → db-3ESJKETS.js} +30 -27
- package/dist/cli/{db-2YP33M4K.mjs → db-6Z5E4HKN.mjs} +10 -7
- package/dist/cli/describe-PNDQB7YS.mjs +48 -0
- package/dist/cli/describe-QUF7VTTR.js +48 -0
- package/dist/cli/describe-core.d.mts +153 -5
- package/dist/cli/describe-core.d.ts +153 -5
- package/dist/cli/describe-core.js +9 -5
- package/dist/cli/describe-core.mjs +10 -6
- package/dist/cli/{executions-WFBU7L2Q.mjs → executions-2NTWQFEG.mjs} +7 -5
- package/dist/cli/{executions-ZLHD4QIT.js → executions-KUOBRX5V.js} +9 -7
- package/dist/cli/{feedback-CN3HJFVF.mjs → feedback-7RPRMSGY.mjs} +6 -5
- package/dist/cli/{feedback-NDV6TPHG.js → feedback-UPHAZJ4C.js} +10 -9
- package/dist/cli/getting-started.d.mts +6 -6
- package/dist/cli/getting-started.d.ts +6 -6
- package/dist/cli/getting-started.js +2 -2
- package/dist/cli/getting-started.mjs +1 -1
- package/dist/cli/{git-QAD6E3HW.mjs → git-SCYP6WSZ.mjs} +5 -4
- package/dist/cli/git-UH653WHV.js +25 -0
- package/dist/cli/index.js +152 -142
- package/dist/cli/index.mjs +56 -46
- package/dist/cli/{legacy-noops-KVC5QJ74.js → legacy-noops-7XMFCVRG.js} +8 -7
- package/dist/cli/{legacy-noops-TPTKNBI2.mjs → legacy-noops-A4KYAGI6.mjs} +5 -4
- package/dist/cli/{monitors-SV57JFLO.mjs → monitors-FLC5J7RI.mjs} +19 -6
- package/dist/cli/{monitors-KCROV6PJ.js → monitors-NZV6IX5H.js} +103 -90
- package/dist/cli/{org-NJYX5743.js → org-IZ7UP3XF.js} +70 -67
- package/dist/cli/{org-KX6QIR7A.mjs → org-LUETJ7Z5.mjs} +9 -6
- package/dist/cli/pages-22ML3O7O.js +252 -0
- package/dist/cli/pages-EUX5EAGF.mjs +252 -0
- package/dist/cli/{play-IQQ57L7Z.mjs → play-CDHPAKKM.mjs} +512 -1508
- package/dist/cli/{play-32L7EQN4.js → play-USJBQADG.js} +1090 -2086
- package/dist/cli/{providers-4WEC2EQN.mjs → providers-CCXZ3SQF.mjs} +7 -5
- package/dist/cli/{providers-ZQV6QLVQ.js → providers-WFEUNPGC.js} +10 -8
- package/dist/cli/{quickstart-HKUSFADF.js → quickstart-O4JSUORZ.js} +13 -12
- package/dist/cli/{quickstart-RQ76RIUE.mjs → quickstart-ZUULI635.mjs} +5 -4
- package/dist/cli/run-ISDJYJMU.js +443 -0
- package/dist/cli/run-QJ4NX5F5.mjs +443 -0
- package/dist/cli/{search-ZRAVFBZC.mjs → search-IX3XKZJ3.mjs} +8 -6
- package/dist/cli/search-TIFNLRPM.js +32 -0
- package/dist/cli/{secrets-CMJOVNVH.mjs → secrets-7VUDXTUZ.mjs} +7 -5
- package/dist/cli/{secrets-J3G5Y43U.js → secrets-ELQSNCTR.js} +16 -14
- package/dist/cli/{sessions-WY7VN4AE.js → sessions-A3FG3AZX.js} +6 -5
- package/dist/cli/{sessions-MDQYY5CB.mjs → sessions-VOIQ62GB.mjs} +5 -4
- package/dist/cli/{settings-4RWZPCT5.mjs → settings-S6N6EFBG.mjs} +14 -11
- package/dist/cli/{settings-HTNTFKCE.js → settings-ZTXQEMZI.js} +80 -77
- package/dist/cli/{setup-P3GYYZWG.mjs → setup-AYPIK4JE.mjs} +12 -10
- package/dist/cli/{setup-QGCAP62X.js → setup-Y3WOIFLS.js} +53 -51
- package/dist/cli/{skills-7NAE4ICL.mjs → skills-5SF5QWNI.mjs} +7 -6
- package/dist/cli/skills-MWFRMG3H.js +31 -0
- package/dist/cli/tools-3XNZ4J64.mjs +55 -0
- package/dist/cli/tools-XEC4OD3R.js +55 -0
- package/dist/cli/{update-GODLRKNB.mjs → update-3U4OVX5R.mjs} +9 -8
- package/dist/cli/update-DWYEYTZE.js +33 -0
- package/dist/cli/{workflow-4BXOUVEO.mjs → workflow-2M5JP7SA.mjs} +10 -8
- package/dist/cli/{workflow-AO3A6LXN.js → workflow-RM7H7555.js} +20 -18
- package/dist/client-DS2IWYZF.d.ts +10 -0
- package/dist/client-DTwnz_AW.d.mts +10 -0
- package/dist/{client-CYqG23K1.d.ts → client-core-B_6HAIBy.d.ts} +385 -12
- package/dist/{client-BbU5_j7n.d.mts → client-core-DzBSlY1U.d.mts} +385 -12
- package/dist/{compiler-manifest-CWz_sNOQ.d.ts → compiler-manifest-Dcyd3-Zd.d.mts} +43 -1
- package/dist/{compiler-manifest-CWz_sNOQ.d.mts → compiler-manifest-Dcyd3-Zd.d.ts} +43 -1
- package/dist/errors-d-sTrZhe.d.mts +142 -0
- package/dist/errors-yQwfgrcX.d.ts +142 -0
- package/dist/{index-BF2JB_Ug.d.mts → index-C6oXchjN.d.mts} +1 -1
- package/dist/{index-4NPXDzlD.d.ts → index-P56zy_z5.d.ts} +1 -1
- package/dist/index.d.mts +11 -147
- package/dist/index.d.ts +11 -147
- package/dist/index.js +16 -12
- package/dist/index.mjs +15 -11
- package/dist/install-integrity.json +141 -104
- package/dist/plays/bundle-play-file.d.mts +3 -3
- package/dist/plays/bundle-play-file.d.ts +3 -3
- package/dist/plays/bundle-play-file.mjs +2 -1
- package/dist/plays/play-description.d.mts +2 -2
- package/dist/plays/play-description.d.ts +2 -2
- package/dist/plays/play-description.js +2 -2
- package/dist/plays/play-description.mjs +1 -1
- package/dist/plays/run-request.d.mts +2 -2
- package/dist/plays/run-request.d.ts +2 -2
- package/dist/release.d.mts +1 -1
- package/dist/release.d.ts +1 -1
- package/dist/release.js +2 -2
- package/dist/release.mjs +1 -1
- package/dist/server.d.mts +17 -0
- package/dist/server.d.ts +17 -0
- package/dist/server.js +76 -0
- package/dist/server.mjs +76 -0
- package/package.json +6 -1
- package/dist/cli/auth-IACERYQH.js +0 -40
- package/dist/cli/chunk-PQUUWFXY.js +0 -95
- package/dist/cli/chunk-YBWAG72P.mjs +0 -95
- package/dist/cli/chunk-YQDUODZW.js +0 -1710
- package/dist/cli/git-JVI36ZFV.js +0 -24
- package/dist/cli/search-75X5LTDE.js +0 -30
- package/dist/cli/skills-BKJ53JOQ.js +0 -30
- package/dist/cli/tools-COWMIEJ6.mjs +0 -45
- package/dist/cli/tools-TASOCE7I.js +0 -45
- package/dist/cli/update-SJIKVME6.js +0 -32
|
@@ -1037,7 +1037,11 @@ export type MaterializePlayDatasetInputOptions<T> = {
|
|
|
1037
1037
|
export type IteratePlayDatasetInputPagesOptions<T> = {
|
|
1038
1038
|
pageSize?: number;
|
|
1039
1039
|
maxPageBytes?: number;
|
|
1040
|
-
estimateRowBytes?: (
|
|
1040
|
+
estimateRowBytes?: (
|
|
1041
|
+
row: T,
|
|
1042
|
+
index: number,
|
|
1043
|
+
sourceIdentity?: PlayDatasetSourceRowIdentity,
|
|
1044
|
+
) => number;
|
|
1041
1045
|
onRow?: (row: T, index: number) => void;
|
|
1042
1046
|
};
|
|
1043
1047
|
|
|
@@ -1076,8 +1080,10 @@ export async function* iteratePlayDatasetInputPages<T>(
|
|
|
1076
1080
|
sourceIdentity: PlayDatasetSourceRowIdentity | undefined,
|
|
1077
1081
|
): Array<{ rows: T[]; offset: number }> => {
|
|
1078
1082
|
options?.onRow?.(row, index);
|
|
1079
|
-
|
|
1080
|
-
|
|
1083
|
+
const rowBytes = Math.max(
|
|
1084
|
+
0,
|
|
1085
|
+
Math.ceil(estimateRowBytes(row, index++, sourceIdentity)),
|
|
1086
|
+
);
|
|
1081
1087
|
const ready: Array<{ rows: T[]; offset: number }> = [];
|
|
1082
1088
|
if (page.length > 0 && pageBytes + rowBytes > maxPageBytes) {
|
|
1083
1089
|
ready.push({ rows: page, offset });
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { readdir, readFile, stat } from 'node:fs/promises';
|
|
2
2
|
import { join, relative } from 'node:path';
|
|
3
3
|
import picomatch from 'picomatch';
|
|
4
|
+
import { DEFAULT_MANIFEST_FILE } from './manifest-contract';
|
|
5
|
+
|
|
6
|
+
export { DEFAULT_MANIFEST_FILE } from './manifest-contract';
|
|
4
7
|
|
|
5
8
|
/**
|
|
6
9
|
* deepline.json — the repo-owned half of deploy configuration. The repo
|
|
@@ -98,8 +101,6 @@ export function parseDeeplineManifest(
|
|
|
98
101
|
};
|
|
99
102
|
}
|
|
100
103
|
|
|
101
|
-
export const DEFAULT_MANIFEST_FILE = 'deepline.json';
|
|
102
|
-
|
|
103
104
|
export async function readDeeplineManifest(
|
|
104
105
|
projectRoot: string,
|
|
105
106
|
manifestFile: string = DEFAULT_MANIFEST_FILE,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { DEFAULT_MANIFEST_FILE } from './manifest';
|
|
1
|
+
import { DEFAULT_MANIFEST_FILE } from './manifest-contract';
|
|
2
2
|
import type { PlayDeploymentDoc, PlayProjectDoc } from './control-plane-types';
|
|
3
3
|
|
|
4
|
-
export { DEFAULT_MANIFEST_FILE } from './manifest';
|
|
4
|
+
export { DEFAULT_MANIFEST_FILE } from './manifest-contract';
|
|
5
5
|
|
|
6
6
|
export type SerializedPlayProject = {
|
|
7
7
|
id: string;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { isSerializedPlayDataset } from './dataset';
|
|
2
|
+
|
|
3
|
+
const label = (key: string) =>
|
|
4
|
+
key
|
|
5
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
|
|
6
|
+
.replace(/[_-]+/g, ' ')
|
|
7
|
+
.replace(/^./, (character) => character.toUpperCase());
|
|
8
|
+
|
|
9
|
+
function datasetRowCount(value: unknown): number | null {
|
|
10
|
+
if (isSerializedPlayDataset(value)) return value.count;
|
|
11
|
+
if (!value || typeof value !== 'object') return null;
|
|
12
|
+
const record = value as Record<string, unknown>;
|
|
13
|
+
return record.kind === 'dataset' &&
|
|
14
|
+
typeof record.tableNamespace === 'string' &&
|
|
15
|
+
typeof record.count === 'number' &&
|
|
16
|
+
Number.isFinite(record.count) &&
|
|
17
|
+
record.count >= 0
|
|
18
|
+
? record.count
|
|
19
|
+
: null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Describe recorded output, never infer external effects from run success. */
|
|
23
|
+
export function summarizeRunOutput(
|
|
24
|
+
result: unknown,
|
|
25
|
+
options: { preview?: boolean } = {},
|
|
26
|
+
): string | undefined {
|
|
27
|
+
const count = datasetRowCount(result);
|
|
28
|
+
if (count !== null) {
|
|
29
|
+
return `${count} ${count === 1 ? 'row' : 'rows'} returned`;
|
|
30
|
+
}
|
|
31
|
+
if (Array.isArray(result)) {
|
|
32
|
+
if (options.preview) return undefined;
|
|
33
|
+
return `${result.length} ${result.length === 1 ? 'item' : 'items'} returned`;
|
|
34
|
+
}
|
|
35
|
+
if (typeof result !== 'object' || result === null) return undefined;
|
|
36
|
+
const output = result as Record<string, unknown>;
|
|
37
|
+
const parts: string[] = [];
|
|
38
|
+
for (const [key, value] of Object.entries(output)) {
|
|
39
|
+
if (key === '_metadata') continue;
|
|
40
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
41
|
+
parts.push(`${label(key)}: ${value}`);
|
|
42
|
+
} else if (typeof value === 'boolean') {
|
|
43
|
+
parts.push(`${label(key)}: ${value ? 'Yes' : 'No'}`);
|
|
44
|
+
} else if (datasetRowCount(value) !== null) {
|
|
45
|
+
const rows = datasetRowCount(value)!;
|
|
46
|
+
parts.push(`${label(key)}: ${rows} ${rows === 1 ? 'row' : 'rows'}`);
|
|
47
|
+
} else if (Array.isArray(value) && !options.preview) {
|
|
48
|
+
parts.push(
|
|
49
|
+
`${label(key)}: ${value.length} ${value.length === 1 ? 'item' : 'items'}`,
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// The summary names available results; the run record retains every value.
|
|
54
|
+
if (parts.length > 0) {
|
|
55
|
+
return [
|
|
56
|
+
...parts.slice(0, 3),
|
|
57
|
+
...(parts.length > 3 ? [`+${parts.length - 3} more results`] : []),
|
|
58
|
+
].join(' · ');
|
|
59
|
+
}
|
|
60
|
+
const fields = Object.keys(output).filter(
|
|
61
|
+
(key) => key !== '_metadata' && output[key] !== undefined,
|
|
62
|
+
);
|
|
63
|
+
return fields.length > 0
|
|
64
|
+
? `Returned ${fields.slice(0, 3).map(label).join(', ')}${fields.length > 3 ? ` and ${fields.length - 3} more fields` : ''}`
|
|
65
|
+
: undefined;
|
|
66
|
+
}
|
|
@@ -132,7 +132,7 @@ export type ScriptPlay = ScriptPlayParts & {
|
|
|
132
132
|
};
|
|
133
133
|
|
|
134
134
|
/**
|
|
135
|
-
* The file `deepline
|
|
135
|
+
* The file `deepline run -e '<code>'` (or `plays run -e`) writes and runs. A one-off inline
|
|
136
136
|
* play is the only play whose tool calls may omit `description`.
|
|
137
137
|
*/
|
|
138
138
|
export const INLINE_PLAY_FILE = '.inline.play.ts';
|
|
@@ -82,6 +82,7 @@ export type ProductNotificationPresentation = {
|
|
|
82
82
|
severity?: ProductNotificationSeverity;
|
|
83
83
|
/** Selects an alternate email layout; absent means the standard one. */
|
|
84
84
|
emailFormat?: 'thank_you';
|
|
85
|
+
playRun?: import('./content').PlayRunEmailContent;
|
|
85
86
|
};
|
|
86
87
|
|
|
87
88
|
type ProductNotificationRuleInput = {
|
|
@@ -189,6 +190,29 @@ function playRunPresentation(
|
|
|
189
190
|
occurredAt?: number,
|
|
190
191
|
trigger?: ProductNotificationTrigger,
|
|
191
192
|
): ProductNotificationPresentation {
|
|
193
|
+
const playRun = {
|
|
194
|
+
name: String(payload.playName),
|
|
195
|
+
description:
|
|
196
|
+
typeof payload.playDescription === 'string'
|
|
197
|
+
? payload.playDescription
|
|
198
|
+
: undefined,
|
|
199
|
+
output:
|
|
200
|
+
typeof payload.outputSummary === 'string'
|
|
201
|
+
? payload.outputSummary
|
|
202
|
+
: undefined,
|
|
203
|
+
runId: String(payload.runId),
|
|
204
|
+
details: [] as NotificationText[],
|
|
205
|
+
};
|
|
206
|
+
const context = [
|
|
207
|
+
...(typeof payload.playDescription === 'string' &&
|
|
208
|
+
payload.playDescription.trim()
|
|
209
|
+
? [`What this Play does: ${payload.playDescription}`]
|
|
210
|
+
: []),
|
|
211
|
+
...(typeof payload.outputSummary === 'string' &&
|
|
212
|
+
payload.outputSummary.trim()
|
|
213
|
+
? [`Run output: ${payload.outputSummary}`]
|
|
214
|
+
: []),
|
|
215
|
+
];
|
|
192
216
|
if (!succeeded) {
|
|
193
217
|
const failedAt =
|
|
194
218
|
typeof occurredAt === 'number'
|
|
@@ -196,6 +220,19 @@ function playRunPresentation(
|
|
|
196
220
|
: null;
|
|
197
221
|
return {
|
|
198
222
|
title: 'Play failed',
|
|
223
|
+
playRun: {
|
|
224
|
+
...playRun,
|
|
225
|
+
error:
|
|
226
|
+
typeof payload.reason === 'string' && payload.reason.trim()
|
|
227
|
+
? payload.reason
|
|
228
|
+
: undefined,
|
|
229
|
+
details: [
|
|
230
|
+
...(failedAt ? [['Failed at ', failedAt] as const] : []),
|
|
231
|
+
...(trigger?.kind === 'consecutive_outcomes'
|
|
232
|
+
? [['Failures ', String(trigger.count)] as const]
|
|
233
|
+
: []),
|
|
234
|
+
],
|
|
235
|
+
},
|
|
199
236
|
summary: [
|
|
200
237
|
'Your play ',
|
|
201
238
|
{ strong: String(payload.playName) },
|
|
@@ -203,6 +240,10 @@ function playRunPresentation(
|
|
|
203
240
|
],
|
|
204
241
|
details: [
|
|
205
242
|
['Play ', { strong: String(payload.playName) }],
|
|
243
|
+
...context,
|
|
244
|
+
...(typeof payload.reason === 'string' && payload.reason.trim()
|
|
245
|
+
? [`Why it failed: ${payload.reason}`]
|
|
246
|
+
: []),
|
|
206
247
|
...(failedAt ? [['Failed at ', failedAt] as const] : []),
|
|
207
248
|
...(trigger?.kind === 'consecutive_outcomes'
|
|
208
249
|
? [['Failures ', String(trigger.count)] as const]
|
|
@@ -217,12 +258,13 @@ function playRunPresentation(
|
|
|
217
258
|
|
|
218
259
|
return {
|
|
219
260
|
title: succeeded ? 'Play succeeded' : 'Play failed',
|
|
261
|
+
playRun,
|
|
220
262
|
summary: [
|
|
221
263
|
`${payload.playName} ${succeeded ? 'succeeded' : 'failed'} in your `,
|
|
222
264
|
{ workspace: true },
|
|
223
265
|
'.',
|
|
224
266
|
],
|
|
225
|
-
details: [`Run: ${payload.runId}`],
|
|
267
|
+
details: [...context, `Run: ${payload.runId}`],
|
|
226
268
|
targetUrl: String(payload.targetUrl),
|
|
227
269
|
subjectKind: 'play',
|
|
228
270
|
subjectId: String(payload.playId),
|
|
@@ -13,6 +13,15 @@ export type NotificationText =
|
|
|
13
13
|
|
|
14
14
|
export type NotificationIcon = 'calendar' | 'book-open';
|
|
15
15
|
|
|
16
|
+
export type PlayRunEmailContent = {
|
|
17
|
+
name: string;
|
|
18
|
+
description?: string;
|
|
19
|
+
output?: string;
|
|
20
|
+
error?: string;
|
|
21
|
+
runId: string;
|
|
22
|
+
details: NotificationText[];
|
|
23
|
+
};
|
|
24
|
+
|
|
16
25
|
export function notificationText(
|
|
17
26
|
content: NotificationText,
|
|
18
27
|
workspaceName?: string,
|
|
@@ -8,7 +8,11 @@ import {
|
|
|
8
8
|
notificationSettingsUrl,
|
|
9
9
|
type NotificationWorkspace,
|
|
10
10
|
} from './workspace';
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
notificationText,
|
|
13
|
+
type NotificationText,
|
|
14
|
+
type PlayRunEmailContent,
|
|
15
|
+
} from './content';
|
|
12
16
|
|
|
13
17
|
export {
|
|
14
18
|
normalizeProductNotificationEmail,
|
|
@@ -38,9 +42,25 @@ type ProductNotificationEmailContent = {
|
|
|
38
42
|
* own format so these emails can diverge later.
|
|
39
43
|
*/
|
|
40
44
|
emailFormat?: 'thank_you';
|
|
45
|
+
playRun?: PlayRunEmailContent;
|
|
41
46
|
};
|
|
42
47
|
|
|
43
48
|
const MAX_RECIPIENTS = 50;
|
|
49
|
+
const MAX_FAILURE_PREVIEW_CHARACTERS = 280;
|
|
50
|
+
const MAX_FAILURE_PREVIEW_LINES = 3;
|
|
51
|
+
|
|
52
|
+
function failurePreview(error: string): string {
|
|
53
|
+
const lines = error.split(/\r?\n/, MAX_FAILURE_PREVIEW_LINES + 1);
|
|
54
|
+
const characters = Array.from(
|
|
55
|
+
lines.slice(0, MAX_FAILURE_PREVIEW_LINES).join('\n'),
|
|
56
|
+
);
|
|
57
|
+
const shortened =
|
|
58
|
+
lines.length > MAX_FAILURE_PREVIEW_LINES ||
|
|
59
|
+
characters.length > MAX_FAILURE_PREVIEW_CHARACTERS;
|
|
60
|
+
return shortened
|
|
61
|
+
? `${characters.slice(0, MAX_FAILURE_PREVIEW_CHARACTERS - 1).join('')}…`
|
|
62
|
+
: characters.join('');
|
|
63
|
+
}
|
|
44
64
|
|
|
45
65
|
/**
|
|
46
66
|
* Lucide icons rasterized to 48px PNGs in the light-theme muted foreground
|
|
@@ -173,9 +193,17 @@ export function renderProductNotificationEmail(
|
|
|
173
193
|
);
|
|
174
194
|
}
|
|
175
195
|
|
|
176
|
-
const
|
|
196
|
+
const playRun = input.content.playRun;
|
|
197
|
+
let targetUrl = input.content.targetUrl
|
|
177
198
|
? workspaceAppUrl(input.appUrl, input.workspaceId, input.content.targetUrl)
|
|
178
199
|
: null;
|
|
200
|
+
if (playRun && input.content.targetUrl) {
|
|
201
|
+
const target = new URL(input.content.targetUrl, input.appUrl);
|
|
202
|
+
target.searchParams.set('runId', playRun.runId);
|
|
203
|
+
target.searchParams.set('tab', 'runs');
|
|
204
|
+
target.searchParams.set('view', 'run');
|
|
205
|
+
targetUrl = workspaceAppUrl(input.appUrl, input.workspaceId, target.href);
|
|
206
|
+
}
|
|
179
207
|
const settingsUrl = notificationSettingsUrl(input, input.groupKey);
|
|
180
208
|
const logoUrl =
|
|
181
209
|
targetUrl ?? workspaceAppUrl(input.appUrl, input.workspaceId, '/dashboard');
|
|
@@ -186,17 +214,39 @@ export function renderProductNotificationEmail(
|
|
|
186
214
|
? unsubscribeUrl(input.oneClickUnsubscribeUrl)
|
|
187
215
|
: optOutUrl;
|
|
188
216
|
const showGroupHeader = input.content.emailFormat !== 'thank_you';
|
|
217
|
+
if (playRun && !targetUrl) {
|
|
218
|
+
throw new Error('Play run email requires a run link.');
|
|
219
|
+
}
|
|
220
|
+
const errorPreview = playRun?.error
|
|
221
|
+
? failurePreview(playRun.error)
|
|
222
|
+
: undefined;
|
|
189
223
|
const text = [
|
|
190
224
|
input.content.title,
|
|
191
|
-
...(showGroupHeader
|
|
225
|
+
...(showGroupHeader && !playRun
|
|
192
226
|
? [`Notification group: ${input.content.groupName}`]
|
|
193
227
|
: []),
|
|
194
|
-
...(targetUrl ? [`Open Deepline: ${targetUrl}`] : []),
|
|
228
|
+
...(targetUrl && !playRun ? [`Open Deepline: ${targetUrl}`] : []),
|
|
195
229
|
'',
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
230
|
+
...(playRun
|
|
231
|
+
? [
|
|
232
|
+
notificationText(input.content.summary, input.workspaceName),
|
|
233
|
+
'',
|
|
234
|
+
`${playRun.name}: ${targetUrl}`,
|
|
235
|
+
...(playRun.description ? [playRun.description] : []),
|
|
236
|
+
'---',
|
|
237
|
+
...(playRun.output ? [playRun.output] : []),
|
|
238
|
+
...(errorPreview ? [`Failure: ${errorPreview}`] : []),
|
|
239
|
+
...playRun.details.map((detail) =>
|
|
240
|
+
notificationText(detail, input.workspaceName),
|
|
241
|
+
),
|
|
242
|
+
`Run: ${playRun.runId} (${targetUrl})`,
|
|
243
|
+
]
|
|
244
|
+
: [
|
|
245
|
+
notificationText(input.content.summary, input.workspaceName),
|
|
246
|
+
...input.content.details.map((detail) =>
|
|
247
|
+
notificationText(detail, input.workspaceName),
|
|
248
|
+
),
|
|
249
|
+
]),
|
|
200
250
|
'',
|
|
201
251
|
`You are receiving this because of your Deepline notification settings: ${settingsUrl}`,
|
|
202
252
|
...(optOutUrl
|
|
@@ -217,16 +267,44 @@ export function renderProductNotificationEmail(
|
|
|
217
267
|
`<td align="left" valign="middle"><a href="${escapeHtml(logoUrl)}" style="display:inline-block;text-decoration:none"><img src="https://code.deepline.com/brand/logo_full_dark.png" width="120" height="auto" alt="Deepline" style="display:block;border:0"></a></td>`,
|
|
218
268
|
`<td align="right" valign="middle">${severityBadge}</td>`,
|
|
219
269
|
'</tr></table>',
|
|
220
|
-
...(showGroupHeader
|
|
270
|
+
...(showGroupHeader && !playRun
|
|
221
271
|
? [
|
|
222
272
|
'<p style="margin:0 0 16px">',
|
|
223
273
|
`<span style="font-size:12px;color:#a3a3a3;letter-spacing:.06em;text-transform:uppercase">${escapeHtml(input.content.groupName)}</span>`,
|
|
224
274
|
'</p>',
|
|
225
275
|
]
|
|
226
276
|
: []),
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
277
|
+
...(playRun
|
|
278
|
+
? [
|
|
279
|
+
`<p style="margin:0 0 24px;font-size:14px;line-height:1.6;color:#525252">${contentHtml(input.content.summary, input.workspaceName)}</p>`,
|
|
280
|
+
`<p style="margin:0 0 8px;font-size:18px;line-height:1.4"><a href="${escapeHtml(targetUrl!)}" style="color:#0a0a0a;text-decoration:underline"><strong>${escapeHtml(playRun.name)}</strong></a></p>`,
|
|
281
|
+
...(playRun.description
|
|
282
|
+
? [
|
|
283
|
+
`<p style="margin:0 0 24px;font-size:14px;line-height:1.6;color:#525252">${escapeHtml(playRun.description)}</p>`,
|
|
284
|
+
]
|
|
285
|
+
: []),
|
|
286
|
+
'<div style="height:1px;background-color:#e5e5e5;margin:24px 0"></div>',
|
|
287
|
+
...(playRun.output
|
|
288
|
+
? [
|
|
289
|
+
`<p style="margin:0 0 16px;font-size:14px;line-height:1.6;color:#0a0a0a">${escapeHtml(playRun.output)}</p>`,
|
|
290
|
+
]
|
|
291
|
+
: []),
|
|
292
|
+
...(errorPreview
|
|
293
|
+
? [
|
|
294
|
+
'<p style="margin:0 0 8px;font-size:14px;color:#0a0a0a">Failure:</p>',
|
|
295
|
+
`<pre style="margin:0 0 16px;padding:12px;background-color:#f5f5f5;border-radius:6px;white-space:pre-wrap;overflow-wrap:anywhere;user-select:all;font-family:Menlo,Consolas,monospace;font-size:14px;line-height:1.6;color:#0a0a0a"><code>${escapeHtml(errorPreview)}</code></pre>`,
|
|
296
|
+
]
|
|
297
|
+
: []),
|
|
298
|
+
...playRun.details.map((detail) =>
|
|
299
|
+
detailHtml(detail, input.workspaceName, false, true),
|
|
300
|
+
),
|
|
301
|
+
`<p style="margin:16px 0 32px;font-size:14px;line-height:1.6;color:#525252">Run: <a href="${escapeHtml(targetUrl!)}" style="color:#525252;text-decoration:underline">${escapeHtml(playRun.runId)}</a></p>`,
|
|
302
|
+
]
|
|
303
|
+
: [
|
|
304
|
+
`<h1 style="margin:0 0 8px;font-size:22px;font-weight:600;color:#0a0a0a;line-height:1.3;letter-spacing:-0.02em">${escapeHtml(input.content.title)}</h1>`,
|
|
305
|
+
`<p style="margin:0 0 24px;font-size:15px;line-height:1.6;color:#525252">${contentHtml(input.content.summary, input.workspaceName)}</p>`,
|
|
306
|
+
]),
|
|
307
|
+
...(!playRun && detailCount > 0
|
|
230
308
|
? [
|
|
231
309
|
`<table role="presentation" width="100%" cellspacing="0" cellpadding="0" style="border:1px solid #e5e5e5;border-radius:10px;margin:0 0 28px"><tr><td style="padding:${showGroupHeader ? '4px' : '11px'} 18px">`,
|
|
232
310
|
...input.content.details.map((detail, index) =>
|
|
@@ -240,7 +318,7 @@ export function renderProductNotificationEmail(
|
|
|
240
318
|
'</td></tr></table>',
|
|
241
319
|
]
|
|
242
320
|
: []),
|
|
243
|
-
...(targetUrl
|
|
321
|
+
...(targetUrl && !playRun
|
|
244
322
|
? [
|
|
245
323
|
'<table role="presentation" cellspacing="0" cellpadding="0" style="margin:0 0 32px"><tr>',
|
|
246
324
|
`<td style="background-color:#0a0a0a;border-radius:6px"><a href="${escapeHtml(targetUrl)}" style="display:inline-block;padding:12px 24px;font-size:14px;font-weight:500;color:#ffffff;text-decoration:none">Open Deepline</a></td>`,
|
|
@@ -173,6 +173,9 @@ export const PRODUCT_NOTIFICATION_EVENT_DEFINITIONS: readonly ProductNotificatio
|
|
|
173
173
|
optionalFacts: {
|
|
174
174
|
triggerKind: 'string',
|
|
175
175
|
isAutomated: 'boolean',
|
|
176
|
+
playDescription: 'string',
|
|
177
|
+
outputSummary: 'string',
|
|
178
|
+
reason: 'string',
|
|
176
179
|
},
|
|
177
180
|
orderingSubjectFact: 'playId',
|
|
178
181
|
allowedTriggers: ['each_match', 'consecutive_outcomes'],
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
export type SlackChannelKey =
|
|
12
12
|
| 'user_signup'
|
|
13
13
|
| 'session_activity'
|
|
14
|
-
| '
|
|
14
|
+
| 'billing_alerts'
|
|
15
15
|
| 'daily_activity_summary'
|
|
16
16
|
| 'integration_requests'
|
|
17
17
|
| 'deploy_events'
|
|
@@ -50,8 +50,6 @@ type ResolvedRequestMetadata = {
|
|
|
50
50
|
|
|
51
51
|
const CHANNEL_WEBHOOK_ENV: Partial<Record<SlackChannelKey, string>> = {
|
|
52
52
|
session_activity: 'SLACK_SESSION_ACTIVITY_WEBHOOK_URL',
|
|
53
|
-
error_activity: 'SLACK_ERROR_ACTIVITY_WEBHOOK_URL',
|
|
54
|
-
daily_activity_summary: 'SLACK_DAILY_ACTIVITY_SUMMARY_WEBHOOK_URL',
|
|
55
53
|
integration_requests: 'SLACK_INTEGRATION_REQUEST_WEBHOOK_URL',
|
|
56
54
|
deploy_events: 'SLACK_DEV_WEBHOOK_URL',
|
|
57
55
|
provider_health: 'SLACK_PROVIDER_HEALTH_WEBHOOK_URL',
|
|
@@ -74,7 +72,6 @@ const CHANNEL_WEBHOOK_FALLBACK_ENVS: Partial<
|
|
|
74
72
|
const SLACK_DEEPLINE_REPORTING_BOT_TOKEN_ENV =
|
|
75
73
|
'SLACK_DEEPLINE_REPORTING_BOT_TOKEN';
|
|
76
74
|
const SLACK_PROVIDER_ALERTS_CHANNEL_ID_ENV = 'SLACK_PROVIDER_ALERTS_CHANNEL_ID';
|
|
77
|
-
const SLACK_ERROR_ACTIVITY_CHANNEL_ID_ENV = 'SLACK_ERROR_ACTIVITY_CHANNEL_ID';
|
|
78
75
|
const SLACK_USER_SIGNUP_CHANNEL_ID_ENV = 'SLACK_USER_SIGNUP_CHANNEL_ID';
|
|
79
76
|
const SLACK_INBOUND_LEADS_CHANNEL_ID_ENV = 'SLACK_INBOUND_LEADS_CHANNEL_ID';
|
|
80
77
|
// #alerts-gtm. Inbound demo requests go where GTM already watches for leads.
|
|
@@ -91,6 +88,11 @@ const DEFAULT_MONITOR_ERROR_ACTIVITY_CHANNEL_ID = 'C0CD0JQTU20';
|
|
|
91
88
|
// #deepline-monitor-cron-failures: failures of scheduled jobs owned by monitors.
|
|
92
89
|
export const MONITOR_CRON_FAILURES_SLACK_CHANNEL_ID = 'C0CCZCKETEV';
|
|
93
90
|
|
|
91
|
+
// #deepline-billing-alerts: charge, ledger and payment notices needing review.
|
|
92
|
+
export const BILLING_ALERTS_SLACK_CHANNEL_ID = 'C0CEBRS6PHS';
|
|
93
|
+
// #internal-reports-deepline-api.
|
|
94
|
+
export const DAILY_ACTIVITY_SUMMARY_SLACK_CHANNEL_ID = 'C0APQ088CKX';
|
|
95
|
+
|
|
94
96
|
export const SDK_CLI_ACTIVITY_SLACK_CHANNEL_ID = 'C0B7D7DB40Y';
|
|
95
97
|
export const SDK_CLI_ERRORS_SLACK_CHANNEL_ID = 'C0B6JUJ9QJW';
|
|
96
98
|
export const SDK_CLI_FEEDBACK_SLACK_CHANNEL_ID = 'C0B63EX130F';
|
|
@@ -114,7 +116,7 @@ const CHANNEL_ALERT_LEVEL: Record<
|
|
|
114
116
|
> = {
|
|
115
117
|
user_signup: 'info',
|
|
116
118
|
session_activity: 'info',
|
|
117
|
-
|
|
119
|
+
billing_alerts: 'error',
|
|
118
120
|
daily_activity_summary: 'info',
|
|
119
121
|
integration_requests: 'info',
|
|
120
122
|
deploy_events: 'info',
|
|
@@ -151,12 +153,16 @@ function getSlackChannelEnvironmentRequirement(
|
|
|
151
153
|
case 'sdk_cli_errors':
|
|
152
154
|
// Vercel crons run only in production.
|
|
153
155
|
case 'monitor_cron_failures':
|
|
156
|
+
// Gauntlet and local tests trigger monitor errors on purpose, and these
|
|
157
|
+
// channels fall back to production channel IDs wherever the bot token is set.
|
|
158
|
+
case 'monitor_activity':
|
|
159
|
+
case 'monitor_error_activity':
|
|
154
160
|
// Preview and local deploys must never page GTM with test submissions.
|
|
155
161
|
case 'inbound_leads':
|
|
162
|
+
case 'billing_alerts':
|
|
163
|
+
case 'daily_activity_summary':
|
|
156
164
|
return 'prod';
|
|
157
165
|
case 'session_activity':
|
|
158
|
-
case 'error_activity':
|
|
159
|
-
case 'daily_activity_summary':
|
|
160
166
|
case 'integration_requests':
|
|
161
167
|
case 'deploy_events':
|
|
162
168
|
case 'provider_alerts':
|
|
@@ -165,8 +171,6 @@ function getSlackChannelEnvironmentRequirement(
|
|
|
165
171
|
case 'dashboard_feedback':
|
|
166
172
|
case 'python_cli_feedback':
|
|
167
173
|
case 'python_cli_session':
|
|
168
|
-
case 'monitor_activity':
|
|
169
|
-
case 'monitor_error_activity':
|
|
170
174
|
case 'plain_thread_activity':
|
|
171
175
|
return 'all';
|
|
172
176
|
default:
|
|
@@ -205,6 +209,8 @@ function requireWebhookUrl(channel: SlackChannelKey): string {
|
|
|
205
209
|
function isBotOnlySlackChannel(channel: SlackChannelKey): boolean {
|
|
206
210
|
return (
|
|
207
211
|
channel === 'user_signup' ||
|
|
212
|
+
channel === 'billing_alerts' ||
|
|
213
|
+
channel === 'daily_activity_summary' ||
|
|
208
214
|
channel === 'sdk_cli_activity' ||
|
|
209
215
|
channel === 'sdk_cli_errors' ||
|
|
210
216
|
channel === 'monitor_cron_failures' ||
|
|
@@ -222,17 +228,10 @@ function resolveBotChannel(
|
|
|
222
228
|
if (!token) return null;
|
|
223
229
|
|
|
224
230
|
switch (channel) {
|
|
225
|
-
case '
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
process.env[SLACK_ERROR_ACTIVITY_CHANNEL_ID_ENV]?.trim();
|
|
230
|
-
if (!channelId) return null;
|
|
231
|
-
return {
|
|
232
|
-
token,
|
|
233
|
-
channelId,
|
|
234
|
-
};
|
|
235
|
-
}
|
|
231
|
+
case 'billing_alerts':
|
|
232
|
+
return { token, channelId: BILLING_ALERTS_SLACK_CHANNEL_ID };
|
|
233
|
+
case 'daily_activity_summary':
|
|
234
|
+
return { token, channelId: DAILY_ACTIVITY_SUMMARY_SLACK_CHANNEL_ID };
|
|
236
235
|
case 'user_signup':
|
|
237
236
|
return {
|
|
238
237
|
token,
|
|
@@ -295,6 +294,17 @@ function isMonitorSlackChannel(channel: SlackChannelKey): boolean {
|
|
|
295
294
|
return channel.startsWith('monitor_');
|
|
296
295
|
}
|
|
297
296
|
|
|
297
|
+
/**
|
|
298
|
+
* `getRuntimeEnv()` reads `DEEPLINE_ENV` and `CONVEX_DEPLOYMENT` before
|
|
299
|
+
* `VERCEL_ENV`, so a Preview carrying a production hint resolves to prod. A
|
|
300
|
+
* non-production Vercel marker wins for monitor channels; workers without
|
|
301
|
+
* Vercel metadata still fall through to the runtime check.
|
|
302
|
+
*/
|
|
303
|
+
function isNonProductionVercelDeployment(): boolean {
|
|
304
|
+
const vercelEnv = process.env.VERCEL_ENV?.trim();
|
|
305
|
+
return Boolean(vercelEnv) && vercelEnv !== 'production';
|
|
306
|
+
}
|
|
307
|
+
|
|
298
308
|
function isSlackChannelUnavailableError(error: unknown): boolean {
|
|
299
309
|
const message = error instanceof Error ? error.message : String(error);
|
|
300
310
|
return (
|
|
@@ -564,6 +574,9 @@ export async function sendSlackEvent(
|
|
|
564
574
|
) {
|
|
565
575
|
return;
|
|
566
576
|
}
|
|
577
|
+
if (isMonitorSlackChannel(channel) && isNonProductionVercelDeployment()) {
|
|
578
|
+
return;
|
|
579
|
+
}
|
|
567
580
|
if (isSyntheticActorEmail(extractActorEmail(payload))) return;
|
|
568
581
|
if (!payload.bypassInternalActorBlock && isBlockedInternalActor(payload)) {
|
|
569
582
|
return;
|
|
@@ -600,10 +613,14 @@ export async function sendSlackEvent(
|
|
|
600
613
|
|
|
601
614
|
const botChannel = resolveBotChannel(channel);
|
|
602
615
|
if (botChannel) {
|
|
603
|
-
// Monitor
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
616
|
+
// Monitor, billing and daily summary callers await this post, some in the
|
|
617
|
+
// request path, so bound it like a webhook post.
|
|
618
|
+
const controller =
|
|
619
|
+
isMonitorSlackChannel(channel) ||
|
|
620
|
+
channel === 'billing_alerts' ||
|
|
621
|
+
channel === 'daily_activity_summary'
|
|
622
|
+
? new AbortController()
|
|
623
|
+
: null;
|
|
607
624
|
const timeout = controller
|
|
608
625
|
? setTimeout(() => controller.abort(), resolveTimeoutMs())
|
|
609
626
|
: null;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The app proxies Better Auth requests to Convex, whose HTTP edge reports the
|
|
3
|
+
* proxy itself as the caller. The app attests the browser's address with an
|
|
4
|
+
* HMAC so Convex can restore it, while a direct caller cannot choose one.
|
|
5
|
+
*/
|
|
6
|
+
export const ATTESTED_CLIENT_IP_HEADER = 'x-deepline-attested-client-ip';
|
|
7
|
+
const DERIVATION_LABEL = 'deepline:attested-client-ip:v1';
|
|
8
|
+
const MAX_AGE_SECONDS = 60;
|
|
9
|
+
|
|
10
|
+
function hmacKey(secret: string) {
|
|
11
|
+
return crypto.subtle.importKey(
|
|
12
|
+
'raw',
|
|
13
|
+
new TextEncoder().encode(`${secret}:${DERIVATION_LABEL}`),
|
|
14
|
+
{ name: 'HMAC', hash: 'SHA-256' },
|
|
15
|
+
false,
|
|
16
|
+
['sign', 'verify'],
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const signedPayload = (ip: string, issuedAt: number) =>
|
|
21
|
+
new TextEncoder().encode(`${ip}|${issuedAt}`);
|
|
22
|
+
|
|
23
|
+
const toHex = (bytes: ArrayBuffer) =>
|
|
24
|
+
Array.from(new Uint8Array(bytes), (byte) =>
|
|
25
|
+
byte.toString(16).padStart(2, '0'),
|
|
26
|
+
).join('');
|
|
27
|
+
|
|
28
|
+
const fromHex = (hex: string) =>
|
|
29
|
+
/^(?:[0-9a-f]{2})+$/.test(hex)
|
|
30
|
+
? Uint8Array.from(hex.match(/../g)!, (pair) => parseInt(pair, 16))
|
|
31
|
+
: null;
|
|
32
|
+
|
|
33
|
+
export async function attestClientIp(input: {
|
|
34
|
+
ip: string;
|
|
35
|
+
secret: string;
|
|
36
|
+
nowMs?: number;
|
|
37
|
+
}): Promise<string> {
|
|
38
|
+
const issuedAt = Math.floor((input.nowMs ?? Date.now()) / 1000);
|
|
39
|
+
const signature = await crypto.subtle.sign(
|
|
40
|
+
'HMAC',
|
|
41
|
+
await hmacKey(input.secret),
|
|
42
|
+
signedPayload(input.ip, issuedAt),
|
|
43
|
+
);
|
|
44
|
+
return `${input.ip}|${issuedAt}|${toHex(signature)}`;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** The attested IP, or null when the value is malformed, stale or forged. */
|
|
48
|
+
export async function verifyAttestedClientIp(input: {
|
|
49
|
+
value: string;
|
|
50
|
+
secret: string;
|
|
51
|
+
nowMs?: number;
|
|
52
|
+
}): Promise<string | null> {
|
|
53
|
+
const [ip, issuedAtText, signatureHex, ...rest] = input.value.split('|');
|
|
54
|
+
const issuedAt = Number(issuedAtText);
|
|
55
|
+
const signature = fromHex(signatureHex ?? '');
|
|
56
|
+
const ageSeconds = (input.nowMs ?? Date.now()) / 1000 - issuedAt;
|
|
57
|
+
if (
|
|
58
|
+
rest.length > 0 ||
|
|
59
|
+
!ip ||
|
|
60
|
+
!signature ||
|
|
61
|
+
!Number.isInteger(issuedAt) ||
|
|
62
|
+
Math.abs(ageSeconds) > MAX_AGE_SECONDS
|
|
63
|
+
) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
const valid = await crypto.subtle.verify(
|
|
67
|
+
'HMAC',
|
|
68
|
+
await hmacKey(input.secret),
|
|
69
|
+
signature,
|
|
70
|
+
signedPayload(ip, issuedAt),
|
|
71
|
+
);
|
|
72
|
+
return valid ? ip : null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Replace `x-forwarded-for` with the attested client IP when the attestation
|
|
77
|
+
* verifies. The attestation header is always removed before the request
|
|
78
|
+
* reaches Better Auth.
|
|
79
|
+
*/
|
|
80
|
+
export async function restoreAttestedClientIp(
|
|
81
|
+
request: Request,
|
|
82
|
+
secret: string,
|
|
83
|
+
): Promise<Request> {
|
|
84
|
+
const attestation = request.headers.get(ATTESTED_CLIENT_IP_HEADER);
|
|
85
|
+
if (attestation === null) return request;
|
|
86
|
+
const headers = new Headers(request.headers);
|
|
87
|
+
headers.delete(ATTESTED_CLIENT_IP_HEADER);
|
|
88
|
+
const ip = await verifyAttestedClientIp({ value: attestation, secret });
|
|
89
|
+
if (ip) headers.set('x-forwarded-for', ip);
|
|
90
|
+
return new Request(request, { headers });
|
|
91
|
+
}
|
|
@@ -25,17 +25,6 @@ export function isInternalEmail(email?: string | null): boolean {
|
|
|
25
25
|
);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
/** Actors allowed to request provider fixtures against the production API. */
|
|
29
|
-
export function isAuthorizedProductionFixtureActor(
|
|
30
|
-
email?: string | null,
|
|
31
|
-
): boolean {
|
|
32
|
-
const normalized = normalizeInternalEmail(email);
|
|
33
|
-
return (
|
|
34
|
-
isInternalEmail(normalized) ||
|
|
35
|
-
/^bootstrap-[0-9a-f]{8}@deepline\.local$/i.test(normalized ?? '')
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
28
|
/** Whether an email belongs to a Deepline staff account. */
|
|
40
29
|
export function isDeeplineUser(email?: string | null): boolean {
|
|
41
30
|
return isInternalEmail(email);
|