@f5xc-salesdemos/xcsh 19.49.0 → 19.51.1
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/package.json +8 -8
- package/src/browser/extension-page-actions.ts +58 -24
- package/src/browser/extension-provider.ts +17 -1
- package/src/internal-urls/build-info.generated.ts +8 -8
- package/src/internal-urls/console-catalog.generated.ts +6 -6
- package/src/internal-urls/console-field-metadata.generated.ts +33 -14
- package/src/tools/catalog-workflow-runner.ts +5 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@f5xc-salesdemos/xcsh",
|
|
4
|
-
"version": "19.
|
|
4
|
+
"version": "19.51.1",
|
|
5
5
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
6
6
|
"homepage": "https://github.com/f5xc-salesdemos/xcsh",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -54,13 +54,13 @@
|
|
|
54
54
|
"dependencies": {
|
|
55
55
|
"@agentclientprotocol/sdk": "0.16.1",
|
|
56
56
|
"@mozilla/readability": "^0.6",
|
|
57
|
-
"@f5xc-salesdemos/xcsh-stats": "19.
|
|
58
|
-
"@f5xc-salesdemos/pi-agent-core": "19.
|
|
59
|
-
"@f5xc-salesdemos/pi-ai": "19.
|
|
60
|
-
"@f5xc-salesdemos/pi-natives": "19.
|
|
61
|
-
"@f5xc-salesdemos/pi-resource-management": "19.
|
|
62
|
-
"@f5xc-salesdemos/pi-tui": "19.
|
|
63
|
-
"@f5xc-salesdemos/pi-utils": "19.
|
|
57
|
+
"@f5xc-salesdemos/xcsh-stats": "19.51.1",
|
|
58
|
+
"@f5xc-salesdemos/pi-agent-core": "19.51.1",
|
|
59
|
+
"@f5xc-salesdemos/pi-ai": "19.51.1",
|
|
60
|
+
"@f5xc-salesdemos/pi-natives": "19.51.1",
|
|
61
|
+
"@f5xc-salesdemos/pi-resource-management": "19.51.1",
|
|
62
|
+
"@f5xc-salesdemos/pi-tui": "19.51.1",
|
|
63
|
+
"@f5xc-salesdemos/pi-utils": "19.51.1",
|
|
64
64
|
"@sinclair/typebox": "^0.34",
|
|
65
65
|
"@xterm/headless": "^6.0",
|
|
66
66
|
"ajv": "^8.20",
|
|
@@ -32,11 +32,14 @@ const CONSOLE_DOMAIN_RE = /\.(volterra\.us|console\.ves\.volterra\.io)$/;
|
|
|
32
32
|
* coords. Runs entirely via `javascript_tool` — one small returnByValue, no
|
|
33
33
|
* full AX serialization.
|
|
34
34
|
*/
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Shared element-matching JS for the catalogue selector grammar (text('…'),
|
|
37
|
+
* role:text('…'), role[name='…'], bare role, and "row:has-text('…') >> sub").
|
|
38
|
+
* Both buildResolverScript (returns coords) and buildElementResolverScript
|
|
39
|
+
* (returns the live element for the deterministic click path) embed this verbatim
|
|
40
|
+
* so they resolve identically — only their tails differ.
|
|
41
|
+
*/
|
|
42
|
+
const RESOLVER_HELPERS = `
|
|
40
43
|
function roleToSelector(role){
|
|
41
44
|
switch(role){
|
|
42
45
|
case'button':return'button,input[type=button],input[type=submit],[role=button]';
|
|
@@ -112,6 +115,14 @@ function findInScope(s){
|
|
|
112
115
|
if(bareRoleM){const c=[...document.querySelectorAll(roleToSelector(s))].filter(isVisible);return c[0]||document.querySelector(roleToSelector(s));}
|
|
113
116
|
{const c=[...document.querySelectorAll(s)].filter(isVisible);return c[0]||document.querySelector(s);}
|
|
114
117
|
}
|
|
118
|
+
`;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* The element-finding block, shared. `__FAIL__('msg')` sentinels are substituted
|
|
122
|
+
* per builder: buildResolverScript → a {found:false,error} JSON return;
|
|
123
|
+
* buildElementResolverScript → `return null`. Sets `el` and scrolls it into view.
|
|
124
|
+
*/
|
|
125
|
+
const RESOLVER_FIND = `
|
|
115
126
|
let el=null;
|
|
116
127
|
if(sel.includes('>>')){
|
|
117
128
|
const parts=sel.split('>>').map(p=>p.trim());
|
|
@@ -119,23 +130,45 @@ if(sel.includes('>>')){
|
|
|
119
130
|
const want=rowM?rowM[1].replace(/\\u0421/g,'C'):'';
|
|
120
131
|
const rows=[...document.querySelectorAll('tr,[role=row],datatable-body-row')];
|
|
121
132
|
const row=rows.find(r=>(r.textContent||'').replace(/\\u0421/g,'C').includes(want));
|
|
122
|
-
if(!row)
|
|
123
|
-
// resolve the sub-selector within the row
|
|
133
|
+
if(!row)__FAIL__('no row matching '+parts[0]);
|
|
124
134
|
const subTextM=parts[1].match(/^([a-z]+):text\\('([^']*)'\\)$/);
|
|
125
135
|
if(subTextM){const want2=subTextM[2];const cs=[...row.querySelectorAll(roleToSelector(subTextM[1]))].filter(isVisible);const nm=t=>t.replace(/\\s+/g,' ').trim();el=cs.find(e=>nm(e.textContent||'')===want2)||cs.find(e=>nm(e.textContent||'').includes(want2));}
|
|
126
136
|
else{const cs=[...row.querySelectorAll(parts[1])].filter(isVisible);el=cs[0]||row.querySelector(parts[1]);}
|
|
127
|
-
if(!el)
|
|
137
|
+
if(!el)__FAIL__('sub-selector '+parts[1]+' not found in row');
|
|
128
138
|
}else{
|
|
129
139
|
el=findInScope(sel);
|
|
130
140
|
}
|
|
131
|
-
if(!el)
|
|
141
|
+
if(!el)__FAIL__('no match for '+sel);
|
|
132
142
|
el.scrollIntoView({block:'center',inline:'center'});
|
|
143
|
+
`;
|
|
144
|
+
|
|
145
|
+
/** Resolve a selector to viewport-center coords (returns JSON). */
|
|
146
|
+
export function buildResolverScript(selector: string): string {
|
|
147
|
+
const sel = JSON.stringify(selector);
|
|
148
|
+
const find = RESOLVER_FIND.replace(/__FAIL__\(([^;]*?)\);/g, "return JSON.stringify({found:false,error:($1)});");
|
|
149
|
+
return `(()=>{
|
|
150
|
+
const sel=${sel};
|
|
151
|
+
${RESOLVER_HELPERS}
|
|
152
|
+
${find}
|
|
133
153
|
const r=el.getBoundingClientRect();
|
|
134
154
|
const inGrid=!!el.closest&&!!el.closest('ngx-datatable,datatable-body-cell,datatable-body-row,[class*=datatable]');
|
|
135
155
|
return JSON.stringify({found:true,x:Math.round(r.x+r.width/2),y:Math.round(r.y+r.height/2),tag:el.tagName,txt:(el.textContent||'').trim().slice(0,30),inGrid:inGrid,val:(el.value!==undefined&&el.value!==null?String(el.value):'')});
|
|
136
156
|
})()`;
|
|
137
157
|
}
|
|
138
158
|
|
|
159
|
+
/** Resolve a selector to the live ELEMENT (returns the element or null) — the
|
|
160
|
+
* input to the deterministic click path (clickElement → getContentQuads + hit-test). */
|
|
161
|
+
export function buildElementResolverScript(selector: string): string {
|
|
162
|
+
const sel = JSON.stringify(selector);
|
|
163
|
+
const find = RESOLVER_FIND.replace(/__FAIL__\([^;]*?\);/g, "return null;");
|
|
164
|
+
return `(()=>{
|
|
165
|
+
const sel=${sel};
|
|
166
|
+
${RESOLVER_HELPERS}
|
|
167
|
+
${find}
|
|
168
|
+
return el;
|
|
169
|
+
})()`;
|
|
170
|
+
}
|
|
171
|
+
|
|
139
172
|
/**
|
|
140
173
|
* Run a `javascript_tool` snippet whose body returns a JSON string, and parse it.
|
|
141
174
|
* The bridge's `javascript_tool` wraps the evaluated value as `{ result: <value> }`,
|
|
@@ -217,14 +250,13 @@ export class ExtensionPageActions implements PageActions {
|
|
|
217
250
|
}
|
|
218
251
|
|
|
219
252
|
async click(selector: string, _context?: string): Promise<void> {
|
|
220
|
-
//
|
|
221
|
-
//
|
|
222
|
-
// the
|
|
223
|
-
//
|
|
224
|
-
//
|
|
225
|
-
|
|
226
|
-
await
|
|
227
|
-
await this.#ext.clickXy(x, y);
|
|
253
|
+
// Deterministic click: resolve the selector to the live element, then let the
|
|
254
|
+
// extension derive geometry from the renderer (DOM.getContentQuads) and
|
|
255
|
+
// hit-test the point (document.elementFromPoint) before dispatching. This
|
|
256
|
+
// replaces the JS getBoundingClientRect coords + 300ms settle heuristic —
|
|
257
|
+
// the hit-test is the gate now (it fails loudly on occlusion instead of
|
|
258
|
+
// landing mid-transition or on an overlay).
|
|
259
|
+
await this.#ext.clickElement(buildElementResolverScript(selector));
|
|
228
260
|
}
|
|
229
261
|
|
|
230
262
|
async fill(selector: string, value: string, _context?: string): Promise<void> {
|
|
@@ -247,7 +279,8 @@ export class ExtensionPageActions implements PageActions {
|
|
|
247
279
|
// For textareas we must NOT press Enter (it inserts a newline); Tab blurs.
|
|
248
280
|
const isTextarea = probe.tag === "TEXTAREA";
|
|
249
281
|
if (probe.inGrid || isTextarea) {
|
|
250
|
-
|
|
282
|
+
// Focus the cell/textarea via the deterministic path (hit-tested).
|
|
283
|
+
await this.#ext.clickElement(buildElementResolverScript(selector));
|
|
251
284
|
await new Promise(r => setTimeout(r, 200));
|
|
252
285
|
// Clear any pre-existing text (Backspace ×N) so re-fills are clean —
|
|
253
286
|
// fresh Add-Item rows are empty, so this is a no-op for create.
|
|
@@ -287,18 +320,19 @@ export class ExtensionPageActions implements PageActions {
|
|
|
287
320
|
// All options appear on click; the option is clicked directly below.
|
|
288
321
|
const resolved = await withTimeout(evalJson(this.#ext, buildResolverScript(selector)), 10_000, "resolve-listbox");
|
|
289
322
|
if (!resolved?.found) throw new Error(`selectOption: selector "${selector}" not found`);
|
|
290
|
-
await withTimeout(this.#ext.
|
|
323
|
+
await withTimeout(this.#ext.clickElement(buildElementResolverScript(selector)), 10_000, "click-listbox");
|
|
291
324
|
await new Promise(r => setTimeout(r, 1200));
|
|
292
325
|
// Click the option whose text matches value (exact-first via the resolver).
|
|
293
326
|
// Best-effort: if it never renders, fall through — the default value usually
|
|
294
327
|
// already applies, and a hard failure here would block create flows.
|
|
295
328
|
try {
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
329
|
+
// Deterministic option click — polls for the option to render (async panel)
|
|
330
|
+
// and hit-tests it. Best-effort; on no-match it throws and we Escape below.
|
|
331
|
+
await withTimeout(
|
|
332
|
+
this.#ext.clickElement(buildElementResolverScript(`option:text('${value}')`), 6_000),
|
|
333
|
+
12_000,
|
|
334
|
+
"click-option",
|
|
300
335
|
);
|
|
301
|
-
await withTimeout(this.#ext.clickXy(optCoords.x, optCoords.y), 10_000, "click-option");
|
|
302
336
|
await new Promise(r => setTimeout(r, 600));
|
|
303
337
|
} catch {
|
|
304
338
|
// Option not selectable (already default, or non-standard widget) — press
|
|
@@ -49,8 +49,15 @@ export interface ExtensionPage {
|
|
|
49
49
|
browserBatch(
|
|
50
50
|
actions: Array<{ tool: string; params: unknown }>,
|
|
51
51
|
): Promise<Array<{ tool: string; content: unknown; is_error: boolean }>>;
|
|
52
|
-
/** Trusted CDP click at viewport coordinates
|
|
52
|
+
/** Trusted CDP click at viewport coordinates. Last-resort primitive for points
|
|
53
|
+
* with no backing element (e.g. a computed portal point); prefer clickElement. */
|
|
53
54
|
clickXy(x: number, y: number): Promise<void>;
|
|
55
|
+
/** Deterministic click: `js` is an expression returning an Element (or null).
|
|
56
|
+
* The extension derives the clickable point from the renderer's layout
|
|
57
|
+
* (DOM.getContentQuads) and hit-tests it (document.elementFromPoint) before
|
|
58
|
+
* dispatching — no JS getBoundingClientRect, no silent mis-clicks. `waitMs`
|
|
59
|
+
* polls for the element (async portals). Throws loudly on occlusion. */
|
|
60
|
+
clickElement(js: string, waitMs?: number): Promise<{ x: number; y: number; hit: boolean }>;
|
|
54
61
|
/** CDP Input.insertText into the focused element (genuine trusted input events). */
|
|
55
62
|
typeText(text: string): Promise<void>;
|
|
56
63
|
/** Atomically type into a CDK-portal typeahead + click the matching option.
|
|
@@ -214,6 +221,15 @@ class BridgeExtensionPage implements ExtensionPage {
|
|
|
214
221
|
unwrap(await this.#server.request("click_xy", { x, y }), "click_xy");
|
|
215
222
|
}
|
|
216
223
|
|
|
224
|
+
async clickElement(js: string, waitMs?: number): Promise<{ x: number; y: number; hit: boolean }> {
|
|
225
|
+
const timeout = Math.max(30_000, (waitMs ?? 0) + 5_000);
|
|
226
|
+
return unwrap(await this.#server.request("click_element", { js, wait_ms: waitMs }, timeout), "click_element") as {
|
|
227
|
+
x: number;
|
|
228
|
+
y: number;
|
|
229
|
+
hit: boolean;
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
|
|
217
233
|
async typeText(text: string): Promise<void> {
|
|
218
234
|
unwrap(await this.#server.request("type_text", { text }), "type_text");
|
|
219
235
|
}
|
|
@@ -17,17 +17,17 @@ export interface BuildInfo {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export const BUILD_INFO: BuildInfo = {
|
|
20
|
-
"version": "19.
|
|
21
|
-
"commit": "
|
|
22
|
-
"shortCommit": "
|
|
20
|
+
"version": "19.51.1",
|
|
21
|
+
"commit": "671ad2b869a09652fe8e49dc726d754f80086d9b",
|
|
22
|
+
"shortCommit": "671ad2b",
|
|
23
23
|
"branch": "main",
|
|
24
|
-
"tag": "v19.
|
|
25
|
-
"commitDate": "2026-06-
|
|
26
|
-
"buildDate": "2026-06-
|
|
24
|
+
"tag": "v19.51.1",
|
|
25
|
+
"commitDate": "2026-06-26T06:28:05Z",
|
|
26
|
+
"buildDate": "2026-06-26T06:51:11.727Z",
|
|
27
27
|
"dirty": true,
|
|
28
28
|
"prNumber": "",
|
|
29
29
|
"repoUrl": "https://github.com/f5xc-salesdemos/xcsh",
|
|
30
30
|
"repoSlug": "f5xc-salesdemos/xcsh",
|
|
31
|
-
"commitUrl": "https://github.com/f5xc-salesdemos/xcsh/commit/
|
|
32
|
-
"releaseUrl": "https://github.com/f5xc-salesdemos/xcsh/releases/tag/v19.
|
|
31
|
+
"commitUrl": "https://github.com/f5xc-salesdemos/xcsh/commit/671ad2b869a09652fe8e49dc726d754f80086d9b",
|
|
32
|
+
"releaseUrl": "https://github.com/f5xc-salesdemos/xcsh/releases/tag/v19.51.1"
|
|
33
33
|
};
|
|
@@ -216,7 +216,7 @@ export const CONSOLE_CATALOG_DATA: ConsoleCatalogData = {
|
|
|
216
216
|
"cluster/update":
|
|
217
217
|
"schema: urn:f5xc:console:workflow:v1\nid: cluster-update\nlabel: Update Clusters\nresource: cluster\noperation: update\nparams:\n namespace:\n required: true\n example: demo\n name:\n required: true\n example: example-cluster\nsteps:\n - id: navigate-to-list\n action: navigate\n url: /web/workspaces/multi-cloud-app-connect/namespaces/{namespace}/manage/virtual_host/clusters\n wait_for: text('Clusters')\n description: Navigate to Clusters list page\n - id: scroll-actions-into-view\n action: scroll\n selector: row:has-text('{name}') >> [ves-e2e-test='row-action-dropdown']\n description: Scroll the Actions column into view\n - id: open-row-actions\n action: click\n selector: row:has-text('{name}') >> [ves-e2e-test='row-action-dropdown']\n wait_for: option:text('Manage Configuration')\n description: Open the row kebab menu\n - id: open-configuration\n action: click\n selector: option:text('Manage Configuration')\n wait_for: button:text('Edit Configuration')\n wait_timeout_ms: 15000\n description: Open the read-only Manage Configuration view\n - id: enter-edit-mode\n action: click\n selector: button:text('Edit Configuration')\n wait_for: \"[class*='save-bt'],[class*='submit-button']\"\n wait_timeout_ms: 20000\n description: Click 'Edit Configuration' to switch from read-only view into the editable form\n - id: modify-fields\n action: wait\n selector: \"[class*='save-bt'],[class*='submit-button']\"\n description: The agent fills the specific fields the user asked to modify (dynamic, not pre-generated)\n - id: save\n action: click\n selector: \"[class*='save-bt'],[class*='submit-button']\"\n context: footer\n wait_for: text('Clusters')\n wait_timeout_ms: 30000\n description: Save/submit changes (union selector matches save-bt OR submit-button)\nmetadata:\n confidence: inferred\n discovered_at: 2026-06-24\n console_version: \"2025.06\"\n notes: Auto-generated by scripts/generate-workflows.ts from api-specs-enriched field metadata.\n",
|
|
218
218
|
"code-base-integration/create":
|
|
219
|
-
"schema: urn:f5xc:console:workflow:v1\nid: code-base-integration-create\nlabel: Create Code Base Integration\nresource: code-base-integration\noperation: create\npreconditions:\n - user_logged_in\n - namespace_selected\n - \"role_minimum: admin\"\nparams:\n namespace:\n required: true\n description: Target namespace\n example: demo\n name:\n required: true\n description: Code Base Integration name (lowercase alphanumeric and hyphens)\n example: example-code-base-integration\n code_base:\n required:
|
|
219
|
+
"schema: urn:f5xc:console:workflow:v1\nid: code-base-integration-create\nlabel: Create Code Base Integration\nresource: code-base-integration\noperation: create\npreconditions:\n - user_logged_in\n - namespace_selected\n - \"role_minimum: admin\"\nparams:\n namespace:\n required: true\n description: Target namespace\n example: demo\n name:\n required: true\n description: Code Base Integration name (lowercase alphanumeric and hyphens)\n example: example-code-base-integration\n code_base:\n required: true\n description: A vsui \"Select item\" listbox (not a configurable). Selects an existing code-base integration. Verified from\n live form screenshot.\nsteps:\n - id: navigate-to-list\n action: navigate\n url: /web/workspaces/web-app-and-api-protection/namespaces/{namespace}/manage/api_security/code_base_integration\n wait_for: text('Code Base Integration')\n description: Navigate to Code Base Integration list page\n - id: click-add-tab\n action: click\n selector: text('Add Code Base Integration')\n wait_for: textbox[name='Name']\n description: Click Add Code Base Integration to open the create form\n - id: fill-name\n action: fill\n selector: textbox[name='Name']\n value: \"{name}\"\n description: Enter Name\n - id: select-code_base\n action: select\n selector: listbox[name='Code Base']\n context: Code Base section\n value: \"{code_base}\"\n description: Select Code Base (references an existing code_base — dependency)\n - id: save\n action: click\n selector: \"[class*='save-bt'],[class*='submit-button']\"\n context: footer\n wait_for: text('{name}')\n wait_timeout_ms: 30000\n description: Save/submit the form (union selector matches save-bt OR submit-button)\npostconditions:\n - resource_list_page_visible\n - \"resource_name_in_list: {name}\"\nmetadata:\n confidence: inferred\n discovered_at: 2026-06-24\n console_version: \"2025.06\"\n notes: Auto-generated by scripts/generate-workflows.ts from api-specs-enriched field metadata.\n",
|
|
220
220
|
"code-base-integration/delete":
|
|
221
221
|
"schema: urn:f5xc:console:workflow:v1\nid: code-base-integration-delete\nlabel: Delete Code Base Integration\nresource: code-base-integration\noperation: delete\npreconditions:\n - user_logged_in\n - namespace_selected\n - \"role_minimum: admin\"\n - \"resource_exists: {name}\"\nparams:\n namespace:\n required: true\n example: demo\n name:\n required: true\n example: example-code-base-integration\nsteps:\n - id: navigate-to-list\n action: navigate\n url: /web/workspaces/web-app-and-api-protection/namespaces/{namespace}/manage/api_security/code_base_integration\n wait_for: text('Code Base Integration')\n description: Navigate to Code Base Integration list page\n - id: scroll-actions-into-view\n action: scroll\n selector: row:has-text('{name}') >> [ves-e2e-test='row-action-dropdown']\n description: Scroll the Actions column into view for the target row\n - id: open-row-actions\n action: click\n selector: row:has-text('{name}') >> [ves-e2e-test='row-action-dropdown']\n wait_for: option:text('Delete')\n description: Open the row kebab menu\n - id: click-delete\n action: click\n selector: option:text('Delete')\n wait_for: button:text('Delete')\n description: Click Delete option\n - id: confirm-delete\n action: click\n selector: button:text('Delete')\n wait_for: text('Code Base Integration')\n wait_timeout_ms: 15000\n description: Confirm deletion\npostconditions:\n - resource_removed_from_list\n - list_page_visible\nmetadata:\n confidence: inferred\n discovered_at: 2026-06-24\n console_version: \"2025.06\"\n notes: Auto-generated by scripts/generate-workflows.ts from api-specs-enriched field metadata.\n",
|
|
222
222
|
"code-base-integration/read":
|
|
@@ -320,7 +320,7 @@ export const CONSOLE_CATALOG_DATA: ConsoleCatalogData = {
|
|
|
320
320
|
"dns-zone/update":
|
|
321
321
|
"schema: urn:f5xc:console:workflow:v1\nid: dns-zone-update\nlabel: Update DNS Zones\nresource: dns-zone\noperation: update\nparams:\n namespace:\n required: true\n example: demo\n name:\n required: true\n example: example-dns-zone\nsteps:\n - id: navigate-to-list\n action: navigate\n url: /web/workspaces/dns-management/manage/zone_management\n wait_for: text('DNS Zones')\n description: Navigate to DNS Zones list page\n - id: scroll-actions-into-view\n action: scroll\n selector: row:has-text('{name}') >> [ves-e2e-test='row-action-dropdown']\n description: Scroll the Actions column into view\n - id: open-row-actions\n action: click\n selector: row:has-text('{name}') >> [ves-e2e-test='row-action-dropdown']\n wait_for: option:text('Manage Configuration')\n description: Open the row kebab menu\n - id: open-configuration\n action: click\n selector: option:text('Manage Configuration')\n wait_for: button:text('Edit Configuration')\n wait_timeout_ms: 15000\n description: Open the read-only Manage Configuration view\n - id: enter-edit-mode\n action: click\n selector: button:text('Edit Configuration')\n wait_for: \"[class*='save-bt'],[class*='submit-button']\"\n wait_timeout_ms: 20000\n description: Click 'Edit Configuration' to switch from read-only view into the editable form\n - id: modify-fields\n action: wait\n selector: \"[class*='save-bt'],[class*='submit-button']\"\n description: The agent fills the specific fields the user asked to modify (dynamic, not pre-generated)\n - id: save\n action: click\n selector: \"[class*='save-bt'],[class*='submit-button']\"\n context: footer\n wait_for: text('DNS Zones')\n wait_timeout_ms: 30000\n description: Save/submit changes (union selector matches save-bt OR submit-button)\nmetadata:\n confidence: inferred\n discovered_at: 2026-06-24\n console_version: \"2025.06\"\n notes: Auto-generated by scripts/generate-workflows.ts from api-specs-enriched field metadata.\n",
|
|
322
322
|
"endpoint/create":
|
|
323
|
-
|
|
323
|
+
'schema: urn:f5xc:console:workflow:v1\nid: endpoint-create\nlabel: Create Endpoints\nresource: endpoint\noperation: create\npreconditions:\n - user_logged_in\n - namespace_selected\n - "role_minimum: admin"\nparams:\n namespace:\n required: true\n description: Target namespace\n example: demo\n name:\n required: true\n description: Endpoints name (lowercase alphanumeric and hyphens)\n example: example-endpoint\n protocol:\n required: false\n description: "Server-required: Must be TCP or UDP"\n default: TCP\n virtual_site_or_site_or_network:\n required: false\n description: Virtual-Site or Site or Network\n default: Virtual Site\n reference:\n required: true\n description: vsui autocomplete dropdown (VSUI-AUTOCOMPLETE-DROPDOWN) selecting a virtual-site, site, or network.\n Dependency resource.\nsteps:\n - id: navigate-to-list\n action: navigate\n url: /web/workspaces/multi-cloud-app-connect/namespaces/{namespace}/manage/virtual_host/endpoints\n wait_for: text(\'Endpoints\')\n description: Navigate to Endpoints list page\n - id: click-add-tab\n action: click\n selector: text(\'Add Endpoint\')\n wait_for: textbox[name=\'Name\']\n description: Click Add Endpoint to open the create form\n - id: fill-name\n action: fill\n selector: textbox[name=\'Name\']\n value: "{name}"\n description: Enter Name\n - id: select-protocol\n action: select\n selector: listbox\n context: Protocol section\n value: "{protocol}"\n description: Select Protocol\n condition: params.protocol is set\n - id: select-virtual_site_or_site_or_network\n action: select\n selector: listbox\n context: Virtual-Site or Site or Network section\n value: "{virtual_site_or_site_or_network}"\n description: Select Virtual-Site or Site or Network\n condition: params.virtual_site_or_site_or_network is set\n - id: select-reference\n action: select\n selector: listbox[name=\'Reference\']\n context: Reference section\n value: "{reference}"\n description: Select Reference (references an existing virtual_site — dependency)\n - id: save\n action: click\n selector: "[class*=\'save-bt\'],[class*=\'submit-button\']"\n context: footer\n wait_for: text(\'{name}\')\n wait_timeout_ms: 30000\n description: Save/submit the form (union selector matches save-bt OR submit-button)\npostconditions:\n - resource_list_page_visible\n - "resource_name_in_list: {name}"\nmetadata:\n confidence: inferred\n discovered_at: 2026-06-24\n console_version: "2025.06"\n notes: Auto-generated by scripts/generate-workflows.ts from api-specs-enriched field metadata.\n',
|
|
324
324
|
"endpoint/delete":
|
|
325
325
|
"schema: urn:f5xc:console:workflow:v1\nid: endpoint-delete\nlabel: Delete Endpoints\nresource: endpoint\noperation: delete\npreconditions:\n - user_logged_in\n - namespace_selected\n - \"role_minimum: admin\"\n - \"resource_exists: {name}\"\nparams:\n namespace:\n required: true\n example: demo\n name:\n required: true\n example: example-endpoint\nsteps:\n - id: navigate-to-list\n action: navigate\n url: /web/workspaces/multi-cloud-app-connect/namespaces/{namespace}/manage/virtual_host/endpoints\n wait_for: text('Endpoints')\n description: Navigate to Endpoints list page\n - id: scroll-actions-into-view\n action: scroll\n selector: row:has-text('{name}') >> [ves-e2e-test='row-action-dropdown']\n description: Scroll the Actions column into view for the target row\n - id: open-row-actions\n action: click\n selector: row:has-text('{name}') >> [ves-e2e-test='row-action-dropdown']\n wait_for: option:text('Delete')\n description: Open the row kebab menu\n - id: click-delete\n action: click\n selector: option:text('Delete')\n wait_for: button:text('Delete')\n description: Click Delete option\n - id: confirm-delete\n action: click\n selector: button:text('Delete')\n wait_for: text('Endpoints')\n wait_timeout_ms: 15000\n description: Confirm deletion\npostconditions:\n - resource_removed_from_list\n - list_page_visible\nmetadata:\n confidence: inferred\n discovered_at: 2026-06-24\n console_version: \"2025.06\"\n notes: Auto-generated by scripts/generate-workflows.ts from api-specs-enriched field metadata.\n",
|
|
326
326
|
"endpoint/read":
|
|
@@ -462,7 +462,7 @@ export const CONSOLE_CATALOG_DATA: ConsoleCatalogData = {
|
|
|
462
462
|
"mcn-secret-policy-rule/update":
|
|
463
463
|
"schema: urn:f5xc:console:workflow:v1\nid: mcn-secret-policy-rule-update\nlabel: Update Secret Policy Rules\nresource: mcn-secret-policy-rule\noperation: update\nparams:\n namespace:\n required: true\n example: demo\n name:\n required: true\n example: example-mcn-secret-policy-rule\nsteps:\n - id: navigate-to-list\n action: navigate\n url: /web/workspaces/multi-cloud-network-connect/manage/secrets/secret_policy_rules\n wait_for: text('Secret Policy Rules')\n description: Navigate to Secret Policy Rules list page\n - id: scroll-actions-into-view\n action: scroll\n selector: row:has-text('{name}') >> [ves-e2e-test='row-action-dropdown']\n description: Scroll the Actions column into view\n - id: open-row-actions\n action: click\n selector: row:has-text('{name}') >> [ves-e2e-test='row-action-dropdown']\n wait_for: option:text('Manage Configuration')\n description: Open the row kebab menu\n - id: open-configuration\n action: click\n selector: option:text('Manage Configuration')\n wait_for: button:text('Edit Configuration')\n wait_timeout_ms: 15000\n description: Open the read-only Manage Configuration view\n - id: enter-edit-mode\n action: click\n selector: button:text('Edit Configuration')\n wait_for: \"[class*='save-bt'],[class*='submit-button']\"\n wait_timeout_ms: 20000\n description: Click 'Edit Configuration' to switch from read-only view into the editable form\n - id: modify-fields\n action: wait\n selector: \"[class*='save-bt'],[class*='submit-button']\"\n description: The agent fills the specific fields the user asked to modify (dynamic, not pre-generated)\n - id: save\n action: click\n selector: \"[class*='save-bt'],[class*='submit-button']\"\n context: footer\n wait_for: text('Secret Policy Rules')\n wait_timeout_ms: 30000\n description: Save/submit changes (union selector matches save-bt OR submit-button)\nmetadata:\n confidence: inferred\n discovered_at: 2026-06-24\n console_version: \"2025.06\"\n notes: Auto-generated by scripts/generate-workflows.ts from api-specs-enriched field metadata.\n",
|
|
464
464
|
"namespace/create":
|
|
465
|
-
"schema: urn:f5xc:console:workflow:v1\nid: namespace-create\nlabel: Create My Namespaces\nresource: namespace\noperation: create\npreconditions:\n - user_logged_in\n - namespace_selected\n - \"role_minimum: admin\"\nparams:\n namespace:\n required: true\n description: Target namespace\n example: demo\n name:\n required: true\n description: My Namespaces name (lowercase alphanumeric and hyphens)\n example: example-namespace\nsteps:\n - id: navigate-to-list\n action: navigate\n url: /web/workspaces/administration/personal-management/namespaces\n wait_for: text('My Namespaces')\n description: Navigate to My Namespaces list page\n - id: click-add-tab\n action: click\n selector: text('Add Namespace')\n wait_for: textbox[name='Name']\n description: Click Add Namespace to open the create form\n - id: fill-name\n action: fill\n selector: textbox[name='Name']\n value: \"{name}\"\n description: Enter Name\n - id: save\n action: click\n selector: \"[class*='save-bt'],[class*='submit-button']\"\n context: footer\n wait_for: text('{name}')\n wait_timeout_ms: 30000\n description: Save/submit the form (union selector matches save-bt OR submit-button)\npostconditions:\n - resource_list_page_visible\n - \"resource_name_in_list: {name}\"\nmetadata:\n confidence: inferred\n discovered_at: 2026-06-24\n console_version: \"2025.06\"\n notes: Auto-generated by scripts/generate-workflows.ts from api-specs-enriched field metadata.\n",
|
|
465
|
+
"schema: urn:f5xc:console:workflow:v1\nid: namespace-create\nlabel: Create My Namespaces\nresource: namespace\noperation: create\npreconditions:\n - user_logged_in\n - namespace_selected\n - \"role_minimum: admin\"\nparams:\n namespace:\n required: true\n description: Target namespace\n example: demo\n name:\n required: true\n description: My Namespaces name (lowercase alphanumeric and hyphens)\n example: example-namespace\nsteps:\n - id: navigate-to-list\n action: navigate\n url: /web/workspaces/administration/personal-management/namespaces\n wait_for: text('My Namespaces')\n description: Navigate to My Namespaces list page\n - id: click-add-tab\n action: click\n selector: text('Add Namespace')\n wait_for: textbox[name='Namespace Name']\n description: Click Add Namespace to open the create form\n - id: fill-name\n action: fill\n selector: textbox[name='Namespace Name']\n value: \"{name}\"\n description: Enter Namespace Name\n - id: save\n action: click\n selector: \"[class*='save-bt'],[class*='submit-button']\"\n context: footer\n wait_for: text('{name}')\n wait_timeout_ms: 30000\n description: Save/submit the form (union selector matches save-bt OR submit-button)\npostconditions:\n - resource_list_page_visible\n - \"resource_name_in_list: {name}\"\nmetadata:\n confidence: inferred\n discovered_at: 2026-06-24\n console_version: \"2025.06\"\n notes: Auto-generated by scripts/generate-workflows.ts from api-specs-enriched field metadata.\n",
|
|
466
466
|
"namespace/delete":
|
|
467
467
|
"schema: urn:f5xc:console:workflow:v1\nid: namespace-delete\nlabel: Delete My Namespaces\nresource: namespace\noperation: delete\npreconditions:\n - user_logged_in\n - namespace_selected\n - \"role_minimum: admin\"\n - \"resource_exists: {name}\"\nparams:\n namespace:\n required: true\n example: demo\n name:\n required: true\n example: example-namespace\nsteps:\n - id: navigate-to-list\n action: navigate\n url: /web/workspaces/administration/personal-management/namespaces\n wait_for: text('My Namespaces')\n description: Navigate to My Namespaces list page\n - id: scroll-actions-into-view\n action: scroll\n selector: row:has-text('{name}') >> [ves-e2e-test='row-action-dropdown']\n description: Scroll the Actions column into view for the target row\n - id: open-row-actions\n action: click\n selector: row:has-text('{name}') >> [ves-e2e-test='row-action-dropdown']\n wait_for: option:text('Delete')\n description: Open the row kebab menu\n - id: click-delete\n action: click\n selector: option:text('Delete')\n wait_for: button:text('Delete')\n description: Click Delete option\n - id: confirm-delete\n action: click\n selector: button:text('Delete')\n wait_for: text('My Namespaces')\n wait_timeout_ms: 15000\n description: Confirm deletion\npostconditions:\n - resource_removed_from_list\n - list_page_visible\nmetadata:\n confidence: inferred\n discovered_at: 2026-06-24\n console_version: \"2025.06\"\n notes: Auto-generated by scripts/generate-workflows.ts from api-specs-enriched field metadata.\n",
|
|
468
468
|
"namespace/read":
|
|
@@ -534,7 +534,7 @@ export const CONSOLE_CATALOG_DATA: ConsoleCatalogData = {
|
|
|
534
534
|
"openapi-file/update":
|
|
535
535
|
"schema: urn:f5xc:console:workflow:v1\nid: openapi-file-update\nlabel: Update OpenAPI Files\nresource: openapi-file\noperation: update\nparams:\n namespace:\n required: true\n example: demo\n name:\n required: true\n example: example-openapi-file\nsteps:\n - id: navigate-to-list\n action: navigate\n url: /web/workspaces/web-app-and-api-protection/namespaces/{namespace}/manage/files/openapi\n wait_for: text('OpenAPI Files')\n description: Navigate to OpenAPI Files list page\n - id: scroll-actions-into-view\n action: scroll\n selector: row:has-text('{name}') >> [ves-e2e-test='row-action-dropdown']\n description: Scroll the Actions column into view\n - id: open-row-actions\n action: click\n selector: row:has-text('{name}') >> [ves-e2e-test='row-action-dropdown']\n wait_for: option:text('Manage Configuration')\n description: Open the row kebab menu\n - id: open-configuration\n action: click\n selector: option:text('Manage Configuration')\n wait_for: button:text('Edit Configuration')\n wait_timeout_ms: 15000\n description: Open the read-only Manage Configuration view\n - id: enter-edit-mode\n action: click\n selector: button:text('Edit Configuration')\n wait_for: \"[class*='save-bt'],[class*='submit-button']\"\n wait_timeout_ms: 20000\n description: Click 'Edit Configuration' to switch from read-only view into the editable form\n - id: modify-fields\n action: wait\n selector: \"[class*='save-bt'],[class*='submit-button']\"\n description: The agent fills the specific fields the user asked to modify (dynamic, not pre-generated)\n - id: save\n action: click\n selector: \"[class*='save-bt'],[class*='submit-button']\"\n context: footer\n wait_for: text('OpenAPI Files')\n wait_timeout_ms: 30000\n description: Save/submit changes (union selector matches save-bt OR submit-button)\nmetadata:\n confidence: inferred\n discovered_at: 2026-06-24\n console_version: \"2025.06\"\n notes: Auto-generated by scripts/generate-workflows.ts from api-specs-enriched field metadata.\n",
|
|
536
536
|
"origin-pool/create":
|
|
537
|
-
|
|
537
|
+
"schema: urn:f5xc:console:workflow:v1\nid: origin-pool-create\nlabel: Create Origin Pools\nresource: origin-pool\noperation: create\npreconditions:\n - user_logged_in\n - namespace_selected\n - \"role_minimum: admin\"\nparams:\n namespace:\n required: true\n description: Target namespace\n example: demo\n name:\n required: true\n description: Origin Pools name (lowercase alphanumeric and hyphens)\n example: example-origin-pool\n origin_servers:\n required: true\n description: 'Default type: Public DNS Name. The sub-form requires \"DNS Name\" (FQDN of the origin).'\n port:\n required: false\n description: Port\n default: 443\nsteps:\n - id: navigate-to-list\n action: navigate\n url: /web/workspaces/web-app-and-api-protection/namespaces/{namespace}/manage/load_balancers/origin_pools\n wait_for: text('Origin Pools')\n description: Navigate to Origin Pools list page\n - id: click-add-tab\n action: click\n selector: text('Add Origin Pool')\n wait_for: textbox[name='Name']\n description: Click Add Origin Pool to open the create form\n - id: fill-name\n action: fill\n selector: textbox[name='Name']\n value: \"{name}\"\n description: \"Enter Name (pattern: ^[a-z][a-z0-9-]*$), max 64 chars\"\n - id: add-origin_servers\n action: click\n selector: button:text('Add Item')\n context: Origin Servers section\n description: \"Add Origin Servers entry (default type: Public DNS Name)\"\n then:\n - id: fill-origin_servers-value\n action: fill\n selector: textbox[name='DNS Name']\n value: \"{origin_servers}\"\n description: Enter DNS Name for the Origin Servers entry\n - id: apply-origin_servers\n action: click\n selector: button:text('Apply')\n description: Confirm Origin Servers entry\n - id: fill-port\n action: fill\n selector: spinbutton[name='Port']\n value: \"{port}\"\n description: \"Set Port (default: 443)\"\n condition: params.port is set\n - id: save\n action: click\n selector: \"[class*='save-bt'],[class*='submit-button']\"\n context: footer\n wait_for: text('{name}')\n wait_timeout_ms: 30000\n description: Save/submit the form (union selector matches save-bt OR submit-button)\npostconditions:\n - resource_list_page_visible\n - \"resource_name_in_list: {name}\"\nmetadata:\n confidence: inferred\n discovered_at: 2026-06-24\n console_version: \"2025.06\"\n notes: Auto-generated by scripts/generate-workflows.ts from api-specs-enriched field metadata.\n",
|
|
538
538
|
"origin-pool/delete":
|
|
539
539
|
"schema: urn:f5xc:console:workflow:v1\nid: origin-pool-delete\nlabel: Delete Origin Pools\nresource: origin-pool\noperation: delete\npreconditions:\n - user_logged_in\n - namespace_selected\n - \"role_minimum: admin\"\n - \"resource_exists: {name}\"\nparams:\n namespace:\n required: true\n example: demo\n name:\n required: true\n example: example-origin-pool\nsteps:\n - id: navigate-to-list\n action: navigate\n url: /web/workspaces/web-app-and-api-protection/namespaces/{namespace}/manage/load_balancers/origin_pools\n wait_for: text('Origin Pools')\n description: Navigate to Origin Pools list page\n - id: scroll-actions-into-view\n action: scroll\n selector: row:has-text('{name}') >> [ves-e2e-test='row-action-dropdown']\n description: Scroll the Actions column into view for the target row\n - id: open-row-actions\n action: click\n selector: row:has-text('{name}') >> [ves-e2e-test='row-action-dropdown']\n wait_for: option:text('Delete')\n description: Open the row kebab menu\n - id: click-delete\n action: click\n selector: option:text('Delete')\n wait_for: button:text('Delete')\n description: Click Delete option\n - id: confirm-delete\n action: click\n selector: button:text('Delete')\n wait_for: text('Origin Pools')\n wait_timeout_ms: 15000\n description: Confirm deletion\npostconditions:\n - resource_removed_from_list\n - list_page_visible\nmetadata:\n confidence: inferred\n discovered_at: 2026-06-24\n console_version: \"2025.06\"\n notes: Auto-generated by scripts/generate-workflows.ts from api-specs-enriched field metadata.\n",
|
|
540
540
|
"origin-pool/read":
|
|
@@ -702,7 +702,7 @@ export const CONSOLE_CATALOG_DATA: ConsoleCatalogData = {
|
|
|
702
702
|
"subnet/update":
|
|
703
703
|
"schema: urn:f5xc:console:workflow:v1\nid: subnet-update\nlabel: Update Subnets\nresource: subnet\noperation: update\nparams:\n namespace:\n required: true\n example: demo\n name:\n required: true\n example: example-subnet\nsteps:\n - id: navigate-to-list\n action: navigate\n url: /web/workspaces/multi-cloud-network-connect/manage/networking/legacy_network_configuration/subnets\n wait_for: text('Subnets')\n description: Navigate to Subnets list page\n - id: scroll-actions-into-view\n action: scroll\n selector: row:has-text('{name}') >> [ves-e2e-test='row-action-dropdown']\n description: Scroll the Actions column into view\n - id: open-row-actions\n action: click\n selector: row:has-text('{name}') >> [ves-e2e-test='row-action-dropdown']\n wait_for: option:text('Manage Configuration')\n description: Open the row kebab menu\n - id: open-configuration\n action: click\n selector: option:text('Manage Configuration')\n wait_for: button:text('Edit Configuration')\n wait_timeout_ms: 15000\n description: Open the read-only Manage Configuration view\n - id: enter-edit-mode\n action: click\n selector: button:text('Edit Configuration')\n wait_for: \"[class*='save-bt'],[class*='submit-button']\"\n wait_timeout_ms: 20000\n description: Click 'Edit Configuration' to switch from read-only view into the editable form\n - id: modify-fields\n action: wait\n selector: \"[class*='save-bt'],[class*='submit-button']\"\n description: The agent fills the specific fields the user asked to modify (dynamic, not pre-generated)\n - id: save\n action: click\n selector: \"[class*='save-bt'],[class*='submit-button']\"\n context: footer\n wait_for: text('Subnets')\n wait_timeout_ms: 30000\n description: Save/submit changes (union selector matches save-bt OR submit-button)\nmetadata:\n confidence: inferred\n discovered_at: 2026-06-24\n console_version: \"2025.06\"\n notes: Auto-generated by scripts/generate-workflows.ts from api-specs-enriched field metadata.\n",
|
|
704
704
|
"tcp-load-balancer/create":
|
|
705
|
-
|
|
705
|
+
"schema: urn:f5xc:console:workflow:v1\nid: tcp-load-balancer-create\nlabel: Create TCP Load Balancers\nresource: tcp-load-balancer\noperation: create\npreconditions:\n - user_logged_in\n - namespace_selected\n - \"role_minimum: admin\"\nparams:\n namespace:\n required: true\n description: Target namespace\n example: demo\n name:\n required: true\n description: TCP Load Balancers name (lowercase alphanumeric and hyphens)\n example: example-tcp-load-balancer\n domains:\n required: true\n description: TCP LB Domains table starts EMPTY (0 items) — needs Add Item click before filling. Fills via ngx-datatable\n grid real-typing after row creation.\n listen_port:\n required: false\n description: vsui listbox dropdown. Verified from live form screenshot.\n default: Listen Port\n example: Listen Port\nsteps:\n - id: navigate-to-list\n action: navigate\n url: /web/workspaces/multi-cloud-app-connect/namespaces/{namespace}/manage/load_balancers/tcp_loadbalancers\n wait_for: text('TCP Load Balancers')\n description: Navigate to TCP Load Balancers list page\n - id: click-add-tab\n action: click\n selector: text('Add TCP Load Balancer')\n wait_for: textbox[name='Name']\n description: Click Add TCP Load Balancer to open the create form\n - id: fill-name\n action: fill\n selector: textbox[name='Name']\n value: \"{name}\"\n description: Enter Name\n - id: add-item-domains\n action: click\n selector: button:text('Add Item')\n context: Domains table\n description: Add a row to the Domains table (starts empty — unlike most tables)\n - id: fill-domains\n action: fill\n selector: ngx-datatable input.form-control\n context: Domains table\n value: \"{domains}\"\n description: Enter Domains in the newly-added table row (Add Item clicked above)\n - id: fill-listen_port\n action: fill\n selector: spinbutton[name='Listen Port']\n value: \"{listen_port}\"\n description: Set Listen Port\n - id: select-listen_port\n action: select\n selector: listbox\n context: Listen Port section\n value: \"{listen_port}\"\n description: Select Listen Port (Listen Port | Port Ranges)\n condition: params.listen_port is set\n - id: save\n action: click\n selector: \"[class*='save-bt'],[class*='submit-button']\"\n context: footer\n wait_for: text('{name}')\n wait_timeout_ms: 30000\n description: Save/submit the form (union selector matches save-bt OR submit-button)\npostconditions:\n - resource_list_page_visible\n - \"resource_name_in_list: {name}\"\nmetadata:\n confidence: inferred\n discovered_at: 2026-06-24\n console_version: \"2025.06\"\n notes: Auto-generated by scripts/generate-workflows.ts from api-specs-enriched field metadata.\n",
|
|
706
706
|
"tcp-load-balancer/delete":
|
|
707
707
|
"schema: urn:f5xc:console:workflow:v1\nid: tcp-load-balancer-delete\nlabel: Delete TCP Load Balancers\nresource: tcp-load-balancer\noperation: delete\npreconditions:\n - user_logged_in\n - namespace_selected\n - \"role_minimum: admin\"\n - \"resource_exists: {name}\"\nparams:\n namespace:\n required: true\n example: demo\n name:\n required: true\n example: example-tcp-load-balancer\nsteps:\n - id: navigate-to-list\n action: navigate\n url: /web/workspaces/multi-cloud-app-connect/namespaces/{namespace}/manage/load_balancers/tcp_loadbalancers\n wait_for: text('TCP Load Balancers')\n description: Navigate to TCP Load Balancers list page\n - id: scroll-actions-into-view\n action: scroll\n selector: row:has-text('{name}') >> [ves-e2e-test='row-action-dropdown']\n description: Scroll the Actions column into view for the target row\n - id: open-row-actions\n action: click\n selector: row:has-text('{name}') >> [ves-e2e-test='row-action-dropdown']\n wait_for: option:text('Delete')\n description: Open the row kebab menu\n - id: click-delete\n action: click\n selector: option:text('Delete')\n wait_for: button:text('Delete')\n description: Click Delete option\n - id: confirm-delete\n action: click\n selector: button:text('Delete')\n wait_for: text('TCP Load Balancers')\n wait_timeout_ms: 15000\n description: Confirm deletion\npostconditions:\n - resource_removed_from_list\n - list_page_visible\nmetadata:\n confidence: inferred\n discovered_at: 2026-06-24\n console_version: \"2025.06\"\n notes: Auto-generated by scripts/generate-workflows.ts from api-specs-enriched field metadata.\n",
|
|
708
708
|
"tcp-load-balancer/read":
|
|
@@ -790,7 +790,7 @@ export const CONSOLE_CATALOG_DATA: ConsoleCatalogData = {
|
|
|
790
790
|
"virtual-network/update":
|
|
791
791
|
"schema: urn:f5xc:console:workflow:v1\nid: virtual-network-update\nlabel: Update Virtual Networks\nresource: virtual-network\noperation: update\nparams:\n namespace:\n required: true\n example: demo\n name:\n required: true\n example: example-virtual-network\nsteps:\n - id: navigate-to-list\n action: navigate\n url: /web/workspaces/multi-cloud-network-connect/manage/networking/legacy_network_configuration/virtual_networks\n wait_for: text('Virtual Networks')\n description: Navigate to Virtual Networks list page\n - id: scroll-actions-into-view\n action: scroll\n selector: row:has-text('{name}') >> [ves-e2e-test='row-action-dropdown']\n description: Scroll the Actions column into view\n - id: open-row-actions\n action: click\n selector: row:has-text('{name}') >> [ves-e2e-test='row-action-dropdown']\n wait_for: option:text('Manage Configuration')\n description: Open the row kebab menu\n - id: open-configuration\n action: click\n selector: option:text('Manage Configuration')\n wait_for: button:text('Edit Configuration')\n wait_timeout_ms: 15000\n description: Open the read-only Manage Configuration view\n - id: enter-edit-mode\n action: click\n selector: button:text('Edit Configuration')\n wait_for: \"[class*='save-bt'],[class*='submit-button']\"\n wait_timeout_ms: 20000\n description: Click 'Edit Configuration' to switch from read-only view into the editable form\n - id: modify-fields\n action: wait\n selector: \"[class*='save-bt'],[class*='submit-button']\"\n description: The agent fills the specific fields the user asked to modify (dynamic, not pre-generated)\n - id: save\n action: click\n selector: \"[class*='save-bt'],[class*='submit-button']\"\n context: footer\n wait_for: text('Virtual Networks')\n wait_timeout_ms: 30000\n description: Save/submit changes (union selector matches save-bt OR submit-button)\nmetadata:\n confidence: inferred\n discovered_at: 2026-06-24\n console_version: \"2025.06\"\n notes: Auto-generated by scripts/generate-workflows.ts from api-specs-enriched field metadata.\n",
|
|
792
792
|
"virtual-site/create":
|
|
793
|
-
"schema: urn:f5xc:console:workflow:v1\nid: virtual-site-create\nlabel: Create Virtual Sites\nresource: virtual-site\noperation: create\npreconditions:\n - user_logged_in\n - namespace_selected\n - \"role_minimum: admin\"\nparams:\n namespace:\n required: true\n description: Target namespace\n example: demo\n name:\n required: true\n description: Virtual Sites name (lowercase alphanumeric and hyphens)\n example: example-virtual-site\n
|
|
793
|
+
"schema: urn:f5xc:console:workflow:v1\nid: virtual-site-create\nlabel: Create Virtual Sites\nresource: virtual-site\noperation: create\npreconditions:\n - user_logged_in\n - namespace_selected\n - \"role_minimum: admin\"\nparams:\n namespace:\n required: true\n description: Target namespace\n example: demo\n name:\n required: true\n description: Virtual Sites name (lowercase alphanumeric and hyphens)\n example: example-virtual-site\n site_selector_expression:\n required: true\n description: 'CDK-portal label-selector: Add Label → type key prefix (e.g. \"ves\") → select from portal → operator →\n value. Verified live via label_select tool.'\n site_type:\n required: false\n description: \"Required: Site Type (RE = Regional Edge, CE = Customer Edge). Select from the listbox.\"\n default: RE\n example: RE\nsteps:\n - id: navigate-to-list\n action: navigate\n url: /web/workspaces/shared-configuration/manage/virtual_sites\n wait_for: text('Virtual Sites')\n description: Navigate to Virtual Sites list page\n - id: click-add-tab\n action: click\n selector: text('Add Virtual Site')\n wait_for: textbox[name='Name']\n description: Click Add Virtual Site to open the create form\n - id: fill-name\n action: fill\n selector: textbox[name='Name']\n value: \"{name}\"\n description: Enter Name\n - id: add-label-site_selector_expression\n action: click\n selector: text('Add Label')\n context: Site Selector Expression section\n description: Open the label-selector typeahead for Site Selector Expression\n - id: select-label-key-site_selector_expression\n action: selectLabel\n selector: input[placeholder='Type to search']\n value: \"{site_selector_expression}\"\n description: Select label key for Site Selector Expression from the CDK portal (type prefix → pick option)\n - id: select-site_type\n action: select\n selector: listbox\n context: Site Type section\n value: \"{site_type}\"\n description: Select Site Type (RE | CE)\n condition: params.site_type is set\n - id: save\n action: click\n selector: \"[class*='save-bt'],[class*='submit-button']\"\n context: footer\n wait_for: text('{name}')\n wait_timeout_ms: 30000\n description: Save/submit the form (union selector matches save-bt OR submit-button)\npostconditions:\n - resource_list_page_visible\n - \"resource_name_in_list: {name}\"\nmetadata:\n confidence: inferred\n discovered_at: 2026-06-24\n console_version: \"2025.06\"\n notes: Auto-generated by scripts/generate-workflows.ts from api-specs-enriched field metadata.\n",
|
|
794
794
|
"virtual-site/delete":
|
|
795
795
|
"schema: urn:f5xc:console:workflow:v1\nid: virtual-site-delete\nlabel: Delete Virtual Sites\nresource: virtual-site\noperation: delete\npreconditions:\n - user_logged_in\n - namespace_selected\n - \"role_minimum: admin\"\n - \"resource_exists: {name}\"\nparams:\n namespace:\n required: true\n example: demo\n name:\n required: true\n example: example-virtual-site\nsteps:\n - id: navigate-to-list\n action: navigate\n url: /web/workspaces/shared-configuration/manage/virtual_sites\n wait_for: text('Virtual Sites')\n description: Navigate to Virtual Sites list page\n - id: scroll-actions-into-view\n action: scroll\n selector: row:has-text('{name}') >> [ves-e2e-test='row-action-dropdown']\n description: Scroll the Actions column into view for the target row\n - id: open-row-actions\n action: click\n selector: row:has-text('{name}') >> [ves-e2e-test='row-action-dropdown']\n wait_for: option:text('Delete')\n description: Open the row kebab menu\n - id: click-delete\n action: click\n selector: option:text('Delete')\n wait_for: button:text('Delete')\n description: Click Delete option\n - id: confirm-delete\n action: click\n selector: button:text('Delete')\n wait_for: text('Virtual Sites')\n wait_timeout_ms: 15000\n description: Confirm deletion\npostconditions:\n - resource_removed_from_list\n - list_page_visible\nmetadata:\n confidence: inferred\n discovered_at: 2026-06-24\n console_version: \"2025.06\"\n notes: Auto-generated by scripts/generate-workflows.ts from api-specs-enriched field metadata.\n",
|
|
796
796
|
"virtual-site/read":
|
|
@@ -745,6 +745,8 @@ export const CONSOLE_FIELD_METADATA: ConsoleFieldMetadataData = {
|
|
|
745
745
|
required: true,
|
|
746
746
|
add_action: "Add Item",
|
|
747
747
|
form_section: "origin-servers",
|
|
748
|
+
sub_field_label: "DNS Name",
|
|
749
|
+
description: 'Default type: Public DNS Name. The sub-form requires "DNS Name" (FQDN of the origin).',
|
|
748
750
|
item_types: {
|
|
749
751
|
public_name: {
|
|
750
752
|
label: "Public DNS Name",
|
|
@@ -871,16 +873,25 @@ export const CONSOLE_FIELD_METADATA: ConsoleFieldMetadataData = {
|
|
|
871
873
|
},
|
|
872
874
|
},
|
|
873
875
|
tcp_loadbalancer: {
|
|
876
|
+
"metadata.name": {
|
|
877
|
+
widget_type: "textbox",
|
|
878
|
+
label: "Name",
|
|
879
|
+
required: true,
|
|
880
|
+
form_section: "metadata",
|
|
881
|
+
},
|
|
874
882
|
domains: {
|
|
875
883
|
widget_type: "table",
|
|
876
884
|
label: "Domains",
|
|
877
|
-
|
|
885
|
+
required: true,
|
|
886
|
+
add_item_first: true,
|
|
878
887
|
form_section: "basic-configuration",
|
|
888
|
+
description:
|
|
889
|
+
"TCP LB Domains table starts EMPTY (0 items) — needs Add Item click before filling. Fills via ngx-datatable grid real-typing after row creation.",
|
|
879
890
|
},
|
|
880
891
|
listen_port: {
|
|
881
892
|
widget_type: "spinbutton",
|
|
882
893
|
label: "Listen Port",
|
|
883
|
-
|
|
894
|
+
required: true,
|
|
884
895
|
form_section: "basic-configuration",
|
|
885
896
|
},
|
|
886
897
|
no_sni: {
|
|
@@ -921,10 +932,12 @@ export const CONSOLE_FIELD_METADATA: ConsoleFieldMetadataData = {
|
|
|
921
932
|
},
|
|
922
933
|
"spec.port_choice": {
|
|
923
934
|
required: true,
|
|
924
|
-
label: "Port
|
|
935
|
+
label: "Listen Port",
|
|
925
936
|
form_section: "basic-configuration",
|
|
926
|
-
|
|
927
|
-
|
|
937
|
+
default: "Listen Port",
|
|
938
|
+
options: ["Listen Port", "Port Ranges"],
|
|
939
|
+
description: "vsui listbox dropdown. Verified from live form screenshot.",
|
|
940
|
+
widget_type: "listbox",
|
|
928
941
|
},
|
|
929
942
|
},
|
|
930
943
|
healthcheck: {
|
|
@@ -1089,10 +1102,11 @@ export const CONSOLE_FIELD_METADATA: ConsoleFieldMetadataData = {
|
|
|
1089
1102
|
namespace: {
|
|
1090
1103
|
"metadata.name": {
|
|
1091
1104
|
widget_type: "textbox",
|
|
1092
|
-
label: "Name",
|
|
1105
|
+
label: "Namespace Name",
|
|
1093
1106
|
required: true,
|
|
1094
1107
|
form_section: "metadata",
|
|
1095
1108
|
notes: "System-level resource — no namespace scope",
|
|
1109
|
+
description: 'Live form uses aria-label "Namespace Name" (not standard "Name")',
|
|
1096
1110
|
},
|
|
1097
1111
|
"metadata.description": {
|
|
1098
1112
|
widget_type: "textbox",
|
|
@@ -1707,11 +1721,13 @@ export const CONSOLE_FIELD_METADATA: ConsoleFieldMetadataData = {
|
|
|
1707
1721
|
form_section: "metadata",
|
|
1708
1722
|
},
|
|
1709
1723
|
"spec.site_selector": {
|
|
1710
|
-
widget_type: "
|
|
1711
|
-
label: "Site Selector",
|
|
1724
|
+
widget_type: "label-selector",
|
|
1725
|
+
label: "Site Selector Expression",
|
|
1712
1726
|
form_section: "selector",
|
|
1713
1727
|
required: true,
|
|
1714
|
-
|
|
1728
|
+
add_action: "Add Label",
|
|
1729
|
+
description:
|
|
1730
|
+
'CDK-portal label-selector: Add Label → type key prefix (e.g. "ves") → select from portal → operator → value. Verified live via label_select tool.',
|
|
1715
1731
|
},
|
|
1716
1732
|
"spec.site_type": {
|
|
1717
1733
|
widget_type: "listbox",
|
|
@@ -2669,12 +2685,13 @@ export const CONSOLE_FIELD_METADATA: ConsoleFieldMetadataData = {
|
|
|
2669
2685
|
form_section: "metadata",
|
|
2670
2686
|
},
|
|
2671
2687
|
"spec.code_base": {
|
|
2672
|
-
widget_type: "
|
|
2688
|
+
widget_type: "listbox",
|
|
2673
2689
|
label: "Code Base",
|
|
2674
2690
|
required: true,
|
|
2675
|
-
default: "",
|
|
2676
2691
|
form_section: "integration-data",
|
|
2677
|
-
|
|
2692
|
+
resource_type: "code_base",
|
|
2693
|
+
description:
|
|
2694
|
+
'A vsui "Select item" listbox (not a configurable). Selects an existing code-base integration. Verified from live form screenshot.',
|
|
2678
2695
|
},
|
|
2679
2696
|
},
|
|
2680
2697
|
container_registry: {
|
|
@@ -3037,11 +3054,13 @@ export const CONSOLE_FIELD_METADATA: ConsoleFieldMetadataData = {
|
|
|
3037
3054
|
form_section: "origin-server",
|
|
3038
3055
|
},
|
|
3039
3056
|
"spec.reference": {
|
|
3040
|
-
widget_type: "
|
|
3057
|
+
widget_type: "listbox",
|
|
3041
3058
|
label: "Reference",
|
|
3042
3059
|
required: true,
|
|
3060
|
+
resource_type: "virtual_site",
|
|
3043
3061
|
form_section: "spec",
|
|
3044
|
-
description:
|
|
3062
|
+
description:
|
|
3063
|
+
"vsui autocomplete dropdown (VSUI-AUTOCOMPLETE-DROPDOWN) selecting a virtual-site, site, or network. Dependency resource.",
|
|
3045
3064
|
},
|
|
3046
3065
|
"spec.network_type": {
|
|
3047
3066
|
widget_type: "listbox",
|
|
@@ -374,6 +374,11 @@ export class CatalogWorkflowRunnerTool
|
|
|
374
374
|
await page.selectOption(resolvedSelector, resolvedValue ?? "", resolvedContext);
|
|
375
375
|
break;
|
|
376
376
|
}
|
|
377
|
+
case "selectLabel": {
|
|
378
|
+
if (!resolvedSelector) throw new ToolError(`Step "${step.id}": selectLabel requires selector`);
|
|
379
|
+
await (page as any).selectLabel(resolvedSelector, resolvedValue ?? "", resolvedContext);
|
|
380
|
+
break;
|
|
381
|
+
}
|
|
377
382
|
case "assert": {
|
|
378
383
|
if (!resolvedSelector) throw new ToolError(`Step "${step.id}": assert requires selector`);
|
|
379
384
|
if (!resolvedExpected) throw new ToolError(`Step "${step.id}": assert requires expected_text`);
|