requestshield 0.1.3 → 0.1.5
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/README.md +380 -63
- package/package.json +5 -1
- package/skills/requestshield/SKILL.md +1 -1
- package/skills/requestshield/references/cli.md +7 -6
- package/src/agent-detector.mjs +37 -9
- package/src/api-client.mjs +100 -5
- package/src/args.mjs +111 -2
- package/src/cli.mjs +233 -18
- package/src/commands/apps-get.mjs +64 -0
- package/src/commands/apps-list.mjs +90 -0
- package/src/commands/billing-get.mjs +110 -0
- package/src/commands/challenge-volume.mjs +81 -0
- package/src/commands/contract.mjs +106 -0
- package/src/commands/update-check.mjs +139 -0
- package/src/config.mjs +8 -0
package/README.md
CHANGED
|
@@ -1,43 +1,290 @@
|
|
|
1
1
|
# RequestShield CLI
|
|
2
2
|
|
|
3
|
-
Customer-facing CLI for
|
|
4
|
-
|
|
3
|
+
Customer-facing CLI for IntelliFend RequestShield. It allows customers to sign
|
|
4
|
+
in, rotate application credentials, install the RequestShield Skill for Codex
|
|
5
|
+
or Claude, and update an npm-installed CLI.
|
|
6
|
+
|
|
7
|
+
Current package version: `0.1.5`.
|
|
5
8
|
|
|
6
9
|
## Requirements
|
|
7
10
|
|
|
8
11
|
- Node.js 22.13 or newer.
|
|
9
|
-
- A customer management API
|
|
12
|
+
- A RequestShield customer management API.
|
|
13
|
+
- npm for local development and publishing.
|
|
14
|
+
|
|
15
|
+
The management API defaults to `https://api.intellifend.ai`. Set
|
|
16
|
+
`REQUESTSHIELD_API_URL` to use a different management API during development.
|
|
17
|
+
|
|
18
|
+
## Implemented commands
|
|
10
19
|
|
|
11
|
-
|
|
12
|
-
|
|
20
|
+
```console
|
|
21
|
+
requestshield signin
|
|
22
|
+
requestshield keys create [--yes]
|
|
23
|
+
requestshield contract
|
|
24
|
+
requestshield apps list [--json]
|
|
25
|
+
requestshield apps get <app-key>
|
|
26
|
+
requestshield challenge volume <app-key> [--from <time>] [--to <time>] [--granularity <value>]
|
|
27
|
+
requestshield get billing <app-key>
|
|
28
|
+
requestshield agent setup [--force]
|
|
29
|
+
requestshield agent setup --codex [--force]
|
|
30
|
+
requestshield agent setup --claude [--force]
|
|
31
|
+
requestshield update check
|
|
32
|
+
requestshield --help
|
|
33
|
+
requestshield --version
|
|
34
|
+
```
|
|
13
35
|
|
|
14
|
-
|
|
36
|
+
### Sign in
|
|
15
37
|
|
|
16
38
|
```console
|
|
17
39
|
requestshield signin
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Starts the device authorization flow. The CLI prints the verification URL and
|
|
43
|
+
user code without opening the browser automatically. After authorization, the
|
|
44
|
+
session is stored for the current operating-system user.
|
|
45
|
+
|
|
46
|
+
For CI or automation, provide `REQUESTSHIELD_ACCESS_TOKEN`. A token supplied by
|
|
47
|
+
the environment is used directly and is not persisted by the CLI.
|
|
48
|
+
|
|
49
|
+
### Create new keys
|
|
50
|
+
|
|
51
|
+
```console
|
|
18
52
|
requestshield keys create
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Asks the customer to type `ROTATE`, then calls the management API to deactivate
|
|
56
|
+
the previous credentials and create a new `appKey` and `apiSecret`.
|
|
57
|
+
|
|
58
|
+
- `appKey` is the public application identifier.
|
|
59
|
+
- `apiSecret` is a backend-only secret displayed once.
|
|
60
|
+
- The CLI does not save the returned `apiSecret`.
|
|
61
|
+
- `--yes` skips the confirmation prompt for non-interactive automation.
|
|
62
|
+
|
|
63
|
+
Store the Secret Key in a backend secret manager immediately after creation.
|
|
64
|
+
|
|
65
|
+
### Get the integration contract
|
|
66
|
+
|
|
67
|
+
```console
|
|
68
|
+
requestshield contract
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Returns the current authoritative integration contract as JSON, including any
|
|
72
|
+
additional SDK-version or CSP fields supplied by the API. The command requires a
|
|
73
|
+
saved sign-in session and validates the core browser, backend, and release fields
|
|
74
|
+
before printing the response.
|
|
75
|
+
|
|
76
|
+
### List applications
|
|
77
|
+
|
|
78
|
+
```console
|
|
79
|
+
requestshield apps list
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Lists the applications the signed-in user is allowed to access:
|
|
83
|
+
|
|
84
|
+
```text
|
|
85
|
+
APP KEY NAME STATUS
|
|
86
|
+
app_123 Production Website pending
|
|
87
|
+
app_456 Staging Website active
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Use `--json` to print the stable `{ "data": [...], "nextCursor": null }`
|
|
91
|
+
response shape. The CLI allowlists `appKey`, `name`, `status`, `createdAt`, and
|
|
92
|
+
`updatedAt`; it never prints an API Secret returned accidentally by the service.
|
|
93
|
+
|
|
94
|
+
### Get an application
|
|
95
|
+
|
|
96
|
+
```console
|
|
97
|
+
requestshield apps get app_123
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Returns `app_key`, `name`, and the application's current status as JSON.
|
|
101
|
+
Valid statuses are:
|
|
102
|
+
|
|
103
|
+
- `ready` — the application key was just created and no traffic has been received.
|
|
104
|
+
- `active` — the application is receiving traffic.
|
|
105
|
+
- `deactivated` — the application has been deactivated.
|
|
106
|
+
|
|
107
|
+
The requested App Key must exactly match the key in the API response.
|
|
108
|
+
|
|
109
|
+
### Get challenge volume
|
|
110
|
+
|
|
111
|
+
```console
|
|
112
|
+
requestshield challenge volume app_123 \
|
|
113
|
+
--from 2026-08-01T00:00:00Z \
|
|
114
|
+
--to 2026-08-27T23:59:59Z \
|
|
115
|
+
--granularity day
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Returns challenge/request volume as JSON. Times must be ISO-8601 timestamps, and
|
|
119
|
+
`--from` cannot be later than `--to`. Granularity values such as `hour` and `day`
|
|
120
|
+
are passed to the API, which owns the supported set.
|
|
121
|
+
|
|
122
|
+
Challenge volume proves that traffic reached the platform; it does not prove
|
|
123
|
+
that the protected backend rejects requests without a valid token.
|
|
124
|
+
|
|
125
|
+
### Get billing information
|
|
126
|
+
|
|
127
|
+
```console
|
|
128
|
+
requestshield get billing app_123
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Returns the selected application's current plan, billing cycle, charges, quota,
|
|
132
|
+
and usage as JSON. The command is read-only and requires a saved sign-in session.
|
|
133
|
+
|
|
134
|
+
### Install the Agent Skill
|
|
135
|
+
|
|
136
|
+
Let the CLI detect the installed coding agent:
|
|
137
|
+
|
|
138
|
+
```console
|
|
19
139
|
requestshield agent setup
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Or select an agent explicitly:
|
|
143
|
+
|
|
144
|
+
```console
|
|
20
145
|
requestshield agent setup --codex
|
|
21
146
|
requestshield agent setup --claude
|
|
22
147
|
```
|
|
23
148
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
149
|
+
The CLI installs the Skill into:
|
|
150
|
+
|
|
151
|
+
- Codex: `~/.agents/skills/requestshield`
|
|
152
|
+
- Claude: `~/.claude/skills/requestshield`
|
|
153
|
+
|
|
154
|
+
If exactly one supported agent is detected, it is selected automatically. If
|
|
155
|
+
both are detected in an interactive terminal, the CLI asks which one to use.
|
|
156
|
+
If neither is detected, select one with `--codex` or `--claude`.
|
|
157
|
+
|
|
158
|
+
Existing Skill content is preserved. Add `--force` to replace it:
|
|
159
|
+
|
|
160
|
+
```console
|
|
161
|
+
requestshield agent setup --codex --force
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Restart the selected agent or start a new task after installation.
|
|
165
|
+
|
|
166
|
+
### Check for updates
|
|
167
|
+
|
|
168
|
+
```console
|
|
169
|
+
requestshield update check
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Checks the npm registry for the latest `@intellifend/requestshield` version.
|
|
173
|
+
When a newer version exists, the CLI displays the current and latest versions
|
|
174
|
+
and asks:
|
|
175
|
+
|
|
176
|
+
```text
|
|
177
|
+
Update to RequestShield <version>? (y/N):
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Entering `y` runs the equivalent of:
|
|
181
|
+
|
|
182
|
+
```console
|
|
183
|
+
npm install --global @intellifend/requestshield@<latest-version>
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
This command requires an interactive terminal, Node.js, and npm. It updates a
|
|
187
|
+
global npm installation; it does not replace a standalone Windows executable.
|
|
188
|
+
|
|
189
|
+
## Install with npm
|
|
190
|
+
|
|
191
|
+
Install globally:
|
|
192
|
+
|
|
193
|
+
```console
|
|
194
|
+
npm install --global @intellifend/requestshield
|
|
195
|
+
requestshield --help
|
|
196
|
+
requestshield --version
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Run a specific version without installing globally:
|
|
29
200
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
201
|
+
```console
|
|
202
|
+
npx --yes --package=@intellifend/requestshield@0.1.5 requestshield --help
|
|
203
|
+
npx --yes --package=@intellifend/requestshield@0.1.5 requestshield signin
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
To invoke the update command through npx, include the package name:
|
|
207
|
+
|
|
208
|
+
```console
|
|
209
|
+
npx --yes --package=@intellifend/requestshield@0.1.5 requestshield update check
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Do not run `npx update check`; npm interprets `update` as the name of a different
|
|
213
|
+
npm package.
|
|
214
|
+
|
|
215
|
+
## Local development
|
|
216
|
+
|
|
217
|
+
From the `requestshield-cli` directory:
|
|
218
|
+
|
|
219
|
+
```console
|
|
220
|
+
npm install
|
|
221
|
+
npm run lint
|
|
222
|
+
npm run typecheck
|
|
223
|
+
npm test
|
|
224
|
+
npm run build
|
|
225
|
+
node src/main.mjs --help
|
|
226
|
+
node src/main.mjs --version
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
The current `build` script validates the syntax of the `.mjs` source files. It
|
|
230
|
+
does not generate a standalone executable.
|
|
231
|
+
|
|
232
|
+
### Test the update flow locally
|
|
233
|
+
|
|
234
|
+
The manual update test mocks the registry and install operation, so it does not
|
|
235
|
+
publish a package or change the installed version:
|
|
236
|
+
|
|
237
|
+
```powershell
|
|
238
|
+
$env:REQUESTSHIELD_MOCK_LATEST_VERSION = "0.1.6"
|
|
239
|
+
npm run test:update-check:manual
|
|
240
|
+
Remove-Item Env:REQUESTSHIELD_MOCK_LATEST_VERSION
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
After entering `y`, the test prints `[MOCK] Would install ...`.
|
|
244
|
+
|
|
245
|
+
## Packaging the RequestShield Skill
|
|
246
|
+
|
|
247
|
+
The canonical Skill is stored at `../skills/requestshield`. Do not maintain a
|
|
248
|
+
second source copy inside this package.
|
|
249
|
+
|
|
250
|
+
Before npm creates the package, the `prepack` hook temporarily copies the
|
|
251
|
+
canonical Skill to `skills/requestshield`. The `postpack` hook removes that
|
|
252
|
+
generated copy after packaging.
|
|
253
|
+
|
|
254
|
+
Inspect the files that npm will publish:
|
|
255
|
+
|
|
256
|
+
```console
|
|
257
|
+
npm pack --dry-run
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Create a local tarball:
|
|
261
|
+
|
|
262
|
+
```console
|
|
263
|
+
npm pack
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Publish to npm
|
|
267
|
+
|
|
268
|
+
npm does not allow an existing package version to be overwritten. Check the
|
|
269
|
+
published version, merge the latest team changes, then choose a new version in
|
|
270
|
+
`package.json` before publishing.
|
|
271
|
+
|
|
272
|
+
```console
|
|
273
|
+
npm view @intellifend/requestshield version
|
|
274
|
+
npm run lint
|
|
275
|
+
npm run typecheck
|
|
276
|
+
npm test
|
|
277
|
+
npm pack --dry-run
|
|
278
|
+
npm publish --access public
|
|
279
|
+
```
|
|
34
280
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
281
|
+
Verify the published package:
|
|
282
|
+
|
|
283
|
+
```console
|
|
284
|
+
npm view @intellifend/requestshield version
|
|
285
|
+
npm dist-tag ls @intellifend/requestshield
|
|
286
|
+
npx --yes --package=@intellifend/requestshield@0.1.5 requestshield --version
|
|
287
|
+
```
|
|
41
288
|
|
|
42
289
|
## Management API contract
|
|
43
290
|
|
|
@@ -51,8 +298,8 @@ supplied.
|
|
|
51
298
|
}
|
|
52
299
|
```
|
|
53
300
|
|
|
54
|
-
The response contains `deviceCode`, `userCode`, `verificationUri`,
|
|
55
|
-
|
|
301
|
+
The response contains `deviceCode`, `userCode`, `verificationUri`, `expiresIn`,
|
|
302
|
+
and `interval`.
|
|
56
303
|
|
|
57
304
|
### Poll sign-in
|
|
58
305
|
|
|
@@ -65,63 +312,133 @@ metadata.
|
|
|
65
312
|
### Rotate keys
|
|
66
313
|
|
|
67
314
|
`POST /v1/cli/keys/rotate` with Bearer authentication and an empty JSON body.
|
|
68
|
-
The response contains `appKey` and one-time `apiSecret`.
|
|
315
|
+
The response contains `appKey` and the one-time `apiSecret`.
|
|
69
316
|
|
|
70
|
-
|
|
317
|
+
### List applications
|
|
71
318
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
319
|
+
`GET /v1/applications` with Bearer authentication and no request body. The API must
|
|
320
|
+
scope results to the authenticated user.
|
|
321
|
+
|
|
322
|
+
```json
|
|
323
|
+
{
|
|
324
|
+
"data": [
|
|
325
|
+
{
|
|
326
|
+
"appKey": "pk_AAAAAAAAAAAAAAAAAAAAAAAA",
|
|
327
|
+
"name": "Checkout",
|
|
328
|
+
"status": "pending",
|
|
329
|
+
"createdAt": "2026-09-11T00:00:00.000Z",
|
|
330
|
+
"updatedAt": "2026-09-11T00:00:00.000Z"
|
|
331
|
+
}
|
|
332
|
+
],
|
|
333
|
+
"nextCursor": null
|
|
334
|
+
}
|
|
77
335
|
```
|
|
78
|
-
## Quick start
|
|
79
336
|
|
|
80
|
-
|
|
337
|
+
Every application requires `appKey`, `name`, `status`, `createdAt`, and `updatedAt`.
|
|
338
|
+
`nextCursor` must be a non-empty string or `null`. An account with no applications
|
|
339
|
+
returns `200` with an empty `data` array. A missing or rejected session returns
|
|
340
|
+
`401`. The response must never contain an API Secret.
|
|
81
341
|
|
|
82
|
-
|
|
342
|
+
### Get an application
|
|
83
343
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
344
|
+
`GET /v1/applications/{appKey}` with Bearer authentication and no request body.
|
|
345
|
+
The path segment is URL-encoded by the CLI.
|
|
346
|
+
|
|
347
|
+
```json
|
|
348
|
+
{
|
|
349
|
+
"ok": true,
|
|
350
|
+
"data": {
|
|
351
|
+
"app_key": "app_123",
|
|
352
|
+
"name": "Website",
|
|
353
|
+
"status": "active"
|
|
354
|
+
}
|
|
355
|
+
}
|
|
91
356
|
```
|
|
92
357
|
|
|
93
|
-
|
|
358
|
+
`status` must be `ready`, `active`, or `deactivated`. The response App Key must
|
|
359
|
+
match the requested key. The CLI rebuilds the output from these three fields so
|
|
360
|
+
unexpected response fields cannot be printed.
|
|
94
361
|
|
|
95
|
-
|
|
96
|
-
|
|
362
|
+
### Get challenge volume
|
|
363
|
+
|
|
364
|
+
`GET /v1/applications/{appKey}/challenge-volume` with Bearer authentication and
|
|
365
|
+
optional `from`, `to`, and `granularity` query parameters.
|
|
366
|
+
|
|
367
|
+
```json
|
|
368
|
+
{
|
|
369
|
+
"ok": true,
|
|
370
|
+
"data": {
|
|
371
|
+
"app_key": "app_123",
|
|
372
|
+
"from": "2026-08-01T00:00:00Z",
|
|
373
|
+
"to": "2026-08-27T23:59:59Z",
|
|
374
|
+
"granularity": "day",
|
|
375
|
+
"challenge_count": 125430
|
|
376
|
+
}
|
|
377
|
+
}
|
|
97
378
|
```
|
|
98
379
|
|
|
99
|
-
|
|
380
|
+
The CLI requires a matching App Key, valid ordered timestamps, a non-empty
|
|
381
|
+
granularity, and a non-negative safe-integer `challenge_count`. It rebuilds the
|
|
382
|
+
output from these fields so unexpected API fields cannot be printed.
|
|
100
383
|
|
|
101
|
-
|
|
102
|
-
this npm package directory. The `prepack` hook temporarily copies the complete
|
|
103
|
-
skill into `skills/requestshield`, and `postpack` removes that generated copy
|
|
104
|
-
after npm creates the tarball. Do not edit the generated copy.
|
|
384
|
+
### Get billing information
|
|
105
385
|
|
|
106
|
-
|
|
386
|
+
`GET /v1/applications/{appKey}/billing` with Bearer authentication and no
|
|
387
|
+
request body.
|
|
107
388
|
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
389
|
+
```json
|
|
390
|
+
{
|
|
391
|
+
"ok": true,
|
|
392
|
+
"data": {
|
|
393
|
+
"plan": {
|
|
394
|
+
"tier": "pro",
|
|
395
|
+
"current_cycle": [
|
|
396
|
+
"2026-07-07T07:07:07",
|
|
397
|
+
"2027-07-07T07:07:07"
|
|
398
|
+
],
|
|
399
|
+
"billing": 1080,
|
|
400
|
+
"next_charge": "2027-07-07T07:07:07"
|
|
401
|
+
},
|
|
402
|
+
"usage": {
|
|
403
|
+
"monthly_quota": 100000,
|
|
404
|
+
"current_usage": 110000,
|
|
405
|
+
"overage_charge": 10
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
113
409
|
```
|
|
114
410
|
|
|
115
|
-
|
|
116
|
-
|
|
411
|
+
The CLI validates all documented fields and rebuilds the nested result so
|
|
412
|
+
unexpected response fields cannot be printed.
|
|
117
413
|
|
|
118
|
-
|
|
119
|
-
npm pack
|
|
120
|
-
npx --yes --package=./requestshield-0.1.0.tgz requestshield agent setup --codex
|
|
121
|
-
```
|
|
414
|
+
### Get the integration contract
|
|
122
415
|
|
|
123
|
-
|
|
416
|
+
`GET /v1/integration-contract` with Bearer authentication and no request body.
|
|
124
417
|
|
|
125
|
-
```
|
|
126
|
-
|
|
418
|
+
```json
|
|
419
|
+
{
|
|
420
|
+
"ok": true,
|
|
421
|
+
"data": {
|
|
422
|
+
"contract_version": "2026-08-27",
|
|
423
|
+
"browser": {
|
|
424
|
+
"script_url": "https://intellifend.ai/intellifend.js",
|
|
425
|
+
"token_header": "X-IntelliFend-Token",
|
|
426
|
+
"available_modes": ["manual"]
|
|
427
|
+
},
|
|
428
|
+
"backend": {
|
|
429
|
+
"supported_languages": ["java"],
|
|
430
|
+
"min_jdk": 17
|
|
431
|
+
},
|
|
432
|
+
"release_state": "released"
|
|
433
|
+
}
|
|
434
|
+
}
|
|
127
435
|
```
|
|
436
|
+
|
|
437
|
+
The CLI requires these core fields and preserves additional authoritative
|
|
438
|
+
contract fields returned by the API. Credential-shaped fields are rejected.
|
|
439
|
+
|
|
440
|
+
## Security notes
|
|
441
|
+
|
|
442
|
+
- Never place an access token or Secret Key in URLs, command arguments, logs,
|
|
443
|
+
test fixtures, or committed files.
|
|
444
|
+
- The CLI does not persist the Secret Key returned by `keys create`.
|
package/package.json
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "requestshield",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Customer CLI for IntelliFend RequestShield.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"requestshield": "src/main.mjs"
|
|
8
8
|
},
|
|
9
|
+
"publishConfig": {
|
|
10
|
+
"access": "public"
|
|
11
|
+
},
|
|
9
12
|
"files": [
|
|
10
13
|
"src/",
|
|
11
14
|
"skills/",
|
|
@@ -18,6 +21,7 @@
|
|
|
18
21
|
"build": "node scripts/check-package.mjs",
|
|
19
22
|
"lint": "node scripts/check-package.mjs",
|
|
20
23
|
"test": "node --test",
|
|
24
|
+
"test:update-check:manual": "node scripts/manual-update-check.mjs",
|
|
21
25
|
"typecheck": "tsc -p jsconfig.json --noEmit",
|
|
22
26
|
"prepack": "node scripts/package-skill.mjs stage",
|
|
23
27
|
"postpack": "node scripts/package-skill.mjs clean",
|
|
@@ -57,7 +57,7 @@ single CLI call or a short answer. Match on what the user wants, not on exact wo
|
|
|
57
57
|
| **Uninstall** | "remove it", "roll it back" | `references/integration-planning.md` (Detect existing integration only) → **Uninstalling**. |
|
|
58
58
|
| **Verify / troubleshoot** | "is it set up right?", "why is it not blocking?", a reason code | `references/integration-planning.md` (Detect existing integration only) → **Verifying**. For a reason code, also read `references/troubleshooting.md`. |
|
|
59
59
|
| **Challenge volume** | "how much traffic", "how many challenges", "show me the volume" | Ask for the time range first. `challenge volume` takes `--from`/`--to`/`--granularity`; a guessed window produces a confident wrong answer. Then run it with the App Key. |
|
|
60
|
-
| **Billing** | "am I being charged", "what plan", "what are my limits" | `requestshield get billing
|
|
60
|
+
| **Billing** | "am I being charged", "what plan", "what are my limits" | Resolve the application, then run `requestshield get billing <app-key>`. |
|
|
61
61
|
| **Service health** | "is the service up", "is it degraded" | `requestshield server`. |
|
|
62
62
|
| **Agent setup** | "set this up for Codex too", "install the skill for Claude" | Run `requestshield agent setup` for auto-detection, or pass the requested agent: `--agent codex` or `--agent claude`. This installs agent guidance; it does not mint keys or edit customer application code. |
|
|
63
63
|
| **Anything else** | | Look the command up in `references/cli.md`. If it is not there, run `requestshield --help` rather than guessing at a flag. |
|
|
@@ -120,10 +120,11 @@ requestshield apps get <app-key>
|
|
|
120
120
|
```
|
|
121
121
|
|
|
122
122
|
**auth.** `apps list` returns the applications the current user can access, each with
|
|
123
|
-
`
|
|
124
|
-
|
|
123
|
+
`appKey`, `name`, `status`, `createdAt`, and `updatedAt`; JSON output also includes
|
|
124
|
+
`nextCursor`. Use it to resolve a human-supplied app name to a key rather than asking
|
|
125
|
+
the user to retype one.
|
|
125
126
|
|
|
126
|
-
`apps get <app-key>` returns `
|
|
127
|
+
`apps get <app-key>` returns `app_key`, `name`, and `status`. Status distinguishes a
|
|
127
128
|
key that has never seen traffic (`ready`) from one in normal service (`active`) — which
|
|
128
129
|
is exactly the difference between "the integration is not wired up yet" and "it is
|
|
129
130
|
working", so check it before spending time debugging code.
|
|
@@ -161,11 +162,11 @@ mode's reference file.
|
|
|
161
162
|
## Billing
|
|
162
163
|
|
|
163
164
|
```bash
|
|
164
|
-
requestshield get billing
|
|
165
|
+
requestshield get billing <app-key>
|
|
165
166
|
```
|
|
166
167
|
|
|
167
|
-
**auth.** Current plan and usage for the application. Read-only;
|
|
168
|
-
user asks about cost or limits.
|
|
168
|
+
**auth.** Current plan and usage for the explicitly selected application. Read-only;
|
|
169
|
+
surface it when the user asks about cost or limits.
|
|
169
170
|
|
|
170
171
|
## Agent integration
|
|
171
172
|
|
package/src/agent-detector.mjs
CHANGED
|
@@ -12,9 +12,21 @@ import path from "node:path";
|
|
|
12
12
|
* @returns {Promise<Array<"codex" | "claude">>}
|
|
13
13
|
*/
|
|
14
14
|
export async function detectAgents(options = {}) {
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
|
|
15
|
+
|
|
16
|
+
const env = options.env ??
|
|
17
|
+
process.env;
|
|
18
|
+
|
|
19
|
+
const homeDir = options.homeDir ??
|
|
20
|
+
os.homedir();
|
|
21
|
+
|
|
22
|
+
const codexHome = env.CODEX_HOME ??
|
|
23
|
+
path.join(homeDir, ".codex");
|
|
24
|
+
|
|
25
|
+
const codexConfigPath =
|
|
26
|
+
path.join(codexHome, "config.toml");
|
|
27
|
+
|
|
28
|
+
const claudeConfigPath =
|
|
29
|
+
path.join(homeDir, ".claude.json");
|
|
18
30
|
|
|
19
31
|
// Executables prove the CLI is on PATH. Configuration files cover desktop
|
|
20
32
|
// installs and agents that were previously configured but are not on PATH.
|
|
@@ -29,8 +41,14 @@ export async function detectAgents(options = {}) {
|
|
|
29
41
|
|
|
30
42
|
/** @type {Array<"codex" | "claude">} */
|
|
31
43
|
const detected = [];
|
|
32
|
-
|
|
33
|
-
if (
|
|
44
|
+
|
|
45
|
+
if (codexCommand || codexConfig) {
|
|
46
|
+
detected.push("codex")
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
if (claudeCommand || claudeConfig || claudeState) {
|
|
50
|
+
detected.push("claude")
|
|
51
|
+
};
|
|
34
52
|
return detected;
|
|
35
53
|
}
|
|
36
54
|
|
|
@@ -41,19 +59,29 @@ export async function detectAgents(options = {}) {
|
|
|
41
59
|
* @param {NodeJS.ProcessEnv} env
|
|
42
60
|
*/
|
|
43
61
|
async function commandExists(command, env) {
|
|
44
|
-
|
|
45
|
-
const
|
|
46
|
-
|
|
62
|
+
|
|
63
|
+
const searchPath = env.PATH ??
|
|
64
|
+
env.Path ?? "";
|
|
65
|
+
|
|
66
|
+
const extensions =
|
|
67
|
+
process.platform === "win32"
|
|
68
|
+
? (env.PATHEXT ?? ".EXE;.CMD;.BAT;.COM")
|
|
69
|
+
.split(";")
|
|
70
|
+
.filter(Boolean)
|
|
47
71
|
: [""];
|
|
48
72
|
|
|
49
73
|
for (const directory of searchPath.split(path.delimiter)) {
|
|
50
|
-
if (!directory)
|
|
74
|
+
if (!directory) {
|
|
75
|
+
continue
|
|
76
|
+
};
|
|
77
|
+
|
|
51
78
|
for (const extension of extensions) {
|
|
52
79
|
try {
|
|
53
80
|
await access(
|
|
54
81
|
path.join(directory, `${command}${extension}`),
|
|
55
82
|
process.platform === "win32" ? constants.F_OK : constants.X_OK,
|
|
56
83
|
);
|
|
84
|
+
|
|
57
85
|
return true;
|
|
58
86
|
} catch {
|
|
59
87
|
// Continue through the remaining executable candidates.
|