@mingyuxu/ai 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ # @mingyuxu/ai
2
+
3
+ doccheck-agent 的统一模型访问层,提供 OpenAI-compatible Provider、多轮工具调用、流式输出、调用预算、用量账本、超时和重试。
4
+
5
+ 通常不需要单独安装;使用 `vet` 请安装 [`doccheck-agent`](https://www.npmjs.com/package/doccheck-agent)。
6
+
7
+ 完整文档与源码:[doccheck-agent](https://github.com/Mingyu-Xu-98/doccheck-agent)
@@ -0,0 +1,17 @@
1
+ /** Budget 护栏 —— LLM 调用/token 硬顶。触顶 → 熔断(可 resume)。 */
2
+ export declare class BudgetExceeded extends Error {
3
+ constructor(message: string);
4
+ }
5
+ export declare class Budget {
6
+ maxLlmCalls: number | null;
7
+ maxTokens: number | null;
8
+ private calls;
9
+ private tokens;
10
+ constructor(opts?: {
11
+ maxLlmCalls?: number | null;
12
+ maxTokens?: number | null;
13
+ });
14
+ charge(calls?: number, tokens?: number): void;
15
+ static fromSpec(budget: Record<string, number>): Budget;
16
+ }
17
+ //# sourceMappingURL=budget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"budget.d.ts","sourceRoot":"","sources":["../src/budget.ts"],"names":[],"mappings":"AAAA,sDAAsD;AAEtD,qBAAa,cAAe,SAAQ,KAAK;gBAC3B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,MAAM;IACjB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,MAAM,CAAK;gBAEP,IAAI,GAAE;QAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAO;IAKjF,MAAM,CAAC,KAAK,SAAI,EAAE,MAAM,SAAI,GAAG,IAAI;IAWnC,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM;CAMxD"}
package/dist/budget.js ADDED
@@ -0,0 +1,34 @@
1
+ /** Budget 护栏 —— LLM 调用/token 硬顶。触顶 → 熔断(可 resume)。 */
2
+ export class BudgetExceeded extends Error {
3
+ constructor(message) {
4
+ super(message);
5
+ this.name = "BudgetExceeded";
6
+ }
7
+ }
8
+ export class Budget {
9
+ maxLlmCalls;
10
+ maxTokens;
11
+ calls = 0;
12
+ tokens = 0;
13
+ constructor(opts = {}) {
14
+ this.maxLlmCalls = opts.maxLlmCalls ?? null;
15
+ this.maxTokens = opts.maxTokens ?? null;
16
+ }
17
+ charge(calls = 0, tokens = 0) {
18
+ this.calls += calls;
19
+ this.tokens += tokens;
20
+ if (this.maxLlmCalls !== null && this.calls > this.maxLlmCalls) {
21
+ throw new BudgetExceeded(`LLM calls ${this.calls} > ${this.maxLlmCalls}`);
22
+ }
23
+ if (this.maxTokens !== null && this.tokens > this.maxTokens) {
24
+ throw new BudgetExceeded(`tokens ${this.tokens} > ${this.maxTokens}`);
25
+ }
26
+ }
27
+ static fromSpec(budget) {
28
+ return new Budget({
29
+ maxLlmCalls: budget.max_llm_calls_per_doc ?? null,
30
+ maxTokens: budget.max_tokens_per_run ?? null,
31
+ });
32
+ }
33
+ }
34
+ //# sourceMappingURL=budget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"budget.js","sourceRoot":"","sources":["../src/budget.ts"],"names":[],"mappings":"AAAA,sDAAsD;AAEtD,MAAM,OAAO,cAAe,SAAQ,KAAK;IACvC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF;AAED,MAAM,OAAO,MAAM;IACjB,WAAW,CAAgB;IAC3B,SAAS,CAAgB;IACjB,KAAK,GAAG,CAAC,CAAC;IACV,MAAM,GAAG,CAAC,CAAC;IAEnB,YAAY,OAAmE,EAAE;QAC/E,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC;QAC5C,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC;IAC1C,CAAC;IAED,MAAM,CAAC,KAAK,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC;QAC1B,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC;QACpB,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC;QACtB,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI,IAAI,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;YAC/D,MAAM,IAAI,cAAc,CAAC,aAAa,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;QAC5E,CAAC;QACD,IAAI,IAAI,CAAC,SAAS,KAAK,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;YAC5D,MAAM,IAAI,cAAc,CAAC,UAAU,IAAI,CAAC,MAAM,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;IAED,MAAM,CAAC,QAAQ,CAAC,MAA8B;QAC5C,OAAO,IAAI,MAAM,CAAC;YAChB,WAAW,EAAE,MAAM,CAAC,qBAAqB,IAAI,IAAI;YACjD,SAAS,EAAE,MAAM,CAAC,kBAAkB,IAAI,IAAI;SAC7C,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -0,0 +1,46 @@
1
+ import type { Message, ToolSchema, ToolCall, ChatResult } from "./providers/base.js";
2
+ import { Ledger } from "./ledger.js";
3
+ /** 7 条铁律 —— worker system 前缀,pack 只能追加不能削弱。 */
4
+ export declare const IRON_RULES: string;
5
+ export type LLMMode = "mock" | "real" | "dry";
6
+ export interface LLMClientOptions {
7
+ mode?: LLMMode;
8
+ baseUrl?: string;
9
+ apiKey?: string;
10
+ model?: string;
11
+ timeoutMs?: number;
12
+ maxRetries?: number;
13
+ ledger?: Ledger;
14
+ provider?: string;
15
+ }
16
+ export type MockFn = () => Record<string, unknown>;
17
+ /** 测试可注入的 chat mock:按当前消息/工具返回本轮助手文本与工具调用。 */
18
+ export type MockChatFn = (messages: Message[], tools: ToolSchema[]) => {
19
+ text?: string;
20
+ toolCalls?: ToolCall[];
21
+ };
22
+ export declare class LLMClient {
23
+ mode: LLMMode;
24
+ model: string;
25
+ ledger?: Ledger;
26
+ readonly providerName: string;
27
+ private timeoutMs;
28
+ private maxRetries;
29
+ private provider;
30
+ constructor(opts?: LLMClientOptions);
31
+ completeJson(system: string, user: string, mockFn?: MockFn): Promise<Record<string, unknown>>;
32
+ /**
33
+ * 多轮对话 + 原生 tool_calls(通用 agent 循环用)。
34
+ * real 走 provider.chat;mock 走注入的 mockFn(驱动确定性测试);dry 返回空。
35
+ * onDelta 提供则请求流式(仅 real 生效)。
36
+ */
37
+ chat(messages: Message[], opts?: {
38
+ tools?: ToolSchema[];
39
+ onDelta?: (t: string) => void;
40
+ onNotice?: (m: string) => void;
41
+ mock?: MockChatFn;
42
+ }): Promise<ChatResult>;
43
+ private charge;
44
+ }
45
+ export declare function parseJsonLoose(text: string): Record<string, unknown>;
46
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACrF,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,+CAA+C;AAC/C,eAAO,MAAM,UAAU,QAQL,CAAC;AAEnB,MAAM,MAAM,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;AAE9C,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACnD,8CAA8C;AAC9C,MAAM,MAAM,UAAU,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAA;CAAE,CAAC;AAEjH,qBAAa,SAAS;IACpB,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAyB;gBAE7B,IAAI,GAAE,gBAAqB;IAejC,YAAY,CAChB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAkBnC;;;;OAIG;IACG,IAAI,CACR,QAAQ,EAAE,OAAO,EAAE,EACnB,IAAI,GAAE;QAAE,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;QAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;QAAC,IAAI,CAAC,EAAE,UAAU,CAAA;KAAO,GACpH,OAAO,CAAC,UAAU,CAAC;IAwBtB,OAAO,CAAC,MAAM;CAGf;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CASpE"}
package/dist/client.js ADDED
@@ -0,0 +1,102 @@
1
+ /**
2
+ * 统一 LLM 客户端(对标 pi-ai 的统一 API)—— real | mock | dry 三态,provider 可换。
3
+ * 从 Python client.py 忠实移植。completeJson(system, user, mockFn?) 是主接口。
4
+ */
5
+ import { getProvider } from "./providers/index.js";
6
+ /** 7 条铁律 —— worker system 前缀,pack 只能追加不能削弱。 */
7
+ export const IRON_RULES = "你是抽取/核查 worker。严格遵守:\n" +
8
+ "1. 只输出 JSON,不要多余文字。\n" +
9
+ "2. 无严格匹配则返回空值,绝不臆造。\n" +
10
+ "3. 逐字复制原文,不改写。\n" +
11
+ "4. 各结果字段相互独立。\n" +
12
+ "5. 去重。\n" +
13
+ "6. 不回显模板占位符。\n" +
14
+ "7. 穷尽扫描给定证据。\n";
15
+ export class LLMClient {
16
+ mode;
17
+ model;
18
+ ledger;
19
+ providerName;
20
+ timeoutMs;
21
+ maxRetries;
22
+ provider = null;
23
+ constructor(opts = {}) {
24
+ this.mode = opts.mode ?? "mock";
25
+ this.model = opts.model ?? "";
26
+ this.ledger = opts.ledger;
27
+ this.timeoutMs = opts.timeoutMs ?? 120_000;
28
+ this.maxRetries = opts.maxRetries ?? 6;
29
+ this.providerName = opts.provider ?? "openai_compatible";
30
+ if (this.mode === "real") {
31
+ this.provider = getProvider(this.providerName, {
32
+ baseUrl: opts.baseUrl,
33
+ apiKey: opts.apiKey,
34
+ });
35
+ }
36
+ }
37
+ async completeJson(system, user, mockFn) {
38
+ if (this.mode === "dry")
39
+ return {};
40
+ if (this.mode === "mock") {
41
+ const out = mockFn ? mockFn() : {};
42
+ this.charge("mock", system.length + user.length, 0);
43
+ return out;
44
+ }
45
+ const { content, usage } = await this.provider.complete({
46
+ system,
47
+ user,
48
+ model: this.model,
49
+ timeoutMs: this.timeoutMs,
50
+ maxRetries: this.maxRetries,
51
+ });
52
+ this.charge(this.model, usage.promptTokens, usage.completionTokens);
53
+ return parseJsonLoose(content);
54
+ }
55
+ /**
56
+ * 多轮对话 + 原生 tool_calls(通用 agent 循环用)。
57
+ * real 走 provider.chat;mock 走注入的 mockFn(驱动确定性测试);dry 返回空。
58
+ * onDelta 提供则请求流式(仅 real 生效)。
59
+ */
60
+ async chat(messages, opts = {}) {
61
+ const tools = opts.tools ?? [];
62
+ if (this.mode === "dry")
63
+ return { text: "", toolCalls: [], usage: { promptTokens: 0, completionTokens: 0 } };
64
+ if (this.mode === "mock") {
65
+ const out = opts.mock ? opts.mock(messages, tools) : {};
66
+ const chars = messages.reduce((n, m) => n + ("content" in m ? String(m.content).length : 0), 0);
67
+ this.charge("mock", chars, 0);
68
+ if (opts.onDelta && out.text)
69
+ opts.onDelta(out.text); // mock 也模拟流式(整段一次增量),行为与 real 一致
70
+ return { text: out.text ?? "", toolCalls: out.toolCalls ?? [], usage: { promptTokens: chars, completionTokens: 0 } };
71
+ }
72
+ if (!this.provider.chat)
73
+ throw new Error(`provider ${this.providerName} 不支持 chat(多轮/tool_calls)`);
74
+ const res = await this.provider.chat({
75
+ messages,
76
+ tools,
77
+ model: this.model,
78
+ timeoutMs: this.timeoutMs,
79
+ maxRetries: this.maxRetries,
80
+ onDelta: opts.onDelta,
81
+ onNotice: opts.onNotice,
82
+ });
83
+ this.charge(this.model, res.usage.promptTokens, res.usage.completionTokens);
84
+ return res;
85
+ }
86
+ charge(model, p, c) {
87
+ this.ledger?.record(model, p, c);
88
+ }
89
+ }
90
+ export function parseJsonLoose(text) {
91
+ try {
92
+ return JSON.parse(text);
93
+ }
94
+ catch {
95
+ const i = text.indexOf("{");
96
+ const j = text.lastIndexOf("}");
97
+ if (i >= 0 && j > i)
98
+ return JSON.parse(text.slice(i, j + 1));
99
+ throw new Error(`not JSON: ${text.slice(0, 80)}`);
100
+ }
101
+ }
102
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @mingyuxu/ai —— 统一多 provider LLM 层(对标 @earendil-works/pi-ai)。
3
+ * 分层底座,零内部依赖(叶子层)。core/check/cli 只依赖这层的 LLMClient/Budget/Ledger。
4
+ */
5
+ export { LLMClient, IRON_RULES, parseJsonLoose } from "./client.js";
6
+ export type { LLMClientOptions, LLMMode, MockFn, MockChatFn } from "./client.js";
7
+ export type { Message, ToolSchema, ToolCall, ChatArgs, ChatResult } from "./providers/base.js";
8
+ export { stripToolTags } from "./providers/openai-compatible.js";
9
+ export { Budget, BudgetExceeded } from "./budget.js";
10
+ export { Ledger } from "./ledger.js";
11
+ export type { LedgerSummary } from "./ledger.js";
12
+ export { getProvider, register, providers, LLMError } from "./providers/index.js";
13
+ export type { Provider, ProviderFactory } from "./providers/index.js";
14
+ export type { CompleteArgs, Usage } from "./providers/base.js";
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACpE,YAAY,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACjF,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC/F,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AACjE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAClF,YAAY,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACtE,YAAY,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @mingyuxu/ai —— 统一多 provider LLM 层(对标 @earendil-works/pi-ai)。
3
+ * 分层底座,零内部依赖(叶子层)。core/check/cli 只依赖这层的 LLMClient/Budget/Ledger。
4
+ */
5
+ export { LLMClient, IRON_RULES, parseJsonLoose } from "./client.js";
6
+ export { stripToolTags } from "./providers/openai-compatible.js";
7
+ export { Budget, BudgetExceeded } from "./budget.js";
8
+ export { Ledger } from "./ledger.js";
9
+ export { getProvider, register, providers, LLMError } from "./providers/index.js";
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAGpE,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AACjE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,24 @@
1
+ /** Token / cost 账本。See it to optimize it —— 每次 LLM 调用记 usage。 */
2
+ export interface LedgerSummary {
3
+ calls: number;
4
+ promptTokens: number;
5
+ completionTokens: number;
6
+ byModel: Record<string, {
7
+ calls: number;
8
+ prompt: number;
9
+ completion: number;
10
+ }>;
11
+ }
12
+ export declare class Ledger {
13
+ calls: number;
14
+ promptTokens: number;
15
+ completionTokens: number;
16
+ byModel: Record<string, {
17
+ calls: number;
18
+ prompt: number;
19
+ completion: number;
20
+ }>;
21
+ record(model: string, promptTokens?: number, completionTokens?: number): void;
22
+ summary(): LedgerSummary;
23
+ }
24
+ //# sourceMappingURL=ledger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledger.d.ts","sourceRoot":"","sources":["../src/ledger.ts"],"names":[],"mappings":"AAAA,iEAAiE;AAEjE,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChF;AAED,qBAAa,MAAM;IACjB,KAAK,SAAK;IACV,YAAY,SAAK;IACjB,gBAAgB,SAAK;IACrB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAM;IAEpF,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,SAAI,EAAE,gBAAgB,SAAI,GAAG,IAAI;IAUnE,OAAO,IAAI,aAAa;CAQzB"}
package/dist/ledger.js ADDED
@@ -0,0 +1,25 @@
1
+ /** Token / cost 账本。See it to optimize it —— 每次 LLM 调用记 usage。 */
2
+ export class Ledger {
3
+ calls = 0;
4
+ promptTokens = 0;
5
+ completionTokens = 0;
6
+ byModel = {};
7
+ record(model, promptTokens = 0, completionTokens = 0) {
8
+ this.calls += 1;
9
+ this.promptTokens += promptTokens;
10
+ this.completionTokens += completionTokens;
11
+ const m = (this.byModel[model] ??= { calls: 0, prompt: 0, completion: 0 });
12
+ m.calls += 1;
13
+ m.prompt += promptTokens;
14
+ m.completion += completionTokens;
15
+ }
16
+ summary() {
17
+ return {
18
+ calls: this.calls,
19
+ promptTokens: this.promptTokens,
20
+ completionTokens: this.completionTokens,
21
+ byModel: this.byModel,
22
+ };
23
+ }
24
+ }
25
+ //# sourceMappingURL=ledger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledger.js","sourceRoot":"","sources":["../src/ledger.ts"],"names":[],"mappings":"AAAA,iEAAiE;AASjE,MAAM,OAAO,MAAM;IACjB,KAAK,GAAG,CAAC,CAAC;IACV,YAAY,GAAG,CAAC,CAAC;IACjB,gBAAgB,GAAG,CAAC,CAAC;IACrB,OAAO,GAA0E,EAAE,CAAC;IAEpF,MAAM,CAAC,KAAa,EAAE,YAAY,GAAG,CAAC,EAAE,gBAAgB,GAAG,CAAC;QAC1D,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC;QAChB,IAAI,CAAC,YAAY,IAAI,YAAY,CAAC;QAClC,IAAI,CAAC,gBAAgB,IAAI,gBAAgB,CAAC;QAC1C,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC;QAC3E,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;QACb,CAAC,CAAC,MAAM,IAAI,YAAY,CAAC;QACzB,CAAC,CAAC,UAAU,IAAI,gBAAgB,CAAC;IACnC,CAAC;IAED,OAAO;QACL,OAAO;YACL,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;YACvC,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Provider 抽象面(对标 pi-ai/api/*:一文件一 provider)。
3
+ *
4
+ * 一个 Provider = 对接一族 LLM API 的适配器。complete() 返回 {content, usage}。
5
+ * 新增 provider = 加一个适配文件 + register,不动 client/core/check。
6
+ */
7
+ export declare class LLMError extends Error {
8
+ constructor(message: string);
9
+ }
10
+ export interface Usage {
11
+ promptTokens: number;
12
+ completionTokens: number;
13
+ }
14
+ export interface CompleteArgs {
15
+ system: string;
16
+ user: string;
17
+ model: string;
18
+ timeoutMs: number;
19
+ maxRetries: number;
20
+ }
21
+ /** 一个工具的可调用契约(OpenAI function schema:name/description/JSON-Schema 参数)。 */
22
+ export interface ToolSchema {
23
+ name: string;
24
+ description: string;
25
+ parameters: Record<string, unknown>;
26
+ }
27
+ /** 模型发起的一次工具调用(arguments 已从 JSON 文本解析为对象)。 */
28
+ export interface ToolCall {
29
+ id: string;
30
+ name: string;
31
+ arguments: Record<string, unknown>;
32
+ }
33
+ /** 对话消息。assistant 可带 toolCalls;tool 回执用 toolCallId 关联。 */
34
+ export type Message = {
35
+ role: "system";
36
+ content: string;
37
+ } | {
38
+ role: "user";
39
+ content: string;
40
+ } | {
41
+ role: "assistant";
42
+ content: string;
43
+ toolCalls?: ToolCall[];
44
+ } | {
45
+ role: "tool";
46
+ toolCallId: string;
47
+ content: string;
48
+ };
49
+ export interface ChatArgs {
50
+ messages: Message[];
51
+ tools?: ToolSchema[];
52
+ model: string;
53
+ timeoutMs: number;
54
+ maxRetries: number;
55
+ /** 提供则请求流式,每段增量文本回调(工具调用不流式,整体解析)。 */
56
+ onDelta?: (text: string) => void;
57
+ /** 限流/重试等运行期提示(让上层能显示,不至于静默假死)。 */
58
+ onNotice?: (msg: string) => void;
59
+ }
60
+ export interface ChatResult {
61
+ /** 本轮助手的自然语言文本(可能为空,若模型只调工具)。 */
62
+ text: string;
63
+ /** 本轮模型请求的工具调用(可能为空,若模型只说话)。 */
64
+ toolCalls: ToolCall[];
65
+ usage: Usage;
66
+ }
67
+ export interface Provider {
68
+ readonly name: string;
69
+ /** 返回 JSON 文本 + usage。传输/协议级失败抛 LLMError。 */
70
+ complete(args: CompleteArgs): Promise<{
71
+ content: string;
72
+ usage: Usage;
73
+ }>;
74
+ /** 多轮 + 原生 tool_calls。可选:老 provider 不实现则通用 agent 不可用。 */
75
+ chat?(args: ChatArgs): Promise<ChatResult>;
76
+ }
77
+ //# sourceMappingURL=base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/providers/base.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,qBAAa,QAAS,SAAQ,KAAK;gBACrB,OAAO,EAAE,MAAM;CAI5B;AAED,MAAM,WAAW,KAAK;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAID,0EAA0E;AAC1E,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAED,8CAA8C;AAC9C,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,0DAA0D;AAC1D,MAAM,MAAM,OAAO,GACf;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAA;CAAE,GAC9D;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1D,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,sCAAsC;IACtC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,mCAAmC;IACnC,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,UAAU;IACzB,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,KAAK,EAAE,KAAK,CAAC;CACd;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,6CAA6C;IAC7C,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC,CAAC;IACzE,yDAAyD;IACzD,IAAI,CAAC,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CAC5C"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Provider 抽象面(对标 pi-ai/api/*:一文件一 provider)。
3
+ *
4
+ * 一个 Provider = 对接一族 LLM API 的适配器。complete() 返回 {content, usage}。
5
+ * 新增 provider = 加一个适配文件 + register,不动 client/core/check。
6
+ */
7
+ export class LLMError extends Error {
8
+ constructor(message) {
9
+ super(message);
10
+ this.name = "LLMError";
11
+ }
12
+ }
13
+ //# sourceMappingURL=base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/providers/base.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,OAAO,QAAS,SAAQ,KAAK;IACjC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Provider 注册表(对标 pi-ai 的多 provider 面)。
3
+ * 新增 provider:写一个 providers/<name>.ts 实现 Provider,然后 register(name, factory)。
4
+ * core/check/cli 只认统一的 LLMClient,加 provider 零波及上层。
5
+ */
6
+ import { Provider } from "./base.js";
7
+ export type ProviderFactory = (cfg: {
8
+ baseUrl?: string;
9
+ apiKey?: string;
10
+ }) => Provider;
11
+ export declare function register(name: string, factory: ProviderFactory): void;
12
+ export declare function getProvider(name: string, cfg?: {
13
+ baseUrl?: string;
14
+ apiKey?: string;
15
+ }): Provider;
16
+ export declare function providers(): string[];
17
+ export { Provider, LLMError } from "./base.js";
18
+ export type { CompleteArgs, Usage } from "./base.js";
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,QAAQ,EAAY,MAAM,WAAW,CAAC;AAG/C,MAAM,MAAM,eAAe,GAAG,CAAC,GAAG,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,KAAK,QAAQ,CAAC;AAIvF,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI,CAErE;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,QAAQ,CAQnG;AAED,wBAAgB,SAAS,IAAI,MAAM,EAAE,CAEpC;AAKD,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC/C,YAAY,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Provider 注册表(对标 pi-ai 的多 provider 面)。
3
+ * 新增 provider:写一个 providers/<name>.ts 实现 Provider,然后 register(name, factory)。
4
+ * core/check/cli 只认统一的 LLMClient,加 provider 零波及上层。
5
+ */
6
+ import { LLMError } from "./base.js";
7
+ import { OpenAICompatibleProvider } from "./openai-compatible.js";
8
+ const REGISTRY = new Map();
9
+ export function register(name, factory) {
10
+ REGISTRY.set(name, factory);
11
+ }
12
+ export function getProvider(name, cfg = {}) {
13
+ const factory = REGISTRY.get(name);
14
+ if (!factory) {
15
+ throw new LLMError(`未知 provider ${name}(已注册:${[...REGISTRY.keys()].sort().join(", ")})——新增 provider 需写适配文件并 register。`);
16
+ }
17
+ return factory(cfg);
18
+ }
19
+ export function providers() {
20
+ return [...REGISTRY.keys()].sort();
21
+ }
22
+ register("openai_compatible", (cfg) => new OpenAICompatibleProvider(cfg));
23
+ // 未来:register("anthropic", ...) / register("google", ...)
24
+ export { LLMError } from "./base.js";
25
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAY,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAIlE,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA2B,CAAC;AAEpD,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,OAAwB;IAC7D,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,MAA6C,EAAE;IACvF,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACnC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,QAAQ,CAChB,eAAe,IAAI,QAAQ,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,kCAAkC,CACpG,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AACrC,CAAC;AAED,QAAQ,CAAC,mBAAmB,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,wBAAwB,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1E,0DAA0D;AAE1D,OAAO,EAAY,QAAQ,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * OpenAI 兼容 provider —— /chat/completions,temperature 0,json_object,分型退避。
3
+ * 用 Node 全局 fetch(零第三方依赖)。SiliconFlow / DeepSeek / vLLM 等都走这里。
4
+ * 从 Python openai_compatible.py 忠实移植(重试语义一致)。
5
+ */
6
+ import { Provider, CompleteArgs, Usage, ChatArgs, ChatResult } from "./base.js";
7
+ export declare class OpenAICompatibleProvider implements Provider {
8
+ readonly name = "openai_compatible";
9
+ private baseUrl;
10
+ private apiKey;
11
+ constructor(cfg?: {
12
+ baseUrl?: string;
13
+ apiKey?: string;
14
+ });
15
+ complete(args: CompleteArgs): Promise<{
16
+ content: string;
17
+ usage: Usage;
18
+ }>;
19
+ chat(args: ChatArgs): Promise<ChatResult>;
20
+ /** 解析 SSE 流:累积文本增量与分片到达的 tool_calls(按 index 归并 arguments)。 */
21
+ private readStream;
22
+ }
23
+ /**
24
+ * 去掉部分模型(如 SiliconFlow 上的 Qwen)漏进 content 的工具调用碎片:
25
+ * 成对 <tool_call>…</tool_call>、未闭合的尾部 <tool_call>…、以及落单的 </tool_call>。
26
+ * 原生 tool_calls 字段才是我们执行的依据,这些文本是冗余噪声。
27
+ */
28
+ export declare function stripToolTags(s: string): string;
29
+ //# sourceMappingURL=openai-compatible.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-compatible.d.ts","sourceRoot":"","sources":["../../src/providers/openai-compatible.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAY,QAAQ,EAAE,UAAU,EAAqB,MAAM,WAAW,CAAC;AAI7G,qBAAa,wBAAyB,YAAW,QAAQ;IACvD,QAAQ,CAAC,IAAI,uBAAuB;IACpC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAS;gBAEX,GAAG,GAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO;IAKrD,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC;IA0DxE,IAAI,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IA2C/C,8DAA8D;YAChD,UAAU;CAkDzB;AA+BD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAK/C"}
@@ -0,0 +1,267 @@
1
+ /**
2
+ * OpenAI 兼容 provider —— /chat/completions,temperature 0,json_object,分型退避。
3
+ * 用 Node 全局 fetch(零第三方依赖)。SiliconFlow / DeepSeek / vLLM 等都走这里。
4
+ * 从 Python openai_compatible.py 忠实移植(重试语义一致)。
5
+ */
6
+ import { LLMError } from "./base.js";
7
+ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
8
+ export class OpenAICompatibleProvider {
9
+ name = "openai_compatible";
10
+ baseUrl;
11
+ apiKey;
12
+ constructor(cfg = {}) {
13
+ this.baseUrl = (cfg.baseUrl ?? "").replace(/\/+$/, "");
14
+ this.apiKey = cfg.apiKey ?? "";
15
+ }
16
+ async complete(args) {
17
+ const body = JSON.stringify({
18
+ model: args.model,
19
+ temperature: 0,
20
+ response_format: { type: "json_object" },
21
+ messages: [
22
+ { role: "system", content: args.system },
23
+ { role: "user", content: args.user },
24
+ ],
25
+ });
26
+ let last = null;
27
+ for (let attempt = 0; attempt <= args.maxRetries; attempt++) {
28
+ const ctrl = new AbortController();
29
+ const timer = setTimeout(() => ctrl.abort(), args.timeoutMs);
30
+ try {
31
+ const resp = await fetch(`${this.baseUrl}/chat/completions`, {
32
+ method: "POST",
33
+ headers: {
34
+ "Content-Type": "application/json",
35
+ Authorization: `Bearer ${this.apiKey}`,
36
+ },
37
+ body,
38
+ signal: ctrl.signal,
39
+ });
40
+ if (!resp.ok) {
41
+ if (resp.status === 429) {
42
+ await sleep(retryAfter(resp, attempt) * 1000);
43
+ last = new Error(`HTTP 429`);
44
+ continue;
45
+ }
46
+ if (resp.status >= 500 && resp.status < 600) {
47
+ await sleep(2 ** attempt * 1000);
48
+ last = new Error(`HTTP ${resp.status}`);
49
+ continue;
50
+ }
51
+ throw new LLMError(`HTTP ${resp.status}: ${resp.statusText}`); // 4xx: no retry
52
+ }
53
+ const data = await resp.json();
54
+ const usage = data.usage ?? {};
55
+ const content = data.choices?.[0]?.message?.content ?? "";
56
+ return {
57
+ content,
58
+ usage: {
59
+ promptTokens: usage.prompt_tokens ?? 0,
60
+ completionTokens: usage.completion_tokens ?? 0,
61
+ },
62
+ };
63
+ }
64
+ catch (e) {
65
+ if (e instanceof LLMError)
66
+ throw e;
67
+ last = e; // network / abort → 退避重试
68
+ await sleep(2 ** attempt * 1000);
69
+ }
70
+ finally {
71
+ clearTimeout(timer);
72
+ }
73
+ }
74
+ throw new LLMError(`exhausted retries: ${String(last)}`);
75
+ }
76
+ async chat(args) {
77
+ const stream = Boolean(args.onDelta);
78
+ const payload = {
79
+ model: args.model,
80
+ temperature: 0,
81
+ messages: args.messages.map(toApiMessage),
82
+ stream,
83
+ };
84
+ if (args.tools?.length) {
85
+ payload.tools = args.tools.map((t) => ({ type: "function", function: { name: t.name, description: t.description, parameters: t.parameters } }));
86
+ payload.tool_choice = "auto";
87
+ }
88
+ if (stream)
89
+ payload.stream_options = { include_usage: true };
90
+ const body = JSON.stringify(payload);
91
+ let last = null;
92
+ for (let attempt = 0; attempt <= args.maxRetries; attempt++) {
93
+ const ctrl = new AbortController();
94
+ const timer = setTimeout(() => ctrl.abort(), args.timeoutMs);
95
+ try {
96
+ const resp = await fetch(`${this.baseUrl}/chat/completions`, {
97
+ method: "POST",
98
+ headers: { "Content-Type": "application/json", Authorization: `Bearer ${this.apiKey}` },
99
+ body,
100
+ signal: ctrl.signal,
101
+ });
102
+ if (!resp.ok) {
103
+ if (resp.status === 429) {
104
+ const w = retryAfter(resp, attempt);
105
+ args.onNotice?.(`服务端限流(429),${w}s 后重试(${attempt + 1}/${args.maxRetries + 1})`);
106
+ await sleep(w * 1000);
107
+ last = new Error("HTTP 429");
108
+ continue;
109
+ }
110
+ if (resp.status >= 500 && resp.status < 600) {
111
+ const w = Math.min(2 ** attempt * 2, 20);
112
+ args.onNotice?.(`服务端 ${resp.status},${w}s 后重试(${attempt + 1}/${args.maxRetries + 1})`);
113
+ await sleep(w * 1000);
114
+ last = new Error(`HTTP ${resp.status}`);
115
+ continue;
116
+ }
117
+ throw new LLMError(`HTTP ${resp.status}: ${resp.statusText}`); // 4xx: no retry
118
+ }
119
+ return stream ? await this.readStream(resp, args.onDelta) : parseChatBody(await resp.json());
120
+ }
121
+ catch (e) {
122
+ if (e instanceof LLMError)
123
+ throw e;
124
+ last = e;
125
+ await sleep(2 ** attempt * 1000);
126
+ }
127
+ finally {
128
+ clearTimeout(timer);
129
+ }
130
+ }
131
+ throw new LLMError(`exhausted retries: ${String(last)}`);
132
+ }
133
+ /** 解析 SSE 流:累积文本增量与分片到达的 tool_calls(按 index 归并 arguments)。 */
134
+ async readStream(resp, onDelta) {
135
+ const reader = resp.body?.getReader();
136
+ if (!reader)
137
+ throw new LLMError("流式响应无 body");
138
+ const decoder = new TextDecoder();
139
+ let buf = "";
140
+ let raw = ""; // 原始 content 累积(含可能的 <tool_call> 噪声)
141
+ let shown = 0; // 已 onDelta 出去的干净文本长度
142
+ const GUARD = 12; // 尾部留一小段不发,避免把半个 <tool_call> 标签当正文吐出
143
+ const emit = (final) => {
144
+ const clean = stripToolTags(raw);
145
+ const to = final ? clean.length : Math.max(shown, clean.length - GUARD);
146
+ if (to > shown) {
147
+ onDelta(clean.slice(shown, to));
148
+ shown = to;
149
+ }
150
+ };
151
+ const calls = new Map();
152
+ let usage = { promptTokens: 0, completionTokens: 0 };
153
+ let done = false;
154
+ // 见到 [DONE] 立即收尾并 cancel(有些 OpenAI 兼容服务 keep-alive,不主动关流,
155
+ // 若只等 reader 结束会永久阻塞)。
156
+ outer: for (;;) {
157
+ const { done: streamEnd, value } = await reader.read();
158
+ if (streamEnd)
159
+ break;
160
+ buf += decoder.decode(value, { stream: true });
161
+ let nl;
162
+ while ((nl = buf.indexOf("\n")) >= 0) {
163
+ const line = buf.slice(0, nl).trim();
164
+ buf = buf.slice(nl + 1);
165
+ if (!line.startsWith("data:"))
166
+ continue;
167
+ const data = line.slice(5).trim();
168
+ if (data === "[DONE]") {
169
+ done = true;
170
+ break outer;
171
+ }
172
+ let chunk;
173
+ try {
174
+ chunk = JSON.parse(data);
175
+ }
176
+ catch {
177
+ continue;
178
+ }
179
+ if (chunk.usage)
180
+ usage = { promptTokens: chunk.usage.prompt_tokens ?? 0, completionTokens: chunk.usage.completion_tokens ?? 0 };
181
+ const delta = chunk.choices?.[0]?.delta;
182
+ if (!delta)
183
+ continue;
184
+ if (typeof delta.content === "string" && delta.content) {
185
+ raw += delta.content;
186
+ emit(false);
187
+ }
188
+ for (const tc of delta.tool_calls ?? []) {
189
+ const slot = calls.get(tc.index) ?? { id: "", name: "", args: "" };
190
+ if (tc.id)
191
+ slot.id = tc.id;
192
+ if (tc.function?.name)
193
+ slot.name = tc.function.name;
194
+ if (tc.function?.arguments)
195
+ slot.args += tc.function.arguments;
196
+ calls.set(tc.index, slot);
197
+ }
198
+ }
199
+ }
200
+ if (done) {
201
+ try {
202
+ await reader.cancel();
203
+ }
204
+ catch { /* 已关则忽略 */ }
205
+ }
206
+ emit(true); // flush 尾部保留窗口
207
+ const toolCalls = [...calls.values()].filter((c) => c.name)
208
+ .map((c, i) => ({ id: c.id || `call_${i}`, name: c.name, arguments: parseArgs(c.args) }));
209
+ return { text: stripToolTags(raw), toolCalls, usage };
210
+ }
211
+ }
212
+ /** kc 内部 Message → OpenAI /chat/completions 消息格式。 */
213
+ function toApiMessage(m) {
214
+ if (m.role === "assistant") {
215
+ const out = { role: "assistant", content: m.content || null };
216
+ if (m.toolCalls?.length) {
217
+ out.tool_calls = m.toolCalls.map((t) => ({ id: t.id, type: "function", function: { name: t.name, arguments: JSON.stringify(t.arguments) } }));
218
+ }
219
+ return out;
220
+ }
221
+ if (m.role === "tool")
222
+ return { role: "tool", tool_call_id: m.toolCallId, content: m.content };
223
+ return { role: m.role, content: m.content };
224
+ }
225
+ /** 非流式响应体 → ChatResult。 */
226
+ function parseChatBody(data) {
227
+ const msg = data.choices?.[0]?.message ?? {};
228
+ const u = data.usage ?? {};
229
+ const toolCalls = (msg.tool_calls ?? []).map((t, i) => ({
230
+ id: t.id || `call_${i}`,
231
+ name: t.function?.name ?? "",
232
+ arguments: parseArgs(t.function?.arguments ?? "{}"),
233
+ })).filter((t) => t.name);
234
+ return {
235
+ text: stripToolTags(msg.content ?? ""),
236
+ toolCalls,
237
+ usage: { promptTokens: u.prompt_tokens ?? 0, completionTokens: u.completion_tokens ?? 0 },
238
+ };
239
+ }
240
+ /**
241
+ * 去掉部分模型(如 SiliconFlow 上的 Qwen)漏进 content 的工具调用碎片:
242
+ * 成对 <tool_call>…</tool_call>、未闭合的尾部 <tool_call>…、以及落单的 </tool_call>。
243
+ * 原生 tool_calls 字段才是我们执行的依据,这些文本是冗余噪声。
244
+ */
245
+ export function stripToolTags(s) {
246
+ return s
247
+ .replace(/<tool_call>[\s\S]*?<\/tool_call>/g, "")
248
+ .replace(/<tool_call>[\s\S]*$/g, "")
249
+ .replace(/<\/tool_call>/g, "");
250
+ }
251
+ function parseArgs(s) {
252
+ if (!s)
253
+ return {};
254
+ try {
255
+ const v = JSON.parse(s);
256
+ return v && typeof v === "object" ? v : {};
257
+ }
258
+ catch {
259
+ return {};
260
+ }
261
+ }
262
+ function retryAfter(resp, attempt) {
263
+ const h = resp.headers.get("retry-after");
264
+ const n = h ? Number(h) : NaN;
265
+ return Number.isFinite(n) ? n : Math.min(5 * (attempt + 1), 20); // 无 Retry-After:5,10,15,20,20,20(交互可接受)
266
+ }
267
+ //# sourceMappingURL=openai-compatible.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-compatible.js","sourceRoot":"","sources":["../../src/providers/openai-compatible.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@mingyuxu/ai",
3
+ "version": "0.1.0",
4
+ "description": "统一多 provider LLM 层(对标 @earendil-works/pi-ai)",
5
+ "keywords": ["agent", "llm", "tool-calling", "openai-compatible"],
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/Mingyu-Xu-98/doccheck-agent.git",
9
+ "directory": "packages/ai"
10
+ },
11
+ "homepage": "https://github.com/Mingyu-Xu-98/doccheck-agent#readme",
12
+ "bugs": { "url": "https://github.com/Mingyu-Xu-98/doccheck-agent/issues" },
13
+ "engines": { "node": ">=20" },
14
+ "type": "module",
15
+ "main": "./dist/index.js",
16
+ "types": "./dist/index.d.ts",
17
+ "exports": {
18
+ ".": "./dist/index.js"
19
+ },
20
+ "scripts": {
21
+ "build": "tsc --build",
22
+ "prepublishOnly": "npm run build"
23
+ },
24
+ "files": [
25
+ "dist"
26
+ ],
27
+ "publishConfig": {
28
+ "access": "public",
29
+ "registry": "https://registry.npmjs.org"
30
+ }
31
+ }