@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
|
@@ -1,92 +1,72 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Channel target registry
|
|
2
|
+
* Channel target registry projected from Channel Definitions.
|
|
3
3
|
*
|
|
4
|
-
* @fileoverview
|
|
4
|
+
* @fileoverview CHANNEL_TARGETS is a projection of templates/channels/<key>/channel.json
|
|
5
5
|
* @author AI Fabrix Team
|
|
6
|
-
* @version 1.
|
|
6
|
+
* @version 1.2.0
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
'use strict';
|
|
10
10
|
|
|
11
11
|
const {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
getChannelDefinition,
|
|
13
|
+
getChannelDefinitionMap,
|
|
14
|
+
listChannelDefinitionKeys
|
|
15
|
+
} = require('./channel-definition-registry');
|
|
16
|
+
const { toChannelTargetProjection } = require('./channel-definition-project');
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
function buildChannelTargets() {
|
|
19
|
+
const targets = {};
|
|
20
|
+
for (const [key, definition] of getChannelDefinitionMap().entries()) {
|
|
21
|
+
targets[key] = toChannelTargetProjection(definition);
|
|
22
|
+
}
|
|
23
|
+
return targets;
|
|
24
|
+
}
|
|
17
25
|
|
|
18
|
-
|
|
26
|
+
/** @type {Record<string, Object>|null} */
|
|
27
|
+
let cachedChannelTargets = null;
|
|
19
28
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
channelType: 'teamsBot',
|
|
24
|
-
templateDir: 'teams-bot',
|
|
25
|
-
artifactFileName: 'channel-teams-bot.json',
|
|
26
|
-
artifactFormat: 'json',
|
|
27
|
-
credentialKey: 'teams-bot',
|
|
28
|
-
routeSystemKey: 'teams',
|
|
29
|
-
capabilities: DEFAULT_CAPABILITIES,
|
|
30
|
-
approvalRequired: true,
|
|
31
|
-
experimental: false
|
|
32
|
-
},
|
|
33
|
-
slack: {
|
|
34
|
-
key: 'slack',
|
|
35
|
-
channelType: 'slack',
|
|
36
|
-
templateDir: 'slack',
|
|
37
|
-
artifactFileName: 'channel-slack.json',
|
|
38
|
-
artifactFormat: 'json',
|
|
39
|
-
credentialKey: 'slack-app',
|
|
40
|
-
routeSystemKey: 'slack',
|
|
41
|
-
capabilities: DEFAULT_CAPABILITIES,
|
|
42
|
-
approvalRequired: true,
|
|
43
|
-
experimental: false
|
|
44
|
-
},
|
|
45
|
-
'microsoft-copilot': {
|
|
46
|
-
key: 'microsoft-copilot',
|
|
47
|
-
channelType: 'microsoftCopilot',
|
|
48
|
-
templateDir: 'microsoft-copilot',
|
|
49
|
-
artifactFileName: 'channel-microsoft-copilot.json',
|
|
50
|
-
artifactFormat: 'json',
|
|
51
|
-
credentialKey: 'microsoft-copilot-channel',
|
|
52
|
-
routeSystemKey: COPILOT_RUNTIME_SYSTEM_KEY,
|
|
53
|
-
capabilities: [...DEFAULT_CAPABILITIES, 'enterpriseActions'],
|
|
54
|
-
approvalRequired: true,
|
|
55
|
-
experimental: false
|
|
56
|
-
},
|
|
57
|
-
chatgpt: {
|
|
58
|
-
key: 'chatgpt',
|
|
59
|
-
channelType: 'chatgpt',
|
|
60
|
-
templateDir: 'chatgpt',
|
|
61
|
-
artifactFileName: 'channel-chatgpt.json',
|
|
62
|
-
artifactFormat: 'json',
|
|
63
|
-
credentialKey: 'chatgpt-channel',
|
|
64
|
-
routeSystemKey: CHATGPT_RUNTIME_SYSTEM_KEY,
|
|
65
|
-
capabilities: ['chat', 'enterpriseActions'],
|
|
66
|
-
approvalRequired: true,
|
|
67
|
-
experimental: false
|
|
68
|
-
},
|
|
69
|
-
'web-embed': {
|
|
70
|
-
key: 'web-embed',
|
|
71
|
-
channelType: 'webEmbed',
|
|
72
|
-
templateDir: 'web-embed',
|
|
73
|
-
artifactFileName: 'channel-web-embed.json',
|
|
74
|
-
artifactFormat: 'json',
|
|
75
|
-
credentialKey: 'web-embed-channel',
|
|
76
|
-
capabilities: DEFAULT_CAPABILITIES,
|
|
77
|
-
approvalRequired: false,
|
|
78
|
-
experimental: true
|
|
29
|
+
function resolveChannelTargets() {
|
|
30
|
+
if (cachedChannelTargets && Object.keys(cachedChannelTargets).length > 0) {
|
|
31
|
+
return cachedChannelTargets;
|
|
79
32
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
33
|
+
cachedChannelTargets = buildChannelTargets();
|
|
34
|
+
return cachedChannelTargets;
|
|
35
|
+
}
|
|
83
36
|
|
|
84
37
|
/**
|
|
85
38
|
* @param {string} channelTarget
|
|
86
39
|
* @returns {boolean}
|
|
87
40
|
*/
|
|
88
41
|
function isChannelTargetKey(channelTarget) {
|
|
89
|
-
return typeof channelTarget === 'string' &&
|
|
42
|
+
return typeof channelTarget === 'string' && channelTarget in resolveChannelTargets();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Human-readable supported channel list for CLI help and error hints.
|
|
47
|
+
* @returns {string}
|
|
48
|
+
*/
|
|
49
|
+
function formatSupportedChannelTargetsHelp() {
|
|
50
|
+
const targets = resolveChannelTargets();
|
|
51
|
+
const keys = Object.keys(targets);
|
|
52
|
+
const stable = keys.filter((key) => !targets[key].experimental);
|
|
53
|
+
const experimental = keys.filter((key) => targets[key].experimental);
|
|
54
|
+
const lines = ['Supported channels:', ` ${stable.join(', ')}`];
|
|
55
|
+
if (experimental.length > 0) {
|
|
56
|
+
lines.push(
|
|
57
|
+
` ${experimental.join(', ')} (experimental — scaffold with --allow-experimental)`
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
return lines.join('\n');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @param {string} channelTarget
|
|
65
|
+
* @returns {string}
|
|
66
|
+
*/
|
|
67
|
+
function formatUnknownChannelTargetError(channelTarget) {
|
|
68
|
+
const live = listLiveChannelTargetKeys().join(', ');
|
|
69
|
+
return `Unknown channel: ${channelTarget}\nLive channels: ${live}`;
|
|
90
70
|
}
|
|
91
71
|
|
|
92
72
|
/**
|
|
@@ -95,11 +75,51 @@ function isChannelTargetKey(channelTarget) {
|
|
|
95
75
|
*/
|
|
96
76
|
function getChannelTarget(channelTarget) {
|
|
97
77
|
if (!isChannelTargetKey(channelTarget)) {
|
|
78
|
+
throw new Error(formatUnknownChannelTargetError(channelTarget));
|
|
79
|
+
}
|
|
80
|
+
return resolveChannelTargets()[channelTarget];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Live keys, plus experimental when `--allow-experimental` is set.
|
|
85
|
+
* @param {{ allowExperimental?: boolean }} [options]
|
|
86
|
+
* @returns {string[]}
|
|
87
|
+
*/
|
|
88
|
+
function listLiveChannelTargetKeys(options = {}) {
|
|
89
|
+
const targets = resolveChannelTargets();
|
|
90
|
+
return Object.keys(targets).filter((key) => {
|
|
91
|
+
const target = targets[key];
|
|
92
|
+
return !target.experimental || options.allowExperimental === true;
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Inquirer list choices for `aifabrix channel add` (labels from the registry).
|
|
98
|
+
* @param {{ allowExperimental?: boolean }} [options]
|
|
99
|
+
* @returns {{ name: string, value: string }[]}
|
|
100
|
+
*/
|
|
101
|
+
function listWizardChannelChoices(options = {}) {
|
|
102
|
+
const targets = resolveChannelTargets();
|
|
103
|
+
return listLiveChannelTargetKeys(options)
|
|
104
|
+
.map((key) => targets[key])
|
|
105
|
+
.sort((a, b) => (a.wizardOrder || 100) - (b.wizardOrder || 100))
|
|
106
|
+
.map((target) => ({ name: target.displayLabel, value: target.key }));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Reject experimental targets unless `--allow-experimental` is set.
|
|
111
|
+
* @param {string} channelTarget
|
|
112
|
+
* @param {{ allowExperimental?: boolean }} [options]
|
|
113
|
+
* @returns {typeof CHANNEL_TARGETS[string]}
|
|
114
|
+
*/
|
|
115
|
+
function assertChannelTargetInstallable(channelTarget, options = {}) {
|
|
116
|
+
const target = getChannelTarget(channelTarget);
|
|
117
|
+
if (target.experimental && options.allowExperimental !== true) {
|
|
98
118
|
throw new Error(
|
|
99
|
-
`
|
|
119
|
+
`Channel target "${channelTarget}" is experimental. Pass --allow-experimental to install.`
|
|
100
120
|
);
|
|
101
121
|
}
|
|
102
|
-
return
|
|
122
|
+
return target;
|
|
103
123
|
}
|
|
104
124
|
|
|
105
125
|
/**
|
|
@@ -113,27 +133,21 @@ function getDefaultChannelDescription() {
|
|
|
113
133
|
);
|
|
114
134
|
}
|
|
115
135
|
|
|
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
|
-
|
|
132
136
|
module.exports = {
|
|
133
|
-
CHANNEL_TARGETS
|
|
134
|
-
|
|
137
|
+
get CHANNEL_TARGETS() {
|
|
138
|
+
return resolveChannelTargets();
|
|
139
|
+
},
|
|
140
|
+
get CHANNEL_TARGET_KEYS() {
|
|
141
|
+
return Object.keys(resolveChannelTargets());
|
|
142
|
+
},
|
|
135
143
|
isChannelTargetKey,
|
|
136
144
|
getChannelTarget,
|
|
137
145
|
getDefaultChannelDescription,
|
|
138
|
-
formatSupportedChannelTargetsHelp
|
|
146
|
+
formatSupportedChannelTargetsHelp,
|
|
147
|
+
formatUnknownChannelTargetError,
|
|
148
|
+
listLiveChannelTargetKeys,
|
|
149
|
+
listWizardChannelChoices,
|
|
150
|
+
assertChannelTargetInstallable,
|
|
151
|
+
getChannelDefinition,
|
|
152
|
+
listChannelDefinitionKeys
|
|
139
153
|
};
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Register ChatGPT callback URLs on the existing chatgpt Integration Client.
|
|
3
|
+
*
|
|
4
|
+
* Never rotates the client secret. Catalog sync is additive — extra URIs stay.
|
|
5
|
+
*
|
|
6
|
+
* @fileoverview HTTPS callback validation + idempotent redirect URI merge
|
|
7
|
+
* @author AI Fabrix Team
|
|
8
|
+
* @version 1.0.0
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
'use strict';
|
|
12
|
+
|
|
13
|
+
const {
|
|
14
|
+
listIntegrationClients,
|
|
15
|
+
getIntegrationClient,
|
|
16
|
+
updateIntegrationClientRedirectUris
|
|
17
|
+
} = require('../api/integration-clients.api');
|
|
18
|
+
const {
|
|
19
|
+
CHATGPT_INTEGRATION_CLIENT_KEY,
|
|
20
|
+
CHATGPT_OAUTH2_PROFILE_ID,
|
|
21
|
+
CHATGPT_OAUTH2_PROFILE_PATH
|
|
22
|
+
} = require('./chatgpt-runtime-contract');
|
|
23
|
+
|
|
24
|
+
const CHATGPT_CALLBACK_CONTRACT = {
|
|
25
|
+
integrationClientKey: CHATGPT_INTEGRATION_CLIENT_KEY,
|
|
26
|
+
oauth2ProfileId: CHATGPT_OAUTH2_PROFILE_ID,
|
|
27
|
+
oauth2ProfilePath: CHATGPT_OAUTH2_PROFILE_PATH,
|
|
28
|
+
vendorLabel: 'ChatGPT'
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @param {Object|null|undefined} contract
|
|
33
|
+
* @returns {typeof CHATGPT_CALLBACK_CONTRACT}
|
|
34
|
+
*/
|
|
35
|
+
function resolveCallbackContract(contract) {
|
|
36
|
+
return {
|
|
37
|
+
integrationClientKey: (contract && contract.integrationClientKey) || CHATGPT_CALLBACK_CONTRACT.integrationClientKey,
|
|
38
|
+
oauth2ProfileId: (contract && contract.oauth2ProfileId) || CHATGPT_CALLBACK_CONTRACT.oauth2ProfileId,
|
|
39
|
+
oauth2ProfilePath: (contract && contract.oauth2ProfilePath) || CHATGPT_CALLBACK_CONTRACT.oauth2ProfilePath,
|
|
40
|
+
vendorLabel: (contract && contract.vendorLabel) || CHATGPT_CALLBACK_CONTRACT.vendorLabel
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @param {string} message
|
|
46
|
+
* @param {string} [boundary]
|
|
47
|
+
* @param {Object} [contract]
|
|
48
|
+
* @returns {Error}
|
|
49
|
+
*/
|
|
50
|
+
function createChatGptCallbackError(message, boundary, contract) {
|
|
51
|
+
const resolved = resolveCallbackContract(contract);
|
|
52
|
+
const error = new Error(`${resolved.vendorLabel} callback: ${message}`);
|
|
53
|
+
error.boundary = boundary || 'callback';
|
|
54
|
+
return error;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @param {string|undefined} value
|
|
59
|
+
* @returns {string}
|
|
60
|
+
*/
|
|
61
|
+
function assertHttpsRedirectUri(value, contract) {
|
|
62
|
+
const trimmed = typeof value === 'string' ? value.trim() : '';
|
|
63
|
+
if (!trimmed) {
|
|
64
|
+
throw createChatGptCallbackError('Callback URL is required.', 'callback', contract);
|
|
65
|
+
}
|
|
66
|
+
let parsed;
|
|
67
|
+
try {
|
|
68
|
+
parsed = new URL(trimmed);
|
|
69
|
+
} catch {
|
|
70
|
+
throw createChatGptCallbackError(`Callback URL is not a valid URL: ${trimmed}`, 'callback', contract);
|
|
71
|
+
}
|
|
72
|
+
if (parsed.protocol !== 'https:') {
|
|
73
|
+
throw createChatGptCallbackError(`Callback URL must be HTTPS: ${trimmed}`, 'callback', contract);
|
|
74
|
+
}
|
|
75
|
+
return trimmed;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* @param {string[]|undefined} existing
|
|
80
|
+
* @param {string} nextUri
|
|
81
|
+
* @returns {{ uris: string[], added: boolean }}
|
|
82
|
+
*/
|
|
83
|
+
function mergeRedirectUris(existing, nextUri) {
|
|
84
|
+
const list = Array.isArray(existing)
|
|
85
|
+
? existing.filter((uri) => typeof uri === 'string' && uri.trim())
|
|
86
|
+
: [];
|
|
87
|
+
if (list.some((uri) => uri.trim() === nextUri)) {
|
|
88
|
+
return { uris: list, added: false };
|
|
89
|
+
}
|
|
90
|
+
return { uris: [...list, nextUri], added: true };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* @param {string[]|undefined} existing
|
|
95
|
+
* @param {string[]} nextUris
|
|
96
|
+
* @returns {{ uris: string[], added: boolean }}
|
|
97
|
+
*/
|
|
98
|
+
function mergeRedirectUriList(existing, nextUris) {
|
|
99
|
+
let uris = Array.isArray(existing) ? [...existing] : [];
|
|
100
|
+
let added = false;
|
|
101
|
+
for (const nextUri of nextUris) {
|
|
102
|
+
const merged = mergeRedirectUris(uris, nextUri);
|
|
103
|
+
uris = merged.uris;
|
|
104
|
+
added = added || merged.added;
|
|
105
|
+
}
|
|
106
|
+
return { uris, added };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* @param {string[]|undefined} values
|
|
111
|
+
* @returns {string[]}
|
|
112
|
+
*/
|
|
113
|
+
function normalizeCallbackUrls(values, contract) {
|
|
114
|
+
const unique = [];
|
|
115
|
+
for (const value of Array.isArray(values) ? values : []) {
|
|
116
|
+
const uri = assertHttpsRedirectUri(value, contract);
|
|
117
|
+
if (!unique.includes(uri)) {
|
|
118
|
+
unique.push(uri);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (unique.length === 0) {
|
|
122
|
+
throw createChatGptCallbackError('Callback URL is required.', 'callback', contract);
|
|
123
|
+
}
|
|
124
|
+
return unique;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* @param {Object} response
|
|
129
|
+
* @returns {Object|Array}
|
|
130
|
+
*/
|
|
131
|
+
function unwrapApiBody(response) {
|
|
132
|
+
if (response && response.data && response.data.data !== undefined && response.data.data !== null) {
|
|
133
|
+
return response.data.data;
|
|
134
|
+
}
|
|
135
|
+
if (response && response.data !== undefined) {
|
|
136
|
+
return response.data;
|
|
137
|
+
}
|
|
138
|
+
return response || {};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* @param {Object} response
|
|
143
|
+
* @returns {Array}
|
|
144
|
+
*/
|
|
145
|
+
function unwrapIntegrationClientList(response) {
|
|
146
|
+
const body = unwrapApiBody(response);
|
|
147
|
+
if (Array.isArray(body)) {
|
|
148
|
+
return body;
|
|
149
|
+
}
|
|
150
|
+
if (Array.isArray(body.data)) {
|
|
151
|
+
return body.data;
|
|
152
|
+
}
|
|
153
|
+
if (Array.isArray(body.items)) {
|
|
154
|
+
return body.items;
|
|
155
|
+
}
|
|
156
|
+
return [];
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* @param {Object} response
|
|
161
|
+
* @returns {Object}
|
|
162
|
+
*/
|
|
163
|
+
function unwrapIntegrationClientRecord(response) {
|
|
164
|
+
const body = unwrapApiBody(response);
|
|
165
|
+
return body.integrationClient || body;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* @param {Object} ctx
|
|
170
|
+
* @param {Object} [contract]
|
|
171
|
+
* @returns {string}
|
|
172
|
+
*/
|
|
173
|
+
function chatgptProfileUrl(ctx, contract) {
|
|
174
|
+
const resolved = resolveCallbackContract(contract);
|
|
175
|
+
const base = ctx && typeof ctx.controllerUrl === 'string' ? ctx.controllerUrl.replace(/\/$/, '') : '';
|
|
176
|
+
if (!base) {
|
|
177
|
+
return resolved.oauth2ProfilePath;
|
|
178
|
+
}
|
|
179
|
+
return `${base}${resolved.oauth2ProfilePath}`;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* @param {Object} ctx
|
|
184
|
+
* @param {Object} [contract]
|
|
185
|
+
* @returns {string}
|
|
186
|
+
*/
|
|
187
|
+
function formatMissingChatGptClientError(ctx, contract) {
|
|
188
|
+
const resolved = resolveCallbackContract(contract);
|
|
189
|
+
return [
|
|
190
|
+
`Integration client "${resolved.integrationClientKey}" was not found.`,
|
|
191
|
+
`Open the ${resolved.vendorLabel} OAuth2 profile (${resolved.oauth2ProfileId}): ${chatgptProfileUrl(ctx, resolved)}`,
|
|
192
|
+
`Enable the ${resolved.vendorLabel} profile, then retry callback registration.`
|
|
193
|
+
].join(' ');
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* @param {Error|Object} errorOrResponse
|
|
198
|
+
* @returns {boolean}
|
|
199
|
+
*/
|
|
200
|
+
function isForbiddenClientError(errorOrResponse) {
|
|
201
|
+
const status = errorOrResponse && errorOrResponse.status;
|
|
202
|
+
if (status === 403) {
|
|
203
|
+
return true;
|
|
204
|
+
}
|
|
205
|
+
const message = errorOrResponse && errorOrResponse.message
|
|
206
|
+
? String(errorOrResponse.message)
|
|
207
|
+
: '';
|
|
208
|
+
return /\b403\b/.test(message) || /forbidden|not allowed|integration-client:update/i.test(message);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* @param {Object} ctx
|
|
213
|
+
* @param {Object} [deps]
|
|
214
|
+
* @returns {Promise<Object>}
|
|
215
|
+
*/
|
|
216
|
+
async function findChatGptIntegrationClient(ctx, deps = {}) {
|
|
217
|
+
const contract = resolveCallbackContract(deps.contract);
|
|
218
|
+
const listFn = deps.listIntegrationClients || listIntegrationClients;
|
|
219
|
+
const getFn = deps.getIntegrationClient || getIntegrationClient;
|
|
220
|
+
const response = await listFn(ctx.controllerUrl, ctx.authConfig, { pageSize: 100 });
|
|
221
|
+
if (response && response.success === false) {
|
|
222
|
+
throw createChatGptCallbackError(
|
|
223
|
+
response.formattedError || response.error || 'Failed to list integration clients.',
|
|
224
|
+
response.status === 403 ? 'permissions' : 'callback',
|
|
225
|
+
contract
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
const match = unwrapIntegrationClientList(response).find(
|
|
229
|
+
(row) => row && row.key === contract.integrationClientKey
|
|
230
|
+
);
|
|
231
|
+
if (!match || !match.id) {
|
|
232
|
+
throw createChatGptCallbackError(formatMissingChatGptClientError(ctx, contract), 'callback', contract);
|
|
233
|
+
}
|
|
234
|
+
const detail = await getFn(ctx.controllerUrl, ctx.authConfig, match.id);
|
|
235
|
+
const record = unwrapIntegrationClientRecord(detail);
|
|
236
|
+
return { ...match, ...record, id: match.id };
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* @param {Object} params
|
|
241
|
+
* @param {Object} client
|
|
242
|
+
* @param {string[]} uris
|
|
243
|
+
* @returns {Promise<Object|null>}
|
|
244
|
+
*/
|
|
245
|
+
async function applyRedirectUriUpdate(params, client, uris) {
|
|
246
|
+
const contract = resolveCallbackContract(params.contract);
|
|
247
|
+
const updateFn = params.updateRedirectUris || updateIntegrationClientRedirectUris;
|
|
248
|
+
try {
|
|
249
|
+
const response = await updateFn(params.ctx.controllerUrl, params.ctx.authConfig, client.id, {
|
|
250
|
+
redirectUris: uris
|
|
251
|
+
});
|
|
252
|
+
if (response && response.success === false && response.status === 403) {
|
|
253
|
+
return { ok: false, fallback: true, profileUrl: chatgptProfileUrl(params.ctx, contract) };
|
|
254
|
+
}
|
|
255
|
+
if (response && response.success === false) {
|
|
256
|
+
throw createChatGptCallbackError(
|
|
257
|
+
response.formattedError || response.error || 'Failed to update redirect URIs.',
|
|
258
|
+
'callback',
|
|
259
|
+
contract
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
} catch (error) {
|
|
263
|
+
if (isForbiddenClientError(error)) {
|
|
264
|
+
return { ok: false, fallback: true, profileUrl: chatgptProfileUrl(params.ctx, contract) };
|
|
265
|
+
}
|
|
266
|
+
throw error;
|
|
267
|
+
}
|
|
268
|
+
return null;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Idempotent HTTPS callback registration. Never rotates secrets.
|
|
273
|
+
* @param {Object} params
|
|
274
|
+
* @returns {Promise<{ ok: boolean, added?: boolean, fallback?: boolean, profileUrl?: string, redirectUris?: string[] }>}
|
|
275
|
+
*/
|
|
276
|
+
async function registerChatGptCallbackUrls(params) {
|
|
277
|
+
const contract = resolveCallbackContract(params.contract);
|
|
278
|
+
const callbackUrls = normalizeCallbackUrls(params.callbackUrls, contract);
|
|
279
|
+
let client;
|
|
280
|
+
try {
|
|
281
|
+
client = await findChatGptIntegrationClient(params.ctx, { ...params, contract });
|
|
282
|
+
} catch (error) {
|
|
283
|
+
if (isForbiddenClientError(error)) {
|
|
284
|
+
return { ok: false, fallback: true, profileUrl: chatgptProfileUrl(params.ctx, contract) };
|
|
285
|
+
}
|
|
286
|
+
throw error;
|
|
287
|
+
}
|
|
288
|
+
const merged = mergeRedirectUriList(client.redirectUris, callbackUrls);
|
|
289
|
+
const forbidden = await applyRedirectUriUpdate(params, client, merged.uris);
|
|
290
|
+
if (forbidden) {
|
|
291
|
+
return forbidden;
|
|
292
|
+
}
|
|
293
|
+
return { ok: true, added: merged.added, redirectUris: merged.uris };
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* @param {Object} params
|
|
298
|
+
* @returns {Promise<Object>}
|
|
299
|
+
*/
|
|
300
|
+
async function registerChatGptCallbackUrl(params) {
|
|
301
|
+
return registerChatGptCallbackUrls({
|
|
302
|
+
...params,
|
|
303
|
+
callbackUrls: [params.callbackUrl]
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
module.exports = {
|
|
308
|
+
assertHttpsRedirectUri,
|
|
309
|
+
mergeRedirectUris,
|
|
310
|
+
unwrapIntegrationClientList,
|
|
311
|
+
findChatGptIntegrationClient,
|
|
312
|
+
formatMissingChatGptClientError,
|
|
313
|
+
registerChatGptCallbackUrl,
|
|
314
|
+
registerChatGptCallbackUrls,
|
|
315
|
+
chatgptProfileUrl,
|
|
316
|
+
resolveCallbackContract,
|
|
317
|
+
CHATGPT_CALLBACK_CONTRACT
|
|
318
|
+
};
|