@f5xc-salesdemos/xcsh 18.48.0 → 18.48.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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@f5xc-salesdemos/xcsh",
4
- "version": "18.48.0",
4
+ "version": "18.48.2",
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.48.0",
52
- "@f5xc-salesdemos/pi-agent-core": "18.48.0",
53
- "@f5xc-salesdemos/pi-ai": "18.48.0",
54
- "@f5xc-salesdemos/pi-natives": "18.48.0",
55
- "@f5xc-salesdemos/pi-tui": "18.48.0",
56
- "@f5xc-salesdemos/pi-utils": "18.48.0",
51
+ "@f5xc-salesdemos/xcsh-stats": "18.48.2",
52
+ "@f5xc-salesdemos/pi-agent-core": "18.48.2",
53
+ "@f5xc-salesdemos/pi-ai": "18.48.2",
54
+ "@f5xc-salesdemos/pi-natives": "18.48.2",
55
+ "@f5xc-salesdemos/pi-tui": "18.48.2",
56
+ "@f5xc-salesdemos/pi-utils": "18.48.2",
57
57
  "@sinclair/typebox": "^0.34",
58
58
  "@xterm/headless": "^6.0",
59
59
  "ajv": "^8.18",
@@ -143,8 +143,16 @@ function formatConstraints(constraints: Record<string, unknown> | undefined): st
143
143
  if (constraints.maximum != null) parts.push(`max: ${constraints.maximum}`);
144
144
  if (constraints.minItems != null) parts.push(`minItems: ${constraints.minItems}`);
145
145
  if (constraints.maxItems != null) parts.push(`maxItems: ${constraints.maxItems}`);
146
+ if (Array.isArray(constraints.ranges)) {
147
+ const formatted = (constraints.ranges as Array<{ minimum: number; maximum: number }>)
148
+ .map(r => (r.minimum === r.maximum ? `{${r.minimum}}` : `[${r.minimum},${r.maximum}]`))
149
+ .join(" ∪ ");
150
+ parts.push(`ranges: ${formatted}`);
151
+ }
146
152
  if (constraints.format) parts.push(`format: ${constraints.format}`);
147
153
  if (Array.isArray(constraints.enum)) parts.push(`enum: ${constraints.enum.join(", ")}`);
154
+ const meta = constraints.metadata as Record<string, unknown> | undefined;
155
+ if (meta?.note) parts.push(`note: ${String(meta.note)}`);
148
156
  return parts.length > 0 ? parts.join(", ") : "--";
149
157
  }
150
158
 
@@ -17,17 +17,17 @@ export interface BuildInfo {
17
17
  }
18
18
 
19
19
  export const BUILD_INFO: BuildInfo = {
20
- "version": "18.48.0",
21
- "commit": "63d4296be7c178ec26412417373def2bfbd644cb",
22
- "shortCommit": "63d4296",
20
+ "version": "18.48.2",
21
+ "commit": "6e820110b9050a56740269c12837b19b27abc08e",
22
+ "shortCommit": "6e82011",
23
23
  "branch": "main",
24
- "tag": "v18.48.0",
25
- "commitDate": "2026-05-06T13:11:55Z",
26
- "buildDate": "2026-05-06T14:22:27.362Z",
27
- "dirty": true,
24
+ "tag": "v18.48.2",
25
+ "commitDate": "2026-05-06T18:00:08Z",
26
+ "buildDate": "2026-05-06T18:23:30.609Z",
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/63d4296be7c178ec26412417373def2bfbd644cb",
32
- "releaseUrl": "https://github.com/f5xc-salesdemos/xcsh/releases/tag/v18.48.0"
31
+ "commitUrl": "https://github.com/f5xc-salesdemos/xcsh/commit/6e820110b9050a56740269c12837b19b27abc08e",
32
+ "releaseUrl": "https://github.com/f5xc-salesdemos/xcsh/releases/tag/v18.48.2"
33
33
  };
