@straiffi/archon 1.8.23 → 1.10.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/dist/client/assets/{ActivityView-BaIZ8eHC.js → ActivityView-Y5IaJiim.js} +1 -1
- package/dist/client/assets/GitHubActionsDialog-GWVxWGPK.js +1 -0
- package/dist/client/assets/VerificationDialog-C4RMuI4y.js +4 -0
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-Dl5UF67P.js → architectureDiagram-3BPJPVTR-CeM6gbLN.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-DCcERfrZ.js → blockDiagram-GPEHLZMM-BP4hta96.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-BGhbASFm.js → c4Diagram-AAUBKEIU-5aJScvhn.js} +1 -1
- package/dist/client/assets/channel-B3DjZXbm.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-C1ARozTV.js → chunk-2J33WTMH-BKc2IelV.js} +1 -1
- package/dist/client/assets/{chunk-3OPIFGDE-BEovLizF.js → chunk-3OPIFGDE-DCc15la5.js} +1 -1
- package/dist/client/assets/{chunk-5ZQYHXKU-C5MmlLa_.js → chunk-5ZQYHXKU-DSD9HbTp.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-8y8jBk4n.js → chunk-727SXJPM-DrAjnKiA.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-q-mByAd3.js → chunk-AQP2D5EJ-DxKnpHfQ.js} +1 -1
- package/dist/client/assets/{chunk-CSCIHK7Q-BOx2mLSz.js → chunk-CSCIHK7Q-DLejrAB_.js} +1 -1
- package/dist/client/assets/{chunk-KSCS5N6A-zEwQFq7q.js → chunk-KSCS5N6A-BWRNmF8S.js} +1 -1
- package/dist/client/assets/{chunk-L5ZTLDWV-C80z6rY_.js → chunk-L5ZTLDWV-D48i966f.js} +1 -1
- package/dist/client/assets/{chunk-LZXEDZCA-BLaEsGPd.js → chunk-LZXEDZCA-DLhg6Bok.js} +2 -2
- package/dist/client/assets/{chunk-ND2GUHAM-x26BZ95L.js → chunk-ND2GUHAM-B4-7cOEq.js} +1 -1
- package/dist/client/assets/{chunk-NZK2D7GU-D2WAxr1p.js → chunk-NZK2D7GU-D2ttXA_d.js} +1 -1
- package/dist/client/assets/{chunk-O5CBEL6O-DDPCrzKh.js → chunk-O5CBEL6O-BrWrOVCq.js} +1 -1
- package/dist/client/assets/{chunk-WU5MYG2G-CE-JcvIc.js → chunk-WU5MYG2G-CLcPwxPe.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-DproSkn2.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-JVMMzJxJ.js +1 -0
- package/dist/client/assets/{dagre-BM42HDAG-Bf7wpUk_.js → dagre-BM42HDAG-DIXN8_VX.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-BQoKmc3B.js → diagram-2AECGRRQ-D2wjdCij.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-D2jarPLn.js → diagram-5GNKFQAL-E1Og_PHE.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-Bcbbjvsl.js → diagram-KO2AKTUF-B6P1Ud8a.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-t862RRBQ.js → diagram-LMA3HP47-C3Jxq56v.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-CacbMcO0.js → diagram-OG6HWLK6-Do9LVhdL.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-DRQ79baI.js → erDiagram-TEJ5UH35-DLb5E4-f.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-BfW4KEdc.js → flowDiagram-I6XJVG4X-CcTs_wU9.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-BPIl0TAj.js → ganttDiagram-6RSMTGT7-q9ez5fri.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-CRIusBMV.js → gitGraphDiagram-PVQCEYII-BcaKiz4c.js} +1 -1
- package/dist/client/assets/index-1CokwSFm.css +2 -0
- package/dist/client/assets/index-CSOKbu3w.js +276 -0
- package/dist/client/assets/{infoDiagram-5YYISTIA-DTKzK8EJ.js → infoDiagram-5YYISTIA-Cu0w4frE.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-DVIHZLvL.js → ishikawaDiagram-YF4QCWOH-CJ47Z-ak.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-CQBZ4tCx.js → journeyDiagram-JHISSGLW-fAL_Zcvs.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-D7naegR0.js → kanban-definition-UN3LZRKU-BTNIybMC.js} +1 -1
- package/dist/client/assets/{line-CizZlaeV.js → line-BvsadeZR.js} +1 -1
- package/dist/client/assets/{mermaid-parser.core-NrDqgpZa.js → mermaid-parser.core-C0EkH2y_.js} +1 -1
- package/dist/client/assets/{mermaid.core-CwVO3oX0.js → mermaid.core-BU5QIIbY.js} +3 -3
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-BWxy3Aa_.js → mindmap-definition-RKZ34NQL-CWbSYK8f.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-B3gXpmBn.js → pieDiagram-4H26LBE5-t4w2cB-y.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-Dpp4g8Al.js → quadrantDiagram-W4KKPZXB-Cqasvrpa.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-lFKXnxml.js → requirementDiagram-4Y6WPE33-_l-mY-tb.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-BBdtwqrS.js → sankeyDiagram-5OEKKPKP-Cr9YrZ-Y.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-ANpVZzqm.js → sequenceDiagram-3UESZ5HK-DvzZhQpb.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-D58ZxmKY.js → stateDiagram-AJRCARHV-cFjPpAO3.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-btHMH5Cg.js +1 -0
- package/dist/client/assets/{timeline-definition-PNZ67QCA-B6FK8IQC.js → timeline-definition-PNZ67QCA-BjRNrEJY.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-lFWtZEEY.js → vennDiagram-CIIHVFJN-xs9afjrw.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-DteAVp4l.js → wardleyDiagram-YWT4CUSO-DH68ZYti.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-CNcDlRLN.js → xychartDiagram-2RQKCTM6-DLW5ktTU.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/server/db.js +225 -12
- package/dist/server/db.js.map +1 -1
- package/dist/server/index.js +80 -26
- package/dist/server/index.js.map +1 -1
- package/dist/server/lib/agent.js +368 -143
- package/dist/server/lib/agent.js.map +1 -1
- package/dist/server/lib/agentProvider.js.map +1 -1
- package/dist/server/lib/approvalReconciliation.js +14 -2
- package/dist/server/lib/approvalReconciliation.js.map +1 -1
- package/dist/server/lib/buildExecutionEnvironment.js +251 -57
- package/dist/server/lib/buildExecutionEnvironment.js.map +1 -1
- package/dist/server/lib/chatOperations.js +125 -3
- package/dist/server/lib/chatOperations.js.map +1 -1
- package/dist/server/lib/chatPostBuildRuns.js +12 -6
- package/dist/server/lib/chatPostBuildRuns.js.map +1 -1
- package/dist/server/lib/chatTargets.js +2 -1
- package/dist/server/lib/chatTargets.js.map +1 -1
- package/dist/server/lib/checkDefinitionCwd.js +34 -0
- package/dist/server/lib/checkDefinitionCwd.js.map +1 -0
- package/dist/server/lib/checkExecutionEnvironment.js +95 -0
- package/dist/server/lib/checkExecutionEnvironment.js.map +1 -0
- package/dist/server/lib/checkPolicyDefinitionIds.js +41 -0
- package/dist/server/lib/checkPolicyDefinitionIds.js.map +1 -0
- package/dist/server/lib/checkRepairDispatch.js +2 -0
- package/dist/server/lib/checkRepairDispatch.js.map +1 -1
- package/dist/server/lib/checkRunner.js +371 -175
- package/dist/server/lib/checkRunner.js.map +1 -1
- package/dist/server/lib/checkRuns.js +99 -8
- package/dist/server/lib/checkRuns.js.map +1 -1
- package/dist/server/lib/claudeAgentProvider.js +3 -6
- package/dist/server/lib/claudeAgentProvider.js.map +1 -1
- package/dist/server/lib/claudeStdin.js +27 -0
- package/dist/server/lib/claudeStdin.js.map +1 -0
- package/dist/server/lib/completedAssistantOutput.js +38 -0
- package/dist/server/lib/completedAssistantOutput.js.map +1 -0
- package/dist/server/lib/consequentialActionAuthority.js +99 -8
- package/dist/server/lib/consequentialActionAuthority.js.map +1 -1
- package/dist/server/lib/consequentialActions.js +42 -2
- package/dist/server/lib/consequentialActions.js.map +1 -1
- package/dist/server/lib/dockerSandboxCredentials.js +10 -3
- package/dist/server/lib/dockerSandboxCredentials.js.map +1 -1
- package/dist/server/lib/dockerSandboxEnvironmentOperations.js +9 -8
- package/dist/server/lib/dockerSandboxEnvironmentOperations.js.map +1 -1
- package/dist/server/lib/dockerSandboxExecutionEnvironment.js +149 -74
- package/dist/server/lib/dockerSandboxExecutionEnvironment.js.map +1 -1
- package/dist/server/lib/dockerSandboxExecutionProvider.js +22 -14
- package/dist/server/lib/dockerSandboxExecutionProvider.js.map +1 -1
- package/dist/server/lib/dockerSandboxNetworkPolicy.js +23 -14
- package/dist/server/lib/dockerSandboxNetworkPolicy.js.map +1 -1
- package/dist/server/lib/dockerSandboxReleaseProfiles.js +91 -0
- package/dist/server/lib/dockerSandboxReleaseProfiles.js.map +1 -0
- package/dist/server/lib/dockerSandboxRuntimeController.js +16 -1
- package/dist/server/lib/dockerSandboxRuntimeController.js.map +1 -1
- package/dist/server/lib/executionCredentialCapabilities.js +9 -6
- package/dist/server/lib/executionCredentialCapabilities.js.map +1 -1
- package/dist/server/lib/executionEnvironment.js.map +1 -1
- package/dist/server/lib/executionEnvironmentLifecycle.js +7 -0
- package/dist/server/lib/executionEnvironmentLifecycle.js.map +1 -1
- package/dist/server/lib/executionEnvironmentOperations.js +241 -0
- package/dist/server/lib/executionEnvironmentOperations.js.map +1 -0
- package/dist/server/lib/executionEnvironmentReconciliation.js +98 -3
- package/dist/server/lib/executionEnvironmentReconciliation.js.map +1 -1
- package/dist/server/lib/executionEnvironmentRoutes.js +66 -27
- package/dist/server/lib/executionEnvironmentRoutes.js.map +1 -1
- package/dist/server/lib/executionEnvironmentValidation.js +2 -2
- package/dist/server/lib/executionEnvironmentValidation.js.map +1 -1
- package/dist/server/lib/executionEnvironmentValidationOperations.js +58 -31
- package/dist/server/lib/executionEnvironmentValidationOperations.js.map +1 -1
- package/dist/server/lib/executionEnvironments.js +187 -9
- package/dist/server/lib/executionEnvironments.js.map +1 -1
- package/dist/server/lib/executionProfileCheckPolicy.js +14 -0
- package/dist/server/lib/executionProfileCheckPolicy.js.map +1 -0
- package/dist/server/lib/executionProfileRoutes.js +9 -1
- package/dist/server/lib/executionProfileRoutes.js.map +1 -1
- package/dist/server/lib/executionProfileStore.js +5 -3
- package/dist/server/lib/executionProfileStore.js.map +1 -1
- package/dist/server/lib/executionProfiles.js +97 -15
- package/dist/server/lib/executionProfiles.js.map +1 -1
- package/dist/server/lib/executionReconciliation.js +43 -6
- package/dist/server/lib/executionReconciliation.js.map +1 -1
- package/dist/server/lib/executionRunAuthority.js +115 -24
- package/dist/server/lib/executionRunAuthority.js.map +1 -1
- package/dist/server/lib/executionTargets.js +30 -4
- package/dist/server/lib/executionTargets.js.map +1 -1
- package/dist/server/lib/executionWorkloads.js +75 -0
- package/dist/server/lib/executionWorkloads.js.map +1 -0
- package/dist/server/lib/git.js +10 -1
- package/dist/server/lib/git.js.map +1 -1
- package/dist/server/lib/opencodeAgentProvider.js +3 -1
- package/dist/server/lib/opencodeAgentProvider.js.map +1 -1
- package/dist/server/lib/opencodeSessionOperations.js +5 -3
- package/dist/server/lib/opencodeSessionOperations.js.map +1 -1
- package/dist/server/lib/planQuestions.js +2 -1
- package/dist/server/lib/planQuestions.js.map +1 -1
- package/dist/server/lib/postBuildCheckRuns.js +9 -5
- package/dist/server/lib/postBuildCheckRuns.js.map +1 -1
- package/dist/server/lib/preview.js +47 -6
- package/dist/server/lib/preview.js.map +1 -1
- package/dist/server/lib/previewProxy.js +11 -3
- package/dist/server/lib/previewProxy.js.map +1 -1
- package/dist/server/lib/productionCheckApprovals.js +97 -35
- package/dist/server/lib/productionCheckApprovals.js.map +1 -1
- package/dist/server/lib/projectMemorySuggestions.js +29 -6
- package/dist/server/lib/projectMemorySuggestions.js.map +1 -1
- package/dist/server/lib/requiredCheckPolicy.js +3 -40
- package/dist/server/lib/requiredCheckPolicy.js.map +1 -1
- package/dist/server/lib/reviewAgentWatchdog.js +75 -0
- package/dist/server/lib/reviewAgentWatchdog.js.map +1 -0
- package/dist/server/lib/reviewFindingReconciliation.js +176 -0
- package/dist/server/lib/reviewFindingReconciliation.js.map +1 -0
- package/dist/server/lib/reviewFindings.js +33 -11
- package/dist/server/lib/reviewFindings.js.map +1 -1
- package/dist/server/lib/run.js +370 -80
- package/dist/server/lib/run.js.map +1 -1
- package/dist/server/lib/serviceRuns.js +196 -0
- package/dist/server/lib/serviceRuns.js.map +1 -0
- package/dist/server/lib/sessionTargets.js +34 -0
- package/dist/server/lib/sessionTargets.js.map +1 -1
- package/dist/server/lib/shell.js +20 -0
- package/dist/server/lib/shell.js.map +1 -1
- package/dist/server/lib/specArtifact.js +36 -15
- package/dist/server/lib/specArtifact.js.map +1 -1
- package/dist/server/lib/specBundleGroups.js +4 -4
- package/dist/server/lib/specBundleGroups.js.map +1 -1
- package/dist/server/lib/specOperations.js +2 -0
- package/dist/server/lib/specOperations.js.map +1 -1
- package/dist/server/lib/specReviewOperations.js +2 -0
- package/dist/server/lib/specReviewOperations.js.map +1 -1
- package/dist/server/lib/specTicketMaterialization.js +37 -24
- package/dist/server/lib/specTicketMaterialization.js.map +1 -1
- package/dist/server/lib/ticketFollowUpOperations.js +9 -4
- package/dist/server/lib/ticketFollowUpOperations.js.map +1 -1
- package/dist/server/lib/ticketRunOperations.js +1 -0
- package/dist/server/lib/ticketRunOperations.js.map +1 -1
- package/dist/server/lib/types.js +1 -0
- package/dist/server/lib/types.js.map +1 -1
- package/dist/server/lib/workloadExecutionEnvironment.js +2 -0
- package/dist/server/lib/workloadExecutionEnvironment.js.map +1 -0
- package/dist/server/lib/workspaceIdentity.js +30 -6
- package/dist/server/lib/workspaceIdentity.js.map +1 -1
- package/dist/server/workers/build.js +39 -8
- package/dist/server/workers/build.js.map +1 -1
- package/dist/server/workers/chat.js +142 -15
- package/dist/server/workers/chat.js.map +1 -1
- package/dist/server/workers/followUp.js +77 -20
- package/dist/server/workers/followUp.js.map +1 -1
- package/dist/server/workers/plan.js +295 -48
- package/dist/server/workers/plan.js.map +1 -1
- package/dist/server/workers/planFollowUp.js +77 -7
- package/dist/server/workers/planFollowUp.js.map +1 -1
- package/dist/server/workers/review.js +149 -38
- package/dist/server/workers/review.js.map +1 -1
- package/dist/server/workers/specReview.js +43 -5
- package/dist/server/workers/specReview.js.map +1 -1
- package/dist/server/workers/specSession.js +156 -31
- package/dist/server/workers/specSession.js.map +1 -1
- package/package.json +1 -1
- package/dist/client/assets/GitHubActionsDialog-BFCqikDY.js +0 -1
- package/dist/client/assets/VerificationDialog-B1_6HMdt.js +0 -4
- package/dist/client/assets/channel-BfskvH2B.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-D4HPfxL3.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-DQQ_WqAU.js +0 -1
- package/dist/client/assets/index-CZ1z72fo.js +0 -276
- package/dist/client/assets/index-SMj5ZmMs.css +0 -2
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-Cv8cmDfz.js +0 -1
package/dist/server/lib/run.js
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import { spawn } from "child_process";
|
|
2
|
-
import { existsSync } from "fs";
|
|
3
|
-
import {
|
|
2
|
+
import { existsSync, realpathSync } from "fs";
|
|
3
|
+
import { isAbsolute, relative, resolve } from "path";
|
|
4
4
|
import { resolveWorktreePath } from "./git.js";
|
|
5
5
|
import { getProjectById, getProjectRunConfig } from "./projects.js";
|
|
6
6
|
import { applyDetectedPreviewTarget, buildPreviewProxyUrl, createIdlePreviewStatus, createRunPreviewStatus, detectPreviewTargets, inferPreviewTargetsFromLogChunk, isPreviewService, normalizePreviewLogText, resolveReachablePreviewTarget, } from "./preview.js";
|
|
7
7
|
import { deactivatePreviewProxyForProject, ensurePreviewProxyForProject, } from "./previewProxy.js";
|
|
8
|
-
import { resolveShell } from "./shell.js";
|
|
8
|
+
import { getHostShellArguments, resolveShell } from "./shell.js";
|
|
9
9
|
import { redactRepositorySecrets } from "./projectMemoryScan.js";
|
|
10
10
|
import { isTicketRunSetupReady } from "./ticketDependencies.js";
|
|
11
11
|
import { listTicketsInRunContext, resolveTicketBranch, resolveTicketContextKey, } from "./tickets.js";
|
|
12
12
|
import { createWorkspaceProcessEnvironment } from "./workspaceProcessEnvironment.js";
|
|
13
|
+
import { resolveWorkloadExecutionEnvironment } from "./buildExecutionEnvironment.js";
|
|
14
|
+
import { getActiveExecutionProfileRevision } from "./executionProfileStore.js";
|
|
15
|
+
import { classifyTicketExecutionTarget, resolveExecutionTarget, } from "./executionTargets.js";
|
|
16
|
+
import { completeServiceRun, createServiceRun, recordServiceRunReleaseFailure, recordServiceRunPlacement, } from "./serviceRuns.js";
|
|
17
|
+
import { transitionExecutionRun } from "./executionRuns.js";
|
|
13
18
|
const runningProcesses = new Map();
|
|
14
19
|
const MAX_PREVIEW_LOG_BUFFER_CHARS = 16_000;
|
|
15
20
|
const getRunConfig = (project) => getProjectRunConfig(project);
|
|
@@ -109,6 +114,10 @@ const trackProcess = (state, proc) => {
|
|
|
109
114
|
proc.on("error", cleanup);
|
|
110
115
|
return proc;
|
|
111
116
|
};
|
|
117
|
+
const trackExecutionHandle = (state, handle) => {
|
|
118
|
+
state.execution_handles?.push(handle);
|
|
119
|
+
return trackProcess(state, handle.child);
|
|
120
|
+
};
|
|
112
121
|
const spawnManagedProcess = (cmd, cwd, stdio, state) => {
|
|
113
122
|
const env = createWorkspaceProcessEnvironment(cwd);
|
|
114
123
|
delete env.PORT;
|
|
@@ -219,9 +228,8 @@ export const runSetupCommandsInWorkspace = async (project, cwd, execution) => {
|
|
|
219
228
|
const hostShell = execution.provider.kind === "host" ? resolveShell() : null;
|
|
220
229
|
const command = hostShell ?? "sh";
|
|
221
230
|
const args = hostShell
|
|
222
|
-
?
|
|
223
|
-
|
|
224
|
-
: ["-i", "-c", cmd]
|
|
231
|
+
? getHostShellArguments(hostShell, cmd, execution.runtimeEnvironment.kind !== "host"
|
|
232
|
+
|| execution.runtimeEnvironment.inheritance !== "governed")
|
|
225
233
|
: ["-lc", cmd];
|
|
226
234
|
const handle = execution.provider.execute({
|
|
227
235
|
phase: "setup",
|
|
@@ -276,7 +284,88 @@ const clearRunState = (contextKey, state, onStopped) => {
|
|
|
276
284
|
runningProcesses.delete(contextKey);
|
|
277
285
|
onStopped?.();
|
|
278
286
|
};
|
|
279
|
-
const
|
|
287
|
+
const canCreateDurableServiceRun = (project, targetDescriptor) => Boolean(targetDescriptor
|
|
288
|
+
&& project.id
|
|
289
|
+
&& project.active_execution_profile_revision_id);
|
|
290
|
+
const getServiceExecutionAgent = (project) => {
|
|
291
|
+
const profile = getActiveExecutionProfileRevision(project.id)?.profile;
|
|
292
|
+
return profile?.check_template_policy.mode === "agent_template"
|
|
293
|
+
? profile.check_template_policy.agent
|
|
294
|
+
: "opencode";
|
|
295
|
+
};
|
|
296
|
+
const getExecutionShell = (provider, runtimeEnvironment, cmd) => {
|
|
297
|
+
const hostShell = provider.kind === "host" ? resolveShell() : null;
|
|
298
|
+
return {
|
|
299
|
+
command: hostShell ?? "sh",
|
|
300
|
+
args: hostShell
|
|
301
|
+
? getHostShellArguments(hostShell, cmd, runtimeEnvironment.kind !== "host" || runtimeEnvironment.inheritance !== "governed")
|
|
302
|
+
: ["-lc", cmd],
|
|
303
|
+
};
|
|
304
|
+
};
|
|
305
|
+
const resolveServiceCwd = (workspacePath, configuredCwd) => {
|
|
306
|
+
if (!configuredCwd) {
|
|
307
|
+
return workspacePath;
|
|
308
|
+
}
|
|
309
|
+
if (isAbsolute(configuredCwd)) {
|
|
310
|
+
throw new Error("Service working directories must be relative to the canonical target");
|
|
311
|
+
}
|
|
312
|
+
const serviceCwd = resolve(workspacePath, configuredCwd);
|
|
313
|
+
const relativePath = relative(workspacePath, serviceCwd);
|
|
314
|
+
if (relativePath === ".." || relativePath.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`)) {
|
|
315
|
+
throw new Error("Service working directories must remain inside the canonical target");
|
|
316
|
+
}
|
|
317
|
+
const realWorkspacePath = realpathSync(workspacePath);
|
|
318
|
+
const realServiceCwd = realpathSync(serviceCwd);
|
|
319
|
+
const realRelativePath = relative(realWorkspacePath, realServiceCwd);
|
|
320
|
+
if (realRelativePath === ".." || realRelativePath.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`)) {
|
|
321
|
+
throw new Error("Service working directories must not escape the canonical target through symbolic links");
|
|
322
|
+
}
|
|
323
|
+
return serviceCwd;
|
|
324
|
+
};
|
|
325
|
+
const finalizeDurableRun = async (state, status, eventType, message) => {
|
|
326
|
+
const runId = state.execution_run_id;
|
|
327
|
+
if (!runId) {
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
const release = state.release_execution_environment;
|
|
331
|
+
if (release) {
|
|
332
|
+
try {
|
|
333
|
+
await release();
|
|
334
|
+
state.release_execution_environment = null;
|
|
335
|
+
}
|
|
336
|
+
catch (error) {
|
|
337
|
+
recordServiceRunReleaseFailure({
|
|
338
|
+
projectId: state.execution_project_id,
|
|
339
|
+
executionRunId: runId,
|
|
340
|
+
message: getErrorMessage(error),
|
|
341
|
+
intendedStatus: status,
|
|
342
|
+
intendedEventType: eventType,
|
|
343
|
+
});
|
|
344
|
+
throw error;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
completeServiceRun({
|
|
348
|
+
projectId: state.execution_project_id,
|
|
349
|
+
executionRunId: runId,
|
|
350
|
+
status,
|
|
351
|
+
code: status === "failed" ? "service_run_failed" : null,
|
|
352
|
+
message,
|
|
353
|
+
eventType,
|
|
354
|
+
});
|
|
355
|
+
};
|
|
356
|
+
const stopRunProcesses = async (state) => {
|
|
357
|
+
for (const proc of state.processes) {
|
|
358
|
+
killManagedProcess(proc, "SIGTERM");
|
|
359
|
+
}
|
|
360
|
+
await waitForProcessesToExit(state.processes, 1000);
|
|
361
|
+
for (const proc of state.processes) {
|
|
362
|
+
if (isProcessAlive(proc)) {
|
|
363
|
+
killManagedProcess(proc, "SIGKILL");
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
await waitForProcessesToExit(state.processes, 1000);
|
|
367
|
+
};
|
|
368
|
+
const startRun = async ({ activeRun, cwd, logLabelPrefix, onStopped, project, runConfig, skipSetup = false, targetDescriptor, }) => {
|
|
280
369
|
const contextKey = activeRun.context_key;
|
|
281
370
|
const state = {
|
|
282
371
|
processes: [],
|
|
@@ -284,6 +373,10 @@ const startRun = async ({ activeRun, cwd, logLabelPrefix, onStopped, project, ru
|
|
|
284
373
|
active_run: activeRun,
|
|
285
374
|
preview_status: createRunPreviewStatus(project, runConfig),
|
|
286
375
|
preview_log_buffer: "",
|
|
376
|
+
execution_run_id: null,
|
|
377
|
+
execution_handles: [],
|
|
378
|
+
release_execution_environment: null,
|
|
379
|
+
execution_project_id: null,
|
|
287
380
|
};
|
|
288
381
|
runningProcesses.set(contextKey, state);
|
|
289
382
|
if (!existsSync(cwd)) {
|
|
@@ -291,12 +384,102 @@ const startRun = async ({ activeRun, cwd, logLabelPrefix, onStopped, project, ru
|
|
|
291
384
|
clearRunState(contextKey, state, onStopped);
|
|
292
385
|
return;
|
|
293
386
|
}
|
|
387
|
+
let execution = null;
|
|
388
|
+
let executionTarget = null;
|
|
389
|
+
if (canCreateDurableServiceRun(project, targetDescriptor)) {
|
|
390
|
+
try {
|
|
391
|
+
const target = await resolveExecutionTarget({
|
|
392
|
+
project,
|
|
393
|
+
descriptor: targetDescriptor,
|
|
394
|
+
expectedWorkspacePath: cwd,
|
|
395
|
+
});
|
|
396
|
+
if (!isActiveRunState(contextKey, state)) {
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
executionTarget = target;
|
|
400
|
+
const source = activeRun.kind === "ticket"
|
|
401
|
+
? {
|
|
402
|
+
kind: "ticket",
|
|
403
|
+
id: activeRun.ticket_id,
|
|
404
|
+
bundleId: target.identity.kind === "bundle-worktree"
|
|
405
|
+
? target.identity.bundleId
|
|
406
|
+
: null,
|
|
407
|
+
}
|
|
408
|
+
: { kind: "project", id: project.id };
|
|
409
|
+
const durableRun = createServiceRun({
|
|
410
|
+
projectId: project.id,
|
|
411
|
+
contextKey,
|
|
412
|
+
source,
|
|
413
|
+
target,
|
|
414
|
+
services: runConfig.services ?? [],
|
|
415
|
+
});
|
|
416
|
+
state.execution_run_id = durableRun.id;
|
|
417
|
+
state.execution_project_id = project.id;
|
|
418
|
+
if (!isActiveRunState(contextKey, state)) {
|
|
419
|
+
await finalizeDurableRun(state, "cancelled", "service_run_cancelled");
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
execution = await resolveWorkloadExecutionEnvironment({
|
|
423
|
+
project,
|
|
424
|
+
executionRunId: durableRun.id,
|
|
425
|
+
agent: getServiceExecutionAgent(project),
|
|
426
|
+
model: project.helper_model,
|
|
427
|
+
target,
|
|
428
|
+
workload: "service",
|
|
429
|
+
onLeaseAcquired: release => {
|
|
430
|
+
state.release_execution_environment = release;
|
|
431
|
+
},
|
|
432
|
+
});
|
|
433
|
+
state.release_execution_environment = execution.release;
|
|
434
|
+
if (!isActiveRunState(contextKey, state)) {
|
|
435
|
+
await finalizeDurableRun(state, "cancelled", "service_run_cancelled");
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
state.execution_provider = execution.provider.kind === "docker_sandbox"
|
|
439
|
+
? "docker_sandbox"
|
|
440
|
+
: "host";
|
|
441
|
+
state.preview_status = createRunPreviewStatus(project, runConfig, state.execution_provider);
|
|
442
|
+
transitionExecutionRun({
|
|
443
|
+
projectId: project.id,
|
|
444
|
+
runId: durableRun.id,
|
|
445
|
+
status: "running",
|
|
446
|
+
domainStatus: "starting",
|
|
447
|
+
eventType: "service_run_starting",
|
|
448
|
+
eventMessage: "Service execution provider and canonical target authority were resolved.",
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
catch (error) {
|
|
452
|
+
if (state.execution_run_id) {
|
|
453
|
+
await finalizeDurableRun(state, "failed", "service_run_start_failed", getErrorMessage(error)).catch(releaseError => {
|
|
454
|
+
console.error("[run] service environment release failed:", getErrorMessage(releaseError));
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
console.error(`[run] durable service start failed for ${logLabelPrefix}:`, getErrorMessage(error));
|
|
458
|
+
clearRunState(contextKey, state, onStopped);
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
294
462
|
if (!skipSetup) {
|
|
295
463
|
try {
|
|
296
|
-
|
|
297
|
-
await
|
|
298
|
-
|
|
299
|
-
|
|
464
|
+
if (execution) {
|
|
465
|
+
await runSetupCommandsInWorkspace(project, cwd, {
|
|
466
|
+
provider: execution.provider,
|
|
467
|
+
target: executionTarget,
|
|
468
|
+
launcherEnvironment: execution.launcherEnvironment,
|
|
469
|
+
runtimeEnvironment: execution.runtimeEnvironment,
|
|
470
|
+
onHandle: handle => {
|
|
471
|
+
if (handle) {
|
|
472
|
+
trackExecutionHandle(state, handle);
|
|
473
|
+
}
|
|
474
|
+
},
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
else {
|
|
478
|
+
for (const cmd of runConfig.setup ?? []) {
|
|
479
|
+
await runCommand(cmd, cwd, state);
|
|
480
|
+
if (!isActiveRunState(contextKey, state)) {
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
300
483
|
}
|
|
301
484
|
}
|
|
302
485
|
}
|
|
@@ -305,6 +488,7 @@ const startRun = async ({ activeRun, cwd, logLabelPrefix, onStopped, project, ru
|
|
|
305
488
|
return;
|
|
306
489
|
}
|
|
307
490
|
console.error(`[run] setup failed for ${logLabelPrefix}:`, getErrorMessage(err));
|
|
491
|
+
await finalizeDurableRun(state, "failed", "service_setup_failed", getErrorMessage(err)).catch(releaseError => console.error("[run] service environment release failed:", getErrorMessage(releaseError)));
|
|
308
492
|
clearRunState(contextKey, state, onStopped);
|
|
309
493
|
return;
|
|
310
494
|
}
|
|
@@ -312,80 +496,175 @@ const startRun = async ({ activeRun, cwd, logLabelPrefix, onStopped, project, ru
|
|
|
312
496
|
if (!isActiveRunState(contextKey, state)) {
|
|
313
497
|
return;
|
|
314
498
|
}
|
|
499
|
+
let serviceFailureMessage = null;
|
|
500
|
+
let startupComplete = false;
|
|
315
501
|
const cleanupIfAllDead = () => {
|
|
316
|
-
if (runningProcesses.get(contextKey) !== state || state.cancelled) {
|
|
502
|
+
if (!startupComplete || runningProcesses.get(contextKey) !== state || state.cancelled) {
|
|
317
503
|
return;
|
|
318
504
|
}
|
|
319
505
|
const anyAlive = state.processes.some(isProcessAlive);
|
|
320
506
|
if (!anyAlive) {
|
|
321
|
-
|
|
507
|
+
void finalizeDurableRun(state, serviceFailureMessage ? "failed" : "completed", serviceFailureMessage ? "service_run_failed" : "service_run_completed", serviceFailureMessage ?? undefined)
|
|
508
|
+
.catch(error => console.error("[run] service environment release failed:", getErrorMessage(error)))
|
|
509
|
+
.finally(() => clearRunState(contextKey, state, onStopped));
|
|
322
510
|
}
|
|
323
511
|
};
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
const
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
512
|
+
let configuredServices;
|
|
513
|
+
try {
|
|
514
|
+
configuredServices = (runConfig.services ?? []).map(service => ({
|
|
515
|
+
service,
|
|
516
|
+
cwd: resolveServiceCwd(cwd, service.cwd),
|
|
517
|
+
}));
|
|
518
|
+
}
|
|
519
|
+
catch (error) {
|
|
520
|
+
await finalizeDurableRun(state, "failed", "service_configuration_invalid", getErrorMessage(error)).catch(releaseError => console.error("[run] service environment release failed:", getErrorMessage(releaseError)));
|
|
521
|
+
clearRunState(contextKey, state, onStopped);
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
try {
|
|
525
|
+
for (const { service, cwd: serviceCwd } of configuredServices) {
|
|
526
|
+
const label = service.name ?? service.cmd;
|
|
527
|
+
let handle = null;
|
|
528
|
+
const proc = execution
|
|
529
|
+
? (() => {
|
|
530
|
+
const shell = getExecutionShell(execution.provider, execution.runtimeEnvironment, service.cmd);
|
|
531
|
+
handle = execution.provider.execute({
|
|
532
|
+
phase: "service",
|
|
533
|
+
target: executionTarget,
|
|
534
|
+
command: shell.command,
|
|
535
|
+
args: shell.args,
|
|
536
|
+
cwd: serviceCwd,
|
|
537
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
538
|
+
launcherEnvironment: execution.launcherEnvironment,
|
|
539
|
+
runtimeEnvironment: execution.runtimeEnvironment,
|
|
540
|
+
detached: process.platform !== "win32",
|
|
541
|
+
});
|
|
542
|
+
return trackExecutionHandle(state, handle);
|
|
543
|
+
})()
|
|
544
|
+
: spawnManagedProcess(service.cmd, serviceCwd, ["ignore", "pipe", "pipe"], state);
|
|
545
|
+
const handleLogChunk = (data) => {
|
|
546
|
+
if (!isPreviewService(service, state.preview_status)) {
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
549
|
+
state.preview_log_buffer = normalizePreviewLogText(`${state.preview_log_buffer}${data.toString()}`).slice(-MAX_PREVIEW_LOG_BUFFER_CHARS);
|
|
550
|
+
const detectedTargets = detectPreviewTargets(state.preview_log_buffer, state.preview_status.capability);
|
|
551
|
+
const previewTargets = detectedTargets.length > 0
|
|
552
|
+
? detectedTargets
|
|
553
|
+
: inferPreviewTargetsFromLogChunk(state.preview_log_buffer, project, service, state.preview_status.capability);
|
|
554
|
+
if (previewTargets.length === 0) {
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
void (async () => {
|
|
558
|
+
for (const detectedTarget of previewTargets) {
|
|
559
|
+
const reachableTarget = await resolveReachablePreviewTarget(detectedTarget, project.preview_path);
|
|
560
|
+
if (!reachableTarget || !isActiveRunState(contextKey, state)) {
|
|
561
|
+
continue;
|
|
562
|
+
}
|
|
563
|
+
if (state.preview_status.detected_url === reachableTarget.url &&
|
|
564
|
+
state.preview_status.proxy_url) {
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
567
|
+
try {
|
|
568
|
+
const proxyOrigin = await ensurePreviewProxyForProject(project.id, reachableTarget.url);
|
|
569
|
+
state.preview_status = {
|
|
570
|
+
...applyDetectedPreviewTarget(state.preview_status, reachableTarget),
|
|
571
|
+
proxy_url: buildPreviewProxyUrl(proxyOrigin, reachableTarget.url),
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
catch (error) {
|
|
575
|
+
state.preview_status = {
|
|
576
|
+
...state.preview_status,
|
|
577
|
+
state: "error",
|
|
578
|
+
proxy_url: null,
|
|
579
|
+
message: getErrorMessage(error) || "Preview proxy failed",
|
|
580
|
+
};
|
|
581
|
+
}
|
|
348
582
|
return;
|
|
349
583
|
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
584
|
+
})();
|
|
585
|
+
};
|
|
586
|
+
proc.stdout?.on("data", (data) => {
|
|
587
|
+
console.log(`[run:${logLabelPrefix}:${label}] ${data.toString().trimEnd()}`);
|
|
588
|
+
handleLogChunk(data);
|
|
589
|
+
});
|
|
590
|
+
proc.stderr?.on("data", (data) => {
|
|
591
|
+
console.error(`[run:${logLabelPrefix}:${label}] ${data.toString().trimEnd()}`);
|
|
592
|
+
handleLogChunk(data);
|
|
593
|
+
});
|
|
594
|
+
proc.on("close", (code) => {
|
|
595
|
+
console.log(`[run:${logLabelPrefix}:${label}] exited with code ${code}`);
|
|
596
|
+
if (code !== 0 && !state.cancelled) {
|
|
597
|
+
serviceFailureMessage = `Service ${label} exited with code ${code ?? "unknown"}.`;
|
|
598
|
+
}
|
|
599
|
+
cleanupIfAllDead();
|
|
600
|
+
});
|
|
601
|
+
proc.on("error", (err) => {
|
|
602
|
+
console.error(`[run:${logLabelPrefix}:${label}] error: ${getErrorMessage(err)}`);
|
|
603
|
+
if (!state.cancelled) {
|
|
604
|
+
serviceFailureMessage = `Service ${label} failed: ${getErrorMessage(err)}`;
|
|
605
|
+
}
|
|
606
|
+
cleanupIfAllDead();
|
|
607
|
+
});
|
|
608
|
+
if (handle) {
|
|
609
|
+
const placementFailure = await handle.placementFailure;
|
|
610
|
+
if (!isActiveRunState(contextKey, state)) {
|
|
365
611
|
return;
|
|
366
612
|
}
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
613
|
+
if (placementFailure) {
|
|
614
|
+
throw placementFailure;
|
|
615
|
+
}
|
|
616
|
+
const placement = await handle.placementIdentity;
|
|
617
|
+
if (!isActiveRunState(contextKey, state)) {
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
recordServiceRunPlacement({
|
|
621
|
+
projectId: project.id,
|
|
622
|
+
executionRunId: state.execution_run_id,
|
|
623
|
+
provider: state.execution_provider,
|
|
624
|
+
environmentId: execution?.environment?.id ?? null,
|
|
625
|
+
environmentRevision: execution?.environment?.environment_revision ?? null,
|
|
626
|
+
placement,
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
catch (error) {
|
|
632
|
+
await stopRunProcesses(state);
|
|
633
|
+
await finalizeDurableRun(state, "failed", "service_placement_failed", getErrorMessage(error)).catch(releaseError => console.error("[run] service environment release failed:", getErrorMessage(releaseError)));
|
|
634
|
+
clearRunState(contextKey, state, onStopped);
|
|
635
|
+
return;
|
|
636
|
+
}
|
|
637
|
+
if (state.execution_run_id && execution && (runConfig.services ?? []).length === 0) {
|
|
638
|
+
recordServiceRunPlacement({
|
|
639
|
+
projectId: project.id,
|
|
640
|
+
executionRunId: state.execution_run_id,
|
|
641
|
+
provider: state.execution_provider,
|
|
642
|
+
environmentId: execution.environment?.id ?? null,
|
|
643
|
+
environmentRevision: execution.environment?.environment_revision ?? null,
|
|
384
644
|
});
|
|
385
645
|
}
|
|
386
646
|
if (!isActiveRunState(contextKey, state)) {
|
|
387
647
|
return;
|
|
388
648
|
}
|
|
649
|
+
if (state.execution_run_id) {
|
|
650
|
+
transitionExecutionRun({
|
|
651
|
+
projectId: project.id,
|
|
652
|
+
runId: state.execution_run_id,
|
|
653
|
+
status: "running",
|
|
654
|
+
domainStatus: "active",
|
|
655
|
+
eventType: "service_run_active",
|
|
656
|
+
eventMessage: state.execution_provider === "docker_sandbox"
|
|
657
|
+
? "Services are active in a shared Docker Sandbox environment; interruption applies to the whole environment."
|
|
658
|
+
: "Services are active as verified host processes.",
|
|
659
|
+
});
|
|
660
|
+
}
|
|
661
|
+
if ((runConfig.services ?? []).length === 0) {
|
|
662
|
+
await finalizeDurableRun(state, "completed", "service_run_completed").catch(error => console.error("[run] service environment release failed:", getErrorMessage(error)));
|
|
663
|
+
clearRunState(contextKey, state, onStopped);
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
666
|
+
startupComplete = true;
|
|
667
|
+
cleanupIfAllDead();
|
|
389
668
|
};
|
|
390
669
|
export const stopAllTickets = async () => {
|
|
391
670
|
const contextKeys = [...runningProcesses.keys()];
|
|
@@ -401,17 +680,10 @@ export const stopTicket = async (ticketOrKey) => {
|
|
|
401
680
|
return;
|
|
402
681
|
}
|
|
403
682
|
state.cancelled = true;
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
await waitForProcessesToExit(processes, 5000);
|
|
409
|
-
for (const proc of processes) {
|
|
410
|
-
if (isProcessAlive(proc)) {
|
|
411
|
-
killManagedProcess(proc, "SIGKILL");
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
await waitForProcessesToExit(processes, 1000);
|
|
683
|
+
await stopRunProcesses(state);
|
|
684
|
+
await finalizeDurableRun(state, "cancelled", "service_run_cancelled", state.execution_provider === "docker_sandbox"
|
|
685
|
+
? "The service run was stopped. Docker Sandbox interruption stops the whole environment and every attached service."
|
|
686
|
+
: "The service run host processes were stopped.").catch(error => console.error("[run] service environment release failed:", getErrorMessage(error)));
|
|
415
687
|
if (runningProcesses.get(contextKey) === state) {
|
|
416
688
|
deactivatePreviewProxyForProject(state.active_run.project_id);
|
|
417
689
|
state.preview_log_buffer = "";
|
|
@@ -445,6 +717,13 @@ export const runTicketInWorkspace = async (ticket, io, project = null, workspace
|
|
|
445
717
|
project: project,
|
|
446
718
|
runConfig,
|
|
447
719
|
skipSetup: isTicketRunSetupReady(ticket),
|
|
720
|
+
targetDescriptor: branch
|
|
721
|
+
? classifyTicketExecutionTarget({
|
|
722
|
+
branch,
|
|
723
|
+
bundleId: ticket.worktree_bundle_id ?? null,
|
|
724
|
+
bundleKind: ticket.bundle?.kind ?? null,
|
|
725
|
+
})
|
|
726
|
+
: undefined,
|
|
448
727
|
});
|
|
449
728
|
};
|
|
450
729
|
export const runProject = async (project, options = {}) => {
|
|
@@ -469,6 +748,17 @@ export const runProject = async (project, options = {}) => {
|
|
|
469
748
|
logLabelPrefix: `project:${project.id}`,
|
|
470
749
|
project,
|
|
471
750
|
runConfig,
|
|
751
|
+
targetDescriptor: targetKind === "bundle" && targetBundleId
|
|
752
|
+
? {
|
|
753
|
+
kind: "bundle-worktree",
|
|
754
|
+
bundleId: targetBundleId,
|
|
755
|
+
branch: options.targetBranch ?? "",
|
|
756
|
+
}
|
|
757
|
+
: {
|
|
758
|
+
kind: "project-root",
|
|
759
|
+
bundleId: null,
|
|
760
|
+
branch: options.targetBranch ?? null,
|
|
761
|
+
},
|
|
472
762
|
});
|
|
473
763
|
};
|
|
474
764
|
export const stopProjectRun = async (projectId, target = {}) => {
|