cngkit 1.1.7 → 1.1.9
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 +261 -82
- package/dist/{chunk-EQEIX7N5.js → chunk-575IBOIA.js} +2 -2
- package/dist/{chunk-EQEIX7N5.js.map → chunk-575IBOIA.js.map} +1 -1
- package/dist/{chunk-QEZQGKFX.js → chunk-CHSTTMTO.js} +2 -2
- package/dist/{chunk-TZKXST4G.js → chunk-LWZPSJVC.js} +48 -20
- package/dist/chunk-LWZPSJVC.js.map +1 -0
- package/dist/{chunk-Z4DDLEWR.js → chunk-NTF45QBC.js} +4 -12
- package/dist/chunk-NTF45QBC.js.map +1 -0
- package/dist/{chunk-HUZZPV5E.js → chunk-OKKJBRUU.js} +16 -12
- package/dist/chunk-OKKJBRUU.js.map +1 -0
- package/dist/chunk-OTQRKCFP.js +139 -0
- package/dist/chunk-OTQRKCFP.js.map +1 -0
- package/dist/{chunk-VI5XQH3U.js → chunk-WPBMAXXM.js} +3 -3
- package/dist/{chunk-VI5XQH3U.js.map → chunk-WPBMAXXM.js.map} +1 -1
- package/dist/cli.js +8 -8
- package/dist/cli.js.map +1 -1
- package/dist/commands/coderoom/index.js +4 -4
- package/dist/commands/coderoom/index.js.map +1 -1
- package/dist/commands/coderoom/join.js +5 -5
- package/dist/commands/coderoom/share.js +5 -5
- package/dist/commands/index.js +4 -4
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/knowledges/audiences.js +6 -6
- package/dist/commands/knowledges/files.js +6 -6
- package/dist/commands/knowledges/glob.js +6 -6
- package/dist/commands/knowledges/grep.js +6 -6
- package/dist/commands/knowledges/index.js +4 -4
- package/dist/commands/knowledges/index.js.map +1 -1
- package/dist/commands/knowledges/list.js +6 -6
- package/dist/commands/knowledges/read.js +6 -6
- package/dist/commands/knowledges/search.js +6 -6
- package/dist/commands/knowledges/status.js +6 -6
- package/dist/commands/login.js +5 -5
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/scrub.js +7 -7
- package/dist/commands/scrub.js.map +1 -1
- package/dist/commands/transcripts.js +9 -9
- package/dist/commands/transcripts.js.map +1 -1
- package/package.json +6 -1
- package/dist/chunk-HUZZPV5E.js.map +0 -1
- package/dist/chunk-TZKXST4G.js.map +0 -1
- package/dist/chunk-XDXRVTPK.js +0 -18
- package/dist/chunk-XDXRVTPK.js.map +0 -1
- package/dist/chunk-Z4DDLEWR.js.map +0 -1
- /package/dist/{chunk-QEZQGKFX.js.map → chunk-CHSTTMTO.js.map} +0 -0
package/README.md
CHANGED
|
@@ -1,130 +1,309 @@
|
|
|
1
1
|
# cngkit
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/cngkit)
|
|
4
|
+
[](https://nodejs.org/)
|
|
5
|
+
|
|
6
|
+
Curly.ng's operator CLI for shared code rooms, safe local cleanup, local agent transcript
|
|
7
|
+
inspection, and terminal access to the hosted Harness knowledge catalog.
|
|
8
|
+
|
|
9
|
+
`cngkit` is built for developers and AI agents who need practical commands that work
|
|
10
|
+
well in terminals, scripts, and coding assistants. Human-facing status lines use Ink
|
|
11
|
+
styling when the terminal supports color. Data-heavy output stays plain and easy to pipe.
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
Run it without installing:
|
|
4
16
|
|
|
5
17
|
```bash
|
|
6
|
-
npx cngkit
|
|
18
|
+
npx --yes cngkit@latest --help
|
|
7
19
|
```
|
|
8
20
|
|
|
9
|
-
|
|
10
|
-
the Cloudflare-backed Harness knowledges catalog:
|
|
21
|
+
Or install it globally:
|
|
11
22
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
- `cngkit scrub [path] --yes` rewrites detected secret values inline with `[CNGKIT_SECRET:<detector>:<verified|unverified>]` placeholders.
|
|
17
|
-
- `cngkit transcripts list [--source all|codex|claude] [--limit n]` lists recent local Claude/Codex transcript files.
|
|
18
|
-
- `cngkit transcripts read <path-or-session-id> [--limit n]` prints normalized user/assistant transcript entries.
|
|
19
|
-
- `cngkit transcripts grep <query> [--limit n] [--file-limit n]` searches recent local transcript entries.
|
|
20
|
-
- `cngkit knowledges status` prints the remote catalog state.
|
|
21
|
-
- `cngkit knowledges audiences` lists available audience filters.
|
|
22
|
-
- `cngkit knowledges search <query> [--limit n]` runs semantic search against Cloudflare Vectorize (default limit 5).
|
|
23
|
-
- `cngkit knowledges list [query] [--limit n]` lists known subskills (default limit 25).
|
|
24
|
-
- `cngkit knowledges files [query] [--audience id] [--limit n]` lists uploaded catalog files (default limit 25).
|
|
25
|
-
- `cngkit knowledges read <file-path> [--offset n] [--limit n]` reads a catalog file excerpt (default limit 200).
|
|
26
|
-
- `cngkit knowledges grep <pattern> [--path path] [--include glob] [--output-mode content|files_with_matches|count] [--context n] [--case-insensitive]` searches catalog file contents (default mode `content`, default path `/`).
|
|
27
|
-
- `cngkit knowledges glob [pattern] [--path path]` lists catalog files by supported glob pattern (default pattern `**/*.md`, default path `/`).
|
|
28
|
-
- `.git/` and files ignored by the repo's `.gitignore` are not synced.
|
|
29
|
-
- Later changes override earlier changes for the MVP conflict rule.
|
|
23
|
+
```bash
|
|
24
|
+
npm install -g cngkit
|
|
25
|
+
cngkit --help
|
|
26
|
+
```
|
|
30
27
|
|
|
31
|
-
|
|
28
|
+
Check the installed version:
|
|
32
29
|
|
|
33
30
|
```bash
|
|
34
|
-
cngkit --
|
|
35
|
-
cngkit scrub --help
|
|
36
|
-
cngkit transcripts --help
|
|
37
|
-
cngkit knowledges --help
|
|
38
|
-
cngkit knowledges read --help
|
|
39
|
-
cngkit knowledges grep --help
|
|
40
|
-
cngkit knowledges glob --help
|
|
31
|
+
cngkit --version
|
|
41
32
|
```
|
|
42
33
|
|
|
43
|
-
|
|
34
|
+
`cngkit` requires Node.js 20 or newer.
|
|
44
35
|
|
|
45
|
-
|
|
46
|
-
- `--version` prints the installed `cngkit` version.
|
|
47
|
-
- `--help` / `-h` prints the progressive help for the current command.
|
|
36
|
+
## What It Does
|
|
48
37
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
38
|
+
```bash
|
|
39
|
+
cngkit login
|
|
40
|
+
cngkit coderoom share
|
|
41
|
+
cngkit coderoom join <room-code>
|
|
42
|
+
cngkit scrub [path]
|
|
43
|
+
cngkit transcripts list --limit 12
|
|
44
|
+
cngkit knowledges search "cloudflare backend" --limit 3
|
|
45
|
+
cngkit knowledges read /libraries/lib-cloudflare/SUBSKILL.md --limit 80
|
|
46
|
+
```
|
|
52
47
|
|
|
53
|
-
|
|
54
|
-
through the Ink runner in `src/cli/command-runner.tsx`. The route files are interface
|
|
55
|
-
adapters only. Command behavior lives under `src/features/<feature>/`, and shared
|
|
56
|
-
runtime concerns such as config, output, browser opening, and API client construction
|
|
57
|
-
live under `src/shared/`. `tsup` emits a file-preserving ESM build so the published
|
|
58
|
-
package contains `dist/cli.js` plus `dist/commands/**`; the private workspace client
|
|
59
|
-
stays bundled while public runtime packages remain normal package dependencies.
|
|
48
|
+
The CLI currently has four main jobs:
|
|
60
49
|
|
|
61
|
-
|
|
50
|
+
- **Coderoom**: start or join a live shared working-tree room.
|
|
51
|
+
- **Scrub**: scan local files for secrets and optionally mask them inline.
|
|
52
|
+
- **Transcripts**: inspect local Claude and Codex transcript files from the terminal.
|
|
53
|
+
- **Knowledges**: search and read the hosted Harness knowledge catalog.
|
|
54
|
+
|
|
55
|
+
## Coderoom
|
|
56
|
+
|
|
57
|
+
Coderoom is a live room for quickly sharing a working tree with another developer or agent.
|
|
58
|
+
One machine starts a room, another joins with the room code, and the Curly backend relays
|
|
59
|
+
file changes.
|
|
60
|
+
|
|
61
|
+
Start a room:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
cngkit coderoom share
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Join a room:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
cngkit coderoom join <room-code>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Use your own room code:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
cngkit coderoom share design-review-01
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Coderoom deliberately skips `.git/` and files ignored by `.gitignore`. It is a live relay,
|
|
80
|
+
not durable cloud storage or a backup system. The current conflict rule is simple: the latest
|
|
81
|
+
received change wins.
|
|
82
|
+
|
|
83
|
+
## Harness Knowledges
|
|
84
|
+
|
|
85
|
+
The `knowledges` commands read the Cloudflare-backed Harness catalog from Curly.ng. They are
|
|
86
|
+
read-only and designed for AI-friendly terminal use.
|
|
87
|
+
|
|
88
|
+
Check catalog health:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
cngkit knowledges status
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Find relevant knowledge:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
cngkit knowledges search "cloudflare backend" --limit 3
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Read a catalog file:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
cngkit knowledges read /libraries/lib-cloudflare/SUBSKILL.md --limit 80
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
List matching files:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
cngkit knowledges glob "**/*.md" --path /libraries/lib-cloudflare
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Search inside files:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
cngkit knowledges grep Cloudflare --path /libraries/lib-cloudflare --output-mode files_with_matches
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Return JSON for another tool:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
cngkit knowledges status --json
|
|
122
|
+
cngkit knowledges search "vector search" --limit 5 --json
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Catalog path shortcuts are supported. For example:
|
|
126
|
+
|
|
127
|
+
```text
|
|
128
|
+
/libraries/lib-cloudflare/SUBSKILL.md
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
maps to:
|
|
132
|
+
|
|
133
|
+
```text
|
|
134
|
+
skills/knowledges/subskills/libraries/lib-cloudflare/SUBSKILL.md
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Secret Scrubbing
|
|
138
|
+
|
|
139
|
+
`scrub` scans a file or directory with TruffleHog and prints a redacted report.
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
cngkit scrub .
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Inline masking rewrites files, so it is gated behind `--yes`:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
cngkit scrub . --yes
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Masked values use this format:
|
|
152
|
+
|
|
153
|
+
```text
|
|
154
|
+
[CNGKIT_SECRET:<detector>:<verified|unverified>]
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
`scrub` requires the `trufflehog` binary on `PATH`.
|
|
158
|
+
|
|
159
|
+
macOS install:
|
|
62
160
|
|
|
63
161
|
```bash
|
|
64
162
|
brew install trufflehog
|
|
65
163
|
```
|
|
66
164
|
|
|
67
|
-
|
|
165
|
+
Safety notes:
|
|
166
|
+
|
|
167
|
+
- The default mode is report-only.
|
|
168
|
+
- Raw secret values are never printed.
|
|
169
|
+
- `--mask` is accepted as a compatibility alias, but inline changes still require `--yes`.
|
|
68
170
|
|
|
69
171
|
## Local Agent Transcripts
|
|
70
172
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
173
|
+
`transcripts` reads local JSONL files from:
|
|
174
|
+
|
|
175
|
+
- `~/.codex/sessions`
|
|
176
|
+
- `~/.codex/archived_sessions`
|
|
177
|
+
- `~/.claude/projects`
|
|
178
|
+
- `~/.claude/history.jsonl`
|
|
179
|
+
|
|
180
|
+
List recent transcript files:
|
|
74
181
|
|
|
75
182
|
```bash
|
|
76
183
|
cngkit transcripts list --limit 12
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Read a transcript by path or partial session id:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
77
189
|
cngkit transcripts read <path-or-session-id> --source codex --limit 80
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Search recent transcript entries:
|
|
193
|
+
|
|
194
|
+
```bash
|
|
78
195
|
cngkit transcripts grep "deploy failed" --source all --file-limit 60 --limit 20
|
|
79
196
|
```
|
|
80
197
|
|
|
81
|
-
|
|
82
|
-
|
|
198
|
+
Transcript commands are local-only. They do not upload transcript content to Curly.ng.
|
|
199
|
+
By default, they print user and assistant text and skip internal prompt, hook, and tool noise.
|
|
200
|
+
Use `--include-internal` when debugging transcript plumbing.
|
|
83
201
|
|
|
84
|
-
##
|
|
202
|
+
## Backend Selection
|
|
85
203
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
204
|
+
By default, `cngkit` talks to:
|
|
205
|
+
|
|
206
|
+
```text
|
|
207
|
+
https://curly.ng
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Override the backend for one command:
|
|
89
211
|
|
|
90
212
|
```bash
|
|
91
|
-
cngkit
|
|
92
|
-
cngkit coderoom join <room-code>
|
|
213
|
+
cngkit --api-base-url https://curly.ng knowledges status
|
|
93
214
|
```
|
|
94
215
|
|
|
95
|
-
|
|
96
|
-
shared workspace: a room code acts like a share link, connected machines act like
|
|
97
|
-
collaborators, and file events act like the activity stream. Current Coderoom
|
|
98
|
-
rooms are live relays, not durable cloud storage.
|
|
216
|
+
Or with an environment variable:
|
|
99
217
|
|
|
100
|
-
|
|
218
|
+
```bash
|
|
219
|
+
CNGKIT_API_BASE_URL=https://curly.ng cngkit knowledges status
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Help
|
|
101
223
|
|
|
102
|
-
|
|
103
|
-
Curly API. These commands are read-only:
|
|
224
|
+
Help is baked into the CLI as Markdown:
|
|
104
225
|
|
|
105
226
|
```bash
|
|
106
|
-
cngkit
|
|
107
|
-
cngkit
|
|
108
|
-
cngkit knowledges
|
|
109
|
-
cngkit
|
|
110
|
-
cngkit knowledges read
|
|
111
|
-
cngkit
|
|
112
|
-
|
|
227
|
+
cngkit --help
|
|
228
|
+
cngkit help
|
|
229
|
+
cngkit help knowledges
|
|
230
|
+
cngkit coderoom --help
|
|
231
|
+
cngkit knowledges read --help
|
|
232
|
+
cngkit transcripts --help
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Help uses terminal Markdown rendering in interactive terminals. Status, warnings, and errors
|
|
236
|
+
use Ink color when the terminal supports it, but `--json`, file reads, glob results, grep
|
|
237
|
+
results, and piped output stay clean.
|
|
238
|
+
|
|
239
|
+
## Terminal UI Stack
|
|
240
|
+
|
|
241
|
+
`cngkit` uses the Ink family without adding a custom command framework:
|
|
242
|
+
|
|
243
|
+
- **Pastel** owns command and subcommand routing through files under `src/commands/`.
|
|
244
|
+
- **Ink** owns terminal rendering through built-in components such as `<Text>`.
|
|
245
|
+
- **marked-terminal** owns terminal Markdown rendering for help screens.
|
|
246
|
+
- **Zod** owns option and argument schemas for each route.
|
|
247
|
+
|
|
248
|
+
So yes, subcommands are built in through Pastel's nested route files. Adding a
|
|
249
|
+
subcommand is normally a new `.tsx` file under the matching command folder:
|
|
250
|
+
|
|
251
|
+
```text
|
|
252
|
+
src/commands/
|
|
253
|
+
coderoom/
|
|
254
|
+
share.tsx cngkit coderoom share
|
|
255
|
+
join.tsx cngkit coderoom join
|
|
256
|
+
knowledges/
|
|
257
|
+
read.tsx cngkit knowledges read
|
|
258
|
+
grep.tsx cngkit knowledges grep
|
|
259
|
+
glob.tsx cngkit knowledges glob
|
|
113
260
|
```
|
|
114
261
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
262
|
+
The CLI does not hand-roll ANSI escape codes. Status styles go through Ink's built-in
|
|
263
|
+
`<Text color="..." bold dimColor>` support, and help screens use a shared Chalk-backed
|
|
264
|
+
Markdown theme through `marked-terminal`. Commands that return content for agents or shell
|
|
265
|
+
pipelines write raw lines instead.
|
|
266
|
+
|
|
267
|
+
## For Contributors
|
|
268
|
+
|
|
269
|
+
The package source lives in `apps/cng`.
|
|
270
|
+
|
|
271
|
+
```text
|
|
272
|
+
src/
|
|
273
|
+
cli/ Pastel bootstrap support, help text, option schemas, Ink output runner
|
|
274
|
+
commands/ Thin Pastel route files
|
|
275
|
+
features/ Command behavior grouped by feature
|
|
276
|
+
shared/ Config, output, browser, API client, shared command utilities
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
The route files under `src/commands/` should stay thin. Put behavior in
|
|
280
|
+
`src/features/<feature>/`, and put cross-feature runtime helpers in `src/shared/`.
|
|
281
|
+
For output, use the shared `CommandOutput` methods:
|
|
282
|
+
|
|
283
|
+
- `success`, `warning`, `info`, `muted`, and `error` for human-facing terminal status.
|
|
284
|
+
- `markdown` for help screens and terminal-only Markdown display.
|
|
285
|
+
- `raw` for JSON, file content, file paths, grep results, and anything another tool may parse.
|
|
286
|
+
|
|
287
|
+
Useful local checks:
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
pnpm --filter cngkit run typecheck
|
|
291
|
+
pnpm --filter cngkit run lint
|
|
292
|
+
pnpm --filter cngkit run build
|
|
293
|
+
pnpm --filter cngkit run smoke
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Release and install the newest npm package on the current machine:
|
|
297
|
+
|
|
298
|
+
```bash
|
|
299
|
+
pnpm --filter cngkit run deploy
|
|
300
|
+
```
|
|
121
301
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
Claude `read`/`grep` tool convention.
|
|
302
|
+
That command runs typecheck, lint, build, smoke, npm pack dry-run, npm publish, registry
|
|
303
|
+
verification, `npm install -g cngkit@latest`, and a final global `cngkit --version` check.
|
|
125
304
|
|
|
126
|
-
|
|
127
|
-
|
|
305
|
+
The package build uses `tsup` to emit a file-preserving ESM build. The published binary is
|
|
306
|
+
`dist/cli.js`, and Pastel discovers command files under `dist/commands/**`.
|
|
128
307
|
|
|
129
308
|
## License
|
|
130
309
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/shared/config.ts
|
|
2
2
|
import { randomBytes, randomUUID } from "crypto";
|
|
3
3
|
import process from "process";
|
|
4
|
-
var packageVersion = "1.1.
|
|
4
|
+
var packageVersion = "1.1.9";
|
|
5
5
|
var defaultApiBaseUrl = "https://curly.ng";
|
|
6
6
|
function resolveApiBaseUrl(options) {
|
|
7
7
|
return options.apiBaseUrl ?? process.env.CNGKIT_API_BASE_URL ?? defaultApiBaseUrl;
|
|
@@ -19,4 +19,4 @@ export {
|
|
|
19
19
|
createRoomCode,
|
|
20
20
|
createPeerId
|
|
21
21
|
};
|
|
22
|
-
//# sourceMappingURL=chunk-
|
|
22
|
+
//# sourceMappingURL=chunk-575IBOIA.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/shared/config.ts"],"sourcesContent":["import { randomBytes, randomUUID } from \"node:crypto\";\nimport process from \"node:process\";\n\nexport const packageVersion = \"1.1.
|
|
1
|
+
{"version":3,"sources":["../src/shared/config.ts"],"sourcesContent":["import { randomBytes, randomUUID } from \"node:crypto\";\nimport process from \"node:process\";\n\nexport const packageVersion = \"1.1.9\";\nexport const defaultApiBaseUrl = \"https://curly.ng\";\n\nexport type GlobalCommandOptions = {\n apiBaseUrl?: string;\n};\n\nexport function resolveApiBaseUrl(options: GlobalCommandOptions): string {\n return options.apiBaseUrl ?? process.env.CNGKIT_API_BASE_URL ?? defaultApiBaseUrl;\n}\n\nexport function createRoomCode(): string {\n return randomBytes(4).toString(\"hex\").toUpperCase();\n}\n\nexport function createPeerId(): string {\n return randomUUID();\n}\n"],"mappings":";AAAA,SAAS,aAAa,kBAAkB;AACxC,OAAO,aAAa;AAEb,IAAM,iBAAiB;AACvB,IAAM,oBAAoB;AAM1B,SAAS,kBAAkB,SAAuC;AACvE,SAAO,QAAQ,cAAc,QAAQ,IAAI,uBAAuB;AAClE;AAEO,SAAS,iBAAyB;AACvC,SAAO,YAAY,CAAC,EAAE,SAAS,KAAK,EAAE,YAAY;AACpD;AAEO,SAAS,eAAuB;AACrC,SAAO,WAAW;AACpB;","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveApiBaseUrl
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-575IBOIA.js";
|
|
4
4
|
import {
|
|
5
5
|
__export
|
|
6
6
|
} from "./chunk-PZ5AY32C.js";
|
|
@@ -3231,4 +3231,4 @@ export {
|
|
|
3231
3231
|
createCngApiClient,
|
|
3232
3232
|
readBackendHealth
|
|
3233
3233
|
};
|
|
3234
|
-
//# sourceMappingURL=chunk-
|
|
3234
|
+
//# sourceMappingURL=chunk-CHSTTMTO.js.map
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from "./chunk-QZEB4VMX.js";
|
|
7
7
|
import {
|
|
8
8
|
createCngApiClient
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-CHSTTMTO.js";
|
|
10
10
|
|
|
11
11
|
// src/features/knowledges/knowledges-api.ts
|
|
12
12
|
function createKnowledgesApi(options) {
|
|
@@ -110,7 +110,7 @@ async function runKnowStatusCommand(options, output, dependencies) {
|
|
|
110
110
|
const api = dependencies?.api ?? createKnowledgesApi(options);
|
|
111
111
|
const response = await api.getCatalog();
|
|
112
112
|
if (options.json) {
|
|
113
|
-
output.
|
|
113
|
+
output.raw(formatJson(response.data));
|
|
114
114
|
return;
|
|
115
115
|
}
|
|
116
116
|
const latestRun = response.data.latestRun;
|
|
@@ -134,7 +134,7 @@ async function runKnowAudiencesCommand(options, output, dependencies) {
|
|
|
134
134
|
const api = dependencies?.api ?? createKnowledgesApi(options);
|
|
135
135
|
const response = await api.listAudiences();
|
|
136
136
|
if (options.json) {
|
|
137
|
-
output.
|
|
137
|
+
output.raw(formatJson(response.data));
|
|
138
138
|
return;
|
|
139
139
|
}
|
|
140
140
|
const lines = response.data.audiences.flatMap((audience) => [
|
|
@@ -150,7 +150,7 @@ async function runKnowSearchCommand(query, options, output, dependencies) {
|
|
|
150
150
|
const api = dependencies?.api ?? createKnowledgesApi(options);
|
|
151
151
|
const response = await api.search(query, coerceLimit(options.limit, 5));
|
|
152
152
|
if (options.json) {
|
|
153
|
-
output.
|
|
153
|
+
output.raw(formatJson(response.data));
|
|
154
154
|
return;
|
|
155
155
|
}
|
|
156
156
|
const lines = response.data.results.flatMap((result, index) => [
|
|
@@ -158,7 +158,11 @@ async function runKnowSearchCommand(query, options, output, dependencies) {
|
|
|
158
158
|
` score ${result.score.toFixed(3)} | ${result.path}`,
|
|
159
159
|
` ${singleLine(result.description || result.contentPreview)}`
|
|
160
160
|
]);
|
|
161
|
-
|
|
161
|
+
if (lines.length > 0) {
|
|
162
|
+
output.info(lines.join("\n"));
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
output.warning(`No results for "${query}".`);
|
|
162
166
|
}
|
|
163
167
|
async function runKnowListCommand(query, options, output, dependencies) {
|
|
164
168
|
const api = dependencies?.api ?? createKnowledgesApi(options);
|
|
@@ -172,7 +176,7 @@ async function runKnowListCommand(query, options, output, dependencies) {
|
|
|
172
176
|
return [subskill.name, subskill.title, subskill.description, subskill.type].join(" ").toLowerCase().includes(normalizedQuery);
|
|
173
177
|
}).slice(0, limit);
|
|
174
178
|
if (options.json) {
|
|
175
|
-
output.
|
|
179
|
+
output.raw(formatJson({ subskills, total: subskills.length }));
|
|
176
180
|
return;
|
|
177
181
|
}
|
|
178
182
|
const lines = subskills.flatMap((subskill) => [
|
|
@@ -180,7 +184,11 @@ async function runKnowListCommand(query, options, output, dependencies) {
|
|
|
180
184
|
` ${subskill.title} | files ${subskill.fileCount} | rating ${subskill.rating}`,
|
|
181
185
|
` ${singleLine(subskill.description)}`
|
|
182
186
|
]);
|
|
183
|
-
|
|
187
|
+
if (lines.length > 0) {
|
|
188
|
+
output.info(lines.join("\n"));
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
output.warning("No matching subskills.");
|
|
184
192
|
}
|
|
185
193
|
async function runKnowFilesCommand(query, options, output, dependencies) {
|
|
186
194
|
const api = dependencies?.api ?? createKnowledgesApi(options);
|
|
@@ -190,7 +198,7 @@ async function runKnowFilesCommand(query, options, output, dependencies) {
|
|
|
190
198
|
limit: coerceLimit(options.limit, 25)
|
|
191
199
|
});
|
|
192
200
|
if (options.json) {
|
|
193
|
-
output.
|
|
201
|
+
output.raw(formatJson(response.data));
|
|
194
202
|
return;
|
|
195
203
|
}
|
|
196
204
|
const lines = response.data.files.map((file) => {
|
|
@@ -198,7 +206,11 @@ async function runKnowFilesCommand(query, options, output, dependencies) {
|
|
|
198
206
|
return `${file.path}
|
|
199
207
|
${title}`;
|
|
200
208
|
});
|
|
201
|
-
|
|
209
|
+
if (lines.length > 0) {
|
|
210
|
+
output.info(lines.join("\n"));
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
output.warning("No matching files.");
|
|
202
214
|
}
|
|
203
215
|
async function runKnowReadCommand(filePath, options, output, dependencies) {
|
|
204
216
|
if (!filePath) {
|
|
@@ -211,12 +223,12 @@ async function runKnowReadCommand(filePath, options, output, dependencies) {
|
|
|
211
223
|
limit: coerceLimit(options.limit, 200, 2e3)
|
|
212
224
|
});
|
|
213
225
|
if (options.json) {
|
|
214
|
-
output.
|
|
226
|
+
output.raw(formatJson(response.data));
|
|
215
227
|
return;
|
|
216
228
|
}
|
|
217
|
-
output.
|
|
229
|
+
output.raw(response.data.content);
|
|
218
230
|
if (response.data.truncated) {
|
|
219
|
-
output.
|
|
231
|
+
output.warning(
|
|
220
232
|
`[truncated: showing ${response.data.limit} lines from offset ${response.data.offset} of ${response.data.total_lines}]`
|
|
221
233
|
);
|
|
222
234
|
}
|
|
@@ -236,18 +248,26 @@ async function runKnowGrepCommand(pattern, options, output, dependencies) {
|
|
|
236
248
|
ignoreCase: options.caseInsensitive === true
|
|
237
249
|
});
|
|
238
250
|
if (options.json) {
|
|
239
|
-
output.
|
|
251
|
+
output.raw(formatJson(response.data));
|
|
240
252
|
return;
|
|
241
253
|
}
|
|
242
254
|
if (response.data.mode === "files_with_matches") {
|
|
243
255
|
const files = limit ? response.data.files.slice(0, limit) : response.data.files;
|
|
244
|
-
|
|
256
|
+
if (files.length > 0) {
|
|
257
|
+
output.raw(files.join("\n"));
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
output.warning(`No files matched "${pattern}".`);
|
|
245
261
|
return;
|
|
246
262
|
}
|
|
247
263
|
if (response.data.mode === "count") {
|
|
248
264
|
const counts = limit ? response.data.counts.slice(0, limit) : response.data.counts;
|
|
249
265
|
const lines2 = counts.map((count) => `${count.file_path}: ${count.match_count}`);
|
|
250
|
-
|
|
266
|
+
if (lines2.length > 0) {
|
|
267
|
+
output.raw(lines2.join("\n"));
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
output.warning(`No matches for "${pattern}".`);
|
|
251
271
|
return;
|
|
252
272
|
}
|
|
253
273
|
const matches = limit ? response.data.matches.slice(0, limit) : response.data.matches;
|
|
@@ -257,7 +277,11 @@ async function runKnowGrepCommand(pattern, options, output, dependencies) {
|
|
|
257
277
|
`> ${match.line}`,
|
|
258
278
|
...match.context_after.map((line) => ` ${line}`)
|
|
259
279
|
]);
|
|
260
|
-
|
|
280
|
+
if (lines.length > 0) {
|
|
281
|
+
output.raw(lines.join("\n"));
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
output.warning(`No matches for "${pattern}".`);
|
|
261
285
|
}
|
|
262
286
|
async function runKnowGlobCommand(pattern, options, output, dependencies) {
|
|
263
287
|
const api = dependencies?.api ?? createKnowledgesApi(options);
|
|
@@ -267,14 +291,18 @@ async function runKnowGlobCommand(pattern, options, output, dependencies) {
|
|
|
267
291
|
path: normalizeCatalogPath(options.path ?? "/")
|
|
268
292
|
});
|
|
269
293
|
if (options.json) {
|
|
270
|
-
output.
|
|
294
|
+
output.raw(formatJson(response.data));
|
|
271
295
|
return;
|
|
272
296
|
}
|
|
273
297
|
const files = limit ? response.data.files.slice(0, limit) : response.data.files;
|
|
274
298
|
const wasClientTruncated = limit ? response.data.files.length > limit : false;
|
|
275
|
-
|
|
299
|
+
if (files.length > 0) {
|
|
300
|
+
output.raw(files.join("\n"));
|
|
301
|
+
} else {
|
|
302
|
+
output.warning("No matching files.");
|
|
303
|
+
}
|
|
276
304
|
if (response.data.truncated || wasClientTruncated) {
|
|
277
|
-
output.
|
|
305
|
+
output.warning(`[truncated: ${response.data.total_files} total files]`);
|
|
278
306
|
}
|
|
279
307
|
}
|
|
280
308
|
|
|
@@ -288,4 +316,4 @@ export {
|
|
|
288
316
|
runKnowGrepCommand,
|
|
289
317
|
runKnowGlobCommand
|
|
290
318
|
};
|
|
291
|
-
//# sourceMappingURL=chunk-
|
|
319
|
+
//# sourceMappingURL=chunk-LWZPSJVC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/features/knowledges/knowledges-api.ts","../src/features/knowledges/knowledges-input.ts","../src/features/knowledges/run-knowledges-command.ts"],"sourcesContent":["import type { CngApi } from \"@cng/client\";\n\nimport { createCngApiClient } from \"../../shared/api-client.js\";\nimport type { GlobalCommandOptions } from \"../../shared/config.js\";\n\nexport type KnowCommandDependencies = {\n api?: KnowledgesApi;\n};\n\nexport type KnowledgesApi = {\n getCatalog(): Promise<CngApi.HarnessCatalogSummaryApiResponse>;\n listAudiences(): Promise<CngApi.HarnessAudiencesApiResponse>;\n search(query: string, limit: number): Promise<CngApi.HarnessSemanticSearchApiResponse>;\n listSubskills(): Promise<CngApi.HarnessSubskillsApiResponse>;\n listFiles(options: {\n query?: string;\n audience?: CngApi.HarnessAudienceId;\n limit: number;\n }): Promise<CngApi.HarnessSubskillAssetsApiResponse>;\n read(options: {\n filePath: string;\n offset?: number;\n limit: number;\n }): Promise<CngApi.HarnessReadApiResponse>;\n grep(options: {\n pattern: string;\n path: string;\n include: string;\n mode: CngApi.HarnessGrepOutputMode;\n context: number;\n ignoreCase: boolean;\n }): Promise<CngApi.HarnessGrepApiResponse>;\n glob(options: { pattern: string; path: string }): Promise<CngApi.HarnessGlobApiResponse>;\n};\n\nexport function createKnowledgesApi(options: GlobalCommandOptions): KnowledgesApi {\n const client = createCngApiClient(options);\n\n return {\n getCatalog: () => client.harnessKnowledges.getHarnessKnowledgesCatalog(),\n listAudiences: () => client.harnessKnowledges.listHarnessKnowledgesAudiences(),\n search: (query, limit) =>\n client.harnessKnowledges.searchHarnessKnowledges({\n q: query,\n limit,\n }),\n listSubskills: () => client.harnessKnowledges.listHarnessKnowledgesSubskills(),\n listFiles: ({ query, audience, limit }) =>\n client.harnessKnowledges.listHarnessSubskillAssets({\n ...(query ? { q: query } : {}),\n ...(audience ? { audience } : {}),\n limit,\n }),\n read: ({ filePath, offset, limit }) =>\n client.harnessFilesystem.getHarnessFilesystemRead({\n file_path: filePath,\n offset,\n limit,\n }),\n grep: ({ pattern, path, include, mode, context, ignoreCase }) =>\n client.harnessFilesystem.getHarnessFilesystemGrep({\n pattern,\n path,\n include,\n output_mode: mode,\n context,\n case_insensitive: ignoreCase ? \"true\" : undefined,\n }),\n glob: ({ pattern, path }) =>\n client.harnessFilesystem.getHarnessFilesystemGlob({\n pattern,\n path,\n }),\n };\n}\n","import type { CngApi } from \"@cng/client\";\n\nexport function normalizeAudienceId(value: string | undefined): CngApi.HarnessAudienceId | undefined {\n if (value === undefined) {\n return undefined;\n }\n\n switch (value) {\n case \"all\":\n case \"operators\":\n case \"builders\":\n case \"researchers\":\n case \"agent-makers\":\n return value;\n default:\n throw new Error(\n `Unknown audience \"${value}\". Run cngkit knowledges audiences to see supported values.`\n );\n }\n}\n\nexport function normalizeCatalogPath(value: string): string {\n const trimmed = value.trim();\n if (trimmed === \"/\" || trimmed === \"\") {\n return \"skills\";\n }\n\n const relativePath = trimmed.replace(/^\\/+/, \"\");\n if (relativePath.startsWith(\"skills/knowledges/\")) {\n return relativePath;\n }\n\n const [firstSegment, ...restSegments] = relativePath.split(\"/\");\n if (!firstSegment) {\n return relativePath;\n }\n\n switch (firstSegment) {\n case \"concepts\":\n case \"domains\":\n case \"formats\":\n case \"languages\":\n case \"libraries\":\n case \"patterns\":\n case \"platforms\":\n case \"procedures\":\n case \"protocols\":\n case \"tools\":\n return `skills/knowledges/subskills/${firstSegment}${restSegments.length > 0 ? `/${restSegments.join(\"/\")}` : \"\"}`;\n default:\n return relativePath;\n }\n}\n\nexport function normalizeGrepMode(value: string | undefined): CngApi.HarnessGrepOutputMode {\n if (value === undefined) {\n return \"content\";\n }\n\n switch (value) {\n case \"content\":\n case \"files_with_matches\":\n case \"count\":\n return value;\n default:\n throw new Error(\"Unknown grep mode. Use one of: content, files_with_matches, count.\");\n }\n}\n","import { formatKnowledgesHelp } from \"../../cli/help-specs.js\";\nimport {\n coerceLimit,\n coerceOptionalNumber,\n formatJson,\n optionalJoinedArgument,\n singleLine,\n type JsonOutputOptions,\n type NumberOption,\n} from \"../../shared/command-utils.js\";\nimport type { GlobalCommandOptions } from \"../../shared/config.js\";\nimport type { CommandOutput } from \"../../shared/output.js\";\nimport { createKnowledgesApi, type KnowCommandDependencies } from \"./knowledges-api.js\";\nimport { normalizeAudienceId, normalizeCatalogPath, normalizeGrepMode } from \"./knowledges-input.js\";\n\nexport type KnowStatusCommandOptions = GlobalCommandOptions & JsonOutputOptions;\n\nexport type KnowAudiencesCommandOptions = GlobalCommandOptions & JsonOutputOptions;\n\nexport type KnowSearchCommandOptions = GlobalCommandOptions &\n JsonOutputOptions & {\n limit?: NumberOption;\n };\n\nexport type KnowListCommandOptions = GlobalCommandOptions &\n JsonOutputOptions & {\n limit?: NumberOption;\n };\n\nexport type KnowFilesCommandOptions = GlobalCommandOptions &\n JsonOutputOptions & {\n audience?: string;\n limit?: NumberOption;\n };\n\nexport type KnowReadCommandOptions = GlobalCommandOptions &\n JsonOutputOptions & {\n offset?: NumberOption;\n limit?: NumberOption;\n };\n\nexport type KnowGrepCommandOptions = GlobalCommandOptions &\n JsonOutputOptions & {\n path?: string;\n include?: string;\n outputMode?: string;\n context?: NumberOption;\n caseInsensitive?: boolean;\n limit?: NumberOption;\n };\n\nexport type KnowGlobCommandOptions = GlobalCommandOptions &\n JsonOutputOptions & {\n path?: string;\n limit?: NumberOption;\n };\n\nexport type KnowledgesCliOptions = KnowFilesCommandOptions &\n KnowGlobCommandOptions &\n KnowGrepCommandOptions &\n KnowReadCommandOptions &\n KnowSearchCommandOptions;\n\nexport async function runKnowledgesCommand(\n args: string[] | undefined,\n options: KnowledgesCliOptions,\n output: CommandOutput,\n dependencies?: KnowCommandDependencies\n): Promise<void> {\n const [subcommand, ...subcommandArgs] = args ?? [];\n\n if (subcommand === undefined || subcommand === \"help\") {\n output.markdown(formatKnowledgesHelp(subcommandArgs[0]));\n return;\n }\n\n switch (subcommand) {\n case \"status\":\n return runKnowStatusCommand(options, output, dependencies);\n case \"audiences\":\n return runKnowAudiencesCommand(options, output, dependencies);\n case \"search\":\n return runKnowSearchCommand(optionalJoinedArgument(subcommandArgs), options, output, dependencies);\n case \"list\":\n return runKnowListCommand(optionalJoinedArgument(subcommandArgs), options, output, dependencies);\n case \"files\":\n return runKnowFilesCommand(optionalJoinedArgument(subcommandArgs), options, output, dependencies);\n case \"read\":\n return runKnowReadCommand(subcommandArgs[0], options, output, dependencies);\n case \"grep\":\n return runKnowGrepCommand(optionalJoinedArgument(subcommandArgs), options, output, dependencies);\n case \"glob\":\n return runKnowGlobCommand(optionalJoinedArgument(subcommandArgs), options, output, dependencies);\n default:\n throw new Error(\n \"Missing knowledges command. Usage: cngkit knowledges <status|audiences|search|list|files|read|grep|glob>\"\n );\n }\n}\n\nexport async function runKnowStatusCommand(\n options: KnowStatusCommandOptions,\n output: CommandOutput,\n dependencies?: KnowCommandDependencies\n): Promise<void> {\n const api = dependencies?.api ?? createKnowledgesApi(options);\n const response = await api.getCatalog();\n\n if (options.json) {\n output.raw(formatJson(response.data));\n return;\n }\n\n const latestRun = response.data.latestRun;\n const lines = [\n `Catalog: ${response.data.name}`,\n `Files: ${response.data.files}`,\n `Blobs: ${response.data.blobs}`,\n `Vectorize: ${response.data.vectorize.index} (${response.data.vectorize.binding})`,\n ];\n\n if (latestRun) {\n lines.push(`Latest run: ${latestRun.status} (${latestRun.id})`);\n if (latestRun.updated_at) {\n lines.push(`Updated: ${latestRun.updated_at}`);\n }\n } else {\n lines.push(\"Latest run: none\");\n }\n\n output.info(lines.join(\"\\n\"));\n}\n\nexport async function runKnowAudiencesCommand(\n options: KnowAudiencesCommandOptions,\n output: CommandOutput,\n dependencies?: KnowCommandDependencies\n): Promise<void> {\n const api = dependencies?.api ?? createKnowledgesApi(options);\n const response = await api.listAudiences();\n\n if (options.json) {\n output.raw(formatJson(response.data));\n return;\n }\n\n const lines = response.data.audiences.flatMap((audience) => [\n `${audience.id} - ${audience.label}`,\n ` ${singleLine(audience.help)}`,\n ]);\n\n output.info(lines.length > 0 ? lines.join(\"\\n\") : \"No audiences available.\");\n}\n\nexport async function runKnowSearchCommand(\n query: string | undefined,\n options: KnowSearchCommandOptions,\n output: CommandOutput,\n dependencies?: KnowCommandDependencies\n): Promise<void> {\n if (!query) {\n throw new Error(\"Missing search query. Usage: cngkit knowledges search <query>\");\n }\n\n const api = dependencies?.api ?? createKnowledgesApi(options);\n const response = await api.search(query, coerceLimit(options.limit, 5));\n\n if (options.json) {\n output.raw(formatJson(response.data));\n return;\n }\n\n const lines = response.data.results.flatMap((result, index) => [\n `${index + 1}. ${result.title} (${result.subskillName})`,\n ` score ${result.score.toFixed(3)} | ${result.path}`,\n ` ${singleLine(result.description || result.contentPreview)}`,\n ]);\n\n if (lines.length > 0) {\n output.info(lines.join(\"\\n\"));\n return;\n }\n\n output.warning(`No results for \"${query}\".`);\n}\n\nexport async function runKnowListCommand(\n query: string | undefined,\n options: KnowListCommandOptions,\n output: CommandOutput,\n dependencies?: KnowCommandDependencies\n): Promise<void> {\n const api = dependencies?.api ?? createKnowledgesApi(options);\n const response = await api.listSubskills();\n const limit = coerceLimit(options.limit, 25);\n const normalizedQuery = query?.toLowerCase();\n const subskills = response.data.subskills\n .filter((subskill) => {\n if (!normalizedQuery) {\n return true;\n }\n return [subskill.name, subskill.title, subskill.description, subskill.type]\n .join(\" \")\n .toLowerCase()\n .includes(normalizedQuery);\n })\n .slice(0, limit);\n\n if (options.json) {\n output.raw(formatJson({ subskills, total: subskills.length }));\n return;\n }\n\n const lines = subskills.flatMap((subskill) => [\n `${subskill.name} [${subskill.type}]`,\n ` ${subskill.title} | files ${subskill.fileCount} | rating ${subskill.rating}`,\n ` ${singleLine(subskill.description)}`,\n ]);\n\n if (lines.length > 0) {\n output.info(lines.join(\"\\n\"));\n return;\n }\n\n output.warning(\"No matching subskills.\");\n}\n\nexport async function runKnowFilesCommand(\n query: string | undefined,\n options: KnowFilesCommandOptions,\n output: CommandOutput,\n dependencies?: KnowCommandDependencies\n): Promise<void> {\n const api = dependencies?.api ?? createKnowledgesApi(options);\n const response = await api.listFiles({\n query,\n audience: normalizeAudienceId(options.audience),\n limit: coerceLimit(options.limit, 25),\n });\n\n if (options.json) {\n output.raw(formatJson(response.data));\n return;\n }\n\n const lines = response.data.files.map((file) => {\n const title = file.display_title ?? file.title ?? file.subskill_name ?? \"Untitled\";\n return `${file.path}\\n ${title}`;\n });\n\n if (lines.length > 0) {\n output.info(lines.join(\"\\n\"));\n return;\n }\n\n output.warning(\"No matching files.\");\n}\n\nexport async function runKnowReadCommand(\n filePath: string | undefined,\n options: KnowReadCommandOptions,\n output: CommandOutput,\n dependencies?: KnowCommandDependencies\n): Promise<void> {\n if (!filePath) {\n throw new Error(\"Missing file_path. Usage: cngkit knowledges read <file_path>\");\n }\n\n const api = dependencies?.api ?? createKnowledgesApi(options);\n const response = await api.read({\n filePath: normalizeCatalogPath(filePath),\n offset: coerceOptionalNumber(options.offset),\n limit: coerceLimit(options.limit, 200, 2000),\n });\n\n if (options.json) {\n output.raw(formatJson(response.data));\n return;\n }\n\n output.raw(response.data.content);\n if (response.data.truncated) {\n output.warning(\n `[truncated: showing ${response.data.limit} lines from offset ${response.data.offset} of ${response.data.total_lines}]`\n );\n }\n}\n\nexport async function runKnowGrepCommand(\n pattern: string | undefined,\n options: KnowGrepCommandOptions,\n output: CommandOutput,\n dependencies?: KnowCommandDependencies\n): Promise<void> {\n if (!pattern) {\n throw new Error(\"Missing pattern. Usage: cngkit knowledges grep <pattern>\");\n }\n\n const api = dependencies?.api ?? createKnowledgesApi(options);\n const limit = options.limit !== undefined ? coerceOptionalNumber(options.limit) : undefined;\n const response = await api.grep({\n pattern,\n path: normalizeCatalogPath(options.path ?? \"/\"),\n include: options.include ?? \"*\",\n mode: normalizeGrepMode(options.outputMode),\n context: coerceLimit(options.context, 0, 20),\n ignoreCase: options.caseInsensitive === true,\n });\n\n if (options.json) {\n output.raw(formatJson(response.data));\n return;\n }\n\n if (response.data.mode === \"files_with_matches\") {\n const files = limit ? response.data.files.slice(0, limit) : response.data.files;\n if (files.length > 0) {\n output.raw(files.join(\"\\n\"));\n return;\n }\n\n output.warning(`No files matched \"${pattern}\".`);\n return;\n }\n\n if (response.data.mode === \"count\") {\n const counts = limit ? response.data.counts.slice(0, limit) : response.data.counts;\n const lines = counts.map((count) => `${count.file_path}: ${count.match_count}`);\n if (lines.length > 0) {\n output.raw(lines.join(\"\\n\"));\n return;\n }\n\n output.warning(`No matches for \"${pattern}\".`);\n return;\n }\n\n const matches = limit ? response.data.matches.slice(0, limit) : response.data.matches;\n const lines = matches.flatMap((match) => [\n `${match.file_path}:${match.line_number}`,\n ...match.context_before.map((line) => ` ${line}`),\n `> ${match.line}`,\n ...match.context_after.map((line) => ` ${line}`),\n ]);\n\n if (lines.length > 0) {\n output.raw(lines.join(\"\\n\"));\n return;\n }\n\n output.warning(`No matches for \"${pattern}\".`);\n}\n\nexport async function runKnowGlobCommand(\n pattern: string | undefined,\n options: KnowGlobCommandOptions,\n output: CommandOutput,\n dependencies?: KnowCommandDependencies\n): Promise<void> {\n const api = dependencies?.api ?? createKnowledgesApi(options);\n const limit = options.limit !== undefined ? coerceOptionalNumber(options.limit) : undefined;\n const response = await api.glob({\n pattern: pattern ?? \"**/*.md\",\n path: normalizeCatalogPath(options.path ?? \"/\"),\n });\n\n if (options.json) {\n output.raw(formatJson(response.data));\n return;\n }\n\n const files = limit ? response.data.files.slice(0, limit) : response.data.files;\n const wasClientTruncated = limit ? response.data.files.length > limit : false;\n\n if (files.length > 0) {\n output.raw(files.join(\"\\n\"));\n } else {\n output.warning(\"No matching files.\");\n }\n if (response.data.truncated || wasClientTruncated) {\n output.warning(`[truncated: ${response.data.total_files} total files]`);\n }\n}\n"],"mappings":"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","names":["lines"]}
|