chore: publish clean community baseline
This commit is contained in:
@@ -0,0 +1,367 @@
|
||||
function inferSchemaKind(typeName) {
|
||||
if (typeName === 'object') return 'object';
|
||||
if (typeName === 'array') return 'array';
|
||||
if (typeName === 'string') return 'string';
|
||||
if (typeName === 'integer') return 'integer';
|
||||
if (typeName === 'number') return 'number';
|
||||
if (typeName === 'boolean') return 'boolean';
|
||||
if (typeName === 'null') return 'null';
|
||||
return 'string';
|
||||
}
|
||||
|
||||
function convertJsonSchemaToCrankSchema(node, requiredNames) {
|
||||
var schemaNode = node || {};
|
||||
var typeName = Array.isArray(schemaNode.type)
|
||||
? schemaNode.type.find(function(value) { return value !== 'null'; }) || 'string'
|
||||
: schemaNode.type || (schemaNode.properties ? 'object' : 'string');
|
||||
var nullable = Array.isArray(schemaNode.type) && schemaNode.type.indexOf('null') >= 0;
|
||||
var kind = schemaNode.enum ? 'enum' : inferSchemaKind(typeName);
|
||||
var schema = {
|
||||
type: kind,
|
||||
description: schemaNode.description || null,
|
||||
required: false,
|
||||
nullable: nullable,
|
||||
default_value: Object.prototype.hasOwnProperty.call(schemaNode, 'default') ? schemaNode.default : null,
|
||||
fields: {},
|
||||
items: null,
|
||||
enum_values: schemaNode.enum || [],
|
||||
variants: [],
|
||||
};
|
||||
|
||||
if (kind === 'object') {
|
||||
var requiredSet = new Set(schemaNode.required || requiredNames || []);
|
||||
Object.keys(schemaNode.properties || {}).forEach(function(fieldName) {
|
||||
var field = convertJsonSchemaToCrankSchema(schemaNode.properties[fieldName], []);
|
||||
field.required = requiredSet.has(fieldName);
|
||||
schema.fields[fieldName] = field;
|
||||
});
|
||||
}
|
||||
|
||||
if (kind === 'array' && schemaNode.items) {
|
||||
schema.items = convertJsonSchemaToCrankSchema(schemaNode.items, []);
|
||||
}
|
||||
|
||||
return schema;
|
||||
}
|
||||
|
||||
function mappingRootForProtocol(protocol) {
|
||||
return '$.request.body';
|
||||
}
|
||||
|
||||
var REQUEST_MAPPING_TARGET_PREFIXES = [
|
||||
'path',
|
||||
'query',
|
||||
'headers',
|
||||
'body',
|
||||
'variables',
|
||||
'grpc',
|
||||
];
|
||||
|
||||
function normalizeInputSource(path) {
|
||||
if (!path) return '$.mcp';
|
||||
if (path === '$') return '$.mcp';
|
||||
if (path.indexOf('$.mcp') === 0) return path;
|
||||
if (path.indexOf('$.input') === 0) return '$.mcp' + path.slice('$.input'.length);
|
||||
return '$.mcp.' + path.replace(/^\$\./, '');
|
||||
}
|
||||
|
||||
function normalizeInputTarget(target) {
|
||||
if (!target) return mappingRootForProtocol(wizardProtocol);
|
||||
if (target.indexOf('$.request.') === 0) return target;
|
||||
if (target.indexOf('request.') === 0) return '$.' + target;
|
||||
|
||||
var normalized = target.replace(/^\$\./, '');
|
||||
var prefix = normalized.split('.')[0];
|
||||
if (REQUEST_MAPPING_TARGET_PREFIXES.indexOf(prefix) >= 0) {
|
||||
return '$.request.' + normalized;
|
||||
}
|
||||
|
||||
return mappingRootForProtocol(wizardProtocol) + '.' + normalized;
|
||||
}
|
||||
|
||||
function normalizeOutputSource(path) {
|
||||
if (!path) return '$.response.body';
|
||||
if (path.indexOf('$.') === 0) return path;
|
||||
return '$.' + path.replace(/^\$\./, '');
|
||||
}
|
||||
|
||||
function normalizeOutputTarget(target) {
|
||||
if (!target) return '$.output';
|
||||
if (target.indexOf('$.output') === 0) return target;
|
||||
if (target.indexOf('output') === 0) return '$.' + target;
|
||||
return '$.output.' + target.replace(/^\$\./, '');
|
||||
}
|
||||
|
||||
function buildMappingSet(rawValue, mode) {
|
||||
var value = rawValue || {};
|
||||
var rules = [];
|
||||
|
||||
Object.keys(value).forEach(function(target) {
|
||||
var source = value[target];
|
||||
if (mode === 'input') {
|
||||
rules.push({
|
||||
source: normalizeInputSource(source),
|
||||
target: normalizeInputTarget(target),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
rules.push({
|
||||
source: normalizeOutputSource(source),
|
||||
target: normalizeOutputTarget(target),
|
||||
});
|
||||
});
|
||||
|
||||
return { rules: rules };
|
||||
}
|
||||
|
||||
function parseExecutionConfig(text) {
|
||||
var value = parseStructuredText(text);
|
||||
var retry = value.retry || {};
|
||||
var headers = value.headers && typeof value.headers === 'object' ? value.headers : {};
|
||||
var selectedUpstream = currentUpstream();
|
||||
if (!selectedUpstream && wizardMode !== 'edit') {
|
||||
throw new Error(tKey('wizard.error.save_upstream_first'));
|
||||
}
|
||||
var authProfileRef = selectedUpstream && selectedUpstream.authProfileId
|
||||
? selectedUpstream.authProfileId
|
||||
: (value.auth && value.auth.profile ? value.auth.profile : null);
|
||||
var config = {
|
||||
timeout_ms: Number(value.timeout_ms || 10000),
|
||||
retry_policy: retry && retry.max_attempts ? { max_attempts: Number(retry.max_attempts) } : null,
|
||||
auth_profile_ref: authProfileRef,
|
||||
headers: headers,
|
||||
protocol_options: null,
|
||||
streaming: null,
|
||||
};
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
function currentUpstream() {
|
||||
var selected = upstreams.find(function(item) { return item.id === selectedUpstreamId; });
|
||||
if (selected) return selected;
|
||||
|
||||
var customName = textValue('new-upstream-name');
|
||||
var customUrl = textValue('new-upstream-url');
|
||||
if (!customUrl) return null;
|
||||
|
||||
var authMode = textValue('new-upstream-auth-mode') || 'none';
|
||||
var authProfileId = authMode === 'existing' ? textValue('new-upstream-auth-profile') : null;
|
||||
var authProfile = authProfileById(authProfileId);
|
||||
return {
|
||||
id: 'custom',
|
||||
name: customName || 'custom-upstream',
|
||||
url: customUrl,
|
||||
staticHeaders: textValue('new-upstream-static-headers') || '{\n}',
|
||||
authMode: authMode,
|
||||
authProfileId: authProfileId || null,
|
||||
authProfileName: authProfile ? authProfile.name : '',
|
||||
authKind: authProfile ? authProfile.kind : null,
|
||||
};
|
||||
}
|
||||
|
||||
function joinUrl(baseUrl, path) {
|
||||
if (!baseUrl) return path || '';
|
||||
if (!path) return baseUrl;
|
||||
return baseUrl.replace(/\/+$/, '') + '/' + path.replace(/^\/+/, '');
|
||||
}
|
||||
|
||||
function parseHeaderMap(text) {
|
||||
if (!text || !text.trim()) return {};
|
||||
var value = parseStructuredText(text);
|
||||
return value && typeof value === 'object' ? value : {};
|
||||
}
|
||||
|
||||
function buildTarget() {
|
||||
var upstream = currentUpstream();
|
||||
if (!upstream || !upstream.url) {
|
||||
throw new Error(tKey('wizard.error.select_upstream'));
|
||||
}
|
||||
|
||||
var pathTemplate = textValue('endpoint-path') || '/';
|
||||
var activeMethod = document.querySelector('.method-card.active');
|
||||
return {
|
||||
kind: 'rest',
|
||||
base_url: upstream.url,
|
||||
method: activeMethod ? activeMethod.dataset.method : 'POST',
|
||||
path_template: pathTemplate,
|
||||
static_headers: parseHeaderMap(upstream.staticHeaders),
|
||||
};
|
||||
}
|
||||
|
||||
function crankSchemaToJsonSchema(schema) {
|
||||
var result = {};
|
||||
var typeName = schema.type === 'enum' ? 'string' : schema.type;
|
||||
result.type = schema.nullable ? [typeName, 'null'] : typeName;
|
||||
if (schema.description) result.description = schema.description;
|
||||
if (schema.default_value !== null && schema.default_value !== undefined) result.default = schema.default_value;
|
||||
if (schema.enum_values && schema.enum_values.length) result.enum = schema.enum_values.slice();
|
||||
if (schema.type === 'object') {
|
||||
result.type = schema.nullable ? ['object', 'null'] : 'object';
|
||||
result.properties = {};
|
||||
var required = [];
|
||||
Object.keys(schema.fields || {}).forEach(function(fieldName) {
|
||||
var field = schema.fields[fieldName];
|
||||
result.properties[fieldName] = crankSchemaToJsonSchema(field);
|
||||
if (field.required) required.push(fieldName);
|
||||
});
|
||||
if (required.length) result.required = required;
|
||||
result.additionalProperties = false;
|
||||
}
|
||||
if (schema.type === 'array' && schema.items) {
|
||||
result.items = crankSchemaToJsonSchema(schema.items);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function exampleValueForSchema(schema) {
|
||||
if (!schema) return {};
|
||||
|
||||
if (schema.default_value !== null && schema.default_value !== undefined) {
|
||||
return schema.default_value;
|
||||
}
|
||||
|
||||
if (schema.enum_values && schema.enum_values.length) {
|
||||
return schema.enum_values[0];
|
||||
}
|
||||
|
||||
if (schema.type === 'object') {
|
||||
var object = {};
|
||||
Object.keys(schema.fields || {}).forEach(function(fieldName) {
|
||||
object[fieldName] = exampleValueForSchema(schema.fields[fieldName]);
|
||||
});
|
||||
return object;
|
||||
}
|
||||
|
||||
if (schema.type === 'array') {
|
||||
return [exampleValueForSchema(schema.items)];
|
||||
}
|
||||
|
||||
if (schema.type === 'integer') return 1;
|
||||
if (schema.type === 'number') return 1.23;
|
||||
if (schema.type === 'boolean') return true;
|
||||
if (schema.type === 'null') return null;
|
||||
return 'string';
|
||||
}
|
||||
|
||||
function firstToolExampleValue(toolDescription, fieldName) {
|
||||
var examples = toolDescription && Array.isArray(toolDescription.examples)
|
||||
? toolDescription.examples
|
||||
: [];
|
||||
if (!examples.length) return null;
|
||||
|
||||
var value = examples[0] && examples[0][fieldName];
|
||||
return value === undefined ? null : value;
|
||||
}
|
||||
|
||||
function prefillWizardSamples(snapshot) {
|
||||
var inputExample = firstToolExampleValue(snapshot.tool_description, 'input');
|
||||
var outputExample = firstToolExampleValue(snapshot.tool_description, 'output');
|
||||
var inputSample = inputExample !== null ? inputExample : exampleValueForSchema(snapshot.input_schema);
|
||||
setValue('wizard-input-sample', JSON.stringify(inputSample, null, 2));
|
||||
setValue('wizard-test-input', JSON.stringify(inputSample, null, 2));
|
||||
setValue('wizard-output-sample', JSON.stringify(
|
||||
outputExample !== null ? outputExample : exampleValueForSchema(snapshot.output_schema),
|
||||
null,
|
||||
2
|
||||
));
|
||||
}
|
||||
|
||||
function mappingSetToEditorValue(mappingSet, mode, protocol) {
|
||||
var rules = mappingSet && mappingSet.rules ? mappingSet.rules : [];
|
||||
var object = {};
|
||||
rules.forEach(function(rule) {
|
||||
if (mode === 'input') {
|
||||
var key = rule.target.indexOf(mappingRootForProtocol(protocol) + '.') === 0
|
||||
? rule.target.replace(mappingRootForProtocol(protocol) + '.', '')
|
||||
: rule.target.replace('$.request.', '');
|
||||
object[key] = rule.source.replace('$.mcp.', '$.input.');
|
||||
return;
|
||||
}
|
||||
var outputKey = rule.target.replace('$.output.', '');
|
||||
object[outputKey] = rule.source;
|
||||
});
|
||||
return window.jsyaml ? window.jsyaml.dump(object, { lineWidth: -1 }) : JSON.stringify(object, null, 2);
|
||||
}
|
||||
|
||||
function executionConfigToEditorValue(config) {
|
||||
var value = {
|
||||
timeout_ms: config.timeout_ms,
|
||||
};
|
||||
if (config.retry_policy) {
|
||||
value.retry = { max_attempts: config.retry_policy.max_attempts };
|
||||
}
|
||||
if (config.auth_profile_ref) {
|
||||
value.auth = { profile: config.auth_profile_ref };
|
||||
}
|
||||
if (config.headers && Object.keys(config.headers).length) {
|
||||
value.headers = config.headers;
|
||||
}
|
||||
return window.jsyaml ? window.jsyaml.dump(value, { lineWidth: -1 }) : JSON.stringify(value, null, 2);
|
||||
}
|
||||
|
||||
function operationSnapshot(versionDocument) {
|
||||
if (!versionDocument) return {};
|
||||
return versionDocument.snapshot || versionDocument;
|
||||
}
|
||||
|
||||
function prefillUpstream(baseUrl, headers, authProfileRef) {
|
||||
var known = upstreams.find(function(item) {
|
||||
return item.url === baseUrl && (item.authProfileId || null) === (authProfileRef || null);
|
||||
});
|
||||
if (known) {
|
||||
pickUpstream(known.id);
|
||||
return;
|
||||
}
|
||||
|
||||
selectedUpstreamId = null;
|
||||
var trigger = document.getElementById('upstream-new-trigger');
|
||||
var form = document.getElementById('upstream-new-form');
|
||||
if (trigger) trigger.classList.add('active');
|
||||
if (form) form.hidden = false;
|
||||
setValue('new-upstream-name', 'imported-upstream');
|
||||
setValue('new-upstream-url', baseUrl);
|
||||
setValue('new-upstream-static-headers', headers && Object.keys(headers).length ? JSON.stringify(headers, null, 2) : '{\n}');
|
||||
setValue('new-upstream-auth-mode', authProfileRef ? 'existing' : 'none');
|
||||
setValue('new-upstream-auth-profile', authProfileRef || '');
|
||||
updateUpstreamAuthUi();
|
||||
|
||||
var valueEl = document.getElementById('upstream-combobox-value');
|
||||
if (valueEl) {
|
||||
valueEl.innerHTML = '';
|
||||
valueEl.appendChild(buildUpstreamTriggerContent('imported-upstream', baseUrl));
|
||||
}
|
||||
}
|
||||
|
||||
function prefillWizardFromEdit(detail, versionDocument) {
|
||||
if (!detail || !versionDocument) return;
|
||||
|
||||
var snapshot = operationSnapshot(versionDocument);
|
||||
setEditModePresentation();
|
||||
selectProtocol(snapshot.protocol || detail.protocol);
|
||||
|
||||
var target = snapshot.target || {};
|
||||
if (target.kind === 'rest') {
|
||||
prefillUpstream(target.base_url, target.static_headers, snapshot.execution_config ? snapshot.execution_config.auth_profile_ref : null);
|
||||
setValue('endpoint-path', target.path_template);
|
||||
document.querySelectorAll('.method-card').forEach(function(card) {
|
||||
card.classList.toggle('active', card.dataset.method === target.method);
|
||||
});
|
||||
}
|
||||
|
||||
setValue('tool-name', snapshot.name || detail.name);
|
||||
setValue('tool-display-name', snapshot.display_name || detail.display_name);
|
||||
setValue('tool-title', snapshot.tool_description ? snapshot.tool_description.title : (snapshot.display_name || detail.display_name));
|
||||
setValue('tool-description', snapshot.tool_description ? snapshot.tool_description.description : '');
|
||||
setValue('tool-input-schema', JSON.stringify(crankSchemaToJsonSchema(snapshot.input_schema), null, 2));
|
||||
setValue('tool-output-schema', JSON.stringify(crankSchemaToJsonSchema(snapshot.output_schema), null, 2));
|
||||
setValue('tool-input-mapping', mappingSetToEditorValue(snapshot.input_mapping, 'input', snapshot.protocol || detail.protocol));
|
||||
setValue('tool-output-mapping', mappingSetToEditorValue(snapshot.output_mapping, 'output', snapshot.protocol || detail.protocol));
|
||||
setValue('tool-exec-config', executionConfigToEditorValue(snapshot.execution_config || {}));
|
||||
prefillWizardSamples(snapshot);
|
||||
|
||||
var toolNameInput = document.getElementById('tool-name');
|
||||
if (toolNameInput) toolNameInput.disabled = true;
|
||||
updateWizardProtocolVisibility();
|
||||
}
|
||||
Reference in New Issue
Block a user