@robinmordasiewicz/f5xc-xcsh 1.0.90-2601022220 → 1.0.91-2601022325

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/completions/_xcsh CHANGED
@@ -27,6 +27,7 @@ _xcsh() {
27
27
  local -a domains builtins
28
28
  domains=(
29
29
  'admin_console_and_ui:Static UI components and console assets.'
30
+ 'ai_services:AI assistant queries and feedback collection.'
30
31
  'api:Interface definitions, schema validation, and grouping.'
31
32
  'authentication:Authentication API'
32
33
  'bigip:iRules, data groups, and APM integration.'
@@ -70,6 +71,9 @@ _xcsh() {
70
71
  'console-ui:Alias for admin_console_and_ui'
71
72
  'ui-assets:Alias for admin_console_and_ui'
72
73
  'static-components:Alias for admin_console_and_ui'
74
+ 'ai:Alias for ai_services'
75
+ 'genai:Alias for ai_services'
76
+ 'assistant:Alias for ai_services'
73
77
  'apisec:Alias for api'
74
78
  'api-discovery:Alias for api'
75
79
  'authn:Alias for authentication'
@@ -176,6 +180,7 @@ _xcsh() {
176
180
  'exit:Exit the shell'
177
181
  'clear:Clear the screen'
178
182
  'history:Show command history'
183
+ 'refresh:Refresh git status in statusline'
179
184
  'context:Show current navigation context'
180
185
  'ctx:Show current navigation context'
181
186
  )
@@ -196,7 +201,7 @@ _xcsh() {
196
201
  (login)
197
202
  _values 'command' 'banner:Display xcsh banner with logo' 'profile:Manage saved connection profiles' 'context:Manage default namespace context'
198
203
  ;;
199
- (help|quit|exit|clear|history|context|ctx)
204
+ (help|quit|exit|clear|history|refresh|context|ctx)
200
205
  ;;
201
206
  (*)
202
207
  local -a actions
@@ -6,9 +6,9 @@ _xcsh_completions() {
6
6
  local cur prev words cword
7
7
  _init_completion || return
8
8
 
9
- local commands="admin_console_and_ui api authentication bigip billing_and_usage blindfold bot_and_threat_defense cdn ce_management certificates cloud_infrastructure cloudstatus completion container_services data_and_privacy_security data_intelligence ddos dns generative_ai login managed_kubernetes marketplace network network_security nginx_one object_storage observability rate_limiting secops_and_incident_response service_mesh shape sites statistics support telemetry_and_insights tenant_and_identity threat_campaign users virtual vpm_and_node_management waf console-ui ui-assets static-components apisec api-discovery authn oidc sso f5-bigip irule ltm billing-usage quotas usage-tracking bf encrypt secrets threat-defense tpm shape-bot cache content ce-mgmt edge-management ce-lifecycle cert certs ssl tls cloud infra provider vk8s containers workloads data-privacy pii sensitive-data lma di intelligence insights dos ddos-protect dns-zone zones mk8s appstack k8s-mgmt market addons extensions net routing bgp netsec nfw nginx nms nginx-plus storage s3 buckets obs monitoring synth ratelimit throttle policer secops incident-response mitigation mesh svc-mesh shape-sec safeap site deployment stats metrics logs tickets help-desk telemetry ti tenant-identity idm user-settings threats campaigns threat-intel user accounts iam lb loadbalancer vhost vpm nodes node-mgmt firewall appfw help quit exit clear history"
9
+ local commands="admin_console_and_ui ai_services api authentication bigip billing_and_usage blindfold bot_and_threat_defense cdn ce_management certificates cloud_infrastructure cloudstatus completion container_services data_and_privacy_security data_intelligence ddos dns generative_ai login managed_kubernetes marketplace network network_security nginx_one object_storage observability rate_limiting secops_and_incident_response service_mesh shape sites statistics support telemetry_and_insights tenant_and_identity threat_campaign users virtual vpm_and_node_management waf console-ui ui-assets static-components ai genai assistant apisec api-discovery authn oidc sso f5-bigip irule ltm billing-usage quotas usage-tracking bf encrypt secrets threat-defense tpm shape-bot cache content ce-mgmt edge-management ce-lifecycle cert certs ssl tls cloud infra provider vk8s containers workloads data-privacy pii sensitive-data lma di intelligence insights dos ddos-protect dns-zone zones mk8s appstack k8s-mgmt market addons extensions net routing bgp netsec nfw nginx nms nginx-plus storage s3 buckets obs monitoring synth ratelimit throttle policer secops incident-response mitigation mesh svc-mesh shape-sec safeap site deployment stats metrics logs tickets help-desk telemetry ti tenant-identity idm user-settings threats campaigns threat-intel user accounts iam lb loadbalancer vhost vpm nodes node-mgmt firewall appfw help quit exit clear history refresh"
10
10
  local actions="list get create delete replace apply status patch add-labels remove-labels"
11
- local builtins="help quit exit clear history context ctx"
11
+ local builtins="help quit exit clear history context ctx refresh"
12
12
  local global_flags="--help -h --version -v --no-color --output -o --namespace -ns --spec"
13
13
 
14
14
  # Handle completion based on position
@@ -54,7 +54,7 @@ _xcsh_completions() {
54
54
  COMPREPLY=($(compgen -W "show set list" -- "${cur}"))
55
55
  return 0
56
56
  ;;
57
- help | quit | exit | clear | history | context | ctx)
57
+ help | quit | exit | clear | history | refresh | context | ctx)
58
58
  return 0
59
59
  ;;
60
60
  *)
@@ -18,11 +18,13 @@ complete -c xcsh -n "__fish_use_subcommand" -a "quit" -d 'Exit the shell'
18
18
  complete -c xcsh -n "__fish_use_subcommand" -a "exit" -d 'Exit the shell'
19
19
  complete -c xcsh -n "__fish_use_subcommand" -a "clear" -d 'Clear the screen'
20
20
  complete -c xcsh -n "__fish_use_subcommand" -a "history" -d 'Show command history'
21
+ complete -c xcsh -n "__fish_use_subcommand" -a "refresh" -d 'Refresh git status in statusline'
21
22
  complete -c xcsh -n "__fish_use_subcommand" -a "context" -d 'Show current navigation context'
22
23
  complete -c xcsh -n "__fish_use_subcommand" -a "ctx" -d 'Show current navigation context'
23
24
 
24
25
  # Domain completions
25
26
  complete -c xcsh -n "__fish_use_subcommand" -a "admin_console_and_ui" -d 'Static UI components and console assets.'
27
+ complete -c xcsh -n "__fish_use_subcommand" -a "ai_services" -d 'AI assistant queries and feedback collection.'
26
28
  complete -c xcsh -n "__fish_use_subcommand" -a "api" -d 'Interface definitions, schema validation, and grouping.'
27
29
  complete -c xcsh -n "__fish_use_subcommand" -a "authentication" -d 'Authentication API'
28
30
  complete -c xcsh -n "__fish_use_subcommand" -a "bigip" -d 'iRules, data groups, and APM integration.'
@@ -68,6 +70,9 @@ complete -c xcsh -n "__fish_use_subcommand" -a "waf" -d 'Request inspection, att
68
70
  complete -c xcsh -n "__fish_use_subcommand" -a "console-ui" -d 'Alias for admin_console_and_ui'
69
71
  complete -c xcsh -n "__fish_use_subcommand" -a "ui-assets" -d 'Alias for admin_console_and_ui'
70
72
  complete -c xcsh -n "__fish_use_subcommand" -a "static-components" -d 'Alias for admin_console_and_ui'
73
+ complete -c xcsh -n "__fish_use_subcommand" -a "ai" -d 'Alias for ai_services'
74
+ complete -c xcsh -n "__fish_use_subcommand" -a "genai" -d 'Alias for ai_services'
75
+ complete -c xcsh -n "__fish_use_subcommand" -a "assistant" -d 'Alias for ai_services'
71
76
  complete -c xcsh -n "__fish_use_subcommand" -a "apisec" -d 'Alias for api'
72
77
  complete -c xcsh -n "__fish_use_subcommand" -a "api-discovery" -d 'Alias for api'
73
78
  complete -c xcsh -n "__fish_use_subcommand" -a "authn" -d 'Alias for authentication'
@@ -206,6 +211,16 @@ complete -c xcsh -n "__fish_seen_subcommand_from admin_console_and_ui" -a "statu
206
211
  complete -c xcsh -n "__fish_seen_subcommand_from admin_console_and_ui" -a "patch" -d 'Patch a resource'
207
212
  complete -c xcsh -n "__fish_seen_subcommand_from admin_console_and_ui" -a "add-labels" -d 'Add labels to a resource'
208
213
  complete -c xcsh -n "__fish_seen_subcommand_from admin_console_and_ui" -a "remove-labels" -d 'Remove labels from a resource'
214
+ complete -c xcsh -n "__fish_seen_subcommand_from ai_services" -a "list" -d 'List resources'
215
+ complete -c xcsh -n "__fish_seen_subcommand_from ai_services" -a "get" -d 'Get a specific resource'
216
+ complete -c xcsh -n "__fish_seen_subcommand_from ai_services" -a "create" -d 'Create a new resource'
217
+ complete -c xcsh -n "__fish_seen_subcommand_from ai_services" -a "delete" -d 'Delete a resource'
218
+ complete -c xcsh -n "__fish_seen_subcommand_from ai_services" -a "replace" -d 'Replace a resource'
219
+ complete -c xcsh -n "__fish_seen_subcommand_from ai_services" -a "apply" -d 'Apply configuration from file'
220
+ complete -c xcsh -n "__fish_seen_subcommand_from ai_services" -a "status" -d 'Get resource status'
221
+ complete -c xcsh -n "__fish_seen_subcommand_from ai_services" -a "patch" -d 'Patch a resource'
222
+ complete -c xcsh -n "__fish_seen_subcommand_from ai_services" -a "add-labels" -d 'Add labels to a resource'
223
+ complete -c xcsh -n "__fish_seen_subcommand_from ai_services" -a "remove-labels" -d 'Remove labels from a resource'
209
224
  complete -c xcsh -n "__fish_seen_subcommand_from api" -a "list" -d 'List resources'
210
225
  complete -c xcsh -n "__fish_seen_subcommand_from api" -a "get" -d 'Get a specific resource'
211
226
  complete -c xcsh -n "__fish_seen_subcommand_from api" -a "create" -d 'Create a new resource'
package/dist/index.js CHANGED
@@ -1372,7 +1372,7 @@ var require_react_development = __commonJS({
1372
1372
  }
1373
1373
  return dispatcher.useContext(Context);
1374
1374
  }
1375
- function useState8(initialState) {
1375
+ function useState9(initialState) {
1376
1376
  var dispatcher = resolveDispatcher();
1377
1377
  return dispatcher.useState(initialState);
1378
1378
  }
@@ -1380,11 +1380,11 @@ var require_react_development = __commonJS({
1380
1380
  var dispatcher = resolveDispatcher();
1381
1381
  return dispatcher.useReducer(reducer, initialArg, init);
1382
1382
  }
1383
- function useRef3(initialValue) {
1383
+ function useRef4(initialValue) {
1384
1384
  var dispatcher = resolveDispatcher();
1385
1385
  return dispatcher.useRef(initialValue);
1386
1386
  }
1387
- function useEffect6(create2, deps) {
1387
+ function useEffect7(create2, deps) {
1388
1388
  var dispatcher = resolveDispatcher();
1389
1389
  return dispatcher.useEffect(create2, deps);
1390
1390
  }
@@ -1396,7 +1396,7 @@ var require_react_development = __commonJS({
1396
1396
  var dispatcher = resolveDispatcher();
1397
1397
  return dispatcher.useLayoutEffect(create2, deps);
1398
1398
  }
1399
- function useCallback6(callback, deps) {
1399
+ function useCallback7(callback, deps) {
1400
1400
  var dispatcher = resolveDispatcher();
1401
1401
  return dispatcher.useCallback(callback, deps);
1402
1402
  }
@@ -2163,19 +2163,19 @@ var require_react_development = __commonJS({
2163
2163
  exports.memo = memo;
2164
2164
  exports.startTransition = startTransition;
2165
2165
  exports.unstable_act = act;
2166
- exports.useCallback = useCallback6;
2166
+ exports.useCallback = useCallback7;
2167
2167
  exports.useContext = useContext7;
2168
2168
  exports.useDebugValue = useDebugValue;
2169
2169
  exports.useDeferredValue = useDeferredValue;
2170
- exports.useEffect = useEffect6;
2170
+ exports.useEffect = useEffect7;
2171
2171
  exports.useId = useId;
2172
2172
  exports.useImperativeHandle = useImperativeHandle;
2173
2173
  exports.useInsertionEffect = useInsertionEffect;
2174
2174
  exports.useLayoutEffect = useLayoutEffect2;
2175
2175
  exports.useMemo = useMemo3;
2176
2176
  exports.useReducer = useReducer;
2177
- exports.useRef = useRef3;
2178
- exports.useState = useState8;
2177
+ exports.useRef = useRef4;
2178
+ exports.useState = useState9;
2179
2179
  exports.useSyncExternalStore = useSyncExternalStore;
2180
2180
  exports.useTransition = useTransition;
2181
2181
  exports.version = ReactVersion;
@@ -44144,6 +44144,47 @@ var generatedDomains = /* @__PURE__ */ new Map([
44144
44144
  }
44145
44145
  ]
44146
44146
  }],
44147
+ ["ai_services", {
44148
+ name: "ai_services",
44149
+ displayName: "Ai Services",
44150
+ description: "Query handling through inference routing with production and test modes. Positive and negative quality markers with detailed categorization capture assistant performance. Streaming connections support authenticated access, subscription lifecycles, and feature flags. IP provisioning services allocate infrastructure resources for model workloads across distributed systems.",
44151
+ descriptionShort: "AI assistant queries and feedback collection.",
44152
+ descriptionMedium: "Natural language processing with quality signals and anomaly monitoring. Token authentication for data stream subscriptions.",
44153
+ aliases: ["ai", "genai", "assistant"],
44154
+ complexity: "simple",
44155
+ isPreview: true,
44156
+ requiresTier: "Advanced",
44157
+ category: "AI",
44158
+ useCases: ["Access AI-powered features", "Configure AI assistant policies", "Enable flow anomaly detection", "Manage AI data collection"],
44159
+ relatedDomains: [],
44160
+ icon: "\u{1F916}",
44161
+ logoSvg: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%236366F1'%3E%3Cpath d='M21 10.12h-6.78l2.74-2.82c-2.73-2.7-7.15-2.8-9.88-.1-2.73 2.71-2.73 7.08 0 9.79s7.15 2.71 9.88 0C18.32 15.65 19 14.08 19 12.1h2c0 1.98-.88 4.55-2.64 6.29-3.51 3.48-9.21 3.48-12.72 0-3.5-3.47-3.53-9.11-.02-12.58s9.14-3.47 12.65 0L21 3v7.12zM12.5 8v4.25l3.5 2.08-.72 1.21L11 13V8h1.5z'/%3E%3C/svg%3E",
44162
+ uiCategory: "AI & Automation",
44163
+ primaryResources: [
44164
+ {
44165
+ name: "ai_policy",
44166
+ description: "AI policy for generative AI traffic control",
44167
+ descriptionShort: "AI policy",
44168
+ tier: "Advanced",
44169
+ icon: "\u{1F916}",
44170
+ category: "Security",
44171
+ supportsLogs: true,
44172
+ supportsMetrics: true
44173
+ },
44174
+ {
44175
+ name: "ai_gateway",
44176
+ description: "AI gateway for LLM API management",
44177
+ descriptionShort: "AI gateway",
44178
+ tier: "Advanced",
44179
+ icon: "\u{1F680}",
44180
+ category: "API Management",
44181
+ supportsLogs: true,
44182
+ supportsMetrics: true,
44183
+ dependencies: { optional: ["ai_policy"] },
44184
+ relationshipHints: ["ai_policy: Policy for AI traffic control"]
44185
+ }
44186
+ ]
44187
+ }],
44147
44188
  ["api", {
44148
44189
  name: "api",
44149
44190
  displayName: "Api",
@@ -44951,47 +44992,6 @@ var generatedDomains = /* @__PURE__ */ new Map([
44951
44992
  }
44952
44993
  ]
44953
44994
  }],
44954
- ["generative_ai", {
44955
- name: "generative_ai",
44956
- displayName: "Generative Ai",
44957
- description: "Query handling through inference routing with production and test modes. Positive and negative quality markers with detailed categorization capture assistant performance. Streaming connections support authenticated access, subscription lifecycles, and feature flags. IP provisioning services allocate infrastructure resources for model workloads across distributed systems.",
44958
- descriptionShort: "AI assistant queries and feedback collection.",
44959
- descriptionMedium: "Natural language processing with quality signals and anomaly monitoring. Token authentication for data stream subscriptions.",
44960
- aliases: ["ai", "genai", "assistant"],
44961
- complexity: "simple",
44962
- isPreview: true,
44963
- requiresTier: "Advanced",
44964
- category: "AI",
44965
- useCases: ["Access AI-powered features", "Configure AI assistant policies", "Enable flow anomaly detection", "Manage AI data collection"],
44966
- relatedDomains: [],
44967
- icon: "\u{1F916}",
44968
- logoSvg: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%236366F1'%3E%3Cpath d='M21 10.12h-6.78l2.74-2.82c-2.73-2.7-7.15-2.8-9.88-.1-2.73 2.71-2.73 7.08 0 9.79s7.15 2.71 9.88 0C18.32 15.65 19 14.08 19 12.1h2c0 1.98-.88 4.55-2.64 6.29-3.51 3.48-9.21 3.48-12.72 0-3.5-3.47-3.53-9.11-.02-12.58s9.14-3.47 12.65 0L21 3v7.12zM12.5 8v4.25l3.5 2.08-.72 1.21L11 13V8h1.5z'/%3E%3C/svg%3E",
44969
- uiCategory: "AI & Automation",
44970
- primaryResources: [
44971
- {
44972
- name: "ai_policy",
44973
- description: "AI policy for generative AI traffic control",
44974
- descriptionShort: "AI policy",
44975
- tier: "Advanced",
44976
- icon: "\u{1F916}",
44977
- category: "Security",
44978
- supportsLogs: true,
44979
- supportsMetrics: true
44980
- },
44981
- {
44982
- name: "ai_gateway",
44983
- description: "AI gateway for LLM API management",
44984
- descriptionShort: "AI gateway",
44985
- tier: "Advanced",
44986
- icon: "\u{1F680}",
44987
- category: "API Management",
44988
- supportsLogs: true,
44989
- supportsMetrics: true,
44990
- dependencies: { optional: ["ai_policy"] },
44991
- relationshipHints: ["ai_policy: Policy for AI traffic control"]
44992
- }
44993
- ]
44994
- }],
44995
44995
  ["managed_kubernetes", {
44996
44996
  name: "managed_kubernetes",
44997
44997
  displayName: "Managed Kubernetes",
@@ -46630,8 +46630,8 @@ function getLogoModeFromEnv(envPrefix) {
46630
46630
  var CLI_NAME = "xcsh";
46631
46631
  var CLI_FULL_NAME = "F5 Distributed Cloud Shell";
46632
46632
  function getVersion() {
46633
- if ("v1.0.90-2601022220") {
46634
- return "v1.0.90-2601022220";
46633
+ if ("v1.0.91-2601022325") {
46634
+ return "v1.0.91-2601022325";
46635
46635
  }
46636
46636
  if (process.env.XCSH_VERSION) {
46637
46637
  return process.env.XCSH_VERSION;
@@ -47025,9 +47025,9 @@ var APIError = class extends Error {
47025
47025
 
47026
47026
  // src/api/client.ts
47027
47027
  var DEFAULT_RETRY_CONFIG = {
47028
- maxRetries: 3,
47029
- initialDelayMs: 1e3,
47030
- maxDelayMs: 1e4,
47028
+ maxRetries: 2,
47029
+ initialDelayMs: 500,
47030
+ maxDelayMs: 5e3,
47031
47031
  backoffMultiplier: 2,
47032
47032
  jitter: true
47033
47033
  };
@@ -47069,7 +47069,7 @@ var APIClient = class {
47069
47069
  constructor(config) {
47070
47070
  this.serverUrl = config.serverUrl.replace(/\/+$/, "");
47071
47071
  this.apiToken = config.apiToken ?? "";
47072
- this.timeout = config.timeout ?? 3e4;
47072
+ this.timeout = config.timeout ?? 15e3;
47073
47073
  this.debug = config.debug ?? false;
47074
47074
  this.retryConfig = {
47075
47075
  ...DEFAULT_RETRY_CONFIG,
@@ -47176,13 +47176,20 @@ var APIClient = class {
47176
47176
  }
47177
47177
  /**
47178
47178
  * Check if an error is retryable
47179
+ *
47180
+ * Permanent network errors (connection refused, DNS not found) are NOT retried
47181
+ * since retrying won't help if the server is unreachable.
47179
47182
  */
47180
47183
  isRetryableError(error) {
47181
47184
  if (error instanceof APIError) {
47182
47185
  return RETRYABLE_STATUS_CODES.has(error.statusCode);
47183
47186
  }
47184
47187
  if (error instanceof Error) {
47185
- return error.name === "AbortError" || error.message.includes("fetch failed") || error.message.includes("network") || error.message.includes("ECONNREFUSED") || error.message.includes("ENOTFOUND") || error.message.includes("ETIMEDOUT");
47188
+ const message = error.message.toLowerCase();
47189
+ if (message.includes("econnrefused") || message.includes("enotfound") || message.includes("ehostunreach") || message.includes("enetunreach")) {
47190
+ return false;
47191
+ }
47192
+ return error.name === "AbortError" || message.includes("etimedout") || message.includes("econnreset") || message.includes("socket hang up");
47186
47193
  }
47187
47194
  return false;
47188
47195
  }
@@ -142398,7 +142405,16 @@ function formatRootHelp() {
142398
142405
  " domains List all available domains",
142399
142406
  " clear Clear the screen",
142400
142407
  " history Show command history",
142408
+ " refresh Refresh git status in statusline",
142401
142409
  " quit, exit Exit the shell",
142410
+ "",
142411
+ "KEYBOARD SHORTCUTS",
142412
+ " Ctrl+C (x2) Exit the shell",
142413
+ " Ctrl+D Exit immediately",
142414
+ " Ctrl+G Refresh git status",
142415
+ " Tab Trigger completion",
142416
+ " Up/Down Navigate history or suggestions",
142417
+ " Escape Cancel suggestions",
142402
142418
  ""
142403
142419
  ];
142404
142420
  }
@@ -144125,7 +144141,7 @@ function buildPlainPrompt(session) {
144125
144141
  }
144126
144142
 
144127
144143
  // src/repl/App.tsx
144128
- var import_react28 = __toESM(require_react(), 1);
144144
+ var import_react29 = __toESM(require_react(), 1);
144129
144145
 
144130
144146
  // src/repl/components/InputBox.tsx
144131
144147
  var import_react23 = __toESM(require_react(), 1);
@@ -146844,9 +146860,9 @@ _xcsh_completions() {
146844
146860
  local cur prev words cword
146845
146861
  _init_completion || return
146846
146862
 
146847
- local commands="${domainNames} ${allAliases.join(" ")} help quit exit clear history"
146863
+ local commands="${domainNames} ${allAliases.join(" ")} help quit exit clear history refresh"
146848
146864
  local actions="${actions}"
146849
- local builtins="help quit exit clear history context ctx"
146865
+ local builtins="help quit exit clear history context ctx refresh"
146850
146866
  local global_flags="--help -h --version -v --no-color --output -o --namespace -ns --spec"
146851
146867
 
146852
146868
  # Handle completion based on position
@@ -146865,7 +146881,7 @@ _xcsh_completions() {
146865
146881
  local domain="\${words[1]}"
146866
146882
  case "\${domain}" in
146867
146883
  ${customDomainCompletions.join("\n")}
146868
- help | quit | exit | clear | history | context | ctx)
146884
+ help | quit | exit | clear | history | refresh | context | ctx)
146869
146885
  return 0
146870
146886
  ;;
146871
146887
  *)
@@ -146954,6 +146970,7 @@ _xcsh() {
146954
146970
  'exit:Exit the shell'
146955
146971
  'clear:Clear the screen'
146956
146972
  'history:Show command history'
146973
+ 'refresh:Refresh git status in statusline'
146957
146974
  'context:Show current navigation context'
146958
146975
  'ctx:Show current navigation context'
146959
146976
  )
@@ -146963,7 +146980,7 @@ _xcsh() {
146963
146980
  (action)
146964
146981
  case \${line[1]} in
146965
146982
  ${customDomainCompletions.join("\n")}
146966
- (help|quit|exit|clear|history|context|ctx)
146983
+ (help|quit|exit|clear|history|refresh|context|ctx)
146967
146984
  ;;
146968
146985
  (*)
146969
146986
  local -a actions
@@ -147055,6 +147072,7 @@ complete -c xcsh -n "__fish_use_subcommand" -a "quit" -d 'Exit the shell'
147055
147072
  complete -c xcsh -n "__fish_use_subcommand" -a "exit" -d 'Exit the shell'
147056
147073
  complete -c xcsh -n "__fish_use_subcommand" -a "clear" -d 'Clear the screen'
147057
147074
  complete -c xcsh -n "__fish_use_subcommand" -a "history" -d 'Show command history'
147075
+ complete -c xcsh -n "__fish_use_subcommand" -a "refresh" -d 'Refresh git status in statusline'
147058
147076
  complete -c xcsh -n "__fish_use_subcommand" -a "context" -d 'Show current navigation context'
147059
147077
  complete -c xcsh -n "__fish_use_subcommand" -a "ctx" -d 'Show current navigation context'
147060
147078
 
@@ -149560,6 +149578,49 @@ function useCompletion(options) {
149560
149578
  };
149561
149579
  }
149562
149580
 
149581
+ // src/repl/hooks/useGitStatus.ts
149582
+ var import_react28 = __toESM(require_react(), 1);
149583
+ var DEFAULT_POLL_INTERVAL_MS = 3e4;
149584
+ var MIN_POLL_INTERVAL_MS = 5e3;
149585
+ function getPollInterval() {
149586
+ const envValue = process.env.XCSH_GIT_POLL_INTERVAL;
149587
+ if (envValue === void 0) return DEFAULT_POLL_INTERVAL_MS;
149588
+ if (envValue === "0") return 0;
149589
+ const seconds = parseInt(envValue, 10);
149590
+ if (isNaN(seconds) || seconds <= 0) return DEFAULT_POLL_INTERVAL_MS;
149591
+ return Math.max(seconds * 1e3, MIN_POLL_INTERVAL_MS);
149592
+ }
149593
+ function useGitStatus(options = {}) {
149594
+ const { enabled = true } = options;
149595
+ const pollIntervalMs = options.pollIntervalMs ?? getPollInterval();
149596
+ const [gitInfo, setGitInfo] = (0, import_react28.useState)(void 0);
149597
+ const [lastRefresh, setLastRefresh] = (0, import_react28.useState)(0);
149598
+ const intervalRef = (0, import_react28.useRef)(null);
149599
+ const refresh = (0, import_react28.useCallback)(() => {
149600
+ const info = getGitInfo();
149601
+ setGitInfo(info);
149602
+ setLastRefresh(Date.now());
149603
+ }, []);
149604
+ (0, import_react28.useEffect)(() => {
149605
+ if (enabled) {
149606
+ refresh();
149607
+ }
149608
+ }, [enabled, refresh]);
149609
+ (0, import_react28.useEffect)(() => {
149610
+ if (!enabled || pollIntervalMs === 0) {
149611
+ return;
149612
+ }
149613
+ intervalRef.current = setInterval(refresh, pollIntervalMs);
149614
+ return () => {
149615
+ if (intervalRef.current) {
149616
+ clearInterval(intervalRef.current);
149617
+ intervalRef.current = null;
149618
+ }
149619
+ };
149620
+ }, [enabled, pollIntervalMs, refresh]);
149621
+ return { gitInfo, refresh, lastRefresh };
149622
+ }
149623
+
149563
149624
  // src/validation/namespace.ts
149564
149625
  function validateNamespaceScope(domain, action, currentNamespace, resourceType) {
149565
149626
  const opInfo = getOperationDescription(domain, action, resourceType);
@@ -149684,7 +149745,8 @@ var BUILTIN_COMMANDS = /* @__PURE__ */ new Set([
149684
149745
  "history",
149685
149746
  "version",
149686
149747
  "domains",
149687
- "whoami"
149748
+ "whoami",
149749
+ "refresh"
149688
149750
  ]);
149689
149751
  function parseCommand(input) {
149690
149752
  const trimmed = input.trim();
@@ -149947,6 +150009,15 @@ function executeBuiltin(cmd, session, ctx) {
149947
150009
  contextChanged: false
149948
150010
  };
149949
150011
  }
150012
+ if (command === "refresh") {
150013
+ return {
150014
+ output: ["Git status refreshed"],
150015
+ shouldExit: false,
150016
+ shouldClear: false,
150017
+ contextChanged: false,
150018
+ refreshGit: true
150019
+ };
150020
+ }
149950
150021
  return {
149951
150022
  output: [`Unknown command: ${cmd.raw}`],
149952
150023
  shouldExit: false,
@@ -150632,7 +150703,8 @@ function getBuiltinDescription(cmd) {
150632
150703
  ["ctx", "Show current context"],
150633
150704
  ["history", "Show command history"],
150634
150705
  ["version", "Show version info"],
150635
- ["domains", "List available domains"]
150706
+ ["domains", "List available domains"],
150707
+ ["refresh", "Refresh git status"]
150636
150708
  ]);
150637
150709
  return descriptions.get(cmd) ?? "Built-in command";
150638
150710
  }
@@ -150658,11 +150730,11 @@ function toUISuggestions(suggestions) {
150658
150730
  function App2({ initialSession } = {}) {
150659
150731
  const { exit } = use_app_default();
150660
150732
  const { stdout } = use_stdout_default();
150661
- const [session] = (0, import_react28.useState)(() => initialSession ?? new REPLSession());
150662
- const [isInitialized, setIsInitialized] = (0, import_react28.useState)(!!initialSession);
150663
- const [input, setInputState] = (0, import_react28.useState)("");
150664
- const inputRef = (0, import_react28.useRef)("");
150665
- const setInput = (0, import_react28.useCallback)(
150733
+ const [session] = (0, import_react29.useState)(() => initialSession ?? new REPLSession());
150734
+ const [isInitialized, setIsInitialized] = (0, import_react29.useState)(!!initialSession);
150735
+ const [input, setInputState] = (0, import_react29.useState)("");
150736
+ const inputRef = (0, import_react29.useRef)("");
150737
+ const setInput = (0, import_react29.useCallback)(
150666
150738
  (value) => {
150667
150739
  setInputState((prev) => {
150668
150740
  const newValue = typeof value === "function" ? value(prev) : value;
@@ -150672,19 +150744,18 @@ function App2({ initialSession } = {}) {
150672
150744
  },
150673
150745
  []
150674
150746
  );
150675
- const [outputItems, setOutputItems] = (0, import_react28.useState)([]);
150676
- const outputIdRef = (0, import_react28.useRef)(0);
150677
- const [prompt, setPrompt] = (0, import_react28.useState)("> ");
150678
- const [width, setWidth] = (0, import_react28.useState)(stdout?.columns ?? 80);
150679
- const [gitInfo, setGitInfo] = (0, import_react28.useState)(void 0);
150680
- const [statusHint, setStatusHint] = (0, import_react28.useState)("Ctrl+C twice to exit");
150681
- const [historyArray, setHistoryArray] = (0, import_react28.useState)([]);
150682
- const [inputKey, setInputKey] = (0, import_react28.useState)(0);
150683
- const [hideStatusBar, setHideStatusBar] = (0, import_react28.useState)(false);
150684
- const [pendingRawStdout, setPendingRawStdout] = (0, import_react28.useState)(
150747
+ const [outputItems, setOutputItems] = (0, import_react29.useState)([]);
150748
+ const outputIdRef = (0, import_react29.useRef)(0);
150749
+ const [prompt, setPrompt] = (0, import_react29.useState)("> ");
150750
+ const [width, setWidth] = (0, import_react29.useState)(stdout?.columns ?? 80);
150751
+ const [statusHint, setStatusHint] = (0, import_react29.useState)("Ctrl+C twice to exit");
150752
+ const [historyArray, setHistoryArray] = (0, import_react29.useState)([]);
150753
+ const [inputKey, setInputKey] = (0, import_react29.useState)(0);
150754
+ const [hideStatusBar, setHideStatusBar] = (0, import_react29.useState)(false);
150755
+ const [pendingRawStdout, setPendingRawStdout] = (0, import_react29.useState)(
150685
150756
  null
150686
150757
  );
150687
- (0, import_react28.useEffect)(() => {
150758
+ (0, import_react29.useEffect)(() => {
150688
150759
  if (hideStatusBar && pendingRawStdout) {
150689
150760
  process.stdout.write(pendingRawStdout);
150690
150761
  process.stdout.write("\n\n\n");
@@ -150692,6 +150763,7 @@ function App2({ initialSession } = {}) {
150692
150763
  setHideStatusBar(false);
150693
150764
  }
150694
150765
  }, [hideStatusBar, pendingRawStdout]);
150766
+ const gitStatus = useGitStatus({ enabled: isInitialized });
150695
150767
  const completion = useCompletion({
150696
150768
  session: isInitialized ? session : null
150697
150769
  });
@@ -150712,7 +150784,7 @@ function App2({ initialSession } = {}) {
150712
150784
  session.saveHistory().finally(() => exit());
150713
150785
  }
150714
150786
  });
150715
- (0, import_react28.useEffect)(() => {
150787
+ (0, import_react29.useEffect)(() => {
150716
150788
  const init = async () => {
150717
150789
  if (!isInitialized) {
150718
150790
  await session.initialize();
@@ -150723,11 +150795,10 @@ function App2({ initialSession } = {}) {
150723
150795
  if (histMgr) {
150724
150796
  setHistoryArray(histMgr.getHistory());
150725
150797
  }
150726
- setGitInfo(getGitInfo());
150727
150798
  };
150728
150799
  init();
150729
150800
  }, [session]);
150730
- (0, import_react28.useEffect)(() => {
150801
+ (0, import_react29.useEffect)(() => {
150731
150802
  const handleResize = () => {
150732
150803
  if (stdout) {
150733
150804
  const newWidth = stdout.columns ?? 80;
@@ -150743,7 +150814,7 @@ function App2({ initialSession } = {}) {
150743
150814
  stdout?.off("resize", handleResize);
150744
150815
  };
150745
150816
  }, [stdout]);
150746
- const addOutput = (0, import_react28.useCallback)((line) => {
150817
+ const addOutput = (0, import_react29.useCallback)((line) => {
150747
150818
  const lines = line.split("\n");
150748
150819
  const newItems = lines.map((content) => ({
150749
150820
  id: outputIdRef.current++,
@@ -150757,7 +150828,7 @@ function App2({ initialSession } = {}) {
150757
150828
  return combined;
150758
150829
  });
150759
150830
  }, []);
150760
- const applyCompletion = (0, import_react28.useCallback)(
150831
+ const applyCompletion = (0, import_react29.useCallback)(
150761
150832
  (suggestion) => {
150762
150833
  const currentInput = inputRef.current;
150763
150834
  let newValue;
@@ -150785,13 +150856,13 @@ function App2({ initialSession } = {}) {
150785
150856
  []
150786
150857
  // No dependencies needed since we use inputRef
150787
150858
  );
150788
- const refreshHistory = (0, import_react28.useCallback)(() => {
150859
+ const refreshHistory = (0, import_react29.useCallback)(() => {
150789
150860
  const histMgr = session.getHistory();
150790
150861
  if (histMgr) {
150791
150862
  setHistoryArray(histMgr.getHistory());
150792
150863
  }
150793
150864
  }, [session]);
150794
- const runCommand = (0, import_react28.useCallback)(
150865
+ const runCommand = (0, import_react29.useCallback)(
150795
150866
  async (cmd) => {
150796
150867
  const trimmed = cmd.trim();
150797
150868
  if (!trimmed) return;
@@ -150814,11 +150885,16 @@ function App2({ initialSession } = {}) {
150814
150885
  if (result.contextChanged) {
150815
150886
  setPrompt(buildPlainPrompt(session));
150816
150887
  }
150888
+ if (result.refreshGit) {
150889
+ gitStatus.refresh();
150890
+ } else {
150891
+ gitStatus.refresh();
150892
+ }
150817
150893
  refreshHistory();
150818
150894
  },
150819
- [session, prompt, addOutput, exit, refreshHistory]
150895
+ [session, prompt, addOutput, exit, refreshHistory, gitStatus]
150820
150896
  );
150821
- const handleInputChange = (0, import_react28.useCallback)(
150897
+ const handleInputChange = (0, import_react29.useCallback)(
150822
150898
  (newValue) => {
150823
150899
  const oldValue = input;
150824
150900
  setInput(newValue);
@@ -150846,7 +150922,7 @@ function App2({ initialSession } = {}) {
150846
150922
  },
150847
150923
  [input, completion]
150848
150924
  );
150849
- const handleSubmit = (0, import_react28.useCallback)(
150925
+ const handleSubmit = (0, import_react29.useCallback)(
150850
150926
  async (value) => {
150851
150927
  if (completion.isShowing && completion.suggestions.length > 0) {
150852
150928
  const selected = completion.selectCurrent();
@@ -150875,6 +150951,12 @@ function App2({ initialSession } = {}) {
150875
150951
  session.saveHistory().finally(() => exit());
150876
150952
  return;
150877
150953
  }
150954
+ if (key.ctrl && char === "g") {
150955
+ gitStatus.refresh();
150956
+ setStatusHint("Git status refreshed");
150957
+ setTimeout(() => setStatusHint("Ctrl+C twice to exit"), 2e3);
150958
+ return;
150959
+ }
150878
150960
  if (key.tab) {
150879
150961
  const currentInput = inputRef.current;
150880
150962
  if (completion.isShowing) {
@@ -150938,7 +151020,7 @@ function App2({ initialSession } = {}) {
150938
151020
  return;
150939
151021
  }
150940
151022
  });
150941
- const handleSuggestionNavigate = (0, import_react28.useCallback)(
151023
+ const handleSuggestionNavigate = (0, import_react29.useCallback)(
150942
151024
  (direction) => {
150943
151025
  if (direction === "up") {
150944
151026
  completion.navigateUp();
@@ -150948,7 +151030,7 @@ function App2({ initialSession } = {}) {
150948
151030
  },
150949
151031
  [completion]
150950
151032
  );
150951
- const handleSuggestionSelect = (0, import_react28.useCallback)(
151033
+ const handleSuggestionSelect = (0, import_react29.useCallback)(
150952
151034
  (suggestion) => {
150953
151035
  applyCompletion(suggestion);
150954
151036
  completion.hide();
@@ -150986,7 +151068,7 @@ function App2({ initialSession } = {}) {
150986
151068
  ) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
150987
151069
  StatusBar,
150988
151070
  {
150989
- gitInfo,
151071
+ gitInfo: gitStatus.gitInfo,
150990
151072
  width,
150991
151073
  hint: statusHint
150992
151074
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robinmordasiewicz/f5xc-xcsh",
3
- "version": "1.0.90-2601022220",
3
+ "version": "1.0.91-2601022325",
4
4
  "description": "F5 Distributed Cloud Shell - Interactive CLI for F5 XC",
5
5
  "type": "module",
6
6
  "bin": {