@knpkv/control-center 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -8
- package/dist/client/.vite/manifest.json +214 -182
- package/dist/client/assets/{ActiveWorkPage-Dd1mxPrq.js → ActiveWorkPage-g2-Jyavo.js} +2 -2
- package/dist/client/assets/{ActiveWorkPage-Dd1mxPrq.js.map → ActiveWorkPage-g2-Jyavo.js.map} +1 -1
- package/dist/client/assets/AgentPage-B6GQdZAs.css +1 -0
- package/dist/client/assets/AgentPage-DmVsEe13.js +6 -0
- package/dist/client/assets/AgentPage-DmVsEe13.js.map +1 -0
- package/dist/client/assets/AtlassianOAuthCallbackPage-C8u9ItMj.js +2 -0
- package/dist/client/assets/{AtlassianOAuthCallbackPage-BPoF6oKf.js.map → AtlassianOAuthCallbackPage-C8u9ItMj.js.map} +1 -1
- package/dist/client/assets/{AuthorizedSharePage-jjqu6W_f.js → AuthorizedSharePage-CVBJ1NTm.js} +2 -2
- package/dist/client/assets/{AuthorizedSharePage-jjqu6W_f.js.map → AuthorizedSharePage-CVBJ1NTm.js.map} +1 -1
- package/dist/client/assets/BrowserCrypto-3BoTVFdl.js +2 -0
- package/dist/client/assets/{BrowserCrypto-BMbjhcvP.js.map → BrowserCrypto-3BoTVFdl.js.map} +1 -1
- package/dist/client/assets/BrowserSessionHydrator-CpZnNm4X.js +2 -0
- package/dist/client/assets/{BrowserSessionHydrator-BC1ymLkL.js.map → BrowserSessionHydrator-CpZnNm4X.js.map} +1 -1
- package/dist/client/assets/{CommandSearch-WwAVDrD9.js → CommandSearch-DUeRRbV2.js} +2 -2
- package/dist/client/assets/{CommandSearch-WwAVDrD9.js.map → CommandSearch-DUeRRbV2.js.map} +1 -1
- package/dist/client/assets/{ItemsPage-CKK_KkJ2.js → ItemsPage-BF2ZkSzh.js} +2 -2
- package/dist/client/assets/{ItemsPage-CKK_KkJ2.js.map → ItemsPage-BF2ZkSzh.js.map} +1 -1
- package/dist/client/assets/{PairPage-DA6cmyqF.js → PairPage-CkaZltHd.js} +2 -2
- package/dist/client/assets/{PairPage-DA6cmyqF.js.map → PairPage-CkaZltHd.js.map} +1 -1
- package/dist/client/assets/PortfolioOverview-CEUHJmGC.js +2 -0
- package/dist/client/assets/{PortfolioOverview-CEI4gpXi.js.map → PortfolioOverview-CEUHJmGC.js.map} +1 -1
- package/dist/client/assets/{PullRequestReviewPanel-D7AKnwL-.js → PullRequestReviewPanel-D1IpvHe2.js} +3 -3
- package/dist/client/assets/{PullRequestReviewPanel-D7AKnwL-.js.map → PullRequestReviewPanel-D1IpvHe2.js.map} +1 -1
- package/dist/client/assets/{ReleaseRoute-CbPW3qUT.js → ReleaseRoute-BuQybrsg.js} +2 -2
- package/dist/client/assets/{ReleaseRoute-CbPW3qUT.js.map → ReleaseRoute-BuQybrsg.js.map} +1 -1
- package/dist/client/assets/ReleaseWorkset-BclY0Nvj.js +2 -0
- package/dist/client/assets/ReleaseWorkset-BclY0Nvj.js.map +1 -0
- package/dist/client/assets/ServicesPage-hw5Ee69-.js +2 -0
- package/dist/client/assets/{ServicesPage-_B89DAvG.js.map → ServicesPage-hw5Ee69-.js.map} +1 -1
- package/dist/client/assets/{TimelinePage-DvpgD8AY.js → TimelinePage-Cj3V98uI.js} +2 -2
- package/dist/client/assets/{TimelinePage-DvpgD8AY.js.map → TimelinePage-Cj3V98uI.js.map} +1 -1
- package/dist/client/assets/{WorkspaceEntityLink-DPj6MKI2.js → WorkspaceEntityLink-C_rc8lxi.js} +2 -2
- package/dist/client/assets/{WorkspaceEntityLink-DPj6MKI2.js.map → WorkspaceEntityLink-C_rc8lxi.js.map} +1 -1
- package/dist/client/assets/WorkspaceEntityRoute-DLLT6fY0.css +1 -0
- package/dist/client/assets/WorkspaceEntityRoute-kbnrQ_lY.js +14 -0
- package/dist/client/assets/WorkspaceEntityRoute-kbnrQ_lY.js.map +1 -0
- package/dist/client/assets/WorkspaceHomeLink-DeYYLEsH.js +2 -0
- package/dist/client/assets/{WorkspaceHomeLink-CkJfzO25.js.map → WorkspaceHomeLink-DeYYLEsH.js.map} +1 -1
- package/dist/client/assets/WorkspacePullRequestDetails-CizqydjN.js +3 -0
- package/dist/client/assets/{WorkspacePullRequestDetails-HwDgp12e.js.map → WorkspacePullRequestDetails-CizqydjN.js.map} +1 -1
- package/dist/client/assets/{WorkspaceReleaseLayout-CGHi8eoo.js → WorkspaceReleaseLayout-CXAQUhkh.js} +2 -2
- package/dist/client/assets/{WorkspaceReleaseLayout-CGHi8eoo.js.map → WorkspaceReleaseLayout-CXAQUhkh.js.map} +1 -1
- package/dist/client/assets/{WorkspaceRichText-D1M637Ff.js → WorkspaceRichText-CCOciILO.js} +2 -2
- package/dist/client/assets/WorkspaceRichText-CCOciILO.js.map +1 -0
- package/dist/client/assets/WorkspaceSettingsPage-GoBfQzBx.css +1 -0
- package/dist/client/assets/WorkspaceSettingsPage-JG-pN_CA.js +2 -0
- package/dist/client/assets/WorkspaceSettingsPage-JG-pN_CA.js.map +1 -0
- package/dist/client/assets/agent-api-Dl9TuGOJ.js +19 -0
- package/dist/client/assets/agent-api-Dl9TuGOJ.js.map +1 -0
- package/dist/client/assets/atlassianOAuthSetupIntentStorage-DE4ySCTb.js +2 -0
- package/dist/client/assets/atlassianOAuthSetupIntentStorage-DE4ySCTb.js.map +1 -0
- package/dist/client/assets/authenticatedMutationClient-DdowMjyo.js +2 -0
- package/dist/client/assets/{authenticatedMutationClient-DYaieXUe.js.map → authenticatedMutationClient-DdowMjyo.js.map} +1 -1
- package/dist/client/assets/{authorizedShareTransport-cxBoQzQ2.js → authorizedShareTransport-CnclcYai.js} +2 -2
- package/dist/client/assets/{authorizedShareTransport-cxBoQzQ2.js.map → authorizedShareTransport-CnclcYai.js.map} +1 -1
- package/dist/client/assets/client-Dq_XQE_l.js +5 -0
- package/dist/client/assets/client-Dq_XQE_l.js.map +1 -0
- package/dist/client/assets/confluenceTasks-DtKq8_eU.js +5 -0
- package/dist/client/assets/confluenceTasks-DtKq8_eU.js.map +1 -0
- package/dist/client/assets/connectionTestTransport-CPK98z7H.js +2 -0
- package/dist/client/assets/connectionTestTransport-CPK98z7H.js.map +1 -0
- package/dist/client/assets/{index-C7_FDTU7.js → index-zVjlBm9l.js} +3 -3
- package/dist/client/assets/{index-C7_FDTU7.js.map → index-zVjlBm9l.js.map} +1 -1
- package/dist/client/assets/{patterns-5N-j-AD2-B9qgekXA.js → patterns-5N-j-AD2-DLfaGePK.js} +2 -2
- package/dist/client/assets/{patterns-5N-j-AD2-B9qgekXA.js.map → patterns-5N-j-AD2-DLfaGePK.js.map} +1 -1
- package/dist/client/assets/{presentPortfolio-C_JsoSWg.js → presentPortfolio-DLEq-vEz.js} +2 -2
- package/dist/client/assets/{presentPortfolio-C_JsoSWg.js.map → presentPortfolio-DLEq-vEz.js.map} +1 -1
- package/dist/client/assets/{presentWorkspaceItems-DboAfwGc.js → presentWorkspaceItems-BOY3FbhO.js} +2 -2
- package/dist/client/assets/{presentWorkspaceItems-DboAfwGc.js.map → presentWorkspaceItems-BOY3FbhO.js.map} +1 -1
- package/dist/client/assets/{pullRequestReviewFailures-DHmYwffV.js → pullRequestReviewFailures-CyjTVnSX.js} +2 -2
- package/dist/client/assets/{pullRequestReviewFailures-DHmYwffV.js.map → pullRequestReviewFailures-CyjTVnSX.js.map} +1 -1
- package/dist/client/assets/{pullRequestReviewThreadReplay-Vy1k53qE.js → pullRequestReviewThreadReplay-CXHspFTr.js} +2 -2
- package/dist/client/assets/{pullRequestReviewThreadReplay-Vy1k53qE.js.map → pullRequestReviewThreadReplay-CXHspFTr.js.map} +1 -1
- package/dist/client/assets/releaseAgentTransport-DaO4svPu.js +2 -0
- package/dist/client/assets/releaseAgentTransport-DaO4svPu.js.map +1 -0
- package/dist/client/assets/releaseRoutes-B4ciNOJj.js +2 -0
- package/dist/client/assets/{releaseRoutes-t9uCfs5T.js.map → releaseRoutes-B4ciNOJj.js.map} +1 -1
- package/dist/client/assets/{serviceOnboarding-DLINCon7.js → serviceOnboarding-D0FmodRi.js} +2 -2
- package/dist/client/assets/{serviceOnboarding-DLINCon7.js.map → serviceOnboarding-D0FmodRi.js.map} +1 -1
- package/dist/client/assets/{useWorkspaceDefaultLanding-CC5ImHkL.js → useWorkspaceDefaultLanding-BaQdg0sY.js} +3 -3
- package/dist/client/assets/{useWorkspaceDefaultLanding-CC5ImHkL.js.map → useWorkspaceDefaultLanding-BaQdg0sY.js.map} +1 -1
- package/dist/client/assets/{useWorkspaceItems-B1X-JNwq.js → useWorkspaceItems-B-7JHtm0.js} +2 -2
- package/dist/client/assets/{useWorkspaceItems-B1X-JNwq.js.map → useWorkspaceItems-B-7JHtm0.js.map} +1 -1
- package/dist/client/assets/workspaceEntityRoutes-DqqDa0AB.js +2 -0
- package/dist/client/assets/workspaceEntityRoutes-DqqDa0AB.js.map +1 -0
- package/dist/client/assets/{workspaceScrollCapture-BsjcWVsk.js → workspaceScrollCapture-BYNfR2wo.js} +2 -2
- package/dist/client/assets/{workspaceScrollCapture-BsjcWVsk.js.map → workspaceScrollCapture-BYNfR2wo.js.map} +1 -1
- package/dist/client/assets/{workspaceSettingsTransport-Dw2hueXv.js → workspaceSettingsTransport-Br4lBmvS.js} +2 -2
- package/dist/client/assets/{workspaceSettingsTransport-Dw2hueXv.js.map → workspaceSettingsTransport-Br4lBmvS.js.map} +1 -1
- package/dist/client/build-graph.json +98 -0
- package/dist/client/index.html +1 -1
- package/dist/server/api/agent.d.ts +12 -0
- package/dist/server/api/agent.d.ts.map +1 -1
- package/dist/server/api/deliveryGraph.d.ts +20 -0
- package/dist/server/api/deliveryGraph.d.ts.map +1 -1
- package/dist/server/api/index.d.ts +1 -1
- package/dist/server/api/index.d.ts.map +1 -1
- package/dist/server/api/index.js +3 -3
- package/dist/server/api/session.d.ts +23 -1
- package/dist/server/api/session.d.ts.map +1 -1
- package/dist/server/api/shares.d.ts +2 -0
- package/dist/server/api/shares.d.ts.map +1 -1
- package/dist/server/assets/{BindConfig-Bj282xDC.js → BindConfig-DAASchDn.js} +315 -36
- package/dist/server/assets/BindConfig-DAASchDn.js.map +1 -0
- package/dist/server/assets/{agent-ZvwskOQu.js → agent-xQhAQXly.js} +26 -6
- package/dist/server/assets/agent-xQhAQXly.js.map +1 -0
- package/dist/server/assets/{controlCenterApi-5j3gOXgE.js → controlCenterApi-DNXK7MT1.js} +4 -3
- package/dist/server/assets/controlCenterApi-DNXK7MT1.js.map +1 -0
- package/dist/server/assets/{manualPluginSynchronization-CzIhZ_Dw.js → manualPluginSynchronization-DFIeUHP9.js} +4 -3
- package/dist/server/assets/manualPluginSynchronization-DFIeUHP9.js.map +1 -0
- package/dist/server/assets/{readiness-BtntBhDj.js → readiness-31Mqc-9H.js} +2 -2
- package/dist/server/assets/{readiness-BtntBhDj.js.map → readiness-31Mqc-9H.js.map} +1 -1
- package/dist/server/assets/{relationshipInferenceMaterialization-CR6xyMNL.js → relationshipInferenceMaterialization-Dyix96px.js} +41 -14
- package/dist/server/assets/relationshipInferenceMaterialization-Dyix96px.js.map +1 -0
- package/dist/server/assets/{workspaceSettings-C2Zsk6RI.js → workspaceSettings-sv8h_h2P.js} +4 -1
- package/dist/server/assets/workspaceSettings-sv8h_h2P.js.map +1 -0
- package/dist/server/build-graph.json +28 -1
- package/dist/server/domain/confluenceTasks.d.ts +27 -0
- package/dist/server/domain/confluenceTasks.d.ts.map +1 -0
- package/dist/server/domain/deliveryGraph.d.ts +2 -0
- package/dist/server/domain/deliveryGraph.d.ts.map +1 -1
- package/dist/server/domain/governedAction/bindings.d.ts +2 -0
- package/dist/server/domain/governedAction/bindings.d.ts.map +1 -1
- package/dist/server/domain/governedAction/model.d.ts +6 -0
- package/dist/server/domain/governedAction/model.d.ts.map +1 -1
- package/dist/server/domain/index.js +2 -2
- package/dist/server/domain/normalizedPage.d.ts +1 -0
- package/dist/server/domain/normalizedPage.d.ts.map +1 -1
- package/dist/server/domain/releasePipelineApproval.d.ts +31 -0
- package/dist/server/domain/releasePipelineApproval.d.ts.map +1 -0
- package/dist/server/index.js +5 -5
- package/dist/server/server/api/Handlers.d.ts +1 -1
- package/dist/server/server/api/Handlers.d.ts.map +1 -1
- package/dist/server/server/application/deliveryGraphInspection.d.ts.map +1 -1
- package/dist/server/server/application/normalizedPluginPageMaterialization.d.ts.map +1 -1
- package/dist/server/server/application/pipelineExecutionProjection.d.ts +1 -0
- package/dist/server/server/application/pipelineExecutionProjection.d.ts.map +1 -1
- package/dist/server/server/application/portfolioSnapshots.d.ts +4 -0
- package/dist/server/server/application/portfolioSnapshots.d.ts.map +1 -1
- package/dist/server/server/application/releasePublicationSubmissions.d.ts +32 -1
- package/dist/server/server/application/releasePublicationSubmissions.d.ts.map +1 -1
- package/dist/server/server/application/releaseRunbookHydration.d.ts +2310 -0
- package/dist/server/server/application/releaseRunbookHydration.d.ts.map +1 -0
- package/dist/server/server/cli.js +3 -3
- package/dist/server/server/governance/governedActionDigests.d.ts +3 -0
- package/dist/server/server/governance/governedActionDigests.d.ts.map +1 -1
- package/dist/server/server/governance/internal/execution-store/recovery-claim.d.ts +1 -0
- package/dist/server/server/governance/internal/execution-store/recovery-claim.d.ts.map +1 -1
- package/dist/server/server/index.js +2 -2
- package/dist/server/server/persistence/Persistence.d.ts +10 -0
- package/dist/server/server/persistence/Persistence.d.ts.map +1 -1
- package/dist/server/server/persistence/object-store/BlobPublisher.d.ts.map +1 -1
- package/dist/server/server/persistence/object-store/PinnedDirectory.d.ts +2 -2
- package/dist/server/server/persistence/object-store/PinnedDirectory.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/delivery-graph/contract.d.ts +10 -0
- package/dist/server/server/persistence/repositories/delivery-graph/contract.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/delivery-graph/decode.d.ts +2 -0
- package/dist/server/server/persistence/repositories/delivery-graph/decode.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/delivery-graph/read.d.ts +6 -0
- package/dist/server/server/persistence/repositories/delivery-graph/read.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/delivery-graph/rows.d.ts +1 -0
- package/dist/server/server/persistence/repositories/delivery-graph/rows.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/delivery-graph/write.d.ts +2 -0
- package/dist/server/server/persistence/repositories/delivery-graph/write.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/deliveryGraphRepository.d.ts +6 -0
- package/dist/server/server/persistence/repositories/deliveryGraphRepository.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/governed-action/codec.d.ts +4 -0
- package/dist/server/server/persistence/repositories/governed-action/codec.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/governed-action/contract.d.ts +2 -0
- package/dist/server/server/persistence/repositories/governed-action/contract.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/governed-action/read.d.ts +4 -0
- package/dist/server/server/persistence/repositories/governed-action/read.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/governed-action/transaction.d.ts +4 -0
- package/dist/server/server/persistence/repositories/governed-action/transaction.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/governed-action/write-preparation.d.ts +1 -0
- package/dist/server/server/persistence/repositories/governed-action/write-preparation.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/governed-action/write-replay.d.ts +2 -0
- package/dist/server/server/persistence/repositories/governed-action/write-replay.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/governed-action/write.d.ts +2 -0
- package/dist/server/server/persistence/repositories/governed-action/write.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/governedActionRepository.d.ts +4 -0
- package/dist/server/server/persistence/repositories/governedActionRepository.d.ts.map +1 -1
- package/package.json +3 -3
- package/dist/client/assets/AgentPage-C3LThgPZ.js +0 -3
- package/dist/client/assets/AgentPage-C3LThgPZ.js.map +0 -1
- package/dist/client/assets/AgentPage-DVSgQgJa.css +0 -1
- package/dist/client/assets/AtlassianOAuthCallbackPage-BPoF6oKf.js +0 -2
- package/dist/client/assets/BrowserCrypto-BMbjhcvP.js +0 -2
- package/dist/client/assets/BrowserSessionHydrator-BC1ymLkL.js +0 -2
- package/dist/client/assets/PortfolioOverview-CEI4gpXi.js +0 -2
- package/dist/client/assets/ReleaseWorkset-BluAe7Sq.js +0 -2
- package/dist/client/assets/ReleaseWorkset-BluAe7Sq.js.map +0 -1
- package/dist/client/assets/ServicesPage-_B89DAvG.js +0 -2
- package/dist/client/assets/WorkspaceEntityRoute-9iMOV64J.css +0 -1
- package/dist/client/assets/WorkspaceEntityRoute-B01fxxB3.js +0 -3
- package/dist/client/assets/WorkspaceEntityRoute-B01fxxB3.js.map +0 -1
- package/dist/client/assets/WorkspaceHomeLink-CkJfzO25.js +0 -2
- package/dist/client/assets/WorkspacePullRequestDetails-HwDgp12e.js +0 -3
- package/dist/client/assets/WorkspaceRichText-D1M637Ff.js.map +0 -1
- package/dist/client/assets/WorkspaceSettingsPage-DyoGiGJG.js +0 -2
- package/dist/client/assets/WorkspaceSettingsPage-DyoGiGJG.js.map +0 -1
- package/dist/client/assets/WorkspaceSettingsPage-P6yfac0b.css +0 -1
- package/dist/client/assets/agent-api-CeONl_8w.js +0 -19
- package/dist/client/assets/agent-api-CeONl_8w.js.map +0 -1
- package/dist/client/assets/authenticatedMutationClient-DYaieXUe.js +0 -2
- package/dist/client/assets/client-DKS82kT_.js +0 -5
- package/dist/client/assets/client-DKS82kT_.js.map +0 -1
- package/dist/client/assets/connectionTestTransport-I_Ga9UNs.js +0 -2
- package/dist/client/assets/connectionTestTransport-I_Ga9UNs.js.map +0 -1
- package/dist/client/assets/releaseRoutes-t9uCfs5T.js +0 -2
- package/dist/client/assets/workspaceEntityRoutes-2TejMrzb.js +0 -2
- package/dist/client/assets/workspaceEntityRoutes-2TejMrzb.js.map +0 -1
- package/dist/server/assets/BindConfig-Bj282xDC.js.map +0 -1
- package/dist/server/assets/agent-ZvwskOQu.js.map +0 -1
- package/dist/server/assets/controlCenterApi-5j3gOXgE.js.map +0 -1
- package/dist/server/assets/manualPluginSynchronization-CzIhZ_Dw.js.map +0 -1
- package/dist/server/assets/relationshipInferenceMaterialization-CR6xyMNL.js.map +0 -1
- package/dist/server/assets/workspaceSettings-C2Zsk6RI.js.map +0 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{Ir as e,Rr as t}from"./agent-api-
|
|
2
|
-
//# sourceMappingURL=presentPortfolio-
|
|
1
|
+
import{Ir as e,Rr as t}from"./agent-api-Dl9TuGOJ.js";var n=[`Build`,`Verify`,`Production`],r={assembling:{label:`Assembling`,tone:`progress`},candidate:{label:`Candidate`,tone:`neutral`},deploying:{label:`Deploying`,tone:`progress`},released:{label:`Released`,tone:`positive`},cancelled:{label:`Cancelled`,tone:`caution`}},i={"release-owner":`Release owner`,"release-approver":`Release approver`},a={label:`Disabled`,message:`This source connection is disabled.`,tone:`neutral`,isUnhealthy:!0},o=e=>{switch(e){case`codecommit`:return`codecommit`;case`codepipeline`:return`codepipeline`;case`jira`:return`jira`;case`confluence`:return`confluence`;case`clockify`:return`clockify`}},s=e=>{if(e===null)return{label:`Not checked`,message:null,tone:`neutral`,isUnhealthy:!1};switch(e._tag){case`healthy`:return{label:`Healthy`,message:null,tone:`positive`,isUnhealthy:!1};case`degraded`:return{label:`Degraded`,message:e.safeMessage,tone:`caution`,isUnhealthy:!0};case`unavailable`:return{label:`Unavailable`,message:e.safeMessage,tone:`critical`,isUnhealthy:!0};case`disabled`:return a}},c=e=>{switch(e._tag){case`current`:return e.provenance._tag===`cache`?`cached`:`current`;case`stale`:return`stale`;case`missing`:return`missing`;case`unavailable`:return`unavailable`}},l=e=>e.provenance._tag===`none`?e.provenance.pluginConnectionId:e.provenance.sourceRevision.pluginConnectionId,u=e=>e.freshness.sourceObservedAt??e.freshness.synchronizedAt,d=e=>t(e,{day:`2-digit`,hour:`2-digit`,hour12:!1,locale:`en-GB`,minute:`2-digit`,month:`short`,timeZoneName:`short`}),f=(t,n)=>{let r=l(t.freshness),i=n.find(({pluginConnectionId:e})=>e===r),f=i===void 0?{label:`Unavailable`,message:`The source connection is missing from the current portfolio snapshot.`,tone:`critical`,isUnhealthy:!0}:i.isEnabled?s(i.health):a,p=c(t.freshness),m=u(t),h=t.freshness._tag===`stale`?f.message??`The source is not current. Preserved facts remain visible from the last successful sync.`:f.isUnhealthy?f.message??`The source needs attention. Saved release facts remain visible.`:null;return{displayName:i?.displayName??`Source connection unavailable`,freshness:p,freshnessDateTime:m===null?null:e(m),freshnessTime:m===null?null:d(m),healthLabel:f.label,healthTone:f.tone,service:i===void 0?null:o(i.providerId),warning:h}},p=e=>e.split(`-`).map(e=>`${e.charAt(0).toLocaleUpperCase(`en-US`)}${e.slice(1)}`).join(` `),m=e=>{if(e!==null)return e._tag===`count`?`${String(e.completed)} of ${String(e.total)} complete`:`${String(e.value)}% complete`},h=e=>{switch(e){case`failed`:return`critical`;case`held`:return`caution`;case`queued`:case`running`:return`progress`;case`succeeded`:return`positive`;case`not-started`:return`neutral`}},g=e=>{switch(e){case`failed`:return`critical`;case`held`:return`caution`;case`pending`:return`progress`;case`passed`:return`positive`;case`not-started`:return`neutral`}},_=e=>{switch(e){case`failed`:case`rolled-back`:return`critical`;case`held`:return`caution`;case`deploying`:case`waiting`:return`progress`;case`succeeded`:return`positive`;case`not-started`:return`neutral`}},v=()=>n.map(e=>({id:e.toLocaleLowerCase(`en-US`),name:e,reason:`No readiness evidence has been evaluated yet.`,state:`Not evaluated`,tone:`neutral`})),y=(e,t,n,r,i)=>{let a=m(i),o={id:e,name:t,state:p(n),tone:r};return a===void 0?o:{...o,reason:a}},b=e=>[y(`build`,`Build`,e.build.state,h(e.build.state),e.build.progress),y(`verify`,`Verify`,e.verify.state,g(e.verify.state),e.verify.progress),y(`production`,`Production`,e.production.state,_(e.production.state),e.production.progress)],x={blocked:{label:`Can't ship`,tone:`critical`},ready:{label:`Can ship`,tone:`positive`},deploying:{label:`Deploying`,tone:`progress`},building:{label:`Building`,tone:`progress`},shipped:{label:`Shipped`,tone:`positive`},held:{label:`Needs links`,tone:`caution`}},S=e=>{switch(e.code){case`input-incomplete`:return`Readiness inputs are incomplete.`;case`relationship-missing`:return`A required delivery link is missing.`;case`relationship-unverified`:return`A delivery link still needs verification.`;case`relationship-rejected`:return`A required delivery link was rejected.`;case`relationship-superseded`:return`A delivery link points to superseded work.`;case`approval-missing`:return`A required approval is missing.`;case`approval-pending`:return`A required approval is pending.`;case`approval-rejected`:return`A required approval was rejected.`;case`approval-expired`:return`A required approval expired.`;case`check-missing`:return`A required check is missing.`;case`check-pending`:return`Required checks are still running.`;case`check-failed`:return`A required check failed.`;case`check-cancelled`:return`A required check was cancelled.`;case`execution-missing`:return`A required pipeline run is missing.`;case`execution-pending`:return`A required pipeline is still running.`;case`execution-failed`:return`A required pipeline failed.`;case`execution-stopped`:return`A required pipeline was stopped.`;case`documentation-missing`:return`Required release documentation is missing.`;case`documentation-draft`:return`Release documentation is still a draft.`;case`documentation-stale`:return`Release documentation is stale.`;case`documentation-superseded`:return`Release documentation was superseded.`;case`deployment-missing`:return`Production deployment evidence is missing.`;case`deployment-failed`:return`Production deployment failed.`;case`deployment-rolled-back`:return`Production deployment was rolled back.`;case`source-stale`:return`A required source is stale.`;case`source-missing`:return`A required source is missing.`;case`source-unavailable`:return`A required source is unavailable.`;case`plugin-degraded`:return`A connected service is degraded.`;case`evidence-expired`:return`Required evidence has expired.`}},C=e=>{switch(e){case`blocked`:return`Required release evidence failed.`;case`ready`:return`All required evidence is verified.`;case`deploying`:return`Production rollout is in progress.`;case`building`:return`Build and verification are in progress.`;case`shipped`:return`Production deployment is verified.`;case`held`:return`Waiting for required delivery links.`}},w=(e,t)=>{let n=r[e.lifecycle],a=f(e,t),o=e.collaborators.map(({avatarFallback:e,displayName:t,personId:n,role:r})=>({avatarFallback:e,id:`${n}:${r}`,name:t,role:i[r]})),s=o.find(({role:e})=>e===i[`release-owner`]),c=o.find(({role:e})=>e===i[`release-approver`]),l=[{id:`service`,label:`Service`,value:e.serviceName},{id:`issues`,label:`Jira`,value:String(e.relationships.issues)},{id:`pull-requests`,label:`PRs`,value:String(e.relationships.pullRequests)},{id:`pipelines`,label:`Pipelines`,value:String(e.relationships.pipelineExecutions)},{id:`gaps`,label:`Gaps`,value:String(e.readiness?.gapCount??0)}],u=e.readiness,d=u===null?`No readiness evidence has been evaluated yet.`:u.authority===`pending`?`Evidence changed. Rechecking this release.`:u.primaryFinding===null?C(u.verdict):S(u.primaryFinding),p=u===null?null:x[u.verdict];return{collaborators:o,collaboratorCount:e.collaboratorCount,facts:l,id:e.releaseId,releasePageAwareness:e.releasePageAwareness,lifecycleLabel:n.label,lifecycleTone:n.tone,readinessVerdict:u?.verdict??`unknown`,readinessReason:d,release:{algorithm:e.relay.algorithm,...c===void 0?{}:{approver:c},codename:e.relay.codename,facts:l,freshness:a.freshness,...a.freshnessDateTime===null||a.freshnessTime===null?{}:{freshnessDateTime:a.freshnessDateTime,freshnessTime:a.freshnessTime},id:e.releaseId,...s===void 0?{}:{owner:s},reason:d,state:u?.verdict??`unknown`,symbolIndices:e.relay.symbolIndices,tone:p?.tone??`neutral`,verdict:p?.label??`Readiness not evaluated`,version:e.version},relay:{algorithm:e.relay.algorithm,codename:e.relay.codename,symbolIndices:e.relay.symbolIndices},serviceName:e.serviceName,source:a,stages:u===null?v():b(u.stages),targetEnvironmentIds:e.targetEnvironmentIds,version:e.version}},T=t=>({generatedAt:e(t.generatedAt),generatedTime:d(t.generatedAt),releases:t.releases.map(e=>w(e,t.plugins)),workspaceId:t.workspaceId});export{T as t};
|
|
2
|
+
//# sourceMappingURL=presentPortfolio-DLEq-vEz.js.map
|
package/dist/client/assets/{presentPortfolio-C_JsoSWg.js.map → presentPortfolio-DLEq-vEz.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presentPortfolio-C_JsoSWg.js","names":[],"sources":["../../../src/client/portfolio/presentPortfolio.ts"],"sourcesContent":["import type {\n RlyFreshnessState,\n RlyPerson,\n RlyReleasePresentation,\n RlyReleaseRelaySymbolIndices,\n RlyService,\n RlyStage\n} from \"@knpkv/rly/patterns\"\nimport type { RlyStateTone } from \"@knpkv/rly/primitives\"\nimport * as DateTime from \"effect/DateTime\"\n\nimport type { PortfolioReleaseRole, PortfolioSnapshot } from \"../../api/portfolio.js\"\nimport type { PluginHealth } from \"../../domain/freshness.js\"\nimport type {\n ReadinessFinding,\n ReadinessProgress,\n ReadinessStages,\n ReadinessVerdict\n} from \"../../domain/readiness/model.js\"\nimport type { ReleaseLifecycle } from \"../../domain/release.js\"\n\nconst READINESS_STAGES: ReadonlyArray<string> = [\"Build\", \"Verify\", \"Production\"]\n\nconst lifecyclePresentation: Readonly<\n Record<ReleaseLifecycle, { readonly label: string; readonly tone: RlyStateTone }>\n> = {\n assembling: { label: \"Assembling\", tone: \"progress\" },\n candidate: { label: \"Candidate\", tone: \"neutral\" },\n deploying: { label: \"Deploying\", tone: \"progress\" },\n released: { label: \"Released\", tone: \"positive\" },\n cancelled: { label: \"Cancelled\", tone: \"caution\" }\n}\n\nconst releaseRoleLabels: Readonly<Record<PortfolioReleaseRole, string>> = {\n \"release-owner\": \"Release owner\",\n \"release-approver\": \"Release approver\"\n}\n\ninterface SourceHealthPresentation {\n readonly label: string\n readonly message: string | null\n readonly tone: RlyStateTone\n readonly isUnhealthy: boolean\n}\n\nconst DISABLED_SOURCE_HEALTH = {\n label: \"Disabled\",\n message: \"This source connection is disabled.\",\n tone: \"neutral\",\n isUnhealthy: true\n} satisfies SourceHealthPresentation\n\nexport interface PortfolioSourcePresentation {\n readonly displayName: string\n readonly freshness: RlyFreshnessState\n readonly freshnessDateTime: string | null\n readonly freshnessTime: string | null\n readonly healthLabel: string\n readonly healthTone: RlyStateTone\n readonly service: RlyService | null\n readonly warning: string | null\n}\n\nexport interface PortfolioReleasePresentation {\n readonly collaborators: ReadonlyArray<RlyPerson>\n readonly collaboratorCount: number\n readonly facts: ReadonlyArray<{ readonly id: string; readonly label: string; readonly value: string }>\n readonly id: PortfolioSnapshot[\"releases\"][number][\"releaseId\"]\n readonly releasePageAwareness: PortfolioSnapshot[\"releases\"][number][\"releasePageAwareness\"]\n readonly lifecycleLabel: string\n readonly lifecycleTone: RlyStateTone\n readonly readinessVerdict: ReadinessVerdict | \"unknown\"\n readonly readinessReason: string\n readonly release: RlyReleasePresentation\n readonly relay: {\n readonly algorithm: string\n readonly codename: string\n readonly symbolIndices: RlyReleaseRelaySymbolIndices\n }\n readonly serviceName: string\n readonly source: PortfolioSourcePresentation\n readonly stages: ReadonlyArray<RlyStage>\n readonly targetEnvironmentIds: PortfolioSnapshot[\"releases\"][number][\"targetEnvironmentIds\"]\n readonly version: PortfolioSnapshot[\"releases\"][number][\"version\"]\n}\n\nexport interface PortfolioPresentation {\n readonly generatedAt: string\n readonly generatedTime: string\n readonly releases: ReadonlyArray<PortfolioReleasePresentation>\n readonly workspaceId: PortfolioSnapshot[\"workspaceId\"]\n}\n\nconst serviceForProvider = (providerId: PortfolioSnapshot[\"plugins\"][number][\"providerId\"]): RlyService => {\n switch (providerId) {\n case \"codecommit\":\n return \"codecommit\"\n case \"codepipeline\":\n return \"codepipeline\"\n case \"jira\":\n return \"jira\"\n case \"confluence\":\n return \"confluence\"\n case \"clockify\":\n return \"clockify\"\n }\n}\n\nconst healthPresentation = (health: PluginHealth | null): SourceHealthPresentation => {\n if (health === null) {\n return { label: \"Not checked\", message: null, tone: \"neutral\", isUnhealthy: false }\n }\n switch (health._tag) {\n case \"healthy\":\n return { label: \"Healthy\", message: null, tone: \"positive\", isUnhealthy: false }\n case \"degraded\":\n return { label: \"Degraded\", message: health.safeMessage, tone: \"caution\", isUnhealthy: true }\n case \"unavailable\":\n return { label: \"Unavailable\", message: health.safeMessage, tone: \"critical\", isUnhealthy: true }\n case \"disabled\":\n return DISABLED_SOURCE_HEALTH\n }\n}\n\nconst freshnessState = (freshness: PortfolioSnapshot[\"releases\"][number][\"freshness\"]): RlyFreshnessState => {\n switch (freshness._tag) {\n case \"current\":\n return freshness.provenance._tag === \"cache\" ? \"cached\" : \"current\"\n case \"stale\":\n return \"stale\"\n case \"missing\":\n return \"missing\"\n case \"unavailable\":\n return \"unavailable\"\n }\n}\n\nconst sourceConnectionId = (\n freshness: PortfolioSnapshot[\"releases\"][number][\"freshness\"]\n): PortfolioSnapshot[\"plugins\"][number][\"pluginConnectionId\"] =>\n freshness.provenance._tag === \"none\"\n ? freshness.provenance.pluginConnectionId\n : freshness.provenance.sourceRevision.pluginConnectionId\n\nconst freshnessTimestamp = (\n release: PortfolioSnapshot[\"releases\"][number]\n): PortfolioSnapshot[\"releases\"][number][\"updatedAt\"] | null =>\n release.freshness.sourceObservedAt ?? release.freshness.synchronizedAt\n\nconst formattedTime = (timestamp: PortfolioSnapshot[\"generatedAt\"]): string =>\n DateTime.formatUtc(timestamp, {\n day: \"2-digit\",\n hour: \"2-digit\",\n hour12: false,\n locale: \"en-GB\",\n minute: \"2-digit\",\n month: \"short\",\n timeZoneName: \"short\"\n })\n\nconst sourcePresentation = (\n release: PortfolioSnapshot[\"releases\"][number],\n plugins: PortfolioSnapshot[\"plugins\"]\n): PortfolioSourcePresentation => {\n const connectionId = sourceConnectionId(release.freshness)\n const plugin = plugins.find(({ pluginConnectionId }) => pluginConnectionId === connectionId)\n const health = plugin === undefined\n ? {\n label: \"Unavailable\",\n message: \"The source connection is missing from the current portfolio snapshot.\",\n tone: \"critical\",\n isUnhealthy: true\n } satisfies SourceHealthPresentation\n : plugin.isEnabled\n ? healthPresentation(plugin.health)\n : DISABLED_SOURCE_HEALTH\n const freshness = freshnessState(release.freshness)\n const timestamp = freshnessTimestamp(release)\n const hasStaleFacts = release.freshness._tag === \"stale\"\n const warning = hasStaleFacts\n ? health.message ?? \"The source is not current. Preserved facts remain visible from the last successful sync.\"\n : health.isUnhealthy\n ? health.message ?? \"The source needs attention. Saved release facts remain visible.\"\n : null\n\n return {\n displayName: plugin?.displayName ?? \"Source connection unavailable\",\n freshness,\n freshnessDateTime: timestamp === null ? null : DateTime.formatIso(timestamp),\n freshnessTime: timestamp === null ? null : formattedTime(timestamp),\n healthLabel: health.label,\n healthTone: health.tone,\n service: plugin === undefined ? null : serviceForProvider(plugin.providerId),\n warning\n }\n}\n\nconst stageStateLabel = (state: string): string =>\n state.split(\"-\").map((part) => `${part.charAt(0).toLocaleUpperCase(\"en-US\")}${part.slice(1)}`).join(\" \")\n\nconst progressReason = (progress: ReadinessProgress | null): string | undefined => {\n if (progress === null) return undefined\n return progress._tag === \"count\"\n ? `${String(progress.completed)} of ${String(progress.total)} complete`\n : `${String(progress.value)}% complete`\n}\n\nconst buildTone = (state: ReadinessStages[\"build\"][\"state\"]): RlyStateTone => {\n switch (state) {\n case \"failed\":\n return \"critical\"\n case \"held\":\n return \"caution\"\n case \"queued\":\n case \"running\":\n return \"progress\"\n case \"succeeded\":\n return \"positive\"\n case \"not-started\":\n return \"neutral\"\n }\n}\n\nconst verifyTone = (state: ReadinessStages[\"verify\"][\"state\"]): RlyStateTone => {\n switch (state) {\n case \"failed\":\n return \"critical\"\n case \"held\":\n return \"caution\"\n case \"pending\":\n return \"progress\"\n case \"passed\":\n return \"positive\"\n case \"not-started\":\n return \"neutral\"\n }\n}\n\nconst productionTone = (state: ReadinessStages[\"production\"][\"state\"]): RlyStateTone => {\n switch (state) {\n case \"failed\":\n case \"rolled-back\":\n return \"critical\"\n case \"held\":\n return \"caution\"\n case \"deploying\":\n case \"waiting\":\n return \"progress\"\n case \"succeeded\":\n return \"positive\"\n case \"not-started\":\n return \"neutral\"\n }\n}\n\nconst unevaluatedStages = (): ReadonlyArray<RlyStage> =>\n READINESS_STAGES.map((name) => ({\n id: name.toLocaleLowerCase(\"en-US\"),\n name,\n reason: \"No readiness evidence has been evaluated yet.\",\n state: \"Not evaluated\",\n tone: \"neutral\"\n }))\n\nconst readinessStage = (\n id: string,\n name: string,\n state: string,\n tone: RlyStateTone,\n progress: ReadinessProgress | null\n): RlyStage => {\n const reason = progressReason(progress)\n const stage = { id, name, state: stageStateLabel(state), tone }\n return reason === undefined ? stage : { ...stage, reason }\n}\n\nconst readinessStages = (stages: ReadinessStages): ReadonlyArray<RlyStage> => [\n readinessStage(\"build\", \"Build\", stages.build.state, buildTone(stages.build.state), stages.build.progress),\n readinessStage(\"verify\", \"Verify\", stages.verify.state, verifyTone(stages.verify.state), stages.verify.progress),\n readinessStage(\n \"production\",\n \"Production\",\n stages.production.state,\n productionTone(stages.production.state),\n stages.production.progress\n )\n]\n\nconst verdictPresentation: Readonly<\n Record<ReadinessVerdict, { readonly label: string; readonly tone: RlyStateTone }>\n> = {\n blocked: { label: \"Can't ship\", tone: \"critical\" },\n ready: { label: \"Can ship\", tone: \"positive\" },\n deploying: { label: \"Deploying\", tone: \"progress\" },\n building: { label: \"Building\", tone: \"progress\" },\n shipped: { label: \"Shipped\", tone: \"positive\" },\n held: { label: \"Needs links\", tone: \"caution\" }\n}\n\nconst findingReason = (finding: ReadinessFinding): string => {\n switch (finding.code) {\n case \"input-incomplete\":\n return \"Readiness inputs are incomplete.\"\n case \"relationship-missing\":\n return \"A required delivery link is missing.\"\n case \"relationship-unverified\":\n return \"A delivery link still needs verification.\"\n case \"relationship-rejected\":\n return \"A required delivery link was rejected.\"\n case \"relationship-superseded\":\n return \"A delivery link points to superseded work.\"\n case \"approval-missing\":\n return \"A required approval is missing.\"\n case \"approval-pending\":\n return \"A required approval is pending.\"\n case \"approval-rejected\":\n return \"A required approval was rejected.\"\n case \"approval-expired\":\n return \"A required approval expired.\"\n case \"check-missing\":\n return \"A required check is missing.\"\n case \"check-pending\":\n return \"Required checks are still running.\"\n case \"check-failed\":\n return \"A required check failed.\"\n case \"check-cancelled\":\n return \"A required check was cancelled.\"\n case \"execution-missing\":\n return \"A required pipeline run is missing.\"\n case \"execution-pending\":\n return \"A required pipeline is still running.\"\n case \"execution-failed\":\n return \"A required pipeline failed.\"\n case \"execution-stopped\":\n return \"A required pipeline was stopped.\"\n case \"documentation-missing\":\n return \"Required release documentation is missing.\"\n case \"documentation-draft\":\n return \"Release documentation is still a draft.\"\n case \"documentation-stale\":\n return \"Release documentation is stale.\"\n case \"documentation-superseded\":\n return \"Release documentation was superseded.\"\n case \"deployment-missing\":\n return \"Production deployment evidence is missing.\"\n case \"deployment-failed\":\n return \"Production deployment failed.\"\n case \"deployment-rolled-back\":\n return \"Production deployment was rolled back.\"\n case \"source-stale\":\n return \"A required source is stale.\"\n case \"source-missing\":\n return \"A required source is missing.\"\n case \"source-unavailable\":\n return \"A required source is unavailable.\"\n case \"plugin-degraded\":\n return \"A connected service is degraded.\"\n case \"evidence-expired\":\n return \"Required evidence has expired.\"\n }\n}\n\nconst verdictReason = (verdict: ReadinessVerdict): string => {\n switch (verdict) {\n case \"blocked\":\n return \"Required release evidence failed.\"\n case \"ready\":\n return \"All required evidence is verified.\"\n case \"deploying\":\n return \"Production rollout is in progress.\"\n case \"building\":\n return \"Build and verification are in progress.\"\n case \"shipped\":\n return \"Production deployment is verified.\"\n case \"held\":\n return \"Waiting for required delivery links.\"\n }\n}\n\nconst releasePresentation = (\n release: PortfolioSnapshot[\"releases\"][number],\n plugins: PortfolioSnapshot[\"plugins\"]\n): PortfolioReleasePresentation => {\n const lifecycle = lifecyclePresentation[release.lifecycle]\n const source = sourcePresentation(release, plugins)\n const collaborators = release.collaborators.map(({ avatarFallback, displayName, personId, role }) => ({\n avatarFallback,\n id: `${personId}:${role}`,\n name: displayName,\n role: releaseRoleLabels[role]\n }))\n const owner = collaborators.find(({ role }) => role === releaseRoleLabels[\"release-owner\"])\n const approver = collaborators.find(({ role }) => role === releaseRoleLabels[\"release-approver\"])\n const facts = [\n { id: \"service\", label: \"Service\", value: release.serviceName },\n { id: \"issues\", label: \"Jira\", value: String(release.relationships.issues) },\n { id: \"pull-requests\", label: \"PRs\", value: String(release.relationships.pullRequests) },\n { id: \"pipelines\", label: \"Pipelines\", value: String(release.relationships.pipelineExecutions) },\n { id: \"gaps\", label: \"Gaps\", value: String(release.readiness?.gapCount ?? 0) }\n ]\n const readiness = release.readiness\n const readinessReason = readiness === null\n ? \"No readiness evidence has been evaluated yet.\"\n : readiness.authority === \"pending\"\n ? \"Evidence changed. Rechecking this release.\"\n : readiness.primaryFinding === null\n ? verdictReason(readiness.verdict)\n : findingReason(readiness.primaryFinding)\n const verdict = readiness === null ? null : verdictPresentation[readiness.verdict]\n return {\n collaborators,\n collaboratorCount: release.collaboratorCount,\n facts,\n id: release.releaseId,\n releasePageAwareness: release.releasePageAwareness,\n lifecycleLabel: lifecycle.label,\n lifecycleTone: lifecycle.tone,\n readinessVerdict: readiness?.verdict ?? \"unknown\",\n readinessReason,\n release: {\n algorithm: release.relay.algorithm,\n ...(approver === undefined ? {} : { approver }),\n codename: release.relay.codename,\n facts,\n freshness: source.freshness,\n ...(source.freshnessDateTime === null || source.freshnessTime === null\n ? {}\n : { freshnessDateTime: source.freshnessDateTime, freshnessTime: source.freshnessTime }),\n id: release.releaseId,\n ...(owner === undefined ? {} : { owner }),\n reason: readinessReason,\n state: readiness?.verdict ?? \"unknown\",\n symbolIndices: release.relay.symbolIndices,\n tone: verdict?.tone ?? \"neutral\",\n verdict: verdict?.label ?? \"Readiness not evaluated\",\n version: release.version\n },\n relay: {\n algorithm: release.relay.algorithm,\n codename: release.relay.codename,\n symbolIndices: release.relay.symbolIndices\n },\n serviceName: release.serviceName,\n source,\n stages: readiness === null ? unevaluatedStages() : readinessStages(readiness.stages),\n targetEnvironmentIds: release.targetEnvironmentIds,\n version: release.version\n }\n}\n\n/** Map one authoritative API snapshot into explicit rly component props without deriving readiness. */\nexport const presentPortfolio = (snapshot: PortfolioSnapshot): PortfolioPresentation => ({\n generatedAt: DateTime.formatIso(snapshot.generatedAt),\n generatedTime: formattedTime(snapshot.generatedAt),\n releases: snapshot.releases.map((release) => releasePresentation(release, snapshot.plugins)),\n workspaceId: snapshot.workspaceId\n})\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"presentPortfolio-DLEq-vEz.js","names":[],"sources":["../../../src/client/portfolio/presentPortfolio.ts"],"sourcesContent":["import type {\n RlyFreshnessState,\n RlyPerson,\n RlyReleasePresentation,\n RlyReleaseRelaySymbolIndices,\n RlyService,\n RlyStage\n} from \"@knpkv/rly/patterns\"\nimport type { RlyStateTone } from \"@knpkv/rly/primitives\"\nimport * as DateTime from \"effect/DateTime\"\n\nimport type { PortfolioReleaseRole, PortfolioSnapshot } from \"../../api/portfolio.js\"\nimport type { PluginHealth } from \"../../domain/freshness.js\"\nimport type {\n ReadinessFinding,\n ReadinessProgress,\n ReadinessStages,\n ReadinessVerdict\n} from \"../../domain/readiness/model.js\"\nimport type { ReleaseLifecycle } from \"../../domain/release.js\"\n\nconst READINESS_STAGES: ReadonlyArray<string> = [\"Build\", \"Verify\", \"Production\"]\n\nconst lifecyclePresentation: Readonly<\n Record<ReleaseLifecycle, { readonly label: string; readonly tone: RlyStateTone }>\n> = {\n assembling: { label: \"Assembling\", tone: \"progress\" },\n candidate: { label: \"Candidate\", tone: \"neutral\" },\n deploying: { label: \"Deploying\", tone: \"progress\" },\n released: { label: \"Released\", tone: \"positive\" },\n cancelled: { label: \"Cancelled\", tone: \"caution\" }\n}\n\nconst releaseRoleLabels: Readonly<Record<PortfolioReleaseRole, string>> = {\n \"release-owner\": \"Release owner\",\n \"release-approver\": \"Release approver\"\n}\n\ninterface SourceHealthPresentation {\n readonly label: string\n readonly message: string | null\n readonly tone: RlyStateTone\n readonly isUnhealthy: boolean\n}\n\nconst DISABLED_SOURCE_HEALTH = {\n label: \"Disabled\",\n message: \"This source connection is disabled.\",\n tone: \"neutral\",\n isUnhealthy: true\n} satisfies SourceHealthPresentation\n\nexport interface PortfolioSourcePresentation {\n readonly displayName: string\n readonly freshness: RlyFreshnessState\n readonly freshnessDateTime: string | null\n readonly freshnessTime: string | null\n readonly healthLabel: string\n readonly healthTone: RlyStateTone\n readonly service: RlyService | null\n readonly warning: string | null\n}\n\nexport interface PortfolioReleasePresentation {\n readonly collaborators: ReadonlyArray<RlyPerson>\n readonly collaboratorCount: number\n readonly facts: ReadonlyArray<{ readonly id: string; readonly label: string; readonly value: string }>\n readonly id: PortfolioSnapshot[\"releases\"][number][\"releaseId\"]\n readonly releasePageAwareness: PortfolioSnapshot[\"releases\"][number][\"releasePageAwareness\"]\n readonly lifecycleLabel: string\n readonly lifecycleTone: RlyStateTone\n readonly readinessVerdict: ReadinessVerdict | \"unknown\"\n readonly readinessReason: string\n readonly release: RlyReleasePresentation\n readonly relay: {\n readonly algorithm: string\n readonly codename: string\n readonly symbolIndices: RlyReleaseRelaySymbolIndices\n }\n readonly serviceName: string\n readonly source: PortfolioSourcePresentation\n readonly stages: ReadonlyArray<RlyStage>\n readonly targetEnvironmentIds: PortfolioSnapshot[\"releases\"][number][\"targetEnvironmentIds\"]\n readonly version: PortfolioSnapshot[\"releases\"][number][\"version\"]\n}\n\nexport interface PortfolioPresentation {\n readonly generatedAt: string\n readonly generatedTime: string\n readonly releases: ReadonlyArray<PortfolioReleasePresentation>\n readonly workspaceId: PortfolioSnapshot[\"workspaceId\"]\n}\n\nconst serviceForProvider = (providerId: PortfolioSnapshot[\"plugins\"][number][\"providerId\"]): RlyService => {\n switch (providerId) {\n case \"codecommit\":\n return \"codecommit\"\n case \"codepipeline\":\n return \"codepipeline\"\n case \"jira\":\n return \"jira\"\n case \"confluence\":\n return \"confluence\"\n case \"clockify\":\n return \"clockify\"\n }\n}\n\nconst healthPresentation = (health: PluginHealth | null): SourceHealthPresentation => {\n if (health === null) {\n return { label: \"Not checked\", message: null, tone: \"neutral\", isUnhealthy: false }\n }\n switch (health._tag) {\n case \"healthy\":\n return { label: \"Healthy\", message: null, tone: \"positive\", isUnhealthy: false }\n case \"degraded\":\n return { label: \"Degraded\", message: health.safeMessage, tone: \"caution\", isUnhealthy: true }\n case \"unavailable\":\n return { label: \"Unavailable\", message: health.safeMessage, tone: \"critical\", isUnhealthy: true }\n case \"disabled\":\n return DISABLED_SOURCE_HEALTH\n }\n}\n\nconst freshnessState = (freshness: PortfolioSnapshot[\"releases\"][number][\"freshness\"]): RlyFreshnessState => {\n switch (freshness._tag) {\n case \"current\":\n return freshness.provenance._tag === \"cache\" ? \"cached\" : \"current\"\n case \"stale\":\n return \"stale\"\n case \"missing\":\n return \"missing\"\n case \"unavailable\":\n return \"unavailable\"\n }\n}\n\nconst sourceConnectionId = (\n freshness: PortfolioSnapshot[\"releases\"][number][\"freshness\"]\n): PortfolioSnapshot[\"plugins\"][number][\"pluginConnectionId\"] =>\n freshness.provenance._tag === \"none\"\n ? freshness.provenance.pluginConnectionId\n : freshness.provenance.sourceRevision.pluginConnectionId\n\nconst freshnessTimestamp = (\n release: PortfolioSnapshot[\"releases\"][number]\n): PortfolioSnapshot[\"releases\"][number][\"updatedAt\"] | null =>\n release.freshness.sourceObservedAt ?? release.freshness.synchronizedAt\n\nconst formattedTime = (timestamp: PortfolioSnapshot[\"generatedAt\"]): string =>\n DateTime.formatUtc(timestamp, {\n day: \"2-digit\",\n hour: \"2-digit\",\n hour12: false,\n locale: \"en-GB\",\n minute: \"2-digit\",\n month: \"short\",\n timeZoneName: \"short\"\n })\n\nconst sourcePresentation = (\n release: PortfolioSnapshot[\"releases\"][number],\n plugins: PortfolioSnapshot[\"plugins\"]\n): PortfolioSourcePresentation => {\n const connectionId = sourceConnectionId(release.freshness)\n const plugin = plugins.find(({ pluginConnectionId }) => pluginConnectionId === connectionId)\n const health = plugin === undefined\n ? {\n label: \"Unavailable\",\n message: \"The source connection is missing from the current portfolio snapshot.\",\n tone: \"critical\",\n isUnhealthy: true\n } satisfies SourceHealthPresentation\n : plugin.isEnabled\n ? healthPresentation(plugin.health)\n : DISABLED_SOURCE_HEALTH\n const freshness = freshnessState(release.freshness)\n const timestamp = freshnessTimestamp(release)\n const hasStaleFacts = release.freshness._tag === \"stale\"\n const warning = hasStaleFacts\n ? health.message ?? \"The source is not current. Preserved facts remain visible from the last successful sync.\"\n : health.isUnhealthy\n ? health.message ?? \"The source needs attention. Saved release facts remain visible.\"\n : null\n\n return {\n displayName: plugin?.displayName ?? \"Source connection unavailable\",\n freshness,\n freshnessDateTime: timestamp === null ? null : DateTime.formatIso(timestamp),\n freshnessTime: timestamp === null ? null : formattedTime(timestamp),\n healthLabel: health.label,\n healthTone: health.tone,\n service: plugin === undefined ? null : serviceForProvider(plugin.providerId),\n warning\n }\n}\n\nconst stageStateLabel = (state: string): string =>\n state.split(\"-\").map((part) => `${part.charAt(0).toLocaleUpperCase(\"en-US\")}${part.slice(1)}`).join(\" \")\n\nconst progressReason = (progress: ReadinessProgress | null): string | undefined => {\n if (progress === null) return undefined\n return progress._tag === \"count\"\n ? `${String(progress.completed)} of ${String(progress.total)} complete`\n : `${String(progress.value)}% complete`\n}\n\nconst buildTone = (state: ReadinessStages[\"build\"][\"state\"]): RlyStateTone => {\n switch (state) {\n case \"failed\":\n return \"critical\"\n case \"held\":\n return \"caution\"\n case \"queued\":\n case \"running\":\n return \"progress\"\n case \"succeeded\":\n return \"positive\"\n case \"not-started\":\n return \"neutral\"\n }\n}\n\nconst verifyTone = (state: ReadinessStages[\"verify\"][\"state\"]): RlyStateTone => {\n switch (state) {\n case \"failed\":\n return \"critical\"\n case \"held\":\n return \"caution\"\n case \"pending\":\n return \"progress\"\n case \"passed\":\n return \"positive\"\n case \"not-started\":\n return \"neutral\"\n }\n}\n\nconst productionTone = (state: ReadinessStages[\"production\"][\"state\"]): RlyStateTone => {\n switch (state) {\n case \"failed\":\n case \"rolled-back\":\n return \"critical\"\n case \"held\":\n return \"caution\"\n case \"deploying\":\n case \"waiting\":\n return \"progress\"\n case \"succeeded\":\n return \"positive\"\n case \"not-started\":\n return \"neutral\"\n }\n}\n\nconst unevaluatedStages = (): ReadonlyArray<RlyStage> =>\n READINESS_STAGES.map((name) => ({\n id: name.toLocaleLowerCase(\"en-US\"),\n name,\n reason: \"No readiness evidence has been evaluated yet.\",\n state: \"Not evaluated\",\n tone: \"neutral\"\n }))\n\nconst readinessStage = (\n id: string,\n name: string,\n state: string,\n tone: RlyStateTone,\n progress: ReadinessProgress | null\n): RlyStage => {\n const reason = progressReason(progress)\n const stage = { id, name, state: stageStateLabel(state), tone }\n return reason === undefined ? stage : { ...stage, reason }\n}\n\nconst readinessStages = (stages: ReadinessStages): ReadonlyArray<RlyStage> => [\n readinessStage(\"build\", \"Build\", stages.build.state, buildTone(stages.build.state), stages.build.progress),\n readinessStage(\"verify\", \"Verify\", stages.verify.state, verifyTone(stages.verify.state), stages.verify.progress),\n readinessStage(\n \"production\",\n \"Production\",\n stages.production.state,\n productionTone(stages.production.state),\n stages.production.progress\n )\n]\n\nconst verdictPresentation: Readonly<\n Record<ReadinessVerdict, { readonly label: string; readonly tone: RlyStateTone }>\n> = {\n blocked: { label: \"Can't ship\", tone: \"critical\" },\n ready: { label: \"Can ship\", tone: \"positive\" },\n deploying: { label: \"Deploying\", tone: \"progress\" },\n building: { label: \"Building\", tone: \"progress\" },\n shipped: { label: \"Shipped\", tone: \"positive\" },\n held: { label: \"Needs links\", tone: \"caution\" }\n}\n\nconst findingReason = (finding: ReadinessFinding): string => {\n switch (finding.code) {\n case \"input-incomplete\":\n return \"Readiness inputs are incomplete.\"\n case \"relationship-missing\":\n return \"A required delivery link is missing.\"\n case \"relationship-unverified\":\n return \"A delivery link still needs verification.\"\n case \"relationship-rejected\":\n return \"A required delivery link was rejected.\"\n case \"relationship-superseded\":\n return \"A delivery link points to superseded work.\"\n case \"approval-missing\":\n return \"A required approval is missing.\"\n case \"approval-pending\":\n return \"A required approval is pending.\"\n case \"approval-rejected\":\n return \"A required approval was rejected.\"\n case \"approval-expired\":\n return \"A required approval expired.\"\n case \"check-missing\":\n return \"A required check is missing.\"\n case \"check-pending\":\n return \"Required checks are still running.\"\n case \"check-failed\":\n return \"A required check failed.\"\n case \"check-cancelled\":\n return \"A required check was cancelled.\"\n case \"execution-missing\":\n return \"A required pipeline run is missing.\"\n case \"execution-pending\":\n return \"A required pipeline is still running.\"\n case \"execution-failed\":\n return \"A required pipeline failed.\"\n case \"execution-stopped\":\n return \"A required pipeline was stopped.\"\n case \"documentation-missing\":\n return \"Required release documentation is missing.\"\n case \"documentation-draft\":\n return \"Release documentation is still a draft.\"\n case \"documentation-stale\":\n return \"Release documentation is stale.\"\n case \"documentation-superseded\":\n return \"Release documentation was superseded.\"\n case \"deployment-missing\":\n return \"Production deployment evidence is missing.\"\n case \"deployment-failed\":\n return \"Production deployment failed.\"\n case \"deployment-rolled-back\":\n return \"Production deployment was rolled back.\"\n case \"source-stale\":\n return \"A required source is stale.\"\n case \"source-missing\":\n return \"A required source is missing.\"\n case \"source-unavailable\":\n return \"A required source is unavailable.\"\n case \"plugin-degraded\":\n return \"A connected service is degraded.\"\n case \"evidence-expired\":\n return \"Required evidence has expired.\"\n }\n}\n\nconst verdictReason = (verdict: ReadinessVerdict): string => {\n switch (verdict) {\n case \"blocked\":\n return \"Required release evidence failed.\"\n case \"ready\":\n return \"All required evidence is verified.\"\n case \"deploying\":\n return \"Production rollout is in progress.\"\n case \"building\":\n return \"Build and verification are in progress.\"\n case \"shipped\":\n return \"Production deployment is verified.\"\n case \"held\":\n return \"Waiting for required delivery links.\"\n }\n}\n\nconst releasePresentation = (\n release: PortfolioSnapshot[\"releases\"][number],\n plugins: PortfolioSnapshot[\"plugins\"]\n): PortfolioReleasePresentation => {\n const lifecycle = lifecyclePresentation[release.lifecycle]\n const source = sourcePresentation(release, plugins)\n const collaborators = release.collaborators.map(({ avatarFallback, displayName, personId, role }) => ({\n avatarFallback,\n id: `${personId}:${role}`,\n name: displayName,\n role: releaseRoleLabels[role]\n }))\n const owner = collaborators.find(({ role }) => role === releaseRoleLabels[\"release-owner\"])\n const approver = collaborators.find(({ role }) => role === releaseRoleLabels[\"release-approver\"])\n const facts = [\n { id: \"service\", label: \"Service\", value: release.serviceName },\n { id: \"issues\", label: \"Jira\", value: String(release.relationships.issues) },\n { id: \"pull-requests\", label: \"PRs\", value: String(release.relationships.pullRequests) },\n { id: \"pipelines\", label: \"Pipelines\", value: String(release.relationships.pipelineExecutions) },\n { id: \"gaps\", label: \"Gaps\", value: String(release.readiness?.gapCount ?? 0) }\n ]\n const readiness = release.readiness\n const readinessReason = readiness === null\n ? \"No readiness evidence has been evaluated yet.\"\n : readiness.authority === \"pending\"\n ? \"Evidence changed. Rechecking this release.\"\n : readiness.primaryFinding === null\n ? verdictReason(readiness.verdict)\n : findingReason(readiness.primaryFinding)\n const verdict = readiness === null ? null : verdictPresentation[readiness.verdict]\n return {\n collaborators,\n collaboratorCount: release.collaboratorCount,\n facts,\n id: release.releaseId,\n releasePageAwareness: release.releasePageAwareness,\n lifecycleLabel: lifecycle.label,\n lifecycleTone: lifecycle.tone,\n readinessVerdict: readiness?.verdict ?? \"unknown\",\n readinessReason,\n release: {\n algorithm: release.relay.algorithm,\n ...(approver === undefined ? {} : { approver }),\n codename: release.relay.codename,\n facts,\n freshness: source.freshness,\n ...(source.freshnessDateTime === null || source.freshnessTime === null\n ? {}\n : { freshnessDateTime: source.freshnessDateTime, freshnessTime: source.freshnessTime }),\n id: release.releaseId,\n ...(owner === undefined ? {} : { owner }),\n reason: readinessReason,\n state: readiness?.verdict ?? \"unknown\",\n symbolIndices: release.relay.symbolIndices,\n tone: verdict?.tone ?? \"neutral\",\n verdict: verdict?.label ?? \"Readiness not evaluated\",\n version: release.version\n },\n relay: {\n algorithm: release.relay.algorithm,\n codename: release.relay.codename,\n symbolIndices: release.relay.symbolIndices\n },\n serviceName: release.serviceName,\n source,\n stages: readiness === null ? unevaluatedStages() : readinessStages(readiness.stages),\n targetEnvironmentIds: release.targetEnvironmentIds,\n version: release.version\n }\n}\n\n/** Map one authoritative API snapshot into explicit rly component props without deriving readiness. */\nexport const presentPortfolio = (snapshot: PortfolioSnapshot): PortfolioPresentation => ({\n generatedAt: DateTime.formatIso(snapshot.generatedAt),\n generatedTime: formattedTime(snapshot.generatedAt),\n releases: snapshot.releases.map((release) => releasePresentation(release, snapshot.plugins)),\n workspaceId: snapshot.workspaceId\n})\n"],"mappings":"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"}
|
package/dist/client/assets/{presentWorkspaceItems-DboAfwGc.js → presentWorkspaceItems-BOY3FbhO.js}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{Ir as e}from"./agent-api-
|
|
2
|
-
//# sourceMappingURL=presentWorkspaceItems-
|
|
1
|
+
import{Ir as e}from"./agent-api-Dl9TuGOJ.js";import{n as t}from"./workspaceEntityPaths-xAl2jRFm.js";var n=e=>{switch(e){case`change-owner`:case`issue-owner`:case`page-owner`:return`Owner`;case`issue-assignee`:return`Assignee`;case`author`:return`Author`;case`operator`:return`Operator`;default:return i(e)}},r=e=>{switch(e){case`issue`:return`jira`;case`pull-request`:return`codecommit`;case`page`:return`confluence`;case`pipeline-execution`:case`deployment`:return`codepipeline`;case`time-entry`:return`clockify`}},i=e=>e.split(`-`).map(e=>`${e.charAt(0).toLocaleUpperCase(`en-US`)}${e.slice(1)}`).join(` `),a=e=>{switch(e._tag){case`issue`:return e.status;case`pull-request`:switch(e.reviewState){case`changes-requested`:return`Changes requested`;case`approved`:return`Approved`;case`merged`:return`Merged`;case`not-requested`:case`requested`:return e.lifecycle!==null&&e.lifecycle!==void 0?i(e.lifecycle):e.reviewState===`requested`?`Review requested`:`Review not requested`}case`page`:case`pipeline-execution`:case`deployment`:return i(e.status);case`time-entry`:return i(e.approvalState)}},o=e=>{let t=e.trim().toLocaleLowerCase(`en-US`);return t===`blocked`||t===`rejected`?{statusGroup:`failed`,tone:`critical`}:t===`closed`||t===`done`||t===`resolved`?{statusGroup:`done`,tone:`positive`}:{statusGroup:`active`,tone:`progress`}},s=(e,t)=>{if(e===`issue`)return o(t);let n=t.toLocaleLowerCase(`en-US`);return[`blocked`,`changes requested`,`failed`,`rejected`,`rolled back`,`stopped`,`superseded`].some(e=>n.includes(e))?{statusGroup:`failed`,tone:`critical`}:[`approved`,`closed`,`current`,`done`,`merged`,`not required`,`ready`,`resolved`,`succeeded`].some(e=>n.includes(e))?{statusGroup:`done`,tone:`positive`}:{statusGroup:`active`,tone:`progress`}},c=(e,t,n)=>`/w/${e}/releases/${t}?object=${encodeURIComponent(n)}#release-work`,l=(i,o,c)=>{let l=o.projection,u=a(l.details),d=o.releaseIds.filter(e=>c===void 0||c.has(e)),f=o.releaseIds.length===1&&!o.releaseMembershipsTruncated?d[0]??null:null,p=(o.owners??[]).map(({avatarFallback:e,displayName:t,personId:r,roles:i})=>({avatarFallback:e,id:r,name:t,role:[...new Set(i.map(n))].join(` · `),roles:i}));return{entityId:l.entityId,freshness:e(o.recordedAt),href:t(i,l.entityId),key:l.displayKey,kind:l.entityType,owner:p.length===0?`Unassigned`:p.map(({name:e})=>e).join(`, `),owners:p,ownersTruncated:o.ownersTruncated??!1,releaseId:f,releaseIds:o.releaseIds,releaseMembershipsTruncated:o.releaseMembershipsTruncated,routableReleaseIds:d,service:r(l.entityType),status:u,...s(l.entityType,u),title:l.title}},u=(e,t,n)=>t.items.filter(({projection:e})=>e.entityState===`present`).map(t=>l(e,t,n)).sort((e,t)=>e.service.localeCompare(t.service)||e.key.localeCompare(t.key));export{c as a,s as i,r as n,a as r,u as t};
|
|
2
|
+
//# sourceMappingURL=presentWorkspaceItems-BOY3FbhO.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presentWorkspaceItems-DboAfwGc.js","names":[],"sources":["../../../src/client/items/presentWorkspaceItems.ts"],"sourcesContent":["import type { RlyService } from \"@knpkv/rly/patterns\"\nimport type { RlyStateTone } from \"@knpkv/rly/primitives\"\nimport * as DateTime from \"effect/DateTime\"\n\nimport type {\n ReleaseDeliveryGraphInspection,\n WorkspaceEntityOwner,\n WorkspaceEntityProjectionIndex\n} from \"../../api/deliveryGraph.js\"\nimport type { Role } from \"../../domain/actors.js\"\nimport type {\n DeliveryEntityDetails,\n DeliveryEntityKind,\n DeliveryEntityStatusGroup\n} from \"../../domain/deliveryGraph.js\"\nimport type { EntityId, ReleaseId, WorkspaceId } from \"../../domain/identifiers.js\"\nimport { workspaceEntityPath } from \"../workspaceEntityPaths.js\"\n\nexport type WorkspaceItemStatus = DeliveryEntityStatusGroup\n\nexport interface WorkspaceItemPresentation {\n readonly entityId: EntityId\n readonly freshness: string\n readonly href: string\n readonly key: string\n readonly kind: DeliveryEntityKind\n readonly owner: string\n readonly owners: ReadonlyArray<WorkspaceItemOwnerPresentation>\n readonly ownersTruncated: boolean\n readonly releaseId: ReleaseId | null\n readonly releaseIds: ReadonlyArray<ReleaseId>\n readonly releaseMembershipsTruncated: boolean\n readonly routableReleaseIds: ReadonlyArray<ReleaseId>\n readonly service: RlyService\n readonly status: string\n readonly statusGroup: WorkspaceItemStatus\n readonly title: string\n readonly tone: RlyStateTone\n}\n\nexport interface WorkspaceItemOwnerPresentation {\n readonly avatarFallback: string\n readonly id: string\n readonly name: string\n readonly role: string\n readonly roles: ReadonlyArray<Role>\n}\n\nconst collaboratorRoleLabel = (role: Role): string => {\n switch (role) {\n case \"change-owner\":\n case \"issue-owner\":\n case \"page-owner\":\n return \"Owner\"\n case \"issue-assignee\":\n return \"Assignee\"\n case \"author\":\n return \"Author\"\n case \"operator\":\n return \"Operator\"\n default:\n return titleCase(role)\n }\n}\n\nexport const serviceFor = (kind: DeliveryEntityKind): RlyService => {\n switch (kind) {\n case \"issue\":\n return \"jira\"\n case \"pull-request\":\n return \"codecommit\"\n case \"page\":\n return \"confluence\"\n case \"pipeline-execution\":\n case \"deployment\":\n return \"codepipeline\"\n case \"time-entry\":\n return \"clockify\"\n }\n}\n\nconst titleCase = (value: string): string =>\n value.split(\"-\").map((part) => `${part.charAt(0).toLocaleUpperCase(\"en-US\")}${part.slice(1)}`).join(\" \")\n\nexport const statusFor = (details: DeliveryEntityDetails): string => {\n switch (details._tag) {\n case \"issue\":\n return details.status\n case \"pull-request\": {\n switch (details.reviewState) {\n case \"changes-requested\":\n return \"Changes requested\"\n case \"approved\":\n return \"Approved\"\n case \"merged\":\n return \"Merged\"\n case \"not-requested\":\n case \"requested\":\n if (details.lifecycle !== null && details.lifecycle !== undefined) return titleCase(details.lifecycle)\n return details.reviewState === \"requested\" ? \"Review requested\" : \"Review not requested\"\n }\n }\n case \"page\":\n case \"pipeline-execution\":\n case \"deployment\":\n return titleCase(details.status)\n case \"time-entry\":\n return titleCase(details.approvalState)\n }\n}\n\nconst issueStatusPresentation = (status: string): Pick<WorkspaceItemPresentation, \"statusGroup\" | \"tone\"> => {\n const value = status.trim().toLocaleLowerCase(\"en-US\")\n if (value === \"blocked\" || value === \"rejected\") return { statusGroup: \"failed\", tone: \"critical\" }\n if (value === \"closed\" || value === \"done\" || value === \"resolved\") {\n return { statusGroup: \"done\", tone: \"positive\" }\n }\n return { statusGroup: \"active\", tone: \"progress\" }\n}\n\nexport const statusPresentation = (\n kind: DeliveryEntityKind,\n status: string\n): Pick<WorkspaceItemPresentation, \"statusGroup\" | \"tone\"> => {\n if (kind === \"issue\") return issueStatusPresentation(status)\n const value = status.toLocaleLowerCase(\"en-US\")\n if (\n [\"blocked\", \"changes requested\", \"failed\", \"rejected\", \"rolled back\", \"stopped\", \"superseded\"].some((part) =>\n value.includes(part)\n )\n ) return { statusGroup: \"failed\", tone: \"critical\" }\n if (\n [\"approved\", \"closed\", \"current\", \"done\", \"merged\", \"not required\", \"ready\", \"resolved\", \"succeeded\"]\n .some((part) => value.includes(part))\n ) return { statusGroup: \"done\", tone: \"positive\" }\n return { statusGroup: \"active\", tone: \"progress\" }\n}\n\nexport const workspaceItemReleaseHref = (\n workspaceId: WorkspaceId,\n releaseId: ReleaseId,\n entityId: EntityId\n): string => `/w/${workspaceId}/releases/${releaseId}?object=${encodeURIComponent(entityId)}#release-work`\n\nconst presentProjection = (\n workspaceId: WorkspaceId,\n entry: ReleaseDeliveryGraphInspection[\"entityProjections\"][number] & {\n readonly canonicalReleaseId: ReleaseId | null\n readonly owners?: ReadonlyArray<WorkspaceEntityOwner>\n readonly ownersTruncated?: boolean\n readonly releaseIds: ReadonlyArray<ReleaseId>\n readonly releaseMembershipsTruncated: boolean\n },\n routableReleaseIds?: ReadonlySet<ReleaseId>\n): WorkspaceItemPresentation => {\n const projection = entry.projection\n const status = statusFor(projection.details)\n const routableMemberships = entry.releaseIds.filter(\n (releaseId) => routableReleaseIds === undefined || routableReleaseIds.has(releaseId)\n )\n const releaseId = entry.releaseIds.length === 1 && !entry.releaseMembershipsTruncated\n ? (routableMemberships[0] ?? null)\n : null\n const owners: ReadonlyArray<WorkspaceItemOwnerPresentation> = (entry.owners ?? []).map(({\n avatarFallback,\n displayName,\n personId,\n roles\n }) => ({\n avatarFallback,\n id: personId,\n name: displayName,\n role: [...new Set(roles.map(collaboratorRoleLabel))].join(\" · \"),\n roles\n }))\n return {\n entityId: projection.entityId,\n freshness: DateTime.formatIso(entry.recordedAt),\n href: workspaceEntityPath(workspaceId, projection.entityId),\n key: projection.displayKey,\n kind: projection.entityType,\n owner: owners.length === 0 ? \"Unassigned\" : owners.map(({ name }) => name).join(\", \"),\n owners,\n ownersTruncated: entry.ownersTruncated ?? false,\n releaseId,\n releaseIds: entry.releaseIds,\n releaseMembershipsTruncated: entry.releaseMembershipsTruncated,\n routableReleaseIds: routableMemberships,\n service: serviceFor(projection.entityType),\n status,\n ...statusPresentation(projection.entityType, status),\n title: projection.title\n }\n}\n\n/** Present one server-authoritative workspace entity index. */\nexport const presentWorkspaceEntityIndex = (\n workspaceId: WorkspaceId,\n index: WorkspaceEntityProjectionIndex,\n routableReleaseIds?: ReadonlySet<ReleaseId>\n): ReadonlyArray<WorkspaceItemPresentation> =>\n index.items\n .filter(({ projection }) => projection.entityState === \"present\")\n .map((entry) => presentProjection(workspaceId, entry, routableReleaseIds))\n .sort((left, right) => left.service.localeCompare(right.service) || left.key.localeCompare(right.key))\n\n/** Present bounded release slices as one deduplicated release-linked item index. */\nexport const presentWorkspaceItems = (\n workspaceId: WorkspaceId,\n inspections: ReadonlyArray<ReleaseDeliveryGraphInspection>\n): ReadonlyArray<WorkspaceItemPresentation> => {\n const items = new Map<EntityId, {\n readonly entry: ReleaseDeliveryGraphInspection[\"entityProjections\"][number]\n readonly releaseIds: Set<ReleaseId>\n }>()\n const canonicalInspections = [...inspections].sort((left, right) => left.releaseId.localeCompare(right.releaseId))\n for (const inspection of canonicalInspections) {\n for (const entry of inspection.entityProjections) {\n const projection = entry.projection\n if (projection.entityState !== \"present\") continue\n const existing = items.get(projection.entityId)\n if (existing !== undefined) {\n existing.releaseIds.add(inspection.releaseId)\n continue\n }\n items.set(projection.entityId, { entry, releaseIds: new Set([inspection.releaseId]) })\n }\n }\n return [...items.values()].map(({ entry, releaseIds: membershipSet }) => {\n const releaseIds = [...membershipSet].sort((left, right) => left.localeCompare(right))\n return presentProjection(workspaceId, {\n ...entry,\n canonicalReleaseId: releaseIds[0] ?? null,\n releaseIds,\n releaseMembershipsTruncated: false\n })\n }).sort((left, right) => left.service.localeCompare(right.service) || left.key.localeCompare(right.key))\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"presentWorkspaceItems-BOY3FbhO.js","names":[],"sources":["../../../src/client/items/presentWorkspaceItems.ts"],"sourcesContent":["import type { RlyService } from \"@knpkv/rly/patterns\"\nimport type { RlyStateTone } from \"@knpkv/rly/primitives\"\nimport * as DateTime from \"effect/DateTime\"\n\nimport type {\n ReleaseDeliveryGraphInspection,\n WorkspaceEntityOwner,\n WorkspaceEntityProjectionIndex\n} from \"../../api/deliveryGraph.js\"\nimport type { Role } from \"../../domain/actors.js\"\nimport type {\n DeliveryEntityDetails,\n DeliveryEntityKind,\n DeliveryEntityStatusGroup\n} from \"../../domain/deliveryGraph.js\"\nimport type { EntityId, ReleaseId, WorkspaceId } from \"../../domain/identifiers.js\"\nimport { workspaceEntityPath } from \"../workspaceEntityPaths.js\"\n\nexport type WorkspaceItemStatus = DeliveryEntityStatusGroup\n\nexport interface WorkspaceItemPresentation {\n readonly entityId: EntityId\n readonly freshness: string\n readonly href: string\n readonly key: string\n readonly kind: DeliveryEntityKind\n readonly owner: string\n readonly owners: ReadonlyArray<WorkspaceItemOwnerPresentation>\n readonly ownersTruncated: boolean\n readonly releaseId: ReleaseId | null\n readonly releaseIds: ReadonlyArray<ReleaseId>\n readonly releaseMembershipsTruncated: boolean\n readonly routableReleaseIds: ReadonlyArray<ReleaseId>\n readonly service: RlyService\n readonly status: string\n readonly statusGroup: WorkspaceItemStatus\n readonly title: string\n readonly tone: RlyStateTone\n}\n\nexport interface WorkspaceItemOwnerPresentation {\n readonly avatarFallback: string\n readonly id: string\n readonly name: string\n readonly role: string\n readonly roles: ReadonlyArray<Role>\n}\n\nconst collaboratorRoleLabel = (role: Role): string => {\n switch (role) {\n case \"change-owner\":\n case \"issue-owner\":\n case \"page-owner\":\n return \"Owner\"\n case \"issue-assignee\":\n return \"Assignee\"\n case \"author\":\n return \"Author\"\n case \"operator\":\n return \"Operator\"\n default:\n return titleCase(role)\n }\n}\n\nexport const serviceFor = (kind: DeliveryEntityKind): RlyService => {\n switch (kind) {\n case \"issue\":\n return \"jira\"\n case \"pull-request\":\n return \"codecommit\"\n case \"page\":\n return \"confluence\"\n case \"pipeline-execution\":\n case \"deployment\":\n return \"codepipeline\"\n case \"time-entry\":\n return \"clockify\"\n }\n}\n\nconst titleCase = (value: string): string =>\n value.split(\"-\").map((part) => `${part.charAt(0).toLocaleUpperCase(\"en-US\")}${part.slice(1)}`).join(\" \")\n\nexport const statusFor = (details: DeliveryEntityDetails): string => {\n switch (details._tag) {\n case \"issue\":\n return details.status\n case \"pull-request\": {\n switch (details.reviewState) {\n case \"changes-requested\":\n return \"Changes requested\"\n case \"approved\":\n return \"Approved\"\n case \"merged\":\n return \"Merged\"\n case \"not-requested\":\n case \"requested\":\n if (details.lifecycle !== null && details.lifecycle !== undefined) return titleCase(details.lifecycle)\n return details.reviewState === \"requested\" ? \"Review requested\" : \"Review not requested\"\n }\n }\n case \"page\":\n case \"pipeline-execution\":\n case \"deployment\":\n return titleCase(details.status)\n case \"time-entry\":\n return titleCase(details.approvalState)\n }\n}\n\nconst issueStatusPresentation = (status: string): Pick<WorkspaceItemPresentation, \"statusGroup\" | \"tone\"> => {\n const value = status.trim().toLocaleLowerCase(\"en-US\")\n if (value === \"blocked\" || value === \"rejected\") return { statusGroup: \"failed\", tone: \"critical\" }\n if (value === \"closed\" || value === \"done\" || value === \"resolved\") {\n return { statusGroup: \"done\", tone: \"positive\" }\n }\n return { statusGroup: \"active\", tone: \"progress\" }\n}\n\nexport const statusPresentation = (\n kind: DeliveryEntityKind,\n status: string\n): Pick<WorkspaceItemPresentation, \"statusGroup\" | \"tone\"> => {\n if (kind === \"issue\") return issueStatusPresentation(status)\n const value = status.toLocaleLowerCase(\"en-US\")\n if (\n [\"blocked\", \"changes requested\", \"failed\", \"rejected\", \"rolled back\", \"stopped\", \"superseded\"].some((part) =>\n value.includes(part)\n )\n ) return { statusGroup: \"failed\", tone: \"critical\" }\n if (\n [\"approved\", \"closed\", \"current\", \"done\", \"merged\", \"not required\", \"ready\", \"resolved\", \"succeeded\"]\n .some((part) => value.includes(part))\n ) return { statusGroup: \"done\", tone: \"positive\" }\n return { statusGroup: \"active\", tone: \"progress\" }\n}\n\nexport const workspaceItemReleaseHref = (\n workspaceId: WorkspaceId,\n releaseId: ReleaseId,\n entityId: EntityId\n): string => `/w/${workspaceId}/releases/${releaseId}?object=${encodeURIComponent(entityId)}#release-work`\n\nconst presentProjection = (\n workspaceId: WorkspaceId,\n entry: ReleaseDeliveryGraphInspection[\"entityProjections\"][number] & {\n readonly canonicalReleaseId: ReleaseId | null\n readonly owners?: ReadonlyArray<WorkspaceEntityOwner>\n readonly ownersTruncated?: boolean\n readonly releaseIds: ReadonlyArray<ReleaseId>\n readonly releaseMembershipsTruncated: boolean\n },\n routableReleaseIds?: ReadonlySet<ReleaseId>\n): WorkspaceItemPresentation => {\n const projection = entry.projection\n const status = statusFor(projection.details)\n const routableMemberships = entry.releaseIds.filter(\n (releaseId) => routableReleaseIds === undefined || routableReleaseIds.has(releaseId)\n )\n const releaseId = entry.releaseIds.length === 1 && !entry.releaseMembershipsTruncated\n ? (routableMemberships[0] ?? null)\n : null\n const owners: ReadonlyArray<WorkspaceItemOwnerPresentation> = (entry.owners ?? []).map(({\n avatarFallback,\n displayName,\n personId,\n roles\n }) => ({\n avatarFallback,\n id: personId,\n name: displayName,\n role: [...new Set(roles.map(collaboratorRoleLabel))].join(\" · \"),\n roles\n }))\n return {\n entityId: projection.entityId,\n freshness: DateTime.formatIso(entry.recordedAt),\n href: workspaceEntityPath(workspaceId, projection.entityId),\n key: projection.displayKey,\n kind: projection.entityType,\n owner: owners.length === 0 ? \"Unassigned\" : owners.map(({ name }) => name).join(\", \"),\n owners,\n ownersTruncated: entry.ownersTruncated ?? false,\n releaseId,\n releaseIds: entry.releaseIds,\n releaseMembershipsTruncated: entry.releaseMembershipsTruncated,\n routableReleaseIds: routableMemberships,\n service: serviceFor(projection.entityType),\n status,\n ...statusPresentation(projection.entityType, status),\n title: projection.title\n }\n}\n\n/** Present one server-authoritative workspace entity index. */\nexport const presentWorkspaceEntityIndex = (\n workspaceId: WorkspaceId,\n index: WorkspaceEntityProjectionIndex,\n routableReleaseIds?: ReadonlySet<ReleaseId>\n): ReadonlyArray<WorkspaceItemPresentation> =>\n index.items\n .filter(({ projection }) => projection.entityState === \"present\")\n .map((entry) => presentProjection(workspaceId, entry, routableReleaseIds))\n .sort((left, right) => left.service.localeCompare(right.service) || left.key.localeCompare(right.key))\n\n/** Present bounded release slices as one deduplicated release-linked item index. */\nexport const presentWorkspaceItems = (\n workspaceId: WorkspaceId,\n inspections: ReadonlyArray<ReleaseDeliveryGraphInspection>\n): ReadonlyArray<WorkspaceItemPresentation> => {\n const items = new Map<EntityId, {\n readonly entry: ReleaseDeliveryGraphInspection[\"entityProjections\"][number]\n readonly releaseIds: Set<ReleaseId>\n }>()\n const canonicalInspections = [...inspections].sort((left, right) => left.releaseId.localeCompare(right.releaseId))\n for (const inspection of canonicalInspections) {\n for (const entry of inspection.entityProjections) {\n const projection = entry.projection\n if (projection.entityState !== \"present\") continue\n const existing = items.get(projection.entityId)\n if (existing !== undefined) {\n existing.releaseIds.add(inspection.releaseId)\n continue\n }\n items.set(projection.entityId, { entry, releaseIds: new Set([inspection.releaseId]) })\n }\n }\n return [...items.values()].map(({ entry, releaseIds: membershipSet }) => {\n const releaseIds = [...membershipSet].sort((left, right) => left.localeCompare(right))\n return presentProjection(workspaceId, {\n ...entry,\n canonicalReleaseId: releaseIds[0] ?? null,\n releaseIds,\n releaseMembershipsTruncated: false\n })\n }).sort((left, right) => left.service.localeCompare(right.service) || left.key.localeCompare(right.key))\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{Ft as e,
|
|
2
|
-
//# sourceMappingURL=pullRequestReviewFailures-
|
|
1
|
+
import{Ft as e,ja as t}from"./agent-api-Dl9TuGOJ.js";var n=n=>t(n,`RequestTimedOutApiError`)||t(n,`RateLimitedApiError`)||t(n,`ServiceUnavailableApiError`)||e(n)&&n.reason._tag===`TransportError`,r=e=>t(e,`UnauthorizedApiError`);export{r as n,n as t};
|
|
2
|
+
//# sourceMappingURL=pullRequestReviewFailures-CyjTVnSX.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pullRequestReviewFailures-
|
|
1
|
+
{"version":3,"file":"pullRequestReviewFailures-CyjTVnSX.js","names":[],"sources":["../../../src/client/entities/pullRequestReviewFailures.ts"],"sourcesContent":["import * as Predicate from \"effect/Predicate\"\nimport * as HttpClientError from \"effect/unstable/http/HttpClientError\"\n\n/** Whether a review snapshot read can be retried without operator intervention. */\nexport const isRecoverablePullRequestReviewFailure = (failure: unknown): boolean =>\n Predicate.isTagged(failure, \"RequestTimedOutApiError\") ||\n Predicate.isTagged(failure, \"RateLimitedApiError\") ||\n Predicate.isTagged(failure, \"ServiceUnavailableApiError\") ||\n (\n HttpClientError.isHttpClientError(failure) &&\n failure.reason._tag === \"TransportError\"\n )\n\n/** Whether an authenticated review request proves that the browser session expired. */\nexport const isUnauthorizedPullRequestReviewFailure = (failure: unknown): boolean =>\n Predicate.isTagged(failure, \"UnauthorizedApiError\")\n"],"mappings":"qDAIA,IAAa,EAAyC,GACpD,EAAmB,EAAS,yBAAyB,GACrD,EAAmB,EAAS,qBAAqB,GACjD,EAAmB,EAAS,4BAA4B,GAEtD,EAAkC,CAAO,GACzC,EAAQ,OAAO,OAAS,iBAIf,EAA0C,GACrD,EAAmB,EAAS,sBAAsB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
2
|
-
//# sourceMappingURL=pullRequestReviewThreadReplay-
|
|
1
|
+
import{Ca as e,_i as t,ai as n,gi as r,oi as i,pi as a,r as o,si as s}from"./agent-api-Dl9TuGOJ.js";import{a as c,t as l}from"./client-Dq_XQE_l.js";import{t as u}from"./authenticatedMutationClient-DdowMjyo.js";import{n as d,t as f}from"./pullRequestReviewFailures-CyjTVnSX.js";var p=128,m=256,h=e=>e.events[0]?.eventSequence??2**53-1,g=(t,n)=>{let r=new Map;for(let i of[...t.events,...n.events]){let t=r.get(i.eventSequence);if(t!==void 0&&!e(t,i))throw Error(`Pull-request review thread contained conflicting duplicate events`);r.set(i.eventSequence,i)}let i=[...r.values()].sort((e,t)=>e.eventSequence-t.eventSequence),a=h(t),s=h(n),c=a<s?t:s<a?n:t.historyLoaded?t:n,l=c.historyLoaded,u=l?i:i.slice(-256);return{events:u,hasEarlier:(a===s?t.historyLoaded&&n.historyLoaded?t.hasEarlier&&n.hasEarlier:t.historyLoaded?t.hasEarlier:n.historyLoaded?n.hasEarlier:t.hasEarlier||n.hasEarlier:c.hasEarlier)||u.length<i.length,historyLoaded:l,nextCursor:o.make(Math.max(t.nextCursor,n.nextCursor)),replayGeneration:Math.max(t.replayGeneration??0,n.replayGeneration??0)}},_=(e,t,n)=>{if(!n.aborted){let n=e.current?.replayGeneration??0,r=t.replayGeneration??n;if(r<n)return e.current??t;let{replacesRetainedWindow:i,...a}=t,o={...a,replayGeneration:r};if(t.replacesRetainedWindow===!0&&r===n&&e.current!==null&&t.nextCursor<e.current.nextCursor)return e.current;let s=e.current!==null&&t.replacesRetainedWindow===!0&&t.events.some(t=>e.current?.events.some(e=>e.eventSequence===t.eventSequence));e.current=e.current===null||r>n||t.replacesRetainedWindow===!0&&t.nextCursor>e.current.nextCursor&&!s?o:g(e.current,a)}return e.current??t},v={enqueue:(e,r,i,o)=>t(n(function*(){return yield*(yield*u).agent.enqueuePullRequestReview({params:{entityId:e},payload:{providerId:r.providerId,model:r.model,profile:`read-only`,reviewProfileId:r.reviewProfile.profileId,...i===void 0?{}:{prompt:i}}})}).pipe(a(c)),{signal:o}),targetSuggestion:(e,r,i,o)=>t(n(function*(){return yield*(yield*u).agent.targetReviewSuggestion({params:{entityId:e,jobId:r.jobId,suggestionId:r.suggestionId},payload:{providerId:i.providerId,model:i.model,profile:`read-only`,reviewProfileId:i.reviewProfile.profileId,intent:r.intent,expectedRevisionId:r.expectedRevisionId,expectedSequence:r.expectedSequence}})}).pipe(a(c)),{signal:o}),cancel:(e,r,i)=>t(n(function*(){return yield*(yield*u).agent.cancelPullRequestReview({params:{entityId:e,jobId:r},payload:{}})}).pipe(a(c)),{signal:i}),extendBudget:(e,r,i)=>t(n(function*(){return yield*(yield*u).agent.extendPullRequestReviewBudget({params:{entityId:e,jobId:r},payload:{}})}).pipe(a(c)),{signal:i}),load:(e,r)=>t(n(function*(){return yield*(yield*l()).agent.pullRequestReview({params:{entityId:e}})}).pipe(a(c)),{signal:r}),loadThread:(e,r,i,o=`after`)=>t(n(function*(){return yield*(yield*l()).agent.pullRequestReviewThread({params:{entityId:e},query:r===null?{}:o===`before`?{before:r}:{after:r}})}).pipe(a(c)),{signal:i}),previewPublication:(e,r,i,o,s)=>t(n(function*(){return yield*(yield*l()).agent.previewReviewSuggestionPublication({params:{entityId:e,jobId:r.jobId,suggestionId:r.suggestionId},query:{revisionId:r.revisionId,...o===void 0?{}:{operation:o},...s===void 0?{}:{commentId:s}}})}).pipe(a(c)),{signal:i}),providers:e=>t(n(function*(){return yield*(yield*l()).agent.providers()}).pipe(a(c)),{signal:e}),publishSuggestion:(e,r,i,o,s,l,d)=>t(n(function*(){return yield*(yield*u).agent.publishReviewSuggestion({params:{entityId:e},payload:{...r,finalContent:i,authorityBinding:o,...l===void 0?{}:{operation:l},...d===void 0?{}:{commentId:d}}})}).pipe(a(c)),{signal:s})},y=async(e,t,n,r=null)=>{let i=[],a=r;for(let r=0;r<128;r++){let r=await e.loadThread(t,a,n);for(let e of r.events)i.push(e);if(!r.hasMore)return{events:i,hasEarlier:r.hasEarlier,historyLoaded:!1,nextCursor:r.nextCursor};if(a!==null&&r.nextCursor<=a)throw Error(`Pull-request review thread cursor did not advance`);a=r.nextCursor}let o=await e.loadThread(t,null,n);if(o.hasMore||a!==null&&o.nextCursor<=a)throw Error(`Pull-request review thread tail fallback was not usable`);return{events:[...o.events],hasEarlier:!0,historyLoaded:!1,nextCursor:o.nextCursor,replacesRetainedWindow:!0}},b=async(e,t,n,r)=>{let i=await y(e,t,n,r?.nextCursor);if(i.replacesRetainedWindow===!0)return{...i,replayGeneration:(r?.replayGeneration??0)+1};let a=r===void 0?i.events:[...r.events,...i.events],o=r?.historyLoaded??!1,s=o?a:a.slice(-256);return{events:s,hasEarlier:(r?.hasEarlier??!1)||i.hasEarlier||s.length<a.length,historyLoaded:o,nextCursor:i.nextCursor,replayGeneration:r?.replayGeneration??i.replayGeneration??0,...r?.replacesRetainedWindow===!0?{replacesRetainedWindow:!0}:{}}},x=async(e,t,n,r)=>{let i=r.events[0]?.eventSequence;if(!r.hasEarlier||i===void 0)return r;let a=await e.loadThread(t,i,n,`before`);if(a.events.some((e,t,n)=>e.eventSequence>=i||t>0&&e.eventSequence<=n[t-1].eventSequence)||a.events.length>0&&a.nextCursor>=i||a.hasMore&&a.events.length===0)throw Error(`Pull-request review history cursor did not retreat`);return{events:[...a.events,...r.events],hasEarlier:a.hasMore,historyLoaded:!0,nextCursor:r.nextCursor,replayGeneration:r.replayGeneration??0}},S=(e,t)=>e.baseRevision===t.baseRevision&&e.entityId===t.entityId&&e.headRevision===t.headRevision&&e.sessionKey===t.sessionKey,C=(e,t,n,a,o,s,c,l)=>(async()=>{try{let r=await x(e,t.entityId,a,n);if(a.aborted||o.current===null||!S(o.current,t))return;let i=_(s,r,a);l(e=>e._tag===`ready`&&S(e,t)?{...e,historyAction:`idle`,thread:i}:e)}catch(e){if(a.aborted||o.current===null||!S(o.current,t))return;d(e)&&c(t.sessionKey),r(i(`Pull-request review history load failed`,e)),l(e=>e._tag===`ready`&&S(e,t)?{...e,historyAction:`failed`}:e)}})(),w=async(e,t,n,i,a,o)=>{let c=n?e.providers(i).then(e=>({catalog:e,needsRetry:!1}),e=>{if(i.aborted||!f(e))throw e;return r(s(`Pull-request review provider catalog load failed`,e)),{catalog:{providers:[]},needsRetry:!0}}):Promise.resolve({catalog:{providers:[]},needsRetry:!1}),[l,u,d]=await Promise.all([e.load(t,i),b(e,t,i,a),c]),p=l._tag===`completed`||l._tag===`failed`?await b(e,t,i,u):u;return{catalog:d.catalog,catalogNeedsRetry:d.needsRetry,review:l,thread:_(o,p,i)}},T=async(e,t,n,a,o)=>{try{return _(o,await b(e,t,n,a),n)}catch(e){throw n.aborted||r(i(`Pull-request review thread refresh failed`,e)),e}};export{m as MAXIMUM_RETAINED_REVIEW_THREAD_EVENTS,p as MAXIMUM_REVIEW_THREAD_PAGE_READS,b as continuePullRequestReviewThread,v as generatedClientPullRequestReviewTransport,_ as installNewestThread,y as loadCompletePullRequestReviewThread,x as loadEarlierPullRequestReviewThread,C as loadEarlierPullRequestReviewThreadIntoState,w as loadPullRequestReviewSnapshot,g as mergePullRequestReviewThreads,T as refreshPullRequestReviewThread};
|
|
2
|
+
//# sourceMappingURL=pullRequestReviewThreadReplay-CXHspFTr.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pullRequestReviewThreadReplay-Vy1k53qE.js","names":[],"sources":["../../../src/client/entities/pullRequestReviewThreadReplay.ts"],"sourcesContent":["/** Bounded browser replay for a durable pull-request review thread. @module */\nimport * as Effect from \"effect/Effect\"\nimport * as Equal from \"effect/Equal\"\nimport * as FetchHttpClient from \"effect/unstable/http/FetchHttpClient\"\nimport { ReleaseAgentThreadCursor } from \"../../api/agent.js\"\nimport type {\n AgentProviderCatalog,\n PullRequestReviewState,\n PullRequestReviewThreadEvent,\n PullRequestReviewThreadPage\n} from \"../../api/agent.js\"\nimport { makeControlCenterApiClient } from \"../../api/client.js\"\nimport type { EntityId } from \"../../domain/identifiers.js\"\nimport { makeAuthenticatedMutationClient } from \"../authenticatedMutationClient.js\"\nimport {\n isRecoverablePullRequestReviewFailure,\n isUnauthorizedPullRequestReviewFailure\n} from \"./pullRequestReviewFailures.js\"\nimport type {\n PullRequestReviewControllerState,\n PullRequestReviewScope,\n PullRequestReviewTransport\n} from \"./usePullRequestReview.js\"\n\nexport const MAXIMUM_REVIEW_THREAD_PAGE_READS = 128\nexport const MAXIMUM_RETAINED_REVIEW_THREAD_EVENTS = 256\n\ninterface PullRequestReviewThreadPageTransport {\n readonly loadThread: (\n entityId: EntityId,\n cursor: ReleaseAgentThreadCursor | null,\n signal: AbortSignal,\n direction?: \"after\" | \"before\"\n ) => Promise<PullRequestReviewThreadPage>\n}\n\nexport interface PullRequestReviewThread {\n readonly events: ReadonlyArray<PullRequestReviewThreadEvent>\n readonly hasEarlier: boolean\n readonly historyLoaded: boolean\n readonly nextCursor: ReleaseAgentThreadCursor\n /** Monotonic window identity used to reject reads started before a tail replacement. */\n readonly replayGeneration?: number\n /** Transient signal that a bounded tail must replace, rather than append to, an older window. */\n readonly replacesRetainedWindow?: true\n}\n\ninterface PullRequestReviewThreadRef {\n current: PullRequestReviewThread | null\n}\n\nconst earliestSequence = (thread: PullRequestReviewThread): number =>\n thread.events[0]?.eventSequence ?? Number.MAX_SAFE_INTEGER\n\n/** Merge concurrent live and backward reads without dropping either cursor direction. */\nexport const mergePullRequestReviewThreads = (\n left: PullRequestReviewThread,\n right: PullRequestReviewThread\n): PullRequestReviewThread => {\n const eventsBySequence = new Map<number, PullRequestReviewThreadEvent>()\n for (const event of [...left.events, ...right.events]) {\n const existing = eventsBySequence.get(event.eventSequence)\n if (existing !== undefined && !Equal.equals(existing, event)) {\n throw new Error(\"Pull-request review thread contained conflicting duplicate events\")\n }\n eventsBySequence.set(event.eventSequence, event)\n }\n const allEvents = [...eventsBySequence.values()].sort(\n (left, right) => left.eventSequence - right.eventSequence\n )\n const leftEarliestSequence = earliestSequence(left)\n const rightEarliestSequence = earliestSequence(right)\n const boundary = leftEarliestSequence < rightEarliestSequence\n ? left\n : rightEarliestSequence < leftEarliestSequence\n ? right\n : left.historyLoaded\n ? left\n : right\n const historyLoaded = boundary.historyLoaded\n const events = historyLoaded\n ? allEvents\n : allEvents.slice(-MAXIMUM_RETAINED_REVIEW_THREAD_EVENTS)\n const hasEarlierAtBoundary = leftEarliestSequence !== rightEarliestSequence\n ? boundary.hasEarlier\n : left.historyLoaded && right.historyLoaded\n ? left.hasEarlier && right.hasEarlier\n : left.historyLoaded\n ? left.hasEarlier\n : right.historyLoaded\n ? right.hasEarlier\n : left.hasEarlier || right.hasEarlier\n return {\n events,\n hasEarlier: hasEarlierAtBoundary || events.length < allEvents.length,\n historyLoaded,\n nextCursor: ReleaseAgentThreadCursor.make(\n Math.max(left.nextCursor, right.nextCursor)\n ),\n replayGeneration: Math.max(left.replayGeneration ?? 0, right.replayGeneration ?? 0)\n }\n}\n\nexport const installNewestThread = (\n target: PullRequestReviewThreadRef,\n candidate: PullRequestReviewThread,\n signal: AbortSignal\n): PullRequestReviewThread => {\n if (!signal.aborted) {\n const retainedGeneration = target.current?.replayGeneration ?? 0\n const candidateGeneration = candidate.replayGeneration ?? retainedGeneration\n if (candidateGeneration < retainedGeneration) return target.current ?? candidate\n const { replacesRetainedWindow: _replacesRetainedWindow, ...retainedCandidate } = candidate\n const versionedCandidate = { ...retainedCandidate, replayGeneration: candidateGeneration }\n if (\n candidate.replacesRetainedWindow === true &&\n candidateGeneration === retainedGeneration &&\n target.current !== null &&\n candidate.nextCursor < target.current.nextCursor\n ) return target.current\n const overlapsRetainedWindow = target.current !== null &&\n candidate.replacesRetainedWindow === true &&\n candidate.events.some((candidateEvent) =>\n target.current?.events.some(\n (retainedEvent) => retainedEvent.eventSequence === candidateEvent.eventSequence\n )\n )\n target.current = target.current === null ||\n candidateGeneration > retainedGeneration ||\n (\n candidate.replacesRetainedWindow === true &&\n candidate.nextCursor > target.current.nextCursor &&\n !overlapsRetainedWindow\n )\n ? versionedCandidate\n : mergePullRequestReviewThreads(target.current, retainedCandidate)\n }\n return target.current ?? candidate\n}\n\n/** Generated-client transport kept outside the default workspace-entity chunk. */\nexport const generatedClientPullRequestReviewTransport: PullRequestReviewTransport = {\n enqueue: (entityId, provider, prompt, signal) =>\n Effect.runPromise(\n Effect.gen(function*() {\n const client = yield* makeAuthenticatedMutationClient\n return yield* client.agent.enqueuePullRequestReview({\n params: { entityId },\n payload: {\n providerId: provider.providerId,\n model: provider.model,\n profile: \"read-only\",\n reviewProfileId: provider.reviewProfile.profileId,\n ...(prompt === undefined ? {} : { prompt })\n }\n })\n }).pipe(Effect.provide(FetchHttpClient.layer)),\n { signal }\n ),\n targetSuggestion: (entityId, target, provider, signal) =>\n Effect.runPromise(\n Effect.gen(function*() {\n const client = yield* makeAuthenticatedMutationClient\n return yield* client.agent.targetReviewSuggestion({\n params: {\n entityId,\n jobId: target.jobId,\n suggestionId: target.suggestionId\n },\n payload: {\n providerId: provider.providerId,\n model: provider.model,\n profile: \"read-only\",\n reviewProfileId: provider.reviewProfile.profileId,\n intent: target.intent,\n expectedRevisionId: target.expectedRevisionId,\n expectedSequence: target.expectedSequence\n }\n })\n }).pipe(Effect.provide(FetchHttpClient.layer)),\n { signal }\n ),\n cancel: (entityId, jobId, signal) =>\n Effect.runPromise(\n Effect.gen(function*() {\n const client = yield* makeAuthenticatedMutationClient\n return yield* client.agent.cancelPullRequestReview({\n params: { entityId, jobId },\n payload: {}\n })\n }).pipe(Effect.provide(FetchHttpClient.layer)),\n { signal }\n ),\n extendBudget: (entityId, jobId, signal) =>\n Effect.runPromise(\n Effect.gen(function*() {\n const client = yield* makeAuthenticatedMutationClient\n return yield* client.agent.extendPullRequestReviewBudget({\n params: { entityId, jobId },\n payload: {}\n })\n }).pipe(Effect.provide(FetchHttpClient.layer)),\n { signal }\n ),\n load: (entityId, signal) =>\n Effect.runPromise(\n Effect.gen(function*() {\n const client = yield* makeControlCenterApiClient()\n return yield* client.agent.pullRequestReview({ params: { entityId } })\n }).pipe(Effect.provide(FetchHttpClient.layer)),\n { signal }\n ),\n loadThread: (entityId, cursor, signal, direction = \"after\") =>\n Effect.runPromise(\n Effect.gen(function*() {\n const client = yield* makeControlCenterApiClient()\n return yield* client.agent.pullRequestReviewThread({\n params: { entityId },\n query: cursor === null\n ? {}\n : direction === \"before\"\n ? { before: cursor }\n : { after: cursor }\n })\n }).pipe(Effect.provide(FetchHttpClient.layer)),\n { signal }\n ),\n previewPublication: (entityId, selection, signal, operation, commentId) =>\n Effect.runPromise(\n Effect.gen(function*() {\n const client = yield* makeControlCenterApiClient()\n return yield* client.agent.previewReviewSuggestionPublication({\n params: {\n entityId,\n jobId: selection.jobId,\n suggestionId: selection.suggestionId\n },\n query: {\n revisionId: selection.revisionId,\n ...(operation === undefined ? {} : { operation }),\n ...(commentId === undefined ? {} : { commentId })\n }\n })\n }).pipe(Effect.provide(FetchHttpClient.layer)),\n { signal }\n ),\n providers: (signal) =>\n Effect.runPromise(\n Effect.gen(function*() {\n const client = yield* makeControlCenterApiClient()\n return yield* client.agent.providers()\n }).pipe(Effect.provide(FetchHttpClient.layer)),\n { signal }\n ),\n publishSuggestion: (entityId, selection, finalContent, authorityBinding, signal, operation, commentId) =>\n Effect.runPromise(\n Effect.gen(function*() {\n const client = yield* makeAuthenticatedMutationClient\n return yield* client.agent.publishReviewSuggestion({\n params: { entityId },\n payload: {\n ...selection,\n finalContent,\n authorityBinding,\n ...(operation === undefined ? {} : { operation }),\n ...(commentId === undefined ? {} : { commentId })\n }\n })\n }).pipe(Effect.provide(FetchHttpClient.layer)),\n { signal }\n )\n}\n\n/** Follow advancing cursors to the durable tail without allowing unbounded replay. */\nexport const loadCompletePullRequestReviewThread = async (\n transport: PullRequestReviewThreadPageTransport,\n entityId: EntityId,\n signal: AbortSignal,\n initialCursor: ReleaseAgentThreadCursor | null = null\n): Promise<PullRequestReviewThread> => {\n const events = new Array<PullRequestReviewThreadEvent>()\n let after = initialCursor\n for (let pageRead = 0; pageRead < MAXIMUM_REVIEW_THREAD_PAGE_READS; pageRead++) {\n const page = await transport.loadThread(entityId, after, signal)\n for (const event of page.events) events.push(event)\n if (!page.hasMore) {\n return {\n events,\n hasEarlier: page.hasEarlier,\n historyLoaded: false,\n nextCursor: page.nextCursor\n }\n }\n if (after !== null && page.nextCursor <= after) {\n throw new Error(\"Pull-request review thread cursor did not advance\")\n }\n after = page.nextCursor\n }\n const tail = await transport.loadThread(entityId, null, signal)\n if (tail.hasMore || (after !== null && tail.nextCursor <= after)) {\n throw new Error(\"Pull-request review thread tail fallback was not usable\")\n }\n return {\n events: [...tail.events],\n hasEarlier: true,\n historyLoaded: false,\n nextCursor: tail.nextCursor,\n replacesRetainedWindow: true\n }\n}\n\n/** Continue one previously loaded thread without replaying its durable prefix. */\nexport const continuePullRequestReviewThread = async (\n transport: PullRequestReviewThreadPageTransport,\n entityId: EntityId,\n signal: AbortSignal,\n previous?: PullRequestReviewThread\n): Promise<PullRequestReviewThread> => {\n const update = await loadCompletePullRequestReviewThread(\n transport,\n entityId,\n signal,\n previous?.nextCursor\n )\n if (update.replacesRetainedWindow === true) {\n return {\n ...update,\n replayGeneration: (previous?.replayGeneration ?? 0) + 1\n }\n }\n const events = previous === undefined\n ? update.events\n : [...previous.events, ...update.events]\n const historyLoaded = previous?.historyLoaded ?? false\n const retainedEvents = historyLoaded\n ? events\n : events.slice(-MAXIMUM_RETAINED_REVIEW_THREAD_EVENTS)\n return {\n events: retainedEvents,\n hasEarlier: (previous?.hasEarlier ?? false) ||\n update.hasEarlier ||\n retainedEvents.length < events.length,\n historyLoaded,\n nextCursor: update.nextCursor,\n replayGeneration: previous?.replayGeneration ?? update.replayGeneration ?? 0,\n ...(previous?.replacesRetainedWindow === true ? { replacesRetainedWindow: true } : {})\n }\n}\n\n/** Prepend one explicit bounded history page without disturbing live replay. */\nexport const loadEarlierPullRequestReviewThread = async (\n transport: PullRequestReviewThreadPageTransport,\n entityId: EntityId,\n signal: AbortSignal,\n previous: PullRequestReviewThread\n): Promise<PullRequestReviewThread> => {\n const before = previous.events[0]?.eventSequence\n if (!previous.hasEarlier || before === undefined) return previous\n const page = await transport.loadThread(entityId, before, signal, \"before\")\n const invalidEvent = page.events.some(\n (event, index, events) =>\n event.eventSequence >= before ||\n (index > 0 && event.eventSequence <= events[index - 1]!.eventSequence)\n )\n if (\n invalidEvent ||\n (page.events.length > 0 && page.nextCursor >= before) ||\n (page.hasMore && page.events.length === 0)\n ) {\n throw new Error(\"Pull-request review history cursor did not retreat\")\n }\n return {\n events: [...page.events, ...previous.events],\n hasEarlier: page.hasMore,\n historyLoaded: true,\n nextCursor: previous.nextCursor,\n replayGeneration: previous.replayGeneration ?? 0\n }\n}\n\ntype ReadyPullRequestReviewState = Extract<\n PullRequestReviewControllerState,\n { readonly _tag: \"ready\" }\n>\n\nconst sameReviewScope = (\n left: PullRequestReviewScope,\n right: PullRequestReviewScope\n): boolean =>\n left.baseRevision === right.baseRevision &&\n left.entityId === right.entityId &&\n left.headRevision === right.headRevision &&\n left.sessionKey === right.sessionKey\n\n/** Apply one dynamic history read without growing the default entity-route chunk. */\nexport const loadEarlierPullRequestReviewThreadIntoState = (\n transport: PullRequestReviewThreadPageTransport,\n current: ReadyPullRequestReviewState,\n currentThread: PullRequestReviewThread,\n signal: AbortSignal,\n latestScope: { current: PullRequestReviewScope | null },\n latestThread: PullRequestReviewThreadRef,\n onSessionExpired: (sessionKey: string) => void,\n setState: (\n update: (state: PullRequestReviewControllerState) => PullRequestReviewControllerState\n ) => void\n): Promise<void> => {\n const run = async (): Promise<void> => {\n try {\n const thread = await loadEarlierPullRequestReviewThread(\n transport,\n current.entityId,\n signal,\n currentThread\n )\n if (\n signal.aborted ||\n latestScope.current === null ||\n !sameReviewScope(latestScope.current, current)\n ) return\n const installed = installNewestThread(latestThread, thread, signal)\n setState((latest) =>\n latest._tag === \"ready\" && sameReviewScope(latest, current)\n ? { ...latest, historyAction: \"idle\", thread: installed }\n : latest\n )\n } catch (failure) {\n if (\n signal.aborted ||\n latestScope.current === null ||\n !sameReviewScope(latestScope.current, current)\n ) return\n if (isUnauthorizedPullRequestReviewFailure(failure)) {\n onSessionExpired(current.sessionKey)\n }\n Effect.runFork(Effect.logError(\"Pull-request review history load failed\", failure))\n setState((latest) =>\n latest._tag === \"ready\" && sameReviewScope(latest, current)\n ? { ...latest, historyAction: \"failed\" }\n : latest\n )\n }\n }\n return run()\n}\n\n/** Load one coherent review snapshot and close a pending-to-terminal tail race. */\nexport const loadPullRequestReviewSnapshot = async (\n transport: PullRequestReviewTransport,\n entityId: EntityId,\n canEnqueue: boolean,\n signal: AbortSignal,\n previous: PullRequestReviewThread | undefined,\n target: PullRequestReviewThreadRef\n): Promise<{\n readonly catalog: AgentProviderCatalog\n readonly catalogNeedsRetry: boolean\n readonly review: PullRequestReviewState\n readonly thread: PullRequestReviewThread\n}> => {\n const catalogPromise = canEnqueue\n ? transport.providers(signal).then(\n (catalog) => ({ catalog, needsRetry: false }),\n (failure: unknown) => {\n if (signal.aborted || !isRecoverablePullRequestReviewFailure(failure)) throw failure\n Effect.runFork(Effect.logWarning(\"Pull-request review provider catalog load failed\", failure))\n return {\n catalog: { providers: [] } satisfies AgentProviderCatalog,\n needsRetry: true\n }\n }\n )\n : Promise.resolve({\n catalog: { providers: [] } satisfies AgentProviderCatalog,\n needsRetry: false\n })\n const [review, initialThread, catalogResult] = await Promise.all([\n transport.load(entityId, signal),\n continuePullRequestReviewThread(transport, entityId, signal, previous),\n catalogPromise\n ])\n const thread = review._tag === \"completed\" || review._tag === \"failed\"\n ? await continuePullRequestReviewThread(transport, entityId, signal, initialThread)\n : initialThread\n return {\n catalog: catalogResult.catalog,\n catalogNeedsRetry: catalogResult.needsRetry,\n review,\n thread: installNewestThread(target, thread, signal)\n }\n}\n\n/** Continue a visible thread while retaining diagnostics for non-fatal refresh failures. */\nexport const refreshPullRequestReviewThread = async (\n transport: PullRequestReviewThreadPageTransport,\n entityId: EntityId,\n signal: AbortSignal,\n previous: PullRequestReviewThread | undefined,\n target: PullRequestReviewThreadRef\n): Promise<PullRequestReviewThread> => {\n try {\n const thread = await continuePullRequestReviewThread(transport, entityId, signal, previous)\n return installNewestThread(target, thread, signal)\n } catch (failure) {\n if (!signal.aborted) {\n Effect.runFork(Effect.logError(\"Pull-request review thread refresh failed\", failure))\n }\n throw failure\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pullRequestReviewThreadReplay-CXHspFTr.js","names":[],"sources":["../../../src/client/entities/pullRequestReviewThreadReplay.ts"],"sourcesContent":["/** Bounded browser replay for a durable pull-request review thread. @module */\nimport * as Effect from \"effect/Effect\"\nimport * as Equal from \"effect/Equal\"\nimport * as FetchHttpClient from \"effect/unstable/http/FetchHttpClient\"\nimport { ReleaseAgentThreadCursor } from \"../../api/agent.js\"\nimport type {\n AgentProviderCatalog,\n PullRequestReviewState,\n PullRequestReviewThreadEvent,\n PullRequestReviewThreadPage\n} from \"../../api/agent.js\"\nimport { makeControlCenterApiClient } from \"../../api/client.js\"\nimport type { EntityId } from \"../../domain/identifiers.js\"\nimport { makeAuthenticatedMutationClient } from \"../authenticatedMutationClient.js\"\nimport {\n isRecoverablePullRequestReviewFailure,\n isUnauthorizedPullRequestReviewFailure\n} from \"./pullRequestReviewFailures.js\"\nimport type {\n PullRequestReviewControllerState,\n PullRequestReviewScope,\n PullRequestReviewTransport\n} from \"./usePullRequestReview.js\"\n\nexport const MAXIMUM_REVIEW_THREAD_PAGE_READS = 128\nexport const MAXIMUM_RETAINED_REVIEW_THREAD_EVENTS = 256\n\ninterface PullRequestReviewThreadPageTransport {\n readonly loadThread: (\n entityId: EntityId,\n cursor: ReleaseAgentThreadCursor | null,\n signal: AbortSignal,\n direction?: \"after\" | \"before\"\n ) => Promise<PullRequestReviewThreadPage>\n}\n\nexport interface PullRequestReviewThread {\n readonly events: ReadonlyArray<PullRequestReviewThreadEvent>\n readonly hasEarlier: boolean\n readonly historyLoaded: boolean\n readonly nextCursor: ReleaseAgentThreadCursor\n /** Monotonic window identity used to reject reads started before a tail replacement. */\n readonly replayGeneration?: number\n /** Transient signal that a bounded tail must replace, rather than append to, an older window. */\n readonly replacesRetainedWindow?: true\n}\n\ninterface PullRequestReviewThreadRef {\n current: PullRequestReviewThread | null\n}\n\nconst earliestSequence = (thread: PullRequestReviewThread): number =>\n thread.events[0]?.eventSequence ?? Number.MAX_SAFE_INTEGER\n\n/** Merge concurrent live and backward reads without dropping either cursor direction. */\nexport const mergePullRequestReviewThreads = (\n left: PullRequestReviewThread,\n right: PullRequestReviewThread\n): PullRequestReviewThread => {\n const eventsBySequence = new Map<number, PullRequestReviewThreadEvent>()\n for (const event of [...left.events, ...right.events]) {\n const existing = eventsBySequence.get(event.eventSequence)\n if (existing !== undefined && !Equal.equals(existing, event)) {\n throw new Error(\"Pull-request review thread contained conflicting duplicate events\")\n }\n eventsBySequence.set(event.eventSequence, event)\n }\n const allEvents = [...eventsBySequence.values()].sort(\n (left, right) => left.eventSequence - right.eventSequence\n )\n const leftEarliestSequence = earliestSequence(left)\n const rightEarliestSequence = earliestSequence(right)\n const boundary = leftEarliestSequence < rightEarliestSequence\n ? left\n : rightEarliestSequence < leftEarliestSequence\n ? right\n : left.historyLoaded\n ? left\n : right\n const historyLoaded = boundary.historyLoaded\n const events = historyLoaded\n ? allEvents\n : allEvents.slice(-MAXIMUM_RETAINED_REVIEW_THREAD_EVENTS)\n const hasEarlierAtBoundary = leftEarliestSequence !== rightEarliestSequence\n ? boundary.hasEarlier\n : left.historyLoaded && right.historyLoaded\n ? left.hasEarlier && right.hasEarlier\n : left.historyLoaded\n ? left.hasEarlier\n : right.historyLoaded\n ? right.hasEarlier\n : left.hasEarlier || right.hasEarlier\n return {\n events,\n hasEarlier: hasEarlierAtBoundary || events.length < allEvents.length,\n historyLoaded,\n nextCursor: ReleaseAgentThreadCursor.make(\n Math.max(left.nextCursor, right.nextCursor)\n ),\n replayGeneration: Math.max(left.replayGeneration ?? 0, right.replayGeneration ?? 0)\n }\n}\n\nexport const installNewestThread = (\n target: PullRequestReviewThreadRef,\n candidate: PullRequestReviewThread,\n signal: AbortSignal\n): PullRequestReviewThread => {\n if (!signal.aborted) {\n const retainedGeneration = target.current?.replayGeneration ?? 0\n const candidateGeneration = candidate.replayGeneration ?? retainedGeneration\n if (candidateGeneration < retainedGeneration) return target.current ?? candidate\n const { replacesRetainedWindow: _replacesRetainedWindow, ...retainedCandidate } = candidate\n const versionedCandidate = { ...retainedCandidate, replayGeneration: candidateGeneration }\n if (\n candidate.replacesRetainedWindow === true &&\n candidateGeneration === retainedGeneration &&\n target.current !== null &&\n candidate.nextCursor < target.current.nextCursor\n ) return target.current\n const overlapsRetainedWindow = target.current !== null &&\n candidate.replacesRetainedWindow === true &&\n candidate.events.some((candidateEvent) =>\n target.current?.events.some(\n (retainedEvent) => retainedEvent.eventSequence === candidateEvent.eventSequence\n )\n )\n target.current = target.current === null ||\n candidateGeneration > retainedGeneration ||\n (\n candidate.replacesRetainedWindow === true &&\n candidate.nextCursor > target.current.nextCursor &&\n !overlapsRetainedWindow\n )\n ? versionedCandidate\n : mergePullRequestReviewThreads(target.current, retainedCandidate)\n }\n return target.current ?? candidate\n}\n\n/** Generated-client transport kept outside the default workspace-entity chunk. */\nexport const generatedClientPullRequestReviewTransport: PullRequestReviewTransport = {\n enqueue: (entityId, provider, prompt, signal) =>\n Effect.runPromise(\n Effect.gen(function*() {\n const client = yield* makeAuthenticatedMutationClient\n return yield* client.agent.enqueuePullRequestReview({\n params: { entityId },\n payload: {\n providerId: provider.providerId,\n model: provider.model,\n profile: \"read-only\",\n reviewProfileId: provider.reviewProfile.profileId,\n ...(prompt === undefined ? {} : { prompt })\n }\n })\n }).pipe(Effect.provide(FetchHttpClient.layer)),\n { signal }\n ),\n targetSuggestion: (entityId, target, provider, signal) =>\n Effect.runPromise(\n Effect.gen(function*() {\n const client = yield* makeAuthenticatedMutationClient\n return yield* client.agent.targetReviewSuggestion({\n params: {\n entityId,\n jobId: target.jobId,\n suggestionId: target.suggestionId\n },\n payload: {\n providerId: provider.providerId,\n model: provider.model,\n profile: \"read-only\",\n reviewProfileId: provider.reviewProfile.profileId,\n intent: target.intent,\n expectedRevisionId: target.expectedRevisionId,\n expectedSequence: target.expectedSequence\n }\n })\n }).pipe(Effect.provide(FetchHttpClient.layer)),\n { signal }\n ),\n cancel: (entityId, jobId, signal) =>\n Effect.runPromise(\n Effect.gen(function*() {\n const client = yield* makeAuthenticatedMutationClient\n return yield* client.agent.cancelPullRequestReview({\n params: { entityId, jobId },\n payload: {}\n })\n }).pipe(Effect.provide(FetchHttpClient.layer)),\n { signal }\n ),\n extendBudget: (entityId, jobId, signal) =>\n Effect.runPromise(\n Effect.gen(function*() {\n const client = yield* makeAuthenticatedMutationClient\n return yield* client.agent.extendPullRequestReviewBudget({\n params: { entityId, jobId },\n payload: {}\n })\n }).pipe(Effect.provide(FetchHttpClient.layer)),\n { signal }\n ),\n load: (entityId, signal) =>\n Effect.runPromise(\n Effect.gen(function*() {\n const client = yield* makeControlCenterApiClient()\n return yield* client.agent.pullRequestReview({ params: { entityId } })\n }).pipe(Effect.provide(FetchHttpClient.layer)),\n { signal }\n ),\n loadThread: (entityId, cursor, signal, direction = \"after\") =>\n Effect.runPromise(\n Effect.gen(function*() {\n const client = yield* makeControlCenterApiClient()\n return yield* client.agent.pullRequestReviewThread({\n params: { entityId },\n query: cursor === null\n ? {}\n : direction === \"before\"\n ? { before: cursor }\n : { after: cursor }\n })\n }).pipe(Effect.provide(FetchHttpClient.layer)),\n { signal }\n ),\n previewPublication: (entityId, selection, signal, operation, commentId) =>\n Effect.runPromise(\n Effect.gen(function*() {\n const client = yield* makeControlCenterApiClient()\n return yield* client.agent.previewReviewSuggestionPublication({\n params: {\n entityId,\n jobId: selection.jobId,\n suggestionId: selection.suggestionId\n },\n query: {\n revisionId: selection.revisionId,\n ...(operation === undefined ? {} : { operation }),\n ...(commentId === undefined ? {} : { commentId })\n }\n })\n }).pipe(Effect.provide(FetchHttpClient.layer)),\n { signal }\n ),\n providers: (signal) =>\n Effect.runPromise(\n Effect.gen(function*() {\n const client = yield* makeControlCenterApiClient()\n return yield* client.agent.providers()\n }).pipe(Effect.provide(FetchHttpClient.layer)),\n { signal }\n ),\n publishSuggestion: (entityId, selection, finalContent, authorityBinding, signal, operation, commentId) =>\n Effect.runPromise(\n Effect.gen(function*() {\n const client = yield* makeAuthenticatedMutationClient\n return yield* client.agent.publishReviewSuggestion({\n params: { entityId },\n payload: {\n ...selection,\n finalContent,\n authorityBinding,\n ...(operation === undefined ? {} : { operation }),\n ...(commentId === undefined ? {} : { commentId })\n }\n })\n }).pipe(Effect.provide(FetchHttpClient.layer)),\n { signal }\n )\n}\n\n/** Follow advancing cursors to the durable tail without allowing unbounded replay. */\nexport const loadCompletePullRequestReviewThread = async (\n transport: PullRequestReviewThreadPageTransport,\n entityId: EntityId,\n signal: AbortSignal,\n initialCursor: ReleaseAgentThreadCursor | null = null\n): Promise<PullRequestReviewThread> => {\n const events = new Array<PullRequestReviewThreadEvent>()\n let after = initialCursor\n for (let pageRead = 0; pageRead < MAXIMUM_REVIEW_THREAD_PAGE_READS; pageRead++) {\n const page = await transport.loadThread(entityId, after, signal)\n for (const event of page.events) events.push(event)\n if (!page.hasMore) {\n return {\n events,\n hasEarlier: page.hasEarlier,\n historyLoaded: false,\n nextCursor: page.nextCursor\n }\n }\n if (after !== null && page.nextCursor <= after) {\n throw new Error(\"Pull-request review thread cursor did not advance\")\n }\n after = page.nextCursor\n }\n const tail = await transport.loadThread(entityId, null, signal)\n if (tail.hasMore || (after !== null && tail.nextCursor <= after)) {\n throw new Error(\"Pull-request review thread tail fallback was not usable\")\n }\n return {\n events: [...tail.events],\n hasEarlier: true,\n historyLoaded: false,\n nextCursor: tail.nextCursor,\n replacesRetainedWindow: true\n }\n}\n\n/** Continue one previously loaded thread without replaying its durable prefix. */\nexport const continuePullRequestReviewThread = async (\n transport: PullRequestReviewThreadPageTransport,\n entityId: EntityId,\n signal: AbortSignal,\n previous?: PullRequestReviewThread\n): Promise<PullRequestReviewThread> => {\n const update = await loadCompletePullRequestReviewThread(\n transport,\n entityId,\n signal,\n previous?.nextCursor\n )\n if (update.replacesRetainedWindow === true) {\n return {\n ...update,\n replayGeneration: (previous?.replayGeneration ?? 0) + 1\n }\n }\n const events = previous === undefined\n ? update.events\n : [...previous.events, ...update.events]\n const historyLoaded = previous?.historyLoaded ?? false\n const retainedEvents = historyLoaded\n ? events\n : events.slice(-MAXIMUM_RETAINED_REVIEW_THREAD_EVENTS)\n return {\n events: retainedEvents,\n hasEarlier: (previous?.hasEarlier ?? false) ||\n update.hasEarlier ||\n retainedEvents.length < events.length,\n historyLoaded,\n nextCursor: update.nextCursor,\n replayGeneration: previous?.replayGeneration ?? update.replayGeneration ?? 0,\n ...(previous?.replacesRetainedWindow === true ? { replacesRetainedWindow: true } : {})\n }\n}\n\n/** Prepend one explicit bounded history page without disturbing live replay. */\nexport const loadEarlierPullRequestReviewThread = async (\n transport: PullRequestReviewThreadPageTransport,\n entityId: EntityId,\n signal: AbortSignal,\n previous: PullRequestReviewThread\n): Promise<PullRequestReviewThread> => {\n const before = previous.events[0]?.eventSequence\n if (!previous.hasEarlier || before === undefined) return previous\n const page = await transport.loadThread(entityId, before, signal, \"before\")\n const invalidEvent = page.events.some(\n (event, index, events) =>\n event.eventSequence >= before ||\n (index > 0 && event.eventSequence <= events[index - 1]!.eventSequence)\n )\n if (\n invalidEvent ||\n (page.events.length > 0 && page.nextCursor >= before) ||\n (page.hasMore && page.events.length === 0)\n ) {\n throw new Error(\"Pull-request review history cursor did not retreat\")\n }\n return {\n events: [...page.events, ...previous.events],\n hasEarlier: page.hasMore,\n historyLoaded: true,\n nextCursor: previous.nextCursor,\n replayGeneration: previous.replayGeneration ?? 0\n }\n}\n\ntype ReadyPullRequestReviewState = Extract<\n PullRequestReviewControllerState,\n { readonly _tag: \"ready\" }\n>\n\nconst sameReviewScope = (\n left: PullRequestReviewScope,\n right: PullRequestReviewScope\n): boolean =>\n left.baseRevision === right.baseRevision &&\n left.entityId === right.entityId &&\n left.headRevision === right.headRevision &&\n left.sessionKey === right.sessionKey\n\n/** Apply one dynamic history read without growing the default entity-route chunk. */\nexport const loadEarlierPullRequestReviewThreadIntoState = (\n transport: PullRequestReviewThreadPageTransport,\n current: ReadyPullRequestReviewState,\n currentThread: PullRequestReviewThread,\n signal: AbortSignal,\n latestScope: { current: PullRequestReviewScope | null },\n latestThread: PullRequestReviewThreadRef,\n onSessionExpired: (sessionKey: string) => void,\n setState: (\n update: (state: PullRequestReviewControllerState) => PullRequestReviewControllerState\n ) => void\n): Promise<void> => {\n const run = async (): Promise<void> => {\n try {\n const thread = await loadEarlierPullRequestReviewThread(\n transport,\n current.entityId,\n signal,\n currentThread\n )\n if (\n signal.aborted ||\n latestScope.current === null ||\n !sameReviewScope(latestScope.current, current)\n ) return\n const installed = installNewestThread(latestThread, thread, signal)\n setState((latest) =>\n latest._tag === \"ready\" && sameReviewScope(latest, current)\n ? { ...latest, historyAction: \"idle\", thread: installed }\n : latest\n )\n } catch (failure) {\n if (\n signal.aborted ||\n latestScope.current === null ||\n !sameReviewScope(latestScope.current, current)\n ) return\n if (isUnauthorizedPullRequestReviewFailure(failure)) {\n onSessionExpired(current.sessionKey)\n }\n Effect.runFork(Effect.logError(\"Pull-request review history load failed\", failure))\n setState((latest) =>\n latest._tag === \"ready\" && sameReviewScope(latest, current)\n ? { ...latest, historyAction: \"failed\" }\n : latest\n )\n }\n }\n return run()\n}\n\n/** Load one coherent review snapshot and close a pending-to-terminal tail race. */\nexport const loadPullRequestReviewSnapshot = async (\n transport: PullRequestReviewTransport,\n entityId: EntityId,\n canEnqueue: boolean,\n signal: AbortSignal,\n previous: PullRequestReviewThread | undefined,\n target: PullRequestReviewThreadRef\n): Promise<{\n readonly catalog: AgentProviderCatalog\n readonly catalogNeedsRetry: boolean\n readonly review: PullRequestReviewState\n readonly thread: PullRequestReviewThread\n}> => {\n const catalogPromise = canEnqueue\n ? transport.providers(signal).then(\n (catalog) => ({ catalog, needsRetry: false }),\n (failure: unknown) => {\n if (signal.aborted || !isRecoverablePullRequestReviewFailure(failure)) throw failure\n Effect.runFork(Effect.logWarning(\"Pull-request review provider catalog load failed\", failure))\n return {\n catalog: { providers: [] } satisfies AgentProviderCatalog,\n needsRetry: true\n }\n }\n )\n : Promise.resolve({\n catalog: { providers: [] } satisfies AgentProviderCatalog,\n needsRetry: false\n })\n const [review, initialThread, catalogResult] = await Promise.all([\n transport.load(entityId, signal),\n continuePullRequestReviewThread(transport, entityId, signal, previous),\n catalogPromise\n ])\n const thread = review._tag === \"completed\" || review._tag === \"failed\"\n ? await continuePullRequestReviewThread(transport, entityId, signal, initialThread)\n : initialThread\n return {\n catalog: catalogResult.catalog,\n catalogNeedsRetry: catalogResult.needsRetry,\n review,\n thread: installNewestThread(target, thread, signal)\n }\n}\n\n/** Continue a visible thread while retaining diagnostics for non-fatal refresh failures. */\nexport const refreshPullRequestReviewThread = async (\n transport: PullRequestReviewThreadPageTransport,\n entityId: EntityId,\n signal: AbortSignal,\n previous: PullRequestReviewThread | undefined,\n target: PullRequestReviewThreadRef\n): Promise<PullRequestReviewThread> => {\n try {\n const thread = await continuePullRequestReviewThread(transport, entityId, signal, previous)\n return installNewestThread(target, thread, signal)\n } catch (failure) {\n if (!signal.aborted) {\n Effect.runFork(Effect.logError(\"Pull-request review thread refresh failed\", failure))\n }\n throw failure\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{r as e}from"./rolldown-runtime-QTnfLwEv.js";import{t}from"./react-CZI7_Jkm.js";import{Hr as n,Ir as r,Li as i,_i as a,ai as o,ja as s,ni as c,pi as l}from"./agent-api-Dl9TuGOJ.js";import{a as u,t as d}from"./client-Dq_XQE_l.js";import{t as f}from"./authenticatedMutationClient-DdowMjyo.js";var p=new Intl.DateTimeFormat(`en-GB`,{dateStyle:`medium`,timeStyle:`short`,timeZone:`UTC`}),m=e=>e===void 0?null:{dateTime:r(e),label:p.format(n(e))},h=(e,t)=>e===void 0?`${t} not synchronized`:`${e.complete?`Complete`:`Partial`} · ${String(e.pagesFetched)} bounded page${e.pagesFetched===1?``:`s`} read`,g=e=>e===null?`Size unavailable`:e<1024?`${String(e)} B`:e<1048576?`${(e/1024).toFixed(1)} KB`:`${(e/1048576).toFixed(1)} MB`,_=e=>e.map(e=>`${e.charAt(0).toLocaleUpperCase(`en-US`)}${e.slice(1)}`).join(` · `),v=e=>{let t=new Map;for(let n of e){let e=t.get(n.sourcePersonId),r=e===void 0?n.roles:[...new Set([...e.roles,...n.roles])],i=e?.resolved===!0&&!n.resolved?e:n;t.set(n.sourcePersonId,{...i,roles:r})}return[...t.values()]},y=(e,t)=>{let n=v(e.contributors??[]),r=new Map(n.map(({displayName:e,sourcePersonId:t})=>[t,e])),i=e.contentState===`lazy`?`lazy`:e.content===null||e.content===void 0?`empty`:`loaded`;return{attachmentInventoryLabel:h(e.attachmentInventory,`Attachment inventory`),attachments:(e.attachments??[]).map(e=>({createdAt:m(e.createdAt),fileSize:g(e.fileSize),id:e.id,mediaType:e.mediaType??`Type unavailable`,title:e.title,version:e.version===null?`Version unavailable`:`v${String(e.version)}`})),content:i===`loaded`?e.content?.markdown??null:null,contentState:i,contributors:n.map(e=>({id:e.sourcePersonId,name:e.displayName,role:`${_(e.roles)}${e.external?` · External`:``}${e.resolved?``:` · Identity unresolved`}`})),createdAt:m(e.createdAt),historyInventoryLabel:h(e.versionHistory,`Revision history`),revision:e.revision,runbookEvidenceCount:t.graph.evidenceItems.length,sourceSpaceId:e.sourceSpaceId??e.spaceKey,status:e.status===`superseded`?`Superseded`:e.status===`draft`?`Draft`:`Current`,taskUpdatesSafe:e.taskUpdatesSafe===!0,updatedAt:m(e.updatedAt),versions:(e.versions??[]).map(e=>({author:e.authorSourcePersonId===null?`Author unavailable`:r.get(e.authorSourcePersonId)??`Identity not resolved`,createdAt:m(e.createdAt),message:e.message??`No revision note`,minorEdit:e.minorEdit,number:e.number})),watcherInventoryLabel:h(e.watcherInventory,`Watcher inventory`)}},b=e(t(),1),x=s(`UnauthorizedApiError`),S=s(`NotFoundApiError`),C=(e,t)=>e._tag!==`idle`&&e.entityId===t.entityId&&e.sessionKey===t.sessionKey&&e.workspaceId===t.workspaceId,w=(e,t)=>C(e,t)&&(e._tag===`ready`||e._tag===`stale`)?e.inspection:null,T=(e,t)=>!e.isSourceCurrent||e.freshness?._tag===`stale`?{_tag:`stale`,inspection:e,reason:`source-stale`,...t}:{_tag:`ready`,inspection:e,...t},E={load:(e,t)=>a(o(function*(){return yield*(yield*d()).deliveryGraph.workspaceEntity({params:{entityId:e}})}).pipe(l(u)),{signal:t})},D=(e,t,n,r,i,a=E)=>{let[o,s]=(0,b.useState)(0),[c,l]=(0,b.useState)({_tag:`idle`});(0,b.useEffect)(()=>{if(r===null){l({_tag:`idle`});return}let o={entityId:t,refreshKey:n,sessionKey:r,workspaceId:e},s=new AbortController;return l(e=>{let t=w(e,o);return t===null?{_tag:`loading`,...o}:{_tag:`stale`,inspection:t,reason:`refreshing`,...o}}),a.load(t,s.signal).then(e=>{s.signal.aborted||l(T(e,o))},e=>{if(!s.signal.aborted){if(x(e)){i(r),l({_tag:`failed`,...o});return}if(S(e)){l({_tag:`not-found`,...o});return}l(e=>{let t=w(e,o);return t===null?{_tag:`failed`,...o}:{_tag:`stale`,inspection:t,reason:`refresh-failed`,...o}})}}),()=>s.abort()},[t,i,n,o,r,a,e]);let u=r===null?null:{entityId:t,refreshKey:n,sessionKey:r,workspaceId:e},d=u===null?{_tag:`idle`}:c._tag===`idle`||!C(c,u)?{_tag:`loading`,...u}:c.refreshKey!==n&&(c._tag===`ready`||c._tag===`stale`)?{_tag:`stale`,inspection:c.inspection,reason:`refreshing`,...u}:c.refreshKey===n?c:{_tag:`loading`,...u};return{retry:(0,b.useCallback)(()=>s(e=>e+1),[]),state:d}},O=e=>a(o(function*(){return yield*(yield*f).agent.submitReleasePublication({params:{releaseId:e.releaseId},payload:{provider:e.provider,title:e.title,markdown:e.markdown,parentId:null,...e.publicationActionId===void 0?{}:{publicationActionId:e.publicationActionId},...e.templateEntityId===void 0?{}:{templateEntityId:e.templateEntityId},...e.targetEntityId===void 0?{}:{targetEntityId:e.targetEntityId},...e.targetRevision===void 0?{}:{targetRevision:e.targetRevision}}})}).pipe(l(u)),e.signal===void 0?void 0:{signal:e.signal}),k=class extends i(`ReleaseAgentProtocolError`){},A=c(`ReleaseAgentTransport.runTurn`)(function*(e){let t=yield*(yield*f).agent.turn({params:{releaseId:e.releaseId},payload:{history:e.history,...e.originPath===void 0?{}:{originPath:e.originPath},prompt:e.prompt,provider:e.provider}});return t.releaseId!==e.releaseId||t.release.releaseId!==e.releaseId?yield*new k:{eventCursor:t.eventCursor,provider:t.provider,release:t.release,reply:t.reply}}),j=c(`ReleaseAgentTransport.loadPresets`)(function*(){let e=yield*(yield*f).agent.providers(),t=[];for(let n of e.providers){let e=String(n.providerId);n.health===`available`&&n.capabilities.includes(`release-chat`)&&(e===`codex`||e===`claude`)&&t.push(e)}return t}),M=(e,{signal:t})=>a(A(e).pipe(l(u)),{signal:t}),N=e=>a(j().pipe(l(u)),{signal:e});export{D as a,E as i,M as n,y as o,O as r,N as t};
|
|
2
|
+
//# sourceMappingURL=releaseAgentTransport-DaO4svPu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"releaseAgentTransport-DaO4svPu.js","names":[],"sources":["../../../src/client/entities/presentWorkspaceConfluencePage.ts","../../../src/client/entities/useWorkspaceEntity.ts","../../../src/client/releases/releaseAgentTransport.ts"],"sourcesContent":["import type { RlyPerson } from \"@knpkv/rly/patterns\"\nimport * as DateTime from \"effect/DateTime\"\n\nimport type { WorkspaceEntityInspection } from \"../../api/deliveryGraph.js\"\nimport type { DeliveryEntityDetails } from \"../../domain/deliveryGraph.js\"\n\ntype PageDetails = Extract<DeliveryEntityDetails, { readonly _tag: \"page\" }>\n\nexport interface WorkspacePageTimestamp {\n readonly dateTime: string\n readonly label: string\n}\n\nexport interface WorkspaceConfluencePagePresentation {\n readonly attachmentInventoryLabel: string\n readonly attachments: ReadonlyArray<{\n readonly createdAt: WorkspacePageTimestamp\n readonly fileSize: string\n readonly id: string\n readonly mediaType: string\n readonly title: string\n readonly version: string\n }>\n readonly content: string | null\n readonly contentState: \"empty\" | \"lazy\" | \"loaded\"\n readonly contributors: ReadonlyArray<RlyPerson>\n readonly createdAt: WorkspacePageTimestamp | null\n readonly historyInventoryLabel: string\n readonly revision: string\n readonly runbookEvidenceCount: number\n readonly sourceSpaceId: string\n readonly status: \"Current\" | \"Draft\" | \"Superseded\"\n readonly taskUpdatesSafe?: boolean\n readonly updatedAt: WorkspacePageTimestamp | null\n readonly versions: ReadonlyArray<{\n readonly author: string\n readonly createdAt: WorkspacePageTimestamp\n readonly message: string\n readonly minorEdit: boolean\n readonly number: number\n }>\n readonly watcherInventoryLabel: string\n}\n\nconst timestampFormatter = new Intl.DateTimeFormat(\"en-GB\", {\n dateStyle: \"medium\",\n timeStyle: \"short\",\n timeZone: \"UTC\"\n})\n\nconst timestampFor = (value: DateTime.DateTime | undefined): WorkspacePageTimestamp | null =>\n value === undefined\n ? null\n : {\n dateTime: DateTime.formatIso(value),\n label: timestampFormatter.format(DateTime.toDateUtc(value))\n }\n\nconst inventoryLabel = (\n inventory: { readonly complete: boolean; readonly pagesFetched: number } | undefined,\n noun: string\n): string =>\n inventory === undefined\n ? `${noun} not synchronized`\n : `${inventory.complete ? \"Complete\" : \"Partial\"} · ${String(inventory.pagesFetched)} bounded page${\n inventory.pagesFetched === 1 ? \"\" : \"s\"\n } read`\n\nconst fileSizeLabel = (bytes: number | null): string => {\n if (bytes === null) return \"Size unavailable\"\n if (bytes < 1_024) return `${String(bytes)} B`\n if (bytes < 1_048_576) return `${(bytes / 1_024).toFixed(1)} KB`\n return `${(bytes / 1_048_576).toFixed(1)} MB`\n}\n\nconst roleLabel = (roles: ReadonlyArray<\"author\" | \"contributor\" | \"owner\" | \"watcher\">): string =>\n roles.map((role) => `${role.charAt(0).toLocaleUpperCase(\"en-US\")}${role.slice(1)}`).join(\" · \")\n\nconst uniqueContributors = (\n contributors: NonNullable<PageDetails[\"contributors\"]>\n): NonNullable<PageDetails[\"contributors\"]> => {\n const byId = new Map<string, NonNullable<PageDetails[\"contributors\"]>[number]>()\n for (const contributor of contributors) {\n const previous = byId.get(contributor.sourcePersonId)\n const roles = previous === undefined\n ? contributor.roles\n : [...new Set([...previous.roles, ...contributor.roles])]\n const identity = previous?.resolved === true && !contributor.resolved ? previous : contributor\n byId.set(contributor.sourcePersonId, { ...identity, roles })\n }\n return [...byId.values()]\n}\n\n/** Present one normalized page as a quiet read-only document with explicit provider boundaries. */\nexport const presentWorkspaceConfluencePage = (\n details: PageDetails,\n inspection: WorkspaceEntityInspection\n): WorkspaceConfluencePagePresentation => {\n const contributors = uniqueContributors(details.contributors ?? [])\n const contributorNameById = new Map(contributors.map(({ displayName, sourcePersonId }) => [\n sourcePersonId,\n displayName\n ]))\n const contentState = details.contentState === \"lazy\"\n ? \"lazy\"\n : details.content === null || details.content === undefined\n ? \"empty\"\n : \"loaded\"\n return {\n attachmentInventoryLabel: inventoryLabel(details.attachmentInventory, \"Attachment inventory\"),\n attachments: (details.attachments ?? []).map((attachment) => ({\n createdAt: timestampFor(attachment.createdAt)!,\n fileSize: fileSizeLabel(attachment.fileSize),\n id: attachment.id,\n mediaType: attachment.mediaType ?? \"Type unavailable\",\n title: attachment.title,\n version: attachment.version === null ? \"Version unavailable\" : `v${String(attachment.version)}`\n })),\n content: contentState === \"loaded\" ? (details.content?.markdown ?? null) : null,\n contentState,\n contributors: contributors.map((contributor) => ({\n id: contributor.sourcePersonId,\n name: contributor.displayName,\n role: `${roleLabel(contributor.roles)}${contributor.external ? \" · External\" : \"\"}${\n contributor.resolved ? \"\" : \" · Identity unresolved\"\n }`\n })),\n createdAt: timestampFor(details.createdAt),\n historyInventoryLabel: inventoryLabel(details.versionHistory, \"Revision history\"),\n revision: details.revision,\n runbookEvidenceCount: inspection.graph.evidenceItems.length,\n sourceSpaceId: details.sourceSpaceId ?? details.spaceKey,\n status: details.status === \"superseded\" ? \"Superseded\" : details.status === \"draft\" ? \"Draft\" : \"Current\",\n taskUpdatesSafe: details.taskUpdatesSafe === true,\n updatedAt: timestampFor(details.updatedAt),\n versions: (details.versions ?? []).map((version) => ({\n author: version.authorSourcePersonId === null\n ? \"Author unavailable\"\n : contributorNameById.get(version.authorSourcePersonId) ?? \"Identity not resolved\",\n createdAt: timestampFor(version.createdAt)!,\n message: version.message ?? \"No revision note\",\n minorEdit: version.minorEdit,\n number: version.number\n })),\n watcherInventoryLabel: inventoryLabel(details.watcherInventory, \"Watcher inventory\")\n }\n}\n","import * as Effect from \"effect/Effect\"\nimport * as Predicate from \"effect/Predicate\"\nimport * as FetchHttpClient from \"effect/unstable/http/FetchHttpClient\"\nimport { useCallback, useEffect, useState } from \"react\"\n\nimport { makeControlCenterApiClient } from \"../../api/client.js\"\nimport type { WorkspaceEntityInspection } from \"../../api/deliveryGraph.js\"\nimport type { EntityId, WorkspaceId } from \"../../domain/identifiers.js\"\n\ninterface WorkspaceEntityScope {\n readonly entityId: EntityId\n readonly refreshKey: string\n readonly sessionKey: string\n readonly workspaceId: WorkspaceId\n}\n\nexport type WorkspaceEntityStaleReason = \"refresh-failed\" | \"refreshing\" | \"source-stale\"\n\n/** Complete controller state for one exact canonical workspace entity read. */\nexport type WorkspaceEntityState =\n | { readonly _tag: \"idle\" }\n | ({ readonly _tag: \"loading\" } & WorkspaceEntityScope)\n | ({ readonly _tag: \"not-found\" } & WorkspaceEntityScope)\n | ({ readonly _tag: \"failed\" } & WorkspaceEntityScope)\n | ({ readonly _tag: \"ready\"; readonly inspection: WorkspaceEntityInspection } & WorkspaceEntityScope)\n | ({\n readonly _tag: \"stale\"\n readonly inspection: WorkspaceEntityInspection\n readonly reason: WorkspaceEntityStaleReason\n } & WorkspaceEntityScope)\n\n/** Browser boundary for one exact authenticated workspace entity read. */\nexport interface WorkspaceEntityTransport {\n readonly load: (entityId: EntityId, signal: AbortSignal) => Promise<WorkspaceEntityInspection>\n}\n\nconst isUnauthorizedFailure = Predicate.isTagged(\"UnauthorizedApiError\")\nconst isNotFoundFailure = Predicate.isTagged(\"NotFoundApiError\")\n\nconst sameIdentity = (state: WorkspaceEntityState, scope: WorkspaceEntityScope): boolean =>\n state._tag !== \"idle\" &&\n state.entityId === scope.entityId &&\n state.sessionKey === scope.sessionKey &&\n state.workspaceId === scope.workspaceId\n\nconst retainedInspection = (\n state: WorkspaceEntityState,\n scope: WorkspaceEntityScope\n): WorkspaceEntityInspection | null =>\n sameIdentity(state, scope) && (state._tag === \"ready\" || state._tag === \"stale\")\n ? state.inspection\n : null\n\nconst successfulState = (\n inspection: WorkspaceEntityInspection,\n scope: WorkspaceEntityScope\n): WorkspaceEntityState =>\n !inspection.isSourceCurrent || inspection.freshness?._tag === \"stale\"\n ? { _tag: \"stale\", inspection, reason: \"source-stale\", ...scope }\n : { _tag: \"ready\", inspection, ...scope }\n\n/** Generated-client transport for the canonical schema-decoded entity inspection. */\nexport const browserWorkspaceEntityTransport: WorkspaceEntityTransport = {\n load: (entityId, signal) =>\n Effect.runPromise(\n Effect.gen(function*() {\n const client = yield* makeControlCenterApiClient()\n return yield* client.deliveryGraph.workspaceEntity({ params: { entityId } })\n }).pipe(Effect.provide(FetchHttpClient.layer)),\n { signal }\n )\n}\n\n/** Keep one entity inspection scoped to the exact workspace, identity, refresh, and browser session. */\nexport const useWorkspaceEntity = (\n workspaceId: WorkspaceId,\n entityId: EntityId,\n refreshKey: string,\n sessionKey: string | null,\n onSessionExpired: (sessionKey: string) => void,\n transport: WorkspaceEntityTransport = browserWorkspaceEntityTransport\n): { readonly retry: () => void; readonly state: WorkspaceEntityState } => {\n const [requestRevision, setRequestRevision] = useState(0)\n const [state, setState] = useState<WorkspaceEntityState>({ _tag: \"idle\" })\n\n useEffect(() => {\n if (sessionKey === null) {\n setState({ _tag: \"idle\" })\n return\n }\n const scope = { entityId, refreshKey, sessionKey, workspaceId } satisfies WorkspaceEntityScope\n const abort = new AbortController()\n setState((current) => {\n const inspection = retainedInspection(current, scope)\n return inspection === null\n ? { _tag: \"loading\", ...scope }\n : { _tag: \"stale\", inspection, reason: \"refreshing\", ...scope }\n })\n transport.load(entityId, abort.signal).then(\n (inspection) => {\n if (!abort.signal.aborted) setState(successfulState(inspection, scope))\n },\n (failure) => {\n if (abort.signal.aborted) return\n if (isUnauthorizedFailure(failure)) {\n onSessionExpired(sessionKey)\n setState({ _tag: \"failed\", ...scope })\n return\n }\n if (isNotFoundFailure(failure)) {\n setState({ _tag: \"not-found\", ...scope })\n return\n }\n setState((current) => {\n const inspection = retainedInspection(current, scope)\n return inspection === null\n ? { _tag: \"failed\", ...scope }\n : { _tag: \"stale\", inspection, reason: \"refresh-failed\", ...scope }\n })\n }\n )\n return () => abort.abort()\n }, [entityId, onSessionExpired, refreshKey, requestRevision, sessionKey, transport, workspaceId])\n\n const scope = sessionKey === null\n ? null\n : { entityId, refreshKey, sessionKey, workspaceId } satisfies WorkspaceEntityScope\n const currentState: WorkspaceEntityState = scope === null\n ? { _tag: \"idle\" }\n : state._tag === \"idle\" || !sameIdentity(state, scope)\n ? { _tag: \"loading\", ...scope }\n : state.refreshKey !== refreshKey && (state._tag === \"ready\" || state._tag === \"stale\")\n ? { _tag: \"stale\", inspection: state.inspection, reason: \"refreshing\", ...scope }\n : state.refreshKey !== refreshKey\n ? { _tag: \"loading\", ...scope }\n : state\n\n return {\n retry: useCallback(() => setRequestRevision((revision) => revision + 1), []),\n state: currentState\n }\n}\n","import * as Data from \"effect/Data\"\nimport * as Effect from \"effect/Effect\"\nimport * as FetchHttpClient from \"effect/unstable/http/FetchHttpClient\"\n\nimport type { ReleasePublicationProvider } from \"../../api/agent.js\"\nimport type { EntityId, GovernedActionId, ReleaseId } from \"../../domain/identifiers.js\"\nimport type { Revision } from \"../../domain/sourceRevision.js\"\nimport type { ReleaseAgentTurn } from \"../AgentPage.js\"\nimport { makeAuthenticatedMutationClient } from \"../authenticatedMutationClient.js\"\n\nexport const submitBrowserReleasePublication = (input: {\n readonly releaseId: ReleaseId\n readonly provider: ReleasePublicationProvider\n readonly title: string\n readonly markdown: string\n readonly publicationActionId?: GovernedActionId\n readonly templateEntityId?: EntityId\n readonly targetEntityId?: EntityId\n readonly targetRevision?: Revision\n readonly signal?: AbortSignal\n}): Promise<{ readonly actionId: string; readonly state: string }> =>\n Effect.runPromise(\n Effect.gen(function*() {\n const client = yield* makeAuthenticatedMutationClient\n return yield* client.agent.submitReleasePublication({\n params: { releaseId: input.releaseId },\n payload: {\n provider: input.provider,\n title: input.title,\n markdown: input.markdown,\n parentId: null,\n ...(input.publicationActionId === undefined ? {} : {\n publicationActionId: input.publicationActionId\n }),\n ...(input.templateEntityId === undefined ? {} : { templateEntityId: input.templateEntityId }),\n ...(input.targetEntityId === undefined ? {} : { targetEntityId: input.targetEntityId }),\n ...(input.targetRevision === undefined ? {} : { targetRevision: input.targetRevision })\n }\n })\n }).pipe(Effect.provide(FetchHttpClient.layer)),\n input.signal === undefined ? undefined : { signal: input.signal }\n )\n\nclass ReleaseAgentProtocolError extends Data.TaggedError(\"ReleaseAgentProtocolError\") {}\n\nconst runTurnEffect = Effect.fn(\"ReleaseAgentTransport.runTurn\")(function*(\n input: Parameters<ReleaseAgentTurn>[0]\n) {\n const client = yield* makeAuthenticatedMutationClient\n const response = yield* client.agent.turn({\n params: { releaseId: input.releaseId },\n payload: {\n history: input.history,\n ...(input.originPath === undefined ? {} : { originPath: input.originPath }),\n prompt: input.prompt,\n provider: input.provider\n }\n })\n if (response.releaseId !== input.releaseId || response.release.releaseId !== input.releaseId) {\n return yield* new ReleaseAgentProtocolError()\n }\n return {\n eventCursor: response.eventCursor,\n provider: response.provider,\n release: response.release,\n reply: response.reply\n }\n})\n\nconst loadPresetsEffect = Effect.fn(\"ReleaseAgentTransport.loadPresets\")(function*() {\n const client = yield* makeAuthenticatedMutationClient\n const catalog = yield* client.agent.providers()\n const presets = new Array<\"claude\" | \"codex\">()\n for (const provider of catalog.providers) {\n const providerId = String(provider.providerId)\n if (\n provider.health === \"available\" &&\n provider.capabilities.includes(\"release-chat\") &&\n (providerId === \"codex\" || providerId === \"claude\")\n ) {\n presets.push(providerId)\n }\n }\n return presets\n})\n\n/** Browser transport for the selected read-only local release-agent preset. */\nexport const runBrowserReleaseAgentTurn: ReleaseAgentTurn = (input, { signal }) =>\n Effect.runPromise(runTurnEffect(input).pipe(Effect.provide(FetchHttpClient.layer)), { signal })\n\n/** Load only configured local release-agent presets from the redacted catalog. */\nexport const loadBrowserReleaseAgentPresets = (\n signal: AbortSignal\n): Promise<ReadonlyArray<\"claude\" | \"codex\">> =>\n Effect.runPromise(loadPresetsEffect().pipe(Effect.provide(FetchHttpClient.layer)), { signal })\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{i as e,s as t}from"./releasePaths-XoI2BHX3.js";import{Dn as n,Mn as r,Nn as i,ga as a,ha as o,ln as s,on as c,qn as l}from"./agent-api-Dl9TuGOJ.js";var u=i({hash:r,pathname:r,search:r}),d=i({_tag:n(`release-origin/v1`),origin:u,releaseId:c,workspaceId:s}),f=(e,t,n)=>{let r=l(d)(e);return o(r)?null:x(r.value,t,n).isStored?r.value:null},p=e=>{let t=l(s)(e);return a(t)?t.value:null},m=e=>{let t=l(c)(e);return a(t)?t.value:null},h=e=>({relay:`release-${e}-relay`,verdict:`release-${e}-verdict`,version:`release-${e}-version`}),g=({hash:e,pathname:t,search:n})=>({hash:e,pathname:t,search:n}),_=e=>e.length<=2048&&(e.length===0||e.startsWith(`?`)),v=e=>e.length<=1024&&(e.length===0||e.startsWith(`#`)),y=(n,r)=>n===e(r)||n===t(r),b=(e,t,n)=>({_tag:`release-origin/v1`,origin:n,releaseId:t,workspaceId:e}),x=(t,n,r)=>{let i={hash:``,pathname:e(n),search:``},a=l(d)(t);if(o(a))return{isStored:!1,origin:i};let s=a.value,c=s.workspaceId===n&&s.releaseId===r,u=y(s.origin.pathname,n);return c&&u&&_(s.origin.search)&&v(s.origin.hash)?{isStored:!0,origin:s.origin}:{isStored:!1,origin:i}},S=(e,t,n)=>x(e,t,n).origin,C=({hash:e,pathname:t,search:n})=>`${t}${n}${e}`;export{S as a,h as c,b as i,x as l,m as n,g as o,p as r,C as s,d as t,f as u};
|
|
2
|
+
//# sourceMappingURL=releaseRoutes-B4ciNOJj.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"releaseRoutes-
|
|
1
|
+
{"version":3,"file":"releaseRoutes-B4ciNOJj.js","names":[],"sources":["../../../src/client/releases/releaseRoutes.ts"],"sourcesContent":["import type { RlyReleaseTransitionNames } from \"@knpkv/rly/patterns\"\nimport * as Option from \"effect/Option\"\nimport * as Schema from \"effect/Schema\"\n\nimport {\n ReleaseId,\n type ReleaseId as ReleaseIdType,\n WorkspaceId,\n type WorkspaceId as WorkspaceIdType\n} from \"../../domain/identifiers.js\"\nimport { releaseParentPath, workspaceItemsPath } from \"./releasePaths.js\"\n\nexport {\n releaseActiveWorkPath,\n releaseAgentPath,\n releaseFullPath,\n releaseParentPath,\n releasePreviewPath,\n workspaceActiveWorkPath,\n workspaceItemsPath\n} from \"./releasePaths.js\"\n\n/** Exact in-application location preserved while release routes are open. */\nexport interface ReleaseOrigin {\n readonly hash: string\n readonly pathname: string\n readonly search: string\n}\n\n/** Router state carried from a release activation through preview and full view. */\nexport interface ReleaseRouteState {\n readonly _tag: \"release-origin/v1\"\n readonly origin: ReleaseOrigin\n readonly releaseId: ReleaseIdType\n readonly workspaceId: WorkspaceIdType\n}\n\n/** Decoded release origin plus whether it came from trusted versioned history state. */\nexport interface ResolvedReleaseOrigin {\n readonly isStored: boolean\n readonly origin: ReleaseOrigin\n}\n\ninterface LocationParts {\n readonly hash: string\n readonly pathname: string\n readonly search: string\n}\n\nconst ReleaseOriginSchema = Schema.Struct({\n hash: Schema.String,\n pathname: Schema.String,\n search: Schema.String\n})\n\n/** Bounded decoder shared by nested client routes that need to retain a release activation. */\nexport const ReleaseRouteStateSchema = Schema.Struct({\n _tag: Schema.Literal(\"release-origin/v1\"),\n origin: ReleaseOriginSchema,\n releaseId: ReleaseId,\n workspaceId: WorkspaceId\n})\n\n/** Retain only safe state for the exact release target, dropping foreign or malformed history data. */\nexport const retainReleaseRouteState = (\n state: unknown,\n workspaceId: WorkspaceIdType,\n releaseId: ReleaseIdType\n): ReleaseRouteState | null => {\n const decoded = Schema.decodeUnknownOption(ReleaseRouteStateSchema)(state)\n if (Option.isNone(decoded)) return null\n return resolveReleaseOrigin(decoded.value, workspaceId, releaseId).isStored ? decoded.value : null\n}\n\n/** Decode one workspace route segment at the browser boundary. */\nexport const decodeWorkspaceRouteId = (value: unknown): WorkspaceIdType | null => {\n const decoded = Schema.decodeUnknownOption(WorkspaceId)(value)\n return Option.isSome(decoded) ? decoded.value : null\n}\n\n/** Decode one release route segment at the browser boundary. */\nexport const decodeReleaseRouteId = (value: unknown): ReleaseIdType | null => {\n const decoded = Schema.decodeUnknownOption(ReleaseId)(value)\n return Option.isSome(decoded) ? decoded.value : null\n}\n\n/** Stable, collision-free geometry names for one release's orchestrated route transition. */\nexport const releaseTransitionNames = (releaseId: ReleaseIdType): RlyReleaseTransitionNames => ({\n relay: `release-${releaseId}-relay`,\n verdict: `release-${releaseId}-verdict`,\n version: `release-${releaseId}-version`\n})\n\n/** Capture a location without retaining mutable router objects. */\nexport const releaseOriginFromLocation = ({ hash, pathname, search }: LocationParts): ReleaseOrigin => ({\n hash,\n pathname,\n search\n})\n\nconst isSearch = (search: string): boolean => search.length <= 2_048 && (search.length === 0 || search.startsWith(\"?\"))\n\nconst isHash = (hash: string): boolean => hash.length <= 1_024 && (hash.length === 0 || hash.startsWith(\"#\"))\n\nconst isRecognizedOriginPath = (pathname: string, workspaceId: WorkspaceIdType): boolean =>\n pathname === releaseParentPath(workspaceId) || pathname === workspaceItemsPath(workspaceId)\n\n/** Construct bounded route state without retaining session or snapshot data. */\nexport const makeReleaseRouteState = (\n workspaceId: WorkspaceIdType,\n releaseId: ReleaseIdType,\n origin: ReleaseOrigin\n): ReleaseRouteState => ({ _tag: \"release-origin/v1\", origin, releaseId, workspaceId })\n\n/** Decode history state without permitting external or malformed navigation targets. */\nexport const resolveReleaseOrigin = (\n state: unknown,\n workspaceId: WorkspaceIdType,\n releaseId: ReleaseIdType\n): ResolvedReleaseOrigin => {\n const fallback = { hash: \"\", pathname: releaseParentPath(workspaceId), search: \"\" }\n const decoded = Schema.decodeUnknownOption(ReleaseRouteStateSchema)(state)\n if (Option.isNone(decoded)) return { isStored: false, origin: fallback }\n const routeState = decoded.value\n const isMatchingTarget = routeState.workspaceId === workspaceId && routeState.releaseId === releaseId\n const isRecognizedOrigin = isRecognizedOriginPath(routeState.origin.pathname, workspaceId)\n return isMatchingTarget && isRecognizedOrigin && isSearch(routeState.origin.search) && isHash(routeState.origin.hash)\n ? { isStored: true, origin: routeState.origin }\n : { isStored: false, origin: fallback }\n}\n\n/** Decode the exact safe origin or return the release's semantic parent. */\nexport const readReleaseOrigin = (\n state: unknown,\n workspaceId: WorkspaceIdType,\n releaseId: ReleaseIdType\n): ReleaseOrigin => resolveReleaseOrigin(state, workspaceId, releaseId).origin\n\n/** Serialize an exact origin for React Router navigation. */\nexport const releaseOriginHref = ({ hash, pathname, search }: ReleaseOrigin): string => `${pathname}${search}${hash}`\n"],"mappings":"2JAiDA,IAAM,EAAsB,EAAc,CACxC,KAAM,EACN,SAAU,EACV,OAAQ,CACV,CAAC,EAGY,EAA0B,EAAc,CACnD,KAAM,EAAe,mBAAmB,EACxC,OAAQ,EACR,UAAW,EACX,YAAa,CACf,CAAC,EAGY,GACX,EACA,EACA,IAC6B,CAC7B,IAAM,EAAU,EAA2B,CAAuB,CAAC,CAAC,CAAK,EAEzE,OADI,EAAc,CAAO,EAAU,KAC5B,EAAqB,EAAQ,MAAO,EAAa,CAAS,CAAC,CAAC,SAAW,EAAQ,MAAQ,IAChG,EAGa,EAA0B,GAA2C,CAChF,IAAM,EAAU,EAA2B,CAAW,CAAC,CAAC,CAAK,EAC7D,OAAO,EAAc,CAAO,EAAI,EAAQ,MAAQ,IAClD,EAGa,EAAwB,GAAyC,CAC5E,IAAM,EAAU,EAA2B,CAAS,CAAC,CAAC,CAAK,EAC3D,OAAO,EAAc,CAAO,EAAI,EAAQ,MAAQ,IAClD,EAGa,EAA0B,IAAyD,CAC9F,MAAO,WAAW,EAAU,QAC5B,QAAS,WAAW,EAAU,UAC9B,QAAS,WAAW,EAAU,SAChC,GAGa,GAA6B,CAAE,OAAM,WAAU,aAA4C,CACtG,OACA,WACA,QACF,GAEM,EAAY,GAA4B,EAAO,QAAU,OAAU,EAAO,SAAW,GAAK,EAAO,WAAW,GAAG,GAE/G,EAAU,GAA0B,EAAK,QAAU,OAAU,EAAK,SAAW,GAAK,EAAK,WAAW,GAAG,GAErG,GAA0B,EAAkB,IAChD,IAAa,EAAkB,CAAW,GAAK,IAAa,EAAmB,CAAW,EAG/E,GACX,EACA,EACA,KACuB,CAAE,KAAM,oBAAqB,SAAQ,YAAW,aAAY,GAGxE,GACX,EACA,EACA,IAC0B,CAC1B,IAAM,EAAW,CAAE,KAAM,GAAI,SAAU,EAAkB,CAAW,EAAG,OAAQ,EAAG,EAC5E,EAAU,EAA2B,CAAuB,CAAC,CAAC,CAAK,EACzE,GAAI,EAAc,CAAO,EAAG,MAAO,CAAE,SAAU,GAAO,OAAQ,CAAS,EACvE,IAAM,EAAa,EAAQ,MACrB,EAAmB,EAAW,cAAgB,GAAe,EAAW,YAAc,EACtF,EAAqB,EAAuB,EAAW,OAAO,SAAU,CAAW,EACzF,OAAO,GAAoB,GAAsB,EAAS,EAAW,OAAO,MAAM,GAAK,EAAO,EAAW,OAAO,IAAI,EAChH,CAAE,SAAU,GAAM,OAAQ,EAAW,MAAO,EAC5C,CAAE,SAAU,GAAO,OAAQ,CAAS,CAC1C,EAGa,GACX,EACA,EACA,IACkB,EAAqB,EAAO,EAAa,CAAS,CAAC,CAAC,OAG3D,GAAqB,CAAE,OAAM,WAAU,YAAoC,GAAG,IAAW,IAAS"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
2
|
-
//# sourceMappingURL=serviceOnboarding-
|
|
1
|
+
import{Jn as e,Mn as t,Nn as n,Vt as r,na as i,nn as a}from"./agent-api-Dl9TuGOJ.js";n({providerId:r,displayName:t,description:t}).annotate({identifier:`FirstPartyServiceIdentity`});var o={codecommit:{providerId:`codecommit`,displayName:`CodeCommit`,description:`Read pull requests from one AWS CodeCommit repository.`},codepipeline:{providerId:`codepipeline`,displayName:`CodePipeline`,description:`Read pipeline and execution state from AWS CodePipeline.`},jira:{providerId:`jira`,displayName:`Jira`,description:`Read delivery issues from Jira Cloud.`},confluence:{providerId:`confluence`,displayName:`Confluence`,description:`Read release documentation from Confluence Cloud.`},clockify:{providerId:`clockify`,displayName:`Clockify`,description:`Read bounded time-entry evidence and govern association corrections and approvals.`}},s=[o.codecommit,o.codepipeline,o.jira,o.confluence,o.clockify],c=e=>s.find(({providerId:t})=>t===e)?.providerId??null,l=e=>`/pair?service=${e}`,u=(e,t)=>c(e.get(t)),d=e=>`/services?enable=${e}`,f=(e,t=null,n=null)=>{let r=new URLSearchParams({enable:e.includes(`jira`)?`jira`:`confluence`});t!==null&&r.set(`atlassianProfile`,t),n!==null&&r.set(`atlassianSite`,n);for(let t of e)r.append(`atlassianProvider`,t);return`/services?${r.toString()}`},p=(e,t)=>`/services?${new URLSearchParams({atlassianRecoveryConnection:e,atlassianRecoveryProfile:t}).toString()}`,m=t=>{let n=t.getAll(`atlassianRecoveryConnection`);if(n.length!==1)return null;let r=e(a)(n[0]);return i(r)?r.success:null},h=e=>{let t=e.getAll(`atlassianRecoveryProfile`);if(t.length!==1)return null;let[n]=t;return n!==void 0&&n.length>0&&n.length<=500&&n.trim()===n?n:null},g=e=>{let t=e.getAll(`atlassianSite`);if(t.length!==1)return null;let[n]=t;return n!==void 0&&n.length>0&&n.length<=512&&n.trim()===n?n:null},_=e=>{let t=e.getAll(`atlassianProfile`);if(t.length!==1)return null;let[n]=t;return n!==void 0&&n.length>0&&n.length<=500&&n.trim()===n?n:null},v=e=>{let t=e.getAll(`atlassianProvider`);return t.length===1&&t[0]===`jira`?[`jira`]:t.length===1&&t[0]===`confluence`?[`confluence`]:t.length===2&&t.includes(`jira`)&&t.includes(`confluence`)?[`jira`,`confluence`]:null};export{g as a,u as c,s as d,v as i,l,f as n,m as o,_ as r,h as s,p as t,d as u};
|
|
2
|
+
//# sourceMappingURL=serviceOnboarding-D0FmodRi.js.map
|