@fastgpt-plugin/sdk-factory 0.0.1-alpha.2 → 0.0.1-alpha.4
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.d.ts +22 -51
- package/dist/index.js +1 -1
- package/package.json +6 -9
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import z from "zod";
|
|
2
|
-
import * as node_stream0 from "node:stream";
|
|
2
|
+
import * as _$node_stream0 from "node:stream";
|
|
3
3
|
|
|
4
4
|
//#region src/manifest.type.d.ts
|
|
5
5
|
declare const UserToolManifestSchema: z.ZodObject<{
|
|
@@ -67,7 +67,7 @@ type Result<T = unknown, E = unknown> = [T, null] | [null, ResultFailure<E>];
|
|
|
67
67
|
//#endregion
|
|
68
68
|
//#region ../../packages/domain/src/ports/invoke.port.d.ts
|
|
69
69
|
declare const InvokeUploadFileInputSchema: z.ZodObject<{
|
|
70
|
-
file: z.ZodUnion<readonly [z.ZodCustom<node_stream0.Readable, node_stream0.Readable>, z.ZodPipe<z.ZodUnion<readonly [z.ZodCustom<Buffer<ArrayBufferLike>, Buffer<ArrayBufferLike>>, z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>]>, z.ZodTransform<Buffer<any>, Uint8Array<ArrayBuffer> | Buffer<ArrayBufferLike>>>]>;
|
|
70
|
+
file: z.ZodUnion<readonly [z.ZodCustom<_$node_stream0.Readable, _$node_stream0.Readable>, z.ZodPipe<z.ZodUnion<readonly [z.ZodCustom<Buffer<ArrayBufferLike>, Buffer<ArrayBufferLike>>, z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>]>, z.ZodTransform<Buffer<any>, Uint8Array<ArrayBuffer> | Buffer<ArrayBufferLike>>>]>;
|
|
71
71
|
fileName: z.ZodOptional<z.ZodString>;
|
|
72
72
|
contentType: z.ZodOptional<z.ZodIntersection<z.ZodEnum<{
|
|
73
73
|
"application/javascript": "application/javascript";
|
|
@@ -102,71 +102,42 @@ declare const InvokeUploadFileInputSchema: z.ZodObject<{
|
|
|
102
102
|
}, z.core.$strip>;
|
|
103
103
|
declare const InvokeUploadFileOutputSchema: z.ZodObject<{
|
|
104
104
|
accessURL: z.ZodString;
|
|
105
|
-
etag: z.ZodString;
|
|
106
|
-
fileName: z.ZodString;
|
|
107
|
-
contentType: z.ZodIntersection<z.ZodEnum<{
|
|
108
|
-
"application/javascript": "application/javascript";
|
|
109
|
-
"application/json": "application/json";
|
|
110
|
-
"application/yaml": "application/yaml";
|
|
111
|
-
"application/zip": "application/zip";
|
|
112
|
-
"image/jpeg": "image/jpeg";
|
|
113
|
-
"image/png": "image/png";
|
|
114
|
-
"image/gif": "image/gif";
|
|
115
|
-
"image/webp": "image/webp";
|
|
116
|
-
"image/svg+xml": "image/svg+xml";
|
|
117
|
-
"application/pdf": "application/pdf";
|
|
118
|
-
"text/plain": "text/plain";
|
|
119
|
-
"text/csv": "text/csv";
|
|
120
|
-
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
|
|
121
|
-
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
|
|
122
|
-
"application/vnd.openxmlformats-officedocument.presentationml.presentation": "application/vnd.openxmlformats-officedocument.presentationml.presentation";
|
|
123
|
-
"application/msword": "application/msword";
|
|
124
|
-
"application/vnd.ms-excel": "application/vnd.ms-excel";
|
|
125
|
-
"application/vnd.ms-powerpoint": "application/vnd.ms-powerpoint";
|
|
126
|
-
"text/markdown": "text/markdown";
|
|
127
|
-
"audio/mpeg": "audio/mpeg";
|
|
128
|
-
"video/mp4": "video/mp4";
|
|
129
|
-
"audio/wav": "audio/wav";
|
|
130
|
-
"text/html": "text/html";
|
|
131
|
-
"application/xml": "application/xml";
|
|
132
|
-
"application/gzip": "application/gzip";
|
|
133
|
-
"application/octet-stream": "application/octet-stream";
|
|
134
|
-
"multipart/form-data": "multipart/form-data";
|
|
135
|
-
"text/event-stream": "text/event-stream";
|
|
136
|
-
}>, z.ZodString>;
|
|
137
|
-
size: z.ZodNumber;
|
|
138
|
-
createTime: z.ZodDate;
|
|
139
105
|
}, z.core.$strip>;
|
|
140
106
|
type InvokeUploadFileInputType = z.infer<typeof InvokeUploadFileInputSchema>;
|
|
141
107
|
type InvokeUploadFileOutputType = z.infer<typeof InvokeUploadFileOutputSchema>;
|
|
108
|
+
declare const InvokeUserInfoOutputSchema: z.ZodObject<{
|
|
109
|
+
username: z.ZodString;
|
|
110
|
+
contact: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
111
|
+
memberName: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
112
|
+
orgs: z.ZodArray<z.ZodObject<{
|
|
113
|
+
pathId: z.ZodString;
|
|
114
|
+
name: z.ZodString;
|
|
115
|
+
}, z.core.$strip>>;
|
|
116
|
+
groups: z.ZodArray<z.ZodObject<{
|
|
117
|
+
name: z.ZodString;
|
|
118
|
+
}, z.core.$strip>>;
|
|
119
|
+
}, z.core.$strip>;
|
|
120
|
+
type InvokeUserInfoOutputType = z.infer<typeof InvokeUserInfoOutputSchema>;
|
|
142
121
|
/**
|
|
143
122
|
* 反向调用 FastGPT 的能力
|
|
144
123
|
*/
|
|
145
124
|
interface InvokePort {
|
|
146
125
|
/** 上传文件 */
|
|
147
126
|
uploadFile(input: InvokeUploadFileInputType): Promise<Result<InvokeUploadFileOutputType>>;
|
|
127
|
+
userInfo(): Promise<Result<InvokeUserInfoOutputType>>;
|
|
148
128
|
}
|
|
149
129
|
//#endregion
|
|
150
130
|
//#region ../../packages/domain/src/value-objects/system-var.vo.d.ts
|
|
151
131
|
declare const SystemVarSchema: z.ZodObject<{
|
|
152
|
-
user: z.ZodObject<{
|
|
153
|
-
id: z.ZodString;
|
|
154
|
-
username: z.ZodString;
|
|
155
|
-
contact: z.ZodString;
|
|
156
|
-
membername: z.ZodString;
|
|
157
|
-
teamName: z.ZodString;
|
|
158
|
-
teamId: z.ZodString;
|
|
159
|
-
name: z.ZodString;
|
|
160
|
-
}, z.core.$strip>;
|
|
161
132
|
app: z.ZodObject<{
|
|
162
133
|
id: z.ZodString;
|
|
163
134
|
name: z.ZodString;
|
|
164
135
|
}, z.core.$strip>;
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
136
|
+
chat: z.ZodObject<{
|
|
137
|
+
chatId: z.ZodString;
|
|
138
|
+
uid: z.ZodOptional<z.ZodString>;
|
|
139
|
+
}, z.core.$strip>;
|
|
140
|
+
invokeToken: z.ZodString;
|
|
170
141
|
time: z.ZodString;
|
|
171
142
|
}, z.core.$strip>;
|
|
172
143
|
type SystemVarType = z.infer<typeof SystemVarSchema>;
|
|
@@ -237,4 +208,4 @@ declare const defineToolSet: ({
|
|
|
237
208
|
})[];
|
|
238
209
|
}) => DefinedToolFactory;
|
|
239
210
|
//#endregion
|
|
240
|
-
export { DefinedToolFactory, createToolHandler, defineTool, defineToolSet };
|
|
211
|
+
export { DefinedToolFactory, type ToolHandlerContext, createToolHandler, defineTool, defineToolSet };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"zod";import{Readable as t}from"node:stream";import{randomUUID as n}from"node:crypto";import r,{Readable as i}from"stream";var a=class e{stream;closed=!1;constructor(e){this.stream=new t({objectMode:!0,read(){}}),e?.(this)}static create(t){return new e(t)}write(e){this.ensureWritable(),this.stream.push(e)}send(e){this.write(e)}close(){this.closed||(this.closed=!0,this.stream.push(null))}end(){this.close()}fail(e){this.closed=!0,this.stream.destroy(e)}toReadable(){return this.stream}onData(e){return this.stream.on(`data`,e),this}onEnd(e){return this.stream.on(`end`,e),this}onError(e){return this.stream.on(`error`,e),this}async consume(e){for await(let t of this.values())await e(t)}async*values(){for await(let e of this.stream)yield e}ensureWritable(){if(this.closed||this.stream.destroyed)throw Error(`StreamData is already closed`)}};const o=e=>(e=e.replace(/(?<=https?:\/\/)[^\s]+/g,`xxx`),e=e.replace(/ns-[\w-]+/g,`xxx`),e),s=(e,t=``)=>o(typeof e==`string`?e:e?.response?.data?.message||e?.response?.message||e?.message||e?.response?.data?.msg||e?.response?.msg||e?.msg||t),c=`application/javascript,application/json,application/yaml,application/zip,image/jpeg,image/png,image/gif,image/webp,image/svg+xml,application/pdf,text/plain,text/csv,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.openxmlformats-officedocument.presentationml.presentation,application/msword,application/vnd.ms-excel,application/vnd.ms-powerpoint,text/markdown,audio/mpeg,video/mp4,audio/wav,text/html,application/xml,application/gzip,application/octet-stream,multipart/form-data,text/event-stream`.split(`,`),l=e.enum(c).and(e.string().regex(/^[^/]+\/[^/]+$/)),u=e.object({fileKey:e.string(),fileName:e.string(),contentType:l,size:e.number(),etag:e.string(),createTime:e.date()}),d=e.object({fileKey:e.string().optional(),path:e.string().optional(),fileName:e.string().optional(),contentType:l.optional(),overwrite:e.boolean().optional(),file:e.union([e.instanceof(i,{error:`Stream cannot be empty`}),e.union([e.instanceof(Buffer,{error:`Buffer is required`}),e.instanceof(Uint8Array,{error:`Uint8Array is required`})]).transform(e=>e instanceof Uint8Array&&!(e instanceof Buffer)?Buffer.from(e):e)])});e.object({...d.omit({fileKey:!0,overwrite:!0,path:!0}).shape});const f=e.object({...u.omit({fileKey:!0}).shape,accessURL:e.string()}),p=e.enum([`uploadFile`]).enum,m=e=>[e,null];function h(e,t){return g(e)?[null,e]:[null,{reason:e,error:t}]}function g(e){return!!(e&&typeof e==`object`&&`reason`in e&&`error`in e)}const _=`__plugin_ipc_stream__`,v=`__pluginIpcDuplexReply__`;var y=class{pending=new Map;readyHandlers=new Set;errorHandlers=new Set;streamHandlers=new Map;incomingStreams=new Map;bufferedIncomingStreams=new Map;pendingStreamWaiters=new Map;requestHandler=null;eventHandler=null;endpoint;options;unsubscribeMessage;closed=!1;constructor(e,t={}){C(e)?(this.endpoint=e,this.options=t):(this.endpoint=process,this.options=e??{}),this.unsubscribeMessage=x(this.endpoint,e=>{this.dispatch(e).catch(e=>{this.emitError(e instanceof Error?e:Error(String(e)))})})}onReady(e){return this.readyHandlers.add(e),()=>{this.readyHandlers.delete(e)}}onError(e){return this.errorHandlers.add(e),()=>{this.errorHandlers.delete(e)}}setRequestHandler(e){this.requestHandler=e}setEventHandler(e){this.eventHandler=e}async requestDuplex(e,t,r){this.ensureOpen();let i=r?.requestId??n(),a=r?.timeoutMs??this.options.defaultTimeoutMs??3e4,o=Date.now(),s=r?.input===void 0?void 0:this.pipeStream(j(i),r.input,{traceId:r.traceId,streamId:r.inputStreamId,meta:r.inputMeta});s&&s.catch(e=>{this.emitError(e instanceof Error?e:Error(String(e)))});let c=await this.request(e,t,{timeoutMs:a,traceId:r?.traceId,requestId:i});if(!E(c))return{requestId:i,result:c,...s===void 0?{}:{inputDone:s}};let l;if(c.hasOutputStream){let e=Date.now()-o,t=Math.max(1,a-e);l=await this.waitForStream(M(i),{timeoutMs:t})}return{requestId:i,result:c.result,...l===void 0?{}:{output:l},...s===void 0?{}:{inputDone:s}}}replyDuplex(e,t,n){return{[v]:!0,...t===void 0?{}:{result:t},...n?.output===void 0?{}:{output:n.output},...n===void 0?{}:{options:{...n.traceId===void 0?{}:{traceId:n.traceId},...n.outputStreamId===void 0?{}:{outputStreamId:n.outputStreamId},...n.outputMeta===void 0?{}:{outputMeta:n.outputMeta}}}}}async waitForRequestInputStream(e,t){return this.waitForStream(j(e.id),t)}onStream(e,t){this.streamHandlers.has(e)||this.streamHandlers.set(e,new Set);let n=this.streamHandlers.get(e),r=t;return n.add(r),()=>{n.delete(r),n.size===0&&this.streamHandlers.delete(e)}}async waitForStream(e,t){this.ensureOpen();let n=this.bufferedIncomingStreams.get(e);if(n&&n.length>0){let t=n.shift();return n.length===0&&this.bufferedIncomingStreams.delete(e),t}return new Promise((n,r)=>{let i={resolve:n,reject:r};t?.timeoutMs!==void 0&&(i.timer=setTimeout(()=>{let t=this.pendingStreamWaiters.get(e);if(!t)return;let n=t.indexOf(i);n>=0&&t.splice(n,1),t.length===0&&this.pendingStreamWaiters.delete(e),r(Error(`Wait stream timeout: ${e}`))},t.timeoutMs)),this.pendingStreamWaiters.has(e)||this.pendingStreamWaiters.set(e,[]),this.pendingStreamWaiters.get(e).push(i)})}async createWritableStream(e,t){this.ensureOpen();let r=t?.streamId??n(),i=!1;return await this.sendStreamFrame({type:`start`,streamId:r,streamName:e,...t?.meta===void 0?{}:{meta:t.meta}},t?.traceId),{streamId:r,write:async e=>{if(i)throw Error(`Stream is already closed: ${r}`);await this.sendStreamFrame({type:`chunk`,streamId:r,chunk:e},t?.traceId)},end:async()=>{i||(i=!0,await this.sendStreamFrame({type:`end`,streamId:r},t?.traceId))},fail:async e=>{i||(i=!0,await this.sendStreamFrame({type:`error`,streamId:r,error:O(e)},t?.traceId))}}}async pipeStream(e,t,n){let r=await this.createWritableStream(e,n);try{for await(let e of A(t))await r.write(e);await r.end()}catch(e){throw await r.fail(e instanceof Error?e:Error(String(e))),e}}async request(e,t,r){this.ensureOpen();let i=r?.requestId??n(),a=r?.timeoutMs??this.options.defaultTimeoutMs??3e4;return new Promise((n,o)=>{let s=setTimeout(()=>{this.pending.delete(i),o(Object.assign(Error(`Request timeout: ${e}`),{code:`REQUEST_TIMEOUT`,requestId:i,method:e}))},a);this.pending.set(i,{resolve:n,reject:o,timer:s}),this.send({id:i,messageType:`request`,method:e,params:t,...r?.traceId===void 0?{}:{traceId:r.traceId},timestamp:Date.now()}).catch(e=>{clearTimeout(s),this.pending.delete(i),o(e)})})}async emit(e,t,r){this.ensureOpen(),await this.send({id:n(),messageType:`event`,method:e,params:t,...r===void 0?{}:{traceId:r},timestamp:Date.now()})}async sendReady(){this.ensureOpen(),await this.send({id:n(),messageType:`ready`,timestamp:Date.now()})}async reply(e,t){this.ensureOpen(),await this.send({id:e.id,messageType:`response`,...t===void 0?{}:{result:t},...e.traceId===void 0?{}:{traceId:e.traceId},timestamp:Date.now()})}async replyError(e,t){this.ensureOpen();let n=O(t);await this.send({id:e.id,messageType:`error`,error:n,...e.traceId===void 0?{}:{traceId:e.traceId},timestamp:Date.now()})}async close(e=Error(`IPC channel closed`)){this.closed||(this.closed=!0,this.unsubscribeMessage(),this.rejectAllPending(e),this.rejectAllPendingStreamWaiters(e),this.failAllIncomingStreams(e))}async dispatch(e){if(!this.closed){if(e.messageType===`response`||e.messageType===`error`){this.handleResponse(e);return}if(e.messageType===`ready`){this.readyHandlers.forEach(t=>t(e));return}if(e.messageType===`event`){if(T(e)){await this.handleStreamFrameMessage(e);return}await this.eventHandler?.(e);return}e.messageType===`request`&&await this.handleRequest(e)}}handleResponse(e){let t=this.pending.get(e.id);if(t){if(clearTimeout(t.timer),this.pending.delete(e.id),e.error){t.reject(k(e.error));return}t.resolve(e.result)}}async handleRequest(e){if(!e.method){await this.replyError(e,{code:`INVALID_REQUEST`,message:`Request method is required`});return}if(!this.requestHandler){await this.replyError(e,{code:`METHOD_NOT_FOUND`,message:`Method not found: ${e.method}`});return}try{let t=await this.requestHandler(e);if(D(t)){await this.handleDuplexReply(e,t);return}await this.reply(e,t)}catch(t){await this.replyError(e,t instanceof Error?t:Error(String(t)))}}rejectAllPending(e){this.pending.forEach((t,n)=>{clearTimeout(t.timer),t.reject(e),this.pending.delete(n)})}rejectAllPendingStreamWaiters(e){this.pendingStreamWaiters.forEach((t,n)=>{t.forEach(t=>{t.timer&&clearTimeout(t.timer),t.reject(e)}),this.pendingStreamWaiters.delete(n)})}failAllIncomingStreams(e){this.incomingStreams.forEach((t,n)=>{t.stream.fail(e),this.incomingStreams.delete(n)}),this.bufferedIncomingStreams.clear()}async sendStreamFrame(e,t){await this.emit(_,e,t)}async handleDuplexReply(e,t){let n=t.options?.traceId??e.traceId;t.output!==void 0&&this.pipeStream(M(e.id),t.output,{traceId:n,streamId:t.options?.outputStreamId,meta:t.options?.outputMeta}).catch(e=>{this.emitError(e instanceof Error?e:Error(String(e)))}),await this.reply(e,{[v]:!0,hasOutputStream:t.output!==void 0,...t.result===void 0?{}:{result:t.result}})}async handleStreamFrameMessage(e){let t=e.params;switch(t.type){case`start`:{let n={streamId:t.streamId,streamName:t.streamName,stream:a.create(),...e.traceId===void 0?{}:{traceId:e.traceId},...t.meta===void 0?{}:{meta:t.meta}};this.incomingStreams.set(t.streamId,n),this.dispatchIncomingStream(n);return}case`chunk`:{let e=this.incomingStreams.get(t.streamId);if(!e){this.emitError(Error(`Stream not found: ${t.streamId}`));return}e.stream.write(t.chunk);return}case`end`:{let e=this.incomingStreams.get(t.streamId);if(!e)return;e.stream.close(),this.incomingStreams.delete(t.streamId);return}case`error`:{let e=this.incomingStreams.get(t.streamId);if(!e)return;e.stream.fail(k(t.error)),this.incomingStreams.delete(t.streamId);return}}}dispatchIncomingStream(e){let t=!1,n=this.pendingStreamWaiters.get(e.streamName);if(n&&n.length>0){let r=n.shift();r.timer&&clearTimeout(r.timer),n.length===0&&this.pendingStreamWaiters.delete(e.streamName),r.resolve(e),t=!0}let r=this.streamHandlers.get(e.streamName);if(r&&r.size>0){r.forEach(t=>{Promise.resolve(t(e)).catch(e=>{this.emitError(e instanceof Error?e:Error(String(e)))})});return}t||(this.bufferedIncomingStreams.has(e.streamName)||this.bufferedIncomingStreams.set(e.streamName,[]),this.bufferedIncomingStreams.get(e.streamName).push(e))}emitError(e){this.errorHandlers.forEach(t=>t(e))}async send(e){await S(this.endpoint,e)}ensureOpen(){if(this.closed)throw Error(`IPC channel closed`)}};function b(e){return new y(process,e)}function x(e,t){let n=e,r=e=>{w(e)&&t(e)};return n.on(`message`,r),()=>n.off(`message`,r)}function S(e,t){let n=e;if(typeof n.send!=`function`)throw Error(`IPC channel not available`);return new Promise((e,r)=>{n.send(t,t=>{if(t){r(t);return}e()})})}function C(e){return!!(e&&typeof e==`object`&&`on`in e&&typeof e.on==`function`&&`off`in e&&typeof e.off==`function`)}function w(e){return!!(e&&typeof e==`object`&&`messageType`in e)}function T(e){return e.messageType===`event`&&e.method===_}function E(e){return!!(e&&typeof e==`object`&&v in e&&`hasOutputStream`in e)}function D(e){return!!(e&&typeof e==`object`&&v in e)}function O(e){return typeof e==`string`?{code:`HANDLER_ERROR`,message:e}:(e instanceof Error,{code:e.code??`HANDLER_ERROR`,message:e.message,...e.stack===void 0?{}:{stack:e.stack}})}function k(e){return Object.assign(Error(e.message),{code:e.code,stack:e.stack})}function A(e){return e instanceof a?e.values():e}function j(e){return`__plugin_ipc_request_input_stream__:${e}`}function M(e){return`__plugin_ipc_request_output_stream__:${e}`}var N=class{constructor(e,t={}){this.channel=e,this.options=t}async uploadFile(e){try{let t=await this.channel.requestDuplex(`__host_invoke__`,{method:p.uploadFile,args:{contentType:e.contentType,fileName:e.fileName}},{requestId:n(),traceId:this.options.invocationId,input:Buffer.isBuffer(e.file)?r.Readable.from(e.file):e.file});return m(f.parse(t.result))}catch(e){return h({en:`Failed to upload file`,"zh-CN":`上传文件失败`},e)}}};const P=e.enum([`en`,`zh-CN`,`zh-Hant`]).enum;e.object({[P.en]:e.string(),[P[`zh-CN`]]:e.string().optional(),[P[`zh-Hant`]]:e.string().optional()});const F=e.object({[P.en]:e.string(),[P[`zh-CN`]]:e.string(),[P[`zh-Hant`]]:e.string()});e.object({pluginId:e.string(),version:e.string(),etag:e.string()});const I=e.literal(`system`).or(e.string()),L=e.object({id:e.string(),name:F});e.array(L);const R=e.enum([`localPool`,`serverless`]).enum;e.object({pluginId:e.string(),version:e.string().optional(),source:I.optional()});var z=class{channel;getChannel(){if(!this.channel)throw Error(`Channel is not initialized yet.`);return this.channel}mode;checkRuntimeMode(){process.env.RUNTIME_MODE==R.localPool&&(this.mode=R.localPool),process.env.RUNTIME_MODE===`dev`&&(this.mode=`dev`)}async init(){this.checkRuntimeMode(),this.mode===`localPool`&&(this.channel=b(),setImmediate(()=>this.getChannel().sendReady())),this.mode===`dev`&&(this.channel=B().pluginChannel,setImmediate(()=>this.getChannel().sendReady()))}constructor(){this.init()}};function B(){let e=globalThis.__FASTGPT_PLUGIN_LOCAL_DEBUG_RUNTIME__;if(!e)throw Error(`Local debug runtime is not initialized. Set it before importing the plugin.`);return e}function V(e){return e}var H=class t extends z{toolHandlers=new Map;childManifests=new Map;secretSchema=e.record(e.string(),e.unknown());constructor(e){super(),this.userToolManifest=e,this.mode&&this.getChannel().setRequestHandler(async e=>{if(e.method===`run`)try{let{input:t,systemVar:n,childId:r,secrets:i}=e.params,o=this.toolHandlers.get(r??`tool`);if(!o)throw Error(`No tool registered`);let s=a.create(),c=a.create();s.onData(e=>{c.send({type:`stream`,data:e})});let l=await o.handler(t,{systemVar:n,secrets:i,invoke:new N(this.getChannel(),{invocationId:e.traceId}),streamResponse:e=>{s.send(e)}});return c.send({type:`response`,data:l}),c.end(),this.getChannel().replyDuplex(e,void 0,{output:c})}catch(t){let n=a.create();return n.write({data:s(t),type:`error`}),n.end(),this.getChannel().replyDuplex(e,void 0,{output:n})}})}setSecretSchema(e){this.secretSchema=e}registerTool(e,t=`tool`,n){this.toolHandlers.set(t,e),n&&this.childManifests.set(t,n)}static getInstance(e){return new t(e)}getSecretSchema(){return this.secretSchema}getToolHandler(e=`tool`){return this.toolHandlers.get(e)}getUserToolManifest(){return this.userToolManifest}getChildManifests(){return[...this.childManifests.values()]}};const U=({manifest:t,handler:n})=>{let r=H.getInstance(t);return r.setSecretSchema(n.secretSchema??e.object()),r.registerTool(n),r},W=({manifest:t,children:n,secretSchema:r})=>{let i=H.getInstance(t);return n.forEach(e=>{i.registerTool(e.handler,e.id,{id:e.id,description:e.description,name:e.name,...e.icon===void 0?{}:{icon:e.icon},...e.toolDescription===void 0?{}:{toolDescription:e.toolDescription}})}),i.setSecretSchema(r??e.object()),i};export{V as createToolHandler,U as defineTool,W as defineToolSet};
|
|
1
|
+
import e from"zod";import{Readable as t}from"node:stream";import{randomUUID as n}from"node:crypto";import r,{Readable as i}from"stream";var a=class e{stream;closed=!1;constructor(e){this.stream=new t({objectMode:!0,read(){}}),e?.(this)}static create(t){return new e(t)}write(e){this.ensureWritable(),this.stream.push(e)}send(e){this.write(e)}close(){this.closed||(this.closed=!0,this.stream.push(null))}end(){this.close()}fail(e){this.closed=!0,this.stream.destroy(e)}toReadable(){return this.stream}onData(e){return this.stream.on(`data`,e),this}onEnd(e){return this.stream.on(`end`,e),this}onError(e){return this.stream.on(`error`,e),this}async consume(e){for await(let t of this.values())await e(t)}async*values(){for await(let e of this.stream)yield e}ensureWritable(){if(this.closed||this.stream.destroyed)throw Error(`StreamData is already closed`)}};const o=e=>(e=e.replace(/(?<=https?:\/\/)[^\s]+/g,`xxx`),e=e.replace(/ns-[\w-]+/g,`xxx`),e),s=(e,t=``)=>o(typeof e==`string`?e:e?.response?.data?.message||e?.response?.message||e?.message||e?.response?.data?.msg||e?.response?.msg||e?.msg||t),c=`application/javascript,application/json,application/yaml,application/zip,image/jpeg,image/png,image/gif,image/webp,image/svg+xml,application/pdf,text/plain,text/csv,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.openxmlformats-officedocument.presentationml.presentation,application/msword,application/vnd.ms-excel,application/vnd.ms-powerpoint,text/markdown,audio/mpeg,video/mp4,audio/wav,text/html,application/xml,application/gzip,application/octet-stream,multipart/form-data,text/event-stream`.split(`,`),l=e.enum(c).and(e.string().regex(/^[^/]+\/[^/]+$/));e.object({fileKey:e.string(),fileName:e.string(),contentType:l,size:e.number(),etag:e.string(),createTime:e.date()});const u=e.object({fileKey:e.string().optional(),path:e.string().optional(),fileName:e.string().optional(),contentType:l.optional(),overwrite:e.boolean().optional(),file:e.union([e.instanceof(i,{error:`Stream cannot be empty`}),e.union([e.instanceof(Buffer,{error:`Buffer is required`}),e.instanceof(Uint8Array,{error:`Uint8Array is required`})]).transform(e=>e instanceof Uint8Array&&!(e instanceof Buffer)?Buffer.from(e):e)])});e.object({...u.omit({fileKey:!0,overwrite:!0,path:!0}).shape});const d=e.object({accessURL:e.string()});e.object({username:e.string(),contact:e.string().nullish(),memberName:e.string().nullish(),orgs:e.array(e.object({pathId:e.string(),name:e.string()})),groups:e.array(e.object({name:e.string()}))});const f=e.enum([`uploadFile`,`userInfo`]).enum,p=e=>[e,null];function m(e,t){return h(e)?[null,e]:[null,{reason:e,error:t}]}function h(e){return!!(e&&typeof e==`object`&&`reason`in e&&`error`in e)}const g=`__host_invoke__`,_=`__plugin_ipc_stream__`,v=`__pluginIpcDuplexReply__`;var y=class{pending=new Map;readyHandlers=new Set;errorHandlers=new Set;streamHandlers=new Map;incomingStreams=new Map;bufferedIncomingStreams=new Map;pendingStreamWaiters=new Map;requestHandler=null;eventHandler=null;endpoint;options;unsubscribeMessage;closed=!1;constructor(e,t={}){C(e)?(this.endpoint=e,this.options=t):(this.endpoint=process,this.options=e??{}),this.unsubscribeMessage=x(this.endpoint,e=>{this.dispatch(e).catch(e=>{this.emitError(e instanceof Error?e:Error(String(e)))})})}onReady(e){return this.readyHandlers.add(e),()=>{this.readyHandlers.delete(e)}}onError(e){return this.errorHandlers.add(e),()=>{this.errorHandlers.delete(e)}}setRequestHandler(e){this.requestHandler=e}setEventHandler(e){this.eventHandler=e}async requestDuplex(e,t,r){this.ensureOpen();let i=r?.requestId??n(),a=r?.timeoutMs??this.options.defaultTimeoutMs??3e4,o=Date.now(),s=r?.input===void 0?void 0:this.pipeStream(j(i),r.input,{traceId:r.traceId,streamId:r.inputStreamId,meta:r.inputMeta});s&&s.catch(e=>{this.emitError(e instanceof Error?e:Error(String(e)))});let c=await this.request(e,t,{timeoutMs:a,traceId:r?.traceId,requestId:i});if(!E(c))return{requestId:i,result:c,...s===void 0?{}:{inputDone:s}};let l;if(c.hasOutputStream){let e=Date.now()-o,t=Math.max(1,a-e);l=await this.waitForStream(M(i),{timeoutMs:t})}return{requestId:i,result:c.result,...l===void 0?{}:{output:l},...s===void 0?{}:{inputDone:s}}}replyDuplex(e,t,n){return{[v]:!0,...t===void 0?{}:{result:t},...n?.output===void 0?{}:{output:n.output},...n===void 0?{}:{options:{...n.traceId===void 0?{}:{traceId:n.traceId},...n.outputStreamId===void 0?{}:{outputStreamId:n.outputStreamId},...n.outputMeta===void 0?{}:{outputMeta:n.outputMeta}}}}}async waitForRequestInputStream(e,t){return this.waitForStream(j(e.id),t)}onStream(e,t){this.streamHandlers.has(e)||this.streamHandlers.set(e,new Set);let n=this.streamHandlers.get(e),r=t;return n.add(r),()=>{n.delete(r),n.size===0&&this.streamHandlers.delete(e)}}async waitForStream(e,t){this.ensureOpen();let n=this.bufferedIncomingStreams.get(e);if(n&&n.length>0){let t=n.shift();return n.length===0&&this.bufferedIncomingStreams.delete(e),t}return new Promise((n,r)=>{let i={resolve:n,reject:r};t?.timeoutMs!==void 0&&(i.timer=setTimeout(()=>{let t=this.pendingStreamWaiters.get(e);if(!t)return;let n=t.indexOf(i);n>=0&&t.splice(n,1),t.length===0&&this.pendingStreamWaiters.delete(e),r(Error(`Wait stream timeout: ${e}`))},t.timeoutMs)),this.pendingStreamWaiters.has(e)||this.pendingStreamWaiters.set(e,[]),this.pendingStreamWaiters.get(e).push(i)})}async createWritableStream(e,t){this.ensureOpen();let r=t?.streamId??n(),i=!1;return await this.sendStreamFrame({type:`start`,streamId:r,streamName:e,...t?.meta===void 0?{}:{meta:t.meta}},t?.traceId),{streamId:r,write:async e=>{if(i)throw Error(`Stream is already closed: ${r}`);await this.sendStreamFrame({type:`chunk`,streamId:r,chunk:e},t?.traceId)},end:async()=>{i||(i=!0,await this.sendStreamFrame({type:`end`,streamId:r},t?.traceId))},fail:async e=>{i||(i=!0,await this.sendStreamFrame({type:`error`,streamId:r,error:O(e)},t?.traceId))}}}async pipeStream(e,t,n){let r=await this.createWritableStream(e,n);try{for await(let e of A(t))await r.write(e);await r.end()}catch(e){throw await r.fail(e instanceof Error?e:Error(String(e))),e}}async request(e,t,r){this.ensureOpen();let i=r?.requestId??n(),a=r?.timeoutMs??this.options.defaultTimeoutMs??3e4;return new Promise((n,o)=>{let s=setTimeout(()=>{this.pending.delete(i),o(Object.assign(Error(`Request timeout: ${e}`),{code:`REQUEST_TIMEOUT`,requestId:i,method:e}))},a);this.pending.set(i,{resolve:n,reject:o,timer:s}),this.send({id:i,messageType:`request`,method:e,params:t,...r?.traceId===void 0?{}:{traceId:r.traceId},timestamp:Date.now()}).catch(e=>{clearTimeout(s),this.pending.delete(i),o(e)})})}async emit(e,t,r){this.ensureOpen(),await this.send({id:n(),messageType:`event`,method:e,params:t,...r===void 0?{}:{traceId:r},timestamp:Date.now()})}async sendReady(){this.ensureOpen(),await this.send({id:n(),messageType:`ready`,timestamp:Date.now()})}async reply(e,t){this.ensureOpen(),await this.send({id:e.id,messageType:`response`,...t===void 0?{}:{result:t},...e.traceId===void 0?{}:{traceId:e.traceId},timestamp:Date.now()})}async replyError(e,t){this.ensureOpen();let n=O(t);await this.send({id:e.id,messageType:`error`,error:n,...e.traceId===void 0?{}:{traceId:e.traceId},timestamp:Date.now()})}async close(e=Error(`IPC channel closed`)){this.closed||(this.closed=!0,this.unsubscribeMessage(),this.rejectAllPending(e),this.rejectAllPendingStreamWaiters(e),this.failAllIncomingStreams(e))}async dispatch(e){if(!this.closed){if(e.messageType===`response`||e.messageType===`error`){this.handleResponse(e);return}if(e.messageType===`ready`){this.readyHandlers.forEach(t=>t(e));return}if(e.messageType===`event`){if(T(e)){await this.handleStreamFrameMessage(e);return}await this.eventHandler?.(e);return}e.messageType===`request`&&await this.handleRequest(e)}}handleResponse(e){let t=this.pending.get(e.id);if(t){if(clearTimeout(t.timer),this.pending.delete(e.id),e.error){t.reject(k(e.error));return}t.resolve(e.result)}}async handleRequest(e){if(!e.method){await this.replyError(e,{code:`INVALID_REQUEST`,message:`Request method is required`});return}if(!this.requestHandler){await this.replyError(e,{code:`METHOD_NOT_FOUND`,message:`Method not found: ${e.method}`});return}try{let t=await this.requestHandler(e);if(D(t)){await this.handleDuplexReply(e,t);return}await this.reply(e,t)}catch(t){await this.replyError(e,t instanceof Error?t:Error(String(t)))}}rejectAllPending(e){this.pending.forEach((t,n)=>{clearTimeout(t.timer),t.reject(e),this.pending.delete(n)})}rejectAllPendingStreamWaiters(e){this.pendingStreamWaiters.forEach((t,n)=>{t.forEach(t=>{t.timer&&clearTimeout(t.timer),t.reject(e)}),this.pendingStreamWaiters.delete(n)})}failAllIncomingStreams(e){this.incomingStreams.forEach((t,n)=>{t.stream.fail(e),this.incomingStreams.delete(n)}),this.bufferedIncomingStreams.clear()}async sendStreamFrame(e,t){await this.emit(_,e,t)}async handleDuplexReply(e,t){let n=t.options?.traceId??e.traceId;t.output!==void 0&&this.pipeStream(M(e.id),t.output,{traceId:n,streamId:t.options?.outputStreamId,meta:t.options?.outputMeta}).catch(e=>{this.emitError(e instanceof Error?e:Error(String(e)))}),await this.reply(e,{[v]:!0,hasOutputStream:t.output!==void 0,...t.result===void 0?{}:{result:t.result}})}async handleStreamFrameMessage(e){let t=e.params;switch(t.type){case`start`:{let n={streamId:t.streamId,streamName:t.streamName,stream:a.create(),...e.traceId===void 0?{}:{traceId:e.traceId},...t.meta===void 0?{}:{meta:t.meta}};this.incomingStreams.set(t.streamId,n),this.dispatchIncomingStream(n);return}case`chunk`:{let e=this.incomingStreams.get(t.streamId);if(!e){this.emitError(Error(`Stream not found: ${t.streamId}`));return}e.stream.write(t.chunk);return}case`end`:{let e=this.incomingStreams.get(t.streamId);if(!e)return;e.stream.close(),this.incomingStreams.delete(t.streamId);return}case`error`:{let e=this.incomingStreams.get(t.streamId);if(!e)return;e.stream.fail(k(t.error)),this.incomingStreams.delete(t.streamId);return}}}dispatchIncomingStream(e){let t=!1,n=this.pendingStreamWaiters.get(e.streamName);if(n&&n.length>0){let r=n.shift();r.timer&&clearTimeout(r.timer),n.length===0&&this.pendingStreamWaiters.delete(e.streamName),r.resolve(e),t=!0}let r=this.streamHandlers.get(e.streamName);if(r&&r.size>0){r.forEach(t=>{Promise.resolve(t(e)).catch(e=>{this.emitError(e instanceof Error?e:Error(String(e)))})});return}t||(this.bufferedIncomingStreams.has(e.streamName)||this.bufferedIncomingStreams.set(e.streamName,[]),this.bufferedIncomingStreams.get(e.streamName).push(e))}emitError(e){this.errorHandlers.forEach(t=>t(e))}async send(e){await S(this.endpoint,e)}ensureOpen(){if(this.closed)throw Error(`IPC channel closed`)}};function b(e){return new y(process,e)}function x(e,t){let n=e,r=e=>{w(e)&&t(e)};return n.on(`message`,r),()=>n.off(`message`,r)}function S(e,t){let n=e;if(typeof n.send!=`function`)throw Error(`IPC channel not available`);return new Promise((e,r)=>{n.send(t,t=>{if(t){r(t);return}e()})})}function C(e){return!!(e&&typeof e==`object`&&`on`in e&&typeof e.on==`function`&&`off`in e&&typeof e.off==`function`)}function w(e){return!!(e&&typeof e==`object`&&`messageType`in e)}function T(e){return e.messageType===`event`&&e.method===_}function E(e){return!!(e&&typeof e==`object`&&v in e&&`hasOutputStream`in e)}function D(e){return!!(e&&typeof e==`object`&&v in e)}function O(e){return typeof e==`string`?{code:`HANDLER_ERROR`,message:e}:(e instanceof Error,{code:e.code??`HANDLER_ERROR`,message:e.message,...e.stack===void 0?{}:{stack:e.stack}})}function k(e){return Object.assign(Error(e.message),{code:e.code,stack:e.stack})}function A(e){return e instanceof a?e.values():e}function j(e){return`__plugin_ipc_request_input_stream__:${e}`}function M(e){return`__plugin_ipc_request_output_stream__:${e}`}var N=class{constructor(e,t={}){this.channel=e,this.options=t}async userInfo(){try{let[e,t]=(await this.channel.requestDuplex(g,{method:f.userInfo,args:{}},{requestId:n(),traceId:this.options.invocationId})).result;return t?m({en:`Failed to get user info`,"zh-CN":`获取用户信息失败`},t):p(e)}catch(e){return m({en:`Failed to get user info`,"zh-CN":`获取用户信息失败`},e)}}async uploadFile(e){try{let[t,r]=(await this.channel.requestDuplex(g,{method:f.uploadFile,args:{contentType:e.contentType,fileName:e.fileName}},{requestId:n(),traceId:this.options.invocationId,input:this.toUploadInputStream(e.file)})).result;return r?m({en:`Failed to upload file`,"zh-CN":`上传文件失败`},r):p(d.parse(t))}catch(e){return m({en:`Failed to upload file`,"zh-CN":`上传文件失败`},e)}}toUploadInputStream(e){return e instanceof r.Readable?e:r.Readable.from(Buffer.from(e))}};const P=e.enum([`en`,`zh-CN`,`zh-Hant`]).enum;e.object({[P.en]:e.string(),[P[`zh-CN`]]:e.string().optional(),[P[`zh-Hant`]]:e.string().optional()});const F=e.object({[P.en]:e.string(),[P[`zh-CN`]]:e.string(),[P[`zh-Hant`]]:e.string()});e.object({pluginId:e.string(),version:e.string(),etag:e.string()});const I=e.literal(`system`).or(e.string()),L=e.object({id:e.string(),name:F});e.array(L);const R=e.enum([`localPool`,`serverless`]).enum;e.object({pluginId:e.string(),version:e.string().optional(),source:I.optional()});var z=class{channel;getChannel(){if(!this.channel)throw Error(`Channel is not initialized yet.`);return this.channel}mode;checkRuntimeMode(){process.env.RUNTIME_MODE==R.localPool&&(this.mode=R.localPool),process.env.RUNTIME_MODE===`dev`&&(this.mode=`dev`)}async init(){this.checkRuntimeMode(),this.mode===`localPool`&&(this.channel=b(),setImmediate(()=>this.getChannel().sendReady())),this.mode===`dev`&&(this.channel=B().pluginChannel,setImmediate(()=>this.getChannel().sendReady()))}constructor(){this.init()}};function B(){let e=globalThis.__FASTGPT_PLUGIN_LOCAL_DEBUG_RUNTIME__;if(!e)throw Error(`Local debug runtime is not initialized. Set it before importing the plugin.`);return e}function V(e){return e}var H=class t extends z{toolHandlers=new Map;childManifests=new Map;secretSchema=e.record(e.string(),e.unknown());constructor(e){super(),this.userToolManifest=e,this.mode&&this.getChannel().setRequestHandler(async e=>{if(e.method===`run`)try{let{input:t,systemVar:n,childId:r,secrets:i}=e.params,o=this.toolHandlers.get(r??`tool`);if(!o)throw Error(`No tool registered`);let c=a.create();return(async()=>{try{let r=await o.handler(t,{systemVar:n,secrets:i,invoke:new N(this.getChannel(),{invocationId:e.traceId}),streamResponse:e=>{c.send({type:`stream`,data:e})}});c.send({type:`response`,data:r})}catch(e){c.send({data:s(e,`Unknown error during tool execution`),type:`error`})}finally{c.end()}})(),this.getChannel().replyDuplex(e,void 0,{output:c})}catch(t){let n=a.create();return n.write({data:s(t,`Unknown error during tool execution`),type:`error`}),n.end(),this.getChannel().replyDuplex(e,void 0,{output:n})}})}setSecretSchema(e){this.secretSchema=e}registerTool(e,t=`tool`,n){this.toolHandlers.set(t,e),n&&this.childManifests.set(t,n)}static getInstance(e){return new t(e)}getSecretSchema(){return this.secretSchema}getToolHandler(e=`tool`){return this.toolHandlers.get(e)}getUserToolManifest(){return this.userToolManifest}getChildManifests(){return[...this.childManifests.values()]}};const U=({manifest:t,handler:n})=>{let r=H.getInstance(t);return r.setSecretSchema(n.secretSchema??e.object()),r.registerTool(n),r},W=({manifest:t,children:n,secretSchema:r})=>{let i=H.getInstance(t);return n.forEach(e=>{i.registerTool(e.handler,e.id,{id:e.id,description:e.description,name:e.name,...e.icon===void 0?{}:{icon:e.icon},...e.toolDescription===void 0?{}:{toolDescription:e.toolDescription}})}),i.setSecretSchema(r??e.object()),i};export{V as createToolHandler,U as defineTool,W as defineToolSet};
|
package/package.json
CHANGED
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fastgpt-plugin/sdk-factory",
|
|
3
|
-
"version": "0.0.1-alpha.
|
|
4
|
-
"peerDependencies": {
|
|
5
|
-
"zod": "^4"
|
|
6
|
-
},
|
|
7
|
-
"scripts": {
|
|
8
|
-
"build": "tsdown"
|
|
9
|
-
},
|
|
3
|
+
"version": "0.0.1-alpha.4",
|
|
10
4
|
"devDependencies": {
|
|
11
|
-
"tsdown": "
|
|
5
|
+
"tsdown": "^0.21.10"
|
|
12
6
|
},
|
|
13
7
|
"type": "module",
|
|
14
8
|
"files": [
|
|
@@ -28,5 +22,8 @@
|
|
|
28
22
|
"private": false,
|
|
29
23
|
"publishConfig": {
|
|
30
24
|
"access": "public"
|
|
25
|
+
},
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsdown"
|
|
31
28
|
}
|
|
32
|
-
}
|
|
29
|
+
}
|