Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 0 additions & 99 deletions docs/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1345,56 +1345,6 @@ paths:
description: Successfully deleted the course series.
"403":
description: Insufficient permissions to perform this operation.

/copilot/message:
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个接口其实早就用不到了,只是之前一直没删

post:
tags:
- Copilot
summary: Generate a message
description: |
Generate a message by sending a list of input messages.

#### Quota & rate limits

- Each message consumes 1 quota from the authenticated user's allowance.
- Per-user short-window rate limits also apply to prevent bursts. Hitting them returns 429 with `Retry-After`.
- Long-window quota limits vary based on the authenticated user's plan.
- When the long-window quota limit is reached, the 403 response includes a `Retry-After` header with the wait
time in seconds.
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CopilotMessageRequest"

responses:
"201":
description: Message successfully generated.
content:
application/json:
schema:
$ref: "#/components/schemas/CopilotCopilotMessage"
example:
role: copilot
content:
type: text
text: Hello!
"403":
description: Insufficient permissions or quota to perform this operation.
headers:
Retry-After:
description: Seconds to wait before retrying after hitting the long-window quota limit.
schema:
type: integer
"429":
description: Too many requests to perform this operation.
headers:
Retry-After:
description: Seconds to wait before retrying after hitting the short-window rate limit.
schema:
type: integer

/copilot/sse/message:
post:
tags:
Expand All @@ -1403,10 +1353,6 @@ paths:
description: |
Generate a structured SSE stream message by sending a list of input messages.

This is the rollout target for new structured streaming clients. During rollout, the legacy
`POST /copilot/stream/message` endpoint remains available with its existing behavior unchanged so clients can
migrate incrementally.

The response is a Server-Sent Events (SSE) stream where each `data:` line contains a single JSON object.

#### Event semantics
Expand Down Expand Up @@ -1490,51 +1436,6 @@ paths:
schema:
type: integer

/copilot/stream/message:
post:
tags:
- Copilot
summary: Generate a stream message
description: |
Generate a stream message by sending a list of input messages.

This is the legacy streaming endpoint kept during rollout. New structured streaming integrations should use
`POST /copilot/sse/message`, while this endpoint remains available with unchanged behavior for backward
compatibility.

#### Quota & rate limits

- Each message consumes 1 quota from the authenticated user's allowance.
- Per-user short-window rate limits also apply to prevent bursts. Hitting them returns 429 with `Retry-After`.
- Long-window quota limits vary based on the authenticated user's plan.
- When the long-window quota limit is reached, the 403 response includes a `Retry-After` header with the wait
time in seconds.
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CopilotMessageRequest"
responses:
"201":
description: Stream Message successfully generated.
content:
application/stream:
"403":
description: Insufficient permissions or quota to perform this operation.
headers:
Retry-After:
description: Seconds to wait before retrying after hitting the long-window quota limit.
schema:
type: integer
"429":
description: Too many requests to perform this operation.
headers:
Retry-After:
description: Seconds to wait before retrying after hitting the short-window rate limit.
schema:
type: integer

/workflow/stream/message:
post:
tags:
Expand Down
7 changes: 3 additions & 4 deletions spx-gui/src/apis/copilot.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ describe('generateSSEMessage', () => {
])
)

const events = await collectMessageEvents(generateSSEMessage('standard', []))
const events = await collectMessageEvents(generateSSEMessage([]))

expect(events).toEqual([
{
Expand Down Expand Up @@ -104,7 +104,7 @@ describe('generateSSEMessage', () => {
])
)

const events = await collectMessageEvents(generateSSEMessage('standard', []))
const events = await collectMessageEvents(generateSSEMessage([]))

expect(events).toEqual([
{
Expand Down Expand Up @@ -154,12 +154,11 @@ describe('generateSSEMessage', () => {
])
)

await collectMessageEvents(generateSSEMessage('standard', [], { tools }))
await collectMessageEvents(generateSSEMessage([], { tools }))

expect(mockedPostJSONSSE).toHaveBeenCalledWith(
'/copilot/sse/message',
{
scope: 'standard',
messages: [],
tools
},
Expand Down
13 changes: 1 addition & 12 deletions spx-gui/src/apis/copilot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
import type { JsonSchema7Type } from 'zod-to-json-schema'
import { client } from './common'

export type CopilotScope = 'standard' | 'code'

export enum ToolType {
Function = 'function'
}
Expand Down Expand Up @@ -96,23 +94,14 @@ export type GenerateSSEMessageOptions = GenerateMessageOptions & {

const timeout = 15 * 1000

export function generateMessage(scope: CopilotScope, messages: Message[], options?: GenerateMessageOptions) {
return client.post(
'/copilot/message',
{ scope, messages },
{ timeout: timeout, signal: options?.signal }
) as Promise<Message>
}

export async function* generateSSEMessage(
scope: CopilotScope,
messages: Message[],
options?: GenerateSSEMessageOptions
): AsyncIterableIterator<MessageEvent> {
try {
const stream = client.postJSONSSE(
'/copilot/sse/message',
Comment thread
nighca marked this conversation as resolved.
{ scope, messages, tools: options?.tools },
{ messages, tools: options?.tools },
Copy link
Copy Markdown
Collaborator Author

@nighca nighca Mar 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个 scope 也没有意义了,最初引入是为了 CodeEditor 中的 Copilot(scope: code)升级为全局 Copilot(scope: standard)的迁移过程顺畅,现在前者已经不存在了

这次改动会在 backend(PR: https://github.com/goplus/builder-backend/pull/167 )中也干掉这个参数,并总是走原 scope: standard 的逻辑

{
timeout: timeout,
signal: options?.signal
Expand Down
9 changes: 3 additions & 6 deletions spx-gui/src/components/copilot/copilot.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,8 @@ class MockMessageEventGenerator implements IMessageEventGenerator {
}

async *generateSSEMessage(
scope: apis.CopilotScope,
messages: apis.Message[],
options?: apis.GenerateMessageOptions
options?: apis.GenerateSSEMessageOptions
): AsyncIterableIterator<apis.MessageEvent> {
const batch = this.eventBatches[this.callCount] ?? []
this.callCount += 1
Expand Down Expand Up @@ -226,9 +225,8 @@ class MockSingleBatchMessageEventGenerator implements IMessageEventGenerator {
) {}

async *generateSSEMessage(
scope: apis.CopilotScope,
messages: apis.Message[],
options?: apis.GenerateMessageOptions
options?: apis.GenerateSSEMessageOptions
): AsyncIterableIterator<apis.MessageEvent> {
for (const event of this.events) {
if (options?.signal?.aborted) {
Expand All @@ -254,9 +252,8 @@ class MockBatchedMessageEventGenerator implements IMessageEventGenerator {
) {}

async *generateSSEMessage(
scope: apis.CopilotScope,
messages: apis.Message[],
options?: apis.GenerateMessageOptions
options?: apis.GenerateSSEMessageOptions
): AsyncIterableIterator<apis.MessageEvent> {
this.calls.push(messages)
this.callOptions.push(options ?? null)
Expand Down
2 changes: 1 addition & 1 deletion spx-gui/src/components/copilot/copilot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ export class Round {
// TODO: history summarization with LLM instead of truncation
const sampledApiMessages = sampleApiMessages(apiMessages)
const toolCalls: Array<ToolCallDraft | null> = []
const result = this.copilot.generator.generateSSEMessage('standard', sampledApiMessages, {
const result = this.copilot.generator.generateSSEMessage(sampledApiMessages, {
signal: this.ctrl.signal,
tools: this.copilot.getTools().map(toApiTool)
})
Expand Down