rivet-design 0.10.7 → 0.10.9
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/index.d.ts +54 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +302 -129
- package/dist/index.js.map +1 -1
- package/dist/mcp/agent-variants/SessionStore.d.ts +23 -1
- package/dist/mcp/agent-variants/SessionStore.d.ts.map +1 -1
- package/dist/mcp/agent-variants/SessionStore.js +42 -0
- package/dist/mcp/agent-variants/SessionStore.js.map +1 -1
- package/dist/mcp/agent-variants/WorktreeOrchestrator.d.ts +99 -2
- package/dist/mcp/agent-variants/WorktreeOrchestrator.d.ts.map +1 -1
- package/dist/mcp/agent-variants/WorktreeOrchestrator.js +734 -74
- package/dist/mcp/agent-variants/WorktreeOrchestrator.js.map +1 -1
- package/dist/mcp/agent-variants/WorktreeOrchestrator.testHelpers.d.ts +8 -2
- package/dist/mcp/agent-variants/WorktreeOrchestrator.testHelpers.d.ts.map +1 -1
- package/dist/mcp/agent-variants/WorktreeOrchestrator.testHelpers.js +24 -5
- package/dist/mcp/agent-variants/WorktreeOrchestrator.testHelpers.js.map +1 -1
- package/dist/mcp/agent-variants/contracts.d.ts +1175 -233
- package/dist/mcp/agent-variants/contracts.d.ts.map +1 -1
- package/dist/mcp/agent-variants/contracts.js +12 -4
- package/dist/mcp/agent-variants/contracts.js.map +1 -1
- package/dist/mcp/agent-variants/designCritique.d.ts +163 -0
- package/dist/mcp/agent-variants/designCritique.d.ts.map +1 -0
- package/dist/mcp/agent-variants/designCritique.js +710 -0
- package/dist/mcp/agent-variants/designCritique.js.map +1 -0
- package/dist/mcp/agent-variants/diffQa.d.ts +7 -0
- package/dist/mcp/agent-variants/diffQa.d.ts.map +1 -0
- package/dist/mcp/agent-variants/diffQa.js +67 -0
- package/dist/mcp/agent-variants/diffQa.js.map +1 -0
- package/dist/mcp/agent-variants/index.d.ts +2 -2
- package/dist/mcp/agent-variants/index.d.ts.map +1 -1
- package/dist/mcp/agent-variants/index.js +2 -1
- package/dist/mcp/agent-variants/index.js.map +1 -1
- package/dist/mcp/agent-variants/pinterestSourceContext.d.ts.map +1 -1
- package/dist/mcp/agent-variants/pinterestSourceContext.js +11 -1
- package/dist/mcp/agent-variants/pinterestSourceContext.js.map +1 -1
- package/dist/mcp/agent-variants/previewQa.d.ts.map +1 -1
- package/dist/mcp/agent-variants/previewQa.js +7 -0
- package/dist/mcp/agent-variants/previewQa.js.map +1 -1
- package/dist/mcp/agent-variants/tools.d.ts.map +1 -1
- package/dist/mcp/agent-variants/tools.js +15 -5
- package/dist/mcp/agent-variants/tools.js.map +1 -1
- package/dist/mcp/auth/httpOAuthProvider.d.ts +103 -0
- package/dist/mcp/auth/httpOAuthProvider.d.ts.map +1 -0
- package/dist/mcp/auth/httpOAuthProvider.js +454 -0
- package/dist/mcp/auth/httpOAuthProvider.js.map +1 -0
- package/dist/mcp/auth/tools.d.ts +2 -0
- package/dist/mcp/auth/tools.d.ts.map +1 -1
- package/dist/mcp/auth/tools.js +12 -5
- package/dist/mcp/auth/tools.js.map +1 -1
- package/dist/mcp/httpServer.d.ts +36 -0
- package/dist/mcp/httpServer.d.ts.map +1 -0
- package/dist/mcp/httpServer.js +307 -0
- package/dist/mcp/httpServer.js.map +1 -0
- package/dist/mcp/server.d.ts +17 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +50 -29
- package/dist/mcp/server.js.map +1 -1
- package/dist/proxy-middleware/proxy-config.d.ts.map +1 -1
- package/dist/proxy-middleware/proxy-config.js +5 -2
- package/dist/proxy-middleware/proxy-config.js.map +1 -1
- package/dist/routes/agentVariants.d.ts +2 -1
- package/dist/routes/agentVariants.d.ts.map +1 -1
- package/dist/routes/agentVariants.js +268 -19
- package/dist/routes/agentVariants.js.map +1 -1
- package/dist/routes/design.d.ts.map +1 -1
- package/dist/routes/design.js +0 -122
- package/dist/routes/design.js.map +1 -1
- package/dist/routes/mcp.d.ts.map +1 -1
- package/dist/routes/mcp.js +2 -1
- package/dist/routes/mcp.js.map +1 -1
- package/dist/server.d.ts +15 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +24 -11
- package/dist/server.js.map +1 -1
- package/dist/services/AgentSessionService.d.ts +5 -1
- package/dist/services/AgentSessionService.d.ts.map +1 -1
- package/dist/services/AgentSessionService.js +11 -4
- package/dist/services/AgentSessionService.js.map +1 -1
- package/dist/services/AuthService.d.ts +1 -0
- package/dist/services/AuthService.d.ts.map +1 -1
- package/dist/services/AuthService.js +11 -1
- package/dist/services/AuthService.js.map +1 -1
- package/dist/services/ConfigManager.d.ts +5 -0
- package/dist/services/ConfigManager.d.ts.map +1 -1
- package/dist/services/ConfigManager.js +25 -3
- package/dist/services/ConfigManager.js.map +1 -1
- package/dist/services/DevServerRuntimeService.d.ts +119 -0
- package/dist/services/DevServerRuntimeService.d.ts.map +1 -0
- package/dist/services/DevServerRuntimeService.js +657 -0
- package/dist/services/DevServerRuntimeService.js.map +1 -0
- package/dist/services/GatewayClient.d.ts +25 -0
- package/dist/services/GatewayClient.d.ts.map +1 -1
- package/dist/services/GatewayClient.js +70 -11
- package/dist/services/GatewayClient.js.map +1 -1
- package/dist/services/InlineVariantGenerationService.d.ts +2 -3
- package/dist/services/InlineVariantGenerationService.d.ts.map +1 -1
- package/dist/services/InlineVariantGenerationService.js +7 -5
- package/dist/services/InlineVariantGenerationService.js.map +1 -1
- package/dist/services/IntegrationsClient.d.ts +20 -0
- package/dist/services/IntegrationsClient.d.ts.map +1 -1
- package/dist/services/IntegrationsClient.js +82 -24
- package/dist/services/IntegrationsClient.js.map +1 -1
- package/dist/services/RequestAuthContext.d.ts +7 -1
- package/dist/services/RequestAuthContext.d.ts.map +1 -1
- package/dist/services/RequestAuthContext.js +15 -2
- package/dist/services/RequestAuthContext.js.map +1 -1
- package/dist/services/SessionBridgeService.d.ts +1 -0
- package/dist/services/SessionBridgeService.d.ts.map +1 -1
- package/dist/services/SessionBridgeService.js +16 -1
- package/dist/services/SessionBridgeService.js.map +1 -1
- package/dist/services/TelemetryService.d.ts +2 -0
- package/dist/services/TelemetryService.d.ts.map +1 -1
- package/dist/services/TelemetryService.js +2 -0
- package/dist/services/TelemetryService.js.map +1 -1
- package/dist/services/VariantHistoryService.d.ts +8 -0
- package/dist/services/VariantHistoryService.d.ts.map +1 -1
- package/dist/services/VariantHistoryService.js +23 -0
- package/dist/services/VariantHistoryService.js.map +1 -1
- package/dist/services/VariantRunService.d.ts +56 -0
- package/dist/services/VariantRunService.d.ts.map +1 -0
- package/dist/services/VariantRunService.js +56 -0
- package/dist/services/VariantRunService.js.map +1 -0
- package/dist/services/VariantsRuntime.d.ts +22 -0
- package/dist/services/VariantsRuntime.d.ts.map +1 -0
- package/dist/services/VariantsRuntime.js +32 -0
- package/dist/services/VariantsRuntime.js.map +1 -0
- package/dist/services/VisualVariantAgentRunner.d.ts +20 -0
- package/dist/services/VisualVariantAgentRunner.d.ts.map +1 -0
- package/dist/services/VisualVariantAgentRunner.js +66 -0
- package/dist/services/VisualVariantAgentRunner.js.map +1 -0
- package/dist/services/WorktreeManager.d.ts +34 -0
- package/dist/services/WorktreeManager.d.ts.map +1 -1
- package/dist/services/WorktreeManager.js +172 -23
- package/dist/services/WorktreeManager.js.map +1 -1
- package/dist/services/createAgentVariantsOrchestrator.d.ts.map +1 -1
- package/dist/services/createAgentVariantsOrchestrator.js +9 -0
- package/dist/services/createAgentVariantsOrchestrator.js.map +1 -1
- package/dist/utils/devServerCommand.d.ts +11 -4
- package/dist/utils/devServerCommand.d.ts.map +1 -1
- package/dist/utils/devServerCommand.js +17 -8
- package/dist/utils/devServerCommand.js.map +1 -1
- package/dist/utils/devServerError.d.ts +34 -0
- package/dist/utils/devServerError.d.ts.map +1 -0
- package/dist/utils/devServerError.js +39 -0
- package/dist/utils/devServerError.js.map +1 -0
- package/dist/utils/elementRefToContext.d.ts +4 -0
- package/dist/utils/elementRefToContext.d.ts.map +1 -0
- package/dist/utils/elementRefToContext.js +63 -0
- package/dist/utils/elementRefToContext.js.map +1 -0
- package/dist/utils/skills/shared-variants-protocol.d.ts.map +1 -1
- package/dist/utils/skills/shared-variants-protocol.js +5 -2
- package/dist/utils/skills/shared-variants-protocol.js.map +1 -1
- package/dist/utils/variantSessionStart.d.ts +3 -0
- package/dist/utils/variantSessionStart.d.ts.map +1 -0
- package/dist/utils/variantSessionStart.js +7 -0
- package/dist/utils/variantSessionStart.js.map +1 -0
- package/package.json +3 -1
- package/src/ui/dist/assets/main-Cwwhwfjq.js +645 -0
- package/src/ui/dist/assets/main-Do6whVIm.css +1 -0
- package/src/ui/dist/index.html +2 -2
- package/dist/services/CommentVariationService.d.ts +0 -34
- package/dist/services/CommentVariationService.d.ts.map +0 -1
- package/dist/services/CommentVariationService.js +0 -136
- package/dist/services/CommentVariationService.js.map +0 -1
- package/dist/services/VariantCodeGeneratorService.d.ts +0 -39
- package/dist/services/VariantCodeGeneratorService.d.ts.map +0 -1
- package/dist/services/VariantCodeGeneratorService.js +0 -109
- package/dist/services/VariantCodeGeneratorService.js.map +0 -1
- package/src/ui/dist/assets/main-DUIrSkV3.css +0 -1
- package/src/ui/dist/assets/main-DYpxGvCu.js +0 -646
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.VariantRunService = void 0;
|
|
4
|
+
const InlineVariantGenerationService_1 = require("./InlineVariantGenerationService");
|
|
5
|
+
/**
|
|
6
|
+
* Product-facing entry point for variant runs.
|
|
7
|
+
*
|
|
8
|
+
* Keeps callers independent from the lower-level variants state machine so
|
|
9
|
+
* desktop UI, MCP requests, and future hosted workers can start/refine/commit
|
|
10
|
+
* variants through the same lifecycle.
|
|
11
|
+
*/
|
|
12
|
+
class VariantRunService {
|
|
13
|
+
orchestrator;
|
|
14
|
+
elementVariantService;
|
|
15
|
+
constructor(options) {
|
|
16
|
+
this.orchestrator = options.orchestrator;
|
|
17
|
+
this.elementVariantService = new InlineVariantGenerationService_1.InlineVariantGenerationService({
|
|
18
|
+
bridge: options.bridge,
|
|
19
|
+
orchestrator: options.orchestrator,
|
|
20
|
+
runner: options.runner,
|
|
21
|
+
createSessionId: options.createSessionId,
|
|
22
|
+
leaseHeartbeatMs: options.leaseHeartbeatMs,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* @effect Starts variants for a selected/commented element using the shared
|
|
27
|
+
* variants lifecycle.
|
|
28
|
+
*/
|
|
29
|
+
async startElementVariants(request) {
|
|
30
|
+
return this.elementVariantService.processVariantRequest(request);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* @effect Starts a refinement work item for an existing static preview variant.
|
|
34
|
+
*/
|
|
35
|
+
refineVariant(args) {
|
|
36
|
+
return this.orchestrator.refineVariant(args);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* @effect Commits the chosen variant through the shared orchestrator path.
|
|
40
|
+
*/
|
|
41
|
+
commitVariant(args) {
|
|
42
|
+
return this.orchestrator.commitVariant(args);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* @effect Cancels a variants session and lets the orchestrator clean up.
|
|
46
|
+
*/
|
|
47
|
+
cancelVariants(args) {
|
|
48
|
+
return this.orchestrator.cancel(args);
|
|
49
|
+
}
|
|
50
|
+
/** Returns the active variants snapshot for UI and orchestration callers. */
|
|
51
|
+
getSnapshot() {
|
|
52
|
+
return this.orchestrator.buildActiveSnapshot();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
exports.VariantRunService = VariantRunService;
|
|
56
|
+
//# sourceMappingURL=VariantRunService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VariantRunService.js","sourceRoot":"","sources":["../../src/services/VariantRunService.ts"],"names":[],"mappings":";;;AAOA,qFAG0C;AAW1C;;;;;;GAMG;AACH,MAAa,iBAAiB;IACX,YAAY,CAA4B;IACxC,qBAAqB,CAAiC;IAEvE,YAAY,OAAiC;QAC3C,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;QACzC,IAAI,CAAC,qBAAqB,GAAG,IAAI,+DAA8B,CAAC;YAC9D,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,eAAe,EAAE,OAAO,CAAC,eAAe;YACxC,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;SAC3C,CAAC,CAAC;IACL,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,oBAAoB,CACxB,OAAsB;QAEtB,OAAO,IAAI,CAAC,qBAAqB,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC;IACnE,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,IAKb;QACC,OAAO,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAC/C,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,IAIb;QACC,OAAO,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAC/C,CAAC;IAED;;OAEG;IACH,cAAc,CAAC,IAGd;QACC,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACxC,CAAC;IAED,6EAA6E;IAC7E,WAAW;QACT,OAAO,IAAI,CAAC,YAAY,CAAC,mBAAmB,EAAE,CAAC;IACjD,CAAC;CACF;AA9DD,8CA8DC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { AgentVariantsOrchestrator } from '../mcp/agent-variants';
|
|
2
|
+
import { SessionBridgeService } from './SessionBridgeService';
|
|
3
|
+
import type { TelemetryService } from './TelemetryService';
|
|
4
|
+
import { VariantRunService } from './VariantRunService';
|
|
5
|
+
import type { InlineVariantAgentRunner } from './InlineVariantGenerationService';
|
|
6
|
+
export type VariantsRuntime = {
|
|
7
|
+
bridge: SessionBridgeService;
|
|
8
|
+
orchestrator: AgentVariantsOrchestrator;
|
|
9
|
+
runService: VariantRunService;
|
|
10
|
+
};
|
|
11
|
+
export type CreateVariantsRuntimeOptions = {
|
|
12
|
+
projectPath: string;
|
|
13
|
+
telemetry?: TelemetryService;
|
|
14
|
+
runner: InlineVariantAgentRunner;
|
|
15
|
+
devServerContext?: Parameters<SessionBridgeService['setDevServerContext']>[0];
|
|
16
|
+
devServerHealth?: Parameters<SessionBridgeService['updateDevServerHealth']>[0];
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Creates the shared runtime used to start, preview, refine, and commit variant sessions.
|
|
20
|
+
*/
|
|
21
|
+
export declare const createVariantsRuntime: (options: CreateVariantsRuntimeOptions) => VariantsRuntime;
|
|
22
|
+
//# sourceMappingURL=VariantsRuntime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VariantsRuntime.d.ts","sourceRoot":"","sources":["../../src/services/VariantsRuntime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAEvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAEjF,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,oBAAoB,CAAC;IAC7B,YAAY,EAAE,yBAAyB,CAAC;IACxC,UAAU,EAAE,iBAAiB,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,MAAM,EAAE,wBAAwB,CAAC;IACjC,gBAAgB,CAAC,EAAE,UAAU,CAAC,oBAAoB,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9E,eAAe,CAAC,EAAE,UAAU,CAC1B,oBAAoB,CAAC,uBAAuB,CAAC,CAC9C,CAAC,CAAC,CAAC,CAAC;CACN,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB,GAChC,SAAS,4BAA4B,KACpC,eAsBF,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createVariantsRuntime = void 0;
|
|
4
|
+
const createAgentVariantsOrchestrator_1 = require("./createAgentVariantsOrchestrator");
|
|
5
|
+
const SessionBridgeService_1 = require("./SessionBridgeService");
|
|
6
|
+
const VariantRunService_1 = require("./VariantRunService");
|
|
7
|
+
/**
|
|
8
|
+
* Creates the shared runtime used to start, preview, refine, and commit variant sessions.
|
|
9
|
+
*/
|
|
10
|
+
const createVariantsRuntime = (options) => {
|
|
11
|
+
const bridge = new SessionBridgeService_1.SessionBridgeService();
|
|
12
|
+
bridge.startSession(options.projectPath);
|
|
13
|
+
if (options.devServerContext) {
|
|
14
|
+
bridge.setDevServerContext(options.devServerContext);
|
|
15
|
+
}
|
|
16
|
+
if (options.devServerHealth) {
|
|
17
|
+
bridge.updateDevServerHealth(options.devServerHealth);
|
|
18
|
+
}
|
|
19
|
+
const orchestrator = (0, createAgentVariantsOrchestrator_1.createAgentVariantsOrchestrator)({
|
|
20
|
+
bridge,
|
|
21
|
+
telemetry: options.telemetry,
|
|
22
|
+
projectPathFallback: options.projectPath,
|
|
23
|
+
});
|
|
24
|
+
const runService = new VariantRunService_1.VariantRunService({
|
|
25
|
+
bridge,
|
|
26
|
+
orchestrator,
|
|
27
|
+
runner: options.runner,
|
|
28
|
+
});
|
|
29
|
+
return { bridge, orchestrator, runService };
|
|
30
|
+
};
|
|
31
|
+
exports.createVariantsRuntime = createVariantsRuntime;
|
|
32
|
+
//# sourceMappingURL=VariantsRuntime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VariantsRuntime.js","sourceRoot":"","sources":["../../src/services/VariantsRuntime.ts"],"names":[],"mappings":";;;AACA,uFAAoF;AACpF,iEAA8D;AAE9D,2DAAwD;AAmBxD;;GAEG;AACI,MAAM,qBAAqB,GAAG,CACnC,OAAqC,EACpB,EAAE;IACnB,MAAM,MAAM,GAAG,IAAI,2CAAoB,EAAE,CAAC;IAC1C,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACzC,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;QAC7B,MAAM,CAAC,mBAAmB,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACvD,CAAC;IACD,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;QAC5B,MAAM,CAAC,qBAAqB,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IACxD,CAAC;IAED,MAAM,YAAY,GAAG,IAAA,iEAA+B,EAAC;QACnD,MAAM;QACN,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,mBAAmB,EAAE,OAAO,CAAC,WAAW;KACzC,CAAC,CAAC;IACH,MAAM,UAAU,GAAG,IAAI,qCAAiB,CAAC;QACvC,MAAM;QACN,YAAY;QACZ,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAC;IAEH,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC;AAC9C,CAAC,CAAC;AAxBW,QAAA,qBAAqB,yBAwBhC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ChangeRequest } from '../types/change-request-types';
|
|
2
|
+
import type { InlineVariantAgentRunner } from './InlineVariantGenerationService';
|
|
3
|
+
import type { TerminalAgentRunResult } from './TerminalAgentRunner';
|
|
4
|
+
/**
|
|
5
|
+
* Runs variant work items through the visual editor's direct agent modification path.
|
|
6
|
+
*/
|
|
7
|
+
export declare class VisualVariantAgentRunner implements InlineVariantAgentRunner {
|
|
8
|
+
getDisplayName(): string;
|
|
9
|
+
/**
|
|
10
|
+
* @effect Executes a single variant request in the provided worktree and streams feedback to the variants lifecycle.
|
|
11
|
+
*/
|
|
12
|
+
runChangeRequest(params: {
|
|
13
|
+
request: ChangeRequest;
|
|
14
|
+
cwd: string;
|
|
15
|
+
sessionId: string;
|
|
16
|
+
resumeSession?: boolean;
|
|
17
|
+
onFeedback: (message: string) => void;
|
|
18
|
+
}): Promise<TerminalAgentRunResult>;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=VisualVariantAgentRunner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VisualVariantAgentRunner.d.ts","sourceRoot":"","sources":["../../src/services/VisualVariantAgentRunner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,aAAa,EAGd,MAAM,+BAA+B,CAAC;AAIvC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AACjF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAyCpE;;GAEG;AACH,qBAAa,wBAAyB,YAAW,wBAAwB;IACvE,cAAc,IAAI,MAAM;IAIxB;;OAEG;IACG,gBAAgB,CAAC,MAAM,EAAE;QAC7B,OAAO,EAAE,aAAa,CAAC;QACvB,GAAG,EAAE,MAAM,CAAC;QACZ,SAAS,EAAE,MAAM,CAAC;QAClB,aAAa,CAAC,EAAE,OAAO,CAAC;QACxB,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;KACvC,GAAG,OAAO,CAAC,sBAAsB,CAAC;CAsCpC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.VisualVariantAgentRunner = void 0;
|
|
4
|
+
const elementRefToContext_1 = require("../utils/elementRefToContext");
|
|
5
|
+
const agent_1 = require("./agent");
|
|
6
|
+
const commentChanges = (request) => request.changes.filter((change) => change.kind === 'comment');
|
|
7
|
+
const buildInstruction = (request) => {
|
|
8
|
+
const comments = commentChanges(request);
|
|
9
|
+
if (comments.length === 0) {
|
|
10
|
+
return 'Apply the requested variant changes.';
|
|
11
|
+
}
|
|
12
|
+
if (comments.length === 1) {
|
|
13
|
+
return comments[0].instruction;
|
|
14
|
+
}
|
|
15
|
+
return comments
|
|
16
|
+
.map((comment, index) => `Comment ${index + 1}: ${comment.instruction}`)
|
|
17
|
+
.join('\n\n');
|
|
18
|
+
};
|
|
19
|
+
const buildElements = (request) => {
|
|
20
|
+
const elements = commentChanges(request).flatMap((comment) => (comment.elements?.length ? comment.elements : [comment.element]).map(elementRefToContext_1.elementRefToContext));
|
|
21
|
+
if (elements.length > 0) {
|
|
22
|
+
return elements;
|
|
23
|
+
}
|
|
24
|
+
return request.changes
|
|
25
|
+
.filter((change) => 'element' in change)
|
|
26
|
+
.map((change) => (0, elementRefToContext_1.elementRefToContext)(change.element));
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Runs variant work items through the visual editor's direct agent modification path.
|
|
30
|
+
*/
|
|
31
|
+
class VisualVariantAgentRunner {
|
|
32
|
+
getDisplayName() {
|
|
33
|
+
return 'Rivet agent';
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* @effect Executes a single variant request in the provided worktree and streams feedback to the variants lifecycle.
|
|
37
|
+
*/
|
|
38
|
+
async runChangeRequest(params) {
|
|
39
|
+
const service = new agent_1.AgentModService(params.cwd);
|
|
40
|
+
const result = await service.executeAgenticModification(buildInstruction(params.request), buildElements(params.request), (event) => {
|
|
41
|
+
if (event.type === 'error' && event.error) {
|
|
42
|
+
params.onFeedback(event.error);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (event.type === 'step' && event.step?.type === 'reasoning') {
|
|
46
|
+
const data = event.step.data;
|
|
47
|
+
if (typeof data.text === 'string' && data.text.trim()) {
|
|
48
|
+
params.onFeedback(data.text.trim());
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}, undefined, undefined, params.resumeSession ? params.sessionId : undefined, undefined, {
|
|
52
|
+
traceId: params.request.traceId ?? params.sessionId,
|
|
53
|
+
agentRunId: params.request.agentRunId ?? params.sessionId,
|
|
54
|
+
posthogSessionId: params.request.telemetryContext?.browserSessionId ?? undefined,
|
|
55
|
+
});
|
|
56
|
+
if (!result.success) {
|
|
57
|
+
return {
|
|
58
|
+
success: false,
|
|
59
|
+
error: result.changes || 'Variant generation failed',
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
return { success: true };
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
exports.VisualVariantAgentRunner = VisualVariantAgentRunner;
|
|
66
|
+
//# sourceMappingURL=VisualVariantAgentRunner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VisualVariantAgentRunner.js","sourceRoot":"","sources":["../../src/services/VisualVariantAgentRunner.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,15 @@ export declare const FRESH_WORKTREES_DIRNAME = ".rivet-variants";
|
|
|
6
6
|
export declare const INSTANCE_PREFIX: string;
|
|
7
7
|
export declare class WorktreeManager {
|
|
8
8
|
private readonly resolveProjectPath;
|
|
9
|
+
/**
|
|
10
|
+
* Ports handed out by `findFreePortFrom` to a dev server that hasn't bound
|
|
11
|
+
* them yet. Until a port is actually listening, a bind/connect probe still
|
|
12
|
+
* sees it as free, so without this set two concurrent variant starts would
|
|
13
|
+
* both walk away with the same "free" port and collide. Released (see
|
|
14
|
+
* `releasePort`) once the dev server has bound the port — at which point the
|
|
15
|
+
* listener check sees it taken — or has failed to start.
|
|
16
|
+
*/
|
|
17
|
+
private readonly reservedPorts;
|
|
9
18
|
/**
|
|
10
19
|
* Accepts either a static path, null, or a lazy getter. The getter form
|
|
11
20
|
* lets long-lived callers (e.g. the agent-variants orchestrator) defer the
|
|
@@ -96,6 +105,31 @@ export declare class WorktreeManager {
|
|
|
96
105
|
applyDiffToProject(diff: string, projectPath: string): Promise<void>;
|
|
97
106
|
/** Bind port 0 to get an OS-assigned free port */
|
|
98
107
|
getFreePort(): Promise<number>;
|
|
108
|
+
/**
|
|
109
|
+
* Find a free port by scanning upward from `startPort` (the framework's
|
|
110
|
+
* default, e.g. 3000 for Next, 5173 for Vite). Returns the first port that is
|
|
111
|
+
* both bindable and not already reserved by a concurrent variant start, so a
|
|
112
|
+
* preview comes up on a sensible, predictable port near the project's normal
|
|
113
|
+
* one — and naturally steps past a port the user's own dev server already
|
|
114
|
+
* holds — instead of a random high port. Falls back to an OS-assigned port if
|
|
115
|
+
* the scan window is exhausted.
|
|
116
|
+
*
|
|
117
|
+
* Port availability is delegated to {@link findAvailablePort}, which (unlike a
|
|
118
|
+
* plain bind check) also rejects a port with an active listener on 127.0.0.1
|
|
119
|
+
* or ::1 — the ports that actually carry `localhost` preview traffic.
|
|
120
|
+
*
|
|
121
|
+
* The returned port is reserved synchronously; the caller MUST `releasePort`
|
|
122
|
+
* it once the dev server has bound it or failed to start (the orchestrator
|
|
123
|
+
* does this in a `finally`). Reserving here is what stops two concurrent
|
|
124
|
+
* starts — neither of which has bound its port yet — from both picking it.
|
|
125
|
+
*/
|
|
126
|
+
findFreePortFrom(startPort: number, scanWindow?: number): Promise<number>;
|
|
127
|
+
/**
|
|
128
|
+
* Release a port previously handed out by {@link findFreePortFrom}. Call once
|
|
129
|
+
* the dev server has bound it (the listener check now sees it taken, so the
|
|
130
|
+
* reservation is redundant) or has failed to start (the port is free again).
|
|
131
|
+
*/
|
|
132
|
+
releasePort(port: number): void;
|
|
99
133
|
/** Validate a diff via `git apply --check` without modifying files */
|
|
100
134
|
validateDiff(diff: string, reverse: boolean): Promise<void>;
|
|
101
135
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorktreeManager.d.ts","sourceRoot":"","sources":["../../src/services/WorktreeManager.ts"],"names":[],"mappings":"AAKA,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"WorktreeManager.d.ts","sourceRoot":"","sources":["../../src/services/WorktreeManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,7 +14,18 @@ const logger_1 = require("../utils/logger");
|
|
|
14
14
|
const designCatalog_1 = require("./templates/designCatalog");
|
|
15
15
|
const viteReactTs_1 = require("./templates/viteReactTs");
|
|
16
16
|
const sourceContext_1 = require("../mcp/agent-variants/sourceContext");
|
|
17
|
+
const devServerError_1 = require("../utils/devServerError");
|
|
18
|
+
const portUtils_1 = require("../utils/portUtils");
|
|
17
19
|
const log = (0, logger_1.createLogger)('WorktreeManager');
|
|
20
|
+
// How long to wait for a freshly-spawned dev server to answer on its port
|
|
21
|
+
// before giving up. Generous because cold Vite/Next boots (esp. first compile)
|
|
22
|
+
// can take 10s+. The probe now fails fast on early process exit, so this
|
|
23
|
+
// ceiling only governs the "spawned but slow / never serves our port" case.
|
|
24
|
+
const DEV_SERVER_READY_TIMEOUT_MS = 30_000;
|
|
25
|
+
// Keep a rolling tail of the dev server's output so a failed start is
|
|
26
|
+
// diagnosable (which port it tried, EADDRINUSE, missing script) without
|
|
27
|
+
// retaining unbounded logs.
|
|
28
|
+
const DEV_SERVER_OUTPUT_TAIL_LIMIT = 4_000;
|
|
18
29
|
// Abort any git child process that goes silent (no stdout/stderr) for this
|
|
19
30
|
// long. Provisioning worktrees for a large project (e.g. React Native, whose
|
|
20
31
|
// working tree carries native build dirs) used to hang indefinitely because
|
|
@@ -43,6 +54,15 @@ const FRESH_ROOTS_REGISTRY_PATH = path_1.default.join(os_1.default.homedir(), '.
|
|
|
43
54
|
const FRESH_SESSION_ERROR = 'Fresh-project sessions have no source project — this operation requires an existing project path.';
|
|
44
55
|
class WorktreeManager {
|
|
45
56
|
resolveProjectPath;
|
|
57
|
+
/**
|
|
58
|
+
* Ports handed out by `findFreePortFrom` to a dev server that hasn't bound
|
|
59
|
+
* them yet. Until a port is actually listening, a bind/connect probe still
|
|
60
|
+
* sees it as free, so without this set two concurrent variant starts would
|
|
61
|
+
* both walk away with the same "free" port and collide. Released (see
|
|
62
|
+
* `releasePort`) once the dev server has bound the port — at which point the
|
|
63
|
+
* listener check sees it taken — or has failed to start.
|
|
64
|
+
*/
|
|
65
|
+
reservedPorts = new Set();
|
|
46
66
|
/**
|
|
47
67
|
* Accepts either a static path, null, or a lazy getter. The getter form
|
|
48
68
|
* lets long-lived callers (e.g. the agent-variants orchestrator) defer the
|
|
@@ -184,8 +204,7 @@ class WorktreeManager {
|
|
|
184
204
|
symlinkNodeModulesIfAvailable(sourceRoot, destRoot) {
|
|
185
205
|
const nodeModulesSource = path_1.default.join(sourceRoot, 'node_modules');
|
|
186
206
|
const nodeModulesDest = path_1.default.join(destRoot, 'node_modules');
|
|
187
|
-
if (fs_1.default.existsSync(nodeModulesSource) &&
|
|
188
|
-
!fs_1.default.existsSync(nodeModulesDest)) {
|
|
207
|
+
if (fs_1.default.existsSync(nodeModulesSource) && !fs_1.default.existsSync(nodeModulesDest)) {
|
|
189
208
|
fs_1.default.mkdirSync(destRoot, { recursive: true });
|
|
190
209
|
fs_1.default.symlinkSync(nodeModulesSource, nodeModulesDest);
|
|
191
210
|
}
|
|
@@ -193,9 +212,14 @@ class WorktreeManager {
|
|
|
193
212
|
/** Apply a patch string via stdin to the given cwd using git apply */
|
|
194
213
|
applyPatchViaStdin(patch, cwd) {
|
|
195
214
|
return new Promise((resolve, reject) => {
|
|
196
|
-
const cp = (0, child_process_1.spawn)('git', ['apply', '--whitespace=nowarn', '-'], {
|
|
215
|
+
const cp = (0, child_process_1.spawn)('git', ['apply', '--whitespace=nowarn', '-'], {
|
|
216
|
+
cwd,
|
|
217
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
218
|
+
});
|
|
197
219
|
let stderr = '';
|
|
198
|
-
cp.stderr.on('data', (d) => {
|
|
220
|
+
cp.stderr.on('data', (d) => {
|
|
221
|
+
stderr += d.toString();
|
|
222
|
+
});
|
|
199
223
|
cp.on('close', (code) => {
|
|
200
224
|
if (code !== 0)
|
|
201
225
|
reject(new Error(`git apply failed: ${stderr}`));
|
|
@@ -314,7 +338,9 @@ class WorktreeManager {
|
|
|
314
338
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
315
339
|
});
|
|
316
340
|
let stderr = '';
|
|
317
|
-
cp.stderr.on('data', (d) => {
|
|
341
|
+
cp.stderr.on('data', (d) => {
|
|
342
|
+
stderr += d.toString();
|
|
343
|
+
});
|
|
318
344
|
cp.on('close', (code) => {
|
|
319
345
|
if (code !== 0)
|
|
320
346
|
reject(new Error(`git apply failed: ${stderr}`));
|
|
@@ -347,6 +373,62 @@ class WorktreeManager {
|
|
|
347
373
|
server.on('error', reject);
|
|
348
374
|
});
|
|
349
375
|
}
|
|
376
|
+
/**
|
|
377
|
+
* Find a free port by scanning upward from `startPort` (the framework's
|
|
378
|
+
* default, e.g. 3000 for Next, 5173 for Vite). Returns the first port that is
|
|
379
|
+
* both bindable and not already reserved by a concurrent variant start, so a
|
|
380
|
+
* preview comes up on a sensible, predictable port near the project's normal
|
|
381
|
+
* one — and naturally steps past a port the user's own dev server already
|
|
382
|
+
* holds — instead of a random high port. Falls back to an OS-assigned port if
|
|
383
|
+
* the scan window is exhausted.
|
|
384
|
+
*
|
|
385
|
+
* Port availability is delegated to {@link findAvailablePort}, which (unlike a
|
|
386
|
+
* plain bind check) also rejects a port with an active listener on 127.0.0.1
|
|
387
|
+
* or ::1 — the ports that actually carry `localhost` preview traffic.
|
|
388
|
+
*
|
|
389
|
+
* The returned port is reserved synchronously; the caller MUST `releasePort`
|
|
390
|
+
* it once the dev server has bound it or failed to start (the orchestrator
|
|
391
|
+
* does this in a `finally`). Reserving here is what stops two concurrent
|
|
392
|
+
* starts — neither of which has bound its port yet — from both picking it.
|
|
393
|
+
*/
|
|
394
|
+
async findFreePortFrom(startPort, scanWindow = 64) {
|
|
395
|
+
const base = Number.isInteger(startPort) && startPort > 0 && startPort <= 65535
|
|
396
|
+
? startPort
|
|
397
|
+
: 3000;
|
|
398
|
+
const limit = Math.min(65535, base + scanWindow - 1);
|
|
399
|
+
let from = base;
|
|
400
|
+
while (from <= limit) {
|
|
401
|
+
let candidate;
|
|
402
|
+
try {
|
|
403
|
+
candidate = await (0, portUtils_1.findAvailablePort)(from);
|
|
404
|
+
}
|
|
405
|
+
catch {
|
|
406
|
+
break; // no bindable port between `from` and 65535
|
|
407
|
+
}
|
|
408
|
+
if (candidate > limit)
|
|
409
|
+
break; // first free port is outside the scan window
|
|
410
|
+
// Check-and-claim with no `await` in between, so two concurrent callers
|
|
411
|
+
// can't both observe the same port as unreserved before claiming it.
|
|
412
|
+
if (!this.reservedPorts.has(candidate)) {
|
|
413
|
+
this.reservedPorts.add(candidate);
|
|
414
|
+
return candidate;
|
|
415
|
+
}
|
|
416
|
+
from = candidate + 1; // reserved by a sibling start — step past it
|
|
417
|
+
}
|
|
418
|
+
// Scan window exhausted (or every free port in it is reserved by a sibling
|
|
419
|
+
// that hasn't bound yet) — fall back to an OS-assigned ephemeral port.
|
|
420
|
+
const fallback = await this.getFreePort();
|
|
421
|
+
this.reservedPorts.add(fallback);
|
|
422
|
+
return fallback;
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Release a port previously handed out by {@link findFreePortFrom}. Call once
|
|
426
|
+
* the dev server has bound it (the listener check now sees it taken, so the
|
|
427
|
+
* reservation is redundant) or has failed to start (the port is free again).
|
|
428
|
+
*/
|
|
429
|
+
releasePort(port) {
|
|
430
|
+
this.reservedPorts.delete(port);
|
|
431
|
+
}
|
|
350
432
|
/** Validate a diff via `git apply --check` without modifying files */
|
|
351
433
|
validateDiff(diff, reverse) {
|
|
352
434
|
if (!diff.trim())
|
|
@@ -361,7 +443,9 @@ class WorktreeManager {
|
|
|
361
443
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
362
444
|
});
|
|
363
445
|
let stderr = '';
|
|
364
|
-
cp.stderr.on('data', (d) => {
|
|
446
|
+
cp.stderr.on('data', (d) => {
|
|
447
|
+
stderr += d.toString();
|
|
448
|
+
});
|
|
365
449
|
cp.on('close', (code) => {
|
|
366
450
|
if (code !== 0)
|
|
367
451
|
reject(new Error(`Diff validation failed: ${stderr.trim()}`));
|
|
@@ -383,50 +467,113 @@ class WorktreeManager {
|
|
|
383
467
|
stdio: 'pipe',
|
|
384
468
|
detached: false,
|
|
385
469
|
});
|
|
386
|
-
|
|
387
|
-
//
|
|
388
|
-
//
|
|
389
|
-
//
|
|
390
|
-
//
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
470
|
+
// Capture a rolling tail of the child's output so a failed start is
|
|
471
|
+
// diagnosable (EADDRINUSE, missing dev script, build crash) instead of a
|
|
472
|
+
// blind timeout. Draining the pipes is also required: with `stdio: 'pipe'`
|
|
473
|
+
// and no consumer, the OS pipe buffer (~64KB) fills within seconds of
|
|
474
|
+
// Vite's HMR/request logging and the child blocks on write, freezing the
|
|
475
|
+
// dev server even though it passed the readiness probe.
|
|
476
|
+
let outputTail = '';
|
|
477
|
+
const drain = (data) => {
|
|
478
|
+
outputTail = (outputTail + data.toString()).slice(-DEV_SERVER_OUTPUT_TAIL_LIMIT);
|
|
395
479
|
log.debug(`[variant-dev:${port}] ${data.toString().trim()}`);
|
|
396
|
-
}
|
|
397
|
-
|
|
480
|
+
};
|
|
481
|
+
proc.stdout?.on('data', drain);
|
|
482
|
+
proc.stderr?.on('data', drain);
|
|
483
|
+
// Track early termination so the probe can fail fast: a dev server that
|
|
484
|
+
// exits (or never spawns) before answering on `port` is never coming up —
|
|
485
|
+
// commonly because the project's dev script ignored the injected port and
|
|
486
|
+
// tried to bind its own default, which was already taken (EADDRINUSE).
|
|
487
|
+
const term = {};
|
|
488
|
+
const onExit = (code, signal) => {
|
|
489
|
+
term.exited = { code, signal };
|
|
490
|
+
};
|
|
491
|
+
const onError = (err) => {
|
|
492
|
+
term.spawnError = err;
|
|
493
|
+
log.warn(`Dev server error (port ${port}):`, err);
|
|
494
|
+
};
|
|
495
|
+
proc.once('exit', onExit);
|
|
496
|
+
proc.once('error', onError);
|
|
497
|
+
const detach = () => {
|
|
498
|
+
proc.off('exit', onExit);
|
|
499
|
+
proc.off('error', onError);
|
|
500
|
+
};
|
|
501
|
+
const fail = (reason) => {
|
|
502
|
+
detach();
|
|
503
|
+
const portInUse = (0, devServerError_1.isPortInUseOutput)(outputTail);
|
|
504
|
+
const detail = outputTail.trim();
|
|
505
|
+
let message;
|
|
506
|
+
if (reason === 'spawn_error') {
|
|
507
|
+
message = `Dev server failed to spawn on port ${port}: ${term.spawnError?.message ?? 'unknown error'}`;
|
|
508
|
+
}
|
|
509
|
+
else if (reason === 'exited') {
|
|
510
|
+
message = `Dev server exited before becoming ready on port ${port} (code=${term.exited?.code ?? 'null'}, signal=${term.exited?.signal ?? 'null'}${portInUse ? ', port already in use' : ''})`;
|
|
511
|
+
}
|
|
512
|
+
else {
|
|
513
|
+
message = `Dev server on port ${port} did not become ready within ${DEV_SERVER_READY_TIMEOUT_MS / 1000}s`;
|
|
514
|
+
}
|
|
515
|
+
throw new devServerError_1.DevServerStartError({
|
|
516
|
+
message: detail ? `${message}\n${detail}` : message,
|
|
517
|
+
reason,
|
|
518
|
+
portInUse,
|
|
519
|
+
detail,
|
|
520
|
+
exitCode: term.exited?.code ?? null,
|
|
521
|
+
signal: term.exited?.signal ?? null,
|
|
522
|
+
});
|
|
523
|
+
};
|
|
524
|
+
const deadline = Date.now() + DEV_SERVER_READY_TIMEOUT_MS;
|
|
398
525
|
while (Date.now() < deadline) {
|
|
526
|
+
if (term.spawnError)
|
|
527
|
+
fail('spawn_error');
|
|
528
|
+
if (term.exited)
|
|
529
|
+
fail('exited');
|
|
399
530
|
try {
|
|
400
531
|
const res = await fetch(`http://localhost:${port}`, {
|
|
401
532
|
signal: AbortSignal.timeout(1_000),
|
|
402
533
|
});
|
|
403
|
-
if (res.status !== 502)
|
|
534
|
+
if (res.status !== 502) {
|
|
535
|
+
detach();
|
|
404
536
|
return proc;
|
|
537
|
+
}
|
|
405
538
|
}
|
|
406
539
|
catch {
|
|
407
540
|
// not up yet
|
|
408
541
|
}
|
|
409
542
|
await new Promise((r) => setTimeout(r, 500));
|
|
410
543
|
}
|
|
544
|
+
// Deadline hit. If the child died during the final wait, report that
|
|
545
|
+
// (actionable) rather than a generic timeout.
|
|
546
|
+
if (term.spawnError)
|
|
547
|
+
fail('spawn_error');
|
|
548
|
+
if (term.exited)
|
|
549
|
+
fail('exited');
|
|
411
550
|
try {
|
|
412
551
|
proc.kill('SIGTERM');
|
|
413
552
|
}
|
|
414
|
-
catch {
|
|
415
|
-
|
|
553
|
+
catch {
|
|
554
|
+
/* ignore */
|
|
555
|
+
}
|
|
556
|
+
return fail('timeout');
|
|
416
557
|
}
|
|
417
558
|
/** Stop a dev server with SIGTERM + SIGKILL fallback */
|
|
418
559
|
async stopDevServer(proc, timeoutMs = 5_000) {
|
|
419
560
|
if (proc.killed || proc.exitCode !== null || proc.pid == null)
|
|
420
561
|
return;
|
|
421
562
|
const exited = new Promise((resolve) => {
|
|
422
|
-
const done = () => {
|
|
563
|
+
const done = () => {
|
|
564
|
+
proc.off('exit', done);
|
|
565
|
+
proc.off('error', done);
|
|
566
|
+
resolve();
|
|
567
|
+
};
|
|
423
568
|
proc.once('exit', done);
|
|
424
569
|
proc.once('error', done);
|
|
425
570
|
});
|
|
426
571
|
try {
|
|
427
572
|
proc.kill('SIGTERM');
|
|
428
573
|
}
|
|
429
|
-
catch {
|
|
574
|
+
catch {
|
|
575
|
+
/* ignore */
|
|
576
|
+
}
|
|
430
577
|
const timedOut = await Promise.race([
|
|
431
578
|
exited.then(() => false),
|
|
432
579
|
new Promise((r) => setTimeout(() => r(true), timeoutMs)),
|
|
@@ -436,7 +583,9 @@ class WorktreeManager {
|
|
|
436
583
|
try {
|
|
437
584
|
proc.kill('SIGKILL');
|
|
438
585
|
}
|
|
439
|
-
catch {
|
|
586
|
+
catch {
|
|
587
|
+
/* ignore */
|
|
588
|
+
}
|
|
440
589
|
await exited;
|
|
441
590
|
}
|
|
442
591
|
/** Remove all worktrees for a session.
|