@f5xc-salesdemos/xcsh 18.31.0 → 18.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@f5xc-salesdemos/xcsh",
4
- "version": "18.31.0",
4
+ "version": "18.32.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",
@@ -31,7 +31,7 @@
31
31
  "xcsh": "src/cli.ts"
32
32
  },
33
33
  "scripts": {
34
- "build": "bun run generate-build-info && bun run generate-api-spec-index && bun --cwd=../stats scripts/generate-client-bundle.ts --generate && bun --cwd=../natives run embed:native && bun build --compile --define PI_COMPILED=true --external mupdf --root ../.. ./src/cli.ts --outfile dist/xcsh && bun --cwd=../natives run embed:native --reset && bun --cwd=../stats scripts/generate-client-bundle.ts --reset",
34
+ "build": "bun run generate-build-info && bun run generate-api-spec-index && test -f src/internal-urls/api-spec-index.generated.ts && bun --cwd=../stats scripts/generate-client-bundle.ts --generate && bun --cwd=../natives run embed:native && bun build --compile --define PI_COMPILED=true --external mupdf --root ../.. ./src/cli.ts --outfile dist/xcsh && bun --cwd=../natives run embed:native --reset && bun --cwd=../stats scripts/generate-client-bundle.ts --reset",
35
35
  "check": "biome check . && bun run check:types",
36
36
  "check:types": "bun run generate-build-info && bun run generate-api-spec-index && tsgo -p tsconfig.json --noEmit",
37
37
  "lint": "biome lint .",
@@ -48,12 +48,12 @@
48
48
  "dependencies": {
49
49
  "@agentclientprotocol/sdk": "0.16.1",
50
50
  "@mozilla/readability": "^0.6",
51
- "@f5xc-salesdemos/xcsh-stats": "18.31.0",
52
- "@f5xc-salesdemos/pi-agent-core": "18.31.0",
53
- "@f5xc-salesdemos/pi-ai": "18.31.0",
54
- "@f5xc-salesdemos/pi-natives": "18.31.0",
55
- "@f5xc-salesdemos/pi-tui": "18.31.0",
56
- "@f5xc-salesdemos/pi-utils": "18.31.0",
51
+ "@f5xc-salesdemos/xcsh-stats": "18.32.0",
52
+ "@f5xc-salesdemos/pi-agent-core": "18.32.0",
53
+ "@f5xc-salesdemos/pi-ai": "18.32.0",
54
+ "@f5xc-salesdemos/pi-natives": "18.32.0",
55
+ "@f5xc-salesdemos/pi-tui": "18.32.0",
56
+ "@f5xc-salesdemos/pi-utils": "18.32.0",
57
57
  "@sinclair/typebox": "^0.34",
58
58
  "@xterm/headless": "^6.0",
59
59
  "ajv": "^8.18",
@@ -78,14 +78,27 @@ interface RawIndex {
78
78
  }
79
79
 
80
80
  const REPO = "f5xc-salesdemos/api-specs-enriched";
81
- const PINNED_TAG = "v2.1.63";
82
81
  const outputPath = path.resolve(import.meta.dir, "../src/internal-urls/api-spec-index.generated.ts");
83
82
  const catalogOutputPath = path.resolve(import.meta.dir, "../src/internal-urls/api-catalog-index.generated.ts");
84
83
 
84
+ async function resolveLatestTag(): Promise<string> {
85
+ const response = await fetch(`https://api.github.com/repos/${REPO}/releases/latest`, {
86
+ headers: { Accept: "application/vnd.github+json" },
87
+ });
88
+ if (!response.ok) {
89
+ throw new Error(`Failed to fetch latest release from ${REPO}: ${response.status} ${response.statusText}`);
90
+ }
91
+ const data = (await response.json()) as { tag_name?: string };
92
+ if (!data.tag_name) {
93
+ throw new Error(`Latest release from ${REPO} has no tag_name`);
94
+ }
95
+ return data.tag_name;
96
+ }
97
+
85
98
  async function downloadFromRelease(): Promise<string> {
86
99
  const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "api-specs-"));
87
100
  downloadedTmpDir = tmpDir;
88
- const tag = process.env.API_SPECS_TAG ?? PINNED_TAG;
101
+ const tag = process.env.API_SPECS_TAG ?? (await resolveLatestTag());
89
102
  const zipName = `f5xc-api-specs-${tag}.zip`;
90
103
  const downloadUrl = `https://github.com/${REPO}/releases/download/${tag}/${zipName}`;
91
104
 
@@ -139,8 +152,8 @@ async function downloadCatalog(specsDir: string): Promise<Record<string, unknown
139
152
  return JSON.parse(fs.readFileSync(catalogPath, "utf-8"));
140
153
  }
