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/api.ts (1 of 26 files). Show all

Unified · Split

packages/core/api/src/tools/api.ts+87−0
@@ -0,0 +1,87 @@
1+import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema } from "@effect/platform";
2+import { Schema } from "effect";
3+import {
4+ ScopeId,
5+ ToolId,
6+ ToolNotFoundError,
7+ ToolInvocationError,
8+ PolicyDeniedError,
9+ ElicitationDeclinedError,
10+} from "@executor/sdk";
11+
12+// ---------------------------------------------------------------------------
13+// Params
14+// ---------------------------------------------------------------------------
15+
16+const scopeIdParam = HttpApiSchema.param("scopeId", ScopeId);
17+const toolIdParam = HttpApiSchema.param("toolId", ToolId);
18+
19+// ---------------------------------------------------------------------------
20+// Response schemas
21+// ---------------------------------------------------------------------------
22+
23+const 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+
31+const ToolSchemaResponse = Schema.Struct({
32+ id: ToolId,
33+ inputSchema: Schema.optional(Schema.Unknown),
34+ outputSchema: Schema.optional(Schema.Unknown),
35+});
36+
37+const ToolInvokePayload = Schema.Struct({
38+ args: Schema.Unknown,
39+});
40+
41+const 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+
51+const ToolNotFound = ToolNotFoundError.annotations(
52+ HttpApiSchema.annotations({ status: 404 }),
53+);
54+const ToolInvocation = ToolInvocationError.annotations(
55+ HttpApiSchema.annotations({ status: 500 }),
56+);
57+const PolicyDenied = PolicyDeniedError.annotations(
58+ HttpApiSchema.annotations({ status: 403 }),
59+);
60+const ElicitationDeclined = ElicitationDeclinedError.annotations(
61+ HttpApiSchema.annotations({ status: 422 }),
62+);
63+
64+// ---------------------------------------------------------------------------
65+// Group
66+// ---------------------------------------------------------------------------
67+
68+export 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