common-qa-mcp 0.1.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.
Files changed (123) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +96 -0
  3. package/dist/adapters/factory.d.ts +15 -0
  4. package/dist/adapters/factory.d.ts.map +1 -0
  5. package/dist/adapters/factory.js +18 -0
  6. package/dist/adapters/factory.js.map +1 -0
  7. package/dist/adapters/remoteMcp/adapter.d.ts +92 -0
  8. package/dist/adapters/remoteMcp/adapter.d.ts.map +1 -0
  9. package/dist/adapters/remoteMcp/adapter.js +219 -0
  10. package/dist/adapters/remoteMcp/adapter.js.map +1 -0
  11. package/dist/adapters/types.d.ts +77 -0
  12. package/dist/adapters/types.d.ts.map +1 -0
  13. package/dist/adapters/types.js +2 -0
  14. package/dist/adapters/types.js.map +1 -0
  15. package/dist/adapters/walnut/actionTypes.d.ts +16 -0
  16. package/dist/adapters/walnut/actionTypes.d.ts.map +1 -0
  17. package/dist/adapters/walnut/actionTypes.js +141 -0
  18. package/dist/adapters/walnut/actionTypes.js.map +1 -0
  19. package/dist/adapters/walnut/mapper.d.ts +34 -0
  20. package/dist/adapters/walnut/mapper.d.ts.map +1 -0
  21. package/dist/adapters/walnut/mapper.js +228 -0
  22. package/dist/adapters/walnut/mapper.js.map +1 -0
  23. package/dist/cli.d.ts +3 -0
  24. package/dist/cli.d.ts.map +1 -0
  25. package/dist/cli.js +36 -0
  26. package/dist/cli.js.map +1 -0
  27. package/dist/config.d.ts +81 -0
  28. package/dist/config.d.ts.map +1 -0
  29. package/dist/config.js +211 -0
  30. package/dist/config.js.map +1 -0
  31. package/dist/connection.d.ts +101 -0
  32. package/dist/connection.d.ts.map +1 -0
  33. package/dist/connection.js +190 -0
  34. package/dist/connection.js.map +1 -0
  35. package/dist/domain/types.d.ts +279 -0
  36. package/dist/domain/types.d.ts.map +1 -0
  37. package/dist/domain/types.js +2 -0
  38. package/dist/domain/types.js.map +1 -0
  39. package/dist/domain/validate.d.ts +3 -0
  40. package/dist/domain/validate.d.ts.map +1 -0
  41. package/dist/domain/validate.js +29 -0
  42. package/dist/domain/validate.js.map +1 -0
  43. package/dist/drafts/store.d.ts +62 -0
  44. package/dist/drafts/store.d.ts.map +1 -0
  45. package/dist/drafts/store.js +119 -0
  46. package/dist/drafts/store.js.map +1 -0
  47. package/dist/httpMain.d.ts +3 -0
  48. package/dist/httpMain.d.ts.map +1 -0
  49. package/dist/httpMain.js +22 -0
  50. package/dist/httpMain.js.map +1 -0
  51. package/dist/index.d.ts +3 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +46 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/initAgents.d.ts +2 -0
  56. package/dist/initAgents.d.ts.map +1 -0
  57. package/dist/initAgents.js +178 -0
  58. package/dist/initAgents.js.map +1 -0
  59. package/dist/log.d.ts +14 -0
  60. package/dist/log.d.ts.map +1 -0
  61. package/dist/log.js +14 -0
  62. package/dist/log.js.map +1 -0
  63. package/dist/mcpResult.d.ts +20 -0
  64. package/dist/mcpResult.d.ts.map +1 -0
  65. package/dist/mcpResult.js +8 -0
  66. package/dist/mcpResult.js.map +1 -0
  67. package/dist/mount.d.ts +12 -0
  68. package/dist/mount.d.ts.map +1 -0
  69. package/dist/mount.js +126 -0
  70. package/dist/mount.js.map +1 -0
  71. package/dist/projectStore.d.ts +5 -0
  72. package/dist/projectStore.d.ts.map +1 -0
  73. package/dist/projectStore.js +60 -0
  74. package/dist/projectStore.js.map +1 -0
  75. package/dist/requestConnection.d.ts +20 -0
  76. package/dist/requestConnection.d.ts.map +1 -0
  77. package/dist/requestConnection.js +44 -0
  78. package/dist/requestConnection.js.map +1 -0
  79. package/dist/serve.d.ts +10 -0
  80. package/dist/serve.d.ts.map +1 -0
  81. package/dist/serve.js +37 -0
  82. package/dist/serve.js.map +1 -0
  83. package/dist/server.d.ts +29 -0
  84. package/dist/server.d.ts.map +1 -0
  85. package/dist/server.js +76 -0
  86. package/dist/server.js.map +1 -0
  87. package/dist/tools/connection.tools.d.ts +16 -0
  88. package/dist/tools/connection.tools.d.ts.map +1 -0
  89. package/dist/tools/connection.tools.js +106 -0
  90. package/dist/tools/connection.tools.js.map +1 -0
  91. package/dist/tools/discovery.tools.d.ts +16 -0
  92. package/dist/tools/discovery.tools.d.ts.map +1 -0
  93. package/dist/tools/discovery.tools.js +369 -0
  94. package/dist/tools/discovery.tools.js.map +1 -0
  95. package/dist/tools/markdown.d.ts +13 -0
  96. package/dist/tools/markdown.d.ts.map +1 -0
  97. package/dist/tools/markdown.js +65 -0
  98. package/dist/tools/markdown.js.map +1 -0
  99. package/dist/tools/recording.tools.d.ts +16 -0
  100. package/dist/tools/recording.tools.d.ts.map +1 -0
  101. package/dist/tools/recording.tools.js +378 -0
  102. package/dist/tools/recording.tools.js.map +1 -0
  103. package/dist/tools/run.tools.d.ts +13 -0
  104. package/dist/tools/run.tools.d.ts.map +1 -0
  105. package/dist/tools/run.tools.js +230 -0
  106. package/dist/tools/run.tools.js.map +1 -0
  107. package/dist/tools/schemas.d.ts +560 -0
  108. package/dist/tools/schemas.d.ts.map +1 -0
  109. package/dist/tools/schemas.js +112 -0
  110. package/dist/tools/schemas.js.map +1 -0
  111. package/dist/tools/testcase.tools.d.ts +50 -0
  112. package/dist/tools/testcase.tools.d.ts.map +1 -0
  113. package/dist/tools/testcase.tools.js +384 -0
  114. package/dist/tools/testcase.tools.js.map +1 -0
  115. package/dist/vendor/actionSignatures.d.ts +117 -0
  116. package/dist/vendor/actionSignatures.d.ts.map +1 -0
  117. package/dist/vendor/actionSignatures.js +420 -0
  118. package/dist/vendor/actionSignatures.js.map +1 -0
  119. package/dist/vendor/logger.d.ts +38 -0
  120. package/dist/vendor/logger.d.ts.map +1 -0
  121. package/dist/vendor/logger.js +174 -0
  122. package/dist/vendor/logger.js.map +1 -0
  123. package/package.json +57 -0
