@wirecat/cli-template 0.14.0 → 0.16.0
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/.github/workflows/ci.yml +17 -0
- package/AGENTS.md +56 -2
- package/CHANGELOG.md +46 -0
- package/README.md +12 -4
- package/biome.json +2 -2
- package/contracts/mcp-tools.json +2 -2
- package/dist/bin/clidev.js +2 -2
- package/dist/bundle/{chunk-LU4A2T7Y.js → all-profiles-FS7AEOE7.js} +8 -5
- package/dist/bundle/{anthropic-ICTW7CNQ.js → anthropic-5RN7BGDI.js} +3 -3
- package/dist/bundle/{app-server-B6BCKXR7.js → app-server-WGTKZQKJ.js} +28 -29
- package/dist/bundle/{bun-sqlite-JE6FJFQT.js → bun-sqlite-WK2IGBGD.js} +2 -2
- package/dist/bundle/{chunk-AS2PJNQ2.js → chunk-2MWNE4L3.js} +1 -1
- package/dist/bundle/{chunk-2DAXUNTS.js → chunk-5HHIPDNW.js} +1 -1
- package/dist/bundle/{chunk-YOJLIVGO.js → chunk-5KAYQKBK.js} +1 -1
- package/dist/bundle/{chunk-62JRF2JA.js → chunk-6WOJIAYA.js} +1 -1
- package/dist/bundle/chunk-7EUX7AZV.js +141 -0
- package/dist/bundle/{chunk-7F5VMLVK.js → chunk-ADFSSIV4.js} +1 -1
- package/dist/bundle/{chunk-U6QD3J3F.js → chunk-ATHZEV2Z.js} +2 -2
- package/dist/bundle/{chunk-UT5TQ6MD.js → chunk-BPMKAZSS.js} +8 -8
- package/dist/bundle/{chunk-DZLHY4IA.js → chunk-C3GNOEJP.js} +1 -1
- package/dist/bundle/{chunk-PIJUGF5F.js → chunk-CTBHQRX6.js} +1 -1
- package/dist/bundle/{chunk-LFLSV353.js → chunk-DEHBTFIC.js} +1 -1
- package/dist/bundle/{chunk-NVNUUHT5.js → chunk-EA3TMI4A.js} +8 -8
- package/dist/bundle/{chunk-BEBD27QT.js → chunk-EILS4BTQ.js} +16 -18
- package/dist/bundle/{chunk-BVLPNNEL.js → chunk-ENDBOYQR.js} +14 -14
- package/dist/bundle/{chunk-6AW4DDK4.js → chunk-ETJXPB6A.js} +1 -1
- package/dist/bundle/{chunk-LATYBJ4T.js → chunk-FMO6F5Q2.js} +1 -1
- package/dist/bundle/{chunk-RJ7AS7UB.js → chunk-HTYLT6ME.js} +24 -7
- package/dist/bundle/{chunk-F34HGYWF.js → chunk-JFXWLQ2L.js} +1 -1
- package/dist/bundle/{chunk-IZKXJJ7V.js → chunk-JJZCPBH3.js} +29 -6
- package/dist/bundle/{chunk-G7W53MQP.js → chunk-LRHX62ZF.js} +2 -2
- package/dist/bundle/{chunk-SOYOOU2D.js → chunk-MBBOINK4.js} +2 -2
- package/dist/bundle/{chunk-BM5ZCDPQ.js → chunk-MEXT6XDP.js} +2 -2
- package/dist/bundle/{chunk-R2JKPHH5.js → chunk-NVPWZF67.js} +1 -1
- package/dist/bundle/{chunk-45244QQ6.js → chunk-OF56L2JU.js} +2 -2
- package/dist/bundle/{chunk-4PA6DJ7F.js → chunk-OGTRPW2K.js} +3 -3
- package/dist/bundle/{chunk-VXOR76ZL.js → chunk-ORV4EGNC.js} +1 -1
- package/dist/bundle/{chunk-TJJ2XSJP.js → chunk-QGOOPPEW.js} +2 -2
- package/dist/bundle/{chunk-NH6LZ3H3.js → chunk-RFJKNFVF.js} +3 -3
- package/dist/bundle/{chunk-R5RYPD23.js → chunk-RYOAQCVJ.js} +1 -1
- package/dist/bundle/{chunk-66VMJGV6.js → chunk-SKBRW5U3.js} +1 -1
- package/dist/bundle/{chunk-BWBZCYUN.js → chunk-TXHCL75B.js} +43 -6
- package/dist/bundle/{chunk-QXOSPYM3.js → chunk-VPCXYY46.js} +1 -1
- package/dist/bundle/{chunk-IOJ2DTCY.js → chunk-WDWP5N6M.js} +2 -0
- package/dist/bundle/{chunk-HYTHTSJP.js → chunk-WM5AMTRY.js} +4 -4
- package/dist/bundle/{chunk-ASHVHS52.js → chunk-YNROUY3R.js} +10 -10
- package/dist/bundle/{chunk-DQIBGCF3.js → chunk-Z5NL6YNU.js} +2 -2
- package/dist/bundle/{chunk-5SAF3XOL.js → chunk-ZSY4WAGI.js} +28 -21
- package/dist/bundle/clidev.js +3 -3
- package/dist/bundle/{command-contract-JMVMT5HT.js → command-contract-ZDU73EPH.js} +9 -9
- package/dist/bundle/{decode-NXB5UKMO.js → decode-QMLOGZ6R.js} +2 -2
- package/dist/bundle/{embed-IKZ24BMC.js → embed-PIR2LJR2.js} +4 -4
- package/dist/bundle/{embedder-GMQ24DOQ.js → embedder-6KBRPAEQ.js} +4 -4
- package/dist/bundle/{first-run-MDD4SIUK.js → first-run-JO3CMY3Z.js} +7 -7
- package/dist/bundle/{first-screen-376CXGXJ.js → first-screen-3T5IXTFL.js} +10 -10
- package/dist/bundle/{node-sqlite-73Z4SFOA.js → node-sqlite-LIK6OYNF.js} +2 -2
- package/dist/bundle/{oauth-EVTPAMZP.js → oauth-7FVF7HQQ.js} +4 -4
- package/dist/bundle/{open-46WZAPJ3.js → open-CRZDEATN.js} +2 -2
- package/dist/bundle/{openai-GWRDAHDU.js → openai-WAJ6WREQ.js} +11 -32
- package/dist/bundle/{program-B3CY3FP7.js → program-ZFFFPBRS.js} +2263 -300
- package/dist/bundle/{prompt-IVEYRLS5.js → prompt-QQIVHO3M.js} +3 -3
- package/dist/bundle/{recognize-WVEKHODM.js → recognize-4KLBZDEC.js} +2 -2
- package/dist/bundle/{remote-4K5VPMC7.js → remote-BABMZTHA.js} +5 -5
- package/dist/bundle/{rerank-V24UJZYJ.js → rerank-P3IQQJIL.js} +4 -4
- package/dist/bundle/{chunk-EMHCXXNJ.js → serve-25SSAKRZ.js} +6 -4
- package/dist/bundle/server-G4GCDMYI.js +52 -0
- package/dist/bundle/{chunk-PX2KP4QE.js → server-P4XUYY5A.js} +27 -7
- package/dist/bundle/{state-ZPYGECVP.js → state-QCQALQBJ.js} +3 -3
- package/dist/bundle/{store-6JQCLPQF.js → store-ZECPRGGH.js} +7 -7
- package/dist/bundle/store-maintenance-command-ECUO5G6L.js +42 -0
- package/dist/commands/comments.d.ts +3 -0
- package/dist/commands/comments.d.ts.map +1 -0
- package/dist/commands/comments.js +114 -0
- package/dist/commands/comments.js.map +1 -0
- package/dist/commands/session.d.ts +3 -0
- package/dist/commands/session.d.ts.map +1 -0
- package/dist/commands/session.js +96 -0
- package/dist/commands/session.js.map +1 -0
- package/dist/config.d.ts +2 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +4 -2
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +83 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +58 -0
- package/dist/context.js.map +1 -0
- package/dist/program.d.ts.map +1 -1
- package/dist/program.js +26 -5
- package/dist/program.js.map +1 -1
- package/dist/sample/comments.d.ts +61 -0
- package/dist/sample/comments.d.ts.map +1 -0
- package/dist/sample/comments.js +39 -0
- package/dist/sample/comments.js.map +1 -0
- package/dist/sample/transport.d.ts +42 -0
- package/dist/sample/transport.d.ts.map +1 -0
- package/dist/sample/transport.js +152 -0
- package/dist/sample/transport.js.map +1 -0
- package/dist/token.d.ts +16 -0
- package/dist/token.d.ts.map +1 -0
- package/dist/token.js +32 -0
- package/dist/token.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/commands.md +234 -12
- package/docs/configuration.md +1 -1
- package/docs/dev/reference-clis.md +3 -2
- package/docs/dev/test-matrix.md +36 -5
- package/docs/index.md +4 -3
- package/docs/security.md +4 -2
- package/kit/dist/new.js +6 -3
- package/lint/overrides.json +9 -1
- package/package.json +3 -4
- package/scripts/test-matrix-untested.ts +19 -0
- package/skills/clidev-cli/SKILL.md +1 -1
- package/src/commands/comments.ts +167 -0
- package/src/commands/session.ts +144 -0
- package/src/comments.test.ts +258 -0
- package/src/config.ts +5 -2
- package/src/context.ts +78 -0
- package/src/mcp.test.ts +71 -76
- package/src/program.test.ts +39 -17
- package/src/program.ts +30 -5
- package/src/sample/comments.ts +51 -0
- package/src/sample/transport.test.ts +117 -0
- package/src/sample/transport.ts +184 -0
- package/src/testing/fake-comments.ts +167 -0
- package/src/testing/harness.ts +51 -0
- package/src/token.ts +42 -0
- package/src/version.ts +1 -1
- package/dist/bundle/all-profiles-NVB2HT2S.js +0 -24
- package/dist/bundle/chunk-GUFPQZUA.js +0 -48
- package/dist/bundle/chunk-NL2DQPT7.js +0 -2
- package/dist/bundle/mcp-KHUZOJO6.js +0 -82
- package/dist/bundle/mcp-MZHWJXAE.js +0 -152
- package/dist/bundle/serve-PJWSOV7F.js +0 -19
- package/dist/bundle/server-2ZN7KZHZ.js +0 -40
- package/dist/bundle/server-5VYM7CCF.js +0 -53
- package/dist/bundle/store-maintenance-command-7XICIYHW.js +0 -42
- package/dist/commands/doctor.d.ts +0 -77
- package/dist/commands/doctor.d.ts.map +0 -1
- package/dist/commands/doctor.js +0 -74
- package/dist/commands/doctor.js.map +0 -1
- package/dist/commands/mcp.d.ts +0 -3
- package/dist/commands/mcp.d.ts.map +0 -1
- package/dist/commands/mcp.js +0 -97
- package/dist/commands/mcp.js.map +0 -1
- package/dist/mcp.d.ts +0 -29
- package/dist/mcp.d.ts.map +0 -1
- package/dist/mcp.js +0 -98
- package/dist/mcp.js.map +0 -1
- package/src/commands/doctor.ts +0 -86
- package/src/commands/mcp.ts +0 -130
- package/src/mcp-http.test.ts +0 -172
- package/src/mcp.ts +0 -140
package/.github/workflows/ci.yml
CHANGED
|
@@ -57,6 +57,23 @@ jobs:
|
|
|
57
57
|
- run: pnpm test
|
|
58
58
|
- run: pnpm smoke:node
|
|
59
59
|
|
|
60
|
+
# The template's own check: a CLI made from it has no kit/. Needs the network for npm and pnpm installs.
|
|
61
|
+
kit-e2e:
|
|
62
|
+
if: github.repository == 'WireCatLabs/cli-template'
|
|
63
|
+
runs-on: ubuntu-latest
|
|
64
|
+
timeout-minutes: 30
|
|
65
|
+
steps:
|
|
66
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
67
|
+
with:
|
|
68
|
+
persist-credentials: false
|
|
69
|
+
- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
|
|
70
|
+
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
|
71
|
+
with:
|
|
72
|
+
node-version: 24
|
|
73
|
+
cache: pnpm
|
|
74
|
+
- run: pnpm install --frozen-lockfile --ignore-scripts
|
|
75
|
+
- run: pnpm kit:e2e
|
|
76
|
+
|
|
60
77
|
version:
|
|
61
78
|
if: github.event_name == 'pull_request'
|
|
62
79
|
runs-on: ubuntu-latest
|
package/AGENTS.md
CHANGED
|
@@ -10,13 +10,67 @@ touches (`WC-<AREA>-<n>`) in the commit message and the pull request. The rules
|
|
|
10
10
|
|
|
11
11
|
[docs/dev/DESIGN.md](docs/dev/DESIGN.md) holds the owner's answers to the
|
|
12
12
|
[design interview](docs/dev/skills/design-interview/SKILL.md) and the decisions made since. Read it before changing
|
|
13
|
-
what a command does, and write a new decision there. Learn
|
|
14
|
-
|
|
13
|
+
what a command does, and write a new decision there. Learn how a command reaches a service from the sample below,
|
|
14
|
+
and the domain, the store and its commands from the reference CLI.
|
|
15
15
|
|
|
16
16
|
<!-- cli-template:reference-cli:start -->
|
|
17
17
|
The reference CLI is not chosen yet; see [Reference CLIs](docs/dev/reference-clis.md).
|
|
18
18
|
<!-- cli-template:reference-cli:end -->
|
|
19
19
|
|
|
20
|
+
## The sample: what to keep, what to replace
|
|
21
|
+
|
|
22
|
+
<!-- cspell:words gcal SECR -->
|
|
23
|
+
|
|
24
|
+
The template ships one working command group, `comments`, against a made-up service, Example Comments, whose address
|
|
25
|
+
never resolves. It shows every pattern a command that reaches a service needs, each tested against a strict fake of
|
|
26
|
+
the service. Build your first command on it: keep the patterns, replace the service. Delete the rest of the sample
|
|
27
|
+
once your own commands cover every pattern below; until then `pnpm test` keeps it working. A CLI made before the
|
|
28
|
+
sample has no `src/sample/`; read it in [cli-template](https://github.com/WireCatLabs/cli-template/tree/main/src).
|
|
29
|
+
Comments marked `SAMPLE:` in the code say what to replace.
|
|
30
|
+
|
|
31
|
+
Keep, the same for every service:
|
|
32
|
+
|
|
33
|
+
- **Token storage**, `src/token.ts`: cli-base `Credentials`, the environment variable, then the keyring, then a
|
|
34
|
+
private file; a run with moved folders never replaces the owner's entry (WC-SECR-4, WC-SECR-24).
|
|
35
|
+
- **Sign-in**, `src/commands/session.ts`: `session start | status | end | list`. The token is read hidden or from
|
|
36
|
+
stdin, never as an argument, and checked against the service before it is kept (WC-ACCT-12, WC-SECR-5). Replace
|
|
37
|
+
the `me` check with your service's. A service with OAuth signs in through cli-core's oauth module instead, as
|
|
38
|
+
[gcal-cli](https://github.com/WireCatLabs/gcal-cli) does (WC-SECR-22).
|
|
39
|
+
- **The command context**, `src/context.ts`: settings, the keyring and the run come from cli-core's `baseContext`
|
|
40
|
+
only, and every request runs inside its `run()`, with the `events` it gives passed to the transport. That is what
|
|
41
|
+
bounds a command by `--timeout` and records a run named after it (WC-LIFE-5, WC-LIFE-15).
|
|
42
|
+
- **Permissions**, `src/program.ts` and `src/config.ts`: the program hands cli-core the whole `configuration`, and
|
|
43
|
+
each command path is its own key (WC-PERM-22). A command that reaches the service another way, such as an
|
|
44
|
+
`api call`, also checks the key of the command it does the same as, with `alsoChecks`.
|
|
45
|
+
- **Writes**, `write` in `src/commands/comments.ts`: the guard asks or refuses by the command's key, the send journal
|
|
46
|
+
records the attempt, the answer carries `operation_id`, and a write is never retried: one that got no answer is
|
|
47
|
+
`outcome_unknown` (WC-PERM-13, WC-PERM-17, WC-OUT-10, WC-LIFE-9). `--dry-run` and `<PREFIX>_READ_ONLY` are
|
|
48
|
+
cli-core's; declare no `--dry-run` of your own.
|
|
49
|
+
- **MCP and doctor**, `src/program.ts`: cli-core's `appMcpCommand` and `appDoctorCommand`, never a copy of them.
|
|
50
|
+
Rewrite `name` and `untrusted` for your service (WC-MCP-11).
|
|
51
|
+
- **The test harness**, `src/testing/harness.ts`: the CLI through its own `run()`, with a memory keyring and the fake
|
|
52
|
+
in place of the network (WC-TEST-2, WC-TEST-3, WC-TEST-6).
|
|
53
|
+
|
|
54
|
+
Replace, your service's own:
|
|
55
|
+
|
|
56
|
+
- **The transport**, `src/sample/transport.ts`: the token in a header only, no redirects, a timeout, cli-core's
|
|
57
|
+
`Pacer`, cli-base's error codes and no retry (WC-SECR-6, WC-SECR-7, WC-OUT-20). Keep its shape; take the address,
|
|
58
|
+
the header and the error mapping from your service's documentation.
|
|
59
|
+
- **Wire shapes and the mapper**, `src/sample/comments.ts`: each field name from the documentation or a captured
|
|
60
|
+
answer, never from memory; no wire type leaves this file (WC-ARCH-3).
|
|
61
|
+
- **The commands**, `src/commands/comments.ts`: a list with `withPaging`, `withQuery` and `answerEntity`, so
|
|
62
|
+
`--json=a,b` and the MCP schema come from one schema (WC-CMD-19, WC-CMD-20); `show`; `create` and `update`.
|
|
63
|
+
- **The strict fake**, `src/testing/fake-comments.ts`: it refuses an unknown path, parameter or field, so a name typed
|
|
64
|
+
from memory fails a test instead of reaching the owner's account. Build yours from the documentation.
|
|
65
|
+
- **The tests**, `src/comments.test.ts` and `src/sample/transport.test.ts`. Keep each case for your commands: a deny
|
|
66
|
+
stops a read before any request, `--dry-run` sends nothing, a lost write is `outcome_unknown`, a recorded run is
|
|
67
|
+
named after its command, and the token reaches no output, run record or file.
|
|
68
|
+
|
|
69
|
+
Remove the sample only once your own commands and their tests cover each pattern above: the skeleton alone is below
|
|
70
|
+
the coverage floor, and the floor is never lowered (WC-TEST-11). To remove it, unmount `commentsCommand` in `src/program.ts` and delete `src/sample/`,
|
|
71
|
+
`src/commands/comments.ts`, `src/testing/fake-comments.ts` and their tests. Then run `pnpm generate`,
|
|
72
|
+
`pnpm exec cli-contract contracts/plan.json --update` and `pnpm test:matrix`.
|
|
73
|
+
|
|
20
74
|
## Template-owned files
|
|
21
75
|
|
|
22
76
|
This CLI was made from [cli-template](https://github.com/WireCatLabs/cli-template). `template.json` names the files
|
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,52 @@ Notable changes to `@wirecat/cli-template`. One section per version, newest firs
|
|
|
5
5
|
|
|
6
6
|
<!-- cspell:words clawhub gcal katex openclaw smol whatsapp -->
|
|
7
7
|
|
|
8
|
+
## 0.16.0 — 06.11.2026
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **`pnpm kit:e2e` runs in CI and checks more.** It makes a CLI with a short name and one with a long name, since a
|
|
13
|
+
rename changes line lengths, and runs `pnpm lint` in each besides `ci:quick` and `test:coverage`. A rename that
|
|
14
|
+
broke Biome's formatting passed it before. The `kit-e2e` job in `.github/workflows/ci.yml` runs it on every pull
|
|
15
|
+
request and merge, in this repository only: a CLI made from the template has no `kit/` and skips the job.
|
|
16
|
+
|
|
17
|
+
- **A working sample shows every pattern a command that reaches a service needs.** `comments list | show | create |
|
|
18
|
+
update` and `session start | status | end | list` reach Example Comments, a made-up service whose address never
|
|
19
|
+
resolves. The token is kept with cli-base's `Credentials`; every request runs inside cli-core's `baseContext` run
|
|
20
|
+
with its `events`; the transport keeps the token in a header, times out and never retries; writes pass the guard
|
|
21
|
+
and the send journal and answer with `operation_id`, and a lost write is `outcome_unknown`. The tests run against a
|
|
22
|
+
strict fake that refuses unknown paths, parameters and fields. `AGENTS.md` lists what to keep and what to replace,
|
|
23
|
+
pattern by pattern, with the rules each follows, and the code marks each replaceable part with `SAMPLE:`. Before,
|
|
24
|
+
the template had no sample, and agents copied the patterns from other CLIs, their bugs included.
|
|
25
|
+
|
|
26
|
+
### Changed — may break callers
|
|
27
|
+
|
|
28
|
+
- **MCP and doctor are cli-core's.** `src/program.ts` mounts `appMcpCommand` and `appDoctorCommand`, as gcal-cli
|
|
29
|
+
does, in place of the template's own `src/mcp.ts`, `src/commands/mcp.ts` and `src/commands/doctor.ts`. `mcp` gains
|
|
30
|
+
`config`, `add`, `check`, `--profiles` and `--permission`; `doctor` gains `--online`, and its answer `store` and
|
|
31
|
+
`profile_lock`. A CLI made from an older skeleton swaps them the same way and removes `@modelcontextprotocol/server`
|
|
32
|
+
and `@modelcontextprotocol/client` from its dependencies.
|
|
33
|
+
|
|
34
|
+
### Fixed
|
|
35
|
+
|
|
36
|
+
- **A new CLI passes `pnpm lint` from its first commit.** Renaming `clidev` changes line lengths, so Biome wraps some
|
|
37
|
+
lines differently, and the first commit's hook or CI failed on formatting. `new`'s next steps now run
|
|
38
|
+
`pnpm lint:fix` after `pnpm install`, and `kit:e2e` does the same before it runs `pnpm lint`.
|
|
39
|
+
- **The MCP server applies the permission table too (WC-PERM-23).** `src/mcp.ts` built its tools without it, so a
|
|
40
|
+
command a profile denies was offered to an agent as available and ran. It now passes `permissions` to
|
|
41
|
+
`toolsFromCommands` and to each tool call: the command is listed as unavailable and refused before it runs. A CLI
|
|
42
|
+
made from an older skeleton adds `permissions` in both places by hand.
|
|
43
|
+
|
|
44
|
+
## 0.15.0 — 06.11.2026
|
|
45
|
+
|
|
46
|
+
### Fixed
|
|
47
|
+
|
|
48
|
+
- **A `deny` in a profile stops a command again.** The skeleton handed cli-core only `resolveSettings`, and cli-core
|
|
49
|
+
checks a command's key only when it gets the permission table too, so a denied read still ran and `--dry-run`
|
|
50
|
+
previewed every command as allowed. `src/program.ts` now passes the whole `configuration`, and `src/config.ts`
|
|
51
|
+
declares `commandPermissions()`, so each command is checked against its own path. A CLI made from an older
|
|
52
|
+
skeleton makes the same two changes by hand.
|
|
53
|
+
|
|
8
54
|
## 0.14.0 — 06.11.2026
|
|
9
55
|
|
|
10
56
|
### Added
|
package/README.md
CHANGED
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
|
|
6
6
|
`clidev` is a command-line tool started from [cli-template](https://github.com/WireCatLabs/cli-template), the kit for
|
|
7
7
|
new WireCat CLIs. It is a working skeleton: the shared root commands, the settings, the agent skill and the MCP
|
|
8
|
-
server run, and every check of the WireCat standards passes.
|
|
9
|
-
with the tool's own
|
|
8
|
+
server run, and every check of the WireCat standards passes. Its one service is a sample, Example Comments, made up
|
|
9
|
+
to show how a command reaches a service; its address never resolves. Replace this page with the tool's own
|
|
10
|
+
introduction once the CLI reaches its real service.
|
|
10
11
|
|
|
11
12
|
To start a new CLI from the template:
|
|
12
13
|
|
|
@@ -30,6 +31,8 @@ such as `personal` in `clidev personal config show`; none is ever assumed. `CLID
|
|
|
30
31
|
| Command | What it does |
|
|
31
32
|
| --- | --- |
|
|
32
33
|
| `clidev doctor` | Checks this installation: version, paths, settings and profiles, without the network |
|
|
34
|
+
| `clidev personal session start` | Signs the profile in with the service's token, kept in the OS keyring |
|
|
35
|
+
| `clidev personal comments list` | The sample: lists, shows, creates and updates comments in Example Comments |
|
|
33
36
|
| `clidev commands --json` | Prints every command as JSON, for agents and scripts |
|
|
34
37
|
| `clidev personal config show` | Shows each setting and where it came from |
|
|
35
38
|
| `clidev skill install` | Installs the agent skill for Claude Code, Codex, Gemini CLI and OpenClaw; `--for hermes` for Hermes Agent |
|
|
@@ -57,6 +60,9 @@ keeps the shared files in step later, so a CLI made today does not drift from on
|
|
|
57
60
|
- **`upgrade`** merges each template change into your CLI file by file, and asks before it touches a file you changed.
|
|
58
61
|
- **The skeleton runs.** The shared root commands, settings with permissions, the agent skill and the MCP server
|
|
59
62
|
work before a line of your own code.
|
|
63
|
+
- **A sample shows every pattern.** `comments` reaches a made-up service the way a real command must: the token in
|
|
64
|
+
the keyring, every request inside cli-core's run, writes behind the guard, and a strict fake in the tests.
|
|
65
|
+
`AGENTS.md` lists what to keep and what to replace.
|
|
60
66
|
- **Every check is wired in:** lint, types, tests with a coverage floor, command contracts, the docs checks and the
|
|
61
67
|
release script.
|
|
62
68
|
|
|
@@ -66,7 +72,8 @@ The copy tool is described in [kit/README.md](kit/README.md).
|
|
|
66
72
|
|
|
67
73
|
A profile is a name you choose for one account, such as `personal` or `work`. It is the first word of every command
|
|
68
74
|
that uses an account. No profile is ever assumed: a command without one stops and lists the profiles on this
|
|
69
|
-
computer.
|
|
75
|
+
computer. `session start` signs a profile in; its token goes to the OS keyring, or to a private file where no
|
|
76
|
+
keyring works.
|
|
70
77
|
|
|
71
78
|
## Settings and permissions
|
|
72
79
|
|
|
@@ -80,7 +87,8 @@ The skeleton connects to no service, keeps no messages and has no commands of it
|
|
|
80
87
|
|
|
81
88
|
## Security
|
|
82
89
|
|
|
83
|
-
`clidev` keeps its settings and state on this computer and
|
|
90
|
+
`clidev` keeps its settings and state on this computer, and its token in the OS keyring. Its only service is the
|
|
91
|
+
sample's, whose address never resolves. See
|
|
84
92
|
[Security](docs/security.md), and report a vulnerability privately as [SECURITY.md](SECURITY.md) says.
|
|
85
93
|
|
|
86
94
|
## When it does not work
|
package/biome.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"extends": ["./config/wirecat/biome.base.json"],
|
|
6
6
|
"overrides": [
|
|
7
7
|
{
|
|
8
|
-
"includes": ["src/**", "
|
|
8
|
+
"includes": ["src/**", "!**/*.test.ts"],
|
|
9
9
|
"linter": {
|
|
10
10
|
"rules": {
|
|
11
11
|
"style": {
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"patterns": [
|
|
16
16
|
{
|
|
17
17
|
"group": ["@modelcontextprotocol/**"],
|
|
18
|
-
"message": "
|
|
18
|
+
"message": "cli-core's appMcpCommand serves MCP; commands and services do not know the protocol"
|
|
19
19
|
}
|
|
20
20
|
]
|
|
21
21
|
}
|
package/contracts/mcp-tools.json
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"type": "object"
|
|
19
19
|
},
|
|
20
20
|
"command": {
|
|
21
|
-
"description": "a command clidev_tools_search returned: \"
|
|
21
|
+
"description": "a command clidev_tools_search returned: \"session list\"",
|
|
22
22
|
"minLength": 1,
|
|
23
23
|
"type": "string"
|
|
24
24
|
}
|
|
@@ -542,7 +542,7 @@
|
|
|
542
542
|
"type": "object"
|
|
543
543
|
},
|
|
544
544
|
"command": {
|
|
545
|
-
"description": "a command clidev_tools_search returned: \"
|
|
545
|
+
"description": "a command clidev_tools_search returned: \"session list\"",
|
|
546
546
|
"minLength": 1,
|
|
547
547
|
"type": "string"
|
|
548
548
|
}
|
package/dist/bin/clidev.js
CHANGED
|
@@ -9,7 +9,7 @@ if (
|
|
|
9
9
|
(words[0] === "--version" || words[0] === "-V") &&
|
|
10
10
|
!Object.keys(process.env).some((key) => key.endsWith("_TEST_ARGV_LOG"))
|
|
11
11
|
) {
|
|
12
|
-
process.stdout.write("0.
|
|
12
|
+
process.stdout.write("0.16.0\n")
|
|
13
13
|
} else {
|
|
14
14
|
// Before the bundle compiles: the bundle's own call comes after its chunks.
|
|
15
15
|
module.enableCompileCache()
|
|
@@ -28,7 +28,7 @@ if (
|
|
|
28
28
|
: next(specifier, context),
|
|
29
29
|
})
|
|
30
30
|
}
|
|
31
|
-
const chunks = ["../bundle/all-profiles-
|
|
31
|
+
const chunks = ["../bundle/all-profiles-FS7AEOE7.js","../bundle/anthropic-5RN7BGDI.js","../bundle/app-server-WGTKZQKJ.js","../bundle/bun-ILPS6AYA.js","../bundle/bun-sqlite-WK2IGBGD.js","../bundle/decode-QMLOGZ6R.js","../bundle/dist-ESHIQU4M.js","../bundle/echarts-DRDGGHJT.js","../bundle/embed-PIR2LJR2.js","../bundle/embedder-6KBRPAEQ.js","../bundle/first-screen-3T5IXTFL.js","../bundle/instructions-EOQOXY6V.js","../bundle/mcp-7HBLFGCW.js","../bundle/node-52WF2326.js","../bundle/node-P4E63KXA.js","../bundle/node-TLZSIHIJ.js","../bundle/node-sqlite-LIK6OYNF.js","../bundle/oauth-7FVF7HQQ.js","../bundle/open-CRZDEATN.js","../bundle/openai-WAJ6WREQ.js","../bundle/process-YIQPKLZI.js","../bundle/program-ZFFFPBRS.js","../bundle/prompt-QQIVHO3M.js","../bundle/recognize-4KLBZDEC.js","../bundle/remote-BABMZTHA.js","../bundle/rerank-P3IQQJIL.js","../bundle/serve-25SSAKRZ.js","../bundle/server-G4GCDMYI.js","../bundle/server-P4XUYY5A.js","../bundle/state-QCQALQBJ.js","../bundle/store-ZECPRGGH.js","../bundle/store-maintenance-command-ECUO5G6L.js"]
|
|
32
32
|
if (((words) => words
|
|
33
33
|
.filter((word) => !word.startsWith("-"))
|
|
34
34
|
.slice(0, 2)
|
|
@@ -9,10 +9,14 @@ import {
|
|
|
9
9
|
StdioServerTransport,
|
|
10
10
|
callerOf,
|
|
11
11
|
serveStdio
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-JFXWLQ2L.js";
|
|
13
13
|
import {
|
|
14
14
|
McpServer
|
|
15
15
|
} from "./chunk-5D4AEUVA.js";
|
|
16
|
+
import "./chunk-ORV4EGNC.js";
|
|
17
|
+
import "./chunk-3WDYHOAF.js";
|
|
18
|
+
import "./chunk-WDWP5N6M.js";
|
|
19
|
+
import "./chunk-Y5E2WNWB.js";
|
|
16
20
|
import {
|
|
17
21
|
__name
|
|
18
22
|
} from "./chunk-ZVVMGPBJ.js";
|
|
@@ -251,7 +255,7 @@ var serveAllProfilesOverStdio = /* @__PURE__ */ __name(async (options, io = {})
|
|
|
251
255
|
}, "serveAllProfilesOverStdio");
|
|
252
256
|
var serveAllProfilesOverHttp = /* @__PURE__ */ __name(async (options, http) => {
|
|
253
257
|
const { build, close } = allProfilesServer(options);
|
|
254
|
-
const { serveOverHttp } = await import("./serve-
|
|
258
|
+
const { serveOverHttp } = await import("./serve-25SSAKRZ.js");
|
|
255
259
|
const listening = await serveOverHttp(build, {
|
|
256
260
|
...http,
|
|
257
261
|
appName: options.command,
|
|
@@ -271,11 +275,10 @@ var serveAllProfilesOverHttp = /* @__PURE__ */ __name(async (options, http) => {
|
|
|
271
275
|
}, "close")
|
|
272
276
|
};
|
|
273
277
|
}, "serveAllProfilesOverHttp");
|
|
274
|
-
|
|
275
278
|
export {
|
|
276
279
|
CHILD_IDLE_MS,
|
|
277
|
-
withProfile,
|
|
278
280
|
allProfilesServer,
|
|
281
|
+
serveAllProfilesOverHttp,
|
|
279
282
|
serveAllProfilesOverStdio,
|
|
280
|
-
|
|
283
|
+
withProfile
|
|
281
284
|
};
|
|
@@ -2,11 +2,11 @@ import { createRequire as __bundleRequire } from "node:module";
|
|
|
2
2
|
const require = __bundleRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
checkedOptions
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-RYOAQCVJ.js";
|
|
6
6
|
import {
|
|
7
7
|
messagesFor,
|
|
8
8
|
systemFor
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-FMO6F5Q2.js";
|
|
10
10
|
import {
|
|
11
11
|
Anthropic
|
|
12
12
|
} from "./chunk-ADLS6FVG.js";
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
optional,
|
|
16
16
|
strictObject,
|
|
17
17
|
string
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-WDWP5N6M.js";
|
|
19
19
|
import "./chunk-Y5E2WNWB.js";
|
|
20
20
|
import {
|
|
21
21
|
__name
|
|
@@ -3,11 +3,10 @@ const require = __bundleRequire(import.meta.url);
|
|
|
3
3
|
import {
|
|
4
4
|
PER_RUN,
|
|
5
5
|
envelope
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-BWBZCYUN.js";
|
|
6
|
+
} from "./chunk-EILS4BTQ.js";
|
|
8
7
|
import {
|
|
9
8
|
mcpUrlOf
|
|
10
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-TXHCL75B.js";
|
|
11
10
|
import {
|
|
12
11
|
answeredWire
|
|
13
12
|
} from "./chunk-VS5LGSTM.js";
|
|
@@ -17,20 +16,20 @@ import {
|
|
|
17
16
|
registerCommands,
|
|
18
17
|
runCommandForAgent,
|
|
19
18
|
toolsFromCommands
|
|
20
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-BPMKAZSS.js";
|
|
21
20
|
import {
|
|
22
21
|
agentJson,
|
|
23
22
|
skillResource
|
|
24
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-WM5AMTRY.js";
|
|
25
24
|
import {
|
|
26
25
|
StdioServerTransport,
|
|
27
26
|
serveStdio
|
|
28
|
-
} from "./chunk-
|
|
29
|
-
import "./chunk-
|
|
30
|
-
import "./chunk-
|
|
31
|
-
import "./chunk-
|
|
32
|
-
import "./chunk-
|
|
33
|
-
import "./chunk-
|
|
27
|
+
} from "./chunk-JFXWLQ2L.js";
|
|
28
|
+
import "./chunk-JJZCPBH3.js";
|
|
29
|
+
import "./chunk-ZSY4WAGI.js";
|
|
30
|
+
import "./chunk-CTBHQRX6.js";
|
|
31
|
+
import "./chunk-5HHIPDNW.js";
|
|
32
|
+
import "./chunk-2MWNE4L3.js";
|
|
34
33
|
import "./chunk-7Z4HR6GO.js";
|
|
35
34
|
import {
|
|
36
35
|
appInstructions
|
|
@@ -40,11 +39,11 @@ import {
|
|
|
40
39
|
} from "./chunk-5D4AEUVA.js";
|
|
41
40
|
import {
|
|
42
41
|
mcpHttpMarker
|
|
43
|
-
} from "./chunk-
|
|
44
|
-
import "./chunk-
|
|
45
|
-
import "./chunk-
|
|
46
|
-
import "./chunk-
|
|
47
|
-
import "./chunk-
|
|
42
|
+
} from "./chunk-ETJXPB6A.js";
|
|
43
|
+
import "./chunk-C3GNOEJP.js";
|
|
44
|
+
import "./chunk-MBBOINK4.js";
|
|
45
|
+
import "./chunk-FMO6F5Q2.js";
|
|
46
|
+
import "./chunk-MEXT6XDP.js";
|
|
48
47
|
import {
|
|
49
48
|
DEFAULT_OUTPUT_BYTES,
|
|
50
49
|
changesAuthorityAt,
|
|
@@ -54,25 +53,25 @@ import {
|
|
|
54
53
|
readOnlyLockOf,
|
|
55
54
|
readsOverMcpAt,
|
|
56
55
|
rootOf2 as rootOf
|
|
57
|
-
} from "./chunk-
|
|
58
|
-
import "./chunk-
|
|
59
|
-
import "./chunk-
|
|
56
|
+
} from "./chunk-HTYLT6ME.js";
|
|
57
|
+
import "./chunk-ORV4EGNC.js";
|
|
58
|
+
import "./chunk-ATHZEV2Z.js";
|
|
60
59
|
import "./chunk-VOTEB3AN.js";
|
|
61
|
-
import "./chunk-
|
|
62
|
-
import "./chunk-
|
|
63
|
-
import "./chunk-
|
|
60
|
+
import "./chunk-EA3TMI4A.js";
|
|
61
|
+
import "./chunk-NVPWZF67.js";
|
|
62
|
+
import "./chunk-5KAYQKBK.js";
|
|
64
63
|
import "./chunk-3WDYHOAF.js";
|
|
65
|
-
import "./chunk-
|
|
66
|
-
import "./chunk-
|
|
64
|
+
import "./chunk-QGOOPPEW.js";
|
|
65
|
+
import "./chunk-RFJKNFVF.js";
|
|
67
66
|
import "./chunk-3MDNAYQA.js";
|
|
68
67
|
import "./chunk-CGFQT3LQ.js";
|
|
69
|
-
import "./chunk-
|
|
70
|
-
import "./chunk-
|
|
71
|
-
import "./chunk-
|
|
68
|
+
import "./chunk-Z5NL6YNU.js";
|
|
69
|
+
import "./chunk-OF56L2JU.js";
|
|
70
|
+
import "./chunk-6WOJIAYA.js";
|
|
72
71
|
import {
|
|
73
72
|
CliError,
|
|
74
73
|
mcpErrorResult
|
|
75
|
-
} from "./chunk-
|
|
74
|
+
} from "./chunk-WDWP5N6M.js";
|
|
76
75
|
import "./chunk-Y5E2WNWB.js";
|
|
77
76
|
import {
|
|
78
77
|
__name
|
|
@@ -193,7 +192,7 @@ var serveAppOverStdio = /* @__PURE__ */ __name(async (command, context, options)
|
|
|
193
192
|
var serveAppOverHttp = /* @__PURE__ */ __name(async (command, context, options, http) => {
|
|
194
193
|
const { app } = options;
|
|
195
194
|
const { build } = createAppServer(command, context, options);
|
|
196
|
-
const { serveOverHttp } = await import("./serve-
|
|
195
|
+
const { serveOverHttp } = await import("./serve-25SSAKRZ.js");
|
|
197
196
|
const listening = await serveOverHttp(build, {
|
|
198
197
|
...http,
|
|
199
198
|
appName: app.command,
|
|
@@ -3,8 +3,8 @@ const require = __bundleRequire(import.meta.url);
|
|
|
3
3
|
import {
|
|
4
4
|
loadVectorExtension,
|
|
5
5
|
vectorExtension
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-DEHBTFIC.js";
|
|
7
|
+
import "./chunk-WDWP5N6M.js";
|
|
8
8
|
import {
|
|
9
9
|
importFrom
|
|
10
10
|
} from "./chunk-Y5E2WNWB.js";
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { createRequire as __bundleRequire } from "node:module";
|
|
2
|
+
const require = __bundleRequire(import.meta.url);
|
|
3
|
+
import {
|
|
4
|
+
CliError,
|
|
5
|
+
isCliError
|
|
6
|
+
} from "./chunk-WDWP5N6M.js";
|
|
7
|
+
import {
|
|
8
|
+
__name
|
|
9
|
+
} from "./chunk-ZVVMGPBJ.js";
|
|
10
|
+
|
|
11
|
+
// node_modules/.pnpm/@wirecat+cli-base@0.77.1_commander@15.0.0_esbuild@0.28.2_typescript@7.0.2_vitest@5.0.5/node_modules/@wirecat/cli-base/dist/http/body.js
|
|
12
|
+
var interrupted = /* @__PURE__ */ __name((signal) => isCliError(signal.reason) ? signal.reason : new CliError(signal.reason instanceof Error && signal.reason.name === "TimeoutError" ? "timeout" : "cancelled", "HTTP response read was interrupted"), "interrupted");
|
|
13
|
+
var checked = /* @__PURE__ */ __name((signal) => {
|
|
14
|
+
if (signal?.aborted)
|
|
15
|
+
throw interrupted(signal);
|
|
16
|
+
}, "checked");
|
|
17
|
+
var abortable = /* @__PURE__ */ __name(async (pending, signal) => {
|
|
18
|
+
if (!signal)
|
|
19
|
+
return pending;
|
|
20
|
+
let abort = /* @__PURE__ */ __name(() => {
|
|
21
|
+
}, "abort");
|
|
22
|
+
const stopped = new Promise((_, reject) => {
|
|
23
|
+
abort = /* @__PURE__ */ __name(() => reject(interrupted(signal)), "abort");
|
|
24
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
25
|
+
if (signal.aborted)
|
|
26
|
+
abort();
|
|
27
|
+
});
|
|
28
|
+
try {
|
|
29
|
+
return await Promise.race([pending, stopped]);
|
|
30
|
+
} finally {
|
|
31
|
+
signal.removeEventListener("abort", abort);
|
|
32
|
+
}
|
|
33
|
+
}, "abortable");
|
|
34
|
+
var readJsonResponse = /* @__PURE__ */ __name(async (response, options) => {
|
|
35
|
+
const { maxBytes, signal } = options ?? {};
|
|
36
|
+
if (!Number.isSafeInteger(maxBytes) || maxBytes < 1)
|
|
37
|
+
throw new CliError("validation_error", "maxBytes must be a positive safe integer");
|
|
38
|
+
if (signal !== void 0 && !(signal instanceof AbortSignal))
|
|
39
|
+
throw new CliError("validation_error", "signal must be an AbortSignal");
|
|
40
|
+
if (signal?.aborted) {
|
|
41
|
+
void response.body?.cancel().catch(() => {
|
|
42
|
+
});
|
|
43
|
+
throw interrupted(signal);
|
|
44
|
+
}
|
|
45
|
+
const length = response.headers.get("content-length");
|
|
46
|
+
if (length !== null && (!/^\d+$/.test(length) || Number(length) > maxBytes)) {
|
|
47
|
+
void response.body?.cancel().catch(() => {
|
|
48
|
+
});
|
|
49
|
+
throw new CliError("invalid_response", "HTTP response exceeds the byte budget");
|
|
50
|
+
}
|
|
51
|
+
if (!response.body)
|
|
52
|
+
throw new CliError("invalid_response", "HTTP response has no body");
|
|
53
|
+
if (response.body.locked)
|
|
54
|
+
throw new CliError("invalid_response", "HTTP response body is already in use");
|
|
55
|
+
const reader = response.body.getReader();
|
|
56
|
+
const chunks = [];
|
|
57
|
+
let bytes = 0;
|
|
58
|
+
try {
|
|
59
|
+
for (; ; ) {
|
|
60
|
+
checked(signal);
|
|
61
|
+
const part = await abortable(reader.read(), signal);
|
|
62
|
+
checked(signal);
|
|
63
|
+
if (part.done)
|
|
64
|
+
break;
|
|
65
|
+
if (!(part.value instanceof Uint8Array))
|
|
66
|
+
throw new CliError("invalid_response", "HTTP response is not bytes");
|
|
67
|
+
bytes += part.value.byteLength;
|
|
68
|
+
if (bytes > maxBytes)
|
|
69
|
+
throw new CliError("invalid_response", "HTTP response exceeds the byte budget");
|
|
70
|
+
if (part.value.byteLength)
|
|
71
|
+
chunks.push(new Uint8Array(part.value));
|
|
72
|
+
}
|
|
73
|
+
const body = new Uint8Array(bytes);
|
|
74
|
+
let offset = 0;
|
|
75
|
+
for (const chunk of chunks) {
|
|
76
|
+
body.set(chunk, offset);
|
|
77
|
+
offset += chunk.byteLength;
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(body));
|
|
81
|
+
} catch {
|
|
82
|
+
throw new CliError("invalid_response", "HTTP response is not valid UTF-8 JSON");
|
|
83
|
+
}
|
|
84
|
+
} catch (error) {
|
|
85
|
+
checked(signal);
|
|
86
|
+
if (isCliError(error))
|
|
87
|
+
throw error;
|
|
88
|
+
throw new CliError("network_error", "HTTP response could not be read");
|
|
89
|
+
} finally {
|
|
90
|
+
void reader.cancel().catch(() => {
|
|
91
|
+
});
|
|
92
|
+
reader.releaseLock();
|
|
93
|
+
}
|
|
94
|
+
}, "readJsonResponse");
|
|
95
|
+
|
|
96
|
+
// node_modules/.pnpm/@wirecat+cli-base@0.77.1_commander@15.0.0_esbuild@0.28.2_typescript@7.0.2_vitest@5.0.5/node_modules/@wirecat/cli-base/dist/http/index.js
|
|
97
|
+
var parseRetryAfter = /* @__PURE__ */ __name((header, now) => {
|
|
98
|
+
if (!header)
|
|
99
|
+
return void 0;
|
|
100
|
+
const trimmed = header.trim();
|
|
101
|
+
if (/^\d+$/.test(trimmed))
|
|
102
|
+
return Number(trimmed) * 1e3;
|
|
103
|
+
const at = Date.parse(trimmed);
|
|
104
|
+
if (Number.isNaN(at))
|
|
105
|
+
return void 0;
|
|
106
|
+
const delta = at - now().getTime();
|
|
107
|
+
return delta > 0 ? delta : void 0;
|
|
108
|
+
}, "parseRetryAfter");
|
|
109
|
+
var parseRateLimitReset = /* @__PURE__ */ __name((header, now) => {
|
|
110
|
+
if (!header)
|
|
111
|
+
return void 0;
|
|
112
|
+
const seconds = Number(header.trim());
|
|
113
|
+
if (!Number.isFinite(seconds))
|
|
114
|
+
return void 0;
|
|
115
|
+
const delta = seconds * 1e3 - now().getTime();
|
|
116
|
+
return delta > 0 ? delta : void 0;
|
|
117
|
+
}, "parseRateLimitReset");
|
|
118
|
+
var providerWaitMs = /* @__PURE__ */ __name((headers, now) => parseRetryAfter(headers.get("retry-after"), now) ?? parseRateLimitReset(headers.get("x-ratelimit-reset"), now), "providerWaitMs");
|
|
119
|
+
var statusToCode = /* @__PURE__ */ __name((status) => {
|
|
120
|
+
if (status === 400 || status === 422)
|
|
121
|
+
return "validation_error";
|
|
122
|
+
if (status === 401)
|
|
123
|
+
return "authentication_error";
|
|
124
|
+
if (status === 403)
|
|
125
|
+
return "permission_error";
|
|
126
|
+
if (status === 404)
|
|
127
|
+
return "not_found";
|
|
128
|
+
if (status === 408)
|
|
129
|
+
return "timeout";
|
|
130
|
+
if (status === 429)
|
|
131
|
+
return "rate_limited";
|
|
132
|
+
if (status === 502 || status === 503 || status === 504)
|
|
133
|
+
return "provider_unavailable";
|
|
134
|
+
return "provider_error";
|
|
135
|
+
}, "statusToCode");
|
|
136
|
+
|
|
137
|
+
export {
|
|
138
|
+
readJsonResponse,
|
|
139
|
+
providerWaitMs,
|
|
140
|
+
statusToCode
|
|
141
|
+
};
|
|
@@ -3,10 +3,10 @@ const require = __bundleRequire(import.meta.url);
|
|
|
3
3
|
import {
|
|
4
4
|
readSharedSection,
|
|
5
5
|
writeSharedSection
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-QGOOPPEW.js";
|
|
7
7
|
import {
|
|
8
8
|
CliError
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-WDWP5N6M.js";
|
|
10
10
|
import {
|
|
11
11
|
__name
|
|
12
12
|
} from "./chunk-ZVVMGPBJ.js";
|