upgrade taskloop
This commit is contained in:
parent
50510ae647
commit
51ceacbc10
@ -3,11 +3,11 @@ import * as fs from 'node:fs';
|
||||
const targetFile = './openmcp-sdk/task-loop.js';
|
||||
|
||||
if (fs.existsSync(targetFile)) {
|
||||
let content = fs.readFileSync(targetFile, 'utf8');
|
||||
let content = fs.readFileSync(targetFile, 'utf-8');
|
||||
|
||||
// Replace element-plus with ./tools.js
|
||||
content = content.replace(/'element-plus'/g, "'./tools.js'");
|
||||
content = content.replace(/"element-plus"/g, "\"./tools.js\"");
|
||||
content = content.replace(/'element-plus'/g, "'./tools.mjs'");
|
||||
content = content.replace(/"element-plus"/g, "\"./tools.mjs\"");
|
||||
|
||||
// content = content.replace(/const chalk = require\("chalk"\);/g, 'const chalk = require("chalk").default;');
|
||||
|
||||
|
@ -34,6 +34,8 @@ export interface IErrorMssage {
|
||||
msg: string
|
||||
}
|
||||
|
||||
export { MessageState };
|
||||
|
||||
export interface IDoConversationResult {
|
||||
stop: boolean;
|
||||
}
|
||||
@ -83,12 +85,18 @@ export class TaskLoop {
|
||||
throw new Error('adapter is required');
|
||||
}
|
||||
|
||||
// 根据 adapter 创建 nodejs 下特殊的、基于 event 的 message bridge (不占用任何端口)
|
||||
createMessageBridge(adapter.emitter);
|
||||
|
||||
// 用于进行连接同步
|
||||
this.nodejsStatus.connectionFut = mcpClientAdapter.launch();
|
||||
}
|
||||
|
||||
// web 环境下 bridge 会自动加载完成
|
||||
this.bridge = useMessageBridge();
|
||||
|
||||
// 注册 HMR
|
||||
mcpClientAdapter.addConnectRefreshListener();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -381,7 +389,7 @@ export class TaskLoop {
|
||||
if (verbose > 0) {
|
||||
console.log(
|
||||
chalk.gray(`[${new Date().toLocaleString()}]`),
|
||||
chalk.blueBright('🔧 calling tool'),
|
||||
chalk.blueBright('🔧 using tool'),
|
||||
chalk.blueBright(toolCall.function!.name)
|
||||
);
|
||||
}
|
||||
@ -395,13 +403,13 @@ export class TaskLoop {
|
||||
if (result.state === 'success') {
|
||||
console.log(
|
||||
chalk.gray(`[${new Date().toLocaleString()}]`),
|
||||
chalk.green('✓ call tools okey dockey'),
|
||||
chalk.green('✓ use tools'),
|
||||
chalk.green(result.state)
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
chalk.gray(`[${new Date().toLocaleString()}]`),
|
||||
chalk.red('× fail to call tools'),
|
||||
chalk.red('× use tools'),
|
||||
chalk.red(result.content.map(item => item.text).join(', '))
|
||||
);
|
||||
}
|
||||
@ -413,7 +421,12 @@ export class TaskLoop {
|
||||
const { verbose = 0 } = this.taskOptions;
|
||||
if (verbose > 0) {
|
||||
console.log(
|
||||
chalk.gray(`[${new Date().toLocaleString()}]`),
|
||||
chalk.gray(`[${new Date().toLocaleString()}]`)
|
||||
);
|
||||
}
|
||||
|
||||
if (verbose > 1) {
|
||||
console.log(
|
||||
chalk.blue('task loop enters a new epoch')
|
||||
);
|
||||
}
|
||||
@ -425,9 +438,15 @@ export class TaskLoop {
|
||||
if (verbose > 0) {
|
||||
console.log(
|
||||
chalk.gray(`[${new Date().toLocaleString()}]`),
|
||||
);
|
||||
}
|
||||
|
||||
if (verbose > 1) {
|
||||
console.log(
|
||||
chalk.green('task loop finish a epoch')
|
||||
);
|
||||
}
|
||||
|
||||
return this.onDone();
|
||||
}
|
||||
|
||||
@ -559,7 +578,7 @@ export class TaskLoop {
|
||||
if (verbose > 0) {
|
||||
console.log(
|
||||
chalk.gray(`[${new Date().toLocaleString()}]`),
|
||||
chalk.yellow('🤖 llm wants to call these tools'),
|
||||
chalk.yellow('🤖 Agent wants to use these tools'),
|
||||
chalk.yellow(this.streamingToolCalls.value.map(tool => tool.function!.name || '').join(', '))
|
||||
);
|
||||
}
|
||||
|
@ -506,9 +506,7 @@ class McpClientAdapter {
|
||||
|
||||
constructor(
|
||||
public platform: string
|
||||
) {
|
||||
this.addConnectRefreshListener();
|
||||
}
|
||||
) {}
|
||||
|
||||
/**
|
||||
* @description 获取连接参数签名
|
||||
@ -562,7 +560,9 @@ class McpClientAdapter {
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @description register HMR
|
||||
*/
|
||||
public addConnectRefreshListener() {
|
||||
// 创建对于 connect/refresh 的监听
|
||||
if (!this.connectrefreshListener) {
|
||||
|
@ -32,8 +32,8 @@ export default defineConfig({
|
||||
lib: {
|
||||
entry: resolve(__dirname, '..', 'renderer/src/components/main-panel/chat/core/task-loop.ts'),
|
||||
name: 'TaskLoop',
|
||||
fileName: 'task-loop',
|
||||
formats: ['cjs']
|
||||
fileName: (format) => `task-loop.js`,
|
||||
formats: ['es']
|
||||
},
|
||||
outDir: resolve(__dirname, '..', 'openmcp-sdk'),
|
||||
emptyOutDir: false,
|
||||
|
@ -1,6 +1,7 @@
|
||||
{
|
||||
"name": "openmcp-sdk",
|
||||
"version": "0.0.8",
|
||||
"type": "module",
|
||||
"description": "openmcp-sdk",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
|
@ -195,7 +195,14 @@ export interface DefaultLLM {
|
||||
model: string;
|
||||
}
|
||||
|
||||
import { MessageState, TaskLoopOptions, type ChatMessage, type ChatSetting, type TaskLoop, type TextMessage } from '../../task-loop.js';
|
||||
import {
|
||||
MessageState,
|
||||
type TaskLoopOptions,
|
||||
type ChatMessage,
|
||||
type ChatSetting,
|
||||
type TaskLoop,
|
||||
type TextMessage
|
||||
} from '../../task-loop.js';
|
||||
|
||||
export function UserMessage(content: string): TextMessage {
|
||||
return {
|
||||
@ -274,7 +281,7 @@ export class OmAgent {
|
||||
const commandString = (
|
||||
mcpConfig.command + ' ' + mcpConfig.args.join(' ')
|
||||
).trim();
|
||||
|
||||
|
||||
this._adapter.addMcp({
|
||||
commandString,
|
||||
connectionType: 'STDIO',
|
||||
@ -283,7 +290,7 @@ export class OmAgent {
|
||||
prompt: mcpConfig.prompt,
|
||||
});
|
||||
} else {
|
||||
const connectionType: ConnectionType = mcpConfig.type === 'http' ? 'STREAMABLE_HTTP': 'SSE';
|
||||
const connectionType: ConnectionType = mcpConfig.type === 'http' ? 'STREAMABLE_HTTP' : 'SSE';
|
||||
this._adapter.addMcp({
|
||||
url: mcpConfig.url,
|
||||
env: mcpConfig.env,
|
||||
@ -309,6 +316,7 @@ export class OmAgent {
|
||||
const adapter = this._adapter;
|
||||
const { TaskLoop } = await import('../../task-loop.js');
|
||||
this._loop = new TaskLoop({ adapter, verbose, maxEpochs, maxJsonParseRetry });
|
||||
|
||||
return this._loop;
|
||||
}
|
||||
|
||||
@ -316,9 +324,14 @@ export class OmAgent {
|
||||
this._defaultLLM = option;
|
||||
}
|
||||
|
||||
public async start(
|
||||
messages: ChatMessage[] | string,
|
||||
settings?: ChatSetting & Partial<TaskLoopOptions>
|
||||
/**
|
||||
* @description Asynchronous invoking agent by string or messages
|
||||
* @param messages Chat message or string
|
||||
* @param settings Chat setting and task loop options
|
||||
* @returns
|
||||
*/
|
||||
public async ainvoke(
|
||||
{ messages, settings }: { messages: ChatMessage[] | string; settings?: ChatSetting & Partial<TaskLoopOptions>; }
|
||||
) {
|
||||
if (messages.length === 0) {
|
||||
throw new Error('messages is empty');
|
||||
@ -333,7 +346,7 @@ export class OmAgent {
|
||||
|
||||
const loop = await this.getLoop({ maxEpochs, maxJsonParseRetry, verbose });
|
||||
const storage = await loop.createStorage(settings);
|
||||
|
||||
|
||||
// set input message
|
||||
// user can invoke [UserMessage("CONTENT")] to make messages quickly
|
||||
// or use string directly
|
||||
@ -363,6 +376,10 @@ export class OmAgent {
|
||||
throw new Error('default LLM is not set, please set it via omagent.setDefaultLLM() or write "defaultLLM" in mcpconfig.json');
|
||||
}
|
||||
|
||||
return await loop.start(storage, userMessage);
|
||||
await loop.start(storage, userMessage);
|
||||
|
||||
// get response from last message in message list
|
||||
const lastMessage = storage.messages.at(-1)?.content;
|
||||
return lastMessage;
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ export class McpServerConnectMonitor {
|
||||
this.filePath = getFilePath(options);
|
||||
|
||||
// 记录实例创建
|
||||
logger.info({ uuid, connectionType: options.connectionType }, 'Created new connection monitor instance');
|
||||
// logger.info({ uuid, connectionType: options.connectionType }, 'Created new connection monitor instance');
|
||||
|
||||
switch (options.connectionType) {
|
||||
case 'STDIO':
|
||||
@ -94,7 +94,7 @@ export class McpServerConnectMonitor {
|
||||
},
|
||||
onStart: () => {
|
||||
// 使用 info 级别记录监控开始
|
||||
logger.info({ uuid: this.uuid, filePath: path.resolve(fileConfig.filePath) }, 'Started monitoring file');
|
||||
// logger.info({ uuid: this.uuid, filePath: path.resolve(fileConfig.filePath) }, 'Started monitoring file');
|
||||
|
||||
try {
|
||||
const stats = fs.statSync(fileConfig.filePath);
|
||||
|
@ -71,7 +71,7 @@ class SingleFileMonitor {
|
||||
this.handleFileChange(true);
|
||||
}
|
||||
});
|
||||
console.log(`正在监控文件: ${this.filePath}`);
|
||||
// console.log(`正在监控文件: ${this.filePath}`);
|
||||
} catch (error) {
|
||||
this.onError(error as Error);
|
||||
}
|
||||
@ -171,7 +171,7 @@ class SingleFileMonitor {
|
||||
if (this.watcher) {
|
||||
// 明确指定close方法的类型,解决TS2554错误
|
||||
(this.watcher.close as (callback?: () => void) => void)(() => {
|
||||
console.log(`已停止监控文件: ${this.filePath}`);
|
||||
// console.log(`已停止监控文件: ${this.filePath}`);
|
||||
});
|
||||
this.watcher = null;
|
||||
}
|
||||
|
@ -14,6 +14,9 @@
|
||||
"noEmitHelpers": false,
|
||||
"experimentalDecorators": true,
|
||||
"sourceMap": true,
|
||||
"types": [
|
||||
"./service/task-loop.d.ts"
|
||||
],
|
||||
// 允许访问 openmcp-sdk 目录
|
||||
"paths": {
|
||||
"@openmcp-sdk/*": [
|
||||
|
Loading…
x
Reference in New Issue
Block a user