@letsping/adapters 0.1.1 → 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.
@@ -9,11 +9,8 @@ interface AdapterOptions<T extends z.ZodType> {
9
9
  service?: string;
10
10
  priority?: "low" | "medium" | "high" | "critical";
11
11
  timeout?: number;
12
+ handler?: (args: z.infer<T>) => Promise<any> | any;
12
13
  }
13
- /**
14
- * Creates a LangChain Tool that pauses execution for human approval.
15
- * Compatible with LangGraph and standard Agents.
16
- */
17
14
  declare function createLetsPingTool<T extends z.ZodType>(options: AdapterOptions<T>): DynamicStructuredTool<any>;
18
15
 
19
16
  export { createLetsPingTool };
@@ -9,11 +9,8 @@ interface AdapterOptions<T extends z.ZodType> {
9
9
  service?: string;
10
10
  priority?: "low" | "medium" | "high" | "critical";
11
11
  timeout?: number;
12
+ handler?: (args: z.infer<T>) => Promise<any> | any;
12
13
  }
13
- /**
14
- * Creates a LangChain Tool that pauses execution for human approval.
15
- * Compatible with LangGraph and standard Agents.
16
- */
17
14
  declare function createLetsPingTool<T extends z.ZodType>(options: AdapterOptions<T>): DynamicStructuredTool<any>;
18
15
 
19
16
  export { createLetsPingTool };
package/dist/langchain.js CHANGED
@@ -51,11 +51,30 @@ function createLetsPingTool(options) {
51
51
  metadata: decision.metadata
52
52
  });
53
53
  }
