modeldispatcher-browser-agent 0.6.0 → 0.6.7
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 +206 -203
- package/dist/externalChat.js +9 -0
- package/dist/externalChat.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/package.json +45 -40
- package/src/agent.ts +206 -206
- package/src/config.ts +117 -117
- package/src/externalChat.ts +124 -115
- package/src/externalChatFavorite.ts +43 -43
- package/src/features.ts +40 -40
- package/src/http.ts +100 -100
- package/src/index.ts +52 -52
- package/src/messages.ts +61 -61
- package/src/providers/anthropic.ts +86 -86
- package/src/providers/gemini.ts +95 -95
- package/src/providers/ollama.ts +81 -81
- package/src/providers/openaiCompatible.ts +89 -89
- package/src/registry.ts +82 -82
- package/src/types.ts +108 -108
package/src/types.ts
CHANGED
|
@@ -1,108 +1,108 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared vocabulary for the browser agent.
|
|
3
|
-
*
|
|
4
|
-
* Mirrors the split model-dispatcher's Python core uses: plain, dependency-free
|
|
5
|
-
* value types here, behaviour in `providers/*` and `agent.ts`.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
export type ProviderId = "gemini" | "openai" | "anthropic" | "groq" | "ollama";
|
|
9
|
-
|
|
10
|
-
/** Static metadata about a provider — enough to render a settings picker. */
|
|
11
|
-
export interface ProviderInfo {
|
|
12
|
-
readonly id: ProviderId;
|
|
13
|
-
readonly name: string;
|
|
14
|
-
/** Whether this provider has a genuinely free tier (not just "has a trial"). */
|
|
15
|
-
readonly free: boolean;
|
|
16
|
-
/** True for providers that need no API key at all (e.g. a local Ollama). */
|
|
17
|
-
readonly noKey?: boolean;
|
|
18
|
-
readonly defaultModel: string;
|
|
19
|
-
/** UI placeholder text for the key input (e.g. "sk-ant-..."). */
|
|
20
|
-
readonly placeholder: string;
|
|
21
|
-
readonly infoUrl: string;
|
|
22
|
-
readonly infoText: string;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* One configured vendor: its model, and the key(s) pooled for it. More than
|
|
27
|
-
* one key is tried in order (e.g. a personal key and a team key) before
|
|
28
|
-
* this vendor is considered exhausted and the dispatcher moves to the next
|
|
29
|
-
* configured provider. Ignored for `provider: "ollama"`, which authenticates
|
|
30
|
-
* via `AgentConfig.ollamaUrl` instead of a key.
|
|
31
|
-
*/
|
|
32
|
-
export interface ProviderCredential {
|
|
33
|
-
readonly provider: ProviderId;
|
|
34
|
-
readonly model: string;
|
|
35
|
-
readonly apiKeys: readonly string[];
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* The full BYOK configuration: an ordered fallback list of vendors (each
|
|
40
|
-
* with its own pooled keys) to try in turn, plus Ollama's local server URL
|
|
41
|
-
* (shared across the whole config — there's only one local Ollama, not one
|
|
42
|
-
* per fallback slot). `dispatch`/`complete`/`streamComplete` walk this list
|
|
43
|
-
* candidate by candidate, mirroring the Python core's fallback chain.
|
|
44
|
-
*/
|
|
45
|
-
export interface AgentConfig {
|
|
46
|
-
readonly providers: readonly ProviderCredential[];
|
|
47
|
-
readonly ollamaUrl: string;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* One concrete attempt: a specific vendor, model, and (for keyed vendors) a
|
|
52
|
-
* single already-resolved key — what an individual `providers/*` module
|
|
53
|
-
* needs to make one call. Distinct from `AgentConfig`, which holds the whole
|
|
54
|
-
* configured fallback list before the dispatch loop has picked a candidate.
|
|
55
|
-
*/
|
|
56
|
-
export interface ProviderCallConfig {
|
|
57
|
-
readonly provider: ProviderId;
|
|
58
|
-
readonly model: string;
|
|
59
|
-
readonly apiKey: string;
|
|
60
|
-
readonly ollamaUrl: string;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export type ChatRole = "system" | "user" | "assistant";
|
|
64
|
-
|
|
65
|
-
export interface ChatMessage {
|
|
66
|
-
readonly role: ChatRole;
|
|
67
|
-
readonly content: string;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/** Options shared by both complete() and streamComplete()/streamChat(). */
|
|
71
|
-
export interface RequestOptions {
|
|
72
|
-
/** System prompt / instruction, applied via each provider's native mechanism. */
|
|
73
|
-
systemInstruction?: string;
|
|
74
|
-
/** Request the provider's structured-JSON response mode where it has one
|
|
75
|
-
* (OpenAI-compatible providers only — Gemini's `responseMimeType` is
|
|
76
|
-
* always requested by callers that need it via a raw prompt instruction,
|
|
77
|
-
* Anthropic and Ollama have no such mode). */
|
|
78
|
-
jsonMode?: boolean;
|
|
79
|
-
maxTokens?: number;
|
|
80
|
-
/** Cancel the request (e.g. component unmount). Independent of, and
|
|
81
|
-
* merged with, the library's own request timeout. */
|
|
82
|
-
signal?: AbortSignal;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export interface StreamOptions extends RequestOptions {
|
|
86
|
-
/** Called with the *cumulative* text so far after every chunk, matching
|
|
87
|
-
* every existing app's streaming callback shape. */
|
|
88
|
-
onChunk: (fullTextSoFar: string) => void;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/** A free, public AI chat web product `openExternalChat` can hand a question
|
|
92
|
-
* off to — the no-API-key escape hatch, distinct from the `ProviderId`s above
|
|
93
|
-
* (which all require a BYOK credential). */
|
|
94
|
-
export type ExternalChatProviderId = "chatgpt" | "claude" | "gemini" | "groq";
|
|
95
|
-
|
|
96
|
-
/** Static metadata about one external chat provider. */
|
|
97
|
-
export interface ExternalChatProviderInfo {
|
|
98
|
-
readonly id: ExternalChatProviderId;
|
|
99
|
-
readonly name: string;
|
|
100
|
-
/** Where `openExternalChat` sends the user when there's no known
|
|
101
|
-
* query-prefill parameter for this provider (or as the base URL the
|
|
102
|
-
* parameter is appended to). */
|
|
103
|
-
readonly homeUrl: string;
|
|
104
|
-
/** Build the deep-link URL for a given question, when this provider has a
|
|
105
|
-
* known (unofficial, reverse-engineered) prefill parameter. `null` when it
|
|
106
|
-
* doesn't — `openExternalChat` falls back to `homeUrl` plus the clipboard. */
|
|
107
|
-
readonly buildUrl: ((question: string) => string) | null;
|
|
108
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Shared vocabulary for the browser agent.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the split model-dispatcher's Python core uses: plain, dependency-free
|
|
5
|
+
* value types here, behaviour in `providers/*` and `agent.ts`.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export type ProviderId = "gemini" | "openai" | "anthropic" | "groq" | "ollama";
|
|
9
|
+
|
|
10
|
+
/** Static metadata about a provider — enough to render a settings picker. */
|
|
11
|
+
export interface ProviderInfo {
|
|
12
|
+
readonly id: ProviderId;
|
|
13
|
+
readonly name: string;
|
|
14
|
+
/** Whether this provider has a genuinely free tier (not just "has a trial"). */
|
|
15
|
+
readonly free: boolean;
|
|
16
|
+
/** True for providers that need no API key at all (e.g. a local Ollama). */
|
|
17
|
+
readonly noKey?: boolean;
|
|
18
|
+
readonly defaultModel: string;
|
|
19
|
+
/** UI placeholder text for the key input (e.g. "sk-ant-..."). */
|
|
20
|
+
readonly placeholder: string;
|
|
21
|
+
readonly infoUrl: string;
|
|
22
|
+
readonly infoText: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* One configured vendor: its model, and the key(s) pooled for it. More than
|
|
27
|
+
* one key is tried in order (e.g. a personal key and a team key) before
|
|
28
|
+
* this vendor is considered exhausted and the dispatcher moves to the next
|
|
29
|
+
* configured provider. Ignored for `provider: "ollama"`, which authenticates
|
|
30
|
+
* via `AgentConfig.ollamaUrl` instead of a key.
|
|
31
|
+
*/
|
|
32
|
+
export interface ProviderCredential {
|
|
33
|
+
readonly provider: ProviderId;
|
|
34
|
+
readonly model: string;
|
|
35
|
+
readonly apiKeys: readonly string[];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The full BYOK configuration: an ordered fallback list of vendors (each
|
|
40
|
+
* with its own pooled keys) to try in turn, plus Ollama's local server URL
|
|
41
|
+
* (shared across the whole config — there's only one local Ollama, not one
|
|
42
|
+
* per fallback slot). `dispatch`/`complete`/`streamComplete` walk this list
|
|
43
|
+
* candidate by candidate, mirroring the Python core's fallback chain.
|
|
44
|
+
*/
|
|
45
|
+
export interface AgentConfig {
|
|
46
|
+
readonly providers: readonly ProviderCredential[];
|
|
47
|
+
readonly ollamaUrl: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* One concrete attempt: a specific vendor, model, and (for keyed vendors) a
|
|
52
|
+
* single already-resolved key — what an individual `providers/*` module
|
|
53
|
+
* needs to make one call. Distinct from `AgentConfig`, which holds the whole
|
|
54
|
+
* configured fallback list before the dispatch loop has picked a candidate.
|
|
55
|
+
*/
|
|
56
|
+
export interface ProviderCallConfig {
|
|
57
|
+
readonly provider: ProviderId;
|
|
58
|
+
readonly model: string;
|
|
59
|
+
readonly apiKey: string;
|
|
60
|
+
readonly ollamaUrl: string;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export type ChatRole = "system" | "user" | "assistant";
|
|
64
|
+
|
|
65
|
+
export interface ChatMessage {
|
|
66
|
+
readonly role: ChatRole;
|
|
67
|
+
readonly content: string;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Options shared by both complete() and streamComplete()/streamChat(). */
|
|
71
|
+
export interface RequestOptions {
|
|
72
|
+
/** System prompt / instruction, applied via each provider's native mechanism. */
|
|
73
|
+
systemInstruction?: string;
|
|
74
|
+
/** Request the provider's structured-JSON response mode where it has one
|
|
75
|
+
* (OpenAI-compatible providers only — Gemini's `responseMimeType` is
|
|
76
|
+
* always requested by callers that need it via a raw prompt instruction,
|
|
77
|
+
* Anthropic and Ollama have no such mode). */
|
|
78
|
+
jsonMode?: boolean;
|
|
79
|
+
maxTokens?: number;
|
|
80
|
+
/** Cancel the request (e.g. component unmount). Independent of, and
|
|
81
|
+
* merged with, the library's own request timeout. */
|
|
82
|
+
signal?: AbortSignal;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface StreamOptions extends RequestOptions {
|
|
86
|
+
/** Called with the *cumulative* text so far after every chunk, matching
|
|
87
|
+
* every existing app's streaming callback shape. */
|
|
88
|
+
onChunk: (fullTextSoFar: string) => void;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** A free, public AI chat web product `openExternalChat` can hand a question
|
|
92
|
+
* off to — the no-API-key escape hatch, distinct from the `ProviderId`s above
|
|
93
|
+
* (which all require a BYOK credential). */
|
|
94
|
+
export type ExternalChatProviderId = "chatgpt" | "claude" | "gemini" | "geminiApp" | "groq";
|
|
95
|
+
|
|
96
|
+
/** Static metadata about one external chat provider. */
|
|
97
|
+
export interface ExternalChatProviderInfo {
|
|
98
|
+
readonly id: ExternalChatProviderId;
|
|
99
|
+
readonly name: string;
|
|
100
|
+
/** Where `openExternalChat` sends the user when there's no known
|
|
101
|
+
* query-prefill parameter for this provider (or as the base URL the
|
|
102
|
+
* parameter is appended to). */
|
|
103
|
+
readonly homeUrl: string;
|
|
104
|
+
/** Build the deep-link URL for a given question, when this provider has a
|
|
105
|
+
* known (unofficial, reverse-engineered) prefill parameter. `null` when it
|
|
106
|
+
* doesn't — `openExternalChat` falls back to `homeUrl` plus the clipboard. */
|
|
107
|
+
readonly buildUrl: ((question: string) => string) | null;
|
|
108
|
+
}
|