retestkit 1.4.1 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +59 -40
- package/dist/config.js +8 -8
- package/dist/config.js.map +1 -1
- package/dist/logger.js +1 -1
- package/dist/logger.js.map +1 -1
- package/dist/prompts/index.d.ts +1 -1
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +21 -21
- package/dist/prompts/index.js.map +1 -1
- package/dist/prompts/templates/mcp/retest-crawl.md +7 -0
- package/{src/prompts/templates/mcp/webtest-discover-flows.md → dist/prompts/templates/mcp/retest-discover-flows.md} +1 -1
- package/{src/prompts/templates/mcp/webtest-discover.md → dist/prompts/templates/mcp/retest-discover.md} +2 -2
- package/dist/prompts/templates/mcp/retest-full-workflow.md +12 -0
- package/{src/prompts/templates/mcp/webtest-generate-tests.md → dist/prompts/templates/mcp/retest-generate-tests.md} +1 -1
- package/{src/prompts/templates/mcp/webtest-run-test.md → dist/prompts/templates/mcp/retest-run-test.md} +1 -1
- package/{src/prompts/templates/mcp/webtest-start.md → dist/prompts/templates/mcp/retest-start.md} +1 -1
- package/{src → dist}/prompts/templates/sampling/system-prefix.md +1 -1
- package/dist/resources/index.js +7 -7
- package/dist/resources/index.js.map +1 -1
- package/dist/schemas/config.js +2 -2
- package/dist/schemas/config.js.map +1 -1
- package/dist/security/index.js +1 -1
- package/dist/security/index.js.map +1 -1
- package/dist/server.js +3 -3
- package/dist/server.js.map +1 -1
- package/dist/test-utils/mock-context.js +22 -22
- package/dist/test-utils/mock-context.js.map +1 -1
- package/dist/tools/index.d.ts +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +5 -5
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/retest/crawl.d.ts.map +1 -0
- package/dist/tools/{webtest → retest}/crawl.js +7 -7
- package/dist/tools/retest/crawl.js.map +1 -0
- package/dist/tools/retest/discover-features.d.ts.map +1 -0
- package/dist/tools/{webtest → retest}/discover-features.js +6 -6
- package/dist/tools/retest/discover-features.js.map +1 -0
- package/dist/tools/retest/discover-flows.d.ts.map +1 -0
- package/dist/tools/{webtest → retest}/discover-flows.js +6 -6
- package/dist/tools/retest/discover-flows.js.map +1 -0
- package/dist/tools/retest/generate-tests.d.ts.map +1 -0
- package/dist/tools/{webtest → retest}/generate-tests.js +5 -5
- package/dist/tools/retest/generate-tests.js.map +1 -0
- package/dist/tools/retest/index.d.ts.map +1 -0
- package/dist/tools/retest/index.js.map +1 -0
- package/dist/tools/retest/run-test-case.d.ts.map +1 -0
- package/dist/tools/{webtest → retest}/run-test-case.js +3 -3
- package/dist/tools/retest/run-test-case.js.map +1 -0
- package/dist/tools/retest/schemas.d.ts.map +1 -0
- package/dist/tools/retest/schemas.js.map +1 -0
- package/dist/tools/retest/start-analysis.d.ts.map +1 -0
- package/dist/tools/{webtest → retest}/start-analysis.js +5 -5
- package/dist/tools/retest/start-analysis.js.map +1 -0
- package/dist/workspace/index.js +8 -8
- package/dist/workspace/index.js.map +1 -1
- package/dist/workspace/types.d.ts +2 -2
- package/dist/workspace/types.d.ts.map +1 -1
- package/package.json +6 -2
- package/.claude/commands/openspec/apply.md +0 -23
- package/.claude/commands/openspec/archive.md +0 -27
- package/.claude/commands/openspec/proposal.md +0 -28
- package/.gemini/commands/openspec/apply.toml +0 -21
- package/.gemini/commands/openspec/archive.toml +0 -25
- package/.gemini/commands/openspec/proposal.toml +0 -26
- package/.github/prompts/openspec-apply.prompt.md +0 -22
- package/.github/prompts/openspec-archive.prompt.md +0 -26
- package/.github/prompts/openspec-proposal.prompt.md +0 -27
- package/.github/workflows/release.yml +0 -33
- package/.kilocode/workflows/openspec-apply.md +0 -17
- package/.kilocode/workflows/openspec-archive.md +0 -21
- package/.kilocode/workflows/openspec-proposal.md +0 -22
- package/.mcp.json +0 -23
- package/.opencode/command/openspec-apply.md +0 -25
- package/.opencode/command/openspec-archive.md +0 -28
- package/.opencode/command/openspec-proposal.md +0 -30
- package/.roo/commands/openspec-apply.md +0 -20
- package/.roo/commands/openspec-archive.md +0 -24
- package/.roo/commands/openspec-proposal.md +0 -25
- package/.vscode/mcp.json +0 -23
- package/AGENTS.md +0 -18
- package/CLAUDE.md +0 -18
- package/dist/tools/webtest/crawl.d.ts.map +0 -1
- package/dist/tools/webtest/crawl.js.map +0 -1
- package/dist/tools/webtest/discover-features.d.ts.map +0 -1
- package/dist/tools/webtest/discover-features.js.map +0 -1
- package/dist/tools/webtest/discover-flows.d.ts.map +0 -1
- package/dist/tools/webtest/discover-flows.js.map +0 -1
- package/dist/tools/webtest/generate-tests.d.ts.map +0 -1
- package/dist/tools/webtest/generate-tests.js.map +0 -1
- package/dist/tools/webtest/index.d.ts.map +0 -1
- package/dist/tools/webtest/index.js.map +0 -1
- package/dist/tools/webtest/run-test-case.d.ts.map +0 -1
- package/dist/tools/webtest/run-test-case.js.map +0 -1
- package/dist/tools/webtest/schemas.d.ts.map +0 -1
- package/dist/tools/webtest/schemas.js.map +0 -1
- package/dist/tools/webtest/start-analysis.d.ts.map +0 -1
- package/dist/tools/webtest/start-analysis.js.map +0 -1
- package/openspec/AGENTS.md +0 -456
- package/openspec/changes/archive/2025-12-18-add-hybrid-artifact-paths/proposal.md +0 -33
- package/openspec/changes/archive/2025-12-18-add-hybrid-artifact-paths/specs/webtest-resources/spec.md +0 -27
- package/openspec/changes/archive/2025-12-18-add-hybrid-artifact-paths/specs/webtest-tools/spec.md +0 -304
- package/openspec/changes/archive/2025-12-18-add-hybrid-artifact-paths/tasks.md +0 -43
- package/openspec/changes/archive/2025-12-18-add-mcp-server-foundation/design.md +0 -209
- package/openspec/changes/archive/2025-12-18-add-mcp-server-foundation/proposal.md +0 -41
- package/openspec/changes/archive/2025-12-18-add-mcp-server-foundation/specs/mcp-server-core/spec.md +0 -183
- package/openspec/changes/archive/2025-12-18-add-mcp-server-foundation/tasks.md +0 -112
- package/openspec/changes/archive/2025-12-18-add-webtest-orchestrator/design.md +0 -333
- package/openspec/changes/archive/2025-12-18-add-webtest-orchestrator/proposal.md +0 -66
- package/openspec/changes/archive/2025-12-18-add-webtest-orchestrator/specs/mcp-server-core/spec.md +0 -129
- package/openspec/changes/archive/2025-12-18-add-webtest-orchestrator/specs/webtest-lifecycle/spec.md +0 -138
- package/openspec/changes/archive/2025-12-18-add-webtest-orchestrator/specs/webtest-logging/spec.md +0 -211
- package/openspec/changes/archive/2025-12-18-add-webtest-orchestrator/specs/webtest-prompts/spec.md +0 -157
- package/openspec/changes/archive/2025-12-18-add-webtest-orchestrator/specs/webtest-resources/spec.md +0 -213
- package/openspec/changes/archive/2025-12-18-add-webtest-orchestrator/specs/webtest-sampling/spec.md +0 -257
- package/openspec/changes/archive/2025-12-18-add-webtest-orchestrator/specs/webtest-tools/spec.md +0 -501
- package/openspec/changes/archive/2025-12-18-add-webtest-orchestrator/tasks.md +0 -264
- package/openspec/changes/archive/2025-12-18-allow-analysis-of-incomplete-crawls/proposal.md +0 -24
- package/openspec/changes/archive/2025-12-18-allow-analysis-of-incomplete-crawls/specs/webtest-tools/spec.md +0 -80
- package/openspec/changes/archive/2025-12-18-allow-analysis-of-incomplete-crawls/tasks.md +0 -8
- package/openspec/changes/archive/2025-12-18-fix-crawl-loop-stability/design.md +0 -90
- package/openspec/changes/archive/2025-12-18-fix-crawl-loop-stability/proposal.md +0 -28
- package/openspec/changes/archive/2025-12-18-fix-crawl-loop-stability/specs/webtest-sampling/spec.md +0 -90
- package/openspec/changes/archive/2025-12-18-fix-crawl-loop-stability/tasks.md +0 -33
- package/openspec/changes/archive/2025-12-18-use-markdown-artifacts/design.md +0 -558
- package/openspec/changes/archive/2025-12-18-use-markdown-artifacts/proposal.md +0 -119
- package/openspec/changes/archive/2025-12-18-use-markdown-artifacts/specs/webtest-resources/spec.md +0 -109
- package/openspec/changes/archive/2025-12-18-use-markdown-artifacts/specs/webtest-tools/spec.md +0 -121
- package/openspec/changes/archive/2025-12-18-use-markdown-artifacts/tasks.md +0 -133
- package/openspec/changes/extract-prompts-to-markdown/design.md +0 -86
- package/openspec/changes/extract-prompts-to-markdown/proposal.md +0 -50
- package/openspec/changes/extract-prompts-to-markdown/specs/webtest-prompts/spec.md +0 -74
- package/openspec/changes/extract-prompts-to-markdown/tasks.md +0 -40
- package/openspec/changes/refactor-webtest-naming/design.md +0 -95
- package/openspec/changes/refactor-webtest-naming/proposal.md +0 -66
- package/openspec/changes/refactor-webtest-naming/specs/webtest-prompts/spec.md +0 -79
- package/openspec/changes/refactor-webtest-naming/specs/webtest-resources/spec.md +0 -80
- package/openspec/changes/refactor-webtest-naming/specs/webtest-sampling/spec.md +0 -122
- package/openspec/changes/refactor-webtest-naming/specs/webtest-tools/spec.md +0 -113
- package/openspec/changes/refactor-webtest-naming/tasks.md +0 -119
- package/openspec/changes/rename-package-to-retest/proposal.md +0 -52
- package/openspec/changes/rename-package-to-retest/specs/mcp-server-core/spec.md +0 -53
- package/openspec/changes/rename-package-to-retest/specs/retest-lifecycle/spec.md +0 -68
- package/openspec/changes/rename-package-to-retest/specs/retest-logging/spec.md +0 -35
- package/openspec/changes/rename-package-to-retest/specs/retest-prompts/spec.md +0 -159
- package/openspec/changes/rename-package-to-retest/specs/retest-resources/spec.md +0 -251
- package/openspec/changes/rename-package-to-retest/specs/retest-sampling/spec.md +0 -99
- package/openspec/changes/rename-package-to-retest/specs/retest-tools/spec.md +0 -295
- package/openspec/changes/rename-package-to-retest/tasks.md +0 -71
- package/openspec/project.md +0 -31
- package/openspec/specs/mcp-server-core/spec.md +0 -178
- package/openspec/specs/webtest-lifecycle/spec.md +0 -136
- package/openspec/specs/webtest-logging/spec.md +0 -209
- package/openspec/specs/webtest-prompts/spec.md +0 -155
- package/openspec/specs/webtest-resources/spec.md +0 -248
- package/openspec/specs/webtest-sampling/spec.md +0 -344
- package/openspec/specs/webtest-tools/spec.md +0 -282
- package/release.config.js +0 -9
- package/src/config.test.ts +0 -96
- package/src/config.ts +0 -32
- package/src/elicitation/index.test.ts +0 -399
- package/src/elicitation/index.ts +0 -171
- package/src/elicitation/types.ts +0 -68
- package/src/index.ts +0 -83
- package/src/lifecycle/index.test.ts +0 -260
- package/src/lifecycle/index.ts +0 -101
- package/src/logger.redaction.test.ts +0 -322
- package/src/logger.test.ts +0 -123
- package/src/logger.ts +0 -229
- package/src/playwright-client/index.ts +0 -392
- package/src/playwright-client/types.ts +0 -99
- package/src/progress/index.test.ts +0 -327
- package/src/progress/index.ts +0 -170
- package/src/progress/types.ts +0 -25
- package/src/prompts/index.test.ts +0 -451
- package/src/prompts/index.ts +0 -246
- package/src/prompts/loader.test.ts +0 -100
- package/src/prompts/loader.ts +0 -59
- package/src/prompts/templates/mcp/webtest-crawl.md +0 -7
- package/src/prompts/templates/mcp/webtest-full-workflow.md +0 -12
- package/src/resources/index.ts +0 -250
- package/src/resources/subscriptions.ts +0 -37
- package/src/sampling/index.test.ts +0 -414
- package/src/sampling/index.ts +0 -286
- package/src/sampling/prompts.ts +0 -194
- package/src/sampling/types.ts +0 -60
- package/src/schemas/config.ts +0 -39
- package/src/security/index.test.ts +0 -441
- package/src/security/index.ts +0 -361
- package/src/security/security-scenarios.test.ts +0 -468
- package/src/server.ts +0 -211
- package/src/test-utils/index.ts +0 -6
- package/src/test-utils/mock-context.ts +0 -426
- package/src/test-utils/mock-playwright-client.ts +0 -422
- package/src/tools/index.ts +0 -11
- package/src/tools/webtest/crawl.test.ts +0 -834
- package/src/tools/webtest/crawl.ts +0 -901
- package/src/tools/webtest/discover-features.ts +0 -412
- package/src/tools/webtest/discover-flows.ts +0 -408
- package/src/tools/webtest/generate-tests.test.ts +0 -532
- package/src/tools/webtest/generate-tests.ts +0 -425
- package/src/tools/webtest/index.ts +0 -7
- package/src/tools/webtest/integration.test.ts +0 -536
- package/src/tools/webtest/run-test-case.test.ts +0 -659
- package/src/tools/webtest/run-test-case.ts +0 -508
- package/src/tools/webtest/schemas.ts +0 -201
- package/src/tools/webtest/start-analysis.test.ts +0 -151
- package/src/tools/webtest/start-analysis.ts +0 -158
- package/src/transports/http.ts +0 -19
- package/src/transports/index.ts +0 -30
- package/src/transports/stdio.ts +0 -7
- package/src/types/capabilities.test.ts +0 -193
- package/src/types/capabilities.ts +0 -50
- package/src/types/context.ts +0 -21
- package/src/types/tool.ts +0 -11
- package/src/workspace/index.ts +0 -945
- package/src/workspace/markdown.ts +0 -272
- package/src/workspace/types.ts +0 -186
- package/tests/integration/server.test.ts +0 -89
- package/tests/integration/tools.test.ts +0 -99
- package/tsconfig.json +0 -20
- package/vitest.config.ts +0 -9
- package/vitest.integration.config.ts +0 -10
- /package/{src → dist}/prompts/templates/sampling/crawl-action.md +0 -0
- /package/{src → dist}/prompts/templates/sampling/feature-discovery.md +0 -0
- /package/{src → dist}/prompts/templates/sampling/flow-discovery.md +0 -0
- /package/{src → dist}/prompts/templates/sampling/page-content-wrapper.md +0 -0
- /package/{src → dist}/prompts/templates/sampling/test-evaluation.md +0 -0
- /package/{src → dist}/prompts/templates/sampling/test-generation.md +0 -0
- /package/dist/tools/{webtest → retest}/crawl.d.ts +0 -0
- /package/dist/tools/{webtest → retest}/discover-features.d.ts +0 -0
- /package/dist/tools/{webtest → retest}/discover-flows.d.ts +0 -0
- /package/dist/tools/{webtest → retest}/generate-tests.d.ts +0 -0
- /package/dist/tools/{webtest → retest}/index.d.ts +0 -0
- /package/dist/tools/{webtest → retest}/index.js +0 -0
- /package/dist/tools/{webtest → retest}/run-test-case.d.ts +0 -0
- /package/dist/tools/{webtest → retest}/schemas.d.ts +0 -0
- /package/dist/tools/{webtest → retest}/schemas.js +0 -0
- /package/dist/tools/{webtest → retest}/start-analysis.d.ts +0 -0
|
@@ -1,408 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import type { McpTool, ToolResult } from "../../types/tool.js";
|
|
3
|
-
import type { ServerContext } from "../../types/context.js";
|
|
4
|
-
import type { WorkspaceManager } from "../../workspace/index.js";
|
|
5
|
-
import type { SamplingClient } from "../../sampling/index.js";
|
|
6
|
-
import type { ResourceManager } from "../../resources/index.js";
|
|
7
|
-
import { buildFlowDiscoveryPrompt } from "../../sampling/prompts.js";
|
|
8
|
-
import { FlowsDiscoverySchema, AnalysisIdSchema, CrawlIdSchema, FeatureSlugSchema, type FlowsDiscovery } from "./schemas.js";
|
|
9
|
-
|
|
10
|
-
export const discoverFlowsInputSchema = z.object({
|
|
11
|
-
analysisId: AnalysisIdSchema,
|
|
12
|
-
featureSlug: FeatureSlugSchema,
|
|
13
|
-
crawlId: CrawlIdSchema
|
|
14
|
-
.optional()
|
|
15
|
-
.describe("Specific crawl to use. If not provided, uses the most recent crawl with captured pages."),
|
|
16
|
-
manualDiscovery: z
|
|
17
|
-
.object({
|
|
18
|
-
featureSlug: z.string(),
|
|
19
|
-
flows: z.array(z.object({
|
|
20
|
-
id: z.string(),
|
|
21
|
-
name: z.string(),
|
|
22
|
-
description: z.string(),
|
|
23
|
-
entryPoint: z.string(),
|
|
24
|
-
steps: z.array(z.string()),
|
|
25
|
-
})),
|
|
26
|
-
suggestedAssertions: z.array(z.string()),
|
|
27
|
-
})
|
|
28
|
-
.optional()
|
|
29
|
-
.describe("Manual discovery result when sampling is unavailable. Provide this after executing the returned prompt."),
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
export type DiscoverFlowsInput = z.infer<typeof discoverFlowsInputSchema>;
|
|
33
|
-
|
|
34
|
-
export function createDiscoverFlowsTool(
|
|
35
|
-
getContext: () => ServerContext & {
|
|
36
|
-
workspaceManager: WorkspaceManager;
|
|
37
|
-
samplingClient: SamplingClient;
|
|
38
|
-
resourceManager: ResourceManager;
|
|
39
|
-
}
|
|
40
|
-
): McpTool<DiscoverFlowsInput> {
|
|
41
|
-
return {
|
|
42
|
-
name: "webtest_discover_flows",
|
|
43
|
-
description: `Discover user flows within a specific feature.
|
|
44
|
-
|
|
45
|
-
This tool uses AI to identify user flows within a feature:
|
|
46
|
-
- Identifies user journeys that accomplish specific goals
|
|
47
|
-
- Maps entry points and step sequences for each flow
|
|
48
|
-
- Suggests assertions that should hold for the flows
|
|
49
|
-
|
|
50
|
-
Outputs flows.md under features/<feature-slug>/. Run webtest_discover_features first to identify features.
|
|
51
|
-
|
|
52
|
-
Requires a crawl with captured pages and a valid feature slug from features.md.`,
|
|
53
|
-
|
|
54
|
-
inputSchema: discoverFlowsInputSchema,
|
|
55
|
-
|
|
56
|
-
async handler(input: DiscoverFlowsInput): Promise<ToolResult> {
|
|
57
|
-
const ctx = getContext();
|
|
58
|
-
const { logger, workspaceManager, samplingClient, resourceManager } = ctx;
|
|
59
|
-
|
|
60
|
-
const discoveryLogger = logger.withCorrelation({
|
|
61
|
-
analysisId: input.analysisId,
|
|
62
|
-
featureSlug: input.featureSlug,
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
discoveryLogger.info("Starting flow discovery", {
|
|
66
|
-
featureSlug: input.featureSlug,
|
|
67
|
-
crawlId: input.crawlId,
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
try {
|
|
71
|
-
// Validate workspace exists
|
|
72
|
-
if (!(await workspaceManager.workspaceExists(input.analysisId))) {
|
|
73
|
-
return {
|
|
74
|
-
content: [
|
|
75
|
-
{
|
|
76
|
-
type: "text",
|
|
77
|
-
text: `Error: Analysis workspace "${input.analysisId}" not found.`,
|
|
78
|
-
},
|
|
79
|
-
],
|
|
80
|
-
isError: true,
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const workspace = await workspaceManager.readWorkspaceIndex(input.analysisId);
|
|
85
|
-
|
|
86
|
-
// Check if features have been discovered
|
|
87
|
-
if (!workspace.features) {
|
|
88
|
-
return {
|
|
89
|
-
content: [
|
|
90
|
-
{
|
|
91
|
-
type: "text",
|
|
92
|
-
text: "Error: No features found. Run webtest_discover_features first.",
|
|
93
|
-
},
|
|
94
|
-
],
|
|
95
|
-
isError: true,
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Find the requested feature
|
|
100
|
-
const feature = workspace.features.features.find(
|
|
101
|
-
(f) => f.slug === input.featureSlug
|
|
102
|
-
);
|
|
103
|
-
|
|
104
|
-
if (!feature) {
|
|
105
|
-
const availableFeatures = workspace.features.features.map((f) => f.slug).join(", ");
|
|
106
|
-
return {
|
|
107
|
-
content: [
|
|
108
|
-
{
|
|
109
|
-
type: "text",
|
|
110
|
-
text: `Error: Feature "${input.featureSlug}" not found. Available features: ${availableFeatures}`,
|
|
111
|
-
},
|
|
112
|
-
],
|
|
113
|
-
isError: true,
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// Find the crawl to use
|
|
118
|
-
let targetCrawlId = input.crawlId;
|
|
119
|
-
let selectedCrawlRef: (typeof workspace.crawls)[0] | undefined;
|
|
120
|
-
|
|
121
|
-
if (!targetCrawlId) {
|
|
122
|
-
// Sort crawls by most recent first
|
|
123
|
-
const sortedCrawls = [...workspace.crawls].sort(
|
|
124
|
-
(a, b) =>
|
|
125
|
-
new Date(b.completedAt || b.startedAt).getTime() -
|
|
126
|
-
new Date(a.completedAt || a.startedAt).getTime()
|
|
127
|
-
);
|
|
128
|
-
|
|
129
|
-
const crawlsWithData = sortedCrawls.filter((c) => c.pagesVisited > 0);
|
|
130
|
-
|
|
131
|
-
if (crawlsWithData.length > 0) {
|
|
132
|
-
selectedCrawlRef = crawlsWithData[0];
|
|
133
|
-
targetCrawlId = selectedCrawlRef.crawlId;
|
|
134
|
-
} else if (sortedCrawls.length > 0) {
|
|
135
|
-
for (const crawlRef of sortedCrawls) {
|
|
136
|
-
try {
|
|
137
|
-
const crawlIndex = await workspaceManager.readCrawlIndex(
|
|
138
|
-
input.analysisId,
|
|
139
|
-
crawlRef.crawlId
|
|
140
|
-
);
|
|
141
|
-
if (crawlIndex.pages.length > 0) {
|
|
142
|
-
selectedCrawlRef = crawlRef;
|
|
143
|
-
targetCrawlId = crawlRef.crawlId;
|
|
144
|
-
break;
|
|
145
|
-
}
|
|
146
|
-
} catch {
|
|
147
|
-
// Crawl index not readable, skip
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
if (!targetCrawlId) {
|
|
153
|
-
return {
|
|
154
|
-
content: [
|
|
155
|
-
{
|
|
156
|
-
type: "text",
|
|
157
|
-
text: "Error: No crawls with captured data found.",
|
|
158
|
-
},
|
|
159
|
-
],
|
|
160
|
-
isError: true,
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
} else {
|
|
164
|
-
selectedCrawlRef = workspace.crawls.find((c) => c.crawlId === targetCrawlId);
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// Load crawl data
|
|
168
|
-
const crawlIndex = await workspaceManager.readCrawlIndex(
|
|
169
|
-
input.analysisId,
|
|
170
|
-
targetCrawlId
|
|
171
|
-
);
|
|
172
|
-
|
|
173
|
-
if (crawlIndex.pages.length === 0) {
|
|
174
|
-
return {
|
|
175
|
-
content: [
|
|
176
|
-
{
|
|
177
|
-
type: "text",
|
|
178
|
-
text: "Error: Crawl has no captured pages.",
|
|
179
|
-
},
|
|
180
|
-
],
|
|
181
|
-
isError: true,
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
discoveryLogger.info("Discovering flows for feature", {
|
|
186
|
-
featureName: feature.name,
|
|
187
|
-
crawlId: targetCrawlId,
|
|
188
|
-
pageCount: crawlIndex.pages.length,
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
// Filter page snapshots relevant to the feature (by entry points)
|
|
192
|
-
// For now, load all pages and let the AI filter
|
|
193
|
-
const pageSnapshots: Array<{ url: string; content: string }> = [];
|
|
194
|
-
|
|
195
|
-
for (const page of crawlIndex.pages.slice(0, 10)) {
|
|
196
|
-
try {
|
|
197
|
-
const snapshotContent = await resourceManager.readResource(
|
|
198
|
-
page.snapshotUri
|
|
199
|
-
);
|
|
200
|
-
if (snapshotContent.text) {
|
|
201
|
-
const snapshot = JSON.parse(snapshotContent.text);
|
|
202
|
-
pageSnapshots.push({
|
|
203
|
-
url: page.url,
|
|
204
|
-
content: snapshot.content || "",
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
} catch (error) {
|
|
208
|
-
discoveryLogger.warn("Failed to load page snapshot", {
|
|
209
|
-
pageId: page.pageId,
|
|
210
|
-
error: error instanceof Error ? error.message : "Unknown error",
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
// Determine discovery source: manual input, sampling, or fallback prompt
|
|
216
|
-
let discovery: FlowsDiscovery;
|
|
217
|
-
|
|
218
|
-
if (input.manualDiscovery) {
|
|
219
|
-
discoveryLogger.info("Using manual discovery input");
|
|
220
|
-
discovery = input.manualDiscovery as FlowsDiscovery;
|
|
221
|
-
} else if (!samplingClient.hasSampling()) {
|
|
222
|
-
const prompt = buildFlowDiscoveryPrompt({
|
|
223
|
-
featureSlug: feature.slug,
|
|
224
|
-
featureName: feature.name,
|
|
225
|
-
featureDescription: feature.description,
|
|
226
|
-
featureEntities: feature.entities,
|
|
227
|
-
featureEntryPoints: feature.entryPoints,
|
|
228
|
-
pageSnapshots,
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
return {
|
|
232
|
-
content: [
|
|
233
|
-
{
|
|
234
|
-
type: "text",
|
|
235
|
-
text: JSON.stringify(
|
|
236
|
-
{
|
|
237
|
-
needsManualInput: true,
|
|
238
|
-
analysisId: input.analysisId,
|
|
239
|
-
featureSlug: input.featureSlug,
|
|
240
|
-
crawlId: targetCrawlId,
|
|
241
|
-
prompt,
|
|
242
|
-
expectedResponseSchema: FlowsDiscoverySchema._def,
|
|
243
|
-
instructions:
|
|
244
|
-
"Execute this prompt with your LLM, then call webtest_discover_flows again with the result in the 'manualDiscovery' parameter",
|
|
245
|
-
},
|
|
246
|
-
null,
|
|
247
|
-
2
|
|
248
|
-
),
|
|
249
|
-
},
|
|
250
|
-
],
|
|
251
|
-
};
|
|
252
|
-
} else {
|
|
253
|
-
const samplingResult = await samplingClient.createMessage({
|
|
254
|
-
systemPrompt: `You are identifying user flows within the "${feature.name}" feature of a web application.
|
|
255
|
-
A "flow" is a user journey that accomplishes a specific goal within this feature.
|
|
256
|
-
Focus only on flows relevant to this specific feature.`,
|
|
257
|
-
userPrompt: buildFlowDiscoveryPrompt({
|
|
258
|
-
featureSlug: feature.slug,
|
|
259
|
-
featureName: feature.name,
|
|
260
|
-
featureDescription: feature.description,
|
|
261
|
-
featureEntities: feature.entities,
|
|
262
|
-
featureEntryPoints: feature.entryPoints,
|
|
263
|
-
pageSnapshots,
|
|
264
|
-
}),
|
|
265
|
-
schema: FlowsDiscoverySchema,
|
|
266
|
-
maxTokens: 4096,
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
if (!samplingResult.success || !samplingResult.data) {
|
|
270
|
-
discoveryLogger.error("Flow discovery sampling failed", {
|
|
271
|
-
error: samplingResult.error,
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
return {
|
|
275
|
-
content: [
|
|
276
|
-
{
|
|
277
|
-
type: "text",
|
|
278
|
-
text: `Error during flow discovery: ${samplingResult.error}`,
|
|
279
|
-
},
|
|
280
|
-
],
|
|
281
|
-
isError: true,
|
|
282
|
-
};
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
discovery = samplingResult.data;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
// Generate flows markdown
|
|
289
|
-
const markdownReport = generateFlowsMarkdown(discovery, feature);
|
|
290
|
-
|
|
291
|
-
// Build frontmatter
|
|
292
|
-
const frontmatter = {
|
|
293
|
-
featureSlug: discovery.featureSlug,
|
|
294
|
-
featureName: feature.name,
|
|
295
|
-
flows: discovery.flows,
|
|
296
|
-
suggestedAssertions: discovery.suggestedAssertions,
|
|
297
|
-
};
|
|
298
|
-
|
|
299
|
-
// Save flows
|
|
300
|
-
const { flowsFilePath, flowsUri, flowCount } =
|
|
301
|
-
await workspaceManager.saveFlows(input.analysisId, input.featureSlug, {
|
|
302
|
-
markdown: markdownReport,
|
|
303
|
-
frontmatter,
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
await resourceManager.notifyListChanged();
|
|
307
|
-
|
|
308
|
-
const result = {
|
|
309
|
-
analysisId: input.analysisId,
|
|
310
|
-
featureSlug: input.featureSlug,
|
|
311
|
-
crawlId: targetCrawlId,
|
|
312
|
-
flowsFilePath,
|
|
313
|
-
flowsUri,
|
|
314
|
-
summary: {
|
|
315
|
-
featureName: feature.name,
|
|
316
|
-
flowCount,
|
|
317
|
-
flows: discovery.flows.map((f) => ({
|
|
318
|
-
id: f.id,
|
|
319
|
-
name: f.name,
|
|
320
|
-
})),
|
|
321
|
-
assertionCount: discovery.suggestedAssertions.length,
|
|
322
|
-
},
|
|
323
|
-
nextSteps: [
|
|
324
|
-
`Use webtest_generate_tests with analysisId="${input.analysisId}" to generate test cases`,
|
|
325
|
-
`Review discovered flows at ${flowsUri}`,
|
|
326
|
-
],
|
|
327
|
-
};
|
|
328
|
-
|
|
329
|
-
discoveryLogger.info("Flow discovery completed", {
|
|
330
|
-
featureSlug: input.featureSlug,
|
|
331
|
-
flowCount,
|
|
332
|
-
flows: discovery.flows.map((f) => f.id),
|
|
333
|
-
});
|
|
334
|
-
|
|
335
|
-
return {
|
|
336
|
-
content: [
|
|
337
|
-
{
|
|
338
|
-
type: "text",
|
|
339
|
-
text: JSON.stringify(result, null, 2),
|
|
340
|
-
},
|
|
341
|
-
],
|
|
342
|
-
};
|
|
343
|
-
} catch (error) {
|
|
344
|
-
const message = error instanceof Error ? error.message : "Unknown error";
|
|
345
|
-
discoveryLogger.error("Flow discovery failed", { error: message });
|
|
346
|
-
|
|
347
|
-
return {
|
|
348
|
-
content: [
|
|
349
|
-
{
|
|
350
|
-
type: "text",
|
|
351
|
-
text: `Error during flow discovery: ${message}`,
|
|
352
|
-
},
|
|
353
|
-
],
|
|
354
|
-
isError: true,
|
|
355
|
-
};
|
|
356
|
-
}
|
|
357
|
-
},
|
|
358
|
-
};
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
function generateFlowsMarkdown(
|
|
362
|
-
discovery: FlowsDiscovery,
|
|
363
|
-
feature: { name: string; slug: string; description: string }
|
|
364
|
-
): string {
|
|
365
|
-
let md = `# User Flows: ${feature.name}
|
|
366
|
-
|
|
367
|
-
## Feature Overview
|
|
368
|
-
|
|
369
|
-
**Slug**: \`${feature.slug}\`
|
|
370
|
-
|
|
371
|
-
${feature.description}
|
|
372
|
-
|
|
373
|
-
## Flows
|
|
374
|
-
|
|
375
|
-
`;
|
|
376
|
-
|
|
377
|
-
for (const flow of discovery.flows) {
|
|
378
|
-
md += `### ${flow.name}
|
|
379
|
-
|
|
380
|
-
**ID**: \`${flow.id}\`
|
|
381
|
-
**Entry Point**: ${flow.entryPoint}
|
|
382
|
-
|
|
383
|
-
${flow.description}
|
|
384
|
-
|
|
385
|
-
**Steps**:
|
|
386
|
-
`;
|
|
387
|
-
for (let i = 0; i < flow.steps.length; i++) {
|
|
388
|
-
md += `${i + 1}. ${flow.steps[i]}\n`;
|
|
389
|
-
}
|
|
390
|
-
md += "\n---\n\n";
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
if (discovery.suggestedAssertions.length > 0) {
|
|
394
|
-
md += `## Suggested Assertions
|
|
395
|
-
|
|
396
|
-
`;
|
|
397
|
-
for (const assertion of discovery.suggestedAssertions) {
|
|
398
|
-
md += `- ${assertion}\n`;
|
|
399
|
-
}
|
|
400
|
-
md += "\n";
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
md += `---
|
|
404
|
-
*Generated by testing-mcp*
|
|
405
|
-
`;
|
|
406
|
-
|
|
407
|
-
return md;
|
|
408
|
-
}
|