@aifabrix/builder 2.52.0 → 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/channels/add-channel.js +126 -19
- package/lib/channels/approval-guides/chatgpt.js +1 -1
- 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/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.js +13 -6
- package/lib/cli/setup-infra.js +31 -4
- package/lib/commands/channel-add-setup.js +28 -9
- package/lib/commands/channel.js +14 -10
- package/lib/commands/integration-definition.js +158 -0
- 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 +125 -166
- package/lib/datasource/capability/capability-resolve.js +15 -5
- package/lib/datasource/capability/copy-operations.js +14 -4
- 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-sync-logging.js +58 -0
- package/lib/role-assistant/knowledge-sync.js +88 -93
- 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 +245 -20
- package/lib/role-assistant/test-runner-workhub.js +100 -18
- package/lib/role-assistant/test-suite.js +119 -0
- package/lib/schema/application-schema.json +56 -6
- package/lib/schema/external-datasource.schema.json +103 -17
- package/lib/schema/external-system.schema.json +54 -3
- package/lib/schema/integration-definition.schema.json +195 -0
- package/lib/utils/authentication-shape.js +6 -0
- package/lib/utils/docker-build.js +3 -3
- package/lib/utils/help-builder.js +1 -0
- package/lib/utils/promote-dev-docker-image.js +97 -18
- package/lib/utils/transient-developer-id.js +28 -0
- package/package.json +1 -1
- package/scripts/pnpm/af.mjs +24 -9
- package/scripts/pnpm/help.mjs +1 -1
- package/templates/applications/dataplane/application.yaml +3 -2
- package/templates/applications/dataplane/env.template +7 -6
- package/templates/applications/miso-controller/application.yaml +23 -9
- package/templates/applications/miso-controller/env.template +8 -2
- 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 +6 -4
- package/templates/channels/chatgpt/integration/README.md +4 -5
- package/templates/channels/chatgpt/integration/chatgpt-system.json +1 -16
- 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/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/.cursor/plans/{Done → Archive}/157.1-security-quality-violations-by-type.csv +0 -0
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builder API channel packaging handlers (plan 167.0).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Package build / branding / zip for workspace channel systemKeys
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const fs = require('../internal/fs-real-sync');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
const { ensureIntegrationDirectory } = require('./workspace-context');
|
|
14
|
+
const { resolveChannelRuntimeValues } = require('../channels/channel-runtime-resolver');
|
|
15
|
+
const { generateChannelArtifact } = require('../channels/channel-artifact-generator');
|
|
16
|
+
const { loadChannelPackageContext } = require('../channels/channel-discovery');
|
|
17
|
+
const {
|
|
18
|
+
readChannelBranding,
|
|
19
|
+
writeChannelBranding,
|
|
20
|
+
mergeChannelBranding
|
|
21
|
+
} = require('../channels/channel-branding');
|
|
22
|
+
const { isChannelTargetKey } = require('../channels/channel-targets');
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @param {import('./workspace-context').WorkspaceContext} ctx
|
|
26
|
+
* @returns {string}
|
|
27
|
+
*/
|
|
28
|
+
function workspaceSystemDir(ctx) {
|
|
29
|
+
return ctx.getIntegrationPath();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Channel target equals workspace systemKey for packaging apps.
|
|
34
|
+
* @param {string} systemKey
|
|
35
|
+
* @returns {string}
|
|
36
|
+
*/
|
|
37
|
+
function requireChannelTarget(systemKey) {
|
|
38
|
+
if (!isChannelTargetKey(systemKey)) {
|
|
39
|
+
throw new Error(
|
|
40
|
+
`systemKey "${systemKey}" is not a supported channel packaging target`
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
return systemKey;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @param {import('./workspace-context').WorkspaceContext} ctx
|
|
48
|
+
* @returns {{ type: string, token: string }}
|
|
49
|
+
*/
|
|
50
|
+
function authConfigFromContext(ctx) {
|
|
51
|
+
return { type: 'bearer', token: ctx.bearerToken };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @param {Object} branding
|
|
56
|
+
* @param {string} channelTarget
|
|
57
|
+
* @returns {Object}
|
|
58
|
+
*/
|
|
59
|
+
function fallbackPackageContext(branding, channelTarget) {
|
|
60
|
+
return {
|
|
61
|
+
displayName: branding.displayName || channelTarget,
|
|
62
|
+
description: branding.description || '',
|
|
63
|
+
governedToolNames: [],
|
|
64
|
+
mcpServerUrl: null,
|
|
65
|
+
installReady: false,
|
|
66
|
+
blocker: 'discoveryUnavailable',
|
|
67
|
+
authentication: null
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @param {import('./workspace-context').WorkspaceContext} ctx
|
|
73
|
+
* @param {Object} body
|
|
74
|
+
* @param {string} channelTarget
|
|
75
|
+
* @param {Object} branding
|
|
76
|
+
* @param {string} dataplaneUrl
|
|
77
|
+
* @param {Object} packageContext
|
|
78
|
+
* @returns {Object}
|
|
79
|
+
*/
|
|
80
|
+
function generatePackageArtifact(ctx, body, channelTarget, branding, dataplaneUrl, packageContext) {
|
|
81
|
+
const appName =
|
|
82
|
+
branding.displayName || body.name || packageContext.displayName || channelTarget;
|
|
83
|
+
const description =
|
|
84
|
+
branding.description || body.description || packageContext.description || '';
|
|
85
|
+
const runtimeValues = resolveChannelRuntimeValues({
|
|
86
|
+
dataplaneBaseUrl: dataplaneUrl,
|
|
87
|
+
channelTarget,
|
|
88
|
+
appName,
|
|
89
|
+
baseName: body.baseName || appName,
|
|
90
|
+
environment: body.environment || ctx.environment || 'dev',
|
|
91
|
+
appDescription: description,
|
|
92
|
+
layerBToolNames: packageContext.governedToolNames || [],
|
|
93
|
+
packageContext,
|
|
94
|
+
iconColorPath: branding.iconColorPath,
|
|
95
|
+
iconOutlinePath: branding.iconOutlinePath
|
|
96
|
+
});
|
|
97
|
+
return generateChannelArtifact({
|
|
98
|
+
projectRoot: ctx.getUserRoot(),
|
|
99
|
+
channelTarget,
|
|
100
|
+
runtimeValues,
|
|
101
|
+
dryRun: body.dryRun === true
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* @param {import('./workspace-context').WorkspaceContext} ctx
|
|
107
|
+
* @param {Object} body
|
|
108
|
+
* @returns {Promise<Object>}
|
|
109
|
+
*/
|
|
110
|
+
async function buildChannelPackage(ctx, body = {}) {
|
|
111
|
+
const channelTarget = requireChannelTarget(ctx.systemKey);
|
|
112
|
+
ensureIntegrationDirectory(ctx);
|
|
113
|
+
const dir = workspaceSystemDir(ctx);
|
|
114
|
+
const branding = mergeChannelBranding(readChannelBranding(dir), body.branding || {});
|
|
115
|
+
if (body.branding && typeof body.branding === 'object') {
|
|
116
|
+
writeChannelBranding(dir, branding);
|
|
117
|
+
}
|
|
118
|
+
const dataplaneUrl = ctx.dataplaneUrl || body.dataplaneUrl;
|
|
119
|
+
if (!dataplaneUrl) {
|
|
120
|
+
throw new Error('dataplaneUrl is required to build a channel package');
|
|
121
|
+
}
|
|
122
|
+
const packageContext = await loadChannelPackageContext({
|
|
123
|
+
dataplaneBaseUrl: dataplaneUrl,
|
|
124
|
+
authConfig: authConfigFromContext(ctx),
|
|
125
|
+
channelTarget,
|
|
126
|
+
branding
|
|
127
|
+
}).catch(() => fallbackPackageContext(branding, channelTarget));
|
|
128
|
+
const artifact = generatePackageArtifact(
|
|
129
|
+
ctx,
|
|
130
|
+
body,
|
|
131
|
+
channelTarget,
|
|
132
|
+
branding,
|
|
133
|
+
dataplaneUrl,
|
|
134
|
+
packageContext
|
|
135
|
+
);
|
|
136
|
+
return {
|
|
137
|
+
channelTarget,
|
|
138
|
+
installReady: artifact.installReady === true,
|
|
139
|
+
blocker: artifact.blocker || packageContext.blocker || null,
|
|
140
|
+
artifactHash: artifact.artifactHash,
|
|
141
|
+
links: artifact.links || {
|
|
142
|
+
readme: artifact.installPath,
|
|
143
|
+
zip: artifact.zipPath || null
|
|
144
|
+
},
|
|
145
|
+
summary: artifact.content ? JSON.parse(artifact.content) : null
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* @param {import('./workspace-context').WorkspaceContext} ctx
|
|
151
|
+
* @returns {Object}
|
|
152
|
+
*/
|
|
153
|
+
function getChannelPackageSummary(ctx) {
|
|
154
|
+
const channelTarget = requireChannelTarget(ctx.systemKey);
|
|
155
|
+
const projectRoot = ctx.getUserRoot();
|
|
156
|
+
const summaryPath = path.join(
|
|
157
|
+
projectRoot,
|
|
158
|
+
'dist',
|
|
159
|
+
'channels',
|
|
160
|
+
channelTarget,
|
|
161
|
+
`channel-${channelTarget}.json`
|
|
162
|
+
);
|
|
163
|
+
if (!fs.existsSync(summaryPath)) {
|
|
164
|
+
throw new Error(`Channel package summary not found: ${summaryPath}`);
|
|
165
|
+
}
|
|
166
|
+
const summary = JSON.parse(fs.readFileSync(summaryPath, 'utf8'));
|
|
167
|
+
return {
|
|
168
|
+
channelTarget,
|
|
169
|
+
summary,
|
|
170
|
+
links: summary.links || null,
|
|
171
|
+
installReady: summary.installReady === true,
|
|
172
|
+
blocker: summary.blocker || null
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* @param {import('./workspace-context').WorkspaceContext} ctx
|
|
178
|
+
* @returns {{ fileName: string, contentType: string, byteLength: number, zipBase64: string }}
|
|
179
|
+
*/
|
|
180
|
+
function getChannelPackageZip(ctx) {
|
|
181
|
+
const channelTarget = requireChannelTarget(ctx.systemKey);
|
|
182
|
+
const summary = getChannelPackageSummary(ctx).summary;
|
|
183
|
+
const zipPath =
|
|
184
|
+
typeof summary?.links?.zip === 'string' && summary.links.zip
|
|
185
|
+
? summary.links.zip
|
|
186
|
+
: path.join(
|
|
187
|
+
ctx.getUserRoot(),
|
|
188
|
+
'dist',
|
|
189
|
+
'channels',
|
|
190
|
+
channelTarget,
|
|
191
|
+
'build',
|
|
192
|
+
`appPackage.${summary.environment || 'dev'}.zip`
|
|
193
|
+
);
|
|
194
|
+
if (!fs.existsSync(zipPath)) {
|
|
195
|
+
throw new Error(`Channel package ZIP not found: ${zipPath}`);
|
|
196
|
+
}
|
|
197
|
+
const buffer = fs.readFileSync(zipPath);
|
|
198
|
+
return {
|
|
199
|
+
fileName: path.basename(zipPath),
|
|
200
|
+
contentType: 'application/zip',
|
|
201
|
+
byteLength: buffer.length,
|
|
202
|
+
zipBase64: buffer.toString('base64')
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* @param {import('./workspace-context').WorkspaceContext} ctx
|
|
208
|
+
* @param {Object} body
|
|
209
|
+
* @returns {Object}
|
|
210
|
+
*/
|
|
211
|
+
function patchChannelBranding(ctx, body = {}) {
|
|
212
|
+
requireChannelTarget(ctx.systemKey);
|
|
213
|
+
ensureIntegrationDirectory(ctx);
|
|
214
|
+
const branding = writeChannelBranding(workspaceSystemDir(ctx), body || {});
|
|
215
|
+
return { systemKey: ctx.systemKey, branding };
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* @param {import('./workspace-context').WorkspaceContext} ctx
|
|
220
|
+
* @returns {Object}
|
|
221
|
+
*/
|
|
222
|
+
function getChannelBranding(ctx) {
|
|
223
|
+
requireChannelTarget(ctx.systemKey);
|
|
224
|
+
return {
|
|
225
|
+
systemKey: ctx.systemKey,
|
|
226
|
+
branding: readChannelBranding(workspaceSystemDir(ctx))
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
module.exports = {
|
|
231
|
+
buildChannelPackage,
|
|
232
|
+
getChannelPackageSummary,
|
|
233
|
+
getChannelPackageZip,
|
|
234
|
+
patchChannelBranding,
|
|
235
|
+
getChannelBranding
|
|
236
|
+
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Apply Builder Integration Definition (BID) into a user workspace.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview POST …/integration-definition/apply
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const {
|
|
13
|
+
applyIntegrationDefinition,
|
|
14
|
+
withDefinitionHash
|
|
15
|
+
} = require('../integration-definition');
|
|
16
|
+
const {
|
|
17
|
+
runWithWorkspaceContext,
|
|
18
|
+
ensureIntegrationDirectory,
|
|
19
|
+
WORKSPACE_INTEGRATION_FORMAT
|
|
20
|
+
} = require('./workspace-context');
|
|
21
|
+
const { touchWorkspaceMeta } = require('./workspace-meta');
|
|
22
|
+
|
|
23
|
+
const OPENAPI_ENRICHMENT_DIR = path.join(
|
|
24
|
+
__dirname,
|
|
25
|
+
'../integration-definition/openapi-enrichment'
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @param {import('./workspace-context').WorkspaceContext} ctx
|
|
30
|
+
* @param {Object} body
|
|
31
|
+
* @param {Object} [body.integrationDefinition]
|
|
32
|
+
* @param {boolean} [body.force]
|
|
33
|
+
* @param {boolean} [body.dryRun]
|
|
34
|
+
* @returns {Promise<Object>}
|
|
35
|
+
*/
|
|
36
|
+
async function applyIntegrationDefinitionInWorkspace(ctx, body = {}) {
|
|
37
|
+
const bidInput = body.integrationDefinition || body.bid || body;
|
|
38
|
+
if (!bidInput || typeof bidInput !== 'object') {
|
|
39
|
+
throw new Error('integrationDefinition object is required in request body');
|
|
40
|
+
}
|
|
41
|
+
const force = body.force === true;
|
|
42
|
+
const dryRun = body.dryRun === true;
|
|
43
|
+
return runWithWorkspaceContext(ctx, async() => {
|
|
44
|
+
ensureIntegrationDirectory(ctx);
|
|
45
|
+
const bid = withDefinitionHash(bidInput);
|
|
46
|
+
const identity = bid.packageIdentity || {};
|
|
47
|
+
const bidKey = String(identity.systemKey || '').trim();
|
|
48
|
+
if (bidKey && bidKey !== ctx.systemKey) {
|
|
49
|
+
throw new Error(
|
|
50
|
+
`BID packageIdentity.systemKey (${bidKey}) must match path systemKey (${ctx.systemKey})`
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
const out = await applyIntegrationDefinition(bid, {
|
|
54
|
+
outputDir: ctx.getIntegrationPath(),
|
|
55
|
+
force,
|
|
56
|
+
dryRun,
|
|
57
|
+
openapiBaseDir: OPENAPI_ENRICHMENT_DIR
|
|
58
|
+
});
|
|
59
|
+
touchWorkspaceMeta(ctx, {
|
|
60
|
+
lastOperation: 'integration-definition-apply',
|
|
61
|
+
format: WORKSPACE_INTEGRATION_FORMAT,
|
|
62
|
+
definitionId: out.definitionId,
|
|
63
|
+
definitionHash: out.definitionHash
|
|
64
|
+
});
|
|
65
|
+
return out;
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
module.exports = { applyIntegrationDefinitionInWorkspace };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const logger = require('../utils/logger');
|
|
4
|
+
const { formatSuccessLine, formatWarningLine, metadata } = require('../utils/cli-test-layout-chalk');
|
|
5
|
+
|
|
6
|
+
function logKnowledgeImportSummary(systemKey, result, options = {}) {
|
|
7
|
+
if (result.skipped) {
|
|
8
|
+
if (options.verbose === true) {
|
|
9
|
+
logger.log(metadata(`Knowledge sync skipped (${systemKey}): ${result.reason}`));
|
|
10
|
+
}
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
if (result.dryRun) {
|
|
14
|
+
logger.log(formatWarningLine(
|
|
15
|
+
`Role assistant knowledge dry-run: ${result.fileCount} file(s), ${result.recordCount} record(s), datasource ${result.datasourceKey}`
|
|
16
|
+
));
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
logger.log(formatSuccessLine(
|
|
20
|
+
`Role assistant knowledge synced (${result.datasourceKey}): ${result.recordCount} record(s) from ${result.fileCount} file(s).`
|
|
21
|
+
));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function logDocumentStorageSettingsPushSummary(systemKey, result, options = {}) {
|
|
25
|
+
if (result.skipped) {
|
|
26
|
+
if (options.verbose === true) {
|
|
27
|
+
logger.log(metadata(`Knowledge document storage settings skipped (${systemKey}): ${result.reason}`));
|
|
28
|
+
}
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (result.dryRun) {
|
|
32
|
+
logger.log(formatWarningLine(
|
|
33
|
+
`Knowledge document storage settings dry-run (${systemKey}): ${result.documentStorageKey || '(clear)'}`
|
|
34
|
+
));
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
logger.log(formatSuccessLine(
|
|
38
|
+
`Knowledge document storage settings updated (${systemKey}): ${result.documentStorageKey || '(cleared)'}`
|
|
39
|
+
));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function logKnowledgeExportSummary(systemKey, result, options = {}) {
|
|
43
|
+
if (result.skipped) {
|
|
44
|
+
if (options.verbose === true) {
|
|
45
|
+
logger.log(metadata(`Knowledge export skipped (${systemKey}): ${result.reason}`));
|
|
46
|
+
}
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
logger.log(formatSuccessLine(
|
|
50
|
+
`Role assistant knowledge exported (${result.datasourceKey}): ${result.count} document(s) to ${result.knowledgePath}.`
|
|
51
|
+
));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
module.exports = {
|
|
55
|
+
logKnowledgeImportSummary,
|
|
56
|
+
logDocumentStorageSettingsPushSummary,
|
|
57
|
+
logKnowledgeExportSummary
|
|
58
|
+
};
|
|
@@ -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,
|
|
@@ -32,6 +30,11 @@ const {
|
|
|
32
30
|
knowledgeSearchMetadataFromFrontmatter,
|
|
33
31
|
splitMarkdownFrontmatter
|
|
34
32
|
} = require('./knowledge-markdown-frontmatter');
|
|
33
|
+
const {
|
|
34
|
+
logKnowledgeImportSummary,
|
|
35
|
+
logDocumentStorageSettingsPushSummary,
|
|
36
|
+
logKnowledgeExportSummary
|
|
37
|
+
} = require('./knowledge-sync-logging');
|
|
35
38
|
|
|
36
39
|
function resolveSystemNode(input) {
|
|
37
40
|
if (!input || typeof input !== 'object') {
|
|
@@ -80,53 +83,91 @@ async function resolveDocumentStorageKeyFromDataplane(dataplaneUrl, authConfig,
|
|
|
80
83
|
}
|
|
81
84
|
|
|
82
85
|
/**
|
|
83
|
-
*
|
|
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.
|
|
84
108
|
* Called on upload/deploy so the operator UI and CLI stay aligned.
|
|
85
109
|
*/
|
|
86
|
-
|
|
110
|
+
function resolveAssistantSettingsPush(params) {
|
|
87
111
|
const {
|
|
88
112
|
systemKey,
|
|
89
|
-
dataplaneUrl,
|
|
90
|
-
authConfig,
|
|
91
113
|
environment = 'dev',
|
|
92
|
-
pathOptions = {}
|
|
93
|
-
dryRun = false
|
|
114
|
+
pathOptions = {}
|
|
94
115
|
} = params;
|
|
95
116
|
const settingsEnv = resolveRoleAssistantSettingsEnvKey(environment);
|
|
96
117
|
const settings = readRoleAssistantSettings(systemKey, { required: false, pathOptions });
|
|
97
118
|
if (!settings) {
|
|
98
|
-
return { skipped: true, reason: 'missing-role-assistant-settings' };
|
|
119
|
+
return { result: { skipped: true, reason: 'missing-role-assistant-settings' } };
|
|
99
120
|
}
|
|
100
121
|
const section = resolveRoleAssistantEnvironmentSettings(settings, settingsEnv, {
|
|
101
122
|
required: false
|
|
102
123
|
});
|
|
103
124
|
if (!section) {
|
|
104
|
-
return { skipped: true, reason: 'missing-env-settings' };
|
|
125
|
+
return { result: { skipped: true, reason: 'missing-env-settings' } };
|
|
105
126
|
}
|
|
106
127
|
const documentStorageKey =
|
|
107
128
|
resolveDocumentStorageKeyFromRoleAssistantSettings(settings, settingsEnv) || '';
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
dryRun: true,
|
|
112
|
-
documentStorageKey: documentStorageKey || null
|
|
113
|
-
};
|
|
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 } };
|
|
114
132
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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
|
+
}
|
|
118
164
|
return {
|
|
119
|
-
skipped:
|
|
120
|
-
|
|
121
|
-
|
|
165
|
+
skipped: false,
|
|
166
|
+
documentStorageKey: null,
|
|
167
|
+
documentStoragePushFailed: true,
|
|
168
|
+
...debugBody
|
|
122
169
|
};
|
|
123
170
|
}
|
|
124
|
-
if (!dataplaneUrl || !authConfig) {
|
|
125
|
-
return { skipped: true, reason: 'missing-dataplane-auth' };
|
|
126
|
-
}
|
|
127
|
-
const response = await updateAssistantSettings(dataplaneUrl, systemKey, authConfig, {
|
|
128
|
-
documentStorageKey
|
|
129
|
-
});
|
|
130
171
|
if (response && response.success === false) {
|
|
131
172
|
throw new Error(
|
|
132
173
|
response.formattedError ||
|
|
@@ -136,10 +177,27 @@ async function pushRoleAssistantDocumentStorageSettings(params) {
|
|
|
136
177
|
}
|
|
137
178
|
return {
|
|
138
179
|
skipped: false,
|
|
139
|
-
documentStorageKey: documentStorageKey || null
|
|
180
|
+
documentStorageKey: documentStorageKey || null,
|
|
181
|
+
...debugBody
|
|
140
182
|
};
|
|
141
183
|
}
|
|
142
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
|
+
|
|
143
201
|
/**
|
|
144
202
|
* Resolve Knowledge document storage key.
|
|
145
203
|
* Order: role-assistant.yaml → dataplane Assistants settings → package dataSources.
|
|
@@ -408,74 +466,11 @@ async function exportRoleAssistantKnowledge(params) {
|
|
|
408
466
|
return { skipped: false, datasourceKey, count: rows.length, knowledgePath, settingsPath };
|
|
409
467
|
}
|
|
410
468
|
|
|
411
|
-
function logKnowledgeImportSummary(systemKey, result, options = {}) {
|
|
412
|
-
if (result.skipped) {
|
|
413
|
-
if (options.verbose === true) {
|
|
414
|
-
logger.log(metadata(`Knowledge sync skipped (${systemKey}): ${result.reason}`));
|
|
415
|
-
}
|
|
416
|
-
return;
|
|
417
|
-
}
|
|
418
|
-
if (result.dryRun) {
|
|
419
|
-
logger.log(
|
|
420
|
-
formatWarningLine(
|
|
421
|
-
`Role assistant knowledge dry-run: ${result.fileCount} file(s), ${result.recordCount} record(s), datasource ${result.datasourceKey}`
|
|
422
|
-
)
|
|
423
|
-
);
|
|
424
|
-
return;
|
|
425
|
-
}
|
|
426
|
-
logger.log(
|
|
427
|
-
formatSuccessLine(
|
|
428
|
-
`Role assistant knowledge synced (${result.datasourceKey}): ${result.recordCount} record(s) from ${result.fileCount} file(s).`
|
|
429
|
-
)
|
|
430
|
-
);
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
function logDocumentStorageSettingsPushSummary(systemKey, result, options = {}) {
|
|
434
|
-
if (result.skipped) {
|
|
435
|
-
if (options.verbose === true) {
|
|
436
|
-
logger.log(
|
|
437
|
-
metadata(`Knowledge document storage settings skipped (${systemKey}): ${result.reason}`)
|
|
438
|
-
);
|
|
439
|
-
}
|
|
440
|
-
return;
|
|
441
|
-
}
|
|
442
|
-
if (result.dryRun) {
|
|
443
|
-
logger.log(
|
|
444
|
-
formatWarningLine(
|
|
445
|
-
`Knowledge document storage settings dry-run (${systemKey}): ${
|
|
446
|
-
result.documentStorageKey || '(clear)'
|
|
447
|
-
}`
|
|
448
|
-
)
|
|
449
|
-
);
|
|
450
|
-
return;
|
|
451
|
-
}
|
|
452
|
-
logger.log(
|
|
453
|
-
formatSuccessLine(
|
|
454
|
-
`Knowledge document storage settings updated (${systemKey}): ${
|
|
455
|
-
result.documentStorageKey || '(cleared)'
|
|
456
|
-
}`
|
|
457
|
-
)
|
|
458
|
-
);
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
function logKnowledgeExportSummary(systemKey, result, options = {}) {
|
|
462
|
-
if (result.skipped) {
|
|
463
|
-
if (options.verbose === true) {
|
|
464
|
-
logger.log(metadata(`Knowledge export skipped (${systemKey}): ${result.reason}`));
|
|
465
|
-
}
|
|
466
|
-
return;
|
|
467
|
-
}
|
|
468
|
-
logger.log(
|
|
469
|
-
formatSuccessLine(
|
|
470
|
-
`Role assistant knowledge exported (${result.datasourceKey}): ${result.count} document(s) to ${result.knowledgePath}.`
|
|
471
|
-
)
|
|
472
|
-
);
|
|
473
|
-
}
|
|
474
|
-
|
|
475
469
|
module.exports = {
|
|
476
470
|
isDigitalWorkerModel,
|
|
477
471
|
resolveRoleAssistantSettingsEnvKey,
|
|
478
472
|
resolveRoleAssistantDocumentStorageKey,
|
|
473
|
+
mapRoleAssistantDebugToAssistantsSettings,
|
|
479
474
|
pushRoleAssistantDocumentStorageSettings,
|
|
480
475
|
importRoleAssistantKnowledge,
|
|
481
476
|
exportRoleAssistantKnowledge,
|