Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.10.0"
".": "0.11.0"
}
8 changes: 4 additions & 4 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 29
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/context-dev/context.dev-ecb277557634e2f0838ea196e2b21f11924f65e133c7977e8c2e1a603b8df466.yml
openapi_spec_hash: 798ce4cb042389a1179bf9af6fc1173d
config_hash: ff35e224e809656528c44163aa41bebd
configured_endpoints: 30
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/context-dev/context.dev-c90f13e3cf4b9ae6a1d8f22c0e7285ab12d412d3a659a51a247a97adc7f08121.yml
openapi_spec_hash: bf7879be38ebf3397a939c80b261a47a
config_hash: daabb160675d86b354711da1e77e5129
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# Changelog

## 0.11.0 (2026-07-12)

Full Changelog: [v0.10.0...v0.11.0](https://github.com/context-dot-dev/context-dev-cli/compare/v0.10.0...v0.11.0)

### Features

* **api:** api update ([0a8b58e](https://github.com/context-dot-dev/context-dev-cli/commit/0a8b58e4e26794d3c2a67f2d4ff92a85a8396d54))
* **api:** api update ([16201c6](https://github.com/context-dot-dev/context-dev-cli/commit/16201c67e3dd1e192a0ca50557518d4bf8314580))
* **api:** api update ([e636b6d](https://github.com/context-dot-dev/context-dev-cli/commit/e636b6d51d9c58cfb2f0845900e22eddcd939d50))
* **api:** api update ([e16a2a9](https://github.com/context-dot-dev/context-dev-cli/commit/e16a2a9ef5a60f1b135bc081867e7404c1e2c8f5))
* **api:** manual updates ([d742101](https://github.com/context-dot-dev/context-dev-cli/commit/d74210104ea1f0a693d91aa8f8b53d6ea433ec70))

## 0.10.0 (2026-07-10)

Full Changelog: [v0.9.0...v0.10.0](https://github.com/context-dot-dev/context-dev-cli/compare/v0.9.0...v0.10.0)
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ require (
github.com/charmbracelet/bubbletea v1.3.6
github.com/charmbracelet/lipgloss v1.1.0
github.com/charmbracelet/x/term v0.2.1
github.com/context-dot-dev/context-go-sdk/v2 v2.1.0
github.com/context-dot-dev/context-go-sdk/v2 v2.2.0
github.com/goccy/go-yaml v1.18.0
github.com/itchyny/json2yaml v0.1.4
github.com/muesli/reflow v0.3.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 h1:payR
github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
github.com/context-dot-dev/context-go-sdk/v2 v2.1.0 h1:Npy3In0Wda7r+TPlvjnoErIe/6s4qZ80uymsC6QCrUQ=
github.com/context-dot-dev/context-go-sdk/v2 v2.1.0/go.mod h1:CvRANWLP0FHj5XyUwzEVX79ujdwr/2Jy375UVzKNQm8=
github.com/context-dot-dev/context-go-sdk/v2 v2.2.0 h1:4jIQ8PVy5Q27H/50je4gSrt5GwO4cpaRyy6idy2ZbCA=
github.com/context-dot-dev/context-go-sdk/v2 v2.2.0/go.mod h1:CvRANWLP0FHj5XyUwzEVX79ujdwr/2Jy375UVzKNQm8=
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
Expand Down
8 changes: 8 additions & 0 deletions pkg/cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,14 @@ func init() {
},
},
Commands: []*cli.Command{
{
Name: "parse",
Category: "API RESOURCE",
Suggest: true,
Commands: []*cli.Command{
&parseHandle,
},
},
{
Name: "web",
Category: "API RESOURCE",
Expand Down
14 changes: 12 additions & 2 deletions pkg/cmd/monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,14 @@ var monitorsCreate = requestflag.WithInnerFlags(cli.Command{
"webhook": {
&requestflag.InnerFlag[string]{
Name: "webhook.url",
Usage: "Webhook URL called when a change is detected.",
Usage: "Webhook URL events are delivered to.",
InnerField: "url",
},
&requestflag.InnerFlag[[]string]{
Name: "webhook.events",
Usage: "Events delivered to this endpoint. `change.detected` fires only when a run detects a change; `run.completed` fires on every completed run — including runs that detected no change — and embeds the change when one was detected. Defaults to `[\"change.detected\"]` when omitted.",
InnerField: "events",
},
&requestflag.InnerFlag[string]{
Name: "webhook.secret",
Usage: "Signing secret used to verify webhook authenticity. Each delivery includes an `X-Context-Signature: t=<unix>,v1=<hmac>` header, where the HMAC is SHA-256 over `\"{t}.{rawRequestBody}\"` keyed by this secret. Recompute it with a constant-time compare and reject stale timestamps to prevent replay. Generated by the API; cannot be set by clients.",
Expand Down Expand Up @@ -174,9 +179,14 @@ var monitorsUpdate = requestflag.WithInnerFlags(cli.Command{
"webhook": {
&requestflag.InnerFlag[string]{
Name: "webhook.url",
Usage: "Webhook URL called when a change is detected.",
Usage: "Webhook URL events are delivered to.",
InnerField: "url",
},
&requestflag.InnerFlag[[]string]{
Name: "webhook.events",
Usage: "Events delivered to this endpoint. `change.detected` fires only when a run detects a change; `run.completed` fires on every completed run — including runs that detected no change — and embeds the change when one was detected. Defaults to `[\"change.detected\"]` when omitted.",
InnerField: "events",
},
&requestflag.InnerFlag[string]{
Name: "webhook.secret",
Usage: "Signing secret used to verify webhook authenticity. Each delivery includes an `X-Context-Signature: t=<unix>,v1=<hmac>` header, where the HMAC is SHA-256 over `\"{t}.{rawRequestBody}\"` keyed by this secret. Recompute it with a constant-time compare and reject stale timestamps to prevent replay. Generated by the API; cannot be set by clients.",
Expand Down
16 changes: 12 additions & 4 deletions pkg/cmd/monitor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func TestMonitorsCreate(t *testing.T) {
"--mode", "web",
"--tag", "pricing",
"--tag", "competitor",
"--webhook", "{url: https://example.com/webhook}",
"--webhook", "{url: https://example.com/webhook, events: [change.detected, run.completed]}",
)
})

Expand All @@ -46,6 +46,7 @@ func TestMonitorsCreate(t *testing.T) {
"--tag", "pricing",
"--tag", "competitor",
"--webhook.url", "https://example.com/webhook",
"--webhook.events", "[change.detected, run.completed]",
)
})

Expand All @@ -68,7 +69,10 @@ func TestMonitorsCreate(t *testing.T) {
" - pricing\n" +
" - competitor\n" +
"webhook:\n" +
" url: https://example.com/webhook\n")
" url: https://example.com/webhook\n" +
" events:\n" +
" - change.detected\n" +
" - run.completed\n")
mocktest.TestRunMockTestWithPipeAndFlags(
t, pipeData,
"--api-key", "string",
Expand Down Expand Up @@ -104,7 +108,7 @@ func TestMonitorsUpdate(t *testing.T) {
"--tag", "pricing",
"--tag", "competitor",
"--target", "{type: page, url: https://acme.com/pricing, normalize_whitespace: true}",
"--webhook", "{url: https://example.com/webhook}",
"--webhook", "{url: https://example.com/webhook, events: [change.detected, run.completed]}",
)
})

Expand All @@ -128,6 +132,7 @@ func TestMonitorsUpdate(t *testing.T) {
"--tag", "competitor",
"--target", "{type: page, url: https://acme.com/pricing, normalize_whitespace: true}",
"--webhook.url", "https://example.com/webhook",
"--webhook.events", "[change.detected, run.completed]",
)
})

Expand All @@ -150,7 +155,10 @@ func TestMonitorsUpdate(t *testing.T) {
" url: https://acme.com/pricing\n" +
" normalize_whitespace: true\n" +
"webhook:\n" +
" url: https://example.com/webhook\n")
" url: https://example.com/webhook\n" +
" events:\n" +
" - change.detected\n" +
" - run.completed\n")
mocktest.TestRunMockTestWithPipeAndFlags(
t, pipeData,
"--api-key", "string",
Expand Down
143 changes: 143 additions & 0 deletions pkg/cmd/parse.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

package cmd

import (
"context"
"fmt"
"os"

"github.com/context-dot-dev/context-dev-cli/internal/apiquery"
"github.com/context-dot-dev/context-dev-cli/internal/binaryparam"
"github.com/context-dot-dev/context-dev-cli/internal/requestflag"
"github.com/context-dot-dev/context-go-sdk/v2"
"github.com/context-dot-dev/context-go-sdk/v2/option"
"github.com/tidwall/gjson"
"github.com/urfave/cli/v3"
)

var parseHandle = cli.Command{
Name: "handle",
Usage: "Converts raw text, source code, web/data, PDF, Microsoft Office, and image bytes\ninto LLM-usable Markdown.",
Suggest: true,
Flags: []cli.Flag{
&requestflag.Flag[string]{
Name: "body",
Required: true,
BodyRoot: true,
FileInput: true,
},
&requestflag.Flag[string]{
Name: "base-url",
Usage: "Optional HTTP(S) source document URL used to resolve relative links and image references. Relative references remain relative when omitted.",
QueryPath: "baseUrl",
},
&requestflag.Flag[string]{
Name: "extension",
Usage: "Optional file extension hint, such as pdf, docx, xlsx, pptx, html, json, csv, md, py, rtf, jpg, png, or txt.",
QueryPath: "extension",
},
&requestflag.Flag[string]{
Name: "filename",
Usage: "Optional filename hint used to infer the extension when extension is omitted.",
QueryPath: "filename",
},
&requestflag.Flag[bool]{
Name: "include-images",
Usage: "Include image references in Markdown output",
Default: false,
QueryPath: "includeImages",
},
&requestflag.Flag[bool]{
Name: "include-links",
Usage: "Preserve hyperlinks in Markdown output",
Default: true,
QueryPath: "includeLinks",
},
&requestflag.Flag[bool]{
Name: "ocr",
Usage: "When true for PDF inputs, detect and OCR images embedded in the selected pages, inserting recognized text at each image's position in page reading order while preserving the PDF text layer. pdfStart/pdfEnd limit the inclusive page range. This is separate from automatic scanned-PDF OCR fallback.",
Default: false,
QueryPath: "ocr",
},
&requestflag.Flag[int64]{
Name: "pdf-end",
Usage: "Last 1-based PDF page to parse. When omitted, parsing ends at the last page. Must be greater than or equal to pdfStart when both are provided.",
QueryPath: "pdfEnd",
},
&requestflag.Flag[int64]{
Name: "pdf-start",
Usage: "First 1-based PDF page to parse. When omitted, parsing starts at the first page.",
QueryPath: "pdfStart",
},
&requestflag.Flag[bool]{
Name: "shorten-base64-images",
Usage: "Shorten base64-encoded image data in the Markdown output",
Default: true,
QueryPath: "shortenBase64Images",
},
&requestflag.Flag[bool]{
Name: "use-main-content-only",
Usage: "Extract only the main content from HTML-like inputs",
Default: false,
QueryPath: "useMainContentOnly",
},
},
Action: handleParseHandle,
HideHelpCommand: true,
}

func handleParseHandle(ctx context.Context, cmd *cli.Command) error {
client := contextdev.NewClient(getDefaultRequestOptions(cmd)...)
unusedArgs := cmd.Args().Slice()
if !cmd.IsSet("body") && len(unusedArgs) > 0 {
cmd.Set("body", unusedArgs[0])
unusedArgs = unusedArgs[1:]
}
if len(unusedArgs) > 0 {
return fmt.Errorf("Unexpected extra arguments: %v", unusedArgs)
}

bodyReader, stdinInUse, err := binaryparam.FileOrStdin(os.Stdin, cmd.Value("body").(string))
if err != nil {
return fmt.Errorf("Failed on param '%s': %w", "body", err)
}
defer bodyReader.Close()

options, err := flagOptions(
cmd,
apiquery.NestedQueryFormatBrackets,
apiquery.ArrayQueryFormatComma,
ApplicationOctetStream,
stdinInUse,
)
if err != nil {
return err
}

params := contextdev.ParseHandleParams{}

Check failure on line 118 in pkg/cmd/parse.go

View workflow job for this annotation

GitHub Actions / test

undefined: contextdev.ParseHandleParams

Check failure on line 118 in pkg/cmd/parse.go

View workflow job for this annotation

GitHub Actions / lint

undefined: contextdev.ParseHandleParams

var res []byte
options = append(options, option.WithResponseBodyInto(&res))
_, err = client.Parse.Handle(

Check failure on line 122 in pkg/cmd/parse.go

View workflow job for this annotation

GitHub Actions / test

client.Parse undefined (type contextdev.Client has no field or method Parse)

Check failure on line 122 in pkg/cmd/parse.go

View workflow job for this annotation

GitHub Actions / lint

client.Parse undefined (type contextdev.Client has no field or method Parse)
ctx,
bodyReader,
params,
options...,
)
if err != nil {
return err
}

obj := gjson.ParseBytes(res)
format := cmd.Root().String("format")
explicitFormat := cmd.Root().IsSet("format")
transform := cmd.Root().String("transform")
return ShowJSON(obj, ShowJSONOpts{
ExplicitFormat: explicitFormat,
Format: format,
RawOutput: cmd.Root().Bool("raw-output"),
Title: "parse handle",
Transform: transform,
})
}
51 changes: 51 additions & 0 deletions pkg/cmd/parse_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

package cmd

import (
"testing"

"github.com/context-dot-dev/context-dev-cli/internal/mocktest"
)

func TestParseHandle(t *testing.T) {
t.Skip("Mock server tests are disabled")
t.Run("regular flags", func(t *testing.T) {
mocktest.TestRunMockTestWithFlags(
t,
"--api-key", "string",
"parse", "handle",
"--body", mocktest.TestFile(t, "Example data"),
"--base-url", "https://example.com",
"--extension", "extension",
"--filename", "filename",
"--include-images=true",
"--include-links=true",
"--ocr=true",
"--pdf-end", "1",
"--pdf-start", "1",
"--shorten-base64-images=true",
"--use-main-content-only=true",
)
})

t.Run("piping data", func(t *testing.T) {
// Test piping YAML data over stdin
pipeData := []byte("Example data")
mocktest.TestRunMockTestWithPipeAndFlags(
t, pipeData,
"--api-key", "string",
"parse", "handle",
"--base-url", "https://example.com",
"--extension", "extension",
"--filename", "filename",
"--include-images=true",
"--include-links=true",
"--ocr=true",
"--pdf-end", "1",
"--pdf-start", "1",
"--shorten-base64-images=true",
"--use-main-content-only=true",
)
})
}
2 changes: 1 addition & 1 deletion pkg/cmd/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

package cmd

const Version = "0.10.0" // x-release-please-version
const Version = "0.11.0" // x-release-please-version
Loading
Loading