chivgent 0.7.0 → 0.9.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/README.md +96 -3
- package/README.zh-CN.md +88 -3
- package/dist/agent.d.ts +14 -0
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +33 -1
- package/dist/agent.js.map +1 -1
- package/dist/auth/credentials.d.ts +26 -0
- package/dist/auth/credentials.d.ts.map +1 -0
- package/dist/auth/credentials.js +29 -0
- package/dist/auth/credentials.js.map +1 -0
- package/dist/auth/env-credentials.d.ts +10 -0
- package/dist/auth/env-credentials.d.ts.map +1 -0
- package/dist/auth/env-credentials.js +18 -0
- package/dist/auth/env-credentials.js.map +1 -0
- package/dist/auth/file-credentials.d.ts +25 -0
- package/dist/auth/file-credentials.d.ts.map +1 -0
- package/dist/auth/file-credentials.js +94 -0
- package/dist/auth/file-credentials.js.map +1 -0
- package/dist/auth/runtime-credentials.d.ts +10 -0
- package/dist/auth/runtime-credentials.d.ts.map +1 -0
- package/dist/auth/runtime-credentials.js +15 -0
- package/dist/auth/runtime-credentials.js.map +1 -0
- package/dist/cli-options.d.ts +16 -9
- package/dist/cli-options.d.ts.map +1 -1
- package/dist/cli-options.js +72 -26
- package/dist/cli-options.js.map +1 -1
- package/dist/cli.js +14 -42
- package/dist/cli.js.map +1 -1
- package/dist/context/compaction.d.ts +39 -0
- package/dist/context/compaction.d.ts.map +1 -0
- package/dist/context/compaction.js +141 -0
- package/dist/context/compaction.js.map +1 -0
- package/dist/context/context-manager.d.ts +72 -0
- package/dist/context/context-manager.d.ts.map +1 -0
- package/dist/context/context-manager.js +129 -0
- package/dist/context/context-manager.js.map +1 -0
- package/dist/context/token-estimator.d.ts +22 -0
- package/dist/context/token-estimator.d.ts.map +1 -0
- package/dist/context/token-estimator.js +43 -0
- package/dist/context/token-estimator.js.map +1 -0
- package/dist/providers/client.d.ts +7 -0
- package/dist/providers/client.d.ts.map +1 -0
- package/dist/providers/client.js +48 -0
- package/dist/providers/client.js.map +1 -0
- package/dist/providers/definitions.d.ts +25 -0
- package/dist/providers/definitions.d.ts.map +1 -0
- package/dist/providers/definitions.js +97 -0
- package/dist/providers/definitions.js.map +1 -0
- package/dist/providers/registry.d.ts +15 -0
- package/dist/providers/registry.d.ts.map +1 -0
- package/dist/providers/registry.js +34 -0
- package/dist/providers/registry.js.map +1 -0
- package/dist/workspace/read.d.ts +2 -0
- package/dist/workspace/read.d.ts.map +1 -1
- package/dist/workspace/read.js +5 -1
- package/dist/workspace/read.js.map +1 -1
- package/dist/workspace/text.d.ts +15 -0
- package/dist/workspace/text.d.ts.map +1 -1
- package/dist/workspace/text.js +21 -2
- package/dist/workspace/text.js.map +1 -1
- package/dist/workspace/write.d.ts.map +1 -1
- package/dist/workspace/write.js +38 -11
- package/dist/workspace/write.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
export const DEFAULT_FILE_EFFECTS = {
|
|
2
|
+
reads: ["read_file"],
|
|
3
|
+
mutates: ["write_file", "edit_file"],
|
|
4
|
+
};
|
|
5
|
+
const SUMMARY_INSTRUCTIONS = `You are compacting an engineering conversation so it can continue in a smaller context.
|
|
6
|
+
Reply with JSON only, no code fence, matching:
|
|
7
|
+
{"summary": string, "decisions": string[], "pendingTasks": string[]}
|
|
8
|
+
summary: what was asked and what was established, in a few sentences.
|
|
9
|
+
decisions: choices that later work must respect.
|
|
10
|
+
pendingTasks: work that was identified but not finished.
|
|
11
|
+
Omit file lists; they are tracked separately.`;
|
|
12
|
+
export class Compactor {
|
|
13
|
+
llm;
|
|
14
|
+
fileEffects;
|
|
15
|
+
constructor(llm, options = {}) {
|
|
16
|
+
this.llm = llm;
|
|
17
|
+
this.fileEffects = options.fileEffects ?? DEFAULT_FILE_EFFECTS;
|
|
18
|
+
}
|
|
19
|
+
async compact(messages, signal) {
|
|
20
|
+
const files = collectFiles(messages, this.fileEffects);
|
|
21
|
+
const prose = await this.summarise(messages, signal);
|
|
22
|
+
return { ...prose, ...files };
|
|
23
|
+
}
|
|
24
|
+
async summarise(messages, signal) {
|
|
25
|
+
const response = await this.llm.complete({
|
|
26
|
+
systemPrompt: SUMMARY_INSTRUCTIONS,
|
|
27
|
+
messages: [{ role: "user", content: renderTranscript(messages) }],
|
|
28
|
+
tools: [],
|
|
29
|
+
...(signal === undefined ? {} : { signal }),
|
|
30
|
+
});
|
|
31
|
+
return parseSummary(response.message.content);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/** Falls back to the raw text when the model does not return usable JSON. */
|
|
35
|
+
export function parseSummary(content) {
|
|
36
|
+
const fallback = {
|
|
37
|
+
summary: content.trim(),
|
|
38
|
+
decisions: [],
|
|
39
|
+
pendingTasks: [],
|
|
40
|
+
};
|
|
41
|
+
const start = content.indexOf("{");
|
|
42
|
+
const end = content.lastIndexOf("}");
|
|
43
|
+
if (start === -1 || end <= start) {
|
|
44
|
+
return fallback;
|
|
45
|
+
}
|
|
46
|
+
let parsed;
|
|
47
|
+
try {
|
|
48
|
+
parsed = JSON.parse(content.slice(start, end + 1));
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return fallback;
|
|
52
|
+
}
|
|
53
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
54
|
+
return fallback;
|
|
55
|
+
}
|
|
56
|
+
const record = parsed;
|
|
57
|
+
const summary = typeof record.summary === "string" && record.summary.trim().length > 0
|
|
58
|
+
? record.summary.trim()
|
|
59
|
+
: fallback.summary;
|
|
60
|
+
return {
|
|
61
|
+
summary,
|
|
62
|
+
decisions: stringList(record.decisions),
|
|
63
|
+
pendingTasks: stringList(record.pendingTasks),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function stringList(value) {
|
|
67
|
+
if (!Array.isArray(value)) {
|
|
68
|
+
return [];
|
|
69
|
+
}
|
|
70
|
+
return value.filter((entry) => typeof entry === "string" && entry.length > 0);
|
|
71
|
+
}
|
|
72
|
+
function collectFiles(messages, effects) {
|
|
73
|
+
const readFiles = new Set();
|
|
74
|
+
const modifiedFiles = new Set();
|
|
75
|
+
for (const message of messages) {
|
|
76
|
+
if (message.role !== "assistant") {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
for (const call of message.toolCalls) {
|
|
80
|
+
const filePath = pathArgument(call);
|
|
81
|
+
if (filePath === undefined) {
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if (effects.mutates.includes(call.name)) {
|
|
85
|
+
modifiedFiles.add(filePath);
|
|
86
|
+
}
|
|
87
|
+
else if (effects.reads.includes(call.name)) {
|
|
88
|
+
readFiles.add(filePath);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// A file that was changed is more relevant as "changed" than as "read".
|
|
93
|
+
for (const filePath of modifiedFiles) {
|
|
94
|
+
readFiles.delete(filePath);
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
readFiles: [...readFiles].sort(),
|
|
98
|
+
modifiedFiles: [...modifiedFiles].sort(),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function pathArgument(call) {
|
|
102
|
+
if (typeof call.arguments !== "object" || call.arguments === null) {
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
const value = call.arguments.path;
|
|
106
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
107
|
+
}
|
|
108
|
+
function renderTranscript(messages) {
|
|
109
|
+
return messages
|
|
110
|
+
.map((message) => {
|
|
111
|
+
if (message.role === "assistant") {
|
|
112
|
+
const calls = message.toolCalls
|
|
113
|
+
.map((call) => `\n[tool call] ${call.name} ${JSON.stringify(call.arguments)}`)
|
|
114
|
+
.join("");
|
|
115
|
+
return `assistant: ${message.content}${calls}`;
|
|
116
|
+
}
|
|
117
|
+
if (message.role === "tool") {
|
|
118
|
+
return `[tool result] ${message.toolName}${message.isError ? " (error)" : ""}: ${message.content}`;
|
|
119
|
+
}
|
|
120
|
+
return `user: ${message.content}`;
|
|
121
|
+
})
|
|
122
|
+
.join("\n\n");
|
|
123
|
+
}
|
|
124
|
+
/** Renders compaction state as the single message that replaces the history. */
|
|
125
|
+
export function renderCompactionState(state) {
|
|
126
|
+
const sections = [`Summary of earlier work:\n${state.summary}`];
|
|
127
|
+
if (state.readFiles.length > 0) {
|
|
128
|
+
sections.push(`Files read:\n${state.readFiles.map((f) => `- ${f}`).join("\n")}`);
|
|
129
|
+
}
|
|
130
|
+
if (state.modifiedFiles.length > 0) {
|
|
131
|
+
sections.push(`Files modified:\n${state.modifiedFiles.map((f) => `- ${f}`).join("\n")}`);
|
|
132
|
+
}
|
|
133
|
+
if (state.decisions.length > 0) {
|
|
134
|
+
sections.push(`Decisions to respect:\n${state.decisions.map((d) => `- ${d}`).join("\n")}`);
|
|
135
|
+
}
|
|
136
|
+
if (state.pendingTasks.length > 0) {
|
|
137
|
+
sections.push(`Still pending:\n${state.pendingTasks.map((t) => `- ${t}`).join("\n")}`);
|
|
138
|
+
}
|
|
139
|
+
return sections.join("\n\n");
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=compaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compaction.js","sourceRoot":"","sources":["../../src/context/compaction.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { Message } from "../messages.js";
|
|
2
|
+
import { Compactor, type CompactionState } from "./compaction.js";
|
|
3
|
+
import { type TokenEstimator } from "./token-estimator.js";
|
|
4
|
+
export declare const DEFAULT_CONTEXT_WINDOW = 128000;
|
|
5
|
+
export declare const DEFAULT_RESERVE_TOKENS = 16384;
|
|
6
|
+
export declare const DEFAULT_KEEP_RECENT_TOKENS = 20000;
|
|
7
|
+
export interface ContextManagerOptions {
|
|
8
|
+
readonly contextWindow?: number;
|
|
9
|
+
/** Head-room left for the model's own reply and for estimator error. */
|
|
10
|
+
readonly reserveTokens?: number;
|
|
11
|
+
/** Roughly how much recent conversation survives a compaction verbatim. */
|
|
12
|
+
readonly keepRecentTokens?: number;
|
|
13
|
+
readonly estimator?: TokenEstimator;
|
|
14
|
+
/** Omit to disable compaction; the transcript is then passed through. */
|
|
15
|
+
readonly compactor?: Compactor;
|
|
16
|
+
readonly onCompaction?: (event: CompactionEvent) => void;
|
|
17
|
+
}
|
|
18
|
+
export interface CompactionEvent {
|
|
19
|
+
readonly droppedMessages: number;
|
|
20
|
+
readonly tokensBefore: number;
|
|
21
|
+
readonly tokensAfter: number;
|
|
22
|
+
readonly state: CompactionState;
|
|
23
|
+
}
|
|
24
|
+
export interface AppliedCompaction {
|
|
25
|
+
readonly state: CompactionState;
|
|
26
|
+
/** Index into the full transcript where verbatim history resumes. */
|
|
27
|
+
readonly splitIndex: number;
|
|
28
|
+
}
|
|
29
|
+
export interface BuildOptions {
|
|
30
|
+
/** The compaction already in force, so it is not recomputed every turn. */
|
|
31
|
+
readonly previous?: AppliedCompaction;
|
|
32
|
+
readonly signal?: AbortSignal;
|
|
33
|
+
}
|
|
34
|
+
export interface BuiltContext {
|
|
35
|
+
readonly messages: readonly Message[];
|
|
36
|
+
/**
|
|
37
|
+
* True when this call summarised history. Providers that chain history
|
|
38
|
+
* server-side must discard their continuation when this is set: with a
|
|
39
|
+
* continuation they replay their own stored history and ignore the messages
|
|
40
|
+
* in the request, which would carry back the very history just removed.
|
|
41
|
+
*/
|
|
42
|
+
readonly compacted: boolean;
|
|
43
|
+
readonly estimatedTokens: number;
|
|
44
|
+
/** Carry this into the next build to reuse the summary. */
|
|
45
|
+
readonly compaction?: AppliedCompaction;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Decides what the model sees for one request.
|
|
49
|
+
*
|
|
50
|
+
* The session owns what happened; this owns what is worth sending. Keeping
|
|
51
|
+
* them apart is what lets a long session stay inside a fixed context window.
|
|
52
|
+
*/
|
|
53
|
+
export declare class ContextManager {
|
|
54
|
+
private readonly contextWindow;
|
|
55
|
+
private readonly reserveTokens;
|
|
56
|
+
private readonly keepRecentTokens;
|
|
57
|
+
private readonly estimator;
|
|
58
|
+
private readonly compactor?;
|
|
59
|
+
private readonly onCompaction?;
|
|
60
|
+
constructor(options?: ContextManagerOptions);
|
|
61
|
+
get budget(): number;
|
|
62
|
+
build(messages: readonly Message[], options?: BuildOptions): Promise<BuiltContext>;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Chooses where recent history begins.
|
|
66
|
+
*
|
|
67
|
+
* Tool results immediately follow the assistant message that requested them,
|
|
68
|
+
* so a split that lands on a tool result would orphan it. Moving forward past
|
|
69
|
+
* the whole group keeps every tool call and its result on the same side.
|
|
70
|
+
*/
|
|
71
|
+
export declare function findSplitIndex(messages: readonly Message[], estimator: TokenEstimator, keepRecentTokens: number): number;
|
|
72
|
+
//# sourceMappingURL=context-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-manager.d.ts","sourceRoot":"","sources":["../../src/context/context-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EACL,SAAS,EAET,KAAK,eAAe,EACrB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAEL,KAAK,cAAc,EACpB,MAAM,sBAAsB,CAAC;AAE9B,eAAO,MAAM,sBAAsB,SAAU,CAAC;AAC9C,eAAO,MAAM,sBAAsB,QAAS,CAAC;AAC7C,eAAO,MAAM,0BAA0B,QAAS,CAAC;AAEjD,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,wEAAwE;IACxE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,2EAA2E;IAC3E,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,SAAS,CAAC,EAAE,cAAc,CAAC;IACpC,yEAAyE;IACzE,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;IAC/B,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;CAC1D;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;CACjC;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,qEAAqE;IACrE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,2EAA2E;IAC3E,QAAQ,CAAC,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IACtC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CAC/B;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAC;IACtC;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,2DAA2D;IAC3D,QAAQ,CAAC,UAAU,CAAC,EAAE,iBAAiB,CAAC;CACzC;AAED;;;;;GAKG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiB;IAC3C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAY;IACvC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAmC;IAEjE,YAAY,OAAO,GAAE,qBAA0B,EAoB9C;IAED,IAAI,MAAM,IAAI,MAAM,CAEnB;IAEK,KAAK,CACT,QAAQ,EAAE,SAAS,OAAO,EAAE,EAC5B,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,YAAY,CAAC,CAuDvB;CACF;AAMD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,SAAS,OAAO,EAAE,EAC5B,SAAS,EAAE,cAAc,EACzB,gBAAgB,EAAE,MAAM,GACvB,MAAM,CA4BR"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { Compactor, renderCompactionState, } from "./compaction.js";
|
|
2
|
+
import { HeuristicTokenEstimator, } from "./token-estimator.js";
|
|
3
|
+
export const DEFAULT_CONTEXT_WINDOW = 128_000;
|
|
4
|
+
export const DEFAULT_RESERVE_TOKENS = 16_384;
|
|
5
|
+
export const DEFAULT_KEEP_RECENT_TOKENS = 20_000;
|
|
6
|
+
/**
|
|
7
|
+
* Decides what the model sees for one request.
|
|
8
|
+
*
|
|
9
|
+
* The session owns what happened; this owns what is worth sending. Keeping
|
|
10
|
+
* them apart is what lets a long session stay inside a fixed context window.
|
|
11
|
+
*/
|
|
12
|
+
export class ContextManager {
|
|
13
|
+
contextWindow;
|
|
14
|
+
reserveTokens;
|
|
15
|
+
keepRecentTokens;
|
|
16
|
+
estimator;
|
|
17
|
+
compactor;
|
|
18
|
+
onCompaction;
|
|
19
|
+
constructor(options = {}) {
|
|
20
|
+
this.contextWindow = options.contextWindow ?? DEFAULT_CONTEXT_WINDOW;
|
|
21
|
+
// A small window must still leave room to reply, so the fixed reserve is
|
|
22
|
+
// capped at a share of the window rather than applied blindly.
|
|
23
|
+
this.reserveTokens =
|
|
24
|
+
options.reserveTokens ??
|
|
25
|
+
Math.min(DEFAULT_RESERVE_TOKENS, Math.floor(this.contextWindow / 4));
|
|
26
|
+
this.keepRecentTokens =
|
|
27
|
+
options.keepRecentTokens ??
|
|
28
|
+
Math.min(DEFAULT_KEEP_RECENT_TOKENS, Math.floor(this.contextWindow / 2));
|
|
29
|
+
this.estimator = options.estimator ?? new HeuristicTokenEstimator();
|
|
30
|
+
if (options.compactor !== undefined) {
|
|
31
|
+
this.compactor = options.compactor;
|
|
32
|
+
}
|
|
33
|
+
if (options.onCompaction !== undefined) {
|
|
34
|
+
this.onCompaction = options.onCompaction;
|
|
35
|
+
}
|
|
36
|
+
if (this.reserveTokens >= this.contextWindow) {
|
|
37
|
+
throw new TypeError("reserveTokens must be smaller than contextWindow.");
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
get budget() {
|
|
41
|
+
return this.contextWindow - this.reserveTokens;
|
|
42
|
+
}
|
|
43
|
+
async build(messages, options = {}) {
|
|
44
|
+
const previous = options.previous;
|
|
45
|
+
const effective = previous === undefined
|
|
46
|
+
? messages
|
|
47
|
+
: [summaryMessage(previous.state), ...messages.slice(previous.splitIndex)];
|
|
48
|
+
const estimatedTokens = this.estimator.estimateMessages(effective);
|
|
49
|
+
if (this.compactor === undefined || estimatedTokens <= this.budget) {
|
|
50
|
+
return {
|
|
51
|
+
messages: effective,
|
|
52
|
+
compacted: false,
|
|
53
|
+
estimatedTokens,
|
|
54
|
+
...(previous === undefined ? {} : { compaction: previous }),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
const cut = findSplitIndex(effective, this.estimator, this.keepRecentTokens);
|
|
58
|
+
// A cut of zero leaves nothing to summarise; with a previous compaction the
|
|
59
|
+
// cut must also clear the injected summary for progress to be made.
|
|
60
|
+
if (cut <= 0 || (previous !== undefined && cut < 1)) {
|
|
61
|
+
return {
|
|
62
|
+
messages: effective,
|
|
63
|
+
compacted: false,
|
|
64
|
+
estimatedTokens,
|
|
65
|
+
...(previous === undefined ? {} : { compaction: previous }),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
const head = effective.slice(0, cut);
|
|
69
|
+
const tail = effective.slice(cut);
|
|
70
|
+
const state = await this.compactor.compact(head, options.signal);
|
|
71
|
+
const compactedMessages = [summaryMessage(state), ...tail];
|
|
72
|
+
const tokensAfter = this.estimator.estimateMessages(compactedMessages);
|
|
73
|
+
// Map the cut back onto the full transcript, allowing for the summary
|
|
74
|
+
// message that the previous compaction injected at the front.
|
|
75
|
+
const splitIndex = previous === undefined
|
|
76
|
+
? cut
|
|
77
|
+
: previous.splitIndex + (cut - 1);
|
|
78
|
+
this.onCompaction?.({
|
|
79
|
+
droppedMessages: head.length,
|
|
80
|
+
tokensBefore: estimatedTokens,
|
|
81
|
+
tokensAfter,
|
|
82
|
+
state,
|
|
83
|
+
});
|
|
84
|
+
return {
|
|
85
|
+
messages: compactedMessages,
|
|
86
|
+
compacted: true,
|
|
87
|
+
estimatedTokens: tokensAfter,
|
|
88
|
+
compaction: { state, splitIndex },
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function summaryMessage(state) {
|
|
93
|
+
return { role: "user", content: renderCompactionState(state) };
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Chooses where recent history begins.
|
|
97
|
+
*
|
|
98
|
+
* Tool results immediately follow the assistant message that requested them,
|
|
99
|
+
* so a split that lands on a tool result would orphan it. Moving forward past
|
|
100
|
+
* the whole group keeps every tool call and its result on the same side.
|
|
101
|
+
*/
|
|
102
|
+
export function findSplitIndex(messages, estimator, keepRecentTokens) {
|
|
103
|
+
let tokens = 0;
|
|
104
|
+
let index = messages.length;
|
|
105
|
+
while (index > 0) {
|
|
106
|
+
const message = messages[index - 1];
|
|
107
|
+
if (message === undefined) {
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
const cost = estimator.estimateMessage(message);
|
|
111
|
+
if (tokens + cost > keepRecentTokens) {
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
tokens += cost;
|
|
115
|
+
index -= 1;
|
|
116
|
+
}
|
|
117
|
+
while (index < messages.length && messages[index]?.role === "tool") {
|
|
118
|
+
index += 1;
|
|
119
|
+
}
|
|
120
|
+
// Always leave at least one real message after the summary.
|
|
121
|
+
if (index >= messages.length) {
|
|
122
|
+
index = messages.length - 1;
|
|
123
|
+
while (index > 0 && messages[index]?.role === "tool") {
|
|
124
|
+
index -= 1;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return index;
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=context-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-manager.js","sourceRoot":"","sources":["../../src/context/context-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Message } from "../messages.js";
|
|
2
|
+
export interface TokenEstimator {
|
|
3
|
+
estimateMessage(message: Message): number;
|
|
4
|
+
estimateMessages(messages: readonly Message[]): number;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Approximates token counts from character length.
|
|
8
|
+
*
|
|
9
|
+
* A real tokenizer is Provider- and model-specific and would pull in a large
|
|
10
|
+
* dependency for a number that only decides *when* to compact. The reserve
|
|
11
|
+
* budget exists to absorb this estimate's error: overshooting compacts a
|
|
12
|
+
* little early, which costs a summary call rather than a failed request.
|
|
13
|
+
*/
|
|
14
|
+
export declare class HeuristicTokenEstimator implements TokenEstimator {
|
|
15
|
+
private readonly charactersPerToken;
|
|
16
|
+
private readonly messageOverheadTokens;
|
|
17
|
+
constructor(charactersPerToken?: number, messageOverheadTokens?: number);
|
|
18
|
+
estimateMessage(message: Message): number;
|
|
19
|
+
estimateMessages(messages: readonly Message[]): number;
|
|
20
|
+
private textOf;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=token-estimator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-estimator.d.ts","sourceRoot":"","sources":["../../src/context/token-estimator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE9C,MAAM,WAAW,cAAc;IAC7B,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC;IAC1C,gBAAgB,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,MAAM,CAAC;CACxD;AAED;;;;;;;GAOG;AACH,qBAAa,uBAAwB,YAAW,cAAc;IAE1D,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IACnC,OAAO,CAAC,QAAQ,CAAC,qBAAqB;IAFxC,YACmB,kBAAkB,SAAI,EACtB,qBAAqB,SAAI,EAK3C;IAED,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAKxC;IAED,gBAAgB,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,MAAM,CAMrD;IAED,OAAO,CAAC,MAAM;CAYf"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Approximates token counts from character length.
|
|
3
|
+
*
|
|
4
|
+
* A real tokenizer is Provider- and model-specific and would pull in a large
|
|
5
|
+
* dependency for a number that only decides *when* to compact. The reserve
|
|
6
|
+
* budget exists to absorb this estimate's error: overshooting compacts a
|
|
7
|
+
* little early, which costs a summary call rather than a failed request.
|
|
8
|
+
*/
|
|
9
|
+
export class HeuristicTokenEstimator {
|
|
10
|
+
charactersPerToken;
|
|
11
|
+
messageOverheadTokens;
|
|
12
|
+
constructor(charactersPerToken = 4, messageOverheadTokens = 4) {
|
|
13
|
+
this.charactersPerToken = charactersPerToken;
|
|
14
|
+
this.messageOverheadTokens = messageOverheadTokens;
|
|
15
|
+
if (charactersPerToken <= 0) {
|
|
16
|
+
throw new TypeError("charactersPerToken must be positive.");
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
estimateMessage(message) {
|
|
20
|
+
return (this.messageOverheadTokens +
|
|
21
|
+
Math.ceil(this.textOf(message).length / this.charactersPerToken));
|
|
22
|
+
}
|
|
23
|
+
estimateMessages(messages) {
|
|
24
|
+
let total = 0;
|
|
25
|
+
for (const message of messages) {
|
|
26
|
+
total += this.estimateMessage(message);
|
|
27
|
+
}
|
|
28
|
+
return total;
|
|
29
|
+
}
|
|
30
|
+
textOf(message) {
|
|
31
|
+
if (message.role === "assistant") {
|
|
32
|
+
const calls = message.toolCalls
|
|
33
|
+
.map((call) => `${call.name}${JSON.stringify(call.arguments)}`)
|
|
34
|
+
.join("");
|
|
35
|
+
return `${message.content}${calls}`;
|
|
36
|
+
}
|
|
37
|
+
if (message.role === "tool") {
|
|
38
|
+
return `${message.toolName}${message.content}`;
|
|
39
|
+
}
|
|
40
|
+
return message.content;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=token-estimator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-estimator.js","sourceRoot":"","sources":["../../src/context/token-estimator.ts"],"names":[],"mappings":"AAOA;;;;;;;GAOG;AACH,MAAM,OAAO,uBAAuB;IAEf,kBAAkB;IAClB,qBAAqB;IAFxC,YACmB,kBAAkB,GAAG,CAAC,EACtB,qBAAqB,GAAG,CAAC;kCADzB,kBAAkB;qCAClB,qBAAqB;QAEtC,IAAI,kBAAkB,IAAI,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,SAAS,CAAC,sCAAsC,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;IAED,eAAe,CAAC,OAAgB;QAC9B,OAAO,CACL,IAAI,CAAC,qBAAqB;YAC1B,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,kBAAkB,CAAC,CACjE,CAAC;IACJ,CAAC;IAED,gBAAgB,CAAC,QAA4B;QAC3C,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,KAAK,IAAI,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;QACzC,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAEO,MAAM,CAAC,OAAgB;QAC7B,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YACjC,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS;iBAC5B,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;iBAC9D,IAAI,CAAC,EAAE,CAAC,CAAC;YACZ,OAAO,GAAG,OAAO,CAAC,OAAO,GAAG,KAAK,EAAE,CAAC;QACtC,CAAC;QACD,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC5B,OAAO,GAAG,OAAO,CAAC,QAAQ,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;QACjD,CAAC;QACD,OAAO,OAAO,CAAC,OAAO,CAAC;IACzB,CAAC;CACF"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { CliOptions } from "../cli-options.js";
|
|
2
|
+
import type { LLMClient } from "../llm.js";
|
|
3
|
+
import { ProviderRegistry } from "./registry.js";
|
|
4
|
+
import { CredentialResolver } from "../auth/credentials.js";
|
|
5
|
+
/** Returns the configured client, or the message explaining what is missing. */
|
|
6
|
+
export declare function createConfiguredClient(options: CliOptions, registry?: ProviderRegistry, resolver?: CredentialResolver): Promise<LLMClient | string>;
|
|
7
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/providers/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAE3C,OAAO,EAA2B,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAK5D,gFAAgF;AAChF,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,UAAU,EACnB,QAAQ,GAAE,gBAA0C,EACpD,QAAQ,GAAE,kBAAuD,GAChE,OAAO,CAAC,SAAS,GAAG,MAAM,CAAC,CAkC7B"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { RetryingLLMClient } from "../retry.js";
|
|
2
|
+
import { defaultProviderRegistry, ProviderRegistry } from "./registry.js";
|
|
3
|
+
import { CredentialResolver } from "../auth/credentials.js";
|
|
4
|
+
import { RuntimeCredentialSource } from "../auth/runtime-credentials.js";
|
|
5
|
+
import { EnvCredentialSource } from "../auth/env-credentials.js";
|
|
6
|
+
import { defaultAuthFile, FileCredentialSource } from "../auth/file-credentials.js";
|
|
7
|
+
/** Returns the configured client, or the message explaining what is missing. */
|
|
8
|
+
export async function createConfiguredClient(options, registry = defaultProviderRegistry, resolver = defaultCredentialResolver(options)) {
|
|
9
|
+
const definition = registry.get(options.provider);
|
|
10
|
+
if (options.model === undefined) {
|
|
11
|
+
const variables = definition.modelEnvKeys.join(" or ");
|
|
12
|
+
return `--model or ${variables} is required for ${definition.id}.`;
|
|
13
|
+
}
|
|
14
|
+
if (definition.requiresBaseURL && options.baseURL === undefined) {
|
|
15
|
+
const variables = definition.baseUrlEnvKeys.join(" or ");
|
|
16
|
+
return `${variables} is required for ${definition.id}.`;
|
|
17
|
+
}
|
|
18
|
+
let credential;
|
|
19
|
+
try {
|
|
20
|
+
credential = await resolver.resolve(definition);
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
return error instanceof Error ? error.message : String(error);
|
|
24
|
+
}
|
|
25
|
+
if (credential === undefined) {
|
|
26
|
+
return resolver.describeExpectations(definition);
|
|
27
|
+
}
|
|
28
|
+
const client = definition.createClient({
|
|
29
|
+
apiKey: credential.apiKey,
|
|
30
|
+
model: options.model,
|
|
31
|
+
...(options.baseURL === undefined ? {} : { baseURL: options.baseURL }),
|
|
32
|
+
});
|
|
33
|
+
return new RetryingLLMClient(client, {
|
|
34
|
+
onRetry: ({ attempt, delayMs, reason }) => {
|
|
35
|
+
process.stderr.write(`Provider call failed (${reason}); retry ${attempt} in ${delayMs}ms.\n`);
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
function defaultCredentialResolver(options) {
|
|
40
|
+
return new CredentialResolver([
|
|
41
|
+
new RuntimeCredentialSource(options.apiKey),
|
|
42
|
+
new EnvCredentialSource(process.env),
|
|
43
|
+
new FileCredentialSource(defaultAuthFile(process.env), (message) => {
|
|
44
|
+
process.stderr.write(`${message}\n`);
|
|
45
|
+
}),
|
|
46
|
+
]);
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/providers/client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAEpF,gFAAgF;AAChF,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,OAAmB,EACnB,QAAQ,GAAqB,uBAAuB,EACpD,QAAQ,GAAuB,yBAAyB,CAAC,OAAO,CAAC;IAEjE,MAAM,UAAU,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAClD,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAChC,MAAM,SAAS,GAAG,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvD,OAAO,cAAc,SAAS,oBAAoB,UAAU,CAAC,EAAE,GAAG,CAAC;IACrE,CAAC;IACD,IAAI,UAAU,CAAC,eAAe,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAChE,MAAM,SAAS,GAAG,UAAU,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACzD,OAAO,GAAG,SAAS,oBAAoB,UAAU,CAAC,EAAE,GAAG,CAAC;IAC1D,CAAC;IAED,IAAI,UAAU,CAAC;IACf,IAAI,CAAC;QACH,UAAU,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAClD,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAChE,CAAC;IACD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,QAAQ,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC;IACnD,CAAC;IAED,MAAM,MAAM,GAAG,UAAU,CAAC,YAAY,CAAC;QACrC,MAAM,EAAE,UAAU,CAAC,MAAM;QACzB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,GAAG,CAAC,OAAO,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;KACvE,CAAC,CAAC;IAEH,OAAO,IAAI,iBAAiB,CAAC,MAAM,EAAE;QACnC,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE;YACxC,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,yBAAyB,MAAM,YAAY,OAAO,OAAO,OAAO,OAAO,CACxE,CAAC;QACJ,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,SAAS,yBAAyB,CAAC,OAAmB;IACpD,OAAO,IAAI,kBAAkB,CAAC;QAC5B,IAAI,uBAAuB,CAAC,OAAO,CAAC,MAAM,CAAC;QAC3C,IAAI,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC;QACpC,IAAI,oBAAoB,CAAC,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE;YACjE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC;QACvC,CAAC,CAAC;KACH,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { LLMClient } from "../llm.js";
|
|
2
|
+
export interface ProviderClientConfig {
|
|
3
|
+
readonly apiKey: string;
|
|
4
|
+
readonly model: string;
|
|
5
|
+
readonly baseURL?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface ProviderDefinition {
|
|
8
|
+
readonly id: string;
|
|
9
|
+
/** Environment variables searched in order for this Provider's API key. */
|
|
10
|
+
readonly envKeys: readonly string[];
|
|
11
|
+
/** Environment variables searched in order for a default model. */
|
|
12
|
+
readonly modelEnvKeys: readonly string[];
|
|
13
|
+
/** Used when neither --model nor an environment variable supplies one. */
|
|
14
|
+
readonly defaultModel?: string;
|
|
15
|
+
/** Environment variables searched in order for a base URL override. */
|
|
16
|
+
readonly baseUrlEnvKeys: readonly string[];
|
|
17
|
+
readonly defaultBaseURL?: string;
|
|
18
|
+
/** True when the Provider cannot be configured without an explicit model. */
|
|
19
|
+
readonly requiresModel: boolean;
|
|
20
|
+
/** True when the Provider cannot be configured without an explicit base URL. */
|
|
21
|
+
readonly requiresBaseURL: boolean;
|
|
22
|
+
createClient(config: ProviderClientConfig): LLMClient;
|
|
23
|
+
}
|
|
24
|
+
export declare const BUILTIN_PROVIDERS: readonly ProviderDefinition[];
|
|
25
|
+
//# sourceMappingURL=definitions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../src/providers/definitions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAK3C,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,mEAAmE;IACnE,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,0EAA0E;IAC1E,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,uEAAuE;IACvE,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,6EAA6E;IAC7E,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,gFAAgF;IAChF,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,YAAY,CAAC,MAAM,EAAE,oBAAoB,GAAG,SAAS,CAAC;CACvD;AAkCD,eAAO,MAAM,iBAAiB,EAAE,SAAS,kBAAkB,EAqE1D,CAAC"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { OpenAIClient } from "./openai.js";
|
|
2
|
+
import { OpenAICompatibleChatClient } from "./openai-compatible-chat.js";
|
|
3
|
+
import { DeepSeekChatClient } from "./deepseek.js";
|
|
4
|
+
/**
|
|
5
|
+
* Most Providers speak OpenAI-compatible Chat Completions and differ only by
|
|
6
|
+
* base URL, so they are declared rather than implemented.
|
|
7
|
+
*/
|
|
8
|
+
function compatibleProvider(definition) {
|
|
9
|
+
return {
|
|
10
|
+
id: definition.id,
|
|
11
|
+
envKeys: definition.envKeys,
|
|
12
|
+
modelEnvKeys: definition.modelEnvKeys,
|
|
13
|
+
...(definition.defaultModel === undefined
|
|
14
|
+
? {}
|
|
15
|
+
: { defaultModel: definition.defaultModel }),
|
|
16
|
+
baseUrlEnvKeys: [],
|
|
17
|
+
defaultBaseURL: definition.defaultBaseURL,
|
|
18
|
+
requiresModel: definition.defaultModel === undefined,
|
|
19
|
+
requiresBaseURL: false,
|
|
20
|
+
createClient: ({ apiKey, model, baseURL }) => new OpenAICompatibleChatClient({
|
|
21
|
+
apiKey,
|
|
22
|
+
model,
|
|
23
|
+
baseURL: baseURL ?? definition.defaultBaseURL,
|
|
24
|
+
continuationTag: `${definition.id}-chat`,
|
|
25
|
+
}),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export const BUILTIN_PROVIDERS = [
|
|
29
|
+
{
|
|
30
|
+
id: "openai",
|
|
31
|
+
envKeys: ["OPENAI_API_KEY"],
|
|
32
|
+
modelEnvKeys: ["OPENAI_MODEL"],
|
|
33
|
+
defaultModel: "gpt-5.6",
|
|
34
|
+
baseUrlEnvKeys: [],
|
|
35
|
+
requiresModel: false,
|
|
36
|
+
requiresBaseURL: false,
|
|
37
|
+
createClient: ({ apiKey, model }) => new OpenAIClient({ apiKey, model }),
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
id: "deepseek",
|
|
41
|
+
envKeys: ["DEEPSEEK_API_KEY"],
|
|
42
|
+
modelEnvKeys: ["DEEPSEEK_MODEL"],
|
|
43
|
+
defaultModel: "deepseek-v4-flash",
|
|
44
|
+
baseUrlEnvKeys: [],
|
|
45
|
+
requiresModel: false,
|
|
46
|
+
requiresBaseURL: false,
|
|
47
|
+
createClient: ({ apiKey, model, baseURL }) => new DeepSeekChatClient({
|
|
48
|
+
apiKey,
|
|
49
|
+
model,
|
|
50
|
+
...(baseURL === undefined ? {} : { baseURL }),
|
|
51
|
+
}),
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
id: "openai-compatible",
|
|
55
|
+
envKeys: ["OPENAI_API_KEY"],
|
|
56
|
+
modelEnvKeys: ["OPENAI_MODEL"],
|
|
57
|
+
baseUrlEnvKeys: ["OPENAI_BASE_URL"],
|
|
58
|
+
requiresModel: true,
|
|
59
|
+
requiresBaseURL: true,
|
|
60
|
+
createClient: ({ apiKey, model, baseURL }) => {
|
|
61
|
+
if (baseURL === undefined) {
|
|
62
|
+
throw new TypeError("OpenAI-compatible Provider requires a base URL.");
|
|
63
|
+
}
|
|
64
|
+
return new OpenAICompatibleChatClient({
|
|
65
|
+
apiKey,
|
|
66
|
+
model,
|
|
67
|
+
baseURL,
|
|
68
|
+
continuationTag: "openai-compatible-chat",
|
|
69
|
+
});
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
compatibleProvider({
|
|
73
|
+
id: "openrouter",
|
|
74
|
+
envKeys: ["OPENROUTER_API_KEY"],
|
|
75
|
+
modelEnvKeys: ["OPENROUTER_MODEL"],
|
|
76
|
+
defaultBaseURL: "https://openrouter.ai/api/v1",
|
|
77
|
+
}),
|
|
78
|
+
compatibleProvider({
|
|
79
|
+
id: "groq",
|
|
80
|
+
envKeys: ["GROQ_API_KEY"],
|
|
81
|
+
modelEnvKeys: ["GROQ_MODEL"],
|
|
82
|
+
defaultBaseURL: "https://api.groq.com/openai/v1",
|
|
83
|
+
}),
|
|
84
|
+
compatibleProvider({
|
|
85
|
+
id: "xai",
|
|
86
|
+
envKeys: ["XAI_API_KEY"],
|
|
87
|
+
modelEnvKeys: ["XAI_MODEL"],
|
|
88
|
+
defaultBaseURL: "https://api.x.ai/v1",
|
|
89
|
+
}),
|
|
90
|
+
compatibleProvider({
|
|
91
|
+
id: "moonshot",
|
|
92
|
+
envKeys: ["MOONSHOT_API_KEY"],
|
|
93
|
+
modelEnvKeys: ["MOONSHOT_MODEL"],
|
|
94
|
+
defaultBaseURL: "https://api.moonshot.cn/v1",
|
|
95
|
+
}),
|
|
96
|
+
];
|
|
97
|
+
//# sourceMappingURL=definitions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/providers/definitions.ts"],"names":[],"mappings":"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"}
|