@bpmsoftwaresolutions/ai-engine-client 1.1.38 → 1.1.39

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +71 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bpmsoftwaresolutions/ai-engine-client",
3
- "version": "1.1.38",
3
+ "version": "1.1.39",
4
4
  "description": "Thin npm client for the AI Engine operator and retrieval APIs",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
package/src/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  const DEFAULT_TIMEOUT_MS = 30000;
2
- export const AI_ENGINE_CLIENT_VERSION = '1.1.38';
2
+ export const AI_ENGINE_CLIENT_VERSION = '1.1.39';
3
3
  export const GOVERNED_MUTATION_REQUIRED_CAPABILITIES = [
4
4
  'executeVerifiedMutation',
5
5
  'post_mutation_verification',
@@ -1541,6 +1541,76 @@ export class AIEngineClient {
1541
1541
  return this._request(`/api/operator/projects/${projectId}`);
1542
1542
  }
1543
1543
 
1544
+ async listProjectWorkflowRuns(projectId, { limit = 25 } = {}) {
1545
+ return this._request(`/api/operator/projects/${projectId}/workflow-runs`, {
1546
+ query: { limit },
1547
+ });
1548
+ }
1549
+
1550
+ async closeProject(projectId, {
1551
+ workflowId,
1552
+ workflowRunIds,
1553
+ reason,
1554
+ operatorIdentity,
1555
+ runTerminalStatus = 'failed',
1556
+ } = {}) {
1557
+ const normalizedProjectId = cleanText(projectId);
1558
+ if (!normalizedProjectId) {
1559
+ throw new Error('projectId is required.');
1560
+ }
1561
+ const normalizedReason = cleanText(reason) || 'close active project';
1562
+ const normalizedOperatorIdentity = cleanText(operatorIdentity) || this.actorId;
1563
+ const resolvedRuns = Array.isArray(workflowRunIds) ? cleanList(workflowRunIds) : [];
1564
+ let resolvedWorkflowId = cleanText(workflowId);
1565
+
1566
+ if (!resolvedWorkflowId || resolvedRuns.length === 0) {
1567
+ const projectPayload = await this.getProject(normalizedProjectId);
1568
+ const summary = isPlainObject(projectPayload?.summary) ? projectPayload.summary : {};
1569
+ if (!resolvedWorkflowId) {
1570
+ resolvedWorkflowId = cleanText(summary.workflow_id) || cleanText(summary.workflowId);
1571
+ }
1572
+ if (resolvedRuns.length === 0) {
1573
+ const workflowRuns = await this.listProjectWorkflowRuns(normalizedProjectId, { limit: 100 });
1574
+ const activeStatuses = new Set(['queued', 'running', 'blocked', 'open', 'active', 'ping-review']);
1575
+ const activeRuns = Array.isArray(workflowRuns)
1576
+ ? workflowRuns.filter((run) => activeStatuses.has(String(run?.status || '').trim().toLowerCase()))
1577
+ : [];
1578
+ for (const run of activeRuns) {
1579
+ const runId = cleanText(run.workflow_run_id || run.workflowRunId);
1580
+ if (runId && !resolvedRuns.includes(runId)) {
1581
+ resolvedRuns.push(runId);
1582
+ }
1583
+ if (!resolvedWorkflowId) {
1584
+ resolvedWorkflowId = cleanText(run.workflow_id || run.workflowId) || resolvedWorkflowId;
1585
+ }
1586
+ }
1587
+ }
1588
+ }
1589
+
1590
+ if (!resolvedWorkflowId) {
1591
+ throw new Error('workflowId could not be resolved for project cleanup.');
1592
+ }
1593
+ if (resolvedRuns.length === 0) {
1594
+ throw new Error('workflowRunIds could not be resolved for project cleanup.');
1595
+ }
1596
+
1597
+ return this._request('/api/operator/cleanup', {
1598
+ method: 'POST',
1599
+ body: {
1600
+ project_id: normalizedProjectId,
1601
+ workflow_id: resolvedWorkflowId,
1602
+ workflow_run_ids: resolvedRuns,
1603
+ reason: normalizedReason,
1604
+ operator_identity: normalizedOperatorIdentity,
1605
+ run_terminal_status: cleanText(runTerminalStatus) || 'failed',
1606
+ },
1607
+ });
1608
+ }
1609
+
1610
+ async closeActiveProject(projectId, options = {}) {
1611
+ return this.closeProject(projectId, options);
1612
+ }
1613
+
1544
1614
  async getProjectCharterReport(projectId) {
1545
1615
  return this._request(`/api/operator/projects/${projectId}/charter/report`);
1546
1616
  }