@f5xc-salesdemos/xcsh 18.35.2 → 18.35.3

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.35.2",
4
+ "version": "18.35.3",
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",
@@ -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.35.2",
52
- "@f5xc-salesdemos/pi-agent-core": "18.35.2",
53
- "@f5xc-salesdemos/pi-ai": "18.35.2",
54
- "@f5xc-salesdemos/pi-natives": "18.35.2",
55
- "@f5xc-salesdemos/pi-tui": "18.35.2",
56
- "@f5xc-salesdemos/pi-utils": "18.35.2",
51
+ "@f5xc-salesdemos/xcsh-stats": "18.35.3",
52
+ "@f5xc-salesdemos/pi-agent-core": "18.35.3",
53
+ "@f5xc-salesdemos/pi-ai": "18.35.3",
54
+ "@f5xc-salesdemos/pi-natives": "18.35.3",
55
+ "@f5xc-salesdemos/pi-tui": "18.35.3",
56
+ "@f5xc-salesdemos/pi-utils": "18.35.3",
57
57
  "@sinclair/typebox": "^0.34",
58
58
  "@xterm/headless": "^6.0",
59
59
  "ajv": "^8.18",
@@ -17,17 +17,17 @@ export interface BuildInfo {
17
17
  }
18
18
 
19
19
  export const BUILD_INFO: BuildInfo = {
20
- "version": "18.35.2",
21
- "commit": "4476717a972f57d501906d71b1377b21e00744df",
22
- "shortCommit": "4476717",
20
+ "version": "18.35.3",
21
+ "commit": "32785b70f062fe1930d72a355fc5d72bedb29128",
22
+ "shortCommit": "32785b7",
23
23
  "branch": "main",
24
- "tag": "v18.35.2",
25
- "commitDate": "2026-05-03T23:47:28Z",
26
- "buildDate": "2026-05-04T00:10:18.411Z",
24
+ "tag": "v18.35.3",
25
+ "commitDate": "2026-05-04T00:13:26Z",
26
+ "buildDate": "2026-05-04T00:32:30.792Z",
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/4476717a972f57d501906d71b1377b21e00744df",
32
- "releaseUrl": "https://github.com/f5xc-salesdemos/xcsh/releases/tag/v18.35.2"
31
+ "commitUrl": "https://github.com/f5xc-salesdemos/xcsh/commit/32785b70f062fe1930d72a355fc5d72bedb29128",
32
+ "releaseUrl": "https://github.com/f5xc-salesdemos/xcsh/releases/tag/v18.35.3"
33
33
  };
@@ -196,13 +196,22 @@ Most tools resolve custom protocol URLs to internal resources (not web URLs):
196
196
 
197
197
  When the user needs to **make an API call** (create, read, update, delete):
198
198
 
199
- 1. `xcsh://api-catalog/?resource={resource_name}` → get endpoint path, method, minimum
200
- payload JSON, required fields, and response summary
199
+ 1. `xcsh://api-catalog/?resource={resource_name}&compact=true` → get endpoint path, method,
200
+ minimum payload JSON, OneOf recommendations, and response summary
201
201
  2. Call `xcsh_api` tool with `method`, `path`, `params` (all `{placeholder}` substitutions), and `payload`
202
202
 
203
+ When the resource type and required parameters are clear, your **first output
204
+ MUST be the catalog tool call** — do not preface with explanation or deliberation.
205
+ If required parameters (e.g., namespace) are ambiguous, ask first.
206
+
203
207
  The `xcsh_api` tool handles authentication, URL construction, and HTTP execution.
204
208
  Never construct curl commands for F5 XC API calls — use `xcsh_api` instead.
205
209
 
210
+ After `xcsh_api` returns a 200 or 201 response, report the result immediately.
211
+ Do not issue a follow-up GET to verify — the response body is the verification.
212
+ Only issue a GET if the user explicitly asks to read current state, or if the
213
+ initial call returned a non-2xx status.
214
+
206
215
  If the resource name is unknown, search first:
207
216
  `xcsh://api-catalog/?search={term}` → find the matching category, then read it.
208
217
 
