ui: gate community wizard capabilities
This commit is contained in:
@@ -575,6 +575,8 @@ var TRANSLATIONS = {
|
||||
'wizard.step1.unary': 'Unary',
|
||||
'wizard.step1.tip_title': 'You can change this later',
|
||||
'wizard.step1.tip_body': 'Switching protocol after configuring subsequent steps will clear schema and mapping data. Save your operation as a draft before experimenting. See protocol migration guide for details.',
|
||||
'wizard.step1.community_protocol_title': 'Community protocol scope',
|
||||
'wizard.step1.community_protocol_note': 'This Community build hides {protocols}. Commercial editions unlock those protocol surfaces.',
|
||||
'wizard.step2.title': 'Select upstream & endpoint',
|
||||
'wizard.step2.subtitle': 'Choose an existing upstream or register a new one. Then define the specific endpoint path this operation will call.',
|
||||
'wizard.required': 'Required',
|
||||
@@ -762,6 +764,8 @@ var TRANSLATIONS = {
|
||||
'wizard.step5.execution': 'Execution',
|
||||
'wizard.step5.exec_title': 'Execution config',
|
||||
'wizard.step5.exec_subtitle': 'Timeouts, retry policy and auth profile reference',
|
||||
'wizard.step5.security_level_title': 'Operation security in Community',
|
||||
'wizard.step5.community_security_note': 'Community supports only the standard operation security level with static AI-agent keys. Short-lived and one-time token flows require a commercial edition.',
|
||||
'wizard.step5.live_title': 'Live validation and publishing',
|
||||
'wizard.step5.draft_actions': 'Draft actions',
|
||||
'wizard.step5.live_save_title': 'Live actions save the draft first',
|
||||
@@ -931,6 +935,8 @@ var TRANSLATIONS = {
|
||||
'agents.title': 'Agents',
|
||||
'agents.subtitle': 'Named MCP endpoints that expose a curated subset of operations to an LLM',
|
||||
'agents.new': 'New agent',
|
||||
'agents.limit.title': 'Agent limit reached',
|
||||
'agents.limit.message': 'This Community build allows up to {limit} AI agent. Upgrade the edition or remove an existing agent to add another one.',
|
||||
'agents.stats.total': 'Total agents',
|
||||
'agents.stats.total_sub': 'across this workspace',
|
||||
'agents.stats.published': 'Published',
|
||||
@@ -1623,6 +1629,8 @@ var TRANSLATIONS = {
|
||||
'wizard.step1.unary': 'Unary',
|
||||
'wizard.step1.tip_title': 'Это можно изменить позже',
|
||||
'wizard.step1.tip_body': 'Смена протокола после настройки следующих шагов очистит схемы и mapping. Сохраните операцию как черновик перед экспериментами. См. гайд по миграции протоколов.',
|
||||
'wizard.step1.community_protocol_title': 'Граница протоколов Community',
|
||||
'wizard.step1.community_protocol_note': 'В этой Community-сборке скрыты {protocols}. Эти протокольные поверхности открываются в коммерческих редакциях.',
|
||||
'wizard.step2.title': 'Выберите upstream и endpoint',
|
||||
'wizard.step2.subtitle': 'Выберите существующий upstream или зарегистрируйте новый. Затем задайте конкретный путь endpoint-а для этой операции.',
|
||||
'wizard.required': 'Обязательно',
|
||||
@@ -1812,6 +1820,8 @@ var TRANSLATIONS = {
|
||||
'wizard.step5.execution': 'Исполнение',
|
||||
'wizard.step5.exec_title': 'Execution config',
|
||||
'wizard.step5.exec_subtitle': 'Таймауты, retry policy и ссылка на auth profile',
|
||||
'wizard.step5.security_level_title': 'Защита операций в Community',
|
||||
'wizard.step5.community_security_note': 'Community поддерживает только стандартный уровень защиты операций со статическими ключами AI-агента. Короткоживущие и одноразовые токены требуют коммерческую редакцию.',
|
||||
'wizard.step5.live_title': 'Live-проверка и публикация',
|
||||
'wizard.step5.draft_actions': 'Действия черновика',
|
||||
'wizard.step5.live_save_title': 'Live-действия сначала сохраняют черновик',
|
||||
@@ -1985,6 +1995,8 @@ var TRANSLATIONS = {
|
||||
'agents.title': 'Агенты',
|
||||
'agents.subtitle': 'Именованные MCP endpoint-ы, открывающие LLM ограниченный набор операций',
|
||||
'agents.new': 'Новый агент',
|
||||
'agents.limit.title': 'Достигнут лимит агентов',
|
||||
'agents.limit.message': 'В этой Community-сборке доступно не более {limit} AI-агента. Чтобы добавить еще одного, удалите существующего агента или перейдите на другую редакцию.',
|
||||
'agents.stats.total': 'Всего агентов',
|
||||
'agents.stats.total_sub': 'в этом воркспейсе',
|
||||
'agents.stats.published': 'Опубликованы',
|
||||
|
||||
@@ -175,6 +175,9 @@
|
||||
function bindProtocolCards() {
|
||||
document.querySelectorAll('.protocol-card').forEach(function(card) {
|
||||
card.addEventListener('click', function() {
|
||||
if (card.hidden || card.getAttribute('aria-disabled') === 'true') {
|
||||
return;
|
||||
}
|
||||
document.querySelectorAll('.protocol-card').forEach(function(item) {
|
||||
item.classList.remove('selected');
|
||||
item.setAttribute('aria-checked', 'false');
|
||||
@@ -214,6 +217,56 @@
|
||||
});
|
||||
}
|
||||
|
||||
function applyEditionProtocolVisibility(capabilities) {
|
||||
var supported = capabilities && Array.isArray(capabilities.supported_protocols)
|
||||
? capabilities.supported_protocols.slice()
|
||||
: ['rest', 'graphql', 'grpc'];
|
||||
var hiddenProtocols = [];
|
||||
|
||||
document.querySelectorAll('.protocol-card').forEach(function(card) {
|
||||
var protocol = card.dataset.protocol || 'rest';
|
||||
var isSupported = supported.indexOf(protocol) >= 0;
|
||||
card.hidden = !isSupported;
|
||||
card.setAttribute('aria-disabled', isSupported ? 'false' : 'true');
|
||||
if (!isSupported) {
|
||||
card.classList.remove('selected');
|
||||
card.setAttribute('aria-checked', 'false');
|
||||
hiddenProtocols.push(protocol);
|
||||
}
|
||||
});
|
||||
|
||||
if (supported.indexOf(window.wizardProtocol) === -1) {
|
||||
window.wizardProtocol = supported[0] || 'rest';
|
||||
}
|
||||
|
||||
var selectedCard = document.querySelector('.protocol-card[data-protocol="' + window.wizardProtocol + '"]');
|
||||
if (selectedCard) {
|
||||
selectedCard.classList.add('selected');
|
||||
selectedCard.setAttribute('aria-checked', 'true');
|
||||
}
|
||||
|
||||
var step3Name = document.getElementById('sidebar-step-3-name');
|
||||
var labels = window.CrankWizardState.step3Labels();
|
||||
if (step3Name) {
|
||||
step3Name.textContent = labels[window.wizardProtocol] || tKey('wizard.step3.rest.label');
|
||||
}
|
||||
|
||||
var note = document.getElementById('wizard-edition-protocol-note');
|
||||
var noteText = document.getElementById('wizard-edition-protocol-note-text');
|
||||
if (note && noteText) {
|
||||
if (hiddenProtocols.length) {
|
||||
note.hidden = false;
|
||||
noteText.textContent = tfKey('wizard.step1.community_protocol_note', {
|
||||
protocols: hiddenProtocols.map(function(protocol) {
|
||||
return tKey('settings.capability.' + protocol);
|
||||
}).join(', ')
|
||||
});
|
||||
} else {
|
||||
note.hidden = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.CrankWizardShell = {
|
||||
TOTAL_STEPS: TOTAL_STEPS,
|
||||
step3PanelId: step3PanelId,
|
||||
@@ -222,5 +275,6 @@
|
||||
goToStep: goToStep,
|
||||
loadWizardPanels: loadWizardPanels,
|
||||
bindProtocolCards: bindProtocolCards,
|
||||
applyEditionProtocolVisibility: applyEditionProtocolVisibility,
|
||||
};
|
||||
}());
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
grpcDescriptorServices: [],
|
||||
soapServiceCatalog: [],
|
||||
wizardProtocolCapabilities: null,
|
||||
wizardEditionCapabilities: null,
|
||||
wizardSecrets: [],
|
||||
wizardAuthProfiles: [],
|
||||
selectedUpstreamId: null,
|
||||
@@ -68,11 +69,29 @@
|
||||
};
|
||||
}
|
||||
|
||||
function defaultEditionCapabilities() {
|
||||
return {
|
||||
edition: 'community',
|
||||
supported_protocols: ['rest', 'graphql', 'grpc'],
|
||||
supported_security_levels: ['standard'],
|
||||
machine_access_modes: ['static_agent_key'],
|
||||
limits: {
|
||||
max_workspaces: 1,
|
||||
max_users_per_workspace: 1,
|
||||
max_agents_per_workspace: 1,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function currentProtocolCapabilities() {
|
||||
var capabilities = window.wizardProtocolCapabilities || defaultProtocolCapabilities();
|
||||
return capabilities[window.wizardProtocol] || capabilities.rest;
|
||||
}
|
||||
|
||||
function currentEditionCapabilities() {
|
||||
return window.wizardEditionCapabilities || defaultEditionCapabilities();
|
||||
}
|
||||
|
||||
async function loadProtocolCapabilities() {
|
||||
if (!window.wizardWorkspaceId || !window.CrankApi || typeof window.CrankApi.getProtocolCapabilities !== 'function') {
|
||||
window.wizardProtocolCapabilities = defaultProtocolCapabilities();
|
||||
@@ -93,6 +112,21 @@
|
||||
return window.wizardProtocolCapabilities;
|
||||
}
|
||||
|
||||
async function loadEditionCapabilities() {
|
||||
if (!window.CrankApi || typeof window.CrankApi.getCapabilities !== 'function') {
|
||||
window.wizardEditionCapabilities = defaultEditionCapabilities();
|
||||
return window.wizardEditionCapabilities;
|
||||
}
|
||||
|
||||
try {
|
||||
window.wizardEditionCapabilities = await window.CrankApi.getCapabilities();
|
||||
} catch (_error) {
|
||||
window.wizardEditionCapabilities = defaultEditionCapabilities();
|
||||
}
|
||||
|
||||
return window.wizardEditionCapabilities;
|
||||
}
|
||||
|
||||
function step3Labels() {
|
||||
return {
|
||||
rest: tKey('wizard.step3.rest.label'),
|
||||
@@ -106,8 +140,11 @@
|
||||
window.CrankWizardState = {
|
||||
state: window,
|
||||
defaultProtocolCapabilities: defaultProtocolCapabilities,
|
||||
defaultEditionCapabilities: defaultEditionCapabilities,
|
||||
currentProtocolCapabilities: currentProtocolCapabilities,
|
||||
currentEditionCapabilities: currentEditionCapabilities,
|
||||
loadProtocolCapabilities: loadProtocolCapabilities,
|
||||
loadEditionCapabilities: loadEditionCapabilities,
|
||||
step3Labels: step3Labels,
|
||||
};
|
||||
}());
|
||||
|
||||
@@ -6,12 +6,14 @@ function tfKey(key, vars) {
|
||||
}
|
||||
var TOTAL_STEPS = window.CrankWizardShell.TOTAL_STEPS;
|
||||
var loadProtocolCapabilities = window.CrankWizardState.loadProtocolCapabilities;
|
||||
var loadEditionCapabilities = window.CrankWizardState.loadEditionCapabilities;
|
||||
var currentProtocolCapabilities = window.CrankWizardState.currentProtocolCapabilities;
|
||||
var loadStep = window.CrankWizardShell.loadStep;
|
||||
var goToStep = window.CrankWizardShell.goToStep;
|
||||
var _doGoToStep = window.CrankWizardShell.doGoToStep;
|
||||
var loadWizardPanels = window.CrankWizardShell.loadWizardPanels;
|
||||
var bindProtocolCards = window.CrankWizardShell.bindProtocolCards;
|
||||
var applyEditionProtocolVisibility = window.CrankWizardShell.applyEditionProtocolVisibility;
|
||||
var step3PanelId = window.CrankWizardShell.step3PanelId;
|
||||
var bindStreamingConfigControls = window.CrankStreamingForm.bindStreamingConfigControls;
|
||||
var collectStreamingConfig = window.CrankStreamingForm.collectStreamingConfig;
|
||||
@@ -85,14 +87,17 @@ async function initWizardPage() {
|
||||
var workspace = window.getCurrentWorkspace ? window.getCurrentWorkspace() : null;
|
||||
wizardWorkspaceId = workspace ? workspace.id : null;
|
||||
window.wizardWorkspaceId = wizardWorkspaceId;
|
||||
var editionCapabilities = await loadEditionCapabilities();
|
||||
await loadProtocolCapabilities();
|
||||
|
||||
await loadWizardPanels([1, 2, 3, 4, 5]);
|
||||
applyEditionProtocolVisibility(editionCapabilities);
|
||||
await loadWizardAuthResources();
|
||||
bindProtocolCards();
|
||||
bindWizardLiveActions();
|
||||
bindStreamingConfigControls();
|
||||
updateUpstreamAuthUi();
|
||||
renderEditionCapabilityHints(editionCapabilities);
|
||||
|
||||
var quickSecretModal = document.getElementById('quick-secret-modal');
|
||||
var quickSecretClose = document.getElementById('quick-secret-close-btn');
|
||||
@@ -141,6 +146,19 @@ async function initWizardPage() {
|
||||
_doGoToStep(1);
|
||||
}
|
||||
|
||||
function renderEditionCapabilityHints(capabilities) {
|
||||
var securityNote = document.getElementById('wizard-security-level-note');
|
||||
var securityText = securityNote ? securityNote.querySelector('.info-callout-text') : null;
|
||||
if (!securityText) return;
|
||||
var levels = capabilities && Array.isArray(capabilities.supported_security_levels)
|
||||
? capabilities.supported_security_levels
|
||||
: ['standard'];
|
||||
securityNote.hidden = !(levels.length === 1 && levels[0] === 'standard');
|
||||
if (!securityNote.hidden) {
|
||||
securityText.textContent = tKey('wizard.step5.community_security_note');
|
||||
}
|
||||
}
|
||||
|
||||
if (window.CrankDiagnostics && typeof window.CrankDiagnostics.bootstrap === 'function') {
|
||||
window.CrankDiagnostics.bootstrap('wizard', initWizardPage);
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user