forked from ericc-ch/copilot-api
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcreate-responses.ts
More file actions
168 lines (141 loc) · 3.82 KB
/
create-responses.ts
File metadata and controls
168 lines (141 loc) · 3.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
import consola from "consola"
import { events } from "fetch-event-stream"
import { copilotHeaders, copilotBaseUrl } from "~/lib/api-config"
import { HTTPError } from "~/lib/error"
import { state } from "~/lib/state"
export const createResponses = async (payload: ResponsesPayload) => {
if (!state.copilotToken) throw new Error("Copilot token not found")
const enableVision =
Array.isArray(payload.input)
&& payload.input.some(
(x) =>
Array.isArray(x.content)
&& x.content.some((part) => part.type === "input_image"),
)
const isAgentCall =
Array.isArray(payload.input)
&& payload.input.some((msg) => ["assistant", "tool"].includes(msg.role))
const headers: Record<string, string> = {
...copilotHeaders(state, enableVision),
"X-Initiator": isAgentCall ? "agent" : "user",
}
const response = await fetch(`${copilotBaseUrl(state)}/responses`, {
method: "POST",
headers,
body: JSON.stringify(payload),
})
if (!response.ok) {
consola.error(
`Failed to create response: HTTP ${response.status} ${response.statusText} from ${response.url}`,
)
throw new HTTPError("Failed to create response", response)
}
if (payload.stream) {
return events(response)
}
return (await response.json()) as ResponseObject
}
// Payload types
export interface ResponsesPayload {
model: string
input: string | Array<InputMessage>
stream?: boolean | null
temperature?: number | null
top_p?: number | null
max_output_tokens?: number | null
tools?: Array<ResponseTool> | null
tool_choice?:
| "auto"
| "none"
| "required"
| { type: "function"; name: string }
| null
previous_response_id?: string | null
instructions?: string | null
reasoning?: { effort: "low" | "medium" | "high" } | null
metadata?: Record<string, string> | null
user?: string | null
}
export interface InputMessage {
role: "user" | "assistant" | "system" | "developer" | "tool"
content: string | Array<InputContentPart>
name?: string
tool_call_id?: string
}
export type InputContentPart = InputTextPart | InputImagePart | InputFilePart
export interface InputTextPart {
type: "input_text"
text: string
}
export interface InputImagePart {
type: "input_image"
image_url?: { url: string; detail?: "low" | "high" | "auto" }
file_id?: string
}
export interface InputFilePart {
type: "input_file"
file_id?: string
file_url?: string
filename?: string
}
export interface ResponseTool {
type: "function"
name: string
description?: string
parameters?: Record<string, unknown>
strict?: boolean | null
}
// Response types (non-streaming)
export interface ResponseObject {
id: string
object: "response"
created_at: number
model: string
output: Array<OutputItem>
status: "completed" | "incomplete" | "failed" | "cancelled"
usage?: ResponseUsage
instructions?: string | null
error?: ResponseError | null
metadata?: Record<string, string> | null
}
export type OutputItem = MessageOutputItem | FunctionCallOutputItem
export interface MessageOutputItem {
type: "message"
id: string
role: "assistant"
content: Array<OutputContentPart>
status: "completed" | "incomplete"
}
export type OutputContentPart = OutputTextPart | RefusalPart
export interface OutputTextPart {
type: "output_text"
text: string
annotations?: Array<unknown>
}
export interface RefusalPart {
type: "refusal"
refusal: string
}
export interface FunctionCallOutputItem {
type: "function_call"
id: string
call_id: string
name: string
arguments: string
status: "completed"
}
export interface ResponseUsage {
input_tokens: number
output_tokens: number
total_tokens: number
input_tokens_details?: {
cached_tokens: number
}
output_tokens_details?: {
reasoning_tokens: number
}
}
export interface ResponseError {
code: string
message: string
}