@opentiny/next-sdk 0.2.3 → 0.2.5
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/agent/AgentModelProvider.ts +74 -61
- package/agent/type.ts +1 -1
- package/agent/utils/getAISDKTools.ts +2 -2
- package/dist/agent/AgentModelProvider.d.ts +3 -11
- package/dist/agent/type.d.ts +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.es.dev.js +14583 -11574
- package/dist/index.es.js +21845 -19128
- package/dist/index.js +2203 -969
- package/dist/index.umd.dev.js +14595 -11587
- package/dist/index.umd.js +90 -77
- package/dist/mcpsdk@1.25.3.dev.js +190 -181
- package/dist/mcpsdk@1.25.3.es.dev.js +190 -181
- package/dist/mcpsdk@1.25.3.es.js +1111 -1105
- package/dist/mcpsdk@1.25.3.js +14 -14
- package/dist/remoter/createRemoter.d.ts +1 -1
- package/dist/skills/index.d.ts +54 -0
- package/dist/webagent.dev.js +22892 -16435
- package/dist/webagent.es.dev.js +22614 -16156
- package/dist/webagent.es.js +25425 -20182
- package/dist/webagent.js +73 -65
- package/dist/webmcp-full.dev.js +190 -181
- package/dist/webmcp-full.es.dev.js +190 -181
- package/dist/webmcp-full.es.js +74 -68
- package/dist/webmcp-full.js +1 -1
- package/index.ts +14 -0
- package/package.json +5 -5
- package/remoter/createRemoter.ts +2 -2
- package/skills/index.ts +141 -0
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import { streamText, stepCountIs, generateText, StreamTextResult } from 'ai'
|
|
2
|
-
import {
|
|
3
|
-
experimental_MCPClientConfig as MCPClientConfig,
|
|
4
|
-
experimental_createMCPClient as createMCPClient
|
|
5
|
-
} from '@ai-sdk/mcp'
|
|
2
|
+
import { MCPClientConfig, createMCPClient } from '@ai-sdk/mcp'
|
|
6
3
|
import type { ToolSet } from 'ai'
|
|
7
4
|
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'
|
|
8
5
|
import { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js'
|
|
@@ -10,7 +7,7 @@ import type { IAgentModelProviderOption, McpServerConfig } from './type'
|
|
|
10
7
|
import { ProviderV2 } from '@ai-sdk/provider'
|
|
11
8
|
import { OpenAIProvider } from '@ai-sdk/openai'
|
|
12
9
|
import { createOpenAI } from '@ai-sdk/openai'
|
|
13
|
-
import { createDeepSeek } from '@ai-sdk/deepseek'
|
|
10
|
+
import { createDeepSeek, DeepSeekProvider } from '@ai-sdk/deepseek'
|
|
14
11
|
import { ExtensionClientTransport } from '../transport/ExtensionClientTransport'
|
|
15
12
|
import { MessageChannelTransport } from '@opentiny/next'
|
|
16
13
|
import { WebMcpClient } from '../WebMcpClient'
|
|
@@ -30,7 +27,7 @@ type ChatMethodFn = typeof streamText | typeof generateText
|
|
|
30
27
|
* @returns 暴露了 chat, chatStream方法
|
|
31
28
|
*/
|
|
32
29
|
export class AgentModelProvider {
|
|
33
|
-
llm: ProviderV2 | OpenAIProvider
|
|
30
|
+
llm: ProviderV2 | OpenAIProvider | DeepSeekProvider
|
|
34
31
|
/** 当前mcpServers对象集合。键为服务器名称,值为 McpServerConfig 或任意的 MCPTransport
|
|
35
32
|
* 参考: https://ai-sdk.dev/docs/ai-sdk-core/tools-and-tool-calling#initializing-an-mcp-client */
|
|
36
33
|
mcpServers: Record<string, McpServerConfig> = {}
|
|
@@ -48,14 +45,6 @@ export class AgentModelProvider {
|
|
|
48
45
|
responseMessages: any[] = []
|
|
49
46
|
/** 是否使用 ReAct 模式(通过提示词而非 function calling 进行工具调用) */
|
|
50
47
|
useReActMode: boolean = false
|
|
51
|
-
/** 流结束后,返回token细节的事件 */
|
|
52
|
-
onUsage?: (usage: {
|
|
53
|
-
cachedInputTokens: number
|
|
54
|
-
inputTokens: number
|
|
55
|
-
reasoningTokens: number
|
|
56
|
-
outputTokens: number
|
|
57
|
-
totalTokens: number
|
|
58
|
-
}) => void
|
|
59
48
|
|
|
60
49
|
constructor({ llmConfig, mcpServers }: IAgentModelProviderOption) {
|
|
61
50
|
if (!llmConfig) {
|
|
@@ -69,7 +58,7 @@ export class AgentModelProvider {
|
|
|
69
58
|
this.llm = llmConfig.llm
|
|
70
59
|
} else if (llmConfig.providerType) {
|
|
71
60
|
const providerType = llmConfig.providerType
|
|
72
|
-
let providerFn: (options: any) => ProviderV2 | OpenAIProvider
|
|
61
|
+
let providerFn: (options: any) => ProviderV2 | OpenAIProvider | DeepSeekProvider
|
|
73
62
|
|
|
74
63
|
if (typeof providerType === 'string') {
|
|
75
64
|
providerFn = AIProviderFactories[providerType]
|
|
@@ -599,6 +588,10 @@ export class AgentModelProvider {
|
|
|
599
588
|
// 配置:最多保留的图片数量
|
|
600
589
|
const maxImages = (options as any).maxImages ?? 3
|
|
601
590
|
|
|
591
|
+
// 模拟开启流
|
|
592
|
+
controller.enqueue({ type: 'start' })
|
|
593
|
+
controller.enqueue({ type: 'start-step' })
|
|
594
|
+
|
|
602
595
|
try {
|
|
603
596
|
while (stepCount < maxSteps) {
|
|
604
597
|
stepCount++
|
|
@@ -618,7 +611,7 @@ export class AgentModelProvider {
|
|
|
618
611
|
messages: messagesForModel
|
|
619
612
|
})
|
|
620
613
|
|
|
621
|
-
//
|
|
614
|
+
// 1、直接问,收集流式输出
|
|
622
615
|
let assistantText = ''
|
|
623
616
|
for await (const part of result.fullStream) {
|
|
624
617
|
if (part.type === 'text-delta') {
|
|
@@ -630,8 +623,10 @@ export class AgentModelProvider {
|
|
|
630
623
|
})
|
|
631
624
|
} else if (part.type === 'text-start') {
|
|
632
625
|
controller.enqueue({ type: 'text-start' })
|
|
633
|
-
} else if (part.type === 'text-end') {
|
|
626
|
+
} else if (part.type === 'text-end' || part.type === 'finish-step' || part.type === 'finish') {
|
|
634
627
|
// 暂时不关闭,等待检查是否有工具调用
|
|
628
|
+
} else if (part.type === 'start' || part.type === 'start-step') {
|
|
629
|
+
// 后面每一轮的start 也要忽略
|
|
635
630
|
} else {
|
|
636
631
|
// 转发其他类型的事件
|
|
637
632
|
controller.enqueue(part)
|
|
@@ -644,12 +639,14 @@ export class AgentModelProvider {
|
|
|
644
639
|
allUserMessages.push(assistantMsg)
|
|
645
640
|
fullMessageHistory.push(assistantMsg)
|
|
646
641
|
|
|
647
|
-
//
|
|
642
|
+
// 2、解析工具调用
|
|
648
643
|
const action = parseReActAction(accumulatedText, tools)
|
|
649
644
|
|
|
650
645
|
if (!action) {
|
|
651
646
|
// 没有工具调用,结束流
|
|
652
647
|
controller.enqueue({ type: 'text-end' })
|
|
648
|
+
controller.enqueue({ type: 'finish-step' })
|
|
649
|
+
controller.enqueue({ type: 'finish' })
|
|
653
650
|
controller.close()
|
|
654
651
|
self.responseMessages = fullMessageHistory
|
|
655
652
|
// 触发 onFinish 回调
|
|
@@ -661,13 +658,15 @@ export class AgentModelProvider {
|
|
|
661
658
|
if (action.toolName === 'computer' && action.arguments?.action === 'terminate') {
|
|
662
659
|
// 视为对话结束
|
|
663
660
|
controller.enqueue({ type: 'text-end' })
|
|
661
|
+
controller.enqueue({ type: 'finish-step' })
|
|
662
|
+
controller.enqueue({ type: 'finish' })
|
|
664
663
|
controller.close()
|
|
665
664
|
self.responseMessages = fullMessageHistory
|
|
666
665
|
streamCompleteResolver({ messages: fullMessageHistory })
|
|
667
666
|
return
|
|
668
667
|
}
|
|
669
668
|
|
|
670
|
-
//
|
|
669
|
+
// 3、是工具调用,发送工具调用开始事件(符合 tiny-robot 格式)
|
|
671
670
|
const toolCallId = `react-${Date.now()}`
|
|
672
671
|
controller.enqueue({
|
|
673
672
|
type: 'tool-input-start',
|
|
@@ -682,8 +681,19 @@ export class AgentModelProvider {
|
|
|
682
681
|
id: toolCallId,
|
|
683
682
|
delta: argsString
|
|
684
683
|
})
|
|
684
|
+
controller.enqueue({
|
|
685
|
+
type: 'tool-input-end',
|
|
686
|
+
id: toolCallId
|
|
687
|
+
})
|
|
688
|
+
|
|
689
|
+
// 4、执行工具调用
|
|
690
|
+
controller.enqueue({
|
|
691
|
+
type: 'tool-call',
|
|
692
|
+
toolCallId: toolCallId,
|
|
693
|
+
toolName: action.toolName,
|
|
694
|
+
input: action.arguments
|
|
695
|
+
})
|
|
685
696
|
|
|
686
|
-
// 执行工具调用
|
|
687
697
|
const toolResult = await self._executeReActToolCall(action.toolName, action.arguments, tools)
|
|
688
698
|
|
|
689
699
|
// 如果结果包含 screenshot,先提取出来,避免 JSON stringify 导致过大
|
|
@@ -715,48 +725,56 @@ export class AgentModelProvider {
|
|
|
715
725
|
} else {
|
|
716
726
|
observationText = JSON.stringify(resultData)
|
|
717
727
|
}
|
|
718
|
-
} else {
|
|
719
|
-
observationText = `工具执行失败 - ${toolResult.error}`
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
// 统一使用 XML 格式的 Observation,如果有截图,添加验证提示
|
|
723
|
-
let finalObservation = `<tool_response>\n${observationText}\n</tool_response>`
|
|
724
|
-
|
|
725
|
-
if (screenshot) {
|
|
726
|
-
finalObservation += `\n请检查截图以确认操作是否成功。如果成功,请继续下一步;如果失败,请重试。`
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
// 发送工具结果(符合 tiny-robot 格式,给 UI 展示用的,不包含 base64 防止卡顿)
|
|
730
|
-
controller.enqueue({
|
|
731
|
-
type: 'tool-result',
|
|
732
|
-
toolCallId: toolCallId,
|
|
733
|
-
result: finalObservation
|
|
734
|
-
})
|
|
735
728
|
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
? {
|
|
739
|
-
role: 'user',
|
|
740
|
-
content: [
|
|
741
|
-
{ type: 'text', text: finalObservation },
|
|
742
|
-
{ type: 'image', image: screenshot }
|
|
743
|
-
]
|
|
744
|
-
}
|
|
745
|
-
: {
|
|
746
|
-
role: 'user',
|
|
747
|
-
content: finalObservation
|
|
748
|
-
}
|
|
729
|
+
// 统一使用 XML 格式的 Observation,如果有截图,添加验证提示
|
|
730
|
+
let finalObservation = `<tool_response>\n${observationText}\n</tool_response>`
|
|
749
731
|
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
732
|
+
if (screenshot) {
|
|
733
|
+
finalObservation += `\n请检查截图以确认操作是否成功。如果成功,请继续下一步;如果失败,请重试。`
|
|
734
|
+
}
|
|
753
735
|
|
|
754
|
-
|
|
755
|
-
|
|
736
|
+
// 发送工具结果(符合 tiny-robot 格式,给 UI 展示用的,不包含 base64 防止卡顿)
|
|
737
|
+
controller.enqueue({
|
|
738
|
+
type: 'tool-result',
|
|
739
|
+
toolCallId: toolCallId,
|
|
740
|
+
result: finalObservation
|
|
741
|
+
})
|
|
742
|
+
|
|
743
|
+
// 添加工具结果到消息历史(ReAct 模式下,工具结果作为 user 消息添加)
|
|
744
|
+
const observationMessage = screenshot
|
|
745
|
+
? {
|
|
746
|
+
role: 'user',
|
|
747
|
+
content: [
|
|
748
|
+
{ type: 'text', text: finalObservation },
|
|
749
|
+
{ type: 'image', image: screenshot }
|
|
750
|
+
]
|
|
751
|
+
}
|
|
752
|
+
: {
|
|
753
|
+
role: 'user',
|
|
754
|
+
content: finalObservation
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
// 添加到所有消息和完整历史
|
|
758
|
+
allUserMessages.push(observationMessage)
|
|
759
|
+
fullMessageHistory.push(observationMessage)
|
|
760
|
+
|
|
761
|
+
// 重置累积文本,准备下一轮
|
|
762
|
+
accumulatedText = ''
|
|
763
|
+
} else {
|
|
764
|
+
observationText = `工具执行失败 - ${toolResult.error}`
|
|
765
|
+
controller.enqueue({
|
|
766
|
+
type: 'tool-error',
|
|
767
|
+
toolCallId: toolCallId,
|
|
768
|
+
input: action.arguments,
|
|
769
|
+
error: { message: observationText }
|
|
770
|
+
})
|
|
771
|
+
}
|
|
756
772
|
}
|
|
757
773
|
|
|
758
774
|
// 达到最大步数
|
|
759
775
|
controller.enqueue({ type: 'text-end' })
|
|
776
|
+
controller.enqueue({ type: 'finish-step' })
|
|
777
|
+
controller.enqueue({ type: 'finish' })
|
|
760
778
|
controller.close()
|
|
761
779
|
self.responseMessages = fullMessageHistory
|
|
762
780
|
// 触发 onFinish 回调
|
|
@@ -819,7 +837,7 @@ export class AgentModelProvider {
|
|
|
819
837
|
const result = chatMethod(chatOptions)
|
|
820
838
|
|
|
821
839
|
// 缓存 ai-sdk 的多轮对话的消息
|
|
822
|
-
;(result as
|
|
840
|
+
;(result as any)?.response?.then((res: any) => {
|
|
823
841
|
// 检查 res.messages 的第一条消息是否是 user 消息
|
|
824
842
|
// 如果不是,且有 lastUserMessage,则先添加 lastUserMessage
|
|
825
843
|
const firstMessage = res.messages?.[0]
|
|
@@ -830,11 +848,6 @@ export class AgentModelProvider {
|
|
|
830
848
|
this.responseMessages.push(...res.messages)
|
|
831
849
|
})
|
|
832
850
|
|
|
833
|
-
// 读取使用量
|
|
834
|
-
result?.usage?.then((usage: any) => {
|
|
835
|
-
this.onUsage?.(usage)
|
|
836
|
-
})
|
|
837
|
-
|
|
838
851
|
return result
|
|
839
852
|
}
|
|
840
853
|
|
package/agent/type.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ProviderV2 } from '@ai-sdk/provider'
|
|
2
|
-
import type {
|
|
2
|
+
import type { MCPClientConfig } from '@ai-sdk/mcp'
|
|
3
3
|
|
|
4
4
|
// 从 MCPClientConfig 中提取 transport 类型
|
|
5
5
|
export type MCPTransport = MCPClientConfig['transport']
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { dynamicTool, jsonSchema, Tool,
|
|
1
|
+
import { dynamicTool, jsonSchema, Tool, ToolExecutionOptions, ToolSet } from 'ai'
|
|
2
2
|
import { WebMcpClient } from '../../WebMcpClient'
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -13,7 +13,7 @@ export const getAISDKTools = async (client: WebMcpClient): Promise<ToolSet> => {
|
|
|
13
13
|
const listToolsResult = await client.listTools()
|
|
14
14
|
|
|
15
15
|
for (const { name, description, inputSchema } of listToolsResult.tools) {
|
|
16
|
-
const execute = async (args: any, options:
|
|
16
|
+
const execute = async (args: any, options: ToolExecutionOptions): Promise<any> => {
|
|
17
17
|
return client.callTool({ name, arguments: args }, { signal: options?.abortSignal })
|
|
18
18
|
}
|
|
19
19
|
|
|
@@ -2,7 +2,7 @@ import { streamText, generateText } from 'ai';
|
|
|
2
2
|
import { IAgentModelProviderOption, McpServerConfig } from './type';
|
|
3
3
|
import { ProviderV2 } from '@ai-sdk/provider';
|
|
4
4
|
import { OpenAIProvider, createOpenAI } from '@ai-sdk/openai';
|
|
5
|
-
import { createDeepSeek } from '@ai-sdk/deepseek';
|
|
5
|
+
import { createDeepSeek, DeepSeekProvider } from '@ai-sdk/deepseek';
|
|
6
6
|
import { WebMcpClient } from '../WebMcpClient';
|
|
7
7
|
|
|
8
8
|
export declare const AIProviderFactories: {
|
|
@@ -14,7 +14,7 @@ export declare const AIProviderFactories: {
|
|
|
14
14
|
* @returns 暴露了 chat, chatStream方法
|
|
15
15
|
*/
|
|
16
16
|
export declare class AgentModelProvider {
|
|
17
|
-
llm: ProviderV2 | OpenAIProvider;
|
|
17
|
+
llm: ProviderV2 | OpenAIProvider | DeepSeekProvider;
|
|
18
18
|
/** 当前mcpServers对象集合。键为服务器名称,值为 McpServerConfig 或任意的 MCPTransport
|
|
19
19
|
* 参考: https://ai-sdk.dev/docs/ai-sdk-core/tools-and-tool-calling#initializing-an-mcp-client */
|
|
20
20
|
mcpServers: Record<string, McpServerConfig>;
|
|
@@ -32,14 +32,6 @@ export declare class AgentModelProvider {
|
|
|
32
32
|
responseMessages: any[];
|
|
33
33
|
/** 是否使用 ReAct 模式(通过提示词而非 function calling 进行工具调用) */
|
|
34
34
|
useReActMode: boolean;
|
|
35
|
-
/** 流结束后,返回token细节的事件 */
|
|
36
|
-
onUsage?: (usage: {
|
|
37
|
-
cachedInputTokens: number;
|
|
38
|
-
inputTokens: number;
|
|
39
|
-
reasoningTokens: number;
|
|
40
|
-
outputTokens: number;
|
|
41
|
-
totalTokens: number;
|
|
42
|
-
}) => void;
|
|
43
35
|
constructor({ llmConfig, mcpServers }: IAgentModelProviderOption);
|
|
44
36
|
/** 创建一个 ai-sdk的 mcpClient, 创建失败则返回 null */
|
|
45
37
|
private _createOneClient;
|
|
@@ -58,7 +50,7 @@ export declare class AgentModelProvider {
|
|
|
58
50
|
/** 全量更新所有的 mcpServers */
|
|
59
51
|
updateMcpServers(mcpServers?: Record<string, McpServerConfig>): Promise<void>;
|
|
60
52
|
/** 插入一个新的mcpServer,如果已经存在则返回false */
|
|
61
|
-
insertMcpServer(serverName: string, mcpServer: McpServerConfig): Promise<false | WebMcpClient | import('@ai-sdk/mcp').
|
|
53
|
+
insertMcpServer(serverName: string, mcpServer: McpServerConfig): Promise<false | WebMcpClient | import('@ai-sdk/mcp').MCPClient | null>;
|
|
62
54
|
/** 通过服务器名称删除mcpServer: mcpServers mcpClients mcpTools ignoreToolnames */
|
|
63
55
|
removeMcpServer(serverName: string): Promise<void>;
|
|
64
56
|
/** 创建临时允许调用的tools集合 */
|
package/dist/agent/type.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ProviderV2 } from '@ai-sdk/provider';
|
|
2
|
-
import {
|
|
2
|
+
import { MCPClientConfig } from '@ai-sdk/mcp';
|
|
3
3
|
|
|
4
4
|
export type MCPTransport = MCPClientConfig['transport'];
|
|
5
5
|
type ProviderFactory = 'openai' | 'deepseek' | ((options: any) => ProviderV2);
|
package/dist/index.d.ts
CHANGED
|
@@ -26,3 +26,4 @@ export { AgentModelProvider } from './agent/AgentModelProvider';
|
|
|
26
26
|
export { getAISDKTools } from './agent/utils/getAISDKTools';
|
|
27
27
|
export { QrCode, type QrCodeOption } from './remoter/QrCode';
|
|
28
28
|
export type * from './agent/type';
|
|
29
|
+
export { getSkillOverviews, formatSkillsForSystemPrompt, getSkillMdPaths, getSkillMdContent, getMainSkillPaths, getMainSkillPathByName, parseSkillFrontMatter, createSkillTools, type SkillMeta, type SkillToolsSet } from './skills/index';
|