@vascend/talos 0.1.5 → 0.1.6
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/core/agent.d.ts +16 -3
- package/dist/core/agent.js +114 -34
- package/dist/core/background.d.ts +10 -3
- package/dist/core/background.js +55 -9
- package/dist/core/bootstrap.js +1 -0
- package/dist/core/compaction.js +1 -1
- package/dist/core/config-storage.d.ts +5 -0
- package/dist/core/config-storage.js +83 -0
- package/dist/core/config.d.ts +11 -2
- package/dist/core/config.js +24 -8
- package/dist/core/context-ledger.js +2 -1
- package/dist/core/context-policy.d.ts +1 -1
- package/dist/core/context-policy.js +10 -7
- package/dist/core/credentials.js +29 -30
- package/dist/core/effort.d.ts +1 -1
- package/dist/core/effort.js +5 -1
- package/dist/core/execution-guidance.d.ts +1 -1
- package/dist/core/execution-guidance.js +2 -0
- package/dist/core/file-coordination.d.ts +3 -0
- package/dist/core/file-coordination.js +28 -0
- package/dist/core/file-lease-store.d.ts +3 -0
- package/dist/core/file-lease-store.js +28 -12
- package/dist/core/fusion.d.ts +24 -0
- package/dist/core/fusion.js +80 -0
- package/dist/core/model-limits.d.ts +1 -0
- package/dist/core/model-limits.js +5 -1
- package/dist/core/permission-queue.js +15 -15
- package/dist/core/request-plan.js +4 -3
- package/dist/core/session-naming.js +4 -0
- package/dist/core/session.d.ts +4 -2
- package/dist/core/session.js +13 -4
- package/dist/core/settings.d.ts +2 -0
- package/dist/core/settings.js +5 -16
- package/dist/core/step-policy.d.ts +18 -0
- package/dist/core/step-policy.js +6 -0
- package/dist/core/tool-artifacts.d.ts +2 -0
- package/dist/core/tool-artifacts.js +21 -3
- package/dist/core/tool-result-index.js +29 -33
- package/dist/core/tool-result-store.js +6 -5
- package/dist/core/types.d.ts +10 -3
- package/dist/core/user-inbox.d.ts +9 -0
- package/dist/core/user-inbox.js +22 -3
- package/dist/core/user-input.js +1 -1
- package/dist/fusion/autopilot-fast.d.ts +59 -0
- package/dist/fusion/autopilot-fast.js +213 -0
- package/dist/fusion/autopilot.d.ts +75 -0
- package/dist/fusion/autopilot.js +308 -0
- package/dist/fusion/focus.d.ts +30 -0
- package/dist/fusion/focus.js +122 -0
- package/dist/fusion/gate.d.ts +30 -0
- package/dist/fusion/gate.js +95 -0
- package/dist/fusion/jev.d.ts +71 -0
- package/dist/fusion/jev.js +164 -0
- package/dist/fusion/receipts.d.ts +25 -0
- package/dist/fusion/receipts.js +34 -0
- package/dist/fusion/route.d.ts +25 -0
- package/dist/fusion/route.js +84 -0
- package/dist/fusion/run.d.ts +4 -0
- package/dist/fusion/run.js +186 -0
- package/dist/horizon/engine.d.ts +20 -1
- package/dist/horizon/engine.js +57 -0
- package/dist/horizon/index.d.ts +2 -2
- package/dist/horizon/index.js +1 -1
- package/dist/horizon/types.d.ts +29 -0
- package/dist/index.js +12 -0
- package/dist/providers/anthropic-oauth.d.ts +8 -3
- package/dist/providers/anthropic-oauth.js +13 -10
- package/dist/providers/anthropic.d.ts +9 -2
- package/dist/providers/anthropic.js +64 -21
- package/dist/providers/cli-models.d.ts +30 -0
- package/dist/providers/cli-models.js +194 -0
- package/dist/providers/model-effort.js +1 -1
- package/dist/providers/openai-oauth.d.ts +8 -3
- package/dist/providers/openai-oauth.js +9 -3
- package/dist/providers/openrouter-manual-fallback.d.ts +3 -1
- package/dist/providers/openrouter-manual-fallback.js +20 -20
- package/dist/providers/registry.js +3 -2
- package/dist/providers/retry.d.ts +3 -0
- package/dist/providers/retry.js +44 -1
- package/dist/remote/cifratura.d.ts +12 -0
- package/dist/remote/cifratura.js +66 -0
- package/dist/remote/index.d.ts +15 -0
- package/dist/remote/index.js +65 -0
- package/dist/remote/relay-client.d.ts +58 -0
- package/dist/remote/relay-client.js +315 -0
- package/dist/remote/sessione-remota.d.ts +60 -0
- package/dist/remote/sessione-remota.js +266 -0
- package/dist/sdk.d.ts +7 -2
- package/dist/sdk.js +3 -1
- package/dist/tools/builtin.js +41 -20
- package/dist/tools/capabilities.d.ts +3 -1
- package/dist/tools/capabilities.js +5 -2
- package/dist/tools/computer-use.js +2 -1
- package/dist/tools/pagination.js +1 -1
- package/dist/tools/program.js +34 -21
- package/dist/tools/team-tools.js +11 -6
- package/dist/tui/account-entry.js +14 -9
- package/dist/tui/agent-label.d.ts +2 -0
- package/dist/tui/agent-label.js +5 -0
- package/dist/tui/agent-sessions-screen.d.ts +12 -2
- package/dist/tui/agent-sessions-screen.js +62 -16
- package/dist/tui/agent-sessions.d.ts +14 -0
- package/dist/tui/agent-sessions.js +67 -6
- package/dist/tui/bottom-input.d.ts +46 -2
- package/dist/tui/bottom-input.js +358 -59
- package/dist/tui/branding.js +8 -4
- package/dist/tui/capability-lists.d.ts +10 -0
- package/dist/tui/capability-lists.js +41 -0
- package/dist/tui/command-output-registry.js +4 -0
- package/dist/tui/command-transcript.d.ts +1 -1
- package/dist/tui/command-transcript.js +17 -21
- package/dist/tui/commands.js +4 -1
- package/dist/tui/compaction-status.d.ts +7 -0
- package/dist/tui/compaction-status.js +39 -0
- package/dist/tui/config-recovery.d.ts +12 -0
- package/dist/tui/config-recovery.js +54 -0
- package/dist/tui/context-meter.d.ts +3 -0
- package/dist/tui/context-meter.js +35 -8
- package/dist/tui/diff.d.ts +9 -0
- package/dist/tui/diff.js +43 -19
- package/dist/tui/fusion-menu.d.ts +5 -0
- package/dist/tui/fusion-menu.js +89 -0
- package/dist/tui/i18n-catalog.js +312 -1
- package/dist/tui/live-command.d.ts +1 -0
- package/dist/tui/live-command.js +9 -0
- package/dist/tui/live-output.d.ts +1 -0
- package/dist/tui/live-output.js +11 -0
- package/dist/tui/model-details.js +13 -12
- package/dist/tui/model-picker.js +17 -7
- package/dist/tui/model-selection.js +19 -10
- package/dist/tui/native-scrollback.js +5 -0
- package/dist/tui/prompt-queue.d.ts +3 -0
- package/dist/tui/prompt-queue.js +19 -1
- package/dist/tui/provider-label.d.ts +2 -0
- package/dist/tui/provider-label.js +9 -0
- package/dist/tui/provider-menu.js +25 -24
- package/dist/tui/queue-screen.js +2 -1
- package/dist/tui/remote-command.d.ts +7 -0
- package/dist/tui/remote-command.js +79 -0
- package/dist/tui/repl.d.ts +8 -2
- package/dist/tui/repl.js +355 -311
- package/dist/tui/review-store.d.ts +1 -0
- package/dist/tui/review-store.js +28 -7
- package/dist/tui/review-team.js +4 -3
- package/dist/tui/runtime-error.d.ts +2 -0
- package/dist/tui/runtime-error.js +26 -0
- package/dist/tui/selector-mouse.d.ts +1 -0
- package/dist/tui/selector-mouse.js +1 -1
- package/dist/tui/selector.d.ts +7 -0
- package/dist/tui/selector.js +19 -2
- package/dist/tui/session-controls.d.ts +26 -0
- package/dist/tui/session-controls.js +65 -0
- package/dist/tui/session-naming-notice.js +5 -3
- package/dist/tui/session-replay.d.ts +1 -0
- package/dist/tui/session-replay.js +101 -32
- package/dist/tui/session-transcript-layout.d.ts +9 -0
- package/dist/tui/session-transcript-layout.js +41 -0
- package/dist/tui/startup.js +63 -33
- package/dist/tui/status-line.d.ts +1 -1
- package/dist/tui/status-line.js +20 -12
- package/dist/tui/talos-art-data.d.ts +1 -0
- package/dist/tui/talos-art-data.js +2 -0
- package/dist/tui/talos-art.d.ts +1 -0
- package/dist/tui/talos-art.js +9 -0
- package/dist/tui/task-labels.d.ts +1 -0
- package/dist/tui/task-labels.js +8 -0
- package/dist/tui/terminal-text.d.ts +2 -1
- package/dist/tui/terminal-text.js +28 -2
- package/dist/tui/theme.js +2 -2
- package/dist/tui/tool-presentation.d.ts +3 -0
- package/dist/tui/tool-presentation.js +98 -0
- package/dist/tui/tool-style.js +4 -0
- package/dist/tui/transcript-store.d.ts +25 -0
- package/dist/tui/transcript-store.js +151 -0
- package/dist/tui/usage-footer.d.ts +1 -1
- package/dist/tui/usage-footer.js +3 -1
- package/dist/tui/vascend-id.d.ts +49 -0
- package/dist/tui/vascend-id.js +321 -0
- package/dist/tui/web-login-screen.js +4 -3
- package/dist/tui/web-login.d.ts +7 -15
- package/dist/tui/web-login.js +38 -78
- package/dist/tui/worker-transcripts.d.ts +31 -0
- package/dist/tui/worker-transcripts.js +91 -0
- package/dist/vascend/candidate-collector.d.ts +6 -5
- package/dist/vascend/candidate-collector.js +44 -43
- package/dist/vascend/context-lint.js +32 -2
- package/dist/vascend/context-market-selection.js +12 -5
- package/dist/vascend/context-pack-render.js +10 -4
- package/dist/vascend/context-packet-mirrors.d.ts +8 -0
- package/dist/vascend/context-packet-mirrors.js +24 -0
- package/dist/vascend/context-plan-events.d.ts +4 -0
- package/dist/vascend/context-plan-events.js +44 -0
- package/dist/vascend/context-snapshot.js +4 -2
- package/dist/vascend/context-store-reader.d.ts +20 -0
- package/dist/vascend/context-store-reader.js +46 -0
- package/dist/vascend/file-lock.d.ts +1 -0
- package/dist/vascend/file-lock.js +26 -0
- package/dist/vascend/granular-kingdom.d.ts +1 -0
- package/dist/vascend/granular-kingdom.js +22 -15
- package/dist/vascend/kingdom-bus.d.ts +1 -0
- package/dist/vascend/kingdom-bus.js +3 -0
- package/dist/vascend/kingdom-channel.d.ts +2 -0
- package/dist/vascend/kingdom-channel.js +3 -0
- package/dist/vascend/kingdom-live.d.ts +32 -4
- package/dist/vascend/kingdom-live.js +149 -13
- package/dist/vascend/kingdom-run.d.ts +5 -1
- package/dist/vascend/kingdom-run.js +6 -2
- package/dist/vascend/kingdom.d.ts +3 -0
- package/dist/vascend/kingdom.js +20 -13
- package/dist/vascend/memory-packet.d.ts +2 -1
- package/dist/vascend/memory-packet.js +31 -44
- package/dist/vascend/plan-store.d.ts +3 -1
- package/dist/vascend/plan-store.js +6 -4
- package/dist/vascend/room-memory.d.ts +10 -1
- package/dist/vascend/room-memory.js +42 -2
- package/dist/vascend/runtime.d.ts +3 -11
- package/dist/vascend/runtime.js +11 -123
- package/dist/vascend/session-search.js +2 -0
- package/dist/vascend/team-session.js +3 -2
- package/dist/vascend/vision.d.ts +3 -1
- package/dist/vascend/vision.js +6 -4
- package/dist/vascend/worker-session.d.ts +20 -0
- package/dist/vascend/worker-session.js +83 -0
- package/package.json +1 -1
|
@@ -11,8 +11,15 @@ interface ApiMessage {
|
|
|
11
11
|
}
|
|
12
12
|
export declare function toApiMessages(req: CompletionRequest): unknown[];
|
|
13
13
|
export declare function normalizeToolPairing(messages: ApiMessage[]): ApiMessage[];
|
|
14
|
-
export
|
|
15
|
-
export declare function
|
|
14
|
+
export type CacheTtl = "5m" | "1h";
|
|
15
|
+
export declare function claudeCacheTtl(env: NodeJS.ProcessEnv): CacheTtl;
|
|
16
|
+
export declare function supportsConversationSystem(model: string): boolean;
|
|
17
|
+
export declare function withSystemCache(system: string, turnContext?: string, ttl?: CacheTtl): unknown[];
|
|
18
|
+
export declare function applyMessageCache(messages: unknown[], ttl?: CacheTtl): unknown[];
|
|
19
|
+
export declare function claudePrompt(req: CompletionRequest, ttl?: CacheTtl): {
|
|
20
|
+
system: unknown[];
|
|
21
|
+
messages: unknown[];
|
|
22
|
+
};
|
|
16
23
|
export declare const CONTEXT_1M_BETA = "context-1m-2025-08-07";
|
|
17
24
|
export declare function wants1m(model: string, env: NodeJS.ProcessEnv): boolean;
|
|
18
25
|
export declare class AnthropicProvider implements Provider {
|
|
@@ -163,12 +163,34 @@ export function normalizeToolPairing(messages) {
|
|
|
163
163
|
}
|
|
164
164
|
return out;
|
|
165
165
|
}
|
|
166
|
-
//
|
|
167
|
-
//
|
|
168
|
-
//
|
|
169
|
-
export function
|
|
166
|
+
// Un'ora come Claude Code, per abbonamento e API key: ogni lettura rinnova la
|
|
167
|
+
// scadenza, quindi le sessioni con pause oltre i 5 minuti non riscrivono tutto
|
|
168
|
+
// il prefisso. TALOS_CLAUDE_CACHE_TTL=5m torna alla durata breve.
|
|
169
|
+
export function claudeCacheTtl(env) {
|
|
170
|
+
return env["TALOS_CLAUDE_CACHE_TTL"] === "5m" ? "5m" : "1h";
|
|
171
|
+
}
|
|
172
|
+
const CACHE_TTL_MS = { "5m": 300_000, "1h": 3_600_000 };
|
|
173
|
+
// Durata applicata dal provider alla cache di questa risposta: la dice la
|
|
174
|
+
// suddivisione di cache_creation per TTL. Una lettura rinnova la durata gia'
|
|
175
|
+
// scritta, che resta quella dell'ultima scrittura nota.
|
|
176
|
+
function reportedCacheTtlMs(usage) {
|
|
177
|
+
const creation = usage["cache_creation"];
|
|
178
|
+
if (Number(creation?.["ephemeral_1h_input_tokens"] ?? 0) > 0)
|
|
179
|
+
return CACHE_TTL_MS["1h"];
|
|
180
|
+
if (Number(creation?.["ephemeral_5m_input_tokens"] ?? 0) > 0)
|
|
181
|
+
return CACHE_TTL_MS["5m"];
|
|
182
|
+
return undefined;
|
|
183
|
+
}
|
|
184
|
+
function cacheControl(ttl) {
|
|
185
|
+
return { type: "ephemeral", ...(ttl === "1h" ? { ttl } : {}) };
|
|
186
|
+
}
|
|
187
|
+
// Only documented models accept authoritative system messages in the history.
|
|
188
|
+
export function supportsConversationSystem(model) {
|
|
189
|
+
return /^claude-(?:opus-(?:5(?:-\d)?|4-8)|(?:fable|mythos)-5(?:-\d)?)(?:-\d{8})?$/.test(model);
|
|
190
|
+
}
|
|
191
|
+
export function withSystemCache(system, turnContext = "", ttl = "5m") {
|
|
170
192
|
return [
|
|
171
|
-
{ type: "text", text: system, cache_control:
|
|
193
|
+
{ type: "text", text: system, cache_control: cacheControl(ttl) },
|
|
172
194
|
...(turnContext ? [{
|
|
173
195
|
type: "text",
|
|
174
196
|
text: `[HORIZON_TURN_CONTEXT]\n${turnContext}\n[/HORIZON_TURN_CONTEXT]`,
|
|
@@ -181,20 +203,39 @@ export function withSystemCache(system, turnContext = "") {
|
|
|
181
203
|
// finisce col turno precedente resta cacheato e viene riconosciuto al turno
|
|
182
204
|
// dopo. Insieme al breakpoint su system restano 3 marcatori, sotto il tetto di
|
|
183
205
|
// 4 dell'API.
|
|
184
|
-
export function applyMessageCache(messages) {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
206
|
+
export function applyMessageCache(messages, ttl = "5m") {
|
|
207
|
+
// Provider projections must not mutate a caller's history.
|
|
208
|
+
const copy = messages.map((message) => {
|
|
209
|
+
const m = message;
|
|
210
|
+
return { ...m, ...(Array.isArray(m.content) ? { content: m.content.map(b => ({ ...b })) } : {}) };
|
|
211
|
+
});
|
|
212
|
+
markCacheBreakpoint(copy[copy.length - 1], ttl);
|
|
213
|
+
if (copy.length > 1)
|
|
214
|
+
markCacheBreakpoint(copy[copy.length - 2], ttl);
|
|
215
|
+
return copy;
|
|
189
216
|
}
|
|
190
|
-
function markCacheBreakpoint(message) {
|
|
217
|
+
function markCacheBreakpoint(message, ttl) {
|
|
191
218
|
const target = message;
|
|
192
219
|
if (!target || !Array.isArray(target.content) || !target.content.length)
|
|
193
220
|
return;
|
|
194
221
|
const blocks = target.content;
|
|
195
222
|
const lastBlock = blocks[blocks.length - 1];
|
|
196
223
|
if (lastBlock)
|
|
197
|
-
lastBlock["cache_control"] =
|
|
224
|
+
lastBlock["cache_control"] = cacheControl(ttl);
|
|
225
|
+
}
|
|
226
|
+
export function claudePrompt(req, ttl = "5m") {
|
|
227
|
+
const inline = supportsConversationSystem(req.model);
|
|
228
|
+
const messages = toApiMessages(req);
|
|
229
|
+
if (inline && req.turnContext)
|
|
230
|
+
messages.push({ role: "system", content: [{
|
|
231
|
+
type: "text", text: `[HORIZON_TURN_CONTEXT]\n${req.turnContext}\n[/HORIZON_TURN_CONTEXT]`,
|
|
232
|
+
}] });
|
|
233
|
+
// Cache the history immediately BEFORE the volatile tail as well as the tail.
|
|
234
|
+
// On the next request only the tail is replaced; all prior history still matches.
|
|
235
|
+
return {
|
|
236
|
+
system: withSystemCache(req.system, inline ? "" : req.turnContext, ttl),
|
|
237
|
+
messages: applyMessageCache(messages, ttl),
|
|
238
|
+
};
|
|
198
239
|
}
|
|
199
240
|
import { anthropicEffort } from "./effort.js";
|
|
200
241
|
import { resolveMaxTokens } from "../core/model-limits.js";
|
|
@@ -233,8 +274,7 @@ export class AnthropicProvider {
|
|
|
233
274
|
const body = {
|
|
234
275
|
model: req.model,
|
|
235
276
|
max_tokens: resolveMaxTokens(req.maxTokens, `anthropic/${req.model}`),
|
|
236
|
-
|
|
237
|
-
messages: applyMessageCache(toApiMessages(req)),
|
|
277
|
+
...claudePrompt(req, claudeCacheTtl(process.env)),
|
|
238
278
|
stream: true,
|
|
239
279
|
tools: req.tools.map((t) => ({
|
|
240
280
|
name: t.name,
|
|
@@ -331,7 +371,7 @@ export async function parseStream(body, onDelta, onActivity, onReasoning, onTool
|
|
|
331
371
|
stopReason ??= "end";
|
|
332
372
|
sawTerminal = true;
|
|
333
373
|
}
|
|
334
|
-
const u = readUsage(evt);
|
|
374
|
+
const u = readUsage(evt, usage);
|
|
335
375
|
if (u)
|
|
336
376
|
usage = u;
|
|
337
377
|
};
|
|
@@ -511,16 +551,19 @@ function readProviderError(evt) {
|
|
|
511
551
|
const message = String(raw?.["message"] ?? evt["message"] ?? "errore streaming senza dettagli");
|
|
512
552
|
return `Errore provider Anthropic (${kind}): ${message}${errorTimingDetail(raw)}${errorTimingDetail(evt)}`;
|
|
513
553
|
}
|
|
514
|
-
function readUsage(evt) {
|
|
515
|
-
const
|
|
554
|
+
function readUsage(evt, previous) {
|
|
555
|
+
const message = evt["message"];
|
|
556
|
+
const usage = (evt["usage"] ?? message?.["usage"]);
|
|
516
557
|
if (!usage)
|
|
517
558
|
return undefined;
|
|
518
559
|
const cacheRead = usage["cache_read_input_tokens"];
|
|
519
560
|
const cacheWrite = usage["cache_creation_input_tokens"];
|
|
561
|
+
const cacheTtlMs = reportedCacheTtlMs(usage) ?? previous?.cacheTtlMs;
|
|
520
562
|
return {
|
|
521
|
-
inputTokens: Number(usage["input_tokens"] ?? 0),
|
|
522
|
-
outputTokens: Number(usage["output_tokens"] ?? 0),
|
|
523
|
-
...(cacheRead !== undefined ? { cacheReadTokens: Number(cacheRead) } : {}),
|
|
524
|
-
...(cacheWrite !== undefined ? { cacheWriteTokens: Number(cacheWrite) } : {}),
|
|
563
|
+
inputTokens: Number(usage["input_tokens"] ?? previous?.inputTokens ?? 0),
|
|
564
|
+
outputTokens: Number(usage["output_tokens"] ?? previous?.outputTokens ?? 0),
|
|
565
|
+
...((cacheRead ?? previous?.cacheReadTokens) !== undefined ? { cacheReadTokens: Number(cacheRead ?? previous?.cacheReadTokens) } : {}),
|
|
566
|
+
...((cacheWrite ?? previous?.cacheWriteTokens) !== undefined ? { cacheWriteTokens: Number(cacheWrite ?? previous?.cacheWriteTokens) } : {}),
|
|
567
|
+
...(cacheTtlMs !== undefined ? { cacheTtlMs } : {}),
|
|
525
568
|
};
|
|
526
569
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export type CliName = "claude" | "codex";
|
|
2
|
+
export interface CliModel {
|
|
3
|
+
readonly id: string;
|
|
4
|
+
readonly label: string;
|
|
5
|
+
readonly description?: string;
|
|
6
|
+
}
|
|
7
|
+
/** Primo CLI nel PATH con l'impronta del binario reale (symlink risolti), o null se non installato. */
|
|
8
|
+
export declare function findCli(name: CliName, env: NodeJS.ProcessEnv): {
|
|
9
|
+
readonly executable: string;
|
|
10
|
+
readonly stamp: string;
|
|
11
|
+
} | null;
|
|
12
|
+
/** Modelli in cache per il CLI installato ora, o undefined se assenti o superati da un aggiornamento. */
|
|
13
|
+
export declare function cachedCliModels(name: CliName, env: NodeJS.ProcessEnv): readonly CliModel[] | undefined;
|
|
14
|
+
/**
|
|
15
|
+
* Righe di `initialize` del CLI Claude Code. Gli alias (default, opus, sonnet)
|
|
16
|
+
* diventano il modello versionato che eseguono: una voce per modello reale,
|
|
17
|
+
* nell'ordine del CLI.
|
|
18
|
+
*/
|
|
19
|
+
export declare function claudeModelsFromInitialize(models: unknown): CliModel[];
|
|
20
|
+
/** Righe di `model/list` dell'app-server Codex, senza i modelli nascosti. */
|
|
21
|
+
export declare function codexModelsFromList(data: unknown): CliModel[];
|
|
22
|
+
/**
|
|
23
|
+
* Rilegge i modelli dai CLI installati la cui cache manca o e' superata, e la
|
|
24
|
+
* salva. Un CLI assente, lento o in errore lascia la cache com'e': il catalogo
|
|
25
|
+
* ripiega su quello statico.
|
|
26
|
+
*/
|
|
27
|
+
export declare function refreshCliModels(env: NodeJS.ProcessEnv, options?: {
|
|
28
|
+
readonly timeoutMs?: number;
|
|
29
|
+
readonly force?: boolean;
|
|
30
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, realpathSync, statSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { delimiter, dirname, isAbsolute, join } from "node:path";
|
|
5
|
+
import { talosConfigDir } from "../core/env-paths.js";
|
|
6
|
+
const QUERY_TIMEOUT_MS = 20_000;
|
|
7
|
+
function cachePath(env) {
|
|
8
|
+
if (env["TALOS_NO_GLOBAL_CONFIG"] === "1" || env["TALOS_DISABLE_CLI_MODELS"] === "1")
|
|
9
|
+
return null;
|
|
10
|
+
return join(talosConfigDir(env), "cli-models.json");
|
|
11
|
+
}
|
|
12
|
+
/** Primo CLI nel PATH con l'impronta del binario reale (symlink risolti), o null se non installato. */
|
|
13
|
+
export function findCli(name, env) {
|
|
14
|
+
const names = process.platform === "win32" ? [`${name}.exe`, `${name}.cmd`] : [name];
|
|
15
|
+
for (const directory of String(env["PATH"] ?? env["Path"] ?? "").split(delimiter)) {
|
|
16
|
+
if (!directory || !isAbsolute(directory))
|
|
17
|
+
continue;
|
|
18
|
+
for (const file of names) {
|
|
19
|
+
const candidate = join(directory, file);
|
|
20
|
+
if (!existsSync(candidate))
|
|
21
|
+
continue;
|
|
22
|
+
try {
|
|
23
|
+
const real = realpathSync(candidate);
|
|
24
|
+
return { executable: candidate, stamp: `${real}@${statSync(real).mtimeMs}` };
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// Voce del PATH non leggibile: si prova la successiva.
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
function readCache(env) {
|
|
34
|
+
const path = cachePath(env);
|
|
35
|
+
if (!path || !existsSync(path))
|
|
36
|
+
return {};
|
|
37
|
+
try {
|
|
38
|
+
const raw = JSON.parse(readFileSync(path, "utf8"));
|
|
39
|
+
return raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return {};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/** Modelli in cache per il CLI installato ora, o undefined se assenti o superati da un aggiornamento. */
|
|
46
|
+
export function cachedCliModels(name, env) {
|
|
47
|
+
if (!cachePath(env))
|
|
48
|
+
return undefined;
|
|
49
|
+
const cli = findCli(name, env);
|
|
50
|
+
const entry = readCache(env)[name];
|
|
51
|
+
if (!cli || !entry || entry.stamp !== cli.stamp)
|
|
52
|
+
return undefined;
|
|
53
|
+
const models = Array.isArray(entry.models) ? entry.models.filter((model) => typeof model?.id === "string" && model.id && typeof model.label === "string") : [];
|
|
54
|
+
return models.length ? models : undefined;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Righe di `initialize` del CLI Claude Code. Gli alias (default, opus, sonnet)
|
|
58
|
+
* diventano il modello versionato che eseguono: una voce per modello reale,
|
|
59
|
+
* nell'ordine del CLI.
|
|
60
|
+
*/
|
|
61
|
+
export function claudeModelsFromInitialize(models) {
|
|
62
|
+
const out = new Map();
|
|
63
|
+
for (const raw of Array.isArray(models) ? models : []) {
|
|
64
|
+
const row = raw;
|
|
65
|
+
if (row["value"] === "default")
|
|
66
|
+
continue;
|
|
67
|
+
const id = String(row["resolvedModel"] || row["value"] || "").trim();
|
|
68
|
+
if (!id || out.has(id))
|
|
69
|
+
continue;
|
|
70
|
+
const label = String(row["displayName"] || id).trim();
|
|
71
|
+
const description = String(row["description"] ?? "").trim();
|
|
72
|
+
out.set(id, { id, label, ...(description ? { description } : {}) });
|
|
73
|
+
}
|
|
74
|
+
return [...out.values()];
|
|
75
|
+
}
|
|
76
|
+
/** Righe di `model/list` dell'app-server Codex, senza i modelli nascosti. */
|
|
77
|
+
export function codexModelsFromList(data) {
|
|
78
|
+
const out = new Map();
|
|
79
|
+
for (const raw of Array.isArray(data) ? data : []) {
|
|
80
|
+
const row = raw;
|
|
81
|
+
if (row["hidden"] === true)
|
|
82
|
+
continue;
|
|
83
|
+
const id = String(row["model"] || row["id"] || "").trim();
|
|
84
|
+
if (!id || out.has(id))
|
|
85
|
+
continue;
|
|
86
|
+
const label = String(row["displayName"] || id).trim();
|
|
87
|
+
const description = String(row["description"] ?? "").trim();
|
|
88
|
+
out.set(id, { id, label, ...(description ? { description } : {}) });
|
|
89
|
+
}
|
|
90
|
+
return [...out.values()];
|
|
91
|
+
}
|
|
92
|
+
// Avvia il CLI, scrive le richieste JSONL e attende la prima riga che `pick`
|
|
93
|
+
// riconosce. Il processo viene sempre terminato, anche su timeout o errore.
|
|
94
|
+
function queryCli(executable, args, requests, pick, env, timeoutMs) {
|
|
95
|
+
return new Promise((resolve, reject) => {
|
|
96
|
+
const child = spawn(executable, [...args], {
|
|
97
|
+
env, cwd: tmpdir(), stdio: ["pipe", "pipe", "ignore"], windowsHide: true,
|
|
98
|
+
shell: process.platform === "win32" && executable.toLowerCase().endsWith(".cmd"),
|
|
99
|
+
});
|
|
100
|
+
let buffer = "";
|
|
101
|
+
let settled = false;
|
|
102
|
+
const finish = (error, value) => {
|
|
103
|
+
if (settled)
|
|
104
|
+
return;
|
|
105
|
+
settled = true;
|
|
106
|
+
clearTimeout(timer);
|
|
107
|
+
child.kill();
|
|
108
|
+
if (error)
|
|
109
|
+
reject(error);
|
|
110
|
+
else
|
|
111
|
+
resolve(value);
|
|
112
|
+
};
|
|
113
|
+
const timer = setTimeout(() => finish(new Error(`${executable} did not answer in time`)), timeoutMs);
|
|
114
|
+
child.on("error", (error) => finish(error));
|
|
115
|
+
child.on("close", () => finish(new Error(`${executable} exited before answering`)));
|
|
116
|
+
child.stdout.setEncoding("utf8");
|
|
117
|
+
child.stdout.on("data", (chunk) => {
|
|
118
|
+
buffer += chunk;
|
|
119
|
+
let newline;
|
|
120
|
+
while ((newline = buffer.indexOf("\n")) >= 0) {
|
|
121
|
+
const line = buffer.slice(0, newline).trim();
|
|
122
|
+
buffer = buffer.slice(newline + 1);
|
|
123
|
+
if (!line.startsWith("{"))
|
|
124
|
+
continue;
|
|
125
|
+
try {
|
|
126
|
+
const value = pick(JSON.parse(line));
|
|
127
|
+
if (value !== undefined)
|
|
128
|
+
finish(null, value);
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
// Righe non JSON (log) ignorate.
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
child.stdin.on("error", () => { });
|
|
136
|
+
child.stdin.write(requests.map((request) => JSON.stringify(request)).join("\n") + "\n");
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
async function queryClaudeModels(executable, env, timeoutMs) {
|
|
140
|
+
const response = await queryCli(executable, ["-p", "--input-format", "stream-json", "--output-format", "stream-json", "--verbose"], [{ type: "control_request", request_id: "talos-models", request: { subtype: "initialize" } }], (message) => {
|
|
141
|
+
const body = message["response"];
|
|
142
|
+
return message["type"] === "control_response" && body?.["request_id"] === "talos-models" ? body : undefined;
|
|
143
|
+
}, env, timeoutMs);
|
|
144
|
+
if (response["subtype"] !== "success")
|
|
145
|
+
throw new Error(String(response["error"] ?? "Claude Code initialize failed"));
|
|
146
|
+
return claudeModelsFromInitialize(response["response"]?.["models"]);
|
|
147
|
+
}
|
|
148
|
+
async function queryCodexModels(executable, env, timeoutMs) {
|
|
149
|
+
const response = await queryCli(executable, ["app-server"], [
|
|
150
|
+
{ id: 1, method: "initialize", params: { clientInfo: { name: "talos", version: "1" } } },
|
|
151
|
+
{ method: "initialized" },
|
|
152
|
+
{ id: 2, method: "model/list", params: {} },
|
|
153
|
+
], (message) => message["id"] === 2 ? message : undefined, env, timeoutMs);
|
|
154
|
+
if (response["error"])
|
|
155
|
+
throw new Error(JSON.stringify(response["error"]));
|
|
156
|
+
return codexModelsFromList(response["result"]?.["data"]);
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Rilegge i modelli dai CLI installati la cui cache manca o e' superata, e la
|
|
160
|
+
* salva. Un CLI assente, lento o in errore lascia la cache com'e': il catalogo
|
|
161
|
+
* ripiega su quello statico.
|
|
162
|
+
*/
|
|
163
|
+
export async function refreshCliModels(env, options = {}) {
|
|
164
|
+
const path = cachePath(env);
|
|
165
|
+
if (!path)
|
|
166
|
+
return;
|
|
167
|
+
const timeoutMs = options.timeoutMs ?? QUERY_TIMEOUT_MS;
|
|
168
|
+
const queries = { claude: queryClaudeModels, codex: queryCodexModels };
|
|
169
|
+
const updates = await Promise.all(Object.keys(queries).map(async (name) => {
|
|
170
|
+
if (!options.force && cachedCliModels(name, env))
|
|
171
|
+
return null;
|
|
172
|
+
const cli = findCli(name, env);
|
|
173
|
+
if (!cli)
|
|
174
|
+
return null;
|
|
175
|
+
try {
|
|
176
|
+
const models = await queries[name](cli.executable, env, timeoutMs);
|
|
177
|
+
return models.length ? [name, { stamp: cli.stamp, models }] : null;
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
}));
|
|
183
|
+
const fresh = updates.filter((update) => update !== null);
|
|
184
|
+
if (!fresh.length)
|
|
185
|
+
return;
|
|
186
|
+
const cache = { ...readCache(env), ...Object.fromEntries(fresh) };
|
|
187
|
+
try {
|
|
188
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
189
|
+
writeFileSync(path, JSON.stringify(cache, null, 2) + "\n", { mode: 0o600 });
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
// Cache non scrivibile: il catalogo resta quello statico.
|
|
193
|
+
}
|
|
194
|
+
}
|
|
@@ -26,7 +26,7 @@ export function modelEfforts(fullModel, metadata = modelCapabilities(fullModel))
|
|
|
26
26
|
return ["", "low", "medium", "high"];
|
|
27
27
|
}
|
|
28
28
|
if (provider === "openai") {
|
|
29
|
-
if (/gpt-6
|
|
29
|
+
if (/gpt-6/.test(id))
|
|
30
30
|
return ["", "low", "medium", "high", "xhigh", "max"];
|
|
31
31
|
if (/gpt-5\.[456]/.test(id))
|
|
32
32
|
return ["", "low", "medium", "high", "xhigh"];
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CliModel } from "./cli-models.js";
|
|
1
2
|
import type { CompletionRequest, ModelTurn, Provider } from "../core/types.js";
|
|
2
3
|
import { type OAuthCreds } from "./oauth-store.js";
|
|
3
4
|
export declare class OpenAIOAuthProvider implements Provider {
|
|
@@ -5,10 +6,14 @@ export declare class OpenAIOAuthProvider implements Provider {
|
|
|
5
6
|
private readonly env;
|
|
6
7
|
private readonly now;
|
|
7
8
|
readonly id = "chatgpt";
|
|
8
|
-
readonly label = "ChatGPT
|
|
9
|
-
readonly models: readonly [
|
|
9
|
+
readonly label = "ChatGPT";
|
|
10
|
+
readonly models: readonly string[];
|
|
11
|
+
readonly modelLabels?: ReadonlyMap<string, {
|
|
12
|
+
readonly label: string;
|
|
13
|
+
readonly description?: string;
|
|
14
|
+
}>;
|
|
10
15
|
readonly supportsFastMode = true;
|
|
11
|
-
constructor(creds: OAuthCreds, env: NodeJS.ProcessEnv, now?: () => number);
|
|
16
|
+
constructor(creds: OAuthCreds, env: NodeJS.ProcessEnv, now?: () => number, cliModels?: readonly CliModel[]);
|
|
12
17
|
private ensureToken;
|
|
13
18
|
complete(req: CompletionRequest): Promise<ModelTurn>;
|
|
14
19
|
}
|
|
@@ -105,13 +105,19 @@ export class OpenAIOAuthProvider {
|
|
|
105
105
|
env;
|
|
106
106
|
now;
|
|
107
107
|
id = "chatgpt";
|
|
108
|
-
label = "ChatGPT
|
|
109
|
-
models
|
|
108
|
+
label = "ChatGPT";
|
|
109
|
+
models;
|
|
110
|
+
modelLabels;
|
|
110
111
|
supportsFastMode = true;
|
|
111
|
-
constructor(creds, env, now = () => Date.now()
|
|
112
|
+
constructor(creds, env, now = () => Date.now(),
|
|
113
|
+
// Modelli del CLI ufficiale installato; senza, il catalogo statico.
|
|
114
|
+
cliModels) {
|
|
112
115
|
this.creds = creds;
|
|
113
116
|
this.env = env;
|
|
114
117
|
this.now = now;
|
|
118
|
+
this.models = cliModels?.length ? cliModels.map((model) => model.id) : CHATGPT_MODELS;
|
|
119
|
+
if (cliModels?.length)
|
|
120
|
+
this.modelLabels = new Map(cliModels.map((model) => [model.id, model]));
|
|
115
121
|
}
|
|
116
122
|
async ensureToken(signal) {
|
|
117
123
|
if (!isExpired(this.creds, this.now()) || !this.creds.refreshToken) {
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import type { OAuthFlow } from "./openrouter-auth.js";
|
|
2
|
+
export type ManualTranslator = (italian: string, english: string, values?: Readonly<Record<string, string | number>>) => string;
|
|
2
3
|
export declare function normalizeAuthCode(raw: string): string;
|
|
3
4
|
export declare function isLikelyAuthCode(value: string): boolean;
|
|
4
5
|
export interface ManualInstructions {
|
|
5
6
|
readonly lines: readonly string[];
|
|
6
7
|
readonly authUrl: string;
|
|
7
8
|
}
|
|
8
|
-
export declare function buildManualInstructions(authUrl: string, reason?: string): ManualInstructions;
|
|
9
|
+
export declare function buildManualInstructions(authUrl: string, reason?: string, tr?: ManualTranslator): ManualInstructions;
|
|
9
10
|
export interface ManualFallbackIo {
|
|
10
11
|
print(line: string): void;
|
|
11
12
|
prompt(label: string): Promise<string | null>;
|
|
12
13
|
}
|
|
13
14
|
export interface ManualFallbackOptions {
|
|
15
|
+
readonly translate?: ManualTranslator;
|
|
14
16
|
readonly reason?: string;
|
|
15
17
|
readonly maxAttempts?: number;
|
|
16
18
|
readonly signal?: AbortSignal;
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
// (niente accesso diretto a stdin/stdout/console), e lo scambio del code arriva
|
|
14
14
|
// dall'OAuthFlow.complete gia' fornito da openrouter-auth.ts. Nessun side effect
|
|
15
15
|
// nascosto, niente dipendenze a runtime.
|
|
16
|
+
const defaultTranslation = (italian, _english, values) => italian.replace(/\{(\w+)\}/g, (match, key) => String(values?.[key] ?? match));
|
|
16
17
|
// ---------------------------------------------------------------------------
|
|
17
18
|
// Validazione / normalizzazione del code incollato
|
|
18
19
|
// ---------------------------------------------------------------------------
|
|
@@ -91,26 +92,24 @@ export function isLikelyAuthCode(value) {
|
|
|
91
92
|
// Costruisce le istruzioni per il percorso manuale. `reason` (opzionale) spiega
|
|
92
93
|
// perche' siamo qui (es. "porta 8976 occupata", "nessun browser disponibile"):
|
|
93
94
|
// se assente usiamo un messaggio neutro.
|
|
94
|
-
export function buildManualInstructions(authUrl, reason) {
|
|
95
|
+
export function buildManualInstructions(authUrl, reason, tr = defaultTranslation) {
|
|
95
96
|
const why = (reason ?? "").trim();
|
|
96
97
|
const lines = [];
|
|
97
|
-
lines.push("Login OpenRouter — modalita' manuale");
|
|
98
|
+
lines.push(tr("Login OpenRouter — modalita' manuale", "OpenRouter sign-in — manual mode"));
|
|
98
99
|
if (why) {
|
|
99
|
-
lines.push(
|
|
100
|
+
lines.push(tr("(callback automatico non disponibile: {reason})", "(automatic callback unavailable: {reason})", { reason: why }));
|
|
100
101
|
}
|
|
101
102
|
else {
|
|
102
|
-
lines.push("(callback automatico non disponibile: completiamo a mano)");
|
|
103
|
+
lines.push(tr("(callback automatico non disponibile: completiamo a mano)", "(automatic callback unavailable: complete sign-in manually)"));
|
|
103
104
|
}
|
|
104
105
|
lines.push("");
|
|
105
|
-
lines.push("1. Apri questo link nel browser (copialo se non e' cliccabile):");
|
|
106
|
+
lines.push(tr("1. Apri questo link nel browser (copialo se non e' cliccabile):", "1. Open this link in the browser (copy it if it is not clickable):"));
|
|
106
107
|
lines.push(` ${authUrl}`);
|
|
107
108
|
lines.push("");
|
|
108
|
-
lines.push("2. Autorizza l'accesso su OpenRouter.");
|
|
109
|
-
lines.push("3. Verrai rediretto a un indirizzo localhost che potrebbe non");
|
|
110
|
-
lines.push(
|
|
111
|
-
lines.push("
|
|
112
|
-
lines.push(" (oppure incolla l'intero URL: estraggo io il code).");
|
|
113
|
-
lines.push("5. Incollalo qui sotto e premi Invio.");
|
|
109
|
+
lines.push(tr("2. Autorizza l'accesso su OpenRouter.", "2. Authorize access on OpenRouter."));
|
|
110
|
+
lines.push(tr("3. Verrai rediretto a un indirizzo localhost che potrebbe non aprirsi: e' normale.", "3. You will be redirected to a localhost address that may not open: this is normal."));
|
|
111
|
+
lines.push(tr("4. Copia il parametro `code` dalla barra degli indirizzi (oppure incolla l'intero URL).", "4. Copy the `code` parameter from the address bar (or paste the entire URL)."));
|
|
112
|
+
lines.push(tr("5. Incollalo qui sotto e premi Invio.", "5. Paste it below and press Enter."));
|
|
114
113
|
return { lines, authUrl };
|
|
115
114
|
}
|
|
116
115
|
// Esegue il percorso di fallback manuale: mostra link+istruzioni, chiede il
|
|
@@ -118,15 +117,16 @@ export function buildManualInstructions(authUrl, reason) {
|
|
|
118
117
|
// input invalido o scambio fallito, fino a maxAttempts o annullamento.
|
|
119
118
|
export async function runManualCodeFallback(io, flow, opts = {}) {
|
|
120
119
|
const maxAttempts = Math.max(1, Math.floor(opts.maxAttempts ?? 3));
|
|
121
|
-
const
|
|
120
|
+
const tr = opts.translate ?? defaultTranslation;
|
|
121
|
+
const instructions = buildManualInstructions(flow.authUrl, opts.reason, tr);
|
|
122
122
|
for (const line of instructions.lines)
|
|
123
123
|
io.print(line);
|
|
124
124
|
let attempts = 0;
|
|
125
125
|
let lastError = "";
|
|
126
126
|
while (attempts < maxAttempts) {
|
|
127
127
|
const remaining = maxAttempts - attempts;
|
|
128
|
-
const hint = attempts === 0 ? "" :
|
|
129
|
-
const raw = await io.prompt(
|
|
128
|
+
const hint = attempts === 0 ? "" : tr(" (tentativi rimasti: {count})", " (attempts remaining: {count})", { count: remaining });
|
|
129
|
+
const raw = await io.prompt(tr("Incolla il code{hint}", "Paste the code{hint}", { hint }));
|
|
130
130
|
// Annullamento esplicito (Esc/EOF): usciamo subito senza consumare logica.
|
|
131
131
|
if (raw === null) {
|
|
132
132
|
return { ok: false, error: "cancelled", attempts };
|
|
@@ -134,9 +134,9 @@ export async function runManualCodeFallback(io, flow, opts = {}) {
|
|
|
134
134
|
attempts += 1;
|
|
135
135
|
const code = normalizeAuthCode(raw);
|
|
136
136
|
if (!isLikelyAuthCode(code)) {
|
|
137
|
-
lastError = "code non riconosciuto";
|
|
137
|
+
lastError = tr("code non riconosciuto", "unrecognized code");
|
|
138
138
|
if (attempts < maxAttempts) {
|
|
139
|
-
io.print("Input non valido: incolla il code (o l'intero URL del callback). Riprova.");
|
|
139
|
+
io.print(tr("Input non valido: incolla il code (o l'intero URL del callback). Riprova.", "Invalid input: paste the code (or the entire callback URL). Try again."));
|
|
140
140
|
}
|
|
141
141
|
continue;
|
|
142
142
|
}
|
|
@@ -148,14 +148,14 @@ export async function runManualCodeFallback(io, flow, opts = {}) {
|
|
|
148
148
|
result = { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
149
149
|
}
|
|
150
150
|
if (result.ok && result.apiKey) {
|
|
151
|
-
io.print("Autenticazione completata: API key ottenuta e salvata.");
|
|
151
|
+
io.print(tr("Autenticazione completata: API key ottenuta e salvata.", "Authentication complete: API key obtained and saved."));
|
|
152
152
|
return { ok: true, apiKey: result.apiKey, attempts };
|
|
153
153
|
}
|
|
154
|
-
lastError = result.error ?? "scambio fallito";
|
|
154
|
+
lastError = result.error ?? tr("scambio fallito", "exchange failed");
|
|
155
155
|
if (attempts < maxAttempts) {
|
|
156
|
-
io.print(
|
|
156
|
+
io.print(tr("Scambio fallito: {error}. Verifica di aver copiato il code giusto e riprova.", "Exchange failed: {error}. Check that you copied the correct code and try again.", { error: lastError }));
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
|
-
io.print("Tentativi esauriti: login manuale non riuscito.");
|
|
159
|
+
io.print(tr("Tentativi esauriti: login manuale non riuscito.", "No attempts left: manual sign-in failed."));
|
|
160
160
|
return { ok: false, error: lastError || "exhausted", attempts };
|
|
161
161
|
}
|
|
@@ -3,6 +3,7 @@ import { AnthropicOAuthProvider } from "./anthropic-oauth.js";
|
|
|
3
3
|
import { OpenAIOAuthProvider } from "./openai-oauth.js";
|
|
4
4
|
import { OpenAICompatProvider } from "./openai-compat.js";
|
|
5
5
|
import { readClaudeCreds, readCodexCreds } from "./oauth-store.js";
|
|
6
|
+
import { cachedCliModels } from "./cli-models.js";
|
|
6
7
|
import { readOpenRouterCreds } from "./openrouter-auth.js";
|
|
7
8
|
import { PROVIDER_CATALOG } from "./catalog.js";
|
|
8
9
|
import { retryConfigFromEnv, withRetry } from "./retry.js";
|
|
@@ -202,11 +203,11 @@ export function defaultRegistry(env, opts = {}) {
|
|
|
202
203
|
if (opts.detectOAuth !== false) {
|
|
203
204
|
const claude = readClaudeCreds(env);
|
|
204
205
|
if (claude)
|
|
205
|
-
add(new AnthropicOAuthProvider(claude, env));
|
|
206
|
+
add(new AnthropicOAuthProvider(claude, env, undefined, cachedCliModels("claude", env)));
|
|
206
207
|
if (env["TALOS_DISABLE_CHATGPT_OAUTH"] !== "1") {
|
|
207
208
|
const codex = readCodexCreds(env);
|
|
208
209
|
if (codex)
|
|
209
|
-
add(new OpenAIOAuthProvider(codex, env));
|
|
210
|
+
add(new OpenAIOAuthProvider(codex, env, undefined, cachedCliModels("codex", env)));
|
|
210
211
|
}
|
|
211
212
|
}
|
|
212
213
|
return reg;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { CompletionRequest, ModelTurn, PlanLimits, Provider } from "../core/types.js";
|
|
2
2
|
export interface RetryConfig {
|
|
3
|
+
readonly autoResumeSession?: boolean;
|
|
3
4
|
readonly maxRetries: number;
|
|
4
5
|
readonly baseDelayMs: number;
|
|
5
6
|
readonly timeoutMs: number;
|
|
@@ -25,12 +26,14 @@ export declare class RetryProvider implements Provider {
|
|
|
25
26
|
get id(): string;
|
|
26
27
|
get label(): string | undefined;
|
|
27
28
|
get models(): readonly string[];
|
|
29
|
+
get modelLabels(): Provider["modelLabels"];
|
|
28
30
|
get supportsFastMode(): boolean;
|
|
29
31
|
private get netMax();
|
|
30
32
|
private get netDelay();
|
|
31
33
|
private get overloadMaxAttempts();
|
|
32
34
|
private overloadDelay;
|
|
33
35
|
private waitForOverload;
|
|
36
|
+
private waitForSessionReset;
|
|
34
37
|
complete(req: CompletionRequest): Promise<ModelTurn>;
|
|
35
38
|
private backoff;
|
|
36
39
|
}
|