@aifabrix/builder 2.53.0 → 2.54.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/bin/aifabrix.js +2 -2
- package/lib/api/assistants.api.js +8 -5
- package/lib/api/channel-identity.api.js +41 -0
- package/lib/api/evidence-authoring.api.js +5 -1
- package/lib/api/evidence.api.js +2 -0
- package/lib/api/types/evidence.types.js +2 -0
- package/lib/api/work-search.api.js +136 -0
- package/lib/channels/add-channel.js +163 -126
- package/lib/channels/approval-guides/chatgpt.js +14 -18
- package/lib/channels/approval-guides/claude.js +29 -0
- package/lib/channels/approval-guides/index.js +88 -22
- package/lib/channels/approval-guides/mcp-client.js +27 -0
- package/lib/channels/approval-guides/microsoft-copilot.js +52 -3
- package/lib/channels/approval-guides/slack.js +10 -10
- package/lib/channels/approval-guides/teams-bot.js +8 -12
- package/lib/channels/channel-add-continuations.js +91 -0
- package/lib/channels/channel-add-ensure.js +124 -27
- package/lib/channels/channel-add-existing.js +160 -28
- package/lib/channels/channel-add-failure.js +60 -0
- package/lib/channels/channel-add-remaining.js +486 -0
- package/lib/channels/channel-add-tty.js +190 -0
- package/lib/channels/channel-add-wizard-config.js +138 -0
- package/lib/channels/channel-add-wizard.js +250 -0
- package/lib/channels/channel-artifact-generator.js +27 -13
- package/lib/channels/channel-cardinality.js +83 -0
- package/lib/channels/channel-catalog-icon.js +45 -0
- package/lib/channels/channel-cli-instructions.js +75 -0
- package/lib/channels/channel-configuration-map.js +213 -0
- package/lib/channels/channel-credential.js +11 -14
- package/lib/channels/channel-definition-project.js +101 -0
- package/lib/channels/channel-definition-registry.js +154 -0
- package/lib/channels/channel-description.js +59 -2
- package/lib/channels/channel-discovery.js +16 -2
- package/lib/channels/channel-external-system.js +86 -9
- package/lib/channels/channel-install-envelope-actions.js +88 -0
- package/lib/channels/channel-install-envelope-microsoft.js +155 -0
- package/lib/channels/channel-install-envelope.js +356 -0
- package/lib/channels/channel-install-help-md.js +172 -0
- package/lib/channels/channel-install-http-payload.js +62 -0
- package/lib/channels/channel-install-inventory.js +115 -0
- package/lib/channels/channel-install-profiles.js +90 -0
- package/lib/channels/channel-instance-collision.js +118 -0
- package/lib/channels/channel-instance-key.js +100 -0
- package/lib/channels/channel-instance-materialize.js +240 -0
- package/lib/channels/channel-integration-generator.js +16 -9
- package/lib/channels/channel-integration-template.js +101 -22
- package/lib/channels/channel-inventory-fetch.js +79 -0
- package/lib/channels/channel-oauth-preflight.js +104 -0
- package/lib/channels/channel-package-version.js +76 -0
- package/lib/channels/channel-predefined-client.js +154 -0
- package/lib/channels/channel-probe.js +7 -2
- package/lib/channels/channel-runtime-resolver.js +180 -72
- package/lib/channels/channel-status-display.js +86 -16
- package/lib/channels/channel-targets.js +106 -92
- package/lib/channels/chatgpt-callback.js +318 -0
- package/lib/channels/chatgpt-channel-add.js +229 -0
- package/lib/channels/chatgpt-preflight.js +396 -0
- package/lib/channels/chatgpt-runtime-contract.js +17 -0
- package/lib/channels/chatgpt-setup-values.js +124 -0
- package/lib/channels/claude-callback.js +67 -0
- package/lib/channels/claude-channel-add.js +254 -0
- package/lib/channels/claude-runtime-contract.js +40 -0
- package/lib/channels/claude-runtime.js +58 -0
- package/lib/channels/claude-setup-values.js +89 -0
- package/lib/channels/mcp-client/config-merge.js +148 -0
- package/lib/channels/mcp-client/ensure-client.js +231 -0
- package/lib/channels/mcp-client/paths.js +53 -0
- package/lib/channels/mcp-client/profiles.js +122 -0
- package/lib/channels/mcp-client/redirect-uris.js +99 -0
- package/lib/channels/mcp-client/runtime.js +59 -0
- package/lib/channels/mcp-client-channel-add.js +186 -0
- package/lib/channels/microsoft-copilot-channel-add.js +117 -7
- package/lib/channels/microsoft-copilot-entra-identifier-uris.js +187 -0
- package/lib/channels/microsoft-copilot-entra-sso-form.js +106 -18
- package/lib/channels/microsoft-copilot-entra-sso.js +31 -2
- package/lib/channels/microsoft-copilot-package-prior.js +107 -0
- package/lib/channels/microsoft-copilot-package.js +29 -28
- package/lib/channels/microsoft-provisioning/a365.js +80 -0
- package/lib/channels/microsoft-provisioning/auth-config.js +240 -0
- package/lib/channels/microsoft-provisioning/auth.js +179 -0
- package/lib/channels/microsoft-provisioning/cli.js +71 -0
- package/lib/channels/microsoft-provisioning/constants.js +75 -0
- package/lib/channels/microsoft-provisioning/errors.js +117 -0
- package/lib/channels/microsoft-provisioning/index.js +55 -0
- package/lib/channels/microsoft-provisioning/install-atk.js +158 -0
- package/lib/channels/microsoft-provisioning/install-teams.js +115 -0
- package/lib/channels/microsoft-provisioning/login-portal-device.js +236 -0
- package/lib/channels/microsoft-provisioning/login-portal-parse.js +71 -0
- package/lib/channels/microsoft-provisioning/login-portal-teams.js +193 -0
- package/lib/channels/microsoft-provisioning/login-portal.js +230 -0
- package/lib/channels/microsoft-provisioning/persist.js +110 -0
- package/lib/channels/microsoft-provisioning/teams-bot-args.js +119 -0
- package/lib/channels/microsoft-provisioning/teams-bot-controller.js +123 -0
- package/lib/channels/microsoft-provisioning/teams-bot-parse.js +134 -0
- package/lib/channels/microsoft-provisioning/teams-bot-persist.js +113 -0
- package/lib/channels/microsoft-provisioning/teams-bot-provision.js +234 -0
- package/lib/channels/microsoft-provisioning/teams-bot-secrets.js +45 -0
- package/lib/channels/microsoft-provisioning/teams-cli.js +82 -0
- package/lib/channels/runtime-tool-catalog.js +5 -2
- package/lib/channels/slack-channel-add-portal.js +130 -0
- package/lib/channels/slack-channel-add-tty-auth.js +95 -0
- package/lib/channels/slack-channel-add.js +258 -0
- package/lib/channels/slack-provisioning/apps.js +181 -0
- package/lib/channels/slack-provisioning/auth-store.js +110 -0
- package/lib/channels/slack-provisioning/auth-ticket.js +185 -0
- package/lib/channels/slack-provisioning/auth.js +115 -0
- package/lib/channels/slack-provisioning/callbacks.js +41 -0
- package/lib/channels/slack-provisioning/cli.js +226 -0
- package/lib/channels/slack-provisioning/constants.js +37 -0
- package/lib/channels/slack-provisioning/credentials.js +169 -0
- package/lib/channels/slack-provisioning/curl-shim.js +132 -0
- package/lib/channels/slack-provisioning/developer-install.js +118 -0
- package/lib/channels/slack-provisioning/env-file.js +120 -0
- package/lib/channels/slack-provisioning/errors.js +47 -0
- package/lib/channels/slack-provisioning/go-ca-bundle.js +137 -0
- package/lib/channels/slack-provisioning/index.js +250 -0
- package/lib/channels/slack-provisioning/install-cli.js +323 -0
- package/lib/channels/slack-provisioning/manifest.js +89 -0
- package/lib/channels/slack-provisioning/oauth-lock.js +33 -0
- package/lib/channels/slack-provisioning/offer-cli.js +113 -0
- package/lib/channels/slack-provisioning/onboard-members.js +122 -0
- package/lib/channels/slack-provisioning/onboard.js +89 -0
- package/lib/channels/slack-provisioning/persist.js +95 -0
- package/lib/channels/slack-provisioning/remaining-urls.js +158 -0
- package/lib/channels/slack-provisioning/with-curl-on-path.js +48 -0
- package/lib/channels/teams-bot-channel-add.js +94 -0
- package/lib/channels/vendor-dataplane-url.js +249 -0
- package/lib/cli/setup-certification.help.js +2 -0
- package/lib/cli/setup-external-system-help.js +2 -0
- package/lib/cli/setup-external-system.js +1 -1
- package/lib/commands/channel-add-help.js +366 -0
- package/lib/commands/channel-add-setup.js +162 -80
- package/lib/commands/channel-configure.js +118 -0
- package/lib/commands/channel.js +10 -1
- package/lib/commands/governance-upload-external.js +6 -3
- package/lib/commands/lifecycle-command-action.js +2 -5
- package/lib/commands/lifecycle-external.js +93 -21
- package/lib/commands/repair-datasource-test-payload.js +4 -2
- package/lib/commands/repair-datasource-webhooks-sync-bridge.js +23 -2
- package/lib/commands/repair-datasource.js +3 -0
- package/lib/commands/repair-external-run.js +59 -25
- package/lib/commands/repair-openapi-rest-runtime.js +127 -0
- package/lib/commands/repair-orchestration-tag-merge.js +339 -0
- package/lib/commands/repair-rbac-catalog-defaults.js +96 -0
- package/lib/commands/repair-rbac-platform-preset.js +26 -15
- package/lib/commands/repair-rbac-reader-roles.js +8 -21
- package/lib/commands/repair-rbac.js +10 -34
- package/lib/commands/repair-system-permissions.js +24 -22
- package/lib/commands/role-assistant-test-output.js +14 -0
- package/lib/commands/role-assistant.js +59 -21
- package/lib/commands/test-e2e-external.js +148 -21
- package/lib/commands/upload-credential-push-log.js +2 -1
- package/lib/commands/upload-publish-context.js +1 -1
- package/lib/commands/upload-role-assistant-shell.js +124 -0
- package/lib/commands/upload-sidecar-followups.js +6 -3
- package/lib/commands/upload.js +18 -3
- package/lib/core/secrets-docker-env.js +4 -1
- package/lib/core/secrets-env-content.js +17 -3
- package/lib/datasource/capability/capability-manifest.js +0 -3
- package/lib/datasource/capability/copy-test-payload.js +3 -0
- package/lib/external-system/deploy-helpers.js +26 -1
- package/lib/external-system/deploy.js +10 -6
- package/lib/external-system/download-helpers.js +29 -2
- package/lib/external-system/download-role-assistant.js +83 -4
- package/lib/external-system/download.js +40 -30
- package/lib/external-system/sync-deploy-manifest.js +3 -2
- package/lib/external-system/upload-identity.js +42 -0
- package/lib/generator/index.js +19 -15
- package/lib/generator/split.js +13 -2
- package/lib/lifecycle/role-assistant-governance.js +146 -0
- package/lib/lifecycle/scenario-upload.js +181 -30
- package/lib/programmatic/builder-api-cors.js +143 -0
- package/lib/programmatic/builder-api-request.js +6 -0
- package/lib/programmatic/builder-api-route-dispatch.js +56 -42
- package/lib/programmatic/builder-api-server.js +8 -1
- package/lib/programmatic/capability-registry.js +54 -0
- package/lib/programmatic/channel-install-help-resolve.js +359 -0
- package/lib/programmatic/channel-install-session.js +218 -0
- package/lib/programmatic/help-content/channel-onboarding.md +2 -0
- package/lib/programmatic/help-content/cip-overview.md +3 -1
- package/lib/programmatic/http-raw-response.js +62 -0
- package/lib/programmatic/openapi-channel-install-bindings.js +179 -0
- package/lib/programmatic/openapi-channel-install-schemas.js +286 -0
- package/lib/programmatic/openapi-component-schemas.js +18 -1
- package/lib/programmatic/openapi-description-enricher.js +3 -1
- package/lib/programmatic/openapi-descriptions.js +74 -3
- package/lib/programmatic/openapi-envelope-examples.js +117 -0
- package/lib/programmatic/openapi-operation-bindings.js +4 -1
- package/lib/programmatic/openapi-schema-descriptions-channel.js +316 -0
- package/lib/programmatic/openapi-spec.js +12 -8
- package/lib/programmatic/platform-rbac-catalog.js +36 -18
- package/lib/programmatic/route-handler-map.js +51 -1
- package/lib/programmatic/route-handlers-context.js +2 -1
- package/lib/programmatic/run-auth-permissions.js +54 -0
- package/lib/programmatic/run-channel-catalog.js +196 -0
- package/lib/programmatic/run-channel-install-artifacts.js +137 -0
- package/lib/programmatic/run-channel-install-copilot.js +353 -0
- package/lib/programmatic/run-channel-install-options.js +232 -0
- package/lib/programmatic/run-channel-install-teams-bot.js +204 -0
- package/lib/programmatic/run-channel-install.js +346 -0
- package/lib/programmatic/run-channel-package.js +87 -7
- package/lib/programmatic/workspace-context.js +2 -0
- package/lib/role-assistant/evidence-sync.js +4 -2
- package/lib/role-assistant/evidence-validation-issues.js +51 -0
- package/lib/role-assistant/knowledge-sync.js +10 -4
- package/lib/role-assistant/settings.js +49 -2
- package/lib/role-assistant/test-cases-evaluate.js +30 -2
- package/lib/role-assistant/test-cases-evidence.js +175 -0
- package/lib/role-assistant/test-cases-search.js +229 -0
- package/lib/role-assistant/test-cases.js +37 -4
- package/lib/role-assistant/test-runner-search.js +149 -0
- package/lib/role-assistant/test-runner-workhub-helpers.js +40 -2
- package/lib/role-assistant/test-runner-workhub-soft.js +9 -3
- package/lib/role-assistant/test-runner-workhub.js +29 -11
- package/lib/role-assistant/test-runner.js +16 -1
- package/lib/schema/external-datasource.schema.json +119 -16
- package/lib/schema/external-system.schema.json +159 -2
- package/lib/schema/mcp-client-profile.schema.json +103 -0
- package/lib/utils/app-path-resolve.js +4 -0
- package/lib/utils/authentication-env-template.js +44 -6
- package/lib/utils/credential-secrets-env.js +6 -1
- package/lib/utils/env-copy.js +19 -7
- package/lib/utils/external-env-template.js +20 -2
- package/lib/utils/paths.js +18 -1
- package/lib/utils/platform-shell-package.js +69 -0
- package/lib/utils/port-resolver.js +50 -1
- package/lib/utils/rewrite-name-flag.js +20 -0
- package/lib/utils/role-assistant-paths.js +13 -10
- package/lib/utils/schema-resolver.js +11 -1
- package/lib/utils/secrets-helpers.js +12 -21
- package/lib/utils/token-manager.js +10 -5
- package/lib/validation/validate.js +40 -0
- package/package.json +1 -1
- package/templates/README.md +1 -1
- package/templates/applications/builder-api/Dockerfile +1 -1
- package/templates/applications/builder-api/env.template +7 -0
- package/templates/applications/dataplane/application.yaml +6 -5
- package/templates/applications/dataplane/env.template +2 -2
- package/templates/applications/dataplane/rbac.yaml +7 -2
- package/templates/applications/keycloak/Dockerfile +30 -4
- package/templates/applications/keycloak/application.yaml +2 -2
- package/templates/applications/keycloak/cimd-lenient-parse/AbstractClientIdMetadataDocumentExecutor.java +896 -0
- package/templates/applications/keycloak/cimd-lenient-parse/SOURCE.md +19 -0
- package/templates/applications/keycloak/env.template +3 -0
- package/templates/applications/miso-controller/application.yaml +1 -2
- package/templates/applications/miso-controller/env.template +2 -0
- package/templates/channels/README.md +5 -5
- package/templates/channels/chatgpt/TROUBLESHOOTING.md +51 -0
- package/templates/channels/chatgpt/channel.json +59 -0
- package/templates/channels/chatgpt/icon.svg +1 -0
- package/templates/channels/chatgpt/install.template.md.hbs +20 -95
- package/templates/channels/chatgpt/integration/README.md +1 -1
- package/templates/channels/chatgpt/integration/application.json +2 -2
- package/templates/channels/chatgpt/integration/chatgpt-system.json +49 -4
- package/templates/channels/chatgpt/integration/env.template +2 -4
- package/templates/channels/chatgpt/integration/rbac.json +13 -0
- package/templates/channels/claude/TROUBLESHOOTING.md +41 -0
- package/templates/channels/claude/channel.json +59 -0
- package/templates/channels/claude/icon.svg +1 -0
- package/templates/channels/claude/install.template.md.hbs +21 -0
- package/templates/channels/claude/integration/README.md +14 -0
- package/templates/channels/claude/integration/application.json +15 -0
- package/templates/channels/claude/integration/claude-system.json +59 -0
- package/templates/channels/claude/integration/env.template +2 -0
- package/templates/channels/claude/integration/rbac.json +13 -0
- package/templates/channels/claude/manifest.template.json.hbs +40 -0
- package/templates/channels/mcp-client/channel.json +72 -0
- package/templates/channels/mcp-client/icon.svg +1 -0
- package/templates/channels/mcp-client/install.template.md.hbs +24 -0
- package/templates/channels/mcp-client/integration/README.md +13 -0
- package/templates/channels/mcp-client/integration/application.json +15 -0
- package/templates/channels/mcp-client/integration/env.template +2 -0
- package/templates/channels/mcp-client/integration/mcp-client-system.json +72 -0
- package/templates/channels/mcp-client/integration/rbac.json +13 -0
- package/templates/channels/mcp-client/manifest.template.json.hbs +41 -0
- package/templates/channels/mcp-client/profiles/cursor.json +26 -0
- package/templates/channels/mcp-client/profiles/github-copilot.json +29 -0
- package/templates/channels/mcp-client/profiles/vscode.json +29 -0
- package/templates/channels/microsoft-copilot/channel.json +73 -0
- package/templates/channels/microsoft-copilot/declarative-agent.template.json.hbs +8 -4
- package/templates/channels/microsoft-copilot/entra-sso-registration.template.md.hbs +65 -5
- package/templates/channels/microsoft-copilot/icon.svg +1 -0
- package/templates/channels/microsoft-copilot/install.template.md.hbs +9 -9
- package/templates/channels/microsoft-copilot/integration/README.md +1 -1
- package/templates/channels/microsoft-copilot/integration/application.json +2 -2
- package/templates/channels/microsoft-copilot/integration/env.template +3 -6
- package/templates/channels/microsoft-copilot/integration/microsoft-copilot-system.json +63 -4
- package/templates/channels/microsoft-copilot/integration/rbac.json +13 -0
- package/templates/channels/microsoft-copilot/oauth-plugin-vault-required.template.md.hbs +5 -5
- package/templates/channels/slack/channel.json +223 -0
- package/templates/channels/slack/icon.svg +1 -0
- package/templates/channels/slack/install.template.md.hbs +36 -28
- package/templates/channels/slack/integration/README.md +245 -22
- package/templates/channels/slack/integration/application.json +44 -7
- package/templates/channels/slack/integration/env.template +15 -6
- package/templates/channels/slack/integration/openapi/openapi.json +126 -0
- package/templates/channels/slack/integration/rbac.json +84 -0
- package/templates/channels/slack/integration/slack-datasource-commands.json +154 -0
- package/templates/channels/slack/integration/slack-datasource-conversations.json +28 -3
- package/templates/channels/slack/integration/slack-datasource-events.json +154 -0
- package/templates/channels/slack/integration/slack-datasource-interactive.json +154 -0
- package/templates/channels/slack/integration/slack-datasource-messages.json +40 -2
- package/templates/channels/slack/integration/slack-system.json +155 -77
- package/templates/channels/slack/manifest.template.json.hbs +5 -2
- package/templates/channels/teams-bot/channel.json +161 -0
- package/templates/channels/teams-bot/icon.svg +1 -0
- package/templates/channels/teams-bot/install.template.md.hbs +12 -13
- package/templates/channels/teams-bot/integration/README.md +5 -4
- package/templates/channels/teams-bot/integration/application.json +6 -4
- package/templates/channels/teams-bot/integration/env.template +5 -4
- package/templates/channels/teams-bot/integration/openapi/openapi.json +68 -0
- package/templates/channels/teams-bot/integration/rbac.json +21 -0
- package/templates/channels/teams-bot/integration/teams-bot-datasource-activities.json +154 -0
- package/templates/channels/teams-bot/integration/teams-bot-system.json +128 -23
- package/templates/channels/web-embed/channel.json +60 -0
- package/templates/channels/web-embed/install.template.md.hbs +1 -1
- package/templates/channels/web-embed/integration/README.md +2 -2
- package/templates/channels/web-embed/integration/application.json +2 -2
- package/templates/channels/web-embed/integration/env.template +1 -1
- package/templates/channels/web-embed/integration/rbac.json +13 -0
- package/templates/channels/web-embed/integration/web-embed-system.json +50 -4
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create or reuse Teams Entra SSO auth-config via Agents Toolkit oauth/register.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Capture auth-config id without operators pasting the CLI flag
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const crypto = require('crypto');
|
|
11
|
+
const os = require('os');
|
|
12
|
+
const fs = require('../../internal/fs-real-sync');
|
|
13
|
+
const { AUTH_CONFIG_ENV_KEY, APP_ID_URI_ENV_KEY, TENANT_GUID_RE } = require('./constants');
|
|
14
|
+
const {
|
|
15
|
+
wrapToolkitError,
|
|
16
|
+
missingCopilotCaptureInputsError,
|
|
17
|
+
missingMicrosoftTenantError
|
|
18
|
+
} = require('./errors');
|
|
19
|
+
const { ensureMicrosoftSession } = require('./auth');
|
|
20
|
+
const { runAtk } = require('./cli');
|
|
21
|
+
const {
|
|
22
|
+
readProvisioningState,
|
|
23
|
+
writeProvisioningState,
|
|
24
|
+
isReusableAuthConfig
|
|
25
|
+
} = require('./persist');
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @param {string} environment
|
|
29
|
+
* @returns {string}
|
|
30
|
+
*/
|
|
31
|
+
function stableTeamsAppId(environment) {
|
|
32
|
+
const digest = crypto
|
|
33
|
+
.createHash('sha1')
|
|
34
|
+
.update(`aifabrix-copilot:${environment || 'dev'}`)
|
|
35
|
+
.digest('hex');
|
|
36
|
+
return `${digest.slice(0, 8)}-${digest.slice(8, 12)}-4${digest.slice(13, 16)}-a${digest.slice(17, 20)}-${digest.slice(20, 32)}`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @param {string|null|undefined} value
|
|
41
|
+
* @returns {string|null}
|
|
42
|
+
*/
|
|
43
|
+
function resolveTeamsAppId(value) {
|
|
44
|
+
const raw = typeof value === 'string' ? value.trim() : '';
|
|
45
|
+
if (!raw) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
const match = raw.match(TENANT_GUID_RE);
|
|
49
|
+
return match ? match[0] : null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Packaged manifest id when known; otherwise a stable per-environment fallback.
|
|
54
|
+
* @param {Object} inputs
|
|
55
|
+
* @returns {string}
|
|
56
|
+
*/
|
|
57
|
+
function teamsAppIdForRegister(inputs) {
|
|
58
|
+
return resolveTeamsAppId(inputs.teamsAppId) || stableTeamsAppId(inputs.environment);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @param {Object} params
|
|
63
|
+
* @returns {string}
|
|
64
|
+
*/
|
|
65
|
+
function buildOauthRegisterYaml(params) {
|
|
66
|
+
const name = params.registrationName || 'aifabrix-runtime-mcp-sso';
|
|
67
|
+
const specificApp = Boolean(resolveTeamsAppId(params.teamsAppId));
|
|
68
|
+
return [
|
|
69
|
+
'# yaml-language-server: $schema=https://aka.ms/m365-agents-toolkit/v1.9/yaml.schema.json',
|
|
70
|
+
'version: v1.9',
|
|
71
|
+
'provision:',
|
|
72
|
+
' - uses: oauth/register',
|
|
73
|
+
' with:',
|
|
74
|
+
` name: ${JSON.stringify(name)}`,
|
|
75
|
+
' flow: authorizationCode',
|
|
76
|
+
' appId: ${{TEAMS_APP_ID}}',
|
|
77
|
+
' clientId: ${{AAD_APP_CLIENT_ID}}',
|
|
78
|
+
' identityProvider: MicrosoftEntra',
|
|
79
|
+
' baseUrl: ${{MCP_SERVER_URL}}',
|
|
80
|
+
` applicableToApps: ${specificApp ? 'SpecificApp' : 'AnyApp'}`,
|
|
81
|
+
' targetAudience: HomeTenant',
|
|
82
|
+
' writeToEnvironmentFile:',
|
|
83
|
+
` configurationId: ${AUTH_CONFIG_ENV_KEY}`,
|
|
84
|
+
` applicationIdUri: ${APP_ID_URI_ENV_KEY}`,
|
|
85
|
+
''
|
|
86
|
+
].join('\n');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* @param {string} content
|
|
91
|
+
* @param {string} key
|
|
92
|
+
* @returns {string|null}
|
|
93
|
+
*/
|
|
94
|
+
function readEnvValue(content, key) {
|
|
95
|
+
const match = String(content || '').match(new RegExp(`^${key}\\s*=\\s*(.*)$`, 'm'));
|
|
96
|
+
if (!match) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
return match[1].trim().replace(/^['"]|['"]$/g, '') || null;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* @param {Object} inputs
|
|
104
|
+
* @returns {string}
|
|
105
|
+
*/
|
|
106
|
+
function writeToolkitProject(inputs) {
|
|
107
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'aifabrix-atk-oauth-'));
|
|
108
|
+
const envDir = path.join(dir, 'env');
|
|
109
|
+
fs.mkdirSync(envDir, { recursive: true });
|
|
110
|
+
fs.writeFileSync(path.join(dir, 'm365agents.yml'), buildOauthRegisterYaml(inputs), 'utf8');
|
|
111
|
+
const prior = inputs.priorAuthConfigId ? `${AUTH_CONFIG_ENV_KEY}=${inputs.priorAuthConfigId}\n` : '';
|
|
112
|
+
const envBody =
|
|
113
|
+
`TEAMSFX_ENV=dev\nTEAMS_APP_ID=${teamsAppIdForRegister(inputs)}\n` +
|
|
114
|
+
`AAD_APP_CLIENT_ID=${inputs.clientId}\nMCP_SERVER_URL=${inputs.mcpServerUrl}\n` +
|
|
115
|
+
`${prior}${APP_ID_URI_ENV_KEY}=\n`;
|
|
116
|
+
fs.writeFileSync(path.join(envDir, '.env.dev'), envBody, 'utf8');
|
|
117
|
+
return dir;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* @param {Object} params
|
|
122
|
+
* @returns {Object|null}
|
|
123
|
+
*/
|
|
124
|
+
function resolveCaptureInputs(params) {
|
|
125
|
+
const clientId =
|
|
126
|
+
typeof params.clientId === 'string' && params.clientId.trim() ? params.clientId.trim() : null;
|
|
127
|
+
const mcpServerUrl =
|
|
128
|
+
typeof params.mcpServerUrl === 'string' && params.mcpServerUrl.trim()
|
|
129
|
+
? params.mcpServerUrl.trim()
|
|
130
|
+
: null;
|
|
131
|
+
const tenantId =
|
|
132
|
+
typeof params.expectedTenantId === 'string' && params.expectedTenantId.trim()
|
|
133
|
+
? params.expectedTenantId.trim()
|
|
134
|
+
: null;
|
|
135
|
+
if (!clientId || !mcpServerUrl) {
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
clientId,
|
|
140
|
+
mcpServerUrl,
|
|
141
|
+
tenantId,
|
|
142
|
+
environment: params.environment || 'dev',
|
|
143
|
+
projectRoot: params.projectRoot || process.cwd(),
|
|
144
|
+
registrationName: params.registrationName,
|
|
145
|
+
teamsAppId: resolveTeamsAppId(params.teamsAppId)
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* @param {string} dir
|
|
151
|
+
* @returns {{ authConfigId: string|null, applicationIdUri: string|null }}
|
|
152
|
+
*/
|
|
153
|
+
function readToolkitOutputs(dir) {
|
|
154
|
+
const envPath = path.join(dir, 'env', '.env.dev');
|
|
155
|
+
const content = fs.existsSync(envPath) ? fs.readFileSync(envPath, 'utf8') : '';
|
|
156
|
+
return {
|
|
157
|
+
authConfigId: readEnvValue(content, AUTH_CONFIG_ENV_KEY),
|
|
158
|
+
applicationIdUri: readEnvValue(content, APP_ID_URI_ENV_KEY)
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* @param {Object} inputs
|
|
164
|
+
* @param {Object} session
|
|
165
|
+
* @param {Object} deps
|
|
166
|
+
* @returns {Promise<{ authConfigId: string, applicationIdUri: string|null }>}
|
|
167
|
+
*/
|
|
168
|
+
async function provisionAuthConfig(inputs, session, deps) {
|
|
169
|
+
const dir = writeToolkitProject(inputs);
|
|
170
|
+
try {
|
|
171
|
+
await runAtk(
|
|
172
|
+
session.binary,
|
|
173
|
+
['provision', '--env', 'dev', '--interactive', 'false'],
|
|
174
|
+
{ cwd: dir },
|
|
175
|
+
deps
|
|
176
|
+
);
|
|
177
|
+
const output = readToolkitOutputs(dir);
|
|
178
|
+
if (!output.authConfigId) {
|
|
179
|
+
throw wrapToolkitError(new Error('oauth/register did not write a configuration id'));
|
|
180
|
+
}
|
|
181
|
+
return output;
|
|
182
|
+
} catch (error) {
|
|
183
|
+
if (error && error.code === 'TOOLKIT') {
|
|
184
|
+
throw error;
|
|
185
|
+
}
|
|
186
|
+
throw wrapToolkitError(error);
|
|
187
|
+
} finally {
|
|
188
|
+
try {
|
|
189
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
190
|
+
} catch {
|
|
191
|
+
// temp workspace is best-effort
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* @param {Object} params
|
|
198
|
+
* @param {Object} [deps]
|
|
199
|
+
* @returns {Promise<{ authConfigId: string, applicationIdUri: string|null }|null>}
|
|
200
|
+
*/
|
|
201
|
+
async function captureCopilotAuthConfigId(params, deps = {}) {
|
|
202
|
+
const inputs = resolveCaptureInputs(params);
|
|
203
|
+
if (!inputs) {
|
|
204
|
+
throw missingCopilotCaptureInputsError(params);
|
|
205
|
+
}
|
|
206
|
+
const persisted = readProvisioningState(inputs.projectRoot);
|
|
207
|
+
if (isReusableAuthConfig(persisted, inputs)) {
|
|
208
|
+
return {
|
|
209
|
+
authConfigId: persisted.authConfigId,
|
|
210
|
+
applicationIdUri: persisted.applicationIdUri || null
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
const session = await ensureMicrosoftSession(inputs.tenantId, deps);
|
|
214
|
+
if (!session) {
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
if (!session.tenantId) {
|
|
218
|
+
throw missingMicrosoftTenantError();
|
|
219
|
+
}
|
|
220
|
+
const created = await provisionAuthConfig(inputs, session, deps);
|
|
221
|
+
writeProvisioningState(inputs.projectRoot, {
|
|
222
|
+
environment: inputs.environment,
|
|
223
|
+
tenantId: inputs.tenantId || session.tenantId,
|
|
224
|
+
mcpServerUrl: inputs.mcpServerUrl,
|
|
225
|
+
teamsAppId: teamsAppIdForRegister(inputs),
|
|
226
|
+
authConfigId: created.authConfigId,
|
|
227
|
+
applicationIdUri: created.applicationIdUri
|
|
228
|
+
});
|
|
229
|
+
return created;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
module.exports = {
|
|
233
|
+
stableTeamsAppId,
|
|
234
|
+
resolveTeamsAppId,
|
|
235
|
+
teamsAppIdForRegister,
|
|
236
|
+
buildOauthRegisterYaml,
|
|
237
|
+
readEnvValue,
|
|
238
|
+
resolveCaptureInputs,
|
|
239
|
+
captureCopilotAuthConfigId
|
|
240
|
+
};
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Microsoft 365 session + Entra tenant check via Agents Toolkit CLI.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Interactive login when required; never persist Microsoft tokens
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const { spawn } = require('child_process');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const fs = require('../../internal/fs-real-sync');
|
|
12
|
+
const { TENANT_GUID_RE, ATK_ACCOUNT_NAME } = require('./constants');
|
|
13
|
+
const { microsoftProvisioningError, wrongTenantError, missingMicrosoftTenantError } = require('./errors');
|
|
14
|
+
const { resolveAtkBinary, runAtk, shouldSkipLiveToolkit } = require('./cli');
|
|
15
|
+
const { atkWritableHome, atkInstallEnv } = require('./install-atk');
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @param {string} text
|
|
19
|
+
* @returns {string|null}
|
|
20
|
+
*/
|
|
21
|
+
function extractTenantId(text) {
|
|
22
|
+
if (typeof text !== 'string' || !text.trim()) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
const trimmed = text.trim();
|
|
26
|
+
try {
|
|
27
|
+
const parsed = JSON.parse(trimmed);
|
|
28
|
+
const fromJson = tenantFromUnknown(parsed);
|
|
29
|
+
if (fromJson) {
|
|
30
|
+
return fromJson;
|
|
31
|
+
}
|
|
32
|
+
} catch {
|
|
33
|
+
// fall through to regex / labelled text
|
|
34
|
+
}
|
|
35
|
+
const labelled = trimmed.match(/tenantId["'\s:=]+([0-9a-f-]{36})/i);
|
|
36
|
+
if (labelled) {
|
|
37
|
+
return labelled[1].toLowerCase();
|
|
38
|
+
}
|
|
39
|
+
const match = trimmed.match(TENANT_GUID_RE);
|
|
40
|
+
return match ? match[0].toLowerCase() : null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @param {unknown} value
|
|
45
|
+
* @returns {string|null}
|
|
46
|
+
*/
|
|
47
|
+
function tenantFromUnknown(value) {
|
|
48
|
+
if (!value) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
if (typeof value === 'string') {
|
|
52
|
+
return extractTenantId(value);
|
|
53
|
+
}
|
|
54
|
+
if (Array.isArray(value)) {
|
|
55
|
+
for (const item of value) {
|
|
56
|
+
const found = tenantFromUnknown(item);
|
|
57
|
+
if (found) {
|
|
58
|
+
return found;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
if (typeof value === 'object' && typeof value.tenantId === 'string') {
|
|
64
|
+
return extractTenantId(value.tenantId);
|
|
65
|
+
}
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @param {string} expected
|
|
71
|
+
* @param {string} actual
|
|
72
|
+
* @returns {void}
|
|
73
|
+
*/
|
|
74
|
+
function assertExpectedTenant(expected, actual) {
|
|
75
|
+
if (!expected) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
if (!actual) {
|
|
79
|
+
throw microsoftProvisioningError(
|
|
80
|
+
'Could not determine the signed-in Microsoft tenant. Run: atk auth login m365',
|
|
81
|
+
'TENANT'
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
if (String(expected).toLowerCase() !== String(actual).toLowerCase()) {
|
|
85
|
+
throw wrongTenantError(expected, actual);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* @param {string} bin
|
|
91
|
+
* @param {Object} [deps]
|
|
92
|
+
* @returns {Promise<void>}
|
|
93
|
+
*/
|
|
94
|
+
function loginM365(bin, deps = {}) {
|
|
95
|
+
if (typeof deps.loginImpl === 'function') {
|
|
96
|
+
return deps.loginImpl(bin);
|
|
97
|
+
}
|
|
98
|
+
return new Promise((resolve, reject) => {
|
|
99
|
+
const child = spawn(bin, ['auth', 'login', 'm365'], {
|
|
100
|
+
stdio: 'inherit',
|
|
101
|
+
env: process.env
|
|
102
|
+
});
|
|
103
|
+
child.on('error', reject);
|
|
104
|
+
child.on('close', (code) => {
|
|
105
|
+
if (code === 0) {
|
|
106
|
+
resolve();
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
reject(new Error(`Microsoft login exited with code ${code}`));
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Toolkit `auth list` often prints only the account email. Device-code login
|
|
116
|
+
* writes tenantId.cache.appStudio — use that when the CLI omits the GUID.
|
|
117
|
+
* @param {Object} [deps]
|
|
118
|
+
* @returns {string|null}
|
|
119
|
+
*/
|
|
120
|
+
function readCachedAppStudioTenantId(deps = {}) {
|
|
121
|
+
const filePath = path.join(
|
|
122
|
+
atkWritableHome(atkInstallEnv(deps.env || process.env)),
|
|
123
|
+
'.fx',
|
|
124
|
+
'account',
|
|
125
|
+
`tenantId.cache.${ATK_ACCOUNT_NAME}`
|
|
126
|
+
);
|
|
127
|
+
if (!fs.existsSync(filePath)) {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
return extractTenantId(fs.readFileSync(filePath, 'utf8'));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* @param {{ stdout?: string, stderr?: string }} listed
|
|
135
|
+
* @param {Object} [deps]
|
|
136
|
+
* @returns {string|null}
|
|
137
|
+
*/
|
|
138
|
+
function tenantIdFromListOrCache(listed, deps) {
|
|
139
|
+
const fromList = extractTenantId(`${listed.stdout}\n${listed.stderr}`);
|
|
140
|
+
return fromList || readCachedAppStudioTenantId(deps);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* @param {string} expectedTenant
|
|
145
|
+
* @param {Object} [deps]
|
|
146
|
+
* @returns {Promise<{ binary: string, tenantId: string }|null>}
|
|
147
|
+
*/
|
|
148
|
+
async function ensureMicrosoftSession(expectedTenant, deps = {}) {
|
|
149
|
+
if (shouldSkipLiveToolkit(deps) && !deps.atkBinary && !deps.execFile) {
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
const binary = await resolveAtkBinary(deps);
|
|
153
|
+
if (!binary) {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
let listed = await runAtk(binary, ['auth', 'list'], {}, deps);
|
|
157
|
+
let tenantId = tenantIdFromListOrCache(listed, deps);
|
|
158
|
+
if (!tenantId && process.stdin.isTTY) {
|
|
159
|
+
await loginM365(binary, deps);
|
|
160
|
+
listed = await runAtk(binary, ['auth', 'list'], {}, deps);
|
|
161
|
+
tenantId = tenantIdFromListOrCache(listed, deps);
|
|
162
|
+
}
|
|
163
|
+
if (!tenantId) {
|
|
164
|
+
tenantId = extractTenantId(expectedTenant);
|
|
165
|
+
}
|
|
166
|
+
if (!tenantId) {
|
|
167
|
+
throw missingMicrosoftTenantError();
|
|
168
|
+
}
|
|
169
|
+
assertExpectedTenant(expectedTenant, tenantId);
|
|
170
|
+
return { binary, tenantId };
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
module.exports = {
|
|
174
|
+
extractTenantId,
|
|
175
|
+
assertExpectedTenant,
|
|
176
|
+
loginM365,
|
|
177
|
+
ensureMicrosoftSession,
|
|
178
|
+
readCachedAppStudioTenantId
|
|
179
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spawn Microsoft 365 Agents Toolkit (`atk` / `teamsapp`) without scattering argv.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Documented CLI only; skipped under Jest unless deps allow it
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const { promisify } = require('util');
|
|
10
|
+
const execFileDefault = promisify(require('child_process').execFile);
|
|
11
|
+
const { findOrInstallAtkBinary, atkInstallEnv } = require('./install-atk');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @returns {boolean}
|
|
15
|
+
*/
|
|
16
|
+
function isJestWorker() {
|
|
17
|
+
return Boolean(process.env.JEST_WORKER_ID);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @param {Object} [deps]
|
|
22
|
+
* @returns {boolean}
|
|
23
|
+
*/
|
|
24
|
+
function shouldSkipLiveToolkit(deps = {}) {
|
|
25
|
+
if (deps.allowInTests === true) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
return isJestWorker();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @param {Object} [deps]
|
|
33
|
+
* @returns {Promise<string|null>}
|
|
34
|
+
*/
|
|
35
|
+
async function resolveAtkBinary(deps = {}) {
|
|
36
|
+
if (typeof deps.atkBinary === 'string' && deps.atkBinary.trim()) {
|
|
37
|
+
return deps.atkBinary.trim();
|
|
38
|
+
}
|
|
39
|
+
if (shouldSkipLiveToolkit(deps)) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
return findOrInstallAtkBinary(deps);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @param {string} bin
|
|
47
|
+
* @param {string[]} args
|
|
48
|
+
* @param {Object} [opts]
|
|
49
|
+
* @param {Object} [deps]
|
|
50
|
+
* @returns {Promise<{ stdout: string, stderr: string }>}
|
|
51
|
+
*/
|
|
52
|
+
async function runAtk(bin, args, opts = {}, deps = {}) {
|
|
53
|
+
const execFileImpl = deps.execFile || execFileDefault;
|
|
54
|
+
const result = await execFileImpl(bin, args, {
|
|
55
|
+
cwd: opts.cwd,
|
|
56
|
+
env: atkInstallEnv(opts.env || deps.env || process.env),
|
|
57
|
+
timeout: opts.timeout || 180000,
|
|
58
|
+
maxBuffer: 2 * 1024 * 1024
|
|
59
|
+
});
|
|
60
|
+
return {
|
|
61
|
+
stdout: result && result.stdout ? String(result.stdout) : '',
|
|
62
|
+
stderr: result && result.stderr ? String(result.stderr) : ''
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
module.exports = {
|
|
67
|
+
isJestWorker,
|
|
68
|
+
shouldSkipLiveToolkit,
|
|
69
|
+
resolveAtkBinary,
|
|
70
|
+
runAtk
|
|
71
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Microsoft provisioning constants (Agents Toolkit + Agent 365 preview).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Shared keys and filenames — no Microsoft tokens
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const STATE_KIND = 'microsoft-copilot-entra-sso';
|
|
10
|
+
const STATE_FILE = 'provisioning-state.json';
|
|
11
|
+
const AUTH_CONFIG_ENV_KEY = 'AIFABRIX_SSO_AUTH_ID';
|
|
12
|
+
const APP_ID_URI_ENV_KEY = 'AIFABRIX_SSO_APP_ID_URI';
|
|
13
|
+
const ATK_BINARIES = ['atk', 'teamsapp'];
|
|
14
|
+
const ATK_NPM_PACKAGE = '@microsoft/m365agentstoolkit-cli';
|
|
15
|
+
/** Teams Toolkit CLI public client — same id `atk auth login m365` uses. */
|
|
16
|
+
const ATK_M365_CLIENT_ID = '7ea7c24c-b1f6-4a20-9d11-9ae12e9e7ac0';
|
|
17
|
+
const ATK_APP_STUDIO_SCOPE = 'https://dev.teams.microsoft.com/AppDefinitions.ReadWrite';
|
|
18
|
+
const ATK_DEVICE_LOGIN_URL = 'https://microsoft.com/devicelogin';
|
|
19
|
+
const ATK_ACCOUNT_NAME = 'appStudio';
|
|
20
|
+
const TEAMS_BINARIES = ['teams'];
|
|
21
|
+
const TEAMS_BOT_STATE_KIND = 'microsoft-teams-bot';
|
|
22
|
+
const TEAMS_BOT_STATE_FILE = 'provisioning-state.json';
|
|
23
|
+
const TEAMS_CLI_PACKAGE = '@microsoft/teams.cli';
|
|
24
|
+
const TEAMS_OPEN_URL = 'https://teams.microsoft.com';
|
|
25
|
+
const TEAMS_ADMIN_APPS_URL = 'https://admin.teams.microsoft.com/policies/manage-apps';
|
|
26
|
+
const KV_TEAMS_BOT_APP_ID = 'teams-bot/botAppId';
|
|
27
|
+
const KV_TEAMS_BOT_APP_SECRET = 'teams-bot/botAppSecret';
|
|
28
|
+
const TEAMS_POLICY_REMAINING =
|
|
29
|
+
'Approve custom app upload / org publish if tenant policy requires it';
|
|
30
|
+
const TEAMS_CLI_MISSING_REMAINING = [
|
|
31
|
+
`Install Teams Developer CLI (${TEAMS_CLI_PACKAGE}) and run teams login`,
|
|
32
|
+
'Re-run aifabrix channel add teams-bot'
|
|
33
|
+
];
|
|
34
|
+
const TENANT_GUID_RE =
|
|
35
|
+
/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i;
|
|
36
|
+
const SECRET_KEY_RE = /(access|refresh)?token|clientsecret|password|secret/i;
|
|
37
|
+
|
|
38
|
+
const AGENT365_CHECKPOINT = Object.freeze({
|
|
39
|
+
preview: true,
|
|
40
|
+
byoMcpRegisterCli: true,
|
|
41
|
+
declarativeAgentsSupported: false,
|
|
42
|
+
republishSupported: false,
|
|
43
|
+
adminApprovalRequired: true,
|
|
44
|
+
copilotStudioApiAttach: false,
|
|
45
|
+
reason:
|
|
46
|
+
'Agent 365 BYO MCP is preview. Declarative Agents are not a supported BYO client. ' +
|
|
47
|
+
'Republish of a registered remote MCP is not supported. Admin approval remains. ' +
|
|
48
|
+
'Copilot Studio attach is pick-from-registry UI, not an API.'
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
module.exports = {
|
|
52
|
+
STATE_KIND,
|
|
53
|
+
STATE_FILE,
|
|
54
|
+
AUTH_CONFIG_ENV_KEY,
|
|
55
|
+
APP_ID_URI_ENV_KEY,
|
|
56
|
+
ATK_BINARIES,
|
|
57
|
+
ATK_NPM_PACKAGE,
|
|
58
|
+
ATK_M365_CLIENT_ID,
|
|
59
|
+
ATK_APP_STUDIO_SCOPE,
|
|
60
|
+
ATK_DEVICE_LOGIN_URL,
|
|
61
|
+
ATK_ACCOUNT_NAME,
|
|
62
|
+
TEAMS_BINARIES,
|
|
63
|
+
TEAMS_BOT_STATE_KIND,
|
|
64
|
+
TEAMS_BOT_STATE_FILE,
|
|
65
|
+
TEAMS_CLI_PACKAGE,
|
|
66
|
+
TEAMS_OPEN_URL,
|
|
67
|
+
TEAMS_ADMIN_APPS_URL,
|
|
68
|
+
KV_TEAMS_BOT_APP_ID,
|
|
69
|
+
KV_TEAMS_BOT_APP_SECRET,
|
|
70
|
+
TEAMS_POLICY_REMAINING,
|
|
71
|
+
TEAMS_CLI_MISSING_REMAINING,
|
|
72
|
+
TENANT_GUID_RE,
|
|
73
|
+
SECRET_KEY_RE,
|
|
74
|
+
AGENT365_CHECKPOINT
|
|
75
|
+
};
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalize Microsoft provisioning failures for Copilot / Teams Bot.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview User-facing errors without toolkit internals or tokens
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @param {string} message
|
|
11
|
+
* @param {string} [code]
|
|
12
|
+
* @returns {Error}
|
|
13
|
+
*/
|
|
14
|
+
function microsoftProvisioningError(message, code) {
|
|
15
|
+
const error = new Error(message);
|
|
16
|
+
error.code = code || 'MICROSOFT_PROVISIONING';
|
|
17
|
+
return error;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @param {string} expectedTenant
|
|
22
|
+
* @param {string} actualTenant
|
|
23
|
+
* @returns {Error}
|
|
24
|
+
*/
|
|
25
|
+
function wrongTenantError(expectedTenant, actualTenant) {
|
|
26
|
+
return microsoftProvisioningError(
|
|
27
|
+
`Signed-in Microsoft tenant "${actualTenant}" does not match the Entra tenant ` +
|
|
28
|
+
`"${expectedTenant}" configured for this environment.`,
|
|
29
|
+
'WRONG_TENANT'
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @param {unknown} error
|
|
35
|
+
* @returns {Error}
|
|
36
|
+
*/
|
|
37
|
+
function wrapToolkitError(error) {
|
|
38
|
+
const raw = error && error.message ? String(error.message) : String(error);
|
|
39
|
+
const compact = raw.replace(/\s+/g, ' ').trim().slice(0, 400);
|
|
40
|
+
return microsoftProvisioningError(
|
|
41
|
+
`Microsoft 365 Agents Toolkit could not create or read the Entra SSO auth-config. ${compact}`,
|
|
42
|
+
'TOOLKIT'
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @param {string} [text]
|
|
48
|
+
* @returns {string}
|
|
49
|
+
*/
|
|
50
|
+
function redactTeamsSecrets(text) {
|
|
51
|
+
return String(text || '')
|
|
52
|
+
.replace(/CLIENT_SECRET=\S+/gi, 'CLIENT_SECRET=***')
|
|
53
|
+
.replace(/clientSecret["'\s:=]+[^\s]+/gi, 'clientSecret=***');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @param {unknown} error
|
|
58
|
+
* @returns {Error}
|
|
59
|
+
*/
|
|
60
|
+
function wrapTeamsCliError(error) {
|
|
61
|
+
const raw = error && error.message ? String(error.message) : String(error);
|
|
62
|
+
const compact = redactTeamsSecrets(raw.replace(/\s+/g, ' ').trim()).slice(0, 400);
|
|
63
|
+
return microsoftProvisioningError(
|
|
64
|
+
`Teams Developer CLI could not provision the Azure-managed bot. ${compact}`,
|
|
65
|
+
'TEAMS_CLI'
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @param {string} expectedEnvironment
|
|
71
|
+
* @param {string} actualEnvironment
|
|
72
|
+
* @returns {Error}
|
|
73
|
+
*/
|
|
74
|
+
function wrongEnvironmentRegistrationError(expectedEnvironment, actualEnvironment) {
|
|
75
|
+
return microsoftProvisioningError(
|
|
76
|
+
`Microsoft registration belongs to environment "${actualEnvironment}", not "${expectedEnvironment}".`,
|
|
77
|
+
'WRONG_ENVIRONMENT'
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @param {Object} [params]
|
|
83
|
+
* @returns {Error}
|
|
84
|
+
*/
|
|
85
|
+
function missingMicrosoftTenantError() {
|
|
86
|
+
return microsoftProvisioningError(
|
|
87
|
+
'Could not determine the signed-in Microsoft tenant after login. Re-run channel add in a terminal.',
|
|
88
|
+
'TENANT'
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* @param {Object} [params]
|
|
94
|
+
* @returns {Error}
|
|
95
|
+
*/
|
|
96
|
+
function missingCopilotCaptureInputsError(params = {}) {
|
|
97
|
+
const clientId = typeof params.clientId === 'string' && params.clientId.trim();
|
|
98
|
+
const error = microsoftProvisioningError(
|
|
99
|
+
clientId
|
|
100
|
+
? 'Microsoft Copilot setup cannot create Entra SSO until the public MCP URL is available.'
|
|
101
|
+
: 'Microsoft Copilot setup cannot create Entra SSO until this environment has an Entra application id.',
|
|
102
|
+
'CAPTURE_INPUTS'
|
|
103
|
+
);
|
|
104
|
+
error.statusCode = 400;
|
|
105
|
+
return error;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
module.exports = {
|
|
109
|
+
microsoftProvisioningError,
|
|
110
|
+
wrongTenantError,
|
|
111
|
+
wrapToolkitError,
|
|
112
|
+
wrapTeamsCliError,
|
|
113
|
+
redactTeamsSecrets,
|
|
114
|
+
wrongEnvironmentRegistrationError,
|
|
115
|
+
missingCopilotCaptureInputsError,
|
|
116
|
+
missingMicrosoftTenantError
|
|
117
|
+
};
|