@letsping/sdk 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -0
- package/LICENSE +21 -0
- package/README.md +60 -9
- package/package.json +24 -3
- package/src/index.d.ts +110 -9
- package/src/index.ts +525 -27
- package/dist/index.d.mts +0 -37
- package/dist/index.d.ts +0 -59
- package/dist/index.js +0 -528
- package/dist/index.js.map +0 -1
- package/dist/index.mjs +0 -493
- package/dist/index.mjs.map +0 -1
- package/dist/integrations/langgraph.d.mts +0 -20
- package/dist/integrations/langgraph.d.ts +0 -17
- package/dist/integrations/langgraph.js +0 -150
- package/dist/integrations/langgraph.js.map +0 -1
- package/dist/integrations/langgraph.mjs +0 -125
- package/dist/integrations/langgraph.mjs.map +0 -1
- package/dist-tsc/index.d.ts +0 -68
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
|
|
20
|
-
// src/integrations/langgraph.ts
|
|
21
|
-
var langgraph_exports = {};
|
|
22
|
-
__export(langgraph_exports, {
|
|
23
|
-
LetsPingCheckpointer: () => LetsPingCheckpointer
|
|
24
|
-
});
|
|
25
|
-
module.exports = __toCommonJS(langgraph_exports);
|
|
26
|
-
var import_langgraph = require("@langchain/langgraph");
|
|
27
|
-
var LetsPingCheckpointer = class extends import_langgraph.BaseCheckpointSaver {
|
|
28
|
-
constructor(client) {
|
|
29
|
-
super();
|
|
30
|
-
this.client = client;
|
|
31
|
-
this.checkpoints = {};
|
|
32
|
-
}
|
|
33
|
-
getTransport() {
|
|
34
|
-
const clientAny = this.client;
|
|
35
|
-
if (typeof clientAny.request === "function") {
|
|
36
|
-
return clientAny.request.bind(this.client);
|
|
37
|
-
}
|
|
38
|
-
return null;
|
|
39
|
-
}
|
|
40
|
-
async saveRemote(threadId, checkpointId, checkpoint, metadata) {
|
|
41
|
-
const transport = this.getTransport();
|
|
42
|
-
if (!transport) {
|
|
43
|
-
console.warn("[LetsPingCheckpointer] Missing underlying transport; falling back to in-memory only.");
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
try {
|
|
47
|
-
await transport("POST", "/langgraph/checkpoints", {
|
|
48
|
-
thread_id: threadId,
|
|
49
|
-
checkpoint_id: checkpointId,
|
|
50
|
-
checkpoint,
|
|
51
|
-
metadata
|
|
52
|
-
});
|
|
53
|
-
} catch (e) {
|
|
54
|
-
console.warn("[LetsPingCheckpointer] Failed to persist checkpoint remotely; falling back to in-memory only.", e);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
async loadRemote(threadId, checkpointId) {
|
|
58
|
-
const transport = this.getTransport();
|
|
59
|
-
if (!transport) {
|
|
60
|
-
console.warn("[LetsPingCheckpointer] Missing underlying transport; using in-memory checkpoints only.");
|
|
61
|
-
return null;
|
|
62
|
-
}
|
|
63
|
-
const search = checkpointId ? `?thread_id=${encodeURIComponent(threadId)}&checkpoint_id=${encodeURIComponent(checkpointId)}` : `?thread_id=${encodeURIComponent(threadId)}&latest=1`;
|
|
64
|
-
try {
|
|
65
|
-
const res = await transport("GET", `/langgraph/checkpoints${search}`);
|
|
66
|
-
if (res && res.checkpoint && res.metadata) {
|
|
67
|
-
return { checkpoint: res.checkpoint, metadata: res.metadata };
|
|
68
|
-
}
|
|
69
|
-
} catch (e) {
|
|
70
|
-
console.warn("[LetsPingCheckpointer] Failed to load remote checkpoint", e);
|
|
71
|
-
}
|
|
72
|
-
return null;
|
|
73
|
-
}
|
|
74
|
-
async deleteRemote(threadId) {
|
|
75
|
-
const transport = this.getTransport();
|
|
76
|
-
if (!transport) return;
|
|
77
|
-
const search = `?thread_id=${encodeURIComponent(threadId)}`;
|
|
78
|
-
try {
|
|
79
|
-
await transport("DELETE", `/langgraph/checkpoints${search}`);
|
|
80
|
-
} catch (e) {
|
|
81
|
-
console.warn("[LetsPingCheckpointer] Failed to delete remote checkpoints", e);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
async put(config, checkpoint, metadata, newVersions) {
|
|
85
|
-
const threadId = config.configurable?.thread_id;
|
|
86
|
-
const checkpointId = checkpoint.id;
|
|
87
|
-
if (!threadId || !checkpointId) {
|
|
88
|
-
return config;
|
|
89
|
-
}
|
|
90
|
-
this.checkpoints[`${threadId}:${checkpointId}`] = { checkpoint, metadata };
|
|
91
|
-
await this.saveRemote(threadId, checkpointId, checkpoint, metadata);
|
|
92
|
-
return {
|
|
93
|
-
configurable: {
|
|
94
|
-
thread_id: threadId,
|
|
95
|
-
checkpoint_id: checkpointId
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
// METHODS REQUIRED BY LANGGRAPH V0.1+
|
|
100
|
-
async putWrites(config, writes, taskId) {
|
|
101
|
-
}
|
|
102
|
-
async deleteThread(threadId) {
|
|
103
|
-
for (const key of Object.keys(this.checkpoints)) {
|
|
104
|
-
if (key.startsWith(`${threadId}:`)) {
|
|
105
|
-
delete this.checkpoints[key];
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
await this.deleteRemote(threadId);
|
|
109
|
-
}
|
|
110
|
-
async getTuple(config) {
|
|
111
|
-
const threadId = config.configurable?.thread_id;
|
|
112
|
-
const checkpointId = config.configurable?.checkpoint_id;
|
|
113
|
-
if (!threadId) return void 0;
|
|
114
|
-
const remote = await this.loadRemote(threadId, checkpointId);
|
|
115
|
-
if (remote) {
|
|
116
|
-
return { config, checkpoint: remote.checkpoint, metadata: remote.metadata };
|
|
117
|
-
}
|
|
118
|
-
if (checkpointId) {
|
|
119
|
-
const match = this.checkpoints[`${threadId}:${checkpointId}`];
|
|
120
|
-
if (match) {
|
|
121
|
-
return { config, checkpoint: match.checkpoint, metadata: match.metadata };
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
let latest;
|
|
125
|
-
for (const [key, val] of Object.entries(this.checkpoints)) {
|
|
126
|
-
if (key.startsWith(`${threadId}:`)) {
|
|
127
|
-
latest = { config, checkpoint: val.checkpoint, metadata: val.metadata };
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
return latest;
|
|
131
|
-
}
|
|
132
|
-
async *list(config, options) {
|
|
133
|
-
const threadId = config.configurable?.thread_id;
|
|
134
|
-
if (!threadId) return;
|
|
135
|
-
const remoteLatest = await this.loadRemote(threadId);
|
|
136
|
-
if (remoteLatest) {
|
|
137
|
-
yield { config, checkpoint: remoteLatest.checkpoint, metadata: remoteLatest.metadata };
|
|
138
|
-
}
|
|
139
|
-
for (const [key, val] of Object.entries(this.checkpoints)) {
|
|
140
|
-
if (key.startsWith(`${threadId}:`)) {
|
|
141
|
-
yield { config, checkpoint: val.checkpoint, metadata: val.metadata };
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
};
|
|
146
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
147
|
-
0 && (module.exports = {
|
|
148
|
-
LetsPingCheckpointer
|
|
149
|
-
});
|
|
150
|
-
//# sourceMappingURL=langgraph.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/integrations/langgraph.ts"],"sourcesContent":["import { BaseCheckpointSaver, Checkpoint, CheckpointMetadata, CheckpointTuple } from \"@langchain/langgraph\";\r\nimport { RunnableConfig } from \"@langchain/core/runnables\";\r\nimport { LetsPing } from \"../index\";\r\n\r\ntype StoredCheckpoint = {\r\n checkpoint: Checkpoint;\r\n metadata: CheckpointMetadata;\r\n};\r\n\r\nexport class LetsPingCheckpointer extends BaseCheckpointSaver {\r\n private checkpoints: Record<string, StoredCheckpoint> = {};\r\n\r\n constructor(public client: LetsPing) {\r\n super();\r\n }\r\n\r\n private getTransport(): (<T = any>(method: string, path: string, body?: any) => Promise<T>) | null {\r\n const clientAny = this.client as any;\r\n if (typeof clientAny.request === \"function\") {\r\n return clientAny.request.bind(this.client);\r\n }\r\n return null;\r\n }\r\n\r\n private async saveRemote(\r\n threadId: string,\r\n checkpointId: string,\r\n checkpoint: Checkpoint,\r\n metadata: CheckpointMetadata\r\n ): Promise<void> {\r\n const transport = this.getTransport();\r\n if (!transport) {\r\n console.warn(\"[LetsPingCheckpointer] Missing underlying transport; falling back to in-memory only.\");\r\n return;\r\n }\r\n try {\r\n await transport(\"POST\", \"/langgraph/checkpoints\", {\r\n thread_id: threadId,\r\n checkpoint_id: checkpointId,\r\n checkpoint,\r\n metadata,\r\n });\r\n } catch (e) {\r\n console.warn(\"[LetsPingCheckpointer] Failed to persist checkpoint remotely; falling back to in-memory only.\", e);\r\n }\r\n }\r\n\r\n private async loadRemote(\r\n threadId: string,\r\n checkpointId?: string\r\n ): Promise<StoredCheckpoint | null> {\r\n const transport = this.getTransport();\r\n if (!transport) {\r\n console.warn(\"[LetsPingCheckpointer] Missing underlying transport; using in-memory checkpoints only.\");\r\n return null;\r\n }\r\n const search = checkpointId\r\n ? `?thread_id=${encodeURIComponent(threadId)}&checkpoint_id=${encodeURIComponent(checkpointId)}`\r\n : `?thread_id=${encodeURIComponent(threadId)}&latest=1`;\r\n try {\r\n const res = await transport<any>(\"GET\", `/langgraph/checkpoints${search}`);\r\n if (res && res.checkpoint && res.metadata) {\r\n return { checkpoint: res.checkpoint as Checkpoint, metadata: res.metadata as CheckpointMetadata };\r\n }\r\n } catch (e) {\r\n // If not found or backend unavailable, fall back to local cache only.\r\n console.warn(\"[LetsPingCheckpointer] Failed to load remote checkpoint\", e);\r\n }\r\n return null;\r\n }\r\n\r\n private async deleteRemote(threadId: string): Promise<void> {\r\n const transport = this.getTransport();\r\n if (!transport) return;\r\n const search = `?thread_id=${encodeURIComponent(threadId)}`;\r\n try {\r\n await transport(\"DELETE\", `/langgraph/checkpoints${search}`);\r\n } catch (e) {\r\n console.warn(\"[LetsPingCheckpointer] Failed to delete remote checkpoints\", e);\r\n }\r\n }\r\n\r\n async put(\r\n config: RunnableConfig,\r\n checkpoint: Checkpoint,\r\n metadata: CheckpointMetadata,\r\n newVersions?: Record<string, string | number>\r\n ): Promise<RunnableConfig> {\r\n const threadId = config.configurable?.thread_id;\r\n const checkpointId = checkpoint.id;\r\n\r\n if (!threadId || !checkpointId) {\r\n return config;\r\n }\r\n\r\n this.checkpoints[`${threadId}:${checkpointId}`] = { checkpoint, metadata };\r\n await this.saveRemote(threadId, checkpointId, checkpoint, metadata);\r\n\r\n return {\r\n configurable: {\r\n thread_id: threadId,\r\n checkpoint_id: checkpointId,\r\n },\r\n };\r\n }\r\n\r\n // METHODS REQUIRED BY LANGGRAPH V0.1+\r\n async putWrites(config: RunnableConfig, writes: any, taskId: string): Promise<void> {\r\n // No-op for V1: LetsPing focuses on primary state parking, not granular sub-task writes.\r\n }\r\n\r\n async deleteThread(threadId: string): Promise<void> {\r\n for (const key of Object.keys(this.checkpoints)) {\r\n if (key.startsWith(`${threadId}:`)) {\r\n delete this.checkpoints[key];\r\n }\r\n }\r\n await this.deleteRemote(threadId);\r\n }\r\n\r\n async getTuple(config: RunnableConfig): Promise<CheckpointTuple | undefined> {\r\n const threadId = config.configurable?.thread_id;\r\n const checkpointId = config.configurable?.checkpoint_id;\r\n if (!threadId) return undefined;\r\n\r\n // Prefer remote truth, fall back to local cache.\r\n const remote = await this.loadRemote(threadId, checkpointId);\r\n if (remote) {\r\n return { config, checkpoint: remote.checkpoint, metadata: remote.metadata };\r\n }\r\n\r\n if (checkpointId) {\r\n const match = this.checkpoints[`${threadId}:${checkpointId}`];\r\n if (match) {\r\n return { config, checkpoint: match.checkpoint, metadata: match.metadata };\r\n }\r\n }\r\n\r\n let latest: CheckpointTuple | undefined;\r\n for (const [key, val] of Object.entries(this.checkpoints)) {\r\n if (key.startsWith(`${threadId}:`)) {\r\n latest = { config, checkpoint: val.checkpoint, metadata: val.metadata };\r\n }\r\n }\r\n return latest;\r\n }\r\n\r\n async *list(config: RunnableConfig, options?: any): AsyncGenerator<CheckpointTuple> {\r\n const threadId = config.configurable?.thread_id;\r\n if (!threadId) return;\r\n\r\n const remoteLatest = await this.loadRemote(threadId);\r\n if (remoteLatest) {\r\n yield { config, checkpoint: remoteLatest.checkpoint, metadata: remoteLatest.metadata };\r\n }\r\n\r\n for (const [key, val] of Object.entries(this.checkpoints)) {\r\n if (key.startsWith(`${threadId}:`)) {\r\n yield { config, checkpoint: val.checkpoint, metadata: val.metadata };\r\n }\r\n }\r\n }\r\n}"],"mappings":"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","names":[]}
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
// src/integrations/langgraph.ts
|
|
2
|
-
import { BaseCheckpointSaver } from "@langchain/langgraph";
|
|
3
|
-
var LetsPingCheckpointer = class extends BaseCheckpointSaver {
|
|
4
|
-
constructor(client) {
|
|
5
|
-
super();
|
|
6
|
-
this.client = client;
|
|
7
|
-
this.checkpoints = {};
|
|
8
|
-
}
|
|
9
|
-
getTransport() {
|
|
10
|
-
const clientAny = this.client;
|
|
11
|
-
if (typeof clientAny.request === "function") {
|
|
12
|
-
return clientAny.request.bind(this.client);
|
|
13
|
-
}
|
|
14
|
-
return null;
|
|
15
|
-
}
|
|
16
|
-
async saveRemote(threadId, checkpointId, checkpoint, metadata) {
|
|
17
|
-
const transport = this.getTransport();
|
|
18
|
-
if (!transport) {
|
|
19
|
-
console.warn("[LetsPingCheckpointer] Missing underlying transport; falling back to in-memory only.");
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
try {
|
|
23
|
-
await transport("POST", "/langgraph/checkpoints", {
|
|
24
|
-
thread_id: threadId,
|
|
25
|
-
checkpoint_id: checkpointId,
|
|
26
|
-
checkpoint,
|
|
27
|
-
metadata
|
|
28
|
-
});
|
|
29
|
-
} catch (e) {
|
|
30
|
-
console.warn("[LetsPingCheckpointer] Failed to persist checkpoint remotely; falling back to in-memory only.", e);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
async loadRemote(threadId, checkpointId) {
|
|
34
|
-
const transport = this.getTransport();
|
|
35
|
-
if (!transport) {
|
|
36
|
-
console.warn("[LetsPingCheckpointer] Missing underlying transport; using in-memory checkpoints only.");
|
|
37
|
-
return null;
|
|
38
|
-
}
|
|
39
|
-
const search = checkpointId ? `?thread_id=${encodeURIComponent(threadId)}&checkpoint_id=${encodeURIComponent(checkpointId)}` : `?thread_id=${encodeURIComponent(threadId)}&latest=1`;
|
|
40
|
-
try {
|
|
41
|
-
const res = await transport("GET", `/langgraph/checkpoints${search}`);
|
|
42
|
-
if (res && res.checkpoint && res.metadata) {
|
|
43
|
-
return { checkpoint: res.checkpoint, metadata: res.metadata };
|
|
44
|
-
}
|
|
45
|
-
} catch (e) {
|
|
46
|
-
console.warn("[LetsPingCheckpointer] Failed to load remote checkpoint", e);
|
|
47
|
-
}
|
|
48
|
-
return null;
|
|
49
|
-
}
|
|
50
|
-
async deleteRemote(threadId) {
|
|
51
|
-
const transport = this.getTransport();
|
|
52
|
-
if (!transport) return;
|
|
53
|
-
const search = `?thread_id=${encodeURIComponent(threadId)}`;
|
|
54
|
-
try {
|
|
55
|
-
await transport("DELETE", `/langgraph/checkpoints${search}`);
|
|
56
|
-
} catch (e) {
|
|
57
|
-
console.warn("[LetsPingCheckpointer] Failed to delete remote checkpoints", e);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
async put(config, checkpoint, metadata, newVersions) {
|
|
61
|
-
const threadId = config.configurable?.thread_id;
|
|
62
|
-
const checkpointId = checkpoint.id;
|
|
63
|
-
if (!threadId || !checkpointId) {
|
|
64
|
-
return config;
|
|
65
|
-
}
|
|
66
|
-
this.checkpoints[`${threadId}:${checkpointId}`] = { checkpoint, metadata };
|
|
67
|
-
await this.saveRemote(threadId, checkpointId, checkpoint, metadata);
|
|
68
|
-
return {
|
|
69
|
-
configurable: {
|
|
70
|
-
thread_id: threadId,
|
|
71
|
-
checkpoint_id: checkpointId
|
|
72
|
-
}
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
// METHODS REQUIRED BY LANGGRAPH V0.1+
|
|
76
|
-
async putWrites(config, writes, taskId) {
|
|
77
|
-
}
|
|
78
|
-
async deleteThread(threadId) {
|
|
79
|
-
for (const key of Object.keys(this.checkpoints)) {
|
|
80
|
-
if (key.startsWith(`${threadId}:`)) {
|
|
81
|
-
delete this.checkpoints[key];
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
await this.deleteRemote(threadId);
|
|
85
|
-
}
|
|
86
|
-
async getTuple(config) {
|
|
87
|
-
const threadId = config.configurable?.thread_id;
|
|
88
|
-
const checkpointId = config.configurable?.checkpoint_id;
|
|
89
|
-
if (!threadId) return void 0;
|
|
90
|
-
const remote = await this.loadRemote(threadId, checkpointId);
|
|
91
|
-
if (remote) {
|
|
92
|
-
return { config, checkpoint: remote.checkpoint, metadata: remote.metadata };
|
|
93
|
-
}
|
|
94
|
-
if (checkpointId) {
|
|
95
|
-
const match = this.checkpoints[`${threadId}:${checkpointId}`];
|
|
96
|
-
if (match) {
|
|
97
|
-
return { config, checkpoint: match.checkpoint, metadata: match.metadata };
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
let latest;
|
|
101
|
-
for (const [key, val] of Object.entries(this.checkpoints)) {
|
|
102
|
-
if (key.startsWith(`${threadId}:`)) {
|
|
103
|
-
latest = { config, checkpoint: val.checkpoint, metadata: val.metadata };
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
return latest;
|
|
107
|
-
}
|
|
108
|
-
async *list(config, options) {
|
|
109
|
-
const threadId = config.configurable?.thread_id;
|
|
110
|
-
if (!threadId) return;
|
|
111
|
-
const remoteLatest = await this.loadRemote(threadId);
|
|
112
|
-
if (remoteLatest) {
|
|
113
|
-
yield { config, checkpoint: remoteLatest.checkpoint, metadata: remoteLatest.metadata };
|
|
114
|
-
}
|
|
115
|
-
for (const [key, val] of Object.entries(this.checkpoints)) {
|
|
116
|
-
if (key.startsWith(`${threadId}:`)) {
|
|
117
|
-
yield { config, checkpoint: val.checkpoint, metadata: val.metadata };
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
};
|
|
122
|
-
export {
|
|
123
|
-
LetsPingCheckpointer
|
|
124
|
-
};
|
|
125
|
-
//# sourceMappingURL=langgraph.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/integrations/langgraph.ts"],"sourcesContent":["import { BaseCheckpointSaver, Checkpoint, CheckpointMetadata, CheckpointTuple } from \"@langchain/langgraph\";\r\nimport { RunnableConfig } from \"@langchain/core/runnables\";\r\nimport { LetsPing } from \"../index\";\r\n\r\ntype StoredCheckpoint = {\r\n checkpoint: Checkpoint;\r\n metadata: CheckpointMetadata;\r\n};\r\n\r\nexport class LetsPingCheckpointer extends BaseCheckpointSaver {\r\n private checkpoints: Record<string, StoredCheckpoint> = {};\r\n\r\n constructor(public client: LetsPing) {\r\n super();\r\n }\r\n\r\n private getTransport(): (<T = any>(method: string, path: string, body?: any) => Promise<T>) | null {\r\n const clientAny = this.client as any;\r\n if (typeof clientAny.request === \"function\") {\r\n return clientAny.request.bind(this.client);\r\n }\r\n return null;\r\n }\r\n\r\n private async saveRemote(\r\n threadId: string,\r\n checkpointId: string,\r\n checkpoint: Checkpoint,\r\n metadata: CheckpointMetadata\r\n ): Promise<void> {\r\n const transport = this.getTransport();\r\n if (!transport) {\r\n console.warn(\"[LetsPingCheckpointer] Missing underlying transport; falling back to in-memory only.\");\r\n return;\r\n }\r\n try {\r\n await transport(\"POST\", \"/langgraph/checkpoints\", {\r\n thread_id: threadId,\r\n checkpoint_id: checkpointId,\r\n checkpoint,\r\n metadata,\r\n });\r\n } catch (e) {\r\n console.warn(\"[LetsPingCheckpointer] Failed to persist checkpoint remotely; falling back to in-memory only.\", e);\r\n }\r\n }\r\n\r\n private async loadRemote(\r\n threadId: string,\r\n checkpointId?: string\r\n ): Promise<StoredCheckpoint | null> {\r\n const transport = this.getTransport();\r\n if (!transport) {\r\n console.warn(\"[LetsPingCheckpointer] Missing underlying transport; using in-memory checkpoints only.\");\r\n return null;\r\n }\r\n const search = checkpointId\r\n ? `?thread_id=${encodeURIComponent(threadId)}&checkpoint_id=${encodeURIComponent(checkpointId)}`\r\n : `?thread_id=${encodeURIComponent(threadId)}&latest=1`;\r\n try {\r\n const res = await transport<any>(\"GET\", `/langgraph/checkpoints${search}`);\r\n if (res && res.checkpoint && res.metadata) {\r\n return { checkpoint: res.checkpoint as Checkpoint, metadata: res.metadata as CheckpointMetadata };\r\n }\r\n } catch (e) {\r\n // If not found or backend unavailable, fall back to local cache only.\r\n console.warn(\"[LetsPingCheckpointer] Failed to load remote checkpoint\", e);\r\n }\r\n return null;\r\n }\r\n\r\n private async deleteRemote(threadId: string): Promise<void> {\r\n const transport = this.getTransport();\r\n if (!transport) return;\r\n const search = `?thread_id=${encodeURIComponent(threadId)}`;\r\n try {\r\n await transport(\"DELETE\", `/langgraph/checkpoints${search}`);\r\n } catch (e) {\r\n console.warn(\"[LetsPingCheckpointer] Failed to delete remote checkpoints\", e);\r\n }\r\n }\r\n\r\n async put(\r\n config: RunnableConfig,\r\n checkpoint: Checkpoint,\r\n metadata: CheckpointMetadata,\r\n newVersions?: Record<string, string | number>\r\n ): Promise<RunnableConfig> {\r\n const threadId = config.configurable?.thread_id;\r\n const checkpointId = checkpoint.id;\r\n\r\n if (!threadId || !checkpointId) {\r\n return config;\r\n }\r\n\r\n this.checkpoints[`${threadId}:${checkpointId}`] = { checkpoint, metadata };\r\n await this.saveRemote(threadId, checkpointId, checkpoint, metadata);\r\n\r\n return {\r\n configurable: {\r\n thread_id: threadId,\r\n checkpoint_id: checkpointId,\r\n },\r\n };\r\n }\r\n\r\n // METHODS REQUIRED BY LANGGRAPH V0.1+\r\n async putWrites(config: RunnableConfig, writes: any, taskId: string): Promise<void> {\r\n // No-op for V1: LetsPing focuses on primary state parking, not granular sub-task writes.\r\n }\r\n\r\n async deleteThread(threadId: string): Promise<void> {\r\n for (const key of Object.keys(this.checkpoints)) {\r\n if (key.startsWith(`${threadId}:`)) {\r\n delete this.checkpoints[key];\r\n }\r\n }\r\n await this.deleteRemote(threadId);\r\n }\r\n\r\n async getTuple(config: RunnableConfig): Promise<CheckpointTuple | undefined> {\r\n const threadId = config.configurable?.thread_id;\r\n const checkpointId = config.configurable?.checkpoint_id;\r\n if (!threadId) return undefined;\r\n\r\n // Prefer remote truth, fall back to local cache.\r\n const remote = await this.loadRemote(threadId, checkpointId);\r\n if (remote) {\r\n return { config, checkpoint: remote.checkpoint, metadata: remote.metadata };\r\n }\r\n\r\n if (checkpointId) {\r\n const match = this.checkpoints[`${threadId}:${checkpointId}`];\r\n if (match) {\r\n return { config, checkpoint: match.checkpoint, metadata: match.metadata };\r\n }\r\n }\r\n\r\n let latest: CheckpointTuple | undefined;\r\n for (const [key, val] of Object.entries(this.checkpoints)) {\r\n if (key.startsWith(`${threadId}:`)) {\r\n latest = { config, checkpoint: val.checkpoint, metadata: val.metadata };\r\n }\r\n }\r\n return latest;\r\n }\r\n\r\n async *list(config: RunnableConfig, options?: any): AsyncGenerator<CheckpointTuple> {\r\n const threadId = config.configurable?.thread_id;\r\n if (!threadId) return;\r\n\r\n const remoteLatest = await this.loadRemote(threadId);\r\n if (remoteLatest) {\r\n yield { config, checkpoint: remoteLatest.checkpoint, metadata: remoteLatest.metadata };\r\n }\r\n\r\n for (const [key, val] of Object.entries(this.checkpoints)) {\r\n if (key.startsWith(`${threadId}:`)) {\r\n yield { config, checkpoint: val.checkpoint, metadata: val.metadata };\r\n }\r\n }\r\n }\r\n}"],"mappings":"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","names":[]}
|
package/dist-tsc/index.d.ts
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
export type Priority = "low" | "medium" | "high" | "critical";
|
|
2
|
-
/**
|
|
3
|
-
* Options for configuring a LetsPing approval request.
|
|
4
|
-
*/
|
|
5
|
-
export interface RequestOptions {
|
|
6
|
-
/** Name of the agent or service (e.g., "billing-agent") */
|
|
7
|
-
service: string;
|
|
8
|
-
/** Specific action being requested (e.g., "refund_user") */
|
|
9
|
-
action: string;
|
|
10
|
-
/** The data payload to be reviewed by the human */
|
|
11
|
-
payload: Record<string, any>;
|
|
12
|
-
/** Urgency level affecting notification routing (default: "medium") */
|
|
13
|
-
priority?: Priority;
|
|
14
|
-
/** JSON Schema (Draft 7) for rendering a structured form in the dashboard */
|
|
15
|
-
schema?: Record<string, any>;
|
|
16
|
-
/** Maximum time to wait for approval in milliseconds (default: 24h) */
|
|
17
|
-
timeoutMs?: number;
|
|
18
|
-
/** (Enterprise) Specific role required for approval (e.g., "finance") */
|
|
19
|
-
role?: string;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* The result of a human approval decision.
|
|
23
|
-
*/
|
|
24
|
-
export interface Decision {
|
|
25
|
-
status: "APPROVED" | "REJECTED" | "APPROVED_WITH_MODIFICATIONS";
|
|
26
|
-
/** The original payload submitted */
|
|
27
|
-
payload: any;
|
|
28
|
-
/** The modified payload if the human edited values during approval */
|
|
29
|
-
patched_payload?: any;
|
|
30
|
-
/** Structural diff of the modifications */
|
|
31
|
-
diff_summary?: any;
|
|
32
|
-
metadata?: {
|
|
33
|
-
resolved_at: string;
|
|
34
|
-
actor_id: string;
|
|
35
|
-
method?: string;
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
export declare class LetsPingError extends Error {
|
|
39
|
-
status?: number | undefined;
|
|
40
|
-
constructor(message: string, status?: number | undefined);
|
|
41
|
-
}
|
|
42
|
-
export declare function computeDiff(original: any, patched: any): any;
|
|
43
|
-
export declare class LetsPing {
|
|
44
|
-
private readonly apiKey;
|
|
45
|
-
private readonly baseUrl;
|
|
46
|
-
private readonly encryptionKey;
|
|
47
|
-
/**
|
|
48
|
-
* @param apiKey Your LetsPing API key (or set LETSPING_API_KEY env var).
|
|
49
|
-
* @param options.encryptionKey
|
|
50
|
-
* Optional base64-encoded AES-256 key for payload encryption.
|
|
51
|
-
* If not provided here, the SDK reads LETSPING_ENCRYPTION_KEY from process.env.
|
|
52
|
-
* Generate once from the dashboard (Settings → Encryption).
|
|
53
|
-
* When set, all payloads are encrypted before leaving this process.
|
|
54
|
-
* LetsPing's backend never sees plaintext values.
|
|
55
|
-
*/
|
|
56
|
-
constructor(apiKey?: string, options?: {
|
|
57
|
-
baseUrl?: string;
|
|
58
|
-
encryptionKey?: string;
|
|
59
|
-
});
|
|
60
|
-
private _encrypt;
|
|
61
|
-
private _decrypt;
|
|
62
|
-
ask(options: RequestOptions): Promise<Decision>;
|
|
63
|
-
defer(options: RequestOptions): Promise<{
|
|
64
|
-
id: string;
|
|
65
|
-
}>;
|
|
66
|
-
private request;
|
|
67
|
-
tool(service: string, action: string, priority?: Priority): (context: string | Record<string, any>) => Promise<string>;
|
|
68
|
-
}
|