@vigilbase/cli 0.2.0 → 0.2.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.
Files changed (235) hide show
  1. package/CLOUDFLARE.md +9 -12
  2. package/COMMANDS.md +192 -111
  3. package/LOCAL.md +77 -84
  4. package/ONE.md +5 -6
  5. package/README.md +349 -173
  6. package/SECURITY.md +6 -4
  7. package/dist/auth/device-auth.d.ts +0 -1
  8. package/dist/auth/device-auth.js +6 -5
  9. package/dist/auth/index.d.ts +1 -2
  10. package/dist/auth/index.js +1 -2
  11. package/dist/auth/provider.d.ts +1 -1
  12. package/dist/auth/provider.js +16 -7
  13. package/dist/auth/refresh.d.ts +23 -4
  14. package/dist/auth/refresh.js +78 -22
  15. package/dist/auth/store.d.ts +78 -4
  16. package/dist/auth/store.js +385 -74
  17. package/dist/auth/token-metadata.d.ts +0 -1
  18. package/dist/auth/token-metadata.js +0 -1
  19. package/dist/auth/types.d.ts +0 -1
  20. package/dist/auth/types.js +0 -1
  21. package/dist/bin.d.ts +0 -1
  22. package/dist/bin.js +0 -1
  23. package/dist/cli.d.ts +4 -2
  24. package/dist/cli.js +13 -11
  25. package/dist/commands/account.d.ts +0 -1
  26. package/dist/commands/account.js +1 -2
  27. package/dist/commands/auth.d.ts +0 -1
  28. package/dist/commands/auth.js +71 -22
  29. package/dist/commands/billing.d.ts +0 -1
  30. package/dist/commands/billing.js +0 -1
  31. package/dist/commands/cloudflare.d.ts +1 -2
  32. package/dist/commands/cloudflare.js +14 -9
  33. package/dist/commands/helpers.d.ts +0 -1
  34. package/dist/commands/helpers.js +0 -1
  35. package/dist/commands/index.d.ts +0 -1
  36. package/dist/commands/index.js +0 -1
  37. package/dist/commands/legacy-validation.d.ts +7 -2
  38. package/dist/commands/legacy-validation.js +15 -3
  39. package/dist/commands/local.d.ts +6 -1
  40. package/dist/commands/local.js +36 -12
  41. package/dist/commands/one.d.ts +0 -1
  42. package/dist/commands/one.js +39 -13
  43. package/dist/commands/public-tools.d.ts +0 -1
  44. package/dist/commands/public-tools.js +63 -29
  45. package/dist/commands/runs.d.ts +0 -1
  46. package/dist/commands/runs.js +1 -2
  47. package/dist/commands/security.d.ts +1 -2
  48. package/dist/commands/security.js +34 -23
  49. package/dist/commands/watchdog.d.ts +0 -1
  50. package/dist/commands/watchdog.js +0 -1
  51. package/dist/index.d.ts +2 -3
  52. package/dist/index.js +1 -2
  53. package/dist/lib/banner.d.ts +0 -1
  54. package/dist/lib/banner.js +0 -1
  55. package/dist/lib/client.d.ts +9 -2
  56. package/dist/lib/client.js +49 -20
  57. package/dist/lib/cloudflare-client.d.ts +0 -1
  58. package/dist/lib/cloudflare-client.js +1 -2
  59. package/dist/lib/config.d.ts +16 -3
  60. package/dist/lib/config.js +41 -14
  61. package/dist/lib/format.d.ts +2 -1
  62. package/dist/lib/format.js +19 -8
  63. package/dist/lib/help.d.ts +4 -2
  64. package/dist/lib/help.js +72 -23
  65. package/dist/lib/network.d.ts +10 -1
  66. package/dist/lib/network.js +31 -4
  67. package/dist/lib/one-client.d.ts +4 -1
  68. package/dist/lib/one-client.js +9 -3
  69. package/dist/lib/one-error-hints.d.ts +19 -0
  70. package/dist/lib/one-error-hints.js +47 -0
  71. package/dist/lib/one-operations.d.ts +0 -1
  72. package/dist/lib/one-operations.js +0 -1
  73. package/dist/lib/open-url.d.ts +0 -1
  74. package/dist/lib/open-url.js +0 -1
  75. package/dist/lib/platform.d.ts +2 -0
  76. package/dist/lib/platform.js +4 -0
  77. package/dist/lib/progress.d.ts +0 -1
  78. package/dist/lib/progress.js +0 -1
  79. package/dist/lib/security-client.d.ts +0 -1
  80. package/dist/lib/security-client.js +0 -1
  81. package/dist/lib/skill-fetch.d.ts +0 -1
  82. package/dist/lib/skill-fetch.js +0 -1
  83. package/dist/lib/system-trust.d.ts +0 -1
  84. package/dist/lib/system-trust.js +0 -1
  85. package/dist/lib/tui.d.ts +0 -1
  86. package/dist/lib/tui.js +0 -1
  87. package/dist/local/cloudflare-checkup/cf/allowlist.d.ts +0 -1
  88. package/dist/local/cloudflare-checkup/cf/allowlist.js +0 -1
  89. package/dist/local/cloudflare-checkup/cf/auth-lifecycle.d.ts +0 -1
  90. package/dist/local/cloudflare-checkup/cf/auth-lifecycle.js +0 -1
  91. package/dist/local/cloudflare-checkup/cf/child-env.d.ts +0 -1
  92. package/dist/local/cloudflare-checkup/cf/child-env.js +0 -1
  93. package/dist/local/cloudflare-checkup/cf/install.d.ts +0 -1
  94. package/dist/local/cloudflare-checkup/cf/install.js +0 -1
  95. package/dist/local/cloudflare-checkup/cf/locate.d.ts +0 -1
  96. package/dist/local/cloudflare-checkup/cf/locate.js +0 -1
  97. package/dist/local/cloudflare-checkup/cf/run-cf.d.ts +0 -1
  98. package/dist/local/cloudflare-checkup/cf/run-cf.js +0 -1
  99. package/dist/local/cloudflare-checkup/collector.d.ts +0 -1
  100. package/dist/local/cloudflare-checkup/collector.js +0 -1
  101. package/dist/local/cloudflare-checkup/contract.d.ts +14 -3
  102. package/dist/local/cloudflare-checkup/contract.js +9 -3
  103. package/dist/local/cloudflare-checkup/email-verification.d.ts +0 -1
  104. package/dist/local/cloudflare-checkup/email-verification.js +0 -1
  105. package/dist/local/cloudflare-checkup/errors.d.ts +4 -1
  106. package/dist/local/cloudflare-checkup/errors.js +8 -2
  107. package/dist/local/cloudflare-checkup/output.d.ts +0 -1
  108. package/dist/local/cloudflare-checkup/output.js +0 -1
  109. package/dist/local/cloudflare-checkup/prompts.d.ts +0 -1
  110. package/dist/local/cloudflare-checkup/prompts.js +0 -1
  111. package/dist/local/cloudflare-checkup/rate-budget.d.ts +0 -1
  112. package/dist/local/cloudflare-checkup/rate-budget.js +0 -1
  113. package/dist/local/cloudflare-checkup/snapshot-file.d.ts +0 -1
  114. package/dist/local/cloudflare-checkup/snapshot-file.js +5 -4
  115. package/dist/local/cloudflare-checkup/submit-client.d.ts +19 -5
  116. package/dist/local/cloudflare-checkup/submit-client.js +63 -17
  117. package/dist/local/cloudflare-checkup/terminal-ui.d.ts +0 -1
  118. package/dist/local/cloudflare-checkup/terminal-ui.js +0 -1
  119. package/dist/types.d.ts +25 -3
  120. package/dist/types.js +16 -1
  121. package/dist/version.d.ts +0 -1
  122. package/dist/version.js +0 -1
  123. package/package.json +5 -9
  124. package/dist/auth/device-auth.d.ts.map +0 -1
  125. package/dist/auth/device-auth.js.map +0 -1
  126. package/dist/auth/index.d.ts.map +0 -1
  127. package/dist/auth/index.js.map +0 -1
  128. package/dist/auth/provider.d.ts.map +0 -1
  129. package/dist/auth/provider.js.map +0 -1
  130. package/dist/auth/refresh.d.ts.map +0 -1
  131. package/dist/auth/refresh.js.map +0 -1
  132. package/dist/auth/store.d.ts.map +0 -1
  133. package/dist/auth/store.js.map +0 -1
  134. package/dist/auth/token-metadata.d.ts.map +0 -1
  135. package/dist/auth/token-metadata.js.map +0 -1
  136. package/dist/auth/types.d.ts.map +0 -1
  137. package/dist/auth/types.js.map +0 -1
  138. package/dist/bin.d.ts.map +0 -1
  139. package/dist/bin.js.map +0 -1
  140. package/dist/cli.d.ts.map +0 -1
  141. package/dist/cli.js.map +0 -1
  142. package/dist/commands/account.d.ts.map +0 -1
  143. package/dist/commands/account.js.map +0 -1
  144. package/dist/commands/auth.d.ts.map +0 -1
  145. package/dist/commands/auth.js.map +0 -1
  146. package/dist/commands/billing.d.ts.map +0 -1
  147. package/dist/commands/billing.js.map +0 -1
  148. package/dist/commands/cloudflare.d.ts.map +0 -1
  149. package/dist/commands/cloudflare.js.map +0 -1
  150. package/dist/commands/helpers.d.ts.map +0 -1
  151. package/dist/commands/helpers.js.map +0 -1
  152. package/dist/commands/index.d.ts.map +0 -1
  153. package/dist/commands/index.js.map +0 -1
  154. package/dist/commands/legacy-validation.d.ts.map +0 -1
  155. package/dist/commands/legacy-validation.js.map +0 -1
  156. package/dist/commands/local.d.ts.map +0 -1
  157. package/dist/commands/local.js.map +0 -1
  158. package/dist/commands/one.d.ts.map +0 -1
  159. package/dist/commands/one.js.map +0 -1
  160. package/dist/commands/public-tools.d.ts.map +0 -1
  161. package/dist/commands/public-tools.js.map +0 -1
  162. package/dist/commands/runs.d.ts.map +0 -1
  163. package/dist/commands/runs.js.map +0 -1
  164. package/dist/commands/security.d.ts.map +0 -1
  165. package/dist/commands/security.js.map +0 -1
  166. package/dist/commands/watchdog.d.ts.map +0 -1
  167. package/dist/commands/watchdog.js.map +0 -1
  168. package/dist/index.d.ts.map +0 -1
  169. package/dist/index.js.map +0 -1
  170. package/dist/lib/banner.d.ts.map +0 -1
  171. package/dist/lib/banner.js.map +0 -1
  172. package/dist/lib/client.d.ts.map +0 -1
  173. package/dist/lib/client.js.map +0 -1
  174. package/dist/lib/cloudflare-client.d.ts.map +0 -1
  175. package/dist/lib/cloudflare-client.js.map +0 -1
  176. package/dist/lib/config.d.ts.map +0 -1
  177. package/dist/lib/config.js.map +0 -1
  178. package/dist/lib/format.d.ts.map +0 -1
  179. package/dist/lib/format.js.map +0 -1
  180. package/dist/lib/help.d.ts.map +0 -1
  181. package/dist/lib/help.js.map +0 -1
  182. package/dist/lib/network.d.ts.map +0 -1
  183. package/dist/lib/network.js.map +0 -1
  184. package/dist/lib/one-client.d.ts.map +0 -1
  185. package/dist/lib/one-client.js.map +0 -1
  186. package/dist/lib/one-operations.d.ts.map +0 -1
  187. package/dist/lib/one-operations.js.map +0 -1
  188. package/dist/lib/open-url.d.ts.map +0 -1
  189. package/dist/lib/open-url.js.map +0 -1
  190. package/dist/lib/progress.d.ts.map +0 -1
  191. package/dist/lib/progress.js.map +0 -1
  192. package/dist/lib/security-client.d.ts.map +0 -1
  193. package/dist/lib/security-client.js.map +0 -1
  194. package/dist/lib/skill-fetch.d.ts.map +0 -1
  195. package/dist/lib/skill-fetch.js.map +0 -1
  196. package/dist/lib/system-trust.d.ts.map +0 -1
  197. package/dist/lib/system-trust.js.map +0 -1
  198. package/dist/lib/tui.d.ts.map +0 -1
  199. package/dist/lib/tui.js.map +0 -1
  200. package/dist/local/cloudflare-checkup/cf/allowlist.d.ts.map +0 -1
  201. package/dist/local/cloudflare-checkup/cf/allowlist.js.map +0 -1
  202. package/dist/local/cloudflare-checkup/cf/auth-lifecycle.d.ts.map +0 -1
  203. package/dist/local/cloudflare-checkup/cf/auth-lifecycle.js.map +0 -1
  204. package/dist/local/cloudflare-checkup/cf/child-env.d.ts.map +0 -1
  205. package/dist/local/cloudflare-checkup/cf/child-env.js.map +0 -1
  206. package/dist/local/cloudflare-checkup/cf/install.d.ts.map +0 -1
  207. package/dist/local/cloudflare-checkup/cf/install.js.map +0 -1
  208. package/dist/local/cloudflare-checkup/cf/locate.d.ts.map +0 -1
  209. package/dist/local/cloudflare-checkup/cf/locate.js.map +0 -1
  210. package/dist/local/cloudflare-checkup/cf/run-cf.d.ts.map +0 -1
  211. package/dist/local/cloudflare-checkup/cf/run-cf.js.map +0 -1
  212. package/dist/local/cloudflare-checkup/collector.d.ts.map +0 -1
  213. package/dist/local/cloudflare-checkup/collector.js.map +0 -1
  214. package/dist/local/cloudflare-checkup/contract.d.ts.map +0 -1
  215. package/dist/local/cloudflare-checkup/contract.js.map +0 -1
  216. package/dist/local/cloudflare-checkup/email-verification.d.ts.map +0 -1
  217. package/dist/local/cloudflare-checkup/email-verification.js.map +0 -1
  218. package/dist/local/cloudflare-checkup/errors.d.ts.map +0 -1
  219. package/dist/local/cloudflare-checkup/errors.js.map +0 -1
  220. package/dist/local/cloudflare-checkup/output.d.ts.map +0 -1
  221. package/dist/local/cloudflare-checkup/output.js.map +0 -1
  222. package/dist/local/cloudflare-checkup/prompts.d.ts.map +0 -1
  223. package/dist/local/cloudflare-checkup/prompts.js.map +0 -1
  224. package/dist/local/cloudflare-checkup/rate-budget.d.ts.map +0 -1
  225. package/dist/local/cloudflare-checkup/rate-budget.js.map +0 -1
  226. package/dist/local/cloudflare-checkup/snapshot-file.d.ts.map +0 -1
  227. package/dist/local/cloudflare-checkup/snapshot-file.js.map +0 -1
  228. package/dist/local/cloudflare-checkup/submit-client.d.ts.map +0 -1
  229. package/dist/local/cloudflare-checkup/submit-client.js.map +0 -1
  230. package/dist/local/cloudflare-checkup/terminal-ui.d.ts.map +0 -1
  231. package/dist/local/cloudflare-checkup/terminal-ui.js.map +0 -1
  232. package/dist/types.d.ts.map +0 -1
  233. package/dist/types.js.map +0 -1
  234. package/dist/version.d.ts.map +0 -1
  235. package/dist/version.js.map +0 -1
