Add `sift batch` so agents reach the batch endpoint through the CLI like
`fetch` and `search`. `batchcmd.go` has `parseBatchArgs` (verb plus the
unchanged args after it; submit takes one arg, status a job id optionally
preceded by `--results`, get a job id plus a non-negative-integer idx, cancel
a job id, else a usage error), `batchMain` dispatch, one small function per
verb, and `batchDo` (bearer header, decode the envelope, print it on stdout,
on non-2xx the error to stderr and `exitFor`). `submitMain` reads the file or
stdin and validates locally: a JSON object with a non-empty `targets` array,
or a bare array of targets or URL strings wrapped into `{"targets": [...]}`.
README gains a "Batch" section (endpoints, serial-per-job/one-worker/
round-robin model, caps, idempotency, lease/TTL/restart, summary-vs-results,
redaction, metrics); SKILL.md gains a "Batch" section.
Co-Authored-By: ornith-1.5-35b-a3b <ornith-1.5-35b-a3b@llama.cpp.invalid>
47 lines
1.4 KiB
Go
47 lines
1.4 KiB
Go
package main
|
|
|
|
import (
|
|
"slices"
|
|
"testing"
|
|
)
|
|
|
|
func TestParseBatchArgs(t *testing.T) {
|
|
cases := []struct {
|
|
args []string
|
|
verb string
|
|
rest []string
|
|
ok bool
|
|
}{
|
|
{[]string{"submit", "targets.json"}, "submit", []string{"targets.json"}, true},
|
|
{[]string{"submit", "-"}, "submit", []string{"-"}, true},
|
|
{[]string{"status", "job-123"}, "status", []string{"job-123"}, true},
|
|
{[]string{"status", "--results", "job-123"}, "status", []string{"--results", "job-123"}, true},
|
|
{[]string{"get", "job-123", "4"}, "get", []string{"job-123", "4"}, true},
|
|
{[]string{"cancel", "job-123"}, "cancel", []string{"job-123"}, true},
|
|
{[]string{}, "", nil, false},
|
|
{[]string{"submit"}, "", nil, false},
|
|
{[]string{"status"}, "", nil, false},
|
|
{[]string{"status", "a", "b"}, "", nil, false},
|
|
{[]string{"status", "--results"}, "", nil, false},
|
|
{[]string{"get", "job-123"}, "", nil, false},
|
|
{[]string{"get", "job-123", "x"}, "", nil, false},
|
|
{[]string{"get", "job-123", "-1"}, "", nil, false},
|
|
{[]string{"cancel"}, "", nil, false},
|
|
{[]string{"bogus", "x"}, "", nil, false},
|
|
}
|
|
for _, c := range cases {
|
|
verb, rest, err := parseBatchArgs(c.args)
|
|
if c.ok {
|
|
if err != nil {
|
|
t.Errorf("%v: unexpected error %v", c.args, err)
|
|
continue
|
|
}
|
|
if verb != c.verb || !slices.Equal(rest, c.rest) {
|
|
t.Errorf("%v: got verb=%q rest=%q", c.args, verb, rest)
|
|
}
|
|
} else if err == nil {
|
|
t.Errorf("%v: want an error", c.args)
|
|
}
|
|
}
|
|
}
|