c16d7964c9dc2ba1e9b23a427a5ebc7e2bb27ced
2 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
7320b50dac |
feat(cli+docs+smoke): inference-task CLI + GC ticker + smoke + docs (v5 Stage 4)
Some checks failed
CI/CD / lint (pull_request) Successful in 55s
CI/CD / test (pull_request) Successful in 1m12s
CI/CD / typecheck (pull_request) Successful in 2m46s
CI/CD / smoke (pull_request) Failing after 1m44s
CI/CD / build (pull_request) Failing after 7m0s
CI/CD / publish (pull_request) Has been skipped
CLI surface for the durable queue:
- `mcpctl get tasks` — table view (ID, STATUS, POOL, LLM, MODEL,
STREAM, AGE, WORKER). Aliases `task`, `tasks`, `inference-task`,
`inference-tasks` all normalize to the canonical plural so URL
construction works uniformly. RESOURCE_ALIASES + completions
generator updated.
- `mcpctl chat-llm <name> --async -m <msg>` — enqueue and exit. stdout
is just the task id (pipeable into `xargs mcpctl get task`); stderr
carries human-readable status. REPL mode is rejected for --async
(fire-and-forget doesn't make sense without -m).
GC ticker in mcpd: 5-min interval. Pending tasks past 1 h queue
timeout flip to error with a clear message; terminal tasks past 7 d
retention get deleted. Both queries are index-backed.
Crash fix uncovered by the smoke: when the async route doesn't await
ref.done, a later cancel/error rejected the in-flight Promise as
unhandled and crashed mcpd. The route now attaches a no-op `.catch`
so the legacy `done` semantic still works for sync callers (chat,
direct infer) without taking out the process for async ones. The
EnqueueInferOptions also gained an explicit `ownerId` field so the
async API can stamp the authenticated user on the row instead of
inheriting 'system' from the constructor's resolveOwner — without
this, every GET/DELETE from the original caller would 404 due to
foreign-owner mismatch.
Smoke (tests/smoke/inference-task.smoke.test.ts):
1. POST /inference-tasks while no worker bound → row=pending.
2. Bring a registrar online → bindSession drain claims and
dispatches → worker complete()s → row=completed → GET returns
the assistant body.
3. Stop worker, enqueue, DELETE → row=cancelled, persisted.
docs/inference-tasks.md (new): full data model, lifecycle diagram,
async API reference, CLI examples, RBAC table, GC defaults, and the
v5 limitations / v6 roadmap. Cross-linked from virtual-llms.md and
agents.md.
Tests + smoke: mcpd 893/893, mcplocal 723/723, cli 437/437, full
smoke 146/146 (was 144, +2 new task smoke). Live mcpd verified via
manual curl: enqueue → cancel → re-fetch — no crash, owner scoping
returns 404 on foreign ids, GC ticker logs at info when it sweeps.
v5 complete: durable queue (Stage 1) + VirtualLlmService rewire
(Stage 2) + async API & RBAC (Stage 3) + CLI/GC/smoke/docs (Stage 4).
|
||
|
|
1dcfdc8b05 |
feat(mcpd): async inference task API + tasks RBAC resource (v5 Stage 3)
Exposes the durable queue (Stage 1+2) as a first-class API so callers
can enqueue work, get a task id immediately, and poll/stream/cancel
without holding open the original HTTP connection.
New endpoints (`/api/v1/inference-tasks`):
POST / → enqueue, return task id (201 + row).
failFast:false — task stays pending if no
worker is up; future bindSession drains.
Rejects 400 for public Llms (the existing
/llms/<name>/infer is the right tool there)
and 404 for missing Llms.
GET / → list owner's tasks. Optional ?status,
?poolName, ?agentId, ?limit query.
Owner-scoped at the route layer; cross-
user listing requires resource-wide grant.
GET /:id → poll one task. 404 (not 403) on a
foreign-owner id to prevent enumeration.
DELETE /:id → cancel a non-terminal task. Already-
terminal rows return 200 + current shape
(no-op). 404 on foreign owner.
GET /:id/stream → SSE feed of `chunk` and `terminal` events.
Re-fetches the row at subscribe time so
already-completed tasks emit one terminal
event and close immediately.
RBAC:
- New `tasks` resource added to RBAC_RESOURCES + the URL→permission
map in main.ts. Default action mapping: GET=view, POST=create,
DELETE=delete. The route layer enforces owner-scoping ON TOP of
the hook (404 on foreign owner) — without this, anyone with
`view:tasks` could list/peek every user's queued work.
- Singular alias `task` and the multi-word `inference-task` /
`inference-tasks` all normalize to `tasks` so users can write
`mcpctl create rbac-binding --resource task --role view ...` or
any of the variants and have it map correctly.
Tests: 9 new route tests covering the wire shapes, owner scoping
(matching/foreign), public-Llm rejection, missing-Llm 404, list
filter, and cancel semantics (pending→cancelled, terminal→no-op).
mcpd 893/893 (was 884, +9). Live smoke: POST against a public Llm
returns the documented 400, POST against missing returns 404, GET
list returns [] cleanly.
Stage 4 (next): CLI surface (`mcpctl get tasks`, `--async` flag on
chat-llm), GC ticker, smoke test (enqueue → connect worker →
drain), docs.
|