@bpmsoftwaresolutions/ai-engine-client 1.1.38 → 1.1.41

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 (3) hide show
  1. package/README.md +17 -0
  2. package/package.json +1 -1
  3. package/src/index.js +71 -1
package/README.md CHANGED
@@ -79,6 +79,21 @@ const generatedUsability = await client.getGeneratedExecutionUsability();
79
79
  const logaUsability = await client.getLogaGeneratedExecutionUsabilityProjection();
80
80
  ```
81
81
 
82
+ ## Project Continuation Runtime
83
+
84
+ Once you know the project identity, use `resumeProjectWork()` as the canonical startup and hydration call for project work.
85
+
86
+ ```js
87
+ const continuation = await client.resumeProjectWork({
88
+ projectIdentifier: charter.project_name,
89
+ actorMode: 'operator',
90
+ executionIntent: 'continue governed work',
91
+ requireClaim: true,
92
+ });
93
+ ```
94
+
95
+ That call resolves the canonical project, active roadmap state, workflow context, tool bindings, and the continuation brief in one governed response. Use the returned `continuation_brief_markdown` as the primary focus surface for LOGA and operator startup flows.
96
+
82
97
  ## Integration Notes
83
98
 
84
99
  ### Auth Modes
@@ -408,6 +423,7 @@ const packet = await client.downloadExternalWorkflowRunArtifact('run-123', 'pack
408
423
  | `startSessionGovernance(body)` | Start a governed external session and return the `session_key` required for mutation-capable assistant turns. |
409
424
  | `claimWorkItem(body)` | Bind an oriented, claim-locked context session to a concrete work item and return the active claim envelope. |
410
425
  | `persistAssistantTurn(body)` | Persist an assistant turn to durable SQL through the API and return refreshed status projections. |
426
+ | `resumeProjectWork({ projectIdentifier, actorMode, executionIntent, requireClaim, workflowRunLimit })` | Canonical project startup and hydration call that resolves the continuation brief, active item, required tools, allowed scope, and next governed action from a project identifier. |
411
427
  | `createExternalAudioRender({ text, voice, model, speed, file })` | Create a client-scoped external audio render using inline text or multipart upload. |
412
428
  | `getExternalAudioRender(audioRenderRunId)` | Read external audio render status for the authenticated client. |
413
429
  | `downloadExternalAudioRender(audioRenderRunId)` | Download the rendered MP3 artifact for the authenticated client. |
@@ -418,6 +434,7 @@ const packet = await client.downloadExternalWorkflowRunArtifact('run-123', 'pack
418
434
  | `getExternalProjectRoadmapActiveItem(projectId)` | API-key-compatible active roadmap item read through the external `/api/v1` boundary. |
419
435
  | `listExternalProjectOpenTasks(projectId)` | API-key-compatible open task read through the external `/api/v1` boundary. |
420
436
  | `getExternalProjectStatusBundle(projectId)` | One-call API-key-compatible bundle for project status, roadmap summary, active item, and open tasks. |
437
+ | `getExternalProjectResumeContext(projectId, { actorMode, executionIntent, requireClaim, workflowRunLimit })` | API-key-compatible continuation bootstrap through the external `/api/v1/projects/:projectId/resume-context` boundary. |
421
438
 
422
439
  ### Operator Status
423
440
  | Method | Description |
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.41",
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.41';
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
  }