@koreanhole/opencodex 2.95.10 → 2.97.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/AGENTS_INSTALL.md +33 -6
- package/README.md +100 -31
- package/package.json +6 -2
- package/src/adapters/cli-agent/acp-client.ts +545 -0
- package/src/adapters/cli-agent/cline/acp.ts +15 -279
- package/src/adapters/cli-agent/cline/adapter.ts +3 -3
- package/src/adapters/cli-agent/cline/live-models.ts +6 -5
- package/src/adapters/cli-agent/cline/stream.ts +6 -37
- package/src/adapters/cli-agent/gemini/acp.ts +656 -0
- package/src/adapters/cli-agent/gemini/adapter.ts +253 -0
- package/src/adapters/cli-agent/gemini/binary.ts +23 -0
- package/src/adapters/cli-agent/gemini/live-models.ts +154 -0
- package/src/adapters/cli-agent/gemini/model-metadata.ts +291 -0
- package/src/adapters/cli-agent/mcp-server.ts +29 -4
- package/src/adapters/cli-agent/tool-intent.ts +71 -0
- package/src/cli/index.ts +81 -19
- package/src/config.ts +50 -9
- package/src/index.ts +1 -0
- package/src/lib/codex-catalog.ts +318 -0
- package/src/lib/redact.ts +4 -1
- package/src/server/index.ts +46 -13
- package/src/server/messages.ts +9 -8
- package/src/server/responses.ts +126 -12
- package/src/types.ts +14 -0
package/src/server/responses.ts
CHANGED
|
@@ -6,8 +6,18 @@ import type {
|
|
|
6
6
|
OcxTool,
|
|
7
7
|
OcxToolChoice,
|
|
8
8
|
OcxUsage,
|
|
9
|
+
OcxProviderModel,
|
|
9
10
|
} from "../types";
|
|
10
11
|
import { runClineTurn, type ClineTurnDeps } from "../adapters/cli-agent/cline/adapter";
|
|
12
|
+
import { runGeminiTurn, type GeminiTurnDeps } from "../adapters/cli-agent/gemini/adapter";
|
|
13
|
+
import { CLINE_PROVIDER_ID, GEMINI_PROVIDER_ID, type ProviderId } from "../config";
|
|
14
|
+
|
|
15
|
+
export interface ProviderTurnDeps {
|
|
16
|
+
cline?: ClineTurnDeps;
|
|
17
|
+
gemini?: GeminiTurnDeps;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
type TurnDepsInput = ClineTurnDeps | ProviderTurnDeps;
|
|
11
21
|
|
|
12
22
|
export interface DeclaredTool {
|
|
13
23
|
tool: OcxTool;
|
|
@@ -34,7 +44,7 @@ export class UnsupportedMediaError extends RequestValidationError {
|
|
|
34
44
|
readonly code = "unsupported_input_modality";
|
|
35
45
|
|
|
36
46
|
constructor() {
|
|
37
|
-
super("
|
|
47
|
+
super("The selected CLI provider is text-only; image, video, and audio input are not supported.");
|
|
38
48
|
this.name = "UnsupportedMediaError";
|
|
39
49
|
}
|
|
40
50
|
}
|
|
@@ -266,15 +276,119 @@ export function resolveClineModel(requested: string, known: Iterable<string>): s
|
|
|
266
276
|
return decodeRoutedModelId(suffix, known);
|
|
267
277
|
}
|
|
268
278
|
|
|
269
|
-
export
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
279
|
+
export type ProviderModelEntry = string | OcxProviderModel;
|
|
280
|
+
export type ProviderModels = Partial<Record<ProviderId, readonly ProviderModelEntry[]>>;
|
|
281
|
+
|
|
282
|
+
export interface RoutedModel {
|
|
283
|
+
providerId: ProviderId;
|
|
284
|
+
modelId: string;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
export function resolveRoutedModel(
|
|
288
|
+
requested: string,
|
|
289
|
+
known: ProviderModels,
|
|
290
|
+
defaultProvider: ProviderId = CLINE_PROVIDER_ID,
|
|
291
|
+
): RoutedModel {
|
|
292
|
+
if (requested === "default") return { providerId: defaultProvider, modelId: "default" };
|
|
293
|
+
const providerId = requested.startsWith(`${CLINE_PROVIDER_ID}/`)
|
|
294
|
+
? CLINE_PROVIDER_ID
|
|
295
|
+
: requested.startsWith(`${GEMINI_PROVIDER_ID}/`)
|
|
296
|
+
? GEMINI_PROVIDER_ID
|
|
297
|
+
: defaultProvider;
|
|
298
|
+
const prefix = `${providerId}/`;
|
|
299
|
+
const suffix = requested.startsWith(prefix) ? requested.slice(prefix.length) : requested;
|
|
300
|
+
return {
|
|
301
|
+
providerId,
|
|
302
|
+
modelId: suffix === "default"
|
|
303
|
+
? "default"
|
|
304
|
+
: decodeRoutedModelId(suffix, (known[providerId] ?? []).map(modelIdOf)),
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function modelIdOf(model: ProviderModelEntry): string {
|
|
309
|
+
return typeof model === "string" ? model : model.id;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
const PROVIDER_LABELS: Record<ProviderId, string> = {
|
|
313
|
+
[CLINE_PROVIDER_ID]: "Cline CLI",
|
|
314
|
+
[GEMINI_PROVIDER_ID]: "Gemini CLI",
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
export function modelList(known: string[] | ProviderModels): Array<Record<string, unknown>> {
|
|
318
|
+
if (Array.isArray(known)) {
|
|
319
|
+
const ids = ["default", ...known.filter(id => id !== "default")];
|
|
320
|
+
return [...new Set(ids)].map(id => ({
|
|
321
|
+
id: `${CLINE_PROVIDER_ID}/${encodeRoutedModelId(id)}`,
|
|
322
|
+
object: "model",
|
|
323
|
+
created: 0,
|
|
324
|
+
owned_by: CLINE_PROVIDER_ID,
|
|
325
|
+
display_name: id === "default" ? "Cline default" : id,
|
|
326
|
+
}));
|
|
327
|
+
}
|
|
328
|
+
const rows: Array<Record<string, unknown>> = [{
|
|
329
|
+
id: "default",
|
|
273
330
|
object: "model",
|
|
274
331
|
created: 0,
|
|
275
|
-
owned_by: "
|
|
276
|
-
display_name:
|
|
277
|
-
}
|
|
332
|
+
owned_by: "opencodex",
|
|
333
|
+
display_name: "Configured default provider",
|
|
334
|
+
}];
|
|
335
|
+
for (const providerId of [CLINE_PROVIDER_ID, GEMINI_PROVIDER_ID] as const) {
|
|
336
|
+
const entries = ["default", ...(known[providerId] ?? []).filter(entry => modelIdOf(entry) !== "default")];
|
|
337
|
+
const seen = new Set<string>();
|
|
338
|
+
for (const entry of entries) {
|
|
339
|
+
const id = modelIdOf(entry);
|
|
340
|
+
if (seen.has(id)) continue;
|
|
341
|
+
seen.add(id);
|
|
342
|
+
const info = typeof entry === "string" ? { id: entry } as OcxProviderModel : entry;
|
|
343
|
+
const reasoning = info.supportedReasoningLevels ?? [];
|
|
344
|
+
rows.push({
|
|
345
|
+
id: `${providerId}/${encodeRoutedModelId(id)}`,
|
|
346
|
+
object: "model",
|
|
347
|
+
created: 0,
|
|
348
|
+
owned_by: providerId,
|
|
349
|
+
display_name: info.name ?? (id === "default" ? `${PROVIDER_LABELS[providerId]} default` : id),
|
|
350
|
+
...(info.description ? { description: info.description } : {}),
|
|
351
|
+
...(reasoning.length > 0
|
|
352
|
+
? {
|
|
353
|
+
supported_reasoning_levels: reasoning.map(level => ({
|
|
354
|
+
effort: level.effort,
|
|
355
|
+
description: level.description,
|
|
356
|
+
})),
|
|
357
|
+
default_reasoning_level: info.defaultReasoningLevel ?? reasoning[0]!.effort,
|
|
358
|
+
}
|
|
359
|
+
: { supported_reasoning_levels: [] }),
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
return rows;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
function providerDeps(deps: TurnDepsInput): ProviderTurnDeps {
|
|
367
|
+
if ("cline" in deps || "gemini" in deps) return deps as ProviderTurnDeps;
|
|
368
|
+
return { cline: deps as ClineTurnDeps };
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
function providerModels(known: string[] | ProviderModels, defaultProvider: ProviderId): ProviderModels {
|
|
372
|
+
return Array.isArray(known) ? { [defaultProvider]: known } : known;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
export function routedTurn(
|
|
376
|
+
parsed: OcxParsedRequest,
|
|
377
|
+
requestedModel: string,
|
|
378
|
+
incoming: IncomingMeta,
|
|
379
|
+
known: string[] | ProviderModels,
|
|
380
|
+
deps: TurnDepsInput,
|
|
381
|
+
defaultProvider: ProviderId = CLINE_PROVIDER_ID,
|
|
382
|
+
): { providerId: ProviderId; run: (emit: (event: AdapterEvent) => void) => Promise<void> } {
|
|
383
|
+
const route = resolveRoutedModel(requestedModel, providerModels(known, defaultProvider), defaultProvider);
|
|
384
|
+
parsed.modelId = route.modelId;
|
|
385
|
+
const resolved = providerDeps(deps);
|
|
386
|
+
return {
|
|
387
|
+
providerId: route.providerId,
|
|
388
|
+
run: route.providerId === GEMINI_PROVIDER_ID
|
|
389
|
+
? emit => runGeminiTurn(parsed, incoming, emit, resolved.gemini)
|
|
390
|
+
: emit => runClineTurn(parsed, incoming, emit, resolved.cline),
|
|
391
|
+
};
|
|
278
392
|
}
|
|
279
393
|
|
|
280
394
|
function usage(value: OcxUsage | undefined): Record<string, unknown> | null {
|
|
@@ -608,12 +722,12 @@ export function streamResponsesResult(
|
|
|
608
722
|
export async function handleResponses(
|
|
609
723
|
body: unknown,
|
|
610
724
|
incoming: IncomingMeta,
|
|
611
|
-
knownModels: string[],
|
|
612
|
-
deps:
|
|
725
|
+
knownModels: string[] | ProviderModels,
|
|
726
|
+
deps: TurnDepsInput = {},
|
|
727
|
+
defaultProvider: ProviderId = CLINE_PROVIDER_ID,
|
|
613
728
|
): Promise<Response> {
|
|
614
729
|
const parsed = parseResponsesRequest(body);
|
|
615
|
-
|
|
616
|
-
const run = (emit: (event: AdapterEvent) => void) => runClineTurn(parsed.parsed, incoming, emit, deps);
|
|
730
|
+
const { run } = routedTurn(parsed.parsed, parsed.requestedModel, incoming, knownModels, deps, defaultProvider);
|
|
617
731
|
if (parsed.parsed.stream) {
|
|
618
732
|
return new Response(streamResponsesResult(parsed, run, incoming.abortSignal), {
|
|
619
733
|
headers: { "content-type": "text/event-stream; charset=utf-8", "cache-control": "no-cache" },
|
package/src/types.ts
CHANGED
|
@@ -89,12 +89,26 @@ export interface OcxParsedRequest {
|
|
|
89
89
|
export interface OcxUsage {
|
|
90
90
|
inputTokens: number;
|
|
91
91
|
outputTokens: number;
|
|
92
|
+
modelId?: string;
|
|
92
93
|
totalTokens?: number;
|
|
93
94
|
cachedInputTokens?: number;
|
|
94
95
|
cacheReadInputTokens?: number;
|
|
95
96
|
cacheCreationInputTokens?: number;
|
|
96
97
|
}
|
|
97
98
|
|
|
99
|
+
export interface OcxReasoningLevel {
|
|
100
|
+
effort: string;
|
|
101
|
+
description: string;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export interface OcxProviderModel {
|
|
105
|
+
id: string;
|
|
106
|
+
name?: string;
|
|
107
|
+
description?: string;
|
|
108
|
+
supportedReasoningLevels?: readonly OcxReasoningLevel[];
|
|
109
|
+
defaultReasoningLevel?: string;
|
|
110
|
+
}
|
|
111
|
+
|
|
98
112
|
export type AdapterEvent =
|
|
99
113
|
| { type: "heartbeat" }
|
|
100
114
|
| { type: "text_delta"; text: string }
|