Repository navigation
UN-4044 [FEAT] Agent-KV extraction engine — public API, schema compiler and hardened code sandbox #2309
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
vishnuszipstack
wants to merge
101
commits into
main
Choose a base branch
from
Feat/agent-kv-api
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+18,205
−36
Open
UN-4044 [FEAT] Agent-KV extraction engine — public API, schema compiler and hardened code sandbox #2309
Changes from all commits
Commits
Show all changes
101 commits
Select commit
Hold shift + click to select a range
8dbeeb2
[SPEC] Agent-KV: agentic key-value extraction API — design document
arunvenkataswamy b6339ac
[SPEC] Agent-KV rev. b: amendments from adversarial feasibility review
arunvenkataswamy ba50af5
[PLAN] Agent-KV OSS half: 15-task TDD implementation plan
arunvenkataswamy 59228e8
feat(agent-kv): shared keys.json schema compiler package with caps
arunvenkataswamy adc892e
feat(agent-kv): AGENT_KV file storage type with its own creds env
arunvenkataswamy 315225e
feat(agent-kv): app scaffold, key/job models, terminal write guard
arunvenkataswamy a7d7118
test(agent-kv): pin org-scoped filter args in mark_terminal guard test
arunvenkataswamy 593e45b
feat(agent-kv): org-scoped key management API with rotate
arunvenkataswamy 3ff2d86
fix(agent-kv): own permission class + org-scoping mechanism test
arunvenkataswamy 72b446b
feat(agent-kv): public mount, bearer-key validator, in-view auth
arunvenkataswamy 6f6b68f
test(agent-kv): pin public URL wiring and decorator application
arunvenkataswamy 9634301
feat(agent-kv): submit serializer enforcing every pre-paid-work cap
arunvenkataswamy 06ad601
test(agent-kv): pin unreadable-PDF rejection and stream rewind
arunvenkataswamy 9d5b6d0
feat(agent-kv): own-namespace concurrency limiter + per-key rate limit
arunvenkataswamy 71c6930
test(agent-kv): pin limiter key namespaces and call ordering
arunvenkataswamy f3b7558
feat(agent-kv): staging, executor dispatch glue, submit view
arunvenkataswamy 7829462
fix(agent-kv): release slot and terminalize on every submit failure path
arunvenkataswamy 2b0f1b5
feat(agent-kv): status/result/cancel/delete with org-scoped 404s
arunvenkataswamy 9c5c6c5
fix(agent-kv): serve failed/cancelled job results per spec §7.3
arunvenkataswamy 3e37737
feat(agent-kv): free authenticated schema validation endpoint
arunvenkataswamy c1b6db0
feat(agent-kv): internal stage-report and finalize APIs (idempotent)
arunvenkataswamy a805b22
fix(agent-kv): race-safe stage merge, counters write-gate, malformed-…
arunvenkataswamy f907337
feat(agent-kv): terminal callbacks on a dedicated callback queue
arunvenkataswamy 0cca794
fix(agent-kv): ide_callback worker consumes the agent_kv_callback queue
arunvenkataswamy 5497dc4
fix(agent-kv): prefer transport-injected error; guard finalize networ…
arunvenkataswamy bfa3ecc
feat(agent-kv): SSRF-guarded webhook sender
arunvenkataswamy 46f2ca5
test(agent-kv): pin IPv6, empty/multi-record resolution, non-2xx, all…
arunvenkataswamy bf0f4b7
feat(agent-kv): undispatched sweep and TTL cleanup internal endpoints
arunvenkataswamy b3601c7
fix(agent-kv): cap the undispatched sweep batch
arunvenkataswamy d2119a9
docs(agent-kv): API reference, env samples, deploy checklist
arunvenkataswamy ab1739b
fix(agent-kv): delete staged input when finalize terminalizes a job (…
arunvenkataswamy 79a94fd
fix(agent-kv): final-review fixes — guarded dispatch stamp, orphan cl…
arunvenkataswamy d055057
feat(agent-kv): gate calculations and structured_output behind deploy…
arunvenkataswamy 9f34593
feat(agent-kv): stage-report internal client; workers depend on the s…
arunvenkataswamy 57f6f11
feat(agent-kv): management commands for sweep and TTL cleanup
arunvenkataswamy 5ff1fe7
docs(agent-kv): concrete cloud deploy checklist
arunvenkataswamy c3b518f
docs(agent-kv): correct executor time-limit baseline and lever
arunvenkataswamy 0787c96
test(agent-kv): e2e lane, rig group, and compose overlay for the inte…
arunvenkataswamy 4c8f4e9
fix(agent-kv): return key on create; serialize the e2e concurrency test
arunvenkataswamy 2145661
chore(agent-kv): re-lock root uv.lock for the schema package workspac…
arunvenkataswamy cbb7cc2
docs+test(agent-kv): cost_summary shape, rollout/time-limit notes, e2…
arunvenkataswamy f625064
fix(agent-kv): 13b integration fixes — platform key by org slug, buck…
arunvenkataswamy 9c6f168
fix(agent-kv): make concurrency slot acquisition atomic (Lua script)
arunvenkataswamy db80544
fix(agent-kv): normalise AGENT_KV_STORAGE_DIR_PREFIX like the executo…
arunvenkataswamy 30586da
test(agent-kv): live e2e coverage for webhook delivery, sync-wait and…
arunvenkataswamy ad9df39
docs(agent-kv): sandbox worker design spec (sub-project #2, S1-S12)
arunvenkataswamy 059615c
docs(agent-kv): sandbox worker implementation plan (12 tasks)
arunvenkataswamy 89011a8
feat(sandbox): register SANDBOX worker type, queue and task route
arunvenkataswamy d2e19e9
feat(sandbox): normative AST safety gate with adversarial tests
arunvenkataswamy 41aab62
fix(sandbox): harden gate against builtins and attribute-form calls
arunvenkataswamy 4fed021
fix(sandbox): switch import check to allowlist (closes module-bypass …
arunvenkataswamy d4023b7
fix(sandbox): reject any reference to dangerous builtins, not just di…
arunvenkataswamy 07e3358
feat(sandbox): scrubbed-env rlimit subprocess runner with hostile-beh…
arunvenkataswamy b5c3d39
fix(sandbox): restrict sys to sys.argv only, closing the _getframe/se…
arunvenkataswamy 7016f0a
fix(sandbox): close sys-aliasing gate bypass, scrub host paths, asser…
arunvenkataswamy c0a08fe
feat(sandbox): execute_sandboxed_code task + worker entrypoint with s…
arunvenkataswamy b4e285a
feat(sandbox): compose service, run-worker command and sample.env wiring
arunvenkataswamy 79e55b1
docs(agent-kv): calculation result shape and sandbox rollout order
arunvenkataswamy 8aa7013
test(agent-kv): e2e calculation happy-path and hostile scenarios (gated)
arunvenkataswamy 5c40f67
fix(agent-kv): retarget hostile calc e2e off an accepted v1 residual
arunvenkataswamy 822fa3c
fix(sandbox): run security tests in CI, allow re.compile, kill child …
arunvenkataswamy 102c94d
docs(agent-kv): document the accepted v1 file-read residual (R12) + g…
arunvenkataswamy 8f074fe
fix(agent-kv): pre-Greptile critical fixes — gate bypass, schema dept…
arunvenkataswamy 04ee462
fix(agent-kv): pre-Greptile robustness + coverage + docs — runner/web…
arunvenkataswamy 9d76701
docs(agent-kv): add architecture overview + handover index
arunvenkataswamy d11a2da
docs(agent-kv): note billing/metering status + push state in overview
arunvenkataswamy 3f3dee1
docs(agent-kv): correct the R12 residual — pathlib is not in the AST …
arunvenkataswamy 0695df5
Merge remote-tracking branch 'origin/main' into Feat/agent-kv-api
arunvenkataswamy 3b67022
fix(agent-kv): give the agent-kv and sandbox queues a consumer on the…
arunvenkataswamy 52a5355
feat(agent-kv): gate submits on the org's subscription, as API deploy…
arunvenkataswamy 86c2ece
feat(agent-kv)!: extractor-scoped wire format — extractors[{name,keys…
arunvenkataswamy 4a4b88c
test(agent-kv): cover the serializer<->view seam the wire-format chan…
arunvenkataswamy 6c2c677
fix(agent-kv): two crashes a live submit found that no unit test could
arunvenkataswamy 936ecee
fix(agent-kv): give agent_kv_callback a consumer on the PG fleet
arunvenkataswamy efc9964
refactor(agent-kv): derive SUPPORTED_EXTRACTORS from V1_EXTRACTOR_NAME
arunvenkataswamy b4c809d
test(agent-kv): fail loudly when an e2e submit drops extractor options
arunvenkataswamy e45ac6d
fix(agent-kv): address code-review findings on the wire-format change
arunvenkataswamy 7fe7166
feat(agent-kv): route a table extractor entry to the table executor
arunvenkataswamy 90076a4
fix(agent-kv): close two review gaps in the table-extractor routing
arunvenkataswamy 8373b91
test(agent-kv): guard the table queue and cover the table extractor e2e
arunvenkataswamy a1f3e5a
UN-4044 docs(agent-kv): document the table extractor in the public AP…
arunvenkataswamy 2824ab2
Merge remote-tracking branch 'origin/main' into agent-kv-api-rebase
vishnuszipstack a79e9d6
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] eba836f
UN-4044 [FIX] Address Greptile review on the Agent-KV API PR
vishnuszipstack e8cd7d0
UN-4044 [MISC] Drop local dev scaffolding committed by mistake
vishnuszipstack cb6f7f2
UN-4044 [FIX] Stop failed TTL cleanups from starving the backlog
vishnuszipstack 10969bd
UN-4044 [FIX] Stranded jobs, the TTL starvation inversion, and a thir…
vishnuszipstack c4276bb
UN-4044 [FIX] Refuse image uploads, cover three orphaned test dirs, c…
vishnuszipstack dcc0c43
UN-4044 [FIX] Fail the limiters closed, refuse ReDoS patterns, bound …
vishnuszipstack ffe96d2
UN-4044 [FIX] Tolerant equality in constraints; correct compile.py's …
vishnuszipstack 0e1f29b
UN-4044 [MISC] Point the deferred-work comments at the tickets that e…
vishnuszipstack 675d3a3
UN-4044 [FIX] Address the re-review of my own review fixes
vishnuszipstack 63b3a91
UN-4044 [FIX] Mock the rate limiter in the validate-view tests
vishnuszipstack b752298
UN-4044 [FIX] Use math.fsum in the sum/avg aggregates
vishnuszipstack 69182b5
UN-4044 [MISC] Clear 29 of the 39 SonarCloud issues on this PR
vishnuszipstack 6bb4119
UN-4044 [MISC] Finish the S5778 hoist in test_auth — mock.Mock() was …
vishnuszipstack 24d22c8
UN-4044 [FEAT] Make array row de-duplication opt-out per array
vishnuszipstack f05aaa0
UN-4044 [FIX] Pin the worker image UID so a pod can assert it
vishnuszipstack 57bd3c6
Merge remote-tracking branch 'origin/main' into Feat/agent-kv-api
vishnuszipstack b962641
UN-4044 [MISC] Clear the 10 remaining SonarCloud issues on this PR
vishnuszipstack 29b15fa
UN-4044 [FIX] Stop the WFE index-planner fixture tripping on float8 t…
vishnuszipstack File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Empty file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| from django.apps import AppConfig | ||
|
|
||
|
|
||
| class AgentKvConfig(AppConfig): | ||
| default_auto_field = "django.db.models.BigAutoField" | ||
| name = "agent_kv" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| #: v1 accepts exactly one extractor (`kv`), so the job row does not carry which | ||
| #: one it ran. When fan-out lands this becomes per-job state rather than a | ||
| #: constant -- the wire format (spec §7.0) is already shaped for that. | ||
| V1_EXTRACTOR_NAME = "kv" | ||
|
|
||
| STAGE_NAMES = [ | ||
| "document_processing", | ||
| "extraction", | ||
| "qa", | ||
| "challenge", | ||
| "normalize", | ||
| "constraints", | ||
| "codegen", | ||
| "code_execution", | ||
| ] | ||
| EXECUTOR_NAME = "agentic_kv" | ||
| OPERATION_KV_EXTRACT = "kv_extract" | ||
| EXECUTION_SOURCE = "agent_kv_api" | ||
|
|
||
| #: The table extractor, served by the cloud `agentic_table` plugin's blind-API | ||
| #: operation. Same executor as the IDE table path (and therefore the same, | ||
| #: already-wired `celery_executor_agentic_table` queue) with a second operation | ||
| #: -- a new executor name would derive a new queue needing wiring at five | ||
| #: sites, and an unwired queue accepts work and drains nothing, silently. | ||
| TABLE_EXTRACTOR_NAME = "table" | ||
|
|
||
| TABLE_EXECUTOR_NAME = "agentic_table" | ||
| OPERATION_TABLE_EXTRACT_API = "table_extract_api" | ||
|
|
||
| #: Which executor and operation each extractor dispatches to. `dispatch_job` | ||
| #: reads this rather than hardcoding one pair, so adding an extractor is one | ||
| #: entry here plus its options serializer and stage list. | ||
| EXTRACTOR_ROUTES = { | ||
| V1_EXTRACTOR_NAME: (EXECUTOR_NAME, OPERATION_KV_EXTRACT), | ||
| TABLE_EXTRACTOR_NAME: (TABLE_EXECUTOR_NAME, OPERATION_TABLE_EXTRACT_API), | ||
| } | ||
|
|
||
| #: The table engine reports one coarse stage: it has no node-level progress | ||
| #: hooks (the IDE path gets `stream_log` only), so inventing finer stages here | ||
| #: would describe progress the executor cannot actually report. | ||
| TABLE_STAGE_NAMES = ["table_extraction"] | ||
|
|
||
| #: Stage names ARE wire format -- they are returned to clients -- and they are | ||
| #: extractor-specific (`qa`/`challenge`/`codegen` mean nothing to the table | ||
| #: extractor). `_status_document` filters a job's recorded stages through the | ||
| #: list for the extractor that ran: `StageReportView` persists whatever name | ||
| #: the executor sends, so without a per-extractor list a table job's stages | ||
| #: would be stored and then silently filtered out of every status response. | ||
| STAGE_NAMES_BY_EXTRACTOR = { | ||
| V1_EXTRACTOR_NAME: STAGE_NAMES, | ||
| TABLE_EXTRACTOR_NAME: TABLE_STAGE_NAMES, | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,158 @@ | ||
| """Executor dispatch glue (spec §5.3). One dispatch per job; UUID task_id.""" | ||
|
|
||
| import logging | ||
| import uuid | ||
|
|
||
| from celery import signature | ||
| from django.conf import settings | ||
| from django.utils import timezone | ||
|
|
||
| from agent_kv.constants import EXECUTION_SOURCE, EXTRACTOR_ROUTES | ||
| from agent_kv.models import AgentKVJob, JobStatus | ||
| from unstract.sdk1.execution.context import ExecutionContext | ||
|
|
||
| logger = logging.getLogger(__name__) | ||
|
|
||
| CALLBACK_QUEUE = "agent_kv_callback" | ||
|
|
||
|
|
||
| class DispatchError(Exception): | ||
| """Enqueue failed; the caller terminalizes the job (spec §5.3).""" | ||
|
|
||
|
|
||
| def _dispatcher(): | ||
| # No `celery_app`: UN-4046 removed that parameter when the routing | ||
| # dispatcher's Celery branch went with the pg_queue_enabled flag. Passing it | ||
| # raises TypeError, so every submit failed to dispatch -- and because it | ||
| # fails at the call rather than at import, nothing catches it until a real | ||
| # request is made. | ||
| from pg_queue.executor_rpc import get_executor_dispatcher | ||
|
|
||
| return get_executor_dispatcher() | ||
|
|
||
|
|
||
| def _platform_api_key(job) -> str: | ||
| # Lazy import: avoids Django app registry init order (mirrors | ||
| # PromptStudioHelper._get_platform_api_key). | ||
| from platform_settings_v2.platform_auth_service import ( | ||
| PlatformAuthenticationService, | ||
| ) | ||
|
|
||
| # ``get_active_platform_key`` takes the org's public *slug* | ||
| # (``Organization.organization_id``, e.g. ``org_abc123``) and resolves it | ||
| # via ``get_organization_by_org_id`` -- NOT the row's UUID primary key that | ||
| # ``job.organization_id`` holds. Passing the PK here silently resolves to | ||
| # no organization and every dispatch fails with ``ActiveKeyNotFound`` | ||
| # (caught live in the Task 13b integration run). | ||
| org_slug = job.organization.organization_id | ||
| platform_key = PlatformAuthenticationService.get_active_platform_key(org_slug) | ||
| if not platform_key: | ||
| raise DispatchError(f"No active platform key for org {org_slug}") | ||
| return str(platform_key.key) | ||
|
|
||
|
|
||
| def dispatch_job(job, *, extractor: str, schema: dict, options: dict) -> None: | ||
| executor_name, operation = EXTRACTOR_ROUTES[extractor] | ||
| org_id = str(job.organization_id) | ||
| # Everything that can fail — platform-key lookup, context construction, | ||
| # and the enqueue call itself — lives inside this try so no internal | ||
| # failure (e.g. a transient DB error resolving the platform key) can | ||
| # escape as a raw, uncaught exception. Only the post-success bookkeeping | ||
| # below runs outside it. | ||
| try: | ||
| job.task_id = uuid.uuid4() | ||
| context = ExecutionContext( | ||
| executor_name=executor_name, | ||
| operation=operation, | ||
| run_id=str(job.id), | ||
| execution_source=EXECUTION_SOURCE, | ||
| organization_id=org_id, | ||
| executor_params={ | ||
| "job_id": str(job.id), | ||
| "input_ref": job.input_ref, | ||
| "schema": schema, | ||
| "options": options, | ||
| "platform_api_key": _platform_api_key(job), | ||
| # The CAP the engine must enforce (spec §6.1/§6.6), not the | ||
| # measured count -- job.pages_total is None for Excel (no | ||
| # pre-OCR page concept), which would otherwise leave the | ||
| # engine with nothing to check the post-OCR virtual-page cap | ||
| # against. The measured count still rides along separately. | ||
| "max_pages": settings.AGENT_KV_MAX_PAGES, | ||
| "pages_total": job.pages_total, | ||
| }, | ||
| ) | ||
| cb_kwargs = {"callback_kwargs": {"job_id": str(job.id), "org_id": org_id}} | ||
| _dispatcher().dispatch_with_callback( | ||
| context, | ||
| on_success=signature( | ||
| "agent_kv_complete", kwargs=cb_kwargs, queue=CALLBACK_QUEUE | ||
| ), | ||
| on_error=signature("agent_kv_error", kwargs=cb_kwargs, queue=CALLBACK_QUEUE), | ||
| task_id=str(job.task_id), | ||
| ) | ||
| except DispatchError: | ||
| raise | ||
| except Exception as e: | ||
| raise DispatchError(str(e)) from e | ||
| job.status = JobStatus.DISPATCHED | ||
| job.dispatched_at = timezone.now() | ||
| # Guarded queryset UPDATE, not job.save(): a plain save would blindly | ||
| # overwrite whatever status this job already raced to. Concretely: the | ||
| # executor can fail (or the job be cancelled) essentially instantly | ||
| # after enqueue, and its finalize callback can land -- marking the row | ||
| # FAILED/CANCELLED -- before this post-enqueue bookkeeping runs. An | ||
| # unconditional save() here would rewrite that terminal status back to | ||
| # DISPATCHED, un-terminalizing the job forever (nothing else ever | ||
| # revisits a DISPATCHED row). Only a still-PENDING row is advanced; a | ||
| # row this UPDATE doesn't match is left exactly as the winning writer | ||
| # left it. `modified_at` is stamped automatically by | ||
| # BaseModelQuerySet.update() (utils/models/base_model.py). | ||
| # Everything below is POST-ENQUEUE bookkeeping. The task is already on the | ||
| # queue, so a failure here must never be reported as a failed dispatch: | ||
| # `SubmitView` turns a DispatchError into a FAILED job, and the executor | ||
| # would then run, callback, and find a terminal row it cannot write to -- | ||
| # the caller told nothing was billed for work that did run. Wrapped rather | ||
| # than left to propagate, which is what the single pre-review UPDATE did. | ||
| # | ||
| # Losing the bookkeeping entirely is recoverable: sweep phase 1 reaps a | ||
| # still-PENDING row with no `dispatched_at`, and phase 2's | ||
| # `dispatched_at IS NULL` arm covers the non-PENDING case. | ||
| try: | ||
| _record_dispatch(job) | ||
| except Exception: | ||
| logger.exception( | ||
| "agent-kv: dispatch bookkeeping failed for job %s after enqueue " | ||
| "(task is queued; the sweep will reconcile)", | ||
| job.id, | ||
| ) | ||
|
|
||
|
|
||
| def _record_dispatch(job) -> None: | ||
| """Persist task_id/status/dispatched_at against whatever the row raced to.""" | ||
| advanced = AgentKVJob.objects.filter(id=job.id, status=JobStatus.PENDING).update( | ||
| task_id=job.task_id, | ||
| status=job.status, | ||
| dispatched_at=job.dispatched_at, | ||
| ) | ||
| if not advanced: | ||
| # The row moved off PENDING between the enqueue above and this write. | ||
| # The benign case is a terminal status (the guard's whole purpose) -- | ||
| # but there is a non-terminal one: StageReportView promotes | ||
| # PENDING -> RUNNING on the executor's FIRST stage report, which can | ||
| # easily land before this bookkeeping. The guard above then matches 0 | ||
| # rows and `dispatched_at` stays NULL -- and a non-terminal row with a | ||
| # NULL `dispatched_at` is invisible to BOTH sweep phases: phase 1 | ||
| # requires `status=PENDING`, phase 2 filters `dispatched_at__lt=cutoff` | ||
| # and SQL `NULL < x` is never true. The job reports `running` forever | ||
| # and `GET result` 409s for the life of the row, with nothing able to | ||
| # recover it. | ||
| # | ||
| # So stamp the dispatch bookkeeping for any still-non-terminal row, | ||
| # WITHOUT touching `status`: the row genuinely was dispatched, and | ||
| # moving RUNNING back to DISPATCHED would lose the executor's own | ||
| # progress. `dispatched_at__isnull=True` keeps this idempotent and | ||
| # stops a retry overwriting the original dispatch time. | ||
| AgentKVJob.objects.filter(id=job.id, dispatched_at__isnull=True).exclude( | ||
| status__in=list(AgentKVJob.TERMINAL) | ||
| ).update(task_id=job.task_id, dispatched_at=job.dispatched_at) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| from rest_framework.exceptions import APIException | ||
|
|
||
|
|
||
| class EngineUnavailable(APIException): | ||
| status_code = 501 | ||
| default_detail = "agent-kv engine not available on this deployment" | ||
|
|
||
|
|
||
| class RateLimited(APIException): | ||
| status_code = 429 | ||
| default_detail = "Too many requests" | ||
|
|
||
|
|
||
| class JobNotFound(APIException): | ||
| status_code = 404 | ||
| default_detail = "Job not found" |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.