allure 3.9.0 → 3.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -1
- package/dist/commands/agent-run.d.ts +21 -0
- package/dist/commands/agent-run.js +151 -0
- package/dist/commands/agent.d.ts +38 -15
- package/dist/commands/agent.js +288 -219
- package/dist/commands/open.js +2 -2
- package/dist/commands/run.js +0 -18
- package/dist/index.js +16 -3
- package/dist/utils/index.d.ts +0 -2
- package/dist/utils/index.js +0 -2
- package/package.json +28 -28
- package/dist/utils/agent-select.d.ts +0 -41
- package/dist/utils/agent-select.js +0 -141
- package/dist/utils/agent-state.d.ts +0 -15
- package/dist/utils/agent-state.js +0 -83
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
|
-
import { argv } from "node:process";
|
|
2
|
+
import process, { argv } from "node:process";
|
|
3
3
|
import { Builtins, Cli } from "clipanion";
|
|
4
|
-
import { AgentCommand, AgentLatestCommand, AgentSelectCommand, AgentStateDirCommand, Allure2Command, AwesomeCommand, CheckCommand, ClassicCommand, CsvCommand, DashboardCommand, GenerateCommand, HistoryCommand, JiraClearCommand, KnownIssueCommand, LogCommand, OpenCommand, QualityGateCommand, ResultsPackCommand, ResultsUnpackCommand, RunCommand, SlackCommand, TestPlanCommand, WatchCommand, } from "./commands/index.js";
|
|
4
|
+
import { AgentCommand, AGENT_TASK_MAP_HELP, AgentCapabilitiesCommand, AgentLatestCommand, AgentQueryCommand, AgentSelectCommand, AgentStateDirCommand, Allure2Command, AwesomeCommand, CheckCommand, ClassicCommand, CsvCommand, DashboardCommand, GenerateCommand, HistoryCommand, JiraClearCommand, KnownIssueCommand, LogCommand, OpenCommand, QualityGateCommand, ResultsPackCommand, ResultsUnpackCommand, RunCommand, SlackCommand, TestPlanCommand, WatchCommand, isAgentTaskMapHelpRequest, } from "./commands/index.js";
|
|
5
5
|
const [node, app, ...args] = argv;
|
|
6
6
|
const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
|
|
7
7
|
const cli = new Cli({
|
|
@@ -11,7 +11,9 @@ const cli = new Cli({
|
|
|
11
11
|
});
|
|
12
12
|
cli.register(AwesomeCommand);
|
|
13
13
|
cli.register(Allure2Command);
|
|
14
|
+
cli.register(AgentCapabilitiesCommand);
|
|
14
15
|
cli.register(AgentLatestCommand);
|
|
16
|
+
cli.register(AgentQueryCommand);
|
|
15
17
|
cli.register(AgentSelectCommand);
|
|
16
18
|
cli.register(AgentStateDirCommand);
|
|
17
19
|
cli.register(AgentCommand);
|
|
@@ -34,6 +36,17 @@ cli.register(ResultsPackCommand);
|
|
|
34
36
|
cli.register(ResultsUnpackCommand);
|
|
35
37
|
cli.register(Builtins.HelpCommand);
|
|
36
38
|
cli.register(Builtins.VersionCommand);
|
|
37
|
-
cli
|
|
39
|
+
void cli
|
|
40
|
+
.run(args)
|
|
41
|
+
.then((exitCode) => {
|
|
42
|
+
if (exitCode === 0 && isAgentTaskMapHelpRequest(args)) {
|
|
43
|
+
process.stdout.write(`\n${AGENT_TASK_MAP_HELP}`);
|
|
44
|
+
}
|
|
45
|
+
process.exitCode = exitCode;
|
|
46
|
+
})
|
|
47
|
+
.catch((error) => {
|
|
48
|
+
console.error(error);
|
|
49
|
+
process.exitCode = 1;
|
|
50
|
+
});
|
|
38
51
|
export { defineConfig } from "@allurereport/plugin-api";
|
|
39
52
|
export { defaultChartsConfig } from "@allurereport/charts-api";
|
package/dist/utils/index.d.ts
CHANGED
package/dist/utils/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "allure",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.11.0",
|
|
4
4
|
"description": "Allure Commandline Tool",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"allure",
|
|
@@ -32,26 +32,26 @@
|
|
|
32
32
|
"lint:fix": "oxlint --import-plugin --fix src test features stories"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@allurereport/charts-api": "3.
|
|
36
|
-
"@allurereport/ci": "3.
|
|
37
|
-
"@allurereport/core": "3.
|
|
38
|
-
"@allurereport/core-api": "3.
|
|
39
|
-
"@allurereport/directory-watcher": "3.
|
|
40
|
-
"@allurereport/plugin-agent": "3.
|
|
41
|
-
"@allurereport/plugin-allure2": "3.
|
|
42
|
-
"@allurereport/plugin-api": "3.
|
|
43
|
-
"@allurereport/plugin-awesome": "3.
|
|
44
|
-
"@allurereport/plugin-classic": "3.
|
|
45
|
-
"@allurereport/plugin-csv": "3.
|
|
46
|
-
"@allurereport/plugin-dashboard": "3.
|
|
47
|
-
"@allurereport/plugin-jira": "3.
|
|
48
|
-
"@allurereport/plugin-log": "3.
|
|
49
|
-
"@allurereport/plugin-progress": "3.
|
|
50
|
-
"@allurereport/plugin-server-reload": "3.
|
|
51
|
-
"@allurereport/plugin-slack": "3.
|
|
52
|
-
"@allurereport/reader-api": "3.
|
|
53
|
-
"@allurereport/service": "3.
|
|
54
|
-
"@allurereport/static-server": "3.
|
|
35
|
+
"@allurereport/charts-api": "3.11.0",
|
|
36
|
+
"@allurereport/ci": "3.11.0",
|
|
37
|
+
"@allurereport/core": "3.11.0",
|
|
38
|
+
"@allurereport/core-api": "3.11.0",
|
|
39
|
+
"@allurereport/directory-watcher": "3.11.0",
|
|
40
|
+
"@allurereport/plugin-agent": "3.11.0",
|
|
41
|
+
"@allurereport/plugin-allure2": "3.11.0",
|
|
42
|
+
"@allurereport/plugin-api": "3.11.0",
|
|
43
|
+
"@allurereport/plugin-awesome": "3.11.0",
|
|
44
|
+
"@allurereport/plugin-classic": "3.11.0",
|
|
45
|
+
"@allurereport/plugin-csv": "3.11.0",
|
|
46
|
+
"@allurereport/plugin-dashboard": "3.11.0",
|
|
47
|
+
"@allurereport/plugin-jira": "3.11.0",
|
|
48
|
+
"@allurereport/plugin-log": "3.11.0",
|
|
49
|
+
"@allurereport/plugin-progress": "3.11.0",
|
|
50
|
+
"@allurereport/plugin-server-reload": "3.11.0",
|
|
51
|
+
"@allurereport/plugin-slack": "3.11.0",
|
|
52
|
+
"@allurereport/reader-api": "3.11.0",
|
|
53
|
+
"@allurereport/service": "3.11.0",
|
|
54
|
+
"@allurereport/static-server": "3.11.0",
|
|
55
55
|
"adm-zip": "^0.5.16",
|
|
56
56
|
"clipanion": "^4.0.0-rc.4",
|
|
57
57
|
"glob": "^13.0.6",
|
|
@@ -63,14 +63,14 @@
|
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"@types/adm-zip": "^0",
|
|
65
65
|
"@types/lodash.omit": "^4.5.9",
|
|
66
|
-
"@types/node": "^20
|
|
66
|
+
"@types/node": "^20",
|
|
67
67
|
"@types/prompts": "^2",
|
|
68
|
-
"@vitest/runner": "^2
|
|
68
|
+
"@vitest/runner": "^2",
|
|
69
69
|
"@vitest/snapshot": "^2.1.9",
|
|
70
|
-
"allure-js-commons": "^3
|
|
71
|
-
"allure-vitest": "^3
|
|
72
|
-
"rimraf": "^6
|
|
73
|
-
"typescript": "^5
|
|
74
|
-
"vitest": "^
|
|
70
|
+
"allure-js-commons": "^3",
|
|
71
|
+
"allure-vitest": "^3",
|
|
72
|
+
"rimraf": "^6",
|
|
73
|
+
"typescript": "^5",
|
|
74
|
+
"vitest": "^4.1.0"
|
|
75
75
|
}
|
|
76
76
|
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import type { TestPlan } from "@allurereport/core-api";
|
|
2
|
-
import { type AgentTestManifestLine } from "@allurereport/plugin-agent";
|
|
3
|
-
export type AgentRerunPreset = "review" | "failed" | "unsuccessful" | "all";
|
|
4
|
-
export type AgentLabelFilter = {
|
|
5
|
-
name: string;
|
|
6
|
-
value: string;
|
|
7
|
-
};
|
|
8
|
-
export type AgentSelectionResult = {
|
|
9
|
-
outputDir: string;
|
|
10
|
-
preset: AgentRerunPreset;
|
|
11
|
-
selectedTests: AgentTestManifestLine[];
|
|
12
|
-
testPlan: TestPlan;
|
|
13
|
-
};
|
|
14
|
-
export type AgentTestPlanContext = {
|
|
15
|
-
outputDir: string;
|
|
16
|
-
preset: AgentRerunPreset;
|
|
17
|
-
selectedCount: number;
|
|
18
|
-
testPlanPath: string;
|
|
19
|
-
cleanup: () => Promise<void>;
|
|
20
|
-
};
|
|
21
|
-
export declare const normalizeAgentRerunPreset: (value?: string) => AgentRerunPreset;
|
|
22
|
-
export declare const parseAgentLabelFilters: (values?: string[]) => AgentLabelFilter[];
|
|
23
|
-
export declare const resolveAgentSelectionOutputDir: (params: {
|
|
24
|
-
cwd: string;
|
|
25
|
-
from?: string;
|
|
26
|
-
latest?: boolean;
|
|
27
|
-
}) => Promise<string>;
|
|
28
|
-
export declare const selectAgentTestPlan: (params: {
|
|
29
|
-
outputDir: string;
|
|
30
|
-
preset?: AgentRerunPreset;
|
|
31
|
-
environments?: string[];
|
|
32
|
-
labelFilters?: AgentLabelFilter[];
|
|
33
|
-
}) => Promise<AgentSelectionResult>;
|
|
34
|
-
export declare const createAgentTestPlanContext: (params: {
|
|
35
|
-
cwd: string;
|
|
36
|
-
from?: string;
|
|
37
|
-
latest?: boolean;
|
|
38
|
-
preset?: AgentRerunPreset;
|
|
39
|
-
environments?: string[];
|
|
40
|
-
labelFilters?: AgentLabelFilter[];
|
|
41
|
-
}) => Promise<AgentTestPlanContext | undefined>;
|
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
2
|
-
import { tmpdir } from "node:os";
|
|
3
|
-
import { join, resolve } from "node:path";
|
|
4
|
-
import { loadAgentOutput, planAgentEnrichmentReview, } from "@allurereport/plugin-agent";
|
|
5
|
-
import { UsageError } from "clipanion";
|
|
6
|
-
import { readLatestAgentState } from "./agent-state.js";
|
|
7
|
-
const AGENT_RERUN_PRESETS = ["review", "failed", "unsuccessful", "all"];
|
|
8
|
-
const ALLURE_ID_LABEL = "ALLURE_ID";
|
|
9
|
-
const isAgentRerunPreset = (value) => AGENT_RERUN_PRESETS.includes(value);
|
|
10
|
-
const readAllureId = (labels) => labels.find((label) => label.name === ALLURE_ID_LABEL)?.value;
|
|
11
|
-
const matchesLabelFilters = (labels, filters) => filters.every((filter) => labels.some((label) => label.name === filter.name && label.value === filter.value));
|
|
12
|
-
const buildTestPlan = (tests) => {
|
|
13
|
-
const seenSelectors = new Set();
|
|
14
|
-
const seenIds = new Set();
|
|
15
|
-
const selected = [];
|
|
16
|
-
for (const test of tests) {
|
|
17
|
-
const selector = test.full_name || undefined;
|
|
18
|
-
const id = readAllureId(test.labels);
|
|
19
|
-
if (selector && !seenSelectors.has(selector)) {
|
|
20
|
-
seenSelectors.add(selector);
|
|
21
|
-
if (id) {
|
|
22
|
-
seenIds.add(id);
|
|
23
|
-
}
|
|
24
|
-
selected.push({
|
|
25
|
-
selector,
|
|
26
|
-
...(id ? { id } : {}),
|
|
27
|
-
});
|
|
28
|
-
continue;
|
|
29
|
-
}
|
|
30
|
-
if (id && !seenIds.has(id)) {
|
|
31
|
-
seenIds.add(id);
|
|
32
|
-
selected.push({ id });
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
return {
|
|
36
|
-
version: "1.0",
|
|
37
|
-
tests: selected,
|
|
38
|
-
};
|
|
39
|
-
};
|
|
40
|
-
const selectTestsByPreset = (output, preset) => {
|
|
41
|
-
switch (preset) {
|
|
42
|
-
case "review": {
|
|
43
|
-
const review = planAgentEnrichmentReview(output);
|
|
44
|
-
const targeted = new Set(review.rerun.targetedTests);
|
|
45
|
-
return output.tests.filter((test) => targeted.has(test.full_name));
|
|
46
|
-
}
|
|
47
|
-
case "failed":
|
|
48
|
-
return output.tests.filter((test) => test.status === "failed" || test.status === "broken");
|
|
49
|
-
case "unsuccessful":
|
|
50
|
-
return output.tests.filter((test) => test.status !== "passed");
|
|
51
|
-
case "all":
|
|
52
|
-
return output.tests;
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
export const normalizeAgentRerunPreset = (value) => {
|
|
56
|
-
if (!value) {
|
|
57
|
-
return "review";
|
|
58
|
-
}
|
|
59
|
-
const normalized = value.trim().toLowerCase();
|
|
60
|
-
if (!isAgentRerunPreset(normalized)) {
|
|
61
|
-
throw new UsageError(`Invalid rerun preset ${JSON.stringify(value)}. Expected one of: ${AGENT_RERUN_PRESETS.join(", ")}`);
|
|
62
|
-
}
|
|
63
|
-
return normalized;
|
|
64
|
-
};
|
|
65
|
-
export const parseAgentLabelFilters = (values) => (values ?? []).map((value) => {
|
|
66
|
-
const separatorIndex = value.indexOf("=");
|
|
67
|
-
if (separatorIndex <= 0 || separatorIndex === value.length - 1) {
|
|
68
|
-
throw new UsageError(`Invalid label filter ${JSON.stringify(value)}. Expected the form name=value, for example feature=checkout`);
|
|
69
|
-
}
|
|
70
|
-
const name = value.slice(0, separatorIndex).trim();
|
|
71
|
-
const filterValue = value.slice(separatorIndex + 1).trim();
|
|
72
|
-
if (!name || !filterValue) {
|
|
73
|
-
throw new UsageError(`Invalid label filter ${JSON.stringify(value)}. Expected the form name=value, for example feature=checkout`);
|
|
74
|
-
}
|
|
75
|
-
return {
|
|
76
|
-
name,
|
|
77
|
-
value: filterValue,
|
|
78
|
-
};
|
|
79
|
-
});
|
|
80
|
-
export const resolveAgentSelectionOutputDir = async (params) => {
|
|
81
|
-
const { cwd, from, latest } = params;
|
|
82
|
-
if (from && latest) {
|
|
83
|
-
throw new UsageError("Use either --from or --latest, not both");
|
|
84
|
-
}
|
|
85
|
-
if (!from && !latest) {
|
|
86
|
-
throw new UsageError("Expected either --from <path> or --latest");
|
|
87
|
-
}
|
|
88
|
-
if (from) {
|
|
89
|
-
return resolve(cwd, from);
|
|
90
|
-
}
|
|
91
|
-
const latestState = await readLatestAgentState(cwd);
|
|
92
|
-
if (!latestState) {
|
|
93
|
-
throw new UsageError(`No latest agent output found for ${cwd}`);
|
|
94
|
-
}
|
|
95
|
-
return latestState.outputDir;
|
|
96
|
-
};
|
|
97
|
-
export const selectAgentTestPlan = async (params) => {
|
|
98
|
-
const preset = params.preset ?? "review";
|
|
99
|
-
const output = await loadAgentOutput(params.outputDir);
|
|
100
|
-
const selectedTests = selectTestsByPreset(output, preset)
|
|
101
|
-
.filter((test) => (params.environments?.length ? params.environments.includes(test.environment_id) : true))
|
|
102
|
-
.filter((test) => (params.labelFilters?.length ? matchesLabelFilters(test.labels, params.labelFilters) : true));
|
|
103
|
-
return {
|
|
104
|
-
outputDir: output.outputDir,
|
|
105
|
-
preset,
|
|
106
|
-
selectedTests,
|
|
107
|
-
testPlan: buildTestPlan(selectedTests),
|
|
108
|
-
};
|
|
109
|
-
};
|
|
110
|
-
export const createAgentTestPlanContext = async (params) => {
|
|
111
|
-
const { from, latest } = params;
|
|
112
|
-
if (!from && !latest) {
|
|
113
|
-
return undefined;
|
|
114
|
-
}
|
|
115
|
-
const outputDir = await resolveAgentSelectionOutputDir({
|
|
116
|
-
cwd: params.cwd,
|
|
117
|
-
from,
|
|
118
|
-
latest,
|
|
119
|
-
});
|
|
120
|
-
const selection = await selectAgentTestPlan({
|
|
121
|
-
outputDir,
|
|
122
|
-
preset: params.preset,
|
|
123
|
-
environments: params.environments,
|
|
124
|
-
labelFilters: params.labelFilters,
|
|
125
|
-
});
|
|
126
|
-
if (!selection.testPlan.tests.length) {
|
|
127
|
-
throw new UsageError(`No tests matched rerun selection in ${selection.outputDir}. Adjust the preset or filters before rerunning.`);
|
|
128
|
-
}
|
|
129
|
-
const tempDir = await mkdtemp(join(tmpdir(), "allure-agent-select-"));
|
|
130
|
-
const testPlanPath = join(tempDir, "testplan.json");
|
|
131
|
-
await writeFile(testPlanPath, `${JSON.stringify(selection.testPlan, null, 2)}\n`, "utf-8");
|
|
132
|
-
return {
|
|
133
|
-
outputDir: selection.outputDir,
|
|
134
|
-
preset: selection.preset,
|
|
135
|
-
selectedCount: selection.testPlan.tests.length,
|
|
136
|
-
testPlanPath,
|
|
137
|
-
cleanup: async () => {
|
|
138
|
-
await rm(tempDir, { recursive: true, force: true });
|
|
139
|
-
},
|
|
140
|
-
};
|
|
141
|
-
};
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export type AgentLatestState = {
|
|
2
|
-
schema: "allure-agent-latest/v1";
|
|
3
|
-
cwd: string;
|
|
4
|
-
outputDir: string;
|
|
5
|
-
expectationsPath?: string;
|
|
6
|
-
command: string;
|
|
7
|
-
startedAt: string;
|
|
8
|
-
finishedAt?: string;
|
|
9
|
-
status: "running" | "finished";
|
|
10
|
-
exitCode?: number | null;
|
|
11
|
-
};
|
|
12
|
-
export declare const ALLURE_AGENT_STATE_DIR_ENV = "ALLURE_AGENT_STATE_DIR";
|
|
13
|
-
export declare const resolveAgentStateDir: (cwd: string) => string;
|
|
14
|
-
export declare const writeLatestAgentState: (value: Omit<AgentLatestState, "schema">) => Promise<AgentLatestState>;
|
|
15
|
-
export declare const readLatestAgentState: (cwd: string) => Promise<AgentLatestState | undefined>;
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { createHash } from "node:crypto";
|
|
2
|
-
import { mkdir, readFile, rename, stat, writeFile } from "node:fs/promises";
|
|
3
|
-
import { tmpdir } from "node:os";
|
|
4
|
-
import { dirname, join, resolve } from "node:path";
|
|
5
|
-
const AGENT_STATE_SCHEMA = "allure-agent-latest/v1";
|
|
6
|
-
export const ALLURE_AGENT_STATE_DIR_ENV = "ALLURE_AGENT_STATE_DIR";
|
|
7
|
-
const isFileNotFoundError = (error) => typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
8
|
-
const projectHash = (cwd) => createHash("sha256").update(cwd).digest("hex").slice(0, 16);
|
|
9
|
-
export const resolveAgentStateDir = (cwd) => {
|
|
10
|
-
const configuredDir = process.env[ALLURE_AGENT_STATE_DIR_ENV]?.trim();
|
|
11
|
-
if (configuredDir) {
|
|
12
|
-
return resolve(configuredDir);
|
|
13
|
-
}
|
|
14
|
-
return join(tmpdir(), `allure-agent-state-${projectHash(resolve(cwd))}`);
|
|
15
|
-
};
|
|
16
|
-
const projectStatePath = (cwd) => join(resolveAgentStateDir(cwd), "latest.json");
|
|
17
|
-
const writeJsonAtomic = async (filePath, value) => {
|
|
18
|
-
await mkdir(dirname(filePath), { recursive: true });
|
|
19
|
-
const tempPath = `${filePath}.${process.pid}.tmp`;
|
|
20
|
-
await writeFile(tempPath, `${JSON.stringify(value, null, 2)}\n`, "utf-8");
|
|
21
|
-
await rename(tempPath, filePath);
|
|
22
|
-
};
|
|
23
|
-
const isAgentLatestState = (value) => {
|
|
24
|
-
if (typeof value !== "object" || value === null) {
|
|
25
|
-
return false;
|
|
26
|
-
}
|
|
27
|
-
const candidate = value;
|
|
28
|
-
return (candidate.schema === AGENT_STATE_SCHEMA &&
|
|
29
|
-
typeof candidate.cwd === "string" &&
|
|
30
|
-
typeof candidate.outputDir === "string" &&
|
|
31
|
-
typeof candidate.command === "string" &&
|
|
32
|
-
typeof candidate.startedAt === "string" &&
|
|
33
|
-
(candidate.expectationsPath === undefined || typeof candidate.expectationsPath === "string") &&
|
|
34
|
-
(candidate.finishedAt === undefined || typeof candidate.finishedAt === "string") &&
|
|
35
|
-
(candidate.status === "running" || candidate.status === "finished") &&
|
|
36
|
-
(candidate.exitCode === undefined || typeof candidate.exitCode === "number" || candidate.exitCode === null));
|
|
37
|
-
};
|
|
38
|
-
export const writeLatestAgentState = async (value) => {
|
|
39
|
-
const normalizedState = {
|
|
40
|
-
schema: AGENT_STATE_SCHEMA,
|
|
41
|
-
cwd: resolve(value.cwd),
|
|
42
|
-
outputDir: resolve(value.outputDir),
|
|
43
|
-
expectationsPath: value.expectationsPath ? resolve(value.expectationsPath) : undefined,
|
|
44
|
-
command: value.command,
|
|
45
|
-
startedAt: value.startedAt,
|
|
46
|
-
finishedAt: value.finishedAt,
|
|
47
|
-
status: value.status,
|
|
48
|
-
exitCode: value.exitCode,
|
|
49
|
-
};
|
|
50
|
-
await writeJsonAtomic(projectStatePath(normalizedState.cwd), normalizedState);
|
|
51
|
-
return normalizedState;
|
|
52
|
-
};
|
|
53
|
-
export const readLatestAgentState = async (cwd) => {
|
|
54
|
-
const normalizedCwd = resolve(cwd);
|
|
55
|
-
const statePath = projectStatePath(normalizedCwd);
|
|
56
|
-
let raw;
|
|
57
|
-
try {
|
|
58
|
-
raw = await readFile(statePath, "utf-8");
|
|
59
|
-
}
|
|
60
|
-
catch (error) {
|
|
61
|
-
if (isFileNotFoundError(error)) {
|
|
62
|
-
return undefined;
|
|
63
|
-
}
|
|
64
|
-
throw error;
|
|
65
|
-
}
|
|
66
|
-
const parsed = JSON.parse(raw);
|
|
67
|
-
if (!isAgentLatestState(parsed)) {
|
|
68
|
-
throw new Error(`Invalid latest agent state in ${statePath}`);
|
|
69
|
-
}
|
|
70
|
-
if (parsed.cwd !== normalizedCwd) {
|
|
71
|
-
return undefined;
|
|
72
|
-
}
|
|
73
|
-
try {
|
|
74
|
-
await stat(parsed.outputDir);
|
|
75
|
-
}
|
|
76
|
-
catch (error) {
|
|
77
|
-
if (isFileNotFoundError(error)) {
|
|
78
|
-
return undefined;
|
|
79
|
-
}
|
|
80
|
-
throw error;
|
|
81
|
-
}
|
|
82
|
-
return parsed;
|
|
83
|
-
};
|