@terreno/mcp 57.8.0 → 57.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/docs/upgrades/57.10.1.md +54 -0
- package/dist/docs/upgrades/57.9.0.md +28 -0
- package/dist/docs/versioned/next/README.md +1 -0
- package/dist/docs/versioned/next/explanation/README.md +4 -0
- package/dist/docs/versioned/next/explanation/admin-plugin-frontend.md +2 -2
- package/dist/docs/versioned/next/explanation/agent-ui-asks.md +299 -0
- package/dist/docs/versioned/next/explanation/agent-ui-blocks.md +67 -0
- package/dist/docs/versioned/next/explanation/ai-observability.md +101 -0
- package/dist/docs/versioned/next/explanation/charts.md +12 -0
- package/dist/docs/versioned/next/explanation/durable-agent-harness.md +531 -0
- package/dist/docs/versioned/next/explanation/example-coverage.md +4 -2
- package/dist/docs/versioned/next/explanation/loop-engineering.md +1 -1
- package/dist/docs/versioned/next/explanation/roadmap-seed-issues.md +49 -1
- package/dist/docs/versioned/next/explanation/typescript-configuration.md +1 -1
- package/dist/docs/versioned/next/explanation/versioning-policy.md +1 -1
- package/dist/docs/versioned/next/how-to/README.md +7 -1
- package/dist/docs/versioned/next/how-to/admin-import-prebuilt.md +1 -1
- package/dist/docs/versioned/next/how-to/agent-ui-asks.md +730 -0
- package/dist/docs/versioned/next/how-to/agent-ui-blocks.md +104 -0
- package/dist/docs/versioned/next/how-to/ai-feature-development.md +156 -0
- package/dist/docs/versioned/next/how-to/build-a-durable-workflow.md +232 -0
- package/dist/docs/versioned/next/how-to/charts-and-dashboards.md +7 -0
- package/dist/docs/versioned/next/how-to/circleci.md +9 -6
- package/dist/docs/versioned/next/how-to/compare-chart-rendered-snapshots.md +8 -0
- package/dist/docs/versioned/next/how-to/install-agent-skills.md +1 -1
- package/dist/docs/versioned/next/how-to/observe-llm-calls.md +197 -0
- package/dist/docs/versioned/next/how-to/run-tests-locally.md +2 -1
- package/dist/docs/versioned/next/how-to/ship-a-new-task-version.md +76 -0
- package/dist/docs/versioned/next/how-to/upgrade-terreno.md +1 -1
- package/dist/docs/versioned/next/implementationPlans/agent-ui-asks.md +688 -0
- package/dist/docs/versioned/next/implementationPlans/agent-ui-blocks.md +10 -6
- package/dist/docs/versioned/next/implementationPlans/ai-observability.md +475 -157
- package/dist/docs/versioned/next/implementationPlans/b2b-platform-program.md +1 -1
- package/dist/docs/versioned/next/implementationPlans/charts-and-dashboards.md +3 -2
- package/dist/docs/versioned/next/implementationPlans/dashboard-chart-parity.md +275 -0
- package/dist/docs/versioned/next/implementationPlans/durable-agent-harness.md +340 -0
- package/dist/docs/versioned/next/implementationPlans/terreno-langfuse-integration.md +1 -1
- package/dist/docs/versioned/next/reference/README.md +3 -0
- package/dist/docs/versioned/next/reference/admin-config.md +2 -0
- package/dist/docs/versioned/next/reference/admin-frontend.md +216 -0
- package/dist/docs/versioned/next/reference/agent-ui-asks.md +1059 -0
- package/dist/docs/versioned/next/reference/ai-harness.md +1881 -0
- package/dist/docs/versioned/next/reference/ai.md +283 -28
- package/dist/docs/versioned/next/reference/api.md +46 -0
- package/dist/docs/versioned/next/reference/blocks.md +178 -0
- package/dist/docs/versioned/next/reference/environment-variables.md +2 -1
- package/dist/docs/versioned/next/reference/feature-flags.md +1 -1
- package/dist/docs/versioned/next/reference/mcp-server.md +17 -0
- package/dist/docs/versioned/next/reference/test.md +11 -2
- package/dist/docs/versioned/next/reference/ui.md +418 -11
- package/dist/docs/versioned/next/tasks/agent-ui-asks.md +213 -0
- package/dist/docs/versioned/next/tasks/agent-ui-blocks.md +2 -1
- package/dist/docs/versioned/next/tasks/ai-observability.md +233 -104
- package/dist/docs/versioned/next/tasks/dashboard-chart-parity.md +145 -0
- package/dist/docs/versioned/next/tasks/durable-agent-harness.md +183 -0
- package/dist/tools.d.ts +4 -0
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +37 -0
- package/dist/tools.js.map +1 -1
- package/package.json +3 -2
- package/src/docs/upgrades/57.10.1.md +54 -0
- package/src/docs/upgrades/57.9.0.md +28 -0
- package/src/docs/versioned/next/README.md +1 -0
- package/src/docs/versioned/next/explanation/README.md +4 -0
- package/src/docs/versioned/next/explanation/admin-plugin-frontend.md +2 -2
- package/src/docs/versioned/next/explanation/agent-ui-asks.md +299 -0
- package/src/docs/versioned/next/explanation/agent-ui-blocks.md +67 -0
- package/src/docs/versioned/next/explanation/ai-observability.md +101 -0
- package/src/docs/versioned/next/explanation/charts.md +12 -0
- package/src/docs/versioned/next/explanation/durable-agent-harness.md +531 -0
- package/src/docs/versioned/next/explanation/example-coverage.md +4 -2
- package/src/docs/versioned/next/explanation/loop-engineering.md +1 -1
- package/src/docs/versioned/next/explanation/roadmap-seed-issues.md +49 -1
- package/src/docs/versioned/next/explanation/typescript-configuration.md +1 -1
- package/src/docs/versioned/next/explanation/versioning-policy.md +1 -1
- package/src/docs/versioned/next/how-to/README.md +7 -1
- package/src/docs/versioned/next/how-to/admin-import-prebuilt.md +1 -1
- package/src/docs/versioned/next/how-to/agent-ui-asks.md +730 -0
- package/src/docs/versioned/next/how-to/agent-ui-blocks.md +104 -0
- package/src/docs/versioned/next/how-to/ai-feature-development.md +156 -0
- package/src/docs/versioned/next/how-to/build-a-durable-workflow.md +232 -0
- package/src/docs/versioned/next/how-to/charts-and-dashboards.md +7 -0
- package/src/docs/versioned/next/how-to/circleci.md +9 -6
- package/src/docs/versioned/next/how-to/compare-chart-rendered-snapshots.md +8 -0
- package/src/docs/versioned/next/how-to/install-agent-skills.md +1 -1
- package/src/docs/versioned/next/how-to/observe-llm-calls.md +197 -0
- package/src/docs/versioned/next/how-to/run-tests-locally.md +2 -1
- package/src/docs/versioned/next/how-to/ship-a-new-task-version.md +76 -0
- package/src/docs/versioned/next/how-to/upgrade-terreno.md +1 -1
- package/src/docs/versioned/next/implementationPlans/agent-ui-asks.md +688 -0
- package/src/docs/versioned/next/implementationPlans/agent-ui-blocks.md +10 -6
- package/src/docs/versioned/next/implementationPlans/ai-observability.md +475 -157
- package/src/docs/versioned/next/implementationPlans/b2b-platform-program.md +1 -1
- package/src/docs/versioned/next/implementationPlans/charts-and-dashboards.md +3 -2
- package/src/docs/versioned/next/implementationPlans/dashboard-chart-parity.md +275 -0
- package/src/docs/versioned/next/implementationPlans/durable-agent-harness.md +340 -0
- package/src/docs/versioned/next/implementationPlans/terreno-langfuse-integration.md +1 -1
- package/src/docs/versioned/next/reference/README.md +3 -0
- package/src/docs/versioned/next/reference/admin-config.md +2 -0
- package/src/docs/versioned/next/reference/admin-frontend.md +216 -0
- package/src/docs/versioned/next/reference/agent-ui-asks.md +1059 -0
- package/src/docs/versioned/next/reference/ai-harness.md +1881 -0
- package/src/docs/versioned/next/reference/ai.md +283 -28
- package/src/docs/versioned/next/reference/api.md +46 -0
- package/src/docs/versioned/next/reference/blocks.md +178 -0
- package/src/docs/versioned/next/reference/environment-variables.md +2 -1
- package/src/docs/versioned/next/reference/feature-flags.md +1 -1
- package/src/docs/versioned/next/reference/mcp-server.md +17 -0
- package/src/docs/versioned/next/reference/test.md +11 -2
- package/src/docs/versioned/next/reference/ui.md +418 -11
- package/src/docs/versioned/next/tasks/agent-ui-asks.md +213 -0
- package/src/docs/versioned/next/tasks/agent-ui-blocks.md +2 -1
- package/src/docs/versioned/next/tasks/ai-observability.md +233 -104
- package/src/docs/versioned/next/tasks/dashboard-chart-parity.md +145 -0
- package/src/docs/versioned/next/tasks/durable-agent-harness.md +183 -0
|
@@ -40,6 +40,8 @@
|
|
|
40
40
|
`AdminAction` has `id`, `label`, optional `confirm`, `background`, and `patchKeys`.
|
|
41
41
|
|
|
42
42
|
`AdminContribution` may provide `models`, `customScreens`, `homeWidgets`, and `scripts`.
|
|
43
|
+
`customScreens[].group` becomes a named sidebar heading (`AI Observability`). Screens without
|
|
44
|
+
`group` stay under **Screens** — that is where **AI Requests** remains.
|
|
43
45
|
Model contributions contain `model`, `routePath`, and `admin`. Duplicate `routePath`s
|
|
44
46
|
throw for registered routers; the same Mongoose model at two paths gets unique config
|
|
45
47
|
`name`s so the admin UI can route to each.
|
|
@@ -434,3 +434,219 @@ import {CommsDashboardScreenWidget, CommsMessageDetail} from "@terreno/admin-fro
|
|
|
434
434
|
The list screen persists filters in the URL (`channel`, `provider`, `status`, `errorClass`, `q`,
|
|
435
435
|
`startDate`, `endDate`, `page`) and calls `/comms/messages`, `/comms/stats`, and
|
|
436
436
|
`/comms/messages/retryMany`.
|
|
437
|
+
|
|
438
|
+
### AI Observability chrome
|
|
439
|
+
|
|
440
|
+
`ObservabilityApp` contributes grouped custom screens (`group: "AI Observability"`): `ai-prompts`,
|
|
441
|
+
`ai-traces`, `ai-evaluators`, `ai-datasets`, `ai-experiments`, and `ai-review` when the local
|
|
442
|
+
plugin is on. `AI Requests` (`ai-requests`) stays ungrouped. Widgets also register detail routes:
|
|
443
|
+
`ai-prompt-editor`, `ai-trace-detail`, `ai-review-item`, `ai-evaluator-detail`, `ai-evaluator-new`,
|
|
444
|
+
`ai-dataset-detail`, `ai-experiment-new`, and `ai-experiment-results`.
|
|
445
|
+
|
|
446
|
+
Every observability screen wraps `AiObservabilityChrome`: breadcrumbs
|
|
447
|
+
`Admin / AI Observability / <Section> / <leaf>` and a status chip from
|
|
448
|
+
`GET /ai/observability/status` (`Local on|off` plus active primaries). Review queue nav and the
|
|
449
|
+
review screen body hide when `localOn` is false.
|
|
450
|
+
|
|
451
|
+
Each observability list screen is contributed with `adminAccess: {resource, action: "list"}` so
|
|
452
|
+
`/admin/config` omits screens the caller cannot list (`aiPrompt`, `aiTrace`, `aiEvaluator`,
|
|
453
|
+
`aiDataset`, `aiExperiment`, `aiReview`). Detail routes stay registered on the host; route
|
|
454
|
+
handlers still enforce Task 4.1 RBAC.
|
|
455
|
+
|
|
456
|
+
`GET /ai/observability/status` includes a `permissions` map (per observability resource and
|
|
457
|
+
action). Legacy admin users and apps without `accessControl` receive all actions `true`. RBAC
|
|
458
|
+
callers receive effective flags for the signed-in user. Pass the same `accessControl` to
|
|
459
|
+
`ObservabilityApp` and `AdminApp` so status permissions match sidebar filtering. Admin widgets
|
|
460
|
+
read the payload through `resolvePromptActionPermissions` and `observabilityActionAllowed` (fail
|
|
461
|
+
closed while status is loading, errored, or missing `permissions`). List screens gate **Create
|
|
462
|
+
prompt** on `aiPrompt:create`, **Create evaluator** on `aiEvaluator:create`, and **New dataset** on
|
|
463
|
+
`aiDataset:create`; experiment lists hide **New experiment** without `aiExperiment:create`.
|
|
464
|
+
Dataset detail hides **Add item** without `aiDataset:update` and **Run experiment** without
|
|
465
|
+
`aiExperiment:create`; dataset lists hide **Import** without
|
|
466
|
+
`aiDataset:update`. Judge schema checks use the production prompt version, or the latest version
|
|
467
|
+
when production is unset. Widgets do not couple to host Redux.
|
|
468
|
+
|
|
469
|
+
`ai-prompts` lists prompts with a folder rail, search, type badge, latest vs production columns
|
|
470
|
+
(tooltips), 7-day usage, and **Create prompt** when `aiPrompt:create` is allowed. The create modal
|
|
471
|
+
includes an optional **Description** (saved on the prompt record and shown on the hub Overview tab).
|
|
472
|
+
`ai-prompt-editor?name=` is a prompt hub with **Overview**, **Versions**, **Traces**, and
|
|
473
|
+
**Experiments** tabs. Overview shows optional description, folder, tags, and latest vs production
|
|
474
|
+
badges. Traces and Experiments render bounded relationship rows from
|
|
475
|
+
`GET /ai/observability/prompts/:name?promptVersion=` (the hub pins the selected version, defaulting
|
|
476
|
+
to latest after the first load, so related traces and experiments are filtered server-side while the
|
|
477
|
+
full immutable version list stays on the detail payload). The **Versions** tab
|
|
478
|
+
hosts the versioned editor: full-width version history rows show `vN`, every label attached to
|
|
479
|
+
that version, and its creation time on one line. The selected row is highlighted. Editor /
|
|
480
|
+
Playground tabs appear on Versions when allowed; **Save as vN+1**, **Set vN as production…**, and
|
|
481
|
+
playground **Run once** hide when `aiPrompt:update`, `aiPrompt:promote`, or `aiPrompt:playground`
|
|
482
|
+
is denied (fields stay read-only). Playground **Run once** does not create a version; hosts may pass `apiKey` to
|
|
483
|
+
`AiPromptEditorScreenWidget`, which forwards it as `x-ai-api-key` without putting the key in the
|
|
484
|
+
request body. Pass `apiKeyLoading` while the host reads a saved key (for example from
|
|
485
|
+
`useStoredState`) so the playground waits instead of showing a missing-key message. Pass
|
|
486
|
+
`playgroundApiKeyHint` when `GET /ai/observability/status` reports
|
|
487
|
+
`playgroundAi.source: "request-key"`; the editor blocks **Run once** and shows that hint until a
|
|
488
|
+
trimmed key is available. When `playgroundAi.source` is `server`, no key is required. When it is
|
|
489
|
+
`unavailable`, the editor explains that the backend must configure `aiService` or
|
|
490
|
+
`requestAiServiceFactory`. A stale playground **503** with the missing-key title is remapped to the
|
|
491
|
+
same hint for `request-key` hosts so operators are not told to fix server configuration. The
|
|
492
|
+
example admin supplies the Gemini key saved from Profile. **Save this run to dataset** stays
|
|
493
|
+
disabled until phase 2.
|
|
494
|
+
|
|
495
|
+
`ai-traces` lists traces with a filter bar: from/to date fields; dropdowns for prompt, status,
|
|
496
|
+
score presence (**All traces / Has a score / No scores**), and data sensitivity
|
|
497
|
+
(**All traces / Sensitive only / Not sensitive**); plus user and session text fields.
|
|
498
|
+
Checkbox selection opens a bulk bar with **Send to human review**, a sensitive-count
|
|
499
|
+
warning, **Clear**, and **Add to dataset** (opens a dataset picker modal; sensitive traces show a
|
|
500
|
+
warning before bulk add). **Send to human review** opens a modal that explains how human
|
|
501
|
+
evaluators define the score fields and reviewer instructions, then requires a human evaluator
|
|
502
|
+
before creating one review-queue item per trace. When local trace storage is on,
|
|
503
|
+
**Run multi-stage trace test** calls the admin-only smoke endpoint and
|
|
504
|
+
opens the resulting detail: two schema-validated LLM stages, one deterministic tool span, and a
|
|
505
|
+
final schema-validated combining LLM stage under one CHAIN root. LLM span input includes
|
|
506
|
+
`outputSchema`. That run needs AI the same way the playground does: hosts may pass `apiKey`,
|
|
507
|
+
`apiKeyLoading`, and `apiKeyHint` to `AiTracesScreenWidget`, which forwards the key as
|
|
508
|
+
`x-ai-api-key`. When `GET /ai/observability/status` reports `playgroundAi.source: "request-key"`
|
|
509
|
+
and no trimmed key is available, the button is disabled and the hint explains where to save one;
|
|
510
|
+
`unavailable` instead reports that the backend must configure `aiService` or
|
|
511
|
+
`requestAiServiceFactory`. The example admin supplies the Gemini key saved from Profile. Rows show a status dot (primary for successful runs, accent for failed runs),
|
|
512
|
+
`sensitive` badge, error line, numeric prompt count, span count, tokens, cost, latency, score count, and
|
|
513
|
+
**Open**. Pagination uses `page` / `limit` / `more` / `total`.
|
|
514
|
+
`ai-trace-detail?id=` shows the header, left span list (kind badge, indent, duration bar),
|
|
515
|
+
right span detail with **collapsed** sensitive I/O, and scores (value + source). The two columns
|
|
516
|
+
size from the row width rather than their content, so a wide span value (multi-stage LLM spans embed
|
|
517
|
+
`outputSchema` JSON) wraps inside the detail column instead of pushing it below the span list.
|
|
518
|
+
|
|
519
|
+
`ai-review` shows Pending / In progress / Done / Skipped tabs with counts. Each tab is
|
|
520
|
+
oldest-first and lists the trace action, prompt, assignee, waiting time, and status.
|
|
521
|
+
**Start reviewing — oldest first** opens the first pending item; the empty state names both
|
|
522
|
+
Traces intake and manual **Assign to me** assignment.
|
|
523
|
+
|
|
524
|
+
`ai-review-item?id=` shows "Item N of M pending", previous/next navigation, read-only
|
|
525
|
+
**What the AI was given** / **What the AI wrote** panels, collapsed long fields with word
|
|
526
|
+
counts, reviewer notes, and a collapsed Raw JSON disclosure. Score controls come from evaluator
|
|
527
|
+
dimensions (numeric slider, boolean Pass / Fail, categorical pills). Actions are
|
|
528
|
+
**Submit & next**, **Skip**, and **Assign to me**; completion toasts report the remaining count
|
|
529
|
+
or **Queue clear**.
|
|
530
|
+
|
|
531
|
+
`ai-evaluators` lists evaluators with type badge, dimension summary, target, and run-mode chips.
|
|
532
|
+
**Create evaluator** opens `ai-evaluator-new` with the name and optional purpose first, then how
|
|
533
|
+
scoring happens (human / JSON assert / LLM judge). New evaluators score a **full trace** only;
|
|
534
|
+
generation span and dataset item targets are not offered yet. Score fields depend on data type:
|
|
535
|
+
boolean has no extra control, numeric asks for min and max, and categorical is a list you add to.
|
|
536
|
+
LLM judge picks the judge prompt from the existing prompt list. Human setup points operators to
|
|
537
|
+
**Send to human review** and omits live sampling because it never applies; automatic evaluators
|
|
538
|
+
explain experiment/manual availability and production sampling, while LLM judges call out the billed
|
|
539
|
+
model-call impact. The optional purpose is saved as the evaluator description and appears on its
|
|
540
|
+
detail screen. LLM judge schema feedback stays idle until a prompt is selected, then shows
|
|
541
|
+
loading/error states and only checks dimensions after its production schema loads.
|
|
542
|
+
`ai-evaluator-detail?id=` leads with the evaluator name, description, and type/target/run-mode
|
|
543
|
+
badges, then explains the saved scores, how scoring works, where it runs, and a **Used by** list
|
|
544
|
+
derived from recent experiments. A failed experiments request shows **Could not load experiments.**
|
|
545
|
+
instead of an empty 30-day list. Its dimension and usage rows use the shared `ObservabilityTable` instead of
|
|
546
|
+
`DataTable`, which sizes to a height-constrained parent and collapses inside a scrolling page. LLM
|
|
547
|
+
judge details show loading or load-failed feedback while resolving the judge prompt; schema
|
|
548
|
+
mismatches appear only after its production schema loads.
|
|
549
|
+
|
|
550
|
+
`ai-datasets` lists datasets with item counts, provenance bar, input-schema binding, and updated
|
|
551
|
+
time. **New dataset** creates a dataset; **Import** on each row accepts `.json` or `.csv` via
|
|
552
|
+
`FilePickerButton` (local URI read) or paste, posting `{rows}` for JSON or `{format:'csv',content}`
|
|
553
|
+
for CSV. `ai-dataset-detail?id=` shows counts, schema binding, tabs **All / Human / Auto / Needs
|
|
554
|
+
review**. Human is proofread items. Auto is unreviewed trace or synthetic items, so a proofread
|
|
555
|
+
trace is not listed in both tabs. The screen includes an items table (input, expected, provenance,
|
|
556
|
+
trace link), **Add item**, and **Run experiment**. The items table uses `ObservabilityTable`: rows grow with their content
|
|
557
|
+
and cells wrap to three lines before truncating, so long inputs and expected outputs no longer
|
|
558
|
+
overlap adjacent rows. Input and Expected receive 2.5× the flexible width of metadata columns.
|
|
559
|
+
Selecting a row opens a scrollable modal with the complete input, expected output, provenance,
|
|
560
|
+
annotation ids, tags, timestamps, metadata, and an **Open source trace** action when linked.
|
|
561
|
+
Opening the source trace dismisses the item modal before navigation.
|
|
562
|
+
Item-query loading and failures render dedicated states with Retry; they never appear as an empty
|
|
563
|
+
dataset.
|
|
564
|
+
|
|
565
|
+
`ObservabilityTable` (`widgets/aiObservability/shell/ObservabilityTable.tsx`) is the shared
|
|
566
|
+
flow-height table for these screens. Columns take a `title`, optional `minWidth`, and optional
|
|
567
|
+
relative `grow`; rows take a `key`, `cells`, and optional click/accessibility properties. A string
|
|
568
|
+
cell renders truncated text and a node cell renders as-is. Its
|
|
569
|
+
bordered shell shrink-wraps the rows inside flex/scroll parents so its bottom border cannot stretch
|
|
570
|
+
into the following section.
|
|
571
|
+
|
|
572
|
+
`ai-experiments` lists experiments with status, running progress, and cost. **New experiment**
|
|
573
|
+
opens a four-step wizard (dataset with counts, prompt versions tagged latest/production/superseded,
|
|
574
|
+
llm-judge and json-assert evaluators, review & run with estimate). A slower in-flight estimate is ignored after the selection changes, so it cannot replace a newer estimate or its error. Human evaluators are omitted. On the prompt-versions step, **Next** and the later
|
|
575
|
+
wizard rail buttons stay disabled until 2–3 versions are selected. `includeUnproofread` and optional model override are on
|
|
576
|
+
the wizard. `ai-experiment-results?id=` polls while pending/running, shows gate tiles per version,
|
|
577
|
+
failing gate count, outliers, a side-by-side per-item output table (failed rows first from the
|
|
578
|
+
API), and **Promote to production** with a confirm modal; promote is blocked when gates fail (409).
|
|
579
|
+
|
|
580
|
+
### AI Harness approvals inbox
|
|
581
|
+
|
|
582
|
+
`HarnessApp` (`@terreno/ai/harness`) contributes custom screen `harness-approvals`
|
|
583
|
+
(`group: "AI Harness"`, label **Approvals**) through `adminContribution()`, so registering
|
|
584
|
+
`HarnessApp` before `AdminApp` is enough on the backend. `HARNESS_ADMIN_WIDGETS["harness-approvals"]`
|
|
585
|
+
(`HarnessApprovalsScreenWidget`) is in the built-in screen registry, so `/admin/harness-approvals`
|
|
586
|
+
renders through `AdminScreenRouter` with no host route file. See
|
|
587
|
+
[AI harness approvals](ai-harness.md#approvals).
|
|
588
|
+
|
|
589
|
+
The inbox lists the pending approvals the signed-in user may decide
|
|
590
|
+
(`GET /harness/approvals`, oldest first), each with title, task (`name@version` from
|
|
591
|
+
`definitionKey`), age, and expiry. Selecting one shows its `summary` (rendered with `MarkdownView`
|
|
592
|
+
when it looks like markdown) and `payload` (pretty JSON; a string payload that looks like
|
|
593
|
+
markdown renders as markdown), plus a **Reason** field and
|
|
594
|
+
**Approve** / **Reject**.
|
|
595
|
+
|
|
596
|
+
| Behavior | Detail |
|
|
597
|
+
| --- | --- |
|
|
598
|
+
| Approve | `POST /harness/approvals/:id/approve` with `{reason}` when one was typed, else `{}`. |
|
|
599
|
+
| Reject | Requires a non-blank reason (checked before the request); `POST .../reject` with `{reason}` (trimmed). |
|
|
600
|
+
| Success | Back to the list with a confirmation; the list refetches. |
|
|
601
|
+
| 409 | "Already decided, expired, or its task ended" notice; back to the list and refetch. |
|
|
602
|
+
| Other errors | The API error `title` under the buttons; the detail stays open. |
|
|
603
|
+
| States | Loading spinner, error with **Try again**, empty (**Nothing to approve.**), **Refresh** button. |
|
|
604
|
+
| Page size | The oldest 100 (`?limit=100`). When the response has `more`, a note says so; deciding items brings the rest into view. |
|
|
605
|
+
| In flight | Both buttons and the reason field are disabled until the decision returns, so it is sent once. |
|
|
606
|
+
|
|
607
|
+
Requests use the host-bound admin request client (`AdminProvider` `getAuthHeaders` / `apiOrigin`),
|
|
608
|
+
never RTK `injectEndpoints`. Test ids: `harness-approvals` (root), `harness-approvals-list`,
|
|
609
|
+
`harness-approvals-empty`, `harness-approvals-error`, `harness-approvals-loading`,
|
|
610
|
+
`harness-approvals-refresh`, `harness-approvals-notice`, `harness-approval-row-<id>-clickable`,
|
|
611
|
+
`harness-approval-detail`, `harness-approval-payload`, `harness-approval-reason`,
|
|
612
|
+
`harness-approval-approve`, `harness-approval-reject`, `harness-approval-error`,
|
|
613
|
+
`harness-approval-back` (standalone only; in admin the page back chevron closes the detail).
|
|
614
|
+
|
|
615
|
+
#### Mount outside admin chrome
|
|
616
|
+
|
|
617
|
+
`HarnessApprovalInbox` is exported for app screens (for example a clinician view). Inside an
|
|
618
|
+
`AdminProvider` it needs no props. Elsewhere, pass a request client from `bindAdminRequest`:
|
|
619
|
+
|
|
620
|
+
```typescript
|
|
621
|
+
import {bindAdminRequest, HarnessApprovalInbox} from "@terreno/admin-frontend";
|
|
622
|
+
import {baseUrl} from "@terreno/rtk";
|
|
623
|
+
import {Page} from "@terreno/ui";
|
|
624
|
+
|
|
625
|
+
// getAuthHeaders: the host's `() => ({Authorization: "Bearer …"})`, as passed to AdminProvider.
|
|
626
|
+
const request = bindAdminRequest({getAuthHeaders, origin: baseUrl});
|
|
627
|
+
|
|
628
|
+
export const SignOffScreen: React.FC = () => (
|
|
629
|
+
<Page title="Sign-offs" scroll>
|
|
630
|
+
<HarnessApprovalInbox request={request} />
|
|
631
|
+
</Page>
|
|
632
|
+
);
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
| Prop | Type | Default | Description |
|
|
636
|
+
| --- | --- | --- | --- |
|
|
637
|
+
| `request` | `(args: AdminRequestArgs) => Promise<unknown>` | `AdminProvider` client | Request client, usually `bindAdminRequest({getAuthHeaders, origin})`. |
|
|
638
|
+
| `baseUrl` | `string` | `/harness` | Where `HarnessApp` is mounted (its `basePath`). Relative paths resolve against the client's `origin`. |
|
|
639
|
+
| `selected` | `HarnessApprovalRow \| undefined` | internal | Controlled selection: the approval whose detail is open. |
|
|
640
|
+
| `onSelectedChange` | `(approval \| undefined) => void` | — | With `selected`, lets the host's back control close the detail; the inbox then hides its own **All approvals** button. The admin screen uses this so the page chevron returns to the list. |
|
|
641
|
+
| `showHeading` | `boolean` | `true` | Show the **Approvals** heading; the admin screen passes `false` because `AdminScreenPage` already titles it. |
|
|
642
|
+
| `testID` | `string` | `harness-approvals` | Root test id. |
|
|
643
|
+
|
|
644
|
+
The built-in admin screen always uses `/harness`. A host that mounts `HarnessApp` at another
|
|
645
|
+
`basePath` registers its own `widgets.screens["harness-approvals"]` that renders
|
|
646
|
+
`<HarnessApprovalInbox baseUrl="/ops/harness" />`.
|
|
647
|
+
|
|
648
|
+
The example backend registers `HarnessApp` with a demo task, `demo.approvalDemo@1`. Start
|
|
649
|
+
approvals with the admin script `startHarnessApprovalDemo` (args `count`, default 2, and `prefix`)
|
|
650
|
+
from the admin Scripts screen or `bun run script startHarnessApprovalDemo --wet`. It needs Mongo
|
|
651
|
+
running as a replica set; without one the backend logs `Harness disabled` and skips the routes.
|
|
652
|
+
`example-frontend/e2e/harness-approvals.spec.ts` approves one and rejects one.
|