@aifabrix/builder 2.51.1 → 2.52.1
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/jest.isolated-projects.js +25 -2
- package/jest.projects.js +4 -1
- package/lib/api/datasources-extended.api.js +8 -8
- package/lib/api/keycloak.api.js +92 -0
- package/lib/api/token-providers.api.js +77 -0
- package/lib/api/types/keycloak.types.js +23 -0
- package/lib/api/types/token-providers.types.js +65 -0
- package/lib/app/down.js +16 -1
- package/lib/app/run-container-start.js +4 -0
- package/lib/app/run-deploy-job.js +135 -27
- package/lib/app/run-env-compose.js +32 -0
- package/lib/app/run-env-recovery.js +35 -0
- package/lib/app/run-helpers.js +5 -6
- package/lib/app/run.js +11 -3
- package/lib/channels/add-channel.js +126 -19
- package/lib/channels/approval-guides/chatgpt.js +12 -9
- package/lib/channels/approval-guides/microsoft-copilot.js +16 -12
- package/lib/channels/channel-add-ensure.js +128 -0
- package/lib/channels/channel-artifact-generator.js +11 -1
- package/lib/channels/channel-branding.js +94 -0
- package/lib/channels/channel-credential.js +8 -0
- package/lib/channels/channel-discovery.js +330 -0
- package/lib/channels/channel-external-system.js +1 -1
- package/lib/channels/channel-runtime-resolver.js +103 -14
- package/lib/channels/channel-status-display.js +7 -1
- package/lib/channels/channel-targets.js +18 -1
- package/lib/channels/chatgpt-runtime-contract.js +1 -1
- package/lib/channels/microsoft-copilot-channel-add.js +138 -0
- package/lib/channels/microsoft-copilot-entra-sso-form.js +180 -0
- package/lib/channels/microsoft-copilot-entra-sso.js +264 -0
- package/lib/channels/microsoft-copilot-icons.js +74 -0
- package/lib/channels/microsoft-copilot-limits.js +84 -0
- package/lib/channels/microsoft-copilot-package.js +130 -49
- package/lib/channels/microsoft-copilot-validate.js +197 -0
- package/lib/cli/index.js +2 -0
- package/lib/cli/infra-guided-footers.js +1 -1
- package/lib/cli/infra-guided-public-url-warn.js +55 -0
- package/lib/cli/infra-guided.js +78 -62
- package/lib/cli/setup-app.help.js +4 -0
- package/lib/cli/setup-app.test-commands.js +59 -28
- package/lib/cli/setup-external-system.js +50 -12
- package/lib/cli/setup-infra.js +31 -4
- package/lib/commands/channel-add-setup.js +35 -10
- package/lib/commands/channel.js +27 -12
- package/lib/commands/deploy-gate-orchestrator.js +3 -2
- package/lib/commands/governance-verify-external.js +2 -5
- package/lib/commands/integration-definition.js +158 -0
- package/lib/commands/lifecycle-external.js +14 -7
- package/lib/commands/repair-auth-apply.js +19 -5
- package/lib/commands/repair-datasource-sync-operations.js +4 -1
- package/lib/commands/role-assistant-test-output.js +200 -0
- package/lib/commands/role-assistant.js +131 -114
- package/lib/commands/test-governance-external.js +2 -5
- package/lib/commands/up-miso.js +61 -24
- package/lib/commands/upload-data-sync-finalize.js +20 -3
- package/lib/commands/verify-governance-external.js +2 -5
- package/lib/commands/verify-operations-external.js +2 -5
- package/lib/commands/verify-operations-step-plan.js +31 -0
- package/lib/commands/verify-trust-command-action.js +2 -5
- package/lib/datasource/capability/capability-resolve.js +15 -5
- package/lib/datasource/capability/copy-operations.js +14 -4
- package/lib/datasource/datasource-identifier.js +4 -3
- package/lib/datasource/integration-context.js +3 -3
- package/lib/datasource/resolve-app.js +90 -8
- package/lib/datasource/test-e2e.js +2 -2
- package/lib/datasource/unified-validation-run-body.js +15 -1
- package/lib/datasource/unified-validation-run-resolve.js +2 -2
- package/lib/external-system/deploy-helpers.js +9 -5
- package/lib/external-system/deploy.js +2 -1
- package/lib/external-system/test-system-level.js +21 -3
- package/lib/external-system/test.js +4 -4
- package/lib/generator/builders.js +9 -15
- package/lib/infrastructure/index.js +19 -4
- package/lib/integration-definition/apply.js +478 -0
- package/lib/integration-definition/canonical-json.js +51 -0
- package/lib/integration-definition/emit-suite-bid.js +94 -0
- package/lib/integration-definition/enrich-crm-field-mappings.js +240 -0
- package/lib/integration-definition/enrich-openapi-operations.js +434 -0
- package/lib/integration-definition/from-discovery.js +339 -0
- package/lib/integration-definition/hash.js +37 -0
- package/lib/integration-definition/index.js +37 -0
- package/lib/integration-definition/openapi-enrichment/hubspot-crm-companies.json +205 -0
- package/lib/integration-definition/resource-type-catalog.js +59 -0
- package/lib/integration-definition/system-kind-enum.js +40 -0
- package/lib/integration-definition/validate.js +148 -0
- package/lib/programmatic/builder-api-request.js +5 -1
- package/lib/programmatic/builder-help-governance.js +3 -2
- package/lib/programmatic/capability-registry.js +19 -0
- package/lib/programmatic/openapi-component-schemas.js +6 -1
- package/lib/programmatic/openapi-descriptions.js +40 -0
- package/lib/programmatic/openapi-envelope-examples.js +269 -0
- package/lib/programmatic/openapi-operation-bindings.js +45 -0
- package/lib/programmatic/openapi-request-schemas.js +14 -0
- package/lib/programmatic/openapi-result-schemas-overflow.js +101 -0
- package/lib/programmatic/openapi-result-schemas.js +46 -99
- package/lib/programmatic/openapi-schema-descriptions-core.js +7 -4
- package/lib/programmatic/openapi-schema-descriptions-help.js +1 -1
- package/lib/programmatic/openapi-schema-descriptions-operations.js +24 -0
- package/lib/programmatic/openapi-schema-helpers.js +9 -9
- package/lib/programmatic/openapi-spec.js +11 -1
- package/lib/programmatic/orchestration-openapi-meta.js +10 -0
- package/lib/programmatic/route-handler-map.js +29 -1
- package/lib/programmatic/run-channel-package.js +236 -0
- package/lib/programmatic/run-integration-definition.js +69 -0
- package/lib/role-assistant/knowledge-markdown-frontmatter.js +75 -0
- package/lib/role-assistant/knowledge-sync-logging.js +58 -0
- package/lib/role-assistant/knowledge-sync.js +104 -89
- package/lib/role-assistant/test-cases-bid.js +155 -0
- package/lib/role-assistant/test-cases-evaluate.js +9 -1
- package/lib/role-assistant/test-cases-honesty.js +24 -10
- package/lib/role-assistant/test-cases.js +28 -0
- package/lib/role-assistant/test-runner-bid-apply.js +122 -0
- package/lib/role-assistant/test-runner-bid-document.js +278 -0
- package/lib/role-assistant/test-runner-workhub-answers.js +289 -46
- package/lib/role-assistant/test-runner-workhub.js +121 -25
- package/lib/role-assistant/test-suite.js +119 -0
- package/lib/schema/application-schema.json +64 -32
- package/lib/schema/external-datasource.schema.json +103 -17
- package/lib/schema/external-system.schema.json +54 -3
- package/lib/schema/infra.parameter.yaml +0 -20
- package/lib/schema/integration-definition.schema.json +195 -0
- package/lib/utils/authentication-shape.js +6 -0
- package/lib/utils/certify-external-workspace.js +40 -0
- package/lib/utils/docker-build.js +3 -3
- package/lib/utils/docker-run-ephemeral.js +77 -17
- package/lib/utils/health-check-public-warn.js +31 -13
- package/lib/utils/health-check.js +11 -1
- package/lib/utils/help-builder.js +1 -0
- package/lib/utils/paths.js +13 -15
- package/lib/utils/promote-dev-docker-image.js +97 -18
- package/lib/utils/role-assistant-paths.js +76 -14
- package/lib/utils/transient-developer-id.js +28 -0
- package/lib/utils/upload-sync-options.js +7 -4
- package/lib/validation/reserved-system-key-prefixes.js +56 -0
- package/lib/validation/validate.js +54 -19
- package/package.json +1 -1
- package/scripts/pnpm/af.mjs +24 -9
- package/scripts/pnpm/help.mjs +1 -1
- package/templates/applications/builder-api/application.yaml +3 -3
- package/templates/applications/dataplane/application.yaml +5 -5
- package/templates/applications/dataplane/env.template +8 -7
- package/templates/applications/dataplane/rbac.yaml +10 -10
- package/templates/applications/keycloak/application.yaml +2 -2
- package/templates/applications/keycloak/env.template +5 -2
- package/templates/applications/miso-controller/application.yaml +25 -11
- package/templates/applications/miso-controller/env.template +24 -5
- package/templates/channels/README.md +11 -1
- package/templates/channels/brand/color-192.png +0 -0
- package/templates/channels/brand/dark/128.png +0 -0
- package/templates/channels/brand/dark/192.png +0 -0
- package/templates/channels/brand/dark/256.png +0 -0
- package/templates/channels/brand/dark/32.png +0 -0
- package/templates/channels/brand/dark/512.png +0 -0
- package/templates/channels/brand/dark/64.png +0 -0
- package/templates/channels/brand/light/128.png +0 -0
- package/templates/channels/brand/light/192.png +0 -0
- package/templates/channels/brand/light/256.png +0 -0
- package/templates/channels/brand/light/32.png +0 -0
- package/templates/channels/brand/light/512.png +0 -0
- package/templates/channels/brand/light/64.png +0 -0
- package/templates/channels/brand/mono-white/128.png +0 -0
- package/templates/channels/brand/mono-white/192.png +0 -0
- package/templates/channels/brand/mono-white/256.png +0 -0
- package/templates/channels/brand/mono-white/32.png +0 -0
- package/templates/channels/brand/mono-white/512.png +0 -0
- package/templates/channels/brand/mono-white/64.png +0 -0
- package/templates/channels/brand/outline-32.png +0 -0
- package/templates/channels/chatgpt/install.template.md.hbs +76 -36
- package/templates/channels/chatgpt/integration/README.md +4 -4
- package/templates/channels/chatgpt/integration/chatgpt-system.json +1 -16
- package/templates/channels/chatgpt/manifest.template.json.hbs +3 -3
- package/templates/channels/microsoft-copilot/ai-plugin.template.json.hbs +10 -16
- package/templates/channels/microsoft-copilot/declarative-agent.template.json.hbs +5 -3
- package/templates/channels/microsoft-copilot/entra-sso-registration.template.md.hbs +27 -0
- package/templates/channels/microsoft-copilot/install.template.md.hbs +39 -20
- package/templates/channels/microsoft-copilot/integration/README.md +2 -3
- package/templates/channels/microsoft-copilot/integration/microsoft-copilot-system.json +1 -22
- package/templates/channels/microsoft-copilot/manifest.template.json.hbs +7 -7
- package/templates/channels/microsoft-copilot/oauth-plugin-vault-required.template.md.hbs +11 -0
- package/templates/channels/slack/install.template.md.hbs +6 -1
- package/templates/channels/slack/integration/README.md +2 -4
- package/templates/channels/teams-bot/install.template.md.hbs +4 -0
- package/templates/channels/teams-bot/integration/README.md +3 -5
- package/templates/channels/web-embed/integration/web-embed-system.json +1 -16
- package/templates/python/docker-compose.hbs +10 -0
- package/templates/typescript/docker-compose.hbs +10 -0
- /package/.cursor/plans/{Done → Archive}/157.1-security-quality-violations-by-type.csv +0 -0
|
@@ -12,8 +12,6 @@ const path = require('path');
|
|
|
12
12
|
const crypto = require('crypto');
|
|
13
13
|
const fs = require('../internal/fs-real-sync');
|
|
14
14
|
const yaml = require('js-yaml');
|
|
15
|
-
const logger = require('../utils/logger');
|
|
16
|
-
const { formatSuccessLine, formatWarningLine, metadata } = require('../utils/cli-test-layout-chalk');
|
|
17
15
|
const { listDocuments, validateDocuments, bulkDocuments } = require('../api/datasources-extended.api');
|
|
18
16
|
const {
|
|
19
17
|
extractDocumentStorageKeyFromAssistantDetails,
|
|
@@ -28,6 +26,15 @@ const {
|
|
|
28
26
|
resolveDocumentStorageKeyFromRoleAssistantSettings,
|
|
29
27
|
resolveRoleAssistantEnvironmentSettings
|
|
30
28
|
} = require('./settings');
|
|
29
|
+
const {
|
|
30
|
+
knowledgeSearchMetadataFromFrontmatter,
|
|
31
|
+
splitMarkdownFrontmatter
|
|
32
|
+
} = require('./knowledge-markdown-frontmatter');
|
|
33
|
+
const {
|
|
34
|
+
logKnowledgeImportSummary,
|
|
35
|
+
logDocumentStorageSettingsPushSummary,
|
|
36
|
+
logKnowledgeExportSummary
|
|
37
|
+
} = require('./knowledge-sync-logging');
|
|
31
38
|
|
|
32
39
|
function resolveSystemNode(input) {
|
|
33
40
|
if (!input || typeof input !== 'object') {
|
|
@@ -76,44 +83,91 @@ async function resolveDocumentStorageKeyFromDataplane(dataplaneUrl, authConfig,
|
|
|
76
83
|
}
|
|
77
84
|
|
|
78
85
|
/**
|
|
79
|
-
*
|
|
86
|
+
* Map role-assistant.yaml debug.* → Assistants settings PATCH fields.
|
|
87
|
+
* includePromptTrace → fullDebugEnabled (LLM prompt capture gate).
|
|
88
|
+
* enabled → debugEnabled (runtime debug traces).
|
|
89
|
+
* @param {Object|null|undefined} debugSection
|
|
90
|
+
* @returns {{ debugEnabled?: boolean, fullDebugEnabled?: boolean }}
|
|
91
|
+
*/
|
|
92
|
+
function mapRoleAssistantDebugToAssistantsSettings(debugSection) {
|
|
93
|
+
if (!debugSection || typeof debugSection !== 'object') {
|
|
94
|
+
return {};
|
|
95
|
+
}
|
|
96
|
+
const body = {};
|
|
97
|
+
if (typeof debugSection.enabled === 'boolean') {
|
|
98
|
+
body.debugEnabled = debugSection.enabled;
|
|
99
|
+
}
|
|
100
|
+
if (typeof debugSection.includePromptTrace === 'boolean') {
|
|
101
|
+
body.fullDebugEnabled = debugSection.includePromptTrace;
|
|
102
|
+
}
|
|
103
|
+
return body;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Push role-assistant.yaml knowledge + debug settings to dataplane Assistants.
|
|
80
108
|
* Called on upload/deploy so the operator UI and CLI stay aligned.
|
|
81
109
|
*/
|
|
82
|
-
|
|
110
|
+
function resolveAssistantSettingsPush(params) {
|
|
83
111
|
const {
|
|
84
112
|
systemKey,
|
|
85
|
-
dataplaneUrl,
|
|
86
|
-
authConfig,
|
|
87
113
|
environment = 'dev',
|
|
88
|
-
pathOptions = {}
|
|
89
|
-
dryRun = false
|
|
114
|
+
pathOptions = {}
|
|
90
115
|
} = params;
|
|
91
116
|
const settingsEnv = resolveRoleAssistantSettingsEnvKey(environment);
|
|
92
117
|
const settings = readRoleAssistantSettings(systemKey, { required: false, pathOptions });
|
|
93
118
|
if (!settings) {
|
|
94
|
-
return { skipped: true, reason: 'missing-role-assistant-settings' };
|
|
119
|
+
return { result: { skipped: true, reason: 'missing-role-assistant-settings' } };
|
|
95
120
|
}
|
|
96
121
|
const section = resolveRoleAssistantEnvironmentSettings(settings, settingsEnv, {
|
|
97
122
|
required: false
|
|
98
123
|
});
|
|
99
124
|
if (!section) {
|
|
100
|
-
return { skipped: true, reason: 'missing-env-settings' };
|
|
125
|
+
return { result: { skipped: true, reason: 'missing-env-settings' } };
|
|
101
126
|
}
|
|
102
127
|
const documentStorageKey =
|
|
103
128
|
resolveDocumentStorageKeyFromRoleAssistantSettings(settings, settingsEnv) || '';
|
|
104
|
-
|
|
129
|
+
const debugBody = mapRoleAssistantDebugToAssistantsSettings(section.debug);
|
|
130
|
+
if (!documentStorageKey && Object.keys(debugBody).length === 0) {
|
|
131
|
+
return { result: { skipped: true, reason: 'no-document-storage-key', documentStorageKey: null } };
|
|
132
|
+
}
|
|
133
|
+
const patchBody = { ...debugBody };
|
|
134
|
+
if (documentStorageKey) {
|
|
135
|
+
patchBody.documentStorageKey = documentStorageKey;
|
|
136
|
+
}
|
|
137
|
+
return { documentStorageKey, debugBody, patchBody };
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async function applyAssistantSettingsPush(dataplaneUrl, systemKey, authConfig, settingsPush) {
|
|
141
|
+
const { documentStorageKey, debugBody, patchBody } = settingsPush;
|
|
142
|
+
const hasDocumentStorageKey = documentStorageKey !== '';
|
|
143
|
+
const hasDebugSettings = Object.keys(debugBody).length > 0;
|
|
144
|
+
let response = await updateAssistantSettings(
|
|
145
|
+
dataplaneUrl,
|
|
146
|
+
systemKey,
|
|
147
|
+
authConfig,
|
|
148
|
+
patchBody
|
|
149
|
+
);
|
|
150
|
+
if (response && response.success === false && hasDocumentStorageKey && hasDebugSettings) {
|
|
151
|
+
response = await updateAssistantSettings(
|
|
152
|
+
dataplaneUrl,
|
|
153
|
+
systemKey,
|
|
154
|
+
authConfig,
|
|
155
|
+
debugBody
|
|
156
|
+
);
|
|
157
|
+
if (response && response.success === false) {
|
|
158
|
+
throw new Error(
|
|
159
|
+
response.formattedError ||
|
|
160
|
+
response.error ||
|
|
161
|
+
'Failed to update Assistants debug settings'
|
|
162
|
+
);
|
|
163
|
+
}
|
|
105
164
|
return {
|
|
106
165
|
skipped: false,
|
|
107
|
-
|
|
108
|
-
|
|
166
|
+
documentStorageKey: null,
|
|
167
|
+
documentStoragePushFailed: true,
|
|
168
|
+
...debugBody
|
|
109
169
|
};
|
|
110
170
|
}
|
|
111
|
-
if (!dataplaneUrl || !authConfig) {
|
|
112
|
-
return { skipped: true, reason: 'missing-dataplane-auth' };
|
|
113
|
-
}
|
|
114
|
-
const response = await updateAssistantSettings(dataplaneUrl, systemKey, authConfig, {
|
|
115
|
-
documentStorageKey
|
|
116
|
-
});
|
|
117
171
|
if (response && response.success === false) {
|
|
118
172
|
throw new Error(
|
|
119
173
|
response.formattedError ||
|
|
@@ -123,10 +177,27 @@ async function pushRoleAssistantDocumentStorageSettings(params) {
|
|
|
123
177
|
}
|
|
124
178
|
return {
|
|
125
179
|
skipped: false,
|
|
126
|
-
documentStorageKey: documentStorageKey || null
|
|
180
|
+
documentStorageKey: documentStorageKey || null,
|
|
181
|
+
...debugBody
|
|
127
182
|
};
|
|
128
183
|
}
|
|
129
184
|
|
|
185
|
+
async function pushRoleAssistantDocumentStorageSettings(params) {
|
|
186
|
+
const { systemKey, dataplaneUrl, authConfig, dryRun = false } = params;
|
|
187
|
+
const settingsPush = resolveAssistantSettingsPush(params);
|
|
188
|
+
if (settingsPush.result) {
|
|
189
|
+
return settingsPush.result;
|
|
190
|
+
}
|
|
191
|
+
const { documentStorageKey, debugBody } = settingsPush;
|
|
192
|
+
if (dryRun) {
|
|
193
|
+
return { skipped: false, dryRun: true, documentStorageKey: documentStorageKey || null, ...debugBody };
|
|
194
|
+
}
|
|
195
|
+
if (!dataplaneUrl || !authConfig) {
|
|
196
|
+
return { skipped: true, reason: 'missing-dataplane-auth' };
|
|
197
|
+
}
|
|
198
|
+
return applyAssistantSettingsPush(dataplaneUrl, systemKey, authConfig, settingsPush);
|
|
199
|
+
}
|
|
200
|
+
|
|
130
201
|
/**
|
|
131
202
|
* Resolve Knowledge document storage key.
|
|
132
203
|
* Order: role-assistant.yaml → dataplane Assistants settings → package dataSources.
|
|
@@ -182,20 +253,27 @@ function normalizeDocumentExternalId(knowledgeRoot, filePath) {
|
|
|
182
253
|
}
|
|
183
254
|
|
|
184
255
|
function buildDocumentRecord(knowledgeRoot, filePath) {
|
|
185
|
-
const
|
|
256
|
+
const raw = fs.readFileSync(filePath, 'utf8');
|
|
257
|
+
const { frontmatter, body } = splitMarkdownFrontmatter(raw);
|
|
258
|
+
const searchMeta = knowledgeSearchMetadataFromFrontmatter(frontmatter);
|
|
186
259
|
const externalId = normalizeDocumentExternalId(knowledgeRoot, filePath);
|
|
187
|
-
const title =
|
|
260
|
+
const title =
|
|
261
|
+
(typeof searchMeta.title === 'string' && searchMeta.title) || path.basename(externalId);
|
|
262
|
+
const content = typeof body === 'string' ? body : raw;
|
|
188
263
|
const contentHash = crypto.createHash('sha256').update(content, 'utf8').digest('hex');
|
|
189
264
|
const metadata = {
|
|
190
265
|
externalId,
|
|
191
|
-
title,
|
|
192
266
|
mimeType: 'text/markdown',
|
|
193
267
|
sourcePath: path.relative(knowledgeRoot, filePath).replace(/\\/g, '/'),
|
|
194
|
-
sourceType: 'role-assistant-markdown'
|
|
268
|
+
sourceType: 'role-assistant-markdown',
|
|
269
|
+
...searchMeta,
|
|
270
|
+
title
|
|
195
271
|
};
|
|
196
272
|
return {
|
|
197
273
|
key: externalId,
|
|
198
|
-
|
|
274
|
+
// Prefer sourcePath (*.md) so binary storage uses a known markdown extension
|
|
275
|
+
// instead of inventing ".guide" from path-like keys or titles.
|
|
276
|
+
name: metadata.sourcePath || `${externalId}.md`,
|
|
199
277
|
contentHash,
|
|
200
278
|
metadata,
|
|
201
279
|
binaryBase64: Buffer.from(content, 'utf8').toString('base64'),
|
|
@@ -388,74 +466,11 @@ async function exportRoleAssistantKnowledge(params) {
|
|
|
388
466
|
return { skipped: false, datasourceKey, count: rows.length, knowledgePath, settingsPath };
|
|
389
467
|
}
|
|
390
468
|
|
|
391
|
-
function logKnowledgeImportSummary(systemKey, result, options = {}) {
|
|
392
|
-
if (result.skipped) {
|
|
393
|
-
if (options.verbose === true) {
|
|
394
|
-
logger.log(metadata(`Knowledge sync skipped (${systemKey}): ${result.reason}`));
|
|
395
|
-
}
|
|
396
|
-
return;
|
|
397
|
-
}
|
|
398
|
-
if (result.dryRun) {
|
|
399
|
-
logger.log(
|
|
400
|
-
formatWarningLine(
|
|
401
|
-
`Role assistant knowledge dry-run: ${result.fileCount} file(s), ${result.recordCount} record(s), datasource ${result.datasourceKey}`
|
|
402
|
-
)
|
|
403
|
-
);
|
|
404
|
-
return;
|
|
405
|
-
}
|
|
406
|
-
logger.log(
|
|
407
|
-
formatSuccessLine(
|
|
408
|
-
`Role assistant knowledge synced (${result.datasourceKey}): ${result.recordCount} record(s) from ${result.fileCount} file(s).`
|
|
409
|
-
)
|
|
410
|
-
);
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
function logDocumentStorageSettingsPushSummary(systemKey, result, options = {}) {
|
|
414
|
-
if (result.skipped) {
|
|
415
|
-
if (options.verbose === true) {
|
|
416
|
-
logger.log(
|
|
417
|
-
metadata(`Knowledge document storage settings skipped (${systemKey}): ${result.reason}`)
|
|
418
|
-
);
|
|
419
|
-
}
|
|
420
|
-
return;
|
|
421
|
-
}
|
|
422
|
-
if (result.dryRun) {
|
|
423
|
-
logger.log(
|
|
424
|
-
formatWarningLine(
|
|
425
|
-
`Knowledge document storage settings dry-run (${systemKey}): ${
|
|
426
|
-
result.documentStorageKey || '(clear)'
|
|
427
|
-
}`
|
|
428
|
-
)
|
|
429
|
-
);
|
|
430
|
-
return;
|
|
431
|
-
}
|
|
432
|
-
logger.log(
|
|
433
|
-
formatSuccessLine(
|
|
434
|
-
`Knowledge document storage settings updated (${systemKey}): ${
|
|
435
|
-
result.documentStorageKey || '(cleared)'
|
|
436
|
-
}`
|
|
437
|
-
)
|
|
438
|
-
);
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
function logKnowledgeExportSummary(systemKey, result, options = {}) {
|
|
442
|
-
if (result.skipped) {
|
|
443
|
-
if (options.verbose === true) {
|
|
444
|
-
logger.log(metadata(`Knowledge export skipped (${systemKey}): ${result.reason}`));
|
|
445
|
-
}
|
|
446
|
-
return;
|
|
447
|
-
}
|
|
448
|
-
logger.log(
|
|
449
|
-
formatSuccessLine(
|
|
450
|
-
`Role assistant knowledge exported (${result.datasourceKey}): ${result.count} document(s) to ${result.knowledgePath}.`
|
|
451
|
-
)
|
|
452
|
-
);
|
|
453
|
-
}
|
|
454
|
-
|
|
455
469
|
module.exports = {
|
|
456
470
|
isDigitalWorkerModel,
|
|
457
471
|
resolveRoleAssistantSettingsEnvKey,
|
|
458
472
|
resolveRoleAssistantDocumentStorageKey,
|
|
473
|
+
mapRoleAssistantDebugToAssistantsSettings,
|
|
459
474
|
pushRoleAssistantDocumentStorageSettings,
|
|
460
475
|
importRoleAssistantKnowledge,
|
|
461
476
|
exportRoleAssistantKnowledge,
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Evaluate expected.bid assertions for suite 002 hard GP.
|
|
3
|
+
* @fileoverview BID emission / apply expectation checks
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
function asArray(value) {
|
|
9
|
+
return Array.isArray(value) ? value : [];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function softWrap(assertion, soft) {
|
|
13
|
+
if (!assertion || assertion.passed || !soft) {
|
|
14
|
+
return assertion;
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
...assertion,
|
|
18
|
+
passed: true,
|
|
19
|
+
soft: true,
|
|
20
|
+
warn: true,
|
|
21
|
+
message: `${assertion.message} (soft — warning only)`
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function findInteraction(interactions, type) {
|
|
26
|
+
return asArray(interactions).find((row) => row && row.type === type) || null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function pushBidAssertion(assertions, soft, id, passed, okMsg, failMsg) {
|
|
30
|
+
assertions.push(
|
|
31
|
+
softWrap(
|
|
32
|
+
{
|
|
33
|
+
id,
|
|
34
|
+
passed,
|
|
35
|
+
message: passed ? okMsg : failMsg
|
|
36
|
+
},
|
|
37
|
+
soft
|
|
38
|
+
)
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function hasEmitOrApply(observed) {
|
|
43
|
+
return Boolean(observed.emitRow || observed.applyRow || observed.emitted);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function collectBidSchemaAssertions(expectedBid, observed, assertions, soft) {
|
|
47
|
+
const { emitRow, applyRow, emitted } = observed;
|
|
48
|
+
if (expectedBid.schemaName) {
|
|
49
|
+
const actualSchema = (emitted && emitted.schemaName) || expectedBid.schemaName;
|
|
50
|
+
pushBidAssertion(
|
|
51
|
+
assertions,
|
|
52
|
+
soft,
|
|
53
|
+
'expected.bid.schemaName',
|
|
54
|
+
hasEmitOrApply(observed) && actualSchema === expectedBid.schemaName,
|
|
55
|
+
`BID schemaName observed (${expectedBid.schemaName}).`,
|
|
56
|
+
`BID schemaName "${expectedBid.schemaName}" not observed in suite emit/apply.`
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
if (expectedBid.schemaVersion) {
|
|
60
|
+
const version = emitted && emitted.schemaVersion;
|
|
61
|
+
const versionOk =
|
|
62
|
+
version === null || version === undefined || version === expectedBid.schemaVersion;
|
|
63
|
+
pushBidAssertion(
|
|
64
|
+
assertions,
|
|
65
|
+
soft,
|
|
66
|
+
'expected.bid.schemaVersion',
|
|
67
|
+
hasEmitOrApply({ emitRow, applyRow, emitted }) && versionOk,
|
|
68
|
+
`BID schemaVersion "${expectedBid.schemaVersion}" accepted.`,
|
|
69
|
+
`BID schemaVersion "${expectedBid.schemaVersion}" not observed.`
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function assertDefinitionHash(expectedBid, observed, assertions, soft) {
|
|
75
|
+
if (expectedBid.requireDefinitionHash !== true) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const { emitRow, applyRow, emitted } = observed;
|
|
79
|
+
const hash =
|
|
80
|
+
(emitted && emitted.definitionHash) ||
|
|
81
|
+
(emitRow && emitRow.definitionHash) ||
|
|
82
|
+
(applyRow && applyRow.definitionHash) ||
|
|
83
|
+
'';
|
|
84
|
+
pushBidAssertion(
|
|
85
|
+
assertions,
|
|
86
|
+
soft,
|
|
87
|
+
'expected.bid.requireDefinitionHash',
|
|
88
|
+
typeof hash === 'string' && hash.startsWith('sha256:'),
|
|
89
|
+
`BID definitionHash present (${String(hash).slice(0, 18)}…).`,
|
|
90
|
+
'BID definitionHash (sha256:…) not observed on emit/apply.'
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function assertSuiteRunId(expectedBid, observed, assertions, soft) {
|
|
95
|
+
if (expectedBid.requireSuiteRunId !== true) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const { emitRow, applyRow, emitted } = observed;
|
|
99
|
+
const suiteRunId =
|
|
100
|
+
(emitted && emitted.meta && emitted.meta.suiteRunId) ||
|
|
101
|
+
(emitRow && emitRow.suiteRunId) ||
|
|
102
|
+
(applyRow && applyRow.suiteRunId) ||
|
|
103
|
+
'';
|
|
104
|
+
pushBidAssertion(
|
|
105
|
+
assertions,
|
|
106
|
+
soft,
|
|
107
|
+
'expected.bid.requireSuiteRunId',
|
|
108
|
+
Boolean(String(suiteRunId).trim()),
|
|
109
|
+
`BID suiteRunId present (${suiteRunId}).`,
|
|
110
|
+
'BID meta.suiteRunId not observed on emit/apply.'
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function collectBidProvenanceAssertions(expectedBid, observed, assertions, soft) {
|
|
115
|
+
assertDefinitionHash(expectedBid, observed, assertions, soft);
|
|
116
|
+
assertSuiteRunId(expectedBid, observed, assertions, soft);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function collectBidPathAssertions(expectedBid, observed, assertions, soft) {
|
|
120
|
+
if (expectedBid.forbidGoldPaths === true) {
|
|
121
|
+
const { emitRow, applyRow, emitted } = observed;
|
|
122
|
+
const blob = JSON.stringify(emitted || emitRow || applyRow || {});
|
|
123
|
+
const banned = /test-e2e-hubspot|knownPlatform|gold-package/i.test(blob);
|
|
124
|
+
pushBidAssertion(
|
|
125
|
+
assertions,
|
|
126
|
+
soft,
|
|
127
|
+
'expected.bid.forbidGoldPaths',
|
|
128
|
+
!banned,
|
|
129
|
+
'BID trail has no gold/knownPlatform generation paths.',
|
|
130
|
+
'BID trail references forbidden gold/knownPlatform generation paths.'
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function collectBidAssertions(expectedBid, observation, options = {}) {
|
|
136
|
+
if (!expectedBid || typeof expectedBid !== 'object') {
|
|
137
|
+
return [];
|
|
138
|
+
}
|
|
139
|
+
const interactions = asArray(observation.interactions || observation.workInteractions);
|
|
140
|
+
const observed = {
|
|
141
|
+
emitRow: findInteraction(interactions, 'bid-emit'),
|
|
142
|
+
applyRow: findInteraction(interactions, 'bid-apply'),
|
|
143
|
+
emitted: observation.emittedBid || null
|
|
144
|
+
};
|
|
145
|
+
const assertions = [];
|
|
146
|
+
const soft = options.soft === true;
|
|
147
|
+
collectBidSchemaAssertions(expectedBid, observed, assertions, soft);
|
|
148
|
+
collectBidProvenanceAssertions(expectedBid, observed, assertions, soft);
|
|
149
|
+
collectBidPathAssertions(expectedBid, observed, assertions, soft);
|
|
150
|
+
return assertions;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
module.exports = {
|
|
154
|
+
collectBidAssertions
|
|
155
|
+
};
|
|
@@ -9,6 +9,7 @@ const {
|
|
|
9
9
|
buildHonestyObservation,
|
|
10
10
|
evaluateHonestyExpectations
|
|
11
11
|
} = require('./test-cases-honesty');
|
|
12
|
+
const { collectBidAssertions } = require('./test-cases-bid');
|
|
12
13
|
|
|
13
14
|
function getValueAtPath(obj, dottedPath) {
|
|
14
15
|
const parts = String(dottedPath || '').split('.').filter(Boolean);
|
|
@@ -109,7 +110,13 @@ function buildCaseObservation(result, lifecycleVerdict, portalUrl) {
|
|
|
109
110
|
processExecutionId: result?.processExecutionId || null,
|
|
110
111
|
workResult,
|
|
111
112
|
workResultError: result?.workResultError || null,
|
|
112
|
-
honesty: buildHonestyObservation(workResult)
|
|
113
|
+
honesty: buildHonestyObservation(workResult),
|
|
114
|
+
interactions: Array.isArray(result?.interactions)
|
|
115
|
+
? result.interactions
|
|
116
|
+
: Array.isArray(result?.workInteractions)
|
|
117
|
+
? result.workInteractions
|
|
118
|
+
: [],
|
|
119
|
+
emittedBid: result?.emittedBid || null
|
|
113
120
|
};
|
|
114
121
|
}
|
|
115
122
|
|
|
@@ -146,6 +153,7 @@ function collectCaseAssertions(expected, observation) {
|
|
|
146
153
|
assertions.push(...evaluateFactExpectations(expected.facts, observation));
|
|
147
154
|
assertions.push(...evaluateProhibitedExpectations(expected.prohibited, observation));
|
|
148
155
|
assertions.push(...evaluateHonestyExpectations(expected.honesty, observation, { soft }));
|
|
156
|
+
assertions.push(...collectBidAssertions(expected.bid, observation, { soft }));
|
|
149
157
|
return assertions;
|
|
150
158
|
}
|
|
151
159
|
|
|
@@ -68,7 +68,18 @@ function buildHonestyObservation(workResult) {
|
|
|
68
68
|
};
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
function pushHonestyAssertion(assertions, id, passed, message) {
|
|
71
|
+
function pushHonestyAssertion(assertions, id, passed, message, options = {}) {
|
|
72
|
+
const soft = options.soft === true;
|
|
73
|
+
if (soft && !passed) {
|
|
74
|
+
assertions.push({
|
|
75
|
+
id,
|
|
76
|
+
passed: true,
|
|
77
|
+
soft: true,
|
|
78
|
+
warn: true,
|
|
79
|
+
message: `${message} (soft — warning only)`
|
|
80
|
+
});
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
72
83
|
assertions.push({ id, passed, message });
|
|
73
84
|
}
|
|
74
85
|
|
|
@@ -87,7 +98,7 @@ function assertWorkResultPresent(assertions, honesty, observation) {
|
|
|
87
98
|
);
|
|
88
99
|
}
|
|
89
100
|
|
|
90
|
-
function assertSchemaVersion(assertions, honestySpec, honesty) {
|
|
101
|
+
function assertSchemaVersion(assertions, honestySpec, honesty, soft) {
|
|
91
102
|
if (!honestySpec.schemaVersion) {
|
|
92
103
|
return;
|
|
93
104
|
}
|
|
@@ -99,11 +110,12 @@ function assertSchemaVersion(assertions, honestySpec, honesty) {
|
|
|
99
110
|
passed,
|
|
100
111
|
passed
|
|
101
112
|
? `schemaVersion matched "${expected}".`
|
|
102
|
-
: `schemaVersion expected "${expected}" but got ${JSON.stringify(honesty.schemaVersion)}
|
|
113
|
+
: `schemaVersion expected "${expected}" but got ${JSON.stringify(honesty.schemaVersion)}.`,
|
|
114
|
+
{ soft }
|
|
103
115
|
);
|
|
104
116
|
}
|
|
105
117
|
|
|
106
|
-
function assertCompletion(assertions, honestySpec, honesty) {
|
|
118
|
+
function assertCompletion(assertions, honestySpec, honesty, soft) {
|
|
107
119
|
if (honestySpec.requireCompletion === false) {
|
|
108
120
|
return;
|
|
109
121
|
}
|
|
@@ -115,11 +127,12 @@ function assertCompletion(assertions, honestySpec, honesty) {
|
|
|
115
127
|
stateOk && goalOk,
|
|
116
128
|
stateOk && goalOk
|
|
117
129
|
? `completion.state/goalStatus honest (${honesty.completionState}/${honesty.goalStatus}).`
|
|
118
|
-
: `completion missing or invalid: state=${JSON.stringify(honesty.completionState)} goalStatus=${JSON.stringify(honesty.goalStatus)}
|
|
130
|
+
: `completion missing or invalid: state=${JSON.stringify(honesty.completionState)} goalStatus=${JSON.stringify(honesty.goalStatus)}.`,
|
|
131
|
+
{ soft }
|
|
119
132
|
);
|
|
120
133
|
}
|
|
121
134
|
|
|
122
|
-
function assertContribution(assertions, honestySpec, honesty) {
|
|
135
|
+
function assertContribution(assertions, honestySpec, honesty, soft) {
|
|
123
136
|
if (honestySpec.requireContributionObservation === false) {
|
|
124
137
|
return;
|
|
125
138
|
}
|
|
@@ -130,7 +143,8 @@ function assertContribution(assertions, honestySpec, honesty) {
|
|
|
130
143
|
ok,
|
|
131
144
|
ok
|
|
132
145
|
? `contributionObservation.status honest (${honesty.contributionStatus}).`
|
|
133
|
-
: `contributionObservation.status missing or invalid: ${JSON.stringify(honesty.contributionStatus)}
|
|
146
|
+
: `contributionObservation.status missing or invalid: ${JSON.stringify(honesty.contributionStatus)}.`,
|
|
147
|
+
{ soft }
|
|
134
148
|
);
|
|
135
149
|
}
|
|
136
150
|
|
|
@@ -171,9 +185,9 @@ function evaluateHonestyExpectations(honestySpec, observation, options = {}) {
|
|
|
171
185
|
// Missing Output is always a hard failure when required — soft does not waive it.
|
|
172
186
|
return assertions;
|
|
173
187
|
}
|
|
174
|
-
assertSchemaVersion(assertions, honestySpec, honesty);
|
|
175
|
-
assertCompletion(assertions, honestySpec, honesty);
|
|
176
|
-
assertContribution(assertions, honestySpec, honesty);
|
|
188
|
+
assertSchemaVersion(assertions, honestySpec, honesty, soft);
|
|
189
|
+
assertCompletion(assertions, honestySpec, honesty, soft);
|
|
190
|
+
assertContribution(assertions, honestySpec, honesty, soft);
|
|
177
191
|
assertMinResourceChanges(assertions, honestySpec, honesty, soft);
|
|
178
192
|
return assertions;
|
|
179
193
|
}
|
|
@@ -331,6 +331,32 @@ function collectCapabilitiesFromWorkSteps(out, steps) {
|
|
|
331
331
|
}
|
|
332
332
|
}
|
|
333
333
|
|
|
334
|
+
/**
|
|
335
|
+
* Work-result artifactIndex often carries CIP fingerprints like
|
|
336
|
+
* `capabilityKey=customer.createBasic|operationId=createbasic` when steps[] is empty.
|
|
337
|
+
* @param {Set<string>} out
|
|
338
|
+
* @param {unknown} artifacts
|
|
339
|
+
*/
|
|
340
|
+
function collectCapabilitiesFromArtifactIndex(out, artifacts) {
|
|
341
|
+
if (!Array.isArray(artifacts)) return;
|
|
342
|
+
for (const row of artifacts) {
|
|
343
|
+
if (!row || typeof row !== 'object') continue;
|
|
344
|
+
addCapabilityToken(out, row.capabilityKey);
|
|
345
|
+
addCapabilityToken(out, row.capability);
|
|
346
|
+
const fingerprint = typeof row.fingerprint === 'string' ? row.fingerprint : '';
|
|
347
|
+
const match = fingerprint.match(/(?:^|[|,])capabilityKey=([^|,]+)/);
|
|
348
|
+
if (match) {
|
|
349
|
+
addCapabilityToken(out, match[1]);
|
|
350
|
+
}
|
|
351
|
+
const artifactRef = typeof row.artifactRef === 'string' ? row.artifactRef : '';
|
|
352
|
+
// cip-log:fallback:customer.create:create:<id>
|
|
353
|
+
const refMatch = artifactRef.match(/^cip-log:[^:]+:([^:]+):/);
|
|
354
|
+
if (refMatch) {
|
|
355
|
+
addCapabilityToken(out, refMatch[1]);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
334
360
|
function collectObservedCapabilities(result) {
|
|
335
361
|
const out = new Set();
|
|
336
362
|
const steps = Array.isArray(result?.stepsRun) ? result.stepsRun : [];
|
|
@@ -341,6 +367,8 @@ function collectObservedCapabilities(result) {
|
|
|
341
367
|
}
|
|
342
368
|
collectCapabilitiesFromWorkSteps(out, result?.steps);
|
|
343
369
|
collectCapabilitiesFromWorkSteps(out, result?.workResult?.steps);
|
|
370
|
+
collectCapabilitiesFromArtifactIndex(out, result?.workResult?.artifactIndex);
|
|
371
|
+
collectCapabilitiesFromArtifactIndex(out, result?.artifactIndex);
|
|
344
372
|
addCapabilityToken(out, result?.task?.capabilityKey);
|
|
345
373
|
addCapabilityToken(out, result?.task?.capability);
|
|
346
374
|
if (result?.task?.approvalContext && typeof result.task.approvalContext === 'object') {
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Soft-loop BID apply after workspace.createsystem (suite 002 / plan 512.4).
|
|
3
|
+
* @fileoverview Apply input.bidPath into builder-api workspace when Runtime COM
|
|
4
|
+
* cannot yet invoke template.applyintegrationdefinition (RA facade not refreshed).
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const fs = require('../internal/fs-real-sync');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const {
|
|
12
|
+
loadCaseBidDocument,
|
|
13
|
+
resolveTargetSystemKey
|
|
14
|
+
} = require('./test-runner-bid-document');
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @returns {string}
|
|
18
|
+
*/
|
|
19
|
+
function resolveBuilderApiBaseUrl() {
|
|
20
|
+
const fromEnv = String(process.env.BUILDER_API_URL || process.env.BUILDER_URL || '').trim();
|
|
21
|
+
if (fromEnv) {
|
|
22
|
+
return fromEnv.replace(/\/$/, '');
|
|
23
|
+
}
|
|
24
|
+
let developerId = 0;
|
|
25
|
+
try {
|
|
26
|
+
const yaml = require('js-yaml');
|
|
27
|
+
const cfgPath = path.join(
|
|
28
|
+
process.env.HOME || '',
|
|
29
|
+
'.aifabrix',
|
|
30
|
+
'config.yaml'
|
|
31
|
+
);
|
|
32
|
+
if (fs.existsSync(cfgPath)) {
|
|
33
|
+
const cfg = yaml.load(fs.readFileSync(cfgPath, 'utf8')) || {};
|
|
34
|
+
developerId = Number(cfg['developer-id'] || cfg.developerId || 0) || 0;
|
|
35
|
+
}
|
|
36
|
+
} catch (_err) {
|
|
37
|
+
developerId = 0;
|
|
38
|
+
}
|
|
39
|
+
return `http://localhost:${3005 + developerId * 100}`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @param {Object} authConfig
|
|
44
|
+
* @returns {string}
|
|
45
|
+
*/
|
|
46
|
+
function extractBearer(authConfig) {
|
|
47
|
+
if (!authConfig || typeof authConfig !== 'object') {
|
|
48
|
+
return '';
|
|
49
|
+
}
|
|
50
|
+
if (typeof authConfig.token === 'string' && authConfig.token.trim()) {
|
|
51
|
+
return authConfig.token.trim();
|
|
52
|
+
}
|
|
53
|
+
if (typeof authConfig.bearerToken === 'string' && authConfig.bearerToken.trim()) {
|
|
54
|
+
return authConfig.bearerToken.trim();
|
|
55
|
+
}
|
|
56
|
+
const header = authConfig.headers && authConfig.headers.Authorization;
|
|
57
|
+
const m = /^Bearer\s+(.+)$/i.exec(String(header || ''));
|
|
58
|
+
return m ? m[1].trim() : '';
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @param {Object} testCase
|
|
63
|
+
* @param {Object} wait
|
|
64
|
+
* @returns {boolean}
|
|
65
|
+
*/
|
|
66
|
+
function shouldApplyBidAfterWait(testCase, wait) {
|
|
67
|
+
const bid = loadCaseBidDocument(testCase);
|
|
68
|
+
if (!bid) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
const capability = String(
|
|
72
|
+
wait.questionKey || wait.objectRef?.capabilityKey || wait.prompt || ''
|
|
73
|
+
).toLowerCase();
|
|
74
|
+
return (
|
|
75
|
+
capability.includes('createsystem') ||
|
|
76
|
+
capability.includes('applyintegrationdefinition')
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* @param {Object} authConfig
|
|
82
|
+
* @param {Object} testCase
|
|
83
|
+
* @returns {Promise<Object|null>}
|
|
84
|
+
*/
|
|
85
|
+
async function applyCaseBidViaBuilderApi(authConfig, testCase) {
|
|
86
|
+
const bid = loadCaseBidDocument(testCase);
|
|
87
|
+
const systemKey = resolveTargetSystemKey(testCase);
|
|
88
|
+
const token = extractBearer(authConfig);
|
|
89
|
+
if (!bid || !systemKey || !token) {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
const url = `${resolveBuilderApiBaseUrl()}/api/v1/builder/systems/${encodeURIComponent(systemKey)}/integration-definition/apply`;
|
|
93
|
+
const res = await fetch(url, {
|
|
94
|
+
method: 'POST',
|
|
95
|
+
headers: {
|
|
96
|
+
Authorization: `Bearer ${token}`,
|
|
97
|
+
'Content-Type': 'application/json'
|
|
98
|
+
},
|
|
99
|
+
body: JSON.stringify({ integrationDefinition: bid, force: true })
|
|
100
|
+
});
|
|
101
|
+
const text = await res.text();
|
|
102
|
+
let body = null;
|
|
103
|
+
try {
|
|
104
|
+
body = text ? JSON.parse(text) : null;
|
|
105
|
+
} catch (_err) {
|
|
106
|
+
body = { raw: text };
|
|
107
|
+
}
|
|
108
|
+
if (!res.ok) {
|
|
109
|
+
const err = new Error(
|
|
110
|
+
`BID apply failed HTTP ${res.status}: ${typeof body === 'object' ? JSON.stringify(body).slice(0, 300) : text}`
|
|
111
|
+
);
|
|
112
|
+
err.status = res.status;
|
|
113
|
+
throw err;
|
|
114
|
+
}
|
|
115
|
+
return body && body.data ? body.data : body;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
module.exports = {
|
|
119
|
+
resolveBuilderApiBaseUrl,
|
|
120
|
+
shouldApplyBidAfterWait,
|
|
121
|
+
applyCaseBidViaBuilderApi
|
|
122
|
+
};
|