@akterjs/client 0.0.0-stage → 0.1.1

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/LICENSE ADDED
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
package/README.md CHANGED
@@ -1,3 +1,18 @@
1
- # Temporary Holding Version
1
+ # @akterjs/client
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Clients for calling actors from anywhere: an Effect client (`Room.client(key)`) and a Promise client (`createClient<App>`) with live query subscriptions. Runs in Bun, Node, Workers and browsers, so it imports only contracts.
4
+
5
+ ```sh
6
+ npm install @akterjs/client
7
+ ```
8
+
9
+ Docs: https://docs.akter.dev. Pricing: https://docs.akter.dev/pricing.
10
+
11
+ Status: both clients work. The package root exports `createClient({ url, actors, headers?, fetch? })`, the Promise client: `akter.Room("lobby").post({ text: "hi" })` returns a Promise that rejects with the contract's error classes, so `instanceof` works, and its public types hold no Effect types. `@akterjs/client/effect` exports `akterClient({ url, headers?, fetch?, webSocket? })`, the layer behind `Room.client(key)`: it provides `RpcClient.Protocol` and `ActorClients` (`@akterjs/effect/contract/actor-client`). Both clients speak the Effect RPC that `akter dev` and Akter Cloud serve (`docs/adr/0016-clients-speak-effect-rpc-everywhere.md`): calls, queries, `create`, `ensure` and `warm` are NDJSON posts to `<url>/rpc` over `fetch`, and each live subscription is its own WebSocket to `<url>/rpc?request=<the RPC request as JSON>` with RPC JSON frames (`src/actor-protocol.layer.ts`). `headers()` runs for every request and every socket, so a refreshed token takes effect on the next one. A socket can't carry headers from a browser, so the client offers the subprotocols `akter-rpc` and `akter-auth.<token>` for an `Authorization: Bearer <token>` header, and sends the other headers in the RPC request frame; the token never goes in the URL. `webSocket` replaces the global `WebSocket` constructor. A subscription whose socket drops resubscribes with backoff (50 ms doubling, at most 5 s apart) and skips any update at or below the version it already delivered, so a reconnect never repeats an update. Both clients read their own writes: when a server answers a command or query `Exit` with the actor's commit `version`, as Akter Cloud does, the client keeps the highest version it has seen for that actor and key and sends it as each later request's `akter-floor` RPC header, and the server never answers it from a cache older than that (`src/read-floors.pure.ts`). `akter dev` answers no versions and gets no floor. Both clients mint a fresh command id for each command and retry a lost reply (a transport failure) with the same id, so a retried command takes effect once. The contract's errors and the hosted ones arrive as their own classes, and both `@akterjs/client` and `@akterjs/client/effect` re-export every hosted one a call can fail with (`ActorAlreadyExistsError`, `ActorNotCreatedError`, `ActorUnavailableError`, `CallerNotAllowedError`, `CommandIdExpiredError`, `HandlerFailedError`, `InvalidRequestError`, `UnauthenticatedError`, and for files `BlobTransferError`, `FileAccessDeniedError`, `FileNotFoundError`, `FilesUnavailableError` and `InvalidFileRequestError`), the same classes `@akterjs/effect` and `@akterjs/effect/contract/errors` export. A request the server ends with only an interrupt, which says it stopped the request without answering, fails with `ActorUnavailableError` ("…stopped this request before it answered. Retry shortly.") rather than interrupting the caller, so a CLI prints why instead of exiting 130 with nothing (`src/remote-interrupt.pure.ts`). A bundle test builds both clients and a contract for browsers and Workers and checks that only contract files and `effect` go in. `pnpm test` runs every client test on Node. `pnpm test:browser` and `pnpm test:workerd` run only the tests `vitest.config.ts` lists for headless Chromium and workerd, which is `tests/promise-client.adapter.portable.test.ts`: it drives the Promise client against a stubbed `fetch` that answers in the wire format, with no server. The other tests need Node, because the bundle test runs esbuild and the rest serve a room with `Akter.serve`. `@akterjs/conformance/client` holds the public-contract fixture both clients pass against `akter dev` here and against Akter Cloud in akter-cloud. Each query also has `subscribe`, and each actor has `state`: `room.messages.subscribe({ limit: 50 })` and `room.state` are streams on the Effect client, and on the Promise client `akter.Room("lobby").messages.subscribe({ limit: 50 }, render, onError?)` (a query declared without a payload subscribes as `subscribe(render, onError?)`) and `akter.Room("lobby").state.subscribe(render, onError?)` return a function that stops the subscription. Each update is `{ value, version }`, where `version` is the actor's journal position of the commit it reflects. An actor declared with `create` also has `create(input)` and `ensure(input)` on both clients: `create` fails with `ActorAlreadyExistsError` (exported by `@akterjs/effect`) when the actor exists, and `ensure` creates it only when it doesn't. Each mints a command id and retries a lost reply with it, like a command, so a retried create replays its first result instead of failing. Each actor also has `warm`: `room.warm` on the Effect client and `akter.Room("lobby").warm()` on the Promise client ask the server to open the actor before its first command, so a page can start the open on load and hide it behind the user's think time. A warm runs no command, journals nothing and leaves the actor's version as it was, and a warm on a key that was never created does nothing. Each actor also has `fork(into)`: `room.fork("copy")` on the Effect client and `akter.Room("lobby").fork("copy")` on the Promise client copy the actor at the moment the fork runs into the new key and return a client or handle on the copy. The copy starts quiet (no timers, outbox or running jobs, `docs/adr/0017-forks-start-quiet.md`), and later commands to either side don't reach the other. Each fork mints a command id and retries a lost reply with it, so a retried fork makes one copy; a fork into a key that exists fails with `ActorAlreadyExistsError`. `akter dev` forks. Akter Cloud refuses the fork RPC for every caller by design (`InvalidRequestError`): a fork there is an operator action on the Cloud API (decision 5), made with `akter actors fork`, the `actors_fork` MCP tool or the Cloud API's `actorForks.create`, `POST /v1/organizations/{organization}/apps/{app}/environments/{environment}/actors/{actor}/{key}/forks`.
12
+
13
+ An actor whose contract declares `files: Akter.fileAccess({ callers })` has files on both clients; one without has no file calls, and its Promise handle has no `.files`. On the Promise client, `akter.Board("b1").files` has `upload(bytes)`, which takes a `Uint8Array` or a `ReadableStream<Uint8Array>` and resolves with the receipt, `list({ prefix?, limit?, cursor? })` and `usage(...)`, which resolve with `{ entries, cursor? }` (and `bytes` for usage), and `download(path, { offset, length }?)`, which resolves with a `ReadableStream<Uint8Array>`. The download is lazy: a missing file errors the stream with `FileNotFoundError` on its first read, not the Promise. A source stream that fails rejects the upload with `UploadSourceError`. On the Effect client, `akterClient` provides `ActorFileClients`, so `Room.files(key)` works over the network as it does in process: `upload(stream)` returns the receipt a command attaches with `Akter.files.attach(path, receipt)`, and `list`, `fileUsage` and `download(path, range?)` read what the actor holds. They are the `<Actor>/files/<operation>` RPCs ADR 0016 reserves, all NDJSON posts. Effect RPC has no client streams, so an upload is a session: `upload/open` returns an id bound to the actor, key and caller, `upload/append` sends chunks of at most 1 MiB in order and is idempotent by offset, so a lost reply is retried with the same offset, and `upload/close` checks the length and returns the receipt. A download streams chunks of at most 256 KiB. The server admits a file call only from a caller kind the declaration lists, and then runs the actor's `files.authorize` rule, which reads the state and the verified principal and refuses with `FileAccessDeniedError` unless it allows the call; a download's path is checked before the rule sees it. A fork admits only an app's operators, the `user` and `apiKey` kinds, because it runs no handler. The key must decode with the actor's key schema. A session another actor, key or caller names is refused. The server keeps at most 64 open sessions, 8 per caller and 8 per actor, and drops one idle for 60 seconds. A file past 1 GiB fails with `FileTooLargeError`. An actor holds at most 16 receipts no command has attached, and a receipt expires an hour after its upload closes.
14
+
15
+ `@akterjs/client/operations` is the actor half of the operation registry that drives the `akter` CLI and the hosted MCP server (the Cloud half is `@akterjs/cloud-api/operations`): `actorOperations` lists each exposed kind (`call`, `query`, `state`, `watch`, `create`, `ensure`, `fork`, and the file kinds `files/list`, `files/usage`, `files/download` and `files/upload`, whose three session RPCs are one kind) with its command, tool name, input schema and annotations, `kindsOf` gives every RPC of an actor's group its kind or none, so a new kind of RPC fails the coverage test until it has an operation, and `actorRequestOf` builds the RPC tag and payload a caller sends, minting a UUIDv7 command id when the kind takes one and none was given. `@akterjs/client/actor-rpc` holds the one-RPC unary and streaming clients those requests go through, with schema-free JSON payloads, and the file transfers both callers run: `uploadSession({ request, content, wait })` opens an upload, appends the bytes in chunks of at most 1 MiB at their offsets and closes it for the receipt, and `downloadChunks({ request, wait })` collects a download's base64 chunks, failing whole rather than returning part of a file.
16
+
17
+ - Depends on: `@akterjs/effect` (peer, contracts only) and `effect` (peer). `@akterjs/effect` is a peer so the app and the client share one copy: the client decodes errors into its classes, and a second copy would break `instanceof` on them.
18
+ - Must not depend on: any private package.
@@ -0,0 +1,77 @@
1
+ import { Schema } from "effect";
2
+ type JsonObject = Schema.JsonObject;
3
+ declare const fieldSchemas: {
4
+ actor: {
5
+ description: string;
6
+ type: string;
7
+ };
8
+ after: {
9
+ description: string;
10
+ type: string;
11
+ };
12
+ commandId: {
13
+ description: string;
14
+ type: string;
15
+ };
16
+ computer: {
17
+ description: string;
18
+ type: string;
19
+ };
20
+ computerPath: {
21
+ description: string;
22
+ type: string;
23
+ };
24
+ content: {
25
+ description: string;
26
+ type: string;
27
+ };
28
+ cursor: {
29
+ description: string;
30
+ type: string;
31
+ };
32
+ direction: {
33
+ description: string;
34
+ enum: string[];
35
+ type: string;
36
+ };
37
+ into: {
38
+ description: string;
39
+ };
40
+ key: {
41
+ description: string;
42
+ };
43
+ length: {
44
+ description: string;
45
+ type: string;
46
+ };
47
+ limit: {
48
+ description: string;
49
+ type: string;
50
+ };
51
+ member: {
52
+ description: string;
53
+ type: string;
54
+ };
55
+ offset: {
56
+ description: string;
57
+ type: string;
58
+ };
59
+ path: {
60
+ description: string;
61
+ type: string;
62
+ };
63
+ payload: {
64
+ description: string;
65
+ };
66
+ prefix: {
67
+ description: string;
68
+ type: string;
69
+ };
70
+ step: {
71
+ description: string;
72
+ type: string;
73
+ };
74
+ };
75
+ type FieldName = keyof typeof fieldSchemas;
76
+ declare const inputOf: (fields: readonly FieldName[]) => JsonObject;
77
+ export { type FieldName, inputOf };
@@ -0,0 +1,85 @@
1
+ import { Array, Record } from "effect";
2
+ // src/actor-fields.pure.ts
3
+ const fieldSchemas = {
4
+ actor: {
5
+ description: "The actor's name in the app, such as Sale.",
6
+ type: "string"
7
+ },
8
+ after: {
9
+ description: "Only log lines after this seq, the last one a page before printed, to read on from there.",
10
+ type: "integer"
11
+ },
12
+ commandId: {
13
+ description: "An id for this call, so a retry with the same id runs it once. A new one is made when it is missing.",
14
+ type: "string"
15
+ },
16
+ computer: {
17
+ description: "The computer's name, as the actor named it.",
18
+ type: "string"
19
+ },
20
+ computerPath: {
21
+ description: "Relative path in the computer's files directory.",
22
+ type: "string"
23
+ },
24
+ content: {
25
+ description: "The file's bytes, as base64.",
26
+ type: "string"
27
+ },
28
+ cursor: {
29
+ description: "Where the page to read starts, from the cursor of the page before.",
30
+ type: "string"
31
+ },
32
+ direction: {
33
+ description: "toComputer or fromComputer; copy-back returns an upload receipt.",
34
+ enum: ["toComputer", "fromComputer"],
35
+ type: "string"
36
+ },
37
+ into: { description: "The new actor's key, as JSON. A bare word is taken as a string key." },
38
+ key: { description: "The actor's key, as JSON. A bare word is taken as a string key." },
39
+ length: {
40
+ description: "How many bytes to read, from offset; give both or neither.",
41
+ type: "integer"
42
+ },
43
+ limit: {
44
+ description: "The most entries to return.",
45
+ type: "integer"
46
+ },
47
+ member: {
48
+ description: "The command or query to run.",
49
+ type: "string"
50
+ },
51
+ offset: {
52
+ description: "The byte to start reading at, with length; give both or neither.",
53
+ type: "integer"
54
+ },
55
+ path: {
56
+ description: "The file's path in the actor, such as photos/cat.png.",
57
+ type: "string"
58
+ },
59
+ payload: { description: "The command's, query's or create input's payload, as JSON." },
60
+ prefix: {
61
+ description: "Only paths that start with this.",
62
+ type: "string"
63
+ },
64
+ step: {
65
+ description: "The step's id, as steps list prints it.",
66
+ type: "string"
67
+ }
68
+ };
69
+ const optional = [
70
+ "after",
71
+ "commandId",
72
+ "cursor",
73
+ "length",
74
+ "limit",
75
+ "offset",
76
+ "payload",
77
+ "prefix"
78
+ ];
79
+ const inputOf = (fields) => ({
80
+ additionalProperties: false,
81
+ properties: Record.fromEntries(Array.map(fields, (name) => [name, fieldSchemas[name]])),
82
+ required: Array.filter(fields, (name) => !Array.contains(optional, name)),
83
+ type: "object"
84
+ });
85
+ export { inputOf };
@@ -0,0 +1,49 @@
1
+ import { FieldName } from "./actor-fields.pure.mjs";
2
+ import { Effect, Option, Schema } from "effect";
3
+ import { SecureRandom } from "effect/crypto";
4
+ import { Rpc } from "effect/rpc";
5
+ type JsonObject = Schema.JsonObject;
6
+ interface Annotations {
7
+ readonly confirm: boolean;
8
+ readonly destructive: boolean;
9
+ readonly idempotent: boolean;
10
+ readonly openWorld: boolean;
11
+ readonly readOnly: boolean;
12
+ }
13
+ type ActorKind = "call" | "computers/cp" | "computers/delete" | "computers/get" | "computers/list" | "computers/logs" | "computers/pause" | "computers/resume" | "computers/stop" | "create" | "ensure" | "files/download" | "files/list" | "files/upload" | "files/usage" | "fork" | "query" | "state" | "steps/get" | "steps/list" | "warm" | "watch";
14
+ interface ActorOperation {
15
+ readonly annotations: Annotations;
16
+ readonly flag: Option.Option<string>;
17
+ readonly command: readonly [string, string];
18
+ readonly description: string;
19
+ readonly fields: readonly FieldName[];
20
+ readonly id: string;
21
+ readonly input: JsonObject;
22
+ readonly kind: ActorKind;
23
+ readonly stream: boolean;
24
+ readonly tool: string;
25
+ }
26
+ declare const unexposedKinds: readonly ActorKind[];
27
+ declare const actorOperations: readonly ActorOperation[];
28
+ interface Addressed {
29
+ readonly actor: string;
30
+ readonly kind: ActorKind;
31
+ readonly member: string;
32
+ }
33
+ declare const tagOf: ({ actor, kind, member }: Addressed) => string;
34
+ declare const kindsOf: (requests: ReadonlyMap<string, Rpc.AnyWithProps>) => readonly (readonly [string, Option.Option<ActorKind>])[];
35
+ interface ActorInput {
36
+ readonly actor: string;
37
+ readonly commandId: Option.Option<string>;
38
+ readonly fileFields: Readonly<Record<string, Schema.Json>>;
39
+ readonly into: Option.Option<Schema.Json>;
40
+ readonly key: Schema.Json;
41
+ readonly member: string;
42
+ readonly payload: Option.Option<Schema.Json>;
43
+ }
44
+ interface ActorRequest {
45
+ readonly payload: Readonly<Record<string, Schema.Json>>;
46
+ readonly tag: string;
47
+ }
48
+ declare const actorRequestOf: (operation: ActorOperation) => ((input: ActorInput) => Effect.Effect<ActorRequest, never, SecureRandom.SecureRandom>);
49
+ export { type ActorInput, type ActorKind, type ActorOperation, type ActorRequest, type Annotations, type FieldName, actorOperations, actorRequestOf, kindsOf, tagOf, unexposedKinds };