@yh-ui/ai-sdk 0.1.21

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.
@@ -0,0 +1,143 @@
1
+ /**
2
+ * YH-UI AI SDK - 增强版 Agent
3
+ *
4
+ * 支持多种推理模式:
5
+ * - Reflexion: 自我反思,从错误中学习
6
+ * - ReWOO: 分离推理与工具调用
7
+ * - LCEL 风格链式编排
8
+ */
9
+ import { type Ref } from 'vue';
10
+ import type { AgentStep, AgentTool, AgentResult, StopCondition } from './future';
11
+ /** Agent 推理模式 */
12
+ export type ReasoningMode = 'react' | 'reflexion' | 'rewoo' | 'plan-execute';
13
+ /** 增强版 Agent 配置 */
14
+ export interface EnhancedAgentConfig {
15
+ /** 推理模式 */
16
+ mode: ReasoningMode;
17
+ /** 最大迭代次数 */
18
+ maxIterations?: number;
19
+ /** 最大工具调用次数 */
20
+ maxToolCalls?: number;
21
+ /** 是否返回推理过程 */
22
+ returnReasoning?: boolean;
23
+ /** 工具列表 */
24
+ tools?: AgentTool[];
25
+ /** 停止条件 */
26
+ stopConditions?: StopCondition[];
27
+ /** 反思次数(Reflexion 专用) */
28
+ maxReflections?: number;
29
+ /** 错误处理 */
30
+ onError?: (error: Error, step: AgentStep) => void | Promise<void>;
31
+ }
32
+ /** LCEL 链步骤 */
33
+ export interface ChainStep {
34
+ name: string;
35
+ handler: (input: unknown) => unknown | Promise<unknown>;
36
+ onError?: (error: Error) => void;
37
+ }
38
+ /** LCEL 链 */
39
+ export interface Chain {
40
+ pipe(step: ChainStep): Chain;
41
+ invoke(input: unknown): Promise<unknown>;
42
+ }
43
+ /**
44
+ * 创建 LCEL 风格链
45
+ *
46
+ * @example
47
+ * ```ts
48
+ * const chain = createChain()
49
+ * .pipe({ name: 'parse', handler: async (input) => JSON.parse(input as string) })
50
+ * .pipe({ name: 'validate', handler: async (input) => { if (!input) throw new Error('Empty'); return input } })
51
+ * .pipe({ name: 'transform', handler: async (input) => ({ data: input }) })
52
+ *
53
+ * const result = await chain.invoke('{"a":1}')
54
+ * ```
55
+ */
56
+ export declare function createChain(initialHandler?: (input: unknown) => unknown | Promise<unknown>): Chain;
57
+ /**
58
+ * 创建并行链(类似 LangChain RunnableParallel)
59
+ */
60
+ export declare function createParallelChain(steps: Record<string, (input: unknown) => unknown | Promise<unknown>>): Chain;
61
+ /**
62
+ * Reflexion Agent 配置
63
+ */
64
+ export interface ReflexionConfig extends Omit<EnhancedAgentConfig, 'mode'> {
65
+ mode: 'reflexion';
66
+ /** 记忆上下文窗口大小 */
67
+ memoryWindow?: number;
68
+ }
69
+ /**
70
+ * 创建 Reflexion Agent
71
+ * 特点:执行后进行自我反思,从错误中学习并改进下一步
72
+ */
73
+ export declare function createReflexionAgent(config: ReflexionConfig): {
74
+ run: (input: string, executeFn: (prompt: string) => Promise<string>, toolFn?: (toolName: string, args: Record<string, unknown>) => Promise<string>) => Promise<AgentResult>;
75
+ steps: Ref<AgentStep[]>;
76
+ reflections: Ref<string[]>;
77
+ isRunning: Ref<boolean, boolean>;
78
+ };
79
+ /**
80
+ * ReWOO Agent 配置
81
+ */
82
+ export interface ReWOOConfig extends Omit<EnhancedAgentConfig, 'mode'> {
83
+ mode: 'rewoo';
84
+ /** 计划生成器 */
85
+ planner?: (task: string) => Promise<{
86
+ steps: Array<{
87
+ id: string;
88
+ description: string;
89
+ dependentIds: string[];
90
+ }>;
91
+ }>;
92
+ }
93
+ /**
94
+ * 创建 ReWOO Agent
95
+ * 特点:先制定完整计划,再批量执行工具,最后基于所有结果生成答案
96
+ */
97
+ export declare function createReWOOAgent(config: ReWOOConfig): {
98
+ run: (input: string, executeFn: (prompt: string) => Promise<string>) => Promise<AgentResult>;
99
+ steps: Ref<AgentStep[]>;
100
+ plan: Ref<Array<{
101
+ id: string;
102
+ description: string;
103
+ result?: string;
104
+ }>>;
105
+ isRunning: Ref<boolean, boolean>;
106
+ };
107
+ /**
108
+ * 创建增强版 Agent(工厂函数)
109
+ *
110
+ * @example
111
+ * ```ts
112
+ * // Reflexion
113
+ * const agent = createEnhancedAgent({
114
+ * mode: 'reflexion',
115
+ * maxIterations: 5,
116
+ * tools: [...]
117
+ * })
118
+ *
119
+ * // ReWOO
120
+ * const agent = createEnhancedAgent({
121
+ * mode: 'rewoo',
122
+ * maxIterations: 10,
123
+ * tools: [...]
124
+ * })
125
+ *
126
+ * const result = await agent.run('任务描述', llmCall, toolCall)
127
+ * ```
128
+ */
129
+ export declare function createEnhancedAgent(config: EnhancedAgentConfig): {
130
+ run: (input: string, executeFn: (prompt: string) => Promise<string>, toolFn?: (toolName: string, args: Record<string, unknown>) => Promise<string>) => Promise<AgentResult>;
131
+ steps: Ref<AgentStep[]>;
132
+ reflections: Ref<string[]>;
133
+ isRunning: Ref<boolean, boolean>;
134
+ } | {
135
+ run: (input: string, executeFn: (prompt: string) => Promise<string>) => Promise<AgentResult>;
136
+ steps: Ref<AgentStep[]>;
137
+ plan: Ref<Array<{
138
+ id: string;
139
+ description: string;
140
+ result?: string;
141
+ }>>;
142
+ isRunning: Ref<boolean, boolean>;
143
+ };
@@ -0,0 +1,267 @@
1
+ import { ref } from "vue";
2
+ export function createChain(initialHandler) {
3
+ const steps = [];
4
+ if (initialHandler) {
5
+ steps.push({ name: "initial", handler: initialHandler });
6
+ }
7
+ return {
8
+ pipe(step) {
9
+ steps.push(step);
10
+ return this;
11
+ },
12
+ async invoke(input) {
13
+ let current = input;
14
+ for (const step of steps) {
15
+ try {
16
+ current = await step.handler(current);
17
+ } catch (err) {
18
+ if (step.onError) {
19
+ step.onError(err);
20
+ } else {
21
+ throw err;
22
+ }
23
+ }
24
+ }
25
+ return current;
26
+ }
27
+ };
28
+ }
29
+ export function createParallelChain(steps) {
30
+ return {
31
+ pipe(step) {
32
+ steps[step.name] = step.handler;
33
+ return this;
34
+ },
35
+ async invoke(input) {
36
+ const results = {};
37
+ const promises = Object.entries(steps).map(async ([key, handler]) => {
38
+ results[key] = await handler(input);
39
+ });
40
+ await Promise.all(promises);
41
+ return results;
42
+ }
43
+ };
44
+ }
45
+ export function createReflexionAgent(config) {
46
+ const {
47
+ maxIterations = 5,
48
+ returnReasoning = true,
49
+ stopConditions = [],
50
+ memoryWindow = 3,
51
+ onError
52
+ } = config;
53
+ const steps = ref([]);
54
+ const reflections = ref([]);
55
+ const isRunning = ref(false);
56
+ async function run(input, executeFn, toolFn) {
57
+ isRunning.value = true;
58
+ steps.value = [];
59
+ reflections.value = [];
60
+ let iteration = 0;
61
+ let currentInput = input;
62
+ let bestOutput = "";
63
+ let bestScore = -Infinity;
64
+ try {
65
+ while (iteration < maxIterations) {
66
+ iteration++;
67
+ const prompt = buildPrompt(currentInput, reflections.value);
68
+ const response = await executeFn(prompt);
69
+ let toolResult = "";
70
+ const actionMatch = response.match(/Action:\s*(\w+)\s*[\n\r]Action Input:\s*(.+)/);
71
+ if (actionMatch && toolFn) {
72
+ const [, toolName, toolInputStr] = actionMatch;
73
+ try {
74
+ const toolInput = JSON.parse(toolInputStr);
75
+ toolResult = await toolFn(toolName, toolInput);
76
+ } catch {
77
+ toolResult = `Failed to parse: ${toolInputStr}`;
78
+ }
79
+ }
80
+ steps.value.push({
81
+ id: `step-${iteration}`,
82
+ type: "thought",
83
+ content: response,
84
+ timestamp: /* @__PURE__ */ new Date()
85
+ });
86
+ if (toolResult) {
87
+ steps.value.push({
88
+ id: `step-${iteration}-obs`,
89
+ type: "observation",
90
+ content: toolResult,
91
+ timestamp: /* @__PURE__ */ new Date()
92
+ });
93
+ }
94
+ const score = await evaluateOutput(response + toolResult);
95
+ if (score > bestScore) {
96
+ bestScore = score;
97
+ bestOutput = response + (toolResult ? `
98
+
99
+ Observation: ${toolResult}` : "");
100
+ }
101
+ if (iteration < maxIterations) {
102
+ const reflection = await reflect(currentInput, response, toolResult, score);
103
+ reflections.value.push(reflection);
104
+ if (reflections.value.length > memoryWindow) {
105
+ reflections.value.shift();
106
+ }
107
+ currentInput = `${input}
108
+
109
+ Previous attempts:
110
+ ${reflections.value.join("\n---\n")}`;
111
+ }
112
+ if (checkStop("", bestOutput)) break;
113
+ }
114
+ return {
115
+ output: bestOutput,
116
+ reasoning: returnReasoning ? steps.value : void 0,
117
+ toolCalls: iteration,
118
+ finished: iteration >= maxIterations
119
+ };
120
+ } catch (err) {
121
+ if (onError) await onError(err, steps.value[steps.value.length - 1]);
122
+ return {
123
+ output: bestOutput,
124
+ reasoning: returnReasoning ? steps.value : void 0,
125
+ toolCalls: iteration,
126
+ finished: false,
127
+ error: err
128
+ };
129
+ } finally {
130
+ isRunning.value = false;
131
+ }
132
+ }
133
+ function buildPrompt(input, reflections2) {
134
+ let prompt = `Task: ${input}
135
+ `;
136
+ if (reflections2.length > 0) {
137
+ prompt += `
138
+ Previous reflections:
139
+ ${reflections2.join("\n")}
140
+ `;
141
+ }
142
+ prompt += "\nProvide your reasoning and any tool actions (Action: toolName\nAction Input: {...}).";
143
+ return prompt;
144
+ }
145
+ async function reflect(task, response, toolResult, score) {
146
+ return `Attempt ${steps.value.length}: ${score < 5 ? "Need to try different approach" : "Making progress"}`;
147
+ }
148
+ async function evaluateOutput(output) {
149
+ return output.length > 10 ? 5 + Math.random() * 5 : Math.random() * 5;
150
+ }
151
+ function checkStop(iterationOutput, bestOutput) {
152
+ for (const cond of stopConditions) {
153
+ if (cond.type === "contains" && cond.value) {
154
+ if (bestOutput.includes(cond.value)) return true;
155
+ }
156
+ if (cond.type === "custom" && cond.value) {
157
+ if (cond.value(bestOutput)) return true;
158
+ }
159
+ }
160
+ return false;
161
+ }
162
+ return {
163
+ run,
164
+ steps,
165
+ reflections,
166
+ isRunning
167
+ };
168
+ }
169
+ export function createReWOOAgent(config) {
170
+ const { returnReasoning = true, onError } = config;
171
+ const steps = ref([]);
172
+ const plan = ref([]);
173
+ const isRunning = ref(false);
174
+ const defaultPlanner = async (task) => {
175
+ return {
176
+ steps: [
177
+ { id: "1", description: `Analyze: ${task.slice(0, 50)}`, dependentIds: [] },
178
+ { id: "2", description: `Gather info for: ${task.slice(0, 50)}`, dependentIds: ["1"] },
179
+ { id: "3", description: `Answer: ${task.slice(0, 50)}`, dependentIds: ["1", "2"] }
180
+ ]
181
+ };
182
+ };
183
+ async function run(input, executeFn) {
184
+ isRunning.value = true;
185
+ steps.value = [];
186
+ plan.value = [];
187
+ try {
188
+ const planner = config.planner || defaultPlanner;
189
+ const planResult = await planner(input);
190
+ plan.value = planResult.steps;
191
+ steps.value.push({
192
+ id: "plan-thought",
193
+ type: "thought",
194
+ content: `Generated plan with ${planResult.steps.length} steps`,
195
+ timestamp: /* @__PURE__ */ new Date()
196
+ });
197
+ const results = {};
198
+ const executed = /* @__PURE__ */ new Set();
199
+ while (executed.size < plan.value.length) {
200
+ const readyStep = plan.value.find(
201
+ (s) => !executed.has(s.id) && s.dependentIds.every((depId) => executed.has(depId))
202
+ );
203
+ if (!readyStep) break;
204
+ const context = Object.entries(results).filter(([id]) => readyStep.dependentIds.includes(id)).map(([, res]) => res).join("\n\n");
205
+ const stepPrompt = `Step: ${readyStep.description}
206
+ Context: ${context || "No prior context"}
207
+ Execute this step and provide the result.`;
208
+ const stepResult = await executeFn(stepPrompt);
209
+ results[readyStep.id] = stepResult;
210
+ executed.add(readyStep.id);
211
+ steps.value.push({
212
+ id: `step-${readyStep.id}`,
213
+ type: "action",
214
+ content: readyStep.description,
215
+ toolOutput: stepResult,
216
+ timestamp: /* @__PURE__ */ new Date()
217
+ });
218
+ }
219
+ const finalPrompt = `Original Task: ${input}
220
+
221
+ Execution Results:
222
+ ${Object.entries(results).map(([id, res]) => `Step ${id}: ${res}`).join("\n\n")}
223
+
224
+ Based on the above results, provide the final answer to the original task.`;
225
+ const finalAnswer = await executeFn(finalPrompt);
226
+ return {
227
+ output: finalAnswer,
228
+ reasoning: returnReasoning ? steps.value : void 0,
229
+ toolCalls: executed.size,
230
+ finished: true
231
+ };
232
+ } catch (err) {
233
+ if (onError) {
234
+ const lastStep = steps.value[steps.value.length - 1];
235
+ if (lastStep) await onError(err, lastStep);
236
+ }
237
+ return {
238
+ output: "",
239
+ reasoning: returnReasoning ? steps.value : void 0,
240
+ toolCalls: 0,
241
+ finished: false,
242
+ error: err
243
+ };
244
+ } finally {
245
+ isRunning.value = false;
246
+ }
247
+ }
248
+ return {
249
+ run,
250
+ steps,
251
+ plan,
252
+ isRunning
253
+ };
254
+ }
255
+ export function createEnhancedAgent(config) {
256
+ switch (config.mode) {
257
+ case "reflexion":
258
+ return createReflexionAgent(config);
259
+ case "rewoo":
260
+ return createReWOOAgent(config);
261
+ case "react":
262
+ case "plan-execute":
263
+ return createReWOOAgent({ ...config, mode: "rewoo" });
264
+ default:
265
+ throw new Error(`Unsupported mode: ${config.mode}`);
266
+ }
267
+ }
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.createLocalStorageCache = createLocalStorageCache;
7
+ exports.createMemoryCache = createMemoryCache;
8
+ exports.createSessionStorageCache = createSessionStorageCache;
9
+ function createMemoryCache() {
10
+ const store = /* @__PURE__ */new Map();
11
+ return {
12
+ get(key) {
13
+ const entry = store.get(key);
14
+ if (!entry) return null;
15
+ if (entry.expiry > 0 && entry.expiry < Date.now()) {
16
+ store.delete(key);
17
+ return null;
18
+ }
19
+ return entry.data;
20
+ },
21
+ set(key, value, ttlMs = 0) {
22
+ store.set(key, {
23
+ data: value,
24
+ expiry: ttlMs > 0 ? Date.now() + ttlMs : 0
25
+ });
26
+ },
27
+ delete(key) {
28
+ store.delete(key);
29
+ },
30
+ has(key) {
31
+ const v = this.get(key);
32
+ return v !== null;
33
+ }
34
+ };
35
+ }
36
+ function createLocalStorageCache(prefix = "yh-ai-cache-") {
37
+ return {
38
+ get(key) {
39
+ try {
40
+ const raw = localStorage.getItem(prefix + key);
41
+ if (!raw) return null;
42
+ const item = JSON.parse(raw);
43
+ if (item.expiry != null && item.expiry < Date.now()) {
44
+ localStorage.removeItem(prefix + key);
45
+ return null;
46
+ }
47
+ return item.data;
48
+ } catch {
49
+ return null;
50
+ }
51
+ },
52
+ set(key, value, ttlMs) {
53
+ try {
54
+ const item = {
55
+ data: value,
56
+ expiry: ttlMs != null ? Date.now() + ttlMs : void 0
57
+ };
58
+ localStorage.setItem(prefix + key, JSON.stringify(item));
59
+ } catch {}
60
+ },
61
+ delete(key) {
62
+ try {
63
+ localStorage.removeItem(prefix + key);
64
+ } catch {}
65
+ }
66
+ };
67
+ }
68
+ function createSessionStorageCache(prefix = "yh-ai-cache-") {
69
+ return {
70
+ get(key) {
71
+ try {
72
+ const raw = sessionStorage.getItem(prefix + key);
73
+ if (!raw) return null;
74
+ const item = JSON.parse(raw);
75
+ if (item.expiry != null && item.expiry < Date.now()) {
76
+ sessionStorage.removeItem(prefix + key);
77
+ return null;
78
+ }
79
+ return item.data;
80
+ } catch {
81
+ return null;
82
+ }
83
+ },
84
+ set(key, value, ttlMs) {
85
+ try {
86
+ const item = {
87
+ data: value,
88
+ expiry: ttlMs != null ? Date.now() + ttlMs : void 0
89
+ };
90
+ sessionStorage.setItem(prefix + key, JSON.stringify(item));
91
+ } catch {}
92
+ },
93
+ delete(key) {
94
+ try {
95
+ sessionStorage.removeItem(prefix + key);
96
+ } catch {}
97
+ }
98
+ };
99
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * YH-UI AI SDK - 缓存适配器
3
+ *
4
+ * 支持 memory / localStorage / sessionStorage,并可接入 Redis 等持久化后端。
5
+ */
6
+ export interface CacheAdapter {
7
+ get(key: string): Promise<unknown> | unknown;
8
+ set(key: string, value: unknown, ttlMs?: number): Promise<void> | void;
9
+ delete(key: string): Promise<void> | void;
10
+ has?(key: string): Promise<boolean> | boolean;
11
+ }
12
+ /**
13
+ * 内存缓存(内置,与现有 cacheStorage 行为一致)
14
+ */
15
+ export declare function createMemoryCache(): CacheAdapter;
16
+ /**
17
+ * localStorage 适配器(TTL 需自行轮询或忽略)
18
+ */
19
+ export declare function createLocalStorageCache(prefix?: string): CacheAdapter;
20
+ /**
21
+ * sessionStorage 适配器
22
+ */
23
+ export declare function createSessionStorageCache(prefix?: string): CacheAdapter;
24
+ /**
25
+ * Redis 缓存适配器接口(由用户或可选包实现)
26
+ * 安装 ioredis 后可实现:get/set(key, JSON.stringify(value), 'PX', ttlMs)/del
27
+ */
28
+ export type RedisCacheConfig = {
29
+ /** Redis URL 或 { host, port, password } */
30
+ url?: string;
31
+ host?: string;
32
+ port?: number;
33
+ password?: string;
34
+ db?: number;
35
+ keyPrefix?: string;
36
+ defaultTtlMs?: number;
37
+ };
38
+ /**
39
+ * 创建 Redis 适配器的类型(实际实现需用户提供或通过可选依赖)
40
+ * 用法:strategy: 'redis', adapter: createRedisCache({ url: 'redis://...' })
41
+ */
42
+ export type RedisCacheAdapterFactory = (config: RedisCacheConfig) => CacheAdapter;
@@ -0,0 +1,95 @@
1
+ export function createMemoryCache() {
2
+ const store = /* @__PURE__ */ new Map();
3
+ return {
4
+ get(key) {
5
+ const entry = store.get(key);
6
+ if (!entry) return null;
7
+ if (entry.expiry > 0 && entry.expiry < Date.now()) {
8
+ store.delete(key);
9
+ return null;
10
+ }
11
+ return entry.data;
12
+ },
13
+ set(key, value, ttlMs = 0) {
14
+ store.set(key, {
15
+ data: value,
16
+ expiry: ttlMs > 0 ? Date.now() + ttlMs : 0
17
+ });
18
+ },
19
+ delete(key) {
20
+ store.delete(key);
21
+ },
22
+ has(key) {
23
+ const v = this.get(key);
24
+ return v !== null;
25
+ }
26
+ };
27
+ }
28
+ export function createLocalStorageCache(prefix = "yh-ai-cache-") {
29
+ return {
30
+ get(key) {
31
+ try {
32
+ const raw = localStorage.getItem(prefix + key);
33
+ if (!raw) return null;
34
+ const item = JSON.parse(raw);
35
+ if (item.expiry != null && item.expiry < Date.now()) {
36
+ localStorage.removeItem(prefix + key);
37
+ return null;
38
+ }
39
+ return item.data;
40
+ } catch {
41
+ return null;
42
+ }
43
+ },
44
+ set(key, value, ttlMs) {
45
+ try {
46
+ const item = {
47
+ data: value,
48
+ expiry: ttlMs != null ? Date.now() + ttlMs : void 0
49
+ };
50
+ localStorage.setItem(prefix + key, JSON.stringify(item));
51
+ } catch {
52
+ }
53
+ },
54
+ delete(key) {
55
+ try {
56
+ localStorage.removeItem(prefix + key);
57
+ } catch {
58
+ }
59
+ }
60
+ };
61
+ }
62
+ export function createSessionStorageCache(prefix = "yh-ai-cache-") {
63
+ return {
64
+ get(key) {
65
+ try {
66
+ const raw = sessionStorage.getItem(prefix + key);
67
+ if (!raw) return null;
68
+ const item = JSON.parse(raw);
69
+ if (item.expiry != null && item.expiry < Date.now()) {
70
+ sessionStorage.removeItem(prefix + key);
71
+ return null;
72
+ }
73
+ return item.data;
74
+ } catch {
75
+ return null;
76
+ }
77
+ },
78
+ set(key, value, ttlMs) {
79
+ try {
80
+ const item = {
81
+ data: value,
82
+ expiry: ttlMs != null ? Date.now() + ttlMs : void 0
83
+ };
84
+ sessionStorage.setItem(prefix + key, JSON.stringify(item));
85
+ } catch {
86
+ }
87
+ },
88
+ delete(key) {
89
+ try {
90
+ sessionStorage.removeItem(prefix + key);
91
+ } catch {
92
+ }
93
+ }
94
+ };
95
+ }