@@ -1,11 +1,17 @@
1
1
  import { z } from 'zod';
2
+ import { singleLine } from './format.js';
2
3
  import { parseJsonResponse, requestText } from './network.js';
3
4
  import { fetchSkillText } from './skill-fetch.js';
5
+ import { AGENT_API_ERROR_CODES, } from '../types.js';
4
6
  export class VigilbaseApiError extends Error {
5
7
  status;
6
8
  body;
7
9
  retryAfterSec;
8
10
  code;
11
+ /** The server's sanitised explanation, set only for known vigilbase.com problem errors. */
12
+ reason;
13
+ /** CLI-authored remediation, never server text (see one-error-hints.ts). */
14
+ hint;
9
15
  constructor(message, options) {
10
16
  super(message);
11
17
  this.name = 'VigilbaseApiError';
@@ -13,6 +19,8 @@ export class VigilbaseApiError extends Error {
13
19
  this.body = options.body;
14
20
  this.retryAfterSec = options.retryAfterSec;
15
21
  this.code = options.code;
22
+ this.reason = options.reason;
23
+ this.hint = options.hint;
16
24
  }
17
25
  }
18
26
  export function retryAfterSeconds(response, body) {
@@ -30,6 +38,41 @@ export function retryAfterSeconds(response, body) {
30
38
  }
31
39
  return undefined;
32
40
  }
41
+ /** Longer messages are withheld rather than cut. */
42
+ const MAX_REASON_SOURCE_LENGTH = 1000;
43
+ const problemSchema = z.object({
44
+ error: z.object({ code: z.unknown(), message: z.string().max(MAX_REASON_SOURCE_LENGTH) }),
45
+ code: z.unknown(),
46
+ });
47
+ /**
48
+ * The reason a vigilbase.com problem+json error gives, when its code is one com sends.
49
+ * Anything else stays redacted: other media types, unknown codes, odd messages.
50
+ */
51
+ function problemReason(response, body) {
52
+ const mediaType = response.headers.get('content-type')?.split(';')[0]?.trim().toLowerCase();
53
+ if (mediaType !== 'application/problem+json')
54
+ return undefined;
55
+ const problem = problemSchema.safeParse(body);
56
+ if (!problem.success)
57
+ return undefined;
58
+ const code = z.enum(AGENT_API_ERROR_CODES).safeParse(problem.data.error.code ?? problem.data.code);
59
+ if (!code.success)
60
+ return undefined;
61
+ const message = singleLine(problem.data.error.message);
62
+ return message ? { code: code.data, message } : undefined;
63
+ }
64
+ function publicApiError(fallback, response, body) {
65
+ const reason = problemReason(response, body);
66
+ return new VigilbaseApiError(reason?.message ?? fallback, {
67
+ status: response.status,
68
+ body,
69
+ retryAfterSec: retryAfterSeconds(response, body),
70
+ code: reason?.code,
71
+ reason: reason?.message,
72
+ });
73
+ }
74
+ /** The versioned public tools API. The unversioned /api/agent/tools aliases sunset on 2027-09-01. */
75
+ export const PUBLIC_TOOLS_PATH = '/api/v1/agent/tools';
33
76
  /**
34
77
  * Public (unauthenticated) vigilbase.com tools client.
35
78
  * Vigilbase One authenticated calls will use a separate client + device-auth tokens.
@@ -55,14 +98,9 @@ export class VigilbaseClient {
55
98
  return { response, body: parseJsonResponse(response, text) };
56
99
  }
57
100
  async listTools() {
58
- const { response, body } = await this.request('/api/agent/tools');
101
+ const { response, body } = await this.request(PUBLIC_TOOLS_PATH);
59
102
  if (!response.ok) {
60
- const message = `Failed to list tools (HTTP ${response.status})`;
61
- throw new VigilbaseApiError(message, {
62
- status: response.status,
63
- body,
64
- retryAfterSec: retryAfterSeconds(response, body),
65
- });
103
+ throw publicApiError(`Failed to list tools (HTTP ${response.status})`, response, body);
66
104
  }
67
105
  const schema = z.object({
68
106
  success: z.literal(true),
@@ -77,31 +115,23 @@ export class VigilbaseClient {
77
115
  return body;
78
116
  }
79
117
  async executeTool(toolName, target) {
80
- const { response, body } = await this.request(`/api/agent/tools/${encodeURIComponent(toolName)}/execute`, {
118
+ const { response, body } = await this.request(`${PUBLIC_TOOLS_PATH}/${encodeURIComponent(toolName)}/execute`, {
81
119
  method: 'POST',
82
120
  headers: { 'Content-Type': 'application/json' },
83
121
  body: JSON.stringify({ target }),
84
122
  });
85
123
  const parsed = (body ?? {});
86
124
  if (response.status === 429) {
87
- throw new VigilbaseApiError('Rate limit exceeded. Retry after the indicated delay.', {
88
- status: 429,
89
- body: parsed,
90
- retryAfterSec: retryAfterSeconds(response, body),
91
- });
125
+ throw publicApiError('Rate limit exceeded. Retry after the indicated delay.', response, parsed);
92
126
  }
93
127
  if (!response.ok && response.status !== 422) {
94
- throw new VigilbaseApiError(`Tool execution failed (HTTP ${response.status})`, {
95
- status: response.status,
96
- body: parsed,
97
- retryAfterSec: retryAfterSeconds(response, body),
98
- });
128
+ throw publicApiError(`Tool execution failed (HTTP ${response.status})`, response, parsed);
99
129
  }
100
130
  if (!z.object({ success: z.boolean() }).passthrough().safeParse(body).success) {
101
131
  throw new VigilbaseApiError('Invalid tool execution response. Check the API URL or retry later.', { status: response.status });
102
132
  }
103
133
  if (!parsed.success) {
104
- throw new VigilbaseApiError('Tool execution was unsuccessful.', { status: response.status, body, retryAfterSec: retryAfterSeconds(response, body) });
134
+ throw publicApiError('Tool execution was unsuccessful.', response, body);
105
135
  }
106
136
  return parsed;
107
137
  }
@@ -116,4 +146,3 @@ export class VigilbaseClient {
116
146
  return `${this.origin}/api/badge/${encodeURIComponent(domain)}${query ? `?${query}` : ''}`;
117
147
  }
118
148
  }
119
- //# sourceMappingURL=client.js.map
@@ -37,4 +37,3 @@ export declare class CloudflareClient {
37
37
  checkupProgress(toolRunId: string): Promise<Record<string, unknown>>;
38
38
  private path;
39
39
  }
40
- //# sourceMappingURL=cloudflare-client.d.ts.map
@@ -61,7 +61,7 @@ export class CloudflareClient {
61
61
  method: 'POST',
62
62
  headers: { 'Content-Type': 'application/json' },
63
63
  body: JSON.stringify({ customerId: scope.customerId, accountId: scope.accountId }),
64
- });
64
+ }, { hasCustomerScope: Boolean(scope.customerId) });
65
65
  }
66
66
  const params = new URLSearchParams();
67
67
  if (scope.customerId)
@@ -78,4 +78,3 @@ export class CloudflareClient {
78
78
  return `${path}${query ? `?${query}` : ''}`;
79
79
  }
80
80
  }
81
- //# sourceMappingURL=cloudflare-client.js.map
@@ -5,10 +5,13 @@ export type CliConfig = {
5
5
  oneBaseUrl: string;
6
6
  /** OAuth client_id for Better Auth device authorization. */
7
7
  clientId: string;
8
- /** Explicit development issuer; production issuer is chosen through One discovery. */
8
+ /** Explicit Identity issuer (--auth-url / VIGILBASE_AUTH_URL). One's discovery must name it; unset, only production Identity is trusted. */
9
9
  identityBaseUrl?: string;
10
10
  authProvider?: import('../auth/provider.js').AuthProvider;
11
- /** Directory for credentials and local config (~/.config/vigilbase). */
11
+ /**
12
+ * Directory for credentials and local config (~/.config/vigilbase). Not validated when the config is built:
13
+ * the credential store rejects a relative path itself, so commands that never use it work whatever it holds.
14
+ */
12
15
  configDir: string;
13
16
  userAgent: string;
14
17
  timeoutMs: number;
@@ -17,14 +20,25 @@ export type CliConfig = {
17
20
  export type CliConfigLegacy = CliConfig & {
18
21
  baseUrl: string;
19
22
  };
23
+ export declare function parseOrigin(raw: string, option: string): string;
20
24
  /** Default request timeout; also used when library callers omit `timeoutMs`. */
21
25
  export declare const DEFAULT_TIMEOUT_MS = 60000;
22
26
  export declare function resolvePublicBaseUrl(explicit?: string | null): string;
23
27
  export declare function resolveOneBaseUrl(explicit?: string | null): string;
24
28
  /** Validate at transport boundaries too: library callers may construct config objects. */
25
29
  export declare function validateOneOrigin(raw: string): string;
30
+ /** Production Identity: the only issuer trusted unless --auth-url / VIGILBASE_AUTH_URL names another. */
31
+ export declare const DEFAULT_IDENTITY_ISSUER = "https://auth.vigilbase.com";
32
+ export declare const STAGING_IDENTITY_ISSUER = "https://identity-staging.vigilbase.com";
26
33
  export declare function resolveIdentityBaseUrl(raw: string): string;
34
+ /**
35
+ * The one Identity issuer this configuration trusts: --auth-url / VIGILBASE_AUTH_URL
36
+ * when set, otherwise production. Staging is trusted only when configured explicitly.
37
+ * Validated here too because library callers may construct config objects.
38
+ */
39
+ export declare function trustedIdentityIssuer(config: Pick<CliConfig, 'oneBaseUrl' | 'identityBaseUrl'>): string;
27
40
  export declare function resolveClientId(explicit?: string | null): string;
41
+ /** The config directory, which must be absolute. */
28
42
  export declare function resolveConfigDir(explicit?: string | null, env?: NodeJS.ProcessEnv): string;
29
43
  export declare function createConfig(options?: {
30
44
  baseUrl?: string | null;
@@ -45,4 +59,3 @@ export declare function createConfig(options?: {
45
59
  export declare function createLocalCommandConfig(timeoutMs?: number): CliConfigLegacy;
46
60
  /** Back-compat helper used by older call sites / tests. */
47
61
  export declare function resolveBaseUrl(explicit?: string | null): string;
48
- //# sourceMappingURL=config.d.ts.map
@@ -9,7 +9,7 @@ const DEFAULT_CLIENT_ID = 'vigilbase-cli';
9
9
  const originSchema = z.string().url().transform((raw) => new URL(raw)).refine((url) => (url.protocol === 'https:' || url.protocol === 'http:') &&
10
10
  !url.username && !url.password &&
11
11
  /^\/+$/.test(url.pathname) && !url.search && !url.hash, 'Expected an HTTP(S) origin without credentials, a path, query, or fragment.').transform((url) => url.origin);
12
- function parseOrigin(raw, option) {
12
+ export function parseOrigin(raw, option) {
13
13
  const result = originSchema.safeParse(raw);
14
14
  if (!result.success) {
15
15
  // Do not echo the input: malformed URLs can contain credentials.
@@ -44,10 +44,32 @@ export function validateOneOrigin(raw) {
44
44
  }
45
45
  return origin;
46
46
  }
47
+ /** Production Identity: the only issuer trusted unless --auth-url / VIGILBASE_AUTH_URL names another. */
48
+ export const DEFAULT_IDENTITY_ISSUER = 'https://auth.vigilbase.com';
49
+ export const STAGING_IDENTITY_ISSUER = 'https://identity-staging.vigilbase.com';
50
+ const IDENTITY_OPTION = '--auth-url / VIGILBASE_AUTH_URL';
51
+ function isIdentityLoopback(origin) {
52
+ return ['localhost', '127.0.0.1', '[::1]'].includes(new URL(origin).hostname);
53
+ }
47
54
  export function resolveIdentityBaseUrl(raw) {
48
- const origin = validateOneOrigin(raw);
49
- if (!['https://auth.vigilbase.com', 'https://identity-staging.vigilbase.com'].includes(origin) && !['localhost', '127.0.0.1', '[::1]'].includes(new URL(origin).hostname))
50
- throw new Error('--auth-url / VIGILBASE_AUTH_URL must identify a registered issuer or explicit loopback development origin.');
55
+ const origin = parseOrigin(raw, IDENTITY_OPTION);
56
+ if (origin !== DEFAULT_IDENTITY_ISSUER && origin !== STAGING_IDENTITY_ISSUER && !isIdentityLoopback(origin)) {
57
+ throw new Error(`${IDENTITY_OPTION} must be ${DEFAULT_IDENTITY_ISSUER}, ${STAGING_IDENTITY_ISSUER} or a loopback development origin.`);
58
+ }
59
+ return origin;
60
+ }
61
+ /**
62
+ * The one Identity issuer this configuration trusts: --auth-url / VIGILBASE_AUTH_URL
63
+ * when set, otherwise production. Staging is trusted only when configured explicitly.
64
+ * Validated here too because library callers may construct config objects.
65
+ */
66
+ export function trustedIdentityIssuer(config) {
67
+ if (!config.identityBaseUrl)
68
+ return DEFAULT_IDENTITY_ISSUER;
69
+ const origin = resolveIdentityBaseUrl(config.identityBaseUrl);
70
+ if (isIdentityLoopback(origin) && !isIdentityLoopback(validateOneOrigin(config.oneBaseUrl))) {
71
+ throw new Error(`${IDENTITY_OPTION} can be a loopback origin only when --one-url / VIGILBASE_ONE_URL is loopback too.`);
72
+ }
51
73
  return origin;
52
74
  }
53
75
  export function resolveClientId(explicit) {
@@ -55,17 +77,23 @@ export function resolveClientId(explicit) {
55
77
  process.env.VIGILBASE_CLIENT_ID?.trim() ||
56
78
  DEFAULT_CLIENT_ID);
57
79
  }
58
- export function resolveConfigDir(explicit, env = process.env) {
80
+ /**
81
+ * VIGILBASE_CONFIG_DIR (or `explicit`), else $XDG_CONFIG_HOME/vigilbase, else ~/.config/vigilbase. A relative
82
+ * XDG_CONFIG_HOME is ignored, as the XDG Base Directory spec says; a relative custom directory is returned as is.
83
+ */
84
+ function configDirFromEnvironment(explicit, env) {
59
85
  const custom = explicit?.trim() || env.VIGILBASE_CONFIG_DIR?.trim();
60
- const xdg = env.XDG_CONFIG_HOME?.trim();
61
- if ((custom && !isAbsolute(custom)) || (xdg && !isAbsolute(xdg))) {
62
- throw new Error('Custom config directories and XDG_CONFIG_HOME must be absolute paths.');
63
- }
64
86
  if (custom)
65
87
  return custom;
66
- if (xdg)
67
- return join(xdg, 'vigilbase');
68
- return join(homedir(), '.config', 'vigilbase');
88
+ const xdg = env.XDG_CONFIG_HOME?.trim();
89
+ return xdg && isAbsolute(xdg) ? join(xdg, 'vigilbase') : join(homedir(), '.config', 'vigilbase');
90
+ }
91
+ /** The config directory, which must be absolute. */
92
+ export function resolveConfigDir(explicit, env = process.env) {
93
+ const configDir = configDirFromEnvironment(explicit, env);
94
+ if (!isAbsolute(configDir))
95
+ throw new Error('VIGILBASE_CONFIG_DIR must be an absolute path.');
96
+ return configDir;
69
97
  }
70
98
  export function createConfig(options) {
71
99
  const publicBaseUrl = resolvePublicBaseUrl(options?.publicBaseUrl ?? options?.baseUrl);
@@ -80,7 +108,7 @@ export function createConfig(options) {
80
108
  oneBaseUrl: resolveOneBaseUrl(options?.oneBaseUrl),
81
109
  ...(options?.identityBaseUrl || process.env.VIGILBASE_AUTH_URL ? { identityBaseUrl: resolveIdentityBaseUrl(options?.identityBaseUrl || process.env.VIGILBASE_AUTH_URL) } : {}),
82
110
  clientId: resolveClientId(options?.clientId),
83
- configDir: resolveConfigDir(options?.configDir),
111
+ configDir: configDirFromEnvironment(options?.configDir, process.env),
84
112
  userAgent: `@vigilbase/cli/${CLI_VERSION} (+https://vigilbase.com; node/${process.version})`,
85
113
  timeoutMs,
86
114
  };
@@ -112,4 +140,3 @@ export function createLocalCommandConfig(timeoutMs) {
112
140
  export function resolveBaseUrl(explicit) {
113
141
  return resolvePublicBaseUrl(explicit);
114
142
  }
115
- //# sourceMappingURL=config.js.map
@@ -5,6 +5,8 @@ export type Writer = {
5
5
  };
6
6
  /** Untrusted API data must never become terminal control sequences or bidi overrides. */
7
7
  export declare function sanitizeTerminal(value: string): string;
8
+ /** One sanitised line, cut to `maxLength` characters with an ellipsis. */
9
+ export declare function singleLine(value: string, maxLength?: number): string;
8
10
  export declare function createWriter(stdout?: NodeJS.WritableStream, stderr?: NodeJS.WritableStream): Writer;
9
11
  export declare function printJson(writer: Writer, value: unknown): void;
10
12
  export declare function formatToolsList(catalog: AgentToolsCatalogResponse, mode: CliOutputMode, writer: Writer, options?: {
@@ -16,4 +18,3 @@ export declare function formatToolsList(catalog: AgentToolsCatalogResponse, mode
16
18
  export declare function formatToolDescription(tool: AgentToolDefinition, mode: CliOutputMode, writer: Writer, skillMarkdown?: string): void;
17
19
  export declare function formatExecuteResult(result: AgentToolExecuteResponse, mode: CliOutputMode, writer: Writer): void;
18
20
  export declare function formatError(error: unknown, mode: CliOutputMode, writer: Writer): void;
19
- //# sourceMappingURL=format.d.ts.map
@@ -3,6 +3,11 @@ import { stripVTControlCharacters } from 'node:util';
3
3
  export function sanitizeTerminal(value) {
4
4
  return stripVTControlCharacters(value).replace(/[\u0000-\u0008\u000b-\u001f\u007f-\u009f\u061c\u200e\u200f\u202a-\u202e\u2066-\u2069]/g, '');
5
5
  }
6
+ /** One sanitised line, cut to `maxLength` characters with an ellipsis. */
7
+ export function singleLine(value, maxLength = 300) {
8
+ const line = sanitizeTerminal(value).replace(/\s+/g, ' ').trim();
9
+ return line.length > maxLength ? `${line.slice(0, maxLength - 1).trimEnd()}…` : line;
10
+ }
6
11
  export function createWriter(stdout = process.stdout, stderr = process.stderr) {
7
12
  return {
8
13
  stdout: (line = '') => {
@@ -257,8 +262,9 @@ export function formatExecuteResult(result, mode, writer) {
257
262
  writer.stdout(head);
258
263
  else
259
264
  writer.stderr(head);
260
- if (result.error) {
261
- writer.stderr(` ${result.error}`);
265
+ const error = typeof result.error === 'string' ? result.error : result.error?.message;
266
+ if (error) {
267
+ writer.stderr(` ${error}`);
262
268
  }
263
269
  for (const line of summarizeResultCompact(result.result)) {
264
270
  writer.stdout(` ${line}`);
@@ -266,11 +272,17 @@ export function formatExecuteResult(result, mode, writer) {
266
272
  }
267
273
  export function formatError(error, mode, writer) {
268
274
  let message = error instanceof Error ? error.message : String(error);
275
+ let reason = '';
269
276
  // Server bodies can contain credentials, customer data, or arbitrary error text.
270
277
  if (error && typeof error === 'object' && 'body' in error && error.body != null && 'status' in error && typeof error.status === 'number') {
271
- message = 'code' in error && error.code === 'FLAREHAWK_VIEW_AS_REQUIRED'
272
- ? 'Select a customer with --customer-id <customer UUID> for security commands.'
273
- : `Request failed (HTTP ${error.status}).`;
278
+ if ('code' in error && error.code === 'FLAREHAWK_VIEW_AS_REQUIRED') {
279
+ message = 'Select a customer with --customer-id <customer UUID> for security commands.';
280
+ }
281
+ else {
282
+ // Only the reason the public client accepted from a known problem+json error is shown.
283
+ reason = 'reason' in error && typeof error.reason === 'string' ? singleLine(error.reason) : '';
284
+ message = reason || `Request failed (HTTP ${error.status}).`;
285
+ }
274
286
  }
275
287
  const payload = {
276
288
  success: false,
@@ -294,7 +306,7 @@ export function formatError(error, mode, writer) {
294
306
  }
295
307
  // CLI-authored remediation (never server text); bounded and sanitised like any output.
296
308
  if ('hint' in error && typeof error.hint === 'string') {
297
- const hint = sanitizeTerminal(error.hint).replace(/\s+/g, ' ').trim().slice(0, 300);
309
+ const hint = singleLine(error.hint);
298
310
  if (hint)
299
311
  payload.hint = hint;
300
312
  }
@@ -303,7 +315,7 @@ export function formatError(error, mode, writer) {
303
315
  printJson(writer, payload);
304
316
  return;
305
317
  }
306
- writer.stderr(`Error: ${message}`);
318
+ writer.stderr(`Error: ${message}${reason && typeof payload.code === 'string' ? ` (${payload.code})` : ''}`);
307
319
  if (typeof payload.retryAfterSec === 'number') {
308
320
  writer.stderr(`Retry after ${payload.retryAfterSec}s`);
309
321
  }
@@ -311,4 +323,3 @@ export function formatError(error, mode, writer) {
311
323
  writer.stderr(`Hint: ${payload.hint}`);
312
324
  }
313
325
  }
314
- //# sourceMappingURL=format.js.map
@@ -1,4 +1,6 @@
1
1
  export declare const HELP_TAGLINE = "one \u00B7 security \u00B7 tools";
2
- export declare const HELP_TEXT = "Usage: vigilbase <command>\n\nPublic tools (no login)\n list List available tools\n run <tool> <target> Run a scan\n headers <url> Check security headers\n email <domain> Check email security\n describe <tool> \u00B7 skill Tool details / skill markdown\n badge <domain> \u00B7 doctor Badge URL \u00B7 connectivity\n\nAuth-required tools (after login)\n website-security \u00B7 react2shell \u00B7 fortibleed-check\n\nOn this machine (no login)\n cloudflare-checkup Run the Cloudflare Checkup on this machine in one\n command (alias: local cloudflare-checkup)\n\nAccount (login required)\n login \u00B7 logout \u00B7 whoami Session\n account [services|org|\u2026] Account overview\n account endpoints Endpoint inventory\n account sessions Active sessions\n account invites [list|create]\n billing [summary|portal] Billing summary / Stripe portal\n runs [list|get <id>] Tool run history\n cf <command> Cloudflare accounts, zones, DNS, WAF, analytics\n security <command> Incidents, logs, assets, detections, intel, reports\n watchdog [list|scans] Watchdog targets / scans\n customers <command> Customer records, billing, reports, investigations\n orgs <command> Organizations, members, permission roles\n monitoring <command> Health, probes, metrics, customer targets\n support tickets Support ticket history\n\nOptions\n -j, --json JSON output\n -h, --help Help for the current command\n -V, --version Installed version\n --timeout <milliseconds> Request timeout (default: 60000)\n --base-url <origin> Public API origin\n --one-url <origin> Vigilbase One origin\n --auth-url <origin> Explicit registered Identity or loopback development issuer\n --client-id <id> Device authorization client ID\n\nUse vigilbase <command> --help for command options.\n\nExamples\n vigilbase headers https://vigilbase.com\n vigilbase email vigilbase.com --json\n vigilbase login\n vigilbase account --json\n vigilbase runs list --json\n vigilbase cf zones\n vigilbase security incidents --severity high\n";
2
+ /** A tool from the catalog the CLI knows offline: it runs as `run <tool> <target>`, not as a command. */
3
+ export declare function isCatalogTool(name: string): boolean;
4
+ export declare const HELP_TEXT: string;
5
+ export declare const HELP_USAGE = "Usage: vigilbase help [<command> | <tool>]";
3
6
  export declare function helpForCommand(command: string): string | null;
4
- //# sourceMappingURL=help.d.ts.map
package/dist/lib/help.js CHANGED
@@ -2,7 +2,39 @@ import { CLOUDFLARE_HELP } from '../commands/cloudflare.js';
2
2
  import { LOCAL_HELP } from '../commands/local.js';
3
3
  import { ONE_HELP } from '../commands/one.js';
4
4
  import { SECURITY_HELP } from '../commands/security.js';
5
+ import { isOneAuthRequiredTool, ONE_AUTH_REQUIRED_TOOLS } from './one-client.js';
5
6
  export const HELP_TAGLINE = 'one · security · tools';
7
+ /** vigilbase.com's public catalog, with each tool's shortcut command. `help <tool>` answers offline. */
8
+ const PUBLIC_TOOL_SHORTCUTS = {
9
+ 'security-headers': 'headers <url>',
10
+ 'email-security': 'email <domain>',
11
+ };
12
+ const PUBLIC_TOOLS = Object.keys(PUBLIC_TOOL_SHORTCUTS);
13
+ function isPublicTool(name) {
14
+ return Object.hasOwn(PUBLIC_TOOL_SHORTCUTS, name);
15
+ }
16
+ /** A tool from the catalog the CLI knows offline: it runs as `run <tool> <target>`, not as a command. */
17
+ export function isCatalogTool(name) {
18
+ return isPublicTool(name) || isOneAuthRequiredTool(name);
19
+ }
20
+ /** Column where descriptions start in the main help: two-space indent, term, at least two spaces. */
21
+ const DESCRIPTION_COLUMN = 31;
22
+ /** Two-column help rows whose descriptions all start at DESCRIPTION_COLUMN. */
23
+ function helpRows(rows) {
24
+ return rows
25
+ .map(([term, description]) => ` ${term.padEnd(DESCRIPTION_COLUMN - 4)} ${description}`)
26
+ .join('\n');
27
+ }
28
+ const GLOBAL_OPTIONS = helpRows([
29
+ ['-j, --json', 'JSON output'],
30
+ ['-h, --help', 'Help for the current command'],
31
+ ['-V, --version', 'Installed version'],
32
+ ['--timeout <milliseconds>', 'Request timeout (default: 60000)'],
33
+ ['--base-url <origin>', 'Public API origin'],
34
+ ['--one-url <origin>', 'Vigilbase One origin'],
35
+ ['--auth-url <origin>', 'Identity issuer (default: auth.vigilbase.com)'],
36
+ ['--client-id <id>', 'Device authorization client ID'],
37
+ ]);
6
38
  export const HELP_TEXT = `Usage: vigilbase <command>
7
39
 
8
40
  Public tools (no login)
@@ -14,7 +46,7 @@ Public tools (no login)
14
46
  badge <domain> · doctor Badge URL · connectivity
15
47
 
16
48
  Auth-required tools (after login)
17
- website-security · react2shell · fortibleed-check
49
+ ${ONE_AUTH_REQUIRED_TOOLS.map((tool) => ` run ${tool} <target>`).join('\n')}
18
50
 
19
51
  On this machine (no login)
20
52
  cloudflare-checkup Run the Cloudflare Checkup on this machine in one
@@ -28,25 +60,18 @@ Account (login required)
28
60
  account invites [list|create]
29
61
  billing [summary|portal] Billing summary / Stripe portal
30
62
  runs [list|get <id>] Tool run history
31
- cf <command> Cloudflare accounts, zones, DNS, WAF, analytics
32
- security <command> Incidents, logs, assets, detections, intel, reports
63
+ cf <command> Cloudflare accounts, zones, DNS, WAF, analytics
64
+ security <command> Incidents, logs, assets, detections, intel, reports
33
65
  watchdog [list|scans] Watchdog targets / scans
34
- customers <command> Customer records, billing, reports, investigations
35
- orgs <command> Organizations, members, permission roles
36
- monitoring <command> Health, probes, metrics, customer targets
37
- support tickets Support ticket history
66
+ customers <command> Customer records, billing, reports, investigations
67
+ orgs <command> Organizations, members, permission roles
68
+ monitoring <command> Health, probes, metrics, customer targets
69
+ support tickets Support ticket history
38
70
 
39
71
  Options
40
- -j, --json JSON output
41
- -h, --help Help for the current command
42
- -V, --version Installed version
43
- --timeout <milliseconds> Request timeout (default: 60000)
44
- --base-url <origin> Public API origin
45
- --one-url <origin> Vigilbase One origin
46
- --auth-url <origin> Explicit registered Identity or loopback development issuer
47
- --client-id <id> Device authorization client ID
72
+ ${GLOBAL_OPTIONS}
48
73
 
49
- Use vigilbase <command> --help for command options.
74
+ Use vigilbase <command> --help or vigilbase help <tool> for usage.
50
75
 
51
76
  Examples
52
77
  vigilbase headers https://vigilbase.com
@@ -57,16 +82,40 @@ Examples
57
82
  vigilbase cf zones
58
83
  vigilbase security incidents --severity high
59
84
  `;
85
+ /** How to run a catalog tool: `help <tool>` and `<tool> --help`, since tools run as `run <tool> <target>`. */
86
+ function helpForTool(tool) {
87
+ if (isPublicTool(tool)) {
88
+ return `Usage: vigilbase run ${tool} <target> [--json] [--via public|one] [--public]
89
+
90
+ Public tool, no login needed. Shortcut: vigilbase ${PUBLIC_TOOL_SHORTCUTS[tool]}
91
+ Details: vigilbase describe ${tool}`;
92
+ }
93
+ if (isOneAuthRequiredTool(tool)) {
94
+ return `Usage: vigilbase run ${tool} <target> [--json]
95
+
96
+ Runs through Vigilbase One: run \`vigilbase login\` first.
97
+ Details: vigilbase describe ${tool}`;
98
+ }
99
+ return null;
100
+ }
101
+ export const HELP_USAGE = 'Usage: vigilbase help [<command> | <tool>]';
60
102
  export function helpForCommand(command) {
61
103
  switch (command) {
104
+ case 'help':
105
+ return `${HELP_USAGE}
106
+
107
+ Shows the usage of a command or of a tool, for example vigilbase help run or
108
+ vigilbase help website-security. Without one, shows every command.`;
62
109
  case 'tools':
63
110
  case 'list':
64
111
  return `Usage: vigilbase list [--json]`;
65
112
  case 'run':
66
113
  return `Usage: vigilbase run <tool> <target> [--json] [--via public|one] [--public]
67
114
 
68
- Public: security-headers, email-security
69
- Login: website-security, react2shell, fortibleed-check`;
115
+ Public: ${PUBLIC_TOOLS.join(', ')}
116
+ Login: ${ONE_AUTH_REQUIRED_TOOLS.join(', ')}
117
+
118
+ Run vigilbase help <tool> for a tool's usage.`;
70
119
  case 'describe':
71
120
  return `Usage: vigilbase describe <tool> [--json] [--no-skill]`;
72
121
  case 'skill':
@@ -76,9 +125,10 @@ Login: website-security, react2shell, fortibleed-check`;
76
125
  case 'doctor':
77
126
  return `Usage: vigilbase doctor [--json]
78
127
 
79
- Checks the public tools API and Vigilbase One session endpoint independently.
80
- Login is optional. Exits with status 1 if either check fails.
81
- Use --base-url, --one-url, and --timeout to check alternate environments.`;
128
+ Checks the public tools API, your session (Identity's userinfo endpoint when
129
+ signed in through Identity, otherwise One's session endpoint) and any saved
130
+ sign-in independently. Login is optional. Exits with status 1 if any check fails.
131
+ Use --base-url, --one-url, --auth-url and --timeout to check other environments.`;
82
132
  case 'account':
83
133
  return `Usage: vigilbase account [services|org|endpoints|sessions|invites|billing] [--json]
84
134
 
@@ -119,7 +169,6 @@ Prefer --token-stdin with piped input to keep tokens out of command arguments.`;
119
169
  case 'email':
120
170
  return `Usage: vigilbase email <domain> [--json] [--via public|one] [--public]`;
121
171
  default:
122
- return null;
172
+ return helpForTool(command);
123
173
  }
124
174
  }
125
- //# sourceMappingURL=help.js.map
@@ -8,10 +8,19 @@ export declare function networkError(error: unknown, url: string, timeoutMs: num
8
8
  export declare const MAX_RESPONSE_BYTES: number;
9
9
  /** Bound decoded bytes even when Content-Length is absent, compressed, or dishonest. */
10
10
  export declare function readBoundedBody(response: Response, signal: AbortSignal, maxBytes?: number): Promise<string>;
11
+ /**
12
+ * A signal that aborts with the reason of the first of `signals` to abort.
13
+ * Uses `AbortSignal.any` (Node 20.3+) and combines them by hand on older
14
+ * Node 20; `dispose` then removes the listeners so a long-lived signal does
15
+ * not collect one per request.
16
+ */
17
+ export declare function anySignal(signals: AbortSignal[]): {
18
+ signal: AbortSignal;
19
+ dispose: () => void;
20
+ };
11
21
  /** Keep the timeout active until the complete response body has been read. */
12
22
  export declare function requestText(config: CliConfig, url: string, init?: RequestInit): Promise<{
13
23
  response: Response;
14
24
  text: string;
15
25
  }>;
16
26
  export declare function parseJsonResponse(response: Response, text: string): unknown;
17
- //# sourceMappingURL=network.d.ts.map
@@ -70,13 +70,40 @@ export async function readBoundedBody(response, signal, maxBytes = MAX_RESPONSE_
70
70
  reader.releaseLock();
71
71
  }
72
72
  }
73
+ /**
74
+ * A signal that aborts with the reason of the first of `signals` to abort.
75
+ * Uses `AbortSignal.any` (Node 20.3+) and combines them by hand on older
76
+ * Node 20; `dispose` then removes the listeners so a long-lived signal does
77
+ * not collect one per request.
78
+ */
79
+ export function anySignal(signals) {
80
+ if (typeof AbortSignal.any === 'function')
81
+ return { signal: AbortSignal.any(signals), dispose: () => undefined };
82
+ const controller = new AbortController();
83
+ const dispose = () => {
84
+ for (const signal of signals)
85
+ signal.removeEventListener('abort', onAbort);
86
+ };
87
+ function onAbort(event) {
88
+ dispose();
89
+ controller.abort(event.target.reason);
90
+ }
91
+ const aborted = signals.find((signal) => signal.aborted);
92
+ if (aborted) {
93
+ controller.abort(aborted.reason);
94
+ return { signal: controller.signal, dispose: () => undefined };
95
+ }
96
+ for (const signal of signals)
97
+ signal.addEventListener('abort', onAbort, { once: true });
98
+ return { signal: controller.signal, dispose };
99
+ }
73
100
  /** Keep the timeout active until the complete response body has been read. */
74
101
  export async function requestText(config, url, init = {}) {
75
102
  const controller = new AbortController();
76
103
  const timer = setTimeout(() => controller.abort(), config.timeoutMs);
77
- const signal = init.signal
78
- ? AbortSignal.any([init.signal, controller.signal])
79
- : controller.signal;
104
+ const { signal, dispose } = init.signal
105
+ ? anySignal([init.signal, controller.signal])
106
+ : { signal: controller.signal, dispose: () => undefined };
80
107
  try {
81
108
  // Never forward token-bearing POST bodies (or credentials) through redirects.
82
109
  // 'manual' is honoured because it surfaces the 3xx without following it.
@@ -93,6 +120,7 @@ export async function requestText(config, url, init = {}) {
93
120
  }
94
121
  finally {
95
122
  clearTimeout(timer);
123
+ dispose();
96
124
  }
97
125
  }
98
126
  export function parseJsonResponse(response, text) {
@@ -106,4 +134,3 @@ export function parseJsonResponse(response, text) {
106
134
  throw new NetworkError(`Expected JSON but received a non-JSON response (HTTP ${response.status}). Check the configured API URL and any proxy or sign-in page.`, 'INVALID_RESPONSE');
107
135
  }
108
136
  }
109
- //# sourceMappingURL=network.js.map
@@ -47,11 +47,15 @@ export declare class VigilbaseOneClient {
47
47
  private readonly config;
48
48
  private accessToken;
49
49
  private readonly managed;
50
+ /** The userinfo endpoint Identity discovery named for the last getSession, if it used Identity. */
51
+ userinfoEndpoint?: string;
50
52
  constructor(config: CliConfig, accessToken: string, managed?: boolean);
51
53
  private request;
52
54
  /** Authenticated JSON transport shared by the One command clients. */
53
55
  requestJson<T extends ApiErrorBody = Record<string, unknown>>(path: string, init?: RequestInit, options?: {
54
56
  allowStatuses?: number[];
57
+ /** Whether the request names a customer outside the query string (a JSON body). */
58
+ hasCustomerScope?: boolean;
55
59
  }): Promise<T>;
56
60
  getSession(): Promise<OneSessionResponse>;
57
61
  getAccount(): Promise<Record<string, unknown>>;
@@ -89,4 +93,3 @@ export declare class VigilbaseOneClient {
89
93
  executeTool(toolName: string, target: string): Promise<OneToolExecuteResponse>;
90
94
  }
91
95
  export {};
92
- //# sourceMappingURL=one-client.d.ts.map