import * as Effect from "effect/Effect";import * as Option from "effect/Option";import * as Schema from "effect/Schema";import * as SchemaTransformation from "effect/SchemaTransformation"; export const TrimmedString = Schema.String.pipe( Schema.decodeTo( Schema.String, SchemaTransformation.transformOrFail({ decode: (value) => Effect.succeed(value.trim()), encode: (value) => Effect.succeed(value.trim()), }), ),);export const TrimmedNonEmptyString = TrimmedString.check(Schema.isNonEmpty()); export const NonNegativeInt = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0));export const PositiveInt = Schema.Int.check(Schema.isGreaterThanOrEqualTo(1));export const PortSchema = Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 65535 })); /** * Safe categories for a failed DPoP proof. These describe the class of failure * without exposing proof contents or server-side authentication details. */export const DpopFailureReason = Schema.Literals([ "time_window", "key_mismatch", "request_mismatch", "token_mismatch", "replay", "invalid_proof",]);export type DpopFailureReason = typeof DpopFailureReason.Type; export const IsoDateTime = Schema.String;export type IsoDateTime = typeof IsoDateTime.Type; /** * Wire codec for server→client arrays whose element unions grow over time * (new literal members, new struct variants). Decoding drops elements the * current build cannot decode instead of failing the whole payload — a client * has to keep decoding configs sent by servers newer than itself, and * rejecting the payload would take down the connection over data the client * couldn't act on anyway. Encoding is the plain array encoding. */export const ForwardCompatibleArray = <Element extends Schema.Top>(element: Element) => { const decodeElement = Schema.decodeUnknownOption(element as never); return Schema.Array(Schema.Unknown).pipe( Schema.decodeTo( Schema.Array(element), SchemaTransformation.transform<ReadonlyArray<Element["Encoded"]>, ReadonlyArray<unknown>>({ decode: (values) => values.filter((value) => Option.isSome(decodeElement(value))) as ReadonlyArray< Element["Encoded"] >, encode: (values) => values, }), ), );}; /** * Construct a branded identifier. Enforces non-empty trimmed strings */const makeEntityId = <Brand extends string>(brand: Brand) => { return TrimmedNonEmptyString.pipe(Schema.brand(brand));}; export const ThreadId = makeEntityId("ThreadId");export type ThreadId = typeof ThreadId.Type;export const ProjectId = makeEntityId("ProjectId");export type ProjectId = typeof ProjectId.Type;export const EnvironmentId = makeEntityId("EnvironmentId");export type EnvironmentId = typeof EnvironmentId.Type;export const CommandId = makeEntityId("CommandId");export type CommandId = typeof CommandId.Type;export const EventId = makeEntityId("EventId");export type EventId = typeof EventId.Type;export const MessageId = makeEntityId("MessageId");export type MessageId = typeof MessageId.Type;export const TurnId = makeEntityId("TurnId");export type TurnId = typeof TurnId.Type;export const AuthSessionId = makeEntityId("AuthSessionId");export type AuthSessionId = typeof AuthSessionId.Type;export const RpcClientId = NonNegativeInt.pipe(Schema.brand("RpcClientId"));export type RpcClientId = typeof RpcClientId.Type; /** * Which client surface a connection or command comes from. Unlike * `AuthClientMetadataDeviceType` (a UA-style device class where web and * desktop are both "desktop"), this names the actual product surface. * Optional everywhere it appears: old clients never send it. */export const ClientSurface = Schema.Literals(["web", "desktop", "mobile", "cli"]);export type ClientSurface = typeof ClientSurface.Type; export const ClientOs = Schema.Literals([ "macOS", "Windows", "Linux", "iOS", "Android", "ChromeOS", "other", "unknown",]);export type ClientOs = typeof ClientOs.Type; export const ClientDeviceType = Schema.Literals(["desktop", "phone", "tablet", "unknown"]);export type ClientDeviceType = typeof ClientDeviceType.Type; export const ClientWebDeployment = Schema.Literals(["hosted", "server"]);export type ClientWebDeployment = typeof ClientWebDeployment.Type; export const ClientConnectionMethod = Schema.Literals(["direct", "ssh", "relay", "unknown"]);export type ClientConnectionMethod = typeof ClientConnectionMethod.Type; export const ProviderItemId = makeEntityId("ProviderItemId");export type ProviderItemId = typeof ProviderItemId.Type;export const RuntimeSessionId = makeEntityId("RuntimeSessionId");export type RuntimeSessionId = typeof RuntimeSessionId.Type;export const RuntimeItemId = makeEntityId("RuntimeItemId");export type RuntimeItemId = typeof RuntimeItemId.Type;export const RuntimeRequestId = makeEntityId("RuntimeRequestId");export type RuntimeRequestId = typeof RuntimeRequestId.Type;export const RuntimeTaskId = makeEntityId("RuntimeTaskId");export type RuntimeTaskId = typeof RuntimeTaskId.Type;export const ApprovalRequestId = makeEntityId("ApprovalRequestId");export type ApprovalRequestId = typeof ApprovalRequestId.Type;export const CheckpointRef = makeEntityId("CheckpointRef");export type CheckpointRef = typeof CheckpointRef.Type;
import * as Effect from "effect/Effect";
import * as Option from "effect/Option";
import * as Schema from "effect/Schema";
import * as SchemaTransformation from "effect/SchemaTransformation";
export const TrimmedString = Schema.String.pipe(
Schema.decodeTo(
Schema.String,
SchemaTransformation.transformOrFail({
decode: (value) => Effect.succeed(value.trim()),
encode: (value) => Effect.succeed(value.trim()),
}),
),
);
export const TrimmedNonEmptyString = TrimmedString.check(Schema.isNonEmpty());
export const NonNegativeInt = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0));
export const PositiveInt = Schema.Int.check(Schema.isGreaterThanOrEqualTo(1));
export const PortSchema = Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 65535 }));
/**
* Safe categories for a failed DPoP proof. These describe the class of failure
* without exposing proof contents or server-side authentication details.
*/
export const DpopFailureReason = Schema.Literals([
"time_window",
"key_mismatch",
"request_mismatch",
"token_mismatch",
"replay",
"invalid_proof",
]);
export type DpopFailureReason = typeof DpopFailureReason.Type;
export const IsoDateTime = Schema.String;
export type IsoDateTime = typeof IsoDateTime.Type;
/**
* Wire codec for server→client arrays whose element unions grow over time
* (new literal members, new struct variants). Decoding drops elements the
* current build cannot decode instead of failing the whole payload — a client
* has to keep decoding configs sent by servers newer than itself, and
* rejecting the payload would take down the connection over data the client
* couldn't act on anyway. Encoding is the plain array encoding.
*/
export const ForwardCompatibleArray = <Element extends Schema.Top>(element: Element) => {
const decodeElement = Schema.decodeUnknownOption(element as never);
return Schema.Array(Schema.Unknown).pipe(
Schema.decodeTo(
Schema.Array(element),
SchemaTransformation.transform<ReadonlyArray<Element["Encoded"]>, ReadonlyArray<unknown>>({
decode: (values) =>
values.filter((value) => Option.isSome(decodeElement(value))) as ReadonlyArray<
Element["Encoded"]
>,
encode: (values) => values,
}),
),
);
};
/**
* Construct a branded identifier. Enforces non-empty trimmed strings
*/
const makeEntityId = <Brand extends string>(brand: Brand) => {
return TrimmedNonEmptyString.pipe(Schema.brand(brand));
};
export const ThreadId = makeEntityId("ThreadId");
export type ThreadId = typeof ThreadId.Type;
export const ProjectId = makeEntityId("ProjectId");
export type ProjectId = typeof ProjectId.Type;
export const EnvironmentId = makeEntityId("EnvironmentId");
export type EnvironmentId = typeof EnvironmentId.Type;
export const CommandId = makeEntityId("CommandId");
export type CommandId = typeof CommandId.Type;
export const EventId = makeEntityId("EventId");
export type EventId = typeof EventId.Type;
export const MessageId = makeEntityId("MessageId");
export type MessageId = typeof MessageId.Type;
export const TurnId = makeEntityId("TurnId");
export type TurnId = typeof TurnId.Type;
export const AuthSessionId = makeEntityId("AuthSessionId");
export type AuthSessionId = typeof AuthSessionId.Type;
export const RpcClientId = NonNegativeInt.pipe(Schema.brand("RpcClientId"));
export type RpcClientId = typeof RpcClientId.Type;
/**
* Which client surface a connection or command comes from. Unlike
* `AuthClientMetadataDeviceType` (a UA-style device class where web and
* desktop are both "desktop"), this names the actual product surface.
* Optional everywhere it appears: old clients never send it.
*/
export const ClientSurface = Schema.Literals(["web", "desktop", "mobile", "cli"]);
export type ClientSurface = typeof ClientSurface.Type;
export const ClientOs = Schema.Literals([
"macOS",
"Windows",
"Linux",
"iOS",
"Android",
"ChromeOS",
"other",
"unknown",
]);
export type ClientOs = typeof ClientOs.Type;
export const ClientDeviceType = Schema.Literals(["desktop", "phone", "tablet", "unknown"]);
export type ClientDeviceType = typeof ClientDeviceType.Type;
export const ClientWebDeployment = Schema.Literals(["hosted", "server"]);
export type ClientWebDeployment = typeof ClientWebDeployment.Type;
export const ClientConnectionMethod = Schema.Literals(["direct", "ssh", "relay", "unknown"]);
export type ClientConnectionMethod = typeof ClientConnectionMethod.Type;
export const ProviderItemId = makeEntityId("ProviderItemId");
export type ProviderItemId = typeof ProviderItemId.Type;
export const RuntimeSessionId = makeEntityId("RuntimeSessionId");
export type RuntimeSessionId = typeof RuntimeSessionId.Type;
export const RuntimeItemId = makeEntityId("RuntimeItemId");
export type RuntimeItemId = typeof RuntimeItemId.Type;
export const RuntimeRequestId = makeEntityId("RuntimeRequestId");
export type RuntimeRequestId = typeof RuntimeRequestId.Type;
export const RuntimeTaskId = makeEntityId("RuntimeTaskId");
export type RuntimeTaskId = typeof RuntimeTaskId.Type;
export const ApprovalRequestId = makeEntityId("ApprovalRequestId");
export type ApprovalRequestId = typeof ApprovalRequestId.Type;
export const CheckpointRef = makeEntityId("CheckpointRef");
export type CheckpointRef = typeof CheckpointRef.Type;