@xdevops/issue-auto-finish 1.0.85 → 1.0.87
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/AIRunnerRegistry-II3WWSFN.js +31 -0
- package/dist/PtyRunner-6UGI5STW.js +22 -0
- package/dist/TerminalManager-RT2N7N5R.js +8 -0
- package/dist/ai-runner/AIRunner.d.ts +9 -1
- package/dist/ai-runner/AIRunner.d.ts.map +1 -1
- package/dist/ai-runner/AIRunnerRegistry.d.ts +37 -1
- package/dist/ai-runner/AIRunnerRegistry.d.ts.map +1 -1
- package/dist/ai-runner/PtyRunner.d.ts +114 -0
- package/dist/ai-runner/PtyRunner.d.ts.map +1 -0
- package/dist/ai-runner/index.d.ts +3 -1
- package/dist/ai-runner/index.d.ts.map +1 -1
- package/dist/{ai-runner-SVUNA3FX.js → ai-runner-HLA44WI6.js} +12 -3
- package/dist/{analyze-SXXPE5XL.js → analyze-ZIXNC5GN.js} +10 -8
- package/dist/{analyze-SXXPE5XL.js.map → analyze-ZIXNC5GN.js.map} +1 -1
- package/dist/{braindump-4E5SDMSZ.js → braindump-56WAY2RD.js} +10 -8
- package/dist/{braindump-4E5SDMSZ.js.map → braindump-56WAY2RD.js.map} +1 -1
- package/dist/{chunk-JINMYD56.js → chunk-2MESXJEZ.js} +3 -3
- package/dist/{chunk-P4O4ZXEC.js → chunk-2YQHKXLL.js} +40 -19
- package/dist/chunk-2YQHKXLL.js.map +1 -0
- package/dist/chunk-AVGZH64A.js +211 -0
- package/dist/chunk-AVGZH64A.js.map +1 -0
- package/dist/{chunk-5UPYA6KH.js → chunk-IP3QTP5A.js} +1028 -763
- package/dist/chunk-IP3QTP5A.js.map +1 -0
- package/dist/chunk-KC5S66OZ.js +177 -0
- package/dist/chunk-KC5S66OZ.js.map +1 -0
- package/dist/{chunk-4QV6D34Y.js → chunk-M5C2WILQ.js} +8 -6
- package/dist/{chunk-4QV6D34Y.js.map → chunk-M5C2WILQ.js.map} +1 -1
- package/dist/{chunk-FWEW5E3B.js → chunk-NZHKAPU6.js} +35 -5
- package/dist/chunk-NZHKAPU6.js.map +1 -0
- package/dist/{chunk-KTYPZTF4.js → chunk-O3WEV5W3.js} +10 -2
- package/dist/chunk-O3WEV5W3.js.map +1 -0
- package/dist/{chunk-K2OTLYJI.js → chunk-QZZGIZWC.js} +457 -202
- package/dist/chunk-QZZGIZWC.js.map +1 -0
- package/dist/{chunk-4LFNFRCL.js → chunk-SAMTXC4A.js} +91 -214
- package/dist/chunk-SAMTXC4A.js.map +1 -0
- package/dist/chunk-U237JSLB.js +1 -0
- package/dist/chunk-U237JSLB.js.map +1 -0
- package/dist/chunk-U6GWFTKA.js +657 -0
- package/dist/chunk-U6GWFTKA.js.map +1 -0
- package/dist/{chunk-HOFYJEJ4.js → chunk-UBQLXQ7I.js} +11 -11
- package/dist/cli/setup/env-metadata.d.ts.map +1 -1
- package/dist/cli.js +8 -7
- package/dist/cli.js.map +1 -1
- package/dist/{config-QLINHCHD.js → config-WTRSZLOC.js} +4 -3
- package/dist/config-WTRSZLOC.js.map +1 -0
- package/dist/config-schema.d.ts +17 -1
- package/dist/config-schema.d.ts.map +1 -1
- package/dist/config.d.ts +20 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/errors/PhaseAbortedError.d.ts +3 -3
- package/dist/errors/PhaseAbortedError.d.ts.map +1 -1
- package/dist/errors-S3BWYA4I.js +43 -0
- package/dist/errors-S3BWYA4I.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -11
- package/dist/{init-TDKDC6YP.js → init-QQDXGTPB.js} +7 -6
- package/dist/{init-TDKDC6YP.js.map → init-QQDXGTPB.js.map} +1 -1
- package/dist/lib.js +9 -7
- package/dist/lib.js.map +1 -1
- package/dist/orchestrator/IssueProcessingContext.d.ts +39 -21
- package/dist/orchestrator/IssueProcessingContext.d.ts.map +1 -1
- package/dist/orchestrator/PipelineOrchestrator.d.ts +10 -1
- package/dist/orchestrator/PipelineOrchestrator.d.ts.map +1 -1
- package/dist/orchestrator/steps/PhaseLoopStep.d.ts +1 -1
- package/dist/orchestrator/steps/PhaseLoopStep.d.ts.map +1 -1
- package/dist/orchestrator/steps/SetupStep.d.ts.map +1 -1
- package/dist/persistence/PlanPersistence.d.ts +7 -1
- package/dist/persistence/PlanPersistence.d.ts.map +1 -1
- package/dist/phases/BasePhase.d.ts +31 -42
- package/dist/phases/BasePhase.d.ts.map +1 -1
- package/dist/phases/BuildPhase.d.ts.map +1 -1
- package/dist/phases/PhaseFactory.d.ts +2 -3
- package/dist/phases/PhaseFactory.d.ts.map +1 -1
- package/dist/phases/PhaseOutcome.d.ts +42 -0
- package/dist/phases/PhaseOutcome.d.ts.map +1 -0
- package/dist/phases/PlanPhase.d.ts +1 -1
- package/dist/phases/PlanPhase.d.ts.map +1 -1
- package/dist/phases/ReleasePhase.d.ts +8 -18
- package/dist/phases/ReleasePhase.d.ts.map +1 -1
- package/dist/phases/UatPhase.d.ts +7 -24
- package/dist/phases/UatPhase.d.ts.map +1 -1
- package/dist/phases/VerifyPhase.d.ts +4 -4
- package/dist/phases/VerifyPhase.d.ts.map +1 -1
- package/dist/poller/IssuePoller.d.ts.map +1 -1
- package/dist/prompts/release-templates.d.ts.map +1 -1
- package/dist/prompts/templates.d.ts.map +1 -1
- package/dist/{restart-RNXGTDWZ.js → restart-BMILTP5X.js} +6 -5
- package/dist/{restart-RNXGTDWZ.js.map → restart-BMILTP5X.js.map} +1 -1
- package/dist/run.js +14 -11
- package/dist/run.js.map +1 -1
- package/dist/settings/ExperimentalSettings.d.ts +1 -1
- package/dist/settings/ExperimentalSettings.d.ts.map +1 -1
- package/dist/start-6QRW6IJI.js +15 -0
- package/dist/start-6QRW6IJI.js.map +1 -0
- package/dist/terminal/TerminalManager.d.ts +62 -0
- package/dist/terminal/TerminalManager.d.ts.map +1 -0
- package/dist/terminal/TerminalWebSocket.d.ts +9 -0
- package/dist/terminal/TerminalWebSocket.d.ts.map +1 -0
- package/dist/tracker/ExecutableTask.d.ts +4 -2
- package/dist/tracker/ExecutableTask.d.ts.map +1 -1
- package/dist/tracker/IssueState.d.ts +11 -1
- package/dist/tracker/IssueState.d.ts.map +1 -1
- package/dist/tracker/IssueTracker.d.ts +19 -1
- package/dist/tracker/IssueTracker.d.ts.map +1 -1
- package/dist/web/WebServer.d.ts +4 -0
- package/dist/web/WebServer.d.ts.map +1 -1
- package/dist/web/routes/terminal.d.ts +11 -0
- package/dist/web/routes/terminal.d.ts.map +1 -0
- package/dist/webhook/CommandExecutor.d.ts.map +1 -1
- package/package.json +7 -1
- package/src/web/frontend/dist/assets/index-COYziOhv.css +1 -0
- package/src/web/frontend/dist/assets/index-D_oTMuJU.js +151 -0
- package/src/web/frontend/dist/index.html +2 -2
- package/dist/chunk-4LFNFRCL.js.map +0 -1
- package/dist/chunk-5UPYA6KH.js.map +0 -1
- package/dist/chunk-DADQSKPL.js +0 -1
- package/dist/chunk-FWEW5E3B.js.map +0 -1
- package/dist/chunk-K2OTLYJI.js.map +0 -1
- package/dist/chunk-KTYPZTF4.js.map +0 -1
- package/dist/chunk-P4O4ZXEC.js.map +0 -1
- package/dist/start-27GRO4DP.js +0 -14
- package/src/web/frontend/dist/assets/index-C4NXoH9S.js +0 -133
- package/src/web/frontend/dist/assets/index-C7lorIa0.css +0 -1
- /package/dist/{ai-runner-SVUNA3FX.js.map → AIRunnerRegistry-II3WWSFN.js.map} +0 -0
- /package/dist/{chunk-DADQSKPL.js.map → PtyRunner-6UGI5STW.js.map} +0 -0
- /package/dist/{config-QLINHCHD.js.map → TerminalManager-RT2N7N5R.js.map} +0 -0
- /package/dist/{start-27GRO4DP.js.map → ai-runner-HLA44WI6.js.map} +0 -0
- /package/dist/{chunk-JINMYD56.js.map → chunk-2MESXJEZ.js.map} +0 -0
- /package/dist/{chunk-HOFYJEJ4.js.map → chunk-UBQLXQ7I.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,22 +1,25 @@
|
|
|
1
1
|
import {
|
|
2
2
|
main
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-GXFG4JU6.js";
|
|
7
|
-
import "./chunk-KTYPZTF4.js";
|
|
3
|
+
} from "./chunk-QZZGIZWC.js";
|
|
4
|
+
import "./chunk-M5C2WILQ.js";
|
|
5
|
+
import "./chunk-UBQLXQ7I.js";
|
|
8
6
|
import "./chunk-HDFNMVRQ.js";
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-GXFG4JU6.js";
|
|
8
|
+
import "./chunk-KC5S66OZ.js";
|
|
9
|
+
import "./chunk-O3WEV5W3.js";
|
|
10
|
+
import "./chunk-IP3QTP5A.js";
|
|
11
|
+
import "./chunk-2YQHKXLL.js";
|
|
12
|
+
import "./chunk-U237JSLB.js";
|
|
13
|
+
import "./chunk-U6GWFTKA.js";
|
|
11
14
|
import "./chunk-ACVOOHAR.js";
|
|
15
|
+
import "./chunk-B7TVVODN.js";
|
|
12
16
|
import "./chunk-YCYVNRLF.js";
|
|
13
|
-
import "./chunk-
|
|
17
|
+
import "./chunk-NZHKAPU6.js";
|
|
14
18
|
import "./chunk-AKXDQH25.js";
|
|
15
|
-
import "./chunk-B7TVVODN.js";
|
|
16
19
|
import "./chunk-TN2SYADO.js";
|
|
20
|
+
import "./chunk-SAMTXC4A.js";
|
|
21
|
+
import "./chunk-AVGZH64A.js";
|
|
17
22
|
import "./chunk-DAX3FD2O.js";
|
|
18
|
-
import "./chunk-DADQSKPL.js";
|
|
19
|
-
import "./chunk-4LFNFRCL.js";
|
|
20
23
|
import "./chunk-GF2RRYHB.js";
|
|
21
24
|
export {
|
|
22
25
|
main
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createSetupRouter
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-KTYPZTF4.js";
|
|
3
|
+
} from "./chunk-UBQLXQ7I.js";
|
|
5
4
|
import "./chunk-HDFNMVRQ.js";
|
|
5
|
+
import "./chunk-O3WEV5W3.js";
|
|
6
6
|
import "./chunk-ACVOOHAR.js";
|
|
7
|
+
import "./chunk-B7TVVODN.js";
|
|
7
8
|
import "./chunk-YCYVNRLF.js";
|
|
8
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-NZHKAPU6.js";
|
|
9
10
|
import {
|
|
10
11
|
getLocalIP
|
|
11
12
|
} from "./chunk-AKXDQH25.js";
|
|
12
|
-
import "./chunk-B7TVVODN.js";
|
|
13
13
|
import "./chunk-TN2SYADO.js";
|
|
14
|
+
import "./chunk-SAMTXC4A.js";
|
|
15
|
+
import "./chunk-AVGZH64A.js";
|
|
14
16
|
import "./chunk-DAX3FD2O.js";
|
|
15
|
-
import "./chunk-4LFNFRCL.js";
|
|
16
17
|
import "./chunk-GF2RRYHB.js";
|
|
17
18
|
|
|
18
19
|
// src/cli/commands/init.ts
|
|
@@ -86,4 +87,4 @@ async function initCommand(options) {
|
|
|
86
87
|
export {
|
|
87
88
|
initCommand
|
|
88
89
|
};
|
|
89
|
-
//# sourceMappingURL=init-
|
|
90
|
+
//# sourceMappingURL=init-QQDXGTPB.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/commands/init.ts"],"sourcesContent":["import express from 'express';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { createSetupRouter } from '../../web/routes/setup.js';\nimport { getLocalIP } from '../../utils/network.js';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nexport interface InitOptions {\n port: number;\n config?: string;\n}\n\nexport async function initCommand(options: InitOptions): Promise<void> {\n const app = express();\n app.use(express.json());\n\n let serverRef: ReturnType<typeof app.listen> | null = null;\n\n let setupRouter;\n try {\n setupRouter = createSetupRouter({\n configPath: options.config,\n onComplete: (configPath) => {\n console.log(`\\n Configuration saved to: ${configPath}`);\n console.log(' Run \"issue-auto-finish start\" to start the service.\\n');\n setTimeout(() => {\n serverRef?.close();\n process.exit(0);\n }, 1000);\n },\n });\n } catch (err) {\n console.error(' Failed to create setup router:', (err as Error).message);\n process.exit(1);\n }\n\n app.use(setupRouter);\n\n const packageRoot = path.resolve(__dirname, '..');\n const publicDir = path.resolve(packageRoot, 'src/web/frontend/dist');\n\n const indexHtml = path.join(publicDir, 'index.html');\n if (fs.existsSync(indexHtml)) {\n app.use(express.static(publicDir));\n app.get('/{*splat}', (_req, res) => {\n res.sendFile('index.html', { root: publicDir }, (err) => {\n if (err) {\n res.status(404).type('html').send('<!DOCTYPE html><html><body>Not Found</body></html>');\n }\n });\n });\n } else {\n app.get('/', (_req, res) => {\n res.type('html').send(`<!DOCTYPE html>\n<html><head><title>Issue Auto-Finish Setup</title></head>\n<body style=\"font-family:system-ui;max-width:600px;margin:60px auto;padding:20px\">\n<h1>Issue Auto-Finish Setup</h1>\n<p>Frontend assets not found. Please build the frontend first:</p>\n<pre>cd issue-auto-finish && npm run web:build</pre>\n<p>Or use the API directly at <code>/api/setup/*</code></p>\n</body></html>`);\n });\n }\n\n serverRef = app.listen(options.port, async () => {\n const url = `http://${getLocalIP()}:${options.port}`;\n const routeCount = setupRouter.stack?.length ?? 0;\n console.log(`\\n Issue Auto-Finish Setup Wizard`);\n console.log(` Open: ${url}`);\n console.log(` Registered ${routeCount} API routes\\n`);\n\n try {\n const open = (await import('open')).default;\n await open(url);\n } catch {\n // Browser open failed, user can manually navigate\n }\n });\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/cli/commands/init.ts"],"sourcesContent":["import express from 'express';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { createSetupRouter } from '../../web/routes/setup.js';\nimport { getLocalIP } from '../../utils/network.js';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nexport interface InitOptions {\n port: number;\n config?: string;\n}\n\nexport async function initCommand(options: InitOptions): Promise<void> {\n const app = express();\n app.use(express.json());\n\n let serverRef: ReturnType<typeof app.listen> | null = null;\n\n let setupRouter;\n try {\n setupRouter = createSetupRouter({\n configPath: options.config,\n onComplete: (configPath) => {\n console.log(`\\n Configuration saved to: ${configPath}`);\n console.log(' Run \"issue-auto-finish start\" to start the service.\\n');\n setTimeout(() => {\n serverRef?.close();\n process.exit(0);\n }, 1000);\n },\n });\n } catch (err) {\n console.error(' Failed to create setup router:', (err as Error).message);\n process.exit(1);\n }\n\n app.use(setupRouter);\n\n const packageRoot = path.resolve(__dirname, '..');\n const publicDir = path.resolve(packageRoot, 'src/web/frontend/dist');\n\n const indexHtml = path.join(publicDir, 'index.html');\n if (fs.existsSync(indexHtml)) {\n app.use(express.static(publicDir));\n app.get('/{*splat}', (_req, res) => {\n res.sendFile('index.html', { root: publicDir }, (err) => {\n if (err) {\n res.status(404).type('html').send('<!DOCTYPE html><html><body>Not Found</body></html>');\n }\n });\n });\n } else {\n app.get('/', (_req, res) => {\n res.type('html').send(`<!DOCTYPE html>\n<html><head><title>Issue Auto-Finish Setup</title></head>\n<body style=\"font-family:system-ui;max-width:600px;margin:60px auto;padding:20px\">\n<h1>Issue Auto-Finish Setup</h1>\n<p>Frontend assets not found. Please build the frontend first:</p>\n<pre>cd issue-auto-finish && npm run web:build</pre>\n<p>Or use the API directly at <code>/api/setup/*</code></p>\n</body></html>`);\n });\n }\n\n serverRef = app.listen(options.port, async () => {\n const url = `http://${getLocalIP()}:${options.port}`;\n const routeCount = setupRouter.stack?.length ?? 0;\n console.log(`\\n Issue Auto-Finish Setup Wizard`);\n console.log(` Open: ${url}`);\n console.log(` Registered ${routeCount} API routes\\n`);\n\n try {\n const open = (await import('open')).default;\n await open(url);\n } catch {\n // Browser open failed, user can manually navigate\n }\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA,OAAO,aAAa;AACpB,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAI9B,IAAM,YAAY,KAAK,QAAQ,cAAc,YAAY,GAAG,CAAC;AAO7D,eAAsB,YAAY,SAAqC;AACrE,QAAM,MAAM,QAAQ;AACpB,MAAI,IAAI,QAAQ,KAAK,CAAC;AAEtB,MAAI,YAAkD;AAEtD,MAAI;AACJ,MAAI;AACF,kBAAc,kBAAkB;AAAA,MAC9B,YAAY,QAAQ;AAAA,MACpB,YAAY,CAAC,eAAe;AAC1B,gBAAQ,IAAI;AAAA,4BAA+B,UAAU,EAAE;AACvD,gBAAQ,IAAI,yDAAyD;AACrE,mBAAW,MAAM;AACf,qBAAW,MAAM;AACjB,kBAAQ,KAAK,CAAC;AAAA,QAChB,GAAG,GAAI;AAAA,MACT;AAAA,IACF,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,YAAQ,MAAM,oCAAqC,IAAc,OAAO;AACxE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,IAAI,WAAW;AAEnB,QAAM,cAAc,KAAK,QAAQ,WAAW,IAAI;AAChD,QAAM,YAAY,KAAK,QAAQ,aAAa,uBAAuB;AAEnE,QAAM,YAAY,KAAK,KAAK,WAAW,YAAY;AACnD,MAAI,GAAG,WAAW,SAAS,GAAG;AAC5B,QAAI,IAAI,QAAQ,OAAO,SAAS,CAAC;AACjC,QAAI,IAAI,aAAa,CAAC,MAAM,QAAQ;AAClC,UAAI,SAAS,cAAc,EAAE,MAAM,UAAU,GAAG,CAAC,QAAQ;AACvD,YAAI,KAAK;AACP,cAAI,OAAO,GAAG,EAAE,KAAK,MAAM,EAAE,KAAK,oDAAoD;AAAA,QACxF;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH,OAAO;AACL,QAAI,IAAI,KAAK,CAAC,MAAM,QAAQ;AAC1B,UAAI,KAAK,MAAM,EAAE,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eAOb;AAAA,IACX,CAAC;AAAA,EACH;AAEA,cAAY,IAAI,OAAO,QAAQ,MAAM,YAAY;AAC/C,UAAM,MAAM,UAAU,WAAW,CAAC,IAAI,QAAQ,IAAI;AAClD,UAAM,aAAa,YAAY,OAAO,UAAU;AAChD,YAAQ,IAAI;AAAA,iCAAoC;AAChD,YAAQ,IAAI,WAAW,GAAG,EAAE;AAC5B,YAAQ,IAAI,gBAAgB,UAAU;AAAA,CAAe;AAErD,QAAI;AACF,YAAM,QAAQ,MAAM,OAAO,MAAM,GAAG;AACpC,YAAM,KAAK,GAAG;AAAA,IAChB,QAAQ;AAAA,IAER;AAAA,EACF,CAAC;AACH;","names":[]}
|
package/dist/lib.js
CHANGED
|
@@ -13,23 +13,23 @@ import {
|
|
|
13
13
|
registerPhase,
|
|
14
14
|
registerPipeline,
|
|
15
15
|
resolvePipelineMode
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-IP3QTP5A.js";
|
|
17
17
|
import {
|
|
18
18
|
AsyncMutex,
|
|
19
19
|
GitOperations,
|
|
20
20
|
eventBus
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-2YQHKXLL.js";
|
|
22
|
+
import "./chunk-U237JSLB.js";
|
|
23
|
+
import "./chunk-U6GWFTKA.js";
|
|
22
24
|
import "./chunk-ACVOOHAR.js";
|
|
25
|
+
import "./chunk-B7TVVODN.js";
|
|
23
26
|
import "./chunk-YCYVNRLF.js";
|
|
24
27
|
import {
|
|
25
28
|
ConfigValidationError,
|
|
26
29
|
loadConfig
|
|
27
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-NZHKAPU6.js";
|
|
28
31
|
import "./chunk-AKXDQH25.js";
|
|
29
|
-
import "./chunk-B7TVVODN.js";
|
|
30
32
|
import "./chunk-TN2SYADO.js";
|
|
31
|
-
import "./chunk-DAX3FD2O.js";
|
|
32
|
-
import "./chunk-DADQSKPL.js";
|
|
33
33
|
import {
|
|
34
34
|
BaseAIRunner,
|
|
35
35
|
ClaudeInternalRunner,
|
|
@@ -40,7 +40,9 @@ import {
|
|
|
40
40
|
isRegisteredRunner,
|
|
41
41
|
registerAIRunner,
|
|
42
42
|
validateRunnerRegistry
|
|
43
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-SAMTXC4A.js";
|
|
44
|
+
import "./chunk-AVGZH64A.js";
|
|
45
|
+
import "./chunk-DAX3FD2O.js";
|
|
44
46
|
import {
|
|
45
47
|
Logger,
|
|
46
48
|
logger
|
package/dist/lib.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/e2e/E2EBrowserRunner.ts","../src/e2e/E2EScriptRunner.ts","../src/e2e/E2ETestHelper.ts"],"sourcesContent":["import { spawn, type ChildProcess } from 'node:child_process';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { setTimeout as sleep } from 'node:timers/promises';\nimport { logger } from '../logger.js';\nimport type { E2eConfig } from '../config.js';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nexport interface BrowserRunnerOptions {\n pythonBin?: string;\n projectRoot?: string;\n configFile?: string;\n headless?: boolean;\n baseUrl?: string;\n storageState?: string;\n outputDir?: string;\n timeout?: number;\n}\n\nexport interface ReplCommand {\n cmd: string;\n [key: string]: unknown;\n}\n\nexport interface ReplResponse {\n ok: boolean;\n data?: unknown;\n error?: string;\n}\n\nexport interface PageMeta {\n url: string;\n title: string;\n ready_state: string;\n}\n\nexport interface StepResult {\n path: string | null;\n label: string;\n}\n\nexport interface ScreenshotResult {\n path?: string;\n base64?: string;\n size: number;\n}\n\n/**\n * TypeScript wrapper around the Python Playwright REPL from oa_pc_uat.\n *\n * Spawns a Python process in interactive REPL mode and communicates via\n * the file-polling protocol (cmd.jsonl / resp.jsonl). This enables\n * issue-auto-finish E2E tests to drive a real browser for verifying\n * web UI changes end-to-end.\n */\nexport class E2EBrowserRunner {\n private proc: ChildProcess | null = null;\n private sessionId: string | null = null;\n private sockDir: string | null = null;\n private cmdFile: string | null = null;\n private respFile: string | null = null;\n private respLinesSeen = 0;\n private readonly options: Required<BrowserRunnerOptions>;\n\n constructor(\n private readonly e2eConfig: E2eConfig,\n opts: BrowserRunnerOptions = {},\n ) {\n const vendorRoot = opts.projectRoot\n ?? path.resolve(__dirname, '../../vendor/oa_pc_uat');\n\n this.options = {\n pythonBin: opts.pythonBin ?? this.e2eConfig.pythonBin ?? 'python3',\n projectRoot: vendorRoot,\n configFile: opts.configFile ?? '',\n headless: opts.headless ?? true,\n baseUrl: opts.baseUrl ?? e2eConfig.baseUrl,\n storageState: opts.storageState ?? '',\n outputDir: opts.outputDir ?? path.join(vendorRoot, 'outputs'),\n timeout: opts.timeout ?? 60_000,\n };\n }\n\n async start(): Promise<void> {\n const args = [\n 'main.py',\n '--headless',\n '-i',\n '--reuse-session',\n '--url', this.options.baseUrl,\n ];\n\n if (this.options.configFile) {\n args.push('--config', this.options.configFile);\n }\n if (this.options.storageState) {\n args.push('--storage-state', this.options.storageState);\n }\n if (this.options.outputDir) {\n args.push('--output-dir', this.options.outputDir);\n }\n\n logger.info('Starting E2E browser REPL', {\n cwd: this.options.projectRoot,\n args: [this.options.pythonBin, ...args],\n });\n\n this.proc = spawn(this.options.pythonBin, args, {\n cwd: this.options.projectRoot,\n stdio: ['pipe', 'pipe', 'pipe'],\n env: {\n ...process.env,\n PYTHONUNBUFFERED: '1',\n },\n });\n\n let stderr = '';\n this.proc.stderr?.on('data', (chunk) => {\n stderr += chunk.toString();\n });\n\n const readyInfo = await this.waitForReady(stderr);\n this.sessionId = readyInfo.session_id;\n this.sockDir = readyInfo.sock_dir;\n this.cmdFile = path.join(this.sockDir, 'cmd.jsonl');\n this.respFile = path.join(this.sockDir, 'resp.jsonl');\n this.respLinesSeen = 1; // skip the __ready__ line in resp.jsonl\n\n logger.info('E2E browser REPL started', {\n sessionId: this.sessionId,\n sockDir: this.sockDir,\n url: readyInfo.url,\n });\n }\n\n async stop(): Promise<void> {\n if (!this.proc) return;\n\n try {\n await this.send({ cmd: 'quit' });\n } catch {\n // ignore errors during quit\n }\n\n await sleep(500);\n\n if (this.proc.exitCode === null) {\n this.proc.kill('SIGTERM');\n await sleep(1000);\n if (this.proc.exitCode === null) {\n this.proc.kill('SIGKILL');\n }\n }\n\n this.proc = null;\n this.sessionId = null;\n this.sockDir = null;\n logger.info('E2E browser REPL stopped');\n }\n\n async send(command: ReplCommand): Promise<ReplResponse> {\n if (!this.cmdFile || !this.respFile) {\n throw new Error('REPL not started — call start() first');\n }\n\n const line = JSON.stringify(command) + '\\n';\n fs.appendFileSync(this.cmdFile, line, 'utf-8');\n\n const deadline = Date.now() + this.options.timeout;\n while (Date.now() < deadline) {\n const content = fs.readFileSync(this.respFile, 'utf-8');\n const lines = content.split('\\n').filter(Boolean);\n\n if (lines.length > this.respLinesSeen) {\n const newLine = lines[this.respLinesSeen]!;\n this.respLinesSeen = lines.length;\n return JSON.parse(newLine) as ReplResponse;\n }\n\n await sleep(100);\n }\n\n throw new Error(`REPL command timed out after ${this.options.timeout}ms: ${command.cmd}`);\n }\n\n // -- High-level helpers -----------------------------------------------\n\n async goto(url: string, waitUntil = 'domcontentloaded'): Promise<PageMeta> {\n const resp = await this.send({ cmd: 'goto', url, wait_until: waitUntil });\n this.assertOk(resp);\n return resp.data as PageMeta;\n }\n\n async navigate(url: string): Promise<PageMeta> {\n const resp = await this.send({ cmd: 'navigate', url });\n this.assertOk(resp);\n return resp.data as PageMeta;\n }\n\n async click(selector: string, timeout = 5000): Promise<void> {\n const resp = await this.send({ cmd: 'click', selector, timeout });\n this.assertOk(resp);\n }\n\n async fill(selector: string, value: string, timeout = 5000): Promise<void> {\n const resp = await this.send({ cmd: 'fill', selector, value, timeout });\n this.assertOk(resp);\n }\n\n async type(selector: string, text: string, delay = 50): Promise<void> {\n const resp = await this.send({ cmd: 'type', selector, text, delay });\n this.assertOk(resp);\n }\n\n async press(key: string, selector?: string): Promise<void> {\n const resp = await this.send({ cmd: 'press', key, selector });\n this.assertOk(resp);\n }\n\n async hover(selector: string): Promise<void> {\n const resp = await this.send({ cmd: 'hover', selector });\n this.assertOk(resp);\n }\n\n async select(selector: string, value: string | string[]): Promise<void> {\n const resp = await this.send({ cmd: 'select', selector, value });\n this.assertOk(resp);\n }\n\n async waitFor(selector: string, state = 'visible', timeout = 10000): Promise<void> {\n const resp = await this.send({ cmd: 'wait_for', selector, state, timeout });\n this.assertOk(resp);\n }\n\n async waitForUrl(url: string, timeout = 15000): Promise<string> {\n const resp = await this.send({ cmd: 'wait_for_url', url, timeout });\n this.assertOk(resp);\n return (resp.data as { current_url: string }).current_url;\n }\n\n async waitIdle(timeout = 15000): Promise<void> {\n const resp = await this.send({ cmd: 'wait_idle', timeout });\n this.assertOk(resp);\n }\n\n async wait(ms: number): Promise<void> {\n const resp = await this.send({ cmd: 'wait', ms });\n this.assertOk(resp);\n }\n\n async screenshot(opts?: { fullPage?: boolean; selector?: string; encode?: boolean; name?: string }): Promise<ScreenshotResult> {\n const resp = await this.send({\n cmd: 'screenshot',\n full_page: opts?.fullPage ?? true,\n selector: opts?.selector,\n encode: opts?.encode ?? false,\n name: opts?.name,\n });\n this.assertOk(resp);\n return resp.data as ScreenshotResult;\n }\n\n async step(label: string): Promise<StepResult> {\n const resp = await this.send({ cmd: 'step', label });\n this.assertOk(resp);\n return resp.data as StepResult;\n }\n\n async meta(): Promise<PageMeta> {\n const resp = await this.send({ cmd: 'meta' });\n this.assertOk(resp);\n return resp.data as PageMeta;\n }\n\n async snapshot(include?: string[]): Promise<Record<string, unknown>> {\n const resp = await this.send({ cmd: 'snapshot', include });\n this.assertOk(resp);\n return resp.data as Record<string, unknown>;\n }\n\n async queryText(text: string, exact = false): Promise<unknown[]> {\n const resp = await this.send({ cmd: 'query_text', text, exact });\n this.assertOk(resp);\n return resp.data as unknown[];\n }\n\n async querySelector(selector: string, max = 50): Promise<unknown[]> {\n const resp = await this.send({ cmd: 'query', selector, max });\n this.assertOk(resp);\n return resp.data as unknown[];\n }\n\n async evaluate(expression: string, arg?: unknown): Promise<unknown> {\n const resp = await this.send({ cmd: 'evaluate', expression, arg });\n this.assertOk(resp);\n return resp.data;\n }\n\n async text(selector = 'body', maxLength = 20000): Promise<string> {\n const resp = await this.send({ cmd: 'text', selector, max_length: maxLength });\n this.assertOk(resp);\n return (resp.data as { text: string }).text;\n }\n\n async html(selector?: string, maxLength = 50000): Promise<string> {\n const resp = await this.send({ cmd: 'html', selector, max_length: maxLength });\n this.assertOk(resp);\n return (resp.data as { html: string }).html;\n }\n\n async networkLog(opts?: { since?: number; type?: string; urlContains?: string; tail?: number }): Promise<{ count: number; entries: unknown[] }> {\n const resp = await this.send({\n cmd: 'network_log',\n since: opts?.since,\n type: opts?.type,\n url_contains: opts?.urlContains,\n tail: opts?.tail,\n });\n this.assertOk(resp);\n return resp.data as { count: number; entries: unknown[] };\n }\n\n async consoleLog(opts?: { since?: number; type?: string; tail?: number }): Promise<{ count: number; entries: unknown[] }> {\n const resp = await this.send({\n cmd: 'console_log',\n since: opts?.since,\n type: opts?.type,\n tail: opts?.tail,\n });\n this.assertOk(resp);\n return resp.data as { count: number; entries: unknown[] };\n }\n\n async requestPairs(opts?: { urlContains?: string; method?: string; statusMin?: number; statusMax?: number }): Promise<{ count: number; entries: unknown[] }> {\n const resp = await this.send({\n cmd: 'request_pairs',\n url_contains: opts?.urlContains,\n method: opts?.method,\n status_min: opts?.statusMin,\n status_max: opts?.statusMax,\n });\n this.assertOk(resp);\n return resp.data as { count: number; entries: unknown[] };\n }\n\n async clearLogs(): Promise<void> {\n const resp = await this.send({ cmd: 'clear_logs' });\n this.assertOk(resp);\n }\n\n get isRunning(): boolean {\n return this.proc !== null && this.proc.exitCode === null;\n }\n\n // -- Private ----------------------------------------------------------\n\n private assertOk(resp: ReplResponse): void {\n if (!resp.ok) {\n throw new Error(`REPL error: ${resp.error}`);\n }\n }\n\n private async waitForReady(stderr: string): Promise<{\n session_id: string;\n sock_dir: string;\n url: string;\n }> {\n if (!this.proc?.stdout) {\n throw new Error('REPL process has no stdout');\n }\n\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(\n `REPL did not become ready within ${this.options.timeout}ms.\\nStderr: ${stderr}`,\n ));\n }, this.options.timeout);\n\n let buffer = '';\n const onData = (chunk: Buffer) => {\n buffer += chunk.toString();\n const lines = buffer.split('\\n');\n for (const line of lines) {\n if (!line.trim()) continue;\n try {\n const msg = JSON.parse(line);\n if (msg.__ready__) {\n clearTimeout(timeout);\n this.proc!.stdout!.off('data', onData);\n resolve({\n session_id: msg.session_id,\n sock_dir: msg.sock_dir,\n url: msg.url,\n });\n return;\n }\n } catch {\n // not JSON yet, keep buffering\n }\n }\n };\n\n this.proc!.stdout!.on('data', onData);\n this.proc!.on('error', (err) => {\n clearTimeout(timeout);\n reject(new Error(`REPL process error: ${err.message}`));\n });\n this.proc!.on('exit', (code) => {\n clearTimeout(timeout);\n reject(new Error(`REPL process exited prematurely (code ${code}).\\nStderr: ${stderr}`));\n });\n });\n }\n}\n","import { spawn } from 'node:child_process';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { logger } from '../logger.js';\nimport type { E2eConfig } from '../config.js';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nexport interface ScriptRunResult {\n success: boolean;\n exitCode: number;\n stdout: string;\n stderr: string;\n outputDir?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface ScriptRunnerOptions {\n pythonBin?: string;\n projectRoot?: string;\n configFile?: string;\n timeoutMs?: number;\n env?: Record<string, string>;\n}\n\n/**\n * Run a Python UAT script (non-interactive) and collect results.\n *\n * Executes `python3 main.py --script <script> --headless` from oa_pc_uat.\n * Suitable for batch E2E verification where each script performs a series\n * of page operations, captures screenshots/logs, then exits.\n */\nexport class E2EScriptRunner {\n private readonly opts: Required<ScriptRunnerOptions>;\n\n constructor(\n private readonly e2eConfig: E2eConfig,\n options: ScriptRunnerOptions = {},\n ) {\n const vendorRoot = options.projectRoot\n ?? path.resolve(__dirname, '../../vendor/oa_pc_uat');\n\n this.opts = {\n pythonBin: options.pythonBin ?? this.e2eConfig.pythonBin ?? 'python3',\n projectRoot: vendorRoot,\n configFile: options.configFile ?? '',\n timeoutMs: options.timeoutMs ?? 300_000,\n env: options.env ?? {},\n };\n }\n\n async runScript(\n scriptPath: string,\n runOpts?: {\n baseUrl?: string;\n outputPath?: string;\n storageState?: string;\n extraArgs?: string[];\n },\n ): Promise<ScriptRunResult> {\n const args = [\n 'main.py',\n '--headless',\n '--reuse-session',\n '--script', scriptPath,\n '--url', runOpts?.baseUrl ?? this.e2eConfig.baseUrl,\n ];\n\n if (this.opts.configFile) {\n args.push('--config', this.opts.configFile);\n }\n if (runOpts?.outputPath) {\n args.push('--output-path', runOpts.outputPath);\n }\n if (runOpts?.storageState) {\n args.push('--storage-state', runOpts.storageState);\n }\n if (runOpts?.extraArgs) {\n args.push(...runOpts.extraArgs);\n }\n\n logger.info('Running E2E script', {\n script: scriptPath,\n cwd: this.opts.projectRoot,\n });\n\n return new Promise<ScriptRunResult>((resolve, reject) => {\n const proc = spawn(this.opts.pythonBin, args, {\n cwd: this.opts.projectRoot,\n env: {\n ...process.env,\n PYTHONUNBUFFERED: '1',\n ...this.opts.env,\n },\n timeout: this.opts.timeoutMs,\n });\n\n let stdout = '';\n let stderr = '';\n\n proc.stdout?.on('data', (chunk) => { stdout += chunk.toString(); });\n proc.stderr?.on('data', (chunk) => { stderr += chunk.toString(); });\n\n proc.on('error', (err) => {\n reject(new Error(`E2E script process error: ${err.message}`));\n });\n\n proc.on('close', (code) => {\n let metadata: Record<string, unknown> | undefined;\n try {\n metadata = JSON.parse(stdout.trim());\n } catch {\n // stdout may not be valid JSON\n }\n\n const exitCode = code ?? 1;\n resolve({\n success: exitCode === 0,\n exitCode,\n stdout,\n stderr,\n outputDir: metadata?.output_dir as string | undefined,\n metadata,\n });\n });\n });\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { E2EBrowserRunner, type BrowserRunnerOptions } from './E2EBrowserRunner.js';\nimport { E2EScriptRunner, type ScriptRunnerOptions } from './E2EScriptRunner.js';\nimport type { E2eConfig } from '../config.js';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nexport interface E2ETestContext {\n browser: E2EBrowserRunner;\n scriptRunner: E2EScriptRunner;\n outputDir: string;\n cleanup: () => Promise<void>;\n}\n\n/**\n * Bootstrap an E2E test context with browser runner, script runner,\n * and temporary output directory. Call `cleanup()` in afterAll/afterEach.\n */\nexport async function createE2ETestContext(\n e2eConfig: E2eConfig,\n opts?: {\n browser?: BrowserRunnerOptions;\n script?: ScriptRunnerOptions;\n outputDir?: string;\n },\n): Promise<E2ETestContext> {\n const outputDir = opts?.outputDir\n ?? fs.mkdtempSync(path.join(process.env.TMPDIR ?? '/tmp', 'iaf-e2e-'));\n\n const browser = new E2EBrowserRunner(e2eConfig, {\n ...opts?.browser,\n outputDir,\n });\n\n const scriptRunner = new E2EScriptRunner(e2eConfig, opts?.script);\n\n return {\n browser,\n scriptRunner,\n outputDir,\n cleanup: async () => {\n if (browser.isRunning) {\n await browser.stop();\n }\n try {\n fs.rmSync(outputDir, { recursive: true, force: true });\n } catch {\n // ignore\n }\n },\n };\n}\n\n/**\n * Resolve the vendor oa_pc_uat root directory.\n * Checks both the submodule path and common fallback locations.\n */\nexport function resolveVendorRoot(fromDir?: string): string {\n const candidates = [\n path.resolve(fromDir ?? __dirname, '../../vendor/oa_pc_uat'),\n path.resolve(fromDir ?? process.cwd(), 'vendor/oa_pc_uat'),\n ];\n\n for (const candidate of candidates) {\n if (fs.existsSync(path.join(candidate, 'main.py'))) {\n return candidate;\n }\n }\n\n throw new Error(\n 'oa_pc_uat vendor directory not found. Run:\\n'\n + ' git submodule update --init vendor/oa_pc_uat\\n'\n + 'Or clone manually:\\n'\n + ' git clone git@git.woa.com:fishcui/oa_pc_uat.git vendor/oa_pc_uat',\n );\n}\n\n/**\n * Check that the Python environment for oa_pc_uat is properly set up.\n * Returns diagnostic info about missing dependencies.\n */\nexport async function checkE2EPrerequisites(\n vendorRoot: string,\n pythonBin = 'python3',\n): Promise<{\n ready: boolean;\n pythonAvailable: boolean;\n playwrightInstalled: boolean;\n chromiumInstalled: boolean;\n issues: string[];\n}> {\n const issues: string[] = [];\n let pythonAvailable = false;\n let playwrightInstalled = false;\n let chromiumInstalled = false;\n\n const { execFileSync } = await import('node:child_process');\n\n try {\n execFileSync(pythonBin, ['--version'], { encoding: 'utf-8' });\n pythonAvailable = true;\n } catch {\n issues.push(`${pythonBin} not found in PATH`);\n }\n\n if (pythonAvailable) {\n try {\n execFileSync(pythonBin, ['-c', 'import playwright'], {\n encoding: 'utf-8',\n cwd: vendorRoot,\n });\n playwrightInstalled = true;\n } catch {\n issues.push(`playwright not installed: run \\`${pythonBin} -m pip install -r vendor/oa_pc_uat/requirements.txt\\``);\n }\n }\n\n if (playwrightInstalled) {\n try {\n execFileSync(pythonBin, ['-c', 'from playwright.sync_api import sync_playwright; p = sync_playwright().start(); b = p.chromium; p.stop()'], {\n encoding: 'utf-8',\n cwd: vendorRoot,\n timeout: 10_000,\n });\n chromiumInstalled = true;\n } catch {\n issues.push(`Chromium not installed: run \\`${pythonBin} -m playwright install chromium\\``);\n }\n }\n\n return {\n ready: issues.length === 0,\n pythonAvailable,\n playwrightInstalled,\n chromiumInstalled,\n issues,\n };\n}\n"],"mappings":"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","names":["spawn","path","fileURLToPath","__dirname","path","fileURLToPath","spawn","fs","path","fileURLToPath","__dirname","path","fileURLToPath","fs"]}
|
|
1
|
+
{"version":3,"sources":["../src/e2e/E2EBrowserRunner.ts","../src/e2e/E2EScriptRunner.ts","../src/e2e/E2ETestHelper.ts"],"sourcesContent":["import { spawn, type ChildProcess } from 'node:child_process';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { setTimeout as sleep } from 'node:timers/promises';\nimport { logger } from '../logger.js';\nimport type { E2eConfig } from '../config.js';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nexport interface BrowserRunnerOptions {\n pythonBin?: string;\n projectRoot?: string;\n configFile?: string;\n headless?: boolean;\n baseUrl?: string;\n storageState?: string;\n outputDir?: string;\n timeout?: number;\n}\n\nexport interface ReplCommand {\n cmd: string;\n [key: string]: unknown;\n}\n\nexport interface ReplResponse {\n ok: boolean;\n data?: unknown;\n error?: string;\n}\n\nexport interface PageMeta {\n url: string;\n title: string;\n ready_state: string;\n}\n\nexport interface StepResult {\n path: string | null;\n label: string;\n}\n\nexport interface ScreenshotResult {\n path?: string;\n base64?: string;\n size: number;\n}\n\n/**\n * TypeScript wrapper around the Python Playwright REPL from oa_pc_uat.\n *\n * Spawns a Python process in interactive REPL mode and communicates via\n * the file-polling protocol (cmd.jsonl / resp.jsonl). This enables\n * issue-auto-finish E2E tests to drive a real browser for verifying\n * web UI changes end-to-end.\n */\nexport class E2EBrowserRunner {\n private proc: ChildProcess | null = null;\n private sessionId: string | null = null;\n private sockDir: string | null = null;\n private cmdFile: string | null = null;\n private respFile: string | null = null;\n private respLinesSeen = 0;\n private readonly options: Required<BrowserRunnerOptions>;\n\n constructor(\n private readonly e2eConfig: E2eConfig,\n opts: BrowserRunnerOptions = {},\n ) {\n const vendorRoot = opts.projectRoot\n ?? path.resolve(__dirname, '../../vendor/oa_pc_uat');\n\n this.options = {\n pythonBin: opts.pythonBin ?? this.e2eConfig.pythonBin ?? 'python3',\n projectRoot: vendorRoot,\n configFile: opts.configFile ?? '',\n headless: opts.headless ?? true,\n baseUrl: opts.baseUrl ?? e2eConfig.baseUrl,\n storageState: opts.storageState ?? '',\n outputDir: opts.outputDir ?? path.join(vendorRoot, 'outputs'),\n timeout: opts.timeout ?? 60_000,\n };\n }\n\n async start(): Promise<void> {\n const args = [\n 'main.py',\n '--headless',\n '-i',\n '--reuse-session',\n '--url', this.options.baseUrl,\n ];\n\n if (this.options.configFile) {\n args.push('--config', this.options.configFile);\n }\n if (this.options.storageState) {\n args.push('--storage-state', this.options.storageState);\n }\n if (this.options.outputDir) {\n args.push('--output-dir', this.options.outputDir);\n }\n\n logger.info('Starting E2E browser REPL', {\n cwd: this.options.projectRoot,\n args: [this.options.pythonBin, ...args],\n });\n\n this.proc = spawn(this.options.pythonBin, args, {\n cwd: this.options.projectRoot,\n stdio: ['pipe', 'pipe', 'pipe'],\n env: {\n ...process.env,\n PYTHONUNBUFFERED: '1',\n },\n });\n\n let stderr = '';\n this.proc.stderr?.on('data', (chunk) => {\n stderr += chunk.toString();\n });\n\n const readyInfo = await this.waitForReady(stderr);\n this.sessionId = readyInfo.session_id;\n this.sockDir = readyInfo.sock_dir;\n this.cmdFile = path.join(this.sockDir, 'cmd.jsonl');\n this.respFile = path.join(this.sockDir, 'resp.jsonl');\n this.respLinesSeen = 1; // skip the __ready__ line in resp.jsonl\n\n logger.info('E2E browser REPL started', {\n sessionId: this.sessionId,\n sockDir: this.sockDir,\n url: readyInfo.url,\n });\n }\n\n async stop(): Promise<void> {\n if (!this.proc) return;\n\n try {\n await this.send({ cmd: 'quit' });\n } catch {\n // ignore errors during quit\n }\n\n await sleep(500);\n\n if (this.proc.exitCode === null) {\n this.proc.kill('SIGTERM');\n await sleep(1000);\n if (this.proc.exitCode === null) {\n this.proc.kill('SIGKILL');\n }\n }\n\n this.proc = null;\n this.sessionId = null;\n this.sockDir = null;\n logger.info('E2E browser REPL stopped');\n }\n\n async send(command: ReplCommand): Promise<ReplResponse> {\n if (!this.cmdFile || !this.respFile) {\n throw new Error('REPL not started — call start() first');\n }\n\n const line = JSON.stringify(command) + '\\n';\n fs.appendFileSync(this.cmdFile, line, 'utf-8');\n\n const deadline = Date.now() + this.options.timeout;\n while (Date.now() < deadline) {\n const content = fs.readFileSync(this.respFile, 'utf-8');\n const lines = content.split('\\n').filter(Boolean);\n\n if (lines.length > this.respLinesSeen) {\n const newLine = lines[this.respLinesSeen]!;\n this.respLinesSeen = lines.length;\n return JSON.parse(newLine) as ReplResponse;\n }\n\n await sleep(100);\n }\n\n throw new Error(`REPL command timed out after ${this.options.timeout}ms: ${command.cmd}`);\n }\n\n // -- High-level helpers -----------------------------------------------\n\n async goto(url: string, waitUntil = 'domcontentloaded'): Promise<PageMeta> {\n const resp = await this.send({ cmd: 'goto', url, wait_until: waitUntil });\n this.assertOk(resp);\n return resp.data as PageMeta;\n }\n\n async navigate(url: string): Promise<PageMeta> {\n const resp = await this.send({ cmd: 'navigate', url });\n this.assertOk(resp);\n return resp.data as PageMeta;\n }\n\n async click(selector: string, timeout = 5000): Promise<void> {\n const resp = await this.send({ cmd: 'click', selector, timeout });\n this.assertOk(resp);\n }\n\n async fill(selector: string, value: string, timeout = 5000): Promise<void> {\n const resp = await this.send({ cmd: 'fill', selector, value, timeout });\n this.assertOk(resp);\n }\n\n async type(selector: string, text: string, delay = 50): Promise<void> {\n const resp = await this.send({ cmd: 'type', selector, text, delay });\n this.assertOk(resp);\n }\n\n async press(key: string, selector?: string): Promise<void> {\n const resp = await this.send({ cmd: 'press', key, selector });\n this.assertOk(resp);\n }\n\n async hover(selector: string): Promise<void> {\n const resp = await this.send({ cmd: 'hover', selector });\n this.assertOk(resp);\n }\n\n async select(selector: string, value: string | string[]): Promise<void> {\n const resp = await this.send({ cmd: 'select', selector, value });\n this.assertOk(resp);\n }\n\n async waitFor(selector: string, state = 'visible', timeout = 10000): Promise<void> {\n const resp = await this.send({ cmd: 'wait_for', selector, state, timeout });\n this.assertOk(resp);\n }\n\n async waitForUrl(url: string, timeout = 15000): Promise<string> {\n const resp = await this.send({ cmd: 'wait_for_url', url, timeout });\n this.assertOk(resp);\n return (resp.data as { current_url: string }).current_url;\n }\n\n async waitIdle(timeout = 15000): Promise<void> {\n const resp = await this.send({ cmd: 'wait_idle', timeout });\n this.assertOk(resp);\n }\n\n async wait(ms: number): Promise<void> {\n const resp = await this.send({ cmd: 'wait', ms });\n this.assertOk(resp);\n }\n\n async screenshot(opts?: { fullPage?: boolean; selector?: string; encode?: boolean; name?: string }): Promise<ScreenshotResult> {\n const resp = await this.send({\n cmd: 'screenshot',\n full_page: opts?.fullPage ?? true,\n selector: opts?.selector,\n encode: opts?.encode ?? false,\n name: opts?.name,\n });\n this.assertOk(resp);\n return resp.data as ScreenshotResult;\n }\n\n async step(label: string): Promise<StepResult> {\n const resp = await this.send({ cmd: 'step', label });\n this.assertOk(resp);\n return resp.data as StepResult;\n }\n\n async meta(): Promise<PageMeta> {\n const resp = await this.send({ cmd: 'meta' });\n this.assertOk(resp);\n return resp.data as PageMeta;\n }\n\n async snapshot(include?: string[]): Promise<Record<string, unknown>> {\n const resp = await this.send({ cmd: 'snapshot', include });\n this.assertOk(resp);\n return resp.data as Record<string, unknown>;\n }\n\n async queryText(text: string, exact = false): Promise<unknown[]> {\n const resp = await this.send({ cmd: 'query_text', text, exact });\n this.assertOk(resp);\n return resp.data as unknown[];\n }\n\n async querySelector(selector: string, max = 50): Promise<unknown[]> {\n const resp = await this.send({ cmd: 'query', selector, max });\n this.assertOk(resp);\n return resp.data as unknown[];\n }\n\n async evaluate(expression: string, arg?: unknown): Promise<unknown> {\n const resp = await this.send({ cmd: 'evaluate', expression, arg });\n this.assertOk(resp);\n return resp.data;\n }\n\n async text(selector = 'body', maxLength = 20000): Promise<string> {\n const resp = await this.send({ cmd: 'text', selector, max_length: maxLength });\n this.assertOk(resp);\n return (resp.data as { text: string }).text;\n }\n\n async html(selector?: string, maxLength = 50000): Promise<string> {\n const resp = await this.send({ cmd: 'html', selector, max_length: maxLength });\n this.assertOk(resp);\n return (resp.data as { html: string }).html;\n }\n\n async networkLog(opts?: { since?: number; type?: string; urlContains?: string; tail?: number }): Promise<{ count: number; entries: unknown[] }> {\n const resp = await this.send({\n cmd: 'network_log',\n since: opts?.since,\n type: opts?.type,\n url_contains: opts?.urlContains,\n tail: opts?.tail,\n });\n this.assertOk(resp);\n return resp.data as { count: number; entries: unknown[] };\n }\n\n async consoleLog(opts?: { since?: number; type?: string; tail?: number }): Promise<{ count: number; entries: unknown[] }> {\n const resp = await this.send({\n cmd: 'console_log',\n since: opts?.since,\n type: opts?.type,\n tail: opts?.tail,\n });\n this.assertOk(resp);\n return resp.data as { count: number; entries: unknown[] };\n }\n\n async requestPairs(opts?: { urlContains?: string; method?: string; statusMin?: number; statusMax?: number }): Promise<{ count: number; entries: unknown[] }> {\n const resp = await this.send({\n cmd: 'request_pairs',\n url_contains: opts?.urlContains,\n method: opts?.method,\n status_min: opts?.statusMin,\n status_max: opts?.statusMax,\n });\n this.assertOk(resp);\n return resp.data as { count: number; entries: unknown[] };\n }\n\n async clearLogs(): Promise<void> {\n const resp = await this.send({ cmd: 'clear_logs' });\n this.assertOk(resp);\n }\n\n get isRunning(): boolean {\n return this.proc !== null && this.proc.exitCode === null;\n }\n\n // -- Private ----------------------------------------------------------\n\n private assertOk(resp: ReplResponse): void {\n if (!resp.ok) {\n throw new Error(`REPL error: ${resp.error}`);\n }\n }\n\n private async waitForReady(stderr: string): Promise<{\n session_id: string;\n sock_dir: string;\n url: string;\n }> {\n if (!this.proc?.stdout) {\n throw new Error('REPL process has no stdout');\n }\n\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(\n `REPL did not become ready within ${this.options.timeout}ms.\\nStderr: ${stderr}`,\n ));\n }, this.options.timeout);\n\n let buffer = '';\n const onData = (chunk: Buffer) => {\n buffer += chunk.toString();\n const lines = buffer.split('\\n');\n for (const line of lines) {\n if (!line.trim()) continue;\n try {\n const msg = JSON.parse(line);\n if (msg.__ready__) {\n clearTimeout(timeout);\n this.proc!.stdout!.off('data', onData);\n resolve({\n session_id: msg.session_id,\n sock_dir: msg.sock_dir,\n url: msg.url,\n });\n return;\n }\n } catch {\n // not JSON yet, keep buffering\n }\n }\n };\n\n this.proc!.stdout!.on('data', onData);\n this.proc!.on('error', (err) => {\n clearTimeout(timeout);\n reject(new Error(`REPL process error: ${err.message}`));\n });\n this.proc!.on('exit', (code) => {\n clearTimeout(timeout);\n reject(new Error(`REPL process exited prematurely (code ${code}).\\nStderr: ${stderr}`));\n });\n });\n }\n}\n","import { spawn } from 'node:child_process';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { logger } from '../logger.js';\nimport type { E2eConfig } from '../config.js';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nexport interface ScriptRunResult {\n success: boolean;\n exitCode: number;\n stdout: string;\n stderr: string;\n outputDir?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface ScriptRunnerOptions {\n pythonBin?: string;\n projectRoot?: string;\n configFile?: string;\n timeoutMs?: number;\n env?: Record<string, string>;\n}\n\n/**\n * Run a Python UAT script (non-interactive) and collect results.\n *\n * Executes `python3 main.py --script <script> --headless` from oa_pc_uat.\n * Suitable for batch E2E verification where each script performs a series\n * of page operations, captures screenshots/logs, then exits.\n */\nexport class E2EScriptRunner {\n private readonly opts: Required<ScriptRunnerOptions>;\n\n constructor(\n private readonly e2eConfig: E2eConfig,\n options: ScriptRunnerOptions = {},\n ) {\n const vendorRoot = options.projectRoot\n ?? path.resolve(__dirname, '../../vendor/oa_pc_uat');\n\n this.opts = {\n pythonBin: options.pythonBin ?? this.e2eConfig.pythonBin ?? 'python3',\n projectRoot: vendorRoot,\n configFile: options.configFile ?? '',\n timeoutMs: options.timeoutMs ?? 300_000,\n env: options.env ?? {},\n };\n }\n\n async runScript(\n scriptPath: string,\n runOpts?: {\n baseUrl?: string;\n outputPath?: string;\n storageState?: string;\n extraArgs?: string[];\n },\n ): Promise<ScriptRunResult> {\n const args = [\n 'main.py',\n '--headless',\n '--reuse-session',\n '--script', scriptPath,\n '--url', runOpts?.baseUrl ?? this.e2eConfig.baseUrl,\n ];\n\n if (this.opts.configFile) {\n args.push('--config', this.opts.configFile);\n }\n if (runOpts?.outputPath) {\n args.push('--output-path', runOpts.outputPath);\n }\n if (runOpts?.storageState) {\n args.push('--storage-state', runOpts.storageState);\n }\n if (runOpts?.extraArgs) {\n args.push(...runOpts.extraArgs);\n }\n\n logger.info('Running E2E script', {\n script: scriptPath,\n cwd: this.opts.projectRoot,\n });\n\n return new Promise<ScriptRunResult>((resolve, reject) => {\n const proc = spawn(this.opts.pythonBin, args, {\n cwd: this.opts.projectRoot,\n env: {\n ...process.env,\n PYTHONUNBUFFERED: '1',\n ...this.opts.env,\n },\n timeout: this.opts.timeoutMs,\n });\n\n let stdout = '';\n let stderr = '';\n\n proc.stdout?.on('data', (chunk) => { stdout += chunk.toString(); });\n proc.stderr?.on('data', (chunk) => { stderr += chunk.toString(); });\n\n proc.on('error', (err) => {\n reject(new Error(`E2E script process error: ${err.message}`));\n });\n\n proc.on('close', (code) => {\n let metadata: Record<string, unknown> | undefined;\n try {\n metadata = JSON.parse(stdout.trim());\n } catch {\n // stdout may not be valid JSON\n }\n\n const exitCode = code ?? 1;\n resolve({\n success: exitCode === 0,\n exitCode,\n stdout,\n stderr,\n outputDir: metadata?.output_dir as string | undefined,\n metadata,\n });\n });\n });\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { E2EBrowserRunner, type BrowserRunnerOptions } from './E2EBrowserRunner.js';\nimport { E2EScriptRunner, type ScriptRunnerOptions } from './E2EScriptRunner.js';\nimport type { E2eConfig } from '../config.js';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nexport interface E2ETestContext {\n browser: E2EBrowserRunner;\n scriptRunner: E2EScriptRunner;\n outputDir: string;\n cleanup: () => Promise<void>;\n}\n\n/**\n * Bootstrap an E2E test context with browser runner, script runner,\n * and temporary output directory. Call `cleanup()` in afterAll/afterEach.\n */\nexport async function createE2ETestContext(\n e2eConfig: E2eConfig,\n opts?: {\n browser?: BrowserRunnerOptions;\n script?: ScriptRunnerOptions;\n outputDir?: string;\n },\n): Promise<E2ETestContext> {\n const outputDir = opts?.outputDir\n ?? fs.mkdtempSync(path.join(process.env.TMPDIR ?? '/tmp', 'iaf-e2e-'));\n\n const browser = new E2EBrowserRunner(e2eConfig, {\n ...opts?.browser,\n outputDir,\n });\n\n const scriptRunner = new E2EScriptRunner(e2eConfig, opts?.script);\n\n return {\n browser,\n scriptRunner,\n outputDir,\n cleanup: async () => {\n if (browser.isRunning) {\n await browser.stop();\n }\n try {\n fs.rmSync(outputDir, { recursive: true, force: true });\n } catch {\n // ignore\n }\n },\n };\n}\n\n/**\n * Resolve the vendor oa_pc_uat root directory.\n * Checks both the submodule path and common fallback locations.\n */\nexport function resolveVendorRoot(fromDir?: string): string {\n const candidates = [\n path.resolve(fromDir ?? __dirname, '../../vendor/oa_pc_uat'),\n path.resolve(fromDir ?? process.cwd(), 'vendor/oa_pc_uat'),\n ];\n\n for (const candidate of candidates) {\n if (fs.existsSync(path.join(candidate, 'main.py'))) {\n return candidate;\n }\n }\n\n throw new Error(\n 'oa_pc_uat vendor directory not found. Run:\\n'\n + ' git submodule update --init vendor/oa_pc_uat\\n'\n + 'Or clone manually:\\n'\n + ' git clone git@git.woa.com:fishcui/oa_pc_uat.git vendor/oa_pc_uat',\n );\n}\n\n/**\n * Check that the Python environment for oa_pc_uat is properly set up.\n * Returns diagnostic info about missing dependencies.\n */\nexport async function checkE2EPrerequisites(\n vendorRoot: string,\n pythonBin = 'python3',\n): Promise<{\n ready: boolean;\n pythonAvailable: boolean;\n playwrightInstalled: boolean;\n chromiumInstalled: boolean;\n issues: string[];\n}> {\n const issues: string[] = [];\n let pythonAvailable = false;\n let playwrightInstalled = false;\n let chromiumInstalled = false;\n\n const { execFileSync } = await import('node:child_process');\n\n try {\n execFileSync(pythonBin, ['--version'], { encoding: 'utf-8' });\n pythonAvailable = true;\n } catch {\n issues.push(`${pythonBin} not found in PATH`);\n }\n\n if (pythonAvailable) {\n try {\n execFileSync(pythonBin, ['-c', 'import playwright'], {\n encoding: 'utf-8',\n cwd: vendorRoot,\n });\n playwrightInstalled = true;\n } catch {\n issues.push(`playwright not installed: run \\`${pythonBin} -m pip install -r vendor/oa_pc_uat/requirements.txt\\``);\n }\n }\n\n if (playwrightInstalled) {\n try {\n execFileSync(pythonBin, ['-c', 'from playwright.sync_api import sync_playwright; p = sync_playwright().start(); b = p.chromium; p.stop()'], {\n encoding: 'utf-8',\n cwd: vendorRoot,\n timeout: 10_000,\n });\n chromiumInstalled = true;\n } catch {\n issues.push(`Chromium not installed: run \\`${pythonBin} -m playwright install chromium\\``);\n }\n }\n\n return {\n ready: issues.length === 0,\n pythonAvailable,\n playwrightInstalled,\n chromiumInstalled,\n issues,\n };\n}\n"],"mappings":"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","names":["spawn","path","fileURLToPath","__dirname","path","fileURLToPath","spawn","fs","path","fileURLToPath","__dirname","path","fileURLToPath","fs"]}
|
|
@@ -48,39 +48,57 @@ export interface SetupResult {
|
|
|
48
48
|
export interface PhaseLoopResult {
|
|
49
49
|
serversStarted: boolean;
|
|
50
50
|
}
|
|
51
|
-
/**
|
|
52
|
-
|
|
53
|
-
*
|
|
54
|
-
* 由 PipelineOrchestrator 一次性构建,步骤函数按需取用。
|
|
55
|
-
*/
|
|
56
|
-
export interface OrchestratorDeps {
|
|
51
|
+
/** 核心依赖 — 所有 Step 共用 */
|
|
52
|
+
export interface CoreDeps {
|
|
57
53
|
tenantId: string;
|
|
58
54
|
config: Config;
|
|
55
|
+
tracker: IssueTracker;
|
|
59
56
|
gongfeng: GongfengClient;
|
|
57
|
+
eventBus: EventBus;
|
|
58
|
+
emitProgress(issueIid: number, step: string, message: string): void;
|
|
59
|
+
}
|
|
60
|
+
/** Git 操作依赖 — Setup / Completion */
|
|
61
|
+
export interface GitDeps {
|
|
60
62
|
mainGit: GitOperations;
|
|
61
63
|
mainGitMutex: AsyncMutex;
|
|
64
|
+
ensureWorktree(wtCtx: WorktreeContext): Promise<void>;
|
|
65
|
+
workspaceManager: WorkspaceManager;
|
|
66
|
+
}
|
|
67
|
+
/** AI 执行依赖 — PhaseLoop */
|
|
68
|
+
export interface AIDeps {
|
|
62
69
|
aiRunner: AIRunner;
|
|
63
70
|
e2eAiRunner?: AIRunner;
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
portAllocator: PortAllocator;
|
|
68
|
-
devServerManager: DevServerManager;
|
|
69
|
-
eventBus: EventBus;
|
|
70
|
-
claimer?: IssueClaimer | null;
|
|
71
|
-
workspaceManager: WorkspaceManager;
|
|
72
|
-
emitProgress(issueIid: number, step: string, message: string): void;
|
|
73
|
-
ensureWorktree(wtCtx: WorktreeContext): Promise<void>;
|
|
74
|
-
installDependencies(workDir: string): Promise<void>;
|
|
75
|
-
buildPhaseHooks(iid: number, issueId: number): import('../phases/BasePhase.js').PhaseLifecycleHooks;
|
|
76
|
-
shouldAutoApprove(issueLabels: string[]): boolean;
|
|
71
|
+
}
|
|
72
|
+
/** 预览服务器依赖 — PhaseLoop / Completion / Failure */
|
|
73
|
+
export interface PreviewDeps {
|
|
77
74
|
shouldDeployServers(issueIid: number): boolean;
|
|
78
75
|
startPreviewServers(wtCtx: WorktreeContext, issue: GongfengIssue): Promise<import('../deploy/PortAllocator.js').PortPair | null>;
|
|
79
76
|
stopPreviewServers(issueIid: number): void;
|
|
80
|
-
tryCreateMergeRequest(issue: GongfengIssue, branchName: string, workDir: string, previewUrl?: string | null): Promise<import('./PipelineOrchestrator.js').MergeRequestResult | null>;
|
|
81
77
|
buildPreviewUrl(issueIid: number): string | null;
|
|
82
78
|
getPortsForIssue(issueIid: number): import('../deploy/PortAllocator.js').PortPair | undefined;
|
|
83
79
|
isPreviewRunning(issueIid: number): boolean;
|
|
84
|
-
|
|
80
|
+
}
|
|
81
|
+
/** 完成/失败处理依赖 — Completion / Failure */
|
|
82
|
+
export interface CompletionDeps {
|
|
83
|
+
tryCreateMergeRequest(issue: GongfengIssue, branchName: string, workDir: string, previewUrl?: string | null): Promise<import('./PipelineOrchestrator.js').MergeRequestResult | null>;
|
|
84
|
+
screenshotPublisher: ScreenshotPublisher;
|
|
85
|
+
claimer?: IssueClaimer | null;
|
|
86
|
+
}
|
|
87
|
+
/** 策略/安装依赖 — Setup / PhaseLoop */
|
|
88
|
+
export interface PolicyDeps {
|
|
89
|
+
shouldAutoApprove(issueLabels: string[]): boolean;
|
|
90
|
+
installDependencies(workDir: string): Promise<void>;
|
|
91
|
+
consumePendingAction?: (iid: number) => 'abort' | 'redo' | 'restart' | undefined;
|
|
92
|
+
supplementStore?: SupplementStore;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* OrchestratorDeps — 编排器注入给各步骤的依赖包。
|
|
96
|
+
*
|
|
97
|
+
* 由 PipelineOrchestrator 一次性构建,步骤函数按需取用。
|
|
98
|
+
* 按域拆分为 CoreDeps / GitDeps / AIDeps / PreviewDeps / CompletionDeps / PolicyDeps。
|
|
99
|
+
*/
|
|
100
|
+
export interface OrchestratorDeps extends CoreDeps, GitDeps, AIDeps, PreviewDeps, CompletionDeps, PolicyDeps {
|
|
101
|
+
portAllocator: PortAllocator;
|
|
102
|
+
devServerManager: DevServerManager;
|
|
85
103
|
}
|
|
86
104
|
//# sourceMappingURL=IssueProcessingContext.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IssueProcessingContext.d.ts","sourceRoot":"","sources":["../../src/orchestrator/IssueProcessingContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAClF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AACrE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;AACrF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE9D;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,aAAa,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,eAAe,CAAC;IACvB,MAAM,EAAE,WAAW,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,WAAW,CAAC;IACzB,gBAAgB,EAAE,sBAAsB,CAAC;IACzC,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,YAAY,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,mCAAmC;IACnC,KAAK,EAAE,aAAa,CAAC;IACrB,MAAM,EAAE,eAAe,CAAC;IACxB,+DAA+D;IAC/D,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,OAAO,CAAC;CACzB;
|
|
1
|
+
{"version":3,"file":"IssueProcessingContext.d.ts","sourceRoot":"","sources":["../../src/orchestrator/IssueProcessingContext.ts"],"names":[],"mappings":"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"}
|
|
@@ -63,6 +63,16 @@ export declare class PipelineOrchestrator {
|
|
|
63
63
|
private ensureNodeModules;
|
|
64
64
|
restartIssue(issueIid: number): Promise<void>;
|
|
65
65
|
cancelIssue(issueIid: number): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Remove the E2E output directory for an issue: {uatVendorDir}/outputs/issue-{iid}
|
|
68
|
+
*/
|
|
69
|
+
private cleanupE2eOutputs;
|
|
70
|
+
/**
|
|
71
|
+
* When WorkspaceManager is active, the workspace root (which contains
|
|
72
|
+
* associate repo clone dirs) may survive after cleanupWorktree removes
|
|
73
|
+
* only the primary worktree. Force-remove the whole workspace root.
|
|
74
|
+
*/
|
|
75
|
+
private cleanupWorkspaceRoot;
|
|
66
76
|
retryFromPhase(issueIid: number, phase: string): void;
|
|
67
77
|
abortIssue(issueIid: number): void;
|
|
68
78
|
continueIssue(issueIid: number): void;
|
|
@@ -83,7 +93,6 @@ export declare class PipelineOrchestrator {
|
|
|
83
93
|
private tryFindExistingMergeRequest;
|
|
84
94
|
private shouldDeployServers;
|
|
85
95
|
private shouldAutoApprove;
|
|
86
|
-
private buildPhaseHooks;
|
|
87
96
|
private startPreviewServers;
|
|
88
97
|
stopPreviewServers(issueIid: number): void;
|
|
89
98
|
stopPreviewAndCleanWorktree(issueIid: number): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PipelineOrchestrator.d.ts","sourceRoot":"","sources":["../../src/orchestrator/PipelineOrchestrator.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAQ1D,OAAO,EAAwG,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAEtK,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAGnE,OAAO,EAA+B,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACnF,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD,OAAO,EAAE,aAAa,EAAiB,MAAM,4BAA4B,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"PipelineOrchestrator.d.ts","sourceRoot":"","sources":["../../src/orchestrator/PipelineOrchestrator.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,7 +6,7 @@ import type { IssueProcessingContext, OrchestratorDeps, PhaseLoopResult } from '
|
|
|
6
6
|
* - 确定恢复阶段索引
|
|
7
7
|
* - 逐个执行阶段
|
|
8
8
|
* - 处理 gate 阶段(自动批准或等待审核)
|
|
9
|
-
* - 执行 AI
|
|
9
|
+
* - 执行 AI 阶段(通过 runPhaseWithLifecycle)
|
|
10
10
|
* - 按需启动预览服务器
|
|
11
11
|
* - verify 阶段支持 verify-fix loop(验证失败自动回退 build 修复)
|
|
12
12
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PhaseLoopStep.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/steps/PhaseLoopStep.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;
|
|
1
|
+
{"version":3,"file":"PhaseLoopStep.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/steps/PhaseLoopStep.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AAe5E,OAAO,KAAK,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAyP9G;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,sBAAsB,EAC3B,IAAI,EAAE,gBAAgB,EACtB,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,eAAe,EACvB,QAAQ,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,GACpC,OAAO,CAAC,eAAe,GAAG;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,CAAC,CAwNhD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SetupStep.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/steps/SetupStep.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAM1G;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,sBAAsB,EAC3B,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,WAAW,CAAC,
|
|
1
|
+
{"version":3,"file":"SetupStep.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/steps/SetupStep.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAM1G;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,sBAAsB,EAC3B,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,WAAW,CAAC,CA6EtB"}
|
|
@@ -10,7 +10,7 @@ export declare class PlanPersistence {
|
|
|
10
10
|
private issueIid;
|
|
11
11
|
constructor(workDir: string, issueIid: number);
|
|
12
12
|
get baseDir(): string;
|
|
13
|
-
|
|
13
|
+
get planDir(): string;
|
|
14
14
|
ensureDir(): void;
|
|
15
15
|
writeIssueMeta(meta: {
|
|
16
16
|
id: number;
|
|
@@ -37,5 +37,11 @@ export declare class PlanPersistence {
|
|
|
37
37
|
}): void;
|
|
38
38
|
updatePhaseSessionId(phaseName: string, sessionId: string): void;
|
|
39
39
|
getPhaseSessionId(phaseName: string): string | undefined;
|
|
40
|
+
/** 读取 planDir 下指定文件,不存在返回 null */
|
|
41
|
+
readFile(filename: string): string | null;
|
|
42
|
+
/** 检查 planDir 下指定文件是否就绪(存在 + 大于 minBytes) */
|
|
43
|
+
isArtifactReady(filename: string, minBytes?: number): boolean;
|
|
44
|
+
/** 写入 planDir 下指定文件(自动 ensureDir) */
|
|
45
|
+
writeFile(filename: string, content: string): void;
|
|
40
46
|
}
|
|
41
47
|
//# sourceMappingURL=PlanPersistence.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlanPersistence.d.ts","sourceRoot":"","sources":["../../src/persistence/PlanPersistence.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAiB,KAAK,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACzF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAOrE,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAS;gBAEb,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAK7C,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,OAAO,
|
|
1
|
+
{"version":3,"file":"PlanPersistence.d.ts","sourceRoot":"","sources":["../../src/persistence/PlanPersistence.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAiB,KAAK,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACzF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAOrE,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAS;gBAEb,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAK7C,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,SAAS,IAAI,IAAI;IAMjB,cAAc,CAAC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAOvG,aAAa,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IAOvC,YAAY,IAAI,YAAY,GAAG,IAAI;IAUnC,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAMpC,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAMlC,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAMpC,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,SAAwB,GAAG,IAAI;IAM1E,eAAe,IAAI,MAAM,EAAE;IAK3B,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,WAAW,GAAG,YAAY;IA8B5G,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAMhC,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAsB1C,kBAAkB,IAAI,MAAM,GAAG,IAAI;IAUnC,iBAAiB,IAAI,WAAW,EAAE;IAWlC,MAAM,CAAC,2BAA2B,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,MAAM;IAalE,mBAAmB,CACjB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;QAAE,iBAAiB,CAAC,EAAE,OAAO,CAAA;KAAE,GACxC,IAAI;IA+BP,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAOhE,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IASxD,kCAAkC;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAUzC,6CAA6C;IAC7C,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,SAAK,GAAG,OAAO;IAUzD,qCAAqC;IACrC,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;CAInD"}
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import type { AIRunner, RunResult, InputRequest } from '../ai-runner/index.js';
|
|
1
|
+
import type { AIRunner, RunResult, InputRequest, StreamEvent } from '../ai-runner/index.js';
|
|
2
2
|
import { GitOperations } from '../git/GitOperations.js';
|
|
3
3
|
import { PlanPersistence } from '../persistence/PlanPersistence.js';
|
|
4
|
-
import { IssueState } from '../tracker/IssueState.js';
|
|
5
|
-
import { ActionLifecycleManager } from '../lifecycle/ActionLifecycleManager.js';
|
|
6
4
|
import { Config } from '../config.js';
|
|
7
5
|
import type { PortPair } from '../deploy/PortAllocator.js';
|
|
8
6
|
import type { DemandSpec } from '../demand/DemandSpec.js';
|
|
9
7
|
import type { WorkspaceLayout } from '../prompts/templates.js';
|
|
8
|
+
import type { PhaseOutcome, PhaseCallbacks } from './PhaseOutcome.js';
|
|
10
9
|
import { Logger } from '../logger.js';
|
|
11
10
|
/** verify-fix loop 的修复上下文 — 当验证失败回退到 build 阶段时注入 */
|
|
12
11
|
export interface FixContext {
|
|
@@ -25,71 +24,61 @@ export interface PhaseContext {
|
|
|
25
24
|
fixContext?: FixContext;
|
|
26
25
|
workspace?: WorkspaceLayout;
|
|
27
26
|
}
|
|
28
|
-
/** 阶段生命周期钩子 — 由编排器注入,阶段不直接依赖 tracker/gongfeng */
|
|
29
|
-
export interface PhaseLifecycleHooks {
|
|
30
|
-
onPhaseStart(phaseName: string): Promise<void>;
|
|
31
|
-
onPhaseDone(phaseName: string): Promise<void>;
|
|
32
|
-
onPhaseFailed(phaseName: string, error: string): Promise<void>;
|
|
33
|
-
onComment(message: string): Promise<void>;
|
|
34
|
-
/** 异步阶段完成后触发 gate 审批(进程退出回调使用) */
|
|
35
|
-
onAsyncGateApproval?(phaseName: string): Promise<void>;
|
|
36
|
-
isNoteSyncEnabled(): boolean;
|
|
37
|
-
isE2eEnabled(): boolean;
|
|
38
|
-
}
|
|
39
27
|
export declare abstract class BasePhase {
|
|
40
|
-
|
|
28
|
+
static readonly MIN_ARTIFACT_BYTES = 50;
|
|
41
29
|
protected aiRunner: AIRunner;
|
|
42
30
|
protected git: GitOperations;
|
|
43
31
|
protected plan: PlanPersistence;
|
|
44
32
|
protected config: Config;
|
|
45
33
|
protected logger: Logger;
|
|
46
|
-
private lifecycle;
|
|
47
|
-
protected hooks: PhaseLifecycleHooks;
|
|
48
34
|
/** 多仓模式下所有 repo 的 GitOperations(repo name → GitOperations) */
|
|
49
|
-
|
|
35
|
+
protected wtGitMap?: Map<string, GitOperations>;
|
|
50
36
|
abstract readonly phaseName: string;
|
|
51
|
-
|
|
52
|
-
get doneState(): IssueState;
|
|
53
|
-
constructor(aiRunner: AIRunner, git: GitOperations, plan: PlanPersistence, config: Config, lifecycle: ActionLifecycleManager, hooks: PhaseLifecycleHooks);
|
|
37
|
+
constructor(aiRunner: AIRunner, git: GitOperations, plan: PlanPersistence, config: Config);
|
|
54
38
|
/** 注入多仓库 GitOperations map(由编排器在创建 phase 后调用) */
|
|
55
39
|
setWtGitMap(map: Map<string, GitOperations>): void;
|
|
56
40
|
protected abstract buildPrompt(ctx: PhaseContext): string;
|
|
57
41
|
protected getRunMode(): 'plan' | 'agent' | undefined;
|
|
58
|
-
|
|
42
|
+
/** 获取阶段预期的产物文件列表。编排器需通过此方法同步产物到 Issue。 */
|
|
43
|
+
getResultFiles(_ctx?: PhaseContext): Array<{
|
|
59
44
|
filename: string;
|
|
60
45
|
label: string;
|
|
61
46
|
}>;
|
|
62
|
-
|
|
63
|
-
|
|
47
|
+
/**
|
|
48
|
+
* 纯逻辑执行 — 零副作用,返回 PhaseOutcome。
|
|
49
|
+
*
|
|
50
|
+
* 阶段内部仅做:构建 prompt → AI 执行 → 验证产物 → 返回结果。
|
|
51
|
+
* 所有副作用(状态转换、Git commit、Issue 评论、事件推送)由编排器统一处理。
|
|
52
|
+
*/
|
|
53
|
+
run(ctx: PhaseContext, callbacks?: PhaseCallbacks): Promise<PhaseOutcome>;
|
|
54
|
+
protected resolveResumeInfo(): {
|
|
55
|
+
resumable: boolean;
|
|
56
|
+
sessionId?: string;
|
|
57
|
+
};
|
|
64
58
|
private isAcpMode;
|
|
65
59
|
protected resolveAIWorkDir(ctx?: PhaseContext): string;
|
|
66
|
-
|
|
67
|
-
private
|
|
60
|
+
/** 检查预期产物文件是否已就绪(存在且满足最小字节数),不抛异常 */
|
|
61
|
+
private checkArtifactsReady;
|
|
62
|
+
protected runAI(displayId: number, prompt: string, onInputRequired?: (request: InputRequest) => Promise<string>, options?: {
|
|
63
|
+
sessionId?: string;
|
|
64
|
+
continueSession?: boolean;
|
|
65
|
+
}, ctx?: PhaseContext, onStreamEvent?: (event: StreamEvent) => void): Promise<RunResult>;
|
|
66
|
+
protected runWithResumeFallback(displayId: number, sessionId: string, resumePrompt: string, fullPrompt: string, onInputRequired?: (request: InputRequest) => Promise<string>, ctx?: PhaseContext, onStreamEvent?: (event: StreamEvent) => void): Promise<RunResult>;
|
|
68
67
|
/**
|
|
69
68
|
* 判断 AI 执行失败是否为永久性错误(不可重试)。
|
|
70
69
|
* 模型不存在、API key 无效等配置问题重试不会成功。
|
|
71
70
|
*/
|
|
72
|
-
|
|
71
|
+
protected classifyRetryable(result: RunResult): boolean;
|
|
73
72
|
/**
|
|
74
73
|
* Heuristic: a resume failure is typically an immediate process exit
|
|
75
74
|
* (exit code != 0, empty output) caused by an invalid/expired session ID.
|
|
76
75
|
*/
|
|
77
76
|
private isResumeFailure;
|
|
78
|
-
|
|
79
|
-
protected notifyPhaseStart(): Promise<void>;
|
|
80
|
-
protected notifyPhaseDone(): Promise<void>;
|
|
81
|
-
protected notifyPhaseFailed(error: string): Promise<void>;
|
|
82
|
-
protected notifyComment(message: string): Promise<void>;
|
|
83
|
-
/**
|
|
84
|
-
* Build an onInputRequired handler for ACP permission delegation.
|
|
85
|
-
* Only returns a handler when codebuddyAcpAutoApprove is false,
|
|
86
|
-
* enabling review gate delegation for permission requests.
|
|
87
|
-
*/
|
|
88
|
-
protected buildInputRequiredHandler(displayId: number): ((request: InputRequest) => Promise<string>) | undefined;
|
|
77
|
+
protected persistSessionId(sessionId: string | undefined): void;
|
|
89
78
|
protected resolveRules(ctx: PhaseContext): Promise<string | null>;
|
|
90
|
-
protected
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
79
|
+
protected validatePhaseOutput(ctx: PhaseContext, _displayId: number, resultFiles?: {
|
|
80
|
+
filename: string;
|
|
81
|
+
label: string;
|
|
82
|
+
}[]): Promise<void>;
|
|
94
83
|
}
|
|
95
84
|
//# sourceMappingURL=BasePhase.d.ts.map
|