@f5-sales-demo/xcsh 20.20.0 → 20.20.2
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/CHANGELOG.md +6 -0
- package/package.json +8 -8
- package/src/cli/update-cli.ts +14 -6
- package/src/commands/update.ts +100 -10
- package/src/internal-urls/build-info.generated.ts +8 -8
- package/src/internal-urls/console-catalog.generated.ts +2 -2
- package/src/locales/en.json +1 -1
- package/src/main.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -16,6 +16,12 @@
|
|
|
16
16
|
contract so TUI, Browser, Office, RPC, and ACP transports no longer identify media by tool name
|
|
17
17
|
([#3202](https://github.com/f5-sales-demo/xcsh/issues/3202)).
|
|
18
18
|
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- Restored bare `xcsh update` as a backward-compatible executable updater while preserving
|
|
22
|
+
manifest-based resource updates and the explicit `xcsh self-update` command
|
|
23
|
+
([#3249](https://github.com/f5-sales-demo/xcsh/issues/3249)).
|
|
24
|
+
|
|
19
25
|
## [20.6.3] - 2026-08-07
|
|
20
26
|
|
|
21
27
|
### Improved
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@f5-sales-demo/xcsh",
|
|
4
|
-
"version": "20.20.
|
|
4
|
+
"version": "20.20.2",
|
|
5
5
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
6
6
|
"homepage": "https://github.com/f5-sales-demo/xcsh",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -61,13 +61,13 @@
|
|
|
61
61
|
},
|
|
62
62
|
"dependencies": {
|
|
63
63
|
"@agentclientprotocol/sdk": "1.3.0",
|
|
64
|
-
"@f5-sales-demo/pi-agent-core": "20.20.
|
|
65
|
-
"@f5-sales-demo/pi-ai": "20.20.
|
|
66
|
-
"@f5-sales-demo/pi-natives": "20.20.
|
|
67
|
-
"@f5-sales-demo/pi-resource-management": "20.20.
|
|
68
|
-
"@f5-sales-demo/pi-tui": "20.20.
|
|
69
|
-
"@f5-sales-demo/pi-utils": "20.20.
|
|
70
|
-
"@f5-sales-demo/xcsh-stats": "20.20.
|
|
64
|
+
"@f5-sales-demo/pi-agent-core": "20.20.2",
|
|
65
|
+
"@f5-sales-demo/pi-ai": "20.20.2",
|
|
66
|
+
"@f5-sales-demo/pi-natives": "20.20.2",
|
|
67
|
+
"@f5-sales-demo/pi-resource-management": "20.20.2",
|
|
68
|
+
"@f5-sales-demo/pi-tui": "20.20.2",
|
|
69
|
+
"@f5-sales-demo/pi-utils": "20.20.2",
|
|
70
|
+
"@f5-sales-demo/xcsh-stats": "20.20.2",
|
|
71
71
|
"@mozilla/readability": "^0.6",
|
|
72
72
|
"@sinclair/typebox": "^0.34",
|
|
73
73
|
"@xterm/headless": "^6.0",
|
package/src/cli/update-cli.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Update CLI command handler.
|
|
3
3
|
*
|
|
4
|
-
* Handles `xcsh self-update`
|
|
4
|
+
* Handles executable updates for explicit `xcsh self-update` and compatible `xcsh update` forms.
|
|
5
5
|
* Auto-detects the installation method (npm, brew, bun, or standalone binary)
|
|
6
6
|
* and updates through the appropriate channel.
|
|
7
7
|
*/
|
|
@@ -439,14 +439,21 @@ export async function runUpdateCommand(opts: { force: boolean; check: boolean })
|
|
|
439
439
|
* Print update command help.
|
|
440
440
|
*/
|
|
441
441
|
export function printUpdateHelp(): void {
|
|
442
|
-
console.log(`${chalk.bold(`${APP_NAME} update`)} -
|
|
442
|
+
console.log(`${chalk.bold(`${APP_NAME} update`)} - Update the executable or existing resources from manifests
|
|
443
443
|
|
|
444
444
|
${chalk.bold("Usage:")}
|
|
445
|
-
${APP_NAME} update [
|
|
445
|
+
${APP_NAME} update [--check | --force]
|
|
446
|
+
${APP_NAME} update -f <manifest> [resource options]
|
|
446
447
|
|
|
447
|
-
${chalk.bold("
|
|
448
|
-
-c, --check Check for updates without installing
|
|
449
|
-
|
|
448
|
+
${chalk.bold("Executable options:")}
|
|
449
|
+
-c, --check Check for executable updates without installing
|
|
450
|
+
--force Force reinstall even if up to date
|
|
451
|
+
|
|
452
|
+
${chalk.bold("Resource input:")}
|
|
453
|
+
-f, --filename <manifest> Update resources from a manifest
|
|
454
|
+
|
|
455
|
+
Short -f means --filename for xcsh update. Use xcsh self-update -f for the
|
|
456
|
+
short executable force form. Executable and resource flags cannot be mixed.
|
|
450
457
|
|
|
451
458
|
${chalk.bold("Install methods (auto-detected):")}
|
|
452
459
|
npm Installed via npm install -g
|
|
@@ -458,5 +465,6 @@ ${chalk.bold("Examples:")}
|
|
|
458
465
|
${APP_NAME} update Update to latest version
|
|
459
466
|
${APP_NAME} update --check Check if updates are available
|
|
460
467
|
${APP_NAME} update --force Force reinstall
|
|
468
|
+
${APP_NAME} update -f manifest.yaml Update resources
|
|
461
469
|
`);
|
|
462
470
|
}
|
package/src/commands/update.ts
CHANGED
|
@@ -1,21 +1,111 @@
|
|
|
1
|
-
import { Command } from "@f5-sales-demo/pi-utils/cli";
|
|
1
|
+
import { CliUsageError, Command, Flags, parseCommandArgv } from "@f5-sales-demo/pi-utils/cli";
|
|
2
2
|
import { runResourceCli } from "../cli/resource-cli";
|
|
3
|
+
import { runUpdateCommand } from "../cli/update-cli";
|
|
4
|
+
import { initTheme } from "../modes/theme/theme";
|
|
3
5
|
import { manifestResourceFlags } from "./resource-flags";
|
|
4
6
|
|
|
7
|
+
const updateFlags = {
|
|
8
|
+
...manifestResourceFlags,
|
|
9
|
+
force: Flags.boolean({
|
|
10
|
+
description: "Force executable update (short -f is reserved for resource manifests)",
|
|
11
|
+
default: false,
|
|
12
|
+
}),
|
|
13
|
+
check: Flags.boolean({ char: "c", description: "Check for executable updates without installing", default: false }),
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
type ResourceOutputFormat = "json" | "yaml" | "table" | "wide";
|
|
17
|
+
|
|
18
|
+
export type UpdateInvocation =
|
|
19
|
+
| { mode: "executable"; force: boolean; check: boolean }
|
|
20
|
+
| {
|
|
21
|
+
mode: "resource";
|
|
22
|
+
filenames: string[] | undefined;
|
|
23
|
+
namespace: string | undefined;
|
|
24
|
+
outputFormat: ResourceOutputFormat;
|
|
25
|
+
recursive: boolean;
|
|
26
|
+
dryRun: "client" | undefined;
|
|
27
|
+
resultFile: string | undefined;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
function explicitlyRequestsDefaultOutput(argv: readonly string[]): boolean {
|
|
31
|
+
return argv.some(arg => arg === "--output" || arg.startsWith("--output=") || arg === "-o");
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Resolve the backward-compatible `update` command before either updater can perform I/O. */
|
|
35
|
+
export function parseUpdateInvocation(argv: readonly string[]): UpdateInvocation {
|
|
36
|
+
if (argv.length === 1 && argv[0] === "-f") {
|
|
37
|
+
throw new CliUsageError(
|
|
38
|
+
"Ambiguous -f: use 'xcsh update --force' or 'xcsh self-update -f' for executable updates; otherwise provide a resource manifest",
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
const parsed = parseCommandArgv(argv, { flags: updateFlags });
|
|
42
|
+
if (parsed.argv.length > 0) {
|
|
43
|
+
throw new CliUsageError(`Unexpected argument${parsed.argv.length === 1 ? "" : "s"}: ${parsed.argv.join(" ")}`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const flags = parsed.flags as {
|
|
47
|
+
filename?: string[];
|
|
48
|
+
namespace?: string;
|
|
49
|
+
output: ResourceOutputFormat;
|
|
50
|
+
recursive: boolean;
|
|
51
|
+
"dry-run"?: "client";
|
|
52
|
+
"result-file"?: string;
|
|
53
|
+
force: boolean;
|
|
54
|
+
check: boolean;
|
|
55
|
+
};
|
|
56
|
+
const executableRequested = flags.force || flags.check;
|
|
57
|
+
const resourceRequested =
|
|
58
|
+
flags.filename !== undefined ||
|
|
59
|
+
flags.namespace !== undefined ||
|
|
60
|
+
flags.recursive ||
|
|
61
|
+
flags["dry-run"] !== undefined ||
|
|
62
|
+
flags["result-file"] !== undefined ||
|
|
63
|
+
flags.output !== "table" ||
|
|
64
|
+
explicitlyRequestsDefaultOutput(argv);
|
|
65
|
+
|
|
66
|
+
if (executableRequested && resourceRequested) {
|
|
67
|
+
throw new CliUsageError("update cannot combine executable-update and resource-update flags");
|
|
68
|
+
}
|
|
69
|
+
if (!resourceRequested) {
|
|
70
|
+
return { mode: "executable", force: flags.force, check: flags.check };
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
mode: "resource",
|
|
74
|
+
filenames: flags.filename,
|
|
75
|
+
namespace: flags.namespace,
|
|
76
|
+
outputFormat: flags.output,
|
|
77
|
+
recursive: flags.recursive,
|
|
78
|
+
dryRun: flags["dry-run"],
|
|
79
|
+
resultFile: flags["result-file"],
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
5
83
|
export default class Update extends Command {
|
|
6
|
-
static description = "Update existing resources from manifests";
|
|
7
|
-
static flags =
|
|
84
|
+
static description = "Update the xcsh executable or existing resources from manifests";
|
|
85
|
+
static flags = updateFlags;
|
|
86
|
+
static examples = [
|
|
87
|
+
"xcsh update # update the executable",
|
|
88
|
+
"xcsh update --check # check the executable version",
|
|
89
|
+
"xcsh update --force # force an executable reinstall",
|
|
90
|
+
"xcsh self-update -f # short force form for the executable",
|
|
91
|
+
"xcsh update -f manifest.yaml # update resources from a manifest",
|
|
92
|
+
];
|
|
8
93
|
|
|
9
94
|
async run(): Promise<void> {
|
|
10
|
-
const
|
|
95
|
+
const invocation = parseUpdateInvocation(this.argv);
|
|
96
|
+
if (invocation.mode === "executable") {
|
|
97
|
+
await initTheme();
|
|
98
|
+
await runUpdateCommand({ force: invocation.force, check: invocation.check });
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
11
101
|
await runResourceCli({
|
|
12
102
|
operation: "update",
|
|
13
|
-
filenames:
|
|
14
|
-
namespace:
|
|
15
|
-
outputFormat:
|
|
16
|
-
recursive:
|
|
17
|
-
dryRun:
|
|
18
|
-
resultFile:
|
|
103
|
+
filenames: invocation.filenames,
|
|
104
|
+
namespace: invocation.namespace,
|
|
105
|
+
outputFormat: invocation.outputFormat,
|
|
106
|
+
recursive: invocation.recursive,
|
|
107
|
+
dryRun: invocation.dryRun,
|
|
108
|
+
resultFile: invocation.resultFile,
|
|
19
109
|
});
|
|
20
110
|
}
|
|
21
111
|
}
|
|
@@ -17,17 +17,17 @@ export interface BuildInfo {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export const BUILD_INFO: BuildInfo = {
|
|
20
|
-
"version": "20.20.
|
|
21
|
-
"commit": "
|
|
22
|
-
"shortCommit": "
|
|
20
|
+
"version": "20.20.2",
|
|
21
|
+
"commit": "04c71999d5ced53fa9200d3ae79a4ad2ba86debb",
|
|
22
|
+
"shortCommit": "04c7199",
|
|
23
23
|
"branch": "main",
|
|
24
|
-
"tag": "v20.20.
|
|
25
|
-
"commitDate": "2026-08-
|
|
26
|
-
"buildDate": "2026-08-
|
|
24
|
+
"tag": "v20.20.2",
|
|
25
|
+
"commitDate": "2026-08-17T12:59:16Z",
|
|
26
|
+
"buildDate": "2026-08-17T13:25:27.576Z",
|
|
27
27
|
"dirty": true,
|
|
28
28
|
"prNumber": "",
|
|
29
29
|
"repoUrl": "https://github.com/f5-sales-demo/xcsh",
|
|
30
30
|
"repoSlug": "f5-sales-demo/xcsh",
|
|
31
|
-
"commitUrl": "https://github.com/f5-sales-demo/xcsh/commit/
|
|
32
|
-
"releaseUrl": "https://github.com/f5-sales-demo/xcsh/releases/tag/v20.20.
|
|
31
|
+
"commitUrl": "https://github.com/f5-sales-demo/xcsh/commit/04c71999d5ced53fa9200d3ae79a4ad2ba86debb",
|
|
32
|
+
"releaseUrl": "https://github.com/f5-sales-demo/xcsh/releases/tag/v20.20.2"
|
|
33
33
|
};
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
import type { ConsoleCatalogData } from "./console-catalog-types";
|
|
4
4
|
|
|
5
|
-
export const CONSOLE_CATALOG_VERSION = "
|
|
5
|
+
export const CONSOLE_CATALOG_VERSION = "1999b4cee787136ee0bc7cd02deba57ac6381885";
|
|
6
6
|
|
|
7
7
|
export const CONSOLE_CATALOG_DATA: ConsoleCatalogData = {
|
|
8
|
-
version: "
|
|
8
|
+
version: "1999b4cee787136ee0bc7cd02deba57ac6381885",
|
|
9
9
|
workflows: {
|
|
10
10
|
"address-allocator/create":
|
|
11
11
|
'---\nschema: urn:xcsh:console:workflow:v1\nid: address-allocator-create\nlabel: Create IP Address Allocators\nresource: address-allocator\noperation: create\npreconditions:\n - user_logged_in\n - "role_minimum: admin"\nparams:\n name:\n required: true\n description: IP Address Allocators name (lowercase alphanumeric and hyphens)\n example: example-address-allocator\n address_allocator_mode:\n required: true\n description: Address Allocator Mode\n allocation_unit:\n required: false\n description: Allocation Unit\n default: 0\n address_pool:\n required: false\n description: Address Pool\n default: value\n address_allocation_scheme:\n required: false\n description: "Server-required: Field should be not nil"\n default: value\nsteps:\n - id: navigate-to-list\n action: navigate\n url: /web/workspaces/multi-cloud-network-connect/manage/networking/legacy_network_configuration/address_allocators\n wait_for: text(\'IP Address Allocators\')\n description: Navigate to IP Address Allocators list page\n - id: click-add-tab\n action: click\n selector: text(\'Add IP Address Allocator\')\n wait_for: textbox[name=\'Name\']\n description: Click Add IP Address Allocator 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-address_allocator_mode\n action: select\n selector: listbox\n context: Address Allocator Mode section\n value: "{address_allocator_mode}"\n description: Select Address Allocator Mode\n - id: fill-allocation_unit\n action: fill\n selector: spinbutton[name=\'Allocation Unit\']\n value: "{allocation_unit}"\n description: Set Allocation Unit\n - id: fill-address_pool\n action: fill\n selector: ngx-datatable input.form-control\n context: Address Pool table\n value: "{address_pool}"\n description: Enter Address Pool in the existing table row (no Add Item needed — the table ships one empty row)\n - id: select-address_allocation_scheme\n action: select\n selector: listbox\n context: Address Allocation Scheme section\n value: "{address_allocation_scheme}"\n description: Select Address Allocation Scheme\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',
|
package/src/locales/en.json
CHANGED
|
@@ -288,7 +288,7 @@
|
|
|
288
288
|
"welcome.modelProvider": "Model Provider",
|
|
289
289
|
"welcome.plugins": "Plugins",
|
|
290
290
|
"welcome.pluginSetupHint": "run: /plugin setup",
|
|
291
|
-
"welcome.updateHint": "run: xcsh
|
|
291
|
+
"welcome.updateHint": "run: xcsh update",
|
|
292
292
|
"welcome.newVersion": "new version",
|
|
293
293
|
"welcome.connectionFailed": "— connection failed",
|
|
294
294
|
"welcome.runLoginReconnect": "Run /login to reconnect",
|
package/src/main.ts
CHANGED
|
@@ -180,7 +180,7 @@ async function runInteractiveMode(
|
|
|
180
180
|
if (settings.get("startup.checkUpdate")) {
|
|
181
181
|
void versionCheckPromise
|
|
182
182
|
.then(latest => {
|
|
183
|
-
if (latest) mode.showStatus(`Update available: v${latest} — run: xcsh
|
|
183
|
+
if (latest) mode.showStatus(`Update available: v${latest} — run: xcsh update`, { dim: true });
|
|
184
184
|
})
|
|
185
185
|
.catch(() => {});
|
|
186
186
|
}
|