@axonflow/sdk 2.0.0 → 2.2.0
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 +39 -36
- package/dist/cjs/client.d.ts +32 -2
- package/dist/cjs/client.d.ts.map +1 -1
- package/dist/cjs/client.js +142 -86
- package/dist/cjs/client.js.map +1 -1
- package/dist/cjs/errors.d.ts +93 -6
- package/dist/cjs/errors.d.ts.map +1 -1
- package/dist/cjs/errors.js +126 -12
- package/dist/cjs/errors.js.map +1 -1
- package/dist/cjs/index.d.ts +3 -3
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +7 -3
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/code-governance.d.ts +2 -0
- package/dist/cjs/types/code-governance.d.ts.map +1 -1
- package/dist/cjs/types/config.d.ts +15 -7
- package/dist/cjs/types/config.d.ts.map +1 -1
- package/dist/cjs/types/policies.d.ts +14 -1
- package/dist/cjs/types/policies.d.ts.map +1 -1
- package/dist/cjs/types/proxy.d.ts +2 -2
- package/dist/cjs/types/proxy.d.ts.map +1 -1
- package/dist/esm/client.d.ts +32 -2
- package/dist/esm/client.d.ts.map +1 -1
- package/dist/esm/client.js +143 -87
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/errors.d.ts +93 -6
- package/dist/esm/errors.d.ts.map +1 -1
- package/dist/esm/errors.js +121 -11
- package/dist/esm/errors.js.map +1 -1
- package/dist/esm/index.d.ts +3 -3
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +3 -3
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/code-governance.d.ts +2 -0
- package/dist/esm/types/code-governance.d.ts.map +1 -1
- package/dist/esm/types/config.d.ts +15 -7
- package/dist/esm/types/config.d.ts.map +1 -1
- package/dist/esm/types/policies.d.ts +14 -1
- package/dist/esm/types/policies.d.ts.map +1 -1
- package/dist/esm/types/proxy.d.ts +2 -2
- package/dist/esm/types/proxy.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/cjs/client.js
CHANGED
|
@@ -12,15 +12,19 @@ class AxonFlow {
|
|
|
12
12
|
constructor(config) {
|
|
13
13
|
this.interceptors = [];
|
|
14
14
|
this.sessionCookie = null;
|
|
15
|
+
// Configuration validation
|
|
16
|
+
if (config.clientSecret && !config.clientId) {
|
|
17
|
+
throw new errors_1.ConfigurationError('clientSecret requires clientId to be set. ' +
|
|
18
|
+
'Provide both clientId and clientSecret for OAuth2-style authentication.');
|
|
19
|
+
}
|
|
15
20
|
// Set defaults first to determine endpoint
|
|
16
21
|
const endpoint = config.endpoint || 'https://staging-eu.getaxonflow.com';
|
|
17
|
-
// Credentials
|
|
18
|
-
|
|
19
|
-
const hasCredentials = !!(config.licenseKey || config.apiKey);
|
|
22
|
+
// Credentials check: OAuth2-style (clientId/clientSecret)
|
|
23
|
+
const hasCredentials = !!(config.clientId && config.clientSecret);
|
|
20
24
|
// Set configuration
|
|
21
25
|
this.config = {
|
|
22
|
-
|
|
23
|
-
|
|
26
|
+
clientId: config.clientId,
|
|
27
|
+
clientSecret: config.clientSecret,
|
|
24
28
|
endpoint,
|
|
25
29
|
mode: config.mode || (hasCredentials ? 'production' : 'sandbox'),
|
|
26
30
|
tenant: config.tenant || 'default',
|
|
@@ -40,17 +44,33 @@ class AxonFlow {
|
|
|
40
44
|
// Initialize interceptors
|
|
41
45
|
this.interceptors = [new openai_1.OpenAIInterceptor(), new anthropic_1.AnthropicInterceptor()];
|
|
42
46
|
if (this.config.debug) {
|
|
47
|
+
// Determine auth method for logging
|
|
48
|
+
const authMethod = hasCredentials ? 'client-credentials' : 'community (no auth)';
|
|
43
49
|
(0, helpers_1.debugLog)('AxonFlow initialized', {
|
|
44
50
|
mode: this.config.mode,
|
|
45
51
|
endpoint: this.config.endpoint,
|
|
46
|
-
authMethod
|
|
47
|
-
? this.config.licenseKey
|
|
48
|
-
? 'license-key'
|
|
49
|
-
: 'api-key'
|
|
50
|
-
: 'community (no auth)',
|
|
52
|
+
authMethod,
|
|
51
53
|
});
|
|
52
54
|
}
|
|
53
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* Get authentication headers based on configured credentials.
|
|
58
|
+
*
|
|
59
|
+
* Uses OAuth2-style Basic auth: Authorization: Basic base64(clientId:clientSecret)
|
|
60
|
+
* Also adds X-Tenant-ID header from clientId for tenant context.
|
|
61
|
+
*
|
|
62
|
+
* @returns Headers object with authentication headers
|
|
63
|
+
*/
|
|
64
|
+
getAuthHeaders() {
|
|
65
|
+
const headers = {};
|
|
66
|
+
// OAuth2-style client credentials
|
|
67
|
+
if (this.config.clientId && this.config.clientSecret) {
|
|
68
|
+
const credentials = Buffer.from(`${this.config.clientId}:${this.config.clientSecret}`).toString('base64');
|
|
69
|
+
headers['Authorization'] = `Basic ${credentials}`;
|
|
70
|
+
headers['X-Tenant-ID'] = this.config.clientId;
|
|
71
|
+
}
|
|
72
|
+
return headers;
|
|
73
|
+
}
|
|
54
74
|
/**
|
|
55
75
|
* Main method to protect AI calls with governance
|
|
56
76
|
* @param aiCall The AI call to protect
|
|
@@ -169,8 +189,8 @@ class AxonFlow {
|
|
|
169
189
|
// Transform SDK request to Agent API format
|
|
170
190
|
const agentRequest = {
|
|
171
191
|
query: request.aiRequest.prompt,
|
|
172
|
-
user_token:
|
|
173
|
-
client_id: this.config.tenant,
|
|
192
|
+
user_token: '',
|
|
193
|
+
client_id: this.config.clientId || this.config.tenant,
|
|
174
194
|
request_type: 'llm_chat',
|
|
175
195
|
context: {
|
|
176
196
|
provider: request.aiRequest.provider,
|
|
@@ -182,12 +202,8 @@ class AxonFlow {
|
|
|
182
202
|
};
|
|
183
203
|
const headers = {
|
|
184
204
|
'Content-Type': 'application/json',
|
|
205
|
+
...this.getAuthHeaders(),
|
|
185
206
|
};
|
|
186
|
-
// Add auth headers only when credentials are provided
|
|
187
|
-
// Community/self-hosted mode works without credentials
|
|
188
|
-
if (this.config.licenseKey) {
|
|
189
|
-
headers['X-License-Key'] = this.config.licenseKey;
|
|
190
|
-
}
|
|
191
207
|
const response = await fetch(url, {
|
|
192
208
|
method: 'POST',
|
|
193
209
|
headers,
|
|
@@ -250,9 +266,10 @@ class AxonFlow {
|
|
|
250
266
|
/**
|
|
251
267
|
* Create a sandbox client for testing
|
|
252
268
|
*/
|
|
253
|
-
static sandbox(
|
|
269
|
+
static sandbox(clientId = 'demo-client', clientSecret = 'demo-secret') {
|
|
254
270
|
return new AxonFlow({
|
|
255
|
-
|
|
271
|
+
clientId,
|
|
272
|
+
clientSecret,
|
|
256
273
|
mode: 'sandbox',
|
|
257
274
|
endpoint: 'https://staging-eu.getaxonflow.com',
|
|
258
275
|
debug: true,
|
|
@@ -389,9 +406,11 @@ class AxonFlow {
|
|
|
389
406
|
* ```
|
|
390
407
|
*/
|
|
391
408
|
async executeQuery(options) {
|
|
409
|
+
// Default to "anonymous" if userToken is empty/undefined (community mode)
|
|
410
|
+
const effectiveUserToken = options.userToken || 'anonymous';
|
|
392
411
|
const agentRequest = {
|
|
393
412
|
query: options.query,
|
|
394
|
-
user_token:
|
|
413
|
+
user_token: effectiveUserToken,
|
|
395
414
|
client_id: this.config.tenant,
|
|
396
415
|
request_type: options.requestType,
|
|
397
416
|
context: options.context || {},
|
|
@@ -399,15 +418,8 @@ class AxonFlow {
|
|
|
399
418
|
const url = `${this.config.endpoint}/api/request`;
|
|
400
419
|
const headers = {
|
|
401
420
|
'Content-Type': 'application/json',
|
|
421
|
+
...this.getAuthHeaders(),
|
|
402
422
|
};
|
|
403
|
-
// Add auth headers only when credentials are provided
|
|
404
|
-
// Community/self-hosted mode works without credentials
|
|
405
|
-
if (this.config.licenseKey) {
|
|
406
|
-
headers['X-License-Key'] = this.config.licenseKey;
|
|
407
|
-
}
|
|
408
|
-
else if (this.config.apiKey) {
|
|
409
|
-
headers['X-Client-Secret'] = this.config.apiKey;
|
|
410
|
-
}
|
|
411
423
|
if (this.config.debug) {
|
|
412
424
|
(0, helpers_1.debugLog)('Proxy Mode: executeQuery', {
|
|
413
425
|
requestType: options.requestType,
|
|
@@ -532,8 +544,8 @@ class AxonFlow {
|
|
|
532
544
|
async queryConnector(connectorName, query, params) {
|
|
533
545
|
const agentRequest = {
|
|
534
546
|
query,
|
|
535
|
-
user_token:
|
|
536
|
-
client_id: this.config.tenant,
|
|
547
|
+
user_token: '',
|
|
548
|
+
client_id: this.config.clientId || this.config.tenant,
|
|
537
549
|
request_type: 'mcp-query',
|
|
538
550
|
context: {
|
|
539
551
|
connector: connectorName,
|
|
@@ -543,10 +555,8 @@ class AxonFlow {
|
|
|
543
555
|
const url = `${this.config.endpoint}/api/request`;
|
|
544
556
|
const headers = {
|
|
545
557
|
'Content-Type': 'application/json',
|
|
558
|
+
...this.getAuthHeaders(),
|
|
546
559
|
};
|
|
547
|
-
if (this.config.licenseKey) {
|
|
548
|
-
headers['X-License-Key'] = this.config.licenseKey;
|
|
549
|
-
}
|
|
550
560
|
const response = await fetch(url, {
|
|
551
561
|
method: 'POST',
|
|
552
562
|
headers,
|
|
@@ -555,7 +565,7 @@ class AxonFlow {
|
|
|
555
565
|
});
|
|
556
566
|
if (!response.ok) {
|
|
557
567
|
const errorText = await response.text();
|
|
558
|
-
throw new
|
|
568
|
+
throw new errors_1.ConnectorError(`Connector query failed: ${response.status} ${response.statusText} - ${errorText}`, connectorName, 'query');
|
|
559
569
|
}
|
|
560
570
|
const agentResponse = await response.json();
|
|
561
571
|
if (this.config.debug) {
|
|
@@ -585,10 +595,8 @@ class AxonFlow {
|
|
|
585
595
|
const url = `${this.config.endpoint}/api/request`;
|
|
586
596
|
const headers = {
|
|
587
597
|
'Content-Type': 'application/json',
|
|
598
|
+
...this.getAuthHeaders(),
|
|
588
599
|
};
|
|
589
|
-
if (this.config.licenseKey) {
|
|
590
|
-
headers['X-License-Key'] = this.config.licenseKey;
|
|
591
|
-
}
|
|
592
600
|
// Use mapTimeout for MAP operations (default 2 minutes)
|
|
593
601
|
const response = await fetch(url, {
|
|
594
602
|
method: 'POST',
|
|
@@ -598,11 +606,11 @@ class AxonFlow {
|
|
|
598
606
|
});
|
|
599
607
|
if (!response.ok) {
|
|
600
608
|
const errorText = await response.text();
|
|
601
|
-
throw new
|
|
609
|
+
throw new errors_1.PlanExecutionError(`Plan generation failed: ${response.status} ${response.statusText} - ${errorText}`, undefined, 'generation');
|
|
602
610
|
}
|
|
603
611
|
const agentResponse = await response.json();
|
|
604
612
|
if (!agentResponse.success) {
|
|
605
|
-
throw new
|
|
613
|
+
throw new errors_1.PlanExecutionError(`Plan generation failed: ${agentResponse.error}`, undefined, 'generation');
|
|
606
614
|
}
|
|
607
615
|
// plan_id can be at top level or inside data
|
|
608
616
|
const planId = agentResponse.plan_id || agentResponse.data?.plan_id;
|
|
@@ -634,10 +642,8 @@ class AxonFlow {
|
|
|
634
642
|
const url = `${this.config.endpoint}/api/request`;
|
|
635
643
|
const headers = {
|
|
636
644
|
'Content-Type': 'application/json',
|
|
645
|
+
...this.getAuthHeaders(),
|
|
637
646
|
};
|
|
638
|
-
if (this.config.licenseKey) {
|
|
639
|
-
headers['X-License-Key'] = this.config.licenseKey;
|
|
640
|
-
}
|
|
641
647
|
// Use mapTimeout for MAP operations (default 2 minutes)
|
|
642
648
|
const response = await fetch(url, {
|
|
643
649
|
method: 'POST',
|
|
@@ -647,7 +653,7 @@ class AxonFlow {
|
|
|
647
653
|
});
|
|
648
654
|
if (!response.ok) {
|
|
649
655
|
const errorText = await response.text();
|
|
650
|
-
throw new
|
|
656
|
+
throw new errors_1.PlanExecutionError(`Plan execution failed: ${response.status} ${response.statusText} - ${errorText}`, planId, 'execution');
|
|
651
657
|
}
|
|
652
658
|
const agentResponse = await response.json();
|
|
653
659
|
if (this.config.debug) {
|
|
@@ -666,7 +672,7 @@ class AxonFlow {
|
|
|
666
672
|
* Get the status of a running or completed plan
|
|
667
673
|
*/
|
|
668
674
|
async getPlanStatus(planId) {
|
|
669
|
-
const url = `${this.config.endpoint}/api/
|
|
675
|
+
const url = `${this.config.endpoint}/api/v1/plan/${planId}`;
|
|
670
676
|
const response = await fetch(url, {
|
|
671
677
|
method: 'GET',
|
|
672
678
|
signal: AbortSignal.timeout(this.config.timeout),
|
|
@@ -749,15 +755,8 @@ class AxonFlow {
|
|
|
749
755
|
};
|
|
750
756
|
const headers = {
|
|
751
757
|
'Content-Type': 'application/json',
|
|
758
|
+
...this.getAuthHeaders(),
|
|
752
759
|
};
|
|
753
|
-
// Add auth headers only when credentials are provided
|
|
754
|
-
// Community/self-hosted mode works without credentials
|
|
755
|
-
if (this.config.licenseKey) {
|
|
756
|
-
headers['X-License-Key'] = this.config.licenseKey;
|
|
757
|
-
}
|
|
758
|
-
else if (this.config.apiKey) {
|
|
759
|
-
headers['X-Client-Secret'] = this.config.apiKey;
|
|
760
|
-
}
|
|
761
760
|
if (this.config.debug) {
|
|
762
761
|
(0, helpers_1.debugLog)('Gateway Mode: Pre-check', { query: options.query.substring(0, 50) });
|
|
763
762
|
}
|
|
@@ -848,15 +847,8 @@ class AxonFlow {
|
|
|
848
847
|
};
|
|
849
848
|
const headers = {
|
|
850
849
|
'Content-Type': 'application/json',
|
|
850
|
+
...this.getAuthHeaders(),
|
|
851
851
|
};
|
|
852
|
-
// Add auth headers only when credentials are provided
|
|
853
|
-
// Community/self-hosted mode works without credentials
|
|
854
|
-
if (this.config.licenseKey) {
|
|
855
|
-
headers['X-License-Key'] = this.config.licenseKey;
|
|
856
|
-
}
|
|
857
|
-
else if (this.config.apiKey) {
|
|
858
|
-
headers['X-Client-Secret'] = this.config.apiKey;
|
|
859
|
-
}
|
|
860
852
|
if (this.config.debug) {
|
|
861
853
|
(0, helpers_1.debugLog)('Gateway Mode: Audit', {
|
|
862
854
|
contextId: options.contextId,
|
|
@@ -1038,23 +1030,19 @@ class AxonFlow {
|
|
|
1038
1030
|
// Policy CRUD Methods - Static Policies
|
|
1039
1031
|
// ============================================================================
|
|
1040
1032
|
/**
|
|
1041
|
-
* Build authentication headers for API requests
|
|
1033
|
+
* Build authentication headers for API requests.
|
|
1034
|
+
* Includes Content-Type and X-Org-ID for policy APIs.
|
|
1035
|
+
* Uses getAuthHeaders() for authentication credentials.
|
|
1042
1036
|
*/
|
|
1043
1037
|
buildAuthHeaders() {
|
|
1044
1038
|
const headers = {
|
|
1045
1039
|
'Content-Type': 'application/json',
|
|
1040
|
+
...this.getAuthHeaders(),
|
|
1046
1041
|
};
|
|
1047
|
-
// Always include tenant ID for policy APIs
|
|
1042
|
+
// Always include tenant ID for policy APIs (X-Org-ID header for server compatibility)
|
|
1043
|
+
// Note: getAuthHeaders() already adds X-Tenant-ID when tenant is non-default
|
|
1048
1044
|
if (this.config.tenant) {
|
|
1049
|
-
headers['X-
|
|
1050
|
-
}
|
|
1051
|
-
// Add auth headers only when credentials are provided
|
|
1052
|
-
// Community/self-hosted mode works without credentials
|
|
1053
|
-
if (this.config.licenseKey) {
|
|
1054
|
-
headers['X-License-Key'] = this.config.licenseKey;
|
|
1055
|
-
}
|
|
1056
|
-
else if (this.config.apiKey) {
|
|
1057
|
-
headers['X-Client-Secret'] = this.config.apiKey;
|
|
1045
|
+
headers['X-Org-ID'] = this.config.tenant;
|
|
1058
1046
|
}
|
|
1059
1047
|
return headers;
|
|
1060
1048
|
}
|
|
@@ -1080,8 +1068,8 @@ class AxonFlow {
|
|
|
1080
1068
|
}
|
|
1081
1069
|
throw new errors_1.APIError(response.status, response.statusText, errorText);
|
|
1082
1070
|
}
|
|
1083
|
-
// Handle
|
|
1084
|
-
if (response.status === 204
|
|
1071
|
+
// Handle 204 No Content responses
|
|
1072
|
+
if (response.status === 204) {
|
|
1085
1073
|
return undefined;
|
|
1086
1074
|
}
|
|
1087
1075
|
return response.json();
|
|
@@ -1318,7 +1306,16 @@ class AxonFlow {
|
|
|
1318
1306
|
(0, helpers_1.debugLog)('Getting static policy versions', { id });
|
|
1319
1307
|
}
|
|
1320
1308
|
const response = await this.policyRequest('GET', `/api/v1/static-policies/${id}/versions`);
|
|
1321
|
-
|
|
1309
|
+
// Transform snake_case API response to camelCase
|
|
1310
|
+
return response.versions.map(v => ({
|
|
1311
|
+
version: v.version,
|
|
1312
|
+
changedBy: v.changed_by,
|
|
1313
|
+
changedAt: v.changed_at,
|
|
1314
|
+
changeType: v.change_type,
|
|
1315
|
+
changeDescription: v.change_description,
|
|
1316
|
+
previousValues: v.previous_values,
|
|
1317
|
+
newValues: v.new_values,
|
|
1318
|
+
}));
|
|
1322
1319
|
}
|
|
1323
1320
|
// ============================================================================
|
|
1324
1321
|
// Policy Override Methods (Enterprise)
|
|
@@ -1423,7 +1420,10 @@ class AxonFlow {
|
|
|
1423
1420
|
if (this.config.debug) {
|
|
1424
1421
|
(0, helpers_1.debugLog)('Listing dynamic policies', { options });
|
|
1425
1422
|
}
|
|
1426
|
-
|
|
1423
|
+
// API returns {"policies": [...]} wrapper via Agent proxy
|
|
1424
|
+
const response = await this.orchestratorRequest('GET', path);
|
|
1425
|
+
// Handle both wrapped and unwrapped responses for compatibility
|
|
1426
|
+
return Array.isArray(response) ? response : response.policies || [];
|
|
1427
1427
|
}
|
|
1428
1428
|
/**
|
|
1429
1429
|
* Get a specific dynamic policy by ID.
|
|
@@ -1435,7 +1435,10 @@ class AxonFlow {
|
|
|
1435
1435
|
if (this.config.debug) {
|
|
1436
1436
|
(0, helpers_1.debugLog)('Getting dynamic policy', { id });
|
|
1437
1437
|
}
|
|
1438
|
-
|
|
1438
|
+
// API returns {"policy": {...}} wrapper via Agent proxy
|
|
1439
|
+
const response = await this.orchestratorRequest('GET', `/api/v1/dynamic-policies/${id}`);
|
|
1440
|
+
// Handle both wrapped and unwrapped responses for compatibility
|
|
1441
|
+
return 'policy' in response ? response.policy : response;
|
|
1439
1442
|
}
|
|
1440
1443
|
/**
|
|
1441
1444
|
* Create a new dynamic policy.
|
|
@@ -1460,7 +1463,10 @@ class AxonFlow {
|
|
|
1460
1463
|
if (this.config.debug) {
|
|
1461
1464
|
(0, helpers_1.debugLog)('Creating dynamic policy', { name: policy.name });
|
|
1462
1465
|
}
|
|
1463
|
-
|
|
1466
|
+
// API returns {"policy": {...}} wrapper via Agent proxy
|
|
1467
|
+
const response = await this.orchestratorRequest('POST', '/api/v1/dynamic-policies', policy);
|
|
1468
|
+
// Handle both wrapped and unwrapped responses for compatibility
|
|
1469
|
+
return 'policy' in response ? response.policy : response;
|
|
1464
1470
|
}
|
|
1465
1471
|
/**
|
|
1466
1472
|
* Update an existing dynamic policy.
|
|
@@ -1473,7 +1479,10 @@ class AxonFlow {
|
|
|
1473
1479
|
if (this.config.debug) {
|
|
1474
1480
|
(0, helpers_1.debugLog)('Updating dynamic policy', { id, updates: Object.keys(policy) });
|
|
1475
1481
|
}
|
|
1476
|
-
|
|
1482
|
+
// API returns {"policy": {...}} wrapper via Agent proxy
|
|
1483
|
+
const response = await this.orchestratorRequest('PUT', `/api/v1/dynamic-policies/${id}`, policy);
|
|
1484
|
+
// Handle both wrapped and unwrapped responses for compatibility
|
|
1485
|
+
return 'policy' in response ? response.policy : response;
|
|
1477
1486
|
}
|
|
1478
1487
|
/**
|
|
1479
1488
|
* Delete a dynamic policy.
|
|
@@ -1497,9 +1506,10 @@ class AxonFlow {
|
|
|
1497
1506
|
if (this.config.debug) {
|
|
1498
1507
|
(0, helpers_1.debugLog)('Toggling dynamic policy', { id, enabled });
|
|
1499
1508
|
}
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1509
|
+
// API returns {"policy": {...}} wrapper via Agent proxy
|
|
1510
|
+
const response = await this.orchestratorRequest('PUT', `/api/v1/dynamic-policies/${id}`, { enabled });
|
|
1511
|
+
// Handle both wrapped and unwrapped responses for compatibility
|
|
1512
|
+
return 'policy' in response ? response.policy : response;
|
|
1503
1513
|
}
|
|
1504
1514
|
/**
|
|
1505
1515
|
* Get effective dynamic policies with tier inheritance applied.
|
|
@@ -1518,7 +1528,10 @@ class AxonFlow {
|
|
|
1518
1528
|
if (this.config.debug) {
|
|
1519
1529
|
(0, helpers_1.debugLog)('Getting effective dynamic policies', { options });
|
|
1520
1530
|
}
|
|
1521
|
-
|
|
1531
|
+
// API returns {"policies": [...]} wrapper via Agent proxy
|
|
1532
|
+
const response = await this.orchestratorRequest('GET', path);
|
|
1533
|
+
// Handle both wrapped and unwrapped responses for compatibility
|
|
1534
|
+
return Array.isArray(response) ? response : response.policies || [];
|
|
1522
1535
|
}
|
|
1523
1536
|
// ============================================================================
|
|
1524
1537
|
// Portal Authentication Methods (Enterprise)
|
|
@@ -1903,6 +1916,49 @@ class AxonFlow {
|
|
|
1903
1916
|
providerType: response.provider_type,
|
|
1904
1917
|
};
|
|
1905
1918
|
}
|
|
1919
|
+
/**
|
|
1920
|
+
* Close a PR without merging and optionally delete the branch.
|
|
1921
|
+
* Useful for cleaning up test PRs created by examples.
|
|
1922
|
+
*
|
|
1923
|
+
* @param prId - PR record ID
|
|
1924
|
+
* @param deleteBranch - Whether to delete the associated branch (default: true)
|
|
1925
|
+
* @returns Closed PR record
|
|
1926
|
+
*
|
|
1927
|
+
* @example
|
|
1928
|
+
* ```typescript
|
|
1929
|
+
* // Close PR and delete branch
|
|
1930
|
+
* const pr = await axonflow.closePR('pr_123');
|
|
1931
|
+
* console.log(`PR #${pr.prNumber} closed`);
|
|
1932
|
+
*
|
|
1933
|
+
* // Close PR but keep branch
|
|
1934
|
+
* const pr = await axonflow.closePR('pr_123', false);
|
|
1935
|
+
* ```
|
|
1936
|
+
*/
|
|
1937
|
+
async closePR(prId, deleteBranch = true) {
|
|
1938
|
+
if (this.config.debug) {
|
|
1939
|
+
(0, helpers_1.debugLog)('Closing PR', { prId, deleteBranch });
|
|
1940
|
+
}
|
|
1941
|
+
const query = deleteBranch ? '?delete_branch=true' : '';
|
|
1942
|
+
const response = await this.portalRequest('DELETE', `/api/v1/code-governance/prs/${prId}${query}`);
|
|
1943
|
+
return {
|
|
1944
|
+
id: response.id,
|
|
1945
|
+
prNumber: response.pr_number,
|
|
1946
|
+
prUrl: response.pr_url,
|
|
1947
|
+
title: response.title,
|
|
1948
|
+
state: response.state,
|
|
1949
|
+
owner: response.owner,
|
|
1950
|
+
repo: response.repo,
|
|
1951
|
+
headBranch: response.head_branch,
|
|
1952
|
+
baseBranch: response.base_branch,
|
|
1953
|
+
filesCount: response.files_count,
|
|
1954
|
+
secretsDetected: response.secrets_detected,
|
|
1955
|
+
unsafePatterns: response.unsafe_patterns,
|
|
1956
|
+
createdAt: response.created_at,
|
|
1957
|
+
closedAt: response.closed_at,
|
|
1958
|
+
createdBy: response.created_by,
|
|
1959
|
+
providerType: response.provider_type,
|
|
1960
|
+
};
|
|
1961
|
+
}
|
|
1906
1962
|
/**
|
|
1907
1963
|
* Sync PR status with the Git provider.
|
|
1908
1964
|
* This updates the local record with the current state from GitHub/GitLab/Bitbucket.
|
|
@@ -2096,8 +2152,8 @@ class AxonFlow {
|
|
|
2096
2152
|
}
|
|
2097
2153
|
throw new errors_1.APIError(response.status, response.statusText, errorText);
|
|
2098
2154
|
}
|
|
2099
|
-
// Handle
|
|
2100
|
-
if (response.status === 204
|
|
2155
|
+
// Handle 204 No Content responses
|
|
2156
|
+
if (response.status === 204) {
|
|
2101
2157
|
return undefined;
|
|
2102
2158
|
}
|
|
2103
2159
|
return response.json();
|
|
@@ -2140,8 +2196,8 @@ class AxonFlow {
|
|
|
2140
2196
|
}
|
|
2141
2197
|
throw new errors_1.APIError(response.status, response.statusText, errorText);
|
|
2142
2198
|
}
|
|
2143
|
-
// Handle
|
|
2144
|
-
if (response.status === 204
|
|
2199
|
+
// Handle 204 No Content responses
|
|
2200
|
+
if (response.status === 204) {
|
|
2145
2201
|
return undefined;
|
|
2146
2202
|
}
|
|
2147
2203
|
return response.json();
|