Resource Detail

When a row of a web console list is chosen, the list opens the resource’s detail, a dialog of @smarter/common’s ResourceDetail. Its Details tab is the list’s own DetailView. Its Manifest, Hierarchy and Dependencies tabs are fetched once, from the row’s detailUrl, which MetaDataWithOwnershipModelSerializer adds to every list api’s rows: /dashboard/api/resource/<kind>/<record locator>/.

  • Manifest is the resource’s manifest, as smarter describe returns it to the resource’s owner, as YAML.

  • Hierarchy is dependency_tree(): every resource that it uses, recursively, drawn as the Prompt Engineer’s Workbench’s Architecture tab draws an LLMClient’s.

  • Dependencies is dependents(): the resources that use it, which keep it from being deleted.

A resource that the user may not read, in the hierarchy or among the dependents, is locked: it has its kind and record locator only. A resource that the user may not read, or whose kind is not the url’s, has no detail: the api answers 404.

The detail of one Smarter resource, for the web console’s resource lists.

Each list of the web console (see smarter.lib.django.listview.SmarterListApiView) opens a resource’s detail when one of its rows is chosen. Besides the row’s own fields, the detail shows:

  • its manifest, as YAML, as smarter describe returns it;

  • its hierarchy: the tree of every resource that it uses, recursively (dependency_tree());

  • its dependents: the resources that use it, and that keep it from being deleted (dependents()).

A resource is identified by its SAM kind and its record locator, e.g. Guardrail and guardrail-rMTAwx. Each row of a list has the url of its detail, its detail_url, which smarter.apps.account.serializers.MetaDataWithOwnershipModelSerializer adds.

class smarter.apps.dashboard.resource_detail.ResourceDetail(**data)[source]

Bases: BaseModel

The detail of one resource: its manifest, the resources that it uses, and those that use it.

dependents: list[SAMDependencyTreeNode]
kind: str
manifest: str | None
manifest_error: str
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str | None
record_locator: str
tree: SAMDependencyTreeNode
url: str | None
smarter.apps.dashboard.resource_detail.instance_of_kind(broker, kind, instance)[source]

Return a resource as a row of a kind’s model, or None if it is not of the kind.

The kind and the record locator of a detail’s url are separate, so a url could pair a resource with another kind, whose broker would then find a different resource by the same name. A resource of the kind is a row of its broker’s model, or of its meta model (a plugin’s PluginMeta). A row of a parent model of the kind’s model, e.g. the ConnectionBase of an SqlConnection, which a list may show, is the kind’s row of the same primary key, if it has one.

Parameters:
  • broker (AbstractBroker) – A broker of the kind.

  • kind (str) – The SAM kind, e.g. Guardrail.

  • instance (Model) – The resource’s Django ORM instance.

Returns:

The resource’s row of the kind’s model, or None.

Return type:

Model | None

smarter.apps.dashboard.resource_detail.manifest_yaml(kind, instance)[source]

Return a resource’s manifest, as YAML, as smarter describe returns it to its owner.

The resource is described on behalf of its owner, as the web console’s manifest pages do, because a broker finds a resource by its name among those of its own user. The caller has already checked that the user may read it (see readable_instance()).

Parameters:
  • kind (str) – The resource’s SAM kind.

  • instance (Model) – The resource’s Django ORM instance, which has a user_profile and a name.

Returns:

The manifest, and an empty string, or None and why it could not be read.

Return type:

tuple[str | None, str]

smarter.apps.dashboard.resource_detail.models_by_record_locator_prefix() → dict[str, type[Model]][source]

Return each Django model that has record locators, by the prefix of its record locators.

A model has record locators when it has get_object_by_locator(), as every TimestampedModel has. The installed models don’t change while the process runs, so the map is computed once per process.

Returns:

The models, e.g. {"guardrail": Guardrail, ...}.

Return type:

dict[str, type[Model]]

smarter.apps.dashboard.resource_detail.readable_instance(user, record_locator)[source]

Return the resource of a record locator, if the user may read it.

Parameters:
  • user – The authenticated user.

  • record_locator (str) – The resource’s record locator, e.g. guardrail-rMTAwx.

Returns:

The resource’s Django ORM instance, or None if there is none, or the user may not read it.

Return type:

Model | None

smarter.apps.dashboard.resource_detail.resource_detail(request, kind, record_locator)[source]

Return the detail of a resource that the request’s user may read.

The hierarchy and the dependents are built by a broker of the user’s own request, so that a resource that the user may not read is locked in them, as in the Prompt Engineer’s Workbench’s Architecture tab.

detail = resource_detail(request, "Guardrail", "guardrail-rMTAwx")
detail.model_dump(mode="json")
# {"kind": "Guardrail", "name": "pii_redaction", "recordLocator": "guardrail-rMTAwx",
#  "url": "/guardrail/guardrails/rMTAwx/", "manifest": "apiVersion: smarter.sh/v1\n...",
#  "manifestError": "", "tree": {...}, "dependents": [{"kind": "LLMClient", ...}]}
Parameters:
  • request – The request, whose user is authenticated.

  • kind (str) – The resource’s SAM kind, e.g. Guardrail.

  • record_locator (str) – The resource’s record locator.

Returns:

The detail, or None if there is no such resource, the user may not read it, or no broker knows its kind.

Return type:

ResourceDetail | None

smarter.apps.dashboard.resource_detail.resource_detail_url(kind, record_locator)[source]

Return the url of a resource’s detail, from its kind and record locator.

The list api serializers (smarter.apps.account.serializers.MetaDataWithOwnershipModelSerializer) and the REST api’s contract models send it as detailUrl.

resource_detail_url("Guardrail", "guardrail-rMTAwx")
# '/dashboard/api/resource/Guardrail/guardrail-rMTAwx/'
Parameters:
  • kind (str | None) – The resource’s SAM kind, e.g. Guardrail.

  • record_locator (str | None) – The resource’s record locator.

Returns:

The url, or None if either is missing.

Return type:

str | None

API view of a resource’s detail, for the web console’s resource lists.

When a row of a list is chosen, the list opens the resource’s detail, whose Manifest, Hierarchy and Dependencies tabs are fetched here, from the row’s detailUrl. See smarter.apps.dashboard.resource_detail.

class smarter.apps.dashboard.views.views.api.resource_detail.ResourceDetailView(**kwargs)[source]

Bases: SmarterAuthenticatedNeverCachedWebView

Return the detail of a resource that the user may read: its manifest, what it uses, and what uses it.

The url names the resource’s SAM kind and its record locator. A resource that doesn’t exist, that the user may not read, or that is not of the kind, is a 404.

Response shape, a dumped ResourceDetail:

{
    "kind": "Guardrail",
    "name": "pii_redaction",
    "recordLocator": "guardrail-rMTAwx",
    "url": "/guardrail/guardrails/rMTAwx/",
    "manifest": "apiVersion: smarter.sh/v1\nkind: Guardrail\n...",
    "manifestError": "",
    "tree": {"kind": "Guardrail", "name": "pii_redaction", "children": [...], ...},
    "dependents": [{"kind": "LLMClient", "name": "stackademy", "children": [], ...}]
}

Example usage:

GET /dashboard/api/resource/Guardrail/guardrail-rMTAwx/
get(request, *args, **kwargs)[source]

Return the same json as a POST, so that the detail can be browsed.

Return type:

JsonResponse

post(request, *args, **kwargs)[source]

Return the resource’s detail.

Parameters:
  • request (HttpRequest) – The request.

  • kwargs – kind and record_locator, from the url.

Returns:

The detail, or {"error": ...}, a 404.

Return type:

JsonResponse