@letsping/sdk 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,37 +1,44 @@
1
- type Priority = "low" | "medium" | "high" | "critical";
2
- interface RequestOptions {
1
+ export type Priority = "low" | "medium" | "high" | "critical";
2
+ export interface RequestOptions {
3
3
  service: string;
4
4
  action: string;
5
5
  payload: Record<string, any>;
6
6
  priority?: Priority;
7
7
  schema?: Record<string, any>;
8
8
  timeoutMs?: number;
9
+ role?: string;
9
10
  }
10
- interface Decision {
11
- status: "APPROVED" | "REJECTED";
11
+ export interface Decision {
12
+ status: "APPROVED" | "REJECTED" | "APPROVED_WITH_MODIFICATIONS";
12
13
  payload: any;
13
14
  patched_payload?: any;
15
+ diff_summary?: any;
14
16
  metadata?: {
15
17
  resolved_at: string;
16
18
  actor_id: string;
17
19
  method?: string;
18
20
  };
19
21
  }
20
- declare class LetsPingError extends Error {
22
+ export declare class LetsPingError extends Error {
21
23
  status?: number | undefined;
22
24
  constructor(message: string, status?: number | undefined);
23
25
  }
24
- declare class LetsPing {
26
+ declare function computeDiff(original: any, patched: any): any;
27
+ export declare class LetsPing {
25
28
  private readonly apiKey;
26
29
  private readonly baseUrl;
30
+ private readonly encryptionKey;
27
31
  constructor(apiKey?: string, options?: {
28
32
  baseUrl?: string;
33
+ encryptionKey?: string;
29
34
  });
35
+ private _encrypt;
36
+ private _decrypt;
30
37
  ask(options: RequestOptions): Promise<Decision>;
31
38
  defer(options: RequestOptions): Promise<{
32
39
  id: string;
33
40
  }>;
34
41
  private request;
42
+ tool(service: string, action: string, priority?: Priority): (context: string | Record<string, any>) => Promise<string>;
35
43
  }
36
-
37
- export { type Decision, LetsPing, LetsPingError, type Priority, type RequestOptions };
44
+ export { computeDiff };
package/dist/index.js CHANGED
@@ -3,6 +3,9 @@ var __defProp = Object.defineProperty;
3
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __commonJS = (cb, mod) => function __require() {
7
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
8
+ };
6
9
  var __export = (target, all) => {
7
10
  for (var name in all)
8
11
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -17,13 +20,58 @@ var __copyProps = (to, from, except, desc) => {
17
20
  };
18
21
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
22
 
23
+ // package.json
24
+ var require_package = __commonJS({
25
+ "package.json"(exports2, module2) {
26
+ module2.exports = {
27
+ name: "@letsping/sdk",
28
+ version: "0.1.3",
29
+ description: "The Human-in-the-Loop SDK for Autonomous Agents",
30
+ main: "./dist/index.js",
31
+ module: "./dist/index.mjs",
32
+ files: [
33
+ "dist"
34
+ ],
35
+ types: "./dist/index.d.ts",
36
+ exports: {
37
+ ".": {
38
+ types: "./dist/index.d.ts",
39
+ require: "./dist/index.js",
40
+ import: "./dist/index.mjs"
41
+ }
42
+ },
43
+ scripts: {
44
+ build: "tsup && tsc --emitDeclarationOnly --outDir dist",
45
+ dev: "tsup --watch",
46
+ clean: "rm -rf dist .turbo"
47
+ },
48
+ dependencies: {},
49
+ devDependencies: {
50
+ tsup: "^8.0.0",
51
+ typescript: "^5.7.2",
52
+ "@types/node": "^22.0.0"
53
+ },
54
+ publishConfig: {
55
+ access: "public"
56
+ }
57
+ };
58
+ }
59
+ });
60
+
20
61
  // src/index.ts
21
62
  var index_exports = {};
22
63
  __export(index_exports, {
23
64
  LetsPing: () => LetsPing,
24
- LetsPingError: () => LetsPingError
65
+ LetsPingError: () => LetsPingError,
66
+ computeDiff: () => computeDiff
25
67
  });
26
68
  module.exports = __toCommonJS(index_exports);
69
+ var import_node_crypto = require("crypto");
70
+ var SDK_VERSION = "0.1.2";
71
+ try {
72
+ SDK_VERSION = require_package().version;
73
+ } catch {
74
+ }
27
75
  var LetsPingError = class extends Error {
28
76
  constructor(message, status) {
29
77
  super(message);
@@ -31,12 +79,81 @@ var LetsPingError = class extends Error {
31
79
  this.name = "LetsPingError";
32
80
  }
33
81
  };
82
+ function isEncEnvelope(v) {
83
+ return typeof v === "object" && v !== null && v._lp_enc === true && typeof v.iv === "string" && typeof v.ct === "string";
84
+ }
85
+ function encryptPayload(keyBase64, payload) {
86
+ const keyBuf = Buffer.from(keyBase64, "base64");
87
+ const iv = (0, import_node_crypto.randomBytes)(12);
88
+ const cipher = (0, import_node_crypto.createCipheriv)("aes-256-gcm", keyBuf, iv);
89
+ const plain = Buffer.from(JSON.stringify(payload), "utf8");
90
+ const ct = Buffer.concat([cipher.update(plain), cipher.final(), cipher.getAuthTag()]);
91
+ return {
92
+ _lp_enc: true,
93
+ iv: iv.toString("base64"),
94
+ ct: ct.toString("base64")
95
+ };
96
+ }
97
+ function decryptPayload(keyBase64, envelope) {
98
+ const keyBuf = Buffer.from(keyBase64, "base64");
99
+ const iv = Buffer.from(envelope.iv, "base64");
100
+ const ctFull = Buffer.from(envelope.ct, "base64");
101
+ const authTag = ctFull.subarray(ctFull.length - 16);
102
+ const ct = ctFull.subarray(0, ctFull.length - 16);
103
+ const decipher = (0, import_node_crypto.createDecipheriv)("aes-256-gcm", keyBuf, iv);
104
+ decipher.setAuthTag(authTag);
105
+ const plain = Buffer.concat([decipher.update(ct), decipher.final()]);
106
+ return JSON.parse(plain.toString("utf8"));
107
+ }
108
+ function computeDiff(original, patched) {
109
+ if (original === patched) return null;
110
+ if (typeof original !== "object" || typeof patched !== "object" || original === null || patched === null || Array.isArray(original) || Array.isArray(patched)) {
111
+ if (JSON.stringify(original) !== JSON.stringify(patched)) {
112
+ return { from: original, to: patched };
113
+ }
114
+ return null;
115
+ }
116
+ const changes = {};
117
+ let hasChanges = false;
118
+ const allKeys = /* @__PURE__ */ new Set([...Object.keys(original), ...Object.keys(patched)]);
119
+ for (const key of allKeys) {
120
+ const oV = original[key];
121
+ const pV = patched[key];
122
+ if (!(key in original)) {
123
+ changes[key] = { from: void 0, to: pV };
124
+ hasChanges = true;
125
+ } else if (!(key in patched)) {
126
+ changes[key] = { from: oV, to: void 0 };
127
+ hasChanges = true;
128
+ } else {
129
+ const nestedDiff = computeDiff(oV, pV);
130
+ if (nestedDiff) {
131
+ changes[key] = nestedDiff;
132
+ hasChanges = true;
133
+ }
134
+ }
135
+ }
136
+ return hasChanges ? changes : null;
137
+ }
34
138
  var LetsPing = class {
35
139
  constructor(apiKey, options) {
36
140
  const key = apiKey || process.env.LETSPING_API_KEY;
37
141
  if (!key) throw new Error("LetsPing: API Key is required. Pass it to the constructor or set LETSPING_API_KEY env var.");
38
142
  this.apiKey = key;
39
143
  this.baseUrl = options?.baseUrl || "https://letsping.co/api";
144
+ this.encryptionKey = options?.encryptionKey ?? process.env.LETSPING_ENCRYPTION_KEY ?? null;
145
+ }
146
+ _encrypt(payload) {
147
+ if (!this.encryptionKey) return payload;
148
+ return encryptPayload(this.encryptionKey, payload);
149
+ }
150
+ _decrypt(val) {
151
+ if (!this.encryptionKey || !isEncEnvelope(val)) return val;
152
+ try {
153
+ return decryptPayload(this.encryptionKey, val);
154
+ } catch {
155
+ return val;
156
+ }
40
157
  }
41
158
  async ask(options) {
42
159
  if (options.schema && options.schema._def) {
@@ -45,13 +162,10 @@ var LetsPing = class {
45
162
  const { id } = await this.request("POST", "/ingest", {
46
163
  service: options.service,
47
164
  action: options.action,
48
- payload: options.payload,
165
+ payload: this._encrypt(options.payload),
49
166
  priority: options.priority || "medium",
50
167
  schema: options.schema,
51
- metadata: {
52
- role: options.role,
53
- sdk: "node"
54
- }
168
+ metadata: { role: options.role, sdk: "node" }
55
169
  });
56
170
  const timeout = options.timeoutMs || 24 * 60 * 60 * 1e3;
57
171
  const start = Date.now();
@@ -61,10 +175,20 @@ var LetsPing = class {
61
175
  try {
62
176
  const check = await this.request("GET", `/status/${id}`);
63
177
  if (check.status === "APPROVED" || check.status === "REJECTED") {
178
+ const decryptedPayload = this._decrypt(check.payload) ?? options.payload;
179
+ const decryptedPatched = check.patched_payload ? this._decrypt(check.patched_payload) : void 0;
180
+ let diff_summary;
181
+ let finalStatus = check.status;
182
+ if (check.status === "APPROVED" && decryptedPatched !== void 0) {
183
+ finalStatus = "APPROVED_WITH_MODIFICATIONS";
184
+ const diff = computeDiff(decryptedPayload, decryptedPatched);
185
+ diff_summary = diff ? { changes: diff } : { changes: "Unknown structure changes" };
186
+ }
64
187
  return {
65
- status: check.status,
66
- payload: options.payload,
67
- patched_payload: check.patched_payload || options.payload,
188
+ status: finalStatus,
189
+ payload: decryptedPayload,
190
+ patched_payload: decryptedPatched,
191
+ diff_summary,
68
192
  metadata: {
69
193
  resolved_at: check.resolved_at,
70
194
  actor_id: check.actor_id
@@ -72,10 +196,8 @@ var LetsPing = class {
72
196
  };
73
197
  }
74
198
  } catch (e) {
75
- const status = e.status;
76
- if (status && status >= 400 && status < 500 && status !== 404 && status !== 429) {
77
- throw e;
78
- }
199
+ const s = e.status;
200
+ if (s && s >= 400 && s < 500 && s !== 404 && s !== 429) throw e;
79
201
  }
80
202
  const jitter = Math.random() * 200;
81
203
  await new Promise((r) => setTimeout(r, delay + jitter));
@@ -84,13 +206,16 @@ var LetsPing = class {
84
206
  throw new LetsPingError(`Request ${id} timed out waiting for approval.`);
85
207
  }
86
208
  async defer(options) {
87
- return this.request("POST", "/ingest", options);
209
+ return this.request("POST", "/ingest", {
210
+ ...options,
211
+ payload: this._encrypt(options.payload)
212
+ });
88
213
  }
89
214
  async request(method, path, body) {
90
215
  const headers = {
91
216
  "Authorization": `Bearer ${this.apiKey}`,
92
217
  "Content-Type": "application/json",
93
- "User-Agent": "letsping-node/0.1.2"
218
+ "User-Agent": `letsping-node/${SDK_VERSION}`
94
219
  };
95
220
  try {
96
221
  const response = await fetch(`${this.baseUrl}${path}`, {
@@ -129,17 +254,23 @@ var LetsPing = class {
129
254
  } else {
130
255
  payload = { raw_context: String(context) };
131
256
  }
132
- const result = await this.ask({
133
- service,
134
- action,
135
- payload,
136
- priority
137
- });
257
+ const result = await this.ask({ service, action, payload, priority });
138
258
  if (result.status === "REJECTED") {
139
- return `STOP: Action Rejected by Human.`;
259
+ return "STOP: Action Rejected by Human.";
140
260
  }
141
- const finalPayload = result.patched_payload || result.payload;
142
- return JSON.stringify(finalPayload);
261
+ if (result.status === "APPROVED_WITH_MODIFICATIONS") {
262
+ return JSON.stringify({
263
+ status: "APPROVED_WITH_MODIFICATIONS",
264
+ message: "The human reviewer authorized this action but modified your original payload. Please review the diff_summary to learn from this correction.",
265
+ diff_summary: result.diff_summary,
266
+ original_payload: result.payload,
267
+ executed_payload: result.patched_payload
268
+ });
269
+ }
270
+ return JSON.stringify({
271
+ status: "APPROVED",
272
+ executed_payload: result.payload
273
+ });
143
274
  } catch (e) {
144
275
  return `ERROR: System Failure: ${e.message}`;
145
276
  }
@@ -149,6 +280,7 @@ var LetsPing = class {
149
280
  // Annotate the CommonJS export names for ESM import in node:
150
281
  0 && (module.exports = {
151
282
  LetsPing,
152
- LetsPingError
283
+ LetsPingError,
284
+ computeDiff
153
285
  });
154
286
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export type Priority = \"low\" | \"medium\" | \"high\" | \"critical\";\r\n\r\n/**\r\n * Options for configuring a LetsPing approval request.\r\n */\r\nexport interface RequestOptions {\r\n /** Name of the agent or service (e.g., \"billing-agent\") */\r\n service: string;\r\n /** Specific action being requested (e.g., \"refund_user\") */\r\n action: string;\r\n /** The data payload to be reviewed by the human */\r\n payload: Record<string, any>;\r\n /** Urgency level affecting notification routing (default: \"medium\") */\r\n priority?: Priority;\r\n /** JSON Schema (Draft 7) for rendering a structured form in the dashboard */\r\n schema?: Record<string, any>;\r\n /** Maximum time to wait for approval in milliseconds (default: 24h) */\r\n timeoutMs?: number;\r\n /** (Enterprise) Specific role required for approval (e.g., \"finance\") */\r\n role?: string;\r\n}\r\n\r\n/**\r\n * The result of a human approval decision.\r\n */\r\nexport interface Decision {\r\n status: \"APPROVED\" | \"REJECTED\";\r\n /** The original payload submitted */\r\n payload: any;\r\n /** The modified payload if the human edited values during approval */\r\n patched_payload?: any;\r\n metadata?: {\r\n resolved_at: string;\r\n actor_id: string;\r\n method?: string;\r\n };\r\n}\r\n\r\nexport class LetsPingError extends Error {\r\n constructor(message: string, public status?: number) {\r\n super(message);\r\n this.name = \"LetsPingError\";\r\n }\r\n}\r\n\r\nexport class LetsPing {\r\n private readonly apiKey: string;\r\n private readonly baseUrl: string;\r\n\r\n constructor(apiKey?: string, options?: { baseUrl?: string }) {\r\n const key = apiKey || process.env.LETSPING_API_KEY;\r\n if (!key) throw new Error(\"LetsPing: API Key is required. Pass it to the constructor or set LETSPING_API_KEY env var.\");\r\n\r\n this.apiKey = key;\r\n this.baseUrl = options?.baseUrl || \"https://letsping.co/api\";\r\n }\r\n\r\n async ask(options: RequestOptions): Promise<Decision> {\r\n if (options.schema && (options.schema as any)._def) {\r\n throw new LetsPingError(\"LetsPing Error: Raw Zod schema detected. You must convert it to JSON Schema (e.g. using 'zod-to-json-schema') before passing it to the SDK.\");\r\n }\r\n\r\n const { id } = await this.request<{ id: string }>(\"POST\", \"/ingest\", {\r\n service: options.service,\r\n action: options.action,\r\n payload: options.payload,\r\n priority: options.priority || \"medium\",\r\n schema: options.schema,\r\n metadata: {\r\n role: options.role,\r\n sdk: \"node\"\r\n }\r\n });\r\n\r\n const timeout = options.timeoutMs || 24 * 60 * 60 * 1000;\r\n const start = Date.now();\r\n let delay = 1000;\r\n const maxDelay = 10000;\r\n\r\n while (Date.now() - start < timeout) {\r\n try {\r\n const check = await this.request<any>(\"GET\", `/status/${id}`);\r\n\r\n if (check.status === \"APPROVED\" || check.status === \"REJECTED\") {\r\n return {\r\n status: check.status,\r\n payload: options.payload,\r\n patched_payload: check.patched_payload || options.payload,\r\n metadata: {\r\n resolved_at: check.resolved_at,\r\n actor_id: check.actor_id\r\n }\r\n };\r\n }\r\n } catch (e: any) {\r\n // Retry on:\r\n // 1. Network errors (status is undefined)\r\n // 2. 404 (not found yet)\r\n // 3. 429 (rate limit)\r\n // 4. 5xx (server error)\r\n // Fail on: 400, 401, 403 (client errors)\r\n const status = e.status;\r\n if (status && status >= 400 && status < 500 && status !== 404 && status !== 429) {\r\n throw e;\r\n }\r\n }\r\n\r\n const jitter = Math.random() * 200;\r\n await new Promise(r => setTimeout(r, delay + jitter));\r\n delay = Math.min(delay * 1.5, maxDelay);\r\n }\r\n\r\n throw new LetsPingError(`Request ${id} timed out waiting for approval.`);\r\n }\r\n\r\n async defer(options: RequestOptions): Promise<{ id: string }> {\r\n return this.request<{ id: string }>(\"POST\", \"/ingest\", options);\r\n }\r\n\r\n private async request<T>(method: string, path: string, body?: any): Promise<T> {\r\n // Shared headers\r\n const headers: Record<string, string> = {\r\n \"Authorization\": `Bearer ${this.apiKey}`,\r\n \"Content-Type\": \"application/json\",\r\n \"User-Agent\": \"letsping-node/0.1.2\"\r\n };\r\n\r\n try {\r\n const response = await fetch(`${this.baseUrl}${path}`, {\r\n method,\r\n headers,\r\n body: body ? JSON.stringify(body) : undefined,\r\n });\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text();\r\n // Try parsing JSON error message\r\n let message = errorText;\r\n try {\r\n const json = JSON.parse(errorText);\r\n if (json.message) message = json.message;\r\n } catch { }\r\n\r\n throw new LetsPingError(`API Error [${response.status}]: ${message}`, response.status);\r\n }\r\n\r\n return response.json() as Promise<T>;\r\n } catch (e: any) {\r\n if (e instanceof LetsPingError) throw e;\r\n // Fetch/Network errors\r\n throw new LetsPingError(`Network Error: ${e.message}`);\r\n }\r\n }\r\n tool(service: string, action: string, priority: Priority = \"medium\"): (context: string | Record<string, any>) => Promise<string> {\r\n return async (context: string | Record<string, any>): Promise<string> => {\r\n let payload: Record<string, any>;\r\n try {\r\n if (typeof context === 'string') {\r\n try {\r\n payload = JSON.parse(context);\r\n } catch {\r\n payload = { raw_context: context };\r\n }\r\n } else if (typeof context === 'object' && context !== null) {\r\n payload = context;\r\n } else {\r\n // Handle numbers, booleans, undefined, etc.\r\n payload = { raw_context: String(context) };\r\n }\r\n\r\n const result = await this.ask({\r\n service,\r\n action,\r\n payload,\r\n priority\r\n });\r\n\r\n if (result.status === \"REJECTED\") {\r\n return `STOP: Action Rejected by Human.`;\r\n }\r\n\r\n const finalPayload = result.patched_payload || result.payload;\r\n return JSON.stringify(finalPayload);\r\n } catch (e: any) {\r\n return `ERROR: System Failure: ${e.message}`;\r\n }\r\n };\r\n }\r\n}"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../package.json","../src/index.ts"],"sourcesContent":["{\n \"name\": \"@letsping/sdk\",\n \"version\": \"0.1.3\",\n \"description\": \"The Human-in-the-Loop SDK for Autonomous Agents\",\n \"main\": \"./dist/index.js\",\n \"module\": \"./dist/index.mjs\",\n \"files\": [\n \"dist\"\n ],\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"require\": \"./dist/index.js\",\n \"import\": \"./dist/index.mjs\"\n }\n },\n \"scripts\": {\n \"build\": \"tsup && tsc --emitDeclarationOnly --outDir dist\",\n \"dev\": \"tsup --watch\",\n \"clean\": \"rm -rf dist .turbo\"\n },\n \"dependencies\": {},\n \"devDependencies\": {\n \"tsup\": \"^8.0.0\",\n \"typescript\": \"^5.7.2\",\n \"@types/node\": \"^22.0.0\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n }\n}","import { createCipheriv, createDecipheriv, randomBytes } from \"node:crypto\";\r\n\nlet SDK_VERSION = \"0.1.2\";\r\ntry {\r\n \n SDK_VERSION = require(\"../package.json\").version;\r\n} catch { }\r\n\r\nexport type Priority = \"low\" | \"medium\" | \"high\" | \"critical\";\r\n\nexport interface RequestOptions {\r\n \r\n service: string;\r\n \r\n action: string;\r\n \r\n payload: Record<string, any>;\r\n \r\n priority?: Priority;\r\n \r\n schema?: Record<string, any>;\r\n \r\n timeoutMs?: number;\r\n \r\n role?: string;\r\n}\r\n\nexport interface Decision {\r\n status: \"APPROVED\" | \"REJECTED\" | \"APPROVED_WITH_MODIFICATIONS\";\r\n \r\n payload: any;\r\n \r\n patched_payload?: any;\r\n \r\n diff_summary?: any;\r\n metadata?: {\r\n resolved_at: string;\r\n actor_id: string;\r\n method?: string;\r\n };\r\n}\r\n\r\nexport class LetsPingError extends Error {\r\n constructor(message: string, public status?: number) {\r\n super(message);\r\n this.name = \"LetsPingError\";\r\n }\r\n}\r\n\ninterface EncEnvelope {\r\n _lp_enc: true;\r\n iv: string; \n ct: string; \n}\r\n\r\nfunction isEncEnvelope(v: unknown): v is EncEnvelope {\r\n return (\r\n typeof v === \"object\" && v !== null &&\r\n (v as any)._lp_enc === true &&\r\n typeof (v as any).iv === \"string\" &&\r\n typeof (v as any).ct === \"string\"\r\n );\r\n}\r\n\r\nfunction encryptPayload(keyBase64: string, payload: Record<string, any>): EncEnvelope {\r\n const keyBuf = Buffer.from(keyBase64, \"base64\");\r\n const iv = randomBytes(12);\r\n const cipher = createCipheriv(\"aes-256-gcm\", keyBuf, iv);\r\n const plain = Buffer.from(JSON.stringify(payload), \"utf8\");\r\n const ct = Buffer.concat([cipher.update(plain), cipher.final(), cipher.getAuthTag()]);\r\n return {\r\n _lp_enc: true,\r\n iv: iv.toString(\"base64\"),\r\n ct: ct.toString(\"base64\"),\r\n };\r\n}\r\n\r\nfunction decryptPayload(keyBase64: string, envelope: EncEnvelope): Record<string, any> {\r\n const keyBuf = Buffer.from(keyBase64, \"base64\");\r\n const iv = Buffer.from(envelope.iv, \"base64\");\r\n const ctFull = Buffer.from(envelope.ct, \"base64\");\r\n \n const authTag = ctFull.subarray(ctFull.length - 16);\r\n const ct = ctFull.subarray(0, ctFull.length - 16);\r\n const decipher = createDecipheriv(\"aes-256-gcm\", keyBuf, iv);\r\n decipher.setAuthTag(authTag);\r\n const plain = Buffer.concat([decipher.update(ct), decipher.final()]);\r\n return JSON.parse(plain.toString(\"utf8\"));\r\n}\r\n\r\nfunction computeDiff(original: any, patched: any): any {\r\n if (original === patched) return null;\r\n\r\n if (\r\n typeof original !== \"object\" ||\r\n typeof patched !== \"object\" ||\r\n original === null ||\r\n patched === null ||\r\n Array.isArray(original) ||\r\n Array.isArray(patched)\r\n ) {\r\n if (JSON.stringify(original) !== JSON.stringify(patched)) {\r\n return { from: original, to: patched };\r\n }\r\n return null;\r\n }\r\n\r\n const changes: Record<string, any> = {};\r\n let hasChanges = false;\r\n const allKeys = new Set([...Object.keys(original), ...Object.keys(patched)]);\r\n\r\n for (const key of allKeys) {\r\n const oV = original[key];\r\n const pV = patched[key];\r\n\r\n if (!(key in original)) {\r\n changes[key] = { from: undefined, to: pV };\r\n hasChanges = true;\r\n } else if (!(key in patched)) {\r\n changes[key] = { from: oV, to: undefined };\r\n hasChanges = true;\r\n } else {\r\n const nestedDiff = computeDiff(oV, pV);\r\n if (nestedDiff) {\r\n changes[key] = nestedDiff;\r\n hasChanges = true;\r\n }\r\n }\r\n }\r\n\r\n return hasChanges ? changes : null;\r\n}\r\n\nexport class LetsPing {\r\n private readonly apiKey: string;\r\n private readonly baseUrl: string;\r\n private readonly encryptionKey: string | null;\r\n\n constructor(apiKey?: string, options?: { baseUrl?: string; encryptionKey?: string }) {\r\n const key = apiKey || process.env.LETSPING_API_KEY;\r\n if (!key) throw new Error(\"LetsPing: API Key is required. Pass it to the constructor or set LETSPING_API_KEY env var.\");\r\n\r\n this.apiKey = key;\r\n this.baseUrl = options?.baseUrl || \"https://letsping.co/api\";\r\n this.encryptionKey = options?.encryptionKey\r\n ?? process.env.LETSPING_ENCRYPTION_KEY\r\n ?? null;\r\n }\r\n\r\n private _encrypt(payload: Record<string, any>): Record<string, any> {\r\n if (!this.encryptionKey) return payload;\r\n return encryptPayload(this.encryptionKey, payload) as any;\r\n }\r\n\r\n private _decrypt(val: any): any {\r\n if (!this.encryptionKey || !isEncEnvelope(val)) return val;\r\n try {\r\n return decryptPayload(this.encryptionKey, val);\r\n } catch {\r\n \n return val;\r\n }\r\n }\r\n\n async ask(options: RequestOptions): Promise<Decision> {\r\n if (options.schema && (options.schema as any)._def) {\r\n throw new LetsPingError(\"LetsPing Error: Raw Zod schema detected. You must convert it to JSON Schema (e.g. using 'zod-to-json-schema') before passing it to the SDK.\");\r\n }\r\n\r\n const { id } = await this.request<{ id: string }>(\"POST\", \"/ingest\", {\r\n service: options.service,\r\n action: options.action,\r\n payload: this._encrypt(options.payload),\r\n priority: options.priority || \"medium\",\r\n schema: options.schema,\r\n metadata: { role: options.role, sdk: \"node\" }\r\n });\r\n\r\n const timeout = options.timeoutMs || 24 * 60 * 60 * 1000;\r\n const start = Date.now();\r\n let delay = 1000;\r\n const maxDelay = 10000;\r\n\r\n while (Date.now() - start < timeout) {\r\n try {\r\n const check = await this.request<any>(\"GET\", `/status/${id}`);\r\n\r\n if (check.status === \"APPROVED\" || check.status === \"REJECTED\") {\r\n const decryptedPayload = this._decrypt(check.payload) ?? options.payload;\r\n const decryptedPatched = check.patched_payload ? this._decrypt(check.patched_payload) : undefined;\r\n\r\n let diff_summary;\r\n let finalStatus = check.status;\r\n if (check.status === \"APPROVED\" && decryptedPatched !== undefined) {\r\n finalStatus = \"APPROVED_WITH_MODIFICATIONS\";\r\n const diff = computeDiff(decryptedPayload, decryptedPatched);\r\n diff_summary = diff ? { changes: diff } : { changes: \"Unknown structure changes\" };\r\n }\r\n\r\n return {\r\n status: finalStatus,\r\n payload: decryptedPayload,\r\n patched_payload: decryptedPatched,\r\n diff_summary,\r\n metadata: {\r\n resolved_at: check.resolved_at,\r\n actor_id: check.actor_id,\r\n }\r\n };\r\n }\r\n } catch (e: any) {\r\n const s = e.status;\r\n if (s && s >= 400 && s < 500 && s !== 404 && s !== 429) throw e;\r\n }\r\n\r\n const jitter = Math.random() * 200;\r\n await new Promise(r => setTimeout(r, delay + jitter));\r\n delay = Math.min(delay * 1.5, maxDelay);\r\n }\r\n\r\n throw new LetsPingError(`Request ${id} timed out waiting for approval.`);\r\n }\r\n\r\n async defer(options: RequestOptions): Promise<{ id: string }> {\r\n return this.request<{ id: string }>(\"POST\", \"/ingest\", {\r\n ...options,\r\n payload: this._encrypt(options.payload),\r\n });\r\n }\r\n\r\n private async request<T>(method: string, path: string, body?: any): Promise<T> {\r\n const headers: Record<string, string> = {\r\n \"Authorization\": `Bearer ${this.apiKey}`,\r\n \"Content-Type\": \"application/json\",\r\n \"User-Agent\": `letsping-node/${SDK_VERSION}`,\r\n };\r\n\r\n try {\r\n const response = await fetch(`${this.baseUrl}${path}`, {\r\n method,\r\n headers,\r\n body: body ? JSON.stringify(body) : undefined,\r\n });\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text();\r\n let message = errorText;\r\n try {\r\n const json = JSON.parse(errorText);\r\n if (json.message) message = json.message;\r\n } catch { }\r\n throw new LetsPingError(`API Error [${response.status}]: ${message}`, response.status);\r\n }\r\n\r\n return response.json() as Promise<T>;\r\n } catch (e: any) {\r\n if (e instanceof LetsPingError) throw e;\r\n throw new LetsPingError(`Network Error: ${e.message}`);\r\n }\r\n }\r\n\r\n tool(service: string, action: string, priority: Priority = \"medium\"): (context: string | Record<string, any>) => Promise<string> {\r\n return async (context: string | Record<string, any>): Promise<string> => {\r\n let payload: Record<string, any>;\r\n try {\r\n if (typeof context === \"string\") {\r\n try { payload = JSON.parse(context); }\r\n catch { payload = { raw_context: context }; }\r\n } else if (typeof context === \"object\" && context !== null) {\r\n payload = context;\r\n } else {\r\n payload = { raw_context: String(context) };\r\n }\r\n\r\n const result = await this.ask({ service, action, payload, priority });\r\n\r\n if (result.status === \"REJECTED\") {\r\n return \"STOP: Action Rejected by Human.\";\r\n }\r\n\r\n if (result.status === \"APPROVED_WITH_MODIFICATIONS\") {\r\n return JSON.stringify({\r\n status: \"APPROVED_WITH_MODIFICATIONS\",\r\n message: \"The human reviewer authorized this action but modified your original payload. Please review the diff_summary to learn from this correction.\",\r\n diff_summary: result.diff_summary,\r\n original_payload: result.payload,\r\n executed_payload: result.patched_payload\r\n });\r\n }\r\n\r\n return JSON.stringify({\r\n status: \"APPROVED\",\r\n executed_payload: result.payload\r\n });\r\n } catch (e: any) {\r\n return `ERROR: System Failure: ${e.message}`;\r\n }\r\n };\r\n }\r\n}\r\n\r\nexport { computeDiff };"],"mappings":"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","names":["exports","module"]}
package/dist/index.mjs CHANGED
@@ -1,4 +1,53 @@
1
+ var __getOwnPropNames = Object.getOwnPropertyNames;
2
+ var __commonJS = (cb, mod) => function __require() {
3
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
4
+ };
5
+
6
+ // package.json
7
+ var require_package = __commonJS({
8
+ "package.json"(exports, module) {
9
+ module.exports = {
10
+ name: "@letsping/sdk",
11
+ version: "0.1.3",
12
+ description: "The Human-in-the-Loop SDK for Autonomous Agents",
13
+ main: "./dist/index.js",
14
+ module: "./dist/index.mjs",
15
+ files: [
16
+ "dist"
17
+ ],
18
+ types: "./dist/index.d.ts",
19
+ exports: {
20
+ ".": {
21
+ types: "./dist/index.d.ts",
22
+ require: "./dist/index.js",
23
+ import: "./dist/index.mjs"
24
+ }
25
+ },
26
+ scripts: {
27
+ build: "tsup && tsc --emitDeclarationOnly --outDir dist",
28
+ dev: "tsup --watch",
29
+ clean: "rm -rf dist .turbo"
30
+ },
31
+ dependencies: {},
32
+ devDependencies: {
33
+ tsup: "^8.0.0",
34
+ typescript: "^5.7.2",
35
+ "@types/node": "^22.0.0"
36
+ },
37
+ publishConfig: {
38
+ access: "public"
39
+ }
40
+ };
41
+ }
42
+ });
43
+
1
44
  // src/index.ts
45
+ import { createCipheriv, createDecipheriv, randomBytes } from "crypto";
46
+ var SDK_VERSION = "0.1.2";
47
+ try {
48
+ SDK_VERSION = require_package().version;
49
+ } catch {
50
+ }
2
51
  var LetsPingError = class extends Error {
3
52
  constructor(message, status) {
4
53
  super(message);
@@ -6,12 +55,81 @@ var LetsPingError = class extends Error {
6
55
  this.name = "LetsPingError";
7
56
  }
8
57
  };
58
+ function isEncEnvelope(v) {
59
+ return typeof v === "object" && v !== null && v._lp_enc === true && typeof v.iv === "string" && typeof v.ct === "string";
60
+ }
61
+ function encryptPayload(keyBase64, payload) {
62
+ const keyBuf = Buffer.from(keyBase64, "base64");
63
+ const iv = randomBytes(12);
64
+ const cipher = createCipheriv("aes-256-gcm", keyBuf, iv);
65
+ const plain = Buffer.from(JSON.stringify(payload), "utf8");
66
+ const ct = Buffer.concat([cipher.update(plain), cipher.final(), cipher.getAuthTag()]);
67
+ return {
68
+ _lp_enc: true,
69
+ iv: iv.toString("base64"),
70
+ ct: ct.toString("base64")
71
+ };
72
+ }
73
+ function decryptPayload(keyBase64, envelope) {
74
+ const keyBuf = Buffer.from(keyBase64, "base64");
75
+ const iv = Buffer.from(envelope.iv, "base64");
76
+ const ctFull = Buffer.from(envelope.ct, "base64");
77
+ const authTag = ctFull.subarray(ctFull.length - 16);
78
+ const ct = ctFull.subarray(0, ctFull.length - 16);
79
+ const decipher = createDecipheriv("aes-256-gcm", keyBuf, iv);
80
+ decipher.setAuthTag(authTag);
81
+ const plain = Buffer.concat([decipher.update(ct), decipher.final()]);
82
+ return JSON.parse(plain.toString("utf8"));
83
+ }
84
+ function computeDiff(original, patched) {
85
+ if (original === patched) return null;
86
+ if (typeof original !== "object" || typeof patched !== "object" || original === null || patched === null || Array.isArray(original) || Array.isArray(patched)) {
87
+ if (JSON.stringify(original) !== JSON.stringify(patched)) {
88
+ return { from: original, to: patched };
89
+ }
90
+ return null;
91
+ }
92
+ const changes = {};
93
+ let hasChanges = false;
94
+ const allKeys = /* @__PURE__ */ new Set([...Object.keys(original), ...Object.keys(patched)]);
95
+ for (const key of allKeys) {
96
+ const oV = original[key];
97
+ const pV = patched[key];
98
+ if (!(key in original)) {
99
+ changes[key] = { from: void 0, to: pV };
100
+ hasChanges = true;
101
+ } else if (!(key in patched)) {
102
+ changes[key] = { from: oV, to: void 0 };
103
+ hasChanges = true;
104
+ } else {
105
+ const nestedDiff = computeDiff(oV, pV);
106
+ if (nestedDiff) {
107
+ changes[key] = nestedDiff;
108
+ hasChanges = true;
109
+ }
110
+ }
111
+ }
112
+ return hasChanges ? changes : null;
113
+ }
9
114
  var LetsPing = class {
10
115
  constructor(apiKey, options) {
11
116
  const key = apiKey || process.env.LETSPING_API_KEY;
12
117
  if (!key) throw new Error("LetsPing: API Key is required. Pass it to the constructor or set LETSPING_API_KEY env var.");
13
118
  this.apiKey = key;
14
119
  this.baseUrl = options?.baseUrl || "https://letsping.co/api";
120
+ this.encryptionKey = options?.encryptionKey ?? process.env.LETSPING_ENCRYPTION_KEY ?? null;
121
+ }
122
+ _encrypt(payload) {
123
+ if (!this.encryptionKey) return payload;
124
+ return encryptPayload(this.encryptionKey, payload);
125
+ }
126
+ _decrypt(val) {
127
+ if (!this.encryptionKey || !isEncEnvelope(val)) return val;
128
+ try {
129
+ return decryptPayload(this.encryptionKey, val);
130
+ } catch {
131
+ return val;
132
+ }
15
133
  }
16
134
  async ask(options) {
17
135
  if (options.schema && options.schema._def) {
@@ -20,13 +138,10 @@ var LetsPing = class {
20
138
  const { id } = await this.request("POST", "/ingest", {
21
139
  service: options.service,
22
140
  action: options.action,
23
- payload: options.payload,
141
+ payload: this._encrypt(options.payload),
24
142
  priority: options.priority || "medium",
25
143
  schema: options.schema,
26
- metadata: {
27
- role: options.role,
28
- sdk: "node"
29
- }
144
+ metadata: { role: options.role, sdk: "node" }
30
145
  });
31
146
  const timeout = options.timeoutMs || 24 * 60 * 60 * 1e3;
32
147
  const start = Date.now();
@@ -36,10 +151,20 @@ var LetsPing = class {
36
151
  try {
37
152
  const check = await this.request("GET", `/status/${id}`);
38
153
  if (check.status === "APPROVED" || check.status === "REJECTED") {
154
+ const decryptedPayload = this._decrypt(check.payload) ?? options.payload;
155
+ const decryptedPatched = check.patched_payload ? this._decrypt(check.patched_payload) : void 0;
156
+ let diff_summary;
157
+ let finalStatus = check.status;
158
+ if (check.status === "APPROVED" && decryptedPatched !== void 0) {
159
+ finalStatus = "APPROVED_WITH_MODIFICATIONS";
160
+ const diff = computeDiff(decryptedPayload, decryptedPatched);
161
+ diff_summary = diff ? { changes: diff } : { changes: "Unknown structure changes" };
162
+ }
39
163
  return {
40
- status: check.status,
41
- payload: options.payload,
42
- patched_payload: check.patched_payload || options.payload,
164
+ status: finalStatus,
165
+ payload: decryptedPayload,
166
+ patched_payload: decryptedPatched,
167
+ diff_summary,
43
168
  metadata: {
44
169
  resolved_at: check.resolved_at,
45
170
  actor_id: check.actor_id
@@ -47,10 +172,8 @@ var LetsPing = class {
47
172
  };
48
173
  }
49
174
  } catch (e) {
50
- const status = e.status;
51
- if (status && status >= 400 && status < 500 && status !== 404 && status !== 429) {
52
- throw e;
53
- }
175
+ const s = e.status;
176
+ if (s && s >= 400 && s < 500 && s !== 404 && s !== 429) throw e;
54
177
  }
55
178
  const jitter = Math.random() * 200;
56
179
  await new Promise((r) => setTimeout(r, delay + jitter));
@@ -59,13 +182,16 @@ var LetsPing = class {
59
182
  throw new LetsPingError(`Request ${id} timed out waiting for approval.`);
60
183
  }
61
184
  async defer(options) {
62
- return this.request("POST", "/ingest", options);
185
+ return this.request("POST", "/ingest", {
186
+ ...options,
187
+ payload: this._encrypt(options.payload)
188
+ });
63
189
  }
64
190
  async request(method, path, body) {
65
191
  const headers = {
66
192
  "Authorization": `Bearer ${this.apiKey}`,
67
193
  "Content-Type": "application/json",
68
- "User-Agent": "letsping-node/0.1.2"
194
+ "User-Agent": `letsping-node/${SDK_VERSION}`
69
195
  };
70
196
  try {
71
197
  const response = await fetch(`${this.baseUrl}${path}`, {
@@ -104,17 +230,23 @@ var LetsPing = class {
104
230
  } else {
105
231
  payload = { raw_context: String(context) };
106
232
  }
107
- const result = await this.ask({
108
- service,
109
- action,
110
- payload,
111
- priority
112
- });
233
+ const result = await this.ask({ service, action, payload, priority });
113
234
  if (result.status === "REJECTED") {
114
- return `STOP: Action Rejected by Human.`;
235
+ return "STOP: Action Rejected by Human.";
115
236
  }
116
- const finalPayload = result.patched_payload || result.payload;
117
- return JSON.stringify(finalPayload);
237
+ if (result.status === "APPROVED_WITH_MODIFICATIONS") {
238
+ return JSON.stringify({
239
+ status: "APPROVED_WITH_MODIFICATIONS",
240
+ message: "The human reviewer authorized this action but modified your original payload. Please review the diff_summary to learn from this correction.",
241
+ diff_summary: result.diff_summary,
242
+ original_payload: result.payload,
243
+ executed_payload: result.patched_payload
244
+ });
245
+ }
246
+ return JSON.stringify({
247
+ status: "APPROVED",
248
+ executed_payload: result.payload
249
+ });
118
250
  } catch (e) {
119
251
  return `ERROR: System Failure: ${e.message}`;
120
252
  }
@@ -123,6 +255,7 @@ var LetsPing = class {
123
255
  };
124
256
  export {
125
257
  LetsPing,
126
- LetsPingError
258
+ LetsPingError,
259
+ computeDiff
127
260
  };
128
261
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export type Priority = \"low\" | \"medium\" | \"high\" | \"critical\";\r\n\r\n/**\r\n * Options for configuring a LetsPing approval request.\r\n */\r\nexport interface RequestOptions {\r\n /** Name of the agent or service (e.g., \"billing-agent\") */\r\n service: string;\r\n /** Specific action being requested (e.g., \"refund_user\") */\r\n action: string;\r\n /** The data payload to be reviewed by the human */\r\n payload: Record<string, any>;\r\n /** Urgency level affecting notification routing (default: \"medium\") */\r\n priority?: Priority;\r\n /** JSON Schema (Draft 7) for rendering a structured form in the dashboard */\r\n schema?: Record<string, any>;\r\n /** Maximum time to wait for approval in milliseconds (default: 24h) */\r\n timeoutMs?: number;\r\n /** (Enterprise) Specific role required for approval (e.g., \"finance\") */\r\n role?: string;\r\n}\r\n\r\n/**\r\n * The result of a human approval decision.\r\n */\r\nexport interface Decision {\r\n status: \"APPROVED\" | \"REJECTED\";\r\n /** The original payload submitted */\r\n payload: any;\r\n /** The modified payload if the human edited values during approval */\r\n patched_payload?: any;\r\n metadata?: {\r\n resolved_at: string;\r\n actor_id: string;\r\n method?: string;\r\n };\r\n}\r\n\r\nexport class LetsPingError extends Error {\r\n constructor(message: string, public status?: number) {\r\n super(message);\r\n this.name = \"LetsPingError\";\r\n }\r\n}\r\n\r\nexport class LetsPing {\r\n private readonly apiKey: string;\r\n private readonly baseUrl: string;\r\n\r\n constructor(apiKey?: string, options?: { baseUrl?: string }) {\r\n const key = apiKey || process.env.LETSPING_API_KEY;\r\n if (!key) throw new Error(\"LetsPing: API Key is required. Pass it to the constructor or set LETSPING_API_KEY env var.\");\r\n\r\n this.apiKey = key;\r\n this.baseUrl = options?.baseUrl || \"https://letsping.co/api\";\r\n }\r\n\r\n async ask(options: RequestOptions): Promise<Decision> {\r\n if (options.schema && (options.schema as any)._def) {\r\n throw new LetsPingError(\"LetsPing Error: Raw Zod schema detected. You must convert it to JSON Schema (e.g. using 'zod-to-json-schema') before passing it to the SDK.\");\r\n }\r\n\r\n const { id } = await this.request<{ id: string }>(\"POST\", \"/ingest\", {\r\n service: options.service,\r\n action: options.action,\r\n payload: options.payload,\r\n priority: options.priority || \"medium\",\r\n schema: options.schema,\r\n metadata: {\r\n role: options.role,\r\n sdk: \"node\"\r\n }\r\n });\r\n\r\n const timeout = options.timeoutMs || 24 * 60 * 60 * 1000;\r\n const start = Date.now();\r\n let delay = 1000;\r\n const maxDelay = 10000;\r\n\r\n while (Date.now() - start < timeout) {\r\n try {\r\n const check = await this.request<any>(\"GET\", `/status/${id}`);\r\n\r\n if (check.status === \"APPROVED\" || check.status === \"REJECTED\") {\r\n return {\r\n status: check.status,\r\n payload: options.payload,\r\n patched_payload: check.patched_payload || options.payload,\r\n metadata: {\r\n resolved_at: check.resolved_at,\r\n actor_id: check.actor_id\r\n }\r\n };\r\n }\r\n } catch (e: any) {\r\n // Retry on:\r\n // 1. Network errors (status is undefined)\r\n // 2. 404 (not found yet)\r\n // 3. 429 (rate limit)\r\n // 4. 5xx (server error)\r\n // Fail on: 400, 401, 403 (client errors)\r\n const status = e.status;\r\n if (status && status >= 400 && status < 500 && status !== 404 && status !== 429) {\r\n throw e;\r\n }\r\n }\r\n\r\n const jitter = Math.random() * 200;\r\n await new Promise(r => setTimeout(r, delay + jitter));\r\n delay = Math.min(delay * 1.5, maxDelay);\r\n }\r\n\r\n throw new LetsPingError(`Request ${id} timed out waiting for approval.`);\r\n }\r\n\r\n async defer(options: RequestOptions): Promise<{ id: string }> {\r\n return this.request<{ id: string }>(\"POST\", \"/ingest\", options);\r\n }\r\n\r\n private async request<T>(method: string, path: string, body?: any): Promise<T> {\r\n // Shared headers\r\n const headers: Record<string, string> = {\r\n \"Authorization\": `Bearer ${this.apiKey}`,\r\n \"Content-Type\": \"application/json\",\r\n \"User-Agent\": \"letsping-node/0.1.2\"\r\n };\r\n\r\n try {\r\n const response = await fetch(`${this.baseUrl}${path}`, {\r\n method,\r\n headers,\r\n body: body ? JSON.stringify(body) : undefined,\r\n });\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text();\r\n // Try parsing JSON error message\r\n let message = errorText;\r\n try {\r\n const json = JSON.parse(errorText);\r\n if (json.message) message = json.message;\r\n } catch { }\r\n\r\n throw new LetsPingError(`API Error [${response.status}]: ${message}`, response.status);\r\n }\r\n\r\n return response.json() as Promise<T>;\r\n } catch (e: any) {\r\n if (e instanceof LetsPingError) throw e;\r\n // Fetch/Network errors\r\n throw new LetsPingError(`Network Error: ${e.message}`);\r\n }\r\n }\r\n tool(service: string, action: string, priority: Priority = \"medium\"): (context: string | Record<string, any>) => Promise<string> {\r\n return async (context: string | Record<string, any>): Promise<string> => {\r\n let payload: Record<string, any>;\r\n try {\r\n if (typeof context === 'string') {\r\n try {\r\n payload = JSON.parse(context);\r\n } catch {\r\n payload = { raw_context: context };\r\n }\r\n } else if (typeof context === 'object' && context !== null) {\r\n payload = context;\r\n } else {\r\n // Handle numbers, booleans, undefined, etc.\r\n payload = { raw_context: String(context) };\r\n }\r\n\r\n const result = await this.ask({\r\n service,\r\n action,\r\n payload,\r\n priority\r\n });\r\n\r\n if (result.status === \"REJECTED\") {\r\n return `STOP: Action Rejected by Human.`;\r\n }\r\n\r\n const finalPayload = result.patched_payload || result.payload;\r\n return JSON.stringify(finalPayload);\r\n } catch (e: any) {\r\n return `ERROR: System Failure: ${e.message}`;\r\n }\r\n };\r\n }\r\n}"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../package.json","../src/index.ts"],"sourcesContent":["{\n \"name\": \"@letsping/sdk\",\n \"version\": \"0.1.3\",\n \"description\": \"The Human-in-the-Loop SDK for Autonomous Agents\",\n \"main\": \"./dist/index.js\",\n \"module\": \"./dist/index.mjs\",\n \"files\": [\n \"dist\"\n ],\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"require\": \"./dist/index.js\",\n \"import\": \"./dist/index.mjs\"\n }\n },\n \"scripts\": {\n \"build\": \"tsup && tsc --emitDeclarationOnly --outDir dist\",\n \"dev\": \"tsup --watch\",\n \"clean\": \"rm -rf dist .turbo\"\n },\n \"dependencies\": {},\n \"devDependencies\": {\n \"tsup\": \"^8.0.0\",\n \"typescript\": \"^5.7.2\",\n \"@types/node\": \"^22.0.0\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n }\n}","import { createCipheriv, createDecipheriv, randomBytes } from \"node:crypto\";\r\n\nlet SDK_VERSION = \"0.1.2\";\r\ntry {\r\n \n SDK_VERSION = require(\"../package.json\").version;\r\n} catch { }\r\n\r\nexport type Priority = \"low\" | \"medium\" | \"high\" | \"critical\";\r\n\nexport interface RequestOptions {\r\n \r\n service: string;\r\n \r\n action: string;\r\n \r\n payload: Record<string, any>;\r\n \r\n priority?: Priority;\r\n \r\n schema?: Record<string, any>;\r\n \r\n timeoutMs?: number;\r\n \r\n role?: string;\r\n}\r\n\nexport interface Decision {\r\n status: \"APPROVED\" | \"REJECTED\" | \"APPROVED_WITH_MODIFICATIONS\";\r\n \r\n payload: any;\r\n \r\n patched_payload?: any;\r\n \r\n diff_summary?: any;\r\n metadata?: {\r\n resolved_at: string;\r\n actor_id: string;\r\n method?: string;\r\n };\r\n}\r\n\r\nexport class LetsPingError extends Error {\r\n constructor(message: string, public status?: number) {\r\n super(message);\r\n this.name = \"LetsPingError\";\r\n }\r\n}\r\n\ninterface EncEnvelope {\r\n _lp_enc: true;\r\n iv: string; \n ct: string; \n}\r\n\r\nfunction isEncEnvelope(v: unknown): v is EncEnvelope {\r\n return (\r\n typeof v === \"object\" && v !== null &&\r\n (v as any)._lp_enc === true &&\r\n typeof (v as any).iv === \"string\" &&\r\n typeof (v as any).ct === \"string\"\r\n );\r\n}\r\n\r\nfunction encryptPayload(keyBase64: string, payload: Record<string, any>): EncEnvelope {\r\n const keyBuf = Buffer.from(keyBase64, \"base64\");\r\n const iv = randomBytes(12);\r\n const cipher = createCipheriv(\"aes-256-gcm\", keyBuf, iv);\r\n const plain = Buffer.from(JSON.stringify(payload), \"utf8\");\r\n const ct = Buffer.concat([cipher.update(plain), cipher.final(), cipher.getAuthTag()]);\r\n return {\r\n _lp_enc: true,\r\n iv: iv.toString(\"base64\"),\r\n ct: ct.toString(\"base64\"),\r\n };\r\n}\r\n\r\nfunction decryptPayload(keyBase64: string, envelope: EncEnvelope): Record<string, any> {\r\n const keyBuf = Buffer.from(keyBase64, \"base64\");\r\n const iv = Buffer.from(envelope.iv, \"base64\");\r\n const ctFull = Buffer.from(envelope.ct, \"base64\");\r\n \n const authTag = ctFull.subarray(ctFull.length - 16);\r\n const ct = ctFull.subarray(0, ctFull.length - 16);\r\n const decipher = createDecipheriv(\"aes-256-gcm\", keyBuf, iv);\r\n decipher.setAuthTag(authTag);\r\n const plain = Buffer.concat([decipher.update(ct), decipher.final()]);\r\n return JSON.parse(plain.toString(\"utf8\"));\r\n}\r\n\r\nfunction computeDiff(original: any, patched: any): any {\r\n if (original === patched) return null;\r\n\r\n if (\r\n typeof original !== \"object\" ||\r\n typeof patched !== \"object\" ||\r\n original === null ||\r\n patched === null ||\r\n Array.isArray(original) ||\r\n Array.isArray(patched)\r\n ) {\r\n if (JSON.stringify(original) !== JSON.stringify(patched)) {\r\n return { from: original, to: patched };\r\n }\r\n return null;\r\n }\r\n\r\n const changes: Record<string, any> = {};\r\n let hasChanges = false;\r\n const allKeys = new Set([...Object.keys(original), ...Object.keys(patched)]);\r\n\r\n for (const key of allKeys) {\r\n const oV = original[key];\r\n const pV = patched[key];\r\n\r\n if (!(key in original)) {\r\n changes[key] = { from: undefined, to: pV };\r\n hasChanges = true;\r\n } else if (!(key in patched)) {\r\n changes[key] = { from: oV, to: undefined };\r\n hasChanges = true;\r\n } else {\r\n const nestedDiff = computeDiff(oV, pV);\r\n if (nestedDiff) {\r\n changes[key] = nestedDiff;\r\n hasChanges = true;\r\n }\r\n }\r\n }\r\n\r\n return hasChanges ? changes : null;\r\n}\r\n\nexport class LetsPing {\r\n private readonly apiKey: string;\r\n private readonly baseUrl: string;\r\n private readonly encryptionKey: string | null;\r\n\n constructor(apiKey?: string, options?: { baseUrl?: string; encryptionKey?: string }) {\r\n const key = apiKey || process.env.LETSPING_API_KEY;\r\n if (!key) throw new Error(\"LetsPing: API Key is required. Pass it to the constructor or set LETSPING_API_KEY env var.\");\r\n\r\n this.apiKey = key;\r\n this.baseUrl = options?.baseUrl || \"https://letsping.co/api\";\r\n this.encryptionKey = options?.encryptionKey\r\n ?? process.env.LETSPING_ENCRYPTION_KEY\r\n ?? null;\r\n }\r\n\r\n private _encrypt(payload: Record<string, any>): Record<string, any> {\r\n if (!this.encryptionKey) return payload;\r\n return encryptPayload(this.encryptionKey, payload) as any;\r\n }\r\n\r\n private _decrypt(val: any): any {\r\n if (!this.encryptionKey || !isEncEnvelope(val)) return val;\r\n try {\r\n return decryptPayload(this.encryptionKey, val);\r\n } catch {\r\n \n return val;\r\n }\r\n }\r\n\n async ask(options: RequestOptions): Promise<Decision> {\r\n if (options.schema && (options.schema as any)._def) {\r\n throw new LetsPingError(\"LetsPing Error: Raw Zod schema detected. You must convert it to JSON Schema (e.g. using 'zod-to-json-schema') before passing it to the SDK.\");\r\n }\r\n\r\n const { id } = await this.request<{ id: string }>(\"POST\", \"/ingest\", {\r\n service: options.service,\r\n action: options.action,\r\n payload: this._encrypt(options.payload),\r\n priority: options.priority || \"medium\",\r\n schema: options.schema,\r\n metadata: { role: options.role, sdk: \"node\" }\r\n });\r\n\r\n const timeout = options.timeoutMs || 24 * 60 * 60 * 1000;\r\n const start = Date.now();\r\n let delay = 1000;\r\n const maxDelay = 10000;\r\n\r\n while (Date.now() - start < timeout) {\r\n try {\r\n const check = await this.request<any>(\"GET\", `/status/${id}`);\r\n\r\n if (check.status === \"APPROVED\" || check.status === \"REJECTED\") {\r\n const decryptedPayload = this._decrypt(check.payload) ?? options.payload;\r\n const decryptedPatched = check.patched_payload ? this._decrypt(check.patched_payload) : undefined;\r\n\r\n let diff_summary;\r\n let finalStatus = check.status;\r\n if (check.status === \"APPROVED\" && decryptedPatched !== undefined) {\r\n finalStatus = \"APPROVED_WITH_MODIFICATIONS\";\r\n const diff = computeDiff(decryptedPayload, decryptedPatched);\r\n diff_summary = diff ? { changes: diff } : { changes: \"Unknown structure changes\" };\r\n }\r\n\r\n return {\r\n status: finalStatus,\r\n payload: decryptedPayload,\r\n patched_payload: decryptedPatched,\r\n diff_summary,\r\n metadata: {\r\n resolved_at: check.resolved_at,\r\n actor_id: check.actor_id,\r\n }\r\n };\r\n }\r\n } catch (e: any) {\r\n const s = e.status;\r\n if (s && s >= 400 && s < 500 && s !== 404 && s !== 429) throw e;\r\n }\r\n\r\n const jitter = Math.random() * 200;\r\n await new Promise(r => setTimeout(r, delay + jitter));\r\n delay = Math.min(delay * 1.5, maxDelay);\r\n }\r\n\r\n throw new LetsPingError(`Request ${id} timed out waiting for approval.`);\r\n }\r\n\r\n async defer(options: RequestOptions): Promise<{ id: string }> {\r\n return this.request<{ id: string }>(\"POST\", \"/ingest\", {\r\n ...options,\r\n payload: this._encrypt(options.payload),\r\n });\r\n }\r\n\r\n private async request<T>(method: string, path: string, body?: any): Promise<T> {\r\n const headers: Record<string, string> = {\r\n \"Authorization\": `Bearer ${this.apiKey}`,\r\n \"Content-Type\": \"application/json\",\r\n \"User-Agent\": `letsping-node/${SDK_VERSION}`,\r\n };\r\n\r\n try {\r\n const response = await fetch(`${this.baseUrl}${path}`, {\r\n method,\r\n headers,\r\n body: body ? JSON.stringify(body) : undefined,\r\n });\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text();\r\n let message = errorText;\r\n try {\r\n const json = JSON.parse(errorText);\r\n if (json.message) message = json.message;\r\n } catch { }\r\n throw new LetsPingError(`API Error [${response.status}]: ${message}`, response.status);\r\n }\r\n\r\n return response.json() as Promise<T>;\r\n } catch (e: any) {\r\n if (e instanceof LetsPingError) throw e;\r\n throw new LetsPingError(`Network Error: ${e.message}`);\r\n }\r\n }\r\n\r\n tool(service: string, action: string, priority: Priority = \"medium\"): (context: string | Record<string, any>) => Promise<string> {\r\n return async (context: string | Record<string, any>): Promise<string> => {\r\n let payload: Record<string, any>;\r\n try {\r\n if (typeof context === \"string\") {\r\n try { payload = JSON.parse(context); }\r\n catch { payload = { raw_context: context }; }\r\n } else if (typeof context === \"object\" && context !== null) {\r\n payload = context;\r\n } else {\r\n payload = { raw_context: String(context) };\r\n }\r\n\r\n const result = await this.ask({ service, action, payload, priority });\r\n\r\n if (result.status === \"REJECTED\") {\r\n return \"STOP: Action Rejected by Human.\";\r\n }\r\n\r\n if (result.status === \"APPROVED_WITH_MODIFICATIONS\") {\r\n return JSON.stringify({\r\n status: \"APPROVED_WITH_MODIFICATIONS\",\r\n message: \"The human reviewer authorized this action but modified your original payload. Please review the diff_summary to learn from this correction.\",\r\n diff_summary: result.diff_summary,\r\n original_payload: result.payload,\r\n executed_payload: result.patched_payload\r\n });\r\n }\r\n\r\n return JSON.stringify({\r\n status: \"APPROVED\",\r\n executed_payload: result.payload\r\n });\r\n } catch (e: any) {\r\n return `ERROR: System Failure: ${e.message}`;\r\n }\r\n };\r\n }\r\n}\r\n\r\nexport { computeDiff };"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,29 +1,32 @@
1
- {
2
- "name": "@letsping/sdk",
3
- "version": "0.1.2",
4
- "description": "The Human-in-the-Loop SDK for Autonomous Agents",
5
- "main": "./dist/index.js",
6
- "module": "./dist/index.mjs",
7
- "types": "./dist/index.d.ts",
8
- "exports": {
9
- ".": {
10
- "types": "./dist/index.d.ts",
11
- "require": "./dist/index.js",
12
- "import": "./dist/index.mjs"
13
- }
14
- },
15
- "scripts": {
16
- "build": "tsup",
17
- "dev": "tsup --watch",
18
- "clean": "rm -rf dist .turbo"
19
- },
20
- "dependencies": {},
21
- "devDependencies": {
22
- "tsup": "^8.0.0",
23
- "typescript": "^5.7.2",
24
- "@types/node": "^22.0.0"
25
- },
26
- "publishConfig": {
27
- "access": "public"
28
- }
1
+ {
2
+ "name": "@letsping/sdk",
3
+ "version": "0.1.3",
4
+ "description": "The Human-in-the-Loop SDK for Autonomous Agents",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "require": "./dist/index.js",
15
+ "import": "./dist/index.mjs"
16
+ }
17
+ },
18
+ "scripts": {
19
+ "build": "tsup && tsc --emitDeclarationOnly --outDir dist",
20
+ "dev": "tsup --watch",
21
+ "clean": "rm -rf dist .turbo"
22
+ },
23
+ "dependencies": {},
24
+ "devDependencies": {
25
+ "tsup": "^8.0.0",
26
+ "typescript": "^5.7.2",
27
+ "@types/node": "^22.0.0"
28
+ },
29
+ "publishConfig": {
30
+ "access": "public"
31
+ }
29
32
  }
package/src/index.d.ts DELETED
@@ -1,35 +0,0 @@
1
- export type Priority = "low" | "medium" | "high" | "critical";
2
- export interface RequestOptions {
3
- service: string;
4
- action: string;
5
- payload: Record<string, any>;
6
- priority?: Priority;
7
- schema?: Record<string, any>;
8
- timeoutMs?: number;
9
- }
10
- export interface Decision {
11
- status: "APPROVED" | "REJECTED";
12
- payload: any;
13
- patched_payload?: any;
14
- metadata?: {
15
- resolved_at: string;
16
- actor_id: string;
17
- method?: string;
18
- };
19
- }
20
- export declare class LetsPingError extends Error {
21
- status?: number | undefined;
22
- constructor(message: string, status?: number | undefined);
23
- }
24
- export declare class LetsPing {
25
- private readonly apiKey;
26
- private readonly baseUrl;
27
- constructor(apiKey?: string, options?: {
28
- baseUrl?: string;
29
- });
30
- ask(options: RequestOptions): Promise<Decision>;
31
- defer(options: RequestOptions): Promise<{
32
- id: string;
33
- }>;
34
- private request;
35
- }
package/src/index.ts DELETED
@@ -1,189 +0,0 @@
1
- export type Priority = "low" | "medium" | "high" | "critical";
2
-
3
- /**
4
- * Options for configuring a LetsPing approval request.
5
- */
6
- export interface RequestOptions {
7
- /** Name of the agent or service (e.g., "billing-agent") */
8
- service: string;
9
- /** Specific action being requested (e.g., "refund_user") */
10
- action: string;
11
- /** The data payload to be reviewed by the human */
12
- payload: Record<string, any>;
13
- /** Urgency level affecting notification routing (default: "medium") */
14
- priority?: Priority;
15
- /** JSON Schema (Draft 7) for rendering a structured form in the dashboard */
16
- schema?: Record<string, any>;
17
- /** Maximum time to wait for approval in milliseconds (default: 24h) */
18
- timeoutMs?: number;
19
- /** (Enterprise) Specific role required for approval (e.g., "finance") */
20
- role?: string;
21
- }
22
-
23
- /**
24
- * The result of a human approval decision.
25
- */
26
- export interface Decision {
27
- status: "APPROVED" | "REJECTED";
28
- /** The original payload submitted */
29
- payload: any;
30
- /** The modified payload if the human edited values during approval */
31
- patched_payload?: any;
32
- metadata?: {
33
- resolved_at: string;
34
- actor_id: string;
35
- method?: string;
36
- };
37
- }
38
-
39
- export class LetsPingError extends Error {
40
- constructor(message: string, public status?: number) {
41
- super(message);
42
- this.name = "LetsPingError";
43
- }
44
- }
45
-
46
- export class LetsPing {
47
- private readonly apiKey: string;
48
- private readonly baseUrl: string;
49
-
50
- constructor(apiKey?: string, options?: { baseUrl?: string }) {
51
- const key = apiKey || process.env.LETSPING_API_KEY;
52
- if (!key) throw new Error("LetsPing: API Key is required. Pass it to the constructor or set LETSPING_API_KEY env var.");
53
-
54
- this.apiKey = key;
55
- this.baseUrl = options?.baseUrl || "https://letsping.co/api";
56
- }
57
-
58
- async ask(options: RequestOptions): Promise<Decision> {
59
- if (options.schema && (options.schema as any)._def) {
60
- throw new LetsPingError("LetsPing Error: Raw Zod schema detected. You must convert it to JSON Schema (e.g. using 'zod-to-json-schema') before passing it to the SDK.");
61
- }
62
-
63
- const { id } = await this.request<{ id: string }>("POST", "/ingest", {
64
- service: options.service,
65
- action: options.action,
66
- payload: options.payload,
67
- priority: options.priority || "medium",
68
- schema: options.schema,
69
- metadata: {
70
- role: options.role,
71
- sdk: "node"
72
- }
73
- });
74
-
75
- const timeout = options.timeoutMs || 24 * 60 * 60 * 1000;
76
- const start = Date.now();
77
- let delay = 1000;
78
- const maxDelay = 10000;
79
-
80
- while (Date.now() - start < timeout) {
81
- try {
82
- const check = await this.request<any>("GET", `/status/${id}`);
83
-
84
- if (check.status === "APPROVED" || check.status === "REJECTED") {
85
- return {
86
- status: check.status,
87
- payload: options.payload,
88
- patched_payload: check.patched_payload || options.payload,
89
- metadata: {
90
- resolved_at: check.resolved_at,
91
- actor_id: check.actor_id
92
- }
93
- };
94
- }
95
- } catch (e: any) {
96
- // Retry on:
97
- // 1. Network errors (status is undefined)
98
- // 2. 404 (not found yet)
99
- // 3. 429 (rate limit)
100
- // 4. 5xx (server error)
101
- // Fail on: 400, 401, 403 (client errors)
102
- const status = e.status;
103
- if (status && status >= 400 && status < 500 && status !== 404 && status !== 429) {
104
- throw e;
105
- }
106
- }
107
-
108
- const jitter = Math.random() * 200;
109
- await new Promise(r => setTimeout(r, delay + jitter));
110
- delay = Math.min(delay * 1.5, maxDelay);
111
- }
112
-
113
- throw new LetsPingError(`Request ${id} timed out waiting for approval.`);
114
- }
115
-
116
- async defer(options: RequestOptions): Promise<{ id: string }> {
117
- return this.request<{ id: string }>("POST", "/ingest", options);
118
- }
119
-
120
- private async request<T>(method: string, path: string, body?: any): Promise<T> {
121
- // Shared headers
122
- const headers: Record<string, string> = {
123
- "Authorization": `Bearer ${this.apiKey}`,
124
- "Content-Type": "application/json",
125
- "User-Agent": "letsping-node/0.1.2"
126
- };
127
-
128
- try {
129
- const response = await fetch(`${this.baseUrl}${path}`, {
130
- method,
131
- headers,
132
- body: body ? JSON.stringify(body) : undefined,
133
- });
134
-
135
- if (!response.ok) {
136
- const errorText = await response.text();
137
- // Try parsing JSON error message
138
- let message = errorText;
139
- try {
140
- const json = JSON.parse(errorText);
141
- if (json.message) message = json.message;
142
- } catch { }
143
-
144
- throw new LetsPingError(`API Error [${response.status}]: ${message}`, response.status);
145
- }
146
-
147
- return response.json() as Promise<T>;
148
- } catch (e: any) {
149
- if (e instanceof LetsPingError) throw e;
150
- // Fetch/Network errors
151
- throw new LetsPingError(`Network Error: ${e.message}`);
152
- }
153
- }
154
- tool(service: string, action: string, priority: Priority = "medium"): (context: string | Record<string, any>) => Promise<string> {
155
- return async (context: string | Record<string, any>): Promise<string> => {
156
- let payload: Record<string, any>;
157
- try {
158
- if (typeof context === 'string') {
159
- try {
160
- payload = JSON.parse(context);
161
- } catch {
162
- payload = { raw_context: context };
163
- }
164
- } else if (typeof context === 'object' && context !== null) {
165
- payload = context;
166
- } else {
167
- // Handle numbers, booleans, undefined, etc.
168
- payload = { raw_context: String(context) };
169
- }
170
-
171
- const result = await this.ask({
172
- service,
173
- action,
174
- payload,
175
- priority
176
- });
177
-
178
- if (result.status === "REJECTED") {
179
- return `STOP: Action Rejected by Human.`;
180
- }
181
-
182
- const finalPayload = result.patched_payload || result.payload;
183
- return JSON.stringify(finalPayload);
184
- } catch (e: any) {
185
- return `ERROR: System Failure: ${e.message}`;
186
- }
187
- };
188
- }
189
- }
package/tsc_error.log DELETED
@@ -1,213 +0,0 @@
1
- npm warn Unknown user config "email". This will stop working in the next major version of npm.
2
- ../../node_modules/@types/node/globals.d.ts(95,18): error TS1005: '>' expected.
3
- ../../node_modules/@types/node/globals.d.ts(95,27): error TS1005: ')' expected.
4
- ../../node_modules/@types/node/globals.d.ts(96,18): error TS1005: '>' expected.
5
- ../../node_modules/@types/node/globals.d.ts(96,27): error TS1005: ';' expected.
6
- ../../node_modules/@types/node/globals.d.ts(97,31): error TS1005: '>' expected.
7
- ../../node_modules/@types/node/globals.d.ts(97,35): error TS1005: ';' expected.
8
- ../../node_modules/@types/node/globals.d.ts(97,43): error TS1161: Unterminated regular expression literal.
9
- ../../node_modules/@types/node/globals.d.ts(98,22): error TS1161: Unterminated regular expression literal.
10
- ../../node_modules/@types/node/globals.d.ts(99,27): error TS1005: ';' expected.
11
- ../../node_modules/@types/node/globals.d.ts(100,29): error TS1005: '>' expected.
12
- ../../node_modules/@types/node/globals.d.ts(100,38): error TS1005: ';' expected.
13
- ../../node_modules/@types/node/globals.d.ts(100,97): error TS1005: ';' expected.
14
- ../../node_modules/@types/node/globals.d.ts(100,107): error TS1161: Unterminated regular expression literal.
15
- ../../node_modules/@types/node/globals.d.ts(101,33): error TS1005: ';' expected.
16
- ../../node_modules/@types/node/globals.d.ts(102,38): error TS1005: ';' expected.
17
- ../../node_modules/@types/node/globals.d.ts(102,46): error TS1228: A type predicate is only allowed in return type position for functions and methods.
18
- ../../node_modules/@types/node/globals.d.ts(102,49): error TS1434: Unexpected keyword or identifier.
19
- ../../node_modules/@types/node/globals.d.ts(102,53): error TS1128: Declaration or statement expected.
20
- ../../node_modules/@types/node/globals.d.ts(102,68): error TS1005: '(' expected.
21
- ../../node_modules/@types/node/globals.d.ts(102,83): error TS1005: ')' expected.
22
- ../../node_modules/@types/node/globals.d.ts(102,105): error TS1005: ';' expected.
23
- ../../node_modules/@types/node/globals.d.ts(102,112): error TS1434: Unexpected keyword or identifier.
24
- ../../node_modules/@types/node/globals.d.ts(102,117): error TS1434: Unexpected keyword or identifier.
25
- ../../node_modules/@types/node/globals.d.ts(103,21): error TS1003: Identifier expected.
26
- ../../node_modules/@types/node/globals.d.ts(103,22): error TS1161: Unterminated regular expression literal.
27
- ../../node_modules/@types/node/globals.d.ts(104,38): error TS1161: Unterminated regular expression literal.
28
- ../../node_modules/@types/node/globals.d.ts(109,20): error TS1005: ';' expected.
29
- ../../node_modules/@types/node/globals.d.ts(110,18): error TS1161: Unterminated regular expression literal.
30
- ../../node_modules/@types/node/globals.d.ts(111,18): error TS1161: Unterminated regular expression literal.
31
- ../../node_modules/@types/node/globals.d.ts(112,9): error TS1128: Declaration or statement expected.
32
- ../../node_modules/@types/node/globals.d.ts(116,14): error TS1005: '>' expected.
33
- ../../node_modules/@types/node/globals.d.ts(116,23): error TS1005: ')' expected.
34
- ../../node_modules/@types/node/globals.d.ts(117,14): error TS1005: '>' expected.
35
- ../../node_modules/@types/node/globals.d.ts(117,23): error TS1005: ';' expected.
36
- ../../node_modules/@types/node/globals.d.ts(118,19): error TS1005: '>' expected.
37
- ../../node_modules/@types/node/globals.d.ts(118,23): error TS1005: ';' expected.
38
- ../../node_modules/@types/node/globals.d.ts(118,49): error TS1005: ';' expected.
39
- ../../node_modules/@types/node/globals.d.ts(119,28): error TS1005: '>' expected.
40
- ../../node_modules/@types/node/globals.d.ts(119,32): error TS1005: ';' expected.
41
- ../../node_modules/@types/node/globals.d.ts(119,40): error TS1161: Unterminated regular expression literal.
42
- ../../node_modules/@types/node/globals.d.ts(120,22): error TS1161: Unterminated regular expression literal.
43
- ../../node_modules/@types/node/globals.d.ts(121,22): error TS1161: Unterminated regular expression literal.
44
- ../../node_modules/@types/node/globals.d.ts(123,27): error TS1005: ';' expected.
45
- ../../node_modules/@types/node/globals.d.ts(124,30): error TS1005: '>' expected.
46
- ../../node_modules/@types/node/globals.d.ts(124,39): error TS1005: ';' expected.
47
- ../../node_modules/@types/node/globals.d.ts(124,154): error TS1109: Expression expected.
48
- ../../node_modules/@types/node/globals.d.ts(126,36): error TS1005: ',' expected.
49
- ../../node_modules/@types/node/globals.d.ts(127,38): error TS1005: '>' expected.
50
- ../../node_modules/@types/node/globals.d.ts(127,47): error TS1005: ')' expected.
51
- ../../node_modules/@types/node/globals.d.ts(128,42): error TS1005: '>' expected.
52
- ../../node_modules/@types/node/globals.d.ts(128,51): error TS1005: ';' expected.
53
- ../../node_modules/@types/node/globals.d.ts(129,54): error TS1005: '>' expected.
54
- ../../node_modules/@types/node/globals.d.ts(129,58): error TS1005: ';' expected.
55
- ../../node_modules/@types/node/globals.d.ts(129,66): error TS1161: Unterminated regular expression literal.
56
- ../../node_modules/@types/node/globals.d.ts(130,46): error TS1161: Unterminated regular expression literal.
57
- ../../node_modules/@types/node/globals.d.ts(132,51): error TS1005: ';' expected.
58
- ../../node_modules/@types/node/globals.d.ts(133,53): error TS1005: '>' expected.
59
- ../../node_modules/@types/node/globals.d.ts(133,62): error TS1005: ';' expected.
60
- ../../node_modules/@types/node/globals.d.ts(133,103): error TS1005: ';' expected.
61
- ../../node_modules/@types/node/globals.d.ts(133,112): error TS1005: ';' expected.
62
- ../../node_modules/@types/node/globals.d.ts(133,126): error TS1161: Unterminated regular expression literal.
63
- ../../node_modules/@types/node/globals.d.ts(134,57): error TS1005: ';' expected.
64
- ../../node_modules/@types/node/globals.d.ts(135,65): error TS1005: ';' expected.
65
- ../../node_modules/@types/node/globals.d.ts(135,70): error TS1435: Unknown keyword or identifier. Did you mean 'get'?
66
- ../../node_modules/@types/node/globals.d.ts(135,76): error TS1434: Unexpected keyword or identifier.
67
- ../../node_modules/@types/node/globals.d.ts(135,86): error TS1434: Unexpected keyword or identifier.
68
- ../../node_modules/@types/node/globals.d.ts(135,90): error TS1434: Unexpected keyword or identifier.
69
- ../../node_modules/@types/node/globals.d.ts(135,94): error TS1434: Unexpected keyword or identifier.
70
- ../../node_modules/@types/node/globals.d.ts(135,99): error TS1434: Unexpected keyword or identifier.
71
- ../../node_modules/@types/node/globals.d.ts(135,102): error TS1434: Unexpected keyword or identifier.
72
- ../../node_modules/@types/node/globals.d.ts(135,112): error TS1434: Unexpected keyword or identifier.
73
- ../../node_modules/@types/node/globals.d.ts(135,114): error TS1434: Unexpected keyword or identifier.
74
- ../../node_modules/@types/node/globals.d.ts(135,124): error TS1434: Unexpected keyword or identifier.
75
- ../../node_modules/@types/node/globals.d.ts(135,138): error TS1434: Unexpected keyword or identifier.
76
- ../../node_modules/@types/node/globals.d.ts(135,143): error TS1434: Unexpected keyword or identifier.
77
- ../../node_modules/@types/node/globals.d.ts(136,29): error TS1003: Identifier expected.
78
- ../../node_modules/@types/node/globals.d.ts(136,30): error TS1161: Unterminated regular expression literal.
79
- ../../node_modules/@types/node/globals.d.ts(137,62): error TS1161: Unterminated regular expression literal.
80
- ../../node_modules/@types/node/globals.d.ts(141,18): error TS1005: '>' expected.
81
- ../../node_modules/@types/node/globals.d.ts(141,27): error TS1005: ')' expected.
82
- ../../node_modules/@types/node/globals.d.ts(142,30): error TS1005: '>' expected.
83
- ../../node_modules/@types/node/globals.d.ts(142,34): error TS1005: ';' expected.
84
- ../../node_modules/@types/node/globals.d.ts(142,66): error TS1109: Expression expected.
85
- ../../node_modules/@types/node/globals.d.ts(143,38): error TS1161: Unterminated regular expression literal.
86
- ../../node_modules/@types/node/globals.d.ts(144,22): error TS1161: Unterminated regular expression literal.
87
- ../../node_modules/@types/node/globals.d.ts(145,25): error TS1128: Declaration or statement expected.
88
- ../../node_modules/@types/node/globals.d.ts(149,29): error TS1005: '>' expected.
89
- ../../node_modules/@types/node/globals.d.ts(149,36): error TS1005: ';' expected.
90
- ../../node_modules/@types/node/globals.d.ts(153,30): error TS1005: ',' expected.
91
- ../../node_modules/@types/node/globals.d.ts(153,44): error TS1005: ',' expected.
92
- ../../node_modules/@types/node/globals.d.ts(153,71): error TS1005: ',' expected.
93
- ../../node_modules/@types/node/globals.d.ts(153,72): error TS1109: Expression expected.
94
- ../../node_modules/@types/node/globals.d.ts(153,74): error TS1109: Expression expected.
95
- ../../node_modules/@types/node/globals.d.ts(155,2): error TS1110: Type expected.
96
- ../../node_modules/@types/node/globals.d.ts(156,6): error TS1161: Unterminated regular expression literal.
97
- ../../node_modules/@types/node/globals.d.ts(157,17): error TS1128: Declaration or statement expected.
98
- ../../node_modules/@types/node/globals.d.ts(157,18): error TS1128: Declaration or statement expected.
99
- ../../node_modules/@types/node/globals.d.ts(161,14): error TS1005: '>' expected.
100
- ../../node_modules/@types/node/globals.d.ts(161,23): error TS1005: ')' expected.
101
- ../../node_modules/@types/node/globals.d.ts(162,18): error TS1005: '>' expected.
102
- ../../node_modules/@types/node/globals.d.ts(162,27): error TS1005: ';' expected.
103
- ../../node_modules/@types/node/globals.d.ts(163,21): error TS1005: '>' expected.
104
- ../../node_modules/@types/node/globals.d.ts(163,30): error TS1005: ';' expected.
105
- ../../node_modules/@types/node/globals.d.ts(163,69): error TS1005: ';' expected.
106
- ../../node_modules/@types/node/globals.d.ts(163,78): error TS1161: Unterminated regular expression literal.
107
- ../../node_modules/@types/node/globals.d.ts(164,25): error TS1005: ';' expected.
108
- ../../node_modules/@types/node/globals.d.ts(164,68): error TS1005: ';' expected.
109
- ../../node_modules/@types/node/globals.d.ts(164,73): error TS1434: Unexpected keyword or identifier.
110
- ../../node_modules/@types/node/globals.d.ts(164,98): error TS1005: ',' expected.
111
- ../../node_modules/@types/node/globals.d.ts(164,112): error TS1351: An identifier or keyword cannot immediately follow a numeric literal.
112
- ../../node_modules/@types/node/globals.d.ts(164,122): error TS1005: ';' expected.
113
- ../../node_modules/@types/node/globals.d.ts(164,126): error TS1434: Unexpected keyword or identifier.
114
- ../../node_modules/@types/node/globals.d.ts(164,131): error TS1434: Unexpected keyword or identifier.
115
- ../../node_modules/@types/node/globals.d.ts(164,135): error TS1434: Unexpected keyword or identifier.
116
- ../../node_modules/@types/node/globals.d.ts(164,146): error TS1003: Identifier expected.
117
- ../../node_modules/@types/node/globals.d.ts(164,147): error TS1161: Unterminated regular expression literal.
118
- ../../node_modules/@types/node/globals.d.ts(165,26): error TS1161: Unterminated regular expression literal.
119
- ../../node_modules/@types/node/globals.d.ts(167,31): error TS1005: ';' expected.
120
- ../../node_modules/@types/node/globals.d.ts(168,34): error TS1005: '>' expected.
121
- ../../node_modules/@types/node/globals.d.ts(168,43): error TS1005: ';' expected.
122
- ../../node_modules/@types/node/globals.d.ts(170,37): error TS1005: '>' expected.
123
- ../../node_modules/@types/node/globals.d.ts(170,42): error TS1005: ';' expected.
124
- ../../node_modules/@types/node/globals.d.ts(171,17): error TS1005: ':' expected.
125
- ../../node_modules/@types/node/globals.d.ts(173,21): error TS1005: ':' expected.
126
- ../../node_modules/@types/node/globals.d.ts(174,10): error TS1109: Expression expected.
127
- ../../node_modules/@types/node/globals.d.ts(175,10): error TS1110: Type expected.
128
- ../../node_modules/@types/node/globals.d.ts(176,10): error TS1161: Unterminated regular expression literal.
129
- ../../node_modules/@types/node/globals.d.ts(178,15): error TS1005: ';' expected.
130
- ../../node_modules/@types/node/globals.d.ts(179,18): error TS1005: '>' expected.
131
- ../../node_modules/@types/node/globals.d.ts(179,27): error TS1005: ';' expected.
132
- ../../node_modules/@types/node/globals.d.ts(180,23): error TS1005: '>' expected.
133
- ../../node_modules/@types/node/globals.d.ts(180,32): error TS1005: ';' expected.
134
- ../../node_modules/@types/node/globals.d.ts(180,106): error TS1005: ';' expected.
135
- ../../node_modules/@types/node/globals.d.ts(180,117): error TS1161: Unterminated regular expression literal.
136
- ../../node_modules/@types/node/globals.d.ts(181,22): error TS1161: Unterminated regular expression literal.
137
- ../../node_modules/@types/node/globals.d.ts(183,27): error TS1005: ';' expected.
138
- ../../node_modules/@types/node/globals.d.ts(184,31): error TS1005: '>' expected.
139
- ../../node_modules/@types/node/globals.d.ts(184,40): error TS1005: ';' expected.
140
- ../../node_modules/@types/node/globals.d.ts(186,30): error TS1161: Unterminated regular expression literal.
141
- ../../node_modules/@types/node/globals.d.ts(191,15): error TS1005: '>' expected.
142
- ../../node_modules/@types/node/globals.d.ts(191,19): error TS1005: ';' expected.
143
- ../../node_modules/@types/node/globals.d.ts(191,27): error TS1161: Unterminated regular expression literal.
144
- ../../node_modules/@types/node/globals.d.ts(192,14): error TS1161: Unterminated regular expression literal.
145
- ../../node_modules/@types/node/globals.d.ts(193,14): error TS1161: Unterminated regular expression literal.
146
- ../../node_modules/@types/node/globals.d.ts(194,14): error TS1161: Unterminated regular expression literal.
147
- ../../node_modules/@types/node/globals.d.ts(197,16): error TS1136: Property assignment expected.
148
- ../../node_modules/@types/node/globals.d.ts(197,19): error TS1005: ';' expected.
149
- ../../node_modules/@types/node/globals.d.ts(202,6): error TS1161: Unterminated regular expression literal.
150
- ../../node_modules/@types/node/globals.d.ts(203,6): error TS1161: Unterminated regular expression literal.
151
- ../../node_modules/@types/node/globals.d.ts(204,17): error TS1128: Declaration or statement expected.
152
- ../../node_modules/@types/node/globals.d.ts(204,18): error TS1128: Declaration or statement expected.
153
- ../../node_modules/@types/node/globals.d.ts(208,14): error TS1005: '>' expected.
154
- ../../node_modules/@types/node/globals.d.ts(208,23): error TS1005: ')' expected.
155
- ../../node_modules/@types/node/globals.d.ts(209,18): error TS1005: '>' expected.
156
- ../../node_modules/@types/node/globals.d.ts(209,27): error TS1005: ';' expected.
157
- ../../node_modules/@types/node/globals.d.ts(210,21): error TS1005: '>' expected.
158
- ../../node_modules/@types/node/globals.d.ts(210,30): error TS1005: ';' expected.
159
- ../../node_modules/@types/node/globals.d.ts(210,71): error TS1005: ';' expected.
160
- ../../node_modules/@types/node/globals.d.ts(210,83): error TS1161: Unterminated regular expression literal.
161
- ../../node_modules/@types/node/globals.d.ts(211,25): error TS1005: ';' expected.
162
- ../../node_modules/@types/node/globals.d.ts(211,69): error TS1005: ';' expected.
163
- ../../node_modules/@types/node/globals.d.ts(211,83): error TS1005: ';' expected.
164
- ../../node_modules/@types/node/globals.d.ts(211,88): error TS1434: Unexpected keyword or identifier.
165
- ../../node_modules/@types/node/globals.d.ts(211,93): error TS1434: Unexpected keyword or identifier.
166
- ../../node_modules/@types/node/globals.d.ts(211,98): error TS1434: Unexpected keyword or identifier.
167
- ../../node_modules/@types/node/globals.d.ts(211,112): error TS1434: Unexpected keyword or identifier.
168
- ../../node_modules/@types/node/globals.d.ts(211,116): error TS1434: Unexpected keyword or identifier.
169
- ../../node_modules/@types/node/globals.d.ts(211,119): error TS1434: Unexpected keyword or identifier.
170
- ../../node_modules/@types/node/globals.d.ts(211,133): error TS1003: Identifier expected.
171
- ../../node_modules/@types/node/globals.d.ts(211,134): error TS1161: Unterminated regular expression literal.
172
- ../../node_modules/@types/node/globals.d.ts(212,26): error TS1161: Unterminated regular expression literal.
173
- ../../node_modules/@types/node/globals.d.ts(214,31): error TS1005: ';' expected.
174
- ../../node_modules/@types/node/globals.d.ts(216,33): error TS1005: '>' expected.
175
- ../../node_modules/@types/node/globals.d.ts(220,20): error TS1005: ':' expected.
176
- ../../node_modules/@types/node/globals.d.ts(222,17): error TS1136: Property assignment expected.
177
- ../../node_modules/@types/node/globals.d.ts(222,21): error TS1005: ';' expected.
178
- ../../node_modules/@types/node/globals.d.ts(226,6): error TS1109: Expression expected.
179
- ../../node_modules/@types/node/globals.d.ts(227,6): error TS1110: Type expected.
180
- ../../node_modules/@types/node/globals.d.ts(231,14): error TS1005: '>' expected.
181
- ../../node_modules/@types/node/globals.d.ts(231,23): error TS1005: ')' expected.
182
- ../../node_modules/@types/node/globals.d.ts(232,26): error TS1005: '>' expected.
183
- ../../node_modules/@types/node/globals.d.ts(232,30): error TS1005: ';' expected.
184
- ../../node_modules/@types/node/globals.d.ts(232,38): error TS1161: Unterminated regular expression literal.
185
- ../../node_modules/@types/node/globals.d.ts(233,18): error TS1161: Unterminated regular expression literal.
186
- ../../node_modules/@types/node/globals.d.ts(234,25): error TS1128: Declaration or statement expected.
187
- ../../node_modules/@types/node/globals.d.ts(237,6): error TS1005: '>' expected.
188
- ../../node_modules/@types/node/globals.d.ts(237,15): error TS1005: ';' expected.
189
- ../../node_modules/@types/node/globals.d.ts(239,33): error TS1005: '>' expected.
190
- ../../node_modules/@types/node/globals.d.ts(239,40): error TS1005: ';' expected.
191
- ../../node_modules/@types/node/globals.d.ts(240,24): error TS1005: ',' expected.
192
- ../../node_modules/@types/node/globals.d.ts(240,50): error TS1128: Declaration or statement expected.
193
- ../../node_modules/@types/node/globals.d.ts(243,26): error TS1005: ',' expected.
194
- ../../node_modules/@types/node/globals.d.ts(243,40): error TS1005: ',' expected.
195
- ../../node_modules/@types/node/globals.d.ts(243,67): error TS1005: ',' expected.
196
- ../../node_modules/@types/node/globals.d.ts(243,68): error TS1109: Expression expected.
197
- ../../node_modules/@types/node/globals.d.ts(243,70): error TS1109: Expression expected.
198
- ../../node_modules/@types/node/globals.d.ts(243,91): error TS1128: Declaration or statement expected.
199
- ../../node_modules/@types/node/globals.d.ts(244,2): error TS1110: Type expected.
200
- ../../node_modules/@types/node/globals.d.ts(247,12): error TS1136: Property assignment expected.
201
- ../../node_modules/@types/node/globals.d.ts(247,15): error TS1005: ';' expected.
202
- ../../node_modules/@types/node/globals.d.ts(247,33): error TS1128: Declaration or statement expected.
203
- ../../node_modules/@types/node/globals.d.ts(250,10): error TS1005: ';' expected.
204
- ../../node_modules/@types/node/globals.d.ts(250,13): error TS1434: Unexpected keyword or identifier.
205
- ../../node_modules/@types/node/globals.d.ts(251,10): error TS1161: Unterminated regular expression literal.
206
- ../../node_modules/@types/node/globals.d.ts(252,10): error TS1161: Unterminated regular expression literal.
207
- ../../node_modules/@types/node/globals.d.ts(253,10): error TS1161: Unterminated regular expression literal.
208
- ../../node_modules/@types/node/globals.d.ts(254,17): error TS1128: Declaration or statement expected.
209
- ../../node_modules/@types/node/globals.d.ts(254,18): error TS1128: Declaration or statement expected.
210
- ../../node_modules/@types/node/globals.d.ts(255,2): error TS1110: Type expected.
211
- ../../node_modules/@types/node/globals.d.ts(256,6): error TS1161: Unterminated regular expression literal.
212
- ../../node_modules/@types/node/globals.d.ts(257,5): error TS1128: Declaration or statement expected.
213
- ../../node_modules/@types/node/globals.d.ts(258,1): error TS1128: Declaration or statement expected.
package/tsconfig.json DELETED
@@ -1,23 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2020",
4
- "module": "ESNext",
5
- "moduleResolution": "Bundler",
6
- "strict": true,
7
- "declaration": true,
8
- "esModuleInterop": true,
9
- "skipLibCheck": true,
10
- "forceConsistentCasingInFileNames": true,
11
- "baseUrl": ".",
12
- "lib": [
13
- "ES2020",
14
- "DOM"
15
- ],
16
- "types": [
17
- "node"
18
- ]
19
- },
20
- "include": [
21
- "src"
22
- ]
23
- }
package/tsup.config.ts DELETED
@@ -1,10 +0,0 @@
1
- import { defineConfig } from "tsup";
2
-
3
- export default defineConfig({
4
- entry: ["src/index.ts"],
5
- format: ["cjs", "esm"],
6
- dts: true,
7
- clean: true,
8
- sourcemap: true,
9
- splitting: false,
10
- });