effect 4.1.0 → 4.1.2
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 +30 -0
- package/THIRD_PARTY_NOTICES.md +62 -0
- package/ai-docs/package.json +2 -2
- package/dist/BigDecimal.d.ts +139 -7
- package/dist/BigDecimal.d.ts.map +1 -1
- package/dist/BigDecimal.js +83 -14
- package/dist/BigDecimal.js.map +1 -1
- package/dist/ByteSize.d.ts.map +1 -1
- package/dist/ByteSize.js +27 -14
- package/dist/ByteSize.js.map +1 -1
- package/dist/Equal.d.ts +2 -2
- package/dist/Equal.d.ts.map +1 -1
- package/dist/Equal.js +3 -3
- package/dist/Equal.js.map +1 -1
- package/dist/Hash.d.ts +3 -2
- package/dist/Hash.d.ts.map +1 -1
- package/dist/Hash.js +5 -4
- package/dist/Hash.js.map +1 -1
- package/dist/Iterable.d.ts.map +1 -1
- package/dist/Iterable.js +38 -32
- package/dist/Iterable.js.map +1 -1
- package/dist/JsonSchema.d.ts.map +1 -1
- package/dist/JsonSchema.js +27 -6
- package/dist/JsonSchema.js.map +1 -1
- package/dist/MutableRef.d.ts.map +1 -1
- package/dist/MutableRef.js +0 -7
- package/dist/MutableRef.js.map +1 -1
- package/dist/Path.d.ts.map +1 -1
- package/dist/Path.js +5 -1
- package/dist/Path.js.map +1 -1
- package/dist/Pool.d.ts.map +1 -1
- package/dist/Pool.js +2 -1
- package/dist/Pool.js.map +1 -1
- package/dist/Ref.d.ts.map +1 -1
- package/dist/Ref.js +0 -8
- package/dist/Ref.js.map +1 -1
- package/dist/Schedule.d.ts.map +1 -1
- package/dist/Schedule.js +8 -3
- package/dist/Schedule.js.map +1 -1
- package/dist/Schema.d.ts +2 -1
- package/dist/Schema.d.ts.map +1 -1
- package/dist/Schema.js +2 -1
- package/dist/Schema.js.map +1 -1
- package/dist/SchemaRepresentation.d.ts +4 -2
- package/dist/SchemaRepresentation.d.ts.map +1 -1
- package/dist/SchemaRepresentation.js +4 -2
- package/dist/SchemaRepresentation.js.map +1 -1
- package/dist/SchemaTransformation.d.ts +2 -2
- package/dist/SchemaTransformation.js +2 -2
- package/dist/Stream.d.ts.map +1 -1
- package/dist/Stream.js +6 -5
- package/dist/Stream.js.map +1 -1
- package/dist/ai/McpClient.d.ts +171 -19
- package/dist/ai/McpClient.d.ts.map +1 -1
- package/dist/ai/McpClient.js +277 -66
- package/dist/ai/McpClient.js.map +1 -1
- package/dist/ai/McpSchema.d.ts +108 -0
- package/dist/ai/McpSchema.d.ts.map +1 -1
- package/dist/ai/McpSchema.js +99 -0
- package/dist/ai/McpSchema.js.map +1 -1
- package/dist/ai/McpServer.d.ts +120 -6
- package/dist/ai/McpServer.d.ts.map +1 -1
- package/dist/ai/McpServer.js +258 -49
- package/dist/ai/McpServer.js.map +1 -1
- package/dist/ai/Prompt.d.ts.map +1 -1
- package/dist/ai/Prompt.js +20 -11
- package/dist/ai/Prompt.js.map +1 -1
- package/dist/ai/Tool.d.ts.map +1 -1
- package/dist/ai/Tool.js +5 -7
- package/dist/ai/Tool.js.map +1 -1
- package/dist/ai/internal/mcpCore.js +72 -3
- package/dist/ai/internal/mcpCore.js.map +1 -1
- package/dist/ai/internal/mcpProtocol/v2024_11_05.js +3 -1
- package/dist/ai/internal/mcpProtocol/v2024_11_05.js.map +1 -1
- package/dist/ai/internal/mcpProtocol/v2025_03_26.js +3 -1
- package/dist/ai/internal/mcpProtocol/v2025_03_26.js.map +1 -1
- package/dist/ai/internal/mcpProtocol/v2025_06_18.js +3 -1
- package/dist/ai/internal/mcpProtocol/v2025_06_18.js.map +1 -1
- package/dist/ai/internal/mcpProtocol/v2025_11_25.js +3 -1
- package/dist/ai/internal/mcpProtocol/v2025_11_25.js.map +1 -1
- package/dist/ai/internal/mcpProtocol/v2026_07_28.js +44 -8
- package/dist/ai/internal/mcpProtocol/v2026_07_28.js.map +1 -1
- package/dist/ai/internal/mcpProtocol.js +12 -0
- package/dist/ai/internal/mcpProtocol.js.map +1 -1
- package/dist/ai/internal/mcpRuntime.js +3 -3
- package/dist/ai/internal/mcpRuntime.js.map +1 -1
- package/dist/ai/internal/mcpSkills.d.ts +2 -0
- package/dist/ai/internal/mcpSkills.d.ts.map +1 -0
- package/dist/ai/internal/mcpSkills.js +428 -0
- package/dist/ai/internal/mcpSkills.js.map +1 -0
- package/dist/ai/internal/structured-output.js +11 -2
- package/dist/ai/internal/structured-output.js.map +1 -1
- package/dist/cluster/ClusterWorkflowEngine.d.ts.map +1 -1
- package/dist/cluster/ClusterWorkflowEngine.js +30 -11
- package/dist/cluster/ClusterWorkflowEngine.js.map +1 -1
- package/dist/cluster/Entity.d.ts +26 -0
- package/dist/cluster/Entity.d.ts.map +1 -1
- package/dist/cluster/Entity.js.map +1 -1
- package/dist/cluster/MessageStorage.d.ts +6 -6
- package/dist/cluster/MessageStorage.d.ts.map +1 -1
- package/dist/cluster/MessageStorage.js +1 -3
- package/dist/cluster/MessageStorage.js.map +1 -1
- package/dist/cluster/Reply.d.ts +1 -1
- package/dist/cluster/Reply.d.ts.map +1 -1
- package/dist/cluster/Reply.js.map +1 -1
- package/dist/cluster/Runners.d.ts.map +1 -1
- package/dist/cluster/Runners.js +13 -2
- package/dist/cluster/Runners.js.map +1 -1
- package/dist/cluster/Sharding.d.ts +13 -0
- package/dist/cluster/Sharding.d.ts.map +1 -1
- package/dist/cluster/Sharding.js +4 -1
- package/dist/cluster/Sharding.js.map +1 -1
- package/dist/cluster/internal/clusterAbandon.d.ts.map +1 -1
- package/dist/cluster/internal/clusterAbandon.js +6 -4
- package/dist/cluster/internal/clusterAbandon.js.map +1 -1
- package/dist/cluster/internal/entityManager.js +63 -11
- package/dist/cluster/internal/entityManager.js.map +1 -1
- package/dist/cluster/internal/transactionNotifications.d.ts +5 -0
- package/dist/cluster/internal/transactionNotifications.d.ts.map +1 -0
- package/dist/cluster/internal/transactionNotifications.js +5 -0
- package/dist/cluster/internal/transactionNotifications.js.map +1 -0
- package/dist/crypto/Aead.d.ts +2 -1
- package/dist/crypto/Aead.d.ts.map +1 -1
- package/dist/crypto/Aead.js +2 -2
- package/dist/crypto/Aead.js.map +1 -1
- package/dist/crypto/Cipher.d.ts +2 -1
- package/dist/crypto/Cipher.d.ts.map +1 -1
- package/dist/crypto/Cipher.js +2 -2
- package/dist/crypto/Cipher.js.map +1 -1
- package/dist/crypto/KeyAgreement.d.ts +3 -2
- package/dist/crypto/KeyAgreement.d.ts.map +1 -1
- package/dist/crypto/KeyAgreement.js +2 -2
- package/dist/crypto/KeyAgreement.js.map +1 -1
- package/dist/crypto/KeyFormat.d.ts +33 -1
- package/dist/crypto/KeyFormat.d.ts.map +1 -1
- package/dist/crypto/KeyFormat.js.map +1 -1
- package/dist/crypto/KeyWrap.d.ts +4 -3
- package/dist/crypto/KeyWrap.d.ts.map +1 -1
- package/dist/crypto/KeyWrap.js +2 -2
- package/dist/crypto/KeyWrap.js.map +1 -1
- package/dist/crypto/Mac.d.ts +2 -1
- package/dist/crypto/Mac.d.ts.map +1 -1
- package/dist/crypto/Mac.js +2 -2
- package/dist/crypto/Mac.js.map +1 -1
- package/dist/crypto/Signature.d.ts +3 -2
- package/dist/crypto/Signature.d.ts.map +1 -1
- package/dist/crypto/Signature.js +2 -2
- package/dist/crypto/Signature.js.map +1 -1
- package/dist/crypto/WebCrypto.d.ts +19 -0
- package/dist/crypto/WebCrypto.d.ts.map +1 -1
- package/dist/crypto/WebCrypto.js.map +1 -1
- package/dist/crypto/internal/asymmetric.js.map +1 -1
- package/dist/crypto/internal/key.js +3 -2
- package/dist/crypto/internal/key.js.map +1 -1
- package/dist/encoding/Base64Url.d.ts.map +1 -1
- package/dist/encoding/Base64Url.js +26 -3
- package/dist/encoding/Base64Url.js.map +1 -1
- package/dist/encoding/Json5.d.ts +44 -0
- package/dist/encoding/Json5.d.ts.map +1 -0
- package/dist/encoding/Json5.js +56 -0
- package/dist/encoding/Json5.js.map +1 -0
- package/dist/encoding/Jsonc.d.ts +47 -0
- package/dist/encoding/Jsonc.d.ts.map +1 -0
- package/dist/encoding/Jsonc.js +120 -0
- package/dist/encoding/Jsonc.js.map +1 -0
- package/dist/encoding/Ndjson.d.ts +5 -4
- package/dist/encoding/Ndjson.d.ts.map +1 -1
- package/dist/encoding/Ndjson.js +6 -5
- package/dist/encoding/Ndjson.js.map +1 -1
- package/dist/encoding/SchemaBinary.d.ts +94 -0
- package/dist/encoding/SchemaBinary.d.ts.map +1 -1
- package/dist/encoding/SchemaBinary.js +219 -6
- package/dist/encoding/SchemaBinary.js.map +1 -1
- package/dist/encoding/Sse.d.ts +3 -1
- package/dist/encoding/Sse.d.ts.map +1 -1
- package/dist/encoding/Sse.js +5 -3
- package/dist/encoding/Sse.js.map +1 -1
- package/dist/encoding/index.d.ts +10 -0
- package/dist/encoding/index.d.ts.map +1 -1
- package/dist/encoding/index.js +10 -0
- package/dist/encoding/index.js.map +1 -1
- package/dist/eventlog/EventLog.d.ts +7 -0
- package/dist/eventlog/EventLog.d.ts.map +1 -1
- package/dist/eventlog/EventLog.js +7 -0
- package/dist/eventlog/EventLog.js.map +1 -1
- package/dist/eventlog/EventLogServer.d.ts +7 -1
- package/dist/eventlog/EventLogServer.d.ts.map +1 -1
- package/dist/eventlog/EventLogServer.js +55 -24
- package/dist/eventlog/EventLogServer.js.map +1 -1
- package/dist/eventlog/EventLogServerEncrypted.d.ts +10 -0
- package/dist/eventlog/EventLogServerEncrypted.d.ts.map +1 -1
- package/dist/eventlog/EventLogServerEncrypted.js.map +1 -1
- package/dist/eventlog/EventLogServerUnencrypted.d.ts +17 -0
- package/dist/eventlog/EventLogServerUnencrypted.d.ts.map +1 -1
- package/dist/eventlog/EventLogServerUnencrypted.js +14 -2
- package/dist/eventlog/EventLogServerUnencrypted.js.map +1 -1
- package/dist/eventlog/EventLogSessionAuth.d.ts +21 -0
- package/dist/eventlog/EventLogSessionAuth.d.ts.map +1 -1
- package/dist/eventlog/EventLogSessionAuth.js +22 -0
- package/dist/eventlog/EventLogSessionAuth.js.map +1 -1
- package/dist/graphql/GraphQLClient.d.ts +3 -1
- package/dist/graphql/GraphQLClient.d.ts.map +1 -1
- package/dist/graphql/GraphQLClient.js.map +1 -1
- package/dist/graphql/GraphQLClientError.d.ts +14 -9
- package/dist/graphql/GraphQLClientError.d.ts.map +1 -1
- package/dist/graphql/GraphQLClientError.js +14 -21
- package/dist/graphql/GraphQLClientError.js.map +1 -1
- package/dist/graphql/GraphQLProtocol.d.ts +12 -3
- package/dist/graphql/GraphQLProtocol.d.ts.map +1 -1
- package/dist/graphql/GraphQLProtocol.js +4 -1
- package/dist/graphql/GraphQLProtocol.js.map +1 -1
- package/dist/http/HttpClient.d.ts +204 -16
- package/dist/http/HttpClient.d.ts.map +1 -1
- package/dist/http/HttpClient.js +93 -13
- package/dist/http/HttpClient.js.map +1 -1
- package/dist/http/HttpServerRequest.d.ts.map +1 -1
- package/dist/http/HttpServerRequest.js +38 -22
- package/dist/http/HttpServerRequest.js.map +1 -1
- package/dist/http/internal/mimeTypes.d.ts +4 -1
- package/dist/http/internal/mimeTypes.d.ts.map +1 -1
- package/dist/http/internal/mimeTypes.js +4 -1
- package/dist/http/internal/mimeTypes.js.map +1 -1
- package/dist/http-api/HttpApiSchema.js +1 -1
- package/dist/http-api/HttpApiSchema.js.map +1 -1
- package/dist/internal/dateTime.js +66 -27
- package/dist/internal/dateTime.js.map +1 -1
- package/dist/internal/effect.js +10 -0
- package/dist/internal/effect.js.map +1 -1
- package/dist/internal/glob.js +234 -56
- package/dist/internal/glob.js.map +1 -1
- package/dist/internal/graphql.js +21 -7
- package/dist/internal/graphql.js.map +1 -1
- package/dist/internal/graphqlHeaders.d.ts +7 -0
- package/dist/internal/graphqlHeaders.d.ts.map +1 -1
- package/dist/internal/graphqlHeaders.js +11 -0
- package/dist/internal/graphqlHeaders.js.map +1 -1
- package/dist/internal/jsonParser.d.ts +5 -0
- package/dist/internal/jsonParser.d.ts.map +1 -0
- package/dist/internal/jsonParser.js +280 -0
- package/dist/internal/jsonParser.js.map +1 -0
- package/dist/internal/persistence.js +8 -1
- package/dist/internal/persistence.js.map +1 -1
- package/dist/internal/request.js +29 -42
- package/dist/internal/request.js.map +1 -1
- package/dist/internal/schema/fromJsonSchemaDocument.js +7 -8
- package/dist/internal/schema/fromJsonSchemaDocument.js.map +1 -1
- package/dist/internal/sql.js +16 -0
- package/dist/internal/sql.js.map +1 -1
- package/dist/internal/version.js +1 -1
- package/dist/jose/JoseError.d.ts +285 -0
- package/dist/jose/JoseError.d.ts.map +1 -0
- package/dist/jose/JoseError.js +269 -0
- package/dist/jose/JoseError.js.map +1 -0
- package/dist/jose/Jwe.d.ts +128 -0
- package/dist/jose/Jwe.d.ts.map +1 -0
- package/dist/jose/Jwe.js +134 -0
- package/dist/jose/Jwe.js.map +1 -0
- package/dist/jose/Jwk.d.ts +597 -0
- package/dist/jose/Jwk.d.ts.map +1 -0
- package/dist/jose/Jwk.js +503 -0
- package/dist/jose/Jwk.js.map +1 -0
- package/dist/jose/Jwks.d.ts +236 -0
- package/dist/jose/Jwks.d.ts.map +1 -0
- package/dist/jose/Jwks.js +306 -0
- package/dist/jose/Jwks.js.map +1 -0
- package/dist/jose/Jws.d.ts +177 -0
- package/dist/jose/Jws.d.ts.map +1 -0
- package/dist/jose/Jws.js +183 -0
- package/dist/jose/Jws.js.map +1 -0
- package/dist/jose/Jwt.d.ts +270 -0
- package/dist/jose/Jwt.d.ts.map +1 -0
- package/dist/jose/Jwt.js +293 -0
- package/dist/jose/Jwt.js.map +1 -0
- package/dist/jose/index.d.ts +51 -0
- package/dist/jose/index.d.ts.map +1 -0
- package/dist/jose/index.js +52 -0
- package/dist/jose/index.js.map +1 -0
- package/dist/jose/internal/compact.d.ts +2 -0
- package/dist/jose/internal/compact.d.ts.map +1 -0
- package/dist/jose/internal/compact.js +179 -0
- package/dist/jose/internal/compact.js.map +1 -0
- package/dist/net/Host.d.ts.map +1 -1
- package/dist/net/Host.js +5 -10
- package/dist/net/Host.js.map +1 -1
- package/dist/observability/OtlpExporter.d.ts +4 -0
- package/dist/observability/OtlpExporter.d.ts.map +1 -1
- package/dist/observability/OtlpExporter.js +40 -12
- package/dist/observability/OtlpExporter.js.map +1 -1
- package/dist/observability/OtlpSerialization.d.ts +1 -1
- package/dist/observability/OtlpSerialization.d.ts.map +1 -1
- package/dist/observability/OtlpSerialization.js +10 -4
- package/dist/observability/OtlpSerialization.js.map +1 -1
- package/dist/observability/internal/otlpProtobuf.js +3 -3
- package/dist/observability/internal/otlpProtobuf.js.map +1 -1
- package/dist/observability/internal/protobuf.js +6 -0
- package/dist/observability/internal/protobuf.js.map +1 -1
- package/dist/persistence/CircuitBreaker.d.ts +98 -38
- package/dist/persistence/CircuitBreaker.d.ts.map +1 -1
- package/dist/persistence/CircuitBreaker.js +67 -29
- package/dist/persistence/CircuitBreaker.js.map +1 -1
- package/dist/persistence/RateLimiter.d.ts +15 -0
- package/dist/persistence/RateLimiter.d.ts.map +1 -1
- package/dist/persistence/RateLimiter.js +76 -16
- package/dist/persistence/RateLimiter.js.map +1 -1
- package/dist/persistence/index.d.ts +1 -1
- package/dist/persistence/index.js +1 -1
- package/dist/reactivity/AtomRegistry.js +17 -7
- package/dist/reactivity/AtomRegistry.js.map +1 -1
- package/dist/rpc/Rpc.d.ts +1 -1
- package/dist/rpc/Rpc.d.ts.map +1 -1
- package/dist/rpc/Rpc.js.map +1 -1
- package/dist/rpc/RpcClient.d.ts +14 -2
- package/dist/rpc/RpcClient.d.ts.map +1 -1
- package/dist/rpc/RpcClient.js +38 -21
- package/dist/rpc/RpcClient.js.map +1 -1
- package/dist/rpc/RpcMessage.d.ts +3 -2
- package/dist/rpc/RpcMessage.d.ts.map +1 -1
- package/dist/rpc/RpcMessage.js.map +1 -1
- package/dist/rpc/RpcServer.d.ts.map +1 -1
- package/dist/rpc/RpcServer.js +10 -1
- package/dist/rpc/RpcServer.js.map +1 -1
- package/dist/sql/Migrator.d.ts +9 -1
- package/dist/sql/Migrator.d.ts.map +1 -1
- package/dist/sql/Migrator.js +18 -6
- package/dist/sql/Migrator.js.map +1 -1
- package/dist/sql/SqlClient.d.ts +46 -3
- package/dist/sql/SqlClient.d.ts.map +1 -1
- package/dist/sql/SqlClient.js +40 -15
- package/dist/sql/SqlClient.js.map +1 -1
- package/dist/sql/Statement.d.ts +46 -3
- package/dist/sql/Statement.d.ts.map +1 -1
- package/dist/sql/Statement.js +32 -26
- package/dist/sql/Statement.js.map +1 -1
- package/dist/workflow/Workflow.d.ts +4 -0
- package/dist/workflow/Workflow.d.ts.map +1 -1
- package/dist/workflow/Workflow.js.map +1 -1
- package/dist/workflow/WorkflowEngine.d.ts.map +1 -1
- package/dist/workflow/WorkflowEngine.js +5 -0
- package/dist/workflow/WorkflowEngine.js.map +1 -1
- package/package.json +7 -3
- package/src/BigDecimal.ts +170 -16
- package/src/ByteSize.ts +29 -14
- package/src/Equal.ts +3 -3
- package/src/Hash.ts +5 -4
- package/src/Iterable.ts +28 -19
- package/src/JsonSchema.ts +45 -7
- package/src/MutableRef.ts +1 -8
- package/src/Path.ts +6 -1
- package/src/Pool.ts +2 -1
- package/src/Ref.ts +0 -8
- package/src/Schedule.ts +8 -6
- package/src/Schema.ts +3 -2
- package/src/SchemaRepresentation.ts +4 -2
- package/src/SchemaTransformation.ts +2 -2
- package/src/Stream.ts +6 -5
- package/src/ai/McpClient.ts +488 -91
- package/src/ai/McpSchema.ts +119 -0
- package/src/ai/McpServer.ts +302 -56
- package/src/ai/Prompt.ts +16 -11
- package/src/ai/Tool.ts +5 -10
- package/src/ai/internal/mcpCore.ts +165 -12
- package/src/ai/internal/mcpProtocol/v2024_11_05.ts +3 -1
- package/src/ai/internal/mcpProtocol/v2025_03_26.ts +3 -1
- package/src/ai/internal/mcpProtocol/v2025_06_18.ts +3 -1
- package/src/ai/internal/mcpProtocol/v2025_11_25.ts +3 -1
- package/src/ai/internal/mcpProtocol/v2026_07_28.ts +42 -9
- package/src/ai/internal/mcpProtocol.ts +15 -0
- package/src/ai/internal/mcpRuntime.ts +6 -3
- package/src/ai/internal/mcpSkills.ts +480 -0
- package/src/ai/internal/structured-output.ts +10 -4
- package/src/cluster/ClusterWorkflowEngine.ts +48 -33
- package/src/cluster/Entity.ts +52 -0
- package/src/cluster/MessageStorage.ts +3 -6
- package/src/cluster/Reply.ts +1 -1
- package/src/cluster/Runners.ts +16 -2
- package/src/cluster/Sharding.ts +17 -1
- package/src/cluster/internal/clusterAbandon.ts +7 -7
- package/src/cluster/internal/entityManager.ts +89 -15
- package/src/cluster/internal/transactionNotifications.ts +7 -0
- package/src/crypto/Aead.ts +3 -3
- package/src/crypto/Cipher.ts +3 -3
- package/src/crypto/KeyAgreement.ts +4 -4
- package/src/crypto/KeyFormat.ts +30 -1
- package/src/crypto/KeyWrap.ts +6 -6
- package/src/crypto/Mac.ts +3 -3
- package/src/crypto/Signature.ts +4 -4
- package/src/crypto/WebCrypto.ts +20 -0
- package/src/crypto/internal/asymmetric.ts +2 -1
- package/src/crypto/internal/key.ts +12 -5
- package/src/encoding/Base64Url.ts +27 -3
- package/src/encoding/Json5.ts +59 -0
- package/src/encoding/Jsonc.ts +126 -0
- package/src/encoding/Ndjson.ts +6 -5
- package/src/encoding/SchemaBinary.ts +228 -7
- package/src/encoding/Sse.ts +5 -3
- package/src/encoding/index.ts +12 -0
- package/src/eventlog/EventLog.ts +7 -0
- package/src/eventlog/EventLogServer.ts +67 -24
- package/src/eventlog/EventLogServerEncrypted.ts +5 -0
- package/src/eventlog/EventLogServerUnencrypted.ts +19 -2
- package/src/eventlog/EventLogSessionAuth.ts +26 -0
- package/src/graphql/GraphQLClient.ts +3 -1
- package/src/graphql/GraphQLClientError.ts +15 -22
- package/src/graphql/GraphQLProtocol.ts +12 -3
- package/src/http/HttpClient.ts +244 -33
- package/src/http/HttpServerRequest.ts +61 -23
- package/src/http/internal/mimeTypes.ts +4 -1
- package/src/http-api/HttpApiSchema.ts +1 -1
- package/src/internal/dateTime.ts +80 -27
- package/src/internal/effect.ts +6 -0
- package/src/internal/glob.ts +279 -63
- package/src/internal/graphql.ts +27 -9
- package/src/internal/graphqlHeaders.ts +13 -0
- package/src/internal/jsonParser.ts +307 -0
- package/src/internal/persistence.ts +9 -1
- package/src/internal/request.ts +51 -58
- package/src/internal/schema/fromJsonSchemaDocument.ts +11 -10
- package/src/internal/sql.ts +25 -0
- package/src/internal/version.ts +1 -1
- package/src/jose/JoseError.ts +329 -0
- package/src/jose/Jwe.ts +196 -0
- package/src/jose/Jwk.ts +777 -0
- package/src/jose/Jwks.ts +418 -0
- package/src/jose/Jws.ts +312 -0
- package/src/jose/Jwt.ts +493 -0
- package/src/jose/index.ts +58 -0
- package/src/jose/internal/compact.ts +195 -0
- package/src/net/Host.ts +5 -10
- package/src/observability/OtlpExporter.ts +42 -18
- package/src/observability/OtlpSerialization.ts +13 -5
- package/src/observability/internal/otlpProtobuf.ts +6 -6
- package/src/observability/internal/protobuf.ts +10 -0
- package/src/persistence/CircuitBreaker.ts +113 -48
- package/src/persistence/RateLimiter.ts +97 -19
- package/src/persistence/index.ts +1 -1
- package/src/reactivity/AtomRegistry.ts +19 -8
- package/src/rpc/Rpc.ts +3 -1
- package/src/rpc/RpcClient.ts +44 -24
- package/src/rpc/RpcMessage.ts +3 -2
- package/src/rpc/RpcServer.ts +12 -1
- package/src/sql/Migrator.ts +35 -18
- package/src/sql/SqlClient.ts +91 -22
- package/src/sql/Statement.ts +60 -35
- package/src/workflow/Workflow.ts +4 -0
- package/src/workflow/WorkflowEngine.ts +5 -0
package/src/ai/McpSchema.ts
CHANGED
|
@@ -1382,6 +1382,125 @@ export class ResourceUpdatedNotification extends Rpc.make("notifications/resourc
|
|
|
1382
1382
|
}
|
|
1383
1383
|
}) {}
|
|
1384
1384
|
|
|
1385
|
+
// =============================================================================
|
|
1386
|
+
// Skills
|
|
1387
|
+
// =============================================================================
|
|
1388
|
+
|
|
1389
|
+
/**
|
|
1390
|
+
* Schema for a file of an Agent Skill served under the MCP Skills extension
|
|
1391
|
+
* (SEP-2640), with the digest and size of its content.
|
|
1392
|
+
*
|
|
1393
|
+
* @stability unstable
|
|
1394
|
+
* @category schemas
|
|
1395
|
+
* @since 4.1.1
|
|
1396
|
+
*/
|
|
1397
|
+
export class SkillResource extends Schema.Class<SkillResource>(
|
|
1398
|
+
"@effect/ai/McpSchema/SkillResource"
|
|
1399
|
+
)({
|
|
1400
|
+
/**
|
|
1401
|
+
* The resource URI of the file.
|
|
1402
|
+
*/
|
|
1403
|
+
uri: Schema.String,
|
|
1404
|
+
/**
|
|
1405
|
+
* The SHA-256 digest of the file's bytes, as `sha256:` followed by 64
|
|
1406
|
+
* lowercase hexadecimal digits.
|
|
1407
|
+
*/
|
|
1408
|
+
digest: Schema.String.check(Schema.isPattern(/^sha256:[0-9a-f]{64}$/)),
|
|
1409
|
+
/**
|
|
1410
|
+
* The length of the file's bytes.
|
|
1411
|
+
*/
|
|
1412
|
+
size: Schema.Natural
|
|
1413
|
+
}) {}
|
|
1414
|
+
|
|
1415
|
+
/**
|
|
1416
|
+
* Schema for the YAML frontmatter of an Agent Skill's `SKILL.md`, as the
|
|
1417
|
+
* Agent Skills specification defines it (https://agentskills.io/specification).
|
|
1418
|
+
*
|
|
1419
|
+
* **Details**
|
|
1420
|
+
*
|
|
1421
|
+
* Fields the specification does not define are kept unchanged. `McpServer`
|
|
1422
|
+
* checks a skill's frontmatter against this schema before serving it. The
|
|
1423
|
+
* frontmatter of a {@link Skill} received from a server is only checked for
|
|
1424
|
+
* the `name` and `description` that the Skills extension requires; decode it
|
|
1425
|
+
* with this schema for the other fields.
|
|
1426
|
+
*
|
|
1427
|
+
* @stability unstable
|
|
1428
|
+
* @category schemas
|
|
1429
|
+
* @since 4.1.1
|
|
1430
|
+
*/
|
|
1431
|
+
export const SkillFrontmatter = Schema.StructWithRest(
|
|
1432
|
+
Schema.Struct({
|
|
1433
|
+
/**
|
|
1434
|
+
* 1 to 64 lowercase letters, digits and hyphens, with no leading, trailing
|
|
1435
|
+
* or consecutive hyphen. It names the directory holding `SKILL.md`.
|
|
1436
|
+
*/
|
|
1437
|
+
name: Schema.String.check(Schema.isMaxLength(64), Schema.isPattern(/^[a-z0-9]+(?:-[a-z0-9]+)*$/)),
|
|
1438
|
+
/**
|
|
1439
|
+
* What the skill does and when to use it, in 1 to 1024 characters.
|
|
1440
|
+
*/
|
|
1441
|
+
description: Schema.String.check(Schema.isNonEmpty(), Schema.isMaxLength(1024)),
|
|
1442
|
+
/**
|
|
1443
|
+
* The skill's license, or the name of a bundled license file.
|
|
1444
|
+
*/
|
|
1445
|
+
license: Schema.optionalKey(Schema.String),
|
|
1446
|
+
/**
|
|
1447
|
+
* Environment requirements, in 1 to 500 characters.
|
|
1448
|
+
*/
|
|
1449
|
+
compatibility: Schema.optionalKey(Schema.String.check(Schema.isNonEmpty(), Schema.isMaxLength(500))),
|
|
1450
|
+
/**
|
|
1451
|
+
* Additional properties not defined by the specification.
|
|
1452
|
+
*/
|
|
1453
|
+
metadata: Schema.optionalKey(Schema.Record(Schema.String, Schema.String)),
|
|
1454
|
+
/**
|
|
1455
|
+
* Space-separated tools the skill asks to run without approval. Hosts must
|
|
1456
|
+
* ignore it for a skill served over MCP unless the user approved the grant.
|
|
1457
|
+
*/
|
|
1458
|
+
"allowed-tools": Schema.optionalKey(Schema.String)
|
|
1459
|
+
}),
|
|
1460
|
+
[UnknownObject]
|
|
1461
|
+
)
|
|
1462
|
+
|
|
1463
|
+
/**
|
|
1464
|
+
* The YAML frontmatter of an Agent Skill's `SKILL.md`.
|
|
1465
|
+
*
|
|
1466
|
+
* @stability unstable
|
|
1467
|
+
* @category models
|
|
1468
|
+
* @since 4.1.1
|
|
1469
|
+
*/
|
|
1470
|
+
export type SkillFrontmatter = typeof SkillFrontmatter.Type
|
|
1471
|
+
|
|
1472
|
+
/**
|
|
1473
|
+
* Schema for an Agent Skill served under the MCP Skills extension (SEP-2640),
|
|
1474
|
+
* as `skills/list` and `skills/get` describe it.
|
|
1475
|
+
*
|
|
1476
|
+
* @stability unstable
|
|
1477
|
+
* @category schemas
|
|
1478
|
+
* @since 4.1.1
|
|
1479
|
+
*/
|
|
1480
|
+
export class Skill extends Schema.Class<Skill>(
|
|
1481
|
+
"@effect/ai/McpSchema/Skill"
|
|
1482
|
+
)({
|
|
1483
|
+
/**
|
|
1484
|
+
* The resource URI of the skill's `SKILL.md`.
|
|
1485
|
+
*/
|
|
1486
|
+
uri: Schema.String,
|
|
1487
|
+
/**
|
|
1488
|
+
* The YAML frontmatter of the skill's `SKILL.md`, as a JSON object, with
|
|
1489
|
+
* every field the author wrote. See {@link SkillFrontmatter} for the fields
|
|
1490
|
+
* the Agent Skills specification defines.
|
|
1491
|
+
*/
|
|
1492
|
+
frontmatter: Schema.StructWithRest(
|
|
1493
|
+
Schema.Struct({ name: Schema.String, description: Schema.String }),
|
|
1494
|
+
[UnknownObject]
|
|
1495
|
+
),
|
|
1496
|
+
/**
|
|
1497
|
+
* Every file of the skill, `SKILL.md` included, or `"dynamic"` when the
|
|
1498
|
+
* server generates the skill's content and publishes no digests.
|
|
1499
|
+
*/
|
|
1500
|
+
resources: Schema.Union([Schema.Array(SkillResource), Schema.Literal("dynamic")]),
|
|
1501
|
+
_meta: optional(UnknownObject)
|
|
1502
|
+
}) {}
|
|
1503
|
+
|
|
1385
1504
|
// =============================================================================
|
|
1386
1505
|
// Prompts
|
|
1387
1506
|
// =============================================================================
|
package/src/ai/McpServer.ts
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
import * as Arr from "../Array.ts"
|
|
15
15
|
import * as Cause from "../Cause.ts"
|
|
16
16
|
import * as Context from "../Context.ts"
|
|
17
|
+
import * as Digest from "../crypto/Digest.ts"
|
|
17
18
|
import * as Data from "../Data.ts"
|
|
18
19
|
import * as Deferred from "../Deferred.ts"
|
|
19
20
|
import * as Duration from "../Duration.ts"
|
|
@@ -53,6 +54,7 @@ import * as AiError from "./AiError.ts"
|
|
|
53
54
|
import * as McpCore from "./internal/mcpCore.ts"
|
|
54
55
|
import * as McpProtocolInternal from "./internal/mcpProtocol.ts"
|
|
55
56
|
import * as McpRuntime from "./internal/mcpRuntime.ts"
|
|
57
|
+
import * as McpSkills from "./internal/mcpSkills.ts"
|
|
56
58
|
import * as InternalStructuredOutput from "./internal/structured-output.ts"
|
|
57
59
|
import type * as McpProtocol from "./McpProtocol.ts"
|
|
58
60
|
import * as McpSchema from "./McpSchema.ts"
|
|
@@ -106,6 +108,8 @@ interface QueuedServerNotification {
|
|
|
106
108
|
|
|
107
109
|
const internalState = new WeakMap<object, {
|
|
108
110
|
readonly core: McpCore.McpCore
|
|
111
|
+
// Registers a skill's own file, skipping the check that reserves it for the skill.
|
|
112
|
+
readonly addSkillFile: McpServer["Service"]["addResource"]
|
|
109
113
|
readonly notifications: Queue.Dequeue<QueuedServerNotification>
|
|
110
114
|
readonly notificationDelivery: { consumers: number; listChangeRevision: number; requestEndpoints: number }
|
|
111
115
|
readonly globalMiddleware: Array<middleware.Fn<any, any, any>>
|
|
@@ -314,6 +318,9 @@ export type MiddlewareMethod =
|
|
|
314
318
|
| "resources/list"
|
|
315
319
|
| "resources/templates/list"
|
|
316
320
|
| "prompts/list"
|
|
321
|
+
| "skills/list"
|
|
322
|
+
| "skills/get"
|
|
323
|
+
| "resources/directory/read"
|
|
317
324
|
|
|
318
325
|
/**
|
|
319
326
|
* Request metadata passed to MCP middleware.
|
|
@@ -322,12 +329,17 @@ export type MiddlewareMethod =
|
|
|
322
329
|
*
|
|
323
330
|
* `target` is the tool name, the requested resource URI, or the prompt name.
|
|
324
331
|
* For `completion/complete` it is the prompt name, or the URI template of the
|
|
325
|
-
* resource template being completed. `
|
|
332
|
+
* resource template being completed. For `skills/get` it is the URI of the
|
|
333
|
+
* skill's `SKILL.md`. `payload` holds the request parameters.
|
|
326
334
|
*
|
|
327
335
|
* On list requests, middleware runs only when it wraps a {@link visibility},
|
|
328
336
|
* once for each registration it wraps. `target` is then the tool name, the
|
|
329
337
|
* resource URI, the URI template or the prompt name of that registration, and
|
|
330
|
-
* `payload` is `undefined`.
|
|
338
|
+
* `payload` is `undefined`. `skills/list` and `resources/directory/read` are
|
|
339
|
+
* list requests whose `target` is the `SKILL.md` URI of each skill; a
|
|
340
|
+
* directory read checks only the skills that have the directory. A skill's
|
|
341
|
+
* files are resources, checked as `resources/list` and `resources/read` with
|
|
342
|
+
* their own URIs.
|
|
331
343
|
*
|
|
332
344
|
* `headers` are the HTTP request headers. They are empty on stdio, on custom
|
|
333
345
|
* transports and for in-process calls. `sessionId` is the `Mcp-Session-Id`
|
|
@@ -725,23 +737,48 @@ class MiddlewareImpl {
|
|
|
725
737
|
}
|
|
726
738
|
}
|
|
727
739
|
|
|
728
|
-
// The innermost middleware comes first.
|
|
740
|
+
// The innermost middleware comes first. Each stack keeps its own order, and
|
|
741
|
+
// where that leaves the order open, stacks provided further outside, which come
|
|
742
|
+
// first in the context, run further outside. Stacks that order the same
|
|
743
|
+
// middleware both ways have no common order, so insertion order decides.
|
|
729
744
|
const getMiddleware = (context: Context.Context<never>): ReadonlyArray<AnyMiddlewareFn> => {
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
745
|
+
// The middleware directly inside each middleware, and how many of those
|
|
746
|
+
// directly outside it are still unplaced.
|
|
747
|
+
const inners = new Map<AnyMiddlewareFn, Array<AnyMiddlewareFn>>()
|
|
748
|
+
const unplacedOuters = new Map<AnyMiddlewareFn, number>()
|
|
749
|
+
for (const [key, stack] of context.mapUnsafe) {
|
|
750
|
+
if (!key.startsWith(middlewareKeyPrefix)) continue
|
|
751
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
752
|
+
const fn = stack[i]
|
|
753
|
+
if (!inners.has(fn)) {
|
|
754
|
+
inners.set(fn, [])
|
|
755
|
+
unplacedOuters.set(fn, 0)
|
|
756
|
+
}
|
|
757
|
+
const outer = stack[i + 1]
|
|
758
|
+
if (outer !== undefined && outer !== fn) {
|
|
759
|
+
inners.get(outer)!.push(fn)
|
|
760
|
+
unplacedOuters.set(fn, unplacedOuters.get(fn)! + 1)
|
|
761
|
+
}
|
|
736
762
|
}
|
|
737
763
|
}
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
764
|
+
// Repeatedly places the first middleware with nothing left to place outside it.
|
|
765
|
+
const outermostFirst: Array<AnyMiddlewareFn> = []
|
|
766
|
+
while (unplacedOuters.size > 0) {
|
|
767
|
+
let next = unplacedOuters.keys().next().value!
|
|
768
|
+
for (const [fn, count] of unplacedOuters) {
|
|
769
|
+
if (count === 0) {
|
|
770
|
+
next = fn
|
|
771
|
+
break
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
unplacedOuters.delete(next)
|
|
775
|
+
outermostFirst.push(next)
|
|
776
|
+
for (const fn of inners.get(next)!) {
|
|
777
|
+
const count = unplacedOuters.get(fn)
|
|
778
|
+
if (count !== undefined) unplacedOuters.set(fn, count - 1)
|
|
742
779
|
}
|
|
743
780
|
}
|
|
744
|
-
return
|
|
781
|
+
return outermostFirst.reverse()
|
|
745
782
|
}
|
|
746
783
|
|
|
747
784
|
const isMcpError = (error: unknown): error is McpErrorBase =>
|
|
@@ -759,7 +796,7 @@ const internalError = new InternalError({ message: "Internal error" })
|
|
|
759
796
|
const rejectWith = (error: McpErrorBase) =>
|
|
760
797
|
Effect.fail(new McpCore.RequestRejected({ code: error.code, message: error.message, data: error.data, error }))
|
|
761
798
|
|
|
762
|
-
type CallMethod = "tools/call" | "resources/read" | "prompts/get" | "completion/complete"
|
|
799
|
+
type CallMethod = "tools/call" | "resources/read" | "prompts/get" | "completion/complete" | "skills/get"
|
|
763
800
|
|
|
764
801
|
type ListMethod = Exclude<MiddlewareMethod, CallMethod>
|
|
765
802
|
|
|
@@ -768,6 +805,7 @@ interface NotFoundErrors {
|
|
|
768
805
|
readonly "resources/read": McpCore.ResourceNotFound
|
|
769
806
|
readonly "prompts/get": McpCore.PromptNotFound
|
|
770
807
|
readonly "completion/complete": InvalidParams
|
|
808
|
+
readonly "skills/get": McpCore.SkillNotFound
|
|
771
809
|
}
|
|
772
810
|
|
|
773
811
|
const notFound = (method: CallMethod, target: string): NotFoundErrors[CallMethod] => {
|
|
@@ -780,6 +818,8 @@ const notFound = (method: CallMethod, target: string): NotFoundErrors[CallMethod
|
|
|
780
818
|
return new McpCore.PromptNotFound({ name: target })
|
|
781
819
|
case "completion/complete":
|
|
782
820
|
return new InvalidParams({ message: "Unknown completion reference or argument" })
|
|
821
|
+
case "skills/get":
|
|
822
|
+
return new McpCore.SkillNotFound({ uri: target })
|
|
783
823
|
}
|
|
784
824
|
}
|
|
785
825
|
|
|
@@ -1127,6 +1167,38 @@ export class McpServer extends Context.Service<McpServer, {
|
|
|
1127
1167
|
))
|
|
1128
1168
|
})
|
|
1129
1169
|
|
|
1170
|
+
// Checking skill ownership and both writes happen in one synchronous step,
|
|
1171
|
+
// so a skill cannot claim the URI in between. Skill files skip the check.
|
|
1172
|
+
const addResource = (
|
|
1173
|
+
options: Parameters<McpServer["Service"]["addResource"]>[0],
|
|
1174
|
+
checkOwnership: boolean
|
|
1175
|
+
): Effect.Effect<void> =>
|
|
1176
|
+
Effect.suspend(() => {
|
|
1177
|
+
if (checkOwnership && internalCore.skills.ownsFile(options.resource.uri)) {
|
|
1178
|
+
return Effect.die(
|
|
1179
|
+
new Cause.IllegalArgumentError(`Resource ${options.resource.uri} is a file of a registered skill`)
|
|
1180
|
+
)
|
|
1181
|
+
}
|
|
1182
|
+
const existingIndex = resources.findIndex(({ resource }) => resource.uri === options.resource.uri)
|
|
1183
|
+
if (existingIndex === -1) {
|
|
1184
|
+
resources.push(options)
|
|
1185
|
+
} else {
|
|
1186
|
+
resources[existingIndex] = options
|
|
1187
|
+
}
|
|
1188
|
+
const { invoke, visible } = makeInvoke(options.services, globalMiddleware)
|
|
1189
|
+
internalCore.resources.register({
|
|
1190
|
+
descriptor: options.resource,
|
|
1191
|
+
visible: visible("resources/list", options.resource.uri),
|
|
1192
|
+
isVisible: isEnabled(options.annotations),
|
|
1193
|
+
read: (invocation) =>
|
|
1194
|
+
invoke(options.handle, invocation, {
|
|
1195
|
+
method: "resources/read",
|
|
1196
|
+
target: options.resource.uri,
|
|
1197
|
+
payload: { uri: options.resource.uri }
|
|
1198
|
+
})
|
|
1199
|
+
})
|
|
1200
|
+
return notifications.client["notifications/resources/list_changed"]({})
|
|
1201
|
+
})
|
|
1130
1202
|
const service = McpServer.of({
|
|
1131
1203
|
notifications: notifications.client,
|
|
1132
1204
|
notifyElicitationComplete: ({ clientId, elicitationId }) =>
|
|
@@ -1222,27 +1294,7 @@ export class McpServer extends Context.Service<McpServer, {
|
|
|
1222
1294
|
get resourceTemplates() {
|
|
1223
1295
|
return resourceTemplates
|
|
1224
1296
|
},
|
|
1225
|
-
addResource:
|
|
1226
|
-
const existingIndex = resources.findIndex(({ resource }) => resource.uri === options.resource.uri)
|
|
1227
|
-
if (existingIndex === -1) {
|
|
1228
|
-
resources.push(options)
|
|
1229
|
-
} else {
|
|
1230
|
-
resources[existingIndex] = options
|
|
1231
|
-
}
|
|
1232
|
-
const { invoke, visible } = makeInvoke(options.services, globalMiddleware)
|
|
1233
|
-
yield* internalCore.resources.register({
|
|
1234
|
-
descriptor: options.resource,
|
|
1235
|
-
visible: visible("resources/list", options.resource.uri),
|
|
1236
|
-
isVisible: isEnabled(options.annotations),
|
|
1237
|
-
read: (invocation) =>
|
|
1238
|
-
invoke(options.handle, invocation, {
|
|
1239
|
-
method: "resources/read",
|
|
1240
|
-
target: options.resource.uri,
|
|
1241
|
-
payload: { uri: options.resource.uri }
|
|
1242
|
-
})
|
|
1243
|
-
})
|
|
1244
|
-
yield* notifications.client["notifications/resources/list_changed"]({})
|
|
1245
|
-
}),
|
|
1297
|
+
addResource: (options) => addResource(options, true),
|
|
1246
1298
|
addResourceTemplate: Effect.fnUntraced(
|
|
1247
1299
|
function*({ annotations, completions, handle, routerPath, services, template }) {
|
|
1248
1300
|
const existingIndex = resourceTemplates.findIndex(({ template: current }) =>
|
|
@@ -1400,6 +1452,7 @@ export class McpServer extends Context.Service<McpServer, {
|
|
|
1400
1452
|
})
|
|
1401
1453
|
internalState.set(service, {
|
|
1402
1454
|
core: internalCore,
|
|
1455
|
+
addSkillFile: (options) => addResource(options, false),
|
|
1403
1456
|
notifications: notificationsQueue,
|
|
1404
1457
|
notificationDelivery,
|
|
1405
1458
|
globalMiddleware
|
|
@@ -1467,9 +1520,11 @@ export interface CacheHint {
|
|
|
1467
1520
|
*
|
|
1468
1521
|
* Each entry sets the freshness and `cacheScope` of one result kind:
|
|
1469
1522
|
* `server/discover`, `tools/list`, `resources/list`,
|
|
1470
|
-
* `resources/templates/list` and `prompts/list`.
|
|
1471
|
-
* `
|
|
1472
|
-
*
|
|
1523
|
+
* `resources/templates/list` and `prompts/list`. `skills` covers the Skills
|
|
1524
|
+
* extension's `skills/list`, `skills/get` and `resources/directory/read`.
|
|
1525
|
+
* Omitted entries, and `resources/read` results, keep
|
|
1526
|
+
* `{ ttlMs: 0, cacheScope: "private" }`. Earlier protocol revisions have no
|
|
1527
|
+
* cache hints and ignore this option.
|
|
1473
1528
|
*
|
|
1474
1529
|
* These are hints for clients. The server does not cache results, and
|
|
1475
1530
|
* visibility and invocation checks still run on every request.
|
|
@@ -1491,6 +1546,7 @@ export interface CacheHints {
|
|
|
1491
1546
|
readonly resources?: CacheHint | undefined
|
|
1492
1547
|
readonly resourceTemplates?: CacheHint | undefined
|
|
1493
1548
|
readonly prompts?: CacheHint | undefined
|
|
1549
|
+
readonly skills?: CacheHint | undefined
|
|
1494
1550
|
}
|
|
1495
1551
|
|
|
1496
1552
|
// Converts each hint to the wire's nonnegative integer `ttlMs` once, when the server is built.
|
|
@@ -2068,7 +2124,7 @@ const runWithRuntime = Effect.fnUntraced(function*(
|
|
|
2068
2124
|
const selectedProtocol = clientState?.protocol ?? runtime.protocols[0]
|
|
2069
2125
|
const profile = reverseKey?.profile ?? clientState?.profile ?? {
|
|
2070
2126
|
protocolVersion: selectedProtocol.protocolVersion,
|
|
2071
|
-
clientCapabilities: {},
|
|
2127
|
+
clientCapabilities: new McpSchema.ClientCapabilities({}),
|
|
2072
2128
|
clientInfo: { name: "unknown", version: "unknown" }
|
|
2073
2129
|
}
|
|
2074
2130
|
return RcMap.get(
|
|
@@ -3050,14 +3106,40 @@ export const registerToolkit: <Tools extends Record<string, Tool.Any>>(
|
|
|
3050
3106
|
const annotations = tool.annotations
|
|
3051
3107
|
const toolMeta = Context.getOrUndefined(annotations, Tool.Meta)
|
|
3052
3108
|
const isDeclaredFailure = Schema.is(tool.failureSchema)
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3109
|
+
// MCP content is JSON, so results and declared failures go through their JSON codec.
|
|
3110
|
+
const encodeJson = (schema: Schema.Constraint) => {
|
|
3111
|
+
const encode = Schema.encodeUnknownEffect(Schema.toCodecJson(schema)) as (
|
|
3112
|
+
value: unknown
|
|
3113
|
+
) => Effect.Effect<unknown, Schema.SchemaError, Tool.HandlerServices<Tools[keyof Tools]>>
|
|
3114
|
+
return (toolResult: unknown) =>
|
|
3115
|
+
Effect.mapError(encode(toolResult), (cause) =>
|
|
3116
|
+
AiError.make({
|
|
3117
|
+
module: "McpServer",
|
|
3118
|
+
method: "registerToolkit",
|
|
3119
|
+
reason: new AiError.ToolResultEncodingError({
|
|
3120
|
+
toolName: tool.name,
|
|
3121
|
+
toolResult,
|
|
3122
|
+
description: cause.message
|
|
3123
|
+
})
|
|
3124
|
+
}))
|
|
3125
|
+
}
|
|
3126
|
+
const encodeFailure = encodeJson(tool.failureSchema)
|
|
3127
|
+
// Successes and "return"-mode failures arrive already encoded by the Toolkit; only their JSON conversion runs here.
|
|
3128
|
+
const encodeReturnedFailure = encodeJson(Schema.toEncoded(tool.failureSchema))
|
|
3129
|
+
const encodeStructured = encodeJson(Schema.toEncoded(tool.successSchema))
|
|
3130
|
+
const failureResult = (encoded: unknown) =>
|
|
3131
|
+
new CallToolResult({ isError: true, content: toolResultContent(encoded) })
|
|
3056
3132
|
const declaredFailureResult = (error: unknown) =>
|
|
3057
3133
|
error instanceof Error && error.message !== ""
|
|
3058
3134
|
? Effect.succeed(toolErrorResult(error.message))
|
|
3059
|
-
: Effect.map(encodeFailure(error),
|
|
3060
|
-
|
|
3135
|
+
: Effect.map(encodeFailure(error), failureResult)
|
|
3136
|
+
const successResult = (result: unknown) =>
|
|
3137
|
+
Effect.map(encodeStructured(result), (structuredContent) =>
|
|
3138
|
+
new CallToolResult({
|
|
3139
|
+
isError: false,
|
|
3140
|
+
structuredContent,
|
|
3141
|
+
content: toolResultContent(structuredContent)
|
|
3142
|
+
}))
|
|
3061
3143
|
const handleCause = (cause: Cause.Cause<unknown>) => {
|
|
3062
3144
|
const failure = Cause.findFail(cause)
|
|
3063
3145
|
if (Result.isSuccess(failure)) {
|
|
@@ -3113,21 +3195,25 @@ export const registerToolkit: <Tools extends Record<string, Tool.Any>>(
|
|
|
3113
3195
|
Stream.unwrap,
|
|
3114
3196
|
Stream.runLast,
|
|
3115
3197
|
Effect.flatMap(Effect.fromOption),
|
|
3116
|
-
Effect.flatMap((result)
|
|
3198
|
+
Effect.flatMap((result): Effect.Effect<
|
|
3199
|
+
CallToolResult,
|
|
3200
|
+
unknown,
|
|
3201
|
+
Tool.HandlerServices<Tools[keyof Tools]>
|
|
3202
|
+
> => {
|
|
3203
|
+
if (!result.isFailure) {
|
|
3204
|
+
// An absent result, such as `Schema.Void`, has no structured form.
|
|
3205
|
+
return result.encodedResult === undefined
|
|
3206
|
+
? Effect.succeed(new CallToolResult({ isError: false, content: [] }))
|
|
3207
|
+
: successResult(result.encodedResult)
|
|
3208
|
+
}
|
|
3117
3209
|
// Declared failures return their encoded payload; anything else is classified by origin.
|
|
3118
|
-
|
|
3119
|
-
? Effect.
|
|
3210
|
+
return result.failureOrigin === "handler"
|
|
3211
|
+
? Effect.map(encodeReturnedFailure(result.encodedResult), failureResult)
|
|
3212
|
+
: Effect.failCause(Cause.annotate(
|
|
3120
3213
|
Cause.fail(result.result),
|
|
3121
3214
|
Context.make(Toolkit.FailureOrigin, result.failureOrigin ?? "result")
|
|
3122
3215
|
))
|
|
3123
|
-
|
|
3124
|
-
new CallToolResult({
|
|
3125
|
-
isError: result.isFailure,
|
|
3126
|
-
structuredContent: result.isFailure ? undefined : result.encodedResult,
|
|
3127
|
-
content: toolResultContent(result.encodedResult)
|
|
3128
|
-
})
|
|
3129
|
-
)
|
|
3130
|
-
),
|
|
3216
|
+
}),
|
|
3131
3217
|
Effect.catchCause(handleCause)
|
|
3132
3218
|
) as Effect.Effect<CallToolResult, InvalidParams, never>
|
|
3133
3219
|
},
|
|
@@ -3565,6 +3651,166 @@ export const resource: {
|
|
|
3565
3651
|
return (options: any) => Layer.effectDiscard(register(options))
|
|
3566
3652
|
} as any
|
|
3567
3653
|
|
|
3654
|
+
/**
|
|
3655
|
+
* A file of a skill: its text, its bytes, or either with an explicit MIME
|
|
3656
|
+
* type. Without one, the MIME type is inferred from the file extension.
|
|
3657
|
+
*
|
|
3658
|
+
* @stability unstable
|
|
3659
|
+
* @category models
|
|
3660
|
+
* @since 4.1.1
|
|
3661
|
+
*/
|
|
3662
|
+
export type SkillFile = string | Uint8Array | {
|
|
3663
|
+
readonly content: string | Uint8Array
|
|
3664
|
+
readonly mimeType?: string | undefined
|
|
3665
|
+
}
|
|
3666
|
+
|
|
3667
|
+
/**
|
|
3668
|
+
* Options for {@link registerSkill} and {@link skill}.
|
|
3669
|
+
*
|
|
3670
|
+
* **Details**
|
|
3671
|
+
*
|
|
3672
|
+
* `uri` addresses the skill's `SKILL.md`, as
|
|
3673
|
+
* `skill://<skill-path>/SKILL.md`. Its last path segment is the skill's name,
|
|
3674
|
+
* which must equal the frontmatter's `name`. Other schemes work the same way.
|
|
3675
|
+
*
|
|
3676
|
+
* `files` maps paths relative to the skill root to the skill's files,
|
|
3677
|
+
* `SKILL.md` included. Files are served verbatim, and the skill's listed
|
|
3678
|
+
* frontmatter is parsed from `SKILL.md`. Quote frontmatter strings that a YAML
|
|
3679
|
+
* 1.1 parser reads as another type, such as `yes` or `1.0`.
|
|
3680
|
+
*
|
|
3681
|
+
* @stability unstable
|
|
3682
|
+
* @category models
|
|
3683
|
+
* @since 4.1.1
|
|
3684
|
+
*/
|
|
3685
|
+
export interface SkillOptions {
|
|
3686
|
+
readonly uri: string
|
|
3687
|
+
readonly files: { readonly "SKILL.md": SkillFile } & Readonly<Record<string, SkillFile>>
|
|
3688
|
+
readonly annotations?: Context.Context<never> | undefined
|
|
3689
|
+
}
|
|
3690
|
+
|
|
3691
|
+
const skillFileEncoder = new TextEncoder()
|
|
3692
|
+
|
|
3693
|
+
// Bytes are copied so that later changes by the caller cannot alter what is
|
|
3694
|
+
// served under the listed digest. `Buffer#slice` shares memory, so copy with
|
|
3695
|
+
// the `Uint8Array` constructor.
|
|
3696
|
+
const toSkillSourceFile = (path: string, file: SkillFile): McpSkills.SourceFile => {
|
|
3697
|
+
const { content, mimeType } = typeof file === "string" || file instanceof Uint8Array ? { content: file } : file
|
|
3698
|
+
return {
|
|
3699
|
+
path,
|
|
3700
|
+
content: typeof content === "string" ? skillFileEncoder.encode(content) : new Uint8Array(content),
|
|
3701
|
+
mimeType
|
|
3702
|
+
}
|
|
3703
|
+
}
|
|
3704
|
+
|
|
3705
|
+
/**
|
|
3706
|
+
* Registers an Agent Skill under the MCP Skills extension (SEP-2640).
|
|
3707
|
+
*
|
|
3708
|
+
* **Details**
|
|
3709
|
+
*
|
|
3710
|
+
* Each file is registered as a resource, and the skill is listed by
|
|
3711
|
+
* `skills/list` and `skills/get` with a manifest of every file's SHA-256
|
|
3712
|
+
* digest and size, computed from the bytes served. Every directory of the
|
|
3713
|
+
* skill namespace is readable with `resources/directory/read`. The server
|
|
3714
|
+
* declares the extension once any skill is registered.
|
|
3715
|
+
*
|
|
3716
|
+
* Fails when the skill breaks the extension's rules: a name that does not
|
|
3717
|
+
* match the URI, a `SKILL.md` without YAML frontmatter, frontmatter that is
|
|
3718
|
+
* not valid {@link McpSchema.SkillFrontmatter}, a file path that leaves the
|
|
3719
|
+
* skill, or more than 512 files or 16 MiB in all. It also fails when the
|
|
3720
|
+
* skill's directory contains or lies inside another skill's, or one of its
|
|
3721
|
+
* files is already registered as a resource. Registering a resource at the
|
|
3722
|
+
* URI of a skill's file afterwards is a defect.
|
|
3723
|
+
*
|
|
3724
|
+
* SHA-256 runs on `crypto.subtle`.
|
|
3725
|
+
*
|
|
3726
|
+
* @see {@link skill} for the layer-based skill registration wrapper
|
|
3727
|
+
*
|
|
3728
|
+
* @stability unstable
|
|
3729
|
+
* @category handlers
|
|
3730
|
+
* @since 4.1.1
|
|
3731
|
+
*/
|
|
3732
|
+
export const registerSkill: (options: SkillOptions) => Effect.Effect<void, Cause.IllegalArgumentError, McpServer> =
|
|
3733
|
+
Effect.fnUntraced(function*(options: SkillOptions) {
|
|
3734
|
+
const files = Object.entries(options.files).map(([path, file]) => toSkillSourceFile(path, file))
|
|
3735
|
+
const skill = yield* McpSkills.makeStaticSkill({ uri: options.uri, files }).pipe(
|
|
3736
|
+
Effect.provide(Digest.layerWebCrypto)
|
|
3737
|
+
)
|
|
3738
|
+
|
|
3739
|
+
const registry = yield* McpServer
|
|
3740
|
+
const { addSkillFile, core, globalMiddleware } = internalState.get(registry)!
|
|
3741
|
+
const services = yield* Effect.context<never>()
|
|
3742
|
+
const annotations = options.annotations ?? Context.empty()
|
|
3743
|
+
const { invoke, visible } = makeInvoke(services, globalMiddleware)
|
|
3744
|
+
// Claims the skill's file URIs before they are registered as resources.
|
|
3745
|
+
yield* core.skills.register({
|
|
3746
|
+
entry: skill.entry,
|
|
3747
|
+
isVisible: isEnabled(annotations),
|
|
3748
|
+
visible: visible("skills/list", options.uri),
|
|
3749
|
+
visibleInDirectories: visible("resources/directory/read", options.uri),
|
|
3750
|
+
get: (invocation) =>
|
|
3751
|
+
invoke(Effect.succeed(skill.entry), invocation, {
|
|
3752
|
+
method: "skills/get",
|
|
3753
|
+
target: options.uri,
|
|
3754
|
+
payload: { uri: options.uri }
|
|
3755
|
+
}),
|
|
3756
|
+
directory: (uri) => skill.directories.get(uri)
|
|
3757
|
+
})
|
|
3758
|
+
for (const { content, resource, text } of skill.files) {
|
|
3759
|
+
const { uri, mimeType } = resource
|
|
3760
|
+
yield* addSkillFile({
|
|
3761
|
+
resource: new Resource(resource),
|
|
3762
|
+
annotations,
|
|
3763
|
+
services,
|
|
3764
|
+
handle: Effect.succeed({
|
|
3765
|
+
contents: [text === undefined ? { uri, mimeType, blob: content } : { uri, mimeType, text }]
|
|
3766
|
+
})
|
|
3767
|
+
})
|
|
3768
|
+
}
|
|
3769
|
+
})
|
|
3770
|
+
|
|
3771
|
+
/**
|
|
3772
|
+
* Creates a layer that registers an Agent Skill under the MCP Skills extension
|
|
3773
|
+
* (SEP-2640).
|
|
3774
|
+
*
|
|
3775
|
+
* **Example** (Publishing a skill with a supporting file)
|
|
3776
|
+
*
|
|
3777
|
+
* ```ts
|
|
3778
|
+
* import { Layer } from "effect"
|
|
3779
|
+
* import { McpProtocol, McpServer } from "effect/ai"
|
|
3780
|
+
*
|
|
3781
|
+
* const RefundsSkill = McpServer.skill({
|
|
3782
|
+
* uri: "skill://billing/refunds/SKILL.md",
|
|
3783
|
+
* files: {
|
|
3784
|
+
* "SKILL.md": `---
|
|
3785
|
+
* name: refunds
|
|
3786
|
+
* description: Process refunds using the billing tools
|
|
3787
|
+
* ---
|
|
3788
|
+
*
|
|
3789
|
+
* Read references/policy.md before issuing a refund.
|
|
3790
|
+
* `,
|
|
3791
|
+
* "references/policy.md": "Refunds above CHF 500 require manager approval.\n"
|
|
3792
|
+
* }
|
|
3793
|
+
* })
|
|
3794
|
+
*
|
|
3795
|
+
* const ServerLayer = RefundsSkill.pipe(
|
|
3796
|
+
* Layer.provide(McpServer.layerHttp({
|
|
3797
|
+
* name: "billing",
|
|
3798
|
+
* version: "1.0.0",
|
|
3799
|
+
* path: "/mcp",
|
|
3800
|
+
* protocols: [McpProtocol.v2026_07_28, McpProtocol.v2025_11_25]
|
|
3801
|
+
* }))
|
|
3802
|
+
* )
|
|
3803
|
+
* ```
|
|
3804
|
+
*
|
|
3805
|
+
* @see {@link registerSkill} for the Effect-level skill registration API
|
|
3806
|
+
*
|
|
3807
|
+
* @stability unstable
|
|
3808
|
+
* @category layers
|
|
3809
|
+
* @since 4.1.1
|
|
3810
|
+
*/
|
|
3811
|
+
export const skill = (options: SkillOptions): Layer.Layer<never, Cause.IllegalArgumentError, McpServer> =>
|
|
3812
|
+
Layer.effectDiscard(registerSkill(options))
|
|
3813
|
+
|
|
3568
3814
|
/**
|
|
3569
3815
|
* Registers an MCP prompt from an Effect program.
|
|
3570
3816
|
*
|
package/src/ai/Prompt.ts
CHANGED
|
@@ -486,6 +486,16 @@ export interface FilePartEncoded extends BasePartEncoded<"file", FilePartOptions
|
|
|
486
486
|
*/
|
|
487
487
|
export interface FilePartOptions extends ProviderOptions {}
|
|
488
488
|
|
|
489
|
+
const TaggedURL = Schema.TaggedStruct("URL", { href: Schema.URLFromString })
|
|
490
|
+
|
|
491
|
+
const urlFromTaggedURL = SchemaTransformation.transform<URL, typeof TaggedURL.Type>({
|
|
492
|
+
decode: ({ href }) => href,
|
|
493
|
+
encode: (href) => (({
|
|
494
|
+
_tag: "URL",
|
|
495
|
+
href
|
|
496
|
+
}) as const)
|
|
497
|
+
})
|
|
498
|
+
|
|
489
499
|
/**
|
|
490
500
|
* Schema for validation and encoding of file parts.
|
|
491
501
|
*
|
|
@@ -535,18 +545,13 @@ export const FilePart: Schema.Struct<{
|
|
|
535
545
|
}) as const)
|
|
536
546
|
})
|
|
537
547
|
)),
|
|
538
|
-
Schema.
|
|
539
|
-
Schema.URL,
|
|
540
|
-
SchemaTransformation.transform({
|
|
541
|
-
decode: ({ href }) => href,
|
|
542
|
-
encode: (href) => (({
|
|
543
|
-
_tag: "URL",
|
|
544
|
-
href
|
|
545
|
-
}) as const)
|
|
546
|
-
})
|
|
547
|
-
)),
|
|
548
|
+
TaggedURL.pipe(Schema.decodeTo(Schema.URL, urlFromTaggedURL)),
|
|
548
549
|
Schema.Uint8Array,
|
|
549
|
-
|
|
550
|
+
// Under the JSON and binary codecs a raw `URL` would serialize as a plain
|
|
551
|
+
// string, indistinguishable from the `Schema.String` member. Serialize it
|
|
552
|
+
// through the same `TaggedURL` instance instead, so the codecs see a
|
|
553
|
+
// single `{ _tag: "URL" }` member rather than two
|
|
554
|
+
Schema.URL.annotate({ toCodecJson: () => Schema.link<URL>()(TaggedURL, urlFromTaggedURL) })
|
|
550
555
|
])
|
|
551
556
|
}).annotate({ identifier: "FilePart" })
|
|
552
557
|
|