@bpmsoftwaresolutions/ai-engine-client 1.0.0-beta.5 → 1.0.0-beta.7

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 +7 -0
  2. package/package.json +1 -1
  3. package/src/index.js +142 -0
package/README.md CHANGED
@@ -77,6 +77,9 @@ const client = AIEngineClient.fromEnv();
77
77
  | `currentCodebaseShapeStatus()` | Codebase shape analysis. |
78
78
  | `getLatestMemoryProjection()` | Current SQL memory projection (startup hydration source). |
79
79
  | `currentProjectStatus({ projectId })` | Current project status projection from SQL memory. |
80
+ | `runAzureSqlBacpacBackup({ databaseName, storageAccount, ... })` | Start an Azure SQL BACPAC export through the operator API. |
81
+ | `listAzureSqlBacpacBackups({ storageAccount, container, ... })` | List recent BACPAC exports visible in the configured blob container. |
82
+ | `listAzureSqlBacpacBackupOperations({ databaseName, resourceGroup, serverName, ... })` | List Azure SQL database operations so callers can poll backup/export status. |
80
83
  | `getDashboard()` | Operator dashboard payload. |
81
84
 
82
85
  ### Retrieval Wrapper
@@ -174,6 +177,9 @@ const client = AIEngineClient.fromEnv();
174
177
  | `listProjects({ limit, includeInactive, processStatus, charterStatus })` | List projects. |
175
178
  | `getProject(projectId)` | Get project detail. |
176
179
  | `getProjectCharterReport(projectId)` | Get the SQL-backed charter report payload for a project. |
180
+ | `createProjectMarkdownDownload(projectId, { reportType, includeMarkdown })` | Create a markdown download descriptor for `charter` or `implementation_roadmap`. |
181
+ | `downloadProjectMarkdownReport(projectId, reportType)` | Download a rendered markdown report as text plus filename metadata. |
182
+ | `downloadProjectCharterReportMarkdown(projectId)` | Download the charter markdown report. |
177
183
  | `getProjectBundle(projectId)` | Get current status, charter report, and roadmap report in one payload. |
178
184
 
179
185
  ### Roadmaps
@@ -184,6 +190,7 @@ const client = AIEngineClient.fromEnv();
184
190
  | `getProjectRoadmapSummary(projectId)` | Roadmap summary. |
185
191
  | `getProjectRoadmapActiveItem(projectId)` | Current active roadmap item. |
186
192
  | `getProjectImplementationRoadmapReport(projectId)` | Get the SQL-backed implementation roadmap report payload. |
193
+ | `downloadProjectImplementationRoadmapReportMarkdown(projectId)` | Download the implementation roadmap markdown report. |
187
194
  | `ensureProjectRoadmapTaskSurface(projectId, { requestedBy, assignedTo, createAcceptanceSubtasks })` | Materialize the active roadmap item's parent task and acceptance subtasks. |
188
195
  | `listProjectOpenTasks(projectId)` | Open tasks for a project. |
189
196
  | `getProjectPerformanceMetrics(projectId, { workflowId, workflowRunId, sinceUtc })` | Performance metrics. |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bpmsoftwaresolutions/ai-engine-client",
3
- "version": "1.0.0-beta.5",
3
+ "version": "1.0.0-beta.7",
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
@@ -20,6 +20,14 @@ async function readJson(response) {
20
20
  return { message: text };
21
21
  }
22
22
 
23
+ function parseContentDispositionFilename(headerValue) {
24
+ const value = String(headerValue || '');
25
+ const quotedMatch = value.match(/filename="([^"]+)"/i);
26
+ if (quotedMatch) return quotedMatch[1];
27
+ const plainMatch = value.match(/filename=([^;]+)/i);
28
+ return plainMatch ? plainMatch[1].trim() : null;
29
+ }
30
+
23
31
  export class AIEngineClient {
24
32
  constructor({ baseUrl, apiKey, actorId, fetchImpl, timeoutMs } = {}) {
25
33
  if (!baseUrl) throw new Error('baseUrl is required.');
@@ -86,6 +94,83 @@ export class AIEngineClient {
86
94
  });
87
95
  }
88
96
 