@@ -7,3 +7,5 @@ Pass all path `{placeholder}` values via `params`, e.g. `{ namespace: "default",
7
7
  Body is sent for all methods except GET when `payload` is provided — including DELETE operations that require a body.
8
8
 
9
9
  Use this tool after reading the API catalog to get the endpoint path and payload structure.
10
+
11
+ API calls to the same F5 XC tenant reuse a single TLS connection — sequential calls are faster than parallel calls. Do not issue multiple xcsh_api calls in the same turn; issue them one at a time.
@@ -25,6 +25,7 @@ export interface XcshApiToolDetails {
25
25
  status: number;
26
26
  url: string;
27
27
  method: string;
28
+ requestId: string;
28
29
  }
29
30
 
30
31
  type XcshApiResult = AgentToolResult<XcshApiToolDetails> & { isError?: boolean };
@@ -35,21 +36,31 @@ export class XcshApiTool implements AgentTool<typeof xcshApiSchema, XcshApiToolD
35
36
  readonly description: string;
36
37
  readonly parameters = xcshApiSchema;
37
38
 
39
+ #apiBase: string;
40
+ #apiToken: string;
41
+
38
42
  constructor(_session: ToolSession) {
39
43
  this.description = prompt.render(xcshApiDescription);
44
+ this.#apiBase = (process.env.F5XC_API_URL ?? "").replace(/\/+$/, "");
45
+ this.#apiToken = process.env.F5XC_API_TOKEN ?? "";
46
+
47
+ if (this.#apiBase && this.#apiToken) {
48
+ fetch(`${this.#apiBase}/api/web/namespaces`, {
49
+ method: "HEAD",
50
+ headers: { Authorization: `APIToken ${this.#apiToken}` },
51
+ }).catch(() => {});
52
+ }
40
53
  }
41
54
 
42
55
  async execute(_toolCallId: string, params: XcshApiParams): Promise<XcshApiResult> {
43
- const apiUrl = process.env.F5XC_API_URL;
44
- if (!apiUrl) {
56
+ if (!this.#apiBase) {
45
57
  return {
46
58
  content: [{ type: "text", text: "Error: F5XC_API_URL environment variable is not set." }],
47
59
  isError: true,
48
60
  };
49
61
  }
50
62
 
51
- const apiToken = process.env.F5XC_API_TOKEN;
52
- if (!apiToken) {
63
+ if (!this.#apiToken) {
53
64
  return {
54
65
  content: [{ type: "text", text: "Error: F5XC_API_TOKEN environment variable is not set." }],
55
66
  isError: true,
@@ -63,13 +74,19 @@ export class XcshApiTool implements AgentTool<typeof xcshApiSchema, XcshApiToolD
63
74
  }
64
75
  }
65
76
 
66
- const url = `${apiUrl.replace(/\/+$/, "")}${resolvedPath}`;
77
+ const url = `${this.#apiBase}${resolvedPath}`;
78
+ const requestId = crypto.randomUUID();
67
79
  const headers: Record<string, string> = {
68
- Authorization: `APIToken ${apiToken}`,
80
+ Authorization: `APIToken ${this.#apiToken}`,
69
81
  Accept: "application/json",
82
+ "X-Request-ID": requestId,
70
83
  };
71
84
 
72
- const init: RequestInit = { method: params.method, headers };
85
+ const init: RequestInit = {
86
+ method: params.method,
87
+ headers,
88
+ signal: AbortSignal.timeout(30_000),
89
+ };
73
90
 
74
91
  if (params.payload && params.method !== "GET") {
75
92
  headers["Content-Type"] = "application/json";
@@ -78,21 +95,12 @@ export class XcshApiTool implements AgentTool<typeof xcshApiSchema, XcshApiToolD
78
95
 
79
96
  try {
80
97
  const response = await fetch(url, init);
81
- const contentType = response.headers.get("content-type") ?? "";
82
- let bodyText: string;
83
-
84
- if (contentType.includes("application/json")) {
85
- const json = await response.json();
86
- bodyText = JSON.stringify(json, null, 2);
87
- } else {
88
- bodyText = await response.text();
89
- }
90
-
98
+ const bodyText = await response.text();
91
99
  const statusLine = `${response.status} ${response.statusText}`;
92
100
 
93
101
  return {
94
102
  content: [{ type: "text", text: `${statusLine}\n\n${bodyText}` }],
95
- details: { status: response.status, url, method: params.method },
103
+ details: { status: response.status, url, method: params.method, requestId },
96
104
  ...(response.status >= 400 ? { isError: true } : {}),
97
105
  };
98
106
  } catch (err) {