@bpmsoftwaresolutions/ai-engine-client 1.1.37 → 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.
- package/package.json +1 -1
- package/src/index.js +175 -1
package/package.json
CHANGED
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.
|
|
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',
|
|
@@ -296,6 +296,15 @@ export class AIEngineClient {
|
|
|
296
296
|
submitArtifact: (scriptId, payload) => this.submitScriptArtifact(scriptId, payload),
|
|
297
297
|
getRunEvidence: (query) => this.getScriptRunEvidence(query),
|
|
298
298
|
};
|
|
299
|
+
this.reports = {
|
|
300
|
+
run: (request) => this.runReportDefinition(request),
|
|
301
|
+
};
|
|
302
|
+
this.projections = {
|
|
303
|
+
render: (request) => this.renderProjection(request),
|
|
304
|
+
};
|
|
305
|
+
this.actions = {
|
|
306
|
+
submit: (request) => this.submitActionIntent(request),
|
|
307
|
+
};
|
|
299
308
|
}
|
|
300
309
|
|
|
301
310
|
static fromEnv(options = {}) {
|
|
@@ -378,6 +387,101 @@ export class AIEngineClient {
|
|
|
378
387
|
return this._request('/api/v1/latest-memory-projection');
|
|
379
388
|
}
|
|
380
389
|
|
|
390
|
+
// ─── Data Access Gateway ──────────────────────────────────────────────────
|
|
391
|
+
|
|
392
|
+
async query({
|
|
393
|
+
surface,
|
|
394
|
+
contractKey,
|
|
395
|
+
parameters = {},
|
|
396
|
+
fields = [],
|
|
397
|
+
fieldAllowlist = [],
|
|
398
|
+
actorScopes = [],
|
|
399
|
+
requiredScopes = [],
|
|
400
|
+
shape = 'json',
|
|
401
|
+
requestedBy,
|
|
402
|
+
} = {}) {
|
|
403
|
+
const normalizedSurface = cleanText(surface) || cleanText(contractKey);
|
|
404
|
+
if (!normalizedSurface) {
|
|
405
|
+
throw new Error('surface is required.');
|
|
406
|
+
}
|
|
407
|
+
const normalizedShape = cleanText(shape) || 'json';
|
|
408
|
+
if (!['json', 'table', 'cards', 'markdown'].includes(normalizedShape)) {
|
|
409
|
+
throw new Error('shape must be one of json, table, cards, or markdown.');
|
|
410
|
+
}
|
|
411
|
+
const normalizedFields = cleanList(fields);
|
|
412
|
+
const normalizedAllowlist = cleanList(fieldAllowlist);
|
|
413
|
+
const disallowedFields = normalizedFields.filter((field) => !normalizedAllowlist.includes(field));
|
|
414
|
+
if (normalizedAllowlist.length > 0 && disallowedFields.length > 0) {
|
|
415
|
+
throw new Error(`Requested fields are not allowed: ${disallowedFields.join(', ')}.`);
|
|
416
|
+
}
|
|
417
|
+
const normalizedActorScopes = cleanList(actorScopes);
|
|
418
|
+
const normalizedRequiredScopes = cleanList(requiredScopes);
|
|
419
|
+
const missingScopes = normalizedRequiredScopes.filter((scope) => !normalizedActorScopes.includes(scope));
|
|
420
|
+
if (missingScopes.length > 0) {
|
|
421
|
+
throw new Error(`Missing required scopes: ${missingScopes.join(', ')}.`);
|
|
422
|
+
}
|
|
423
|
+
return this._request('/api/gateway/query', {
|
|
424
|
+
method: 'POST',
|
|
425
|
+
body: {
|
|
426
|
+
surface: normalizedSurface,
|
|
427
|
+
parameters: isPlainObject(parameters) ? parameters : {},
|
|
428
|
+
fields: normalizedFields,
|
|
429
|
+
field_allowlist: normalizedAllowlist,
|
|
430
|
+
actor_scopes: normalizedActorScopes,
|
|
431
|
+
required_scopes: normalizedRequiredScopes,
|
|
432
|
+
shape: normalizedShape,
|
|
433
|
+
requested_by: cleanText(requestedBy),
|
|
434
|
+
},
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
async runReportDefinition({ reportKey, definition = {}, requestedBy } = {}) {
|
|
439
|
+
const normalizedReportKey = cleanText(reportKey);
|
|
440
|
+
if (!normalizedReportKey) {
|
|
441
|
+
throw new Error('reportKey is required.');
|
|
442
|
+
}
|
|
443
|
+
return this._request('/api/gateway/reports/run', {
|
|
444
|
+
method: 'POST',
|
|
445
|
+
body: {
|
|
446
|
+
report_key: normalizedReportKey,
|
|
447
|
+
definition: isPlainObject(definition) ? definition : {},
|
|
448
|
+
requested_by: cleanText(requestedBy),
|
|
449
|
+
},
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
async renderProjection({ projectionType, viewContract = {}, requestedBy } = {}) {
|
|
454
|
+
const normalizedProjectionType = cleanText(projectionType);
|
|
455
|
+
if (!normalizedProjectionType) {
|
|
456
|
+
throw new Error('projectionType is required.');
|
|
457
|
+
}
|
|
458
|
+
return this._request('/api/gateway/projections/render', {
|
|
459
|
+
method: 'POST',
|
|
460
|
+
body: {
|
|
461
|
+
projection_type: normalizedProjectionType,
|
|
462
|
+
view_contract: isPlainObject(viewContract) ? viewContract : {},
|
|
463
|
+
requested_by: cleanText(requestedBy),
|
|
464
|
+
},
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
async submitActionIntent({ action, target = {}, payload = {}, requiredScope, requestedBy } = {}) {
|
|
469
|
+
const normalizedAction = cleanText(action);
|
|
470
|
+
if (!normalizedAction) {
|
|
471
|
+
throw new Error('action is required.');
|
|
472
|
+
}
|
|
473
|
+
return this._request('/api/gateway/actions/submit', {
|
|
474
|
+
method: 'POST',
|
|
475
|
+
body: {
|
|
476
|
+
action: normalizedAction,
|
|
477
|
+
target: isPlainObject(target) ? target : {},
|
|
478
|
+
payload: isPlainObject(payload) ? payload : {},
|
|
479
|
+
required_scope: cleanText(requiredScope) || 'ai-engine.write',
|
|
480
|
+
requested_by: cleanText(requestedBy),
|
|
481
|
+
},
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
|
|
381
485
|
async currentProjectStatus({ projectId } = {}) {
|
|
382
486
|
return this._request('/api/operator/current-project-status', {
|
|
383
487
|
query: { project_id: projectId },
|
|
@@ -1437,6 +1541,76 @@ export class AIEngineClient {
|
|
|
1437
1541
|
return this._request(`/api/operator/projects/${projectId}`);
|
|
1438
1542
|
}
|
|
1439
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
|
+
|
|
1440
1614
|
async getProjectCharterReport(projectId) {
|
|
1441
1615
|
return this._request(`/api/operator/projects/${projectId}/charter/report`);
|
|
1442
1616
|
}
|