@gjermundgaraba/effect-actions 0.18.2 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -47
- package/dist/Action.d.mts +96 -47
- package/dist/Action.mjs +11 -14
- package/dist/ActionCli.d.mts +81 -42
- package/dist/ActionCli.mjs +52 -33
- package/dist/ActionHttp.d.mts +84 -43
- package/dist/ActionHttp.mjs +2 -2
- package/dist/ActionMcp.d.mts +54 -27
- package/dist/ActionMcp.mjs +5 -5
- package/dist/ActionRpc.d.mts +48 -35
- package/dist/ActionRpc.mjs +1 -1
- package/dist/ActionToolkit.d.mts +32 -13
- package/dist/ActionToolkit.mjs +10 -7
- package/dist/Authentication.d.mts +92 -40
- package/dist/Authentication.mjs +37 -35
- package/dist/Testing.d.mts +22 -24
- package/dist/authentication/provider.d.mts +1 -4
- package/dist/authentication/provider.mjs +1 -1
- package/dist/authentication/refusal.mjs +2 -1
- package/dist/cli/commands.d.mts +34 -11
- package/dist/cli/commands.mjs +47 -22
- package/dist/contract/caller.mjs +1 -1
- package/dist/contract/declared.mjs +27 -14
- package/dist/contract/errors.d.mts +42 -17
- package/dist/contract/errors.mjs +42 -17
- package/dist/contract/hints.mjs +3 -2
- package/dist/contract/implementation.d.mts +5 -8
- package/dist/contract/implementation.mjs +29 -17
- package/dist/contract/media.d.mts +6 -2
- package/dist/contract/media.mjs +6 -2
- package/dist/contract/names.mjs +14 -12
- package/dist/contract/status.mjs +3 -10
- package/dist/http/client.d.mts +15 -4
- package/dist/http/client.mjs +1 -1
- package/dist/mcp/client.d.mts +21 -8
- package/dist/mcp/client.mjs +6 -8
- package/docs/Action-failures.md +6 -15
- package/docs/Action.md +159 -191
- package/docs/ActionCli-failures.md +12 -92
- package/docs/ActionCli.md +102 -156
- package/docs/ActionHttp-failures.md +14 -76
- package/docs/ActionHttp.md +150 -176
- package/docs/ActionMcp-failures.md +2 -22
- package/docs/ActionMcp.md +79 -170
- package/docs/ActionRpc-failures.md +3 -12
- package/docs/ActionRpc.md +183 -120
- package/docs/ActionToolkit-failures.md +3 -10
- package/docs/ActionToolkit.md +112 -109
- package/docs/Authentication-advanced.md +167 -108
- package/docs/Authentication-failures.md +11 -91
- package/docs/Authentication.md +114 -135
- package/docs/README.md +45 -30
- package/docs/Testing-failures.md +2 -6
- package/docs/Testing.md +126 -159
- package/docs/setup-failures.md +8 -32
- package/docs/setup.md +42 -37
- package/examples/README.md +6 -10
- package/examples/assistant/README.md +20 -38
- package/examples/assistant/src/agent.ts +2 -3
- package/examples/assistant/src/cli.ts +4 -9
- package/examples/assistant/src/commands.ts +6 -4
- package/examples/assistant/src/identity/authorize.ts +3 -3
- package/examples/assistant/src/tasks/Tasks.ts +1 -2
- package/examples/assistant/src/tasks/handlers.ts +3 -3
- package/examples/assistant/src/toolkit.ts +6 -8
- package/examples/assistant/test/commands.test.ts +16 -11
- package/examples/assistant/test/tasks/tasks.test.ts +0 -2
- package/examples/assistant/test/toolkit.test.ts +0 -1
- package/examples/kitchen-sink/README.md +30 -52
- package/examples/kitchen-sink/src/Actions.ts +2 -3
- package/examples/kitchen-sink/src/Api.ts +3 -4
- package/examples/kitchen-sink/src/admin/Admin.ts +1 -1
- package/examples/kitchen-sink/src/admin/authenticate.ts +3 -3
- package/examples/kitchen-sink/src/admin/authorize.ts +1 -2
- package/examples/kitchen-sink/src/agent.ts +1 -1
- package/examples/kitchen-sink/src/assistant/handlers.ts +1 -6
- package/examples/kitchen-sink/src/attachments/Attachments.ts +4 -8
- package/examples/kitchen-sink/src/attachments/download.ts +5 -8
- package/examples/kitchen-sink/src/attachments/handlers.ts +2 -3
- package/examples/kitchen-sink/src/browser.ts +3 -4
- package/examples/kitchen-sink/src/cli.ts +6 -7
- package/examples/kitchen-sink/src/config.ts +2 -0
- package/examples/kitchen-sink/src/identity/Identity.ts +7 -7
- package/examples/kitchen-sink/src/identity/authenticate.ts +3 -5
- package/examples/kitchen-sink/src/identity/authorize.ts +4 -3
- package/examples/kitchen-sink/src/identity/quota.ts +1 -1
- package/examples/kitchen-sink/src/issues/Issues.ts +2 -2
- package/examples/kitchen-sink/src/issues/assistant.ts +3 -3
- package/examples/kitchen-sink/src/issues/guide.ts +2 -3
- package/examples/kitchen-sink/src/ops.ts +3 -6
- package/examples/kitchen-sink/src/request-policy.ts +3 -3
- package/examples/kitchen-sink/src/routes.ts +4 -6
- package/examples/kitchen-sink/src/seed.ts +0 -1
- package/examples/kitchen-sink/src/server.ts +11 -12
- package/examples/kitchen-sink/src/stdio.ts +3 -2
- package/examples/kitchen-sink/src/workspaces/tenant.ts +3 -1
- package/examples/kitchen-sink/test/admin/admin.test.ts +0 -1
- package/examples/kitchen-sink/test/assistant/assistant.test.ts +1 -1
- package/examples/kitchen-sink/test/attachments/attachments.test.ts +1 -2
- package/examples/kitchen-sink/test/identity/identity.test.ts +0 -1
- package/examples/kitchen-sink/test/issues/issues.test.ts +0 -2
- package/examples/kitchen-sink/test/request-policy.test.ts +1 -1
- package/examples/kitchen-sink/test/routes.test.ts +3 -3
- package/examples/live-rpc/README.md +8 -49
- package/examples/live-rpc/src/browser.ts +8 -41
- package/examples/live-rpc/src/chat/Chat.ts +9 -3
- package/examples/live-rpc/src/chat/room.ts +1 -1
- package/examples/live-rpc/src/client.ts +2 -3
- package/examples/live-rpc/src/page.ts +34 -0
- package/examples/live-rpc/src/routes.ts +6 -7
- package/examples/live-rpc/src/server.ts +6 -4
- package/examples/live-rpc/test/browser.test.ts +6 -5
- package/examples/live-rpc/test/routes.test.ts +16 -15
- package/examples/live-rpc/test/server.test.ts +1 -1
- package/examples/mcp-tools/README.md +22 -45
- package/examples/mcp-tools/src/printers/Printers.ts +3 -7
- package/examples/mcp-tools/src/routes.ts +0 -7
- package/examples/mcp-tools/src/server.ts +1 -1
- package/examples/mcp-tools/test/printers/printers.test.ts +2 -3
- package/examples/mcp-tools/test/routes.test.ts +2 -3
- package/examples/notes-service/README.md +9 -43
- package/examples/notes-service/src/cli.ts +0 -3
- package/examples/notes-service/src/commands.ts +7 -17
- package/examples/notes-service/src/identity/authorize.ts +2 -5
- package/examples/notes-service/src/identity/verifier.ts +3 -4
- package/examples/notes-service/src/notes/Notes.ts +2 -6
- package/examples/notes-service/src/notes/store.ts +5 -1
- package/examples/notes-service/src/routes.ts +6 -8
- package/examples/notes-service/src/server.ts +4 -3
- package/examples/notes-service/src/stdio.ts +4 -3
- package/examples/notes-service/test/commands.test.ts +1 -1
- package/examples/notes-service/test/notes/as.ts +6 -0
- package/examples/notes-service/test/notes/idempotency.test.ts +1 -4
- package/examples/notes-service/test/notes/in-process.test.ts +50 -0
- package/examples/notes-service/test/notes/notes.test.ts +3 -42
- package/examples/notes-service/test/routes.test.ts +2 -2
- package/examples/quickstart/README.md +1 -1
- package/examples/quickstart/src/client.ts +1 -0
- package/examples/quickstart/src/server.ts +2 -4
- package/examples/quickstart/test/{greeting/greeting.test.ts → routes.test.ts} +3 -3
- package/package.json +1 -1
- package/docs/Action-in-process.md +0 -93
- package/docs/CONTEXT.md +0 -46
- package/docs/guarantees.md +0 -44
package/docs/guarantees.md
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
# Guarantees
|
|
2
|
-
|
|
3
|
-
What a caller sees on each surface for each outcome of a call, and what the library leaves to the application. Read the table when you write a client by hand, assert on a raw response in a test, or need to know how a failure on one surface looks on another. A typed client decodes all of it for you: [Testing.md](Testing.md#assert-on-errors).
|
|
4
|
-
|
|
5
|
-
## Wire behavior
|
|
6
|
-
|
|
7
|
-
One call, on each surface. An HTTP route is `POST <prefix>/<action>` with a JSON body, the prefix `/api` by default. "Its JSON" is the value as its schema's JSON codec encodes it, such as `{"_tag":"NoteNotFound","id":"9"}`. A built-in error's JSON is `{"_tag":"InvalidInput","message":"…","issues":[{"path":["name"],"message":"…"}]}`, `{"_tag":"Unauthenticated","message":"…"}` or `{"_tag":"Forbidden","message":"…"}`, a `Forbidden` with the `scopes` it names. The CLI column is a command under `Command.run`.
|
|
8
|
-
|
|
9
|
-
| Case | HTTP | MCP | RPC | Toolkit | CLI |
|
|
10
|
-
| ---------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
|
|
11
|
-
| Success | its JSON as the body; an empty **200** for an action without `success` | `isError: false`, `structuredContent` its JSON, and the same JSON as one text block; both `null` for an action without `success` | the call's success | a result with `isFailure: false`: `result` the value, `encodedResult` its JSON | its JSON on stdout, indented, or `render`'s text; nothing for an action without `success` |
|
|
12
|
-
| Input that does not decode | **400** `InvalidInput` | `isError: true`, text `Invalid parameters for tool '<name>': …` | the typed `InvalidInput` | a result with `isFailure: true`: `result` an `AiError` whose `reason` is a `ToolParameterValidationError` | `InvalidInput`'s JSON on stderr, exit 1; a missing flag or a rejected choice is Effect CLI's own parse error instead |
|
|
13
|
-
| Undeclared input field | refused, nested ones too: **400** `InvalidInput` naming its path | refused, as input that does not decode | refused: `InvalidInput` naming its path | **dropped**: the call runs without it | refused, in `--input` and in a flag's JSON value: `InvalidInput` |
|
|
14
|
-
| Declared error | its JSON with its `httpApiStatus`, **422** without one | `isError: true`, its JSON as one text block, no `structuredContent` | the call's typed failure | a result with `isFailure: true`: `result` the error, `encodedResult` its JSON | its JSON on stderr; the command fails with a `UserError` whose `cause` is the error; exit 1 by default |
|
|
15
|
-
| Protected action, credential missing or not verified | **401** `Unauthenticated` with the scheme's challenge, or what the verifier fails with, before the body is read; a public route reads no credential | the same HTTP answer in place of a JSON-RPC one, before the arguments are decoded; on an endpoint that also serves a public tool, that tool's call and `tools/list` need no credential, but one a request presents is still verified ([Protect tools](ActionMcp.md#protect-tools)) | the typed `Unauthenticated`, or what the verifier fails with, before the payload is decoded; never a status | no credential: the host provides the identity around the call ([Name the caller](ActionToolkit.md#name-the-caller)) | no credential: the host provides the identity to the command ([Name the caller](ActionCli.md#name-the-caller)) |
|
|
16
|
-
| `Unauthenticated` or `Forbidden` from the authorizer or a handler | its JSON with **401** or **403**, after the input is decoded; on a protected route under Bearer, a 401 and a `Forbidden` naming `scopes` also carry a challenge | `isError: true`, its JSON as text, in a **200** over HTTP; on an endpoint under Bearer, a protected tool's step-up refusal is the HTTP **401** or **403** instead, with its JSON and challenge, unless a handler's notification has started the response | the call's typed failure; never a status or a challenge | a result with `isFailure: true`, as a declared error | as a declared error |
|
|
17
|
-
| Defect, undeclared failure, or a success or error that does not encode | an empty **500** | `isError: true`, text `Tool execution failed due to an internal server error.` | that call's defect, an `Error` whose message is `Internal server error`; the connection's other calls go on | a defect or a rejected failure is the call's defect; the rest fail it with an `AiError`, `Failed to encode result for tool …` | an accepted error that does not encode is a `UserError` printed as its tag and message; the rest are the command's defect |
|
|
18
|
-
| Unknown path, method or name | a path no layer serves, or a method other than `POST` on a route: **404** | another HTTP method: an empty **405** with `Allow: POST, DELETE`, signed out the **401** of an endpoint with authentication; an unknown tool: a JSON-RPC error `-32602`, with **200** over HTTP | an rpc the layer does not serve ends its call with `Unknown request tag` | Effect's own | Effect CLI's own |
|
|
19
|
-
| Body that is not JSON, or not typed as JSON | not JSON: **400** `InvalidInput`; `Content-Type` missing or not JSON: **415**; both after authentication on a protected route | not JSON: a JSON-RPC error `-32700` with **200**; `Content-Type` missing or not JSON: an empty **415**; over stdio, a line that is not JSON goes unanswered | the protocol's own | — | a flag or `--input` that is not the JSON its field takes: `InvalidInput` |
|
|
20
|
-
|
|
21
|
-
- **Typed clients.** `ActionHttp.client`, `ActionRpc.client`, `ActionMcp.client` and `Action.client` fail with a declared or built-in error as its decoded value. Each drops undeclared fields as it encodes an input, since TypeScript lets a wider value through, and fails with `InvalidInput` for an input that does not encode, sending nothing. `Action.client` has no wire but passes input, success and failure through the same JSON codecs; an undeclared failure or a success that does not encode is its call's defect. Over MCP a verifier's declared error is the endpoint's HTTP answer: `ActionMcp.client` decodes it given the endpoint's `authentication`, and fails with an `McpCallError` without.
|
|
22
|
-
- **An action without input** takes `{}` and nothing else, on every surface. Over HTTP, send the body `{}` typed as JSON: no body is a **400**, and no `Content-Type` a **415**.
|
|
23
|
-
- **A media field**, `Action.Image`, is `{ "data": "<base64>", "mimeType": "image/png" }` inside the JSON on every surface but MCP, which lifts it out of `structuredContent` into a block of its own: [Return images and other media](ActionMcp.md#return-images-and-other-media).
|
|
24
|
-
- **A failure the action's errors reject**, undeclared or breaking a check, is its call's defect on every surface, beside the `SchemaError` saying why. A class error's checks are not rerun: one built with `disableChecks` is accepted, and fails to encode instead.
|
|
25
|
-
- **Internal failures are never sent.** Over HTTP, MCP and RPC, the cause of a defect goes to the log and to the call's `ErrorReporter`s: those the server runs with, as provided around `HttpRouter.serve` or `Testing.layer`, win over those provided to one surface's layer, which only fill in what a request lacks.
|
|
26
|
-
- **Messages for invalid input.** A message for input that does not decode names paths and what the schema expects, never a field's value. A path names every key it passes through, a record's keys and an undeclared key included, so never key a record by a secret such as an email or a token. A schema's own `message` annotation, or a filter's message, is sent as written, so never put the input in one.
|
|
27
|
-
- **Earlier MCP revisions.** The MCP column is 2026-07-28. A 2025-11-25 or 2025-06-18 client, over HTTP or stdio, gets `structuredContent` only for a success that is an object, and any other success as its text block alone, a string unquoted; a 2025-06-18 client gets invalid arguments as a JSON-RPC error instead of a result. Over HTTP such a client opens a session, which on an endpoint serving a protected tool only a signed-in caller does: it signs in for every request there, a public tool's call and `tools/list` included. A `requestScoped` endpoint serves only 2026-07-28, and only `POST`. Stdio authenticates nothing: the host provides the identity around `runStdio` ([Serve tools over stdio](ActionMcp.md#serve-tools-over-stdio)).
|
|
28
|
-
- **Request bodies have no size limit** unless the host sets one, on every route of the server, MCP endpoints included ([Serve the routes](ActionHttp.md#serve-the-routes)).
|
|
29
|
-
|
|
30
|
-
[kitchen-sink/test/identity/identity.test.ts](../examples/kitchen-sink/test/identity/identity.test.ts) asserts the 401 and the 403 as sent, and [assistant/test/toolkit.test.ts](../examples/assistant/test/toolkit.test.ts) a refusal as a Toolkit result.
|
|
31
|
-
|
|
32
|
-
## Scope
|
|
33
|
-
|
|
34
|
-
What the library does not do, where a reader might expect it to:
|
|
35
|
-
|
|
36
|
-
- **Verify credentials or issue them.** The application writes the verifier ([Verify credentials](Authentication.md#verify-credentials)), and login, consent and token issuance are its own. The library defines no scopes: a `Forbidden` names the scopes a call lacks, and the library answers with the OAuth challenge ([Publish OAuth discovery](Authentication.md#publish-oauth-discovery)). OAuth, its discovery, challenges and step-up, is Bearer's.
|
|
37
|
-
- **Decide who may do what.** It runs the `authorize` an implementation states and writes no rule of its own ([Authorize calls](Action.md#authorize-calls)).
|
|
38
|
-
- **Filter tool discovery by caller.** `tools/list` names every tool its endpoint serves, protected ones included, to anyone who may list them. Serve public tools on an endpoint of their own if signed-out callers must not see the protected ones.
|
|
39
|
-
- **Limit requests.** A rate limit is the handler's, failing with an error its action declares, or middleware's.
|
|
40
|
-
- **Allow browsers across origins.** CORS for JSON routes is the host's, with `HttpRouter.cors`; an MCP endpoint refuses a browser `Origin` it does not list ([Allow browser clients](ActionMcp.md#allow-browser-clients)).
|
|
41
|
-
- **Stream, upload or retry.** Actions are unary JSON calls: one input, one success or one declared error. Every HTTP route is a `POST`, a read-only action's included; RPC needs a protocol speaking JSON.
|
|
42
|
-
- **Expire MCP sessions, or serve MCP features other than tools.** A session a client of a 2025 revision opens over HTTP lasts until that client ends it or the process stops ([Serve tools over HTTP](ActionMcp.md#serve-tools-over-http)). Prompts and resources are Effect's native ones, given as `features` ([Add native prompts and resources](ActionMcp.md#add-native-prompts-and-resources)).
|
|
43
|
-
- **Mix identities.** An action names one identity service, and a remote surface one authentication descriptor.
|
|
44
|
-
- **Harden a deployment.** Real token validation, request limits and error reporting are the application's. The examples mark each shortcut they take `DEMO ONLY`: [examples](../examples/README.md).
|