54
- return JSON.stringify({
54
+ const executed_input = decision.patched_payload || decision.payload;
55
+ let execution_output;
56
+ if (options.handler) {
57
+ execution_output = await options.handler(executed_input);
58
+ }
59
+ if (decision.patched_payload) {
60
+ const diff = (0, import_sdk.computeDiff)(decision.payload, decision.patched_payload);
61
+ const diff_summary = diff ? { changes: diff } : { changes: "Unknown structure changes" };
62
+ const letsping_context2 = {
63
+ status: "APPROVED_WITH_MODIFICATIONS",
64
+ message: "The human reviewer authorized this action but modified your original payload. Please review the diff_summary to learn from this correction.",
65
+ diff_summary,
66
+ original_input: decision.payload,
67
+ executed_input,
68
+ metadata: decision.metadata
69
+ };
70
+ return JSON.stringify(options.handler ? { letsping_context: letsping_context2, execution_output } : letsping_context2);
71
+ }
72
+ const letsping_context = {
55
73
  status: "APPROVED",
56
- approved_input: decision.patched_payload || decision.payload,
74
+ executed_input,
57
75
  metadata: decision.metadata
58
- });
76
+ };
77
+ return JSON.stringify(options.handler ? { letsping_context, execution_output } : letsping_context);
59
78
  } catch (error) {
60
79
  return JSON.stringify({
61
80
  status: "ERROR",
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/langchain.ts"],"sourcesContent":["import { DynamicStructuredTool } from \"@langchain/core/tools\";\r\nimport { LetsPing } from \"@letsping/sdk\";\r\nimport { z } from \"zod\";\r\n\r\ninterface AdapterOptions<T extends z.ZodType> {\r\n name: string;\r\n description: string;\r\n schema: T;\r\n apiKey: string;\r\n service?: string;\r\n priority?: \"low\" | \"medium\" | \"high\" | \"critical\";\r\n timeout?: number;\r\n}\r\n\r\n/**\r\n * Creates a LangChain Tool that pauses execution for human approval.\r\n * Compatible with LangGraph and standard Agents.\r\n */\r\nexport function createLetsPingTool<T extends z.ZodType>(options: AdapterOptions<T>) {\r\n if (!options.apiKey) {\r\n throw new Error(\"LetsPing Adapter Error: 'apiKey' is required.\");\r\n }\r\n\r\n const lp = new LetsPing(options.apiKey);\r\n\r\n return new DynamicStructuredTool({\r\n name: options.name,\r\n description: `${options.description} [SYSTEM NOTE: This tool pauses execution until a human approves the request via LetsPing. Do not expect an immediate result.]`,\r\n schema: options.schema as any,\r\n func: async (args: any) => {\r\n try {\r\n const decision = await lp.ask({\r\n service: options.service || \"langchain-agent\",\r\n action: options.name,\r\n priority: options.priority || \"medium\",\r\n payload: args,\r\n schema: options.schema,\r\n timeoutMs: options.timeout\r\n });\r\n\r\n if (decision.status === \"REJECTED\") {\r\n return JSON.stringify({\r\n status: \"REJECTED\",\r\n message: \"The human operator denied this request. Do not proceed with the action.\",\r\n metadata: decision.metadata\r\n });\r\n }\r\n\r\n return JSON.stringify({\r\n status: \"APPROVED\",\r\n approved_input: decision.patched_payload || decision.payload,\r\n metadata: decision.metadata\r\n });\r\n\r\n } catch (error: any) {\r\n return JSON.stringify({\r\n status: \"ERROR\",\r\n error: error.message || \"Unknown error during LetsPing approval process\",\r\n suggestion: \"Inform the user that the request for approval failed or timed out.\"\r\n });\r\n }\r\n }\r\n });\r\n}"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAsC;AACtC,iBAAyB;AAiBlB,SAAS,mBAAwC,SAA4B;AAChF,MAAI,CAAC,QAAQ,QAAQ;AACjB,UAAM,IAAI,MAAM,+CAA+C;AAAA,EACnE;AAEA,QAAM,KAAK,IAAI,oBAAS,QAAQ,MAAM;AAEtC,SAAO,IAAI,mCAAsB;AAAA,IAC7B,MAAM,QAAQ;AAAA,IACd,aAAa,GAAG,QAAQ,WAAW;AAAA,IACnC,QAAQ,QAAQ;AAAA,IAChB,MAAM,OAAO,SAAc;AACvB,UAAI;AACA,cAAM,WAAW,MAAM,GAAG,IAAI;AAAA,UAC1B,SAAS,QAAQ,WAAW;AAAA,UAC5B,QAAQ,QAAQ;AAAA,UAChB,UAAU,QAAQ,YAAY;AAAA,UAC9B,SAAS;AAAA,UACT,QAAQ,QAAQ;AAAA,UAChB,WAAW,QAAQ;AAAA,QACvB,CAAC;AAED,YAAI,SAAS,WAAW,YAAY;AAChC,iBAAO,KAAK,UAAU;AAAA,YAClB,QAAQ;AAAA,YACR,SAAS;AAAA,YACT,UAAU,SAAS;AAAA,UACvB,CAAC;AAAA,QACL;AAEA,eAAO,KAAK,UAAU;AAAA,UAClB,QAAQ;AAAA,UACR,gBAAgB,SAAS,mBAAmB,SAAS;AAAA,UACrD,UAAU,SAAS;AAAA,QACvB,CAAC;AAAA,MAEL,SAAS,OAAY;AACjB,eAAO,KAAK,UAAU;AAAA,UAClB,QAAQ;AAAA,UACR,OAAO,MAAM,WAAW;AAAA,UACxB,YAAY;AAAA,QAChB,CAAC;AAAA,MACL;AAAA,IACJ;AAAA,EACJ,CAAC;AACL;","names":[]}
1
+ {"version":3,"sources":["../src/langchain.ts"],"sourcesContent":["import { DynamicStructuredTool } from \"@langchain/core/tools\";\r\nimport { LetsPing, computeDiff } from \"@letsping/sdk\";\r\nimport { z } from \"zod\";\r\n\r\ninterface AdapterOptions<T extends z.ZodType> {\r\n name: string;\r\n description: string;\r\n schema: T;\r\n apiKey: string;\r\n service?: string;\r\n priority?: \"low\" | \"medium\" | \"high\" | \"critical\";\r\n timeout?: number;\r\n handler?: (args: z.infer<T>) => Promise<any> | any;\r\n}\r\n\nexport function createLetsPingTool<T extends z.ZodType>(options: AdapterOptions<T>) {\r\n if (!options.apiKey) {\r\n throw new Error(\"LetsPing Adapter Error: 'apiKey' is required.\");\r\n }\r\n\r\n const lp = new LetsPing(options.apiKey);\r\n\r\n return new DynamicStructuredTool({\r\n name: options.name,\r\n description: `${options.description} [SYSTEM NOTE: This tool pauses execution until a human approves the request via LetsPing. Do not expect an immediate result.]`,\r\n schema: options.schema as any,\r\n func: async (args: any) => {\r\n try {\r\n const decision = await lp.ask({\r\n service: options.service || \"langchain-agent\",\r\n action: options.name,\r\n priority: options.priority || \"medium\",\r\n payload: args,\r\n schema: options.schema,\r\n timeoutMs: options.timeout\r\n });\r\n\r\n if (decision.status === \"REJECTED\") {\r\n return JSON.stringify({\r\n status: \"REJECTED\",\r\n message: \"The human operator denied this request. Do not proceed with the action.\",\r\n metadata: decision.metadata\r\n });\r\n }\r\n\r\n const executed_input = decision.patched_payload || decision.payload;\r\n let execution_output;\r\n if (options.handler) {\r\n execution_output = await options.handler(executed_input);\r\n }\r\n\r\n if (decision.patched_payload) {\r\n const diff = computeDiff(decision.payload, decision.patched_payload);\r\n const diff_summary = diff ? { changes: diff } : { changes: \"Unknown structure changes\" };\r\n\r\n const letsping_context = {\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,\r\n original_input: decision.payload,\r\n executed_input,\r\n metadata: decision.metadata\r\n };\r\n\r\n return JSON.stringify(options.handler ? { letsping_context, execution_output } : letsping_context);\r\n }\r\n\r\n const letsping_context = {\r\n status: \"APPROVED\",\r\n executed_input,\r\n metadata: decision.metadata\r\n };\r\n\r\n return JSON.stringify(options.handler ? { letsping_context, execution_output } : letsping_context);\r\n\r\n } catch (error: any) {\r\n return JSON.stringify({\r\n status: \"ERROR\",\r\n error: error.message || \"Unknown error during LetsPing approval process\",\r\n suggestion: \"Inform the user that the request for approval failed or timed out.\"\r\n });\r\n }\r\n }\r\n });\r\n}"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAsC;AACtC,iBAAsC;AAc/B,SAAS,mBAAwC,SAA4B;AAChF,MAAI,CAAC,QAAQ,QAAQ;AACjB,UAAM,IAAI,MAAM,+CAA+C;AAAA,EACnE;AAEA,QAAM,KAAK,IAAI,oBAAS,QAAQ,MAAM;AAEtC,SAAO,IAAI,mCAAsB;AAAA,IAC7B,MAAM,QAAQ;AAAA,IACd,aAAa,GAAG,QAAQ,WAAW;AAAA,IACnC,QAAQ,QAAQ;AAAA,IAChB,MAAM,OAAO,SAAc;AACvB,UAAI;AACA,cAAM,WAAW,MAAM,GAAG,IAAI;AAAA,UAC1B,SAAS,QAAQ,WAAW;AAAA,UAC5B,QAAQ,QAAQ;AAAA,UAChB,UAAU,QAAQ,YAAY;AAAA,UAC9B,SAAS;AAAA,UACT,QAAQ,QAAQ;AAAA,UAChB,WAAW,QAAQ;AAAA,QACvB,CAAC;AAED,YAAI,SAAS,WAAW,YAAY;AAChC,iBAAO,KAAK,UAAU;AAAA,YAClB,QAAQ;AAAA,YACR,SAAS;AAAA,YACT,UAAU,SAAS;AAAA,UACvB,CAAC;AAAA,QACL;AAEA,cAAM,iBAAiB,SAAS,mBAAmB,SAAS;AAC5D,YAAI;AACJ,YAAI,QAAQ,SAAS;AACjB,6BAAmB,MAAM,QAAQ,QAAQ,cAAc;AAAA,QAC3D;AAEA,YAAI,SAAS,iBAAiB;AAC1B,gBAAM,WAAO,wBAAY,SAAS,SAAS,SAAS,eAAe;AACnE,gBAAM,eAAe,OAAO,EAAE,SAAS,KAAK,IAAI,EAAE,SAAS,4BAA4B;AAEvF,gBAAMA,oBAAmB;AAAA,YACrB,QAAQ;AAAA,YACR,SAAS;AAAA,YACT;AAAA,YACA,gBAAgB,SAAS;AAAA,YACzB;AAAA,YACA,UAAU,SAAS;AAAA,UACvB;AAEA,iBAAO,KAAK,UAAU,QAAQ,UAAU,EAAE,kBAAAA,mBAAkB,iBAAiB,IAAIA,iBAAgB;AAAA,QACrG;AAEA,cAAM,mBAAmB;AAAA,UACrB,QAAQ;AAAA,UACR;AAAA,UACA,UAAU,SAAS;AAAA,QACvB;AAEA,eAAO,KAAK,UAAU,QAAQ,UAAU,EAAE,kBAAkB,iBAAiB,IAAI,gBAAgB;AAAA,MAErG,SAAS,OAAY;AACjB,eAAO,KAAK,UAAU;AAAA,UAClB,QAAQ;AAAA,UACR,OAAO,MAAM,WAAW;AAAA,UACxB,YAAY;AAAA,QAChB,CAAC;AAAA,MACL;AAAA,IACJ;AAAA,EACJ,CAAC;AACL;","names":["letsping_context"]}
@@ -1,6 +1,6 @@
1
1
  // src/langchain.ts
2
2
  import { DynamicStructuredTool } from "@langchain/core/tools";
3
- import { LetsPing } from "@letsping/sdk";
3
+ import { LetsPing, computeDiff } from "@letsping/sdk";
4
4
  function createLetsPingTool(options) {
5
5
  if (!options.apiKey) {
6
6
  throw new Error("LetsPing Adapter Error: 'apiKey' is required.");
@@ -27,11 +27,30 @@ function createLetsPingTool(options) {
27
27
  metadata: decision.metadata
28
28
  });
29
29
  }
30
- return JSON.stringify({
30
+ const executed_input = decision.patched_payload || decision.payload;
31
+ let execution_output;
32
+ if (options.handler) {
33
+ execution_output = await options.handler(executed_input);
34
+ }
35
+ if (decision.patched_payload) {
36
+ const diff = computeDiff(decision.payload, decision.patched_payload);
37
+ const diff_summary = diff ? { changes: diff } : { changes: "Unknown structure changes" };
38
+ const letsping_context2 = {
39
+ status: "APPROVED_WITH_MODIFICATIONS",
40
+ message: "The human reviewer authorized this action but modified your original payload. Please review the diff_summary to learn from this correction.",
41
+ diff_summary,
42
+ original_input: decision.payload,
43
+ executed_input,
44
+ metadata: decision.metadata
45
+ };
46
+ return JSON.stringify(options.handler ? { letsping_context: letsping_context2, execution_output } : letsping_context2);
47
+ }
48
+ const letsping_context = {
31
49
  status: "APPROVED",
32
- approved_input: decision.patched_payload || decision.payload,
50
+ executed_input,
33
51
  metadata: decision.metadata
34
- });
52
+ };
53
+ return JSON.stringify(options.handler ? { letsping_context, execution_output } : letsping_context);
35
54
  } catch (error) {
36
55
  return JSON.stringify({
37
56
  status: "ERROR",
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/langchain.ts"],"sourcesContent":["import { DynamicStructuredTool } from \"@langchain/core/tools\";\r\nimport { LetsPing } from \"@letsping/sdk\";\r\nimport { z } from \"zod\";\r\n\r\ninterface AdapterOptions<T extends z.ZodType> {\r\n name: string;\r\n description: string;\r\n schema: T;\r\n apiKey: string;\r\n service?: string;\r\n priority?: \"low\" | \"medium\" | \"high\" | \"critical\";\r\n timeout?: number;\r\n}\r\n\r\n/**\r\n * Creates a LangChain Tool that pauses execution for human approval.\r\n * Compatible with LangGraph and standard Agents.\r\n */\r\nexport function createLetsPingTool<T extends z.ZodType>(options: AdapterOptions<T>) {\r\n if (!options.apiKey) {\r\n throw new Error(\"LetsPing Adapter Error: 'apiKey' is required.\");\r\n }\r\n\r\n const lp = new LetsPing(options.apiKey);\r\n\r\n return new DynamicStructuredTool({\r\n name: options.name,\r\n description: `${options.description} [SYSTEM NOTE: This tool pauses execution until a human approves the request via LetsPing. Do not expect an immediate result.]`,\r\n schema: options.schema as any,\r\n func: async (args: any) => {\r\n try {\r\n const decision = await lp.ask({\r\n service: options.service || \"langchain-agent\",\r\n action: options.name,\r\n priority: options.priority || \"medium\",\r\n payload: args,\r\n schema: options.schema,\r\n timeoutMs: options.timeout\r\n });\r\n\r\n if (decision.status === \"REJECTED\") {\r\n return JSON.stringify({\r\n status: \"REJECTED\",\r\n message: \"The human operator denied this request. Do not proceed with the action.\",\r\n metadata: decision.metadata\r\n });\r\n }\r\n\r\n return JSON.stringify({\r\n status: \"APPROVED\",\r\n approved_input: decision.patched_payload || decision.payload,\r\n metadata: decision.metadata\r\n });\r\n\r\n } catch (error: any) {\r\n return JSON.stringify({\r\n status: \"ERROR\",\r\n error: error.message || \"Unknown error during LetsPing approval process\",\r\n suggestion: \"Inform the user that the request for approval failed or timed out.\"\r\n });\r\n }\r\n }\r\n });\r\n}"],"mappings":";AAAA,SAAS,6BAA6B;AACtC,SAAS,gBAAgB;AAiBlB,SAAS,mBAAwC,SAA4B;AAChF,MAAI,CAAC,QAAQ,QAAQ;AACjB,UAAM,IAAI,MAAM,+CAA+C;AAAA,EACnE;AAEA,QAAM,KAAK,IAAI,SAAS,QAAQ,MAAM;AAEtC,SAAO,IAAI,sBAAsB;AAAA,IAC7B,MAAM,QAAQ;AAAA,IACd,aAAa,GAAG,QAAQ,WAAW;AAAA,IACnC,QAAQ,QAAQ;AAAA,IAChB,MAAM,OAAO,SAAc;AACvB,UAAI;AACA,cAAM,WAAW,MAAM,GAAG,IAAI;AAAA,UAC1B,SAAS,QAAQ,WAAW;AAAA,UAC5B,QAAQ,QAAQ;AAAA,UAChB,UAAU,QAAQ,YAAY;AAAA,UAC9B,SAAS;AAAA,UACT,QAAQ,QAAQ;AAAA,UAChB,WAAW,QAAQ;AAAA,QACvB,CAAC;AAED,YAAI,SAAS,WAAW,YAAY;AAChC,iBAAO,KAAK,UAAU;AAAA,YAClB,QAAQ;AAAA,YACR,SAAS;AAAA,YACT,UAAU,SAAS;AAAA,UACvB,CAAC;AAAA,QACL;AAEA,eAAO,KAAK,UAAU;AAAA,UAClB,QAAQ;AAAA,UACR,gBAAgB,SAAS,mBAAmB,SAAS;AAAA,UACrD,UAAU,SAAS;AAAA,QACvB,CAAC;AAAA,MAEL,SAAS,OAAY;AACjB,eAAO,KAAK,UAAU;AAAA,UAClB,QAAQ;AAAA,UACR,OAAO,MAAM,WAAW;AAAA,UACxB,YAAY;AAAA,QAChB,CAAC;AAAA,MACL;AAAA,IACJ;AAAA,EACJ,CAAC;AACL;","names":[]}
1
+ {"version":3,"sources":["../src/langchain.ts"],"sourcesContent":["import { DynamicStructuredTool } from \"@langchain/core/tools\";\r\nimport { LetsPing, computeDiff } from \"@letsping/sdk\";\r\nimport { z } from \"zod\";\r\n\r\ninterface AdapterOptions<T extends z.ZodType> {\r\n name: string;\r\n description: string;\r\n schema: T;\r\n apiKey: string;\r\n service?: string;\r\n priority?: \"low\" | \"medium\" | \"high\" | \"critical\";\r\n timeout?: number;\r\n handler?: (args: z.infer<T>) => Promise<any> | any;\r\n}\r\n\nexport function createLetsPingTool<T extends z.ZodType>(options: AdapterOptions<T>) {\r\n if (!options.apiKey) {\r\n throw new Error(\"LetsPing Adapter Error: 'apiKey' is required.\");\r\n }\r\n\r\n const lp = new LetsPing(options.apiKey);\r\n\r\n return new DynamicStructuredTool({\r\n name: options.name,\r\n description: `${options.description} [SYSTEM NOTE: This tool pauses execution until a human approves the request via LetsPing. Do not expect an immediate result.]`,\r\n schema: options.schema as any,\r\n func: async (args: any) => {\r\n try {\r\n const decision = await lp.ask({\r\n service: options.service || \"langchain-agent\",\r\n action: options.name,\r\n priority: options.priority || \"medium\",\r\n payload: args,\r\n schema: options.schema,\r\n timeoutMs: options.timeout\r\n });\r\n\r\n if (decision.status === \"REJECTED\") {\r\n return JSON.stringify({\r\n status: \"REJECTED\",\r\n message: \"The human operator denied this request. Do not proceed with the action.\",\r\n metadata: decision.metadata\r\n });\r\n }\r\n\r\n const executed_input = decision.patched_payload || decision.payload;\r\n let execution_output;\r\n if (options.handler) {\r\n execution_output = await options.handler(executed_input);\r\n }\r\n\r\n if (decision.patched_payload) {\r\n const diff = computeDiff(decision.payload, decision.patched_payload);\r\n const diff_summary = diff ? { changes: diff } : { changes: \"Unknown structure changes\" };\r\n\r\n const letsping_context = {\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,\r\n original_input: decision.payload,\r\n executed_input,\r\n metadata: decision.metadata\r\n };\r\n\r\n return JSON.stringify(options.handler ? { letsping_context, execution_output } : letsping_context);\r\n }\r\n\r\n const letsping_context = {\r\n status: \"APPROVED\",\r\n executed_input,\r\n metadata: decision.metadata\r\n };\r\n\r\n return JSON.stringify(options.handler ? { letsping_context, execution_output } : letsping_context);\r\n\r\n } catch (error: any) {\r\n return JSON.stringify({\r\n status: \"ERROR\",\r\n error: error.message || \"Unknown error during LetsPing approval process\",\r\n suggestion: \"Inform the user that the request for approval failed or timed out.\"\r\n });\r\n }\r\n }\r\n });\r\n}"],"mappings":";AAAA,SAAS,6BAA6B;AACtC,SAAS,UAAU,mBAAmB;AAc/B,SAAS,mBAAwC,SAA4B;AAChF,MAAI,CAAC,QAAQ,QAAQ;AACjB,UAAM,IAAI,MAAM,+CAA+C;AAAA,EACnE;AAEA,QAAM,KAAK,IAAI,SAAS,QAAQ,MAAM;AAEtC,SAAO,IAAI,sBAAsB;AAAA,IAC7B,MAAM,QAAQ;AAAA,IACd,aAAa,GAAG,QAAQ,WAAW;AAAA,IACnC,QAAQ,QAAQ;AAAA,IAChB,MAAM,OAAO,SAAc;AACvB,UAAI;AACA,cAAM,WAAW,MAAM,GAAG,IAAI;AAAA,UAC1B,SAAS,QAAQ,WAAW;AAAA,UAC5B,QAAQ,QAAQ;AAAA,UAChB,UAAU,QAAQ,YAAY;AAAA,UAC9B,SAAS;AAAA,UACT,QAAQ,QAAQ;AAAA,UAChB,WAAW,QAAQ;AAAA,QACvB,CAAC;AAED,YAAI,SAAS,WAAW,YAAY;AAChC,iBAAO,KAAK,UAAU;AAAA,YAClB,QAAQ;AAAA,YACR,SAAS;AAAA,YACT,UAAU,SAAS;AAAA,UACvB,CAAC;AAAA,QACL;AAEA,cAAM,iBAAiB,SAAS,mBAAmB,SAAS;AAC5D,YAAI;AACJ,YAAI,QAAQ,SAAS;AACjB,6BAAmB,MAAM,QAAQ,QAAQ,cAAc;AAAA,QAC3D;AAEA,YAAI,SAAS,iBAAiB;AAC1B,gBAAM,OAAO,YAAY,SAAS,SAAS,SAAS,eAAe;AACnE,gBAAM,eAAe,OAAO,EAAE,SAAS,KAAK,IAAI,EAAE,SAAS,4BAA4B;AAEvF,gBAAMA,oBAAmB;AAAA,YACrB,QAAQ;AAAA,YACR,SAAS;AAAA,YACT;AAAA,YACA,gBAAgB,SAAS;AAAA,YACzB;AAAA,YACA,UAAU,SAAS;AAAA,UACvB;AAEA,iBAAO,KAAK,UAAU,QAAQ,UAAU,EAAE,kBAAAA,mBAAkB,iBAAiB,IAAIA,iBAAgB;AAAA,QACrG;AAEA,cAAM,mBAAmB;AAAA,UACrB,QAAQ;AAAA,UACR;AAAA,UACA,UAAU,SAAS;AAAA,QACvB;AAEA,eAAO,KAAK,UAAU,QAAQ,UAAU,EAAE,kBAAkB,iBAAiB,IAAI,gBAAgB;AAAA,MAErG,SAAS,OAAY;AACjB,eAAO,KAAK,UAAU;AAAA,UAClB,QAAQ;AAAA,UACR,OAAO,MAAM,WAAW;AAAA,UACxB,YAAY;AAAA,QAChB,CAAC;AAAA,MACL;AAAA,IACJ;AAAA,EACJ,CAAC;AACL;","names":["letsping_context"]}
package/dist/vercel.d.mts CHANGED
@@ -9,42 +9,80 @@ interface AdapterOptions<T extends z.ZodType> {
9
9
  service?: string;
10
10
  priority?: "low" | "medium" | "high" | "critical";
11
11
  timeout?: number;
12
+ handler?: (args: z.infer<T>) => Promise<any> | any;
12
13
  }
13
- /**
14
- * Creates a Vercel AI SDK Tool that pauses execution for human approval.
15
- * @example
16
- * const tools = {
17
- * refund: letsPing({
18
- * name: "refund_user",
19
- * description: "Refund a user transaction",
20
- * schema: z.object({ amount: z.number() }),
21
- * apiKey: process.env.LETSPING_API_KEY!
22
- * })
23
- * }
24
- */
25
14
  declare function letsPing<T extends z.ZodType>(options: AdapterOptions<T>): ai.CoreTool<T, {
26
15
  status: string;
27
16
  message: string;
17
+ diff_summary: {
18
+ changes: any;
19
+ };
20
+ original_input: any;
21
+ executed_input: any;
28
22
  metadata: {
29
23
  resolved_at: string;
30
24
  actor_id: string;
31
25
  method?: string;
32
26
  } | undefined;
33
- rejection_reason: any;
34
- original_input?: undefined;
35
- approved_input?: undefined;
36
- error?: undefined;
37
- suggestion?: undefined;
38
27
  } | {
39
28
  status: string;
40
29
  original_input: T extends ai.Schema<any> ? T["_type"] : T extends z.ZodTypeAny ? z.TypeOf<T> : never;
41
- approved_input: any;
30
+ executed_input: any;
42
31
  metadata: {
43
32
  resolved_at: string;
44
33
  actor_id: string;
45
34
  method?: string;
46
35
  } | undefined;
36
+ } | {
37
+ status: string;
38
+ message: string;
39
+ metadata: {
40
+ resolved_at: string;
41
+ actor_id: string;
42
+ method?: string;
43
+ } | undefined;
44
+ rejection_reason: any;
45
+ letsping_context?: undefined;
46
+ execution_output?: undefined;
47
+ error?: undefined;
48
+ suggestion?: undefined;
49
+ } | {
50
+ letsping_context: {
51
+ status: string;
52
+ message: string;
53
+ diff_summary: {
54
+ changes: any;
55
+ };
56
+ original_input: any;
57
+ executed_input: any;
58
+ metadata: {
59
+ resolved_at: string;
60
+ actor_id: string;
61
+ method?: string;
62
+ } | undefined;
63
+ };
64
+ execution_output: any;
65
+ status?: undefined;
66
+ message?: undefined;
67
+ metadata?: undefined;
68
+ rejection_reason?: undefined;
69
+ error?: undefined;
70
+ suggestion?: undefined;
71
+ } | {
72
+ letsping_context: {
73
+ status: string;
74
+ original_input: T extends ai.Schema<any> ? T["_type"] : T extends z.ZodTypeAny ? z.TypeOf<T> : never;
75
+ executed_input: any;
76
+ metadata: {
77
+ resolved_at: string;
78
+ actor_id: string;
79
+ method?: string;
80
+ } | undefined;
81
+ };
82
+ execution_output: any;
83
+ status?: undefined;
47
84
  message?: undefined;
85
+ metadata?: undefined;
48
86
  rejection_reason?: undefined;
49
87
  error?: undefined;
50
88
  suggestion?: undefined;
@@ -55,34 +93,83 @@ declare function letsPing<T extends z.ZodType>(options: AdapterOptions<T>): ai.C
55
93
  message?: undefined;
56
94
  metadata?: undefined;
57
95
  rejection_reason?: undefined;
58
- original_input?: undefined;
59
- approved_input?: undefined;
96
+ letsping_context?: undefined;
97
+ execution_output?: undefined;
60
98
  }> & {
61
99
  execute: (args: T extends ai.Schema<any> ? T["_type"] : T extends z.ZodTypeAny ? z.TypeOf<T> : never, options: {
62
100
  abortSignal?: AbortSignal;
63
101
  }) => PromiseLike<{
64
102
  status: string;
65
103
  message: string;
104
+ diff_summary: {
105
+ changes: any;
106
+ };
107
+ original_input: any;
108
+ executed_input: any;
66
109
  metadata: {
67
110
  resolved_at: string;
68
111
  actor_id: string;
69
112
  method?: string;
70
113
  } | undefined;
71
- rejection_reason: any;
72
- original_input?: undefined;
73
- approved_input?: undefined;
74
- error?: undefined;
75
- suggestion?: undefined;
76
114
  } | {
77
115
  status: string;
78
116
  original_input: T extends ai.Schema<any> ? T["_type"] : T extends z.ZodTypeAny ? z.TypeOf<T> : never;
79
- approved_input: any;
117
+ executed_input: any;
80
118
  metadata: {
81
119
  resolved_at: string;
82
120
  actor_id: string;
83
121
  method?: string;
84
122
  } | undefined;
123
+ } | {
124
+ status: string;
125
+ message: string;
126
+ metadata: {
127
+ resolved_at: string;
128
+ actor_id: string;
129
+ method?: string;
130
+ } | undefined;
131
+ rejection_reason: any;
132
+ letsping_context?: undefined;
133
+ execution_output?: undefined;
134
+ error?: undefined;
135
+ suggestion?: undefined;
136
+ } | {
137
+ letsping_context: {
138
+ status: string;
139
+ message: string;
140
+ diff_summary: {
141
+ changes: any;
142
+ };
143
+ original_input: any;
144
+ executed_input: any;
145
+ metadata: {
146
+ resolved_at: string;
147
+ actor_id: string;
148
+ method?: string;
149
+ } | undefined;
150
+ };
151
+ execution_output: any;
152
+ status?: undefined;
85
153
  message?: undefined;
154
+ metadata?: undefined;
155
+ rejection_reason?: undefined;
156
+ error?: undefined;
157
+ suggestion?: undefined;
158
+ } | {
159
+ letsping_context: {
160
+ status: string;
161
+ original_input: T extends ai.Schema<any> ? T["_type"] : T extends z.ZodTypeAny ? z.TypeOf<T> : never;
162
+ executed_input: any;
163
+ metadata: {
164
+ resolved_at: string;
165
+ actor_id: string;
166
+ method?: string;
167
+ } | undefined;
168
+ };
169
+ execution_output: any;
170
+ status?: undefined;
171
+ message?: undefined;
172
+ metadata?: undefined;
86
173
  rejection_reason?: undefined;
87
174
  error?: undefined;
88
175
  suggestion?: undefined;
@@ -93,8 +180,8 @@ declare function letsPing<T extends z.ZodType>(options: AdapterOptions<T>): ai.C
93
180
  message?: undefined;
94
181
  metadata?: undefined;
95
182
  rejection_reason?: undefined;
96
- original_input?: undefined;
97
- approved_input?: undefined;
183
+ letsping_context?: undefined;
184
+ execution_output?: undefined;
98
185
  }>;
99
186
  };
100
187
 
package/dist/vercel.d.ts CHANGED
@@ -9,42 +9,80 @@ interface AdapterOptions<T extends z.ZodType> {
9
9
  service?: string;
10
10
  priority?: "low" | "medium" | "high" | "critical";
11
11
  timeout?: number;
12
+ handler?: (args: z.infer<T>) => Promise<any> | any;
12
13
  }
13
- /**
14
- * Creates a Vercel AI SDK Tool that pauses execution for human approval.
15
- * @example
16
- * const tools = {
17
- * refund: letsPing({
18
- * name: "refund_user",
19
- * description: "Refund a user transaction",
20
- * schema: z.object({ amount: z.number() }),
21
- * apiKey: process.env.LETSPING_API_KEY!
22
- * })
23
- * }
24
- */
25
14
  declare function letsPing<T extends z.ZodType>(options: AdapterOptions<T>): ai.CoreTool<T, {
26
15
  status: string;
27
16
  message: string;
17
+ diff_summary: {
18
+ changes: any;
19
+ };
20
+ original_input: any;
21
+ executed_input: any;
28
22
  metadata: {
29
23
  resolved_at: string;
30
24
  actor_id: string;
31
25
  method?: string;
32
26
  } | undefined;
33
- rejection_reason: any;
34
- original_input?: undefined;
35
- approved_input?: undefined;
36
- error?: undefined;
37
- suggestion?: undefined;
38
27
  } | {
39
28
  status: string;
40
29
  original_input: T extends ai.Schema<any> ? T["_type"] : T extends z.ZodTypeAny ? z.TypeOf<T> : never;
41
- approved_input: any;
30
+ executed_input: any;
42
31
  metadata: {
43
32
  resolved_at: string;
44
33
  actor_id: string;
45
34
  method?: string;
46
35
  } | undefined;
36
+ } | {
37
+ status: string;
38
+ message: string;
39
+ metadata: {
40
+ resolved_at: string;
41
+ actor_id: string;
42
+ method?: string;
43
+ } | undefined;
44
+ rejection_reason: any;
45
+ letsping_context?: undefined;
46
+ execution_output?: undefined;
47
+ error?: undefined;
48
+ suggestion?: undefined;
49
+ } | {
50
+ letsping_context: {
51
+ status: string;
52
+ message: string;
53
+ diff_summary: {
54
+ changes: any;
55
+ };
56
+ original_input: any;
57
+ executed_input: any;
58
+ metadata: {
59
+ resolved_at: string;
60
+ actor_id: string;
61
+ method?: string;
62
+ } | undefined;
63
+ };
64
+ execution_output: any;
65
+ status?: undefined;
66
+ message?: undefined;
67
+ metadata?: undefined;
68
+ rejection_reason?: undefined;
69
+ error?: undefined;
70
+ suggestion?: undefined;
71
+ } | {
72
+ letsping_context: {
73
+ status: string;
74
+ original_input: T extends ai.Schema<any> ? T["_type"] : T extends z.ZodTypeAny ? z.TypeOf<T> : never;
75
+ executed_input: any;
76
+ metadata: {
77
+ resolved_at: string;
78
+ actor_id: string;
79
+ method?: string;
80
+ } | undefined;
81
+ };
82
+ execution_output: any;
83
+ status?: undefined;
47
84
  message?: undefined;
85
+ metadata?: undefined;
48
86
  rejection_reason?: undefined;
49
87
  error?: undefined;
50
88
  suggestion?: undefined;
@@ -55,34 +93,83 @@ declare function letsPing<T extends z.ZodType>(options: AdapterOptions<T>): ai.C
55
93
  message?: undefined;
56
94
  metadata?: undefined;
57
95
  rejection_reason?: undefined;
58
- original_input?: undefined;
59
- approved_input?: undefined;
96
+ letsping_context?: undefined;
97
+ execution_output?: undefined;
60
98
  }> & {
61
99
  execute: (args: T extends ai.Schema<any> ? T["_type"] : T extends z.ZodTypeAny ? z.TypeOf<T> : never, options: {
62
100
  abortSignal?: AbortSignal;
63
101
  }) => PromiseLike<{
64
102
  status: string;
65
103
  message: string;
104
+ diff_summary: {
105
+ changes: any;
106
+ };
107
+ original_input: any;
108
+ executed_input: any;
66
109
  metadata: {
67
110
  resolved_at: string;
68
111
  actor_id: string;
69
112
  method?: string;
70
113
  } | undefined;
71
- rejection_reason: any;
72
- original_input?: undefined;
73
- approved_input?: undefined;
74
- error?: undefined;
75
- suggestion?: undefined;
76
114
  } | {
77
115
  status: string;
78
116
  original_input: T extends ai.Schema<any> ? T["_type"] : T extends z.ZodTypeAny ? z.TypeOf<T> : never;
79
- approved_input: any;
117
+ executed_input: any;
80
118
  metadata: {
81
119
  resolved_at: string;
82
120
  actor_id: string;
83
121
  method?: string;
84
122
  } | undefined;
123
+ } | {
124
+ status: string;
125
+ message: string;
126
+ metadata: {
127
+ resolved_at: string;
128
+ actor_id: string;
129
+ method?: string;
130
+ } | undefined;
131
+ rejection_reason: any;
132
+ letsping_context?: undefined;
133
+ execution_output?: undefined;
134
+ error?: undefined;
135
+ suggestion?: undefined;
136
+ } | {
137
+ letsping_context: {
138
+ status: string;
139
+ message: string;
140
+ diff_summary: {
141
+ changes: any;
142
+ };
143
+ original_input: any;
144
+ executed_input: any;
145
+ metadata: {
146
+ resolved_at: string;
147
+ actor_id: string;
148
+ method?: string;
149
+ } | undefined;
150
+ };
151
+ execution_output: any;
152
+ status?: undefined;
85
153
  message?: undefined;
154
+ metadata?: undefined;
155
+ rejection_reason?: undefined;
156
+ error?: undefined;
157
+ suggestion?: undefined;
158
+ } | {
159
+ letsping_context: {
160
+ status: string;
161
+ original_input: T extends ai.Schema<any> ? T["_type"] : T extends z.ZodTypeAny ? z.TypeOf<T> : never;
162
+ executed_input: any;
163
+ metadata: {
164
+ resolved_at: string;
165
+ actor_id: string;
166
+ method?: string;
167
+ } | undefined;
168
+ };
169
+ execution_output: any;
170
+ status?: undefined;
171
+ message?: undefined;
172
+ metadata?: undefined;
86
173
  rejection_reason?: undefined;
87
174
  error?: undefined;
88
175
  suggestion?: undefined;
@@ -93,8 +180,8 @@ declare function letsPing<T extends z.ZodType>(options: AdapterOptions<T>): ai.C
93
180
  message?: undefined;
94
181
  metadata?: undefined;
95
182
  rejection_reason?: undefined;
96
- original_input?: undefined;
97
- approved_input?: undefined;
183
+ letsping_context?: undefined;
184
+ execution_output?: undefined;
98
185
  }>;
99
186
  };
100
187
 
package/dist/vercel.js CHANGED
@@ -51,12 +51,31 @@ function letsPing(options) {
51
51
  rejection_reason: decision.rejection_reason || "No reason provided"
52
52
  };
53
53
  }
54
- return {
54
+ const executed_input = decision.patched_payload || decision.payload;
55
+ let execution_output;
56
+ if (options.handler) {
57
+ execution_output = await options.handler(executed_input);
58
+ }
59
+ if (decision.patched_payload) {
60
+ const diff = (0, import_sdk.computeDiff)(decision.payload, decision.patched_payload);
61
+ const diff_summary = diff ? { changes: diff } : { changes: "Unknown structure changes" };
62
+ const letsping_context2 = {
63
+ status: "APPROVED_WITH_MODIFICATIONS",
64
+ message: "The human reviewer authorized this action but modified your original payload. Please review the diff_summary to learn from this correction.",
65
+ diff_summary,
66
+ original_input: decision.payload,
67
+ executed_input,
68
+ metadata: decision.metadata
69
+ };
70
+ return options.handler ? { letsping_context: letsping_context2, execution_output } : letsping_context2;
71
+ }
72
+ const letsping_context = {
55
73
  status: "APPROVED",
56
74
  original_input: args,
57
- approved_input: decision.patched_payload || decision.payload,
75
+ executed_input,
58
76
  metadata: decision.metadata
59
77
  };
78
+ return options.handler ? { letsping_context, execution_output } : letsping_context;
60
79
  } catch (error) {
61
80
  return {
62
81
  status: "ERROR",
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/vercel.ts"],"sourcesContent":["import { tool as createVercelTool } from \"ai\";\r\nimport { LetsPing } from \"@letsping/sdk\";\r\nimport { z } from \"zod\";\r\n\r\ninterface AdapterOptions<T extends z.ZodType> {\r\n name: string;\r\n description: string;\r\n schema: T;\r\n apiKey: string;\r\n service?: string;\r\n priority?: \"low\" | \"medium\" | \"high\" | \"critical\";\r\n timeout?: number;\r\n}\r\n\r\n/**\r\n * Creates a Vercel AI SDK Tool that pauses execution for human approval.\r\n * @example\r\n * const tools = {\r\n * refund: letsPing({\r\n * name: \"refund_user\",\r\n * description: \"Refund a user transaction\",\r\n * schema: z.object({ amount: z.number() }),\r\n * apiKey: process.env.LETSPING_API_KEY!\r\n * })\r\n * }\r\n */\r\nexport function letsPing<T extends z.ZodType>(options: AdapterOptions<T>) {\r\n if (!options.apiKey) {\r\n throw new Error(\"LetsPing Adapter Error: 'apiKey' is required.\");\r\n }\r\n\r\n const lp = new LetsPing(options.apiKey);\r\n\r\n return createVercelTool({\r\n description: `${options.description} [SYSTEM NOTE: This tool pauses execution to wait for human approval. Do not expect an immediate result.]`,\r\n parameters: options.schema,\r\n execute: async (args) => {\r\n try {\r\n const decision = await lp.ask({\r\n service: options.service || \"vercel-ai-sdk\",\r\n action: options.name,\r\n priority: options.priority || \"medium\",\r\n payload: args,\r\n schema: options.schema,\r\n timeoutMs: options.timeout\r\n });\r\n\r\n if (decision.status === \"REJECTED\") {\r\n return {\r\n status: \"REJECTED\",\r\n message: \"The human operator explicitly denied this action. Do not proceed.\",\r\n metadata: decision.metadata,\r\n rejection_reason: (decision as any).rejection_reason || \"No reason provided\"\r\n };\r\n }\r\n\r\n return {\r\n status: \"APPROVED\",\r\n original_input: args,\r\n approved_input: decision.patched_payload || decision.payload,\r\n metadata: decision.metadata\r\n };\r\n\r\n } catch (error: any) {\r\n return {\r\n status: \"ERROR\",\r\n error: error.message || \"Control plane unreachable or request timed out.\",\r\n suggestion: \"Inform the user that the request for approval failed.\"\r\n };\r\n }\r\n },\r\n });\r\n}"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBAAyC;AACzC,iBAAyB;AAyBlB,SAAS,SAA8B,SAA4B;AACtE,MAAI,CAAC,QAAQ,QAAQ;AACjB,UAAM,IAAI,MAAM,+CAA+C;AAAA,EACnE;AAEA,QAAM,KAAK,IAAI,oBAAS,QAAQ,MAAM;AAEtC,aAAO,UAAAA,MAAiB;AAAA,IACpB,aAAa,GAAG,QAAQ,WAAW;AAAA,IACnC,YAAY,QAAQ;AAAA,IACpB,SAAS,OAAO,SAAS;AACrB,UAAI;AACA,cAAM,WAAW,MAAM,GAAG,IAAI;AAAA,UAC1B,SAAS,QAAQ,WAAW;AAAA,UAC5B,QAAQ,QAAQ;AAAA,UAChB,UAAU,QAAQ,YAAY;AAAA,UAC9B,SAAS;AAAA,UACT,QAAQ,QAAQ;AAAA,UAChB,WAAW,QAAQ;AAAA,QACvB,CAAC;AAED,YAAI,SAAS,WAAW,YAAY;AAChC,iBAAO;AAAA,YACH,QAAQ;AAAA,YACR,SAAS;AAAA,YACT,UAAU,SAAS;AAAA,YACnB,kBAAmB,SAAiB,oBAAoB;AAAA,UAC5D;AAAA,QACJ;AAEA,eAAO;AAAA,UACH,QAAQ;AAAA,UACR,gBAAgB;AAAA,UAChB,gBAAgB,SAAS,mBAAmB,SAAS;AAAA,UACrD,UAAU,SAAS;AAAA,QACvB;AAAA,MAEJ,SAAS,OAAY;AACjB,eAAO;AAAA,UACH,QAAQ;AAAA,UACR,OAAO,MAAM,WAAW;AAAA,UACxB,YAAY;AAAA,QAChB;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ,CAAC;AACL;","names":["createVercelTool"]}
1
+ {"version":3,"sources":["../src/vercel.ts"],"sourcesContent":["import { tool as createVercelTool } from \"ai\";\r\nimport { LetsPing, computeDiff } from \"@letsping/sdk\";\r\nimport { z } from \"zod\";\r\n\r\ninterface AdapterOptions<T extends z.ZodType> {\r\n name: string;\r\n description: string;\r\n schema: T;\r\n apiKey: string;\r\n service?: string;\r\n priority?: \"low\" | \"medium\" | \"high\" | \"critical\";\r\n timeout?: number;\r\n handler?: (args: z.infer<T>) => Promise<any> | any;\r\n}\r\n\nexport function letsPing<T extends z.ZodType>(options: AdapterOptions<T>) {\r\n if (!options.apiKey) {\r\n throw new Error(\"LetsPing Adapter Error: 'apiKey' is required.\");\r\n }\r\n\r\n const lp = new LetsPing(options.apiKey);\r\n\r\n return createVercelTool({\r\n description: `${options.description} [SYSTEM NOTE: This tool pauses execution to wait for human approval. Do not expect an immediate result.]`,\r\n parameters: options.schema,\r\n execute: async (args) => {\r\n try {\r\n const decision = await lp.ask({\r\n service: options.service || \"vercel-ai-sdk\",\r\n action: options.name,\r\n priority: options.priority || \"medium\",\r\n payload: args,\r\n schema: options.schema,\r\n timeoutMs: options.timeout\r\n });\r\n\r\n if (decision.status === \"REJECTED\") {\r\n return {\r\n status: \"REJECTED\",\r\n message: \"The human operator explicitly denied this action. Do not proceed.\",\r\n metadata: decision.metadata,\r\n rejection_reason: (decision as any).rejection_reason || \"No reason provided\"\r\n };\r\n }\r\n\r\n const executed_input = decision.patched_payload || decision.payload;\r\n let execution_output;\r\n if (options.handler) {\r\n execution_output = await options.handler(executed_input);\r\n }\r\n\r\n if (decision.patched_payload) {\r\n const diff = computeDiff(decision.payload, decision.patched_payload);\r\n const diff_summary = diff ? { changes: diff } : { changes: \"Unknown structure changes\" };\r\n\r\n const letsping_context = {\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,\r\n original_input: decision.payload,\r\n executed_input,\r\n metadata: decision.metadata\r\n };\r\n\r\n return options.handler ? { letsping_context, execution_output } : letsping_context;\r\n }\r\n\r\n const letsping_context = {\r\n status: \"APPROVED\",\r\n original_input: args,\r\n executed_input,\r\n metadata: decision.metadata\r\n };\r\n\r\n return options.handler ? { letsping_context, execution_output } : letsping_context;\r\n\r\n } catch (error: any) {\r\n return {\r\n status: \"ERROR\",\r\n error: error.message || \"Control plane unreachable or request timed out.\",\r\n suggestion: \"Inform the user that the request for approval failed.\"\r\n };\r\n }\r\n },\r\n });\r\n}"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBAAyC;AACzC,iBAAsC;AAc/B,SAAS,SAA8B,SAA4B;AACtE,MAAI,CAAC,QAAQ,QAAQ;AACjB,UAAM,IAAI,MAAM,+CAA+C;AAAA,EACnE;AAEA,QAAM,KAAK,IAAI,oBAAS,QAAQ,MAAM;AAEtC,aAAO,UAAAA,MAAiB;AAAA,IACpB,aAAa,GAAG,QAAQ,WAAW;AAAA,IACnC,YAAY,QAAQ;AAAA,IACpB,SAAS,OAAO,SAAS;AACrB,UAAI;AACA,cAAM,WAAW,MAAM,GAAG,IAAI;AAAA,UAC1B,SAAS,QAAQ,WAAW;AAAA,UAC5B,QAAQ,QAAQ;AAAA,UAChB,UAAU,QAAQ,YAAY;AAAA,UAC9B,SAAS;AAAA,UACT,QAAQ,QAAQ;AAAA,UAChB,WAAW,QAAQ;AAAA,QACvB,CAAC;AAED,YAAI,SAAS,WAAW,YAAY;AAChC,iBAAO;AAAA,YACH,QAAQ;AAAA,YACR,SAAS;AAAA,YACT,UAAU,SAAS;AAAA,YACnB,kBAAmB,SAAiB,oBAAoB;AAAA,UAC5D;AAAA,QACJ;AAEA,cAAM,iBAAiB,SAAS,mBAAmB,SAAS;AAC5D,YAAI;AACJ,YAAI,QAAQ,SAAS;AACjB,6BAAmB,MAAM,QAAQ,QAAQ,cAAc;AAAA,QAC3D;AAEA,YAAI,SAAS,iBAAiB;AAC1B,gBAAM,WAAO,wBAAY,SAAS,SAAS,SAAS,eAAe;AACnE,gBAAM,eAAe,OAAO,EAAE,SAAS,KAAK,IAAI,EAAE,SAAS,4BAA4B;AAEvF,gBAAMC,oBAAmB;AAAA,YACrB,QAAQ;AAAA,YACR,SAAS;AAAA,YACT;AAAA,YACA,gBAAgB,SAAS;AAAA,YACzB;AAAA,YACA,UAAU,SAAS;AAAA,UACvB;AAEA,iBAAO,QAAQ,UAAU,EAAE,kBAAAA,mBAAkB,iBAAiB,IAAIA;AAAA,QACtE;AAEA,cAAM,mBAAmB;AAAA,UACrB,QAAQ;AAAA,UACR,gBAAgB;AAAA,UAChB;AAAA,UACA,UAAU,SAAS;AAAA,QACvB;AAEA,eAAO,QAAQ,UAAU,EAAE,kBAAkB,iBAAiB,IAAI;AAAA,MAEtE,SAAS,OAAY;AACjB,eAAO;AAAA,UACH,QAAQ;AAAA,UACR,OAAO,MAAM,WAAW;AAAA,UACxB,YAAY;AAAA,QAChB;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ,CAAC;AACL;","names":["createVercelTool","letsping_context"]}
package/dist/vercel.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  // src/vercel.ts
2
2
  import { tool as createVercelTool } from "ai";
3
- import { LetsPing } from "@letsping/sdk";
3
+ import { LetsPing, computeDiff } from "@letsping/sdk";
4
4
  function letsPing(options) {
5
5
  if (!options.apiKey) {
6
6
  throw new Error("LetsPing Adapter Error: 'apiKey' is required.");
@@ -27,12 +27,31 @@ function letsPing(options) {
27
27
  rejection_reason: decision.rejection_reason || "No reason provided"
28
28
  };
29
29
  }
30
- return {
30
+ const executed_input = decision.patched_payload || decision.payload;
31
+ let execution_output;
32
+ if (options.handler) {
33
+ execution_output = await options.handler(executed_input);
34
+ }
35
+ if (decision.patched_payload) {
36
+ const diff = computeDiff(decision.payload, decision.patched_payload);
37
+ const diff_summary = diff ? { changes: diff } : { changes: "Unknown structure changes" };
38
+ const letsping_context2 = {
39
+ status: "APPROVED_WITH_MODIFICATIONS",
40
+ message: "The human reviewer authorized this action but modified your original payload. Please review the diff_summary to learn from this correction.",
41
+ diff_summary,
42
+ original_input: decision.payload,
43
+ executed_input,
44
+ metadata: decision.metadata
45
+ };
46
+ return options.handler ? { letsping_context: letsping_context2, execution_output } : letsping_context2;
47
+ }
48
+ const letsping_context = {
31
49
  status: "APPROVED",
32
50
  original_input: args,
33
- approved_input: decision.patched_payload || decision.payload,
51
+ executed_input,
34
52
  metadata: decision.metadata
35
53
  };
54
+ return options.handler ? { letsping_context, execution_output } : letsping_context;
36
55
  } catch (error) {
37
56
  return {
38
57
  status: "ERROR",
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/vercel.ts"],"sourcesContent":["import { tool as createVercelTool } from \"ai\";\r\nimport { LetsPing } from \"@letsping/sdk\";\r\nimport { z } from \"zod\";\r\n\r\ninterface AdapterOptions<T extends z.ZodType> {\r\n name: string;\r\n description: string;\r\n schema: T;\r\n apiKey: string;\r\n service?: string;\r\n priority?: \"low\" | \"medium\" | \"high\" | \"critical\";\r\n timeout?: number;\r\n}\r\n\r\n/**\r\n * Creates a Vercel AI SDK Tool that pauses execution for human approval.\r\n * @example\r\n * const tools = {\r\n * refund: letsPing({\r\n * name: \"refund_user\",\r\n * description: \"Refund a user transaction\",\r\n * schema: z.object({ amount: z.number() }),\r\n * apiKey: process.env.LETSPING_API_KEY!\r\n * })\r\n * }\r\n */\r\nexport function letsPing<T extends z.ZodType>(options: AdapterOptions<T>) {\r\n if (!options.apiKey) {\r\n throw new Error(\"LetsPing Adapter Error: 'apiKey' is required.\");\r\n }\r\n\r\n const lp = new LetsPing(options.apiKey);\r\n\r\n return createVercelTool({\r\n description: `${options.description} [SYSTEM NOTE: This tool pauses execution to wait for human approval. Do not expect an immediate result.]`,\r\n parameters: options.schema,\r\n execute: async (args) => {\r\n try {\r\n const decision = await lp.ask({\r\n service: options.service || \"vercel-ai-sdk\",\r\n action: options.name,\r\n priority: options.priority || \"medium\",\r\n payload: args,\r\n schema: options.schema,\r\n timeoutMs: options.timeout\r\n });\r\n\r\n if (decision.status === \"REJECTED\") {\r\n return {\r\n status: \"REJECTED\",\r\n message: \"The human operator explicitly denied this action. Do not proceed.\",\r\n metadata: decision.metadata,\r\n rejection_reason: (decision as any).rejection_reason || \"No reason provided\"\r\n };\r\n }\r\n\r\n return {\r\n status: \"APPROVED\",\r\n original_input: args,\r\n approved_input: decision.patched_payload || decision.payload,\r\n metadata: decision.metadata\r\n };\r\n\r\n } catch (error: any) {\r\n return {\r\n status: \"ERROR\",\r\n error: error.message || \"Control plane unreachable or request timed out.\",\r\n suggestion: \"Inform the user that the request for approval failed.\"\r\n };\r\n }\r\n },\r\n });\r\n}"],"mappings":";AAAA,SAAS,QAAQ,wBAAwB;AACzC,SAAS,gBAAgB;AAyBlB,SAAS,SAA8B,SAA4B;AACtE,MAAI,CAAC,QAAQ,QAAQ;AACjB,UAAM,IAAI,MAAM,+CAA+C;AAAA,EACnE;AAEA,QAAM,KAAK,IAAI,SAAS,QAAQ,MAAM;AAEtC,SAAO,iBAAiB;AAAA,IACpB,aAAa,GAAG,QAAQ,WAAW;AAAA,IACnC,YAAY,QAAQ;AAAA,IACpB,SAAS,OAAO,SAAS;AACrB,UAAI;AACA,cAAM,WAAW,MAAM,GAAG,IAAI;AAAA,UAC1B,SAAS,QAAQ,WAAW;AAAA,UAC5B,QAAQ,QAAQ;AAAA,UAChB,UAAU,QAAQ,YAAY;AAAA,UAC9B,SAAS;AAAA,UACT,QAAQ,QAAQ;AAAA,UAChB,WAAW,QAAQ;AAAA,QACvB,CAAC;AAED,YAAI,SAAS,WAAW,YAAY;AAChC,iBAAO;AAAA,YACH,QAAQ;AAAA,YACR,SAAS;AAAA,YACT,UAAU,SAAS;AAAA,YACnB,kBAAmB,SAAiB,oBAAoB;AAAA,UAC5D;AAAA,QACJ;AAEA,eAAO;AAAA,UACH,QAAQ;AAAA,UACR,gBAAgB;AAAA,UAChB,gBAAgB,SAAS,mBAAmB,SAAS;AAAA,UACrD,UAAU,SAAS;AAAA,QACvB;AAAA,MAEJ,SAAS,OAAY;AACjB,eAAO;AAAA,UACH,QAAQ;AAAA,UACR,OAAO,MAAM,WAAW;AAAA,UACxB,YAAY;AAAA,QAChB;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ,CAAC;AACL;","names":[]}
1
+ {"version":3,"sources":["../src/vercel.ts"],"sourcesContent":["import { tool as createVercelTool } from \"ai\";\r\nimport { LetsPing, computeDiff } from \"@letsping/sdk\";\r\nimport { z } from \"zod\";\r\n\r\ninterface AdapterOptions<T extends z.ZodType> {\r\n name: string;\r\n description: string;\r\n schema: T;\r\n apiKey: string;\r\n service?: string;\r\n priority?: \"low\" | \"medium\" | \"high\" | \"critical\";\r\n timeout?: number;\r\n handler?: (args: z.infer<T>) => Promise<any> | any;\r\n}\r\n\nexport function letsPing<T extends z.ZodType>(options: AdapterOptions<T>) {\r\n if (!options.apiKey) {\r\n throw new Error(\"LetsPing Adapter Error: 'apiKey' is required.\");\r\n }\r\n\r\n const lp = new LetsPing(options.apiKey);\r\n\r\n return createVercelTool({\r\n description: `${options.description} [SYSTEM NOTE: This tool pauses execution to wait for human approval. Do not expect an immediate result.]`,\r\n parameters: options.schema,\r\n execute: async (args) => {\r\n try {\r\n const decision = await lp.ask({\r\n service: options.service || \"vercel-ai-sdk\",\r\n action: options.name,\r\n priority: options.priority || \"medium\",\r\n payload: args,\r\n schema: options.schema,\r\n timeoutMs: options.timeout\r\n });\r\n\r\n if (decision.status === \"REJECTED\") {\r\n return {\r\n status: \"REJECTED\",\r\n message: \"The human operator explicitly denied this action. Do not proceed.\",\r\n metadata: decision.metadata,\r\n rejection_reason: (decision as any).rejection_reason || \"No reason provided\"\r\n };\r\n }\r\n\r\n const executed_input = decision.patched_payload || decision.payload;\r\n let execution_output;\r\n if (options.handler) {\r\n execution_output = await options.handler(executed_input);\r\n }\r\n\r\n if (decision.patched_payload) {\r\n const diff = computeDiff(decision.payload, decision.patched_payload);\r\n const diff_summary = diff ? { changes: diff } : { changes: \"Unknown structure changes\" };\r\n\r\n const letsping_context = {\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,\r\n original_input: decision.payload,\r\n executed_input,\r\n metadata: decision.metadata\r\n };\r\n\r\n return options.handler ? { letsping_context, execution_output } : letsping_context;\r\n }\r\n\r\n const letsping_context = {\r\n status: \"APPROVED\",\r\n original_input: args,\r\n executed_input,\r\n metadata: decision.metadata\r\n };\r\n\r\n return options.handler ? { letsping_context, execution_output } : letsping_context;\r\n\r\n } catch (error: any) {\r\n return {\r\n status: \"ERROR\",\r\n error: error.message || \"Control plane unreachable or request timed out.\",\r\n suggestion: \"Inform the user that the request for approval failed.\"\r\n };\r\n }\r\n },\r\n });\r\n}"],"mappings":";AAAA,SAAS,QAAQ,wBAAwB;AACzC,SAAS,UAAU,mBAAmB;AAc/B,SAAS,SAA8B,SAA4B;AACtE,MAAI,CAAC,QAAQ,QAAQ;AACjB,UAAM,IAAI,MAAM,+CAA+C;AAAA,EACnE;AAEA,QAAM,KAAK,IAAI,SAAS,QAAQ,MAAM;AAEtC,SAAO,iBAAiB;AAAA,IACpB,aAAa,GAAG,QAAQ,WAAW;AAAA,IACnC,YAAY,QAAQ;AAAA,IACpB,SAAS,OAAO,SAAS;AACrB,UAAI;AACA,cAAM,WAAW,MAAM,GAAG,IAAI;AAAA,UAC1B,SAAS,QAAQ,WAAW;AAAA,UAC5B,QAAQ,QAAQ;AAAA,UAChB,UAAU,QAAQ,YAAY;AAAA,UAC9B,SAAS;AAAA,UACT,QAAQ,QAAQ;AAAA,UAChB,WAAW,QAAQ;AAAA,QACvB,CAAC;AAED,YAAI,SAAS,WAAW,YAAY;AAChC,iBAAO;AAAA,YACH,QAAQ;AAAA,YACR,SAAS;AAAA,YACT,UAAU,SAAS;AAAA,YACnB,kBAAmB,SAAiB,oBAAoB;AAAA,UAC5D;AAAA,QACJ;AAEA,cAAM,iBAAiB,SAAS,mBAAmB,SAAS;AAC5D,YAAI;AACJ,YAAI,QAAQ,SAAS;AACjB,6BAAmB,MAAM,QAAQ,QAAQ,cAAc;AAAA,QAC3D;AAEA,YAAI,SAAS,iBAAiB;AAC1B,gBAAM,OAAO,YAAY,SAAS,SAAS,SAAS,eAAe;AACnE,gBAAM,eAAe,OAAO,EAAE,SAAS,KAAK,IAAI,EAAE,SAAS,4BAA4B;AAEvF,gBAAMA,oBAAmB;AAAA,YACrB,QAAQ;AAAA,YACR,SAAS;AAAA,YACT;AAAA,YACA,gBAAgB,SAAS;AAAA,YACzB;AAAA,YACA,UAAU,SAAS;AAAA,UACvB;AAEA,iBAAO,QAAQ,UAAU,EAAE,kBAAAA,mBAAkB,iBAAiB,IAAIA;AAAA,QACtE;AAEA,cAAM,mBAAmB;AAAA,UACrB,QAAQ;AAAA,UACR,gBAAgB;AAAA,UAChB;AAAA,UACA,UAAU,SAAS;AAAA,QACvB;AAEA,eAAO,QAAQ,UAAU,EAAE,kBAAkB,iBAAiB,IAAI;AAAA,MAEtE,SAAS,OAAY;AACjB,eAAO;AAAA,UACH,QAAQ;AAAA,UACR,OAAO,MAAM,WAAW;AAAA,UACxB,YAAY;AAAA,QAChB;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ,CAAC;AACL;","names":["letsping_context"]}
package/package.json CHANGED
@@ -1,44 +1,44 @@
1
- {
2
- "name": "@letsping/adapters",
3
- "version": "0.1.1",
4
- "description": "Drop-in Human-in-the-Loop adapters for Vercel AI SDK and LangChain",
5
- "files": [
6
- "dist"
7
- ],
8
- "exports": {
9
- "./vercel": {
10
- "types": "./dist/vercel.d.ts",
11
- "import": "./dist/vercel.js",
12
- "require": "./dist/vercel.js"
13
- },
14
- "./langchain": {
15
- "types": "./dist/langchain.d.ts",
16
- "import": "./dist/langchain.js",
17
- "require": "./dist/langchain.js"
18
- }
19
- },
20
- "scripts": {
21
- "build": "tsup",
22
- "dev": "tsup --watch",
23
- "clean": "rm -rf dist .turbo"
24
- },
25
- "peerDependencies": {
26
- "@langchain/core": ">=0.1.0",
27
- "ai": ">=2.0.0",
28
- "zod": ">=3.0.0"
29
- },
30
- "dependencies": {
31
- "@letsping/sdk": "^0.1.0"
32
- },
33
- "devDependencies": {
34
- "tsup": "^8.0.0",
35
- "typescript": "^5.0.0",
36
- "@types/node": "^20.0.0",
37
- "ai": "^3.0.0",
38
- "@langchain/core": "^0.1.0",
39
- "zod": "^3.0.0"
40
- },
41
- "publishConfig": {
42
- "access": "public"
43
- }
1
+ {
2
+ "name": "@letsping/adapters",
3
+ "version": "0.1.3",
4
+ "description": "Drop-in Human-in-the-Loop adapters for Vercel AI SDK and LangChain",
5
+ "files": [
6
+ "dist"
7
+ ],
8
+ "exports": {
9
+ "./vercel": {
10
+ "types": "./dist/vercel.d.ts",
11
+ "import": "./dist/vercel.js",
12
+ "require": "./dist/vercel.js"
13
+ },
14
+ "./langchain": {
15
+ "types": "./dist/langchain.d.ts",
16
+ "import": "./dist/langchain.js",
17
+ "require": "./dist/langchain.js"
18
+ }
19
+ },
20
+ "scripts": {
21
+ "build": "tsup",
22
+ "dev": "tsup --watch",
23
+ "clean": "rm -rf dist .turbo"
24
+ },
25
+ "peerDependencies": {
26
+ "@langchain/core": ">=0.1.0",
27
+ "ai": ">=2.0.0",
28
+ "zod": ">=3.0.0"
29
+ },
30
+ "dependencies": {
31
+ "@letsping/sdk": "0.1.3"
32
+ },
33
+ "devDependencies": {
34
+ "tsup": "^8.0.0",
35
+ "typescript": "^5.0.0",
36
+ "@types/node": "^20.0.0",
37
+ "ai": "^3.0.0",
38
+ "@langchain/core": "^0.1.0",
39
+ "zod": "^3.0.0"
40
+ },
41
+ "publishConfig": {
42
+ "access": "public"
43
+ }
44
44
  }