@renderinc/sdk 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/dist/experimental/object/api.d.ts +2 -1
  2. package/dist/experimental/object/api.d.ts.map +1 -1
  3. package/dist/experimental/object/api.js +20 -3
  4. package/dist/experimental/object/client.d.ts +3 -1
  5. package/dist/experimental/object/client.d.ts.map +1 -1
  6. package/dist/experimental/object/client.js +47 -6
  7. package/dist/experimental/object/index.d.ts +1 -1
  8. package/dist/experimental/object/index.d.ts.map +1 -1
  9. package/dist/experimental/object/types.d.ts +17 -0
  10. package/dist/experimental/object/types.d.ts.map +1 -1
  11. package/dist/generated/schema.d.ts +167 -28
  12. package/dist/generated/schema.d.ts.map +1 -1
  13. package/dist/workflows/uds.d.ts.map +1 -1
  14. package/dist/workflows/uds.js +3 -2
  15. package/package.json +4 -1
  16. package/CHANGELOG.md +0 -33
  17. package/biome.json +0 -84
  18. package/examples/client/main.ts +0 -42
  19. package/examples/client/package-lock.json +0 -601
  20. package/examples/client/package.json +0 -16
  21. package/examples/client/tsconfig.json +0 -17
  22. package/examples/task/main.ts +0 -90
  23. package/examples/task/package-lock.json +0 -584
  24. package/examples/task/package.json +0 -16
  25. package/examples/task/tsconfig.json +0 -17
  26. package/src/errors.test.ts +0 -75
  27. package/src/errors.ts +0 -73
  28. package/src/experimental/experimental.ts +0 -56
  29. package/src/experimental/index.ts +0 -24
  30. package/src/experimental/object/api.ts +0 -91
  31. package/src/experimental/object/client.test.ts +0 -138
  32. package/src/experimental/object/client.ts +0 -317
  33. package/src/experimental/object/index.ts +0 -22
  34. package/src/experimental/object/types.test.ts +0 -87
  35. package/src/experimental/object/types.ts +0 -131
  36. package/src/generated/schema.ts +0 -12937
  37. package/src/index.ts +0 -7
  38. package/src/render.ts +0 -35
  39. package/src/utils/create-api-client.ts +0 -13
  40. package/src/utils/get-base-url.test.ts +0 -58
  41. package/src/utils/get-base-url.ts +0 -16
  42. package/src/version.ts +0 -37
  43. package/src/workflows/client/client.test.ts +0 -68
  44. package/src/workflows/client/client.ts +0 -142
  45. package/src/workflows/client/create-client.ts +0 -17
  46. package/src/workflows/client/index.ts +0 -3
  47. package/src/workflows/client/sse.ts +0 -95
  48. package/src/workflows/client/types.ts +0 -56
  49. package/src/workflows/executor.ts +0 -124
  50. package/src/workflows/index.ts +0 -7
  51. package/src/workflows/registry.test.ts +0 -76
  52. package/src/workflows/registry.ts +0 -88
  53. package/src/workflows/runner.ts +0 -38
  54. package/src/workflows/schema.ts +0 -348
  55. package/src/workflows/task.ts +0 -117
  56. package/src/workflows/types.test.ts +0 -52
  57. package/src/workflows/types.ts +0 -89
  58. package/src/workflows/uds.ts +0 -139
  59. package/test-types.ts +0 -14
  60. package/tsconfig.build.json +0 -4
  61. package/tsconfig.json +0 -23
  62. package/vitest.config.ts +0 -8
