@vymalo/opencode-oauth2 0.12.0 → 0.14.0
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/dist/cache.d.ts +6 -6
- package/dist/cache.js +100 -104
- package/dist/cache.js.map +1 -1
- package/dist/config.d.ts +107 -107
- package/dist/config.js +173 -182
- package/dist/config.js.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lib.js +1 -0
- package/dist/lib.js.map +1 -1
- package/dist/logging.d.ts +6 -6
- package/dist/logging.js +57 -56
- package/dist/logging.js.map +1 -1
- package/dist/model-discovery.d.ts +3 -3
- package/dist/model-discovery.js +61 -66
- package/dist/model-discovery.js.map +1 -1
- package/dist/model-normalization.js +84 -73
- package/dist/model-normalization.js.map +1 -1
- package/dist/oauth/browser.js +29 -25
- package/dist/oauth/browser.js.map +1 -1
- package/dist/oauth/client.d.ts +46 -46
- package/dist/oauth/client.js +411 -430
- package/dist/oauth/client.js.map +1 -1
- package/dist/oauth/device-code.d.ts +23 -23
- package/dist/oauth/device-code.js +225 -235
- package/dist/oauth/device-code.js.map +1 -1
- package/dist/oauth/discovery.d.ts +5 -5
- package/dist/oauth/discovery.js +34 -34
- package/dist/oauth/discovery.js.map +1 -1
- package/dist/oauth/http-utils.d.ts +27 -27
- package/dist/oauth/http-utils.js +96 -107
- package/dist/oauth/http-utils.js.map +1 -1
- package/dist/oauth/local-callback.d.ts +5 -5
- package/dist/oauth/local-callback.js +76 -74
- package/dist/oauth/local-callback.js.map +1 -1
- package/dist/oauth/pkce.d.ts +2 -2
- package/dist/oauth/pkce.js +9 -5
- package/dist/oauth/pkce.js.map +1 -1
- package/dist/oauth/subject-token.d.ts +15 -15
- package/dist/oauth/subject-token.js +68 -73
- package/dist/oauth/subject-token.js.map +1 -1
- package/dist/opencode.d.ts +15 -15
- package/dist/opencode.js +477 -497
- package/dist/opencode.js.map +1 -1
- package/dist/plugin.d.ts +39 -39
- package/dist/plugin.js +270 -277
- package/dist/plugin.js.map +1 -1
- package/dist/responses-repair.d.ts +12 -35
- package/dist/responses-repair.js +119 -125
- package/dist/responses-repair.js.map +1 -1
- package/dist/scheduler.d.ts +5 -5
- package/dist/scheduler.js +43 -45
- package/dist/scheduler.js.map +1 -1
- package/dist/types.d.ts +25 -25
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -1
- package/package.json +3 -3
|
@@ -1,41 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
* Responses streaming events **without** the `output_index` / `content_index`
|
|
6
|
-
* fields that the canonical OpenAI Responses API always includes. The AI SDK's
|
|
7
|
-
* `@ai-sdk/openai` responses parser (and, downstream, OpenCode) key each
|
|
8
|
-
* message part by those indices, so when they are absent the text part is never
|
|
9
|
-
* associated with its deltas and the host fails with
|
|
10
|
-
* `text part <msg_id> not found` — even though the request, auth, routing, and
|
|
11
|
-
* the gateway's final (non-streamed) object are all fine.
|
|
12
|
-
*
|
|
13
|
-
* This module injects the missing indices on the fly:
|
|
14
|
-
* - `output_index` is assigned per item in the order their
|
|
15
|
-
* `response.output_item.added` events arrive (reasoning → 0, message → 1, …).
|
|
16
|
-
* - `content_index` is set to `0` on the single content / text / reasoning part
|
|
17
|
-
* of each item (these gateways only ever emit one).
|
|
18
|
-
*
|
|
19
|
-
* Existing index fields are never overwritten, so the transform is a safe no-op
|
|
20
|
-
* against a conformant gateway. Only the oauth2 plugin's `responseApi` path
|
|
21
|
-
* installs it (as a wrapping `options.fetch`), and only for requests to the
|
|
22
|
-
* `/responses` route with a `text/event-stream` body.
|
|
23
|
-
*/
|
|
24
|
-
/**
|
|
25
|
-
* Pure text form — repair a complete SSE document. Exposed for testing; the
|
|
26
|
-
* runtime path uses {@link makeResponsesRepairStream}.
|
|
27
|
-
*/
|
|
2
|
+
* Pure text form — repair a complete SSE document. Exposed for testing; the
|
|
3
|
+
* runtime path uses {@link makeResponsesRepairStream}.
|
|
4
|
+
*/
|
|
28
5
|
export declare function repairResponsesSseText(input: string): string;
|
|
29
6
|
/**
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
7
|
+
* Streaming form — a `TransformStream` that repairs SSE byte chunks, buffering
|
|
8
|
+
* across chunk boundaries so a split mid-event is handled correctly.
|
|
9
|
+
*/
|
|
33
10
|
export declare function makeResponsesRepairStream(): TransformStream<Uint8Array, Uint8Array>;
|
|
34
11
|
/**
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
12
|
+
* Wrap a `fetch` so Responses-API SSE responses are run through the index
|
|
13
|
+
* repair before the AI SDK parses them. Non-`/responses` requests and
|
|
14
|
+
* non-streaming responses pass through unchanged. Composes with a `delegate`
|
|
15
|
+
* (a pre-existing `options.fetch`) so stacking with other fetch-wrapping
|
|
16
|
+
* plugins works regardless of order.
|
|
17
|
+
*/
|
|
41
18
|
export declare function createResponsesRepairFetch(delegate?: typeof fetch): typeof fetch;
|
package/dist/responses-repair.js
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
2
|
+
* Repair non-conformant OpenAI **Responses API** SSE streams.
|
|
3
|
+
*
|
|
4
|
+
* Some gateways (observed: Envoy AI Gateway fronting a local model server) emit
|
|
5
|
+
* Responses streaming events **without** the `output_index` / `content_index`
|
|
6
|
+
* fields that the canonical OpenAI Responses API always includes. The AI SDK's
|
|
7
|
+
* `@ai-sdk/openai` responses parser (and, downstream, OpenCode) key each
|
|
8
|
+
* message part by those indices, so when they are absent the text part is never
|
|
9
|
+
* associated with its deltas and the host fails with
|
|
10
|
+
* `text part <msg_id> not found` — even though the request, auth, routing, and
|
|
11
|
+
* the gateway's final (non-streamed) object are all fine.
|
|
12
|
+
*
|
|
13
|
+
* This module injects the missing indices on the fly:
|
|
14
|
+
* - `output_index` is assigned per item in the order their
|
|
15
|
+
* `response.output_item.added` events arrive (reasoning → 0, message → 1, …).
|
|
16
|
+
* - `content_index` is set to `0` on the single content / text / reasoning part
|
|
17
|
+
* of each item (these gateways only ever emit one).
|
|
18
|
+
*
|
|
19
|
+
* Existing index fields are never overwritten, so the transform is a safe no-op
|
|
20
|
+
* against a conformant gateway. Only the oauth2 plugin's `responseApi` path
|
|
21
|
+
* installs it (as a wrapping `options.fetch`), and only for requests to the
|
|
22
|
+
* `/responses` route with a `text/event-stream` body.
|
|
23
|
+
*/
|
|
24
24
|
const CONTENT_EVENT = /content_part|output_text|reasoning_text/;
|
|
25
25
|
// One SSE frame: an optional `event:` line then a `data:` line carrying JSON.
|
|
26
26
|
// Tolerant of CRLF (`\r\n`) as well as LF line endings — both are valid SSE.
|
|
@@ -28,120 +28,114 @@ const BLOCK_RE = /^(?:event:\s*(\S+)[^\S\r\n]*[\r\n]+)?data:\s*(\{[\s\S]*\})\s*$
|
|
|
28
28
|
// Frame boundary is a blank line: `\n\n` or `\r\n\r\n`.
|
|
29
29
|
const FRAME_BOUNDARY = /\r\n\r\n|\n\n/;
|
|
30
30
|
/**
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
* Stateful per-stream renderer. Tracks the `item_id → output_index` mapping
|
|
32
|
+
* across blocks (the map must persist for the whole stream, so each stream gets
|
|
33
|
+
* its own injector instance).
|
|
34
|
+
*/
|
|
35
35
|
function createIndexInjector() {
|
|
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
|
-
return `${eventLine}data: ${JSON.stringify(event)}\n\n`;
|
|
66
|
-
};
|
|
36
|
+
const outputIndex = new Map();
|
|
37
|
+
let nextIndex = 0;
|
|
38
|
+
return (block) => {
|
|
39
|
+
const match = block.match(BLOCK_RE);
|
|
40
|
+
if (!match) {
|
|
41
|
+
// Comments, `data: [DONE]`, keep-alives — pass through untouched.
|
|
42
|
+
return block;
|
|
43
|
+
}
|
|
44
|
+
let event;
|
|
45
|
+
try {
|
|
46
|
+
event = JSON.parse(match[2]);
|
|
47
|
+
} catch {
|
|
48
|
+
return block;
|
|
49
|
+
}
|
|
50
|
+
const type = typeof event.type === "string" ? event.type : "";
|
|
51
|
+
const item = event.item;
|
|
52
|
+
const itemId = (item && typeof item.id === "string" ? item.id : undefined) ?? (typeof event.item_id === "string" ? event.item_id : undefined);
|
|
53
|
+
if (type === "response.output_item.added" && itemId && !outputIndex.has(itemId)) {
|
|
54
|
+
outputIndex.set(itemId, nextIndex++);
|
|
55
|
+
}
|
|
56
|
+
if (itemId && outputIndex.has(itemId) && event.output_index === undefined) {
|
|
57
|
+
event.output_index = outputIndex.get(itemId);
|
|
58
|
+
}
|
|
59
|
+
if (CONTENT_EVENT.test(type) && event.content_index === undefined) {
|
|
60
|
+
event.content_index = 0;
|
|
61
|
+
}
|
|
62
|
+
const eventLine = match[1] ? `event: ${match[1]}\n` : "";
|
|
63
|
+
return `${eventLine}data: ${JSON.stringify(event)}\n\n`;
|
|
64
|
+
};
|
|
67
65
|
}
|
|
68
66
|
/**
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
67
|
+
* Pure text form — repair a complete SSE document. Exposed for testing; the
|
|
68
|
+
* runtime path uses {@link makeResponsesRepairStream}.
|
|
69
|
+
*/
|
|
72
70
|
export function repairResponsesSseText(input) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
.split(/(?<=\r\n\r\n|\n\n)/)
|
|
78
|
-
.map(render)
|
|
79
|
-
.join("");
|
|
71
|
+
const render = createIndexInjector();
|
|
72
|
+
// Split after each blank-line boundary (LF or CRLF), keeping it attached to
|
|
73
|
+
// its frame.
|
|
74
|
+
return input.split(/(?<=\r\n\r\n|\n\n)/).map(render).join("");
|
|
80
75
|
}
|
|
81
76
|
/**
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
77
|
+
* Streaming form — a `TransformStream` that repairs SSE byte chunks, buffering
|
|
78
|
+
* across chunk boundaries so a split mid-event is handled correctly.
|
|
79
|
+
*/
|
|
85
80
|
export function makeResponsesRepairStream() {
|
|
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
|
-
|
|
81
|
+
const render = createIndexInjector();
|
|
82
|
+
const decoder = new TextDecoder();
|
|
83
|
+
const encoder = new TextEncoder();
|
|
84
|
+
let buffer = "";
|
|
85
|
+
return new TransformStream({
|
|
86
|
+
transform(chunk, controller) {
|
|
87
|
+
buffer += decoder.decode(chunk, { stream: true });
|
|
88
|
+
let out = "";
|
|
89
|
+
let match;
|
|
90
|
+
while ((match = FRAME_BOUNDARY.exec(buffer)) !== null) {
|
|
91
|
+
const end = match.index + match[0].length;
|
|
92
|
+
out += render(buffer.slice(0, end));
|
|
93
|
+
buffer = buffer.slice(end);
|
|
94
|
+
}
|
|
95
|
+
if (out) {
|
|
96
|
+
controller.enqueue(encoder.encode(out));
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
flush(controller) {
|
|
100
|
+
buffer += decoder.decode();
|
|
101
|
+
if (buffer) {
|
|
102
|
+
controller.enqueue(encoder.encode(render(buffer)));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
});
|
|
111
106
|
}
|
|
112
107
|
function urlOf(input) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
108
|
+
if (typeof input === "string") {
|
|
109
|
+
return input;
|
|
110
|
+
}
|
|
111
|
+
if (input instanceof URL) {
|
|
112
|
+
return input.href;
|
|
113
|
+
}
|
|
114
|
+
return input.url;
|
|
120
115
|
}
|
|
121
116
|
/**
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
117
|
+
* Wrap a `fetch` so Responses-API SSE responses are run through the index
|
|
118
|
+
* repair before the AI SDK parses them. Non-`/responses` requests and
|
|
119
|
+
* non-streaming responses pass through unchanged. Composes with a `delegate`
|
|
120
|
+
* (a pre-existing `options.fetch`) so stacking with other fetch-wrapping
|
|
121
|
+
* plugins works regardless of order.
|
|
122
|
+
*/
|
|
128
123
|
export function createResponsesRepairFetch(delegate) {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
};
|
|
145
|
-
return repaired;
|
|
124
|
+
const base = delegate ?? globalThis.fetch;
|
|
125
|
+
const repaired = async (input, init) => {
|
|
126
|
+
const response = await base(input, init);
|
|
127
|
+
// HTTP media types are case-insensitive, so normalize before matching.
|
|
128
|
+
const contentType = (response.headers.get("content-type") ?? "").toLowerCase();
|
|
129
|
+
if (!response.body || !urlOf(input).includes("/responses") || !contentType.includes("text/event-stream")) {
|
|
130
|
+
return response;
|
|
131
|
+
}
|
|
132
|
+
return new Response(response.body.pipeThrough(makeResponsesRepairStream()), {
|
|
133
|
+
status: response.status,
|
|
134
|
+
statusText: response.statusText,
|
|
135
|
+
headers: response.headers
|
|
136
|
+
});
|
|
137
|
+
};
|
|
138
|
+
return repaired;
|
|
146
139
|
}
|
|
140
|
+
|
|
147
141
|
//# sourceMappingURL=responses-repair.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"
|
|
1
|
+
{"mappings":"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","names":[],"sources":["../src/responses-repair.ts"],"version":3,"file":"responses-repair.js","sourceRoot":""}
|
package/dist/scheduler.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { Logger } from "./logging.js";
|
|
2
2
|
export interface SchedulerHandle {
|
|
3
|
-
|
|
3
|
+
stop(): void;
|
|
4
4
|
}
|
|
5
5
|
export interface SchedulerOptions {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
intervalMs: number;
|
|
7
|
+
logger: Logger;
|
|
8
|
+
taskName: string;
|
|
9
|
+
run: () => Promise<void>;
|
|
10
10
|
}
|
|
11
11
|
export declare function startScheduler(options: SchedulerOptions): SchedulerHandle;
|
package/dist/scheduler.js
CHANGED
|
@@ -1,48 +1,46 @@
|
|
|
1
1
|
export function startScheduler(options) {
|
|
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
|
-
};
|
|
2
|
+
let failures = 0;
|
|
3
|
+
let stopped = false;
|
|
4
|
+
let timeout;
|
|
5
|
+
const schedule = (delayMs) => {
|
|
6
|
+
timeout = setTimeout(() => {
|
|
7
|
+
void tick();
|
|
8
|
+
}, delayMs);
|
|
9
|
+
};
|
|
10
|
+
const backoffDelay = () => {
|
|
11
|
+
const retryWindow = 15e3 * 2 ** Math.max(0, failures - 1);
|
|
12
|
+
return Math.min(options.intervalMs, retryWindow);
|
|
13
|
+
};
|
|
14
|
+
const tick = async () => {
|
|
15
|
+
if (stopped) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
options.logger.trace("oauth2_scheduler_tick", {
|
|
19
|
+
taskName: options.taskName,
|
|
20
|
+
failures
|
|
21
|
+
});
|
|
22
|
+
try {
|
|
23
|
+
await options.run();
|
|
24
|
+
failures = 0;
|
|
25
|
+
schedule(options.intervalMs);
|
|
26
|
+
} catch (error) {
|
|
27
|
+
failures += 1;
|
|
28
|
+
options.logger.warn("sync_schedule_retry", {
|
|
29
|
+
taskName: options.taskName,
|
|
30
|
+
failures,
|
|
31
|
+
delayMs: backoffDelay(),
|
|
32
|
+
error: error instanceof Error ? error.message : String(error)
|
|
33
|
+
});
|
|
34
|
+
schedule(backoffDelay());
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
schedule(options.intervalMs);
|
|
38
|
+
return { stop() {
|
|
39
|
+
stopped = true;
|
|
40
|
+
if (timeout) {
|
|
41
|
+
clearTimeout(timeout);
|
|
42
|
+
}
|
|
43
|
+
} };
|
|
47
44
|
}
|
|
45
|
+
|
|
48
46
|
//# sourceMappingURL=scheduler.js.map
|
package/dist/scheduler.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"
|
|
1
|
+
{"mappings":"AAaA,OAAO,SAAS,eAAe,SAA4C;CACzE,IAAI,WAAW;CACf,IAAI,UAAU;CACd,IAAI;CAEJ,MAAM,YAAY,YAA0B;EAC1C,UAAU,iBAAiB;GACzB,KAAK,KAAK;EACZ,GAAG,OAAO;CACZ;CAEA,MAAM,qBAA6B;EACjC,MAAM,cAAc,OAAS,KAAK,KAAK,IAAI,GAAG,WAAW,CAAC;EAC1D,OAAO,KAAK,IAAI,QAAQ,YAAY,WAAW;CACjD;CAEA,MAAM,OAAO,YAA2B;EACtC,IAAI,SAAS;GACX;EACF;EAEA,QAAQ,OAAO,MAAM,yBAAyB;GAC5C,UAAU,QAAQ;GAClB;EACF,CAAC;EAED,IAAI;GACF,MAAM,QAAQ,IAAI;GAClB,WAAW;GACX,SAAS,QAAQ,UAAU;EAC7B,SAAS,OAAO;GACd,YAAY;GACZ,QAAQ,OAAO,KAAK,uBAAuB;IACzC,UAAU,QAAQ;IAClB;IACA,SAAS,aAAa;IACtB,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;GAC9D,CAAC;GACD,SAAS,aAAa,CAAC;EACzB;CACF;CAEA,SAAS,QAAQ,UAAU;CAE3B,OAAO,EACL,OAAO;EACL,UAAU;EACV,IAAI,SAAS;GACX,aAAa,OAAO;EACtB;CACF,EACF;AACF","names":[],"sources":["../src/scheduler.ts"],"version":3,"file":"scheduler.js","sourceRoot":""}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
1
|
export interface RawModel {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
id: string;
|
|
3
|
+
[key: string]: unknown;
|
|
4
4
|
}
|
|
5
5
|
export interface NormalizedModel {
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
id: string;
|
|
7
|
+
displayName: string;
|
|
8
8
|
}
|
|
9
9
|
export interface ModelDiff {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
added: string[];
|
|
11
|
+
removed: string[];
|
|
12
|
+
renamed: Array<{
|
|
13
|
+
id: string;
|
|
14
|
+
before: string;
|
|
15
|
+
after: string;
|
|
16
|
+
}>;
|
|
17
17
|
}
|
|
18
18
|
export interface TokenSet {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
accessToken: string;
|
|
20
|
+
tokenType: string;
|
|
21
|
+
refreshToken?: string;
|
|
22
|
+
scope?: string;
|
|
23
|
+
expiresAt?: number;
|
|
24
24
|
}
|
|
25
25
|
export interface CachedServerState {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
26
|
+
serverId: string;
|
|
27
|
+
updatedAt: number;
|
|
28
|
+
lastSyncAt?: number;
|
|
29
|
+
models: NormalizedModel[];
|
|
30
|
+
rawModels: RawModel[];
|
|
31
|
+
token?: TokenSet;
|
|
32
32
|
}
|
|
33
33
|
export interface ServerSnapshot {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
serverId: string;
|
|
35
|
+
models: NormalizedModel[];
|
|
36
|
+
lastSyncAt?: number;
|
|
37
37
|
}
|
package/dist/types.js
CHANGED
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"
|
|
1
|
+
{"mappings":"","names":[],"sources":["../src/types.ts"],"version":3,"file":"types.js","sourceRoot":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vymalo/opencode-oauth2",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "OpenCode plugin for OAuth2/OIDC-secured, OpenAI-compatible model providers with periodic model sync.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "vymalo contributors",
|
|
@@ -52,11 +52,11 @@
|
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@ai-sdk/openai": "^2.0.106",
|
|
54
54
|
"ai": "^5.0.199",
|
|
55
|
-
"vite": "^8.
|
|
55
|
+
"vite": "^8.2.1",
|
|
56
56
|
"vitest": "^4.1.7"
|
|
57
57
|
},
|
|
58
58
|
"scripts": {
|
|
59
|
-
"build": "
|
|
59
|
+
"build": "node ../../scripts/build-package.mjs",
|
|
60
60
|
"lint": "biome lint .",
|
|
61
61
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
62
62
|
"test": "vitest run",
|