@aifabrix/builder 2.54.1 → 2.55.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/README.md +8 -0
- package/lib/agent-kit/apply-ops.js +82 -0
- package/lib/agent-kit/checksums.js +28 -0
- package/lib/agent-kit/classify.js +113 -0
- package/lib/agent-kit/claude-shim.js +61 -0
- package/lib/agent-kit/constants.js +55 -0
- package/lib/agent-kit/file-list.js +103 -0
- package/lib/agent-kit/host-approve.js +130 -0
- package/lib/agent-kit/hosting/github.js +63 -0
- package/lib/agent-kit/hosts.js +71 -0
- package/lib/agent-kit/init.js +319 -0
- package/lib/agent-kit/kit-root.js +17 -0
- package/lib/agent-kit/managed-section.js +79 -0
- package/lib/agent-kit/package-load.js +45 -0
- package/lib/agent-kit/plan-ops.js +69 -0
- package/lib/agent-kit/remote-prompts.js +239 -0
- package/lib/agent-kit/render-host-markdown.js +40 -0
- package/lib/agent-kit/repo-guard.js +47 -0
- package/lib/agent-kit/report.js +107 -0
- package/lib/agent-kit/run.js +82 -0
- package/lib/agent-kit/scm/git.js +122 -0
- package/lib/agent-kit/state-file.js +83 -0
- package/lib/agent-kit/status.js +50 -0
- package/lib/agent-kit/v1-detect.js +81 -0
- package/lib/agent-kit/validate-kit.js +87 -0
- package/lib/agent-kit/workspace-name.js +40 -0
- package/lib/agent-kit/workspace-skeleton.js +103 -0
- package/lib/api/role-assistant-test-pack.api.js +86 -0
- package/lib/api/work-search.api.js +31 -4
- package/lib/api/work.api.js +19 -12
- package/lib/app/list-external-systems.js +2 -1
- package/lib/app/show-display.js +33 -6
- package/lib/app/show.js +25 -2
- package/lib/channels/add-channel.js +1 -0
- package/lib/channels/approval-guides/claude.js +2 -2
- package/lib/channels/channel-add-failure.js +1 -0
- package/lib/channels/channel-add-remaining.js +15 -9
- package/lib/channels/channel-definition-status.js +115 -0
- package/lib/channels/channel-description.js +2 -1
- package/lib/channels/channel-install-envelope.js +4 -2
- package/lib/channels/channel-integration-generator.js +2 -0
- package/lib/channels/channel-runtime-resolver.js +14 -0
- package/lib/channels/channel-targets.js +31 -5
- package/lib/channels/claude-setup-values.js +4 -1
- package/lib/channels/slack-channel-add.js +59 -6
- package/lib/channels/slack-mcp-callback.js +51 -0
- package/lib/channels/slack-mcp-runtime.js +156 -0
- package/lib/channels/slack-provisioning/install-cli.js +14 -2
- package/lib/channels/slack-provisioning/with-curl-on-path.js +6 -1
- package/lib/cli/index.js +4 -0
- package/lib/cli/setup-certification-commands.js +2 -2
- package/lib/cli/setup-certification.help.js +3 -1
- package/lib/commands/agent-kit-help.js +79 -0
- package/lib/commands/agent-kit.js +346 -0
- package/lib/commands/channel-add-help.js +5 -5
- package/lib/commands/datasource-capability-relate-cli.js +5 -4
- package/lib/commands/repair-auth-apply.js +1 -1
- package/lib/commands/repair-datasource-key-skip.js +39 -0
- package/lib/commands/repair-datasource-keys.js +24 -12
- package/lib/commands/repair-rbac.js +16 -10
- package/lib/commands/role-assistant-copy-output.js +61 -0
- package/lib/commands/role-assistant-copy.js +155 -0
- package/lib/commands/role-assistant-test-output.js +8 -9
- package/lib/commands/role-assistant-test-result-rows.js +42 -0
- package/lib/commands/role-assistant.js +117 -48
- package/lib/commands/search.js +143 -0
- package/lib/commands/test-trust-external.js +7 -5
- package/lib/commands/upload-sidecar-followups.js +4 -1
- package/lib/commands/verify-operations-skip-e2e.js +131 -0
- package/lib/commands/verify-operations-step-plan.js +6 -33
- package/lib/commands/verify-operations-steps.js +3 -1
- package/lib/datasource/capability/relate-operations.js +28 -10
- package/lib/datasource/capability/run-capability-relate.js +48 -25
- package/lib/datasource/datasource-identifier.js +13 -5
- package/lib/deployment/deployer-poll-run.js +117 -35
- package/lib/external-system/deploy-dataplane-published.js +70 -0
- package/lib/external-system/deploy.js +12 -2
- package/lib/external-system/download-role-assistant.js +41 -15
- package/lib/external-system/download.js +7 -1
- package/lib/generator/wizard-datasource-key.js +54 -0
- package/lib/generator/wizard.js +55 -54
- package/lib/integration-definition/apply-datasource-keys.js +75 -0
- package/lib/integration-definition/apply-relationships.js +195 -0
- package/lib/integration-definition/apply-static-enterprise.js +229 -0
- package/lib/integration-definition/apply-system-file.js +71 -0
- package/lib/integration-definition/apply-test-endpoint.js +89 -0
- package/lib/integration-definition/apply-viewpoint-defaults.js +157 -0
- package/lib/integration-definition/apply.js +78 -59
- package/lib/integration-definition/enrich-openapi-operations.js +36 -10
- package/lib/integration-definition/enrich-openapi-pick.js +87 -0
- package/lib/lifecycle/role-assistant-governance.js +56 -21
- package/lib/programmatic/capability-registry.js +1 -0
- package/lib/programmatic/index.js +2 -0
- package/lib/programmatic/openapi-apply-result-schemas.js +8 -0
- package/lib/programmatic/openapi-channel-install-schemas.js +4 -1
- package/lib/programmatic/openapi-component-schemas.js +1 -0
- package/lib/programmatic/openapi-descriptions.js +9 -3
- package/lib/programmatic/openapi-envelope-examples.js +7 -0
- package/lib/programmatic/openapi-operation-bindings.js +5 -0
- package/lib/programmatic/openapi-request-schemas.js +5 -0
- package/lib/programmatic/openapi-schema-descriptions-channel.js +8 -5
- package/lib/programmatic/openapi-schema-descriptions-operations.js +19 -0
- package/lib/programmatic/openapi-spec.js +1 -0
- package/lib/programmatic/request-timeout.js +3 -0
- package/lib/programmatic/route-handler-map.js +7 -0
- package/lib/programmatic/run-channel-catalog.js +50 -8
- package/lib/programmatic/run-channel-install-options.js +5 -1
- package/lib/programmatic/run-download.js +41 -0
- package/lib/protection/auth-context.js +3 -1
- package/lib/protection/protection-display.js +3 -2
- package/lib/protection/report-exit.js +50 -0
- package/lib/protection/run-commands.js +2 -0
- package/lib/role-assistant/package-validate.js +175 -0
- package/lib/role-assistant/test-case-assertion-row.js +36 -0
- package/lib/role-assistant/test-case-copy-bind.js +77 -0
- package/lib/role-assistant/test-case-copy-expected.js +127 -0
- package/lib/role-assistant/test-case-copy-from-work.js +90 -0
- package/lib/role-assistant/test-case-copy-interactions.js +67 -0
- package/lib/role-assistant/test-case-copy.js +119 -0
- package/lib/role-assistant/test-case-expected-catalog.js +135 -0
- package/lib/role-assistant/test-case-validate.js +88 -0
- package/lib/role-assistant/test-cases-bid.js +117 -4
- package/lib/role-assistant/test-cases-evaluate.js +137 -30
- package/lib/role-assistant/test-cases-honesty.js +155 -6
- package/lib/role-assistant/test-cases-lifecycle.js +291 -0
- package/lib/role-assistant/test-cases-search-graph.js +122 -0
- package/lib/role-assistant/test-cases-search.js +20 -2
- package/lib/role-assistant/test-cases.js +34 -168
- package/lib/role-assistant/test-pack-map.js +180 -0
- package/lib/role-assistant/test-pack-sync.js +187 -0
- package/lib/role-assistant/test-runner-debug.js +54 -0
- package/lib/role-assistant/test-runner-respond-body.js +36 -0
- package/lib/role-assistant/test-runner-search.js +20 -5
- package/lib/role-assistant/test-runner-start-payload.js +63 -10
- package/lib/role-assistant/test-runner-workhub-answers.js +45 -16
- package/lib/role-assistant/test-runner-workhub.js +45 -21
- package/lib/role-assistant/test-runner.js +50 -10
- package/lib/schema/external-datasource.schema.json +36 -5
- package/lib/schema/external-system.schema.json +20 -2
- package/lib/schema/role-assistant-test-case.schema.json +408 -0
- package/lib/search/dataplane-context.js +23 -0
- package/lib/search/search-args.js +211 -0
- package/lib/search/search-display.js +238 -0
- package/lib/search/search-errors.js +50 -0
- package/lib/search/search-prompts.js +119 -0
- package/lib/search/search-roles.js +85 -0
- package/lib/search/search-run.js +241 -0
- package/lib/search/search-skills.js +198 -0
- package/lib/utils/authentication-slot-show.js +153 -0
- package/lib/utils/credential-display.js +43 -1
- package/lib/utils/external-system-readiness-compact-blocks.js +5 -1
- package/lib/utils/external-system-readiness-compact-display.js +30 -1
- package/lib/utils/external-system-validators.js +2 -1
- package/lib/utils/help-builder.js +3 -1
- package/lib/utils/schema-loader.js +37 -0
- package/lib/validation/validate-external-file.js +5 -1
- package/lib/validation/validate.js +3 -2
- package/package.json +1 -1
- package/templates/agent-kit/adapters/claude/nested.CLAUDE.md +1 -0
- package/templates/agent-kit/adapters/claude/root.CLAUDE.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-0-plan.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-1-validate.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-2-build.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-3-push.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-biz-1-validate.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-biz-2-build.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-biz-3-prove.md +5 -0
- package/templates/agent-kit/agent-kit.yaml +45 -0
- package/templates/agent-kit/instructions/AGENTKIT.md +83 -0
- package/templates/agent-kit/instructions/integration.AGENTS.md +25 -0
- package/templates/agent-kit/instructions/role-assistant.AGENTS.md +22 -0
- package/templates/agent-kit/instructions/root.AGENTS.md +37 -0
- package/templates/agent-kit/parity-inventory.yaml +188 -0
- package/templates/agent-kit/skills/aifabrix-connected-system/SKILL.md +58 -0
- package/templates/agent-kit/skills/aifabrix-connected-system/references/contract-checklist.md +40 -0
- package/templates/agent-kit/skills/aifabrix-connected-system/references/delivery-gates.md +54 -0
- package/templates/agent-kit/skills/aifabrix-connected-system/references/production-safety.md +35 -0
- package/templates/agent-kit/skills/aifabrix-connected-system/scripts/reserved-system-key.js +19 -0
- package/templates/agent-kit/skills/aifabrix-plan/SKILL.md +51 -0
- package/templates/agent-kit/skills/aifabrix-plan/references/challenge-checklist.md +108 -0
- package/templates/agent-kit/skills/aifabrix-plan/references/interaction.md +34 -0
- package/templates/agent-kit/skills/aifabrix-plan/references/plan-template.md +182 -0
- package/templates/agent-kit/skills/aifabrix-prove/SKILL.md +50 -0
- package/templates/agent-kit/skills/aifabrix-prove/references/demo-template.md +65 -0
- package/templates/agent-kit/skills/aifabrix-prove/references/evidence-lifecycle.md +68 -0
- package/templates/agent-kit/skills/aifabrix-prove/references/learning-template.md +66 -0
- package/templates/agent-kit/skills/aifabrix-role-assistant/SKILL.md +42 -0
- package/templates/agent-kit/skills/aifabrix-role-assistant/references/package-boundary.md +21 -0
- package/templates/agent-kit/skills/shared/hosts.md +78 -0
- package/templates/agent-kit/workspace/.cursor/plans/README.md +22 -0
- package/templates/agent-kit/workspace/LICENSE.mit +21 -0
- package/templates/agent-kit/workspace/README.md +89 -0
- package/templates/applications/builder-api/Dockerfile +3 -1
- package/templates/applications/dataplane/application.yaml +2 -2
- package/templates/applications/dataplane/env.template +1 -1
- package/templates/applications/dataplane/rbac.yaml +28 -0
- package/templates/applications/keycloak/env.template +3 -3
- package/templates/applications/miso-controller/application.yaml +1 -1
- package/templates/applications/miso-controller/env.template +8 -9
- package/templates/channels/claude/TROUBLESHOOTING.md +3 -0
- package/templates/channels/claude/channel.json +1 -1
- package/templates/channels/claude/install.template.md.hbs +1 -0
- package/templates/channels/claude/integration/claude-system.json +1 -1
- package/templates/channels/slack/channel.json +11 -0
- package/templates/channels/slack/install.template.md.hbs +9 -0
- package/templates/channels/slack/integration/slack-system.json +11 -0
- package/templates/channels/slack/manifest.template.json.hbs +6 -3
- package/templates/channels/teams-bot/channel.json +1 -0
- package/templates/python/docker-compose.hbs +14 -0
- package/templates/typescript/docker-compose.hbs +14 -0
package/lib/api/work.api.js
CHANGED
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
9
|
const { createDataplaneApiClient } = require('./index');
|
|
10
|
+
const { throwIfApiFailed } = require('./api-response-errors');
|
|
10
11
|
const { unwrapApiData } = require('../utils/external-system-readiness-core');
|
|
12
|
+
const { pickHumanRespondBody } = require('../role-assistant/test-runner-respond-body');
|
|
11
13
|
|
|
12
14
|
/** Work Hub plan create runs LLM planning; 30s default is too short under load/reload. */
|
|
13
15
|
const WORK_PLAN_TIMEOUT_MS = 120000;
|
|
@@ -59,7 +61,10 @@ function assertObjectShape(value, fallbackMessage) {
|
|
|
59
61
|
*/
|
|
60
62
|
async function startWorkIntent(dataplaneUrl, authConfig, body) {
|
|
61
63
|
const client = createDataplaneApiClient(dataplaneUrl, authConfig);
|
|
62
|
-
const res = await client.post('/api/v1/work/start', {
|
|
64
|
+
const res = await client.post('/api/v1/work/start', {
|
|
65
|
+
body,
|
|
66
|
+
timeoutMs: WORK_PLAN_TIMEOUT_MS
|
|
67
|
+
});
|
|
63
68
|
if (res && res.success === false) {
|
|
64
69
|
throw new Error(extractApiErrorMessage(res, 'work.start request failed'));
|
|
65
70
|
}
|
|
@@ -70,7 +75,7 @@ async function startWorkIntent(dataplaneUrl, authConfig, body) {
|
|
|
70
75
|
|
|
71
76
|
/**
|
|
72
77
|
* GET /api/v1/work/executions/{processExecutionId}
|
|
73
|
-
* @requiresPermission {Dataplane} worker
|
|
78
|
+
* @requiresPermission {Dataplane} worker:read
|
|
74
79
|
* @async
|
|
75
80
|
* @param {string} dataplaneUrl
|
|
76
81
|
* @param {Object} authConfig
|
|
@@ -80,12 +85,13 @@ async function startWorkIntent(dataplaneUrl, authConfig, body) {
|
|
|
80
85
|
async function getWorkExecutionStatus(dataplaneUrl, authConfig, processExecutionId) {
|
|
81
86
|
const client = createDataplaneApiClient(dataplaneUrl, authConfig);
|
|
82
87
|
const encodedId = encodeURIComponent(String(processExecutionId));
|
|
83
|
-
const
|
|
88
|
+
const endpoint = `/api/v1/work/executions/${encodedId}`;
|
|
89
|
+
const res = await client.get(endpoint, {
|
|
84
90
|
timeoutMs: WORK_TASK_TIMEOUT_MS
|
|
85
91
|
});
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
92
|
+
throwIfApiFailed(res, {
|
|
93
|
+
endpointUrl: `${String(dataplaneUrl || '').replace(/\/$/, '')}${endpoint}`
|
|
94
|
+
});
|
|
89
95
|
const unwrapped = unwrapWorkPayload(res);
|
|
90
96
|
assertObjectShape(unwrapped, 'work.status returned an unexpected response shape');
|
|
91
97
|
return unwrapped;
|
|
@@ -105,7 +111,7 @@ async function respondWorkExecution(dataplaneUrl, authConfig, processExecutionId
|
|
|
105
111
|
const client = createDataplaneApiClient(dataplaneUrl, authConfig);
|
|
106
112
|
const encodedId = encodeURIComponent(String(processExecutionId));
|
|
107
113
|
const res = await client.post(`/api/v1/work/executions/${encodedId}/respond`, {
|
|
108
|
-
body,
|
|
114
|
+
body: pickHumanRespondBody(body),
|
|
109
115
|
timeoutMs: WORK_TASK_TIMEOUT_MS
|
|
110
116
|
});
|
|
111
117
|
if (res && res.success === false) {
|
|
@@ -143,7 +149,7 @@ async function continueWorkExecution(dataplaneUrl, authConfig, processExecutionI
|
|
|
143
149
|
|
|
144
150
|
/**
|
|
145
151
|
* GET /api/v1/work/executions/{processExecutionId}/result
|
|
146
|
-
* @requiresPermission {Dataplane} worker
|
|
152
|
+
* @requiresPermission {Dataplane} worker:read
|
|
147
153
|
* @async
|
|
148
154
|
* @param {string} dataplaneUrl
|
|
149
155
|
* @param {Object} authConfig
|
|
@@ -154,6 +160,7 @@ async function continueWorkExecution(dataplaneUrl, authConfig, processExecutionI
|
|
|
154
160
|
async function getWorkExecutionResult(dataplaneUrl, authConfig, processExecutionId, query = {}) {
|
|
155
161
|
const client = createDataplaneApiClient(dataplaneUrl, authConfig);
|
|
156
162
|
const encodedId = encodeURIComponent(String(processExecutionId));
|
|
163
|
+
const endpoint = `/api/v1/work/executions/${encodedId}/result`;
|
|
157
164
|
const params = {};
|
|
158
165
|
if (query && typeof query === 'object') {
|
|
159
166
|
if (query.requestedDepth) {
|
|
@@ -166,13 +173,13 @@ async function getWorkExecutionResult(dataplaneUrl, authConfig, processExecution
|
|
|
166
173
|
params.projection = String(query.projection);
|
|
167
174
|
}
|
|
168
175
|
}
|
|
169
|
-
const res = await client.get(
|
|
176
|
+
const res = await client.get(endpoint, {
|
|
170
177
|
params,
|
|
171
178
|
timeoutMs: WORK_TASK_TIMEOUT_MS
|
|
172
179
|
});
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
180
|
+
throwIfApiFailed(res, {
|
|
181
|
+
endpointUrl: `${String(dataplaneUrl || '').replace(/\/$/, '')}${endpoint}`
|
|
182
|
+
});
|
|
176
183
|
const unwrapped = unwrapWorkPayload(res);
|
|
177
184
|
assertObjectShape(unwrapped, 'work.result returned an unexpected response shape');
|
|
178
185
|
return unwrapped;
|
|
@@ -15,6 +15,7 @@ const { listExternalSystems } = require('../api/external-systems.api');
|
|
|
15
15
|
const { formatApiError } = require('../utils/api-error-handler');
|
|
16
16
|
const { getListAuthToken } = require('./list');
|
|
17
17
|
const logger = require('../utils/logger');
|
|
18
|
+
const { formatLifecycleLabel } = require('../utils/external-system-readiness-compact-display');
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* Normalize list response shapes from the dataplane API client.
|
|
@@ -56,7 +57,7 @@ function displayExternalSystems(systems, environment, dataplaneUrl, json) {
|
|
|
56
57
|
systems.forEach((system) => {
|
|
57
58
|
const key = system.key || system.systemKey || system.id || '—';
|
|
58
59
|
const displayName = system.displayName || key;
|
|
59
|
-
const status = system.status || 'unknown';
|
|
60
|
+
const status = formatLifecycleLabel(system.status || 'unknown');
|
|
60
61
|
logger.log(`✔ ${chalk.cyan(key)} - ${displayName} (${status})`);
|
|
61
62
|
});
|
|
62
63
|
logger.log(chalk.gray(' To show details: aifabrix show <systemKey> --online\n'));
|
package/lib/app/show-display.js
CHANGED
|
@@ -11,6 +11,11 @@
|
|
|
11
11
|
|
|
12
12
|
const chalk = require('chalk');
|
|
13
13
|
const logger = require('../utils/logger');
|
|
14
|
+
const { formatCredentialShowLine } = require('../utils/authentication-slot-show');
|
|
15
|
+
const {
|
|
16
|
+
formatConnectedSystemLifecycleLabel,
|
|
17
|
+
formatLifecycleLabel
|
|
18
|
+
} = require('../utils/external-system-readiness-compact-display');
|
|
14
19
|
|
|
15
20
|
function logSourceAndHeader(summary) {
|
|
16
21
|
const isOffline = summary.source === 'offline';
|
|
@@ -93,14 +98,36 @@ function logApplicationFields(a) {
|
|
|
93
98
|
logApplicationOptional(a);
|
|
94
99
|
}
|
|
95
100
|
|
|
101
|
+
/**
|
|
102
|
+
* Draft / Published / Archived only — never controller `active`.
|
|
103
|
+
* @param {Object} a
|
|
104
|
+
* @param {Object} [summary]
|
|
105
|
+
* @returns {string|null}
|
|
106
|
+
*/
|
|
107
|
+
function resolveExternalApplicationStatusLabel(a, summary) {
|
|
108
|
+
const ext = summary && summary.externalSystem;
|
|
109
|
+
const fromDataplane = ext && !ext.error ? (ext.status || ext.dataplaneStatus) : null;
|
|
110
|
+
return formatConnectedSystemLifecycleLabel(fromDataplane || a.status);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function logExternalApplicationStatus(a, summary) {
|
|
114
|
+
const label = resolveExternalApplicationStatusLabel(a, summary);
|
|
115
|
+
if (label) logger.log(` Status: ${label}`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function formatDataplaneStatusDisplay(status) {
|
|
119
|
+
if (status === undefined || status === null || status === '' || status === '—') return '—';
|
|
120
|
+
return formatConnectedSystemLifecycleLabel(status) || formatLifecycleLabel(status);
|
|
121
|
+
}
|
|
122
|
+
|
|
96
123
|
/** Application section for online + external: Key, Display name, Description, Deployment, Status (no Type; Dataplane block follows). */
|
|
97
|
-
function logApplicationFieldsOnlineExternal(a) {
|
|
124
|
+
function logApplicationFieldsOnlineExternal(a, summary) {
|
|
98
125
|
logger.log('🧷 Application - external');
|
|
99
126
|
logger.log(` Key: ${a.key ?? '—'}`);
|
|
100
127
|
logger.log(` Display name: ${a.displayName ?? '—'}`);
|
|
101
128
|
logger.log(` Description: ${a.description ?? '—'}`);
|
|
102
129
|
logger.log(' Deployment: —');
|
|
103
|
-
|
|
130
|
+
logExternalApplicationStatus(a, summary);
|
|
104
131
|
}
|
|
105
132
|
|
|
106
133
|
/** Application section for offline + external: Key, Display name, Description, Deployment, Status, Version when present. */
|
|
@@ -110,7 +137,7 @@ function logApplicationFieldsOfflineExternal(a) {
|
|
|
110
137
|
logger.log(` Display name: ${a.displayName ?? '—'}`);
|
|
111
138
|
logger.log(` Description: ${a.description ?? '—'}`);
|
|
112
139
|
logger.log(' Deployment: —');
|
|
113
|
-
|
|
140
|
+
logExternalApplicationStatus(a);
|
|
114
141
|
if (a.version !== undefined && a.version !== null) logger.log(` Version: ${a.version}`);
|
|
115
142
|
}
|
|
116
143
|
|
|
@@ -129,7 +156,7 @@ function logApplicationSection(a, summary) {
|
|
|
129
156
|
const onlineExternal = summary.source === 'online' && isExternal;
|
|
130
157
|
const offlineExternal = summary.source === 'offline' && isExternal;
|
|
131
158
|
if (onlineExternal) {
|
|
132
|
-
logApplicationFieldsOnlineExternal(a);
|
|
159
|
+
logApplicationFieldsOnlineExternal(a, summary);
|
|
133
160
|
} else if (offlineExternal) {
|
|
134
161
|
logApplicationFieldsOfflineExternal(a);
|
|
135
162
|
} else {
|
|
@@ -205,8 +232,8 @@ function logDatabasesSection(dbNames) {
|
|
|
205
232
|
function logExternalSystemMain(ext) {
|
|
206
233
|
logger.log('🧩 Dataplane');
|
|
207
234
|
logger.log(` Version: ${ext.version ?? '—'}`);
|
|
208
|
-
logger.log(` Credential: ${ext
|
|
209
|
-
logger.log(` Status: ${ext.status
|
|
235
|
+
logger.log(` Credential: ${formatCredentialShowLine(ext)}`);
|
|
236
|
+
logger.log(` Status: ${formatDataplaneStatusDisplay(ext.status)}`);
|
|
210
237
|
logger.log(` API docs: ${ext.openApiDocsPageUrl ?? ext.apiDocumentUrl ?? '—'}`);
|
|
211
238
|
logger.log(` MCP server: ${ext.mcpServerUrl ?? '—'}`);
|
|
212
239
|
logger.log(` OpenAPI spec: ${ext.apiDocumentUrl ?? '—'}`);
|
package/lib/app/show.js
CHANGED
|
@@ -33,6 +33,8 @@ const {
|
|
|
33
33
|
attachCertificationVerifyFromDataplane,
|
|
34
34
|
sanitizeCertificationForJson
|
|
35
35
|
} = require('./certification-show-enrich');
|
|
36
|
+
const { resolveManifestAuthMethod } = require('../utils/external-system-readiness-compact-display');
|
|
37
|
+
const { resolveAuthenticationSlots } = require('../utils/authentication-slot-show');
|
|
36
38
|
|
|
37
39
|
/**
|
|
38
40
|
* Attach `runReloadDefault` / `runProxyDefault` from ~/.aifabrix `applications.<appKey>`.
|
|
@@ -466,6 +468,13 @@ function pickExternalVersion(res, config, system) {
|
|
|
466
468
|
return (res && res.version) ?? config.version ?? system.version ?? '—';
|
|
467
469
|
}
|
|
468
470
|
|
|
471
|
+
function pickCredentialMethod(config, system) {
|
|
472
|
+
const source = config && (config.authentication || config.authentications) ? config : system;
|
|
473
|
+
const method = resolveManifestAuthMethod(source);
|
|
474
|
+
if (!method || method === 'unknown') return undefined;
|
|
475
|
+
return method;
|
|
476
|
+
}
|
|
477
|
+
|
|
469
478
|
function resolveExternalSystemMeta(res, config, system, application, appKey) {
|
|
470
479
|
return {
|
|
471
480
|
displayName: pickExternalDisplayName(res, system, application, appKey),
|
|
@@ -501,13 +510,27 @@ function buildBaseExternalResult(configData, appKey, openapiFiles, openapiEndpoi
|
|
|
501
510
|
permissions: application.permissions
|
|
502
511
|
},
|
|
503
512
|
openapiFiles,
|
|
504
|
-
openapiEndpoints
|
|
513
|
+
openapiEndpoints,
|
|
514
|
+
credentialMethod: pickCredentialMethod(config, system),
|
|
515
|
+
authenticationSlots: resolveAuthenticationSlots(config, system)
|
|
505
516
|
};
|
|
506
517
|
}
|
|
507
518
|
|
|
519
|
+
function applyCredentialFieldsToResult(result, res) {
|
|
520
|
+
if (res.credentialId !== undefined && res.credentialId !== null) result.credentialId = res.credentialId;
|
|
521
|
+
if (res.authenticationStatus !== undefined && res.authenticationStatus !== null) {
|
|
522
|
+
result.authenticationStatus = res.authenticationStatus;
|
|
523
|
+
}
|
|
524
|
+
const resConfig = res.config && typeof res.config === 'object' ? res.config : {};
|
|
525
|
+
const fromConfig = pickCredentialMethod(resConfig, {});
|
|
526
|
+
if (fromConfig) result.credentialMethod = fromConfig;
|
|
527
|
+
const fromSlots = resolveAuthenticationSlots(resConfig, {});
|
|
528
|
+
if (fromSlots.length > 0) result.authenticationSlots = fromSlots;
|
|
529
|
+
}
|
|
530
|
+
|
|
508
531
|
function applySystemResponseToResult(result, res) {
|
|
509
532
|
result.dataplaneStatus = res.status;
|
|
510
|
-
|
|
533
|
+
applyCredentialFieldsToResult(result, res);
|
|
511
534
|
if (res.showOpenApiDocs !== undefined) result.showOpenApiDocs = res.showOpenApiDocs;
|
|
512
535
|
if (res.mcpServerUrl !== undefined && res.mcpServerUrl !== null) result.mcpServerUrl = res.mcpServerUrl;
|
|
513
536
|
if (res.apiDocumentUrl !== undefined && res.apiDocumentUrl !== null) result.apiDocumentUrl = res.apiDocumentUrl;
|
|
@@ -350,6 +350,7 @@ async function resolveInstallRuntimeValues(params, packageContext, runtimeToolNa
|
|
|
350
350
|
appDescription: description,
|
|
351
351
|
icon: options.icon,
|
|
352
352
|
commandPrefix: options.commandPrefix,
|
|
353
|
+
enableMcpServer: options.enableMcpServer,
|
|
353
354
|
layerBToolNames: runtimeToolNames,
|
|
354
355
|
packageContext,
|
|
355
356
|
entraProvider,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Claude remaining workspace steps (customer-facing).
|
|
3
3
|
*
|
|
4
|
-
* @fileoverview Short Claude connector Name
|
|
4
|
+
* @fileoverview Short Claude connector Name, Server URL, and OAuth steps — no protocol dump
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
'use strict';
|
|
@@ -21,7 +21,7 @@ function buildClaudeApprovalGuide(ctx) {
|
|
|
21
21
|
credentialPortalUrl: null,
|
|
22
22
|
steps: [
|
|
23
23
|
`Open ${CLAUDE_CONNECTORS_URL}`,
|
|
24
|
-
`Add a custom connector with Name: ${name}; Server URL: ${serverUrl}.`
|
|
24
|
+
`Add a custom connector with Name: ${name}; Server URL: ${serverUrl}; Authentication: OAuth.`
|
|
25
25
|
]
|
|
26
26
|
};
|
|
27
27
|
}
|
|
@@ -16,6 +16,7 @@ const BOUNDARY_MATCHERS = [
|
|
|
16
16
|
tests: [/unknown channel/i, /already configured/i, /needs a terminal/i, /--name is required/i, /needs --target/i, /unknown mcp client profile/i]
|
|
17
17
|
},
|
|
18
18
|
{ boundary: 'experimental', tests: [/is experimental/i] },
|
|
19
|
+
{ boundary: 'unavailable', tests: [/is coming soon/i, /is not available/i] },
|
|
19
20
|
{ boundary: 'preflight', tests: [/chatgpt preflight/i, /claude preflight/i, /mcp client preflight/i, /authentication required/i, /dataplanebaseurl is required/i] },
|
|
20
21
|
{ boundary: 'callback', tests: [/chatgpt callback/i, /claude callback/i, /mcp client callback/i] },
|
|
21
22
|
{ boundary: 'oauth', tests: [/oauth/i, /trustedissuer/i, /vault-reference/i] },
|
|
@@ -30,6 +30,7 @@ const { printMcpClientDryRunTty } = require('./mcp-client-channel-add');
|
|
|
30
30
|
const { printClaudeDryRunTty } = require('./claude-channel-add');
|
|
31
31
|
const { CLAUDE_REMAINING_STEPS } = require('./claude-runtime-contract');
|
|
32
32
|
const { vendorFacingUrlsFromCtx } = require('./vendor-dataplane-url');
|
|
33
|
+
const { slackMcpRemainingSteps } = require('./slack-mcp-runtime');
|
|
33
34
|
const {
|
|
34
35
|
channelDisplayLabel,
|
|
35
36
|
printValidating,
|
|
@@ -280,18 +281,23 @@ function slackRecoveryOrHandshake(ctx, custom) {
|
|
|
280
281
|
* @param {Object|null} ctx
|
|
281
282
|
* @returns {Object}
|
|
282
283
|
*/
|
|
283
|
-
function slackRemainingSpec(ctx) {
|
|
284
|
+
function slackRemainingSpec(ctx, runtimeValues) {
|
|
284
285
|
const custom = slackCustomSteps(ctx);
|
|
286
|
+
const mcpSteps = slackMcpRemainingSteps(runtimeValues);
|
|
287
|
+
let spec;
|
|
285
288
|
if (ctx && ctx.slackConnected === true) {
|
|
286
|
-
|
|
289
|
+
spec = slackConnectedRemaining(ctx, custom);
|
|
290
|
+
} else if (ctx && ctx.slackSlashCommand) {
|
|
291
|
+
spec = slackSlashRemaining(ctx, custom);
|
|
292
|
+
} else if (ctx && ctx.slackHandshakeFailed === true) {
|
|
293
|
+
spec = slackFailedRemaining(custom);
|
|
294
|
+
} else {
|
|
295
|
+
spec = slackRecoveryOrHandshake(ctx, custom);
|
|
287
296
|
}
|
|
288
|
-
if (
|
|
289
|
-
return
|
|
297
|
+
if (mcpSteps.length === 0) {
|
|
298
|
+
return spec;
|
|
290
299
|
}
|
|
291
|
-
|
|
292
|
-
return slackFailedRemaining(custom);
|
|
293
|
-
}
|
|
294
|
-
return slackRecoveryOrHandshake(ctx, custom);
|
|
300
|
+
return { ...spec, steps: [...(spec.steps || []), ...mcpSteps] };
|
|
295
301
|
}
|
|
296
302
|
|
|
297
303
|
/**
|
|
@@ -350,7 +356,7 @@ function teamsBotRemainingSpec(ctx, runtimeValues) {
|
|
|
350
356
|
*/
|
|
351
357
|
function remainingSpec(channelTarget, ctx, runtimeValues) {
|
|
352
358
|
if (channelTarget === 'slack') {
|
|
353
|
-
return slackRemainingSpec(ctx);
|
|
359
|
+
return slackRemainingSpec(ctx, runtimeValues);
|
|
354
360
|
}
|
|
355
361
|
if (channelTarget === 'microsoft-copilot') {
|
|
356
362
|
return copilotRemainingSpec(ctx, runtimeValues);
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Channel Definition catalog/install status (visible | hide | coming-soon).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Omit or visible: listed and installable. hide: omitted and refused. coming-soon: listed read-only.
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const registry = require('./channel-definition-registry');
|
|
12
|
+
|
|
13
|
+
const CHANNEL_STATUSES = ['visible', 'hide', 'coming-soon'];
|
|
14
|
+
const COMING_SOON_REASON = 'This channel is coming soon.';
|
|
15
|
+
const HIDE_REASON = 'This channel is not available.';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @param {Object|null} definition
|
|
19
|
+
* @returns {'visible'|'hide'|'coming-soon'}
|
|
20
|
+
*/
|
|
21
|
+
function normalizeChannelStatus(definition) {
|
|
22
|
+
const raw = definition && definition.channel && definition.channel.status;
|
|
23
|
+
if (raw === 'hide' || raw === 'coming-soon') {
|
|
24
|
+
return raw;
|
|
25
|
+
}
|
|
26
|
+
return 'visible';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Live status from the Channel Definition registry (spy-friendly).
|
|
31
|
+
* @param {string} key
|
|
32
|
+
* @returns {'visible'|'hide'|'coming-soon'}
|
|
33
|
+
*/
|
|
34
|
+
function channelStatusOf(key) {
|
|
35
|
+
return normalizeChannelStatus(registry.getChannelDefinition(key));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @param {string} status
|
|
40
|
+
* @returns {boolean}
|
|
41
|
+
*/
|
|
42
|
+
function isCatalogHiddenStatus(status) {
|
|
43
|
+
return status === 'hide';
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @param {string} status
|
|
48
|
+
* @returns {boolean}
|
|
49
|
+
*/
|
|
50
|
+
function isInstallableStatus(status) {
|
|
51
|
+
return status === 'visible';
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @param {string} key
|
|
56
|
+
* @param {string} status
|
|
57
|
+
* @returns {Error}
|
|
58
|
+
*/
|
|
59
|
+
function statusUnavailableError(key, status) {
|
|
60
|
+
const message =
|
|
61
|
+
status === 'coming-soon'
|
|
62
|
+
? `Channel target "${key}" is coming soon.`
|
|
63
|
+
: `Channel target "${key}" is not available.`;
|
|
64
|
+
const err = new Error(message);
|
|
65
|
+
err.statusCode = 403;
|
|
66
|
+
return err;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Refuse new install for hide and coming-soon. Continue of an existing session skips.
|
|
71
|
+
* --force / allowExperimental do not override.
|
|
72
|
+
* @param {string} key
|
|
73
|
+
* @param {{ continueInstall?: boolean }} [options]
|
|
74
|
+
* @returns {void}
|
|
75
|
+
*/
|
|
76
|
+
function assertChannelStatusInstallable(key, options = {}) {
|
|
77
|
+
if (options.continueInstall === true) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const status = channelStatusOf(key);
|
|
81
|
+
if (isInstallableStatus(status)) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
throw statusUnavailableError(key, status);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Overlay coming-soon onto a catalog/detail projection (canInstall false).
|
|
89
|
+
* @param {string} status
|
|
90
|
+
* @param {Object} [projection]
|
|
91
|
+
* @returns {Object}
|
|
92
|
+
*/
|
|
93
|
+
function applyChannelStatusProjection(status, projection = {}) {
|
|
94
|
+
if (status !== 'coming-soon') {
|
|
95
|
+
return { ...projection, status };
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
...projection,
|
|
99
|
+
status,
|
|
100
|
+
canInstall: false,
|
|
101
|
+
blockedReason: COMING_SOON_REASON
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
module.exports = {
|
|
106
|
+
CHANNEL_STATUSES,
|
|
107
|
+
COMING_SOON_REASON,
|
|
108
|
+
HIDE_REASON,
|
|
109
|
+
normalizeChannelStatus,
|
|
110
|
+
channelStatusOf,
|
|
111
|
+
isCatalogHiddenStatus,
|
|
112
|
+
isInstallableStatus,
|
|
113
|
+
assertChannelStatusInstallable,
|
|
114
|
+
applyChannelStatusProjection
|
|
115
|
+
};
|
|
@@ -99,7 +99,8 @@ function fillSlackManifestDescriptions(channelTarget, runtimeValues) {
|
|
|
99
99
|
return {
|
|
100
100
|
...runtimeValues,
|
|
101
101
|
appLongDescription,
|
|
102
|
-
appLongDescriptionJson: JSON.stringify(appLongDescription)
|
|
102
|
+
appLongDescriptionJson: JSON.stringify(appLongDescription),
|
|
103
|
+
enableMcpServer: runtimeValues.enableMcpServer === true
|
|
103
104
|
};
|
|
104
105
|
}
|
|
105
106
|
|
|
@@ -135,7 +135,8 @@ function claudeCopyActions(runtimeValues) {
|
|
|
135
135
|
const values = buildClaudeFormValues({ runtimeValues: runtimeValues || {} });
|
|
136
136
|
return [
|
|
137
137
|
copyValueAction('Name', values.name, 'copy-name'),
|
|
138
|
-
copyValueAction('Server URL', values.serverUrl, 'copy-server-url')
|
|
138
|
+
copyValueAction('Server URL', values.serverUrl, 'copy-server-url'),
|
|
139
|
+
copyValueAction('Authentication', values.authentication, 'copy-authentication')
|
|
139
140
|
].filter(Boolean);
|
|
140
141
|
}
|
|
141
142
|
|
|
@@ -195,7 +196,8 @@ function claudeEnvelopeParts(params) {
|
|
|
195
196
|
useValues: runtimeOk
|
|
196
197
|
? {
|
|
197
198
|
Name: values.name,
|
|
198
|
-
'Server URL': values.serverUrl
|
|
199
|
+
'Server URL': values.serverUrl,
|
|
200
|
+
Authentication: values.authentication
|
|
199
201
|
}
|
|
200
202
|
: {}
|
|
201
203
|
};
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
const path = require('path');
|
|
14
14
|
const { getChannelTarget } = require('./channel-targets');
|
|
15
|
+
const { assertChannelStatusInstallable } = require('./channel-definition-status');
|
|
15
16
|
const { getIntegrationPath } = require('../utils/paths');
|
|
16
17
|
const {
|
|
17
18
|
copyChannelIntegrationTemplate,
|
|
@@ -29,6 +30,7 @@ const { generateDeployJson } = require('../generator/index');
|
|
|
29
30
|
*/
|
|
30
31
|
async function scaffoldChannelIntegration(channelTarget, options = {}) {
|
|
31
32
|
const target = getChannelTarget(channelTarget);
|
|
33
|
+
assertChannelStatusInstallable(channelTarget, options);
|
|
32
34
|
if (target.experimental && !options.allowExperimental) {
|
|
33
35
|
throw new Error(
|
|
34
36
|
`Channel target "${channelTarget}" is experimental. Pass --allow-experimental to scaffold.`
|
|
@@ -36,6 +36,7 @@ const { applyCopilotOauthProfile, applyCopilotRuntimeDomain } = require('./chann
|
|
|
36
36
|
const { chatgptDiscoveryBlockerLabel } = require('./chatgpt-setup-values');
|
|
37
37
|
const { applyMcpClientRuntimeValues } = require('./mcp-client/runtime');
|
|
38
38
|
const { applyClaudeRuntimeValues } = require('./claude-runtime');
|
|
39
|
+
const { applySlackMcpRuntimeValues } = require('./slack-mcp-runtime');
|
|
39
40
|
|
|
40
41
|
const DEFAULT_SLACK_COMMAND_PREFIX = 'af';
|
|
41
42
|
|
|
@@ -347,6 +348,7 @@ function applySlackRuntimeValues(resolved, params) {
|
|
|
347
348
|
Object.assign(resolved, resolveSlackOAuthManifestFields());
|
|
348
349
|
delete resolved.oauthCallbackUrl;
|
|
349
350
|
resolved.commandPrefix = normalizeSlackCommandPrefix(params.commandPrefix);
|
|
351
|
+
resolved.enableMcpServer = isTrueLike(params.enableMcpServer);
|
|
350
352
|
resolved.packageVersion =
|
|
351
353
|
typeof params.packageVersion === 'string' && params.packageVersion.trim()
|
|
352
354
|
? params.packageVersion.trim()
|
|
@@ -356,6 +358,17 @@ function applySlackRuntimeValues(resolved, params) {
|
|
|
356
358
|
resolved.appLongDescriptionJson = JSON.stringify(appLongDescription);
|
|
357
359
|
}
|
|
358
360
|
|
|
361
|
+
/**
|
|
362
|
+
* @param {unknown} value
|
|
363
|
+
* @returns {boolean}
|
|
364
|
+
*/
|
|
365
|
+
function isTrueLike(value) {
|
|
366
|
+
if (value === true) {
|
|
367
|
+
return true;
|
|
368
|
+
}
|
|
369
|
+
return typeof value === 'string' && /^(true|1|yes|on)$/i.test(value.trim());
|
|
370
|
+
}
|
|
371
|
+
|
|
359
372
|
/**
|
|
360
373
|
* Slack slash alias prefix: letters then letters/digits, 1–16 chars.
|
|
361
374
|
* @param {unknown} raw
|
|
@@ -438,6 +451,7 @@ function applyChannelSpecificRuntime(resolved, params) {
|
|
|
438
451
|
if (params.channelTarget === 'slack') {
|
|
439
452
|
applySlackRuntimeValues(resolved, params);
|
|
440
453
|
applyDiscoveryPackageContext(resolved, params.packageContext);
|
|
454
|
+
applySlackMcpRuntimeValues(resolved, params);
|
|
441
455
|
}
|
|
442
456
|
if (params.channelTarget === 'microsoft-copilot') {
|
|
443
457
|
applyMicrosoftCopilotRuntimeValues(resolved, params);
|
|
@@ -14,6 +14,12 @@ const {
|
|
|
14
14
|
listChannelDefinitionKeys
|
|
15
15
|
} = require('./channel-definition-registry');
|
|
16
16
|
const { toChannelTargetProjection } = require('./channel-definition-project');
|
|
17
|
+
const {
|
|
18
|
+
assertChannelStatusInstallable,
|
|
19
|
+
channelStatusOf,
|
|
20
|
+
isCatalogHiddenStatus,
|
|
21
|
+
isInstallableStatus
|
|
22
|
+
} = require('./channel-definition-status');
|
|
17
23
|
|
|
18
24
|
function buildChannelTargets() {
|
|
19
25
|
const targets = {};
|
|
@@ -48,15 +54,21 @@ function isChannelTargetKey(channelTarget) {
|
|
|
48
54
|
*/
|
|
49
55
|
function formatSupportedChannelTargetsHelp() {
|
|
50
56
|
const targets = resolveChannelTargets();
|
|
51
|
-
const
|
|
52
|
-
const stable =
|
|
53
|
-
const experimental =
|
|
57
|
+
const installable = listInstallableChannelTargetKeys({ allowExperimental: true });
|
|
58
|
+
const stable = installable.filter((key) => !targets[key].experimental);
|
|
59
|
+
const experimental = installable.filter((key) => targets[key].experimental);
|
|
60
|
+
const comingSoon = listLiveChannelTargetKeys({ allowExperimental: true }).filter(
|
|
61
|
+
(key) => channelStatusOf(key) === 'coming-soon'
|
|
62
|
+
);
|
|
54
63
|
const lines = ['Supported channels:', ` ${stable.join(', ')}`];
|
|
55
64
|
if (experimental.length > 0) {
|
|
56
65
|
lines.push(
|
|
57
66
|
` ${experimental.join(', ')} (experimental — scaffold with --allow-experimental)`
|
|
58
67
|
);
|
|
59
68
|
}
|
|
69
|
+
if (comingSoon.length > 0) {
|
|
70
|
+
lines.push(` ${comingSoon.join(', ')} (coming soon — not installable)`);
|
|
71
|
+
}
|
|
60
72
|
return lines.join('\n');
|
|
61
73
|
}
|
|
62
74
|
|
|
@@ -81,18 +93,30 @@ function getChannelTarget(channelTarget) {
|
|
|
81
93
|
}
|
|
82
94
|
|
|
83
95
|
/**
|
|
84
|
-
* Live keys, plus experimental when `--allow-experimental` is set.
|
|
96
|
+
* Live keys (not hide), plus experimental when `--allow-experimental` is set.
|
|
85
97
|
* @param {{ allowExperimental?: boolean }} [options]
|
|
86
98
|
* @returns {string[]}
|
|
87
99
|
*/
|
|
88
100
|
function listLiveChannelTargetKeys(options = {}) {
|
|
89
101
|
const targets = resolveChannelTargets();
|
|
90
102
|
return Object.keys(targets).filter((key) => {
|
|
103
|
+
if (isCatalogHiddenStatus(channelStatusOf(key))) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
91
106
|
const target = targets[key];
|
|
92
107
|
return !target.experimental || options.allowExperimental === true;
|
|
93
108
|
});
|
|
94
109
|
}
|
|
95
110
|
|
|
111
|
+
/**
|
|
112
|
+
* Keys that may start a new install (visible). Coming-soon is catalog-only.
|
|
113
|
+
* @param {{ allowExperimental?: boolean }} [options]
|
|
114
|
+
* @returns {string[]}
|
|
115
|
+
*/
|
|
116
|
+
function listInstallableChannelTargetKeys(options = {}) {
|
|
117
|
+
return listLiveChannelTargetKeys(options).filter((key) => isInstallableStatus(channelStatusOf(key)));
|
|
118
|
+
}
|
|
119
|
+
|
|
96
120
|
/**
|
|
97
121
|
* Inquirer list choices for `aifabrix channel add` (labels from the registry).
|
|
98
122
|
* @param {{ allowExperimental?: boolean }} [options]
|
|
@@ -100,7 +124,7 @@ function listLiveChannelTargetKeys(options = {}) {
|
|
|
100
124
|
*/
|
|
101
125
|
function listWizardChannelChoices(options = {}) {
|
|
102
126
|
const targets = resolveChannelTargets();
|
|
103
|
-
return
|
|
127
|
+
return listInstallableChannelTargetKeys(options)
|
|
104
128
|
.map((key) => targets[key])
|
|
105
129
|
.sort((a, b) => (a.wizardOrder || 100) - (b.wizardOrder || 100))
|
|
106
130
|
.map((target) => ({ name: target.displayLabel, value: target.key }));
|
|
@@ -114,6 +138,7 @@ function listWizardChannelChoices(options = {}) {
|
|
|
114
138
|
*/
|
|
115
139
|
function assertChannelTargetInstallable(channelTarget, options = {}) {
|
|
116
140
|
const target = getChannelTarget(channelTarget);
|
|
141
|
+
assertChannelStatusInstallable(channelTarget, options);
|
|
117
142
|
if (target.experimental && options.allowExperimental !== true) {
|
|
118
143
|
throw new Error(
|
|
119
144
|
`Channel target "${channelTarget}" is experimental. Pass --allow-experimental to install.`
|
|
@@ -146,6 +171,7 @@ module.exports = {
|
|
|
146
171
|
formatSupportedChannelTargetsHelp,
|
|
147
172
|
formatUnknownChannelTargetError,
|
|
148
173
|
listLiveChannelTargetKeys,
|
|
174
|
+
listInstallableChannelTargetKeys,
|
|
149
175
|
listWizardChannelChoices,
|
|
150
176
|
assertChannelTargetInstallable,
|
|
151
177
|
getChannelDefinition,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Customer-facing Claude connector form values: Name
|
|
2
|
+
* Customer-facing Claude connector form values: Name, Server URL, OAuth.
|
|
3
3
|
*
|
|
4
4
|
* @fileoverview Claude channel form values — describe, don't configure
|
|
5
5
|
*/
|
|
@@ -78,6 +78,9 @@ function formatClaudeFormValueLines(values) {
|
|
|
78
78
|
if (values.serverUrl) {
|
|
79
79
|
lines.push(`Server URL: ${values.serverUrl}`);
|
|
80
80
|
}
|
|
81
|
+
if (values.authentication) {
|
|
82
|
+
lines.push(`Authentication: ${values.authentication}`);
|
|
83
|
+
}
|
|
81
84
|
return lines;
|
|
82
85
|
}
|
|
83
86
|
|