@openserv-labs/client 1.0.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/LICENSE +21 -0
- package/README.md +646 -0
- package/dist/agents-api.d.ts +139 -0
- package/dist/agents-api.d.ts.map +1 -0
- package/dist/agents-api.js +182 -0
- package/dist/client.d.ts +107 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +187 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +34 -0
- package/dist/integrations-api.d.ts +34 -0
- package/dist/integrations-api.d.ts.map +1 -0
- package/dist/integrations-api.js +46 -0
- package/dist/payments-api.d.ts +126 -0
- package/dist/payments-api.d.ts.map +1 -0
- package/dist/payments-api.js +155 -0
- package/dist/provision.d.ts +194 -0
- package/dist/provision.d.ts.map +1 -0
- package/dist/provision.js +541 -0
- package/dist/tasks-api.d.ts +103 -0
- package/dist/tasks-api.d.ts.map +1 -0
- package/dist/tasks-api.js +110 -0
- package/dist/triggers-api.d.ts +254 -0
- package/dist/triggers-api.d.ts.map +1 -0
- package/dist/triggers-api.js +309 -0
- package/dist/types.d.ts +219 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/web3-api.d.ts +117 -0
- package/dist/web3-api.d.ts.map +1 -0
- package/dist/web3-api.js +185 -0
- package/dist/workflow.d.ts +27 -0
- package/dist/workflow.d.ts.map +1 -0
- package/dist/workflow.js +50 -0
- package/dist/workflows-api.d.ts +142 -0
- package/dist/workflows-api.d.ts.map +1 -0
- package/dist/workflows-api.js +357 -0
- package/package.json +70 -0
|
@@ -0,0 +1,541 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.setLogger = setLogger;
|
|
37
|
+
exports.provision = provision;
|
|
38
|
+
exports.isProvisioned = isProvisioned;
|
|
39
|
+
exports.getProvisionedInfo = getProvisionedInfo;
|
|
40
|
+
exports.clearProvisionedState = clearProvisionedState;
|
|
41
|
+
const ethers_1 = require("ethers");
|
|
42
|
+
const fs = __importStar(require("node:fs"));
|
|
43
|
+
const path = __importStar(require("node:path"));
|
|
44
|
+
const client_1 = require("./client");
|
|
45
|
+
const triggers_api_1 = require("./triggers-api");
|
|
46
|
+
const STATE_FILE = ".openserv.json";
|
|
47
|
+
const defaultLogger = {
|
|
48
|
+
info: (...args) => console.log("[provision]", ...args),
|
|
49
|
+
warn: (...args) => console.warn("[provision]", ...args),
|
|
50
|
+
error: (...args) => console.error("[provision]", ...args),
|
|
51
|
+
};
|
|
52
|
+
let logger = defaultLogger;
|
|
53
|
+
/**
|
|
54
|
+
* Set a custom logger for provision operations.
|
|
55
|
+
*
|
|
56
|
+
* @param customLogger - Logger implementation to use
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```typescript
|
|
60
|
+
* setLogger({
|
|
61
|
+
* info: (...args) => myLogger.info(...args),
|
|
62
|
+
* warn: (...args) => myLogger.warn(...args),
|
|
63
|
+
* error: (...args) => myLogger.error(...args)
|
|
64
|
+
* });
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
function setLogger(customLogger) {
|
|
68
|
+
logger = customLogger;
|
|
69
|
+
}
|
|
70
|
+
// ============================================================================
|
|
71
|
+
// Helpers
|
|
72
|
+
// ============================================================================
|
|
73
|
+
/**
|
|
74
|
+
* Format axios error for logging
|
|
75
|
+
*/
|
|
76
|
+
function formatAxiosError(error) {
|
|
77
|
+
const axiosError = error;
|
|
78
|
+
return axiosError.response
|
|
79
|
+
? JSON.stringify({
|
|
80
|
+
status: axiosError.response.status,
|
|
81
|
+
data: axiosError.response.data,
|
|
82
|
+
})
|
|
83
|
+
: axiosError.message || "Unknown error";
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Inject x402 trigger properties (wallet address and waitForCompletion)
|
|
87
|
+
*/
|
|
88
|
+
function injectX402Props(props, walletAddress, triggerType) {
|
|
89
|
+
if (triggerType !== "x402")
|
|
90
|
+
return props;
|
|
91
|
+
return {
|
|
92
|
+
...props,
|
|
93
|
+
x402WalletAddress: props.x402WalletAddress || walletAddress,
|
|
94
|
+
waitForCompletion: props.waitForCompletion ?? true,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
// ============================================================================
|
|
98
|
+
// State Management (JSON)
|
|
99
|
+
// ============================================================================
|
|
100
|
+
/**
|
|
101
|
+
* Read the current state from .openserv.json
|
|
102
|
+
*/
|
|
103
|
+
function readState() {
|
|
104
|
+
const statePath = path.resolve(process.cwd(), STATE_FILE);
|
|
105
|
+
try {
|
|
106
|
+
if (fs.existsSync(statePath)) {
|
|
107
|
+
const content = fs.readFileSync(statePath, "utf-8");
|
|
108
|
+
return JSON.parse(content);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
logger.warn("Error reading state file:", error);
|
|
113
|
+
}
|
|
114
|
+
// Return empty state
|
|
115
|
+
return {
|
|
116
|
+
agents: {},
|
|
117
|
+
workflows: {},
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Write state to .openserv.json
|
|
122
|
+
*/
|
|
123
|
+
function writeState(state) {
|
|
124
|
+
const statePath = path.resolve(process.cwd(), STATE_FILE);
|
|
125
|
+
fs.writeFileSync(statePath, JSON.stringify(state, null, 2));
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Write an environment variable to .env file
|
|
129
|
+
*/
|
|
130
|
+
function writeEnvVar(key, value) {
|
|
131
|
+
const envPath = path.resolve(process.cwd(), ".env");
|
|
132
|
+
let existingContent = "";
|
|
133
|
+
try {
|
|
134
|
+
if (fs.existsSync(envPath)) {
|
|
135
|
+
existingContent = fs.readFileSync(envPath, "utf-8");
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
// File doesn't exist, start fresh
|
|
140
|
+
}
|
|
141
|
+
const lines = existingContent.split("\n");
|
|
142
|
+
let found = false;
|
|
143
|
+
const updatedLines = lines.map((line) => {
|
|
144
|
+
if (line.trim().startsWith(`${key}=`)) {
|
|
145
|
+
found = true;
|
|
146
|
+
return `${key}=${value}`;
|
|
147
|
+
}
|
|
148
|
+
return line;
|
|
149
|
+
});
|
|
150
|
+
if (!found) {
|
|
151
|
+
updatedLines.push(`${key}=${value}`);
|
|
152
|
+
}
|
|
153
|
+
fs.writeFileSync(envPath, updatedLines.join("\n"));
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Read wallet credentials from .env via process.env
|
|
157
|
+
*/
|
|
158
|
+
function getWalletFromEnv() {
|
|
159
|
+
return {
|
|
160
|
+
privateKey: process.env.WALLET_PRIVATE_KEY,
|
|
161
|
+
address: process.env.WALLET_ADDRESS,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Write wallet credentials to .env file
|
|
166
|
+
*/
|
|
167
|
+
function writeWalletToEnv(privateKey, address) {
|
|
168
|
+
writeEnvVar("WALLET_PRIVATE_KEY", privateKey);
|
|
169
|
+
writeEnvVar("WALLET_ADDRESS", address);
|
|
170
|
+
}
|
|
171
|
+
// ============================================================================
|
|
172
|
+
// Wallet Management
|
|
173
|
+
// ============================================================================
|
|
174
|
+
/**
|
|
175
|
+
* Get or create a wallet for authentication
|
|
176
|
+
*/
|
|
177
|
+
async function getOrCreateWallet() {
|
|
178
|
+
const { privateKey, address } = getWalletFromEnv();
|
|
179
|
+
if (privateKey && address) {
|
|
180
|
+
return { privateKey, address };
|
|
181
|
+
}
|
|
182
|
+
// Create new wallet
|
|
183
|
+
const wallet = ethers_1.ethers.Wallet.createRandom();
|
|
184
|
+
const newPrivateKey = wallet.privateKey;
|
|
185
|
+
const newAddress = wallet.address;
|
|
186
|
+
// Persist to .env (secrets stay in .env)
|
|
187
|
+
writeWalletToEnv(newPrivateKey, newAddress);
|
|
188
|
+
logger.info("Created new wallet:", newAddress);
|
|
189
|
+
return { privateKey: newPrivateKey, address: newAddress };
|
|
190
|
+
}
|
|
191
|
+
// ============================================================================
|
|
192
|
+
// Platform API Client
|
|
193
|
+
// ============================================================================
|
|
194
|
+
async function createAuthenticatedClient(privateKey) {
|
|
195
|
+
const wallet = new ethers_1.ethers.Wallet(privateKey);
|
|
196
|
+
const walletAddress = wallet.address;
|
|
197
|
+
// Check if we have a saved user API key (for session continuity)
|
|
198
|
+
const state = readState();
|
|
199
|
+
const existingApiKey = state.userApiKey;
|
|
200
|
+
if (existingApiKey) {
|
|
201
|
+
// Try to use existing API key
|
|
202
|
+
const client = new client_1.PlatformClient({ apiKey: existingApiKey });
|
|
203
|
+
try {
|
|
204
|
+
// Verify it works by listing agents (a simple authenticated call)
|
|
205
|
+
await client.agents.list();
|
|
206
|
+
logger.info("Using existing user API key");
|
|
207
|
+
return { client, walletAddress };
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
logger.info("Existing user API key invalid, re-authenticating");
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
// Authenticate with wallet using SIWE
|
|
214
|
+
const client = new client_1.PlatformClient();
|
|
215
|
+
const apiKey = await client.authenticate(privateKey);
|
|
216
|
+
// Save the user API key to state file for reuse (session continuity)
|
|
217
|
+
writeState({
|
|
218
|
+
...state,
|
|
219
|
+
userApiKey: apiKey,
|
|
220
|
+
});
|
|
221
|
+
logger.info("User API key saved to state file");
|
|
222
|
+
return { client, walletAddress };
|
|
223
|
+
}
|
|
224
|
+
// ============================================================================
|
|
225
|
+
// Provisioning Functions
|
|
226
|
+
// ============================================================================
|
|
227
|
+
// Default endpoint URL - SDK v2.0.0+ automatically updates to this when run(agent) is called
|
|
228
|
+
const DEFAULT_AGENT_ENDPOINT = "https://agents-proxy.openserv.ai";
|
|
229
|
+
/**
|
|
230
|
+
* Register or update an agent on the platform
|
|
231
|
+
*/
|
|
232
|
+
async function provisionAgent(client, config) {
|
|
233
|
+
const state = readState();
|
|
234
|
+
const existingAgent = state.agents[config.name];
|
|
235
|
+
const endpointUrl = config.endpointUrl || DEFAULT_AGENT_ENDPOINT;
|
|
236
|
+
if (existingAgent) {
|
|
237
|
+
// Update existing agent - only update endpoint if explicitly provided
|
|
238
|
+
const agentId = existingAgent.id;
|
|
239
|
+
try {
|
|
240
|
+
const updateParams = {
|
|
241
|
+
id: agentId,
|
|
242
|
+
name: config.name,
|
|
243
|
+
capabilities_description: config.description,
|
|
244
|
+
};
|
|
245
|
+
// Only update endpoint if explicitly provided (not using default)
|
|
246
|
+
if (config.endpointUrl) {
|
|
247
|
+
updateParams.endpoint_url = config.endpointUrl;
|
|
248
|
+
logger.info(`Updating agent ${agentId} endpoint to ${config.endpointUrl}`);
|
|
249
|
+
}
|
|
250
|
+
await client.agents.update(updateParams);
|
|
251
|
+
logger.info(`Updated agent ${agentId}`);
|
|
252
|
+
return {
|
|
253
|
+
agentId,
|
|
254
|
+
apiKey: existingAgent.apiKey,
|
|
255
|
+
authToken: existingAgent.authToken,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
logger.warn(`Failed to update agent ${agentId}: ${formatAxiosError(error)}`);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
// Register new agent
|
|
263
|
+
const agent = await client.agents.create({
|
|
264
|
+
name: config.name,
|
|
265
|
+
capabilities_description: config.description,
|
|
266
|
+
endpoint_url: endpointUrl,
|
|
267
|
+
});
|
|
268
|
+
const agentId = agent.id;
|
|
269
|
+
// Get agent API key
|
|
270
|
+
const apiKey = await client.agents.getApiKey({ id: agentId });
|
|
271
|
+
// Generate and save auth token for securing agent requests
|
|
272
|
+
const { authToken, authTokenHash } = await client.agents.generateAuthToken();
|
|
273
|
+
await client.agents.saveAuthToken({ id: agentId, authTokenHash });
|
|
274
|
+
logger.info("Generated and saved auth token for agent");
|
|
275
|
+
// Persist agent state (including auth token)
|
|
276
|
+
state.agents[config.name] = { id: agentId, apiKey, authToken };
|
|
277
|
+
writeState(state);
|
|
278
|
+
logger.info(`Registered agent ${agentId}: ${config.name}`);
|
|
279
|
+
return { agentId, apiKey, authToken };
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Provision a workflow (workspace + trigger + task)
|
|
283
|
+
*/
|
|
284
|
+
async function provisionWorkflow(client, agentId, agentName, walletAddress, config) {
|
|
285
|
+
const state = readState();
|
|
286
|
+
const workflowName = config.name || "default";
|
|
287
|
+
// Initialize workflows structure if needed
|
|
288
|
+
if (!state.workflows[agentName]) {
|
|
289
|
+
state.workflows[agentName] = {};
|
|
290
|
+
}
|
|
291
|
+
const existingWorkflow = state.workflows[agentName][workflowName];
|
|
292
|
+
let workflowId;
|
|
293
|
+
let triggerId;
|
|
294
|
+
let triggerToken;
|
|
295
|
+
let needsCreate = true;
|
|
296
|
+
if (existingWorkflow) {
|
|
297
|
+
// Update existing workflow
|
|
298
|
+
workflowId = existingWorkflow.workspaceId;
|
|
299
|
+
triggerId = existingWorkflow.triggerId;
|
|
300
|
+
triggerToken = existingWorkflow.triggerToken;
|
|
301
|
+
needsCreate = false;
|
|
302
|
+
try {
|
|
303
|
+
// Get existing trigger to preserve required fields
|
|
304
|
+
const existingTrigger = await client.triggers.get({
|
|
305
|
+
workflowId,
|
|
306
|
+
id: triggerId,
|
|
307
|
+
});
|
|
308
|
+
// Build new props, preserving existing values and injecting x402 props
|
|
309
|
+
const triggerProps = injectX402Props({ ...existingTrigger.props, ...(0, triggers_api_1.triggerConfigToProps)(config.trigger) }, walletAddress, config.trigger.type);
|
|
310
|
+
await client.triggers.update({
|
|
311
|
+
workflowId,
|
|
312
|
+
id: triggerId,
|
|
313
|
+
name: existingTrigger.name || config.trigger.type,
|
|
314
|
+
props: triggerProps,
|
|
315
|
+
});
|
|
316
|
+
logger.info(`Updated workflow ${workflowName} (${workflowId})`);
|
|
317
|
+
}
|
|
318
|
+
catch (error) {
|
|
319
|
+
logger.warn(`Failed to update workflow ${workflowName}: ${formatAxiosError(error)}`);
|
|
320
|
+
needsCreate = true;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
if (needsCreate) {
|
|
324
|
+
// Map trigger type to integration identifier
|
|
325
|
+
const triggerTypeToIntegration = {
|
|
326
|
+
x402: "x402-trigger",
|
|
327
|
+
webhook: "webhook-trigger",
|
|
328
|
+
cron: "cron-trigger",
|
|
329
|
+
manual: "manual-trigger",
|
|
330
|
+
};
|
|
331
|
+
const integrationIdentifier = triggerTypeToIntegration[config.trigger.type] || "manual-trigger";
|
|
332
|
+
// Create trigger props with x402 properties injected
|
|
333
|
+
const triggerProps = injectX402Props((0, triggers_api_1.triggerConfigToProps)(config.trigger), walletAddress, config.trigger.type);
|
|
334
|
+
// Step 1: Create workflow without triggers/tasks (avoids sync API issues)
|
|
335
|
+
const workflow = await client.workflows.create({
|
|
336
|
+
name: `${workflowName} Workflow`,
|
|
337
|
+
goal: config.task?.description || "Process requests",
|
|
338
|
+
agentIds: [agentId],
|
|
339
|
+
});
|
|
340
|
+
workflowId = workflow.id;
|
|
341
|
+
logger.info(`Created workflow ${workflowName} (${workflowId})`);
|
|
342
|
+
// Step 2: Get or create integration connection for the trigger type
|
|
343
|
+
const integrationConnectionId = await client.integrations.getOrCreateConnection(integrationIdentifier);
|
|
344
|
+
// Step 3: Create trigger using direct API
|
|
345
|
+
const trigger = await client.triggers.create({
|
|
346
|
+
workflowId,
|
|
347
|
+
name: config.trigger.type,
|
|
348
|
+
integrationConnectionId,
|
|
349
|
+
props: triggerProps,
|
|
350
|
+
});
|
|
351
|
+
triggerId = trigger.id;
|
|
352
|
+
triggerToken = trigger.token || "";
|
|
353
|
+
logger.info(`Created trigger ${triggerId} (token: ${triggerToken || "N/A"})`);
|
|
354
|
+
// Step 4: Create task using direct API
|
|
355
|
+
await client.tasks.create({
|
|
356
|
+
workflowId,
|
|
357
|
+
agentId,
|
|
358
|
+
description: config.task?.description || "Process the incoming request",
|
|
359
|
+
body: config.task?.body || "",
|
|
360
|
+
input: "",
|
|
361
|
+
});
|
|
362
|
+
logger.info(`Created task for workflow ${workflowId}`);
|
|
363
|
+
// Step 5: Activate trigger
|
|
364
|
+
await client.triggers.activate({ workflowId, id: triggerId });
|
|
365
|
+
// Step 6: Set workspace to running
|
|
366
|
+
await client.workflows.setRunning({ id: workflowId });
|
|
367
|
+
// Persist workflow state
|
|
368
|
+
state.workflows[agentName][workflowName] = {
|
|
369
|
+
workspaceId: workflowId,
|
|
370
|
+
triggerId,
|
|
371
|
+
triggerToken,
|
|
372
|
+
};
|
|
373
|
+
writeState(state);
|
|
374
|
+
logger.info(`Provisioned workflow ${workflowName} (${workflowId})`);
|
|
375
|
+
}
|
|
376
|
+
// Validate that all required values are set
|
|
377
|
+
// Note: triggerToken may be empty for manual/cron triggers (only x402/webhook have tokens)
|
|
378
|
+
if (!workflowId || !triggerId) {
|
|
379
|
+
throw new Error("Failed to provision workflow: missing required IDs");
|
|
380
|
+
}
|
|
381
|
+
// Ensure triggerToken is at least an empty string
|
|
382
|
+
if (triggerToken === undefined) {
|
|
383
|
+
triggerToken = "";
|
|
384
|
+
}
|
|
385
|
+
// Build URLs
|
|
386
|
+
const paywallUrl = config.trigger.type === "x402"
|
|
387
|
+
? `https://platform.openserv.ai/workspace/paywall/${triggerToken}`
|
|
388
|
+
: undefined;
|
|
389
|
+
const apiEndpoint = config.trigger.type === "webhook"
|
|
390
|
+
? `https://api.openserv.ai/workspaces/${workflowId}/triggers/${triggerId}/fire`
|
|
391
|
+
: undefined;
|
|
392
|
+
return {
|
|
393
|
+
workflowId,
|
|
394
|
+
triggerId,
|
|
395
|
+
triggerToken,
|
|
396
|
+
paywallUrl,
|
|
397
|
+
apiEndpoint,
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
// ============================================================================
|
|
401
|
+
// Main Provision Function
|
|
402
|
+
// ============================================================================
|
|
403
|
+
/**
|
|
404
|
+
* Provision an agent and workflow on the OpenServ platform.
|
|
405
|
+
* This function handles:
|
|
406
|
+
* - Wallet creation/retrieval
|
|
407
|
+
* - Platform authentication (with session persistence)
|
|
408
|
+
* - Agent registration/update
|
|
409
|
+
* - Workflow creation/update
|
|
410
|
+
* - State persistence to .openserv.json
|
|
411
|
+
*
|
|
412
|
+
* @param config - Provisioning configuration
|
|
413
|
+
* @returns Provision result with IDs and URLs
|
|
414
|
+
*
|
|
415
|
+
* @example
|
|
416
|
+
* ```ts
|
|
417
|
+
* import { provision, triggers } from '@openserv-labs/client';
|
|
418
|
+
*
|
|
419
|
+
* const result = await provision({
|
|
420
|
+
* agent: {
|
|
421
|
+
* name: 'my-agent',
|
|
422
|
+
* description: 'My autonomous agent',
|
|
423
|
+
* // endpointUrl is optional - SDK v2.0.0+ auto-updates to agents-proxy when run(agent) is called
|
|
424
|
+
* },
|
|
425
|
+
* workflow: {
|
|
426
|
+
* name: 'default',
|
|
427
|
+
* trigger: triggers.webhook(),
|
|
428
|
+
* task: {
|
|
429
|
+
* description: 'Process incoming requests',
|
|
430
|
+
* },
|
|
431
|
+
* },
|
|
432
|
+
* });
|
|
433
|
+
*
|
|
434
|
+
* console.log('Agent ID:', result.agentId);
|
|
435
|
+
* console.log('API Endpoint:', result.apiEndpoint);
|
|
436
|
+
* ```
|
|
437
|
+
*/
|
|
438
|
+
async function provision(config) {
|
|
439
|
+
// Get or create wallet
|
|
440
|
+
const { privateKey } = await getOrCreateWallet();
|
|
441
|
+
// Create authenticated client (reuses saved API key for session continuity)
|
|
442
|
+
const { client, walletAddress } = await createAuthenticatedClient(privateKey);
|
|
443
|
+
// Provision agent (returns agentId, apiKey, and authToken)
|
|
444
|
+
const { agentId, apiKey, authToken } = await provisionAgent(client, config.agent);
|
|
445
|
+
// Set credentials in process.env so Agent can read them
|
|
446
|
+
process.env.OPENSERV_API_KEY = apiKey;
|
|
447
|
+
if (authToken) {
|
|
448
|
+
process.env.OPENSERV_AUTH_TOKEN = authToken;
|
|
449
|
+
}
|
|
450
|
+
// Provision workflow (pass agent name and wallet address for x402 triggers)
|
|
451
|
+
const workflowResult = await provisionWorkflow(client, agentId, config.agent.name, walletAddress, config.workflow);
|
|
452
|
+
return {
|
|
453
|
+
agentId,
|
|
454
|
+
apiKey,
|
|
455
|
+
authToken,
|
|
456
|
+
...workflowResult,
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
460
|
+
* Check if an agent and workflow are already provisioned.
|
|
461
|
+
*
|
|
462
|
+
* This checks the local `.openserv.json` state file.
|
|
463
|
+
*
|
|
464
|
+
* @param agentName - Name of the agent to check
|
|
465
|
+
* @param workflowName - Name of the workflow (defaults to "default")
|
|
466
|
+
* @returns True if both agent and workflow are provisioned
|
|
467
|
+
*
|
|
468
|
+
* @example
|
|
469
|
+
* ```typescript
|
|
470
|
+
* if (isProvisioned('my-agent', 'api-workflow')) {
|
|
471
|
+
* console.log('Already provisioned!');
|
|
472
|
+
* } else {
|
|
473
|
+
* await provision(config);
|
|
474
|
+
* }
|
|
475
|
+
* ```
|
|
476
|
+
*/
|
|
477
|
+
function isProvisioned(agentName, workflowName) {
|
|
478
|
+
const state = readState();
|
|
479
|
+
const workflow = workflowName || "default";
|
|
480
|
+
const agent = state.agents[agentName];
|
|
481
|
+
const workflowState = state.workflows[agentName]?.[workflow];
|
|
482
|
+
return !!agent && !!workflowState;
|
|
483
|
+
}
|
|
484
|
+
/**
|
|
485
|
+
* Get provisioned workflow info from the local state file.
|
|
486
|
+
*
|
|
487
|
+
* @param agentName - Name of the agent
|
|
488
|
+
* @param workflowName - Name of the workflow (defaults to "default")
|
|
489
|
+
* @returns Object with agent and workflow details, or null if not provisioned
|
|
490
|
+
*
|
|
491
|
+
* @example
|
|
492
|
+
* ```typescript
|
|
493
|
+
* const info = getProvisionedInfo('my-agent', 'api-workflow');
|
|
494
|
+
* if (info) {
|
|
495
|
+
* console.log('Agent ID:', info.agentId);
|
|
496
|
+
* console.log('Workflow ID:', info.workflowId);
|
|
497
|
+
* }
|
|
498
|
+
* ```
|
|
499
|
+
*/
|
|
500
|
+
function getProvisionedInfo(agentName, workflowName) {
|
|
501
|
+
const state = readState();
|
|
502
|
+
const workflow = workflowName || "default";
|
|
503
|
+
const agent = state.agents[agentName];
|
|
504
|
+
const workflowState = state.workflows[agentName]?.[workflow];
|
|
505
|
+
if (!agent || !workflowState) {
|
|
506
|
+
return null;
|
|
507
|
+
}
|
|
508
|
+
return {
|
|
509
|
+
agentId: agent.id,
|
|
510
|
+
apiKey: agent.apiKey,
|
|
511
|
+
authToken: agent.authToken,
|
|
512
|
+
workflowId: workflowState.workspaceId,
|
|
513
|
+
triggerId: workflowState.triggerId,
|
|
514
|
+
triggerToken: workflowState.triggerToken,
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* Clear all provisioned state.
|
|
519
|
+
*
|
|
520
|
+
* This deletes the `.openserv.json` file. Useful for testing or resetting.
|
|
521
|
+
* Note: This does not delete resources from the platform, only the local state file.
|
|
522
|
+
*
|
|
523
|
+
* @example
|
|
524
|
+
* ```typescript
|
|
525
|
+
* clearProvisionedState();
|
|
526
|
+
* // Now provision will create new resources
|
|
527
|
+
* await provision(config);
|
|
528
|
+
* ```
|
|
529
|
+
*/
|
|
530
|
+
function clearProvisionedState() {
|
|
531
|
+
const statePath = path.resolve(process.cwd(), STATE_FILE);
|
|
532
|
+
try {
|
|
533
|
+
if (fs.existsSync(statePath)) {
|
|
534
|
+
fs.unlinkSync(statePath);
|
|
535
|
+
logger.info("Cleared provision state file");
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
catch (error) {
|
|
539
|
+
logger.warn("Error clearing state file:", error);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type { PlatformClient } from "./client";
|
|
2
|
+
import type { Task } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* API for managing tasks within workflows.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* const client = new PlatformClient({ apiKey: 'your-key' });
|
|
9
|
+
*
|
|
10
|
+
* // Create a task
|
|
11
|
+
* const task = await client.tasks.create({
|
|
12
|
+
* workflowId: 123,
|
|
13
|
+
* agentId: 456,
|
|
14
|
+
* description: 'Process the data',
|
|
15
|
+
* body: 'Additional details'
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* // Create a task with dependencies
|
|
19
|
+
* const task2 = await client.tasks.create({
|
|
20
|
+
* workflowId: 123,
|
|
21
|
+
* agentId: 456,
|
|
22
|
+
* description: 'Follow-up task',
|
|
23
|
+
* dependencies: [task.id]
|
|
24
|
+
* });
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare class TasksAPI {
|
|
28
|
+
private client;
|
|
29
|
+
constructor(client: PlatformClient);
|
|
30
|
+
/**
|
|
31
|
+
* Create a new task in a workflow.
|
|
32
|
+
* @param params - Parameters object
|
|
33
|
+
* @param params.workflowId - The workflow ID to create the task in
|
|
34
|
+
* @param params.agentId - The agent ID to assign the task to
|
|
35
|
+
* @param params.description - Short description of the task
|
|
36
|
+
* @param params.body - Detailed task body (defaults to description)
|
|
37
|
+
* @param params.input - Input data for the task
|
|
38
|
+
* @param params.dependencies - Array of task IDs this task depends on
|
|
39
|
+
* @returns The created task
|
|
40
|
+
*/
|
|
41
|
+
create(params: {
|
|
42
|
+
workflowId: number | string;
|
|
43
|
+
agentId: number | string;
|
|
44
|
+
description: string;
|
|
45
|
+
body?: string;
|
|
46
|
+
input?: string;
|
|
47
|
+
dependencies?: (number | string)[];
|
|
48
|
+
}): Promise<Task>;
|
|
49
|
+
/**
|
|
50
|
+
* Get a task by ID.
|
|
51
|
+
* @param params - Parameters object
|
|
52
|
+
* @param params.workflowId - The workflow ID
|
|
53
|
+
* @param params.id - The task ID
|
|
54
|
+
* @returns The task
|
|
55
|
+
*/
|
|
56
|
+
get(params: {
|
|
57
|
+
workflowId: number | string;
|
|
58
|
+
id: number | string;
|
|
59
|
+
}): Promise<Task>;
|
|
60
|
+
/**
|
|
61
|
+
* List all tasks in a workflow.
|
|
62
|
+
* @param params - Parameters object
|
|
63
|
+
* @param params.workflowId - The workflow ID
|
|
64
|
+
* @returns Array of tasks
|
|
65
|
+
*/
|
|
66
|
+
list(params: {
|
|
67
|
+
workflowId: number | string;
|
|
68
|
+
}): Promise<Task[]>;
|
|
69
|
+
/**
|
|
70
|
+
* Update an existing task.
|
|
71
|
+
* @param params - Parameters object
|
|
72
|
+
* @param params.workflowId - The workflow ID
|
|
73
|
+
* @param params.id - The task ID to update
|
|
74
|
+
* @param params.description - New description (optional)
|
|
75
|
+
* @param params.body - New body (optional)
|
|
76
|
+
* @param params.input - New input (optional)
|
|
77
|
+
* @param params.status - New status (optional)
|
|
78
|
+
* @param params.assigneeAgentId - New assignee agent ID (optional)
|
|
79
|
+
* @param params.dependencies - New dependencies (optional)
|
|
80
|
+
* @returns The updated task
|
|
81
|
+
*/
|
|
82
|
+
update(params: {
|
|
83
|
+
workflowId: number | string;
|
|
84
|
+
id: number | string;
|
|
85
|
+
description?: string;
|
|
86
|
+
body?: string;
|
|
87
|
+
input?: string;
|
|
88
|
+
status?: string;
|
|
89
|
+
assigneeAgentId?: number;
|
|
90
|
+
dependencies?: number[];
|
|
91
|
+
}): Promise<Task>;
|
|
92
|
+
/**
|
|
93
|
+
* Delete a task.
|
|
94
|
+
* @param params - Parameters object
|
|
95
|
+
* @param params.workflowId - The workflow ID
|
|
96
|
+
* @param params.id - The task ID to delete
|
|
97
|
+
*/
|
|
98
|
+
delete(params: {
|
|
99
|
+
workflowId: number | string;
|
|
100
|
+
id: number | string;
|
|
101
|
+
}): Promise<void>;
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=tasks-api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tasks-api.d.ts","sourceRoot":"","sources":["../src/tasks-api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,SAAS,CAAC;AAEhD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,QAAQ;IACP,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,cAAc;IAE1C;;;;;;;;;;OAUG;IACG,MAAM,CAAC,MAAM,EAAE;QACnB,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;QAC5B,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;QACzB,WAAW,EAAE,MAAM,CAAC;QACpB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,YAAY,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;KACpC,GAAG,OAAO,CAAC,IAAI,CAAC;IAyBjB;;;;;;OAMG;IACG,GAAG,CAAC,MAAM,EAAE;QAChB,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;QAC5B,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;KACrB,GAAG,OAAO,CAAC,IAAI,CAAC;IAMjB;;;;;OAKG;IACG,IAAI,CAAC,MAAM,EAAE;QAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAIpE;;;;;;;;;;;;OAYG;IACG,MAAM,CAAC,MAAM,EAAE;QACnB,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;QAC5B,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;QACpB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;KACzB,GAAG,OAAO,CAAC,IAAI,CAAC;IAOjB;;;;;OAKG;IACG,MAAM,CAAC,MAAM,EAAE;QACnB,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;QAC5B,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;KACrB,GAAG,OAAO,CAAC,IAAI,CAAC;CAKlB"}
|