61 lines
2.4 KiB
Markdown
61 lines
2.4 KiB
Markdown
# P5c task 02: `sift extract <file.pdf>`
|
|
|
|
**Branch:** `p5c` (`git switch p5c`; `git status --short` must be empty, otherwise stop)
|
|
**Commit subject:** `cli: sift extract uploads a local PDF; README and skill`
|
|
|
|
## Goal
|
|
|
|
`sift extract thesis.pdf [--pages 41-60] [--grep RE] [--question Q] [--json]` uploads the file
|
|
to `/v1/extract` and prints the answer exactly as `sift fetch` does.
|
|
|
|
## Files
|
|
|
|
- Copy: `cmd/sift/extract_test.go`
|
|
- Create: `cmd/sift/extractcmd.go`
|
|
- Modify: `cmd/sift/main.go` (a `case "extract":` and one help line), `README.md`,
|
|
`skill/SKILL.md`, `docs/implementer-log.md`
|
|
|
|
## Interfaces
|
|
|
|
```go
|
|
package main
|
|
|
|
type extractOpts struct {
|
|
File, Pages, Grep, Question, Mode string
|
|
JSON bool
|
|
}
|
|
|
|
const extractUsage = "usage: sift extract <file.pdf> [--pages a-b] [--grep RE] [--question Q] [--mode clean|digest] [--json]"
|
|
|
|
func parseExtractOpts(args []string) (extractOpts, error) // flags before or after the file, as fetch
|
|
func extractURL(base string, o extractOpts) string // base + "/v1/extract?" + only the options that are set; mode=digest when Question is set and Mode is empty
|
|
```
|
|
|
|
## Rules
|
|
|
|
1. The command:
|
|
- Resolve the base URL and key exactly as `sift fetch` does (reuse its client-config helpers; do not copy them).
|
|
- `stat` the file: over 100 MiB → exit with a message before uploading.
|
|
- `POST` the bytes with `Content-Type: application/pdf` and the bearer key.
|
|
- Print `content` (or the whole envelope with `--json`), with the same errors and exit codes as fetch (`exitFor`).
|
|
- Do not read the whole file into memory twice: stream it with `os.Open` as the request body and set `ContentLength`.
|
|
2. **`README.md`:** a `sift extract` subsection next to `sift fetch`.
|
|
3. **`skill/SKILL.md`:** "A PDF on disk (an attachment, a download): `sift extract <file>`, with the same `--pages`/`--grep`/`--question`. Never run `pdftotext` yourself."
|
|
|
|
## Steps
|
|
|
|
- [ ] **1.** `git switch p5c`; copy the given test. **2. See it fail.**
|
|
- [ ] **3.** `extractcmd.go`, `main.go`, README, skill.
|
|
- [ ] **4.** `gofmt -w`; `go test -race -count=3 ./cmd/sift/` → `ok`. **5.** `make gate`.
|
|
- [ ] **6.** `make build && bin/sift extract 2>&1 | head -1` prints the usage line.
|
|
- [ ] **7.** Row `p5c/02-extract-cli`; commit.
|
|
|
|
```sh
|
|
git add cmd/sift README.md skill/SKILL.md docs/implementer-log.md
|
|
git commit -F .state/commit-msg.txt
|
|
```
|
|
|
|
## Done when
|
|
|
|
- All tests pass; `make gate` ok; given file byte-identical.
|