@aifabrix/builder 2.51.0 → 2.52.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/jest.isolated-projects.js +77 -1
- package/jest.projects.js +5 -426
- package/lib/api/assistants.api.js +67 -0
- package/lib/api/datasources-extended.api.js +6 -6
- package/lib/api/evidence-authoring-helpers.js +267 -0
- package/lib/api/evidence-authoring.api.js +337 -0
- package/lib/api/evidence.api.js +57 -1
- package/lib/api/index.js +24 -7
- package/lib/api/pipeline.api.js +43 -3
- package/lib/api/records-bulk.api.js +28 -3
- package/lib/api/types/evidence.types.js +156 -8
- package/lib/api/work.api.js +283 -0
- package/lib/app/run-container-start.js +4 -0
- package/lib/app/run-deploy-job.js +216 -0
- package/lib/app/run-env-compose.js +32 -0
- package/lib/app/run-env-recovery.js +35 -0
- package/lib/app/run-helpers.js +15 -9
- package/lib/app/run.js +18 -2
- package/lib/channels/add-channel.js +54 -23
- package/lib/channels/approval-guides/chatgpt.js +13 -9
- package/lib/channels/approval-guides/microsoft-copilot.js +7 -8
- package/lib/channels/channel-artifact-generator.js +14 -2
- package/lib/channels/channel-credential.js +3 -1
- package/lib/channels/channel-probe-evidence.js +79 -0
- package/lib/channels/channel-probe.js +265 -13
- package/lib/channels/channel-runtime-resolver.js +120 -29
- package/lib/channels/channel-status-display.js +44 -0
- package/lib/channels/channel-targets.js +25 -1
- package/lib/channels/chatgpt-runtime-contract.js +29 -0
- package/lib/channels/microsoft-copilot-package.js +280 -0
- package/lib/channels/runtime-tool-catalog.js +165 -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 +65 -56
- package/lib/cli/setup-app.help.js +4 -0
- package/lib/cli/setup-app.js +4 -0
- package/lib/cli/setup-app.test-commands.js +59 -28
- package/lib/cli/setup-external-system-help.js +8 -2
- package/lib/cli/setup-external-system.js +62 -12
- package/lib/commands/app-test.js +2 -14
- package/lib/commands/channel-add-setup.js +8 -2
- package/lib/commands/channel.js +16 -5
- package/lib/commands/datasource-load-export-cli.js +6 -1
- package/lib/commands/deploy-gate-failure-details.js +19 -17
- package/lib/commands/deploy-gate-orchestrator.js +3 -2
- package/lib/commands/dev-down.js +2 -6
- package/lib/commands/evidence-kind.js +65 -15
- package/lib/commands/governance-generate-external.js +56 -21
- package/lib/commands/governance-verify-external.js +2 -5
- package/lib/commands/lifecycle-external.js +21 -8
- package/lib/commands/repair-datasource-apply.js +10 -1
- package/lib/commands/repair-datasource-run.js +4 -2
- package/lib/commands/repair-datasource-test-payload.js +80 -19
- package/lib/commands/repair-datasource-webhooks-sync-bridge.js +42 -3
- package/lib/commands/repair-internal.js +9 -1
- package/lib/commands/repair-openapi-sync.js +34 -17
- package/lib/commands/role-assistant.js +371 -0
- 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 +25 -7
- package/lib/commands/upload-sidecar-followups.js +144 -47
- package/lib/commands/upload.js +43 -6
- package/lib/commands/verify-governance-combined-external.js +73 -9
- package/lib/commands/verify-governance-db.js +80 -25
- package/lib/commands/verify-governance-external.js +31 -10
- 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/commands/wizard-core-helpers.js +7 -3
- package/lib/commands/wizard-core.js +78 -9
- package/lib/datasource/bulk-loader-run-batches.js +4 -2
- package/lib/datasource/bulk-loader-service.js +5 -1
- package/lib/datasource/datasource-identifier.js +4 -3
- package/lib/datasource/datasource-validate-summary.js +2 -2
- 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/datasource/validate.js +13 -6
- package/lib/external-system/deploy-helpers.js +39 -1
- package/lib/external-system/deploy.js +25 -11
- package/lib/external-system/download-helpers.js +111 -2
- package/lib/external-system/download-role-assistant.js +55 -0
- package/lib/external-system/download.js +45 -26
- package/lib/external-system/test-helpers.js +1 -1
- package/lib/external-system/test-system-level.js +21 -3
- package/lib/external-system/test.js +43 -7
- package/lib/generator/builders.js +12 -15
- package/lib/generator/wizard.js +51 -4
- package/lib/lifecycle/access-control-abac.js +121 -0
- package/lib/lifecycle/lifecycle-governance-options.js +4 -1
- package/lib/lifecycle/product-model.js +3 -2
- package/lib/lifecycle/report-display.js +14 -2
- package/lib/programmatic/capability-registry.js +20 -1
- package/lib/programmatic/command-options.js +1 -0
- package/lib/programmatic/index.js +4 -0
- package/lib/programmatic/manifest-patch-section.js +48 -9
- package/lib/programmatic/manifest-section-registry-data.js +3 -2
- package/lib/programmatic/openapi-apply-result-schemas.js +44 -0
- package/lib/programmatic/openapi-component-schemas.js +16 -1
- package/lib/programmatic/openapi-description-enricher.js +3 -1
- package/lib/programmatic/openapi-descriptions.js +55 -5
- package/lib/programmatic/openapi-evidence-schemas.js +161 -0
- package/lib/programmatic/openapi-manifest-schemas.js +6 -2
- package/lib/programmatic/openapi-operation-bindings.js +99 -0
- package/lib/programmatic/openapi-request-schemas.js +36 -1
- package/lib/programmatic/openapi-result-schemas.js +1 -1
- package/lib/programmatic/openapi-schema-descriptions-certify.js +5 -1
- package/lib/programmatic/openapi-schema-descriptions-core.js +1 -1
- package/lib/programmatic/openapi-schema-descriptions-evidence.js +156 -0
- package/lib/programmatic/openapi-schema-descriptions-manifest.js +4 -3
- package/lib/programmatic/openapi-schema-descriptions-operations.js +70 -0
- package/lib/programmatic/openapi-spec.js +47 -28
- package/lib/programmatic/orchestration-openapi-meta.js +5 -0
- package/lib/programmatic/request-timeout.js +3 -0
- package/lib/programmatic/route-handler-map.js +89 -2
- package/lib/programmatic/run-certify.js +15 -2
- package/lib/programmatic/run-deploy.js +74 -0
- package/lib/programmatic/run-evidence-authoring.js +80 -0
- package/lib/programmatic/run-protection.js +124 -0
- package/lib/programmatic/run-template-workspace.js +28 -1
- package/lib/programmatic/workspace-context.js +6 -0
- package/lib/protection/auth-context.js +48 -6
- package/lib/protection/paths.js +22 -0
- package/lib/protection/run-protection-create-helpers.js +22 -1
- package/lib/protection/run-protection-create.js +1 -1
- package/lib/protection/sync-after-upload.js +1 -1
- package/lib/role-assistant/evidence-sync.js +450 -0
- package/lib/role-assistant/github-workflow.js +96 -0
- package/lib/role-assistant/knowledge-markdown-frontmatter.js +75 -0
- package/lib/role-assistant/knowledge-sync.js +485 -0
- package/lib/role-assistant/settings.js +126 -0
- package/lib/role-assistant/test-cases-evaluate.js +170 -0
- package/lib/role-assistant/test-cases-honesty.js +184 -0
- package/lib/role-assistant/test-cases.js +364 -0
- package/lib/role-assistant/test-runner-workhub-answers.js +221 -0
- package/lib/role-assistant/test-runner-workhub.js +399 -0
- package/lib/role-assistant/test-runner.js +500 -0
- package/lib/schema/application-schema.json +24 -28
- package/lib/schema/deployment-rules.yaml +1 -0
- package/lib/schema/external-datasource.schema.json +38 -4
- package/lib/schema/external-system.schema.json +4 -4
- package/lib/schema/role-assistant-settings.schema.json +108 -0
- package/lib/utils/api.js +52 -27
- package/lib/utils/app-path-resolve.js +72 -24
- package/lib/utils/authentication-shape.js +3 -1
- package/lib/utils/certify-external-workspace.js +40 -0
- package/lib/utils/deployment-validation.js +28 -3
- package/lib/utils/docker-run-ephemeral.js +115 -0
- package/lib/utils/enterprise-knowledge-paths.js +29 -12
- package/lib/utils/env-copy-keycloak.js +196 -0
- package/lib/utils/env-copy.js +34 -1
- package/lib/utils/external-system-readiness-compact-display.js +3 -0
- 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 +80 -38
- package/lib/utils/pipeline-upload-auth-retry.js +15 -3
- package/lib/utils/role-assistant-paths.js +160 -0
- package/lib/utils/schema-loader.js +41 -0
- package/lib/utils/schema-resolver.js +36 -4
- package/lib/utils/token-manager.js +38 -29
- package/lib/utils/upload-sync-options.js +7 -4
- package/lib/utils/url-declarative-resolve-load-doc.js +38 -1
- package/lib/validation/external-manifest-validator.js +31 -8
- package/lib/validation/reserved-system-key-prefixes.js +56 -0
- package/lib/validation/validate-external-file.js +8 -1
- package/lib/validation/validate.js +54 -19
- package/package.json +2 -1
- package/scripts/export-builder-api-evidence.js +1 -1
- package/templates/applications/builder-api/application.yaml +3 -3
- package/templates/applications/dataplane/application.yaml +24 -17
- package/templates/applications/dataplane/env.template +2 -2
- package/templates/applications/dataplane/rbac.yaml +24 -10
- package/templates/applications/keycloak/application.yaml +2 -2
- package/templates/applications/keycloak/env.template +5 -2
- package/templates/applications/miso-controller/application.yaml +3 -3
- package/templates/applications/miso-controller/env.template +17 -2
- package/templates/channels/chatgpt/install.template.md.hbs +82 -26
- package/templates/channels/chatgpt/integration/README.md +11 -7
- package/templates/channels/chatgpt/integration/application.json +2 -2
- package/templates/channels/chatgpt/integration/chatgpt-system.json +3 -3
- package/templates/channels/chatgpt/integration/env.template +1 -1
- package/templates/channels/chatgpt/manifest.template.json.hbs +36 -5
- package/templates/channels/microsoft-copilot/ai-plugin.template.json.hbs +28 -0
- package/templates/channels/microsoft-copilot/declarative-agent.template.json.hbs +22 -0
- package/templates/channels/microsoft-copilot/install.template.md.hbs +32 -22
- package/templates/channels/microsoft-copilot/integration/README.md +9 -7
- package/templates/channels/microsoft-copilot/integration/application.json +2 -2
- package/templates/channels/microsoft-copilot/integration/env.template +1 -1
- package/templates/channels/microsoft-copilot/integration/microsoft-copilot-system.json +7 -6
- package/templates/channels/microsoft-copilot/manifest.template.json.hbs +34 -6
- package/templates/channels/slack/install.template.md.hbs +6 -1
- package/templates/python/docker-compose.hbs +10 -0
- package/templates/typescript/docker-compose.hbs +10 -0
- /package/.cursor/plans/{157.1-security-quality-violations-by-type.csv → Done/157.1-security-quality-violations-by-type.csv} +0 -0
|
@@ -8,6 +8,11 @@
|
|
|
8
8
|
|
|
9
9
|
'use strict';
|
|
10
10
|
|
|
11
|
+
const {
|
|
12
|
+
CHATGPT_RUNTIME_SYSTEM_KEY,
|
|
13
|
+
COPILOT_RUNTIME_SYSTEM_KEY
|
|
14
|
+
} = require('./chatgpt-runtime-contract');
|
|
15
|
+
|
|
11
16
|
/** @typedef {'teams-bot'|'slack'|'microsoft-copilot'|'chatgpt'|'web-embed'} ChannelTargetKey */
|
|
12
17
|
|
|
13
18
|
const DEFAULT_CAPABILITIES = ['chat', 'notify', 'documentApproval'];
|
|
@@ -44,6 +49,7 @@ const CHANNEL_TARGETS = {
|
|
|
44
49
|
artifactFileName: 'channel-microsoft-copilot.json',
|
|
45
50
|
artifactFormat: 'json',
|
|
46
51
|
credentialKey: 'microsoft-copilot-channel',
|
|
52
|
+
routeSystemKey: COPILOT_RUNTIME_SYSTEM_KEY,
|
|
47
53
|
capabilities: [...DEFAULT_CAPABILITIES, 'enterpriseActions'],
|
|
48
54
|
approvalRequired: true,
|
|
49
55
|
experimental: false
|
|
@@ -55,6 +61,7 @@ const CHANNEL_TARGETS = {
|
|
|
55
61
|
artifactFileName: 'channel-chatgpt.json',
|
|
56
62
|
artifactFormat: 'json',
|
|
57
63
|
credentialKey: 'chatgpt-channel',
|
|
64
|
+
routeSystemKey: CHATGPT_RUNTIME_SYSTEM_KEY,
|
|
58
65
|
capabilities: ['chat', 'enterpriseActions'],
|
|
59
66
|
approvalRequired: true,
|
|
60
67
|
experimental: false
|
|
@@ -106,10 +113,27 @@ function getDefaultChannelDescription() {
|
|
|
106
113
|
);
|
|
107
114
|
}
|
|
108
115
|
|
|
116
|
+
/**
|
|
117
|
+
* Human-readable supported channel list for CLI help and error hints.
|
|
118
|
+
* @returns {string}
|
|
119
|
+
*/
|
|
120
|
+
function formatSupportedChannelTargetsHelp() {
|
|
121
|
+
const stable = CHANNEL_TARGET_KEYS.filter((key) => !CHANNEL_TARGETS[key].experimental);
|
|
122
|
+
const experimental = CHANNEL_TARGET_KEYS.filter((key) => CHANNEL_TARGETS[key].experimental);
|
|
123
|
+
const lines = ['Supported channels:', ` ${stable.join(', ')}`];
|
|
124
|
+
if (experimental.length > 0) {
|
|
125
|
+
lines.push(
|
|
126
|
+
` ${experimental.join(', ')} (experimental — scaffold with --allow-experimental)`
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
return lines.join('\n');
|
|
130
|
+
}
|
|
131
|
+
|
|
109
132
|
module.exports = {
|
|
110
133
|
CHANNEL_TARGETS,
|
|
111
134
|
CHANNEL_TARGET_KEYS,
|
|
112
135
|
isChannelTargetKey,
|
|
113
136
|
getChannelTarget,
|
|
114
|
-
getDefaultChannelDescription
|
|
137
|
+
getDefaultChannelDescription,
|
|
138
|
+
formatSupportedChannelTargetsHelp
|
|
115
139
|
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChatGPT custom MCP app runtime contract constants (plan 163).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Runtime-orchestration MCP contract fields used by chatgpt channel templates and probes
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const RUNTIME_ORCHESTRATION_SYSTEM_KEY = 'runtime-orchestration';
|
|
12
|
+
|
|
13
|
+
const CHATGPT_RUNTIME_SYSTEM_KEY = RUNTIME_ORCHESTRATION_SYSTEM_KEY;
|
|
14
|
+
const CHATGPT_RUNTIME_TRANSPORT = 'streamable-http';
|
|
15
|
+
const CHATGPT_RUNTIME_AUTH_MODE = 'oauth21-authorization-code-pkce-s256';
|
|
16
|
+
|
|
17
|
+
const COPILOT_RUNTIME_SYSTEM_KEY = RUNTIME_ORCHESTRATION_SYSTEM_KEY;
|
|
18
|
+
const COPILOT_RUNTIME_TRANSPORT = 'streamable-http';
|
|
19
|
+
const COPILOT_RUNTIME_AUTH_MODE = 'microsoft-entra-sso-or-oauth';
|
|
20
|
+
|
|
21
|
+
module.exports = {
|
|
22
|
+
RUNTIME_ORCHESTRATION_SYSTEM_KEY,
|
|
23
|
+
CHATGPT_RUNTIME_SYSTEM_KEY,
|
|
24
|
+
CHATGPT_RUNTIME_TRANSPORT,
|
|
25
|
+
CHATGPT_RUNTIME_AUTH_MODE,
|
|
26
|
+
COPILOT_RUNTIME_SYSTEM_KEY,
|
|
27
|
+
COPILOT_RUNTIME_TRANSPORT,
|
|
28
|
+
COPILOT_RUNTIME_AUTH_MODE
|
|
29
|
+
};
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Microsoft Copilot package artifact generation (plan 164).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Build source files, package ZIP, and lifecycle summary for microsoft-copilot channel
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const crypto = require('crypto');
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
const path = require('path');
|
|
14
|
+
const AdmZip = require('adm-zip');
|
|
15
|
+
|
|
16
|
+
const PLACEHOLDER_ICON_BASE64 =
|
|
17
|
+
'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO2s9WQAAAAASUVORK5CYII=';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {string} outputPath
|
|
21
|
+
* @param {Object} runtimeValues
|
|
22
|
+
* @returns {Object}
|
|
23
|
+
*/
|
|
24
|
+
function buildCopilotOutputPaths(outputPath, runtimeValues) {
|
|
25
|
+
const rootDir = path.dirname(outputPath);
|
|
26
|
+
const sourceDir = path.join(rootDir, 'source');
|
|
27
|
+
const buildDir = path.join(rootDir, 'build');
|
|
28
|
+
const installDir = path.join(rootDir, 'install');
|
|
29
|
+
const environment = String(runtimeValues.environment || 'dev').trim() || 'dev';
|
|
30
|
+
const zipFileName = `appPackage.${environment}.zip`;
|
|
31
|
+
return {
|
|
32
|
+
rootDir,
|
|
33
|
+
sourceDir,
|
|
34
|
+
buildDir,
|
|
35
|
+
installDir,
|
|
36
|
+
summaryPath: outputPath,
|
|
37
|
+
zipFileName,
|
|
38
|
+
zipPath: path.join(buildDir, zipFileName),
|
|
39
|
+
validationPath: path.join(installDir, 'validation.json'),
|
|
40
|
+
installPath: path.join(installDir, 'README.md')
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @returns {{ color: Buffer, outline: Buffer }}
|
|
46
|
+
*/
|
|
47
|
+
function getPlaceholderIcons() {
|
|
48
|
+
const icon = Buffer.from(PLACEHOLDER_ICON_BASE64, 'base64');
|
|
49
|
+
return { color: icon, outline: icon };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @param {Object} runtimeValues
|
|
54
|
+
* @param {(templatePath: string, context: Object) => string} renderTemplateFile
|
|
55
|
+
* @param {string} templatesDir
|
|
56
|
+
* @returns {{ sourceFiles: Record<string, string>, installText: string }}
|
|
57
|
+
*/
|
|
58
|
+
function renderCopilotTemplates(runtimeValues, renderTemplateFile, templatesDir) {
|
|
59
|
+
const sourceFiles = {
|
|
60
|
+
'manifest.json': renderTemplateFile(path.join(templatesDir, 'manifest.template.json.hbs'), runtimeValues),
|
|
61
|
+
'declarativeAgent.json': renderTemplateFile(
|
|
62
|
+
path.join(templatesDir, 'declarative-agent.template.json.hbs'),
|
|
63
|
+
runtimeValues
|
|
64
|
+
),
|
|
65
|
+
'ai-plugin.json': renderTemplateFile(
|
|
66
|
+
path.join(templatesDir, 'ai-plugin.template.json.hbs'),
|
|
67
|
+
runtimeValues
|
|
68
|
+
)
|
|
69
|
+
};
|
|
70
|
+
const installText = renderTemplateFile(path.join(templatesDir, 'install.template.md.hbs'), runtimeValues);
|
|
71
|
+
return { sourceFiles, installText };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* @param {Record<string, string>} sourceFiles
|
|
76
|
+
* @param {(content: string) => void} assertNoSecretsInArtifact
|
|
77
|
+
*/
|
|
78
|
+
function assertNoSecretsInSourceFiles(sourceFiles, assertNoSecretsInArtifact) {
|
|
79
|
+
for (const content of Object.values(sourceFiles)) {
|
|
80
|
+
assertNoSecretsInArtifact(content);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @param {Record<string, string>} sourceFiles
|
|
86
|
+
* @param {{ color: Buffer, outline: Buffer }} icons
|
|
87
|
+
* @returns {Buffer}
|
|
88
|
+
*/
|
|
89
|
+
function buildCopilotZipBuffer(sourceFiles, icons) {
|
|
90
|
+
const zip = new AdmZip();
|
|
91
|
+
zip.addFile('manifest.json', Buffer.from(sourceFiles['manifest.json'], 'utf8'));
|
|
92
|
+
zip.addFile('declarativeAgent.json', Buffer.from(sourceFiles['declarativeAgent.json'], 'utf8'));
|
|
93
|
+
zip.addFile('ai-plugin.json', Buffer.from(sourceFiles['ai-plugin.json'], 'utf8'));
|
|
94
|
+
zip.addFile('color.png', icons.color);
|
|
95
|
+
zip.addFile('outline.png', icons.outline);
|
|
96
|
+
return zip.toBuffer();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* @param {Object} runtimeValues
|
|
101
|
+
* @param {Object} paths
|
|
102
|
+
* @param {string[]} sourceFileNames
|
|
103
|
+
* @returns {Object}
|
|
104
|
+
*/
|
|
105
|
+
function buildCopilotValidation(runtimeValues, paths, sourceFileNames) {
|
|
106
|
+
return {
|
|
107
|
+
tier: 'builderValidated',
|
|
108
|
+
environment: runtimeValues.environment,
|
|
109
|
+
sourceFiles: sourceFileNames,
|
|
110
|
+
zipFile: paths.zipFileName,
|
|
111
|
+
runtimeSystemKey: runtimeValues.runtimeSystemKey,
|
|
112
|
+
runtimeMcpUrl: runtimeValues.mcpUrl,
|
|
113
|
+
runtimeTransport: runtimeValues.runtimeTransport,
|
|
114
|
+
expectedLayerBToolNames: runtimeValues.layerBToolNames || [],
|
|
115
|
+
boundaries: {
|
|
116
|
+
onePackagePerEnvironment: true,
|
|
117
|
+
topLevelVendorToolsExposed: false,
|
|
118
|
+
roleAssistantResolution: 'dynamic-runtime'
|
|
119
|
+
},
|
|
120
|
+
requiresMicrosoftAdmin: [
|
|
121
|
+
'upload-package',
|
|
122
|
+
'tenant-approval',
|
|
123
|
+
'assignment-and-consent',
|
|
124
|
+
'first-copilot-invoke'
|
|
125
|
+
]
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* @param {Array<string|Buffer>} parts
|
|
131
|
+
* @returns {string}
|
|
132
|
+
*/
|
|
133
|
+
function computeCopilotArtifactHash(parts) {
|
|
134
|
+
const hash = crypto.createHash('sha256');
|
|
135
|
+
for (const part of parts) {
|
|
136
|
+
if (Buffer.isBuffer(part)) {
|
|
137
|
+
hash.update(part);
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
hash.update(String(part), 'utf8');
|
|
141
|
+
}
|
|
142
|
+
return hash.digest('hex');
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* @param {Object} runtimeValues
|
|
147
|
+
* @param {Object} paths
|
|
148
|
+
* @param {Object} validation
|
|
149
|
+
* @param {string} artifactHash
|
|
150
|
+
* @returns {Object}
|
|
151
|
+
*/
|
|
152
|
+
function buildCopilotSummary(runtimeValues, paths, validation, artifactHash) {
|
|
153
|
+
return {
|
|
154
|
+
channelTarget: runtimeValues.channelTarget,
|
|
155
|
+
name: runtimeValues.appName,
|
|
156
|
+
baseName: runtimeValues.baseName,
|
|
157
|
+
description: runtimeValues.appDescription,
|
|
158
|
+
environment: runtimeValues.environment,
|
|
159
|
+
runtime: {
|
|
160
|
+
runtimeSystemKey: runtimeValues.runtimeSystemKey,
|
|
161
|
+
remoteMcpUrl: runtimeValues.mcpUrl,
|
|
162
|
+
transport: runtimeValues.runtimeTransport,
|
|
163
|
+
assistantCatalogUrl: runtimeValues.assistantCatalogUrl,
|
|
164
|
+
roleAssistantResolution: 'dynamic-runtime',
|
|
165
|
+
layerBToolNames: runtimeValues.layerBToolNames || []
|
|
166
|
+
},
|
|
167
|
+
authentication: {
|
|
168
|
+
mode: runtimeValues.runtimeAuthMode,
|
|
169
|
+
credentialKey: runtimeValues.credentialKey,
|
|
170
|
+
credentialPortalUrl: runtimeValues.credentialPortalUrl,
|
|
171
|
+
scopes: runtimeValues.scopes || []
|
|
172
|
+
},
|
|
173
|
+
package: {
|
|
174
|
+
appId: runtimeValues.packageAppId,
|
|
175
|
+
version: runtimeValues.packageVersion,
|
|
176
|
+
sourceFiles: ['manifest.json', 'declarativeAgent.json', 'ai-plugin.json', 'color.png', 'outline.png'],
|
|
177
|
+
zipFileName: paths.zipFileName,
|
|
178
|
+
installGuide: path.relative(paths.rootDir, paths.installPath),
|
|
179
|
+
validationFile: path.relative(paths.rootDir, paths.validationPath)
|
|
180
|
+
},
|
|
181
|
+
probeTiers: {
|
|
182
|
+
builderValidated: true,
|
|
183
|
+
runtimeValidated: false,
|
|
184
|
+
requiresMicrosoftAdmin: true
|
|
185
|
+
},
|
|
186
|
+
artifact: {
|
|
187
|
+
format: 'microsoft-365-copilot-package',
|
|
188
|
+
hash: artifactHash,
|
|
189
|
+
generatedAt: new Date().toISOString()
|
|
190
|
+
},
|
|
191
|
+
validation
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* @param {Object} params
|
|
197
|
+
*/
|
|
198
|
+
function writeCopilotArtifacts(params) {
|
|
199
|
+
const { paths, sourceFiles, icons, zipBuffer, installText, validationText, summaryText } = params;
|
|
200
|
+
fs.mkdirSync(paths.sourceDir, { recursive: true });
|
|
201
|
+
fs.mkdirSync(paths.buildDir, { recursive: true });
|
|
202
|
+
fs.mkdirSync(paths.installDir, { recursive: true });
|
|
203
|
+
fs.writeFileSync(path.join(paths.sourceDir, 'manifest.json'), sourceFiles['manifest.json'], 'utf8');
|
|
204
|
+
fs.writeFileSync(
|
|
205
|
+
path.join(paths.sourceDir, 'declarativeAgent.json'),
|
|
206
|
+
sourceFiles['declarativeAgent.json'],
|
|
207
|
+
'utf8'
|
|
208
|
+
);
|
|
209
|
+
fs.writeFileSync(path.join(paths.sourceDir, 'ai-plugin.json'), sourceFiles['ai-plugin.json'], 'utf8');
|
|
210
|
+
fs.writeFileSync(path.join(paths.sourceDir, 'color.png'), icons.color);
|
|
211
|
+
fs.writeFileSync(path.join(paths.sourceDir, 'outline.png'), icons.outline);
|
|
212
|
+
fs.writeFileSync(paths.zipPath, zipBuffer);
|
|
213
|
+
fs.writeFileSync(paths.installPath, installText, 'utf8');
|
|
214
|
+
fs.writeFileSync(paths.validationPath, validationText, 'utf8');
|
|
215
|
+
fs.writeFileSync(paths.summaryPath, summaryText, 'utf8');
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* @param {Object} params
|
|
220
|
+
* @param {Object} params.runtimeValues
|
|
221
|
+
* @param {string} params.templatesDir
|
|
222
|
+
* @param {string} params.outputPath
|
|
223
|
+
* @param {boolean} [params.dryRun]
|
|
224
|
+
* @param {(content: string) => void} params.assertNoSecretsInArtifact
|
|
225
|
+
* @param {(templatePath: string, context: Object) => string} params.renderTemplateFile
|
|
226
|
+
* @returns {{ outputPath: string, artifactHash: string, content: string, installPath: string }}
|
|
227
|
+
*/
|
|
228
|
+
function generateMicrosoftCopilotPackage(params) {
|
|
229
|
+
const runtimeValues = params.runtimeValues || {};
|
|
230
|
+
const paths = buildCopilotOutputPaths(params.outputPath, runtimeValues);
|
|
231
|
+
const icons = getPlaceholderIcons();
|
|
232
|
+
const { sourceFiles, installText } = renderCopilotTemplates(
|
|
233
|
+
runtimeValues,
|
|
234
|
+
params.renderTemplateFile,
|
|
235
|
+
params.templatesDir
|
|
236
|
+
);
|
|
237
|
+
assertNoSecretsInSourceFiles(sourceFiles, params.assertNoSecretsInArtifact);
|
|
238
|
+
params.assertNoSecretsInArtifact(installText);
|
|
239
|
+
const zipBuffer = buildCopilotZipBuffer(sourceFiles, icons);
|
|
240
|
+
const validation = buildCopilotValidation(runtimeValues, paths, Object.keys(sourceFiles));
|
|
241
|
+
const validationText = JSON.stringify(validation, null, 2);
|
|
242
|
+
const artifactHash = computeCopilotArtifactHash([
|
|
243
|
+
sourceFiles['manifest.json'],
|
|
244
|
+
sourceFiles['declarativeAgent.json'],
|
|
245
|
+
sourceFiles['ai-plugin.json'],
|
|
246
|
+
installText,
|
|
247
|
+
validationText,
|
|
248
|
+
zipBuffer
|
|
249
|
+
]);
|
|
250
|
+
const summary = buildCopilotSummary(runtimeValues, paths, validation, artifactHash);
|
|
251
|
+
const summaryText = JSON.stringify(summary, null, 2);
|
|
252
|
+
params.assertNoSecretsInArtifact(summaryText);
|
|
253
|
+
if (!params.dryRun) {
|
|
254
|
+
writeCopilotArtifacts({
|
|
255
|
+
paths,
|
|
256
|
+
sourceFiles,
|
|
257
|
+
icons,
|
|
258
|
+
zipBuffer,
|
|
259
|
+
installText,
|
|
260
|
+
validationText,
|
|
261
|
+
summaryText
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
return {
|
|
265
|
+
outputPath: paths.summaryPath,
|
|
266
|
+
artifactHash,
|
|
267
|
+
content: summaryText,
|
|
268
|
+
installPath: paths.installPath
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
module.exports = {
|
|
273
|
+
generateMicrosoftCopilotPackage,
|
|
274
|
+
buildCopilotOutputPaths,
|
|
275
|
+
renderCopilotTemplates,
|
|
276
|
+
buildCopilotZipBuffer,
|
|
277
|
+
buildCopilotValidation,
|
|
278
|
+
buildCopilotSummary,
|
|
279
|
+
computeCopilotArtifactHash
|
|
280
|
+
};
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve Runtime Layer B tool names from Dataplane.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Runtime-orchestration MCP tool discovery for channel artifacts and probes
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.1.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const { createDataplaneApiClient } = require('../api/index');
|
|
12
|
+
const { getChannelTarget } = require('./channel-targets');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Prefer the first-party MCP gateway catalog, then MCP OpenAPI, then legacy paths.
|
|
16
|
+
*/
|
|
17
|
+
const TOOL_CATALOG_BUILDERS = Object.freeze([
|
|
18
|
+
(systemKey) =>
|
|
19
|
+
`/api/v1/mcp/servers/tools?filter=${encodeURIComponent(`systemKey:eq:${systemKey}`)}&pageSize=100`,
|
|
20
|
+
(systemKey) => `/api/v1/mcp/${systemKey}/docs/mcp-openapi.json`,
|
|
21
|
+
(systemKey) => `/api/v1/external/systems/${systemKey}/mcp/tools`,
|
|
22
|
+
(systemKey) => `/api/v1/external/systems/${systemKey}/mcp/tools/list`,
|
|
23
|
+
(systemKey) => `/api/v1/external/systems/${systemKey}/mcp/catalog`,
|
|
24
|
+
(systemKey) => `/api/v1/external/systems/${systemKey}/tools`
|
|
25
|
+
]);
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @param {unknown} value
|
|
29
|
+
* @returns {string[]}
|
|
30
|
+
*/
|
|
31
|
+
function extractToolNames(value) {
|
|
32
|
+
if (Array.isArray(value)) {
|
|
33
|
+
return value
|
|
34
|
+
.map((item) => {
|
|
35
|
+
if (typeof item === 'string') return item.trim();
|
|
36
|
+
if (!item || typeof item !== 'object') return '';
|
|
37
|
+
return String(item.name || item.toolName || item.key || '').trim();
|
|
38
|
+
})
|
|
39
|
+
.filter(Boolean);
|
|
40
|
+
}
|
|
41
|
+
if (!value || typeof value !== 'object') {
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
const body = /** @type {Record<string, unknown>} */ (value);
|
|
45
|
+
if (body.paths && typeof body.paths === 'object') {
|
|
46
|
+
return extractToolNamesFromOpenApiPaths(body.paths);
|
|
47
|
+
}
|
|
48
|
+
const candidates = [body.tools, body.items, body.data, body.result];
|
|
49
|
+
for (const candidate of candidates) {
|
|
50
|
+
const names = extractToolNames(candidate);
|
|
51
|
+
if (names.length > 0) {
|
|
52
|
+
return names;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return [];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @param {Record<string, unknown>} paths
|
|
60
|
+
* @returns {string[]}
|
|
61
|
+
*/
|
|
62
|
+
function extractToolNamesFromOpenApiPaths(paths) {
|
|
63
|
+
const names = [];
|
|
64
|
+
for (const pathKey of Object.keys(paths || {})) {
|
|
65
|
+
const match = String(pathKey).match(/\/tools\/([^/]+)\/execute$/);
|
|
66
|
+
if (match && match[1] && match[1] !== 'execute') {
|
|
67
|
+
names.push(match[1]);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return [...new Set(names)];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* @param {string} routeSystemKey
|
|
75
|
+
* @returns {string[]}
|
|
76
|
+
*/
|
|
77
|
+
function buildToolCatalogEndpoints(routeSystemKey) {
|
|
78
|
+
return TOOL_CATALOG_BUILDERS.map((build) => build(routeSystemKey));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @param {Object} response
|
|
83
|
+
* @returns {string[]}
|
|
84
|
+
*/
|
|
85
|
+
function extractToolNamesFromClientResponse(response) {
|
|
86
|
+
const direct = extractToolNames(response);
|
|
87
|
+
if (direct.length > 0) return preferLayerBToolNames(direct);
|
|
88
|
+
return preferLayerBToolNames(extractToolNames(response?.data ?? response));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Prefer MCP Layer B names (`work.start`) over REST-ish operation ids.
|
|
93
|
+
*
|
|
94
|
+
* @param {string[]} names
|
|
95
|
+
* @returns {string[]}
|
|
96
|
+
*/
|
|
97
|
+
function preferLayerBToolNames(names) {
|
|
98
|
+
const list = Array.isArray(names) ? names : [];
|
|
99
|
+
const dotted = list.filter((name) => /^[a-z][a-z0-9]*\.[a-z][a-z0-9.]*$/i.test(name));
|
|
100
|
+
return dotted.length > 0 ? dotted : list;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* @param {string} dataplaneUrl
|
|
105
|
+
* @param {Object} authConfig
|
|
106
|
+
* @param {string} channelTarget
|
|
107
|
+
* @returns {Promise<string[]>}
|
|
108
|
+
*/
|
|
109
|
+
async function fetchRuntimeLayerBToolNames(dataplaneUrl, authConfig, channelTarget) {
|
|
110
|
+
const target = getChannelTarget(channelTarget);
|
|
111
|
+
const routeSystemKey = target.routeSystemKey || target.key;
|
|
112
|
+
const client = createDataplaneApiClient(dataplaneUrl, authConfig);
|
|
113
|
+
const endpoints = buildToolCatalogEndpoints(routeSystemKey);
|
|
114
|
+
for (const endpoint of endpoints) {
|
|
115
|
+
try {
|
|
116
|
+
const response = await client.get(endpoint, { timeoutMs: 10000 });
|
|
117
|
+
const names = extractToolNamesFromClientResponse(response);
|
|
118
|
+
if (Array.isArray(names) && names.length > 0) {
|
|
119
|
+
return [...new Set(names)].sort();
|
|
120
|
+
}
|
|
121
|
+
} catch {
|
|
122
|
+
// Try the next endpoint candidate.
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return [];
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* True when Runtime MCP gateway docs or tool catalog is reachable.
|
|
130
|
+
*
|
|
131
|
+
* @async
|
|
132
|
+
* @param {string} dataplaneUrl
|
|
133
|
+
* @param {Object} authConfig
|
|
134
|
+
* @param {string} routeSystemKey
|
|
135
|
+
* @returns {Promise<boolean>}
|
|
136
|
+
*/
|
|
137
|
+
async function isRuntimeMcpGatewayReachable(dataplaneUrl, authConfig, routeSystemKey) {
|
|
138
|
+
if (!dataplaneUrl || !routeSystemKey) return false;
|
|
139
|
+
const client = createDataplaneApiClient(dataplaneUrl, authConfig);
|
|
140
|
+
const candidates = [
|
|
141
|
+
`/api/v1/mcp/${routeSystemKey}/docs/mcp-openapi.json`,
|
|
142
|
+
`/api/v1/mcp/servers/tools?filter=${encodeURIComponent(`systemKey:eq:${routeSystemKey}`)}&pageSize=1`
|
|
143
|
+
];
|
|
144
|
+
for (const endpoint of candidates) {
|
|
145
|
+
try {
|
|
146
|
+
const response = await client.get(endpoint, { timeoutMs: 8000 });
|
|
147
|
+
if (response && response.success !== false) {
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
} catch {
|
|
151
|
+
// try next
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
module.exports = {
|
|
158
|
+
TOOL_CATALOG_BUILDERS,
|
|
159
|
+
extractToolNames,
|
|
160
|
+
extractToolNamesFromOpenApiPaths,
|
|
161
|
+
preferLayerBToolNames,
|
|
162
|
+
buildToolCatalogEndpoints,
|
|
163
|
+
fetchRuntimeLayerBToolNames,
|
|
164
|
+
isRuntimeMcpGatewayReachable
|
|
165
|
+
};
|
package/lib/cli/index.js
CHANGED
|
@@ -24,6 +24,7 @@ const { setupDatasourceCommands } = require('../commands/datasource');
|
|
|
24
24
|
const { setupDimensionCommands } = require('../commands/dimension');
|
|
25
25
|
const { setupResourceTypeCommands } = require('../commands/resource-type');
|
|
26
26
|
const { setupRoleCommands } = require('../commands/role');
|
|
27
|
+
const { setupRoleAssistantCommands } = require('../commands/role-assistant');
|
|
27
28
|
const { setupEvidenceKindCommands } = require('../commands/evidence-kind');
|
|
28
29
|
const { setupEnterpriseKnowledgeCommands } = require('../commands/enterprise-knowledge');
|
|
29
30
|
const { setupIdentityCommands } = require('../commands/identity');
|
|
@@ -76,6 +77,7 @@ function setupExtendedCliCommands(program) {
|
|
|
76
77
|
setupDimensionCommands(program);
|
|
77
78
|
setupResourceTypeCommands(program);
|
|
78
79
|
setupRoleCommands(program);
|
|
80
|
+
setupRoleAssistantCommands(program);
|
|
79
81
|
setupEvidenceKindCommands(program);
|
|
80
82
|
setupEnterpriseKnowledgeCommands(program);
|
|
81
83
|
setupIdentityCommands(program);
|
|
@@ -95,7 +95,7 @@ function logPlatformSetupDurationHint(scope = 'platform') {
|
|
|
95
95
|
const line =
|
|
96
96
|
scope === 'dataplane'
|
|
97
97
|
? 'Installation may take a few minutes. Authenticating and starting Dataplane — please wait.'
|
|
98
|
-
: 'Installation may take a few minutes. Keycloak, Miso Controller, and
|
|
98
|
+
: 'Installation may take a few minutes. Keycloak, Miso Controller, Dataplane, and Builder API are starting — please wait.';
|
|
99
99
|
logger.log(chalk.yellow(`⚠ ${line}`));
|
|
100
100
|
}
|
|
101
101
|
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Consolidate deferred public-URL health warnings for guided install UX.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const logger = require('../utils/logger');
|
|
8
|
+
const { formatWarningLine } = require('../utils/cli-test-layout-chalk');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {string} message
|
|
12
|
+
* @returns {{ kind: 'dns'|'localhost', url: string }|null}
|
|
13
|
+
*/
|
|
14
|
+
function extractPublicUrlFromWarning(message) {
|
|
15
|
+
const text = String(message || '');
|
|
16
|
+
const dnsMatch = text.match(/Public URL was not verified \(DNS\):\s*(\S+)/);
|
|
17
|
+
if (dnsMatch) {
|
|
18
|
+
return { kind: 'dns', url: dnsMatch[1].replace(/\.$/, '') };
|
|
19
|
+
}
|
|
20
|
+
const match = text.match(/Public URL was not verified:\s*(\S+)/);
|
|
21
|
+
if (match) {
|
|
22
|
+
return { kind: 'localhost', url: match[1].replace(/\.$/, '') };
|
|
23
|
+
}
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Print one consolidated public-URL warning (avoid N near-duplicate lines).
|
|
29
|
+
* @param {string[]} messages
|
|
30
|
+
*/
|
|
31
|
+
function flushDeferredPublicUrlWarnings(messages) {
|
|
32
|
+
const list = (messages || []).filter(Boolean);
|
|
33
|
+
if (list.length === 0) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const parsed = list.map(extractPublicUrlFromWarning).filter(Boolean);
|
|
37
|
+
if (parsed.length === 0) {
|
|
38
|
+
for (const message of list) {
|
|
39
|
+
logger.log(formatWarningLine(message));
|
|
40
|
+
}
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const urls = [...new Set(parsed.map((row) => row.url))];
|
|
44
|
+
const hasDns = parsed.some((row) => row.kind === 'dns');
|
|
45
|
+
const urlPart = urls.length === 1 ? urls[0] : urls.join(', ');
|
|
46
|
+
const detail = hasDns
|
|
47
|
+
? 'Hostname DNS and/or Traefik routing/TLS could not be verified; health succeeded via localhost only.'
|
|
48
|
+
: 'Health checks succeeded via localhost only. Validate Traefik routing, TLS, and DNS.';
|
|
49
|
+
logger.log(formatWarningLine(`Public URL was not verified: ${urlPart}. ${detail}`));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = {
|
|
53
|
+
extractPublicUrlFromWarning,
|
|
54
|
+
flushDeferredPublicUrlWarnings
|
|
55
|
+
};
|