97
+ async runAzureSqlBacpacBackup({
98
+ databaseName,
99
+ storageAccount,
100
+ container,
101
+ resourceGroup,
102
+ serverName,
103
+ outputName,
104
+ adminUser,
105
+ adminPassword,
106
+ subscription,
107
+ storageKey,
108
+ skipContainerCreate,
109
+ noWait,
110
+ } = {}) {
111
+ return this._request('/api/operator/database/backups/azure-sql-bacpac', {
112
+ method: 'POST',
113
+ body: {
114
+ database_name: databaseName,
115
+ storage_account: storageAccount,
116
+ container,
117
+ resource_group: resourceGroup,
118
+ server_name: serverName,
119
+ output_name: outputName,
120
+ admin_user: adminUser,
121
+ admin_password: adminPassword,
122
+ subscription,
123
+ storage_key: storageKey,
124
+ skip_container_create: skipContainerCreate,
125
+ no_wait: noWait,
126
+ },
127
+ });
128
+ }
129
+
130
+ async listAzureSqlBacpacBackups({
131
+ storageAccount,
132
+ container,
133
+ resourceGroup,
134
+ serverName,
135
+ subscription,
136
+ storageKey,
137
+ prefix,
138
+ limit,
139
+ } = {}) {
140
+ return this._request('/api/operator/database/backups/azure-sql-bacpac', {
141
+ query: {
142
+ storage_account: storageAccount,
143
+ container,
144
+ resource_group: resourceGroup,
145
+ server_name: serverName,
146
+ subscription,
147
+ storage_key: storageKey,
148
+ prefix,
149
+ limit,
150
+ },
151
+ });
152
+ }
153
+
154
+ async listAzureSqlBacpacBackupOperations({
155
+ databaseName,
156
+ resourceGroup,
157
+ serverName,
158
+ subscription,
159
+ operationFilter,
160
+ limit,
161
+ } = {}) {
162
+ return this._request('/api/operator/database/backups/azure-sql-bacpac/operations', {
163
+ query: {
164
+ database_name: databaseName,
165
+ resource_group: resourceGroup,
166
+ server_name: serverName,
167
+ subscription,
168
+ operation_filter: operationFilter,
169
+ limit,
170
+ },
171
+ });
172
+ }
173
+
89
174
  async getDashboard() {
90
175
  return this._request('/api/dashboard');
91
176
  }
@@ -482,6 +567,21 @@ export class AIEngineClient {
482
567
  return this._request(`/api/operator/projects/${projectId}/charter/report`);
483
568
  }
484
569
 
570
+ async createProjectMarkdownDownload(projectId, { reportType, includeMarkdown = false } = {}) {
571
+ return this._request(`/api/operator/projects/${projectId}/markdown-report-downloads`, {
572
+ method: 'POST',
573
+ body: { report_type: reportType, include_markdown: includeMarkdown },
574
+ });
575
+ }
576
+
577
+ async downloadProjectMarkdownReport(projectId, reportType) {
578
+ return this._requestText(`/api/operator/projects/${projectId}/markdown-reports/${reportType}/download`);
579
+ }
580
+
581
+ async downloadProjectCharterReportMarkdown(projectId) {
582
+ return this.downloadProjectMarkdownReport(projectId, 'charter');
583
+ }
584
+
485
585
  async getProjectBundle(projectId) {
486
586
  return this._request(`/api/operator/projects/${projectId}/bundle`);
487
587
  }
@@ -510,6 +610,10 @@ export class AIEngineClient {
510
610
  return this._request(`/api/operator/projects/${projectId}/implementation-roadmap/report`);
511
611
  }
512
612
 
613
+ async downloadProjectImplementationRoadmapReportMarkdown(projectId) {
614
+ return this.downloadProjectMarkdownReport(projectId, 'implementation_roadmap');
615
+ }
616
+
513
617
  async ensureProjectRoadmapTaskSurface(projectId, {
514
618
  requestedBy,
515
619
  assignedTo,
@@ -1110,6 +1214,44 @@ export class AIEngineClient {
1110
1214
  clearTimeout(timeoutHandle);
1111
1215
  }
1112
1216
  }
1217
+
1218
+ async _requestText(path, { method = 'GET', query, headers, body } = {}) {
1219
+ const url = appendQuery(`${this.baseUrl}${path}`, query);
1220
+ const controller = new AbortController();
1221
+ const timeoutHandle = setTimeout(() => controller.abort(), this.timeoutMs);
1222
+ try {
1223
+ const response = await this.fetchImpl(url, {
1224
+ method,
1225
+ headers: {
1226
+ accept: 'text/markdown, text/plain;q=0.9, application/json;q=0.8',
1227
+ 'content-type': body ? 'application/json' : undefined,
1228
+ 'x-actor-id': this.actorId,
1229
+ authorization: this.apiKey ? `Bearer ${this.apiKey}` : undefined,
1230
+ ...headers,
1231
+ },
1232
+ body: body ? JSON.stringify(body) : undefined,
1233
+ signal: controller.signal,
1234
+ });
1235
+ const contentType = response.headers.get('content-type') || '';
1236
+ const contentDisposition = response.headers.get('content-disposition') || '';
1237
+ if (!response.ok) {
1238
+ const payload = contentType.includes('application/json')
1239
+ ? await response.json()
1240
+ : { message: await response.text() };
1241
+ const error = new Error(payload?.message || payload?.error || `Request failed with status ${response.status}.`);
1242
+ error.status = response.status;
1243
+ error.payload = payload;
1244
+ throw error;
1245
+ }
1246
+ return {
1247
+ text: await response.text(),
1248
+ contentType,
1249
+ fileName: parseContentDispositionFilename(contentDisposition),
1250
+ };
1251
+ } finally {
1252
+ clearTimeout(timeoutHandle);
1253
+ }
1254
+ }
1113
1255
  }
1114
1256
 
1115
1257
  export function createAIEngineClient(options) {