@fastgpt-plugin/cli 0.1.0-alpha.9 → 0.1.0-beta.2

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/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import e from"node:path";import{consola as t}from"consola";import{Command as n}from"commander";import r from"node:fs/promises";import{input as i,select as a}from"@inquirer/prompts";import{kebabCase as o}from"es-toolkit";import{build as s}from"tsdown";import{Visitor as c,parseSync as l}from"oxc-parser";import{createHash as u}from"node:crypto";var d=`@fastgpt-plugin/cli`,f=`0.1.0-alpha.9`;const p=d,m=f,h=`This is a FastGPT plugin`,g=e.join(import.meta.dirname,`../templates`),_=t.withTag(p);var v=class{};const y={input:i,select:a};async function b(e,t){return e.input({...t,validate:e=>!e||e.trim().length===0?`请输入有效的内容`:!0})}var x=class{deps;constructor(e=y){this.deps=e}async run(e){let t=(()=>{if(e.typeFlag)return e.typeFlag===`tool-suite`?`tool-suite`:`tool`})();if(e.nameArg&&t&&e.descriptionFlag!==void 0)return{name:e.nameArg,cwd:e.cwd,type:t,description:e.descriptionFlag};let n=e.nameArg??await(async()=>await b(this.deps,{message:`插件名称`,default:`./packages/my-tool`}))(),r=t??await(async()=>await this.deps.select({message:`选择插件类型`,choices:[{name:`单工具`,value:`tool`,description:`创建一个独立的工具`},{name:`工具集`,value:`tool-suite`,description:`创建一个包含多个子工具的工具集`}]}))(),i=e.descriptionFlag??await(async()=>await b(this.deps,{message:`插件描述`,default:h}))();return{name:n,cwd:e.cwd,type:r,description:i}}},S=class extends v{register(e){e.command(`create`).description(`创建新的 FastGPT 插件项目`).argument(`[name]`,`插件名称`).option(`-t, --type <type>`,`插件类型: 单工具 | 工具集`).option(`-d, --description <desc>`,`插件描述`).option(`--cwd <path>`,`工作目录`,process.cwd()).action(async(e,t)=>{let n=await new x().run({nameArg:e,typeFlag:t.type,descriptionFlag:t.description,cwd:t.cwd});await this.run(n)})}async run(t){let n=e.resolve(t.cwd,t.name),i=e.join(g,t.type===`tool-suite`?`tool-suite`:`tool`),a=await this.collectTemplateFiles(i),o=t.description??h;await this.ensureDir(n);for(let s of a){let a=e.join(i,s),c=e.join(n,s);await this.ensureDir(e.dirname(c));let l=await r.readFile(a,`utf-8`),u=this.applyPlaceholders(l,t.name,o);await r.writeFile(c,u,`utf-8`)}_.success(`创建插件项目: ${t.name} (${t.type})`,{cwd:t.cwd})}applyPlaceholders(t,n,r){return n=e.basename(n),n=o(n),t.replace(/\{\{name\}\}/g,n).replace(/\{\{description\}\}/g,r)}async collectTemplateFiles(t){let n=[],i=async a=>{let o=await r.readdir(a,{withFileTypes:!0});for(let r of o){let o=e.join(a,r.name);if(r.isDirectory())await i(o);else{let r=e.relative(t,o).replace(/\\/g,`/`);n.push(r)}}};return await i(t),n.sort()}async ensureDir(e){await r.mkdir(e,{recursive:!0})}};async function C(t){let n=e.join(t.rootDir,`src`);if(!await T(n))return E(``);let i=[],a=async n=>{let o=await r.readdir(n,{withFileTypes:!0});for(let r of o){let o=e.join(n,r.name);if(r.isDirectory()){if(r.name===`__tests__`)continue;await a(o);continue}if(!r.isFile())continue;let s=r.name;if(s.includes(`.test.`)||s.includes(`.spec.`))continue;let c=e.relative(t.rootDir,o).split(e.sep).join(`/`);c.startsWith(`src/`)&&i.push({rel:c,abs:o})}};await a(n),i.sort((e,t)=>e.rel.localeCompare(t.rel));let o=``;for(let e of i){let t=E(await r.readFile(e.abs));o+=`${e.rel}:${t}\n`}return E(o)}async function w(t){let{rootDir:n,toolId:r}=t,i=[...t.children].sort(),a=[];for(let t of i){let i=await C({rootDir:e.join(n,`children`,t)});a.push(`${r}/${t}:${i}`)}return E(a.length>0?`${a.join(`
3
- `)}\n`:``)}async function T(e){try{return await r.access(e),!0}catch{return!1}}function E(e){let t=u(`md5`);return t.update(e),t.digest(`hex`)}function D(e){let t=e.split(`/`);return t.at(-3)===`children`?`${t.at(-4)}/${t.at(-2)}`:t.at(-2)||`unknown`}async function O(t){let n=e.join(t,`children`);try{await r.access(n)}catch{return[]}try{return await r.readdir(n)}catch{return[]}}function k(e,t){return e.some(e=>e.type===`Property`&&e.key?.type===`Identifier`&&e.key?.name===t)}function A(e,t){let n=t.sort((e,t)=>t.start-e.start),r=e;for(let e of n)r=r.slice(0,e.start)+e.content+r.slice(e.end);return r}async function j({sourceCode:t,filePath:n}){if(t.includes(`toolId:`))return{code:t,hasToolId:!0};let r=D(n),i=e.dirname(n),a=await O(i),o=await C({rootDir:i}),s=a.length>0?await w({rootDir:i,toolId:r,children:a}):null,u=l(e.basename(n),t,{sourceType:`module`});if(u.errors.length>0)throw Error(`Parse errors: ${u.errors.map(e=>e.message).join(`, `)}`);let d=[],f=[];new c({CallExpression(e){e.callee?.type===`Identifier`&&(e.callee.name===`defineTool`||e.callee.name===`defineToolSet`)&&e.arguments?.[0]?.type===`ObjectExpression`&&f.push(e)}}).visit(u.program);for(let e of f){let t=e.arguments[0];if(t?.type!==`ObjectExpression`)continue;let n=t,i=n.properties||[],c=e.callee?.type===`Identifier`&&e.callee.name===`defineToolSet`,l=!k(i,`toolId`),u=!k(i,`etag`),f=c&&!k(i,`children`)&&a.length>0;if(!l&&!u&&!f)continue;let p=i[i.length-1],m=p?p.end:(n.start??0)+1,h=[];if(l&&h.push(`toolId: '${r}'`),u){let e=c&&s?s:o;h.push(`etag: '${e}'`)}if(f){let e=a.map(e=>e).join(`, `);h.push(`children: [${e}]`);let t=a.map(e=>`import ${e} from './children/${e}';`).join(`
2
+ import{consola as e}from"consola/basic";import{Command as t}from"commander";import n from"node:path";import r from"node:fs/promises";import{build as i}from"tsdown";import{Visitor as a,parseSync as o}from"oxc-parser";import{createHash as s}from"node:crypto";import{input as c,select as l}from"@inquirer/prompts";import{kebabCase as u}from"es-toolkit";import{createWriteStream as d}from"node:fs";import{ZipFile as f}from"yazl";const p=e;var m=`@fastgpt-plugin/cli`,h=`0.1.0-beta.2`;const g=m,_=h,v=`This is a FastGPT plugin`,y=n.join(import.meta.dirname,`../templates`);var b=class{};async function x(e){let t=n.join(e.rootDir,`src`);if(!await C(t))return w(``);let i=[],a=async t=>{let o=await r.readdir(t,{withFileTypes:!0});for(let r of o){let o=n.join(t,r.name);if(r.isDirectory()){if(r.name===`__tests__`)continue;await a(o);continue}if(!r.isFile())continue;let s=r.name;if(s.includes(`.test.`)||s.includes(`.spec.`))continue;let c=n.relative(e.rootDir,o).split(n.sep).join(`/`);c.startsWith(`src/`)&&i.push({rel:c,abs:o})}};await a(t),i.sort((e,t)=>e.rel.localeCompare(t.rel));let o=``;for(let e of i){let t=w(await r.readFile(e.abs));o+=`${e.rel}:${t}\n`}return w(o)}async function S(e){let{rootDir:t,toolId:r}=e,i=[...e.children].sort(),a=[];for(let e of i){let i=await x({rootDir:n.join(t,`children`,e)});a.push(`${r}/${e}:${i}`)}return w(a.length>0?`${a.join(`
3
+ `)}\n`:``)}async function C(e){try{return await r.access(e),!0}catch{return!1}}function w(e){let t=s(`md5`);return t.update(e),t.digest(`hex`)}function T(e){let t=e.split(`/`);return t.at(-3)===`children`?`${t.at(-4)}/${t.at(-2)}`:t.at(-2)||`unknown`}async function E(e){let t=n.join(e,`children`);try{await r.access(t)}catch{return[]}try{return await r.readdir(t)}catch{return[]}}function D(e,t){return e.some(e=>e.type===`Property`&&e.key?.type===`Identifier`&&e.key?.name===t)}function O(e,t){let n=t.sort((e,t)=>t.start-e.start),r=e;for(let e of n)r=r.slice(0,e.start)+e.content+r.slice(e.end);return r}async function k({sourceCode:e,filePath:t}){if(e.includes(`toolId:`))return{code:e,hasToolId:!0};let r=T(t),i=n.dirname(t),s=await E(i),c=await x({rootDir:i}),l=s.length>0?await S({rootDir:i,toolId:r,children:s}):null,u=o(n.basename(t),e,{sourceType:`module`});if(u.errors.length>0)throw Error(`Parse errors: ${u.errors.map(e=>e.message).join(`, `)}`);let d=[],f=[];new a({CallExpression(e){e.callee?.type===`Identifier`&&(e.callee.name===`defineTool`||e.callee.name===`defineToolSet`)&&e.arguments?.[0]?.type===`ObjectExpression`&&f.push(e)}}).visit(u.program);for(let e of f){let t=e.arguments[0];if(t?.type!==`ObjectExpression`)continue;let n=t,i=n.properties||[],a=e.callee?.type===`Identifier`&&e.callee.name===`defineToolSet`,o=!D(i,`toolId`),u=!D(i,`etag`),f=a&&!D(i,`children`)&&s.length>0;if(!o&&!u&&!f)continue;let p=i[i.length-1],m=p?p.end:(n.start??0)+1,h=[];if(o&&h.push(`toolId: '${r}'`),u){let e=a&&l?l:c;h.push(`etag: '${e}'`)}if(f){let e=s.map(e=>e).join(`, `);h.push(`children: [${e}]`);let t=s.map(e=>`import ${e} from './children/${e}';`).join(`
4
4
  `);d.push({start:0,end:0,content:t+`
5
5
  `})}if(h.length>0){let e=(p?`,
6
6
  `:`
7
7
  `)+h.join(`,
8
- `);d.push({start:m,end:m,content:e})}}return d.length===0?{code:t,hasToolId:!1}:{code:A(t,d),hasToolId:!0}}async function M(t){let n=e.resolve(t.entry);await F(n,`入口目录不存在: ${n}`);let i=e.join(n,`config.ts`);await F(i,`找不到 config.ts 文件: ${i}`);let a=e.join(n,`index.ts`);await F(a,`找不到 index.ts 文件: ${a}`);let o=e.join(n,`.build-temp`);await P(o);let c=Date.now(),l=0,u=0,d=0;try{let a=Date.now(),f=await j({sourceCode:await r.readFile(i,`utf-8`),filePath:i});await r.writeFile(e.join(o,`config.ts`),f.code,`utf-8`),l=Date.now()-a;let p=Date.now();await N(n,o,n),u=Date.now()-p;let m=e.resolve(t.output);await P(m);let h=e.join(o,`index.ts`),g=Date.now();await s({entry:[h],outDir:m,format:[t.format],clean:!0,minify:t.minify,inlineOnly:!1,nodeProtocol:!0,platform:`node`,target:`node22`,dts:!1,treeshake:!0,noExternal:[`*`],outExtensions:()=>({dts:`.d.ts`,js:`.js`})}),d=Date.now()-g;let v=await r.readdir(m),y=Date.now()-c;return _.info([`构建阶段耗时统计:`,` • config 转换: ${I(l)}`,` • 源码复制: ${I(u)}`,` • tsdown 构建: ${I(d)}`,` • 总耗时: ${I(y)}`].join(`
9
- `)),{entryDir:n,outputDir:m,files:v.map(e=>e)}}finally{try{await r.rm(o,{recursive:!0,force:!0})}catch{}}}async function N(t,n,i){let a=await r.readdir(t,{withFileTypes:!0});for(let o of a){if(o.name===`node_modules`||o.name===`dist`||o.name.startsWith(`.build-`))continue;let a=e.join(t,o.name),s=e.join(n,o.name);if(o.isDirectory())await P(s),await N(a,s,i);else if(o.isFile()&&!(o.name===`config.ts`&&t===i))if(o.name===`config.ts`){let e=await j({sourceCode:await r.readFile(a,`utf-8`),filePath:a});await r.writeFile(s,e.code,`utf-8`)}else await r.copyFile(a,s)}}async function P(e){await r.mkdir(e,{recursive:!0})}async function F(e,t){try{await r.access(e)}catch{throw Error(t)}}function I(e){return e<1e3?`${e}ms`:`${(e/1e3).toFixed(2)}s`}var L=class extends v{register(e){e.command(`build`).description(`构建 FastGPT 插件为可分发的包`).option(`-e, --entry <path>`,`工具入口目录`,process.cwd()).option(`-o, --output <path>`,`输出目录`,`./dist`).option(`-m, --minify`,`压缩输出代码`,!1).option(`-f, --format <format>`,`输出格式: esm | cjs`,`esm`).action(async e=>{await this.run({entry:e.entry,output:e.output,minify:e.minify,format:e.format})})}async run(e){let t=Date.now();_.start(`准备构建插件...`);try{let n=await M(e),r=((Date.now()-t)/1e3).toFixed(2);_.success(`构建完成,用时 ${r}s`),_.info(`输出目录: ${n.outputDir}`),n.files.length>0?(_.info(`生成的文件列表:`),n.files.forEach(e=>{_.info(` • ${e}`)})):_.info(`未检测到输出文件,请检查配置。`)}catch(e){_.error(`构建失败,详情如下:`),_.error(e instanceof Error?e:Error(String(e))),_.info(`如果这是在 CI 中发生的,请查看上方构建日志以获取更多信息。`),process.exit(1)}}};function R(){let e=new n;return e.name(p).version(m).description(`FastGPT 插件开发 CLI`),new S().register(e),new L().register(e),e}async function z(e){await R().parseAsync(e??process.argv)}process.on(`SIGINT`,()=>{process.exit(130)}),(async()=>{try{await z()}catch(e){e instanceof Error&&(e.name===`ExitPromptError`||e.message.includes(`SIGINT`)||e.message.includes(`force closed`))&&process.exit(130),_.error(e),process.exitCode=1}})();export{};
8
+ `);d.push({start:m,end:m,content:e})}}return d.length===0?{code:e,hasToolId:!1}:{code:O(e,d),hasToolId:!0}}async function A(e){let t=n.resolve(e.entry);await N(t,`入口目录不存在: ${t}`);let a=n.join(t,`config.ts`);await N(a,`找不到 config.ts 文件: ${a}`);let o=n.join(t,`index.ts`);await N(o,`找不到 index.ts 文件: ${o}`);let s=n.join(t,`.build-temp`);await M(s);let c=Date.now(),l=0,u=0,d=0;try{let o=Date.now(),f=await k({sourceCode:await r.readFile(a,`utf-8`),filePath:a});await r.writeFile(n.join(s,`config.ts`),f.code,`utf-8`),l=Date.now()-o;let m=Date.now();await j(t,s,t),u=Date.now()-m;let h=n.resolve(e.output);await M(h);let g=n.join(s,`index.ts`),_=Date.now();await i({entry:[g],outDir:h,format:[e.format],clean:!0,minify:e.minify,inlineOnly:!1,nodeProtocol:!0,platform:`node`,target:`node22`,dts:!1,treeshake:!0,noExternal:[`*`],outExtensions:()=>({dts:`.d.ts`,js:`.js`})}),d=Date.now()-_;let v=await r.readdir(h),y=Date.now()-c;return p.info([`构建阶段耗时统计:`,`• config 转换: ${P(l)}`,`• 源码复制: ${P(u)}`,`• tsdown 构建: ${P(d)}`,`• 总耗时: ${P(y)}`].join(`
9
+ `)),{entryDir:t,outputDir:h,files:v.map(e=>e)}}finally{try{await r.rm(s,{recursive:!0,force:!0})}catch{}}}async function j(e,t,i){let a=await r.readdir(e,{withFileTypes:!0});for(let o of a){if(o.name===`node_modules`||o.name===`dist`||o.name.startsWith(`.build-`))continue;let a=n.join(e,o.name),s=n.join(t,o.name);if(o.isDirectory())await M(s),await j(a,s,i);else if(o.isFile()&&!(o.name===`config.ts`&&e===i))if(o.name===`config.ts`){let e=await k({sourceCode:await r.readFile(a,`utf-8`),filePath:a});await r.writeFile(s,e.code,`utf-8`)}else await r.copyFile(a,s)}}async function M(e){await r.mkdir(e,{recursive:!0})}async function N(e,t){try{await r.access(e)}catch{throw Error(t)}}function P(e){return e<1e3?`${e}ms`:`${(e/1e3).toFixed(2)}s`}var F=class extends b{register(e){e.command(`build`).description(`构建 FastGPT 插件为可分发的包`).option(`-e, --entry <path>`,`工具入口目录`,process.cwd()).option(`-o, --output <path>`,`输出目录`,`./dist`).option(`-m, --minify`,`压缩输出代码`,!1).option(`-f, --format <format>`,`输出格式: esm | cjs`,`esm`).action(async e=>{await this.run({entry:e.entry,output:e.output,minify:e.minify,format:e.format})})}async run(e){let t=Date.now();try{let n=await A(e),r=((Date.now()-t)/1e3).toFixed(2);p.success(`构建完成,用时 ${r}s`),p.info(`输出目录: ${n.outputDir}`),n.files.length>0?(p.info(`生成的文件列表:`),n.files.forEach(e=>{p.info(`• ${e}`)})):p.info(`未检测到输出文件,请检查配置。`)}catch(e){p.error(`构建失败,详情如下:`),p.error(e instanceof Error?e:Error(String(e))),p.info(`如果这是在 CI 中发生的,请查看上方构建日志以获取更多信息。`),process.exit(1)}}};const I={input:c,select:l};async function L(e,t){return e.input({...t,validate:e=>!e||e.trim().length===0?`请输入有效的内容`:!0})}var R=class{deps;constructor(e=I){this.deps=e}async run(e){let t=(()=>{if(e.typeFlag)return e.typeFlag===`tool-suite`?`tool-suite`:`tool`})();if(e.nameArg&&t&&e.descriptionFlag!==void 0)return{name:e.nameArg,cwd:e.cwd,type:t,description:e.descriptionFlag};let n=e.nameArg??await(async()=>await L(this.deps,{message:`插件名称`,default:`./packages/my-tool`}))(),r=t??await(async()=>await this.deps.select({message:`选择插件类型`,choices:[{name:`单工具`,value:`tool`,description:`创建一个独立的工具`},{name:`工具集`,value:`tool-suite`,description:`创建一个包含多个子工具的工具集`}]}))(),i=e.descriptionFlag??await(async()=>await L(this.deps,{message:`插件描述`,default:v}))();return{name:n,cwd:e.cwd,type:r,description:i}}},z=class extends b{register(e){e.command(`create`).description(`创建新的 FastGPT 插件项目`).argument(`[name]`,`插件名称`).option(`-t, --type <type>`,`插件类型: 单工具 | 工具集`).option(`-d, --description <desc>`,`插件描述`).option(`--cwd <path>`,`工作目录`,process.cwd()).action(async(e,t)=>{let n=await new R().run({nameArg:e,typeFlag:t.type,descriptionFlag:t.description,cwd:t.cwd});await this.run(n)})}async run(e){let t=n.resolve(e.cwd,e.name),i=n.join(y,e.type===`tool-suite`?`tool-suite`:`tool`),a=await this.collectTemplateFiles(i),o=e.description??v;await this.ensureDir(t);for(let s of a){let a=n.join(i,s),c=n.join(t,s);await this.ensureDir(n.dirname(c));let l=await r.readFile(a,`utf-8`),u=this.applyPlaceholders(l,e.name,o);await r.writeFile(c,u,`utf-8`)}p.success(`创建插件项目: ${e.name} (${e.type})`,{cwd:e.cwd})}applyPlaceholders(e,t,r){return t=n.basename(t),t=u(t),e.replace(/\{\{name\}\}/g,t).replace(/\{\{description\}\}/g,r)}async collectTemplateFiles(e){let t=[],i=async a=>{let o=await r.readdir(a,{withFileTypes:!0});for(let r of o){let o=n.join(a,r.name);if(r.isDirectory())await i(o);else{let r=n.relative(e,o).replace(/\\/g,`/`);t.push(r)}}};return await i(e),t.sort()}async ensureDir(e){await r.mkdir(e,{recursive:!0})}},B=class extends b{register(e){e.command(`pack`).description(`将 FastGPT 工具或工具集打包为 .pkg 文件`).option(`-e, --entry <path>`,`工具入口目录`,process.cwd()).option(`-o, --output <path>`,`输出目录(默认使用入口目录)`).option(`-n, --name <name>`,`包名称(默认使用入口目录名)`).action(async e=>{await this.run(e)})}async run(e){let t=Date.now(),i=n.resolve(e.entry),a=n.resolve(e.output||i),o=e.name||n.basename(i),s=n.join(a,`${o}.pkg`);try{await U(i,`入口目录不存在: ${i}`);let e=n.join(i,`dist`,`index.js`),o=n.join(i,`logo.svg`),c=n.join(i,`README.md`),l=n.join(i,`assets`),u=n.join(i,`children`);await U(e,`找不到 dist/index.js 文件: ${e}`),await H(a);let m=new f,h=d(s),g=new Promise((e,t)=>{m.outputStream.pipe(h).on(`close`,()=>e()),m.outputStream.on(`error`,e=>t(e)),h.on(`error`,e=>t(e))});if(m.addFile(e,`index.js`),await V(o)&&m.addFile(o,`logo.svg`),await V(c)&&m.addFile(c,`README.md`),await V(l)&&await W(m,l,`assets`),await V(u)){let e=await r.readdir(u,{withFileTypes:!0});for(let t of e){if(!t.isDirectory())continue;let e=t.name,r=n.join(u,e),i=n.join(r,`logo.svg`);m.addEmptyDirectory(`${e}/`),await V(i)&&m.addFile(i,`${e}/logo.svg`)}}m.end(),await g;let _=((Date.now()-t)/1e3).toFixed(2);p.success(`打包完成,用时 ${_}s`),p.info(`输出文件: ${s}`)}catch(e){p.error(`打包失败,详情如下:`),p.error(e instanceof Error?e:Error(String(e))),process.exit(1)}}};async function V(e){try{return await r.access(e),!0}catch{return!1}}async function H(e){await r.mkdir(e,{recursive:!0})}async function U(e,t){try{await r.access(e)}catch{throw Error(t)}}async function W(e,t,i){let a=await r.readdir(t,{withFileTypes:!0});for(let r of a){let a=n.join(t,r.name),o=n.join(i,r.name).split(n.sep).join(`/`);r.isDirectory()?(e.addEmptyDirectory(`${o}/`),await W(e,a,o)):r.isFile()&&e.addFile(a,o)}}function G(){let e=new t;return e.name(g).version(_).description(`FastGPT 插件开发 CLI`),new F().register(e),new z().register(e),new B().register(e),e}async function K(e){await G().parseAsync(e??process.argv)}process.on(`SIGINT`,()=>{process.exit(130)}),(async()=>{try{await K()}catch(e){e instanceof Error&&(e.name===`ExitPromptError`||e.message.includes(`SIGINT`)||e.message.includes(`force closed`))&&process.exit(130),p.error(e),process.exitCode=1}})();export{};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fastgpt-plugin/cli",
3
- "version": "0.1.0-alpha.9",
3
+ "version": "0.1.0-beta.2",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "publishConfig": {
@@ -22,15 +22,18 @@
22
22
  "prepublishOnly": "npm run build"
23
23
  },