141
154
 
142
- const tag = process.env.API_SPECS_TAG ?? PINNED_TAG;
143
- const catalogUrl = `https://github.com/${REPO}/releases/download/${tag}/api-catalog.json`;
155
+ const catalogTag = process.env.API_SPECS_TAG ?? (await resolveLatestTag());
156
+ const catalogUrl = `https://github.com/${REPO}/releases/download/${catalogTag}/api-catalog.json`;
144
157
  console.log(`Downloading API catalog from ${catalogUrl}...`);
145
158
  try {
146
159
  const response = await fetch(catalogUrl, { redirect: "follow" });
@@ -17,17 +17,17 @@ export interface BuildInfo {
17
17
  }
18
18
 
19
19
  export const BUILD_INFO: BuildInfo = {
20
- "version": "18.31.0",
21
- "commit": "a0a4cd1c5d9256ab214c2e5ade08aeecccdb2a48",
22
- "shortCommit": "a0a4cd1",
20
+ "version": "18.32.0",
21
+ "commit": "c5505c8b32a0441554d88d83cded48c25b110135",
22
+ "shortCommit": "c5505c8",
23
23
  "branch": "main",
24
- "tag": "v18.31.0",
25
- "commitDate": "2026-05-01T20:50:25Z",
26
- "buildDate": "2026-05-01T21:15:11.839Z",
24
+ "tag": "v18.32.0",
25
+ "commitDate": "2026-05-02T02:44:42Z",
26
+ "buildDate": "2026-05-02T03:10:54.675Z",
27
27
  "dirty": false,
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/a0a4cd1c5d9256ab214c2e5ade08aeecccdb2a48",
32
- "releaseUrl": "https://github.com/f5xc-salesdemos/xcsh/releases/tag/v18.31.0"
31
+ "commitUrl": "https://github.com/f5xc-salesdemos/xcsh/commit/c5505c8b32a0441554d88d83cded48c25b110135",
32
+ "releaseUrl": "https://github.com/f5xc-salesdemos/xcsh/releases/tag/v18.32.0"
33
33
  };
@@ -18,6 +18,7 @@
18
18
  * - xcsh://api-catalog/{category} - Category operations with curl templates
19
19
  */
20
20
  import * as path from "node:path";
21
+ import { logger } from "@f5xc-salesdemos/pi-utils";
21
22
  import type { ContextStatus } from "../services/f5xc-context";
22
23
  import { type ApiCatalogResolver, createApiCatalogResolver } from "./api-catalog-resolve";
23
24
  import type { ApiCatalogCategorySummary, ApiCatalogIndex } from "./api-catalog-types";
@@ -32,9 +33,9 @@ const ABOUT_ROUTE = "about";
32
33
  const API_SPEC_HOST = "api-spec";
33
34
  const API_CATALOG_HOST = "api-catalog";
34
35
 
35
- const EMPTY_INDEX: ApiSpecIndex = { version: "unknown", timestamp: "", domains: [] };
36
+ const EMPTY_INDEX: ApiSpecIndex = { version: "unavailable", timestamp: "", domains: [] };
36
37
  const EMPTY_CATALOG_INDEX: ApiCatalogIndex = {
37
- version: "unknown",
38
+ version: "unavailable",
38
39
  displayName: "F5 Distributed Cloud",
39
40
  service: "f5xc",
40
41
  categoryCount: 0,
@@ -47,15 +48,26 @@ let _apiSpecCache: { index: ApiSpecIndex; blobs: Record<string, string>; version
47
48
  function loadApiSpecs(): { index: ApiSpecIndex; blobs: Record<string, string>; version: string } {
48
49
  if (_apiSpecCache) return _apiSpecCache;
49
50
  try {
50
- // eslint-disable-next-line @typescript-eslint/no-require-imports
51
- const mod = require("./api-spec-index.generated");
51
+ const mod = require("./api-spec-index.generated") as {
52
+ API_SPEC_INDEX?: ApiSpecIndex;
53
+ API_SPEC_BLOBS?: Record<string, string>;
54
+ API_SPEC_VERSION?: string;
55
+ };
56
+ const index = mod.API_SPEC_INDEX ?? EMPTY_INDEX;
57
+ const version = mod.API_SPEC_VERSION ?? "unknown";
58
+ if (index.domains.length === 0) {
59
+ logger.warn("api-spec index loaded but contains 0 domains");
60
+ }
52
61
  _apiSpecCache = {
53
- index: mod.API_SPEC_INDEX ?? EMPTY_INDEX,
62
+ index,
54
63
  blobs: mod.API_SPEC_BLOBS ?? {},
55
- version: mod.API_SPEC_VERSION ?? "unknown",
64
+ version,
56
65
  };
57
- } catch {
58
- _apiSpecCache = { index: EMPTY_INDEX, blobs: {}, version: "unknown" };
66
+ } catch (err) {
67
+ logger.warn("api-spec index unavailable, embedded specs disabled", {
68
+ error: err instanceof Error ? err.message : String(err),
69
+ });
70
+ _apiSpecCache = { index: EMPTY_INDEX, blobs: {}, version: "unavailable" };
59
71
  }
60
72
  return _apiSpecCache;
61
73
  }
@@ -73,14 +85,25 @@ function loadApiCatalog(): {
73
85
  } {
74
86
  if (_apiCatalogCache) return _apiCatalogCache;
75
87
  try {
76
- // eslint-disable-next-line @typescript-eslint/no-require-imports
77
- const mod = require("./api-catalog-index.generated");
88
+ const mod = require("./api-catalog-index.generated") as {
89
+ API_CATALOG_INDEX?: ApiCatalogIndex;
90
+ API_CATALOG_CATEGORY_SUMMARIES?: readonly ApiCatalogCategorySummary[];
91
+ API_CATALOG_BLOBS?: Record<string, string>;
92
+ };
93
+ const index = mod.API_CATALOG_INDEX ?? EMPTY_CATALOG_INDEX;
94
+ const summaries = mod.API_CATALOG_CATEGORY_SUMMARIES ?? [];
95
+ if (summaries.length === 0) {
96
+ logger.warn("api-catalog index loaded but contains 0 categories");
97
+ }
78
98
  _apiCatalogCache = {
79
- index: mod.API_CATALOG_INDEX ?? EMPTY_CATALOG_INDEX,
80
- summaries: mod.API_CATALOG_CATEGORY_SUMMARIES ?? [],
99
+ index,
100
+ summaries,
81
101
  blobs: mod.API_CATALOG_BLOBS ?? {},
82
102
  };
83
- } catch {
103
+ } catch (err) {
104
+ logger.warn("api-catalog index unavailable, catalog disabled", {
105
+ error: err instanceof Error ? err.message : String(err),
106
+ });
84
107
  _apiCatalogCache = { index: EMPTY_CATALOG_INDEX, summaries: [], blobs: {} };
85
108
  }
86
109
  return _apiCatalogCache;