@itz4blitz/agentful 1.2.0 → 1.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/README.md +28 -1
- package/bin/cli.js +11 -1055
- package/bin/hooks/block-file-creation.js +271 -0
- package/bin/hooks/product-spec-watcher.js +151 -0
- package/lib/index.js +0 -11
- package/lib/init.js +2 -21
- package/lib/parallel-execution.js +235 -0
- package/lib/presets.js +26 -4
- package/package.json +4 -7
- package/template/.claude/agents/architect.md +2 -2
- package/template/.claude/agents/backend.md +17 -30
- package/template/.claude/agents/frontend.md +17 -39
- package/template/.claude/agents/orchestrator.md +63 -4
- package/template/.claude/agents/product-analyzer.md +1 -1
- package/template/.claude/agents/tester.md +16 -29
- package/template/.claude/commands/agentful-generate.md +221 -14
- package/template/.claude/commands/agentful-init.md +621 -0
- package/template/.claude/commands/agentful-product.md +1 -1
- package/template/.claude/commands/agentful-start.md +99 -1
- package/template/.claude/product/EXAMPLES.md +2 -2
- package/template/.claude/product/index.md +1 -1
- package/template/.claude/settings.json +22 -0
- package/template/.claude/skills/research/SKILL.md +432 -0
- package/template/CLAUDE.md +5 -6
- package/template/bin/hooks/architect-drift-detector.js +242 -0
- package/template/bin/hooks/product-spec-watcher.js +151 -0
- package/version.json +1 -1
- package/bin/hooks/post-agent.js +0 -101
- package/bin/hooks/post-feature.js +0 -227
- package/bin/hooks/pre-agent.js +0 -118
- package/bin/hooks/pre-feature.js +0 -138
- package/lib/VALIDATION_README.md +0 -455
- package/lib/ci/claude-action-integration.js +0 -641
- package/lib/ci/index.js +0 -10
- package/lib/core/analyzer.js +0 -497
- package/lib/core/cli.js +0 -141
- package/lib/core/detectors/conventions.js +0 -342
- package/lib/core/detectors/framework.js +0 -276
- package/lib/core/detectors/index.js +0 -15
- package/lib/core/detectors/language.js +0 -199
- package/lib/core/detectors/patterns.js +0 -356
- package/lib/core/generator.js +0 -626
- package/lib/core/index.js +0 -9
- package/lib/core/output-parser.js +0 -458
- package/lib/core/storage.js +0 -515
- package/lib/core/templates.js +0 -556
- package/lib/pipeline/cli.js +0 -423
- package/lib/pipeline/engine.js +0 -928
- package/lib/pipeline/executor.js +0 -440
- package/lib/pipeline/index.js +0 -33
- package/lib/pipeline/integrations.js +0 -559
- package/lib/pipeline/schemas.js +0 -288
- package/lib/remote/client.js +0 -361
- package/lib/server/auth.js +0 -270
- package/lib/server/client-example.js +0 -190
- package/lib/server/executor.js +0 -477
- package/lib/server/index.js +0 -494
- package/lib/update-helpers.js +0 -505
- package/lib/validation.js +0 -460
package/lib/server/auth.js
DELETED
|
@@ -1,270 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Authentication Middleware for Agentful Server
|
|
3
|
-
*
|
|
4
|
-
* Supports three authentication modes:
|
|
5
|
-
* - tailscale: Network-level security (Tailscale handles auth)
|
|
6
|
-
* - hmac: HMAC-SHA256 signature verification with replay protection
|
|
7
|
-
* - none: Local-only access (127.0.0.1)
|
|
8
|
-
*
|
|
9
|
-
* @module server/auth
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import crypto from 'crypto';
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Replay protection window (5 minutes)
|
|
16
|
-
*/
|
|
17
|
-
const REPLAY_WINDOW_MS = 5 * 60 * 1000;
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Maximum size for signature cache (prevents memory exhaustion)
|
|
21
|
-
*/
|
|
22
|
-
const MAX_SIGNATURE_CACHE_SIZE = 10000;
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* In-memory store for seen request signatures (prevents replay attacks)
|
|
26
|
-
* In production, use Redis or similar distributed cache
|
|
27
|
-
*/
|
|
28
|
-
const seenSignatures = new Map();
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Clean up old signatures periodically (every 10 minutes)
|
|
32
|
-
*/
|
|
33
|
-
setInterval(() => {
|
|
34
|
-
const cutoff = Date.now() - REPLAY_WINDOW_MS;
|
|
35
|
-
for (const [signature, timestamp] of seenSignatures.entries()) {
|
|
36
|
-
if (timestamp < cutoff) {
|
|
37
|
-
seenSignatures.delete(signature);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// If cache is still too large after cleanup, remove oldest entries (LRU)
|
|
42
|
-
if (seenSignatures.size > MAX_SIGNATURE_CACHE_SIZE) {
|
|
43
|
-
const sortedEntries = Array.from(seenSignatures.entries())
|
|
44
|
-
.sort((a, b) => a[1] - b[1]);
|
|
45
|
-
const toRemove = sortedEntries.slice(0, seenSignatures.size - MAX_SIGNATURE_CACHE_SIZE);
|
|
46
|
-
for (const [sig] of toRemove) {
|
|
47
|
-
seenSignatures.delete(sig);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}, 10 * 60 * 1000);
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Verify HMAC signature with replay protection
|
|
54
|
-
* @param {string} timestamp - Request timestamp
|
|
55
|
-
* @param {string} body - Request body (JSON string)
|
|
56
|
-
* @param {string} signature - HMAC signature from header
|
|
57
|
-
* @param {string} secret - Shared secret
|
|
58
|
-
* @returns {Object} Verification result { valid: boolean, error?: string }
|
|
59
|
-
*/
|
|
60
|
-
export function verifyHMACSignature(timestamp, body, signature, secret) {
|
|
61
|
-
// Validate timestamp format
|
|
62
|
-
const requestTime = parseInt(timestamp, 10);
|
|
63
|
-
if (isNaN(requestTime)) {
|
|
64
|
-
return { valid: false, error: 'Invalid timestamp format' };
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Check timestamp is within acceptable window
|
|
68
|
-
const now = Date.now();
|
|
69
|
-
const timeDiff = Math.abs(now - requestTime);
|
|
70
|
-
|
|
71
|
-
if (timeDiff > REPLAY_WINDOW_MS) {
|
|
72
|
-
return {
|
|
73
|
-
valid: false,
|
|
74
|
-
error: `Timestamp outside acceptable window (${REPLAY_WINDOW_MS / 1000}s)`,
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Check for replay attack
|
|
79
|
-
if (seenSignatures.has(signature)) {
|
|
80
|
-
return { valid: false, error: 'Signature already used (replay attack)' };
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Compute expected signature
|
|
84
|
-
const message = timestamp + body;
|
|
85
|
-
const expectedSignature = crypto
|
|
86
|
-
.createHmac('sha256', secret)
|
|
87
|
-
.update(message)
|
|
88
|
-
.digest('hex');
|
|
89
|
-
|
|
90
|
-
// Compare signatures (constant-time comparison to prevent timing attacks)
|
|
91
|
-
const signatureBuffer = Buffer.from(signature);
|
|
92
|
-
const expectedBuffer = Buffer.from(expectedSignature);
|
|
93
|
-
|
|
94
|
-
// Ensure buffers are same length before timingSafeEqual to prevent crash
|
|
95
|
-
if (signatureBuffer.length !== expectedBuffer.length) {
|
|
96
|
-
return { valid: false, error: 'Invalid signature' };
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const isValid = crypto.timingSafeEqual(signatureBuffer, expectedBuffer);
|
|
100
|
-
|
|
101
|
-
if (!isValid) {
|
|
102
|
-
return { valid: false, error: 'Invalid signature' };
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Store signature to prevent replay (with cache size limit)
|
|
106
|
-
if (seenSignatures.size >= MAX_SIGNATURE_CACHE_SIZE) {
|
|
107
|
-
// Find and remove oldest entry
|
|
108
|
-
let oldestSig = null;
|
|
109
|
-
let oldestTime = Infinity;
|
|
110
|
-
for (const [sig, time] of seenSignatures.entries()) {
|
|
111
|
-
if (time < oldestTime) {
|
|
112
|
-
oldestTime = time;
|
|
113
|
-
oldestSig = sig;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
if (oldestSig) {
|
|
117
|
-
seenSignatures.delete(oldestSig);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
seenSignatures.set(signature, requestTime);
|
|
122
|
-
|
|
123
|
-
return { valid: true };
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Minimum secret length for HMAC (256 bits / 32 bytes)
|
|
128
|
-
*/
|
|
129
|
-
const MIN_SECRET_LENGTH = 32;
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Create authentication middleware based on mode
|
|
133
|
-
* @param {string} mode - Authentication mode ('tailscale', 'hmac', 'none')
|
|
134
|
-
* @param {Object} config - Configuration options
|
|
135
|
-
* @param {string} [config.secret] - Shared secret (required for HMAC mode)
|
|
136
|
-
* @returns {Function} Middleware function
|
|
137
|
-
*/
|
|
138
|
-
export function createAuthMiddleware(mode, config = {}) {
|
|
139
|
-
switch (mode) {
|
|
140
|
-
case 'tailscale':
|
|
141
|
-
// Tailscale mode: No authentication needed (network-level security)
|
|
142
|
-
return (req, res, next) => {
|
|
143
|
-
next();
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
case 'hmac':
|
|
147
|
-
if (!config.secret) {
|
|
148
|
-
throw new Error('HMAC mode requires a secret');
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// Validate secret strength
|
|
152
|
-
if (config.secret.length < MIN_SECRET_LENGTH) {
|
|
153
|
-
throw new Error(
|
|
154
|
-
`HMAC secret must be at least ${MIN_SECRET_LENGTH} characters. ` +
|
|
155
|
-
`Use: openssl rand -hex 32`
|
|
156
|
-
);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
return (req, res, next) => {
|
|
160
|
-
// Extract headers
|
|
161
|
-
const signature = req.headers['x-agentful-signature'];
|
|
162
|
-
const timestamp = req.headers['x-agentful-timestamp'];
|
|
163
|
-
|
|
164
|
-
// Validate headers present
|
|
165
|
-
if (!signature || !timestamp) {
|
|
166
|
-
res.writeHead(401, { 'Content-Type': 'application/json' });
|
|
167
|
-
return res.end(
|
|
168
|
-
JSON.stringify({
|
|
169
|
-
error: 'Authentication required',
|
|
170
|
-
message: 'Missing X-Agentful-Signature or X-Agentful-Timestamp header',
|
|
171
|
-
})
|
|
172
|
-
);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// Verify signature
|
|
176
|
-
const result = verifyHMACSignature(
|
|
177
|
-
timestamp,
|
|
178
|
-
req.rawBody || '',
|
|
179
|
-
signature,
|
|
180
|
-
config.secret
|
|
181
|
-
);
|
|
182
|
-
|
|
183
|
-
if (!result.valid) {
|
|
184
|
-
res.writeHead(401, { 'Content-Type': 'application/json' });
|
|
185
|
-
return res.end(
|
|
186
|
-
JSON.stringify({
|
|
187
|
-
error: 'Authentication failed',
|
|
188
|
-
message: result.error,
|
|
189
|
-
})
|
|
190
|
-
);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
next();
|
|
194
|
-
};
|
|
195
|
-
|
|
196
|
-
case 'none':
|
|
197
|
-
// None mode: Allow all connections (use with SSH tunnel for security)
|
|
198
|
-
return (req, res, next) => {
|
|
199
|
-
next();
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
default:
|
|
203
|
-
throw new Error(`Unknown authentication mode: ${mode}`);
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Maximum request body size (10MB)
|
|
209
|
-
*/
|
|
210
|
-
const MAX_BODY_SIZE = 10 * 1024 * 1024;
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
* Middleware to capture raw request body (needed for HMAC verification)
|
|
214
|
-
* Must be used before express.json() middleware
|
|
215
|
-
*/
|
|
216
|
-
export function captureRawBody(req, res, next) {
|
|
217
|
-
let data = '';
|
|
218
|
-
let size = 0;
|
|
219
|
-
|
|
220
|
-
req.on('data', (chunk) => {
|
|
221
|
-
size += chunk.length;
|
|
222
|
-
|
|
223
|
-
// Check if body size exceeds limit
|
|
224
|
-
if (size > MAX_BODY_SIZE) {
|
|
225
|
-
req.destroy();
|
|
226
|
-
res.writeHead(413, { 'Content-Type': 'application/json' });
|
|
227
|
-
res.end(
|
|
228
|
-
JSON.stringify({
|
|
229
|
-
error: 'Payload Too Large',
|
|
230
|
-
message: `Request body exceeds maximum size of ${MAX_BODY_SIZE / 1024 / 1024}MB`,
|
|
231
|
-
})
|
|
232
|
-
);
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
data += chunk.toString();
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
req.on('end', () => {
|
|
240
|
-
req.rawBody = data;
|
|
241
|
-
next();
|
|
242
|
-
});
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
* Generate HMAC signature for a request (for client use)
|
|
247
|
-
* @param {string} body - Request body (JSON string)
|
|
248
|
-
* @param {string} secret - Shared secret
|
|
249
|
-
* @returns {Object} Headers to add to request { 'X-Agentful-Signature', 'X-Agentful-Timestamp' }
|
|
250
|
-
*/
|
|
251
|
-
export function generateHMACHeaders(body, secret) {
|
|
252
|
-
const timestamp = Date.now().toString();
|
|
253
|
-
const message = timestamp + body;
|
|
254
|
-
const signature = crypto
|
|
255
|
-
.createHmac('sha256', secret)
|
|
256
|
-
.update(message)
|
|
257
|
-
.digest('hex');
|
|
258
|
-
|
|
259
|
-
return {
|
|
260
|
-
'X-Agentful-Signature': signature,
|
|
261
|
-
'X-Agentful-Timestamp': timestamp,
|
|
262
|
-
};
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
export default {
|
|
266
|
-
createAuthMiddleware,
|
|
267
|
-
verifyHMACSignature,
|
|
268
|
-
captureRawBody,
|
|
269
|
-
generateHMACHeaders,
|
|
270
|
-
};
|
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Example Client for Agentful Server
|
|
3
|
-
*
|
|
4
|
-
* Demonstrates how to make authenticated requests to agentful serve
|
|
5
|
-
*
|
|
6
|
-
* @module server/client-example
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { generateHMACHeaders } from './auth.js';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Example: Trigger agent execution with HMAC authentication
|
|
13
|
-
*/
|
|
14
|
-
async function triggerAgentWithHMAC() {
|
|
15
|
-
const serverUrl = 'https://your-server.com:3000';
|
|
16
|
-
const secret = 'your-shared-secret';
|
|
17
|
-
|
|
18
|
-
// Request body
|
|
19
|
-
const body = JSON.stringify({
|
|
20
|
-
agent: 'backend',
|
|
21
|
-
task: 'Implement user authentication API',
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
// Generate HMAC headers
|
|
25
|
-
const headers = generateHMACHeaders(body, secret);
|
|
26
|
-
|
|
27
|
-
// Make request
|
|
28
|
-
const response = await fetch(`${serverUrl}/trigger`, {
|
|
29
|
-
method: 'POST',
|
|
30
|
-
headers: {
|
|
31
|
-
'Content-Type': 'application/json',
|
|
32
|
-
...headers,
|
|
33
|
-
},
|
|
34
|
-
body,
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
if (!response.ok) {
|
|
38
|
-
const error = await response.json();
|
|
39
|
-
throw new Error(`Request failed: ${error.message}`);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const result = await response.json();
|
|
43
|
-
console.log('Execution started:', result.executionId);
|
|
44
|
-
|
|
45
|
-
return result.executionId;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Example: Check execution status
|
|
50
|
-
*/
|
|
51
|
-
async function checkExecutionStatus(executionId) {
|
|
52
|
-
const serverUrl = 'https://your-server.com:3000';
|
|
53
|
-
const secret = 'your-shared-secret';
|
|
54
|
-
|
|
55
|
-
// For GET requests, body is empty
|
|
56
|
-
const body = '';
|
|
57
|
-
const headers = generateHMACHeaders(body, secret);
|
|
58
|
-
|
|
59
|
-
const response = await fetch(`${serverUrl}/status/${executionId}`, {
|
|
60
|
-
method: 'GET',
|
|
61
|
-
headers,
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
if (!response.ok) {
|
|
65
|
-
const error = await response.json();
|
|
66
|
-
throw new Error(`Request failed: ${error.message}`);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const status = await response.json();
|
|
70
|
-
console.log('Execution status:', status.state);
|
|
71
|
-
console.log('Duration:', status.duration, 'ms');
|
|
72
|
-
|
|
73
|
-
return status;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Example: Trigger and poll for completion
|
|
78
|
-
*/
|
|
79
|
-
async function triggerAndWait() {
|
|
80
|
-
const executionId = await triggerAgentWithHMAC();
|
|
81
|
-
|
|
82
|
-
console.log('Waiting for execution to complete...');
|
|
83
|
-
|
|
84
|
-
// Poll every 5 seconds
|
|
85
|
-
while (true) {
|
|
86
|
-
await new Promise((resolve) => setTimeout(resolve, 5000));
|
|
87
|
-
|
|
88
|
-
const status = await checkExecutionStatus(executionId);
|
|
89
|
-
|
|
90
|
-
if (status.state === 'completed') {
|
|
91
|
-
console.log('Execution completed successfully!');
|
|
92
|
-
console.log('Output:', status.output);
|
|
93
|
-
break;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
if (status.state === 'failed') {
|
|
97
|
-
console.error('Execution failed:', status.error);
|
|
98
|
-
break;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Example: No authentication (localhost only)
|
|
105
|
-
*/
|
|
106
|
-
async function triggerAgentLocalhost() {
|
|
107
|
-
const serverUrl = 'http://localhost:3000';
|
|
108
|
-
|
|
109
|
-
const response = await fetch(`${serverUrl}/trigger`, {
|
|
110
|
-
method: 'POST',
|
|
111
|
-
headers: {
|
|
112
|
-
'Content-Type': 'application/json',
|
|
113
|
-
},
|
|
114
|
-
body: JSON.stringify({
|
|
115
|
-
agent: 'backend',
|
|
116
|
-
task: 'Implement user authentication API',
|
|
117
|
-
}),
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
const result = await response.json();
|
|
121
|
-
console.log('Execution started:', result.executionId);
|
|
122
|
-
|
|
123
|
-
return result.executionId;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Example: Tailscale mode (no auth headers needed)
|
|
128
|
-
*/
|
|
129
|
-
async function triggerAgentTailscale() {
|
|
130
|
-
const serverUrl = 'http://your-tailscale-ip:3000';
|
|
131
|
-
|
|
132
|
-
const response = await fetch(`${serverUrl}/trigger`, {
|
|
133
|
-
method: 'POST',
|
|
134
|
-
headers: {
|
|
135
|
-
'Content-Type': 'application/json',
|
|
136
|
-
},
|
|
137
|
-
body: JSON.stringify({
|
|
138
|
-
agent: 'backend',
|
|
139
|
-
task: 'Implement user authentication API',
|
|
140
|
-
}),
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
const result = await response.json();
|
|
144
|
-
console.log('Execution started:', result.executionId);
|
|
145
|
-
|
|
146
|
-
return result.executionId;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Example: List available agents
|
|
151
|
-
*/
|
|
152
|
-
async function listAgents() {
|
|
153
|
-
const serverUrl = 'http://localhost:3000';
|
|
154
|
-
|
|
155
|
-
const response = await fetch(`${serverUrl}/agents`);
|
|
156
|
-
const result = await response.json();
|
|
157
|
-
|
|
158
|
-
console.log('Available agents:', result.agents);
|
|
159
|
-
return result.agents;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* Example: List recent executions
|
|
164
|
-
*/
|
|
165
|
-
async function listExecutions(filters = {}) {
|
|
166
|
-
const serverUrl = 'http://localhost:3000';
|
|
167
|
-
|
|
168
|
-
// Build query string
|
|
169
|
-
const params = new URLSearchParams();
|
|
170
|
-
if (filters.agent) params.append('agent', filters.agent);
|
|
171
|
-
if (filters.state) params.append('state', filters.state);
|
|
172
|
-
if (filters.limit) params.append('limit', filters.limit.toString());
|
|
173
|
-
|
|
174
|
-
const response = await fetch(`${serverUrl}/executions?${params}`);
|
|
175
|
-
const result = await response.json();
|
|
176
|
-
|
|
177
|
-
console.log(`Found ${result.count} executions`);
|
|
178
|
-
return result.executions;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
// Export examples
|
|
182
|
-
export default {
|
|
183
|
-
triggerAgentWithHMAC,
|
|
184
|
-
checkExecutionStatus,
|
|
185
|
-
triggerAndWait,
|
|
186
|
-
triggerAgentLocalhost,
|
|
187
|
-
triggerAgentTailscale,
|
|
188
|
-
listAgents,
|
|
189
|
-
listExecutions,
|
|
190
|
-
};
|