diff --git a/.github/agents/spx-upgrader.md b/.github/agents/spx-upgrader.md index c8b818bc76..b44b5b98a6 100644 --- a/.github/agents/spx-upgrader.md +++ b/.github/agents/spx-upgrader.md @@ -9,7 +9,7 @@ You are a release specialist dedicated to upgrading spx across goplus/builder sa - For released versions, verify they exist by running `gh release view --repo goplus/spx v` - Verify the matching web package exists by running `npm view @xgo-pkgs/spx@ version` - Run `pnpm add @xgo-pkgs/spx@ --save-exact` in `spx-gui/` to update `spx-gui/package.json` and `spx-gui/pnpm-lock.yaml` -- Refresh Go modules in `tools/ai/`, `tools/spxls/`, and `tools/ispx/` via `go get github.com/goplus/spx/v2@v` followed by `go mod tidy` in each directory +- Refresh Go modules in `tools/ai/`, `tools/spxls/`, and `tools/ispx/` via `go get github.com/goplus/spx/v3@v` followed by `go mod tidy` in each directory - Execute `pnpm install --frozen-lockfile` in `spx-gui/` to install dependencies and expose the installed runtime assets under `spx-gui/public/` via `postinstall` - Execute `bash build-wasm.sh` in `spx-gui/` to build Wasm components - Run `pnpm run lint`, `pnpm run test -- --run` in `spx-gui/`, plus `go test ./...` inside `tools/ai/`, `tools/spxls/`, and `tools/ispx/` if there are packages to test diff --git a/docs/develop/code-editor/base.ts b/docs/develop/code-editor/base.ts index a79ce81b93..71322fd720 100644 --- a/docs/develop/code-editor/base.ts +++ b/docs/develop/code-editor/base.ts @@ -68,7 +68,7 @@ interface DefinitionIdentifier { * If `main`, it's the current user package. * Exmples: * - `fmt` - * - `github.com/goplus/spx/v2` + * - `github.com/goplus/spx/v3` * - `main` */ package?: string diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 5d191d7dcb..0663030c8a 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -1683,7 +1683,6 @@ paths: - title - thumbnail - entrypoint - - references - prompt properties: title: @@ -1692,8 +1691,6 @@ paths: $ref: "#/components/schemas/Course/properties/thumbnail" entrypoint: $ref: "#/components/schemas/Course/properties/entrypoint" - references: - $ref: "#/components/schemas/Course/properties/references" prompt: $ref: "#/components/schemas/Course/properties/prompt" responses: @@ -3137,8 +3134,6 @@ paths: $ref: "#/components/schemas/Course/properties/thumbnail" entrypoint: $ref: "#/components/schemas/Course/properties/entrypoint" - references: - $ref: "#/components/schemas/Course/properties/references" prompt: $ref: "#/components/schemas/Course/properties/prompt" responses: @@ -4600,7 +4595,7 @@ paths: description: | Scratch project file, such as .sb2, .sb3, or project zip. Form field name must be `file`. - Maximum size is 64 MiB. + Maximum size is 128 MiB. type: string format: binary responses: @@ -5409,8 +5404,6 @@ paths: $ref: "#/components/schemas/AccountApp/properties/clientType" redirectURIs: $ref: "#/components/schemas/AccountApp/properties/redirectURIs" - allowedOrigins: - $ref: "#/components/schemas/AccountApp/properties/allowedOrigins" responses: "201": description: Account app created. @@ -5489,8 +5482,6 @@ paths: $ref: "#/components/schemas/AccountApp/properties/status" redirectURIs: $ref: "#/components/schemas/AccountApp/properties/redirectURIs" - allowedOrigins: - $ref: "#/components/schemas/AccountApp/properties/allowedOrigins" responses: "200": description: Account app updated. @@ -6357,12 +6348,12 @@ components: examples: - John Doe avatar: - description: Public HTTP URL or Kodo universal URL of the user's avatar image. + description: Public HTTP URL of the user's avatar image. type: string format: uri + pattern: "^https?://" examples: - https://avatars.example.com/users/10137.png - - kodo://xbuilder-usercontent-test/files/avatar.png description: description: Brief bio or description of the user. type: string @@ -6667,7 +6658,6 @@ components: - status - redirectURIs - redirectURIPatterns - - allowedOrigins properties: id: $ref: "#/components/schemas/Model/properties/id" @@ -6743,16 +6733,6 @@ components: type: string examples: - - https://app-*.example.com/oauth/callback - allowedOrigins: - description: | - Allowed web origins. - - Production web origins must use `https`, must not include path, query, or fragment, and must be matched - exactly by the server. - type: array - items: - type: string - format: uri AccountAppSecret: type: object @@ -7580,7 +7560,6 @@ components: - title - thumbnail - entrypoint - - references - prompt properties: id: @@ -7613,11 +7592,6 @@ components: minLength: 1 examples: - /editor/john/loop - references: - description: References associated with the course. - type: array - items: - $ref: "#/components/schemas/CourseReference" prompt: description: Prompt text for the course (used for copilot assistance). type: string @@ -7625,26 +7599,6 @@ components: examples: - Learn the basics of XGo programming language - CourseReference: - description: Reference to a resource associated with a course. - type: object - required: - - type - - fullName - properties: - type: - description: Type of the reference. - type: string - enum: - - project - examples: - - project - fullName: - description: Full name of the reference, in the format `owner/project`. - $ref: "#/components/schemas/ProjectFullName" - examples: - - john/NiuXiaoQi - CourseSeries: description: Collection of related courses. type: object diff --git a/spx-gui/package.json b/spx-gui/package.json index c5c7bf7594..4a054b2f65 100644 --- a/spx-gui/package.json +++ b/spx-gui/package.json @@ -21,6 +21,7 @@ "dependencies": { "@floating-ui/dom": "^1.7.6", "@jridgewell/resolve-uri": "^3.1.2", + "@lottiefiles/dotlottie-web": "0.41.0", "@lottiefiles/dotlottie-vue": "^0.5.8", "@nighca/fflate": "^0.8.3", "@scalar/api-reference": "^1.40.0", @@ -43,7 +44,7 @@ "@vue/runtime-core": "3.5.25", "@vue/test-utils": "^2.4.5", "@vue/tsconfig": "^0.8.1", - "@xgo-pkgs/spx": "2.0.4", + "@xgo-pkgs/spx": "3.0.0", "bowser": "^2.14.1", "browserslist": "^4.28.0", "browserslist-to-esbuild": "^2.1.1", diff --git a/spx-gui/pnpm-lock.yaml b/spx-gui/pnpm-lock.yaml index 47037b526c..57528b3447 100644 --- a/spx-gui/pnpm-lock.yaml +++ b/spx-gui/pnpm-lock.yaml @@ -17,6 +17,9 @@ importers: '@lottiefiles/dotlottie-vue': specifier: ^0.5.8 version: 0.5.8(vue@3.5.25(typescript@5.9.3)) + '@lottiefiles/dotlottie-web': + specifier: 0.41.0 + version: 0.41.0 '@nighca/fflate': specifier: ^0.8.3 version: 0.8.3 @@ -81,8 +84,8 @@ importers: specifier: ^0.8.1 version: 0.8.1(typescript@5.9.3)(vue@3.5.25(typescript@5.9.3)) '@xgo-pkgs/spx': - specifier: 2.0.4 - version: 2.0.4 + specifier: 3.0.0 + version: 3.0.0 bowser: specifier: ^2.14.1 version: 2.14.1 @@ -1224,8 +1227,8 @@ packages: peerDependencies: vue: ^3.5.0 - '@xgo-pkgs/spx@2.0.4': - resolution: {integrity: sha512-aV6L7UD/6GXH6dEUjzSTU/7kpLXsN/L8Wy8rnFzR4gez0otKlmxjX8Ogft9COaQR1hQ5N0AvhXw0jPJdN+5FjA==} + '@xgo-pkgs/spx@3.0.0': + resolution: {integrity: sha512-+aLj+XSXJZpuBJcAGgOqhHDEBs7qcer3xQ/ZkiSvNPDdXEfn1006V1X8VS6avXsGyr/eKSHV4ep4rpuKMgQrRg==} abbrev@2.0.0: resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} @@ -4195,7 +4198,7 @@ snapshots: dependencies: vue: 3.5.25(typescript@5.9.3) - '@xgo-pkgs/spx@2.0.4': {} + '@xgo-pkgs/spx@3.0.0': {} abbrev@2.0.0: {} diff --git a/spx-gui/pnpm-workspace.yaml b/spx-gui/pnpm-workspace.yaml index bc26a2df3d..e6ef30d6e3 100644 --- a/spx-gui/pnpm-workspace.yaml +++ b/spx-gui/pnpm-workspace.yaml @@ -2,3 +2,5 @@ packages: - . allowBuilds: vue-demi: true +minimumReleaseAgeExclude: + - '@xgo-pkgs/spx' diff --git a/spx-gui/src/apis/account/common.ts b/spx-gui/src/apis/account/common.ts index c046ae3d3f..4f64d345c6 100644 --- a/spx-gui/src/apis/account/common.ts +++ b/spx-gui/src/apis/account/common.ts @@ -70,8 +70,6 @@ export type AccountApp = AccountModel & { redirectURIs: string[] /** Read-only allowed redirect URI patterns */ redirectURIPatterns: string[] - /** Allowed web origins */ - allowedOrigins: string[] } export type AccountAppSecret = { diff --git a/spx-gui/src/apis/admin/account.ts b/spx-gui/src/apis/admin/account.ts index fdb7bb1819..0a741f8ae5 100644 --- a/spx-gui/src/apis/admin/account.ts +++ b/spx-gui/src/apis/admin/account.ts @@ -194,8 +194,6 @@ export type CreateAccountAppParams = { clientType: AccountAppClientType /** Allowed redirect URIs */ redirectURIs: string[] - /** Allowed web origins */ - allowedOrigins?: string[] } export function createAccountApp(params: CreateAccountAppParams) { @@ -213,8 +211,6 @@ export type UpdateAccountAppParams = { status?: AccountAppStatus /** Allowed redirect URIs */ redirectURIs?: string[] - /** Allowed web origins */ - allowedOrigins?: string[] } export function updateAccountApp(appID: string, params: UpdateAccountAppParams) { diff --git a/spx-gui/src/apis/course.ts b/spx-gui/src/apis/course.ts index f66cd40331..ab0fc2369e 100644 --- a/spx-gui/src/apis/course.ts +++ b/spx-gui/src/apis/course.ts @@ -3,14 +3,6 @@ import { client, type ByPage, type PaginationParams } from './common' export const courseTitleMaxLength = 200 export const coursePromptMaxLength = 4000 -export type ProjectReference = { - type: 'project' - /** Full name of the project, in the format `owner/project`. */ - fullName: string -} - -export type Reference = ProjectReference // We may support more reference types in the future - export type Course = { /** Unique identifier */ id: string @@ -22,8 +14,6 @@ export type Course = { thumbnail: string /** Starting URL of the course */ entrypoint: string - /** References of the course */ - references: Reference[] /** Prompt (for copilot) of the course */ prompt: string } @@ -33,7 +23,7 @@ export function getCourse(id: string, signal?: AbortSignal) { return client.get(`/courses/${encodeURIComponent(id)}`, undefined, { signal }) as Promise } -export type AddUpdateCourseParams = Pick +export type AddUpdateCourseParams = Pick /** Add a new course */ export function addCourse(params: AddUpdateCourseParams, signal?: AbortSignal) { diff --git a/spx-gui/src/apis/project-conversion.ts b/spx-gui/src/apis/project-conversion.ts index b0284de427..25a5287ab7 100644 --- a/spx-gui/src/apis/project-conversion.ts +++ b/spx-gui/src/apis/project-conversion.ts @@ -2,7 +2,7 @@ import { DefaultException } from '@/utils/exception' import { client } from './common' import { humanizeFileSize } from '@/utils/utils' -const maxFileSize = 64 * 1024 * 1024 // 64MB +const maxFileSize = 128 * 1024 * 1024 // 128MB const convertTimeout = 60 * 1000 // 60s /** diff --git a/spx-gui/src/apis/user.ts b/spx-gui/src/apis/user.ts index b5fd4a17e0..bb9e3a9268 100644 --- a/spx-gui/src/apis/user.ts +++ b/spx-gui/src/apis/user.ts @@ -16,7 +16,7 @@ export type User = { username: string /** Display name of the user */ displayName: string - /** URL of the user's avatar image */ + /** Public HTTP URL of the user's avatar image */ avatar: string /** Brief bio or description of the user */ description: string diff --git a/spx-gui/src/apps/xbuilder/pages/admin/app.vue b/spx-gui/src/apps/xbuilder/pages/admin/app.vue index be069ef084..69e8104d86 100644 --- a/spx-gui/src/apps/xbuilder/pages/admin/app.vue +++ b/spx-gui/src/apps/xbuilder/pages/admin/app.vue @@ -12,7 +12,6 @@ import CopyButton from '@/components/common/CopyButton.vue' import UIIcon from '@/components/ui/icons/UIIcon.vue' import * as accountAdminApis from '@/apis/admin/account' import { - accountAppAllowedOriginsTip, accountAppClientTypeLabels, accountAppRedirectURIPatternsTip, accountAppRedirectURIsTip, @@ -52,11 +51,9 @@ usePageTitle(() => const displayName = ref('') const status = ref('active') const redirectURIs = ref('') -const allowedOrigins = ref('') const savedDisplayName = ref('') const savedStatus = ref('active') const savedRedirectURIs = ref([]) -const savedAllowedOrigins = ref([]) const appUpdatedAt = ref('') const appFallbackText = computed(() => displayName.value.trim().charAt(0).toUpperCase() || '?') const trimmedDisplayName = computed(() => displayName.value.trim()) @@ -68,28 +65,22 @@ watch( displayName.value = value.displayName status.value = value.status redirectURIs.value = value.redirectURIs.join('\n') - allowedOrigins.value = value.allowedOrigins.join('\n') savedDisplayName.value = value.displayName savedStatus.value = value.status savedRedirectURIs.value = value.redirectURIs - savedAllowedOrigins.value = value.allowedOrigins appUpdatedAt.value = value.updatedAt }, { immediate: true } ) const parsedRedirectURIs = computed(() => parseLines(redirectURIs.value)) -const parsedAllowedOrigins = computed(() => parseLines(allowedOrigins.value)) const isActive = computed(() => status.value === 'active') const isIdentityChanged = computed( () => trimmedDisplayName.value !== '' && trimmedDisplayName.value !== savedDisplayName.value ) const isStatusChanged = computed(() => status.value !== savedStatus.value) -const areEndpointsChanged = computed( - () => - parsedRedirectURIs.value.length > 0 && - (!areStringListsEqual(parsedRedirectURIs.value, savedRedirectURIs.value) || - !areStringListsEqual(parsedAllowedOrigins.value, savedAllowedOrigins.value)) +const areRedirectURIsChanged = computed( + () => parsedRedirectURIs.value.length > 0 && !areStringListsEqual(parsedRedirectURIs.value, savedRedirectURIs.value) ) function areStringListsEqual(a: string[], b: string[]) { @@ -123,14 +114,12 @@ const handleUpdateIdentity = useMessageHandle( { en: 'App identity updated', zh: '应用信息已更新' } ) -const handleUpdateEndpoints = useMessageHandle( +const handleUpdateRedirectURIs = useMessageHandle( async () => { const updated = await accountAdminApis.updateAccountApp(props.appID, { - redirectURIs: parsedRedirectURIs.value, - allowedOrigins: parsedAllowedOrigins.value + redirectURIs: parsedRedirectURIs.value }) savedRedirectURIs.value = updated.redirectURIs - savedAllowedOrigins.value = updated.allowedOrigins appUpdatedAt.value = updated.updatedAt }, { en: 'Failed to update OAuth endpoints', zh: '更新 OAuth 地址配置失败' }, @@ -339,13 +328,13 @@ function deleteSecret(secretID: string) {

{{ $t({ - en: 'Exact destinations and browser origins trusted by this app.', - zh: '此应用信任的精确回调地址和浏览器来源。' + en: 'Exact callback destinations trusted by this app.', + zh: '此应用信任的精确回调地址。' }) }}

-
+