From 2babc0935b8430456d162817cd669c8b4d8cd544 Mon Sep 17 00:00:00 2001 From: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com> Date: Sat, 29 Aug 2026 14:06:34 +0800 Subject: [PATCH] fix(cli): add namespace sync manifest endpoint Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com> --- .../cli/CliNamespaceController.java | 69 +++++++++++++++++++ .../dto/cli/CliNamespaceSyncItemResponse.java | 17 +++++ .../dto/cli/CliNamespaceSyncResponse.java | 11 +++ .../service/cli/CliSkillAppService.java | 42 ++++++++++- .../cli/CliSkillControllerTest.java | 32 +++++++++ .../service/cli/CliSkillAppServiceTest.java | 26 +++++++ .../policy/RouteSecurityPolicyRegistry.java | 2 + .../RouteSecurityPolicyRegistryTest.java | 11 +++ .../skill/service/SkillQueryService.java | 42 +++++++++++ .../skill/service/SkillQueryServiceTest.java | 40 +++++++++++ web/src/api/generated/schema.d.ts | 68 ++++++++++++++++++ 11 files changed, 359 insertions(+), 1 deletion(-) create mode 100644 server/skillhub-app/src/main/java/com/iflytek/skillhub/controller/cli/CliNamespaceController.java create mode 100644 server/skillhub-app/src/main/java/com/iflytek/skillhub/dto/cli/CliNamespaceSyncItemResponse.java create mode 100644 server/skillhub-app/src/main/java/com/iflytek/skillhub/dto/cli/CliNamespaceSyncResponse.java diff --git a/server/skillhub-app/src/main/java/com/iflytek/skillhub/controller/cli/CliNamespaceController.java b/server/skillhub-app/src/main/java/com/iflytek/skillhub/controller/cli/CliNamespaceController.java new file mode 100644 index 00000000..9fb9f140 --- /dev/null +++ b/server/skillhub-app/src/main/java/com/iflytek/skillhub/controller/cli/CliNamespaceController.java @@ -0,0 +1,69 @@ +package com.iflytek.skillhub.controller.cli; + +import com.iflytek.skillhub.controller.BaseApiController; +import com.iflytek.skillhub.domain.namespace.NamespaceRole; +import com.iflytek.skillhub.dto.ApiResponse; +import com.iflytek.skillhub.dto.ApiResponseFactory; +import com.iflytek.skillhub.dto.cli.CliNamespaceSyncResponse; +import com.iflytek.skillhub.ratelimit.RateLimit; +import com.iflytek.skillhub.service.cli.CliSkillAppService; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Map; + +/** + * CLI namespace-scoped read endpoints. + */ +@RestController +@RequestMapping("/api/cli/v1/namespaces") +public class CliNamespaceController extends BaseApiController { + + private static final int DEFAULT_LIMIT = 100; + private static final int MAX_LIMIT = 100; + + private final CliSkillAppService cliSkillAppService; + + public CliNamespaceController(CliSkillAppService cliSkillAppService, ApiResponseFactory responseFactory) { + super(responseFactory); + this.cliSkillAppService = cliSkillAppService; + } + + @GetMapping("/{namespace}/skills") + @RateLimit(category = "skills", authenticated = 60, anonymous = 0) + public ApiResponse listSkills( + @PathVariable String namespace, + @RequestParam(required = false) String cursor, + @RequestParam(defaultValue = "100") int limit, + @RequestAttribute(value = "userId", required = false) String userId, + @RequestAttribute(value = "userNsRoles", required = false) Map userNsRoles) { + int page = parseCursor(cursor); + int normalizedLimit = Math.min(Math.max(limit, 1), MAX_LIMIT); + return ok("response.success.read", cliSkillAppService.listNamespaceSkills( + namespace, + page, + normalizedLimit, + userId, + userNsRoles + )); + } + + private int parseCursor(String cursor) { + if (cursor == null || cursor.isBlank()) { + return 0; + } + try { + int page = Integer.parseInt(cursor); + if (page < 0) { + throw new NumberFormatException("negative cursor"); + } + return page; + } catch (NumberFormatException ex) { + throw new IllegalArgumentException("cursor must be a non-negative page number", ex); + } + } +} diff --git a/server/skillhub-app/src/main/java/com/iflytek/skillhub/dto/cli/CliNamespaceSyncItemResponse.java b/server/skillhub-app/src/main/java/com/iflytek/skillhub/dto/cli/CliNamespaceSyncItemResponse.java new file mode 100644 index 00000000..9f743a7f --- /dev/null +++ b/server/skillhub-app/src/main/java/com/iflytek/skillhub/dto/cli/CliNamespaceSyncItemResponse.java @@ -0,0 +1,17 @@ +package com.iflytek.skillhub.dto.cli; + +import java.time.Instant; + +/** + * Installable skill metadata used by the CLI namespace workspace synchronizer. + */ +public record CliNamespaceSyncItemResponse( + String namespace, + String slug, + String version, + Long versionId, + String fingerprint, + Instant updatedAt, + String visibility, + String downloadUrl +) {} diff --git a/server/skillhub-app/src/main/java/com/iflytek/skillhub/dto/cli/CliNamespaceSyncResponse.java b/server/skillhub-app/src/main/java/com/iflytek/skillhub/dto/cli/CliNamespaceSyncResponse.java new file mode 100644 index 00000000..60507972 --- /dev/null +++ b/server/skillhub-app/src/main/java/com/iflytek/skillhub/dto/cli/CliNamespaceSyncResponse.java @@ -0,0 +1,11 @@ +package com.iflytek.skillhub.dto.cli; + +import java.util.List; + +/** + * Cursor-shaped response consumed by the CLI namespace workspace synchronizer. + */ +public record CliNamespaceSyncResponse( + List items, + String nextCursor +) {} diff --git a/server/skillhub-app/src/main/java/com/iflytek/skillhub/service/cli/CliSkillAppService.java b/server/skillhub-app/src/main/java/com/iflytek/skillhub/service/cli/CliSkillAppService.java index 1fcd2e25..984b7d01 100644 --- a/server/skillhub-app/src/main/java/com/iflytek/skillhub/service/cli/CliSkillAppService.java +++ b/server/skillhub-app/src/main/java/com/iflytek/skillhub/service/cli/CliSkillAppService.java @@ -1,14 +1,16 @@ package com.iflytek.skillhub.service.cli; import com.iflytek.skillhub.domain.namespace.NamespaceRole; +import com.iflytek.skillhub.domain.skill.Skill; import com.iflytek.skillhub.domain.skill.SkillVisibility; import com.iflytek.skillhub.domain.skill.service.SkillDownloadService; import com.iflytek.skillhub.domain.skill.service.SkillPublishService; import com.iflytek.skillhub.domain.skill.service.SkillQueryService; import com.iflytek.skillhub.domain.skill.validation.PackageEntry; -import com.iflytek.skillhub.dto.SkillSummaryResponse; import com.iflytek.skillhub.dto.cli.CliDeleteResponse; import com.iflytek.skillhub.dto.cli.CliDryRunResponse; +import com.iflytek.skillhub.dto.cli.CliNamespaceSyncItemResponse; +import com.iflytek.skillhub.dto.cli.CliNamespaceSyncResponse; import com.iflytek.skillhub.dto.cli.CliPublishResponse; import com.iflytek.skillhub.dto.cli.CliResolveResponse; import com.iflytek.skillhub.service.AuditRequestContext; @@ -16,6 +18,8 @@ import com.iflytek.skillhub.service.SkillDeleteAppService; import com.iflytek.skillhub.service.SkillSearchAppService; import jakarta.servlet.http.HttpServletRequest; import org.springframework.core.io.InputStreamResource; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; @@ -82,6 +86,42 @@ public class CliSkillAppService { ); } + public CliNamespaceSyncResponse listNamespaceSkills( + String namespace, + int page, + int limit, + String userId, + Map userNsRoles) { + Map roles = userNsRoles != null ? userNsRoles : Map.of(); + Page skills = skillQueryService.listInstallableSkillsByNamespace( + namespace, userId, roles, PageRequest.of(page, limit)); + + List items = skills.getContent().stream() + .map(skill -> toNamespaceSyncItem(skill, namespace, userId, roles)) + .toList(); + String nextCursor = skills.hasNext() ? String.valueOf(page + 1) : null; + return new CliNamespaceSyncResponse(items, nextCursor); + } + + private CliNamespaceSyncItemResponse toNamespaceSyncItem( + Skill skill, + String namespace, + String userId, + Map userNsRoles) { + SkillQueryService.ResolvedVersionDTO resolved = skillQueryService.resolveVersion( + namespace, skill.getSlug(), null, null, null, userId, userNsRoles); + return new CliNamespaceSyncItemResponse( + namespace, + skill.getSlug(), + resolved.version(), + resolved.versionId(), + resolved.fingerprint(), + skill.getUpdatedAt(), + skill.getVisibility().name(), + resolved.downloadUrl() + ); + } + public ResponseEntity downloadLatest(String namespace, String slug, HttpServletRequest request) { String userId = (String) request.getAttribute("userId"); @SuppressWarnings("unchecked") diff --git a/server/skillhub-app/src/test/java/com/iflytek/skillhub/controller/cli/CliSkillControllerTest.java b/server/skillhub-app/src/test/java/com/iflytek/skillhub/controller/cli/CliSkillControllerTest.java index 9f6fe695..953d9ebb 100644 --- a/server/skillhub-app/src/test/java/com/iflytek/skillhub/controller/cli/CliSkillControllerTest.java +++ b/server/skillhub-app/src/test/java/com/iflytek/skillhub/controller/cli/CliSkillControllerTest.java @@ -132,6 +132,38 @@ class CliSkillControllerTest { verify(apiTokenService).touchLastUsed(token); } + @Test + void namespaceSyncReturnsCursorResponseForValidBearer() throws Exception { + ApiToken token = new ApiToken("sync-user", "cli", "sk_test", "hash", "[]"); + UserAccount user = new UserAccount("sync-user", "Sync User", "sync@example.com", ""); + var response = new com.iflytek.skillhub.dto.cli.CliNamespaceSyncResponse( + List.of(new com.iflytek.skillhub.dto.cli.CliNamespaceSyncItemResponse( + "team-a", "demo", "1.0.0", 42L, "sha256:fingerprint", + java.time.Instant.parse("2026-08-20T00:00:00Z"), "NAMESPACE_ONLY", + "/api/v1/skills/team-a/demo/versions/1.0.0/download" + )), + "2" + ); + + given(apiTokenService.validateToken("sync-token")).willReturn(Optional.of(token)); + given(userAccountRepository.findById("sync-user")).willReturn(Optional.of(user)); + given(userRoleBindingRepository.findByUserId("sync-user")).willReturn(List.of()); + given(cliSkillAppService.listNamespaceSkills("team-a", 1, 25, "sync-user", Map.of())) + .willReturn(response); + + mockMvc.perform(get("/api/cli/v1/namespaces/team-a/skills") + .param("cursor", "1") + .param("limit", "25") + .header(HttpHeaders.AUTHORIZATION, "Bearer sync-token")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.data.items[0].namespace").value("team-a")) + .andExpect(jsonPath("$.data.items[0].slug").value("demo")) + .andExpect(jsonPath("$.data.items[0].version").value("1.0.0")) + .andExpect(jsonPath("$.data.nextCursor").value("2")); + + verify(cliSkillAppService).listNamespaceSkills("team-a", 1, 25, "sync-user", Map.of()); + } + @Test void resolveReturnsCliResolveResponse() throws Exception { given(cliSkillAppService.resolve("global", "demo", null, null, null)).willReturn( diff --git a/server/skillhub-app/src/test/java/com/iflytek/skillhub/service/cli/CliSkillAppServiceTest.java b/server/skillhub-app/src/test/java/com/iflytek/skillhub/service/cli/CliSkillAppServiceTest.java index f503c834..76b1bfd9 100644 --- a/server/skillhub-app/src/test/java/com/iflytek/skillhub/service/cli/CliSkillAppServiceTest.java +++ b/server/skillhub-app/src/test/java/com/iflytek/skillhub/service/cli/CliSkillAppServiceTest.java @@ -32,6 +32,8 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; import java.math.BigDecimal; import java.time.Instant; @@ -222,6 +224,30 @@ class CliSkillAppServiceTest { assertEquals("abc123", response.fingerprint()); } + @Test + void listNamespaceSkills_mapsInstallableVersionsToCliManifest() { + Skill skill = new Skill(7L, "demo", "user-1", SkillVisibility.NAMESPACE_ONLY); + setField(skill, "id", 10L); + skill.setLatestVersionId(42L); + skill.setUpdatedBy("user-1"); + + given(skillQueryService.listInstallableSkillsByNamespace( + eq("team-a"), eq("user-1"), eq(Map.of()), eq(PageRequest.of(0, 100)))) + .willReturn(new PageImpl<>(List.of(skill), PageRequest.of(0, 100), 1)); + given(skillQueryService.resolveVersion("team-a", "demo", null, null, null, "user-1", Map.of())) + .willReturn(new SkillQueryService.ResolvedVersionDTO( + 10L, "team-a", "demo", "1.0.0", 42L, "sha256:fingerprint", null, + "/api/v1/skills/team-a/demo/versions/1.0.0/download")); + + var result = service.listNamespaceSkills("team-a", 0, 100, "user-1", Map.of()); + + assertEquals(1, result.items().size()); + assertEquals("demo", result.items().getFirst().slug()); + assertEquals("1.0.0", result.items().getFirst().version()); + assertEquals("sha256:fingerprint", result.items().getFirst().fingerprint()); + assertNull(result.nextCursor()); + } + @Test void deleteRemote_delegatesToDeleteAppService() { var auditContext = new AuditRequestContext("127.0.0.1", "CLI/1.0"); diff --git a/server/skillhub-auth/src/main/java/com/iflytek/skillhub/auth/policy/RouteSecurityPolicyRegistry.java b/server/skillhub-auth/src/main/java/com/iflytek/skillhub/auth/policy/RouteSecurityPolicyRegistry.java index 84caaca8..1d136076 100644 --- a/server/skillhub-auth/src/main/java/com/iflytek/skillhub/auth/policy/RouteSecurityPolicyRegistry.java +++ b/server/skillhub-auth/src/main/java/com/iflytek/skillhub/auth/policy/RouteSecurityPolicyRegistry.java @@ -83,6 +83,7 @@ public class RouteSecurityPolicyRegistry { RouteAuthorizationPolicy.authenticated(HttpMethod.GET, "/api/web/namespaces/*"), RouteAuthorizationPolicy.authenticated(null, "/api/v1/admin/**"), RouteAuthorizationPolicy.authenticated(HttpMethod.GET, "/api/cli/v1/auth/whoami"), + RouteAuthorizationPolicy.authenticated(HttpMethod.GET, "/api/cli/v1/namespaces/*/skills"), RouteAuthorizationPolicy.permitAll(HttpMethod.GET, "/api/cli/v1/skills/search"), RouteAuthorizationPolicy.permitAll(HttpMethod.GET, "/api/cli/v1/skills/*/*/resolve"), RouteAuthorizationPolicy.permitAll(HttpMethod.GET, "/api/cli/v1/skills/*/*/download"), @@ -133,6 +134,7 @@ public class RouteSecurityPolicyRegistry { ApiTokenPolicy.require(HttpMethod.POST, "/api/web/skills/*/publish", "skill:publish"), ApiTokenPolicy.require(HttpMethod.POST, "/api/v1/publish", "skill:publish"), ApiTokenPolicy.allow(HttpMethod.GET, "/api/cli/v1/auth/whoami"), + ApiTokenPolicy.allow(HttpMethod.GET, "/api/cli/v1/namespaces/*/skills"), ApiTokenPolicy.allow(HttpMethod.GET, "/api/cli/v1/skills/search"), ApiTokenPolicy.allow(HttpMethod.GET, "/api/cli/v1/skills/*/*/resolve"), ApiTokenPolicy.allow(HttpMethod.GET, "/api/cli/v1/skills/*/*/download"), diff --git a/server/skillhub-auth/src/test/java/com/iflytek/skillhub/auth/policy/RouteSecurityPolicyRegistryTest.java b/server/skillhub-auth/src/test/java/com/iflytek/skillhub/auth/policy/RouteSecurityPolicyRegistryTest.java index 7e071a01..1f3b33d2 100644 --- a/server/skillhub-auth/src/test/java/com/iflytek/skillhub/auth/policy/RouteSecurityPolicyRegistryTest.java +++ b/server/skillhub-auth/src/test/java/com/iflytek/skillhub/auth/policy/RouteSecurityPolicyRegistryTest.java @@ -98,6 +98,7 @@ class RouteSecurityPolicyRegistryTest { @Test void apiTokenPolicySupportsNativeCliRoutes() { assertTrue(registry.authorizeApiToken("GET", "/api/cli/v1/auth/whoami", Set.of()).allowed()); + assertTrue(registry.authorizeApiToken("GET", "/api/cli/v1/namespaces/team-a/skills", Set.of()).allowed()); assertTrue(registry.authorizeApiToken("GET", "/api/cli/v1/skills/search", Set.of()).allowed()); assertTrue(registry.authorizeApiToken("GET", "/api/cli/v1/skills/global/demo/resolve", Set.of()).allowed()); assertFalse(registry.authorizeApiToken("POST", "/api/cli/v1/skills/global/publish", Set.of()).allowed()); @@ -107,6 +108,16 @@ class RouteSecurityPolicyRegistryTest { assertTrue(registry.authorizeApiToken("DELETE", "/api/cli/v1/skills/global/demo", Set.of("skill:delete")).allowed()); } + @Test + void routeAuthorizationRequiresAuthenticationForNativeCliNamespaceSync() { + boolean matched = registry.authorizationPolicies().stream() + .anyMatch(policy -> policy.method() == HttpMethod.GET + && "/api/cli/v1/namespaces/*/skills".equals(policy.pattern()) + && policy.accessLevel() == RouteSecurityPolicyRegistry.AccessLevel.AUTHENTICATED); + + assertTrue(matched); + } + @Test void routeAuthorizationProtectsNativeCliRemoteDeleteByAuthenticationNotSuperAdminRole() { boolean matched = registry.authorizationPolicies().stream() diff --git a/server/skillhub-domain/src/main/java/com/iflytek/skillhub/domain/skill/service/SkillQueryService.java b/server/skillhub-domain/src/main/java/com/iflytek/skillhub/domain/skill/service/SkillQueryService.java index 66c5e319..c7a86cd7 100644 --- a/server/skillhub-domain/src/main/java/com/iflytek/skillhub/domain/skill/service/SkillQueryService.java +++ b/server/skillhub-domain/src/main/java/com/iflytek/skillhub/domain/skill/service/SkillQueryService.java @@ -37,6 +37,7 @@ import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.TreeSet; +import java.util.function.Function; import java.util.stream.Collectors; /** @@ -286,6 +287,47 @@ public class SkillQueryService { return new PageImpl<>(pageContent, pageable, accessibleSkills.size()); } + /** + * Lists only active, visible skills whose latest version can be installed. + * + *

This is intentionally separate from {@link #listSkillsByNamespace}: + * the portal discovery method also exposes skills without a published + * version, while the CLI sync manifest must contain concrete downloadable + * versions. Filtering happens before pagination so cursors remain stable. + */ + public Page listInstallableSkillsByNamespace( + String namespaceSlug, + String currentUserId, + Map userNsRoles, + Pageable pageable) { + + Namespace namespace = findNamespace(namespaceSlug); + List accessibleSkills = skillRepository + .findByNamespaceIdAndStatus(namespace.getId(), SkillStatus.ACTIVE) + .stream() + .filter(skill -> visibilityChecker.canAccess(skill, currentUserId, userNsRoles)) + .toList(); + + Map latestVersions = skillVersionRepository.findByIdIn( + accessibleSkills.stream() + .map(Skill::getLatestVersionId) + .filter(Objects::nonNull) + .distinct() + .toList()) + .stream() + .collect(Collectors.toMap(SkillVersion::getId, Function.identity())); + + List installableSkills = accessibleSkills.stream() + .filter(skill -> SkillInstallability.isInstallableVersion(latestVersions.get(skill.getLatestVersionId()))) + .sorted(Comparator.comparing(Skill::getSlug) + .thenComparing(Skill::getId, Comparator.nullsLast(Comparator.naturalOrder()))) + .toList(); + + int start = Math.min((int) pageable.getOffset(), installableSkills.size()); + int end = Math.min(start + pageable.getPageSize(), installableSkills.size()); + return new PageImpl<>(installableSkills.subList(start, end), pageable, installableSkills.size()); + } + /** * Returns metadata for a visible version, including the stored manifest and * parsed metadata payload. diff --git a/server/skillhub-domain/src/test/java/com/iflytek/skillhub/domain/skill/service/SkillQueryServiceTest.java b/server/skillhub-domain/src/test/java/com/iflytek/skillhub/domain/skill/service/SkillQueryServiceTest.java index dc5782c4..7fb08e3c 100644 --- a/server/skillhub-domain/src/test/java/com/iflytek/skillhub/domain/skill/service/SkillQueryServiceTest.java +++ b/server/skillhub-domain/src/test/java/com/iflytek/skillhub/domain/skill/service/SkillQueryServiceTest.java @@ -239,6 +239,46 @@ class SkillQueryServiceTest { verify(skillRepository).findByNamespaceIdAndStatus(1L, SkillStatus.ACTIVE); } + @Test + void installableNamespaceDiscoveryFiltersBeforePaginationAndSortsBySlug() throws Exception { + Namespace namespace = new Namespace("team-a", "Team A", "owner-1"); + setId(namespace, 1L); + Skill ready = new Skill(1L, "ready", "owner-1", SkillVisibility.NAMESPACE_ONLY); + setId(ready, 10L); + ready.setLatestVersionId(100L); + Skill draft = new Skill(1L, "draft", "owner-1", SkillVisibility.NAMESPACE_ONLY); + setId(draft, 11L); + draft.setLatestVersionId(101L); + Skill publicReady = new Skill(1L, "public-ready", "owner-2", SkillVisibility.PUBLIC); + setId(publicReady, 12L); + publicReady.setLatestVersionId(102L); + + SkillVersion readyVersion = new SkillVersion(10L, "1.0.0", "owner-1"); + setId(readyVersion, 100L); + readyVersion.setStatus(SkillVersionStatus.PUBLISHED); + readyVersion.setDownloadReady(true); + SkillVersion draftVersion = new SkillVersion(11L, "1.0.0", "owner-1"); + setId(draftVersion, 101L); + draftVersion.setStatus(SkillVersionStatus.DRAFT); + SkillVersion publicReadyVersion = new SkillVersion(12L, "2.0.0", "owner-2"); + setId(publicReadyVersion, 102L); + publicReadyVersion.setStatus(SkillVersionStatus.PUBLISHED); + publicReadyVersion.setDownloadReady(true); + + when(namespaceRepository.findBySlug("team-a")).thenReturn(Optional.of(namespace)); + when(skillRepository.findByNamespaceIdAndStatus(1L, SkillStatus.ACTIVE)) + .thenReturn(List.of(ready, draft, publicReady)); + when(skillVersionRepository.findByIdIn(List.of(100L, 101L, 102L))) + .thenReturn(List.of(readyVersion, draftVersion, publicReadyVersion)); + + Page result = service.listInstallableSkillsByNamespace( + "team-a", "viewer", Map.of(1L, NamespaceRole.MEMBER), PageRequest.of(0, 1)); + + assertEquals(2, result.getTotalElements()); + assertEquals("public-ready", result.getContent().getFirst().getSlug()); + assertTrue(result.hasNext()); + } + @Test void versionContentRejectsPublicArchivedSkillForNonManager() throws Exception { Namespace namespace = new Namespace("global", "Global", "owner-1"); diff --git a/web/src/api/generated/schema.d.ts b/web/src/api/generated/schema.d.ts index 423ee239..69d55df9 100644 --- a/web/src/api/generated/schema.d.ts +++ b/web/src/api/generated/schema.d.ts @@ -3348,6 +3348,22 @@ export interface paths { patch?: never; trace?: never; }; + "/api/cli/v1/namespaces/{namespace}/skills": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["listSkills_1"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/api/cli/v1/auth/whoami": { parameters: { query?: never; @@ -4347,6 +4363,8 @@ export interface components { namespace?: string; /** Format: date-time */ updatedAt?: string; + ownerId?: string; + ownerDisplayName?: string; canSubmitPromotion?: boolean; headlineVersion?: components["schemas"]["SkillLifecycleVersionResponse"]; publishedVersion?: components["schemas"]["SkillLifecycleVersionResponse"]; @@ -5330,6 +5348,31 @@ export interface components { /** Format: int32 */ limit?: number; }; + ApiResponseCliNamespaceSyncResponse: { + /** Format: int32 */ + code?: number; + msg?: string; + data?: components["schemas"]["CliNamespaceSyncResponse"]; + /** Format: date-time */ + timestamp?: string; + requestId?: string; + }; + CliNamespaceSyncItemResponse: { + namespace?: string; + slug?: string; + version?: string; + /** Format: int64 */ + versionId?: number; + fingerprint?: string; + /** Format: date-time */ + updatedAt?: string; + visibility?: string; + downloadUrl?: string; + }; + CliNamespaceSyncResponse: { + items?: components["schemas"]["CliNamespaceSyncItemResponse"][]; + nextCursor?: string; + }; ApiResponseCliWhoAmIResponse: { /** Format: int32 */ code?: number; @@ -11357,6 +11400,31 @@ export interface operations { }; }; }; + listSkills_1: { + parameters: { + query?: { + cursor?: string; + limit?: number; + }; + header?: never; + path: { + namespace: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["ApiResponseCliNamespaceSyncResponse"]; + }; + }; + }; + }; whoami_1: { parameters: { query?: never;