@gnahz77/opencode-copilot-multi-auth 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -7
- package/dist/auth.d.ts +18 -0
- package/dist/auth.js +195 -0
- package/dist/constants.d.ts +9 -0
- package/dist/constants.js +28 -0
- package/dist/errors.d.ts +2 -0
- package/dist/errors.js +6 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +309 -0
- package/dist/models.d.ts +193 -0
- package/dist/models.js +150 -0
- package/dist/pool.d.ts +8 -0
- package/dist/pool.js +157 -0
- package/dist/routing.d.ts +8 -0
- package/dist/routing.js +12 -0
- package/dist/tui.d.ts +5 -0
- package/dist/tui.js +44 -0
- package/dist/types.d.ts +133 -0
- package/dist/types.js +1 -0
- package/dist/usage.d.ts +11 -0
- package/dist/usage.js +113 -0
- package/dist/utils.d.ts +28 -0
- package/dist/utils.js +216 -0
- package/index.mjs +12 -1211
- package/package.json +28 -3
package/dist/utils.js
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { RESPONSES_API_ALTERNATE_INPUT_TYPES } from "./constants.js";
|
|
2
|
+
function isRecord(value) {
|
|
3
|
+
return Boolean(value) && typeof value === "object";
|
|
4
|
+
}
|
|
5
|
+
function parseBody(body) {
|
|
6
|
+
if (typeof body === "string") {
|
|
7
|
+
return JSON.parse(body);
|
|
8
|
+
}
|
|
9
|
+
return body;
|
|
10
|
+
}
|
|
11
|
+
export function normalizeHeaderObject(headers) {
|
|
12
|
+
if (!headers) {
|
|
13
|
+
return {};
|
|
14
|
+
}
|
|
15
|
+
if (typeof Headers !== "undefined" && headers instanceof Headers) {
|
|
16
|
+
return Object.fromEntries(headers.entries());
|
|
17
|
+
}
|
|
18
|
+
if (Array.isArray(headers)) {
|
|
19
|
+
return Object.fromEntries(headers);
|
|
20
|
+
}
|
|
21
|
+
const objectHeaders = headers;
|
|
22
|
+
const normalized = {};
|
|
23
|
+
for (const [key, value] of Object.entries(objectHeaders)) {
|
|
24
|
+
normalized[key] = String(value);
|
|
25
|
+
}
|
|
26
|
+
return normalized;
|
|
27
|
+
}
|
|
28
|
+
export function normalizeList(value) {
|
|
29
|
+
return Array.isArray(value) ? value : [];
|
|
30
|
+
}
|
|
31
|
+
function escapeRegex(value) {
|
|
32
|
+
return value.replace(/[|\\{}()[\]^$+?.]/g, "\\$&");
|
|
33
|
+
}
|
|
34
|
+
export function matchesModelIdPattern(pattern, rawModelId) {
|
|
35
|
+
if (typeof pattern !== "string") {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
const matcher = new RegExp(`^${escapeRegex(pattern).replaceAll("*", ".*")}$`);
|
|
39
|
+
return matcher.test(rawModelId);
|
|
40
|
+
}
|
|
41
|
+
export function matchesAnyModelIdPattern(patterns, rawModelId) {
|
|
42
|
+
return normalizeList(patterns).some((pattern) => matchesModelIdPattern(pattern, rawModelId));
|
|
43
|
+
}
|
|
44
|
+
export function normalizePriority(value) {
|
|
45
|
+
return Number.isInteger(value) ? value : 0;
|
|
46
|
+
}
|
|
47
|
+
export function normalizeDomain(urlOrDomain) {
|
|
48
|
+
if (!urlOrDomain || typeof urlOrDomain !== "string") {
|
|
49
|
+
return "github.com";
|
|
50
|
+
}
|
|
51
|
+
const value = urlOrDomain.trim();
|
|
52
|
+
if (!value) {
|
|
53
|
+
return "github.com";
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
const parsed = value.includes("://")
|
|
57
|
+
? new URL(value)
|
|
58
|
+
: new URL(`https://${value}`);
|
|
59
|
+
return parsed.hostname.toLowerCase();
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return value
|
|
63
|
+
.replace(/^https?:\/\//i, "")
|
|
64
|
+
.replace(/\/.*$/, "")
|
|
65
|
+
.replace(/\/+$/, "")
|
|
66
|
+
.toLowerCase();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
export function normalizeIdSource(value) {
|
|
70
|
+
return String(value ?? "")
|
|
71
|
+
.toLowerCase()
|
|
72
|
+
.replace(/[^a-z0-9-]/g, "-")
|
|
73
|
+
.replace(/-+/g, "-")
|
|
74
|
+
.replace(/^-+|-+$/g, "");
|
|
75
|
+
}
|
|
76
|
+
export function preserveStringOrDefault(value, fallback) {
|
|
77
|
+
if (typeof value === "string" && value.trim()) {
|
|
78
|
+
return value;
|
|
79
|
+
}
|
|
80
|
+
return fallback;
|
|
81
|
+
}
|
|
82
|
+
export function zeroCost() {
|
|
83
|
+
return {
|
|
84
|
+
input: 0,
|
|
85
|
+
output: 0,
|
|
86
|
+
cache: {
|
|
87
|
+
read: 0,
|
|
88
|
+
write: 0,
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
export function isLiveChatModel(model) {
|
|
93
|
+
if (!isRecord(model)) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
const capabilities = model.capabilities;
|
|
97
|
+
return isRecord(capabilities) && capabilities.type === "chat";
|
|
98
|
+
}
|
|
99
|
+
export function isPickerModel(model) {
|
|
100
|
+
if (!isLiveChatModel(model) || !isRecord(model)) {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
return model.model_picker_enabled !== false;
|
|
104
|
+
}
|
|
105
|
+
export function getReleaseDate(id, version, fallback = "") {
|
|
106
|
+
if (typeof version === "string" && version.startsWith(`${id}-`)) {
|
|
107
|
+
return version.slice(id.length + 1);
|
|
108
|
+
}
|
|
109
|
+
return typeof version === "string" ? version : fallback;
|
|
110
|
+
}
|
|
111
|
+
export function getHeader(headers, name) {
|
|
112
|
+
if (!headers)
|
|
113
|
+
return undefined;
|
|
114
|
+
const target = name.toLowerCase();
|
|
115
|
+
if (typeof Headers !== "undefined" && headers instanceof Headers) {
|
|
116
|
+
return headers.get(name) ?? headers.get(target) ?? undefined;
|
|
117
|
+
}
|
|
118
|
+
if (Array.isArray(headers)) {
|
|
119
|
+
const found = headers.find(([key]) => String(key).toLowerCase() === target);
|
|
120
|
+
return found?.[1];
|
|
121
|
+
}
|
|
122
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
123
|
+
if (key.toLowerCase() === target) {
|
|
124
|
+
return value;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return undefined;
|
|
128
|
+
}
|
|
129
|
+
export function getConversationMetadata(init) {
|
|
130
|
+
try {
|
|
131
|
+
const body = parseBody(init?.body);
|
|
132
|
+
if (isRecord(body) && Array.isArray(body.messages)) {
|
|
133
|
+
const messages = body.messages;
|
|
134
|
+
const lastMessage = messages[messages.length - 1];
|
|
135
|
+
const role = lastMessage?.role;
|
|
136
|
+
return {
|
|
137
|
+
isVision: messages.some((message) => Array.isArray(message?.content)
|
|
138
|
+
&& message.content.some((part) => part?.type === "image_url")),
|
|
139
|
+
isAgent: role === "tool" || role === "assistant",
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
if (isRecord(body) && Array.isArray(body.input)) {
|
|
143
|
+
const inputList = body.input;
|
|
144
|
+
const lastInput = inputList[inputList.length - 1];
|
|
145
|
+
const isAssistant = lastInput?.role === "assistant";
|
|
146
|
+
const hasAgentType = lastInput?.type
|
|
147
|
+
? RESPONSES_API_ALTERNATE_INPUT_TYPES.includes(lastInput.type)
|
|
148
|
+
: false;
|
|
149
|
+
return {
|
|
150
|
+
isVision: Array.isArray(lastInput?.content)
|
|
151
|
+
&& lastInput.content.some((part) => part?.type === "input_image"),
|
|
152
|
+
isAgent: isAssistant || hasAgentType,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
// intentional: return safe defaults on any parse/inspection error
|
|
158
|
+
}
|
|
159
|
+
return {
|
|
160
|
+
isVision: false,
|
|
161
|
+
isAgent: false,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
export function getRequestedRawModelId(init) {
|
|
165
|
+
try {
|
|
166
|
+
const body = parseBody(init?.body);
|
|
167
|
+
if (!isRecord(body) || typeof body.model !== "string") {
|
|
168
|
+
return undefined;
|
|
169
|
+
}
|
|
170
|
+
return body.model.trim() ? body.model.trim() : undefined;
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
return undefined;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
export function applyBaseURLToRequestInput(input, baseURL) {
|
|
177
|
+
if (!baseURL) {
|
|
178
|
+
return input;
|
|
179
|
+
}
|
|
180
|
+
try {
|
|
181
|
+
const original = typeof input === "string" || input instanceof URL
|
|
182
|
+
? new URL(String(input))
|
|
183
|
+
: typeof Request !== "undefined" && input instanceof Request
|
|
184
|
+
? new URL(input.url)
|
|
185
|
+
: null;
|
|
186
|
+
if (!original) {
|
|
187
|
+
return input;
|
|
188
|
+
}
|
|
189
|
+
const nextBase = new URL(baseURL);
|
|
190
|
+
const nextUrl = new URL(`${original.pathname}${original.search}${original.hash}`, nextBase);
|
|
191
|
+
if (typeof Request !== "undefined" && input instanceof Request) {
|
|
192
|
+
return new Request(nextUrl.toString(), input);
|
|
193
|
+
}
|
|
194
|
+
return nextUrl.toString();
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
return input;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
export function isValidBaseURL(value) {
|
|
201
|
+
if (typeof value !== "string" || !value.trim()) {
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
try {
|
|
205
|
+
new URL(value);
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
export function resolveClaudeThinkingBudget(model, variant) {
|
|
213
|
+
if (!model?.id?.includes("claude"))
|
|
214
|
+
return undefined;
|
|
215
|
+
return variant === "thinking" ? 16000 : undefined;
|
|
216
|
+
}
|