@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
|
@@ -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,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse optional YAML frontmatter from Role Assistant knowledge markdown.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview knowledge-markdown-frontmatter
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const yaml = require('js-yaml');
|
|
12
|
+
|
|
13
|
+
const SEARCH_META_KEYS = [
|
|
14
|
+
'aspect',
|
|
15
|
+
'knowledgeType',
|
|
16
|
+
'knowledgeKey',
|
|
17
|
+
'title',
|
|
18
|
+
'resourceType',
|
|
19
|
+
'roleKey'
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Split markdown into optional YAML frontmatter and body.
|
|
24
|
+
* @param {string} content
|
|
25
|
+
* @returns {{ frontmatter: Object|null, body: string }}
|
|
26
|
+
*/
|
|
27
|
+
function splitMarkdownFrontmatter(content) {
|
|
28
|
+
const text = typeof content === 'string' ? content : '';
|
|
29
|
+
if (!text.startsWith('---')) {
|
|
30
|
+
return { frontmatter: null, body: text };
|
|
31
|
+
}
|
|
32
|
+
const end = text.indexOf('\n---', 3);
|
|
33
|
+
if (end < 0) {
|
|
34
|
+
return { frontmatter: null, body: text };
|
|
35
|
+
}
|
|
36
|
+
const raw = text.slice(3, end).trim();
|
|
37
|
+
const body = text.slice(end + 4).replace(/^(?:\r?\n)+/, '');
|
|
38
|
+
if (!raw) {
|
|
39
|
+
return { frontmatter: {}, body };
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
const parsed = yaml.load(raw);
|
|
43
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
44
|
+
return { frontmatter: null, body: text };
|
|
45
|
+
}
|
|
46
|
+
return { frontmatter: parsed, body };
|
|
47
|
+
} catch (_error) {
|
|
48
|
+
return { frontmatter: null, body: text };
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Project searchable metadata fields from frontmatter.
|
|
54
|
+
* @param {Object|null|undefined} frontmatter
|
|
55
|
+
* @returns {Object}
|
|
56
|
+
*/
|
|
57
|
+
function knowledgeSearchMetadataFromFrontmatter(frontmatter) {
|
|
58
|
+
const out = {};
|
|
59
|
+
if (!frontmatter || typeof frontmatter !== 'object') {
|
|
60
|
+
return out;
|
|
61
|
+
}
|
|
62
|
+
for (const key of SEARCH_META_KEYS) {
|
|
63
|
+
const value = frontmatter[key];
|
|
64
|
+
if (typeof value === 'string' && value.trim()) {
|
|
65
|
+
out[key] = value.trim();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
module.exports = {
|
|
72
|
+
SEARCH_META_KEYS,
|
|
73
|
+
splitMarkdownFrontmatter,
|
|
74
|
+
knowledgeSearchMetadataFromFrontmatter
|
|
75
|
+
};
|
|
@@ -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
|
+
};
|