@openserv-labs/client 1.0.0 → 1.0.1

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 CHANGED
@@ -215,16 +215,19 @@ const cronTrigger = await client.triggers.create({
215
215
  )
216
216
  })
217
217
 
218
- // Create an x402 (paid) trigger
218
+ // Create an x402 (paid) trigger with a beautiful name and description
219
219
  const paidTrigger = await client.triggers.create({
220
220
  workflowId: 789,
221
- name: 'Paid API',
221
+ name: 'AI Research Assistant',
222
+ description: 'Get comprehensive research reports on any topic powered by AI',
222
223
  type: 'x402',
223
224
  props: triggerConfigToProps(
224
225
  triggers.x402({
226
+ name: 'AI Research Assistant',
227
+ description: 'Get comprehensive research reports on any topic powered by AI',
225
228
  price: '0.01',
226
229
  input: {
227
- query: { type: 'string', description: 'Search query' }
230
+ query: { type: 'string', description: 'Research topic or question' }
228
231
  }
229
232
  })
230
233
  )
@@ -489,21 +492,23 @@ console.log(result.apiEndpoint) // Webhook URL to call
489
492
  ```typescript
490
493
  import { provision, triggers, isProvisioned, getProvisionedInfo, clearProvisionedState } from '@openserv-labs/client'
491
494
 
492
- // Provision with x402 (paid) trigger
495
+ // Provision with x402 (paid) trigger - include beautiful name and description
493
496
  const paidResult = await provision({
494
497
  agent: {
495
- name: 'paid-agent',
496
- description: 'Premium AI service',
497
- endpointUrl: 'https://paid-agent.example.com' // Required for production
498
+ name: 'research-assistant',
499
+ description: 'Premium AI research service',
500
+ endpointUrl: 'https://research-agent.example.com' // Required for production
498
501
  },
499
502
  workflow: {
500
- name: 'paid-workflow',
503
+ name: 'research-workflow',
501
504
  trigger: triggers.x402({
505
+ name: 'AI Research Assistant',
506
+ description: 'Get comprehensive research reports on any topic powered by AI',
502
507
  price: '0.01',
503
- input: { prompt: { type: 'string' } }
508
+ input: { prompt: { type: 'string', description: 'Research topic or question' } }
504
509
  }),
505
510
  task: {
506
- description: 'Process paid requests and deliver premium results'
511
+ description: 'Process research requests and deliver comprehensive reports'
507
512
  }
508
513
  }
509
514
  })
@@ -549,29 +554,39 @@ Use the `triggers` factory for type-safe trigger configuration:
549
554
  ```typescript
550
555
  import { triggers, triggerConfigToProps } from '@openserv-labs/client'
551
556
 
552
- // Webhook trigger
557
+ // Webhook trigger with name and description
553
558
  triggers.webhook({
559
+ name: 'Data Ingestion Webhook',
560
+ description: 'Receives data from external systems for processing',
554
561
  input: { message: { type: 'string' } },
555
562
  waitForCompletion: true,
556
563
  timeout: 180
557
564
  })
558
565
 
559
- // Cron trigger
566
+ // Cron trigger with name and description
560
567
  triggers.cron({
561
- schedule: '0 */6 * * *', // Every 6 hours
568
+ name: 'Daily Report Generator',
569
+ description: 'Generates daily analytics reports every 6 hours',
570
+ schedule: '0 */6 * * *',
562
571
  timezone: 'UTC'
563
572
  })
564
573
 
565
- // x402 (paid) trigger
574
+ // x402 (paid) trigger with beautiful name and description
575
+ // These appear in the x402-services listing
566
576
  triggers.x402({
577
+ name: 'AI Research Assistant',
578
+ description: 'Get comprehensive research reports on any topic powered by AI',
567
579
  price: '0.05',
568
- input: { prompt: { type: 'string', description: 'User prompt' } },
580
+ input: { prompt: { type: 'string', description: 'Research topic or question' } },
569
581
  timeout: 300,
570
582
  walletAddress: '0x...'
571
583
  })
572
584
 
573
- // Manual trigger
574
- triggers.manual()
585
+ // Manual trigger with name and description
586
+ triggers.manual({
587
+ name: 'Manual Test Trigger',
588
+ description: 'For testing workflows manually'
589
+ })
575
590
  ```
576
591
 
577
592
  ## Environment Variables
@@ -1 +1 @@
1
- {"version":3,"file":"agents-api.d.ts","sourceRoot":"","sources":["../src/agents-api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,KAAK,EACV,KAAK,EAKL,yBAAyB,EAC1B,MAAM,SAAS,CAAC;AAEjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,SAAS;IACR,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,cAAc;IAE1C;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;IAK9B;;;;;;;;OAQG;IACG,eAAe,CAAC,MAAM,CAAC,EAAE;QAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,iBAAiB,CAAC,EAAE,OAAO,CAAC;KAC7B,GAAG,OAAO,CAAC,yBAAyB,CAAC;IAetC;;;;;OAKG;IACG,GAAG,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,KAAK,CAAC;IAI1D;;;;;;;OAOG;IACG,WAAW,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAO9D;;;;;;;OAOG;IACG,MAAM,CAAC,MAAM,EAAE;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,wBAAwB,EAAE,MAAM,CAAC;QACjC,YAAY,EAAE,MAAM,CAAC;KACtB,GAAG,OAAO,CAAC,KAAK,CAAC;IAWlB;;;;;OAKG;IACG,SAAS,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAQjE;;;;;;;;OAQG;IACG,MAAM,CAAC,MAAM,EAAE;QACnB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;QACpB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,wBAAwB,CAAC,EAAE,MAAM,CAAC;KACnC,GAAG,OAAO,CAAC,KAAK,CAAC;IAuClB;;;;OAIG;IACG,MAAM,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAK5D;;;OAGG;IACG,iBAAiB,IAAI,OAAO,CAAC;QACjC,SAAS,EAAE,MAAM,CAAC;QAClB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;IAOF;;;OAGG;IACG,aAAa,CAAC,MAAM,EAAE;QAC1B,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;QACpB,aAAa,EAAE,MAAM,CAAC;KACvB,GAAG,OAAO,CAAC,IAAI,CAAC;CAKlB"}
1
+ {"version":3,"file":"agents-api.d.ts","sourceRoot":"","sources":["../src/agents-api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,KAAK,EACV,KAAK,EAKL,yBAAyB,EAC1B,MAAM,SAAS,CAAC;AAEjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,SAAS;IACR,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,cAAc;IAE1C;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;IAK9B;;;;;;;;OAQG;IACG,eAAe,CAAC,MAAM,CAAC,EAAE;QAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,iBAAiB,CAAC,EAAE,OAAO,CAAC;KAC7B,GAAG,OAAO,CAAC,yBAAyB,CAAC;IAetC;;;;;OAKG;IACG,GAAG,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,KAAK,CAAC;IAI1D;;;;;;;OAOG;IACG,WAAW,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAO9D;;;;;;;OAOG;IACG,MAAM,CAAC,MAAM,EAAE;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,wBAAwB,EAAE,MAAM,CAAC;QACjC,YAAY,EAAE,MAAM,CAAC;KACtB,GAAG,OAAO,CAAC,KAAK,CAAC;IAWlB;;;;;OAKG;IACG,SAAS,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAQjE;;;;;;;;OAQG;IACG,MAAM,CAAC,MAAM,EAAE;QACnB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;QACpB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,wBAAwB,CAAC,EAAE,MAAM,CAAC;KACnC,GAAG,OAAO,CAAC,KAAK,CAAC;IAwClB;;;;OAIG;IACG,MAAM,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAK5D;;;OAGG;IACG,iBAAiB,IAAI,OAAO,CAAC;QACjC,SAAS,EAAE,MAAM,CAAC;QAClB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;IAOF;;;OAGG;IACG,aAAa,CAAC,MAAM,EAAE;QAC1B,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;QACpB,aAAa,EAAE,MAAM,CAAC;KACvB,GAAG,OAAO,CAAC,IAAI,CAAC;CAKlB"}
@@ -145,8 +145,9 @@ class AgentsAPI {
145
145
  is_trading_agent: currentAgent.is_trading_agent ?? false,
146
146
  scopes,
147
147
  };
148
- // Note: endpoint_url is required for external agents. The GET single agent
149
- // endpoint doesn't return it, so it must be provided in the update params.
148
+ // endpoint_url is required for external agents.
149
+ // For your own agents, the GET endpoint returns endpoint_url.
150
+ // For other agents (not owned by you), endpoint_url is not returned.
150
151
  if (updatePayload.kind === "external" && !updatePayload.endpoint_url) {
151
152
  throw new Error("endpoint_url is required when updating an external agent");
152
153
  }
@@ -100,11 +100,16 @@ export interface Logger {
100
100
  export declare function setLogger(customLogger: Logger): void;
101
101
  /**
102
102
  * Provision an agent and workflow on the OpenServ platform.
103
+ *
104
+ * **This function is idempotent** - you can call it multiple times with the same
105
+ * config and it will update existing resources rather than create duplicates.
106
+ * There's no need to check `isProvisioned()` before calling this function.
107
+ *
103
108
  * This function handles:
104
109
  * - Wallet creation/retrieval
105
110
  * - Platform authentication (with session persistence)
106
- * - Agent registration/update
107
- * - Workflow creation/update
111
+ * - Agent registration/update (creates if new, updates if exists)
112
+ * - Workflow creation/update (creates if new, updates if exists)
108
113
  * - State persistence to .openserv.json
109
114
  *
110
115
  * @param config - Provisioning configuration
@@ -114,11 +119,11 @@ export declare function setLogger(customLogger: Logger): void;
114
119
  * ```ts
115
120
  * import { provision, triggers } from '@openserv-labs/client';
116
121
  *
122
+ * // Just call provision - it handles create vs update automatically
117
123
  * const result = await provision({
118
124
  * agent: {
119
125
  * name: 'my-agent',
120
126
  * description: 'My autonomous agent',
121
- * // endpointUrl is optional - SDK v2.0.0+ auto-updates to agents-proxy when run(agent) is called
122
127
  * },
123
128
  * workflow: {
124
129
  * name: 'default',
@@ -139,17 +144,25 @@ export declare function provision(config: ProvisionConfig): Promise<ProvisionRes
139
144
  *
140
145
  * This checks the local `.openserv.json` state file.
141
146
  *
147
+ * **Note:** Since `provision()` is idempotent, you typically don't need to call
148
+ * this before provisioning. This function is useful for:
149
+ * - Skipping setup logs/messages on subsequent runs
150
+ * - Checking status without making API calls
151
+ * - Conditional logic based on provisioning state
152
+ *
142
153
  * @param agentName - Name of the agent to check
143
154
  * @param workflowName - Name of the workflow (defaults to "default")
144
155
  * @returns True if both agent and workflow are provisioned
145
156
  *
146
157
  * @example
147
158
  * ```typescript
148
- * if (isProvisioned('my-agent', 'api-workflow')) {
149
- * console.log('Already provisioned!');
150
- * } else {
151
- * await provision(config);
159
+ * // Optional: use for conditional logging
160
+ * if (!isProvisioned('my-agent', 'api-workflow')) {
161
+ * console.log('First-time setup...');
152
162
  * }
163
+ *
164
+ * // provision() is idempotent - safe to call regardless
165
+ * await provision(config);
153
166
  * ```
154
167
  */
155
168
  export declare function isProvisioned(agentName: string, workflowName?: string): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"provision.d.ts","sourceRoot":"","sources":["../src/provision.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,aAAa,EAAwB,MAAM,gBAAgB,CAAC;AAM1E;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,eAAe;IAC9B,0BAA0B;IAC1B,KAAK,EAAE;QACL,gCAAgC;QAChC,IAAI,EAAE,MAAM,CAAC;QACb,8CAA8C;QAC9C,WAAW,EAAE,MAAM,CAAC;QACpB;;;;;WAKG;QACH,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,6BAA6B;IAC7B,QAAQ,EAAE;QACR,4BAA4B;QAC5B,IAAI,EAAE,MAAM,CAAC;QACb,mDAAmD;QACnD,OAAO,EAAE,aAAa,CAAC;QACvB,kCAAkC;QAClC,IAAI,CAAC,EAAE;YACL,uBAAuB;YACvB,WAAW,CAAC,EAAE,MAAM,CAAC;YACrB,yBAAyB;YACzB,IAAI,CAAC,EAAE,MAAM,CAAC;SACf,CAAC;KACH,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,6BAA6B;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gCAAgC;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,+BAA+B;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,2CAA2C;IAC3C,YAAY,EAAE,MAAM,CAAC;IACrB,oCAAoC;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AA2BD;;;GAGG;AACH,MAAM,WAAW,MAAM;IACrB,iCAAiC;IACjC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACnC,2BAA2B;IAC3B,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACnC,yBAAyB;IACzB,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;CACrC;AAUD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAEpD;AA2bD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,eAAe,GACtB,OAAO,CAAC,eAAe,CAAC,CAkC1B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,EACjB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAMT;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,YAAY,CAAC,EAAE,MAAM,GACpB;IACD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,IAAI,CAmBP;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAU5C"}
1
+ {"version":3,"file":"provision.d.ts","sourceRoot":"","sources":["../src/provision.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,aAAa,EAAwB,MAAM,gBAAgB,CAAC;AAM1E;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,eAAe;IAC9B,0BAA0B;IAC1B,KAAK,EAAE;QACL,gCAAgC;QAChC,IAAI,EAAE,MAAM,CAAC;QACb,8CAA8C;QAC9C,WAAW,EAAE,MAAM,CAAC;QACpB;;;;;WAKG;QACH,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,6BAA6B;IAC7B,QAAQ,EAAE;QACR,4BAA4B;QAC5B,IAAI,EAAE,MAAM,CAAC;QACb,mDAAmD;QACnD,OAAO,EAAE,aAAa,CAAC;QACvB,kCAAkC;QAClC,IAAI,CAAC,EAAE;YACL,uBAAuB;YACvB,WAAW,CAAC,EAAE,MAAM,CAAC;YACrB,yBAAyB;YACzB,IAAI,CAAC,EAAE,MAAM,CAAC;SACf,CAAC;KACH,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,6BAA6B;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gCAAgC;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,+BAA+B;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,2CAA2C;IAC3C,YAAY,EAAE,MAAM,CAAC;IACrB,oCAAoC;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AA4BD;;;GAGG;AACH,MAAM,WAAW,MAAM;IACrB,iCAAiC;IACjC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACnC,2BAA2B;IAC3B,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACnC,yBAAyB;IACzB,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;CACrC;AAUD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAEpD;AA2hBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,eAAe,GACtB,OAAO,CAAC,eAAe,CAAC,CAkC1B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,EACjB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAMT;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,YAAY,CAAC,EAAE,MAAM,GACpB;IACD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,IAAI,CAmBP;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAU5C"}
package/dist/provision.js CHANGED
@@ -227,28 +227,41 @@ async function createAuthenticatedClient(privateKey) {
227
227
  // Default endpoint URL - SDK v2.0.0+ automatically updates to this when run(agent) is called
228
228
  const DEFAULT_AGENT_ENDPOINT = "https://agents-proxy.openserv.ai";
229
229
  /**
230
- * Register or update an agent on the platform
230
+ * Check if an error is a "not found" error (404)
231
+ */
232
+ function isNotFoundError(error) {
233
+ const axiosError = error;
234
+ return axiosError.response?.status === 404;
235
+ }
236
+ /**
237
+ * Register or update an agent on the platform.
238
+ * This function is idempotent - calling it multiple times with the same config
239
+ * will update the existing agent rather than create duplicates.
231
240
  */
232
241
  async function provisionAgent(client, config) {
233
242
  const state = readState();
234
243
  const existingAgent = state.agents[config.name];
235
- const endpointUrl = config.endpointUrl || DEFAULT_AGENT_ENDPOINT;
236
244
  if (existingAgent) {
237
- // Update existing agent - only update endpoint if explicitly provided
245
+ // Update existing agent
238
246
  const agentId = existingAgent.id;
239
247
  try {
240
- const updateParams = {
248
+ // Fetch current agent from API to get the latest endpoint_url
249
+ const currentAgent = await client.agents.get({ id: agentId });
250
+ // Use config endpoint if provided, otherwise preserve current endpoint, or use default
251
+ const endpointUrl = config.endpointUrl ||
252
+ currentAgent.endpoint_url ||
253
+ DEFAULT_AGENT_ENDPOINT;
254
+ await client.agents.update({
241
255
  id: agentId,
242
256
  name: config.name,
243
257
  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);
258
+ endpoint_url: endpointUrl,
259
+ });
251
260
  logger.info(`Updated agent ${agentId}`);
261
+ // Update stored endpoint
262
+ const freshState = readState();
263
+ freshState.agents[config.name] = { ...existingAgent, endpointUrl };
264
+ writeState(freshState);
252
265
  return {
253
266
  agentId,
254
267
  apiKey: existingAgent.apiKey,
@@ -256,10 +269,22 @@ async function provisionAgent(client, config) {
256
269
  };
257
270
  }
258
271
  catch (error) {
259
- logger.warn(`Failed to update agent ${agentId}: ${formatAxiosError(error)}`);
272
+ // Only create a new agent if the existing one was deleted from the platform (404)
273
+ // For any other error (network issues, auth problems, etc.), propagate the error
274
+ if (isNotFoundError(error)) {
275
+ logger.info(`Agent ${agentId} no longer exists on platform, will create new one`);
276
+ // Clear the stale agent from state before creating new one
277
+ delete state.agents[config.name];
278
+ writeState(state);
279
+ }
280
+ else {
281
+ // Re-throw non-404 errors to avoid creating duplicate agents
282
+ throw new Error(`Failed to update agent ${agentId}: ${formatAxiosError(error)}`);
283
+ }
260
284
  }
261
285
  }
262
- // Register new agent
286
+ // Register new agent (only reached if no existing agent, or existing was deleted)
287
+ const endpointUrl = config.endpointUrl || DEFAULT_AGENT_ENDPOINT;
263
288
  const agent = await client.agents.create({
264
289
  name: config.name,
265
290
  capabilities_description: config.description,
@@ -272,9 +297,15 @@ async function provisionAgent(client, config) {
272
297
  const { authToken, authTokenHash } = await client.agents.generateAuthToken();
273
298
  await client.agents.saveAuthToken({ id: agentId, authTokenHash });
274
299
  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);
300
+ // Re-read state to avoid overwriting concurrent changes
301
+ const freshState = readState();
302
+ freshState.agents[config.name] = {
303
+ id: agentId,
304
+ apiKey,
305
+ authToken,
306
+ endpointUrl,
307
+ };
308
+ writeState(freshState);
278
309
  logger.info(`Registered agent ${agentId}: ${config.name}`);
279
310
  return { agentId, apiKey, authToken };
280
311
  }
@@ -316,8 +347,18 @@ async function provisionWorkflow(client, agentId, agentName, walletAddress, conf
316
347
  logger.info(`Updated workflow ${workflowName} (${workflowId})`);
317
348
  }
318
349
  catch (error) {
319
- logger.warn(`Failed to update workflow ${workflowName}: ${formatAxiosError(error)}`);
320
- needsCreate = true;
350
+ // Only create a new workflow if the existing one was deleted from the platform (404)
351
+ // For any other error, propagate it to avoid creating duplicates
352
+ if (isNotFoundError(error)) {
353
+ logger.info(`Workflow ${workflowId} no longer exists on platform, will create new one`);
354
+ // Clear stale workflow from state
355
+ delete state.workflows[agentName][workflowName];
356
+ writeState(state);
357
+ needsCreate = true;
358
+ }
359
+ else {
360
+ throw new Error(`Failed to update workflow ${workflowName}: ${formatAxiosError(error)}`);
361
+ }
321
362
  }
322
363
  }
323
364
  if (needsCreate) {
@@ -342,9 +383,13 @@ async function provisionWorkflow(client, agentId, agentName, walletAddress, conf
342
383
  // Step 2: Get or create integration connection for the trigger type
343
384
  const integrationConnectionId = await client.integrations.getOrCreateConnection(integrationIdentifier);
344
385
  // Step 3: Create trigger using direct API
386
+ // Use the trigger's name/description if provided, otherwise default to type
387
+ const triggerName = config.trigger.name || config.trigger.type;
388
+ const triggerDescription = config.trigger.description;
345
389
  const trigger = await client.triggers.create({
346
390
  workflowId,
347
- name: config.trigger.type,
391
+ name: triggerName,
392
+ description: triggerDescription,
348
393
  integrationConnectionId,
349
394
  props: triggerProps,
350
395
  });
@@ -352,25 +397,70 @@ async function provisionWorkflow(client, agentId, agentName, walletAddress, conf
352
397
  triggerToken = trigger.token || "";
353
398
  logger.info(`Created trigger ${triggerId} (token: ${triggerToken || "N/A"})`);
354
399
  // Step 4: Create task using direct API
355
- await client.tasks.create({
400
+ const task = await client.tasks.create({
356
401
  workflowId,
357
402
  agentId,
358
403
  description: config.task?.description || "Process the incoming request",
359
404
  body: config.task?.body || "",
360
405
  input: "",
361
406
  });
362
- logger.info(`Created task for workflow ${workflowId}`);
363
- // Step 5: Activate trigger
407
+ const taskId = task.id;
408
+ logger.info(`Created task ${taskId} for workflow ${workflowId}`);
409
+ // Step 5: Create workflow nodes and edges to link trigger to task
410
+ const triggerNodeId = `trigger-${triggerId}`;
411
+ const taskNodeId = `task-${taskId}`;
412
+ const workflowNodes = [
413
+ {
414
+ id: triggerNodeId,
415
+ type: "trigger",
416
+ triggerId,
417
+ position: { x: 0, y: 100 },
418
+ inputPorts: [],
419
+ outputPorts: [{ id: "output" }],
420
+ isEndNode: false,
421
+ },
422
+ {
423
+ id: taskNodeId,
424
+ type: "task",
425
+ taskId,
426
+ position: { x: 300, y: 100 },
427
+ inputPorts: [{ id: "input" }],
428
+ outputPorts: [{ id: "output" }],
429
+ isEndNode: true,
430
+ },
431
+ ];
432
+ const workflowEdges = [
433
+ {
434
+ id: `edge-${triggerId}-${taskId}`,
435
+ source: triggerNodeId,
436
+ target: taskNodeId,
437
+ sourcePort: "output",
438
+ targetPort: "input",
439
+ },
440
+ ];
441
+ await client.put(`/workspaces/${workflowId}/workflow`, {
442
+ workflow: {
443
+ nodes: workflowNodes,
444
+ edges: workflowEdges,
445
+ lastUpdatedTimestamp: Date.now(),
446
+ },
447
+ });
448
+ logger.info(`Created workflow edges linking trigger ${triggerId} to task ${taskId}`);
449
+ // Step 6: Activate trigger
364
450
  await client.triggers.activate({ workflowId, id: triggerId });
365
- // Step 6: Set workspace to running
451
+ // Step 7: Set workspace to running
366
452
  await client.workflows.setRunning({ id: workflowId });
367
- // Persist workflow state
368
- state.workflows[agentName][workflowName] = {
453
+ // Re-read state to avoid overwriting concurrent changes
454
+ const freshState = readState();
455
+ if (!freshState.workflows[agentName]) {
456
+ freshState.workflows[agentName] = {};
457
+ }
458
+ freshState.workflows[agentName][workflowName] = {
369
459
  workspaceId: workflowId,
370
460
  triggerId,
371
461
  triggerToken,
372
462
  };
373
- writeState(state);
463
+ writeState(freshState);
374
464
  logger.info(`Provisioned workflow ${workflowName} (${workflowId})`);
375
465
  }
376
466
  // Validate that all required values are set
@@ -402,11 +492,16 @@ async function provisionWorkflow(client, agentId, agentName, walletAddress, conf
402
492
  // ============================================================================
403
493
  /**
404
494
  * Provision an agent and workflow on the OpenServ platform.
495
+ *
496
+ * **This function is idempotent** - you can call it multiple times with the same
497
+ * config and it will update existing resources rather than create duplicates.
498
+ * There's no need to check `isProvisioned()` before calling this function.
499
+ *
405
500
  * This function handles:
406
501
  * - Wallet creation/retrieval
407
502
  * - Platform authentication (with session persistence)
408
- * - Agent registration/update
409
- * - Workflow creation/update
503
+ * - Agent registration/update (creates if new, updates if exists)
504
+ * - Workflow creation/update (creates if new, updates if exists)
410
505
  * - State persistence to .openserv.json
411
506
  *
412
507
  * @param config - Provisioning configuration
@@ -416,11 +511,11 @@ async function provisionWorkflow(client, agentId, agentName, walletAddress, conf
416
511
  * ```ts
417
512
  * import { provision, triggers } from '@openserv-labs/client';
418
513
  *
514
+ * // Just call provision - it handles create vs update automatically
419
515
  * const result = await provision({
420
516
  * agent: {
421
517
  * name: 'my-agent',
422
518
  * description: 'My autonomous agent',
423
- * // endpointUrl is optional - SDK v2.0.0+ auto-updates to agents-proxy when run(agent) is called
424
519
  * },
425
520
  * workflow: {
426
521
  * name: 'default',
@@ -461,17 +556,25 @@ async function provision(config) {
461
556
  *
462
557
  * This checks the local `.openserv.json` state file.
463
558
  *
559
+ * **Note:** Since `provision()` is idempotent, you typically don't need to call
560
+ * this before provisioning. This function is useful for:
561
+ * - Skipping setup logs/messages on subsequent runs
562
+ * - Checking status without making API calls
563
+ * - Conditional logic based on provisioning state
564
+ *
464
565
  * @param agentName - Name of the agent to check
465
566
  * @param workflowName - Name of the workflow (defaults to "default")
466
567
  * @returns True if both agent and workflow are provisioned
467
568
  *
468
569
  * @example
469
570
  * ```typescript
470
- * if (isProvisioned('my-agent', 'api-workflow')) {
471
- * console.log('Already provisioned!');
472
- * } else {
473
- * await provision(config);
571
+ * // Optional: use for conditional logging
572
+ * if (!isProvisioned('my-agent', 'api-workflow')) {
573
+ * console.log('First-time setup...');
474
574
  * }
575
+ *
576
+ * // provision() is idempotent - safe to call regardless
577
+ * await provision(config);
475
578
  * ```
476
579
  */
477
580
  function isProvisioned(agentName, workflowName) {
@@ -21,6 +21,10 @@ export interface InputSchema {
21
21
  */
22
22
  export interface WebhookTriggerConfig {
23
23
  type: "webhook";
24
+ /** Display name for the trigger (shown in listings and UI) */
25
+ name?: string;
26
+ /** Description of what this trigger does */
27
+ description?: string;
24
28
  /** Input schema for webhook payload validation */
25
29
  input?: InputSchema;
26
30
  /** Whether to wait for workflow completion before responding */
@@ -33,6 +37,10 @@ export interface WebhookTriggerConfig {
33
37
  */
34
38
  export interface X402TriggerConfig {
35
39
  type: "x402";
40
+ /** Display name for the service (e.g., "AI Research Assistant") - shown in x402-services listing */
41
+ name?: string;
42
+ /** Description of what this service does - shown in x402-services listing */
43
+ description?: string;
36
44
  /** Price in USD (e.g., "0.01") */
37
45
  price: string;
38
46
  /** Input schema for request validation */
@@ -47,6 +55,10 @@ export interface X402TriggerConfig {
47
55
  */
48
56
  export interface CronTriggerConfig {
49
57
  type: "cron";
58
+ /** Display name for the trigger (shown in listings and UI) */
59
+ name?: string;
60
+ /** Description of what this trigger does */
61
+ description?: string;
50
62
  /** Cron expression (e.g., "0 9 * * *" for daily at 9 AM) */
51
63
  schedule: string;
52
64
  /** Timezone (default: "UTC") */
@@ -57,6 +69,10 @@ export interface CronTriggerConfig {
57
69
  */
58
70
  export interface ManualTriggerConfig {
59
71
  type: "manual";
72
+ /** Display name for the trigger (shown in listings and UI) */
73
+ name?: string;
74
+ /** Description of what this trigger does */
75
+ description?: string;
60
76
  }
61
77
  /**
62
78
  * Union type for all trigger configurations.
@@ -86,6 +102,8 @@ export declare const triggers: {
86
102
  * @returns Webhook trigger configuration
87
103
  */
88
104
  webhook: (opts?: {
105
+ name?: string;
106
+ description?: string;
89
107
  input?: InputSchema;
90
108
  waitForCompletion?: boolean;
91
109
  timeout?: number;
@@ -93,10 +111,14 @@ export declare const triggers: {
93
111
  /**
94
112
  * Create an x402 (paid) trigger configuration.
95
113
  * @param opts - Options for the x402 trigger
114
+ * @param opts.name - Display name for the service (e.g., "AI Research Assistant")
115
+ * @param opts.description - Description of what this service does
96
116
  * @param opts.price - Price in USD (e.g., "0.01")
97
117
  * @returns x402 trigger configuration
98
118
  */
99
119
  x402: (opts: {
120
+ name?: string;
121
+ description?: string;
100
122
  price: string;
101
123
  input?: InputSchema;
102
124
  timeout?: number;
@@ -110,14 +132,20 @@ export declare const triggers: {
110
132
  * @returns Cron trigger configuration
111
133
  */
112
134
  cron: (opts: {
135
+ name?: string;
136
+ description?: string;
113
137
  schedule: string;
114
138
  timezone?: string;
115
139
  }) => CronTriggerConfig;
116
140
  /**
117
141
  * Create a manual trigger configuration.
142
+ * @param opts - Optional settings for the manual trigger
118
143
  * @returns Manual trigger configuration
119
144
  */
120
- manual: () => ManualTriggerConfig;
145
+ manual: (opts?: {
146
+ name?: string;
147
+ description?: string;
148
+ }) => ManualTriggerConfig;
121
149
  };
122
150
  /**
123
151
  * Convert an InputSchema to JSON Schema format.
@@ -167,7 +195,8 @@ export declare class TriggersAPI {
167
195
  * Create a new trigger in a workflow.
168
196
  * @param params - Parameters object
169
197
  * @param params.workflowId - The workflow ID
170
- * @param params.name - Name for the trigger
198
+ * @param params.name - Display name for the trigger (e.g., "AI Research Assistant")
199
+ * @param params.description - Description of what this trigger does
171
200
  * @param params.integrationConnectionId - Integration connection ID (e.g., from getOrCreateConnection)
172
201
  * @param params.props - Trigger properties (use triggerConfigToProps helper)
173
202
  * @param params.trigger_name - Optional specific trigger name
@@ -176,6 +205,7 @@ export declare class TriggersAPI {
176
205
  create(params: {
177
206
  workflowId: number | string;
178
207
  name: string;
208
+ description?: string;
179
209
  integrationConnectionId: string;
180
210
  props?: Record<string, unknown>;
181
211
  trigger_name?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"triggers-api.d.ts","sourceRoot":"","sources":["../src/triggers-api.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"triggers-api.d.ts","sourceRoot":"","sources":["../src/triggers-api.ts"],"names":[],"mappings":"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"}
@@ -36,6 +36,8 @@ exports.triggers = {
36
36
  /**
37
37
  * Create an x402 (paid) trigger configuration.
38
38
  * @param opts - Options for the x402 trigger
39
+ * @param opts.name - Display name for the service (e.g., "AI Research Assistant")
40
+ * @param opts.description - Description of what this service does
39
41
  * @param opts.price - Price in USD (e.g., "0.01")
40
42
  * @returns x402 trigger configuration
41
43
  */
@@ -56,10 +58,12 @@ exports.triggers = {
56
58
  }),
57
59
  /**
58
60
  * Create a manual trigger configuration.
61
+ * @param opts - Optional settings for the manual trigger
59
62
  * @returns Manual trigger configuration
60
63
  */
61
- manual: () => ({
64
+ manual: (opts) => ({
62
65
  type: "manual",
66
+ ...opts,
63
67
  }),
64
68
  };
65
69
  // ============================================================================
@@ -167,16 +171,18 @@ class TriggersAPI {
167
171
  * Create a new trigger in a workflow.
168
172
  * @param params - Parameters object
169
173
  * @param params.workflowId - The workflow ID
170
- * @param params.name - Name for the trigger
174
+ * @param params.name - Display name for the trigger (e.g., "AI Research Assistant")
175
+ * @param params.description - Description of what this trigger does
171
176
  * @param params.integrationConnectionId - Integration connection ID (e.g., from getOrCreateConnection)
172
177
  * @param params.props - Trigger properties (use triggerConfigToProps helper)
173
178
  * @param params.trigger_name - Optional specific trigger name
174
179
  * @returns The created trigger
175
180
  */
176
181
  async create(params) {
177
- const { workflowId, name, integrationConnectionId, props, trigger_name } = params;
182
+ const { workflowId, name, description, integrationConnectionId, props, trigger_name, } = params;
178
183
  const data = await this.client.post(`/workspaces/${workflowId}/trigger`, {
179
184
  name,
185
+ description: description || name,
180
186
  // If trigger_name not specified, server will use the integration's default
181
187
  ...(trigger_name && { trigger_name }),
182
188
  integrationConnectionId,
@@ -134,7 +134,7 @@ export declare class WorkflowsAPI {
134
134
  edges?: EdgeDefinition[];
135
135
  }): Promise<void>;
136
136
  private syncInternal;
137
- private getIntegrationConnectionId;
137
+ private getIntegrationIdentifier;
138
138
  private getTriggerName;
139
139
  private resolveEdgeRef;
140
140
  private resolveNodeId;
@@ -1 +1 @@
1
- {"version":3,"file":"workflows-api.d.ts","sourceRoot":"","sources":["../src/workflows-api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,KAAK,EACV,cAAc,EAEd,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,IAAI,EAGL,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,YAAY;IACX,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,cAAc;IAE1C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BG;IACG,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,QAAQ,CAAC;IA4BvD;;;;;OAKG;IACG,GAAG,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,QAAQ,CAAC;IA8C7D;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IAWjC;;;;;;;OAOG;IACG,MAAM,CAAC,MAAM,EAAE;QACnB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;QACpB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,GAAG,OAAO,CAAC,QAAQ,CAAC;IAWrB;;;;OAIG;IACG,MAAM,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAI5D;;;;;;;OAOG;IACG,UAAU,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAMhE;;;;;OAKG;IACG,OAAO,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,KAAK,EAAE,IAAI,EAAE,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAoB5E;;;;;;;;;;;;OAYG;IACG,IAAI,CAAC,MAAM,EAAE;QACjB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE,iBAAiB,EAAE,CAAC;QAC/B,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;QACzB,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;KAC1B,GAAG,OAAO,CAAC,IAAI,CAAC;YAWH,YAAY;IA8H1B,OAAO,CAAC,0BAA0B;IAWlC,OAAO,CAAC,cAAc;IAWtB,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,aAAa;CAQtB"}
1
+ {"version":3,"file":"workflows-api.d.ts","sourceRoot":"","sources":["../src/workflows-api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,KAAK,EACV,cAAc,EAEd,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,IAAI,EAGL,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,YAAY;IACX,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,cAAc;IAE1C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BG;IACG,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,QAAQ,CAAC;IA4BvD;;;;;OAKG;IACG,GAAG,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,QAAQ,CAAC;IA8C7D;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IAWjC;;;;;;;OAOG;IACG,MAAM,CAAC,MAAM,EAAE;QACnB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;QACpB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,GAAG,OAAO,CAAC,QAAQ,CAAC;IAWrB;;;;OAIG;IACG,MAAM,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAI5D;;;;;;;OAOG;IACG,UAAU,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAMhE;;;;;OAKG;IACG,OAAO,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,KAAK,EAAE,IAAI,EAAE,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAoB5E;;;;;;;;;;;;OAYG;IACG,IAAI,CAAC,MAAM,EAAE;QACjB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE,iBAAiB,EAAE,CAAC;QAC/B,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;QACzB,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;KAC1B,GAAG,OAAO,CAAC,IAAI,CAAC;YAWH,YAAY;IA2J1B,OAAO,CAAC,wBAAwB;IAWhC,OAAO,CAAC,cAAc;IAWtB,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,aAAa;CAQtB"}
@@ -231,20 +231,27 @@ class WorkflowsAPI {
231
231
  for (const t of currentTasks || []) {
232
232
  taskNameToId.set(t.name || t.description, t.id);
233
233
  }
234
- // Build triggers array with IDs
234
+ // Build triggers array with IDs - need to resolve integration connection IDs
235
235
  if (config.triggers) {
236
- syncPayload.triggers = config.triggers.map((t) => ({
237
- id: t.id || triggerNameToId.get(t.name) || `new-${t.name}`,
238
- name: t.name,
239
- description: t.name,
240
- // Use integrationConnectionId if provided, otherwise fall back to type-based lookup
241
- integrationConnectionId: t.integrationConnectionId || this.getIntegrationConnectionId(t.type),
242
- // trigger_name is required by the sync endpoint
243
- // Different triggers use different names: manual uses "on_event", webhook uses "on_request"
244
- trigger_name: this.getTriggerName(t.type),
245
- props: t.props || {},
246
- attributes: {},
236
+ const triggersWithConnections = await Promise.all(config.triggers.map(async (t) => {
237
+ // Get the actual integration connection ID (UUID)
238
+ let integrationConnectionId = t.integrationConnectionId;
239
+ if (!integrationConnectionId && t.type) {
240
+ const identifier = this.getIntegrationIdentifier(t.type);
241
+ integrationConnectionId =
242
+ await this.client.integrations.getOrCreateConnection(identifier);
243
+ }
244
+ return {
245
+ id: t.id || triggerNameToId.get(t.name) || `new-${t.name}`,
246
+ name: t.name,
247
+ description: t.name,
248
+ integrationConnectionId: integrationConnectionId || "",
249
+ trigger_name: this.getTriggerName(t.type),
250
+ props: t.props || {},
251
+ attributes: {},
252
+ };
247
253
  }));
254
+ syncPayload.triggers = triggersWithConnections;
248
255
  }
249
256
  // Build tasks array with IDs
250
257
  if (config.tasks) {
@@ -301,7 +308,7 @@ class WorkflowsAPI {
301
308
  });
302
309
  }
303
310
  }
304
- // Add edges with required fields
311
+ // Add edges
305
312
  if (config.edges) {
306
313
  config.edges.forEach((e, i) => {
307
314
  const sourceNode = this.resolveEdgeRef(e.from);
@@ -315,21 +322,40 @@ class WorkflowsAPI {
315
322
  });
316
323
  });
317
324
  }
325
+ else if (config.triggers &&
326
+ config.tasks &&
327
+ config.triggers.length > 0 &&
328
+ config.tasks.length > 0) {
329
+ // Auto-generate edges connecting triggers to the first task
330
+ const firstTask = config.tasks[0];
331
+ if (firstTask) {
332
+ const firstTaskName = firstTask.name;
333
+ config.triggers.forEach((trigger, i) => {
334
+ edges.push({
335
+ id: `edge-auto-${i}`,
336
+ source: `trigger-${trigger.name}`,
337
+ target: `task-${firstTaskName}`,
338
+ sourcePort: "output",
339
+ targetPort: "input",
340
+ });
341
+ });
342
+ }
343
+ }
318
344
  syncPayload.workflow = { nodes, edges };
319
345
  }
320
346
  // Call the sync endpoint
321
347
  await this.client.put(`/workspaces/${workflowId}/sync`, syncPayload);
322
348
  }
323
- getIntegrationConnectionId(type) {
349
+ getIntegrationIdentifier(type) {
324
350
  if (!type)
325
- return "";
351
+ return "manual-trigger";
326
352
  const mapping = {
327
353
  x402: "x402-trigger",
328
354
  webhook: "webhook-trigger",
329
355
  cron: "cron-trigger",
330
356
  manual: "manual-trigger",
331
357
  };
332
- return mapping[type] || type;
358
+ return mapping[type] || "manual-trigger";
333
359
  }
334
360
  getTriggerName(type) {
335
361
  if (!type)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openserv-labs/client",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "OpenServ Platform Client - Manage agents, workflows, tasks, and triggers via the OpenServ API",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",