@f5xc-salesdemos/xcsh 19.44.2 → 19.45.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 (58) hide show
  1. package/package.json +8 -8
  2. package/scripts/capture-ax-fixture.ts +5 -5
  3. package/scripts/capture-login-fixture.ts +1 -1
  4. package/scripts/extension-uat-harness.ts +7 -7
  5. package/scripts/generate-api-spec-index.ts +2 -2
  6. package/scripts/generate-terraform-index.ts +8 -8
  7. package/scripts/uat-matrix-modalities.ts +7 -7
  8. package/scripts/uat-matrix.ts +13 -13
  9. package/src/browser/extension-page-actions.ts +10 -4
  10. package/src/browser/extension-provider.ts +3 -3
  11. package/src/browser/input-commit.ts +1 -1
  12. package/src/cli/chrome-cli.ts +1 -1
  13. package/src/config/context-schema.json +3 -3
  14. package/src/config/settings-schema.ts +5 -5
  15. package/src/internal-urls/api-catalog-resolve.ts +5 -5
  16. package/src/internal-urls/branding-index.generated.ts +8 -8
  17. package/src/internal-urls/build-info-runtime.ts +2 -2
  18. package/src/internal-urls/build-info.generated.ts +8 -8
  19. package/src/internal-urls/console-catalog.generated.ts +264 -264
  20. package/src/internal-urls/console-field-metadata.generated.ts +36 -11
  21. package/src/internal-urls/docs-index.generated.ts +26 -26
  22. package/src/internal-urls/terraform-index.generated.ts +252 -252
  23. package/src/internal-urls/terraform-resolve.ts +13 -13
  24. package/src/internal-urls/xcsh-protocol.ts +3 -3
  25. package/src/main.ts +3 -3
  26. package/src/modes/components/context-add-wizard.ts +6 -6
  27. package/src/modes/components/plugins/utils.ts +1 -1
  28. package/src/modes/components/status-line/presets.ts +15 -15
  29. package/src/modes/components/status-line/segments.ts +10 -10
  30. package/src/modes/components/status-line-segment-editor.ts +1 -1
  31. package/src/modes/components/welcome-checks.ts +2 -2
  32. package/src/modes/components/welcome.ts +1 -1
  33. package/src/modes/controllers/context-command-controller.ts +3 -3
  34. package/src/modes/interactive-mode.ts +1 -1
  35. package/src/modes/theme/defaults/xcsh-dark.json +2 -2
  36. package/src/modes/theme/defaults/xcsh-light.json +2 -2
  37. package/src/modes/theme/theme-schema.json +4 -4
  38. package/src/modes/theme/theme.ts +6 -6
  39. package/src/prompts/system/system-prompt.md +10 -10
  40. package/src/prompts/tools/xcsh-api.md +16 -16
  41. package/src/sdk.ts +12 -12
  42. package/src/services/context-env.ts +17 -17
  43. package/src/services/{f5xc-api-client.ts → xcsh-api-client.ts} +22 -22
  44. package/src/services/{f5xc-context-command.ts → xcsh-context-command.ts} +36 -36
  45. package/src/services/{f5xc-context-display.ts → xcsh-context-display.ts} +1 -1
  46. package/src/services/{f5xc-context-segment.ts → xcsh-context-segment.ts} +4 -4
  47. package/src/services/{f5xc-context.ts → xcsh-context.ts} +104 -112
  48. package/src/services/{f5xc-env.ts → xcsh-env.ts} +42 -20
  49. package/src/services/{f5xc-knowledge.ts → xcsh-knowledge.ts} +2 -2
  50. package/src/services/{f5xc-table.ts → xcsh-table.ts} +3 -3
  51. package/src/session/session-manager.ts +2 -2
  52. package/src/slash-commands/builtin-registry.ts +1 -1
  53. package/src/slash-commands/export-command.ts +4 -4
  54. package/src/slash-commands/resource-commands.ts +4 -4
  55. package/src/system-prompt.ts +1 -1
  56. package/src/tools/catalog-workflow-runner.ts +6 -6
  57. package/src/tools/xcsh-api.ts +12 -12
  58. /package/src/services/{f5xc-context-indicators.ts → xcsh-context-indicators.ts} +0 -0
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@f5xc-salesdemos/xcsh",
4
- "version": "19.44.2",
4
+ "version": "19.45.0",
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.44.2",
58
- "@f5xc-salesdemos/pi-agent-core": "19.44.2",
59
- "@f5xc-salesdemos/pi-ai": "19.44.2",
60
- "@f5xc-salesdemos/pi-natives": "19.44.2",
61
- "@f5xc-salesdemos/pi-resource-management": "19.44.2",
62
- "@f5xc-salesdemos/pi-tui": "19.44.2",
63
- "@f5xc-salesdemos/pi-utils": "19.44.2",
57
+ "@f5xc-salesdemos/xcsh-stats": "19.45.0",
58
+ "@f5xc-salesdemos/pi-agent-core": "19.45.0",
59
+ "@f5xc-salesdemos/pi-ai": "19.45.0",
60
+ "@f5xc-salesdemos/pi-natives": "19.45.0",
61
+ "@f5xc-salesdemos/pi-resource-management": "19.45.0",
62
+ "@f5xc-salesdemos/pi-tui": "19.45.0",
63
+ "@f5xc-salesdemos/pi-utils": "19.45.0",
64
64
  "@sinclair/typebox": "^0.34",
