Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 76 additions & 11 deletions packages/core/api/src/account/api.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { HttpApi, HttpApiEndpoint, HttpApiGroup } from "effect/unstable/httpapi";
import { HttpApi, HttpApiEndpoint, HttpApiGroup, OpenApi } from "effect/unstable/httpapi";
import { Schema } from "effect";

// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -170,68 +170,133 @@ export const AccountApi = HttpApiGroup.make("account")
HttpApiEndpoint.get("me", "/account/me", {
success: AccountMeResponse,
error: [AccountError, AccountUnauthorized],
}),
}).annotateMerge(
OpenApi.annotations({
identifier: "account.me",
summary: "Current Account",
description: "Returns the authenticated user and their current organization (if any).",
}),
),
)
.add(
HttpApiEndpoint.get("listApiKeys", "/account/api-keys", {
success: ApiKeysResponse,
error: [AccountError, AccountUnauthorized, AccountNoOrganization],
}),
}).annotateMerge(
OpenApi.annotations({
identifier: "account.listApiKeys",
summary: "List API Keys",
description: "Lists the API keys for the current organization, each with a masked value.",
}),
),
)
.add(
HttpApiEndpoint.post("createApiKey", "/account/api-keys", {
payload: CreateApiKeyBody,
success: CreatedApiKeyResponse,
error: [AccountError, AccountUnauthorized, AccountNoOrganization],
}),
}).annotateMerge(
OpenApi.annotations({
identifier: "account.createApiKey",
summary: "Create API Key",
description:
"Creates a named API key for the current organization and returns its one-time plaintext value.",
}),
),
)
.add(
HttpApiEndpoint.delete("revokeApiKey", "/account/api-keys/:apiKeyId", {
params: ApiKeyParams,
success: SuccessResponse,
error: [AccountError, AccountUnauthorized, AccountNoOrganization],
}),
}).annotateMerge(
OpenApi.annotations({
identifier: "account.revokeApiKey",
summary: "Revoke API Key",
description: "Revokes the API key identified by the given id for the current organization.",
}),
),
)
.add(
HttpApiEndpoint.get("listMembers", "/account/members", {
success: OrgMembersResponse,
error: [AccountError, AccountUnauthorized, AccountNoOrganization],
}),
}).annotateMerge(
OpenApi.annotations({
identifier: "account.listMembers",
summary: "List Members",
description:
"Lists the members of the current organization along with optional seat usage.",
}),
),
)
.add(
HttpApiEndpoint.get("listRoles", "/account/roles", {
success: OrgRolesResponse,
error: [AccountError, AccountUnauthorized, AccountNoOrganization],
}),
}).annotateMerge(
OpenApi.annotations({
identifier: "account.listRoles",
summary: "List Roles",
description:
"Lists the roles available for assigning to members of the current organization.",
}),
),
)
.add(
HttpApiEndpoint.post("inviteMember", "/account/members/invite", {
payload: InviteMemberBody,
success: InviteMemberResponse,
error: [AccountError, AccountUnauthorized, AccountForbidden, AccountNoOrganization],
}),
}).annotateMerge(
OpenApi.annotations({
identifier: "account.inviteMember",
summary: "Invite Member",
description:
"Invites a user by email to the current organization, optionally with a specific role.",
}),
),
)
.add(
HttpApiEndpoint.delete("removeMember", "/account/members/:membershipId", {
params: MembershipParams,
success: SuccessResponse,
error: [AccountError, AccountUnauthorized, AccountForbidden, AccountNoOrganization],
}),
}).annotateMerge(
OpenApi.annotations({
identifier: "account.removeMember",
summary: "Remove Member",
description:
"Removes the membership identified by the given id from the current organization.",
}),
),
)
.add(
HttpApiEndpoint.patch("updateMemberRole", "/account/members/:membershipId/role", {
params: MembershipParams,
payload: UpdateMemberRoleBody,
success: SuccessResponse,
error: [AccountError, AccountUnauthorized, AccountForbidden, AccountNoOrganization],
}),
}).annotateMerge(
OpenApi.annotations({
identifier: "account.updateMemberRole",
summary: "Update Member Role",
description: "Updates the role of the membership identified by the given id.",
}),
),
)
.add(
HttpApiEndpoint.patch("updateOrgName", "/account/name", {
payload: UpdateOrgNameBody,
success: UpdateOrgNameResponse,
error: [AccountError, AccountUnauthorized, AccountForbidden, AccountNoOrganization],
}),
}).annotateMerge(
OpenApi.annotations({
identifier: "account.updateOrgName",
summary: "Update Org Name",
description: "Updates the display name of the current organization.",
}),
),
);