@@ -0,0 +1,112 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Zod mirrors of src/domain/types.ts, used ONLY as MCP tool inputSchemas.
4
+ * `validateTestCase` (src/domain/validate.ts) deliberately does not check
5
+ * `controlFlow.kind` -- these schemas are the only gate on that literal
6
+ * union, per the design brief ("zod is the only gate").
7
+ */
8
+ export const zLocator = z.object({ name: z.string(), value: z.string(), unique: z.boolean().optional() });
9
+ export const zCondition = z.object({
10
+ type: z.string(),
11
+ selector: z.string().optional(),
12
+ objectId: z.string().optional(),
13
+ text: z.string().optional(),
14
+ variableName: z.string().optional(),
15
+ variableValue: z.string().optional(),
16
+ });
17
+ export const zControlFlow = z.object({
18
+ kind: z.enum(['if', 'else', 'if_end', 'while', 'while_end']),
19
+ condition: zCondition.optional(),
20
+ blockId: z.string().optional(),
21
+ maxIterations: z.number().int().positive().optional(),
22
+ });
23
+ export const zStepType = z.enum(['web', 'api', 'control_flow', 'function', 'database', 'android', 'mainframe']);
24
+ export const zFlags = z.object({
25
+ skip: z.boolean().optional(),
26
+ screenshot: z.boolean().optional(),
27
+ continueOnFailure: z.boolean().optional(),
28
+ optional: z.boolean().optional(),
29
+ });
30
+ export const zObjectRef = z.object({
31
+ id: z.string().optional(),
32
+ name: z.string().optional(),
33
+ locators: z.array(zLocator).optional(),
34
+ });
35
+ export const zFunctionCall = z.object({
36
+ testCaseId: z.string(),
37
+ testCaseName: z.string().optional(),
38
+ inputParams: z.record(z.string(), z.unknown()).optional(),
39
+ continueOnFailure: z.boolean().optional(),
40
+ });
41
+ /** A step with no `n` -- callers never assign step numbers; DraftStore renumbers
42
+ * contiguously from 1 after every op. Used for add_step and tc_draft_create's
43
+ * initial `steps`. */
44
+ export const zNewStep = z.object({
45
+ description: z.string(),
46
+ actionType: z.string(),
47
+ stepType: zStepType,
48
+ objectRef: zObjectRef.optional(),
49
+ value: z.string().optional(),
50
+ expectedResult: z.string().optional(),
51
+ controlFlow: zControlFlow.optional(),
52
+ functionCall: zFunctionCall.optional(),
53
+ api: z.record(z.string(), z.unknown()).optional(),
54
+ db: z.record(z.string(), z.unknown()).optional(),
55
+ flags: zFlags.optional(),
56
+ });
57
+ /** A partial patch onto an existing step (update_step). */
58
+ export const zStepPatch = zNewStep.partial();
59
+ export const zPriority = z.enum(['critical', 'high', 'medium', 'low']);
60
+ export const zCategory = z.enum(['automated', 'manual', 'playwright']);
61
+ /** set_meta's patch -- TestCase-level fields only. `steps`/`id`/`version` are
62
+ * deliberately absent: steps are store-managed, id/version are backend
63
+ * concerns that don't exist for an unsaved draft. */
64
+ export const zTestCaseMetaPatch = z.object({
65
+ title: z.string().optional(),
66
+ description: z.string().optional(),
67
+ objective: z.string().optional(),
68
+ priority: zPriority.optional(),
69
+ status: z.string().optional(),
70
+ category: zCategory.optional(),
71
+ preconditions: z.string().optional(),
72
+ expectedOutcome: z.string().optional(),
73
+ folderOrModule: z.string().optional(),
74
+ storyRef: z.string().optional(),
75
+ tags: z.array(z.string()).optional(),
76
+ });
77
+ export const zDraftOp = z.discriminatedUnion('op', [
78
+ z.object({ op: z.literal('set_meta'), patch: zTestCaseMetaPatch }),
79
+ z.object({ op: z.literal('add_step'), at: z.number().int().positive().optional(), step: zNewStep }),
80
+ z.object({ op: z.literal('update_step'), n: z.number().int().positive(), patch: zStepPatch }),
81
+ z.object({ op: z.literal('remove_step'), n: z.number().int().positive() }),
82
+ z.object({ op: z.literal('move_step'), n: z.number().int().positive(), to: z.number().int().positive() }),
83
+ ]);
84
+ /** Granular modify ops for journal_modify (superset of the step ops + control-flow/nested authoring).
85
+ * `n`/`from`/`to` are the client-visible step numbers from journal_grep (1-based). */
86
+ export const zJournalOp = z.discriminatedUnion('op', [
87
+ z.object({ op: z.literal('set_meta'), patch: zTestCaseMetaPatch }),
88
+ z.object({ op: z.literal('add_step'), at: z.number().int().positive().optional(), step: zNewStep }),
89
+ z.object({ op: z.literal('update_step'), n: z.number().int().positive(), patch: zStepPatch }),
90
+ z.object({ op: z.literal('remove_step'), n: z.number().int().positive() }),
91
+ z.object({ op: z.literal('move_step'), n: z.number().int().positive(), to: z.number().int().positive() }),
92
+ z.object({
93
+ op: z.literal('wrap_in_loop'),
94
+ from: z.number().int().positive(),
95
+ to: z.number().int().positive(),
96
+ condition: zCondition.optional(),
97
+ maxIterations: z.number().int().positive().optional(),
98
+ }),
99
+ z.object({
100
+ op: z.literal('wrap_in_if'),
101
+ from: z.number().int().positive(),
102
+ to: z.number().int().positive(),
103
+ condition: zCondition.optional(),
104
+ }),
105
+ z.object({
106
+ op: z.literal('insert_nested'),
107
+ at: z.number().int().positive().optional(),
108
+ tcId: z.string(),
109
+ name: z.string().optional(),
110
+ }),
111
+ ]);
112
+ //# sourceMappingURL=schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../src/tools/schemas.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { Draft, DraftStore } from '../drafts/store.js';
3
+ import type { ProviderAdapter } from '../adapters/types.js';
4
+ export type TestcaseToolsDeps = {
5
+ drafts: DraftStore;
6
+ /** Default origin for tc_draft_open when the caller doesn't pass frontendOrigin. */
7
+ walnutUiOrigin?: string | undefined;
8
+ /** Loopback base for the local Walnut agent, used ONLY by the default
9
+ * (network) openInAgentWindowViaHttp fallback below -- i.e. only when
10
+ * `openEditorWindow` is absent. Irrelevant once this tool surface is mounted
11
+ * in-process inside the agent itself (src/mcp/qa/mount.ts always supplies
12
+ * `openEditorWindow`, so this field is never consulted there). */
13
+ agentUrl?: string | undefined;
14
+ /**
15
+ * Direct in-process override for opening the editor window. Set by
16
+ * src/mcp/qa/mount.ts to call routes/editorWindow.routes.ts's
17
+ * `openEditorWindow()` directly -- no HTTP hop, because this tool module now
18
+ * runs inside the same process as the Electron window it's asking to open.
19
+ * Left undefined for the standalone stdio dev harness (src/mcp/qa/index.ts),
20
+ * which is a genuinely separate process and falls back to the original
21
+ * loopback-fetch behavior below.
22
+ */
23
+ openEditorWindow?: ((url: string, title: string) => Promise<boolean>) | undefined;
24
+ /** The live provider adapter for the current connection, or null when offline. `tc_save` uses it to
25
+ * persist a draft to the product (create/update). Optional so offline-only callers still compile. */
26
+ getAdapter?: (() => ProviderAdapter | null) | undefined;
27
+ };
28
+ /** Every draft-returning tool shares this shape: markdown steps table +
29
+ * validation summary line in `content`, the neutral TestCase in
30
+ * `structuredContent` (spec: "one shared helper, not duplicated per tool").
31
+ * Exported so mcp/qa/tools/recording.tools.ts's `recording_save` (a
32
+ * draft-returning tool too -- it hands live-recorded steps into the SAME
33
+ * DraftStore) reuses this instead of a second hand-written literal. */
34
+ export declare function draftResult(draft: Draft): {
35
+ structuredContent?: Record<string, unknown>;
36
+ content: {
37
+ type: "text";
38
+ text: string;
39
+ }[];
40
+ };
41
+ /**
42
+ * Registers the offline draft-authoring tool surface: actions_catalog plus the
43
+ * 5 tc_draft_* tools. Every handler here works with `adapter === null` and
44
+ * touches no network -- draft state lives entirely in `deps.drafts`
45
+ * (in-memory, per DraftStore's own contract) and validation runs against the
46
+ * static WALNUT_ACTIONS catalog via offlineCatalogFor. There is deliberately
47
+ * no save/persist tool: nothing this module does writes to any backend.
48
+ */
49
+ export declare function registerTestcaseTools(server: McpServer, deps: TestcaseToolsDeps): void;
50
+ //# sourceMappingURL=testcase.tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testcase.tools.d.ts","sourceRoot":"","sources":["../../src/tools/testcase.tools.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE,OAAO,KAAK,EAAE,KAAK,EAAW,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAU5D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,UAAU,CAAC;IACnB,oFAAoF;IACpF,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC;;;;sEAIkE;IAClE,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B;;;;;;;;OAQG;IACH,gBAAgB,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;IAClF;0GACsG;IACtG,UAAU,CAAC,EAAE,CAAC,MAAM,eAAe,GAAG,IAAI,CAAC,GAAG,SAAS,CAAC;CACzD,CAAC;AA+CF;;;;;uEAKuE;AACvE,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK;;;;;;EAKvC;AA6BD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,iBAAiB,GAAG,IAAI,CA+UtF"}
@@ -0,0 +1,384 @@
1
+ import { z } from 'zod';
2
+ import { ok, err } from '../mcpResult.js';
3
+ import { validateTestCase } from '../domain/validate.js';
4
+ import { WALNUT_ACTIONS, actionDefsFrom, offlineCatalogFor } from '../adapters/walnut/actionTypes.js';
5
+ import { toWalnutStep } from '../adapters/walnut/mapper.js';
6
+ import { stepsMarkdown, validationSummaryLine } from './markdown.js';
7
+ import { zCategory, zDraftOp, zNewStep, zPriority } from './schemas.js';
8
+ function describeError(e) {
9
+ return e instanceof Error ? e.message : String(e);
10
+ }
11
+ /**
12
+ * Asks a SEPARATELY-RUNNING local Walnut agent to draw the editor in its own
13
+ * Electron window, over a loopback HTTP call to POST /editor/open.
14
+ *
15
+ * This is the ORIGINAL common-qa-mcp behavior, preserved verbatim as the
16
+ * fallback for `TestcaseToolsDeps.openEditorWindow` being absent -- i.e. for
17
+ * the standalone stdio dev harness (src/mcp/qa/index.ts), which really is a
18
+ * different OS process from the agent and has no direct function to call.
19
+ * When this tool surface is mounted IN-PROCESS inside the agent
20
+ * (src/mcp/qa/mount.ts), that mount always supplies `deps.openEditorWindow`,
21
+ * which calls routes/editorWindow.routes.ts's openEditorWindow() directly and
22
+ * this HTTP path is never used.
23
+ *
24
+ * Returns false for every "not available" case -- agent not running, running as a
25
+ * plain node dev server (it answers 501), or slow -- because this is an
26
+ * optimisation over returning a link, never a failure the user should see. The
27
+ * short timeout keeps a stale port from stalling the tool call.
28
+ */
29
+ async function openInAgentWindowViaHttp(agentUrl, url, title) {
30
+ const base = agentUrl ?? 'http://127.0.0.1:4050';
31
+ const ctl = new AbortController();
32
+ const timer = setTimeout(() => ctl.abort(), 1500);
33
+ try {
34
+ const res = await fetch(`${base.replace(/\/$/, '')}/editor/open`, {
35
+ method: 'POST',
36
+ headers: { 'Content-Type': 'application/json' },
37
+ body: JSON.stringify({ url, title }),
38
+ signal: ctl.signal,
39
+ });
40
+ return res.ok;
41
+ }
42
+ catch {
43
+ return false;
44
+ }
45
+ finally {
46
+ clearTimeout(timer);
47
+ }
48
+ }
49
+ /** Every draft-returning tool shares this shape: markdown steps table +
50
+ * validation summary line in `content`, the neutral TestCase in
51
+ * `structuredContent` (spec: "one shared helper, not duplicated per tool").
52
+ * Exported so mcp/qa/tools/recording.tools.ts's `recording_save` (a
53
+ * draft-returning tool too -- it hands live-recorded steps into the SAME
54
+ * DraftStore) reuses this instead of a second hand-written literal. */
55
+ export function draftResult(draft) {
56
+ const issues = validateTestCase(draft.tc, offlineCatalogFor);
57
+ const summary = validationSummaryLine(draft.tc, issues);
58
+ const text = `Draft ${draft.draftId} · ${summary}\n\n${stepsMarkdown(draft.tc)}`;
59
+ return ok(text, { draftId: draft.draftId, tc: draft.tc, issues });
60
+ }
61
+ function toBase64Url(payload) {
62
+ return Buffer.from(JSON.stringify(payload), 'utf8')
63
+ .toString('base64')
64
+ .replace(/\+/g, '-')
65
+ .replace(/\//g, '_')
66
+ .replace(/=+$/, '');
67
+ }
68
+ /**
69
+ * Builds the exact `/embed/test-case-draft#d=<payload>` URL walnut-frontend's
70
+ * real TestStepsEditor reads, per scripts/open-in-walnut-editor.ts. `mode` is
71
+ * hardcoded to 'view' -- there is no save path in this server yet, so offering
72
+ * an editable Save affordance the backend can't fulfil would be misleading.
73
+ */
74
+ function buildEditorUrl(origin, draft) {
75
+ const trimmed = origin.endsWith('/') ? origin.slice(0, -1) : origin;
76
+ const payload = {
77
+ title: draft.tc.title,
78
+ priority: draft.tc.priority,
79
+ category: draft.tc.category,
80
+ draftId: draft.draftId,
81
+ mode: 'view',
82
+ test_steps: draft.tc.steps.map(toWalnutStep),
83
+ };
84
+ return `${trimmed}/embed/test-case-draft#d=${toBase64Url(payload)}`;
85
+ }
86
+ /**
87
+ * Registers the offline draft-authoring tool surface: actions_catalog plus the
88
+ * 5 tc_draft_* tools. Every handler here works with `adapter === null` and
89
+ * touches no network -- draft state lives entirely in `deps.drafts`
90
+ * (in-memory, per DraftStore's own contract) and validation runs against the
91
+ * static WALNUT_ACTIONS catalog via offlineCatalogFor. There is deliberately
92
+ * no save/persist tool: nothing this module does writes to any backend.
93
+ */
94
+ export function registerTestcaseTools(server, deps) {
95
+ server.registerTool('actions_catalog', {
96
+ title: 'List the offline action-type catalog',
97
+ description: 'Static per-platform action-type vocabulary (web/android/api/database/mainframe), used for offline draft validation. No network call.',
98
+ inputSchema: { platform: z.enum(['web', 'android', 'api', 'database', 'mainframe']).optional() },
99
+ annotations: { readOnlyHint: true },
100
+ }, async ({ platform }) => {
101
+ try {
102
+ const all = actionDefsFrom(WALNUT_ACTIONS);
103
+ const defs = platform ? all.filter((a) => a.platform === platform) : all;
104
+ const text = `${defs.length} action type${defs.length === 1 ? '' : 's'}${platform ? ` for ${platform}` : ''}.\n\n` +
105
+ defs.map((a) => `- \`${a.actionType}\` (${a.platform})`).join('\n');
106
+ return ok(text, { actions: defs });
107
+ }
108
+ catch (e) {
109
+ return err(describeError(e));
110
+ }
111
+ });
112
+ server.registerTool('tc_draft_create', {
113
+ title: 'Create a test-case draft',
114
+ description: 'Create a new in-memory test-case draft from steps you author yourself. Nothing is persisted -- no disk, ' +
115
+ 'no backend, no network. Use tc_draft_open to hand it to the Walnut editor for viewing.\n\n' +
116
+ 'DO NOT USE THIS FOR A REAL WEB APPLICATION. Steps written here have no locators, so the test case cannot ' +
117
+ 'execute -- it only reads plausibly. Whenever there is an app you can reach (the user gives a URL, names an ' +
118
+ 'environment, or asks for a test of a real flow), call `recording_start` instead and drive the app with ' +
119
+ '`browser_*`: that captures real locators, real element names and real parameters, and is the DEFAULT way ' +
120
+ 'to create a web test case. You do not need the user to say "record" -- if a test case for a real app is ' +
121
+ 'wanted, recording is how it is made.\n\n' +
122
+ 'Legitimate uses: a manual test case (no automation), API/database steps that need no element binding, ' +
123
+ 'restructuring or drafting steps the user supplied verbatim, or sketching a plan when no app is reachable ' +
124
+ '-- and say plainly that the result is not executable until recorded.\n\n' +
125
+ 'INPUT VALUES MUST BE PARAMETERIZED. When a step has a value (text to type, a URL to open, an expected ' +
126
+ 'string), put a `${param}` token in its description AND set the step `value` -- e.g. description ' +
127
+ '"Enter ${username} in the Username field", value "standard_user". On save these bind into the test ' +
128
+ "case's default test-data row (the dataset Walnut auto-creates), so it can run with data. A value with " +
129
+ 'no `${param}` in the same description has nowhere to bind and is dropped -- this is how Walnut stores ' +
130
+ 'web values (never inline on the step).',
131
+ inputSchema: {
132
+ title: z.string().min(1),
133
+ priority: zPriority.optional(),
134
+ category: zCategory.optional(),
135
+ description: z.string().optional().describe('Optional test-case description / summary.'),
136
+ storyRef: z.string().optional().describe('Link this test case to a USER STORY — its id or business key (US_123, from story_list / ' +
137
+ 'story_get). Used when drafting MANUAL test cases for a story so they save linked to it.'),
138
+ steps: z.array(zNewStep).optional(),
139
+ },
140
+ }, async ({ title, priority, category, description, storyRef, steps }) => {
141
+ try {
142
+ const tc = {
143
+ title,
144
+ priority: priority ?? 'medium',
145
+ category: category ?? 'automated',
146
+ ...(description ? { description } : {}),
147
+ ...(storyRef ? { storyRef } : {}),
148
+ // zod (zNewStep) is the runtime gate on shape; DraftStore.create
149
+ // assigns real step numbers regardless of what's passed here.
150
+ steps: (steps ?? []),
151
+ };
152
+ const draftId = deps.drafts.create(tc);
153
+ return draftResult(deps.drafts.get(draftId));
154
+ }
155
+ catch (e) {
156
+ return err(describeError(e));
157
+ }
158
+ });
159
+ server.registerTool('tc_draft_update', {
160
+ title: 'Update a test-case draft',
161
+ description: 'Apply one or more ops (set_meta | add_step | update_step | remove_step | move_step) to a draft. Steps renumber contiguously from 1 after every op.',
162
+ inputSchema: { draftId: z.string(), ops: z.array(zDraftOp).min(1) },
163
+ }, async ({ draftId, ops }) => {
164
+ try {
165
+ const draft = deps.drafts.applyOps(draftId, ops);
166
+ return draftResult(draft);
167
+ }
168
+ catch (e) {
169
+ return err(describeError(e));
170
+ }
171
+ });
172
+ server.registerTool('tc_draft_get', {
173
+ title: 'Get a test-case draft',
174
+ description: 'Fetch a draft by id: readable steps table, validation summary, and the neutral TestCase.',
175
+ inputSchema: { draftId: z.string() },
176
+ annotations: { readOnlyHint: true },
177
+ }, async ({ draftId }) => {
178
+ try {
179
+ return draftResult(deps.drafts.get(draftId));
180
+ }
181
+ catch (e) {
182
+ return err(describeError(e));
183
+ }
184
+ });
185
+ server.registerTool('tc_draft_discard', {
186
+ title: 'Discard a test-case draft',
187
+ description: 'Delete an in-memory draft. Nothing was ever persisted, so there is nothing else to undo.',
188
+ inputSchema: { draftId: z.string() },
189
+ }, async ({ draftId }) => {
190
+ try {
191
+ deps.drafts.delete(draftId);
192
+ return ok(`Discarded draft ${draftId}. Nothing was ever persisted.`);
193
+ }
194
+ catch (e) {
195
+ return err(describeError(e));
196
+ }
197
+ });
198
+ server.registerTool('tc_draft_open', {
199
+ title: 'Open a draft in the Walnut editor',
200
+ description: "Show this draft in walnut-frontend's real editor. Prefers the Walnut agent's own native window when the agent is running; otherwise returns a link to open. The draft rides in the URL fragment -- nothing is uploaded, no backend call is made.",
201
+ inputSchema: {
202
+ draftId: z.string(),
203
+ frontendOrigin: z.string().optional(),
204
+ /** Set false to always return a link instead of using the agent window. */
205
+ useAgentWindow: z.boolean().optional(),
206
+ },
207
+ annotations: { readOnlyHint: true },
208
+ }, async ({ draftId, frontendOrigin, useAgentWindow }) => {
209
+ try {
210
+ const draft = deps.drafts.get(draftId);
211
+ const origin = frontendOrigin ?? deps.walnutUiOrigin ?? 'http://localhost:8080';
212
+ const url = buildEditorUrl(origin, draft);
213
+ const issues = validateTestCase(draft.tc, offlineCatalogFor);
214
+ const summary = `Draft ${draft.draftId} · ${validationSummaryLine(draft.tc, issues)}`;
215
+ // Preferred path: the agent is Electron, so it can draw the editor in its
216
+ // own window -- no browser tab, and no need for the AI client to render UI.
217
+ // Any failure here is not an error for this tool: fall through to the link.
218
+ const openWindow = deps.openEditorWindow ?? ((u, t) => openInAgentWindowViaHttp(deps.agentUrl, u, t));
219
+ const openedInAgent = useAgentWindow === false ? false : await openWindow(url, draft.tc.title);
220
+ if (openedInAgent) {
221
+ return ok(`Opened "${draft.tc.title}" in the Walnut agent's editor window.\n\n${summary}\n\n` +
222
+ `If you would rather use a browser: ${url}`, { url, draftId: draft.draftId, openedIn: 'agent-window', tc: draft.tc });
223
+ }
224
+ return ok(`${url}\n\n` +
225
+ `Open this link to view "${draft.tc.title}" in the Walnut editor -- nothing is uploaded, the draft rides in the URL fragment.\n\n` +
226
+ `${summary}`, { url, draftId: draft.draftId, openedIn: 'link', tc: draft.tc });
227
+ }
228
+ catch (e) {
229
+ return err(describeError(e));
230
+ }
231
+ });
232
+ server.registerTool('tc_save', {
233
+ title: 'Save a draft test case to the product',
234
+ description: 'Validate a draft, then PERSIST it to the connected product — creating a NEW test case, or ' +
235
+ 'UPDATING the one it was opened from (when the draft carries an id). Returns the product id + a ' +
236
+ 'deep link. Requires a live connection (qa_connect); the persist is forwarded to the product MCP.',
237
+ inputSchema: { draftId: z.string().describe('The draft id from tc_draft_create / tc_draft_open.') },
238
+ annotations: { readOnlyHint: false },
239
+ }, async ({ draftId }) => {
240
+ const adapter = deps.getAdapter?.();
241
+ if (!adapter) {
242
+ return err('Not connected to a product. Use qa_connect first — saving persists to the backend.');
243
+ }
244
+ let draft;
245
+ try {
246
+ draft = deps.drafts.get(draftId);
247
+ }
248
+ catch {
249
+ return err(`No draft "${draftId}". Author one with tc_draft_create, or open an existing test case with tc_draft_open.`);
250
+ }
251
+ const issues = validateTestCase(draft.tc, offlineCatalogFor);
252
+ if (issues.length) {
253
+ const detail = issues.map((i) => `- step ${i.step ?? '-'}${i.field ? ` (${i.field})` : ''}: ${i.msg}`).join('\n');
254
+ return err(`Cannot save "${draft.tc.title}" — ${issues.length} validation issue(s):\n${detail}`);
255
+ }
256
+ try {
257
+ const isUpdate = !!draft.tc.id;
258
+ const saved = isUpdate
259
+ ? await adapter.updateTestCase(draft.tc.id, draft.tc)
260
+ : await adapter.createTestCase(draft.tc);
261
+ // Bind the draft to the id it was just created as, so a subsequent tc_draft_update + tc_save
262
+ // UPDATES this same test case in place instead of creating a duplicate (the anisha TC_627→TC_628
263
+ // trap). No-op on an update (already bound).
264
+ if (!isUpdate && saved.id) {
265
+ try {
266
+ deps.drafts.markSaved(draft.draftId, saved.id);
267
+ }
268
+ catch { /* draft already gone — nothing to bind */ }
269
+ }
270
+ const link = saved.productUrl ? `\n${saved.productUrl}` : '';
271
+ return ok(`${isUpdate ? 'Updated' : 'Created'} test case ${saved.id}.${link}`, { saved, draftId: draft.draftId });
272
+ }
273
+ catch (e) {
274
+ return err(describeError(e));
275
+ }
276
+ });
277
+ server.registerTool('tc_automate', {
278
+ title: 'Convert a manual test case to automated (record in place)',
279
+ description: 'Promote an existing MANUAL test case to AUTOMATED, IN PLACE. Reads the test case, uses its steps ' +
280
+ 'as the guide to drive a REAL browser recording (the web sub-agent, with real locators), then ' +
281
+ 'REPLACES the same test case\'s steps with the recorded ones and flips its category to ' +
282
+ '"automated" — keeping its story link. The manual steps are superseded (this is the promote-in-' +
283
+ 'place the user chose). Pass `url` (the app entry point) unless the manual steps already contain ' +
284
+ 'one, and `extra` for credentials / data / what to assert; `profile` reuses a signed-in browser ' +
285
+ 'profile. Requires a live connection + the web recording agent.',
286
+ inputSchema: {
287
+ tcId: z.string().describe('The manual test case id (or business key TC_123) to automate.'),
288
+ url: z.string().optional().describe('Starting URL for the recording (the app under test).'),
289
+ profile: z.string().optional().describe('Reuse a signed-in browser profile (else a fresh one).'),
290
+ extra: z.string().optional().describe('Extra guidance for the recorder: credentials, data, assertions.'),
291
+ },
292
+ annotations: { readOnlyHint: false },
293
+ }, async ({ tcId, url, profile, extra }) => {
294
+ const adapter = deps.getAdapter?.();
295
+ if (!adapter)
296
+ return err('Not connected to a product. Use qa_connect first.');
297
+ if (!adapter.callRaw)
298
+ return err('This product agent does not expose recording — cannot automate here.');
299
+ let source;
300
+ try {
301
+ source = await adapter.getTestCase(tcId);
302
+ }
303
+ catch (e) {
304
+ return err(`Could not read test case "${tcId}": ${describeError(e)}`);
305
+ }
306
+ // Compose a recording task from the (manual) steps — the guide the web loop follows.
307
+ const stepLines = source.steps
308
+ .map((s, i) => `${i + 1}. ${s.description}${s.expectedResult ? ` (expect: ${s.expectedResult})` : ''}`)
309
+ .join('\n');
310
+ const task = 'Automate this test case by performing it in a real browser and asserting the expected results.\n\n' +
311
+ `Test case: ${source.title}\n` +
312
+ (source.preconditions ? `Preconditions: ${source.preconditions}\n` : '') +
313
+ (url ? `Start URL: ${url}\n` : '') +
314
+ (extra ? `${extra}\n` : '') +
315
+ `\nSteps:\n${stepLines}`;
316
+ if (!url && !/https?:\/\//.test(task)) {
317
+ return err(`To automate "${source.title}" I need the app URL — the manual steps don't contain one. ` +
318
+ 'Call again with `url` (and any credentials/data via `extra`).');
319
+ }
320
+ // Recording is NON-BLOCKING on the agent: web() starts it + returns a sessionId; the result comes
321
+ // via web_status. tc_automate does that start→poll internally, then promotes in place. The agent's
322
+ // one-recording-in-flight guard means even if this call is retried it can't spawn a second browser.
323
+ let sessionId;
324
+ try {
325
+ const startRes = (await adapter.callRaw('web', {
326
+ task,
327
+ ...(url ? { url } : {}),
328
+ ...(profile ? { profile } : {}),
329
+ }));
330
+ if (startRes.isError)
331
+ return startRes;
332
+ sessionId = startRes.structuredContent?.sessionId;
333
+ }
334
+ catch (e) {
335
+ return err(`Recording failed to start: ${describeError(e)}`);
336
+ }
337
+ if (!sessionId)
338
+ return err('Recording did not start (no sessionId returned).');
339
+ let recorded;
340
+ const deadline = Date.now() + 6 * 60000; // internal cap; recording continues server-side regardless
341
+ while (Date.now() < deadline) {
342
+ await new Promise((r) => setTimeout(r, 6000));
343
+ let st;
344
+ try {
345
+ st = (await adapter.callRaw('web_status', { sessionId }));
346
+ }
347
+ catch (e) {
348
+ return err(`Recording status check failed: ${describeError(e)}`);
349
+ }
350
+ if (st.isError)
351
+ return st; // recording error — forward verbatim
352
+ const sc = st.structuredContent;
353
+ if (sc?.status === 'done' && sc.tc) {
354
+ recorded = sc.tc;
355
+ break;
356
+ }
357
+ // else still 'recording' → keep polling
358
+ }
359
+ if (!recorded || !recorded.steps?.length) {
360
+ return err(`The recording for "${source.title}" is still running (session ${sessionId}) or produced no steps. ` +
361
+ `Poll web_status({ sessionId: "${sessionId}" }); once it's done, retry tc_automate.`);
362
+ }
363
+ // Promote IN PLACE: same id, recorded steps, category automated, story link + metadata kept.
364
+ const promoted = {
365
+ ...recorded,
366
+ id: tcId,
367
+ title: source.title,
368
+ priority: source.priority,
369
+ category: 'automated',
370
+ ...(source.description ? { description: source.description } : {}),
371
+ ...(source.storyRef ? { storyRef: source.storyRef } : {}),
372
+ };
373
+ try {
374
+ const saved = await adapter.updateTestCase(tcId, promoted);
375
+ const link = saved.productUrl ? `\n${saved.productUrl}` : '';
376
+ return ok(`Automated "${source.title}" (${tcId}) — recorded ${recorded.steps.length} step(s) and saved it ` +
377
+ `as AUTOMATED in place${source.storyRef ? ', keeping the story link' : ''}.${link}`, { saved, recordedStepCount: recorded.steps.length });
378
+ }
379
+ catch (e) {
380
+ return err(`Recorded the flow but saving the automated version failed: ${describeError(e)}`);
381
+ }
382
+ });
383
+ }
384
+ //# sourceMappingURL=testcase.tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testcase.tools.js","sourceRoot":"","sources":["../../src/tools/testcase.tools.ts"],"names":[],"mappings":"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"}