From ca9b86aadabb179e29e10542823e0e7d89602d88 Mon Sep 17 00:00:00 2001 From: "a.tolmachev" Date: Thu, 7 May 2026 21:16:36 +0000 Subject: [PATCH] community: remove remaining premium wizard and admin surface --- apps/admin-api/Cargo.toml | 5 + apps/admin-api/src/service.rs | 498 +--------------------- apps/mcp-server/Cargo.toml | 5 + apps/ui/html/wizard/step5.html | 194 --------- apps/ui/js/agents.js | 12 +- apps/ui/js/api.js | 40 -- apps/ui/js/catalog.js | 8 +- apps/ui/js/usage.js | 24 -- apps/ui/js/wizard-live.js | 222 +--------- apps/ui/js/wizard-model.js | 267 +----------- apps/ui/js/wizard-upstreams.js | 8 +- apps/ui/js/wizard.js | 34 -- apps/ui/scripts/build.js | 4 - crates/crank-registry/src/postgres/mod.rs | 1 + crates/crank-runtime/Cargo.toml | 4 + 15 files changed, 48 insertions(+), 1278 deletions(-) diff --git a/apps/admin-api/Cargo.toml b/apps/admin-api/Cargo.toml index e30845f..d60ac5f 100644 --- a/apps/admin-api/Cargo.toml +++ b/apps/admin-api/Cargo.toml @@ -5,6 +5,11 @@ license.workspace = true rust-version.workspace = true version.workspace = true +[[bin]] +name = "admin-api" +path = "src/main.rs" +test = false + [dependencies] argon2.workspace = true axum.workspace = true diff --git a/apps/admin-api/src/service.rs b/apps/admin-api/src/service.rs index 2e329c1..b4cbf70 100644 --- a/apps/admin-api/src/service.rs +++ b/apps/admin-api/src/service.rs @@ -17,15 +17,15 @@ use crank_core::{ }; use crank_mapping::{JsonPathRoot, MappingSet, infer_mapping_from_samples}; use crank_registry::{ - AgentSummary, AgentVersionRecord, AsyncJobFilter, CreateAgentRequest, CreateAsyncJobRequest, + AgentSummary, AgentVersionRecord, CreateAgentRequest, CreateAsyncJobRequest, CreateInvitationRequest, CreateInvocationLogRequest, CreatePlatformApiKeyRequest, CreateSecretRequest, CreateStreamSessionRequest, CreateVersionRequest, CreateWorkspaceRequest, InvitationRecord, InvocationLogRecord, ListInvocationLogsQuery, MembershipRecord, OperationAgentRef, OperationSampleMetadata, OperationSummary, OperationUsageSummary, - OperationVersionRecord, Page, PlatformApiKeyRecord, PostgresRegistry, PublishAgentRequest, + OperationVersionRecord, PlatformApiKeyRecord, PostgresRegistry, PublishAgentRequest, PublishRequest, RegistryError, RegistryOperation, RotateSecretRequest, SampleKind, SaveAgentBindingsRequest, SaveAuthProfileRequest, SaveSampleMetadataRequest, - StreamSessionFilter, UpdateAsyncJobStatusRequest, UpdateWorkspaceRequest, + UpdateAsyncJobStatusRequest, UpdateWorkspaceRequest, UsageAgentBreakdown, UsageBucket, UsageOperationBreakdown, UsageQuery, UsageSummary, UsageTimelinePoint, WorkspaceMembershipRecord, WorkspaceRecord, }; @@ -434,74 +434,6 @@ pub struct ProtocolCapabilityView { pub supports_aggregation_mode: Vec, } -#[derive(Clone, Debug, Deserialize)] -pub struct StreamSessionsQuery { - pub operation_id: Option, - pub agent_id: Option, - pub status: Option, - pub mode: Option, - pub page: Option, - pub page_size: Option, -} - -#[derive(Clone, Debug, Serialize)] -pub struct StreamSessionSummaryView { - pub id: String, - pub operation_id: String, - pub agent_id: Option, - pub protocol: Protocol, - pub mode: ExecutionMode, - pub status: StreamStatus, - #[serde(with = "time::serde::rfc3339")] - pub expires_at: OffsetDateTime, - #[serde(with = "time::serde::rfc3339::option")] - pub last_poll_at: Option, - #[serde(with = "time::serde::rfc3339")] - pub created_at: OffsetDateTime, - #[serde(with = "time::serde::rfc3339::option")] - pub closed_at: Option, -} - -#[derive(Clone, Debug, Serialize)] -pub struct StreamSessionDetailView { - #[serde(flatten)] - pub summary: StreamSessionSummaryView, - pub cursor: Option, -} - -#[derive(Clone, Debug, Deserialize)] -pub struct AsyncJobsQuery { - pub operation_id: Option, - pub agent_id: Option, - pub status: Option, - pub page: Option, - pub page_size: Option, -} - -#[derive(Clone, Debug, Serialize)] -pub struct AsyncJobSummaryView { - pub id: String, - pub operation_id: String, - pub agent_id: Option, - pub status: JobStatus, - pub progress: Value, - #[serde(with = "time::serde::rfc3339")] - pub created_at: OffsetDateTime, - #[serde(with = "time::serde::rfc3339")] - pub updated_at: OffsetDateTime, - #[serde(with = "time::serde::rfc3339::option")] - pub finished_at: Option, - #[serde(with = "time::serde::rfc3339::option")] - pub expires_at: Option, -} - -#[derive(Clone, Debug, Serialize)] -pub struct AsyncJobDetailView { - #[serde(flatten)] - pub summary: AsyncJobSummaryView, - pub error: Option, -} - #[derive(Clone, Debug, Deserialize)] pub struct GenerateDraftPayload { #[serde(default)] @@ -1613,327 +1545,6 @@ impl AdminService { )) } - #[instrument(skip(self))] - pub async fn list_stream_sessions( - &self, - workspace_id: &WorkspaceId, - query: StreamSessionsQuery, - ) -> Result, ApiError> { - self.ensure_workspace_exists(workspace_id).await?; - let operation_id = query.operation_id.as_deref().map(OperationId::new); - let agent_id = query.agent_id.as_deref().map(AgentId::new); - let limit = query.page_size.unwrap_or(20).max(1); - let page = self - .registry - .list_stream_sessions(StreamSessionFilter { - workspace_id, - agent_id: agent_id.as_ref(), - operation_id: operation_id.as_ref(), - status: query.status, - mode: query.mode, - limit, - }) - .await?; - - Ok(Page { - items: page - .items - .into_iter() - .map(stream_session_summary_view) - .collect(), - total: page.total, - }) - } - - #[instrument(skip(self))] - pub async fn get_stream_session( - &self, - workspace_id: &WorkspaceId, - session_id: &crank_core::StreamSessionId, - ) -> Result { - self.ensure_workspace_exists(workspace_id).await?; - let session = self - .registry - .get_stream_session(session_id) - .await? - .ok_or_else(|| { - ApiError::not_found_with_context( - format!("stream session {} was not found", session_id.as_str()), - json!({ "session_id": session_id.as_str() }), - ) - })?; - ensure_stream_session_workspace(&session, workspace_id)?; - let session = self - .touch_stream_session_poll_if_ready(workspace_id, session) - .await?; - - Ok(stream_session_detail_view(session)) - } - - #[instrument(skip(self))] - pub async fn stop_stream_session( - &self, - workspace_id: &WorkspaceId, - session_id: &crank_core::StreamSessionId, - ) -> Result { - self.ensure_workspace_exists(workspace_id).await?; - let session = self - .registry - .get_stream_session(session_id) - .await? - .ok_or_else(|| { - ApiError::not_found_with_context( - format!("stream session {} was not found", session_id.as_str()), - json!({ "session_id": session_id.as_str() }), - ) - })?; - ensure_stream_session_workspace(&session, workspace_id)?; - self.registry - .close_stream_session(session_id, &OffsetDateTime::now_utc()) - .await?; - let updated = self - .registry - .get_stream_session(session_id) - .await? - .ok_or_else(|| { - ApiError::not_found_with_context( - format!("stream session {} was not found", session_id.as_str()), - json!({ "session_id": session_id.as_str() }), - ) - })?; - - Ok(stream_session_detail_view(updated)) - } - - #[instrument(skip(self))] - pub async fn list_async_jobs( - &self, - workspace_id: &WorkspaceId, - query: AsyncJobsQuery, - ) -> Result, ApiError> { - self.ensure_workspace_exists(workspace_id).await?; - let operation_id = query.operation_id.as_deref().map(OperationId::new); - let agent_id = query.agent_id.as_deref().map(AgentId::new); - let limit = query.page_size.unwrap_or(20).max(1); - let page = self - .registry - .list_async_jobs(AsyncJobFilter { - workspace_id, - agent_id: agent_id.as_ref(), - operation_id: operation_id.as_ref(), - status: query.status, - limit, - }) - .await?; - - Ok(Page { - items: page.items.into_iter().map(async_job_summary_view).collect(), - total: page.total, - }) - } - - #[instrument(skip(self))] - pub async fn get_async_job( - &self, - workspace_id: &WorkspaceId, - job_id: &crank_core::AsyncJobId, - ) -> Result { - self.ensure_workspace_exists(workspace_id).await?; - let job = self.registry.get_async_job(job_id).await?.ok_or_else(|| { - ApiError::not_found_with_context( - format!("async job {} was not found", job_id.as_str()), - json!({ "job_id": job_id.as_str() }), - ) - })?; - ensure_async_job_workspace(&job, workspace_id)?; - let job = if matches!(job.status, JobStatus::Completed) { - job - } else { - self.touch_async_job_poll_if_ready(workspace_id, job) - .await? - }; - - Ok(async_job_detail_view(job)) - } - - #[instrument(skip(self))] - pub async fn cancel_async_job( - &self, - workspace_id: &WorkspaceId, - job_id: &crank_core::AsyncJobId, - ) -> Result { - self.ensure_workspace_exists(workspace_id).await?; - let job = self.registry.get_async_job(job_id).await?.ok_or_else(|| { - ApiError::not_found_with_context( - format!("async job {} was not found", job_id.as_str()), - json!({ "job_id": job_id.as_str() }), - ) - })?; - ensure_async_job_workspace(&job, workspace_id)?; - self.registry - .cancel_async_job(job_id, &OffsetDateTime::now_utc()) - .await?; - let updated = self.registry.get_async_job(job_id).await?.ok_or_else(|| { - ApiError::not_found_with_context( - format!("async job {} was not found", job_id.as_str()), - json!({ "job_id": job_id.as_str() }), - ) - })?; - - Ok(async_job_detail_view(updated)) - } - - #[instrument(skip(self))] - pub async fn get_async_job_result( - &self, - workspace_id: &WorkspaceId, - job_id: &crank_core::AsyncJobId, - ) -> Result { - self.ensure_workspace_exists(workspace_id).await?; - let job = self.registry.get_async_job(job_id).await?.ok_or_else(|| { - ApiError::not_found_with_context( - format!("async job {} was not found", job_id.as_str()), - json!({ "job_id": job_id.as_str() }), - ) - })?; - ensure_async_job_workspace(&job, workspace_id)?; - let job = if matches!(job.status, JobStatus::Completed) { - job - } else { - self.touch_async_job_poll_if_ready(workspace_id, job) - .await? - }; - - match job.status { - JobStatus::Completed => Ok(job.result.unwrap_or(Value::Null)), - JobStatus::Failed => Err(ApiError::conflict_with_context( - "async job failed", - json!({ - "job_id": job_id.as_str(), - "status": "failed", - "error": job.error, - }), - )), - JobStatus::Cancelled => Err(ApiError::conflict_with_context( - "async job was cancelled", - json!({ - "job_id": job_id.as_str(), - "status": "cancelled", - }), - )), - _ => Err(ApiError::conflict_with_context( - "async job result is not ready", - json!({ - "job_id": job_id.as_str(), - "status": match job.status { - JobStatus::Created => "created", - JobStatus::Running => "running", - JobStatus::Completed => "completed", - JobStatus::Failed => "failed", - JobStatus::Cancelled => "cancelled", - JobStatus::Expired => "expired", - }, - }), - )), - } - } - - async fn touch_stream_session_poll_if_ready( - &self, - workspace_id: &WorkspaceId, - session: StreamSession, - ) -> Result { - let poll_interval_ms = self - .streaming_poll_interval_ms(workspace_id, &session.operation_id) - .await?; - let now = OffsetDateTime::now_utc(); - let remaining_delay_ms = session.remaining_poll_delay_ms(now, poll_interval_ms); - - if remaining_delay_ms > 0 { - return Err(ApiError::rate_limited_with_context( - "stream session poll rate limit exceeded", - json!({ - "session_id": session.id.as_str(), - "poll_after_ms": remaining_delay_ms, - }), - )); - } - - self.registry - .touch_stream_session_poll(&session.id, &now) - .await - .map_err(ApiError::from) - } - - async fn touch_async_job_poll_if_ready( - &self, - workspace_id: &WorkspaceId, - job: AsyncJobHandle, - ) -> Result { - let poll_interval_ms = self - .streaming_poll_interval_ms(workspace_id, &job.operation_id) - .await?; - let now = OffsetDateTime::now_utc(); - let remaining_delay_ms = job.remaining_poll_delay_ms(now, poll_interval_ms); - - if remaining_delay_ms > 0 { - return Err(ApiError::rate_limited_with_context( - "async job poll rate limit exceeded", - json!({ - "job_id": job.id.as_str(), - "poll_after_ms": remaining_delay_ms, - }), - )); - } - - self.registry - .touch_async_job_poll(&job.id, &now) - .await - .map_err(ApiError::from) - } - - async fn streaming_poll_interval_ms( - &self, - workspace_id: &WorkspaceId, - operation_id: &OperationId, - ) -> Result { - let summary = self - .registry - .get_operation_summary(workspace_id, operation_id) - .await? - .ok_or_else(|| { - ApiError::not_found_with_context( - format!("operation {} was not found", operation_id.as_str()), - json!({ "operation_id": operation_id.as_str() }), - ) - })?; - let version = self - .registry - .get_operation_version(workspace_id, operation_id, summary.current_draft_version) - .await? - .ok_or_else(|| { - ApiError::not_found_with_context( - format!( - "operation version {} for {} was not found", - summary.current_draft_version, - operation_id.as_str() - ), - json!({ - "operation_id": operation_id.as_str(), - "version": summary.current_draft_version, - }), - ) - })?; - - Ok(version - .snapshot - .execution_config - .streaming - .as_ref() - .and_then(|streaming| streaming.poll_interval_ms) - .unwrap_or(1_000)) - } - pub async fn list_operations( &self, workspace_id: &WorkspaceId, @@ -3557,6 +3168,7 @@ impl AdminService { fn validate_operation_payload(&self, payload: &OperationPayload) -> Result<(), ApiError> { self.validate_operation_capabilities(payload.protocol, payload.security_level)?; validate_protocol_target(payload.protocol, &payload.target)?; + validate_streaming_policy(&payload.execution_config)?; validate_response_cache_policy(&payload.target, &payload.execution_config)?; payload.input_mapping.validate_paths()?; payload.output_mapping.validate_paths()?; @@ -3566,6 +3178,7 @@ impl AdminService { fn validate_registry_operation(&self, operation: &RegistryOperation) -> Result<(), ApiError> { self.validate_operation_capabilities(operation.protocol, operation.security_level)?; validate_protocol_target(operation.protocol, &operation.target)?; + validate_streaming_policy(&operation.execution_config)?; validate_response_cache_policy(&operation.target, &operation.execution_config)?; operation.input_mapping.validate_paths()?; operation.output_mapping.validate_paths()?; @@ -4498,91 +4111,6 @@ fn protocol_capability_view(protocol: Protocol, edition: ProductEdition) -> Prot } } -fn stream_session_summary_view(session: StreamSession) -> StreamSessionSummaryView { - StreamSessionSummaryView { - id: session.id.as_str().to_owned(), - operation_id: session.operation_id.as_str().to_owned(), - agent_id: session.agent_id.map(|value| value.as_str().to_owned()), - protocol: session.protocol, - mode: session.mode, - status: session.status, - expires_at: session.expires_at, - last_poll_at: session.last_poll_at, - created_at: session.created_at, - closed_at: session.closed_at, - } -} - -fn stream_session_detail_view(session: StreamSession) -> StreamSessionDetailView { - StreamSessionDetailView { - cursor: session.cursor.clone(), - summary: stream_session_summary_view(session), - } -} - -fn async_job_summary_view(job: AsyncJobHandle) -> AsyncJobSummaryView { - AsyncJobSummaryView { - id: job.id.as_str().to_owned(), - operation_id: job.operation_id.as_str().to_owned(), - agent_id: job.agent_id.map(|value| value.as_str().to_owned()), - status: job.status, - progress: job.progress, - created_at: job.created_at, - updated_at: job.updated_at, - finished_at: job.finished_at, - expires_at: job.expires_at, - } -} - -fn async_job_detail_view(job: AsyncJobHandle) -> AsyncJobDetailView { - AsyncJobDetailView { - error: job.error.clone(), - summary: async_job_summary_view(job), - } -} - -fn ensure_stream_session_workspace( - session: &StreamSession, - workspace_id: &WorkspaceId, -) -> Result<(), ApiError> { - if &session.workspace_id == workspace_id { - return Ok(()); - } - - Err(ApiError::not_found_with_context( - format!( - "stream session {} was not found in workspace {}", - session.id.as_str(), - workspace_id.as_str() - ), - json!({ - "session_id": session.id.as_str(), - "workspace_id": workspace_id.as_str(), - }), - )) -} - -fn ensure_async_job_workspace( - job: &AsyncJobHandle, - workspace_id: &WorkspaceId, -) -> Result<(), ApiError> { - if &job.workspace_id == workspace_id { - return Ok(()); - } - - Err(ApiError::not_found_with_context( - format!( - "async job {} was not found in workspace {}", - job.id.as_str(), - workspace_id.as_str() - ), - json!({ - "job_id": job.id.as_str(), - "workspace_id": workspace_id.as_str(), - }), - )) -} - fn usage_window(period: UsagePeriod) -> Result<(UsagePeriod, String, UsageBucket), ApiError> { let now = OffsetDateTime::now_utc(); let (start, bucket) = match period { @@ -4710,6 +4238,22 @@ fn agent_mcp_endpoint(workspace_slug: &str, agent_slug: &str) -> String { format!("/mcp/v1/{workspace_slug}/{agent_slug}") } +fn validate_streaming_policy( + execution_config: &crank_core::ExecutionConfig, +) -> Result<(), ApiError> { + if execution_config.streaming.is_some() { + return Err(ApiError::validation_with_context( + "streaming execution is not supported in Community".to_owned(), + json!({ + "field": "execution_config.streaming", + "edition": "community", + }), + )); + } + + Ok(()) +} + fn validate_response_cache_policy( target: &Target, execution_config: &crank_core::ExecutionConfig, diff --git a/apps/mcp-server/Cargo.toml b/apps/mcp-server/Cargo.toml index 2e8cef1..dc92744 100644 --- a/apps/mcp-server/Cargo.toml +++ b/apps/mcp-server/Cargo.toml @@ -5,6 +5,11 @@ license.workspace = true rust-version.workspace = true version.workspace = true +[[bin]] +name = "mcp-server" +path = "src/main.rs" +test = false + [dependencies] async-trait = "0.1" axum.workspace = true diff --git a/apps/ui/html/wizard/step5.html b/apps/ui/html/wizard/step5.html index dcc27d0..4890f45 100644 --- a/apps/ui/html/wizard/step5.html +++ b/apps/ui/html/wizard/step5.html @@ -98,175 +98,6 @@ tls: - - -
-
-
- - - - -
-
-
Streaming execution
-
Bounded stream, session and async job settings for MCP tool families.
-
-
-
-
-
- - -
-
- - -
-
- - -
-
- -
Unary keeps the existing request-response model. Other modes create bounded stream-aware MCP tools.
- -
-
- - -
-
- - -
-
- - -
-
- -
-
- - -
-
- - -
-
- - -
-
- -
-
- - -
-
- - -
-
- - -
-
- -
-
- - -
-
- - -
-
- - -
-
- -
-
- - -
-
- - -
-
- - -
-
- -
- - -
- - -
-
-
Live validation and publishing
@@ -375,31 +206,6 @@ tls:
- -
diff --git a/apps/ui/js/agents.js b/apps/ui/js/agents.js index 2099454..b57ac55 100644 --- a/apps/ui/js/agents.js +++ b/apps/ui/js/agents.js @@ -466,19 +466,11 @@ document.addEventListener('alpine:init', function() { }, protocolBadge(operation) { - if (operation.protocol === 'rest') return 'badge badge-rest'; - if (operation.protocol === 'graphql') return 'badge badge-graphql'; - if (operation.protocol === 'websocket') return 'badge badge-rest'; - if (operation.protocol === 'soap') return 'badge badge-rest'; - return 'badge badge-grpc'; + return 'badge badge-rest'; }, protocolLabel(operation) { - if (operation.protocol === 'rest') return 'REST'; - if (operation.protocol === 'graphql') return 'GQL'; - if (operation.protocol === 'websocket') return 'WS'; - if (operation.protocol === 'soap') return 'SOAP'; - return 'gRPC'; + return 'REST'; }, formatDate(dateStr) { diff --git a/apps/ui/js/api.js b/apps/ui/js/api.js index 106f3cb..b76bc0c 100644 --- a/apps/ui/js/api.js +++ b/apps/ui/js/api.js @@ -246,46 +246,6 @@ uploadOutputSample: function(workspaceId, operationId, sample) { return post('/workspaces/' + encodeURIComponent(workspaceId) + '/operations/' + encodeURIComponent(operationId) + '/samples/output-json', sample); }, - uploadProtoFile: function(workspaceId, operationId, content, fileName) { - return postBytes( - '/workspaces/' + encodeURIComponent(workspaceId) + '/operations/' + encodeURIComponent(operationId) + '/descriptors/proto', - content, - fileName - ); - }, - uploadDescriptorSet: function(workspaceId, operationId, content, fileName) { - return postBytes( - '/workspaces/' + encodeURIComponent(workspaceId) + '/operations/' + encodeURIComponent(operationId) + '/descriptors/descriptor-set', - content, - fileName - ); - }, - uploadWsdlFile: function(workspaceId, operationId, content, fileName) { - return postBytes( - '/workspaces/' + encodeURIComponent(workspaceId) + '/operations/' + encodeURIComponent(operationId) + '/descriptors/wsdl', - content, - fileName - ); - }, - uploadXsdFile: function(workspaceId, operationId, content, fileName) { - return postBytes( - '/workspaces/' + encodeURIComponent(workspaceId) + '/operations/' + encodeURIComponent(operationId) + '/descriptors/xsd', - content, - fileName - ); - }, - listGrpcServices: function(workspaceId, operationId, version) { - return get( - '/workspaces/' + encodeURIComponent(workspaceId) + '/operations/' + encodeURIComponent(operationId) + '/grpc/services' - + query({ version: version }) - ); - }, - listSoapServices: function(workspaceId, operationId, version) { - return get( - '/workspaces/' + encodeURIComponent(workspaceId) + '/operations/' + encodeURIComponent(operationId) + '/soap/services' - + query({ version: version }) - ); - }, generateDraft: function(workspaceId, operationId, payload) { return post('/workspaces/' + encodeURIComponent(workspaceId) + '/operations/' + encodeURIComponent(operationId) + '/drafts/generate', payload || {}); }, diff --git a/apps/ui/js/catalog.js b/apps/ui/js/catalog.js index f389dd9..279494d 100644 --- a/apps/ui/js/catalog.js +++ b/apps/ui/js/catalog.js @@ -475,13 +475,7 @@ document.addEventListener('alpine:init', function() { }, protocolLabel(operation) { - if (operation.protocol === 'rest') { - return operation.method ? ('REST · ' + operation.method) : 'REST'; - } - if (operation.protocol === 'graphql') return 'GraphQL'; - if (operation.protocol === 'websocket') return 'WebSocket'; - if (operation.protocol === 'soap') return 'SOAP'; - return 'gRPC'; + return operation.method ? ('REST · ' + operation.method) : 'REST'; }, protocolClass(operation) { diff --git a/apps/ui/js/usage.js b/apps/ui/js/usage.js index a6fa3c5..fc91401 100644 --- a/apps/ui/js/usage.js +++ b/apps/ui/js/usage.js @@ -66,34 +66,10 @@ document.addEventListener('DOMContentLoaded', function () { } function protocolColor(protocol) { - if (protocol === 'graphql' || protocol === 'Graphql') { - return 'var(--purple)'; - } - if (protocol === 'grpc' || protocol === 'Grpc') { - return 'var(--accent)'; - } - if (protocol === 'websocket' || protocol === 'Websocket') { - return 'var(--teal)'; - } - if (protocol === 'soap' || protocol === 'Soap') { - return 'var(--blue)'; - } return 'var(--blue)'; } function protocolLabel(protocol) { - if (protocol === 'graphql' || protocol === 'Graphql') { - return 'GraphQL'; - } - if (protocol === 'grpc' || protocol === 'Grpc') { - return 'gRPC'; - } - if (protocol === 'websocket' || protocol === 'Websocket') { - return 'WebSocket'; - } - if (protocol === 'soap' || protocol === 'Soap') { - return 'SOAP'; - } return 'REST'; } diff --git a/apps/ui/js/wizard-live.js b/apps/ui/js/wizard-live.js index cc2e34f..3d1a01a 100644 --- a/apps/ui/js/wizard-live.js +++ b/apps/ui/js/wizard-live.js @@ -1,6 +1,3 @@ -var updateStreamingModeOptions = window.CrankStreamingForm.updateStreamingModeOptions; -var updateStreamingConfigVisibility = window.CrankStreamingForm.updateStreamingConfigVisibility; - function buildToolDescription() { return { title: textValue('tool-title') || textValue('tool-display-name') || textValue('tool-name'), @@ -68,18 +65,7 @@ function setEditModePresentation() { function selectProtocol(protocol) { wizardProtocol = protocol || 'rest'; document.querySelectorAll('.protocol-card').forEach(function(card) { - var proto = card.dataset.protocol - || (card.classList.contains('rest') - ? 'rest' - : card.classList.contains('graphql') - ? 'graphql' - : card.classList.contains('grpc') - ? 'grpc' - : card.classList.contains('websocket') - ? 'websocket' - : card.classList.contains('soap') - ? 'soap' - : 'rest'); + var proto = card.dataset.protocol || 'rest'; var selected = proto === wizardProtocol; card.classList.toggle('selected', selected); card.setAttribute('aria-checked', selected ? 'true' : 'false'); @@ -101,32 +87,11 @@ function bindWizardLiveActions() { bindLiveAction('wizard-export-yaml', tKey('wizard.busy.export_yaml'), exportWizardYaml); bindLiveAction('wizard-import-yaml', tKey('wizard.busy.import_yaml'), importWizardYaml); bindLiveAction('wizard-publish-operation', tKey('wizard.busy.publish'), publishWizardOperation); - bindClick('wizard-select-descriptor-set', function() { - var input = document.getElementById('wizard-descriptor-set-input'); - if (input) input.click(); - }); - bindLiveAction('wizard-upload-descriptor-set', tKey('wizard.busy.descriptor'), uploadDescriptorSetAndDiscover); - bindClick('wizard-select-soap-wsdl', function() { - var input = document.getElementById('wizard-soap-wsdl-input'); - if (input) input.click(); - }); - bindClick('wizard-select-soap-xsd', function() { - var input = document.getElementById('wizard-soap-xsd-input'); - if (input) input.click(); - }); - bindLiveAction('wizard-upload-soap-contracts', tKey('wizard.busy.wsdl'), uploadSoapArtifactsAndInspect); bindClick('wizard-import-yaml-file-trigger', function() { var input = document.getElementById('wizard-import-yaml-file'); if (input) input.click(); }); - var descriptorInput = document.getElementById('wizard-descriptor-set-input'); - if (descriptorInput) descriptorInput.addEventListener('change', handleDescriptorSetSelection); - var soapWsdlInput = document.getElementById('wizard-soap-wsdl-input'); - if (soapWsdlInput) soapWsdlInput.addEventListener('change', handleSoapWsdlSelection); - var soapXsdInput = document.getElementById('wizard-soap-xsd-input'); - if (soapXsdInput) soapXsdInput.addEventListener('change', handleSoapXsdSelection); - var yamlInput = document.getElementById('wizard-import-yaml-file'); if (yamlInput) yamlInput.addEventListener('change', handleImportYamlFileSelection); } @@ -183,10 +148,6 @@ async function runWizardLiveAction(button, busyLabel, handler) { } function updateWizardProtocolVisibility() { - var grpcTools = document.getElementById('wizard-grpc-live-tools'); - if (grpcTools) grpcTools.hidden = wizardProtocol !== 'grpc'; - updateStreamingModeOptions(); - updateStreamingConfigVisibility(); if (typeof window.renderEditionCapabilityHints === 'function' && window.CrankWizardState && typeof window.CrankWizardState.currentEditionCapabilities === 'function') { @@ -253,82 +214,6 @@ async function refreshCurrentOperationState() { }; } -async function uploadPendingGrpcArtifacts(payload) { - if (wizardProtocol !== 'grpc' || !wizardEditId) return; - - var descriptorResponse = null; - - if (wizardProtoUpload) { - descriptorResponse = await window.CrankApi.uploadProtoFile( - wizardWorkspaceId, - wizardEditId, - new TextEncoder().encode(wizardProtoUpload.content), - wizardProtoUpload.fileName - ); - wizardProtoUpload = null; - } - - if (wizardDescriptorSetUpload) { - descriptorResponse = await window.CrankApi.uploadDescriptorSet( - wizardWorkspaceId, - wizardEditId, - wizardDescriptorSetUpload.bytes, - wizardDescriptorSetUpload.fileName - ); - wizardDescriptorSetUpload = null; - var descriptorName = document.getElementById('wizard-descriptor-set-name'); - if (descriptorName) descriptorName.textContent = tKey('wizard.descriptor.uploaded'); - } - - if (!descriptorResponse) return; - - payload.target.descriptor_ref = descriptorResponse.descriptor_id; - payload.target.descriptor_set_b64 = ''; - await window.CrankApi.updateOperation( - wizardWorkspaceId, - wizardEditId, - updateOperationPayload(payload) - ); -} - -async function uploadPendingSoapArtifacts(payload) { - if (wizardProtocol !== 'soap' || !wizardEditId) return; - - var wsdlResponse = null; - if (wizardSoapWsdlUpload) { - wsdlResponse = await window.CrankApi.uploadWsdlFile( - wizardWorkspaceId, - wizardEditId, - wizardSoapWsdlUpload.bytes, - wizardSoapWsdlUpload.fileName - ); - wizardSoapWsdlUpload = null; - var wsdlName = document.getElementById('wizard-soap-wsdl-name'); - if (wsdlName) wsdlName.textContent = tKey('wizard.step3.soap.wsdl_uploaded'); - } - - if (wizardSoapXsdUpload) { - await window.CrankApi.uploadXsdFile( - wizardWorkspaceId, - wizardEditId, - wizardSoapXsdUpload.bytes, - wizardSoapXsdUpload.fileName - ); - wizardSoapXsdUpload = null; - var xsdName = document.getElementById('wizard-soap-xsd-name'); - if (xsdName) xsdName.textContent = tKey('wizard.step3.soap.xsd_uploaded'); - } - - if (!wsdlResponse) return; - - payload.target.wsdl_ref = wsdlResponse.descriptor_id; - await window.CrankApi.updateOperation( - wizardWorkspaceId, - wizardEditId, - updateOperationPayload(payload) - ); -} - async function persistCurrentDraft(stayOnPage) { if (!wizardWorkspaceId) { throw new Error(tKey('wizard.error.no_workspace')); @@ -360,8 +245,6 @@ async function persistCurrentDraft(stayOnPage) { if (toolNameInput) toolNameInput.disabled = true; } - await uploadPendingGrpcArtifacts(payload); - await uploadPendingSoapArtifacts(payload); await refreshCurrentOperationState(); if (stayOnPage) { @@ -395,109 +278,6 @@ function setTextareaValue(id, value) { } function describeWizardTestResult(result) { - if (wizardProtocol === 'websocket') { - if (!result.ok && result.errors && result.errors.length) { - var websocketError = result.errors[0] || {}; - var websocketMessage = websocketError.message || ''; - var websocketBody = tKey('wizard.test.websocket_failed_body'); - if (/reconnect policy exhausted/i.test(websocketMessage)) { - websocketBody = tKey('wizard.test.websocket_failed_reconnect_body'); - } else if (/close frame before collection completed|closed before collection completed/i.test(websocketMessage)) { - websocketBody = tKey('wizard.test.websocket_failed_closed_body'); - } - return { - title: tKey('wizard.test.websocket_failed'), - body: websocketBody, - isError: true, - }; - } - - if (result.stream_session && result.stream_session.session_id) { - return { - title: tKey('wizard.test.websocket_session_started'), - body: tfKey('wizard.test.websocket_session_started_body', { - session_id: result.stream_session.session_id, - poll_after_ms: result.stream_session.poll_after_ms, - }), - isError: false, - }; - } - - if (result.async_job && result.async_job.job_id) { - return { - title: tKey('wizard.test.websocket_async_job_started'), - body: tfKey('wizard.test.websocket_async_job_started_body', { - job_id: result.async_job.job_id, - }), - isError: false, - }; - } - - if (result.window) { - var itemCount = Array.isArray(result.response_preview && result.response_preview.items) - ? result.response_preview.items.length - : 0; - var websocketBodyParts = [ - tfKey('wizard.test.websocket_window_completed_body', { items: itemCount }) - ]; - if (result.window.truncated) { - websocketBodyParts.push(tKey('wizard.test.websocket_window_truncated_note')); - } - if (result.window.has_more) { - websocketBodyParts.push(tKey('wizard.test.websocket_window_more_note')); - } - if (!result.window.window_complete) { - websocketBodyParts.push(tKey('wizard.test.websocket_window_incomplete_note')); - } - return { - title: result.ok ? tKey('wizard.test.websocket_window_completed') : tKey('wizard.test.websocket_failed'), - body: websocketBodyParts.join(' '), - isError: !result.ok, - }; - } - } - - if (result.stream_session && result.stream_session.session_id) { - return { - title: tKey('wizard.test.session_started'), - body: tfKey('wizard.test.session_started_body', { - session_id: result.stream_session.session_id, - poll_after_ms: result.stream_session.poll_after_ms - }), - isError: false, - }; - } - - if (result.async_job && result.async_job.job_id) { - return { - title: tKey('wizard.test.async_job_started'), - body: tfKey('wizard.test.async_job_started_body', { - job_id: result.async_job.job_id - }), - isError: false, - }; - } - - if (result.window) { - var bodyParts = [ - tKey('wizard.test.window_completed_body') - ]; - if (result.window.truncated) { - bodyParts.push(tKey('wizard.test.window_truncated_note')); - } - if (result.window.has_more) { - bodyParts.push(tKey('wizard.test.window_more_note')); - } - if (!result.window.window_complete) { - bodyParts.push(tKey('wizard.test.window_incomplete_note')); - } - return { - title: result.ok ? tKey('wizard.test.window_completed') : tKey('wizard.test.failed'), - body: bodyParts.join(' '), - isError: !result.ok, - }; - } - return { title: result.ok ? tKey('wizard.test.completed') : tKey('wizard.test.failed'), body: result.ok ? tKey('wizard.test.completed_body') : tKey('wizard.test.failed_body'), diff --git a/apps/ui/js/wizard-model.js b/apps/ui/js/wizard-model.js index 1d451c5..fc92eae 100644 --- a/apps/ui/js/wizard-model.js +++ b/apps/ui/js/wizard-model.js @@ -45,10 +45,6 @@ function convertJsonSchemaToCrankSchema(node, requiredNames) { } function mappingRootForProtocol(protocol) { - if (protocol === 'graphql') return '$.request.variables'; - if (protocol === 'grpc') return '$.request.message'; - if (protocol === 'soap') return '$.request.body'; - if (protocol === 'websocket') return '$.request.body'; return '$.request.body'; } @@ -107,46 +103,9 @@ function parseExecutionConfig(text) { auth_profile_ref: authProfileRef, headers: headers, protocol_options: null, + streaming: null, }; - if (wizardProtocol === 'grpc') { - var useTls = false; - if (value.protocol_options && value.protocol_options.grpc) { - useTls = !!value.protocol_options.grpc.use_tls; - } else if (value.tls) { - useTls = !!value.tls.verify; - } - config.protocol_options = { grpc: { use_tls: useTls } }; - } else if (wizardProtocol === 'websocket') { - var websocketProtocolOptions = value.protocol_options && value.protocol_options.websocket - ? value.protocol_options.websocket - : {}; - var heartbeatInterval = websocketProtocolOptions.heartbeat_interval_ms != null - ? Number(websocketProtocolOptions.heartbeat_interval_ms) - : numericValueOrNull('websocket-heartbeat-interval-ms'); - var reconnectAttempts = websocketProtocolOptions.reconnect_max_attempts != null - ? Number(websocketProtocolOptions.reconnect_max_attempts) - : numericValueOrNull('websocket-reconnect-max-attempts'); - var reconnectBackoff = websocketProtocolOptions.reconnect_backoff_ms != null - ? Number(websocketProtocolOptions.reconnect_backoff_ms) - : numericValueOrNull('websocket-reconnect-backoff-ms'); - var runtimeOptions = {}; - if (Number.isFinite(heartbeatInterval) && heartbeatInterval > 0) { - runtimeOptions.heartbeat_interval_ms = heartbeatInterval; - } - if (Number.isFinite(reconnectAttempts) && reconnectAttempts >= 0) { - runtimeOptions.reconnect_max_attempts = reconnectAttempts; - } - if (Number.isFinite(reconnectBackoff) && reconnectBackoff >= 0) { - runtimeOptions.reconnect_backoff_ms = reconnectBackoff; - } - if (Object.keys(runtimeOptions).length) { - config.protocol_options = { websocket: runtimeOptions }; - } - } - - config.streaming = collectStreamingConfig(); - return config; } @@ -156,9 +115,6 @@ function currentUpstream() { var customName = textValue('new-upstream-name'); var customUrl = textValue('new-upstream-url'); - if (!customUrl && wizardProtocol === 'soap') { - customUrl = textValue('soap-endpoint-override'); - } if (!customUrl) return null; var authMode = textValue('new-upstream-auth-mode') || 'none'; @@ -182,72 +138,12 @@ function joinUrl(baseUrl, path) { return baseUrl.replace(/\/+$/, '') + '/' + path.replace(/^\/+/, ''); } -function selectedGraphqlOperationType() { - var active = document.querySelector('.gql-type-card.active'); - return active ? active.dataset.gqlType : 'query'; -} - -function graphqlTopLevelField(queryText) { - var match = queryText.replace(/#[^\n]*/g, '').match(/\{\s*([A-Za-z_][A-Za-z0-9_]*)/); - return match ? match[1] : null; -} - -function graphqlOperationName(queryText) { - var match = queryText.match(/\b(query|mutation)\s+([A-Za-z_][A-Za-z0-9_]*)/); - return match ? match[2] : textValue('tool-name'); -} - -function parseGrpcRoute(route) { - var normalized = route.replace(/^\/+/, ''); - var parts = normalized.split('/'); - if (parts.length !== 2) { - return { - package: '', - service: '', - method: '', - }; - } - - var servicePart = parts[0]; - var method = parts[1]; - var serviceSegments = servicePart.split('.'); - var service = serviceSegments.pop() || ''; - var packageName = serviceSegments.join('.'); - - return { - package: packageName, - service: service, - method: method, - }; -} - function parseHeaderMap(text) { if (!text || !text.trim()) return {}; var value = parseStructuredText(text); return value && typeof value === 'object' ? value : {}; } -function numericValueOrNull(id) { - var value = textValue(id); - if (!value) return null; - var parsed = Number(value); - return Number.isFinite(parsed) && parsed > 0 ? parsed : null; -} - -function stringValueOrNull(id) { - var value = textValue(id); - return value ? value : null; -} - -function textareaLines(id) { - var value = textValue(id); - if (!value) return []; - return value - .split(/\r?\n/) - .map(function(line) { return line.trim(); }) - .filter(Boolean); -} - function buildTarget() { var upstream = currentUpstream(); if (!upstream || !upstream.url) { @@ -255,85 +151,13 @@ function buildTarget() { } var pathTemplate = textValue('endpoint-path') || '/'; - - if (wizardProtocol === 'rest') { - 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), - }; - } - - if (wizardProtocol === 'graphql') { - var queryTemplate = textValue('gql-query-editor'); - var topField = graphqlTopLevelField(queryTemplate); - return { - kind: 'graphql', - endpoint: joinUrl(upstream.url, pathTemplate), - operation_type: selectedGraphqlOperationType(), - operation_name: graphqlOperationName(queryTemplate), - query_template: queryTemplate, - response_path: topField ? '$.response.body.data.' + topField : '$.response.body.data', - }; - } - - if (wizardProtocol === 'soap') { - var endpointOverride = textValue('soap-endpoint-override') || upstream.url; - var existingWsdlRef = wizardCurrentVersion && wizardCurrentVersion.target && wizardCurrentVersion.target.kind === 'soap' - ? wizardCurrentVersion.target.wsdl_ref - : 'sample_wsdl_pending'; - - return { - kind: 'soap', - wsdl_ref: existingWsdlRef, - service_name: textValue('soap-service-name') || 'Service', - port_name: textValue('soap-port-name') || 'Port', - operation_name: textValue('soap-operation-name') || 'Operation', - endpoint_override: endpointOverride || null, - soap_version: textValue('soap-version') || 'soap_11', - soap_action: textValue('soap-action') || null, - binding_style: textValue('soap-binding-style') || 'document_literal', - headers: [], - fault_contract: null, - metadata: { input_part_names: [], output_part_names: [], namespaces: [] }, - }; - } - - if (wizardProtocol === 'websocket') { - return { - kind: 'websocket', - url: joinUrl(upstream.url, textValue('websocket-path')), - subprotocols: textareaLines('websocket-subprotocols'), - subscribe_message_template: stringValueOrNull('websocket-subscribe-template') - ? parseStructuredText(textValue('websocket-subscribe-template')) - : null, - unsubscribe_message_template: stringValueOrNull('websocket-unsubscribe-template') - ? parseStructuredText(textValue('websocket-unsubscribe-template')) - : null, - static_headers: parseHeaderMap(upstream.staticHeaders), - }; - } - - var route = textValue('grpc-manual-route') || (document.getElementById('grpc-path-value') ? document.getElementById('grpc-path-value').textContent.trim() : ''); - var descriptorRef = wizardCurrentVersion && wizardCurrentVersion.target && wizardCurrentVersion.target.kind === 'grpc' - ? wizardCurrentVersion.target.descriptor_ref - : 'desc_pending'; - var descriptorSetB64 = wizardCurrentVersion && wizardCurrentVersion.target && wizardCurrentVersion.target.kind === 'grpc' - ? (wizardCurrentVersion.target.descriptor_set_b64 || '') - : ''; - var parsedRoute = parseGrpcRoute(route); - + var activeMethod = document.querySelector('.method-card.active'); return { - kind: 'grpc', - server_addr: upstream.url, - package: parsedRoute.package, - service: parsedRoute.service, - method: parsedRoute.method, - descriptor_ref: descriptorRef, - descriptor_set_b64: descriptorSetB64, + kind: 'rest', + base_url: upstream.url, + method: activeMethod ? activeMethod.dataset.method : 'POST', + path_template: pathTemplate, + static_headers: parseHeaderMap(upstream.staticHeaders), }; } @@ -390,28 +214,6 @@ function executionConfigToEditorValue(config) { if (config.headers && Object.keys(config.headers).length) { value.headers = config.headers; } - if (config.protocol_options && config.protocol_options.grpc) { - value.tls = { verify: !!config.protocol_options.grpc.use_tls }; - } - if (config.protocol_options && config.protocol_options.websocket) { - value.protocol_options = value.protocol_options || {}; - value.protocol_options.websocket = {}; - if (config.protocol_options.websocket.heartbeat_interval_ms != null) { - value.protocol_options.websocket.heartbeat_interval_ms = config.protocol_options.websocket.heartbeat_interval_ms; - } - if (config.protocol_options.websocket.reconnect_max_attempts != null) { - value.protocol_options.websocket.reconnect_max_attempts = config.protocol_options.websocket.reconnect_max_attempts; - } - if (config.protocol_options.websocket.reconnect_backoff_ms != null) { - value.protocol_options.websocket.reconnect_backoff_ms = config.protocol_options.websocket.reconnect_backoff_ms; - } - if (!Object.keys(value.protocol_options.websocket).length) { - delete value.protocol_options.websocket; - } - if (!Object.keys(value.protocol_options).length) { - delete value.protocol_options; - } - } return window.jsyaml ? window.jsyaml.dump(value, { lineWidth: -1 }) : JSON.stringify(value, null, 2); } @@ -456,60 +258,6 @@ function prefillWizardFromEdit(detail, versionDocument) { document.querySelectorAll('.method-card').forEach(function(card) { card.classList.toggle('active', card.dataset.method === target.method); }); - } else if (target.kind === 'graphql') { - var endpoint = target.endpoint || ''; - var parsedEndpoint = new URL(endpoint, window.location.origin); - prefillUpstream(parsedEndpoint.origin, {}, versionDocument.execution_config ? versionDocument.execution_config.auth_profile_ref : null); - setValue('endpoint-path', parsedEndpoint.pathname + parsedEndpoint.search); - setValue('gql-query-editor', target.query_template); - document.querySelectorAll('.gql-type-card').forEach(function(card) { - card.classList.toggle('active', card.dataset.gqlType === target.operation_type); - }); - } else if (target.kind === 'grpc') { - prefillUpstream(target.server_addr, {}, versionDocument.execution_config ? versionDocument.execution_config.auth_profile_ref : null); - var route = '/' + (target.package ? target.package + '.' : '') + target.service + '/' + target.method; - setValue('grpc-manual-route', route); - setValue('grpc-manual-req-type', ''); - setValue('grpc-manual-res-type', ''); - grpcManualRouteInput(route); - grpcManualTypeInput(); - } else if (target.kind === 'soap') { - prefillUpstream( - target.endpoint_override || '', - {}, - versionDocument.execution_config ? versionDocument.execution_config.auth_profile_ref : null - ); - setValue('soap-service-name', target.service_name || ''); - setValue('soap-port-name', target.port_name || ''); - setValue('soap-operation-name', target.operation_name || ''); - setValue('soap-endpoint-override', target.endpoint_override || ''); - setValue('soap-action', target.soap_action || ''); - setValue('soap-version', target.soap_version || 'soap_11'); - setValue('soap-binding-style', target.binding_style || 'document_literal'); - } else if (target.kind === 'websocket') { - prefillUpstream( - target.url, - target.static_headers || {}, - versionDocument.execution_config ? versionDocument.execution_config.auth_profile_ref : null - ); - setValue('websocket-path', ''); - setValue('websocket-subprotocols', (target.subprotocols || []).join('\n')); - setValue( - 'websocket-subscribe-template', - target.subscribe_message_template ? JSON.stringify(target.subscribe_message_template, null, 2) : '' - ); - setValue( - 'websocket-unsubscribe-template', - target.unsubscribe_message_template ? JSON.stringify(target.unsubscribe_message_template, null, 2) : '' - ); - var websocketOptions = versionDocument.execution_config - && versionDocument.execution_config.protocol_options - && versionDocument.execution_config.protocol_options.websocket - ? versionDocument.execution_config.protocol_options.websocket - : null; - setValue('websocket-heartbeat-interval-ms', websocketOptions && websocketOptions.heartbeat_interval_ms ? websocketOptions.heartbeat_interval_ms : ''); - setValue('websocket-reconnect-max-attempts', websocketOptions && websocketOptions.reconnect_max_attempts != null ? websocketOptions.reconnect_max_attempts : ''); - setValue('websocket-reconnect-backoff-ms', websocketOptions && websocketOptions.reconnect_backoff_ms ? websocketOptions.reconnect_backoff_ms : ''); } setValue('tool-name', detail.name); @@ -521,7 +269,6 @@ function prefillWizardFromEdit(detail, versionDocument) { setValue('tool-input-mapping', mappingSetToEditorValue(versionDocument.input_mapping, 'input', detail.protocol)); setValue('tool-output-mapping', mappingSetToEditorValue(versionDocument.output_mapping, 'output', detail.protocol)); setValue('tool-exec-config', executionConfigToEditorValue(versionDocument.execution_config)); - applyStreamingConfig(versionDocument.execution_config ? versionDocument.execution_config.streaming : null); var toolNameInput = document.getElementById('tool-name'); if (toolNameInput) toolNameInput.disabled = true; diff --git a/apps/ui/js/wizard-upstreams.js b/apps/ui/js/wizard-upstreams.js index e2063c6..07aa55c 100644 --- a/apps/ui/js/wizard-upstreams.js +++ b/apps/ui/js/wizard-upstreams.js @@ -1,9 +1,7 @@ /* ── Upstream selector (Step 2) ── */ var upstreams = [ - { id: 'open-meteo', name: 'Open Meteo', url: 'https://api.open-meteo.com', staticHeaders: '{}', authProfileId: null, authProfileName: '', authKind: null }, - { id: 'countries-graphql', name: 'Countries GraphQL', url: 'https://countries.trevorblades.com', staticHeaders: '{}', authProfileId: null, authProfileName: '', authKind: null }, - { id: 'grpcb', name: 'grpcb.in', url: 'https://grpcb.in:443', staticHeaders: '{}', authProfileId: null, authProfileName: '', authKind: null } + { id: 'open-meteo', name: 'Open Meteo', url: 'https://api.open-meteo.com', staticHeaders: '{}', authProfileId: null, authProfileName: '', authKind: null } ]; var dropdownOpen = false; @@ -290,10 +288,6 @@ function pickUpstream(id) { var trigger = document.getElementById('upstream-new-trigger'); if (trigger) trigger.classList.remove('active'); - var reflectName = document.getElementById('grpc-reflect-upstream-name'); - var reflectUrl = document.getElementById('grpc-reflect-upstream-url'); - if (reflectName) reflectName.textContent = u.name; - if (reflectUrl) reflectUrl.textContent = u.url; } function startNewUpstream() { diff --git a/apps/ui/js/wizard.js b/apps/ui/js/wizard.js index 3fc748c..263d094 100644 --- a/apps/ui/js/wizard.js +++ b/apps/ui/js/wizard.js @@ -15,9 +15,6 @@ 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; -var applyStreamingConfig = window.CrankStreamingForm.applyStreamingConfig; var saveOperation = window.CrankWizardLive.saveOperation; var loadOperationForEdit = window.CrankWizardLive.loadOperationForEdit; var bindWizardLiveActions = window.CrankWizardLive.bindWizardLiveActions; @@ -34,8 +31,6 @@ var wizardDescriptorSetUpload = window.wizardDescriptorSetUpload; var wizardSoapWsdlUpload = window.wizardSoapWsdlUpload; var wizardSoapXsdUpload = window.wizardSoapXsdUpload; var wizardTestResponsePreview = window.wizardTestResponsePreview; -var grpcDescriptorServices = window.grpcDescriptorServices; -var soapServiceCatalog = window.soapServiceCatalog; var wizardProtocolCapabilities = window.wizardProtocolCapabilities; var wizardSecrets = window.wizardSecrets; var wizardAuthProfiles = window.wizardAuthProfiles; @@ -95,7 +90,6 @@ async function initWizardPage() { await loadWizardAuthResources(); bindProtocolCards(); bindWizardLiveActions(); - bindStreamingConfigControls(); updateUpstreamAuthUi(); renderEditionCapabilityHints(editionCapabilities); @@ -149,9 +143,6 @@ async function initWizardPage() { function renderEditionCapabilityHints(capabilities) { var securityNote = document.getElementById('wizard-security-level-note'); var securityText = securityNote ? securityNote.querySelector('.info-callout-text') : null; - var streamingNote = document.getElementById('wizard-streaming-capability-note'); - var streamingText = streamingNote ? streamingNote.querySelector('.info-callout-text') : null; - var streamingCard = document.getElementById('wizard-streaming-config-card'); if (!securityText) return; var levels = capabilities && Array.isArray(capabilities.supported_security_levels) ? capabilities.supported_security_levels @@ -160,25 +151,6 @@ function renderEditionCapabilityHints(capabilities) { if (!securityNote.hidden) { securityText.textContent = tKey('wizard.step5.community_security_note'); } - - var protocolCapabilities = currentProtocolCapabilities(); - var modes = protocolCapabilities && Array.isArray(protocolCapabilities.supports_execution_modes) - ? protocolCapabilities.supports_execution_modes - : ['unary']; - var hasStreamingModes = modes.some(function(mode) { return mode !== 'unary'; }); - if (streamingCard) { - streamingCard.hidden = !hasStreamingModes; - } - if (streamingNote && streamingText) { - var edition = capabilities && capabilities.edition ? capabilities.edition : 'community'; - var shouldExplainCommunityLimit = edition === 'community' - && !hasStreamingModes - && ['rest', 'grpc'].indexOf(wizardProtocol) >= 0; - streamingNote.hidden = !shouldExplainCommunityLimit; - if (shouldExplainCommunityLimit) { - streamingText.textContent = tKey('wizard.step5.community_streaming_note'); - } - } } window.renderEditionCapabilityHints = renderEditionCapabilityHints; @@ -285,12 +257,6 @@ document.addEventListener('click', function() { }); -/* ══════════════════════════════════════════════ - gRPC — source selector -══════════════════════════════════════════════ */ - -var grpcSource = 'proto'; // 'proto' | 'reflection' | 'manual' - function textValue(id) { var element = document.getElementById(id); return element ? element.value.trim() : ''; diff --git a/apps/ui/scripts/build.js b/apps/ui/scripts/build.js index 2c6471a..7ca2cc9 100644 --- a/apps/ui/scripts/build.js +++ b/apps/ui/scripts/build.js @@ -88,10 +88,6 @@ const BUNDLES = { 'node_modules/js-yaml/dist/js-yaml.min.js', 'js/wizard-state.js', 'js/wizard-shell.js', - 'js/streaming-form.js', - 'js/stream-test-run.js', - 'js/wizard-grpc.js', - 'js/wizard-artifacts.js', 'js/wizard-upstreams.js', 'js/wizard-model.js', 'js/wizard-live.js', diff --git a/crates/crank-registry/src/postgres/mod.rs b/crates/crank-registry/src/postgres/mod.rs index 38ad00e..019d47b 100644 --- a/crates/crank-registry/src/postgres/mod.rs +++ b/crates/crank-registry/src/postgres/mod.rs @@ -2434,6 +2434,7 @@ mod tests { auth_profile_ref: Some("auth_crank".into()), headers: BTreeMap::from([("X-Request-Id".to_owned(), "static".to_owned())]), protocol_options: None, + response_cache: None, streaming: None, }, tool_description: ToolDescription { diff --git a/crates/crank-runtime/Cargo.toml b/crates/crank-runtime/Cargo.toml index c1cb90a..16a0883 100644 --- a/crates/crank-runtime/Cargo.toml +++ b/crates/crank-runtime/Cargo.toml @@ -5,6 +5,10 @@ license.workspace = true rust-version.workspace = true version.workspace = true +[lib] +path = "src/lib.rs" +test = false + [features] default = [] protocol-graphql = []