/**
Expand Down
44 changes: 38 additions & 6 deletions packages/core/api/src/connections/api.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { HttpApiEndpoint, HttpApiGroup } from "effect/unstable/httpapi";
import { HttpApiEndpoint, HttpApiGroup, OpenApi } from "effect/unstable/httpapi";
import { Schema } from "effect";

import {
Expand Down Expand Up @@ -64,34 +64,66 @@ export const ConnectionsApi = HttpApiGroup.make("connections")
params: ScopeParams,
success: Schema.Array(ConnectionRefResponse),
error: InternalError,
}),
}).annotateMerge(
OpenApi.annotations({
identifier: "connections.list",
summary: "List Connections",
description: "Lists all provider connections belonging to the given scope.",
}),
),
)
.add(
HttpApiEndpoint.delete("remove", "/scopes/:scopeId/connections/:connectionId", {
params: ConnectionParams,
success: Schema.Struct({ removed: Schema.Boolean }),
error: [InternalError, ConnectionInUse],
}),
}).annotateMerge(
OpenApi.annotations({
identifier: "connections.remove",
summary: "Remove Connection",
description:
"Deletes the specified connection from the scope, failing if it is still in use.",
}),
),
)
.add(
HttpApiEndpoint.get("usages", "/scopes/:scopeId/connections/:connectionId/usages", {
params: ConnectionParams,
success: Schema.Array(Usage),
error: InternalError,
}),
}).annotateMerge(
OpenApi.annotations({
identifier: "connections.usages",
summary: "List Connection Usages",
description: "Returns the usage records associated with the specified connection.",
}),
),
)
.add(
HttpApiEndpoint.get("identity", "/scopes/:scopeId/connections/:connectionId/identity", {
params: ConnectionParams,
success: ConnectionIdentityResponse,
error: InternalError,
}),
}).annotateMerge(
OpenApi.annotations({
identifier: "connections.identity",
summary: "Get Connection Identity",
description:
"Resolves the identity details and availability status for the specified connection.",
}),
),
)
.add(
HttpApiEndpoint.patch("updateIdentity", "/scopes/:scopeId/connections/:connectionId/identity", {
params: ConnectionParams,
payload: UpdateConnectionIdentityPayload,
success: ConnectionRefResponse,
error: [InternalError, ConnectionNotFound],
}),
}).annotateMerge(
OpenApi.annotations({
identifier: "connections.updateIdentity",
summary: "Update Connection Identity",
description: "Sets or clears the manual identity override for the specified connection.",
}),
),
);
29 changes: 25 additions & 4 deletions packages/core/api/src/executions/api.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { HttpApiEndpoint, HttpApiGroup } from "effect/unstable/httpapi";
import { HttpApiEndpoint, HttpApiGroup, OpenApi } from "effect/unstable/httpapi";
import { Schema } from "effect";

import { InternalError } from "@executor-js/sdk/shared";
Expand Down Expand Up @@ -58,20 +58,41 @@ export const ExecutionsApi = HttpApiGroup.make("executions")
params: ExecutionParams,
success: PausedExecutionInfo,
error: [InternalError, ExecutionNotFoundError],
}),
}).annotateMerge(
OpenApi.annotations({
identifier: "executions.getPaused",
summary: "Get Paused Execution",
description:
"Retrieve the text and structured output of a paused execution by its execution ID.",
}),
),
)
.add(
HttpApiEndpoint.post("execute", "/executions", {
payload: ExecuteRequest,
success: ExecuteResponse,
error: InternalError,
}),
}).annotateMerge(
OpenApi.annotations({
identifier: "executions.execute",
summary: "Execute Code",
description:
"Run the provided code and return either a completed result or a paused execution awaiting input.",
}),
),
)
.add(
HttpApiEndpoint.post("resume", "/executions/:executionId/resume", {
params: ExecutionParams,
payload: ResumeRequest,
success: ResumeResponse,
error: [InternalError, ExecutionNotFoundError],
}),
}).annotateMerge(
OpenApi.annotations({
identifier: "executions.resume",
summary: "Resume Execution",
description:
"Resume a paused execution by accepting, declining, or cancelling it, optionally providing content.",
}),
),
);
47 changes: 41 additions & 6 deletions packages/core/api/src/oauth/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
// `/scopes/:scopeId/{mcp,openapi,graphql}/oauth/*`.
// ---------------------------------------------------------------------------

import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema } from "effect/unstable/httpapi";
import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema, OpenApi } from "effect/unstable/httpapi";
import { Schema } from "effect";

import {
Expand Down Expand Up @@ -137,36 +137,71 @@ export const OAuthApi = HttpApiGroup.make("oauth")
payload: ProbePayload,
success: ProbeResponse,
error: [InternalError, OAuthProbeError],
}),
}).annotateMerge(
OpenApi.annotations({
identifier: "oauth.probe",
summary: "Probe OAuth Endpoint",
description:
"Probes an endpoint to discover its OAuth resource and authorization server metadata and whether it supports dynamic client registration.",
}),
),
)
.add(
HttpApiEndpoint.post("start", "/scopes/:scopeId/oauth/start", {
params: ScopeParams,
payload: StartPayload,
success: StartResponse,
error: [InternalError, OAuthStartError],
}),
}).annotateMerge(
OpenApi.annotations({
identifier: "oauth.start",
summary: "Start OAuth Flow",
description:
"Starts an OAuth flow by persisting a session and returning an authorization URL, or minting the connection inline for client-credentials strategies.",
}),
),
)
.add(
HttpApiEndpoint.post("complete", "/scopes/:scopeId/oauth/complete", {
params: ScopeParams,
payload: CompletePayload,
success: CompleteResponse,
error: [InternalError, OAuthCompleteError, OAuthSessionNotFoundError],
}),
}).annotateMerge(
OpenApi.annotations({
identifier: "oauth.complete",
summary: "Complete OAuth Flow",
description:
"Completes an OAuth flow by exchanging the authorization code for tokens, minting the connection, and dropping the session.",
}),
),
)
.add(
HttpApiEndpoint.post("cancel", "/scopes/:scopeId/oauth/cancel", {
params: ScopeParams,
payload: CancelPayload,
success: CancelResponse,
error: [InternalError, OAuthSessionNotFoundError],
}),
}).annotateMerge(
OpenApi.annotations({
identifier: "oauth.cancel",
summary: "Cancel OAuth Flow",
description:
"Cancels an in-flight OAuth session without exchanging the authorization code.",
}),
),
)
.add(
HttpApiEndpoint.get("callback", "/oauth/callback", {
query: CallbackUrlParams,
success: HtmlResponse,
error: [InternalError, OAuthCompleteError, OAuthSessionNotFoundError],
}),
}).annotateMerge(
OpenApi.annotations({
identifier: "oauth.callback",
summary: "OAuth Redirect Callback",
description:
"Handles the OAuth redirect with state and code query params and renders popup HTML that posts the completion result back to the opener.",
}),
),
);
Loading
Loading