@prompteryx/sdk 0.4.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.
@@ -0,0 +1,62 @@
1
+ /**
2
+ * ⚠️ NOT SHIPPED in @prompteryx/sdk 0.4.0 (2026-09-03) — not exported from
3
+ * src/index.ts. The /api/v1/custom-nodes* routes this resource targets do
4
+ * not exist on the live API (every call 404s). Verified against the 31
5
+ * live v1 routes in docs/API_SDK_DEVELOPER_PLAN_GOLIVE_AUDIT.md. Kept as
6
+ * source for a future release; do not re-export without re-verifying.
7
+ *
8
+ * `px.customNodes.*` — user-built reusable nodes.
9
+ *
10
+ * Custom Nodes are HTTP-call wrappers, expression transforms, or
11
+ * composed sub-workflows the user creates in the platform. They
12
+ * become first-class node types available in Visual Studio AND via
13
+ * the SDK as direct one-shot invocations.
14
+ *
15
+ * Use cases:
16
+ * - Call a private API your team owns with a stored credential
17
+ * reference (you wire up the auth once, every workflow uses it).
18
+ * - Reusable data transforms shared across workflows.
19
+ * - Sub-workflows you compose into bigger ones.
20
+ *
21
+ * Billing: a custom node run counts as 1 workflow execution (it
22
+ * runs as a single-node workflow internally). Credentials referenced
23
+ * by the node are scoped to the SAME user / project as the node;
24
+ * cross-user credential access is forbidden by the runtime.
25
+ */
26
+
27
+ import type { HttpClient } from '../client'
28
+ import type { CustomNodeSummary, ExecutionRecord } from '../types'
29
+
30
+ export class CustomNodesResource {
31
+ constructor(private readonly http: HttpClient) {}
32
+
33
+ async list(): Promise<CustomNodeSummary[]> {
34
+ const res = await this.http.request<{ nodes: CustomNodeSummary[] }>(
35
+ '/api/v1/custom-nodes',
36
+ )
37
+ return res.nodes ?? []
38
+ }
39
+
40
+ async get(nodeId: string): Promise<CustomNodeSummary> {
41
+ return this.http.request(`/api/v1/custom-nodes/${encodeURIComponent(nodeId)}`)
42
+ }
43
+
44
+ /**
45
+ * Execute a custom node with the given input. Returns the node's
46
+ * structured output. Same SSRF protections + credential isolation
47
+ * as Visual Studio.
48
+ *
49
+ * ```ts
50
+ * const result = await px.customNodes.run('node_abc', {
51
+ * userId: 'u_123',
52
+ * action: 'lookup',
53
+ * })
54
+ * ```
55
+ */
56
+ async run(nodeId: string, input: Record<string, unknown> = {}): Promise<{ output: unknown; execution: ExecutionRecord }> {
57
+ return this.http.request(`/api/v1/custom-nodes/${encodeURIComponent(nodeId)}/execute`, {
58
+ method: 'POST',
59
+ body: { input },
60
+ })
61
+ }
62
+ }
@@ -0,0 +1,84 @@
1
+ /**
2
+ * `px.executions.*` — status, logs (polled OR streamed), wait.
3
+ */
4
+
5
+ import type { HttpClient } from '../client'
6
+ import { TimeoutError } from '../errors'
7
+ import type { ExecutionLogEvent, ExecutionRecord, ExecutionStatus } from '../types'
8
+
9
+ const TERMINAL_STATES: ExecutionStatus[] = [
10
+ 'completed',
11
+ 'failed',
12
+ 'cancelled',
13
+ 'timed_out',
14
+ ]
15
+
16
+ export class ExecutionsResource {
17
+ constructor(private readonly http: HttpClient) {}
18
+
19
+ /** Get current execution record. */
20
+ async get(executionId: string): Promise<ExecutionRecord> {
21
+ return this.http.request(`/api/v1/executions/${encodeURIComponent(executionId)}`)
22
+ }
23
+
24
+ /**
25
+ * Block until the execution reaches a terminal state. Polls every
26
+ * `pollIntervalMs` (default 2s) until it's `completed`/`failed`/
27
+ * `cancelled`/`timed_out`, OR until `timeoutMs` elapses (default 5min).
28
+ *
29
+ * Throws `TimeoutError` on timeout; otherwise returns the final record.
30
+ */
31
+ async wait(
32
+ executionId: string,
33
+ opts: { timeoutMs?: number; pollIntervalMs?: number; signal?: AbortSignal } = {},
34
+ ): Promise<ExecutionRecord> {
35
+ const timeoutMs = opts.timeoutMs ?? 5 * 60_000
36
+ const pollIntervalMs = opts.pollIntervalMs ?? 2_000
37
+ const deadline = Date.now() + timeoutMs
38
+ while (true) {
39
+ if (opts.signal?.aborted) throw new TimeoutError(`Wait cancelled for ${executionId}`)
40
+ const exec = await this.get(executionId)
41
+ if (TERMINAL_STATES.includes(exec.status)) return exec
42
+ if (Date.now() > deadline) {
43
+ throw new TimeoutError(`Execution ${executionId} did not finish within ${timeoutMs}ms`)
44
+ }
45
+ await new Promise((r) => setTimeout(r, pollIntervalMs))
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Get the logs for a finished (or in-progress) execution as a one-shot
51
+ * fetch. For real-time streaming use `stream(executionId)` instead.
52
+ */
53
+ async logs(executionId: string): Promise<ExecutionLogEvent[]> {
54
+ const res = await this.http.request<{ logs: ExecutionLogEvent[] }>(
55
+ `/api/v1/executions/${encodeURIComponent(executionId)}/logs`,
56
+ )
57
+ return res.logs ?? []
58
+ }
59
+
60
+ /**
61
+ * Stream log events as they arrive. Async iterable:
62
+ *
63
+ * for await (const ev of px.executions.stream(execId)) {
64
+ * console.log(ev.message)
65
+ * if (ev.type === 'done') break
66
+ * }
67
+ */
68
+ async *stream(
69
+ executionId: string,
70
+ opts: { signal?: AbortSignal } = {},
71
+ ): AsyncGenerator<ExecutionLogEvent, void, void> {
72
+ yield* this.http.streamSse<ExecutionLogEvent>(
73
+ `/api/v1/executions/${encodeURIComponent(executionId)}/logs/stream`,
74
+ { signal: opts.signal },
75
+ )
76
+ }
77
+
78
+ /** Get a single node's output from a finished execution. */
79
+ async getNodeOutput(executionId: string, nodeId: string): Promise<unknown> {
80
+ return this.http.request(
81
+ `/api/v1/executions/${encodeURIComponent(executionId)}/nodes/${encodeURIComponent(nodeId)}/output`,
82
+ )
83
+ }
84
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * `px.profiles.*` — Chrome profile management.
3
+ *
4
+ * Profiles are persistent browser identities — they store cookies,
5
+ * local storage, extensions, and login state across sessions. Two
6
+ * kinds:
7
+ * • `cloud` — lives on the Prompteryx cloud browser infrastructure.
8
+ * Accessible from any device, but starts logged out (you have to
9
+ * log in once after creating).
10
+ * • `local` — runs on the user's own Chrome via the Prompteryx
11
+ * plugin. Reuses whatever Chrome profile the user is already
12
+ * signed into (Gmail, banking, internal SSO). Cloud-only
13
+ * workloads can't access this.
14
+ */
15
+
16
+ import type { HttpClient } from '../client'
17
+ import type { ProfileSummary } from '../types'
18
+
19
+ export class ProfilesResource {
20
+ constructor(private readonly http: HttpClient) {}
21
+
22
+ async list(opts: { kind?: 'cloud' | 'local' } = {}): Promise<ProfileSummary[]> {
23
+ const res = await this.http.request<{ profiles: ProfileSummary[] }>(
24
+ '/api/v1/profiles',
25
+ { query: { kind: opts.kind } },
26
+ )
27
+ return res.profiles ?? []
28
+ }
29
+
30
+ async get(profileId: string): Promise<ProfileSummary> {
31
+ return this.http.request(`/api/v1/profiles/${encodeURIComponent(profileId)}`)
32
+ }
33
+
34
+ /** Create a new CLOUD profile. Local profiles are managed by the
35
+ * plugin and cannot be created via the API. */
36
+ async create(opts: { name: string }): Promise<ProfileSummary> {
37
+ return this.http.request('/api/v1/profiles', {
38
+ method: 'POST',
39
+ body: { name: opts.name, kind: 'cloud' },
40
+ })
41
+ }
42
+
43
+ async delete(profileId: string): Promise<{ ok: true }> {
44
+ return this.http.request(`/api/v1/profiles/${encodeURIComponent(profileId)}`, {
45
+ method: 'DELETE',
46
+ })
47
+ }
48
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * ⚠️ NOT SHIPPED in @prompteryx/sdk 0.4.0 (2026-09-03) — not exported from
3
+ * src/index.ts. The live /api/v1/recordings route is a POST-only ACTION
4
+ * recorder used by the MCP server (actions: start/stop/save — it captures
5
+ * workflow actions, not session videos); GET list is a 405 and
6
+ * /api/v1/recordings/{id} does not exist. Verified in
7
+ * docs/API_SDK_DEVELOPER_PLAN_GOLIVE_AUDIT.md. Kept as source for a future
8
+ * release; do not re-export without re-verifying the endpoints.
9
+ *
10
+ * `px.recordings.*` — list session recordings + signed-URL retrieval.
11
+ */
12
+
13
+ import type { HttpClient } from '../client'
14
+ import type { SessionRecording } from '../types'
15
+
16
+ export class RecordingsResource {
17
+ constructor(private readonly http: HttpClient) {}
18
+
19
+ /** List your recordings, newest first. */
20
+ async list(opts: { limit?: number } = {}): Promise<SessionRecording[]> {
21
+ const res = await this.http.request<{ recordings: SessionRecording[] }>(
22
+ '/api/v1/recordings',
23
+ { query: { limit: opts.limit } },
24
+ )
25
+ return res.recordings ?? []
26
+ }
27
+
28
+ /** Get a single recording's metadata + signed playback URL. */
29
+ async get(sessionId: string): Promise<SessionRecording> {
30
+ return this.http.request(`/api/v1/recordings/${encodeURIComponent(sessionId)}`)
31
+ }
32
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * `px.schedules.*` — server-side workflow scheduling.
3
+ *
4
+ * Set a workflow to run on cron / interval; the platform's Cloud
5
+ * Scheduler will fire it on schedule even when no client is connected.
6
+ * Wraps the same scheduling primitive the Visual Studio "Active"
7
+ * toggle uses.
8
+ */
9
+
10
+ import type { HttpClient } from '../client'
11
+ import type { CreateScheduleOptions, ScheduleSummary } from '../types'
12
+
13
+ export class SchedulesResource {
14
+ constructor(private readonly http: HttpClient) {}
15
+
16
+ async list(opts: { active?: boolean; workflowId?: string } = {}): Promise<ScheduleSummary[]> {
17
+ const res = await this.http.request<{ schedules: ScheduleSummary[] }>(
18
+ '/api/v1/schedules',
19
+ { query: { active: opts.active, workflowId: opts.workflowId } },
20
+ )
21
+ return res.schedules ?? []
22
+ }
23
+
24
+ async get(scheduleId: string): Promise<ScheduleSummary> {
25
+ return this.http.request(`/api/v1/schedules/${encodeURIComponent(scheduleId)}`)
26
+ }
27
+
28
+ /** Create a new schedule. Returns the created record. */
29
+ async create(opts: CreateScheduleOptions): Promise<ScheduleSummary> {
30
+ return this.http.request('/api/v1/schedules', {
31
+ method: 'POST',
32
+ body: opts,
33
+ })
34
+ }
35
+
36
+ /** Pause / resume / change cron / timezone. */
37
+ async update(scheduleId: string, patch: Partial<CreateScheduleOptions> & { active?: boolean }): Promise<ScheduleSummary> {
38
+ return this.http.request(`/api/v1/schedules/${encodeURIComponent(scheduleId)}`, {
39
+ method: 'PATCH',
40
+ body: patch,
41
+ })
42
+ }
43
+
44
+ async delete(scheduleId: string): Promise<{ ok: true }> {
45
+ return this.http.request(`/api/v1/schedules/${encodeURIComponent(scheduleId)}`, {
46
+ method: 'DELETE',
47
+ })
48
+ }
49
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * `px.subscription.*` — plan + balance + usage telemetry.
3
+ *
4
+ * Programmatic access to the same numbers the in-app `/subscription`
5
+ * and `/cloud-platform/plans` pages display. Use this to:
6
+ * • Check the user's remaining AI Credits before kicking off a
7
+ * long workflow.
8
+ * • Read monthly execution counts for your own dashboards.
9
+ * • Detect a plan downgrade and react in your code.
10
+ */
11
+
12
+ import type { HttpClient } from '../client'
13
+ import type { SubscriptionStatus } from '../types'
14
+
15
+ export class SubscriptionResource {
16
+ constructor(private readonly http: HttpClient) {}
17
+
18
+ /** Get the current plan + balances + usage. */
19
+ async get(): Promise<SubscriptionStatus> {
20
+ return this.http.request('/api/v1/subscription')
21
+ }
22
+
23
+ // NOT SHIPPED (2026-09-03, v0.4.0): usage() was removed — the route it
24
+ // targeted (/api/v1/subscription/usage) does not exist on the live API
25
+ // (the only usage route is /api/v1/usage, with a different shape).
26
+ // Re-add once a real time-series endpoint ships.
27
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * ⚠️ NOT SHIPPED in @prompteryx/sdk 0.4.0 (2026-09-03) — not exported from
3
+ * src/index.ts. The /api/v1/templates* routes this resource targets do not
4
+ * exist on the live API (every call 404s). Verified against the 31 live v1
5
+ * routes in docs/API_SDK_DEVELOPER_PLAN_GOLIVE_AUDIT.md. Kept as source for
6
+ * a future release; do not re-export without re-verifying.
7
+ *
8
+ * `px.templates.*` — workflow templates catalogue.
9
+ *
10
+ * Templates are pre-built workflows the user can fork into their
11
+ * own account. They include both platform-curated templates and
12
+ * user-shared ones. Forking a template returns a new `workflowId`
13
+ * scoped to the calling user.
14
+ */
15
+
16
+ import type { HttpClient } from '../client'
17
+ import type { TemplateSummary } from '../types'
18
+
19
+ export class TemplatesResource {
20
+ constructor(private readonly http: HttpClient) {}
21
+
22
+ /** Browse templates. Use `category` + `search` to filter. */
23
+ async list(opts: { category?: string; search?: string; limit?: number } = {}): Promise<TemplateSummary[]> {
24
+ const res = await this.http.request<{ templates: TemplateSummary[] }>(
25
+ '/api/v1/templates',
26
+ { query: { category: opts.category, q: opts.search, limit: opts.limit } },
27
+ )
28
+ return res.templates ?? []
29
+ }
30
+
31
+ async get(templateId: string): Promise<TemplateSummary & { nodes?: unknown[] }> {
32
+ return this.http.request(`/api/v1/templates/${encodeURIComponent(templateId)}`)
33
+ }
34
+
35
+ /**
36
+ * Fork a template into the user's workspace. Returns the new
37
+ * workflow id; the user can then run / edit it like any other
38
+ * workflow.
39
+ */
40
+ async fork(templateId: string, opts: { name?: string } = {}): Promise<{ workflowId: string }> {
41
+ return this.http.request(`/api/v1/templates/${encodeURIComponent(templateId)}/fork`, {
42
+ method: 'POST',
43
+ body: { name: opts.name },
44
+ })
45
+ }
46
+ }
@@ -0,0 +1,84 @@
1
+ /**
2
+ * `px.workflows.*` — Visual Studio workflows.
3
+ *
4
+ * Trigger workflows you (or anyone you share with) built in Visual
5
+ * Studio. Workflows are first-class platform objects: they have
6
+ * permanent IDs, can be scheduled, shared, templated, and edited
7
+ * visually. Triggering one via the SDK is fully equivalent to
8
+ * pressing Run in the UI — same runtime, same node executor, same
9
+ * billing path.
10
+ */
11
+
12
+ import type { HttpClient } from '../client'
13
+ import { TimeoutError } from '../errors'
14
+ import type {
15
+ ExecutionRecord,
16
+ RunWorkflowOptions,
17
+ RunWorkflowResult,
18
+ WorkflowSummary,
19
+ } from '../types'
20
+
21
+ export class WorkflowsResource {
22
+ constructor(private readonly http: HttpClient) {}
23
+
24
+ async list(opts: { limit?: number; search?: string; tag?: string } = {}): Promise<WorkflowSummary[]> {
25
+ const res = await this.http.request<{ workflows: WorkflowSummary[] }>(
26
+ '/api/v1/workflows',
27
+ { query: { limit: opts.limit, q: opts.search, tag: opts.tag } },
28
+ )
29
+ return res.workflows ?? []
30
+ }
31
+
32
+ async get(workflowId: string): Promise<WorkflowSummary & { nodes?: unknown[] }> {
33
+ return this.http.request(`/api/v1/workflows/${encodeURIComponent(workflowId)}`)
34
+ }
35
+
36
+ /**
37
+ * Trigger a workflow. Returns immediately with `executionId`. Use
38
+ * `px.executions.wait(id)` to block until completion or
39
+ * `px.executions.stream(id)` to follow log events live.
40
+ *
41
+ * The `execution` options override the workflow's saved settings
42
+ * for this one run — you don't have to edit the workflow in VS to
43
+ * change the proxy, region, profile, etc.
44
+ */
45
+ async run(workflowId: string, opts: RunWorkflowOptions = {}): Promise<RunWorkflowResult> {
46
+ return this.http.request<RunWorkflowResult>(
47
+ `/api/v1/workflows/${encodeURIComponent(workflowId)}/execute`,
48
+ {
49
+ method: 'POST',
50
+ body: {
51
+ variables: opts.input,
52
+ executionOptions: opts.execution,
53
+ },
54
+ },
55
+ )
56
+ }
57
+
58
+ /**
59
+ * Run + block. Returns the final ExecutionRecord. Throws
60
+ * `TimeoutError` if the run takes longer than `timeoutMs`
61
+ * (default 5 minutes).
62
+ */
63
+ async runAndWait(
64
+ workflowId: string,
65
+ opts: RunWorkflowOptions & { timeoutMs?: number; pollIntervalMs?: number } = {},
66
+ ): Promise<ExecutionRecord> {
67
+ const started = await this.run(workflowId, opts)
68
+ return this.waitInternal(started.executionId, opts.timeoutMs ?? 5 * 60_000, opts.pollIntervalMs ?? 2_000)
69
+ }
70
+
71
+ private async waitInternal(executionId: string, timeoutMs: number, pollIntervalMs: number): Promise<ExecutionRecord> {
72
+ const deadline = Date.now() + timeoutMs
73
+ while (true) {
74
+ const exec = await this.http.request<ExecutionRecord>(
75
+ `/api/v1/executions/${encodeURIComponent(executionId)}`,
76
+ )
77
+ if (['completed', 'failed', 'cancelled', 'timed_out'].includes(exec.status)) return exec
78
+ if (Date.now() > deadline) {
79
+ throw new TimeoutError(`Execution ${executionId} did not finish within ${timeoutMs}ms`)
80
+ }
81
+ await new Promise((r) => setTimeout(r, pollIntervalMs))
82
+ }
83
+ }
84
+ }