65
65
  "@xterm/headless": "^6.0",
66
66
  "ajv": "^8.20",
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env bun
2
2
  // One-shot capture: login + open the HTTP-LB create form + snapshot the accessibility tree.
3
- // Creds via env (F5XC_USERNAME/F5XC_CONSOLE_PASSWORD); never hard-coded. Output is the resolver's test oracle.
3
+ // Creds via env (XCSH_USERNAME/XCSH_CONSOLE_PASSWORD); never hard-coded. Output is the resolver's test oracle.
4
4
  import puppeteer from "puppeteer";
5
5
 
6
6
  const CHROME = process.env.CHROME_PATH;
7
- const BASE = process.env.F5XC_CONSOLE_URL ?? "https://nferreira.staging.volterra.us";
8
- const NS = process.env.F5XC_NS ?? "demo";
7
+ const BASE = process.env.XCSH_CONSOLE_URL ?? "https://nferreira.staging.volterra.us";
8
+ const NS = process.env.XCSH_NS ?? "demo";
9
9
  const OUT = "test/browser/fixtures/xc-http-lb-create.ax.json";
10
10
 
11
11
  const browser = await puppeteer.launch({
@@ -18,8 +18,8 @@ try {
18
18
  await page.goto(BASE, { waitUntil: "networkidle2", timeout: 45000 }).catch(() => {});
19
19
  if (/login-staging\.volterra\.us/.test(page.url())) {
20
20
  await page.waitForSelector("#username", { timeout: 20000 });
21
- await page.type("#username", process.env.F5XC_USERNAME ?? "");
22
- await page.type("#password", process.env.F5XC_CONSOLE_PASSWORD ?? "");
21
+ await page.type("#username", process.env.XCSH_USERNAME ?? "");
22
+ await page.type("#password", process.env.XCSH_CONSOLE_PASSWORD ?? "");
23
23
  await Promise.all([
24
24
  page.waitForNavigation({ waitUntil: "networkidle2", timeout: 45000 }).catch(() => {}),
25
25
  page.click("#kc-login").catch(() => page.keyboard.press("Enter")),
@@ -13,7 +13,7 @@
13
13
  import puppeteer from "puppeteer";
14
14
 
15
15
  const CHROME = process.env.CHROME_PATH;
16
- const BASE = process.env.F5XC_API_URL ?? "https://nferreira.staging.volterra.us";
16
+ const BASE = process.env.XCSH_API_URL ?? "https://nferreira.staging.volterra.us";
17
17
  const PROFILE = "/tmp/xc-login-capture-profile";
18
18
  const LOGIN_OUT = "test/browser/fixtures/xc-login-wall.html";
19
19
 
@@ -15,7 +15,7 @@
15
15
  */
16
16
  import { type BridgeServer, startBridgeServer } from "../src/browser/extension-bridge";
17
17
 
18
- const BASE = process.env.F5XC_API_URL ?? "https://nferreira.staging.volterra.us";
18
+ const BASE = process.env.XCSH_API_URL ?? "https://nferreira.staging.volterra.us";
19
19
  const ROUTE = `${BASE}/web/workspaces/web-app-and-api-protection/namespaces/demo/manage/load_balancers/http_loadbalancers`;
20
20
 
21
21
  let server: BridgeServer;
@@ -69,9 +69,9 @@ async function run() {
69
69
  }
70
70
 
71
71
  console.log("[1b] login (native F5 XC auth)");
72
- const F5XC_USERNAME = process.env.F5XC_USERNAME;
73
- const F5XC_CONSOLE_PASSWORD = process.env.F5XC_CONSOLE_PASSWORD;
74
- if (F5XC_USERNAME && F5XC_CONSOLE_PASSWORD) {
72
+ const XCSH_USERNAME = process.env.XCSH_USERNAME;
73
+ const XCSH_CONSOLE_PASSWORD = process.env.XCSH_CONSOLE_PASSWORD;
74
+ if (XCSH_USERNAME && XCSH_CONSOLE_PASSWORD) {
75
75
  try {
76
76
  // Login directly to the target deep-link — NOT /web. Going to /web triggers
77
77
  // an OIDC flow, then the subsequent navigate to the LB URL interrupts it
@@ -79,7 +79,7 @@ async function run() {
79
79
  // means ONE navigation, one OIDC flow, no interruption.
80
80
  const l = await tool(
81
81
  "login",
82
- { email: F5XC_USERNAME, password: F5XC_CONSOLE_PASSWORD, consoleUrl: ROUTE },
82
+ { email: XCSH_USERNAME, password: XCSH_CONSOLE_PASSWORD, consoleUrl: ROUTE },
83
83
  90000,
84
84
  );
85
85
  (l as any)?.loggedIn
@@ -89,11 +89,11 @@ async function run() {
89
89
  fail("login", (e as Error).message);
90
90
  }
91
91
  } else {
92
- console.log(" ⏭ login skipped (no F5XC_USERNAME/F5XC_CONSOLE_PASSWORD env) — relying on existing session");
92
+ console.log(" ⏭ login skipped (no XCSH_USERNAME/XCSH_CONSOLE_PASSWORD env) — relying on existing session");
93
93
  }
94
94
 
95
95
  console.log("[2] navigate");
96
- if (F5XC_USERNAME && F5XC_CONSOLE_PASSWORD) {
96
+ if (XCSH_USERNAME && XCSH_CONSOLE_PASSWORD) {
97
97
  // Login already navigated to ROUTE — skip the redundant second navigate
98
98
  // (two navigations to the same OIDC-protected URL in succession → CSRF).
99
99
  pass("navigate", "skipped (login already navigated to target)");
@@ -150,7 +150,7 @@ async function downloadFromRelease(): Promise<string> {
150
150
  const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "api-specs-"));
151
151
  downloadedTmpDir = tmpDir;
152
152
  const tag = process.env.API_SPECS_TAG ?? (await resolveLatestTag());
153
- const zipName = `f5xc-api-specs-${tag}.zip`;
153
+ const zipName = `xcsh-api-specs-${tag}.zip`;
154
154
  const downloadUrl = `https://github.com/${REPO}/releases/download/${tag}/${zipName}`;
155
155
 
156
156
  console.log(`Downloading API specs from ${downloadUrl}...`);
@@ -552,7 +552,7 @@ if (catalog) {
552
552
  `export const API_CATALOG_INDEX: ApiCatalogIndex = {`,
553
553
  `\tversion: ${JSON.stringify(catalog.version ?? "unknown")},`,
554
554
  `\tdisplayName: ${JSON.stringify(catalog.displayName ?? "F5 Distributed Cloud")},`,
555
- `\tservice: ${JSON.stringify(catalog.service ?? "f5xc")},`,
555
+ `\tservice: ${JSON.stringify(catalog.service ?? "xcsh")},`,
556
556
  `\tcategoryCount: ${categories.length},`,
557
557
  `\tauth: ${JSON.stringify(catalog.auth ?? {})},`,
558
558
  `\tdefaults: ${JSON.stringify(catalog.defaults ?? {})},`,
@@ -9,13 +9,13 @@ const LOCAL_JSON_PATH = path.resolve(
9
9
  "..",
10
10
  "..",
11
11
  "..",
12
- "terraform-provider-f5xc",
12
+ "terraform-provider-xcsh",
13
13
  "docs",
14
14
  "terraform-llms-index.json",
15
15
  );
16
16
 
17
17
  const GITHUB_RAW_URL =
18
- "https://raw.githubusercontent.com/f5xc-salesdemos/terraform-provider-f5xc/main/docs/terraform-llms-index.json";
18
+ "https://raw.githubusercontent.com/f5xc-salesdemos/terraform-provider-xcsh/main/docs/terraform-llms-index.json";
19
19
 
20
20
  async function loadTerraformIndex(): Promise<unknown> {
21
21
  const localFile = Bun.file(LOCAL_JSON_PATH);
@@ -41,14 +41,14 @@ async function loadTerraformIndex(): Promise<unknown> {
41
41
  // Backfill provider fields that older terraform-llms-index.json revisions lack, so the
42
42
  // generated index always satisfies TerraformProvider regardless of which provider-repo
43
43
  // revision it was fetched from (the source repo is the authority once it ships them).
44
- const DEFAULT_CONFIG_BLOCK = 'provider "f5xc" {}';
44
+ const DEFAULT_CONFIG_BLOCK = 'provider "xcsh" {}';
45
45
  const DEFAULT_AUTH_METHODS = [
46
- 'REQUIRED: every .tf must contain a `provider "f5xc" {}` block. Without it Terraform errors: "Provider requires explicit configuration. Add a provider block".',
46
+ 'REQUIRED: every .tf must contain a `provider "xcsh" {}` block. Without it Terraform errors: "Provider requires explicit configuration. Add a provider block".',
47
47
  "Configure exactly ONE auth method, via environment variables (preferred) or explicit arguments in the provider block:",
48
- "api_token (env F5XC_API_TOKEN) — API token authentication.",
49
- "api_p12_file + p12_password (env F5XC_P12_FILE + F5XC_P12_PASSWORD) — PKCS#12 certificate authentication.",
50
- "api_cert + api_key (env F5XC_CERT + F5XC_KEY) — PEM certificate authentication.",
51
- "api_url (env F5XC_API_URL) — tenant base URL without /api suffix, e.g. https://your-tenant.console.ves.volterra.io.",
48
+ "api_token (env XCSH_API_TOKEN) — API token authentication.",
49
+ "api_p12_file + p12_password (env XCSH_P12_FILE + XCSH_P12_PASSWORD) — PKCS#12 certificate authentication.",
50
+ "api_cert + api_key (env XCSH_CERT + XCSH_KEY) — PEM certificate authentication.",
51
+ "api_url (env XCSH_API_URL) — tenant base URL without /api suffix, e.g. https://your-tenant.console.ves.volterra.io.",
52
52
  ];
53
53
 
54
54
  function normalizeProvider(data: unknown): unknown {
@@ -108,7 +108,7 @@ export function detectRouted(stdout: string): Cell["routedTo"] {
108
108
  if (usedConsole && !usedApi) return "console";
109
109
  if (usedApi && !usedConsole) return "api";
110
110
  if (usedConsole && usedApi) return "console"; // console drove it even if it also read via API
111
- if (/```(hcl|terraform)|resource\s+"f5xc_/.test(stdout)) return "file";
111
+ if (/```(hcl|terraform)|resource\s+"xcsh_/.test(stdout)) return "file";
112
112
  return "unknown";
113
113
  }
114
114
 
@@ -168,7 +168,7 @@ export async function runConsole(p: ConsolePhrase, cfg: MatrixConfig): Promise<C
168
168
  const run = await runXcsh(args, {
169
169
  timeoutMs: cfg.cellTimeoutMs,
170
170
  bin: cfg.xcshBin,
171
- env: { ...process.env, F5XC_API_URL: cfg.apiUrl },
171
+ env: { ...process.env, XCSH_API_URL: cfg.apiUrl },
172
172
  });
173
173
 
174
174
  const routedTo = detectRouted(run.stdout);
@@ -268,7 +268,7 @@ export async function runJson(p: CrudPhrase, cfg: MatrixConfig): Promise<Cell> {
268
268
  const run = await runXcsh(["--print", "--no-session", p.phrase], {
269
269
  timeoutMs: 120_000,
270
270
  bin: cfg.xcshBin,
271
- env: { ...process.env, F5XC_API_URL: cfg.apiUrl, F5XC_API_TOKEN: cfg.apiToken },
271
+ env: { ...process.env, XCSH_API_URL: cfg.apiUrl, XCSH_API_TOKEN: cfg.apiToken },
272
272
  });
273
273
 
274
274
  let code = await apiGet(verifyPath, cfg);
@@ -318,7 +318,7 @@ function extractHcl(stdout: string, workdir: string): string {
318
318
  let m: RegExpExecArray | null;
319
319
  // biome-ignore lint/suspicious/noAssignInExpressions: standard regex loop
320
320
  while ((m = fence.exec(stdout)) !== null) {
321
- if (/resource\s+"f5xc_|provider\s+"f5xc"|terraform\s*\{/.test(m[1]!)) hcl += `\n${m[1]}`;
321
+ if (/resource\s+"xcsh_|provider\s+"xcsh"|terraform\s*\{/.test(m[1]!)) hcl += `\n${m[1]}`;
322
322
  }
323
323
  return hcl.trim();
324
324
  }
@@ -330,14 +330,14 @@ async function terraformAvailable(): Promise<boolean> {
330
330
 
331
331
  export async function runHcl(p: TfPhrase, cfg: MatrixConfig, tfOk: boolean): Promise<Cell> {
332
332
  const start = performance.now();
333
- const id = `H-${(p.expect_resource ?? p.operation).replace(/^f5xc_/, "")}-${p.operation}`;
333
+ const id = `H-${(p.expect_resource ?? p.operation).replace(/^xcsh_/, "")}-${p.operation}`;
334
334
  const workdir = fs.mkdtempSync(path.join(os.tmpdir(), "uat-hcl-"));
335
335
  try {
336
336
  const run = await runXcsh(["--print", "--no-session", p.phrase], {
337
337
  timeoutMs: 120_000,
338
338
  bin: cfg.xcshBin,
339
339
  cwd: workdir,
340
- env: { ...process.env, F5XC_API_URL: cfg.apiUrl },
340
+ env: { ...process.env, XCSH_API_URL: cfg.apiUrl },
341
341
  });
342
342
 
343
343
  // expect_command phrases (plan/destroy explanations): keyword presence only.
@@ -427,7 +427,7 @@ export async function runI18n(p: I18nPhrase, locale: string, cfg: MatrixConfig):
427
427
  timeoutMs: 120_000,
428
428
  bin: cfg.xcshBin,
429
429
  cwd: workdir,
430
- env: { ...process.env, F5XC_API_URL: cfg.apiUrl },
430
+ env: { ...process.env, XCSH_API_URL: cfg.apiUrl },
431
431
  });
432
432
  const hcl = extractHcl(run.stdout, workdir);
433
433
  const ok = hcl.includes(p.expected_resource_type) && p.expected_fields.every(f => hcl.includes(f));
@@ -13,7 +13,7 @@
13
13
  * [--filter <regex over phrase ids>] [--no-cleanup] [--cleanup-only]
14
14
  * [--dry-run] [--self-test-api] [--strict-nl] [--report-dir <dir>]
15
15
  *
16
- * Env: F5XC_API_URL, F5XC_API_TOKEN, F5XC_USERNAME, F5XC_CONSOLE_PASSWORD, F5XC_NAMESPACE=demo,
16
+ * Env: XCSH_API_URL, XCSH_API_TOKEN, XCSH_USERNAME, XCSH_CONSOLE_PASSWORD, XCSH_NAMESPACE=demo,
17
17
  * XCSH_BIN=xcsh
18
18
  */
19
19
  import * as fs from "node:fs";
@@ -122,10 +122,10 @@ function applyLimitFilter<T>(items: T[], args: Args, idOf: (t: T) => string): T[
122
122
  function cfgFromEnv(args: Args): MatrixConfig {
123
123
  return {
124
124
  xcshBin: process.env.XCSH_BIN ?? "xcsh",
125
- apiUrl: process.env.F5XC_API_URL ?? "https://nferreira.staging.volterra.us",
126
- apiToken: process.env.F5XC_API_TOKEN ?? "",
127
- consoleNamespace: process.env.F5XC_NAMESPACE ?? "demo",
128
- tenant: (process.env.F5XC_API_URL ?? "https://nferreira.staging.volterra.us")
125
+ apiUrl: process.env.XCSH_API_URL ?? "https://nferreira.staging.volterra.us",
126
+ apiToken: process.env.XCSH_API_TOKEN ?? "",
127
+ consoleNamespace: process.env.XCSH_NAMESPACE ?? "demo",
128
+ tenant: (process.env.XCSH_API_URL ?? "https://nferreira.staging.volterra.us")
129
129
  .replace(/^https?:\/\//, "")
130
130
  .split(".")[0]!,
131
131
  observable: args.observable,
@@ -152,21 +152,21 @@ async function ensureExtensionConnectedAndLogin(cfg: MatrixConfig): Promise<void
152
152
  );
153
153
  }
154
154
  console.log("[console] extension connected ✅");
155
- const F5XC_USERNAME = process.env.F5XC_USERNAME;
156
- const F5XC_CONSOLE_PASSWORD = process.env.F5XC_CONSOLE_PASSWORD;
157
- if (F5XC_USERNAME && F5XC_CONSOLE_PASSWORD) {
155
+ const XCSH_USERNAME = process.env.XCSH_USERNAME;
156
+ const XCSH_CONSOLE_PASSWORD = process.env.XCSH_CONSOLE_PASSWORD;
157
+ if (XCSH_USERNAME && XCSH_CONSOLE_PASSWORD) {
158
158
  const route = `${cfg.apiUrl}/web/workspaces/web-app-and-api-protection/namespaces/${cfg.consoleNamespace}/manage/load_balancers/http_loadbalancers`;
159
159
  console.log("[console] establishing session via login tool...");
160
160
  const r = await server.request(
161
161
  "login",
162
- { email: F5XC_USERNAME, password: F5XC_CONSOLE_PASSWORD, consoleUrl: route },
162
+ { email: XCSH_USERNAME, password: XCSH_CONSOLE_PASSWORD, consoleUrl: route },
163
163
  160_000,
164
164
  );
165
165
  if (r.is_error || !(r.content as any)?.loggedIn)
166
166
  throw new Error(`login failed: ${JSON.stringify(r.content).slice(0, 160)}`);
167
167
  console.log("[console] logged in ✅ (session persists across xcsh runs)");
168
168
  } else {
169
- console.log("[console] no F5XC_USERNAME/F5XC_CONSOLE_PASSWORD — relying on an existing Chrome session");
169
+ console.log("[console] no XCSH_USERNAME/XCSH_CONSOLE_PASSWORD — relying on an existing Chrome session");
170
170
  }
171
171
  } finally {
172
172
  // Release the socket so each `xcsh --print` can own it (the extension reconnects via its alarm).
@@ -211,7 +211,7 @@ async function main() {
211
211
  const startedAt = new Date().toISOString();
212
212
 
213
213
  if (args.cleanupOnly) {
214
- if (!cfg.apiToken) throw new Error("F5XC_API_TOKEN required for cleanup");
214
+ if (!cfg.apiToken) throw new Error("XCSH_API_TOKEN required for cleanup");
215
215
  await cleanup(cfg);
216
216
  return;
217
217
  }
@@ -244,7 +244,7 @@ async function main() {
244
244
 
245
245
  // --- API self-test ---
246
246
  if (args.selfTestApi) {
247
- if (!cfg.apiToken) throw new Error("F5XC_API_TOKEN required");
247
+ if (!cfg.apiToken) throw new Error("XCSH_API_TOKEN required");
248
248
  const present = await apiGet(`/api/config/namespaces/${cfg.consoleNamespace}/healthchecks`, cfg);
249
249
  const absent = await apiGet(
250
250
  `/api/config/namespaces/${cfg.consoleNamespace}/healthchecks/uat-definitely-absent-xyz`,
@@ -254,7 +254,7 @@ async function main() {
254
254
  process.exit(present === "200" && absent === "404" ? 0 : 1);
255
255
  }
256
256
 
257
- if (!cfg.apiToken) throw new Error("F5XC_API_TOKEN required for verification");
257
+ if (!cfg.apiToken) throw new Error("XCSH_API_TOKEN required for verification");
258
258
 
259
259
  // --- Console FIRST (human watching) ---
260
260
  if (args.modalities.has("console")) {
@@ -43,6 +43,7 @@ function roleToSelector(role){
43
43
  case'link':return'a[href],[role=link]';
44
44
  case'tab':return'[role=tab]';
45
45
  case'textbox':return'input:not([type=checkbox]):not([type=radio]):not([type=submit]):not([type=button]),textarea,[role=textbox]';
46
+ case'textarea':return'textarea';
46
47
  case'spinbutton':return'input[type=number],[role=spinbutton]';
47
48
  case'checkbox':return'input[type=checkbox],[role=checkbox]';
48
49
  case'radio':return'input[type=radio],[role=radio]';
@@ -169,7 +170,7 @@ function buildFillScript(selector: string, value: string): string {
169
170
  const val = JSON.stringify(value);
170
171
  return `(()=>{
171
172
  const sel=${sel};
172
- function roleToSel(r){const m={button:'button,input[type=button],input[type=submit],[role=button]',link:'a[href],[role=link]',tab:'[role=tab]',textbox:'input:not([type=checkbox]):not([type=radio]):not([type=submit]):not([type=button]),textarea,[role=textbox]',spinbutton:'input[type=number],[role=spinbutton]',checkbox:'input[type=checkbox],[role=checkbox]',combobox:'select,[role=combobox]',listbox:'[role=listbox],select',option:'[role=option],option',heading:'h1,h2,h3,h4,h5,h6,[role=heading]'};return m[r]||'[role='+r+']';}
173
+ function roleToSel(r){const m={button:'button,input[type=button],input[type=submit],[role=button]',link:'a[href],[role=link]',tab:'[role=tab]',textbox:'input:not([type=checkbox]):not([type=radio]):not([type=submit]):not([type=button]),textarea,[role=textbox]',textarea:'textarea',spinbutton:'input[type=number],[role=spinbutton]',checkbox:'input[type=checkbox],[role=checkbox]',combobox:'select,[role=combobox]',listbox:'[role=listbox],select',option:'[role=option],option',heading:'h1,h2,h3,h4,h5,h6,[role=heading]'};return m[r]||'[role='+r+']';}
173
174
  function norm(t){return t.replace(/\\u0421/g,'C').replace(/\\s+/g,' ').trim();}
174
175
  function findText(text,rSel){return(rSel?[...document.querySelectorAll(rSel)]:[...document.querySelectorAll('*')]).find(e=>{const n=norm(e.textContent||'');return n===norm(text)||n.includes(norm(text));});}
175
176
  function findRoleName(role,name){const cs=[...document.querySelectorAll(roleToSel(role))];const w=norm(name);return cs.find(e=>norm(e.getAttribute('aria-label')||e.getAttribute('name')||e.getAttribute('placeholder')||e.textContent||'').includes(w))||(role==='textbox'?cs.find(e=>norm((e.closest('[class*=form-group],[class*=field],.row')||{}).textContent||'').includes(w)):null);}
@@ -239,7 +240,13 @@ export class ExtensionPageActions implements PageActions {
239
240
  if (!probe?.found) {
240
241
  throw new Error(`fill("${selector}"): ${probe?.error ?? "selector not found"}`);
241
242
  }
242
- if (probe.inGrid) {
243
+ // Two element classes need REAL CDP keystrokes, not a synthetic value-setter:
244
+ // - ngx-datatable inline cells (probe.inGrid) — commit on Enter.
245
+ // - <textarea> inside vsui secret/Blindfold sub-forms (container_registry's
246
+ // "Secret to Blindfold") — the native setter leaves them empty/required.
247
+ // For textareas we must NOT press Enter (it inserts a newline); Tab blurs.
248
+ const isTextarea = probe.tag === "TEXTAREA";
249
+ if (probe.inGrid || isTextarea) {
243
250
  await this.#ext.clickXy(probe.x as number, probe.y as number);
244
251
  await new Promise(r => setTimeout(r, 200));
245
252
  // Clear any pre-existing text (Backspace ×N) so re-fills are clean —
@@ -248,8 +255,7 @@ export class ExtensionPageActions implements PageActions {
248
255
  for (let i = 0; i < curLen; i++) await this.#ext.keyPress("Backspace").catch(() => {});
249
256
  await this.#ext.typeText(value);
250
257
  await new Promise(r => setTimeout(r, 200));
251
- // Enter commits the inline row to the model; Angular marks it ng-valid.
252
- await this.#ext.keyPress("Enter").catch(() => {});
258
+ await this.#ext.keyPress(probe.inGrid && !isTextarea ? "Enter" : "Tab").catch(() => {});
253
259
  await new Promise(r => setTimeout(r, 300));
254
260
  const after = await evalJson(this.#ext, buildResolverScript(selector));
255
261
  if (typeof after?.val === "string" && after.val.includes(value)) return;
@@ -252,13 +252,13 @@ export class ExtensionBrowserProvider implements BrowserProvider {
252
252
 
253
253
  const page: ExtensionPage = new BridgeExtensionPage(server);
254
254
 
255
- // Auto-login: if F5XC_USERNAME + F5XC_CONSOLE_PASSWORD are available (set by
255
+ // Auto-login: if XCSH_USERNAME + XCSH_CONSOLE_PASSWORD are available (set by
256
256
  // ContextService from the context's env map), login automatically — the login
257
257
  // tool handles "already authenticated" (instant return) so calling it every
258
258
  // time is cheap and guarantees a valid session. Falls back to navigate-only
259
259
  // (co-drive) if credentials aren't available.
260
- const email = process.env.F5XC_USERNAME;
261
- const password = process.env.F5XC_CONSOLE_PASSWORD;
260
+ const email = process.env.XCSH_USERNAME;
261
+ const password = process.env.XCSH_CONSOLE_PASSWORD;
262
262
  if (email && password) {
263
263
  await page.login(email, password, consoleUrl);
264
264
  } else {
@@ -2,7 +2,7 @@
2
2
  * Commit a value into a form control so that a framework which patched the
3
3
  * element's `value` descriptor still observes the change.
4
4
  *
5
- * Why this exists: the F5XC console's `vsui-input` (e.g. over the HTTP-LB
5
+ * Why this exists: the XCSH console's `vsui-input` (e.g. over the HTTP-LB
6
6
  * "Domains" ngx-datatable cell) overrides the native `<input>` `value`
7
7
  * descriptor with its own accessor. Typing real keystrokes — or assigning
8
8
  * `el.value = …` directly — leaves the text in the DOM but never reaches the
@@ -18,7 +18,7 @@ export type ChromeAction = "status" | "relaunch" | "setup";
18
18
  export const EXTENSION_ID = "klajkjdoehjidngligegnpknogmjjhkc";
19
19
  export const EXTENSION_IDS = [EXTENSION_ID];
20
20
 
21
- const NATIVE_HOST_NAME = "com.f5xc.xcsh.chrome_host";
21
+ const NATIVE_HOST_NAME = "com.xcsh.xcsh.chrome_host";
22
22
 
23
23
  function nativeHostDir(platform: NodeJS.Platform, home: string): string {
24
24
  if (platform === "darwin")
@@ -2,7 +2,7 @@
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
3
  "$id": "https://raw.githubusercontent.com/f5xc-salesdemos/xcsh/main/packages/coding-agent/src/config/context-schema.json",
4
4
  "title": "F5 XC Context",
5
- "description": "Schema for F5 XC context files stored in ~/.config/f5xc/contexts/<name>.json. Validated at load, create, and import time.",
5
+ "description": "Schema for F5 XC context files stored in ~/.config/xcsh/contexts/<name>.json. Validated at load, create, and import time.",
6
6
  "type": "object",
7
7
  "required": ["apiUrl", "apiToken"],
8
8
  "additionalProperties": false,
@@ -39,7 +39,7 @@
39
39
  "type": "string",
40
40
  "minLength": 1,
41
41
  "default": "default",
42
- "description": "Default namespace for CRUD operations. Projected as F5XC_NAMESPACE in bash environment. Use /context namespace to change."
42
+ "description": "Default namespace for CRUD operations. Projected as XCSH_NAMESPACE in bash environment. Use /context namespace to change."
43
43
  },
44
44
  "env": {
45
45
  "type": "object",
@@ -55,7 +55,7 @@
55
55
  },
56
56
  {
57
57
  "not": {
58
- "enum": ["F5XC_NAMESPACE", "F5XC_API_URL", "F5XC_API_TOKEN", "F5XC_TENANT"]
58
+ "enum": ["XCSH_NAMESPACE", "XCSH_API_URL", "XCSH_API_TOKEN", "XCSH_TENANT"]
59
59
  },
60
60
  "description": "Reserved keys have dedicated top-level fields and must not appear in env."
61
61
  }
@@ -76,7 +76,7 @@ export type StatusLineSegmentId =
76
76
  | "cache_read"
77
77
  | "cache_write"
78
78
  | "session_name"
79
- | "context_f5xc"
79
+ | "context_xcsh"
80
80
  | "os_icon";
81
81
 
82
82
  interface UiMetadata {
@@ -1904,14 +1904,14 @@ export const SETTINGS_SCHEMA = {
1904
1904
  "thinkingBudgets.xhigh": { type: "number", default: 32768 },
1905
1905
 
1906
1906
  // ────────────────────────────────────────────────────────────────────────
1907
- // Fork-specific settings (xcsh / f5xc)
1907
+ // Fork-specific settings (xcsh / xcsh)
1908
1908
  // ────────────────────────────────────────────────────────────────────────
1909
1909
 
1910
- /** Per-session environment variables injected into bash (used by f5xc context system) */
1910
+ /** Per-session environment variables injected into bash (used by xcsh context system) */
1911
1911
  "bash.environment": { type: "record", default: {} as Record<string, string> },
1912
1912
 
1913
- /** Sensitive env var key names from the active f5xc context (populated by ContextService) */
1914
- "f5xc.sensitiveKeys": { type: "array", default: [] as string[] },
1913
+ /** Sensitive env var key names from the active xcsh context (populated by ContextService) */
1914
+ "xcsh.sensitiveKeys": { type: "array", default: [] as string[] },
1915
1915
 
1916
1916
  /** Clear terminal on startup */
1917
1917
  "startup.clearScreen": { type: "boolean", default: false },
@@ -252,7 +252,7 @@ function renderCatalogDetail(cat: ApiCatalogCategory, index: ApiCatalogIndex, op
252
252
  // Universal reference format hint — shown even in compact mode
253
253
  if (op.method.toUpperCase() === "POST" || op.method.toUpperCase() === "PUT") {
254
254
  sections.push(
255
- 'Object references: `{"namespace": "$F5XC_NAMESPACE", "name": "<name>"}`. Pool arrays: `[{"pool": {"namespace": "$F5XC_NAMESPACE", "name": "<name>"}, "weight": 1, "priority": 1}]`.',
255
+ 'Object references: `{"namespace": "$XCSH_NAMESPACE", "name": "<name>"}`. Pool arrays: `[{"pool": {"namespace": "$XCSH_NAMESPACE", "name": "<name>"}, "weight": 1, "priority": 1}]`.',
256
256
  );
257
257
  }
258
258
 
@@ -340,13 +340,13 @@ async function fetchNamespaceInventory(
340
340
  data: Readonly<Record<string, ApiCatalogCategory>>,
341
341
  url: InternalUrl,
342
342
  ): Promise<string> {
343
- const apiBase = (process.env.F5XC_API_URL ?? "").replace(/\/+$/, "");
344
- const apiToken = process.env.F5XC_API_TOKEN ?? "";
343
+ const apiBase = (process.env.XCSH_API_URL ?? "").replace(/\/+$/, "");
344
+ const apiToken = process.env.XCSH_API_TOKEN ?? "";
345
345
  if (!apiBase || !apiToken) {
346
- return "# Namespace Inventory\n\nError: No API credentials configured. Set F5XC_API_URL and F5XC_API_TOKEN, or activate a context.\n";
346
+ return "# Namespace Inventory\n\nError: No API credentials configured. Set XCSH_API_URL and XCSH_API_TOKEN, or activate a context.\n";
347
347
  }
348
348
 
349
- const ns = url.searchParams.get("ns") ?? process.env.F5XC_NAMESPACE ?? "default";
349
+ const ns = url.searchParams.get("ns") ?? process.env.XCSH_NAMESPACE ?? "default";
350
350
  const CONFIG_PREFIX = "/api/config/namespaces/{namespace}/";
351
351
  const APP_KW =
352
352
  /loadbalancer|pool|firewall|_policys|setting|type|mitigation|identification|network|route|host|definition|rate_limiter|prefix_set|cdn|waf|api_/i;
@@ -31,21 +31,21 @@ export const BRANDING_DEPRECATIONS = {
31
31
  note: "Still live on registry with no deprecation notice. High risk of AI model recommendation due to training data prevalence.\n",
32
32
  },
33
33
  canonical: {
34
- registry: "registry.terraform.io/providers/f5xc-salesdemos/f5xc",
35
- source: "f5xc-salesdemos/f5xc",
36
- github: "github.com/f5xc-salesdemos/terraform-provider-f5xc",
37
- docs: "https://f5xc-salesdemos.github.io/terraform-provider-f5xc/",
38
- llms_txt: "https://f5xc-salesdemos.github.io/terraform-provider-f5xc/llms.txt",
34
+ registry: "registry.terraform.io/providers/f5xc-salesdemos/xcsh",
35
+ source: "f5xc-salesdemos/xcsh",
36
+ github: "github.com/f5xc-salesdemos/terraform-provider-xcsh",
37
+ docs: "https://f5xc-salesdemos.github.io/terraform-provider-xcsh/",
38
+ llms_txt: "https://f5xc-salesdemos.github.io/terraform-provider-xcsh/llms.txt",
39
39
  },
40
40
  required_providers_block:
41
- 'terraform {\n required_providers {\n f5xc = {\n source = "f5xc-salesdemos/f5xc"\n }\n }\n}\n',
41
+ 'terraform {\n required_providers {\n xcsh = {\n source = "f5xc-salesdemos/xcsh"\n }\n }\n}\n',
42
42
  },
43
43
  api_endpoint: {
44
44
  deprecated: {
45
45
  url: "console.ves.volterra.io",
46
46
  },
47
47
  canonical: {
48
- note: "Tenant-specific. No hardcoded default. Require F5XC_API_URL env var.",
48
+ note: "Tenant-specific. No hardcoded default. Require XCSH_API_URL env var.",
49
49
  },
50
50
  },
51
51
  documentation: {
@@ -53,7 +53,7 @@ export const BRANDING_DEPRECATIONS = {
53
53
  note: "docs.cloud.f5.com references to Volterra provider point to the deprecated volterraedge/volterra registry.\n",
54
54
  },
55
55
  canonical: {
56
- url: "https://f5xc-salesdemos.github.io/terraform-provider-f5xc/",
56
+ url: "https://f5xc-salesdemos.github.io/terraform-provider-xcsh/",
57
57
  },
58
58
  },
59
59
  } as const;
@@ -1,7 +1,7 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
3
  import { $ } from "bun";
4
- import type { ContextStatus } from "../services/f5xc-context";
4
+ import type { ContextStatus } from "../services/xcsh-context";
5
5
  import { BUILD_INFO, type BuildInfo } from "./build-info.generated";
6
6
 
7
7
  export type BuildInfoSource = "compiled" | "live-git" | "embedded-fallback";
@@ -114,7 +114,7 @@ function renderAuthStatusLine(context: ContextStatus, nowMs: number): string {
114
114
  }
115
115
 
116
116
  function renderPlatformContext(context: ContextStatus | null, nowMs: number): string {
117
- // xcsh can be connected via a named context OR via F5XC_API_URL / F5XC_API_TOKEN env vars.
117
+ // xcsh can be connected via a named context OR via XCSH_API_URL / XCSH_API_TOKEN env vars.
118
118
  // In the env-only case, activeContextName is null but activeContextTenant (derived from the
119
119
  // env URL) and credentialSource ("environment") are still populated. Guard on tenant, not
120
120
  // name, so env-backed deployments see the configured state instead of the unconfigured copy.
@@ -17,17 +17,17 @@ export interface BuildInfo {
17
17
  }
18
18
 
19
19
  export const BUILD_INFO: BuildInfo = {
20
- "version": "19.44.2",
21
- "commit": "6e93a54c64e7bdd78d54b56b0c0237025aa420c7",
22
- "shortCommit": "6e93a54",
20
+ "version": "19.45.0",
21
+ "commit": "60deceedc40dbe381063bb844f14f02c993ca9f7",
22
+ "shortCommit": "60decee",
23
23
  "branch": "main",
24
- "tag": "v19.44.2",
25
- "commitDate": "2026-06-25T00:16:19Z",
26
- "buildDate": "2026-06-25T00:38:03.351Z",
24
+ "tag": "v19.45.0",
25
+ "commitDate": "2026-06-25T15:02:43Z",
26
+ "buildDate": "2026-06-25T15:51:07.484Z",
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/6e93a54c64e7bdd78d54b56b0c0237025aa420c7",
32
- "releaseUrl": "https://github.com/f5xc-salesdemos/xcsh/releases/tag/v19.44.2"
31
+ "commitUrl": "https://github.com/f5xc-salesdemos/xcsh/commit/60deceedc40dbe381063bb844f14f02c993ca9f7",
32
+ "releaseUrl": "https://github.com/f5xc-salesdemos/xcsh/releases/tag/v19.45.0"
33
33
  };