// ---------------------------------------------------------------------------// Artifacts HTTP API — saved generative-UI components.//// An artifact is the JSX source a model produced plus the title/description an// agent matches against. Owner-scoped: every endpoint reads and writes only// what the bound owner scope may see, so no owner travels on the wire.// --------------------------------------------------------------------------- import { HttpApiEndpoint, HttpApiGroup } from "effect/unstable/httpapi";import { Schema } from "effect";import { ArtifactId, ArtifactNotFoundError, InternalError, Owner } from "@executor-js/sdk/shared"; // ---------------------------------------------------------------------------// Params// --------------------------------------------------------------------------- const ArtifactParams = { artifactId: ArtifactId }; // ---------------------------------------------------------------------------// Response / payload schemas// --------------------------------------------------------------------------- /** What a list returns — no `code`, so a long list stays cheap. */const ArtifactSummaryResponse = Schema.Struct({ id: ArtifactId, owner: Owner, title: Schema.String, description: Schema.NullOr(Schema.String), createdAt: Schema.Number, updatedAt: Schema.Number,}); const ArtifactResponse = Schema.Struct({ ...ArtifactSummaryResponse.fields, code: Schema.String,}); /** Omit `id` to create; pass one to overwrite that artifact in place. */const SaveArtifactPayload = Schema.Struct({ id: Schema.optional(ArtifactId), title: Schema.String, description: Schema.optional(Schema.NullOr(Schema.String)), code: Schema.String,}); const RenameArtifactPayload = Schema.Struct({ title: Schema.String,}); // ---------------------------------------------------------------------------// Error schemas with HTTP status annotations// --------------------------------------------------------------------------- const ArtifactNotFound = ArtifactNotFoundError.annotate({ httpApiStatus: 404 }); // ---------------------------------------------------------------------------// Group// --------------------------------------------------------------------------- export const ArtifactsApi = HttpApiGroup.make("artifacts") .add( HttpApiEndpoint.get("list", "/artifacts", { success: Schema.Array(ArtifactSummaryResponse), error: InternalError, }), ) .add( HttpApiEndpoint.get("get", "/artifacts/:artifactId", { params: ArtifactParams, success: ArtifactResponse, error: [InternalError, ArtifactNotFound], }), ) .add( HttpApiEndpoint.post("save", "/artifacts", { payload: SaveArtifactPayload, success: ArtifactResponse, error: [InternalError, ArtifactNotFound], }), ) .add( HttpApiEndpoint.patch("rename", "/artifacts/:artifactId", { params: ArtifactParams, payload: RenameArtifactPayload, success: ArtifactResponse, error: [InternalError, ArtifactNotFound], }), ) .add( HttpApiEndpoint.delete("remove", "/artifacts/:artifactId", { params: ArtifactParams, success: Schema.Struct({ removed: Schema.Boolean }), error: InternalError, }), );
// ---------------------------------------------------------------------------
// Artifacts HTTP API — saved generative-UI components.
//
// An artifact is the JSX source a model produced plus the title/description an
// agent matches against. Owner-scoped: every endpoint reads and writes only
// what the bound owner scope may see, so no owner travels on the wire.
// ---------------------------------------------------------------------------
import { HttpApiEndpoint, HttpApiGroup } from "effect/unstable/httpapi";
import { Schema } from "effect";
import { ArtifactId, ArtifactNotFoundError, InternalError, Owner } from "@executor-js/sdk/shared";
// ---------------------------------------------------------------------------
// Params
// ---------------------------------------------------------------------------
const ArtifactParams = { artifactId: ArtifactId };
// ---------------------------------------------------------------------------
// Response / payload schemas
// ---------------------------------------------------------------------------
/** What a list returns — no `code`, so a long list stays cheap. */
const ArtifactSummaryResponse = Schema.Struct({
id: ArtifactId,
owner: Owner,
title: Schema.String,
description: Schema.NullOr(Schema.String),
createdAt: Schema.Number,
updatedAt: Schema.Number,
});
const ArtifactResponse = Schema.Struct({
...ArtifactSummaryResponse.fields,
code: Schema.String,
});
/** Omit `id` to create; pass one to overwrite that artifact in place. */
const SaveArtifactPayload = Schema.Struct({
id: Schema.optional(ArtifactId),
title: Schema.String,
description: Schema.optional(Schema.NullOr(Schema.String)),
code: Schema.String,
});
const RenameArtifactPayload = Schema.Struct({
title: Schema.String,
});
// ---------------------------------------------------------------------------
// Error schemas with HTTP status annotations
// ---------------------------------------------------------------------------
const ArtifactNotFound = ArtifactNotFoundError.annotate({ httpApiStatus: 404 });
// ---------------------------------------------------------------------------
// Group
// ---------------------------------------------------------------------------
export const ArtifactsApi = HttpApiGroup.make("artifacts")
.add(
HttpApiEndpoint.get("list", "/artifacts", {
success: Schema.Array(ArtifactSummaryResponse),
error: InternalError,
}),
)
.add(
HttpApiEndpoint.get("get", "/artifacts/:artifactId", {
params: ArtifactParams,
success: ArtifactResponse,
error: [InternalError, ArtifactNotFound],
}),
)
.add(
HttpApiEndpoint.post("save", "/artifacts", {
payload: SaveArtifactPayload,
success: ArtifactResponse,
error: [InternalError, ArtifactNotFound],
}),
)
.add(
HttpApiEndpoint.patch("rename", "/artifacts/:artifactId", {
params: ArtifactParams,
payload: RenameArtifactPayload,
success: ArtifactResponse,
error: [InternalError, ArtifactNotFound],
}),
)
.add(
HttpApiEndpoint.delete("remove", "/artifacts/:artifactId", {
params: ArtifactParams,
success: Schema.Struct({ removed: Schema.Boolean }),
error: InternalError,
}),
);