24
24
  "dependencies": {
25
+ "@fastgpt-plugin/helpers": "0.0.1-alpha.3",
25
26
  "@oxc-parser/binding-wasm32-wasi": "^0.112.0",
26
- "oxc-parser": "^0.112.0",
27
27
  "@inquirer/prompts": "^8.2.0",
28
28
  "commander": "^14.0.3",
29
29
  "consola": "^3.4.2",
30
30
  "es-toolkit": "^1.44.0",
31
- "tsdown": "^0.20.1"
31
+ "oxc-parser": "^0.112.0",
32
+ "tsdown": "^0.20.1",
33
+ "yazl": "^3.3.1"
32
34
  },
33
35
  "devDependencies": {
36
+ "@types/yazl": "^3.3.0",
34
37
  "typescript": "^5",
35
38
  "vite-tsconfig-paths": "^6.0.5",
36
39
  "vitest": "^4.0.18"
@@ -1,7 +1,7 @@
1
1
  import { defineTool, WorkflowIOValueTypeEnum, ToolTagEnum } from '@fastgpt-plugin/helpers';
2
2
 
3
3
  export default defineTool({
4
- tags: [ToolTagEnum.enum.tools],
4
+ tags: [ToolTagEnum.tools],
5
5
  name: {
6
6
  'zh-CN': '{{name}}',
7
7
  en: '{{name}}'
@@ -18,10 +18,10 @@ export default defineTool({
18
18
  inputs: [],
19
19
  outputs: [
20
20
  {
21
- key: 'message',
22
- valueType: WorkflowIOValueTypeEnum.enum.string,
23
- label: 'Message',
24
- description: 'Tool output message'
21
+ key: 'time',
22
+ valueType: WorkflowIOValueTypeEnum.string,
23
+ label: '时间',
24
+ description: '当前时间'
25
25
  }
26
26
  ]
27
27
  }
@@ -1,11 +1,11 @@
1
1
  import { exportTool } from '@fastgpt-plugin/helpers/tools/helper';
2
2
  import config from './config';
3
- import { tool as toolCb } from './src/tool';
4
- import { InputType, OutputType } from './src/schemas';
3
+ import { InputSchema, OutputSchema } from './src/schemas';
4
+ import { handler } from './src/tool';
5
5
 
6
6
  export default exportTool({
7
- toolCb,
8
- InputType,
9
- OutputType,
7
+ handler,
8
+ InputSchema,
9
+ OutputSchema,
10
10
  config
11
11
  });
@@ -5,16 +5,17 @@
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "scripts": {
8
- "build": "npx @fastgpt-plugin/cli build",
8
+ "build": "npx @fastgpt-plugin/cli build --minify",
9
+ "build:dev": "npx @fastgpt-plugin/cli build",
10
+ "pack": "npx @fastgpt-plugin/cli pack",
9
11
  "test": "vitest run"
10
12
  },
11
- "dependencies": {
12
- "@fastgpt-plugin/helpers": "catalog:",
13
- "zod": "catalog:"
14
- },
13
+ "dependencies": {},
15
14
  "devDependencies": {
16
15
  "@fastgpt-plugin/cli": "catalog:",
16
+ "@fastgpt-plugin/helpers": "catalog:",
17
17
  "typescript": "catalog:",
18
- "vitest": "catalog:"
18
+ "vitest": "catalog:",
19
+ "zod": "catalog:"
19
20
  }
20
21
  }
@@ -1,7 +1,9 @@
1
1
  import { z } from 'zod';
2
2
 
3
- export const InputType = z.object({});
3
+ export const InputSchema = z.object({});
4
+ export type Input = z.infer<typeof InputSchema>;
4
5
 
5
- export const OutputType = z.object({
6
- message: z.string()
6
+ export const OutputSchema = z.object({
7
+ time: z.string().nonempty()
7
8
  });
9
+ export type Output = z.infer<typeof OutputSchema>;
@@ -1,37 +1,17 @@
1
1
  import { describe, expect, it } from 'vitest';
2
- import { InputType, OutputType } from './schemas';
2
+ import { InputSchema, OutputSchema } from './schemas';
3
3
  import { tool } from './tool';
4
+ import { mockedEventEmitter, mockedSystemVar } from '@fastgpt-plugin/helpers/tools/mocks';
4
5
 
5
6
  describe('get-time', () => {
6
7
  it('should run with valid IO schemas', async () => {
7
- const input = InputType.parse({});
8
+ const input = InputSchema.parse({});
8
9
  const result = await tool(input, {
9
- systemVar: {
10
- user: {
11
- id: 'test',
12
- username: 'test',
13
- contact: 'test',
14
- membername: 'test',
15
- teamName: 'test',
16
- teamId: 'test',
17
- name: 'test'
18
- },
19
- app: {
20
- id: 'test',
21
- name: 'test'
22
- },
23
- tool: {
24
- id: 'test',
25
- version: '0.0.1'
26
- },
27
- time: new Date().toISOString()
28
- },
29
- streamResponse: () => {
30
- // noop
31
- }
10
+ systemVar: mockedSystemVar,
11
+ emitter: mockedEventEmitter
32
12
  });
33
13
 
34
- const output = OutputType.parse(result);
14
+ const output = OutputSchema.parse(result);
35
15
  expect(output).toBeDefined();
36
16
  });
37
17
  });
@@ -1,10 +1,8 @@
1
- import type { RunToolSecondParamsType } from '@fastgpt-plugin/helpers/tools/schemas/req';
2
- import type { z } from 'zod';
3
- import type { InputType, OutputType } from './schemas';
1
+ import type { ToolContextType } from '@fastgpt-plugin/helpers/tools/schemas/req';
2
+ import type { Input, Output } from './schemas';
4
3
 
5
- export async function tool(
6
- _input: z.infer<typeof InputType>,
7
- _ctx: RunToolSecondParamsType
8
- ): Promise<z.infer<typeof OutputType>> {
9
- return { message: 'Hello from {{name}}' };
4
+ export async function handler(_: Input, ctx: ToolContextType): Promise<Output> {
5
+ const { systemVar } = ctx;
6
+
7
+ return { time: systemVar.time };
10
8
  }
@@ -1,7 +1,7 @@
1
- import { defineTool, WorkflowIOValueTypeEnum, ToolTagEnum } from '@fastgpt-plugin/helpers';
1
+ import { defineTool, ToolTagEnum, WorkflowIOValueTypeEnum } from '@fastgpt-plugin/helpers';
2
2
 
3
3
  export default defineTool({
4
- tags: [ToolTagEnum.enum.tools],
4
+ tags: [ToolTagEnum.tools],
5
5
  name: {
6
6
  'zh-CN': '{{name}}',
7
7
  en: '{{name}}'
@@ -14,14 +14,14 @@ export default defineTool({
14
14
  versionList: [
15
15
  {
16
16
  value: '0.0.1',
17
- description: 'Initial version',
17
+ description: 'Default version',
18
18
  inputs: [],
19
19
  outputs: [
20
20
  {
21
- key: 'message',
22
- valueType: WorkflowIOValueTypeEnum.enum.string,
23
- label: 'Message',
24
- description: 'Tool output message'
21
+ key: 'time',
22
+ valueType: WorkflowIOValueTypeEnum.string,
23
+ label: '时间',
24
+ description: '当前时间'
25
25
  }
26
26
  ]
27
27
  }
@@ -1,11 +1,11 @@
1
1
  import { exportTool } from '@fastgpt-plugin/helpers/tools/helper';
2
2
  import config from './config';
3
- import { tool as toolCb } from './src/tool';
4
- import { InputType, OutputType } from './src/schemas';
3
+ import { InputSchema, OutputSchema } from './src/schemas';
4
+ import { handler } from './src/tool';
5
5
 
6
6
  export default exportTool({
7
- toolCb,
8
- InputType,
9
- OutputType,
7
+ handler,
8
+ InputSchema,
9
+ OutputSchema,
10
10
  config
11
11
  });
@@ -1,7 +1,9 @@
1
1
  import { z } from 'zod';
2
2
 
3
- export const InputType = z.object({});
3
+ export const InputSchema = z.object({});
4
+ export type Input = z.infer<typeof InputSchema>;
4
5
 
5
- export const OutputType = z.object({
6
- message: z.string()
6
+ export const OutputSchema = z.object({
7
+ time: z.string().nonempty()
7
8
  });
9
+ export type Output = z.infer<typeof OutputSchema>;
@@ -1,10 +1,8 @@
1
- import type { RunToolSecondParamsType } from '@fastgpt-plugin/helpers/tools/schemas/req';
2
- import type { z } from 'zod';
3
- import { InputType, OutputType } from './schemas';
1
+ import type { ToolContextType } from '@fastgpt-plugin/helpers/tools/schemas/req';
2
+ import type { Input, Output } from './schemas';
4
3
 
5
- export async function tool(
6
- _input: z.infer<typeof InputType>,
7
- _ctx: RunToolSecondParamsType
8
- ): Promise<z.infer<typeof OutputType>> {
9
- return { message: 'Hello from {{name}}' };
4
+ export async function handler(_: Input, ctx: ToolContextType): Promise<Output> {
5
+ const { systemVar } = ctx;
6
+
7
+ return { time: systemVar.time };
10
8
  }
@@ -1,7 +1,7 @@
1
- import { defineToolSet, ToolTagEnum } from '@fastgpt-plugin/helpers';
1
+ import { defineTool, ToolTagEnum, WorkflowIOValueTypeEnum } from '@fastgpt-plugin/helpers';
2
2
 
3
- export default defineToolSet({
4
- tags: [ToolTagEnum.enum.tools],
3
+ export default defineTool({
4
+ tags: [ToolTagEnum.tools],
5
5
  name: {
6
6
  'zh-CN': '{{name}}',
7
7
  en: '{{name}}'
@@ -9,5 +9,21 @@ export default defineToolSet({
9
9
  description: {
10
10
  'zh-CN': '{{description}}',
11
11
  en: '{{description}}'
12
- }
12
+ },
13
+ icon: 'core/workflow/template/{{name}}',
14
+ versionList: [
15
+ {
16
+ value: '0.0.1',
17
+ description: 'Default version',
18
+ inputs: [],
19
+ outputs: [
20
+ {
21
+ key: 'time',
22
+ valueType: WorkflowIOValueTypeEnum.string,
23
+ label: '时间',
24
+ description: '当前时间'
25
+ }
26
+ ]
27
+ }
28
+ ]
13
29
  });
@@ -5,16 +5,17 @@
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "scripts": {
8
- "build": "npx @fastgpt-plugin/cli build",
8
+ "build": "npx @fastgpt-plugin/cli build --minify",
9
+ "build:dev": "npx @fastgpt-plugin/cli build",
10
+ "pack": "npx @fastgpt-plugin/cli pack",
9
11
  "test": "vitest run"
10
12
  },
11
- "dependencies": {
12
- "@fastgpt-plugin/helpers": "catalog:",
13
- "zod": "catalog:"
14
- },
13
+ "dependencies": {},
15
14
  "devDependencies": {
16
15
  "@fastgpt-plugin/cli": "catalog:",
16
+ "@fastgpt-plugin/helpers": "catalog:",
17
17
  "typescript": "catalog:",
18
- "vitest": "catalog:"
18
+ "vitest": "catalog:",
19
+ "zod": "catalog:"
19
20
  }
20
21
  }
@@ -5,4 +5,3 @@ export default defineConfig({
5
5
  environment: 'node'
6
6
  }
7
7
  });
8
-