durable-actors 0.5.2 → 0.5.4

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.
Files changed (82) hide show
  1. package/README.md +23 -26
  2. package/dist/actor/sandbox.d.ts +40 -0
  3. package/dist/actor/sandbox.d.ts.map +1 -0
  4. package/dist/actor/sandbox.js +32 -0
  5. package/dist/actor/sandbox.js.map +1 -0
  6. package/dist/actor/schema.d.ts +2 -0
  7. package/dist/actor/schema.d.ts.map +1 -1
  8. package/dist/actor/schema.js.map +1 -1
  9. package/dist/cli/actor-source-watcher.d.ts +18 -4
  10. package/dist/cli/actor-source-watcher.d.ts.map +1 -1
  11. package/dist/cli/actor-source-watcher.js +104 -34
  12. package/dist/cli/actor-source-watcher.js.map +1 -1
  13. package/dist/cli/dev.d.ts.map +1 -1
  14. package/dist/cli/dev.js +12 -1
  15. package/dist/cli/dev.js.map +1 -1
  16. package/dist/cli/generate.d.ts.map +1 -1
  17. package/dist/cli/generate.js +25 -6
  18. package/dist/cli/generate.js.map +1 -1
  19. package/dist/cli/python.d.ts +6 -0
  20. package/dist/cli/python.d.ts.map +1 -0
  21. package/dist/cli/python.js +50 -0
  22. package/dist/cli/python.js.map +1 -0
  23. package/dist/cli.js +14 -2
  24. package/dist/cli.js.map +1 -1
  25. package/dist/client/remoteClient.d.ts.map +1 -1
  26. package/dist/client/remoteClient.js +1 -10
  27. package/dist/client/remoteClient.js.map +1 -1
  28. package/dist/client-runtime/client.d.ts +0 -2
  29. package/dist/client-runtime/client.d.ts.map +1 -1
  30. package/dist/client-runtime/client.js +0 -3
  31. package/dist/client-runtime/client.js.map +1 -1
  32. package/dist/compiler/actor-compiler.d.ts +2 -0
  33. package/dist/compiler/actor-compiler.d.ts.map +1 -1
  34. package/dist/compiler/actor-compiler.js +9 -0
  35. package/dist/compiler/actor-compiler.js.map +1 -1
  36. package/dist/compiler/deployment-build.js +7 -0
  37. package/dist/compiler/deployment-build.js.map +1 -1
  38. package/dist/compiler/features/sandbox.d.ts +9 -0
  39. package/dist/compiler/features/sandbox.d.ts.map +1 -0
  40. package/dist/compiler/features/sandbox.js +50 -0
  41. package/dist/compiler/features/sandbox.js.map +1 -0
  42. package/dist/compiler/types.d.ts +8 -1
  43. package/dist/compiler/types.d.ts.map +1 -1
  44. package/dist/compiler/types.js +1 -0
  45. package/dist/compiler/types.js.map +1 -1
  46. package/dist/compiler/validate-public-contract.d.ts.map +1 -1
  47. package/dist/compiler/validate-public-contract.js +4 -0
  48. package/dist/compiler/validate-public-contract.js.map +1 -1
  49. package/dist/generated/client-runtime.d.ts.map +1 -1
  50. package/dist/generated/client-runtime.js +1 -1
  51. package/dist/generated/client-runtime.js.map +1 -1
  52. package/dist/host/actor-runtime.d.ts.map +1 -1
  53. package/dist/host/actor-runtime.js +2 -3
  54. package/dist/host/actor-runtime.js.map +1 -1
  55. package/dist/index.d.ts +2 -0
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +1 -0
  58. package/dist/index.js.map +1 -1
  59. package/dist/templates/actor/package.json +1 -1
  60. package/dist/templates/ai-chat/README.md +3 -25
  61. package/dist/templates/ai-chat/package.json +1 -1
  62. package/dist/templates/ai-chat/src/Chat.tsx +9 -2
  63. package/dist/templates/ai-chat/src/actors.ts +2 -3
  64. package/dist/templates/ai-chat/src/backend.ts +7 -2
  65. package/dist/templates/chat/README.md +1 -1
  66. package/dist/templates/chat/package.json +1 -1
  67. package/dist/templates/documents/README.md +1 -1
  68. package/dist/templates/documents/package.json +1 -1
  69. package/dist/templates/python/.env.example +1 -0
  70. package/dist/templates/python/README.md +7 -0
  71. package/dist/templates/python/gitignore +6 -0
  72. package/dist/templates/python/package.json +11 -0
  73. package/dist/templates/python/pnpm-workspace.yaml +2 -0
  74. package/dist/templates/python/pyproject.toml +8 -0
  75. package/dist/templates/python/src/actors.py +9 -0
  76. package/dist/wire/public-contract.d.ts +4 -0
  77. package/dist/wire/public-contract.d.ts.map +1 -1
  78. package/package.json +2 -2
  79. package/dist/actor/invocationContext.d.ts +0 -4
  80. package/dist/actor/invocationContext.d.ts.map +0 -1
  81. package/dist/actor/invocationContext.js +0 -10
  82. package/dist/actor/invocationContext.js.map +0 -1
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- <div align="center">
1
+ <div align="left">
2
2
  <a href="https://github.com/TerseAI/durable-actors/blob/main/.github/assets/team-agent.gif">
3
3
  <picture>
4
4
  <source media="(prefers-reduced-motion: reduce)" srcset="https://raw.githubusercontent.com/TerseAI/durable-actors/main/.github/assets/team-agent.png">
@@ -9,7 +9,7 @@
9
9
  <h1>Durable Actors</h1>
10
10
 
11
11
  <p><strong>Durable state for collaborative apps and AI agents.</strong></p>
12
- <p>TypeScript actors. Rust runtime. Built by Terse.</p>
12
+ <p>TypeScript actors. Rust runtime.</p>
13
13
 
14
14
  <p>
15
15
  <a href="https://github.com/TerseAI/durable-actors/stargazers"><img alt="GitHub stars" src="https://img.shields.io/github/stars/TerseAI/durable-actors?style=flat&amp;logo=github&amp;color=f5a623"></a>
@@ -97,17 +97,9 @@ console.log(await counter.increment())
97
97
 
98
98
  For complete sample applications, see [AI Chat](https://github.com/TerseAI/durable-actors/tree/main/examples/ai-chat), [Collaborative documents](https://github.com/TerseAI/durable-actors/tree/main/examples/documents), and [Chatroom](https://github.com/TerseAI/durable-actors/tree/main/examples/chat).
99
99
 
100
- ## Define an Actor
100
+ ## Define an actor
101
101
 
102
- Install `ai` in your actor project:
103
-
104
- ```sh
105
- pnpm install ai
106
- # Or with npm:
107
- npm install ai
108
- ```
109
-
110
- Define and export actors in your actor project’s `src/actors.ts`, the default entrypoint loaded by `durable-actors dev`. For example, a chat history actor:
102
+ Install `ai` in your actor project, then define actors in `src/actors.ts`. This chat history stores completed exchanges in one persisted array:
111
103
 
112
104
  ```ts
113
105
  import type { UIMessage } from "ai"
@@ -120,16 +112,15 @@ export class ChatHistory extends Actor {
120
112
  return this.messages
121
113
  }
122
114
 
123
- async append(message: UIMessage) {
124
- this.messages.push(message)
125
- return this.messages
115
+ async append(...messages: UIMessage[]) {
116
+ this.messages.push(...messages)
126
117
  }
127
118
  }
128
119
  ```
129
120
 
130
- ## Stream from the backend (Express)
121
+ ## Stream from your backend
131
122
 
132
- After adding `ChatHistory`, rerun `npx durable-actors generate` in your application and use its generated client:
123
+ Generate a type-safe client with `npx durable-actors generate`. In your Express backend, load the conversation, stream a reply, and save the prompt and reply together when the stream succeeds:
133
124
 
134
125
  ```ts
135
126
  import { openai } from "@ai-sdk/openai"
@@ -149,7 +140,8 @@ app.post("/api/chat", async (request, response) => {
149
140
  const [message] = await validateUIMessages({ messages: [request.body.messages.at(-1)] })
150
141
  if (message.role !== "user") return response.sendStatus(400)
151
142
  const chat = actors.ChatHistory.get(request.body.id)
152
- const messages = await chat.append(message)
143
+ const messages = [...(await chat.load()), message]
144
+ let failed = false
153
145
  const result = streamText({
154
146
  model: openai("gpt-5-mini"),
155
147
  messages: await convertToModelMessages(messages)
@@ -160,15 +152,23 @@ app.post("/api/chat", async (request, response) => {
160
152
  stream: result.stream,
161
153
  originalMessages: messages,
162
154
  generateMessageId: generateId,
155
+ onError: () => {
156
+ failed = true
157
+ return "Reply failed. Check the API key and try again."
158
+ },
163
159
  onEnd: async ({ responseMessage, outcome }) => {
164
- if (outcome.status === "completed") await chat.append(responseMessage)
160
+ if (!failed && outcome.status === "completed") await chat.append(message, responseMessage)
165
161
  }
166
162
  })
167
163
  })
168
164
  })
169
165
  ```
170
166
 
171
- ## Connect the frontend (React)
167
+ Failed or interrupted attempts are not saved. Each completed exchange is persisted in one actor call.
168
+
169
+ ## Connect the frontend
170
+
171
+ The AI SDK's `useChat` handles streaming and retries:
172
172
 
173
173
  ```tsx
174
174
  import { useChat } from "@ai-sdk/react"
@@ -177,7 +177,7 @@ import type { UIMessage } from "ai"
177
177
  const history: UIMessage[] = await fetch("/api/chat/lobby").then(response => response.json())
178
178
 
179
179
  function Chat() {
180
- const { messages, sendMessage, status } = useChat({ id: "lobby", messages: history })
180
+ const { messages, sendMessage, regenerate, status, error } = useChat({ id: "lobby", messages: history })
181
181
  const busy = status === "submitted" || status === "streaming"
182
182
 
183
183
  return (
@@ -187,14 +187,11 @@ function Chat() {
187
187
  {message.role}: {message.parts.map(part => (part.type === "text" ? part.text : "")).join("")}
188
188
  </p>
189
189
  ))}
190
- <form
191
- action={async form => {
192
- await sendMessage({ text: String(form.get("message")) })
193
- }}
194
- >
190
+ <form action={async form => { await sendMessage({ text: String(form.get("message")) }) }}>
195
191
  <input name="message" aria-label="Message" required disabled={busy} />
196
192
  <button disabled={busy}>Send</button>
197
193
  </form>
194
+ {error && <p role="alert">{error.message} <button onClick={() => regenerate()} disabled={busy}>Retry</button></p>}
198
195
  </>
199
196
  )
200
197
  }
@@ -0,0 +1,40 @@
1
+ import { z } from "zod";
2
+ declare const sandboxRegion: z.ZodEnum<{
3
+ canada: "canada";
4
+ "north-america-east": "north-america-east";
5
+ "north-america-central": "north-america-central";
6
+ "north-america-south": "north-america-south";
7
+ "north-america-west": "north-america-west";
8
+ "europe-west": "europe-west";
9
+ "asia-southeast": "asia-southeast";
10
+ }>;
11
+ declare const sandboxOptionsSchema: z.ZodObject<{
12
+ cpu: z.ZodOptional<z.ZodNumber>;
13
+ memoryMiB: z.ZodOptional<z.ZodNumber>;
14
+ idleTimeoutMs: z.ZodOptional<z.ZodNumber>;
15
+ regions: z.ZodOptional<z.ZodArray<z.ZodEnum<{
16
+ canada: "canada";
17
+ "north-america-east": "north-america-east";
18
+ "north-america-central": "north-america-central";
19
+ "north-america-south": "north-america-south";
20
+ "north-america-west": "north-america-west";
21
+ "europe-west": "europe-west";
22
+ "asia-southeast": "asia-southeast";
23
+ }>>>;
24
+ }, z.core.$strict>;
25
+ type SandboxRegion = z.infer<typeof sandboxRegion>;
26
+ interface SandboxOptions {
27
+ /** CPU cores, from 0.1 to 64 in increments of 0.001. */
28
+ readonly cpu?: number;
29
+ /** Memory request and cap, from 128 to 262144 MiB. */
30
+ readonly memoryMiB?: number;
31
+ /** Inactivity before eviction, from 1 to 86400000 ms. Inherits the server default (normally 10000). */
32
+ readonly idleTimeoutMs?: number;
33
+ /** Allowed compute regions, without priority order. Existing actors remain in their saved region. */
34
+ readonly regions?: readonly SandboxRegion[];
35
+ }
36
+ /** Overrides the deployment's sandbox defaults for this actor class. */
37
+ declare function Sandbox(options: SandboxOptions): (_value: Function, context: Pick<ClassDecoratorContext, "kind">) => void;
38
+ export { Sandbox, sandboxOptionsSchema };
39
+ export type { SandboxOptions, SandboxRegion };
40
+ //# sourceMappingURL=sandbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../src/actor/sandbox.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,QAAA,MAAM,aAAa;;;;;;;;EAQjB,CAAA;AAEF,QAAA,MAAM,oBAAoB;;;;;;;;;;;;;kBAUxB,CAAA;AAEF,KAAK,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAA;AAClD,UAAU,cAAc;IACpB,wDAAwD;IACxD,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;IACrB,sDAAsD;IACtD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,uGAAuG;IACvG,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;IAC/B,qGAAqG;IACrG,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,aAAa,EAAE,CAAA;CAC9C;AAED,wEAAwE;AACxE,iBAAS,OAAO,CAAC,OAAO,EAAE,cAAc,IAE5B,QAAQ,QAAQ,EAAE,SAAS,IAAI,CAAC,qBAAqB,EAAE,MAAM,CAAC,KAAG,IAAI,CAGhF;AAED,OAAO,EAAE,OAAO,EAAE,oBAAoB,EAAE,CAAA;AACxC,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,CAAA"}
@@ -0,0 +1,32 @@
1
+ import { z } from "zod";
2
+ import { ActorDefinitionError } from "../errors.js";
3
+ const sandboxRegion = z.enum([
4
+ "canada",
5
+ "north-america-east",
6
+ "north-america-central",
7
+ "north-america-south",
8
+ "north-america-west",
9
+ "europe-west",
10
+ "asia-southeast"
11
+ ]);
12
+ const sandboxOptionsSchema = z.strictObject({
13
+ cpu: z.number().min(0.1).max(64).multipleOf(0.001).optional(),
14
+ memoryMiB: z.number().int().min(128).max(262144).optional(),
15
+ idleTimeoutMs: z.number().int().min(1).max(86400000).optional(),
16
+ regions: z
17
+ .array(sandboxRegion)
18
+ .min(1)
19
+ .max(sandboxRegion.options.length)
20
+ .refine(regions => new Set(regions).size === regions.length, "regions must be unique")
21
+ .optional()
22
+ });
23
+ /** Overrides the deployment's sandbox defaults for this actor class. */
24
+ function Sandbox(options) {
25
+ sandboxOptionsSchema.parse(options);
26
+ return (_value, context) => {
27
+ if (context.kind !== "class")
28
+ throw new ActorDefinitionError("@Sandbox requires an actor class");
29
+ };
30
+ }
31
+ export { Sandbox, sandboxOptionsSchema };
32
+ //# sourceMappingURL=sandbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../src/actor/sandbox.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAEnD,MAAM,aAAa,GAAG,CAAC,CAAC,IAAI,CAAC;IACzB,QAAQ;IACR,oBAAoB;IACpB,uBAAuB;IACvB,qBAAqB;IACrB,oBAAoB;IACpB,aAAa;IACb,gBAAgB;CACnB,CAAC,CAAA;AAEF,MAAM,oBAAoB,GAAG,CAAC,CAAC,YAAY,CAAC;IACxC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE;IAC7D,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE;IAC3D,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,QAAQ,EAAE;IAC/D,OAAO,EAAE,CAAC;SACL,KAAK,CAAC,aAAa,CAAC;SACpB,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC;SACjC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,MAAM,EAAE,wBAAwB,CAAC;SACrF,QAAQ,EAAE;CAClB,CAAC,CAAA;AAcF,wEAAwE;AACxE,SAAS,OAAO,CAAC,OAAuB;IACpC,oBAAoB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IACnC,OAAO,CAAC,MAAgB,EAAE,OAA4C,EAAQ,EAAE;QAC5E,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO;YAAE,MAAM,IAAI,oBAAoB,CAAC,kCAAkC,CAAC,CAAA;IACpG,CAAC,CAAA;AACL,CAAC;AAED,OAAO,EAAE,OAAO,EAAE,oBAAoB,EAAE,CAAA"}
@@ -1,4 +1,5 @@
1
1
  import type { SocketContract } from "../wire/contract.js";
2
+ import type { SandboxOptions } from "./sandbox.js";
2
3
  declare const ACTOR_ARTIFACT_VERSION = 1;
3
4
  declare enum Persistence {
4
5
  Persisted = "persisted",
@@ -14,6 +15,7 @@ interface ActorFieldSchema {
14
15
  interface ActorSchema {
15
16
  readonly actorName: string;
16
17
  readonly fields: readonly ActorFieldSchema[];
18
+ readonly sandbox?: SandboxOptions;
17
19
  readonly reentrantMethods?: readonly string[];
18
20
  readonly contract?: SocketContract;
19
21
  }
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/actor/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAEzD,QAAA,MAAM,sBAAsB,IAAI,CAAA;AAEhC,aAAK,WAAW;IACZ,SAAS,cAAc;IACvB,SAAS,cAAc;CAC1B;AAED,UAAU,gBAAgB;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAA;IACjC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;IAC1B,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,GAAG,WAAW,CAAA;IAC7C,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAC/B;AAED,UAAU,WAAW;IACjB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,MAAM,EAAE,SAAS,gBAAgB,EAAE,CAAA;IAC5C,QAAQ,CAAC,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC7C,QAAQ,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAA;CACrC;AAED,OAAO,EAAE,sBAAsB,EAAE,WAAW,EAAE,CAAA;AAC9C,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,CAAA"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/actor/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAEzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAElD,QAAA,MAAM,sBAAsB,IAAI,CAAA;AAEhC,aAAK,WAAW;IACZ,SAAS,cAAc;IACvB,SAAS,cAAc;CAC1B;AAED,UAAU,gBAAgB;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAA;IACjC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;IAC1B,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,GAAG,WAAW,CAAA;IAC7C,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAC/B;AAED,UAAU,WAAW;IACjB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,MAAM,EAAE,SAAS,gBAAgB,EAAE,CAAA;IAC5C,QAAQ,CAAC,OAAO,CAAC,EAAE,cAAc,CAAA;IACjC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC7C,QAAQ,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAA;CACrC;AAED,OAAO,EAAE,sBAAsB,EAAE,WAAW,EAAE,CAAA;AAC9C,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/actor/schema.ts"],"names":[],"mappings":"AAEA,MAAM,sBAAsB,GAAG,CAAC,CAAA;AAEhC,IAAK,WAGJ;AAHD,WAAK,WAAW;IACZ,sCAAuB,CAAA;IACvB,sCAAuB,CAAA;AAC3B,CAAC,EAHI,WAAW,KAAX,WAAW,QAGf;AAiBD,OAAO,EAAE,sBAAsB,EAAE,WAAW,EAAE,CAAA"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/actor/schema.ts"],"names":[],"mappings":"AAIA,MAAM,sBAAsB,GAAG,CAAC,CAAA;AAEhC,IAAK,WAGJ;AAHD,WAAK,WAAW;IACZ,sCAAuB,CAAA;IACvB,sCAAuB,CAAA;AAC3B,CAAC,EAHI,WAAW,KAAX,WAAW,QAGf;AAkBD,OAAO,EAAE,sBAAsB,EAAE,WAAW,EAAE,CAAA"}
@@ -1,11 +1,25 @@
1
+ import { watch } from "chokidar";
1
2
  interface ActorSourceWatcherOptions {
2
3
  projectDirectory: string;
3
4
  dataDirectory?: string;
4
5
  }
5
- interface ActorSourceWatcher {
6
+ declare function watchActorSources(options: ActorSourceWatcherOptions, refresh: () => Promise<void>): Promise<ActorSourceWatcher>;
7
+ declare class ActorSourceWatcher {
8
+ private readonly options;
9
+ private readonly refresh;
10
+ private readonly createWatcher;
11
+ private readonly warn;
12
+ private watcher?;
13
+ private timer?;
14
+ private updates;
15
+ private closing?;
16
+ private disabled;
17
+ constructor(options: ActorSourceWatcherOptions, refresh: () => Promise<void>, createWatcher: typeof watch, warn: (message: string) => void);
18
+ start(): Promise<void>;
6
19
  close(): Promise<void>;
20
+ private scheduleRefresh;
21
+ private waitUntilReady;
22
+ private disable;
7
23
  }
8
- declare function watchActorSources(options: ActorSourceWatcherOptions, refresh: () => Promise<void>): Promise<ActorSourceWatcher>;
9
- export { watchActorSources };
10
- export type { ActorSourceWatcher };
24
+ export { ActorSourceWatcher, watchActorSources };
11
25
  //# sourceMappingURL=actor-source-watcher.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"actor-source-watcher.d.ts","sourceRoot":"","sources":["../../src/cli/actor-source-watcher.ts"],"names":[],"mappings":"AAGA,UAAU,yBAAyB;IAC/B,gBAAgB,EAAE,MAAM,CAAA;IACxB,aAAa,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,UAAU,kBAAkB;IACxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACzB;AAED,iBAAe,iBAAiB,CAC5B,OAAO,EAAE,yBAAyB,EAClC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAC7B,OAAO,CAAC,kBAAkB,CAAC,CAkC7B;AAqBD,OAAO,EAAE,iBAAiB,EAAE,CAAA;AAC5B,YAAY,EAAE,kBAAkB,EAAE,CAAA"}
1
+ {"version":3,"file":"actor-source-watcher.d.ts","sourceRoot":"","sources":["../../src/cli/actor-source-watcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,EAAE,MAAM,UAAU,CAAA;AAIhD,UAAU,yBAAyB;IAC/B,gBAAgB,EAAE,MAAM,CAAA;IACxB,aAAa,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,iBAAe,iBAAiB,CAC5B,OAAO,EAAE,yBAAyB,EAClC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAC7B,OAAO,CAAC,kBAAkB,CAAC,CAI7B;AAED,cAAM,kBAAkB;IAQhB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,IAAI;IAVzB,OAAO,CAAC,OAAO,CAAC,CAAW;IAC3B,OAAO,CAAC,KAAK,CAAC,CAA+B;IAC7C,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,OAAO,CAAC,CAAe;IAC/B,OAAO,CAAC,QAAQ,CAAQ;gBAGH,OAAO,EAAE,yBAAyB,EAClC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EAC5B,aAAa,EAAE,OAAO,KAAK,EAC3B,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI;IAG9C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAuBtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAY5B,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,cAAc;YAgBR,OAAO;CAUxB;AA0CD,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,CAAA"}
@@ -1,46 +1,115 @@
1
1
  import { watch } from "chokidar";
2
+ import { existsSync } from "node:fs";
2
3
  import path from "node:path";
3
4
  async function watchActorSources(options, refresh) {
4
- const watcher = watch(options.projectDirectory, {
5
- ignored: (watchedPath, stats) => ignoredActorPath(watchedPath, options) ||
6
- (stats !== undefined && !stats.isDirectory() && (!stats.isFile() || !isActorSource(watchedPath))),
7
- ignoreInitial: true,
8
- followSymlinks: false,
9
- atomic: true,
10
- awaitWriteFinish: { stabilityThreshold: 100, pollInterval: 20 }
11
- });
12
- let timer;
13
- let updates = Promise.resolve();
14
- watcher.on("all", (_event, changedPath) => {
15
- if (!isActorSource(changedPath))
5
+ const watcher = new ActorSourceWatcher(options, refresh, watch, message => console.warn(message));
6
+ await watcher.start();
7
+ return watcher;
8
+ }
9
+ class ActorSourceWatcher {
10
+ options;
11
+ refresh;
12
+ createWatcher;
13
+ warn;
14
+ watcher;
15
+ timer;
16
+ updates = Promise.resolve();
17
+ closing;
18
+ disabled = false;
19
+ constructor(options, refresh, createWatcher, warn) {
20
+ this.options = options;
21
+ this.refresh = refresh;
22
+ this.createWatcher = createWatcher;
23
+ this.warn = warn;
24
+ }
25
+ async start() {
26
+ try {
27
+ this.watcher = this.createWatcher(this.options.projectDirectory, {
28
+ ignored: (watchedPath, stats) => ignoredActorPath(watchedPath, this.options) ||
29
+ (stats?.isDirectory() === true && existsSync(path.join(watchedPath, "pyvenv.cfg"))) ||
30
+ (stats !== undefined && !stats.isDirectory() && (!stats.isFile() || !isActorSource(watchedPath))),
31
+ ignoreInitial: true,
32
+ followSymlinks: false,
33
+ atomic: true,
34
+ awaitWriteFinish: { stabilityThreshold: 100, pollInterval: 20 }
35
+ });
36
+ this.watcher.on("all", (_event, changedPath) => this.scheduleRefresh(changedPath));
37
+ await this.waitUntilReady(this.watcher);
38
+ }
39
+ catch (error) {
40
+ if (isWatchLimit(error))
41
+ await this.disable(error);
42
+ else {
43
+ await this.close();
44
+ throw error;
45
+ }
46
+ }
47
+ }
48
+ async close() {
49
+ this.disabled = true;
50
+ clearTimeout(this.timer);
51
+ if (!this.closing) {
52
+ this.closing = this.watcher?.close() ?? Promise.resolve();
53
+ // Chokidar removes listeners on close, but pending filesystem operations can still emit errors.
54
+ this.watcher?.on("error", () => { });
55
+ }
56
+ await this.closing;
57
+ await this.updates;
58
+ }
59
+ scheduleRefresh(changedPath) {
60
+ if (this.disabled || !isActorSource(changedPath))
16
61
  return;
17
- clearTimeout(timer);
18
- timer = setTimeout(() => {
19
- updates = updates.then(refresh).catch(reportWatchError);
62
+ clearTimeout(this.timer);
63
+ this.timer = setTimeout(() => {
64
+ this.updates = this.updates.then(this.refresh).catch(reportWatchError);
20
65
  }, 75);
21
- });
22
- await new Promise((resolve, reject) => {
23
- watcher.once("ready", resolve);
24
- watcher.once("error", reject);
25
- }).catch(async (error) => {
26
- await watcher.close();
27
- throw error;
28
- });
29
- watcher.on("error", reportWatchError);
30
- return {
31
- async close() {
32
- clearTimeout(timer);
33
- await watcher.close();
34
- await updates;
35
- }
36
- };
66
+ }
67
+ waitUntilReady(watcher) {
68
+ return new Promise((resolve, reject) => {
69
+ let ready = false;
70
+ watcher.once("ready", () => {
71
+ ready = true;
72
+ resolve();
73
+ });
74
+ watcher.on("error", error => {
75
+ if (this.disabled)
76
+ return;
77
+ if (isWatchLimit(error))
78
+ void this.disable(error).then(resolve, reject);
79
+ else if (!ready)
80
+ reject(error);
81
+ else
82
+ reportWatchError(error);
83
+ });
84
+ });
85
+ }
86
+ async disable(error) {
87
+ if (!this.disabled)
88
+ this.warn(`Actor source watcher reached the OS file/watch limit (${error.code}). Automatic reload is disabled; ` +
89
+ "the development server will continue running. Restart it to apply source changes. " +
90
+ "Close other watchers or raise your OS file/watch limit, then restart to restore automatic reload. " +
91
+ "Use --no-watch to disable watching explicitly.");
92
+ await this.close();
93
+ }
94
+ }
95
+ function isWatchLimit(error) {
96
+ return error instanceof Error && "code" in error && ["EMFILE", "ENFILE", "ENOSPC"].includes(String(error.code));
37
97
  }
38
98
  function ignoredActorPath(candidate, options) {
39
99
  const relative = path.relative(options.projectDirectory, candidate);
40
100
  if (!relative || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative))
41
101
  return false;
42
102
  const components = relative.split(path.sep);
43
- if (components.includes(".git") || components.includes("node_modules"))
103
+ if (components.some(component => [
104
+ ".git",
105
+ "node_modules",
106
+ ".venv",
107
+ "venv",
108
+ "__pycache__",
109
+ ".mypy_cache",
110
+ ".pytest_cache",
111
+ ".ruff_cache"
112
+ ].includes(component)))
44
113
  return true;
45
114
  if ([".durable-actors", "generated"].includes(components[0]))
46
115
  return true;
@@ -50,10 +119,11 @@ function ignoredActorPath(candidate, options) {
50
119
  return candidate === state || candidate.startsWith(`${state}${path.sep}`);
51
120
  }
52
121
  function isActorSource(candidate) {
53
- return /\.(?:[cm]?[jt]sx?|json|ya?ml)$/u.test(candidate) || path.basename(candidate) === "bun.lock";
122
+ return (/\.(?:[cm]?[jt]sx?|json|ya?ml|py|toml)$/u.test(candidate) ||
123
+ ["bun.lock", "uv.lock", "requirements.txt"].includes(path.basename(candidate)));
54
124
  }
55
125
  function reportWatchError(error) {
56
126
  console.error(`Actor source update failed: ${error instanceof Error ? error.message : String(error)}`);
57
127
  }
58
- export { watchActorSources };
128
+ export { ActorSourceWatcher, watchActorSources };
59
129
  //# sourceMappingURL=actor-source-watcher.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"actor-source-watcher.js","sourceRoot":"","sources":["../../src/cli/actor-source-watcher.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"actor-source-watcher.js","sourceRoot":"","sources":["../../src/cli/actor-source-watcher.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/cli/dev.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAgC,MAAM,WAAW,CAAA;AAejE,UAAU,UAAU;IAChB,sFAAsF;IACtF,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,OAAO,GAAG,KAAK,CAAA;IACxB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,OAAO,CAAA;CACjB;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAwBzD;AA+BD,iBAAe,MAAM,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAK1D;AA2GD,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,EAAE,CAAA"}
1
+ {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/cli/dev.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAgC,MAAM,WAAW,CAAA;AAgBjE,UAAU,UAAU;IAChB,sFAAsF;IACtF,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,OAAO,GAAG,KAAK,CAAA;IACxB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,OAAO,CAAA;CACjB;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA2BzD;AA+BD,iBAAe,MAAM,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAM1D;AA8GD,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,EAAE,CAAA"}
package/dist/cli/dev.js CHANGED
@@ -9,6 +9,7 @@ import { projectSdkModule } from "../projectSdk.js";
9
9
  import { fetchRuntimeExecutablePath } from "../runtimeInstaller.js";
10
10
  import { watchActorSources } from "./actor-source-watcher.js";
11
11
  import { ControlPlaneClient } from "./control-plane.js";
12
+ import { checkPython, pythonExecutable } from "./python.js";
12
13
  import { runtimeConnection, runtimeEnvironment, startRustRuntime } from "./rust-runtime.js";
13
14
  export function registerDevCommand(program) {
14
15
  program
@@ -25,6 +26,9 @@ No configuration is required. Optional overrides in .env:
25
26
  DURABLE_ACTORS_PROJECT project directory (default: current directory)
26
27
  DURABLE_ACTORS_ENTRYPOINT actor source file, relative to the project (default: src/actors.ts)
27
28
 
29
+ Python projects: durable-actors init my-project --template python
30
+ DURABLE_ACTORS_PYTHON selects an interpreter; otherwise dev uses the project .venv.
31
+
28
32
  Create a project with: durable-actors init my-project`)
29
33
  .action(async (options) => {
30
34
  process.exitCode = await runDev(developmentOptions(options, process.env));
@@ -58,6 +62,8 @@ const developmentEnvironment = z.object({
58
62
  });
59
63
  async function runDev(options) {
60
64
  const project = await developmentProject(options);
65
+ if (options.entrypoint.endsWith(".py"))
66
+ return runDevRuntime(options, project);
61
67
  const local = await projectSdkModule(project, "./cli/dev.js", import.meta.url, options.sdkResolveFrom);
62
68
  if (local !== undefined)
63
69
  return (await import(local)).runDev({ ...options, project });
@@ -85,8 +91,11 @@ async function developmentPathStats(candidate) {
85
91
  });
86
92
  }
87
93
  async function runDevRuntime(options, project) {
94
+ const python = options.entrypoint.endsWith(".py") ? await pythonExecutable(project) : undefined;
95
+ if (python)
96
+ await checkPython(project, [options.entrypoint], python);
88
97
  const executable = await fetchRuntimeExecutablePath();
89
- const runtime = startRustRuntime(executable, [...devArguments(options), "--ready-fd", "3"], runtimeEnvironment(executable), true, true);
98
+ const runtime = startRustRuntime(executable, [...devArguments(options), "--ready-fd", "3"], { ...runtimeEnvironment(executable), ...(python ? { DURABLE_ACTORS_PYTHON: python } : {}) }, true, true);
90
99
  const connection = runtimeConnection(runtime.readiness, runtime.exited);
91
100
  const settings = connection.then(value => configuredSettings(z
92
101
  .object({
@@ -118,6 +127,8 @@ async function runDevRuntime(options, project) {
118
127
  }
119
128
  }
120
129
  async function publishLocalCode(options, project, client) {
130
+ if (options.entrypoint.endsWith(".py"))
131
+ await checkPython(project, [options.entrypoint]);
121
132
  await client.registerDeployment({
122
133
  imageRef: "local",
123
134
  workingDirectory: project,
@@ -1 +1 @@
1
- {"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/cli/dev.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/cli/dev.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/cli/generate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAanC,iBAAS,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAUvD;AA+CD,OAAO,EAAE,uBAAuB,EAAE,CAAA"}
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/cli/generate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAA;AAe3C,iBAAS,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAgBvD;AAyDD,OAAO,EAAE,uBAAuB,EAAE,CAAA"}
@@ -1,13 +1,19 @@
1
+ import { Option } from "commander";
1
2
  import path from "node:path";
2
3
  import { z } from "zod";
3
4
  import { connectionHelp } from "./connection.js";
4
5
  import { createControlPlaneClient } from "./control-plane.js";
6
+ import { compilePythonContract, generatePythonClient } from "./python.js";
5
7
  function registerGenerateCommand(program) {
6
8
  program
7
9
  .command("generate")
8
10
  .argument("[entrypoint]", "actor source file to compile instead of fetching from the server")
9
11
  .description("Generate actor clients from the running server or an explicit source file")
10
- .option("--out-dir <directory>", "generated JavaScript and declaration directory", "generated")
12
+ .option("--out-dir <directory>", "generated client directory", "generated")
13
+ .addOption(new Option("--language <language>", "client language (inferred from the contract)").choices([
14
+ "typescript",
15
+ "python"
16
+ ]))
11
17
  .option("--config <file>", "TypeScript configuration file (local source only)")
12
18
  .option("--control-plane-url <url>", "control-plane origin (overrides DURABLE_ACTORS_CONTROL_PLANE_URL)")
13
19
  .addHelpText("after", connectionHelp)
@@ -15,13 +21,23 @@ function registerGenerateCommand(program) {
15
21
  }
16
22
  async function generate(entrypoint, options) {
17
23
  validateOptions(entrypoint, options);
18
- const { generateClient } = await import("../compiler/generators/client-generator.js");
19
- const contract = entrypoint
24
+ const source = entrypoint
20
25
  ? await localContract(entrypoint, options.config)
21
26
  : await remoteContract(options.controlPlaneUrl);
22
27
  const directory = path.resolve(options.outDir);
28
+ const summary = z.object({ actors: z.array(z.unknown()), typescript: z.unknown().optional() }).parse(source);
29
+ const language = options.language ?? (summary.typescript === undefined ? "python" : "typescript");
30
+ if (language === "python")
31
+ await generatePythonClient(source, directory);
32
+ else
33
+ await generateTypeScriptClient(source, directory);
34
+ console.log(`Generated ${summary.actors.length} actor contract(s) in ${directory}.`);
35
+ }
36
+ async function generateTypeScriptClient(source, directory) {
37
+ const { generateClient } = await import("../compiler/generators/client-generator.js");
38
+ const { parsePublicContract } = await import("../compiler/validate-public-contract.js");
39
+ const contract = parsePublicContract(source);
23
40
  await generateClient(contract, directory);
24
- console.log(`Generated ${contract.actors.length} actor contract(s) in ${directory}.`);
25
41
  const dependencies = Object.entries(contract.typescript.dependencies);
26
42
  if (dependencies.length)
27
43
  console.log(`Type dependencies: ${dependencies.map(([name, version]) => `${name}@${version}`).join(", ")}. Install compatible versions in the calling project.`);
@@ -29,21 +45,24 @@ async function generate(entrypoint, options) {
29
45
  function validateOptions(entrypoint, options) {
30
46
  if (entrypoint && options.controlPlaneUrl !== undefined)
31
47
  throw new Error("--control-plane-url cannot be combined with a source entrypoint.");
48
+ if (options.config && entrypoint?.endsWith(".py"))
49
+ throw new Error("--config applies to TypeScript source only.");
32
50
  if (options.config && !entrypoint)
33
51
  throw new Error("--config requires a source entrypoint.");
34
52
  }
35
53
  async function localContract(entrypoint, configFile) {
54
+ if (entrypoint.endsWith(".py"))
55
+ return compilePythonContract(entrypoint);
36
56
  const { ActorCompiler } = await import("../compiler/actor-compiler.js");
37
57
  return new ActorCompiler().compileContract(entrypoint, { configFile });
38
58
  }
39
59
  async function remoteContract(controlPlaneUrl) {
40
- const { parsePublicContract } = await import("../compiler/validate-public-contract.js");
41
60
  const client = createControlPlaneClient({
42
61
  ...process.env,
43
62
  DURABLE_ACTORS_CONTROL_PLANE_URL: controlPlaneUrl ?? process.env.DURABLE_ACTORS_CONTROL_PLANE_URL
44
63
  }, fetch);
45
64
  const publication = publicationSchema.parse(await client.getContract());
46
- return parsePublicContract(publication.contract);
65
+ return publication.contract;
47
66
  }
48
67
  const publicationSchema = z.strictObject({
49
68
  contractHash: z.string().regex(/^sha256:[a-f0-9]{64}$/u),