@runplane/runplane-sdk 1.1.1 → 1.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/README.md +107 -52
- package/dist/index.d.ts +1 -122
- package/dist/index.js +17 -100
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,83 +1,122 @@
|
|
|
1
1
|
# @runplane/runplane-sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Control what your AI agents are allowed to do — in real time.
|
|
4
4
|
|
|
5
5
|
Runplane sits between your AI agents and execution. Every action passes through `guard()`, which enforces a decision before your code runs.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 🚀 Start in 2 Minutes
|
|
10
|
+
|
|
11
|
+
### 1. Install the SDK
|
|
8
12
|
|
|
9
13
|
```bash
|
|
10
14
|
npm install @runplane/runplane-sdk
|
|
11
15
|
```
|
|
12
16
|
|
|
13
|
-
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
### 2. Get your API key (Free 14-day trial)
|
|
20
|
+
|
|
21
|
+
👉 https://runplane.ai/
|
|
22
|
+
|
|
23
|
+
Create your account and copy your API key.
|
|
24
|
+
|
|
25
|
+
⚠️ **Important:** The SDK will not work without a valid API key.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
### 3. Run your first protected action
|
|
14
30
|
|
|
15
31
|
```javascript
|
|
16
32
|
require("dotenv").config()
|
|
17
|
-
const { Runplane } = require("@
|
|
33
|
+
const { Runplane } = require("@runplane/runplane-sdk")
|
|
34
|
+
|
|
18
35
|
const runplane = new Runplane({
|
|
19
36
|
apiKey: process.env.RUNPLANE_API_KEY,
|
|
20
37
|
})
|
|
21
38
|
|
|
22
|
-
|
|
23
|
-
await runplane.guard(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
)
|
|
39
|
+
async function main() {
|
|
40
|
+
await runplane.guard(
|
|
41
|
+
"transfer_funds",
|
|
42
|
+
"finance-system",
|
|
43
|
+
{ fromAccountId: "acc_1", toAccountId: "acc_2", amount: 400 },
|
|
44
|
+
async () => {
|
|
45
|
+
return await executeTransfer()
|
|
46
|
+
}
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
main()
|
|
31
51
|
```
|
|
32
52
|
|
|
33
|
-
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 💡 What Runplane Does
|
|
56
|
+
|
|
57
|
+
Runplane gives you **real-time control over AI agent actions**.
|
|
58
|
+
|
|
59
|
+
Before any action runs, Runplane evaluates:
|
|
60
|
+
|
|
61
|
+
* Policies
|
|
62
|
+
* Risk
|
|
63
|
+
* Context
|
|
34
64
|
|
|
35
|
-
|
|
65
|
+
And returns a decision:
|
|
66
|
+
|
|
67
|
+
* **ALLOW** → execution continues
|
|
68
|
+
* **BLOCK** → action is stopped
|
|
69
|
+
* **REQUIRE_APPROVAL** → human approval required
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## ⚙️ How It Works
|
|
74
|
+
|
|
75
|
+
`guard()` calls the Runplane API before executing your handler:
|
|
36
76
|
|
|
37
77
|
1. Sends action + target + context to Runplane
|
|
38
78
|
2. Runplane evaluates policies and risk
|
|
39
|
-
3. Returns
|
|
40
|
-
- **ALLOW** → handler executes immediately
|
|
41
|
-
- **BLOCK** → throws `RunplaneError`, handler never runs
|
|
42
|
-
- **REQUIRE_APPROVAL** → throws `RunplaneError`, awaits human decision
|
|
79
|
+
3. Returns a decision:
|
|
43
80
|
|
|
44
|
-
|
|
81
|
+
* **ALLOW** → handler executes
|
|
82
|
+
* **BLOCK** → throws `RunplaneError`
|
|
83
|
+
* **REQUIRE_APPROVAL** → throws `RunplaneError` and waits for approval
|
|
45
84
|
|
|
46
|
-
|
|
85
|
+
---
|
|
47
86
|
|
|
48
|
-
|
|
87
|
+
## 📘 API Reference
|
|
88
|
+
|
|
89
|
+
### `new Runplane(config)`
|
|
49
90
|
|
|
50
91
|
```javascript
|
|
51
92
|
const runplane = new Runplane({
|
|
52
|
-
apiKey: "your_api_key",
|
|
53
|
-
baseUrl: "https://runplane.ai",
|
|
93
|
+
apiKey: "your_api_key",
|
|
94
|
+
baseUrl: "https://runplane.ai",
|
|
54
95
|
})
|
|
55
96
|
```
|
|
56
97
|
|
|
57
|
-
|
|
98
|
+
---
|
|
58
99
|
|
|
59
|
-
|
|
100
|
+
### `guard(action, target, context, handler)`
|
|
60
101
|
|
|
61
102
|
```javascript
|
|
62
103
|
const result = await runplane.guard(
|
|
63
|
-
"delete_record",
|
|
64
|
-
"hr_system",
|
|
65
|
-
{ employeeId: "emp_123" },
|
|
104
|
+
"delete_record",
|
|
105
|
+
"hr_system",
|
|
106
|
+
{ employeeId: "emp_123" },
|
|
66
107
|
async () => {
|
|
67
|
-
// Your code here - only runs if ALLOW
|
|
68
108
|
return await deleteEmployee("emp_123")
|
|
69
109
|
}
|
|
70
110
|
)
|
|
71
111
|
```
|
|
72
112
|
|
|
73
|
-
**Returns:**
|
|
113
|
+
**Returns:** handler result if ALLOW
|
|
114
|
+
**Throws:** `RunplaneError` if BLOCK or REQUIRE_APPROVAL
|
|
74
115
|
|
|
75
|
-
|
|
116
|
+
---
|
|
76
117
|
|
|
77
118
|
### `decide(payload)`
|
|
78
119
|
|
|
79
|
-
Low-level method to request a decision without automatic enforcement.
|
|
80
|
-
|
|
81
120
|
```javascript
|
|
82
121
|
const result = await runplane.decide({
|
|
83
122
|
action: "send_email",
|
|
@@ -85,17 +124,19 @@ const result = await runplane.decide({
|
|
|
85
124
|
context: { recipients: 1200 },
|
|
86
125
|
})
|
|
87
126
|
|
|
88
|
-
console.log(result.decision)
|
|
127
|
+
console.log(result.decision)
|
|
89
128
|
```
|
|
90
129
|
|
|
91
|
-
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## 🧠 Handling Decisions
|
|
92
133
|
|
|
93
134
|
```javascript
|
|
94
135
|
const { Runplane, RunplaneError } = require("@runplane/runplane-sdk")
|
|
95
136
|
|
|
96
137
|
try {
|
|
97
138
|
await runplane.guard("action", "target", {}, async () => {
|
|
98
|
-
//
|
|
139
|
+
// your code
|
|
99
140
|
})
|
|
100
141
|
} catch (err) {
|
|
101
142
|
if (err instanceof RunplaneError) {
|
|
@@ -109,36 +150,50 @@ try {
|
|
|
109
150
|
}
|
|
110
151
|
```
|
|
111
152
|
|
|
112
|
-
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## 📊 Decision Types
|
|
113
156
|
|
|
114
|
-
| Decision
|
|
115
|
-
|
|
116
|
-
| `ALLOW`
|
|
117
|
-
| `BLOCK`
|
|
118
|
-
| `REQUIRE_APPROVAL` |
|
|
157
|
+
| Decision | Behavior |
|
|
158
|
+
| ------------------ | ---------------------------- |
|
|
159
|
+
| `ALLOW` | Handler executes immediately |
|
|
160
|
+
| `BLOCK` | Throws `RunplaneError` |
|
|
161
|
+
| `REQUIRE_APPROVAL` | Requires human approval |
|
|
119
162
|
|
|
120
|
-
|
|
163
|
+
---
|
|
121
164
|
|
|
122
|
-
|
|
165
|
+
## ❗ Error Object
|
|
123
166
|
|
|
124
167
|
```javascript
|
|
125
168
|
{
|
|
126
169
|
message: "Runplane blocked this action",
|
|
127
|
-
code: "BLOCK",
|
|
128
|
-
runplane: {
|
|
170
|
+
code: "BLOCK",
|
|
171
|
+
runplane: {
|
|
129
172
|
decision: "BLOCK",
|
|
130
|
-
reason: "Policy
|
|
173
|
+
reason: "Policy violation",
|
|
131
174
|
requestId: "req_abc123",
|
|
132
175
|
riskScore: 91,
|
|
133
176
|
}
|
|
134
177
|
}
|
|
135
178
|
```
|
|
136
179
|
|
|
137
|
-
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## ⚠️ Requirements
|
|
183
|
+
|
|
184
|
+
* Node.js 18+
|
|
185
|
+
* Runplane API key 👉 https://runplane.ai/
|
|
186
|
+
* Internet access
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## 💬 Feedback
|
|
191
|
+
|
|
192
|
+
Got stuck? Something unclear? Want to suggest improvements?
|
|
193
|
+
|
|
194
|
+
👉 https://runplane.ai/
|
|
138
195
|
|
|
139
|
-
|
|
140
|
-
- Valid Runplane API key
|
|
141
|
-
- Network access to `https://runplane.ai`
|
|
196
|
+
---
|
|
142
197
|
|
|
143
198
|
## License
|
|
144
199
|
|
package/dist/index.d.ts
CHANGED
|
@@ -104,138 +104,17 @@ type RunplaneErrorCode = "BLOCKED" | "DENIED" | "TIMEOUT" | "NETWORK_ERROR" | "I
|
|
|
104
104
|
* @runplane/runplane-sdk - Main client for the Runplane API
|
|
105
105
|
*/
|
|
106
106
|
|
|
107
|
-
/**
|
|
108
|
-
* Runplane SDK Client
|
|
109
|
-
*
|
|
110
|
-
* The main entry point for interacting with the Runplane control plane.
|
|
111
|
-
* Use this to request execution clearance before performing sensitive actions.
|
|
112
|
-
*
|
|
113
|
-
* @example
|
|
114
|
-
* ```typescript
|
|
115
|
-
* import { Runplane } from "@runplane/runplane-sdk";
|
|
116
|
-
*
|
|
117
|
-
* const runplane = new Runplane({
|
|
118
|
-
* apiKey: process.env.RUNPLANE_SYSTEM_KEY!,
|
|
119
|
-
* baseUrl: "https://runplane.ai",
|
|
120
|
-
* failMode: "closed"
|
|
121
|
-
* });
|
|
122
|
-
*
|
|
123
|
-
* const decision = await runplane.decide({
|
|
124
|
-
* actionType: "send_email",
|
|
125
|
-
* target: "marketing_list",
|
|
126
|
-
* context: { recipients: 1200 }
|
|
127
|
-
* });
|
|
128
|
-
*
|
|
129
|
-
* if (decision.decision === "ALLOW") {
|
|
130
|
-
* // Proceed with the action
|
|
131
|
-
* }
|
|
132
|
-
* ```
|
|
133
|
-
*/
|
|
134
107
|
declare class Runplane {
|
|
135
108
|
private readonly baseUrl;
|
|
136
109
|
private readonly apiKey;
|
|
137
110
|
private readonly timeoutMs;
|
|
138
111
|
private readonly failMode;
|
|
139
112
|
private readonly approvalPoller;
|
|
113
|
+
private hasLoggedInit;
|
|
140
114
|
constructor(config: RunplaneConfig);
|
|
141
|
-
/**
|
|
142
|
-
* Request a decision from the Runplane control plane.
|
|
143
|
-
*
|
|
144
|
-
* Call this before executing any sensitive action. The response will indicate
|
|
145
|
-
* whether the action should be ALLOWED, BLOCKED, or REQUIRE_APPROVAL.
|
|
146
|
-
*
|
|
147
|
-
* @param request - The action details to evaluate
|
|
148
|
-
* @returns The decision response
|
|
149
|
-
*
|
|
150
|
-
* @example
|
|
151
|
-
* ```typescript
|
|
152
|
-
* const decision = await runplane.decide({
|
|
153
|
-
* actionType: "delete_record",
|
|
154
|
-
* target: "users.prod",
|
|
155
|
-
* context: { recordId: "usr_123", reason: "gdpr_request" }
|
|
156
|
-
* });
|
|
157
|
-
*
|
|
158
|
-
* switch (decision.decision) {
|
|
159
|
-
* case "ALLOW":
|
|
160
|
-
* await deleteRecord(recordId);
|
|
161
|
-
* break;
|
|
162
|
-
* case "BLOCK":
|
|
163
|
-
* console.error("Action blocked:", decision.reason);
|
|
164
|
-
* break;
|
|
165
|
-
* case "REQUIRE_APPROVAL":
|
|
166
|
-
* // Wait for human approval
|
|
167
|
-
* const result = await runplane.waitForApproval(decision.requestId);
|
|
168
|
-
* if (result.approved) {
|
|
169
|
-
* await deleteRecord(recordId);
|
|
170
|
-
* }
|
|
171
|
-
* break;
|
|
172
|
-
* }
|
|
173
|
-
* ```
|
|
174
|
-
*/
|
|
175
115
|
decide(request: DecideRequest): Promise<DecideResponse>;
|
|
176
|
-
/**
|
|
177
|
-
* Wait for an approval decision on a pending request.
|
|
178
|
-
*
|
|
179
|
-
* Use this when decide() returns REQUIRE_APPROVAL. This method will poll
|
|
180
|
-
* the approval endpoint until the request is approved, denied, or times out.
|
|
181
|
-
*
|
|
182
|
-
* @param requestId - The requestId from the decide() response
|
|
183
|
-
* @param options - Optional configuration for polling behavior
|
|
184
|
-
* @returns The approval result
|
|
185
|
-
*
|
|
186
|
-
* @example
|
|
187
|
-
* ```typescript
|
|
188
|
-
* const decision = await runplane.decide({ ... });
|
|
189
|
-
*
|
|
190
|
-
* if (decision.decision === "REQUIRE_APPROVAL") {
|
|
191
|
-
* console.log("Waiting for approval...");
|
|
192
|
-
*
|
|
193
|
-
* const result = await runplane.waitForApproval(decision.requestId, {
|
|
194
|
-
* timeoutMs: 600000, // 10 minutes
|
|
195
|
-
* onPoll: (status, elapsed) => {
|
|
196
|
-
* console.log(`Still waiting... ${elapsed}ms elapsed`);
|
|
197
|
-
* }
|
|
198
|
-
* });
|
|
199
|
-
*
|
|
200
|
-
* if (result.approved) {
|
|
201
|
-
* console.log("Approved by:", result.resolvedBy);
|
|
202
|
-
* } else {
|
|
203
|
-
* console.log("Denied:", result.comment);
|
|
204
|
-
* }
|
|
205
|
-
* }
|
|
206
|
-
* ```
|
|
207
|
-
*/
|
|
208
116
|
waitForApproval(requestId: string, options?: WaitForApprovalOptions): Promise<WaitForApprovalResult>;
|
|
209
|
-
/**
|
|
210
|
-
* Guard a function with containment evaluation.
|
|
211
|
-
*
|
|
212
|
-
* This is a convenience method that wraps decide() and waitForApproval()
|
|
213
|
-
* into a single call. If the action is blocked or denied, it throws.
|
|
214
|
-
* If approved, it executes the provided function.
|
|
215
|
-
*
|
|
216
|
-
* @param actionType - Type of action being performed
|
|
217
|
-
* @param target - Target resource
|
|
218
|
-
* @param context - Additional context
|
|
219
|
-
* @param fn - Function to execute if allowed
|
|
220
|
-
* @returns The result of fn()
|
|
221
|
-
* @throws RunplaneError if blocked, denied, or times out (in closed mode)
|
|
222
|
-
*
|
|
223
|
-
* @example
|
|
224
|
-
* ```typescript
|
|
225
|
-
* const result = await runplane.guard(
|
|
226
|
-
* "payment_transfer",
|
|
227
|
-
* "external_bank",
|
|
228
|
-
* { amount: 50000, currency: "USD" },
|
|
229
|
-
* async () => {
|
|
230
|
-
* return await paymentService.transfer(amount, recipient);
|
|
231
|
-
* }
|
|
232
|
-
* );
|
|
233
|
-
* ```
|
|
234
|
-
*/
|
|
235
117
|
guard<T>(actionType: string, target: string, context: Record<string, unknown> | null, fn: () => Promise<T>): Promise<T>;
|
|
236
|
-
/**
|
|
237
|
-
* Handle API failures according to failMode
|
|
238
|
-
*/
|
|
239
118
|
private handleFailure;
|
|
240
119
|
}
|
|
241
120
|
|
package/dist/index.js
CHANGED
|
@@ -138,10 +138,16 @@ var DEFAULT_APPROVAL_TIMEOUT_MS = 3e5;
|
|
|
138
138
|
var DEFAULT_APPROVAL_POLL_INTERVAL_MS = 2e3;
|
|
139
139
|
var Runplane = class {
|
|
140
140
|
constructor(config) {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
141
|
+
// 🔥 New: log only once per instance
|
|
142
|
+
this.hasLoggedInit = false;
|
|
143
|
+
if (!config?.apiKey || config.apiKey.trim() === "") {
|
|
144
|
+
throw new Error(
|
|
145
|
+
`Runplane API key is required.
|
|
146
|
+
|
|
147
|
+
\u{1F449} Start your free 14-day trial:
|
|
148
|
+
https://runplane.ai/
|
|
149
|
+
|
|
150
|
+
Then add your API key to the SDK config.`
|
|
145
151
|
);
|
|
146
152
|
}
|
|
147
153
|
this.apiKey = config.apiKey;
|
|
@@ -155,40 +161,6 @@ var Runplane = class {
|
|
|
155
161
|
pollIntervalMs: config.approvalPollIntervalMs ?? DEFAULT_APPROVAL_POLL_INTERVAL_MS
|
|
156
162
|
});
|
|
157
163
|
}
|
|
158
|
-
/**
|
|
159
|
-
* Request a decision from the Runplane control plane.
|
|
160
|
-
*
|
|
161
|
-
* Call this before executing any sensitive action. The response will indicate
|
|
162
|
-
* whether the action should be ALLOWED, BLOCKED, or REQUIRE_APPROVAL.
|
|
163
|
-
*
|
|
164
|
-
* @param request - The action details to evaluate
|
|
165
|
-
* @returns The decision response
|
|
166
|
-
*
|
|
167
|
-
* @example
|
|
168
|
-
* ```typescript
|
|
169
|
-
* const decision = await runplane.decide({
|
|
170
|
-
* actionType: "delete_record",
|
|
171
|
-
* target: "users.prod",
|
|
172
|
-
* context: { recordId: "usr_123", reason: "gdpr_request" }
|
|
173
|
-
* });
|
|
174
|
-
*
|
|
175
|
-
* switch (decision.decision) {
|
|
176
|
-
* case "ALLOW":
|
|
177
|
-
* await deleteRecord(recordId);
|
|
178
|
-
* break;
|
|
179
|
-
* case "BLOCK":
|
|
180
|
-
* console.error("Action blocked:", decision.reason);
|
|
181
|
-
* break;
|
|
182
|
-
* case "REQUIRE_APPROVAL":
|
|
183
|
-
* // Wait for human approval
|
|
184
|
-
* const result = await runplane.waitForApproval(decision.requestId);
|
|
185
|
-
* if (result.approved) {
|
|
186
|
-
* await deleteRecord(recordId);
|
|
187
|
-
* }
|
|
188
|
-
* break;
|
|
189
|
-
* }
|
|
190
|
-
* ```
|
|
191
|
-
*/
|
|
192
164
|
async decide(request) {
|
|
193
165
|
const controller = new AbortController();
|
|
194
166
|
const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
@@ -197,7 +169,7 @@ var Runplane = class {
|
|
|
197
169
|
method: "POST",
|
|
198
170
|
headers: {
|
|
199
171
|
"Content-Type": "application/json",
|
|
200
|
-
|
|
172
|
+
Authorization: `Bearer ${this.apiKey}`
|
|
201
173
|
},
|
|
202
174
|
body: JSON.stringify({
|
|
203
175
|
agentKey: this.apiKey,
|
|
@@ -240,68 +212,16 @@ var Runplane = class {
|
|
|
240
212
|
clearTimeout(timeout);
|
|
241
213
|
}
|
|
242
214
|
}
|
|
243
|
-
/**
|
|
244
|
-
* Wait for an approval decision on a pending request.
|
|
245
|
-
*
|
|
246
|
-
* Use this when decide() returns REQUIRE_APPROVAL. This method will poll
|
|
247
|
-
* the approval endpoint until the request is approved, denied, or times out.
|
|
248
|
-
*
|
|
249
|
-
* @param requestId - The requestId from the decide() response
|
|
250
|
-
* @param options - Optional configuration for polling behavior
|
|
251
|
-
* @returns The approval result
|
|
252
|
-
*
|
|
253
|
-
* @example
|
|
254
|
-
* ```typescript
|
|
255
|
-
* const decision = await runplane.decide({ ... });
|
|
256
|
-
*
|
|
257
|
-
* if (decision.decision === "REQUIRE_APPROVAL") {
|
|
258
|
-
* console.log("Waiting for approval...");
|
|
259
|
-
*
|
|
260
|
-
* const result = await runplane.waitForApproval(decision.requestId, {
|
|
261
|
-
* timeoutMs: 600000, // 10 minutes
|
|
262
|
-
* onPoll: (status, elapsed) => {
|
|
263
|
-
* console.log(`Still waiting... ${elapsed}ms elapsed`);
|
|
264
|
-
* }
|
|
265
|
-
* });
|
|
266
|
-
*
|
|
267
|
-
* if (result.approved) {
|
|
268
|
-
* console.log("Approved by:", result.resolvedBy);
|
|
269
|
-
* } else {
|
|
270
|
-
* console.log("Denied:", result.comment);
|
|
271
|
-
* }
|
|
272
|
-
* }
|
|
273
|
-
* ```
|
|
274
|
-
*/
|
|
275
215
|
async waitForApproval(requestId, options) {
|
|
276
216
|
return this.approvalPoller.poll(requestId, options);
|
|
277
217
|
}
|
|
278
|
-
/**
|
|
279
|
-
* Guard a function with containment evaluation.
|
|
280
|
-
*
|
|
281
|
-
* This is a convenience method that wraps decide() and waitForApproval()
|
|
282
|
-
* into a single call. If the action is blocked or denied, it throws.
|
|
283
|
-
* If approved, it executes the provided function.
|
|
284
|
-
*
|
|
285
|
-
* @param actionType - Type of action being performed
|
|
286
|
-
* @param target - Target resource
|
|
287
|
-
* @param context - Additional context
|
|
288
|
-
* @param fn - Function to execute if allowed
|
|
289
|
-
* @returns The result of fn()
|
|
290
|
-
* @throws RunplaneError if blocked, denied, or times out (in closed mode)
|
|
291
|
-
*
|
|
292
|
-
* @example
|
|
293
|
-
* ```typescript
|
|
294
|
-
* const result = await runplane.guard(
|
|
295
|
-
* "payment_transfer",
|
|
296
|
-
* "external_bank",
|
|
297
|
-
* { amount: 50000, currency: "USD" },
|
|
298
|
-
* async () => {
|
|
299
|
-
* return await paymentService.transfer(amount, recipient);
|
|
300
|
-
* }
|
|
301
|
-
* );
|
|
302
|
-
* ```
|
|
303
|
-
*/
|
|
304
218
|
async guard(actionType, target, context, fn) {
|
|
219
|
+
if (!this.hasLoggedInit) {
|
|
220
|
+
console.log(
|
|
221
|
+
"Runplane active. Manage your policies at https://runplane.ai/"
|
|
222
|
+
);
|
|
223
|
+
this.hasLoggedInit = true;
|
|
224
|
+
}
|
|
305
225
|
const response = await this.decide({
|
|
306
226
|
actionType,
|
|
307
227
|
target,
|
|
@@ -337,9 +257,6 @@ var Runplane = class {
|
|
|
337
257
|
response.requestId
|
|
338
258
|
);
|
|
339
259
|
}
|
|
340
|
-
/**
|
|
341
|
-
* Handle API failures according to failMode
|
|
342
|
-
*/
|
|
343
260
|
handleFailure(reason, request) {
|
|
344
261
|
const requestId = request.requestId ?? crypto.randomUUID();
|
|
345
262
|
if (this.failMode === "open") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@runplane/runplane-sdk",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.3",
|
|
4
4
|
"description": "Runtime governance SDK for AI agent actions. Wrap sensitive operations with guard() to enforce ALLOW, BLOCK, or REQUIRE_APPROVAL decisions before execution.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"license": "MIT",
|
|
38
38
|
"repository": {
|
|
39
39
|
"type": "git",
|
|
40
|
-
"url": "https://github.com/runplane/sdk.git"
|
|
40
|
+
"url": "git+https://github.com/runplane/sdk.git"
|
|
41
41
|
},
|
|
42
42
|
"homepage": "https://runplane.ai/developer",
|
|
43
43
|
"bugs": {
|