package/src/index.ts DELETED
@@ -1,7 +0,0 @@
1
- // Main Render SDK class
2
-
3
- export * from "./errors.js";
4
- // Experimental features - types only (instances accessed via render.experimental)
5
- export type { ExperimentalClient } from "./experimental/index.js";
6
- export { Render } from "./render.js";
7
- export { getUserAgent, VERSION } from "./version.js";
package/src/render.ts DELETED
@@ -1,35 +0,0 @@
1
- import type { Client } from "openapi-fetch";
2
- import { RenderError } from "./errors.js";
3
- import { ExperimentalClient } from "./experimental/experimental.js";
4
- import type { paths } from "./generated/schema.js";
5
- import { createApiClient } from "./utils/create-api-client.js";
6
- import { getBaseUrl } from "./utils/get-base-url.js";
7
- import { WorkflowsClient } from "./workflows/client/index.js";
8
- import type { ClientOptions } from "./workflows/client/types.js";
9
-
10
- /**
11
- * Main Render SDK class providing access to all Render products
12
- */
13
- export class Render {
14
- public readonly workflows: WorkflowsClient;
15
- public readonly experimental: ExperimentalClient;
16
-
17
- private readonly apiClient: Client<paths>;
18
-
19
- /**
20
- * Create a new Render SDK instance
21
- * @param options Client configuration options
22
- */
23
- constructor(options?: ClientOptions) {
24
- const token = options?.token || process.env.RENDER_API_KEY;
25
- if (!token) {
26
- throw new RenderError(
27
- "API token is required. Provide it via options.token or RENDER_API_KEY environment variable.",
28
- );
29
- }
30
- const baseUrl = getBaseUrl(options);
31
- this.apiClient = createApiClient(baseUrl, token);
32
- this.workflows = new WorkflowsClient(this.apiClient, baseUrl, token);
33
- this.experimental = new ExperimentalClient(this.apiClient);
34
- }
35
- }
@@ -1,13 +0,0 @@
1
- import createClient, { type Client } from "openapi-fetch";
2
- import type { paths } from "../generated/schema";
3
- import { getUserAgent } from "../version.js";
4
-
5
- export function createApiClient(baseUrl: string, token: string): Client<paths> {
6
- return createClient<paths>({
7
- baseUrl: `${baseUrl}/v1`,
8
- headers: {
9
- Authorization: `Bearer ${token}`,
10
- "User-Agent": getUserAgent(),
11
- },
12
- });
13
- }
@@ -1,58 +0,0 @@
1
- import { getBaseUrl } from "./get-base-url.js";
2
-
3
- describe("getBaseUrl", () => {
4
- const originalEnv = process.env;
5
-
6
- beforeEach(() => {
7
- process.env = { ...originalEnv };
8
- process.env.RENDER_USE_LOCAL_DEV = undefined;
9
- process.env.RENDER_LOCAL_DEV_URL = undefined;
10
- });
11
-
12
- afterEach(() => {
13
- process.env = originalEnv;
14
- });
15
-
16
- it("returns production URL by default", () => {
17
- expect(getBaseUrl()).toBe("https://api.render.com");
18
- });
19
-
20
- it("returns custom baseUrl when provided", () => {
21
- expect(getBaseUrl({ baseUrl: "https://custom.api.com" })).toBe("https://custom.api.com");
22
- });
23
-
24
- it("returns local dev URL when useLocalDev is true", () => {
25
- expect(getBaseUrl({ useLocalDev: true })).toBe("http://localhost:8120");
26
- });
27
-
28
- it("respects custom localDevUrl", () => {
29
- expect(getBaseUrl({ useLocalDev: true, localDevUrl: "http://localhost:9000" })).toBe(
30
- "http://localhost:9000",
31
- );
32
- });
33
-
34
- it("respects RENDER_USE_LOCAL_DEV env var", () => {
35
- process.env.RENDER_USE_LOCAL_DEV = "true";
36
- expect(getBaseUrl()).toBe("http://localhost:8120");
37
- });
38
-
39
- it("respects RENDER_LOCAL_DEV_URL env var", () => {
40
- process.env.RENDER_USE_LOCAL_DEV = "true";
41
- process.env.RENDER_LOCAL_DEV_URL = "http://localhost:7777";
42
- expect(getBaseUrl()).toBe("http://localhost:7777");
43
- });
44
-
45
- it("option overrides env var for localDevUrl", () => {
46
- process.env.RENDER_USE_LOCAL_DEV = "true";
47
- process.env.RENDER_LOCAL_DEV_URL = "http://localhost:7777";
48
- expect(getBaseUrl({ useLocalDev: true, localDevUrl: "http://localhost:9999" })).toBe(
49
- "http://localhost:9999",
50
- );
51
- });
52
-
53
- it("ignores baseUrl option when in local dev mode", () => {
54
- expect(getBaseUrl({ useLocalDev: true, baseUrl: "https://custom.api.com" })).toBe(
55
- "http://localhost:8120",
56
- );
57
- });
58
- });
@@ -1,16 +0,0 @@
1
- interface GetBaseUrlProps {
2
- useLocalDev?: boolean;
3
- localDevUrl?: string;
4
- baseUrl?: string;
5
- }
6
- export function getBaseUrl(options?: GetBaseUrlProps): string {
7
- let baseUrl: string;
8
- const useLocalDev = options?.useLocalDev ?? process.env.RENDER_USE_LOCAL_DEV === "true";
9
-
10
- if (useLocalDev) {
11
- baseUrl = options?.localDevUrl || process.env.RENDER_LOCAL_DEV_URL || "http://localhost:8120";
12
- } else {
13
- baseUrl = options?.baseUrl || "https://api.render.com";
14
- }
15
- return baseUrl;
16
- }
package/src/version.ts DELETED
@@ -1,37 +0,0 @@
1
- /**
2
- * Version information for the Render SDK.
3
- */
4
-
5
- import { readFileSync } from "node:fs";
6
- import { join } from "node:path";
7
-
8
- /**
9
- * Get the SDK version from package.json.
10
- * __dirname points to dist/ after compilation, package.json is one level up.
11
- */
12
- function getVersion(): string {
13
- try {
14
- const pkgPath = join(__dirname, "..", "package.json");
15
- const pkg = JSON.parse(readFileSync(pkgPath, "utf-8")) as { version?: string };
16
- return pkg.version ?? "unknown";
17
- } catch {
18
- return "unknown";
19
- }
20
- }
21
-
22
- /** The current version of the Render TypeScript SDK. */
23
- export const VERSION = getVersion();
24
-
25
- /**
26
- * Get the User-Agent string for the SDK.
27
- *
28
- * Returns a string like:
29
- * render-sdk-typescript/0.1.0 (node/20.10.0; darwin/arm64)
30
- */
31
- export function getUserAgent(): string {
32
- const nodeVersion = process.version.replace("v", "");
33
- const platform = process.platform;
34
- const arch = process.arch;
35
-
36
- return `render-sdk-typescript/${VERSION} (node/${nodeVersion}; ${platform}/${arch})`;
37
- }
@@ -1,68 +0,0 @@
1
- import type { Client } from "openapi-fetch";
2
- import { AbortError, ClientError, ServerError } from "../../errors.js";
3
- import type { paths } from "../../generated/schema.js";
4
- import { WorkflowsClient } from "./client.js";
5
-
6
- describe("WorkflowsClient", () => {
7
- describe("runTask", () => {
8
- it("throws AbortError if signal already aborted", async () => {
9
- // No API calls occur; client throws before using the client
10
- const mockApiClient = {} as unknown as Client<paths>;
11
- const client = new WorkflowsClient(mockApiClient, "http://test", "token");
12
-
13
- const controller = new AbortController();
14
- controller.abort();
15
- await expect(client.runTask("task-1", ["data"], controller.signal)).rejects.toBeInstanceOf(
16
- AbortError,
17
- );
18
- });
19
- });
20
-
21
- describe("handleApiError (via getTaskRun)", () => {
22
- it("throws ServerError for 5xx status", async () => {
23
- const mockApiClient = {
24
- GET: vi.fn().mockResolvedValue({
25
- error: { message: "Internal error" },
26
- response: { status: 500 },
27
- }),
28
- } as unknown as Client<paths>;
29
-
30
- const client = new WorkflowsClient(mockApiClient, "http://test", "token");
31
-
32
- await expect(client.getTaskRun("run-123")).rejects.toBeInstanceOf(ServerError);
33
- await expect(client.getTaskRun("run-123")).rejects.toMatchObject({
34
- statusCode: 500,
35
- });
36
- });
37
-
38
- it("throws ClientError for 4xx status", async () => {
39
- const mockApiClient = {
40
- GET: vi.fn().mockResolvedValue({
41
- error: { message: "Not found" },
42
- response: { status: 404 },
43
- }),
44
- } as unknown as Client<paths>;
45
-
46
- const client = new WorkflowsClient(mockApiClient, "http://test", "token");
47
-
48
- await expect(client.getTaskRun("run-123")).rejects.toBeInstanceOf(ClientError);
49
- await expect(client.getTaskRun("run-123")).rejects.toMatchObject({
50
- statusCode: 404,
51
- });
52
- });
53
- });
54
-
55
- describe("listTaskRuns", () => {
56
- it("throws ClientError for 400 status", async () => {
57
- const mockApiClient = {
58
- GET: vi.fn().mockResolvedValue({
59
- error: { message: "Bad request" },
60
- response: { status: 400 },
61
- }),
62
- } as unknown as Client<paths>;
63
-
64
- const client = new WorkflowsClient(mockApiClient, "http://test", "token");
65
- await expect(client.listTaskRuns({ taskId: ["task-1"] })).rejects.toBeInstanceOf(ClientError);
66
- });
67
- });
68
- });
@@ -1,142 +0,0 @@
1
- import type { Client as ApiClient } from "openapi-fetch";
2
- import { AbortError, ClientError, ServerError } from "../../errors.js";
3
- import type { paths } from "../../generated/schema.js";
4
- import { SSEClient } from "./sse.js";
5
- import type {
6
- ListTaskRunsParams,
7
- TaskData,
8
- TaskIdentifier,
9
- TaskRun,
10
- TaskRunDetails,
11
- } from "./types.js";
12
-
13
- /**
14
- * Helper function to handle API errors and throw appropriate custom error types
15
- */
16
- function handleApiError(error: any, response: Response, context: string): never {
17
- const statusCode = response.status;
18
- const errorMessage = `${context}: ${error}`;
19
-
20
- if (statusCode >= 500) {
21
- throw new ServerError(errorMessage, statusCode, error);
22
- } else if (statusCode >= 400) {
23
- throw new ClientError(errorMessage, statusCode, error);
24
- }
25
- throw new ClientError(errorMessage, statusCode, error);
26
- }
27
-
28
- /**
29
- * Main Render SDK Client
30
- */
31
- export class WorkflowsClient {
32
- private readonly sse: SSEClient;
33
- private readonly apiClient: ApiClient<paths>;
34
-
35
- /**
36
- * Create a new Render SDK client
37
- * @param options Client configuration options
38
- * @returns New client instance
39
- */
40
- constructor(apiClient: ApiClient<paths>, baseUrl: string, token: string) {
41
- this.sse = new SSEClient(baseUrl, token);
42
- this.apiClient = apiClient;
43
- }
44
-
45
- async runTask(
46
- taskIdentifier: TaskIdentifier,
47
- inputData: TaskData,
48
- signal?: AbortSignal,
49
- ): Promise<TaskRunDetails> {
50
- if (signal?.aborted) {
51
- throw new AbortError();
52
- }
53
-
54
- let taskRunId: string | null = null;
55
- const abortHandler = async () => {
56
- if (taskRunId) {
57
- await this.cancelTaskRun(taskRunId);
58
- throw new AbortError();
59
- }
60
- };
61
-
62
- try {
63
- // Register abort handler before making the request
64
- signal?.addEventListener("abort", abortHandler);
65
-
66
- const { data, error, response } = await this.apiClient.POST("/task-runs", {
67
- body: {
68
- task: taskIdentifier,
69
- input: inputData,
70
- },
71
- signal,
72
- });
73
-
74
- if (error) {
75
- handleApiError(error, response, "Failed to run task");
76
- }
77
-
78
- taskRunId = data.id;
79
-
80
- // Pass signal to waitForTask so it can handle cancellation during wait
81
- return await this.waitForTask(data.id, signal);
82
- } catch (err) {
83
- // Handle DOMException AbortError from fetch
84
- if (err instanceof DOMException && err.name === "AbortError") {
85
- throw new AbortError();
86
- }
87
- throw err;
88
- } finally {
89
- signal?.removeEventListener("abort", abortHandler);
90
- }
91
- }
92
-
93
- private async waitForTask(taskRunId: string, signal?: AbortSignal): Promise<TaskRunDetails> {
94
- return this.sse.waitOnTaskRun(taskRunId, signal);
95
- }
96
-
97
- /**
98
- * Get task run details by ID
99
- * @param taskRunId Task run ID
100
- * @returns Task run details
101
- */
102
-
103
- async getTaskRun(taskRunId: string): Promise<TaskRunDetails> {
104
- const { data, error, response } = await this.apiClient.GET("/task-runs/{taskRunId}", {
105
- params: { path: { taskRunId } },
106
- });
107
- if (error) {
108
- handleApiError(error, response, "Failed to get task run");
109
- }
110
- return data;
111
- }
112
-
113
- /**
114
- * Cancel a task run
115
- * @param taskRunId Task run ID
116
- */
117
-
118
- private async cancelTaskRun(taskRunId: string): Promise<void> {
119
- const { error, response } = await this.apiClient.DELETE("/task-runs/{taskRunId}", {
120
- params: { path: { taskRunId } },
121
- });
122
- if (error) {
123
- handleApiError(error, response, "Failed to cancel task run");
124
- }
125
- }
126
-
127
- /**
128
- * List task runs with optional filters
129
- * @param params Filter parameters
130
- * @returns List of task runs
131
- */
132
-
133
- async listTaskRuns(params: ListTaskRunsParams): Promise<TaskRun[]> {
134
- const { data, error, response } = await this.apiClient.GET("/task-runs", {
135
- params: { query: params },
136
- });
137
- if (error) {
138
- handleApiError(error, response, "Failed to list task runs");
139
- }
140
- return data;
141
- }
142
- }
@@ -1,17 +0,0 @@
1
- import { RenderError } from "../../errors";
2
- import { createApiClient } from "../../utils/create-api-client";
3
- import { getBaseUrl } from "../../utils/get-base-url";
4
- import { WorkflowsClient } from "./client";
5
- import type { ClientOptions } from "./types";
6
-
7
- export function createWorkflowsClient(options?: ClientOptions): WorkflowsClient {
8
- const token = options?.token || process.env.RENDER_API_KEY;
9
- if (!token) {
10
- throw new RenderError(
11
- "API token is required. Provide it via options.token or RENDER_API_KEY environment variable.",
12
- );
13
- }
14
- const baseUrl = getBaseUrl(options);
15
- const apiClient = createApiClient(baseUrl, token);
16
- return new WorkflowsClient(apiClient, baseUrl, token);
17
- }
@@ -1,3 +0,0 @@
1
- export { WorkflowsClient } from "./client.js";
2
- export { createWorkflowsClient } from "./create-client.js";
3
- export * from "./types.js";
@@ -1,95 +0,0 @@
1
- import { EventSource } from "eventsource";
2
- import { AbortError } from "../../errors.js";
3
- import { getUserAgent } from "../../version.js";
4
- import type { TaskRunDetails } from "./types.js";
5
-
6
- /**
7
- * Task event types emitted by the SSE stream
8
- */
9
- export enum TaskEventType {
10
- COMPLETED = "task.completed",
11
- FAILED = "task.failed",
12
- RUNNING = "task.running",
13
- PENDING = "task.pending",
14
- }
15
-
16
- /**
17
- * SSE Client for streaming task run events
18
- */
19
- export class SSEClient {
20
- constructor(
21
- private readonly baseUrl: string,
22
- private readonly token: string,
23
- ) {}
24
-
25
- async waitOnTaskRun(taskRunId: string, signal?: AbortSignal): Promise<TaskRunDetails> {
26
- return new Promise((resolve, reject) => {
27
- let eventSource: EventSource | null = null;
28
-
29
- const abortHandler = () => {
30
- cleanup();
31
- reject(new AbortError());
32
- };
33
-
34
- const cleanup = () => {
35
- if (eventSource) {
36
- eventSource.removeEventListener(TaskEventType.COMPLETED, eventHandler);
37
- eventSource.removeEventListener(TaskEventType.FAILED, eventHandler);
38
- eventSource.removeEventListener("error", errorHandler);
39
- eventSource.close();
40
- eventSource = null;
41
- }
42
- signal?.removeEventListener("abort", abortHandler);
43
- };
44
-
45
- const eventHandler = (event: MessageEvent) => {
46
- try {
47
- const details = JSON.parse(event.data) as TaskRunDetails;
48
- cleanup();
49
- resolve(details);
50
- } catch (e) {
51
- cleanup();
52
- reject(new Error(`Failed to parse task run details: ${e}`));
53
- }
54
- };
55
-
56
- const errorHandler = (error: any) => {
57
- cleanup();
58
- reject(new Error(`SSE connection error: ${error.message || "Unknown error"}`));
59
- };
60
-
61
- // Check if already aborted
62
- if (signal?.aborted) {
63
- reject(new AbortError());
64
- return;
65
- }
66
-
67
- // Listen for abort signal
68
- signal?.addEventListener("abort", abortHandler);
69
-
70
- try {
71
- const url = new URL("/v1/task-runs/events", this.baseUrl);
72
- url.searchParams.append("taskRunIds", taskRunId);
73
-
74
- eventSource = new EventSource(url.toString(), {
75
- fetch: (input, init) =>
76
- fetch(input, {
77
- ...init,
78
- headers: {
79
- ...init?.headers,
80
- Authorization: `Bearer ${this.token}`,
81
- "User-Agent": getUserAgent(),
82
- },
83
- }),
84
- });
85
-
86
- eventSource.addEventListener(TaskEventType.COMPLETED, eventHandler);
87
- eventSource.addEventListener(TaskEventType.FAILED, eventHandler);
88
- eventSource.addEventListener("error", errorHandler);
89
- } catch (e) {
90
- cleanup();
91
- reject(e);
92
- }
93
- });
94
- }
95
- }
@@ -1,56 +0,0 @@
1
- import type { components, paths } from "../../generated/schema";
2
-
3
- /**
4
- * Task identifier in the format "workflow-slug/task-name"
5
- */
6
- export type TaskIdentifier = string;
7
-
8
- /**
9
- * Task input data as an array of parameters
10
- */
11
- export type TaskData = Array<any>;
12
-
13
- /**
14
- * Task run status enum
15
- */
16
- export enum TaskRunStatus {
17
- PENDING = "pending",
18
- RUNNING = "running",
19
- COMPLETED = "completed",
20
- FAILED = "failed",
21
- }
22
-
23
- /**
24
- * Basic task run information
25
- */
26
-
27
- export type TaskRun = components["schemas"]["TaskRun"];
28
-
29
- /**
30
- * Detailed task run information including results and errors
31
- */
32
-
33
- export type TaskRunDetails = components["schemas"]["TaskRunDetails"];
34
-
35
- /**
36
- * Parameters for listing task runs
37
- */
38
- export type ListTaskRunsParams = paths["/task-runs"]["get"]["parameters"]["query"];
39
-
40
- /**
41
- * Request body for running a task
42
- */
43
- export interface RunTaskRequest {
44
- task: TaskIdentifier;
45
- input: TaskData;
46
- }
47
-
48
- /**
49
- * Client configuration options
50
- */
51
- export interface ClientOptions {
52
- token?: string;
53
- baseUrl?: string;
54
- useLocalDev?: boolean;
55
- localDevUrl?: string;
56
- }
@@ -1,124 +0,0 @@
1
- import { RenderError } from "../errors.js";
2
- import { TaskRegistry } from "./registry.js";
3
- import { setCurrentContext } from "./task.js";
4
- import type { TaskContext, TaskFunction, TaskResult } from "./types.js";
5
- import { UDSClient } from "./uds.js";
6
-
7
- /**
8
- * Implementation of TaskResult
9
- */
10
- class TaskResultImpl<T> implements TaskResult<T> {
11
- constructor(
12
- private readonly subtaskId: string,
13
- private readonly udsClient: UDSClient,
14
- ) {}
15
-
16
- async get(): Promise<T> {
17
- // Poll for subtask result
18
- const pollInterval = 500; // half a second
19
-
20
- while (true) {
21
- const result = await this.udsClient.getSubtaskResult(this.subtaskId);
22
-
23
- if (!result.still_running && result.complete) {
24
- if (result.complete.output) {
25
- const json = Buffer.from(result.complete.output, "base64").toString();
26
- const decoded = JSON.parse(json);
27
- return decoded[0];
28
- }
29
- return undefined as T;
30
- } else if (!result.still_running && result.error) {
31
- throw new RenderError(`Subtask failed: ${result.error}`);
32
- }
33
-
34
- // Still pending, wait and retry
35
- await new Promise((resolve) => setTimeout(resolve, pollInterval));
36
- }
37
- }
38
- }
39
-
40
- /**
41
- * Implementation of TaskContext
42
- */
43
- class TaskContextImpl implements TaskContext {
44
- constructor(private readonly udsClient: UDSClient) {}
45
-
46
- executeTask<TArgs extends any[], TResult>(
47
- _task: TaskFunction<TArgs, TResult>,
48
- taskName: string,
49
- ...args: TArgs
50
- ): TaskResult<TResult> {
51
- const registry = TaskRegistry.getInstance();
52
-
53
- if (!registry.has(taskName)) {
54
- throw new RenderError(`Task '${taskName}' is not registered`);
55
- }
56
-
57
- // Execute subtask via UDS
58
- const subtaskIdPromise = this.udsClient.runSubtask(taskName, args);
59
-
60
- // Return a TaskResult that will poll for completion
61
- return {
62
- get: async () => {
63
- const subtaskId = await subtaskIdPromise;
64
- const result = new TaskResultImpl<TResult>(subtaskId, this.udsClient);
65
- return result.get();
66
- },
67
- };
68
- }
69
- }
70
-
71
- /**
72
- * Task executor that runs tasks via Unix socket communication
73
- */
74
- export class TaskExecutor {
75
- private readonly udsClient: UDSClient;
76
- private readonly context: TaskContext;
77
-
78
- constructor(socketPath: string) {
79
- this.udsClient = new UDSClient(socketPath);
80
- this.context = new TaskContextImpl(this.udsClient);
81
- }
82
-
83
- /**
84
- * Execute a single task
85
- */
86
- async executeTask(): Promise<void> {
87
- const registry = TaskRegistry.getInstance();
88
-
89
- try {
90
- // Get task input
91
- const input = await this.udsClient.getInput();
92
- const taskName = input.task_name;
93
- const inputData = JSON.parse(Buffer.from(input.input, "base64").toString());
94
-
95
- // Get task from registry
96
- const taskMetadata = registry.get(taskName);
97
- if (!taskMetadata) {
98
- throw new RenderError(`Task '${taskName}' not found in registry`);
99
- }
100
-
101
- // Execute task with context
102
- const result = await setCurrentContext(this.context, async () => {
103
- return await taskMetadata.func(...inputData);
104
- });
105
-
106
- // Send result
107
- await this.udsClient.sendCallback(result);
108
- } catch (error) {
109
- // Send error
110
- const errorMessage = error instanceof Error ? error.message : String(error);
111
- await this.udsClient.sendCallback(undefined, errorMessage);
112
- throw error;
113
- }
114
- }
115
-
116
- /**
117
- * Register all tasks with the workflow system
118
- */
119
- async registerTasks(): Promise<void> {
120
- const registry = TaskRegistry.getInstance();
121
- const tasks = registry.getAllTasks();
122
- await this.udsClient.registerTasks(tasks);
123
- }
124
- }
@@ -1,7 +0,0 @@
1
- // Export client API
2
- export * from "./client/index.js";
3
- export { TaskExecutor } from "./executor.js";
4
- export { TaskRegistry } from "./registry.js";
5
- export { run, startTaskServer } from "./runner.js";
6
- export { getCurrentContext, setCurrentContext, task } from "./task.js";
7
- export * from "./types.js";