Skip to content
 
 

Repository files navigation

Wippy logo

Module Session

Latest Release License Documentation

Artifacts

An artifact is generated content that outlives the message that produced it. A tool returns _control.artifacts, this module persists it, writes the messages that reference it, and serves it over HTTP.

Render mode and placement

An artifact carries two independent settings.

Setting Field on _control.artifacts[] Stored as
Render mode type the kind column
Placement display_type meta.display_type

Render mode determines how a client draws the artifact. It is returned as type by GET /artifact/{id}.

type Drawn as
inline (default) the content itself, in the message
standalone a chip the reader clicks to open the artifact
inline-interactive the artifact in a sandboxed, proxy-enabled frame
view_ref a server-rendered page reference; requires page_id

Values are stored verbatim and are not validated. A value outside this set matches no renderer branch, and the artifact renders as nothing.

Placement determines which messages this module writes, and therefore how the artifact reaches the thread.

display_type Messages written How it reaches the thread
standalone type="artifact" with metadata.artifact_id, plus system artifact_created the client renders the artifact message
inline a developer message carrying an embed instruction, plus system the agent pastes <artifact id="…"/> into its reply

The reference tools derive placement from instructions: true → inline, otherwise standalone. The standalone artifact message is written only when instructions is exactly false; nil does not qualify.

The two settings are independent — any combination is valid. A standalone placement with an inline render mode puts the content in its own message; a standalone render mode with an inline placement gives a chip embedded in the agent's reply.

Placement must not be mapped onto type. Returning meta.display_type as type for every kind was tried and reverted: it collapses the two settings into one, so a standalone placement can no longer carry inline content — the combination the reference tools produce by default. An author who wants a chip asks for the render mode directly (type = "standalone") rather than getting it as a side effect of where the artifact is delivered.

Content modes

Exactly one applies. title is always required.

Mode Fields Stored content Default content_type
Text content, optional content_type the string verbatim text/markdown
Component tag content = a wippy-component-tag-1.0 package JSON application/json
Component / page package content = a wippy-component-1.0 package JSON application/json
Page reference page_id, optional params params as JSON text/html

A page reference also requires type: "view_ref". Its content endpoint renders the page server-side rather than returning stored bytes.

Control payload

return {
  success = true,
  _control = {
    artifacts = {
      {
        title        = "Q3 summary",   -- required
        content      = "# Q3 …",       -- one content mode
        content_type = "text/markdown",
        type         = "standalone",   -- render mode; omitted ⇒ "inline"
        display_type = "standalone",   -- placement
        instructions = false,
        preview      = "",             -- shown before the artifact loads
        description  = nil,
        icon         = nil,
        status       = nil,            -- omitted ⇒ "idle"
      },
    },
  },
}

_control.artifacts is a list; one tool call may produce several artifacts. A failing tool returns no _control.

HTTP API

GET /artifact/{id} returns metadata for one artifact.

Field Source
uuid artifact_id
type the kind column; for view_ref, meta.display_type
kind the kind column
display_type meta.display_type
title, created_at, updated_at columns
content_type, description, icon, status from meta
page_id, is_view_reference, params view_ref only
content_version constant 1; see limitations

GET /artifact/{id}/content returns raw bytes with Content-Type from meta.content_type, or text/plain when absent. A view_ref is rendered server-side.

GET /artifacts?session_id=&limit=&cursor= returns an actor-scoped catalog, metadata only. Pagination is keyset over (created_at DESC, artifact_id DESC). Cursors are opaque (v1:<uuid>) and resolved within the caller's own scope, so a cursor naming an inaccessible row is rejected. Rows carry kind and display_type; they do not carry type, so that one field name does not mean different things on two endpoints.

Realtime

Event Topic Payload
standalone artifact message stored session:<id>:message:<message_id> { type: "artifact", message_id, artifact_id }
any artifact created session:<id> { type: "update", artifact_added, session_id }

Only session:-prefixed topics are relayed to clients.

Limitations

  • kind is stored verbatim from type with no enum check.
  • Updating an artifact replaces meta wholesale. The update path supplies only content_type, description, icon and status, so display_type, page_id and preview do not survive an update.
  • Supplying both title and content matches the create path first, so an update shaped that way produces a second artifact with a new id.
  • content_version is constant, so a client caching on it will not refetch updated content. Use updated_at.
  • A delegated tool call produces no artifact; the control payload is ignored.
  • SQLite does not cascade artifact deletion with its session. Orphaned rows remain listable, and fetching one returns HTTP 500.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages