History

feat: API contract, server handler, and frontend with effect-atom

- packages/core/api: HttpApi contract with ToolsApi + SecretsApi groups SDK tagged errors pass through directly with status annotations (ToolNotFoundError→404, PolicyDeniedError→403, etc.) - apps/server: API handler implementation via HttpApiBuilder Exports createApiHandler() for reuse (no baked-in server runtime) Handlers are pure pass-through — no manual error catching - apps/web: Vite + React frontend served on same port as API Vite plugin forwards /v1/*, /docs, /openapi.json to Effect handler effect-atom integration: AtomHttpApi.Tag typed client, query/mutation atoms RegistryProvider + useAtomValue with Result pattern matching - Catalog pins @effect/platform, platform-bun, platform-node, cluster - All 9 packages typecheck clean

Rhys Sullivan committed 7 months ago

Commit 8babea81 parent 00219a926 files · +1022 −32Browse files

Showing the changes to packages/core/api/src/tools (1 of 26 files). Show all

Unified · Split

packages/core/api/src/tools/api.ts+87−0
@@ -0,0 +1,87 @@
1import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema } from "@effect/platform";
2import { Schema } from "effect";
3import {
4 ScopeId,
5 ToolId,
6 ToolNotFoundError,
7 ToolInvocationError,
8 PolicyDeniedError,
9 ElicitationDeclinedError,
10} from "@executor/sdk";
11
12// ---------------------------------------------------------------------------
13// Params
14// ---------------------------------------------------------------------------
15
16const scopeIdParam = HttpApiSchema.param("scopeId", ScopeId);
17const toolIdParam = HttpApiSchema.param("toolId", ToolId);
18
19// ---------------------------------------------------------------------------
20// Response schemas
21// ---------------------------------------------------------------------------
22
23const ToolMetadataResponse = Schema.Struct({
24 id: ToolId,
25 name: Schema.String,
26 description: Schema.optional(Schema.String),
27 tags: Schema.Array(Schema.String),
28 mayElicit: Schema.optional(Schema.Boolean),
29});
30
31const ToolSchemaResponse = Schema.Struct({
32 id: ToolId,
33 inputSchema: Schema.optional(Schema.Unknown),
34 outputSchema: Schema.optional(Schema.Unknown),
35});
36
37const ToolInvokePayload = Schema.Struct({
38 args: Schema.Unknown,
39});
40
41const ToolInvokeResponse = Schema.Struct({
42 data: Schema.Unknown,
43 error: Schema.NullOr(Schema.Unknown),
44 status: Schema.optional(Schema.Number),
45});
46
47// ---------------------------------------------------------------------------
48// Error schemas with HTTP status annotations
49// ---------------------------------------------------------------------------
50
51const ToolNotFound = ToolNotFoundError.annotations(
52 HttpApiSchema.annotations({ status: 404 }),
53);
54const ToolInvocation = ToolInvocationError.annotations(
55 HttpApiSchema.annotations({ status: 500 }),
56);
57const PolicyDenied = PolicyDeniedError.annotations(
58 HttpApiSchema.annotations({ status: 403 }),
59);
60const ElicitationDeclined = ElicitationDeclinedError.annotations(
61 HttpApiSchema.annotations({ status: 422 }),
62);
63
64// ---------------------------------------------------------------------------
65// Group
66// ---------------------------------------------------------------------------
67
68export class ToolsApi extends HttpApiGroup.make("tools")
69 .add(
70 HttpApiEndpoint.get("list")`/scopes/${scopeIdParam}/tools`
71 .addSuccess(Schema.Array(ToolMetadataResponse)),
72 )
73 .add(
74 HttpApiEndpoint.get("schema")`/scopes/${scopeIdParam}/tools/${toolIdParam}/schema`
75 .addSuccess(ToolSchemaResponse)
76 .addError(ToolNotFound),
77 )
78 .add(
79 HttpApiEndpoint.post("invoke")`/scopes/${scopeIdParam}/tools/${toolIdParam}/invoke`
80 .setPayload(ToolInvokePayload)
81 .addSuccess(ToolInvokeResponse)
82 .addError(ToolNotFound)
83 .addError(ToolInvocation)
84 .addError(PolicyDenied)
85 .addError(ElicitationDeclined),
86 )
87 .prefix("/v1") {}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t