@secondlayer/sdk 1.0.1 → 3.0.0-alpha.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.
@@ -1,157 +0,0 @@
1
- // src/errors.ts
2
- class ApiError extends Error {
3
- status;
4
- body;
5
- constructor(status, message, body) {
6
- super(message);
7
- this.status = status;
8
- this.body = body;
9
- this.name = "ApiError";
10
- }
11
- }
12
-
13
- class VersionConflictError extends ApiError {
14
- currentVersion;
15
- expectedVersion;
16
- constructor(currentVersion, expectedVersion, message = `Version conflict: expected ${expectedVersion}, current ${currentVersion}`) {
17
- super(409, message, { currentVersion, expectedVersion });
18
- this.currentVersion = currentVersion;
19
- this.expectedVersion = expectedVersion;
20
- this.name = "VersionConflictError";
21
- }
22
- }
23
-
24
- // src/base.ts
25
- var DEFAULT_BASE_URL = "https://api.secondlayer.tools";
26
-
27
- class BaseClient {
28
- baseUrl;
29
- apiKey;
30
- origin;
31
- constructor(options = {}) {
32
- this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
33
- this.apiKey = options.apiKey;
34
- this.origin = options.origin ?? "cli";
35
- }
36
- static authHeaders(apiKey) {
37
- const headers = {
38
- "Content-Type": "application/json"
39
- };
40
- if (apiKey) {
41
- headers.Authorization = `Bearer ${apiKey}`;
42
- }
43
- return headers;
44
- }
45
- async request(method, path, body) {
46
- const url = `${this.baseUrl}${path}`;
47
- const headers = BaseClient.authHeaders(this.apiKey);
48
- headers["x-sl-origin"] = this.origin;
49
- let response;
50
- try {
51
- response = await fetch(url, {
52
- method,
53
- headers,
54
- body: body ? JSON.stringify(body) : undefined
55
- });
56
- } catch {
57
- throw new ApiError(0, `Cannot reach API at ${this.baseUrl}. Check your connection or try again.`);
58
- }
59
- if (!response.ok) {
60
- if (response.status === 401) {
61
- throw new ApiError(401, "API key invalid or expired.");
62
- }
63
- if (response.status === 429) {
64
- const retryAfter = response.headers.get("Retry-After");
65
- const msg = retryAfter ? `Rate limited. Wait ${retryAfter} seconds.` : "Rate limited. Try again later.";
66
- throw new ApiError(429, msg);
67
- }
68
- if (response.status >= 500) {
69
- throw new ApiError(response.status, `Server error. Try again or check status at ${this.baseUrl}/health`);
70
- }
71
- const errorBody = await response.text();
72
- let message = `HTTP ${response.status}`;
73
- let parsedBody = errorBody;
74
- try {
75
- const json = JSON.parse(errorBody);
76
- parsedBody = json;
77
- const err = json.error ?? json.message;
78
- if (typeof err === "string") {
79
- message = err;
80
- } else if (err && typeof err === "object") {
81
- message = JSON.stringify(err);
82
- }
83
- } catch {
84
- if (errorBody)
85
- message = errorBody;
86
- }
87
- throw new ApiError(response.status, message, parsedBody);
88
- }
89
- if (response.status === 204) {
90
- return;
91
- }
92
- return response.json();
93
- }
94
- }
95
-
96
- // src/marketplace/client.ts
97
- function buildMarketplaceQuery(opts) {
98
- const qs = new URLSearchParams;
99
- if (opts.tags?.length)
100
- qs.set("tags", opts.tags.join(","));
101
- if (opts.search)
102
- qs.set("search", opts.search);
103
- if (opts.sort)
104
- qs.set("_sort", opts.sort);
105
- if (opts.limit !== undefined)
106
- qs.set("_limit", String(opts.limit));
107
- if (opts.offset !== undefined)
108
- qs.set("_offset", String(opts.offset));
109
- const str = qs.toString();
110
- return str ? `?${str}` : "";
111
- }
112
- function buildSubgraphQueryString(params) {
113
- const qs = new URLSearchParams;
114
- if (params.sort)
115
- qs.set("_sort", params.sort);
116
- if (params.order)
117
- qs.set("_order", params.order);
118
- if (params.limit !== undefined)
119
- qs.set("_limit", String(params.limit));
120
- if (params.offset !== undefined)
121
- qs.set("_offset", String(params.offset));
122
- if (params.fields)
123
- qs.set("_fields", params.fields);
124
- if (params.filters) {
125
- for (const [key, value] of Object.entries(params.filters)) {
126
- qs.set(key, String(value));
127
- }
128
- }
129
- const str = qs.toString();
130
- return str ? `?${str}` : "";
131
- }
132
-
133
- class Marketplace extends BaseClient {
134
- async browse(opts = {}) {
135
- return this.request("GET", `/api/marketplace/subgraphs${buildMarketplaceQuery(opts)}`);
136
- }
137
- async get(name) {
138
- return this.request("GET", `/api/marketplace/subgraphs/${name}`);
139
- }
140
- async creator(slug) {
141
- return this.request("GET", `/api/marketplace/creators/${slug}`);
142
- }
143
- async fork(name, newName) {
144
- return this.request("POST", `/api/marketplace/subgraphs/${name}/fork`, {
145
- newName
146
- });
147
- }
148
- async queryTable(name, table, params = {}) {
149
- return this.request("GET", `/api/marketplace/subgraphs/${name}/${table}${buildSubgraphQueryString(params)}`);
150
- }
151
- }
152
- export {
153
- Marketplace
154
- };
155
-
156
- //# debugId=89434BF75099946264756E2164756E21
157
- //# sourceMappingURL=index.js.map
@@ -1,12 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/errors.ts", "../src/base.ts", "../src/marketplace/client.ts"],
4
- "sourcesContent": [
5
- "/**\n * Error thrown by {@link SecondLayer} when an API request fails.\n * Includes the HTTP status code for programmatic error handling.\n *\n * @example\n * ```ts\n * try {\n * await client.subgraphs.get(\"my-subgraph\");\n * } catch (err) {\n * if (err instanceof ApiError && err.status === 404) {\n * console.log(\"Subgraph not found\");\n * }\n * }\n * ```\n */\nexport class ApiError extends Error {\n\tconstructor(\n\t\t/** HTTP status code (0 for network errors). */\n\t\tpublic status: number,\n\t\tmessage: string,\n\t\t/** Raw response body (parsed JSON if possible) — preserved for callers that need error details. */\n\t\tpublic body?: unknown,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"ApiError\";\n\t}\n}\n\n/**\n * Thrown by {@link Workflows.deploy} when the server rejects a deploy because the\n * provided `expectedVersion` does not match the current stored version.\n */\nexport class VersionConflictError extends ApiError {\n\tconstructor(\n\t\tpublic currentVersion: string,\n\t\tpublic expectedVersion: string,\n\t\tmessage = `Version conflict: expected ${expectedVersion}, current ${currentVersion}`,\n\t) {\n\t\tsuper(409, message, { currentVersion, expectedVersion });\n\t\tthis.name = \"VersionConflictError\";\n\t}\n}\n",
6
- "import { ApiError } from \"./errors.ts\";\n\nexport interface SecondLayerOptions {\n\t/** Base URL of the Secondlayer API (trailing slashes are stripped). */\n\tbaseUrl: string;\n\t/** Bearer token for authenticated requests. */\n\tapiKey?: string;\n\t/** Deploy origin label sent as `x-sl-origin` (telemetry). Defaults to `cli`. */\n\torigin?: \"cli\" | \"mcp\" | \"session\";\n}\n\nconst DEFAULT_BASE_URL = \"https://api.secondlayer.tools\";\n\nexport abstract class BaseClient {\n\tprotected baseUrl: string;\n\tprotected apiKey?: string;\n\tprotected origin: \"cli\" | \"mcp\" | \"session\";\n\n\tconstructor(options: Partial<SecondLayerOptions> = {}) {\n\t\tthis.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n\t\tthis.apiKey = options.apiKey;\n\t\tthis.origin = options.origin ?? \"cli\";\n\t}\n\n\tstatic authHeaders(apiKey?: string): Record<string, string> {\n\t\tconst headers: Record<string, string> = {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t};\n\t\tif (apiKey) {\n\t\t\theaders.Authorization = `Bearer ${apiKey}`;\n\t\t}\n\t\treturn headers;\n\t}\n\n\tprotected async request<T>(\n\t\tmethod: string,\n\t\tpath: string,\n\t\tbody?: unknown,\n\t): Promise<T> {\n\t\tconst url = `${this.baseUrl}${path}`;\n\t\tconst headers = BaseClient.authHeaders(this.apiKey);\n\t\theaders[\"x-sl-origin\"] = this.origin;\n\n\t\tlet response: Response;\n\t\ttry {\n\t\t\tresponse = await fetch(url, {\n\t\t\t\tmethod,\n\t\t\t\theaders,\n\t\t\t\tbody: body ? JSON.stringify(body) : undefined,\n\t\t\t});\n\t\t} catch {\n\t\t\tthrow new ApiError(\n\t\t\t\t0,\n\t\t\t\t`Cannot reach API at ${this.baseUrl}. Check your connection or try again.`,\n\t\t\t);\n\t\t}\n\n\t\tif (!response.ok) {\n\t\t\tif (response.status === 401) {\n\t\t\t\tthrow new ApiError(401, \"API key invalid or expired.\");\n\t\t\t}\n\n\t\t\tif (response.status === 429) {\n\t\t\t\tconst retryAfter = response.headers.get(\"Retry-After\");\n\t\t\t\tconst msg = retryAfter\n\t\t\t\t\t? `Rate limited. Wait ${retryAfter} seconds.`\n\t\t\t\t\t: \"Rate limited. Try again later.\";\n\t\t\t\tthrow new ApiError(429, msg);\n\t\t\t}\n\n\t\t\tif (response.status >= 500) {\n\t\t\t\tthrow new ApiError(\n\t\t\t\t\tresponse.status,\n\t\t\t\t\t`Server error. Try again or check status at ${this.baseUrl}/health`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst errorBody = await response.text();\n\t\t\tlet message = `HTTP ${response.status}`;\n\t\t\tlet parsedBody: unknown = errorBody;\n\t\t\ttry {\n\t\t\t\tconst json = JSON.parse(errorBody);\n\t\t\t\tparsedBody = json;\n\t\t\t\tconst err = json.error ?? json.message;\n\t\t\t\tif (typeof err === \"string\") {\n\t\t\t\t\tmessage = err;\n\t\t\t\t} else if (err && typeof err === \"object\") {\n\t\t\t\t\tmessage = JSON.stringify(err);\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\tif (errorBody) message = errorBody;\n\t\t\t}\n\t\t\tthrow new ApiError(response.status, message, parsedBody);\n\t\t}\n\n\t\tif (response.status === 204) {\n\t\t\treturn undefined as T;\n\t\t}\n\n\t\treturn response.json() as Promise<T>;\n\t}\n}\n",
7
- "import type {\n\tCreatorProfile,\n\tMarketplaceSubgraphDetail,\n\tMarketplaceSubgraphSummary,\n\tSubgraphQueryParams,\n} from \"@secondlayer/shared/schemas\";\nimport { BaseClient } from \"../base.ts\";\n\nexport interface MarketplaceBrowseOptions {\n\ttags?: string[];\n\tsearch?: string;\n\tsort?: \"recent\" | \"popular\" | \"name\";\n\tlimit?: number;\n\toffset?: number;\n}\n\nfunction buildMarketplaceQuery(opts: MarketplaceBrowseOptions): string {\n\tconst qs = new URLSearchParams();\n\tif (opts.tags?.length) qs.set(\"tags\", opts.tags.join(\",\"));\n\tif (opts.search) qs.set(\"search\", opts.search);\n\tif (opts.sort) qs.set(\"_sort\", opts.sort);\n\tif (opts.limit !== undefined) qs.set(\"_limit\", String(opts.limit));\n\tif (opts.offset !== undefined) qs.set(\"_offset\", String(opts.offset));\n\tconst str = qs.toString();\n\treturn str ? `?${str}` : \"\";\n}\n\nfunction buildSubgraphQueryString(params: SubgraphQueryParams): string {\n\tconst qs = new URLSearchParams();\n\tif (params.sort) qs.set(\"_sort\", params.sort);\n\tif (params.order) qs.set(\"_order\", params.order);\n\tif (params.limit !== undefined) qs.set(\"_limit\", String(params.limit));\n\tif (params.offset !== undefined) qs.set(\"_offset\", String(params.offset));\n\tif (params.fields) qs.set(\"_fields\", params.fields);\n\tif (params.filters) {\n\t\tfor (const [key, value] of Object.entries(params.filters)) {\n\t\t\tqs.set(key, String(value));\n\t\t}\n\t}\n\tconst str = qs.toString();\n\treturn str ? `?${str}` : \"\";\n}\n\nexport class Marketplace extends BaseClient {\n\tasync browse(\n\t\topts: MarketplaceBrowseOptions = {},\n\t): Promise<{\n\t\tdata: MarketplaceSubgraphSummary[];\n\t\tmeta: { total: number; limit: number; offset: number };\n\t}> {\n\t\treturn this.request(\"GET\", `/api/marketplace/subgraphs${buildMarketplaceQuery(opts)}`);\n\t}\n\n\tasync get(name: string): Promise<MarketplaceSubgraphDetail> {\n\t\treturn this.request(\"GET\", `/api/marketplace/subgraphs/${name}`);\n\t}\n\n\tasync creator(slug: string): Promise<CreatorProfile> {\n\t\treturn this.request(\"GET\", `/api/marketplace/creators/${slug}`);\n\t}\n\n\tasync fork(\n\t\tname: string,\n\t\tnewName?: string,\n\t): Promise<{\n\t\taction: string;\n\t\tsubgraphId: string;\n\t\tname: string;\n\t\tforkedFrom: string;\n\t}> {\n\t\treturn this.request(\"POST\", `/api/marketplace/subgraphs/${name}/fork`, {\n\t\t\tnewName,\n\t\t});\n\t}\n\n\tasync queryTable(\n\t\tname: string,\n\t\ttable: string,\n\t\tparams: SubgraphQueryParams = {},\n\t): Promise<{\n\t\tdata: unknown[];\n\t\tmeta: { total: number; limit: number; offset: number };\n\t}> {\n\t\treturn this.request(\n\t\t\t\"GET\",\n\t\t\t`/api/marketplace/subgraphs/${name}/${table}${buildSubgraphQueryString(params)}`,\n\t\t);\n\t}\n}\n"
8
- ],
9
- "mappings": ";AAeO,MAAM,iBAAiB,MAAM;AAAA,EAG3B;AAAA,EAGA;AAAA,EALR,WAAW,CAEH,QACP,SAEO,MACN;AAAA,IACD,MAAM,OAAO;AAAA,IALN;AAAA,IAGA;AAAA,IAGP,KAAK,OAAO;AAAA;AAEd;AAAA;AAMO,MAAM,6BAA6B,SAAS;AAAA,EAE1C;AAAA,EACA;AAAA,EAFR,WAAW,CACH,gBACA,iBACP,UAAU,8BAA8B,4BAA4B,kBACnE;AAAA,IACD,MAAM,KAAK,SAAS,EAAE,gBAAgB,gBAAgB,CAAC;AAAA,IAJhD;AAAA,IACA;AAAA,IAIP,KAAK,OAAO;AAAA;AAEd;;;AC9BA,IAAM,mBAAmB;AAAA;AAElB,MAAe,WAAW;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EAEV,WAAW,CAAC,UAAuC,CAAC,GAAG;AAAA,IACtD,KAAK,WAAW,QAAQ,WAAW,kBAAkB,QAAQ,QAAQ,EAAE;AAAA,IACvE,KAAK,SAAS,QAAQ;AAAA,IACtB,KAAK,SAAS,QAAQ,UAAU;AAAA;AAAA,SAG1B,WAAW,CAAC,QAAyC;AAAA,IAC3D,MAAM,UAAkC;AAAA,MACvC,gBAAgB;AAAA,IACjB;AAAA,IACA,IAAI,QAAQ;AAAA,MACX,QAAQ,gBAAgB,UAAU;AAAA,IACnC;AAAA,IACA,OAAO;AAAA;AAAA,OAGQ,QAAU,CACzB,QACA,MACA,MACa;AAAA,IACb,MAAM,MAAM,GAAG,KAAK,UAAU;AAAA,IAC9B,MAAM,UAAU,WAAW,YAAY,KAAK,MAAM;AAAA,IAClD,QAAQ,iBAAiB,KAAK;AAAA,IAE9B,IAAI;AAAA,IACJ,IAAI;AAAA,MACH,WAAW,MAAM,MAAM,KAAK;AAAA,QAC3B;AAAA,QACA;AAAA,QACA,MAAM,OAAO,KAAK,UAAU,IAAI,IAAI;AAAA,MACrC,CAAC;AAAA,MACA,MAAM;AAAA,MACP,MAAM,IAAI,SACT,GACA,uBAAuB,KAAK,8CAC7B;AAAA;AAAA,IAGD,IAAI,CAAC,SAAS,IAAI;AAAA,MACjB,IAAI,SAAS,WAAW,KAAK;AAAA,QAC5B,MAAM,IAAI,SAAS,KAAK,6BAA6B;AAAA,MACtD;AAAA,MAEA,IAAI,SAAS,WAAW,KAAK;AAAA,QAC5B,MAAM,aAAa,SAAS,QAAQ,IAAI,aAAa;AAAA,QACrD,MAAM,MAAM,aACT,sBAAsB,wBACtB;AAAA,QACH,MAAM,IAAI,SAAS,KAAK,GAAG;AAAA,MAC5B;AAAA,MAEA,IAAI,SAAS,UAAU,KAAK;AAAA,QAC3B,MAAM,IAAI,SACT,SAAS,QACT,8CAA8C,KAAK,gBACpD;AAAA,MACD;AAAA,MAEA,MAAM,YAAY,MAAM,SAAS,KAAK;AAAA,MACtC,IAAI,UAAU,QAAQ,SAAS;AAAA,MAC/B,IAAI,aAAsB;AAAA,MAC1B,IAAI;AAAA,QACH,MAAM,OAAO,KAAK,MAAM,SAAS;AAAA,QACjC,aAAa;AAAA,QACb,MAAM,MAAM,KAAK,SAAS,KAAK;AAAA,QAC/B,IAAI,OAAO,QAAQ,UAAU;AAAA,UAC5B,UAAU;AAAA,QACX,EAAO,SAAI,OAAO,OAAO,QAAQ,UAAU;AAAA,UAC1C,UAAU,KAAK,UAAU,GAAG;AAAA,QAC7B;AAAA,QACC,MAAM;AAAA,QACP,IAAI;AAAA,UAAW,UAAU;AAAA;AAAA,MAE1B,MAAM,IAAI,SAAS,SAAS,QAAQ,SAAS,UAAU;AAAA,IACxD;AAAA,IAEA,IAAI,SAAS,WAAW,KAAK;AAAA,MAC5B;AAAA,IACD;AAAA,IAEA,OAAO,SAAS,KAAK;AAAA;AAEvB;;;ACrFA,SAAS,qBAAqB,CAAC,MAAwC;AAAA,EACtE,MAAM,KAAK,IAAI;AAAA,EACf,IAAI,KAAK,MAAM;AAAA,IAAQ,GAAG,IAAI,QAAQ,KAAK,KAAK,KAAK,GAAG,CAAC;AAAA,EACzD,IAAI,KAAK;AAAA,IAAQ,GAAG,IAAI,UAAU,KAAK,MAAM;AAAA,EAC7C,IAAI,KAAK;AAAA,IAAM,GAAG,IAAI,SAAS,KAAK,IAAI;AAAA,EACxC,IAAI,KAAK,UAAU;AAAA,IAAW,GAAG,IAAI,UAAU,OAAO,KAAK,KAAK,CAAC;AAAA,EACjE,IAAI,KAAK,WAAW;AAAA,IAAW,GAAG,IAAI,WAAW,OAAO,KAAK,MAAM,CAAC;AAAA,EACpE,MAAM,MAAM,GAAG,SAAS;AAAA,EACxB,OAAO,MAAM,IAAI,QAAQ;AAAA;AAG1B,SAAS,wBAAwB,CAAC,QAAqC;AAAA,EACtE,MAAM,KAAK,IAAI;AAAA,EACf,IAAI,OAAO;AAAA,IAAM,GAAG,IAAI,SAAS,OAAO,IAAI;AAAA,EAC5C,IAAI,OAAO;AAAA,IAAO,GAAG,IAAI,UAAU,OAAO,KAAK;AAAA,EAC/C,IAAI,OAAO,UAAU;AAAA,IAAW,GAAG,IAAI,UAAU,OAAO,OAAO,KAAK,CAAC;AAAA,EACrE,IAAI,OAAO,WAAW;AAAA,IAAW,GAAG,IAAI,WAAW,OAAO,OAAO,MAAM,CAAC;AAAA,EACxE,IAAI,OAAO;AAAA,IAAQ,GAAG,IAAI,WAAW,OAAO,MAAM;AAAA,EAClD,IAAI,OAAO,SAAS;AAAA,IACnB,YAAY,KAAK,UAAU,OAAO,QAAQ,OAAO,OAAO,GAAG;AAAA,MAC1D,GAAG,IAAI,KAAK,OAAO,KAAK,CAAC;AAAA,IAC1B;AAAA,EACD;AAAA,EACA,MAAM,MAAM,GAAG,SAAS;AAAA,EACxB,OAAO,MAAM,IAAI,QAAQ;AAAA;AAAA;AAGnB,MAAM,oBAAoB,WAAW;AAAA,OACrC,OAAM,CACX,OAAiC,CAAC,GAIhC;AAAA,IACF,OAAO,KAAK,QAAQ,OAAO,6BAA6B,sBAAsB,IAAI,GAAG;AAAA;AAAA,OAGhF,IAAG,CAAC,MAAkD;AAAA,IAC3D,OAAO,KAAK,QAAQ,OAAO,8BAA8B,MAAM;AAAA;AAAA,OAG1D,QAAO,CAAC,MAAuC;AAAA,IACpD,OAAO,KAAK,QAAQ,OAAO,6BAA6B,MAAM;AAAA;AAAA,OAGzD,KAAI,CACT,MACA,SAME;AAAA,IACF,OAAO,KAAK,QAAQ,QAAQ,8BAA8B,aAAa;AAAA,MACtE;AAAA,IACD,CAAC;AAAA;AAAA,OAGI,WAAU,CACf,MACA,OACA,SAA8B,CAAC,GAI7B;AAAA,IACF,OAAO,KAAK,QACX,OACA,8BAA8B,QAAQ,QAAQ,yBAAyB,MAAM,GAC9E;AAAA;AAEF;",
10
- "debugId": "89434BF75099946264756E2164756E21",
11
- "names": []
12
- }
@@ -1,191 +0,0 @@
1
- import { WorkflowRun, WorkflowRunStatus } from "@secondlayer/workflows";
2
- interface SecondLayerOptions {
3
- /** Base URL of the Secondlayer API (trailing slashes are stripped). */
4
- baseUrl: string;
5
- /** Bearer token for authenticated requests. */
6
- apiKey?: string;
7
- /** Deploy origin label sent as `x-sl-origin` (telemetry). Defaults to `cli`. */
8
- origin?: "cli" | "mcp" | "session";
9
- }
10
- declare abstract class BaseClient {
11
- protected baseUrl: string;
12
- protected apiKey?: string;
13
- protected origin: "cli" | "mcp" | "session";
14
- constructor(options?: Partial<SecondLayerOptions>);
15
- static authHeaders(apiKey?: string): Record<string, string>;
16
- protected request<T>(method: string, path: string, body?: unknown): Promise<T>;
17
- }
18
- interface WorkflowSource {
19
- name: string;
20
- version: string;
21
- sourceCode: string | null;
22
- readOnly: boolean;
23
- reason?: string;
24
- updatedAt: string;
25
- }
26
- interface WorkflowStepEvent {
27
- id: string;
28
- stepIndex: number;
29
- stepId: string;
30
- stepType: string;
31
- status: string;
32
- output?: unknown;
33
- error: string | null;
34
- retryCount: number;
35
- aiTokensUsed: number;
36
- startedAt: string | null;
37
- completedAt: string | null;
38
- durationMs: number | null;
39
- ts: string;
40
- }
41
- interface WorkflowRunDoneEvent {
42
- runId: string;
43
- status: string;
44
- error?: string | null;
45
- completedAt?: string | null;
46
- }
47
- type WorkflowTailEvent = {
48
- type: "step"
49
- step: WorkflowStepEvent
50
- } | {
51
- type: "done"
52
- done: WorkflowRunDoneEvent
53
- } | {
54
- type: "heartbeat"
55
- ts: string
56
- } | {
57
- type: "timeout"
58
- message: string
59
- };
60
- interface DeployDryRunResponse {
61
- valid: boolean;
62
- validation?: {
63
- name: string
64
- triggerType: string
65
- };
66
- bundleSize: number;
67
- error?: string;
68
- }
69
- interface DeployResponse {
70
- action: "created" | "updated";
71
- workflowId: string;
72
- version: string;
73
- message: string;
74
- }
75
- interface BundleWorkflowResponse {
76
- ok: true;
77
- name: string;
78
- trigger: Record<string, unknown>;
79
- handlerCode: string;
80
- sourceCode: string;
81
- retries: Record<string, unknown> | null;
82
- timeout: number | null;
83
- bundleSize: number;
84
- }
85
- interface WorkflowSummary {
86
- name: string;
87
- status: "active" | "paused";
88
- triggerType: "event" | "schedule" | "manual";
89
- createdAt: string;
90
- updatedAt: string;
91
- }
92
- interface WorkflowDetail extends WorkflowSummary {
93
- trigger: Record<string, unknown>;
94
- retries?: {
95
- maxAttempts?: number
96
- backoffMs?: number
97
- };
98
- timeout?: number;
99
- totalRuns: number;
100
- lastRunAt: string | null;
101
- }
102
- interface WorkflowRunSummary {
103
- id: string;
104
- workflowName: string;
105
- status: WorkflowRunStatus;
106
- duration: number;
107
- aiTokensUsed: number;
108
- triggeredAt: string;
109
- completedAt: string | null;
110
- }
111
- declare class Workflows extends BaseClient {
112
- deploy(data: {
113
- name: string
114
- trigger: Record<string, unknown>
115
- handlerCode: string
116
- sourceCode?: string
117
- expectedVersion?: string
118
- retries?: Record<string, unknown>
119
- timeout?: number
120
- clientRequestId?: string
121
- } & {
122
- dryRun?: false
123
- }): Promise<DeployResponse>;
124
- deploy(data: {
125
- name: string
126
- trigger: Record<string, unknown>
127
- handlerCode: string
128
- sourceCode?: string
129
- expectedVersion?: string
130
- retries?: Record<string, unknown>
131
- timeout?: number
132
- dryRun: true
133
- }): Promise<DeployDryRunResponse>;
134
- getSource(name: string): Promise<WorkflowSource>;
135
- /**
136
- * Bundle a TypeScript workflow source on the server. Used by the web chat
137
- * authoring loop so Vercel's serverless runtime doesn't have to run esbuild.
138
- * CLI and MCP still bundle locally — this method is for clients that can't
139
- * install `@secondlayer/bundler` directly (e.g. browser tooling, edge
140
- * functions).
141
- */
142
- bundle(data: {
143
- code: string
144
- }): Promise<BundleWorkflowResponse>;
145
- pauseAll(): Promise<{
146
- paused: number
147
- workflows: Array<{
148
- name: string
149
- version: string
150
- status: string
151
- }>
152
- }>;
153
- cancelRun(runId: string): Promise<{
154
- runId: string
155
- status: string
156
- cancelled: boolean
157
- completedAt?: string
158
- message?: string
159
- }>;
160
- rollback(name: string, toVersion?: string): Promise<{
161
- action: "rolled-back"
162
- name: string
163
- fromVersion: string
164
- restoredFromVersion: string
165
- version: string
166
- }>;
167
- /**
168
- * Subscribe to a workflow run's server-sent event stream. Resolves when the
169
- * run completes, times out, or the signal is aborted. Throws on HTTP errors
170
- * opening the stream.
171
- */
172
- streamRun(name: string, runId: string, onEvent: (event: WorkflowTailEvent) => void, signal?: AbortSignal): Promise<void>;
173
- list(): Promise<{
174
- workflows: WorkflowSummary[]
175
- }>;
176
- get(name: string): Promise<WorkflowDetail>;
177
- trigger(name: string, input?: Record<string, unknown>): Promise<{
178
- runId: string
179
- }>;
180
- pause(name: string): Promise<void>;
181
- resume(name: string): Promise<void>;
182
- delete(name: string): Promise<void>;
183
- listRuns(name: string, params?: {
184
- status?: WorkflowRunStatus
185
- limit?: number
186
- }): Promise<{
187
- runs: WorkflowRunSummary[]
188
- }>;
189
- getRun(runId: string): Promise<WorkflowRun>;
190
- }
191
- export { Workflows, WorkflowSummary, WorkflowRunSummary, WorkflowDetail };
@@ -1,244 +0,0 @@
1
- // src/errors.ts
2
- class ApiError extends Error {
3
- status;
4
- body;
5
- constructor(status, message, body) {
6
- super(message);
7
- this.status = status;
8
- this.body = body;
9
- this.name = "ApiError";
10
- }
11
- }
12
-
13
- class VersionConflictError extends ApiError {
14
- currentVersion;
15
- expectedVersion;
16
- constructor(currentVersion, expectedVersion, message = `Version conflict: expected ${expectedVersion}, current ${currentVersion}`) {
17
- super(409, message, { currentVersion, expectedVersion });
18
- this.currentVersion = currentVersion;
19
- this.expectedVersion = expectedVersion;
20
- this.name = "VersionConflictError";
21
- }
22
- }
23
-
24
- // src/base.ts
25
- var DEFAULT_BASE_URL = "https://api.secondlayer.tools";
26
-
27
- class BaseClient {
28
- baseUrl;
29
- apiKey;
30
- origin;
31
- constructor(options = {}) {
32
- this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
33
- this.apiKey = options.apiKey;
34
- this.origin = options.origin ?? "cli";
35
- }
36
- static authHeaders(apiKey) {
37
- const headers = {
38
- "Content-Type": "application/json"
39
- };
40
- if (apiKey) {
41
- headers.Authorization = `Bearer ${apiKey}`;
42
- }
43
- return headers;
44
- }
45
- async request(method, path, body) {
46
- const url = `${this.baseUrl}${path}`;
47
- const headers = BaseClient.authHeaders(this.apiKey);
48
- headers["x-sl-origin"] = this.origin;
49
- let response;
50
- try {
51
- response = await fetch(url, {
52
- method,
53
- headers,
54
- body: body ? JSON.stringify(body) : undefined
55
- });
56
- } catch {
57
- throw new ApiError(0, `Cannot reach API at ${this.baseUrl}. Check your connection or try again.`);
58
- }
59
- if (!response.ok) {
60
- if (response.status === 401) {
61
- throw new ApiError(401, "API key invalid or expired.");
62
- }
63
- if (response.status === 429) {
64
- const retryAfter = response.headers.get("Retry-After");
65
- const msg = retryAfter ? `Rate limited. Wait ${retryAfter} seconds.` : "Rate limited. Try again later.";
66
- throw new ApiError(429, msg);
67
- }
68
- if (response.status >= 500) {
69
- throw new ApiError(response.status, `Server error. Try again or check status at ${this.baseUrl}/health`);
70
- }
71
- const errorBody = await response.text();
72
- let message = `HTTP ${response.status}`;
73
- let parsedBody = errorBody;
74
- try {
75
- const json = JSON.parse(errorBody);
76
- parsedBody = json;
77
- const err = json.error ?? json.message;
78
- if (typeof err === "string") {
79
- message = err;
80
- } else if (err && typeof err === "object") {
81
- message = JSON.stringify(err);
82
- }
83
- } catch {
84
- if (errorBody)
85
- message = errorBody;
86
- }
87
- throw new ApiError(response.status, message, parsedBody);
88
- }
89
- if (response.status === 204) {
90
- return;
91
- }
92
- return response.json();
93
- }
94
- }
95
-
96
- // src/workflows/client.ts
97
- function parseSseChunk(raw) {
98
- let event = "message";
99
- const dataLines = [];
100
- for (const line of raw.split(`
101
- `)) {
102
- if (line.startsWith("event:")) {
103
- event = line.slice(6).trim();
104
- } else if (line.startsWith("data:")) {
105
- dataLines.push(line.slice(5).trimStart());
106
- }
107
- }
108
- if (dataLines.length === 0)
109
- return null;
110
- const data = dataLines.join(`
111
- `);
112
- try {
113
- const parsed = JSON.parse(data);
114
- switch (event) {
115
- case "step":
116
- return { type: "step", step: parsed };
117
- case "done":
118
- return { type: "done", done: parsed };
119
- case "heartbeat":
120
- return {
121
- type: "heartbeat",
122
- ts: typeof parsed === "string" ? parsed : String(parsed)
123
- };
124
- case "timeout":
125
- return {
126
- type: "timeout",
127
- message: parsed.message ?? "timeout"
128
- };
129
- default:
130
- return null;
131
- }
132
- } catch {
133
- return null;
134
- }
135
- }
136
-
137
- class Workflows extends BaseClient {
138
- async deploy(data) {
139
- try {
140
- return await this.request("POST", "/api/workflows", data);
141
- } catch (err) {
142
- if (err instanceof ApiError && err.status === 409) {
143
- const body = err.body;
144
- if (body?.currentVersion && body.expectedVersion) {
145
- throw new VersionConflictError(body.currentVersion, body.expectedVersion, err.message);
146
- }
147
- }
148
- throw err;
149
- }
150
- }
151
- async getSource(name) {
152
- return this.request("GET", `/api/workflows/${name}/source`);
153
- }
154
- async bundle(data) {
155
- return this.request("POST", "/api/workflows/bundle", data);
156
- }
157
- async pauseAll() {
158
- return this.request("POST", "/api/workflows/pause-all");
159
- }
160
- async cancelRun(runId) {
161
- return this.request("POST", `/api/workflows/runs/${runId}/cancel`);
162
- }
163
- async rollback(name, toVersion) {
164
- return this.request("POST", `/api/workflows/${name}/rollback`, toVersion ? { toVersion } : {});
165
- }
166
- async streamRun(name, runId, onEvent, signal) {
167
- const url = `${this.baseUrl}/api/workflows/${name}/runs/${runId}/stream`;
168
- const headers = {
169
- Accept: "text/event-stream",
170
- "x-sl-origin": this.origin
171
- };
172
- if (this.apiKey) {
173
- headers.Authorization = `Bearer ${this.apiKey}`;
174
- }
175
- const res = await fetch(url, { headers, signal });
176
- if (!res.ok || !res.body) {
177
- throw new ApiError(res.status, `Failed to open workflow run stream (HTTP ${res.status})`);
178
- }
179
- const reader = res.body.pipeThrough(new TextDecoderStream).getReader();
180
- let buffer = "";
181
- while (true) {
182
- const { value, done } = await reader.read();
183
- if (done)
184
- break;
185
- buffer += value;
186
- let sep = buffer.indexOf(`
187
-
188
- `);
189
- while (sep !== -1) {
190
- const chunk = buffer.slice(0, sep);
191
- buffer = buffer.slice(sep + 2);
192
- const parsed = parseSseChunk(chunk);
193
- if (parsed) {
194
- onEvent(parsed);
195
- if (parsed.type === "done" || parsed.type === "timeout") {
196
- await reader.cancel().catch(() => {
197
- return;
198
- });
199
- return;
200
- }
201
- }
202
- sep = buffer.indexOf(`
203
-
204
- `);
205
- }
206
- }
207
- }
208
- async list() {
209
- return this.request("GET", "/api/workflows");
210
- }
211
- async get(name) {
212
- return this.request("GET", `/api/workflows/${name}`);
213
- }
214
- async trigger(name, input) {
215
- return this.request("POST", `/api/workflows/${name}/trigger`, input ? { input } : undefined);
216
- }
217
- async pause(name) {
218
- return this.request("POST", `/api/workflows/${name}/pause`);
219
- }
220
- async resume(name) {
221
- return this.request("POST", `/api/workflows/${name}/resume`);
222
- }
223
- async delete(name) {
224
- return this.request("DELETE", `/api/workflows/${name}`);
225
- }
226
- async listRuns(name, params) {
227
- const qs = new URLSearchParams;
228
- if (params?.status)
229
- qs.set("status", params.status);
230
- if (params?.limit !== undefined)
231
- qs.set("limit", String(params.limit));
232
- const query = qs.toString();
233
- return this.request("GET", `/api/workflows/${name}/runs${query ? `?${query}` : ""}`);
234
- }
235
- async getRun(runId) {
236
- return this.request("GET", `/api/workflows/runs/${runId}`);
237
- }
238
- }
239
- export {
240
- Workflows
241
- };
242
-
243
- //# debugId=653D77D9FE60E3F464756E2164756E21
244
- //# sourceMappingURL=index.js.map
@@ -1,12 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/errors.ts", "../src/base.ts", "../src/workflows/client.ts"],
4
- "sourcesContent": [
5
- "/**\n * Error thrown by {@link SecondLayer} when an API request fails.\n * Includes the HTTP status code for programmatic error handling.\n *\n * @example\n * ```ts\n * try {\n * await client.subgraphs.get(\"my-subgraph\");\n * } catch (err) {\n * if (err instanceof ApiError && err.status === 404) {\n * console.log(\"Subgraph not found\");\n * }\n * }\n * ```\n */\nexport class ApiError extends Error {\n\tconstructor(\n\t\t/** HTTP status code (0 for network errors). */\n\t\tpublic status: number,\n\t\tmessage: string,\n\t\t/** Raw response body (parsed JSON if possible) — preserved for callers that need error details. */\n\t\tpublic body?: unknown,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"ApiError\";\n\t}\n}\n\n/**\n * Thrown by {@link Workflows.deploy} when the server rejects a deploy because the\n * provided `expectedVersion` does not match the current stored version.\n */\nexport class VersionConflictError extends ApiError {\n\tconstructor(\n\t\tpublic currentVersion: string,\n\t\tpublic expectedVersion: string,\n\t\tmessage = `Version conflict: expected ${expectedVersion}, current ${currentVersion}`,\n\t) {\n\t\tsuper(409, message, { currentVersion, expectedVersion });\n\t\tthis.name = \"VersionConflictError\";\n\t}\n}\n",
6
- "import { ApiError } from \"./errors.ts\";\n\nexport interface SecondLayerOptions {\n\t/** Base URL of the Secondlayer API (trailing slashes are stripped). */\n\tbaseUrl: string;\n\t/** Bearer token for authenticated requests. */\n\tapiKey?: string;\n\t/** Deploy origin label sent as `x-sl-origin` (telemetry). Defaults to `cli`. */\n\torigin?: \"cli\" | \"mcp\" | \"session\";\n}\n\nconst DEFAULT_BASE_URL = \"https://api.secondlayer.tools\";\n\nexport abstract class BaseClient {\n\tprotected baseUrl: string;\n\tprotected apiKey?: string;\n\tprotected origin: \"cli\" | \"mcp\" | \"session\";\n\n\tconstructor(options: Partial<SecondLayerOptions> = {}) {\n\t\tthis.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n\t\tthis.apiKey = options.apiKey;\n\t\tthis.origin = options.origin ?? \"cli\";\n\t}\n\n\tstatic authHeaders(apiKey?: string): Record<string, string> {\n\t\tconst headers: Record<string, string> = {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t};\n\t\tif (apiKey) {\n\t\t\theaders.Authorization = `Bearer ${apiKey}`;\n\t\t}\n\t\treturn headers;\n\t}\n\n\tprotected async request<T>(\n\t\tmethod: string,\n\t\tpath: string,\n\t\tbody?: unknown,\n\t): Promise<T> {\n\t\tconst url = `${this.baseUrl}${path}`;\n\t\tconst headers = BaseClient.authHeaders(this.apiKey);\n\t\theaders[\"x-sl-origin\"] = this.origin;\n\n\t\tlet response: Response;\n\t\ttry {\n\t\t\tresponse = await fetch(url, {\n\t\t\t\tmethod,\n\t\t\t\theaders,\n\t\t\t\tbody: body ? JSON.stringify(body) : undefined,\n\t\t\t});\n\t\t} catch {\n\t\t\tthrow new ApiError(\n\t\t\t\t0,\n\t\t\t\t`Cannot reach API at ${this.baseUrl}. Check your connection or try again.`,\n\t\t\t);\n\t\t}\n\n\t\tif (!response.ok) {\n\t\t\tif (response.status === 401) {\n\t\t\t\tthrow new ApiError(401, \"API key invalid or expired.\");\n\t\t\t}\n\n\t\t\tif (response.status === 429) {\n\t\t\t\tconst retryAfter = response.headers.get(\"Retry-After\");\n\t\t\t\tconst msg = retryAfter\n\t\t\t\t\t? `Rate limited. Wait ${retryAfter} seconds.`\n\t\t\t\t\t: \"Rate limited. Try again later.\";\n\t\t\t\tthrow new ApiError(429, msg);\n\t\t\t}\n\n\t\t\tif (response.status >= 500) {\n\t\t\t\tthrow new ApiError(\n\t\t\t\t\tresponse.status,\n\t\t\t\t\t`Server error. Try again or check status at ${this.baseUrl}/health`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst errorBody = await response.text();\n\t\t\tlet message = `HTTP ${response.status}`;\n\t\t\tlet parsedBody: unknown = errorBody;\n\t\t\ttry {\n\t\t\t\tconst json = JSON.parse(errorBody);\n\t\t\t\tparsedBody = json;\n\t\t\t\tconst err = json.error ?? json.message;\n\t\t\t\tif (typeof err === \"string\") {\n\t\t\t\t\tmessage = err;\n\t\t\t\t} else if (err && typeof err === \"object\") {\n\t\t\t\t\tmessage = JSON.stringify(err);\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\tif (errorBody) message = errorBody;\n\t\t\t}\n\t\t\tthrow new ApiError(response.status, message, parsedBody);\n\t\t}\n\n\t\tif (response.status === 204) {\n\t\t\treturn undefined as T;\n\t\t}\n\n\t\treturn response.json() as Promise<T>;\n\t}\n}\n",
7
- "import type { WorkflowRun, WorkflowRunStatus } from \"@secondlayer/workflows\";\nimport { BaseClient } from \"../base.ts\";\nimport { ApiError, VersionConflictError } from \"../errors.ts\";\n\nfunction parseSseChunk(raw: string): WorkflowTailEvent | null {\n\tlet event = \"message\";\n\tconst dataLines: string[] = [];\n\tfor (const line of raw.split(\"\\n\")) {\n\t\tif (line.startsWith(\"event:\")) {\n\t\t\tevent = line.slice(6).trim();\n\t\t} else if (line.startsWith(\"data:\")) {\n\t\t\tdataLines.push(line.slice(5).trimStart());\n\t\t}\n\t}\n\tif (dataLines.length === 0) return null;\n\tconst data = dataLines.join(\"\\n\");\n\ttry {\n\t\tconst parsed = JSON.parse(data);\n\t\tswitch (event) {\n\t\t\tcase \"step\":\n\t\t\t\treturn { type: \"step\", step: parsed as WorkflowStepEvent };\n\t\t\tcase \"done\":\n\t\t\t\treturn { type: \"done\", done: parsed as WorkflowRunDoneEvent };\n\t\t\tcase \"heartbeat\":\n\t\t\t\treturn {\n\t\t\t\t\ttype: \"heartbeat\",\n\t\t\t\t\tts: typeof parsed === \"string\" ? parsed : String(parsed),\n\t\t\t\t};\n\t\t\tcase \"timeout\":\n\t\t\t\treturn {\n\t\t\t\t\ttype: \"timeout\",\n\t\t\t\t\tmessage: (parsed as { message?: string }).message ?? \"timeout\",\n\t\t\t\t};\n\t\t\tdefault:\n\t\t\t\treturn null;\n\t\t}\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport interface WorkflowSource {\n\tname: string;\n\tversion: string;\n\tsourceCode: string | null;\n\treadOnly: boolean;\n\treason?: string;\n\tupdatedAt: string;\n}\n\nexport interface WorkflowStepEvent {\n\tid: string;\n\tstepIndex: number;\n\tstepId: string;\n\tstepType: string;\n\tstatus: string;\n\toutput?: unknown;\n\terror: string | null;\n\tretryCount: number;\n\taiTokensUsed: number;\n\tstartedAt: string | null;\n\tcompletedAt: string | null;\n\tdurationMs: number | null;\n\tts: string;\n}\n\nexport interface WorkflowRunDoneEvent {\n\trunId: string;\n\tstatus: string;\n\terror?: string | null;\n\tcompletedAt?: string | null;\n}\n\nexport type WorkflowTailEvent =\n\t| { type: \"step\"; step: WorkflowStepEvent }\n\t| { type: \"done\"; done: WorkflowRunDoneEvent }\n\t| { type: \"heartbeat\"; ts: string }\n\t| { type: \"timeout\"; message: string };\n\nexport interface DeployDryRunResponse {\n\tvalid: boolean;\n\tvalidation?: { name: string; triggerType: string };\n\tbundleSize: number;\n\terror?: string;\n}\n\nexport interface DeployResponse {\n\taction: \"created\" | \"updated\";\n\tworkflowId: string;\n\tversion: string;\n\tmessage: string;\n}\n\nexport interface BundleWorkflowResponse {\n\tok: true;\n\tname: string;\n\ttrigger: Record<string, unknown>;\n\thandlerCode: string;\n\tsourceCode: string;\n\tretries: Record<string, unknown> | null;\n\ttimeout: number | null;\n\tbundleSize: number;\n}\n\nexport interface WorkflowSummary {\n\tname: string;\n\tstatus: \"active\" | \"paused\";\n\ttriggerType: \"event\" | \"schedule\" | \"manual\";\n\tcreatedAt: string;\n\tupdatedAt: string;\n}\n\nexport interface WorkflowDetail extends WorkflowSummary {\n\ttrigger: Record<string, unknown>;\n\tretries?: { maxAttempts?: number; backoffMs?: number };\n\ttimeout?: number;\n\ttotalRuns: number;\n\tlastRunAt: string | null;\n}\n\nexport interface WorkflowRunSummary {\n\tid: string;\n\tworkflowName: string;\n\tstatus: WorkflowRunStatus;\n\tduration: number;\n\taiTokensUsed: number;\n\ttriggeredAt: string;\n\tcompletedAt: string | null;\n}\n\nexport class Workflows extends BaseClient {\n\tasync deploy(\n\t\tdata: {\n\t\t\tname: string;\n\t\t\ttrigger: Record<string, unknown>;\n\t\t\thandlerCode: string;\n\t\t\tsourceCode?: string;\n\t\t\texpectedVersion?: string;\n\t\t\tretries?: Record<string, unknown>;\n\t\t\ttimeout?: number;\n\t\t\tclientRequestId?: string;\n\t\t} & { dryRun?: false },\n\t): Promise<DeployResponse>;\n\tasync deploy(data: {\n\t\tname: string;\n\t\ttrigger: Record<string, unknown>;\n\t\thandlerCode: string;\n\t\tsourceCode?: string;\n\t\texpectedVersion?: string;\n\t\tretries?: Record<string, unknown>;\n\t\ttimeout?: number;\n\t\tdryRun: true;\n\t}): Promise<DeployDryRunResponse>;\n\tasync deploy(data: {\n\t\tname: string;\n\t\ttrigger: Record<string, unknown>;\n\t\thandlerCode: string;\n\t\tsourceCode?: string;\n\t\texpectedVersion?: string;\n\t\tdryRun?: boolean;\n\t\tclientRequestId?: string;\n\t\tretries?: Record<string, unknown>;\n\t\ttimeout?: number;\n\t}): Promise<DeployResponse | DeployDryRunResponse> {\n\t\ttry {\n\t\t\treturn await this.request(\"POST\", \"/api/workflows\", data);\n\t\t} catch (err) {\n\t\t\tif (err instanceof ApiError && err.status === 409) {\n\t\t\t\tconst body = err.body as\n\t\t\t\t\t| { currentVersion?: string; expectedVersion?: string }\n\t\t\t\t\t| undefined;\n\t\t\t\tif (body?.currentVersion && body.expectedVersion) {\n\t\t\t\t\tthrow new VersionConflictError(\n\t\t\t\t\t\tbody.currentVersion,\n\t\t\t\t\t\tbody.expectedVersion,\n\t\t\t\t\t\terr.message,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\tasync getSource(name: string): Promise<WorkflowSource> {\n\t\treturn this.request(\"GET\", `/api/workflows/${name}/source`);\n\t}\n\n\t/**\n\t * Bundle a TypeScript workflow source on the server. Used by the web chat\n\t * authoring loop so Vercel's serverless runtime doesn't have to run esbuild.\n\t * CLI and MCP still bundle locally — this method is for clients that can't\n\t * install `@secondlayer/bundler` directly (e.g. browser tooling, edge\n\t * functions).\n\t */\n\tasync bundle(data: { code: string }): Promise<BundleWorkflowResponse> {\n\t\treturn this.request(\"POST\", \"/api/workflows/bundle\", data);\n\t}\n\n\tasync pauseAll(): Promise<{\n\t\tpaused: number;\n\t\tworkflows: Array<{ name: string; version: string; status: string }>;\n\t}> {\n\t\treturn this.request(\"POST\", \"/api/workflows/pause-all\");\n\t}\n\n\tasync cancelRun(runId: string): Promise<{\n\t\trunId: string;\n\t\tstatus: string;\n\t\tcancelled: boolean;\n\t\tcompletedAt?: string;\n\t\tmessage?: string;\n\t}> {\n\t\treturn this.request(\"POST\", `/api/workflows/runs/${runId}/cancel`);\n\t}\n\n\tasync rollback(\n\t\tname: string,\n\t\ttoVersion?: string,\n\t): Promise<{\n\t\taction: \"rolled-back\";\n\t\tname: string;\n\t\tfromVersion: string;\n\t\trestoredFromVersion: string;\n\t\tversion: string;\n\t}> {\n\t\treturn this.request(\n\t\t\t\"POST\",\n\t\t\t`/api/workflows/${name}/rollback`,\n\t\t\ttoVersion ? { toVersion } : {},\n\t\t);\n\t}\n\n\t/**\n\t * Subscribe to a workflow run's server-sent event stream. Resolves when the\n\t * run completes, times out, or the signal is aborted. Throws on HTTP errors\n\t * opening the stream.\n\t */\n\tasync streamRun(\n\t\tname: string,\n\t\trunId: string,\n\t\tonEvent: (event: WorkflowTailEvent) => void,\n\t\tsignal?: AbortSignal,\n\t): Promise<void> {\n\t\tconst url = `${this.baseUrl}/api/workflows/${name}/runs/${runId}/stream`;\n\t\tconst headers: Record<string, string> = {\n\t\t\tAccept: \"text/event-stream\",\n\t\t\t\"x-sl-origin\": this.origin,\n\t\t};\n\t\tif (this.apiKey) {\n\t\t\theaders.Authorization = `Bearer ${this.apiKey}`;\n\t\t}\n\n\t\tconst res = await fetch(url, { headers, signal });\n\t\tif (!res.ok || !res.body) {\n\t\t\tthrow new ApiError(\n\t\t\t\tres.status,\n\t\t\t\t`Failed to open workflow run stream (HTTP ${res.status})`,\n\t\t\t);\n\t\t}\n\n\t\tconst reader = res.body.pipeThrough(new TextDecoderStream()).getReader();\n\t\tlet buffer = \"\";\n\n\t\twhile (true) {\n\t\t\tconst { value, done } = await reader.read();\n\t\t\tif (done) break;\n\t\t\tbuffer += value;\n\n\t\t\tlet sep = buffer.indexOf(\"\\n\\n\");\n\t\t\twhile (sep !== -1) {\n\t\t\t\tconst chunk = buffer.slice(0, sep);\n\t\t\t\tbuffer = buffer.slice(sep + 2);\n\t\t\t\tconst parsed = parseSseChunk(chunk);\n\t\t\t\tif (parsed) {\n\t\t\t\t\tonEvent(parsed);\n\t\t\t\t\tif (parsed.type === \"done\" || parsed.type === \"timeout\") {\n\t\t\t\t\t\tawait reader.cancel().catch(() => undefined);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tsep = buffer.indexOf(\"\\n\\n\");\n\t\t\t}\n\t\t}\n\t}\n\n\tasync list(): Promise<{ workflows: WorkflowSummary[] }> {\n\t\treturn this.request(\"GET\", \"/api/workflows\");\n\t}\n\n\tasync get(name: string): Promise<WorkflowDetail> {\n\t\treturn this.request(\"GET\", `/api/workflows/${name}`);\n\t}\n\n\tasync trigger(\n\t\tname: string,\n\t\tinput?: Record<string, unknown>,\n\t): Promise<{ runId: string }> {\n\t\treturn this.request(\n\t\t\t\"POST\",\n\t\t\t`/api/workflows/${name}/trigger`,\n\t\t\tinput ? { input } : undefined,\n\t\t);\n\t}\n\n\tasync pause(name: string): Promise<void> {\n\t\treturn this.request(\"POST\", `/api/workflows/${name}/pause`);\n\t}\n\n\tasync resume(name: string): Promise<void> {\n\t\treturn this.request(\"POST\", `/api/workflows/${name}/resume`);\n\t}\n\n\tasync delete(name: string): Promise<void> {\n\t\treturn this.request(\"DELETE\", `/api/workflows/${name}`);\n\t}\n\n\tasync listRuns(\n\t\tname: string,\n\t\tparams?: { status?: WorkflowRunStatus; limit?: number },\n\t): Promise<{ runs: WorkflowRunSummary[] }> {\n\t\tconst qs = new URLSearchParams();\n\t\tif (params?.status) qs.set(\"status\", params.status);\n\t\tif (params?.limit !== undefined) qs.set(\"limit\", String(params.limit));\n\t\tconst query = qs.toString();\n\t\treturn this.request(\n\t\t\t\"GET\",\n\t\t\t`/api/workflows/${name}/runs${query ? `?${query}` : \"\"}`,\n\t\t);\n\t}\n\n\tasync getRun(runId: string): Promise<WorkflowRun> {\n\t\treturn this.request(\"GET\", `/api/workflows/runs/${runId}`);\n\t}\n}\n"
8
- ],
9
- "mappings": ";AAeO,MAAM,iBAAiB,MAAM;AAAA,EAG3B;AAAA,EAGA;AAAA,EALR,WAAW,CAEH,QACP,SAEO,MACN;AAAA,IACD,MAAM,OAAO;AAAA,IALN;AAAA,IAGA;AAAA,IAGP,KAAK,OAAO;AAAA;AAEd;AAAA;AAMO,MAAM,6BAA6B,SAAS;AAAA,EAE1C;AAAA,EACA;AAAA,EAFR,WAAW,CACH,gBACA,iBACP,UAAU,8BAA8B,4BAA4B,kBACnE;AAAA,IACD,MAAM,KAAK,SAAS,EAAE,gBAAgB,gBAAgB,CAAC;AAAA,IAJhD;AAAA,IACA;AAAA,IAIP,KAAK,OAAO;AAAA;AAEd;;;AC9BA,IAAM,mBAAmB;AAAA;AAElB,MAAe,WAAW;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EAEV,WAAW,CAAC,UAAuC,CAAC,GAAG;AAAA,IACtD,KAAK,WAAW,QAAQ,WAAW,kBAAkB,QAAQ,QAAQ,EAAE;AAAA,IACvE,KAAK,SAAS,QAAQ;AAAA,IACtB,KAAK,SAAS,QAAQ,UAAU;AAAA;AAAA,SAG1B,WAAW,CAAC,QAAyC;AAAA,IAC3D,MAAM,UAAkC;AAAA,MACvC,gBAAgB;AAAA,IACjB;AAAA,IACA,IAAI,QAAQ;AAAA,MACX,QAAQ,gBAAgB,UAAU;AAAA,IACnC;AAAA,IACA,OAAO;AAAA;AAAA,OAGQ,QAAU,CACzB,QACA,MACA,MACa;AAAA,IACb,MAAM,MAAM,GAAG,KAAK,UAAU;AAAA,IAC9B,MAAM,UAAU,WAAW,YAAY,KAAK,MAAM;AAAA,IAClD,QAAQ,iBAAiB,KAAK;AAAA,IAE9B,IAAI;AAAA,IACJ,IAAI;AAAA,MACH,WAAW,MAAM,MAAM,KAAK;AAAA,QAC3B;AAAA,QACA;AAAA,QACA,MAAM,OAAO,KAAK,UAAU,IAAI,IAAI;AAAA,MACrC,CAAC;AAAA,MACA,MAAM;AAAA,MACP,MAAM,IAAI,SACT,GACA,uBAAuB,KAAK,8CAC7B;AAAA;AAAA,IAGD,IAAI,CAAC,SAAS,IAAI;AAAA,MACjB,IAAI,SAAS,WAAW,KAAK;AAAA,QAC5B,MAAM,IAAI,SAAS,KAAK,6BAA6B;AAAA,MACtD;AAAA,MAEA,IAAI,SAAS,WAAW,KAAK;AAAA,QAC5B,MAAM,aAAa,SAAS,QAAQ,IAAI,aAAa;AAAA,QACrD,MAAM,MAAM,aACT,sBAAsB,wBACtB;AAAA,QACH,MAAM,IAAI,SAAS,KAAK,GAAG;AAAA,MAC5B;AAAA,MAEA,IAAI,SAAS,UAAU,KAAK;AAAA,QAC3B,MAAM,IAAI,SACT,SAAS,QACT,8CAA8C,KAAK,gBACpD;AAAA,MACD;AAAA,MAEA,MAAM,YAAY,MAAM,SAAS,KAAK;AAAA,MACtC,IAAI,UAAU,QAAQ,SAAS;AAAA,MAC/B,IAAI,aAAsB;AAAA,MAC1B,IAAI;AAAA,QACH,MAAM,OAAO,KAAK,MAAM,SAAS;AAAA,QACjC,aAAa;AAAA,QACb,MAAM,MAAM,KAAK,SAAS,KAAK;AAAA,QAC/B,IAAI,OAAO,QAAQ,UAAU;AAAA,UAC5B,UAAU;AAAA,QACX,EAAO,SAAI,OAAO,OAAO,QAAQ,UAAU;AAAA,UAC1C,UAAU,KAAK,UAAU,GAAG;AAAA,QAC7B;AAAA,QACC,MAAM;AAAA,QACP,IAAI;AAAA,UAAW,UAAU;AAAA;AAAA,MAE1B,MAAM,IAAI,SAAS,SAAS,QAAQ,SAAS,UAAU;AAAA,IACxD;AAAA,IAEA,IAAI,SAAS,WAAW,KAAK;AAAA,MAC5B;AAAA,IACD;AAAA,IAEA,OAAO,SAAS,KAAK;AAAA;AAEvB;;;ACjGA,SAAS,aAAa,CAAC,KAAuC;AAAA,EAC7D,IAAI,QAAQ;AAAA,EACZ,MAAM,YAAsB,CAAC;AAAA,EAC7B,WAAW,QAAQ,IAAI,MAAM;AAAA,CAAI,GAAG;AAAA,IACnC,IAAI,KAAK,WAAW,QAAQ,GAAG;AAAA,MAC9B,QAAQ,KAAK,MAAM,CAAC,EAAE,KAAK;AAAA,IAC5B,EAAO,SAAI,KAAK,WAAW,OAAO,GAAG;AAAA,MACpC,UAAU,KAAK,KAAK,MAAM,CAAC,EAAE,UAAU,CAAC;AAAA,IACzC;AAAA,EACD;AAAA,EACA,IAAI,UAAU,WAAW;AAAA,IAAG,OAAO;AAAA,EACnC,MAAM,OAAO,UAAU,KAAK;AAAA,CAAI;AAAA,EAChC,IAAI;AAAA,IACH,MAAM,SAAS,KAAK,MAAM,IAAI;AAAA,IAC9B,QAAQ;AAAA,WACF;AAAA,QACJ,OAAO,EAAE,MAAM,QAAQ,MAAM,OAA4B;AAAA,WACrD;AAAA,QACJ,OAAO,EAAE,MAAM,QAAQ,MAAM,OAA+B;AAAA,WACxD;AAAA,QACJ,OAAO;AAAA,UACN,MAAM;AAAA,UACN,IAAI,OAAO,WAAW,WAAW,SAAS,OAAO,MAAM;AAAA,QACxD;AAAA,WACI;AAAA,QACJ,OAAO;AAAA,UACN,MAAM;AAAA,UACN,SAAU,OAAgC,WAAW;AAAA,QACtD;AAAA;AAAA,QAEA,OAAO;AAAA;AAAA,IAER,MAAM;AAAA,IACP,OAAO;AAAA;AAAA;AAAA;AA6FF,MAAM,kBAAkB,WAAW;AAAA,OAuBnC,OAAM,CAAC,MAUsC;AAAA,IAClD,IAAI;AAAA,MACH,OAAO,MAAM,KAAK,QAAQ,QAAQ,kBAAkB,IAAI;AAAA,MACvD,OAAO,KAAK;AAAA,MACb,IAAI,eAAe,YAAY,IAAI,WAAW,KAAK;AAAA,QAClD,MAAM,OAAO,IAAI;AAAA,QAGjB,IAAI,MAAM,kBAAkB,KAAK,iBAAiB;AAAA,UACjD,MAAM,IAAI,qBACT,KAAK,gBACL,KAAK,iBACL,IAAI,OACL;AAAA,QACD;AAAA,MACD;AAAA,MACA,MAAM;AAAA;AAAA;AAAA,OAIF,UAAS,CAAC,MAAuC;AAAA,IACtD,OAAO,KAAK,QAAQ,OAAO,kBAAkB,aAAa;AAAA;AAAA,OAUrD,OAAM,CAAC,MAAyD;AAAA,IACrE,OAAO,KAAK,QAAQ,QAAQ,yBAAyB,IAAI;AAAA;AAAA,OAGpD,SAAQ,GAGX;AAAA,IACF,OAAO,KAAK,QAAQ,QAAQ,0BAA0B;AAAA;AAAA,OAGjD,UAAS,CAAC,OAMb;AAAA,IACF,OAAO,KAAK,QAAQ,QAAQ,uBAAuB,cAAc;AAAA;AAAA,OAG5D,SAAQ,CACb,MACA,WAOE;AAAA,IACF,OAAO,KAAK,QACX,QACA,kBAAkB,iBAClB,YAAY,EAAE,UAAU,IAAI,CAAC,CAC9B;AAAA;AAAA,OAQK,UAAS,CACd,MACA,OACA,SACA,QACgB;AAAA,IAChB,MAAM,MAAM,GAAG,KAAK,yBAAyB,aAAa;AAAA,IAC1D,MAAM,UAAkC;AAAA,MACvC,QAAQ;AAAA,MACR,eAAe,KAAK;AAAA,IACrB;AAAA,IACA,IAAI,KAAK,QAAQ;AAAA,MAChB,QAAQ,gBAAgB,UAAU,KAAK;AAAA,IACxC;AAAA,IAEA,MAAM,MAAM,MAAM,MAAM,KAAK,EAAE,SAAS,OAAO,CAAC;AAAA,IAChD,IAAI,CAAC,IAAI,MAAM,CAAC,IAAI,MAAM;AAAA,MACzB,MAAM,IAAI,SACT,IAAI,QACJ,4CAA4C,IAAI,SACjD;AAAA,IACD;AAAA,IAEA,MAAM,SAAS,IAAI,KAAK,YAAY,IAAI,iBAAmB,EAAE,UAAU;AAAA,IACvE,IAAI,SAAS;AAAA,IAEb,OAAO,MAAM;AAAA,MACZ,QAAQ,OAAO,SAAS,MAAM,OAAO,KAAK;AAAA,MAC1C,IAAI;AAAA,QAAM;AAAA,MACV,UAAU;AAAA,MAEV,IAAI,MAAM,OAAO,QAAQ;AAAA;AAAA,CAAM;AAAA,MAC/B,OAAO,QAAQ,IAAI;AAAA,QAClB,MAAM,QAAQ,OAAO,MAAM,GAAG,GAAG;AAAA,QACjC,SAAS,OAAO,MAAM,MAAM,CAAC;AAAA,QAC7B,MAAM,SAAS,cAAc,KAAK;AAAA,QAClC,IAAI,QAAQ;AAAA,UACX,QAAQ,MAAM;AAAA,UACd,IAAI,OAAO,SAAS,UAAU,OAAO,SAAS,WAAW;AAAA,YACxD,MAAM,OAAO,OAAO,EAAE,MAAM,MAAG;AAAA,cAAG;AAAA,aAAS;AAAA,YAC3C;AAAA,UACD;AAAA,QACD;AAAA,QACA,MAAM,OAAO,QAAQ;AAAA;AAAA,CAAM;AAAA,MAC5B;AAAA,IACD;AAAA;AAAA,OAGK,KAAI,GAA8C;AAAA,IACvD,OAAO,KAAK,QAAQ,OAAO,gBAAgB;AAAA;AAAA,OAGtC,IAAG,CAAC,MAAuC;AAAA,IAChD,OAAO,KAAK,QAAQ,OAAO,kBAAkB,MAAM;AAAA;AAAA,OAG9C,QAAO,CACZ,MACA,OAC6B;AAAA,IAC7B,OAAO,KAAK,QACX,QACA,kBAAkB,gBAClB,QAAQ,EAAE,MAAM,IAAI,SACrB;AAAA;AAAA,OAGK,MAAK,CAAC,MAA6B;AAAA,IACxC,OAAO,KAAK,QAAQ,QAAQ,kBAAkB,YAAY;AAAA;AAAA,OAGrD,OAAM,CAAC,MAA6B;AAAA,IACzC,OAAO,KAAK,QAAQ,QAAQ,kBAAkB,aAAa;AAAA;AAAA,OAGtD,OAAM,CAAC,MAA6B;AAAA,IACzC,OAAO,KAAK,QAAQ,UAAU,kBAAkB,MAAM;AAAA;AAAA,OAGjD,SAAQ,CACb,MACA,QAC0C;AAAA,IAC1C,MAAM,KAAK,IAAI;AAAA,IACf,IAAI,QAAQ;AAAA,MAAQ,GAAG,IAAI,UAAU,OAAO,MAAM;AAAA,IAClD,IAAI,QAAQ,UAAU;AAAA,MAAW,GAAG,IAAI,SAAS,OAAO,OAAO,KAAK,CAAC;AAAA,IACrE,MAAM,QAAQ,GAAG,SAAS;AAAA,IAC1B,OAAO,KAAK,QACX,OACA,kBAAkB,YAAY,QAAQ,IAAI,UAAU,IACrD;AAAA;AAAA,OAGK,OAAM,CAAC,OAAqC;AAAA,IACjD,OAAO,KAAK,QAAQ,OAAO,uBAAuB,OAAO;AAAA;AAE3D;",
10
- "debugId": "653D77D9FE60E3F464756E2164756E21",
11
- "names": []
12
- }