@@ -2,7 +2,7 @@ import { type Component, padding, truncateToWidth, visibleWidth } from "@f5xc-sa
2
2
  import { APP_NAME } from "@f5xc-salesdemos/pi-utils";
3
3
  import { theme } from "../../modes/theme/theme";
4
4
  import { formatStatusIcon } from "../../services/f5xc-context-indicators";
5
- import type { ModelStatus, ServiceStatus, WelcomeProfileStatus } from "./welcome-checks";
5
+ import type { ModelStatus, ServiceStatus } from "./welcome-checks";
6
6
 
7
7
  export interface UpdateStatus {
8
8
  available: boolean;
@@ -15,7 +15,6 @@ export class WelcomeComponent implements Component {
15
15
  private modelStatus: ModelStatus,
16
16
  private services: ServiceStatus[] = [],
17
17
  private updateStatus?: UpdateStatus,
18
- private profileStatus?: WelcomeProfileStatus,
19
18
  ) {}
20
19
  invalidate(): void {}
21
20
  setModelStatus(status: ModelStatus): void {
@@ -27,9 +26,6 @@ export class WelcomeComponent implements Component {
27
26
  setUpdateStatus(status: UpdateStatus | undefined): void {
28
27
  this.updateStatus = status;
29
28
  }
30
- setProfileStatus(status: WelcomeProfileStatus | undefined): void {
31
- this.profileStatus = status;
32
- }
33
29
 
34
30
  render(termWidth: number): string[] {
35
31
  const minLeftCol = 48;
@@ -129,9 +125,6 @@ export class WelcomeComponent implements Component {
129
125
  for (const svc of this.services) {
130
126
  lines.push(this.#renderServiceLine(svc));
131
127
  }
132
- if (this.profileStatus) {
133
- lines.push(" User Profile", ...this.#renderProfileStatus());
134
- }
135
128
  if (this.#showUpdateSection()) {
136
129
  lines.push(this.#renderUpdateLine());
137
130
  }
@@ -155,12 +148,6 @@ export class WelcomeComponent implements Component {
155
148
  lines.push(this.#renderUpdateLine());
156
149
  }
157
150
  }
158
- if (this.profileStatus) {
159
- lines.push(separator);
160
- for (const line of this.#renderProfileStatus()) {
161
- lines.push(line);
162
- }
163
- }
164
151
  lines.push("");
165
152
  return lines;
166
153
  }
@@ -202,25 +189,6 @@ export class WelcomeComponent implements Component {
202
189
  }
203
190
  }
204
191
 
205
- #renderProfileStatus(): string[] {
206
- if (!this.profileStatus) return [];
207
- const { state, name, staleDays } = this.profileStatus;
208
- switch (state) {
209
- case "current":
210
- return [` ${formatStatusIcon("connected")} ${theme.fg("muted", name ?? "profile loaded")}`];
211
- case "stale":
212
- return [
213
- ` ${formatStatusIcon("warning")} ${theme.fg("muted", name ?? "profile")} ${theme.fg("warning", `\u2014 stale${staleDays !== undefined ? ` (${staleDays}d)` : ""}`)}`,
214
- ` ${theme.fg("dim", "Run")} ${theme.fg("contentAccent", "xcsh://user?seed=true")}`,
215
- ];
216
- case "missing":
217
- return [
218
- ` ${formatStatusIcon("warning")} ${theme.fg("warning", "No profile yet")}`,
219
- ` ${theme.fg("dim", "Run")} ${theme.fg("contentAccent", "xcsh://user?seed=true")}`,
220
- ];
221
- }
222
- }
223
-
224
192
  #f5ColorLine(line: string): string {
225
193
  const red = "\x1b[38;5;160m";
226
194
  const white = "\x1b[1;37m";
@@ -57,7 +57,6 @@ import {
57
57
  checkGcloudStatus,
58
58
  checkGitHubStatus,
59
59
  checkGitLabStatus,
60
- checkProfileStatus,
61
60
  checkSalesforceStatus,
62
61
  mapAwsStatus,
63
62
  mapAzureStatus,
@@ -325,32 +324,21 @@ export class InteractiveMode implements InteractiveModeContext {
325
324
  );
326
325
 
327
326
  // Run blocking welcome screen status checks in parallel
328
- const [
329
- welcomeResult,
330
- gitlabStatus,
331
- salesforceStatus,
332
- githubStatus,
333
- azureStatus,
334
- awsStatus,
335
- gcloudStatus,
336
- profileStatus,
337
- ] = await Promise.all([
338
- logger.time("InteractiveMode.init:welcomeChecks", () =>
339
- runWelcomeChecks(this.session.model, this.session.modelRegistry.authStorage),
340
- ),
341
- checkGitLabStatus(getProjectDir()).catch(() => undefined),
342
- checkSalesforceStatus(getProjectDir()).catch(() => undefined),
343
- checkGitHubStatus().catch(() => undefined),
344
- checkAzureStatus().catch(() => undefined),
345
- checkAwsStatus().catch(() => undefined),
346
- checkGcloudStatus().catch(() => undefined),
347
- checkProfileStatus().catch(() => undefined),
348
- ]);
349
-
350
- // Refresh stale or missing profile in background — fire and forget
351
- if (profileStatus?.state === "stale" || profileStatus?.state === "missing") {
352
- seedProfile().catch(err => logger.warn("Background profile refresh failed", { error: String(err) }));
353
- }
327
+ const [welcomeResult, gitlabStatus, salesforceStatus, githubStatus, azureStatus, awsStatus, gcloudStatus] =
328
+ await Promise.all([
329
+ logger.time("InteractiveMode.init:welcomeChecks", () =>
330
+ runWelcomeChecks(this.session.model, this.session.modelRegistry.authStorage),
331
+ ),
332
+ checkGitLabStatus(getProjectDir()).catch(() => undefined),
333
+ checkSalesforceStatus(getProjectDir()).catch(() => undefined),
334
+ checkGitHubStatus().catch(() => undefined),
335
+ checkAzureStatus().catch(() => undefined),
336
+ checkAwsStatus().catch(() => undefined),
337
+ checkGcloudStatus().catch(() => undefined),
338
+ ]);
339
+
340
+ // Refresh user profile in background — fire and forget
341
+ seedProfile().catch(err => logger.warn("Background profile refresh failed", { error: String(err) }));
354
342
  const startupQuiet = settings.get("startup.quiet");
355
343
  this.#welcomeComponent = undefined;
356
344
 
@@ -379,7 +367,6 @@ export class InteractiveMode implements InteractiveModeContext {
379
367
  welcomeResult.model,
380
368
  services,
381
369
  this.#initialUpdateStatus,
382
- profileStatus,
383
370
  );
384
371
 
385
372
  // Setup UI layout
@@ -152,13 +152,8 @@ Available F5 XC documentation topics: {{knowledgeTopics}}.
152
152
  {{#if userProfile}}
153
153
  ## Primary Human
154
154
 
155
- {{userProfile.name}} ({{userProfile.role}}, {{userProfile.org}}).
156
- Full profile at `xcsh://user`. **MUST** read when:
157
- - Addressing the user by name or drafting communications from/to them
158
- - A tool call needs personal identifiers (Salesforce user ID, GitHub username, email, phone)
159
- - User asks about themselves ("my email", "who is my manager", "where am I from")
160
- - Answering relationship/identity questions ("who is your human", "who do you work with")
161
- **SHOULD NOT** read for routine technical work, code changes, or product questions.
155
+ {{userProfile.name}}, {{userProfile.role}}, {{userProfile.org}}.
156
+ `xcsh://user`. **MUST** read when: identity, communications, personal identifiers. **SHOULD NOT** for routine technical work.
162
157
  {{/if}}
163
158
 
164
159
  {{#if contextFiles.length}}