@xpert-ai/plugin-sdk 3.7.1 → 3.8.0

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.
Files changed (41) hide show
  1. package/index.cjs.js +851 -834
  2. package/index.esm.js +826 -837
  3. package/package.json +5 -1
  4. package/src/index.d.ts +2 -0
  5. package/src/lib/agent/handoff/agent-chat.contract.d.ts +20 -0
  6. package/src/lib/agent/handoff/handoff-processor.decorator.d.ts +11 -0
  7. package/src/lib/agent/handoff/handoff-processor.registry.d.ts +6 -0
  8. package/src/lib/agent/handoff/handoff.interface.d.ts +17 -0
  9. package/src/lib/agent/handoff/index.d.ts +6 -0
  10. package/src/lib/agent/handoff/message-type.d.ts +24 -0
  11. package/src/lib/agent/handoff/types.d.ts +110 -0
  12. package/src/lib/agent/index.d.ts +1 -0
  13. package/src/lib/agent/middleware/runtime.d.ts +2 -0
  14. package/src/lib/agent/middleware/strategy.interface.d.ts +5 -1
  15. package/src/lib/agent/middleware/types.d.ts +73 -8
  16. package/src/lib/ai-model/ai-model.d.ts +3 -1
  17. package/src/lib/ai-model/utils/index.d.ts +1 -0
  18. package/src/lib/ai-model/utils/limits.d.ts +4 -0
  19. package/src/lib/channel/cancel-conversation.command.d.ts +14 -0
  20. package/src/lib/channel/index.d.ts +4 -0
  21. package/src/lib/channel/strategy.decorator.d.ts +23 -0
  22. package/src/lib/channel/strategy.interface.d.ts +345 -0
  23. package/src/lib/channel/strategy.registry.d.ts +30 -0
  24. package/src/lib/core/permissions/analytics.d.ts +46 -0
  25. package/src/lib/core/{permissions.d.ts → permissions/general.d.ts} +9 -12
  26. package/src/lib/core/permissions/handoff.d.ts +36 -0
  27. package/src/lib/core/permissions/index.d.ts +24 -0
  28. package/src/lib/core/permissions/operation.d.ts +8 -0
  29. package/src/lib/core/permissions/user.d.ts +29 -0
  30. package/src/lib/core/utils.d.ts +6 -0
  31. package/src/lib/integration/strategy.interface.d.ts +3 -1
  32. package/src/lib/sandbox/index.d.ts +8 -0
  33. package/src/lib/sandbox/protocol.d.ts +265 -0
  34. package/src/lib/sandbox/sandbox.d.ts +70 -0
  35. package/src/lib/sandbox/sandbox.decorator.d.ts +2 -0
  36. package/src/lib/sandbox/sandbox.interface.d.ts +38 -0
  37. package/src/lib/sandbox/sandbox.registry.d.ts +6 -0
  38. package/src/lib/toolset/strategy.interface.d.ts +2 -6
  39. package/src/lib/types.d.ts +7 -1
  40. package/src/lib/workflow/node/strategy.interface.d.ts +4 -2
  41. package/src/lib/workflow/trigger/strategy.interface.d.ts +13 -0
@@ -0,0 +1,265 @@
1
+ /**
2
+ * Protocol definition for pluggable memory backends.
3
+ *
4
+ * This module defines the BackendProtocol that all backend implementations
5
+ * must follow. Backends can store files in different locations (state, filesystem,
6
+ * database, etc.) and provide a uniform interface for file operations.
7
+ */
8
+ export type MaybePromise<T> = T | Promise<T>;
9
+ /**
10
+ * Structured file listing info.
11
+ *
12
+ * Minimal contract used across backends. Only "path" is required.
13
+ * Other fields are best-effort and may be absent depending on backend.
14
+ */
15
+ export interface FileInfo {
16
+ /** File path */
17
+ path: string;
18
+ /** Whether this is a directory */
19
+ is_dir?: boolean;
20
+ /** File size in bytes (approximate) */
21
+ size?: number;
22
+ /** ISO 8601 timestamp of last modification */
23
+ modified_at?: string;
24
+ }
25
+ /**
26
+ * Structured grep match entry.
27
+ */
28
+ export interface GrepMatch {
29
+ /** File path where match was found */
30
+ path: string;
31
+ /** Line number (1-indexed) */
32
+ line: number;
33
+ /** The matching line text */
34
+ text: string;
35
+ }
36
+ /**
37
+ * File data structure used by backends.
38
+ *
39
+ * All file data is represented as objects with this structure:
40
+ */
41
+ export interface FileData {
42
+ /** Lines of text content */
43
+ content: string[];
44
+ /** ISO format timestamp of creation */
45
+ created_at: string;
46
+ /** ISO format timestamp of last modification */
47
+ modified_at: string;
48
+ }
49
+ /**
50
+ * Result from backend write operations.
51
+ *
52
+ * Checkpoint backends populate filesUpdate with {file_path: file_data} for LangGraph state.
53
+ * External backends set filesUpdate to null (already persisted to disk/S3/database/etc).
54
+ */
55
+ export interface WriteResult {
56
+ /** Error message on failure, undefined on success */
57
+ error?: string;
58
+ /** File path of written file, undefined on failure */
59
+ path?: string;
60
+ /**
61
+ * State update dict for checkpoint backends, null for external storage.
62
+ * Checkpoint backends populate this with {file_path: file_data} for LangGraph state.
63
+ * External backends set null (already persisted to disk/S3/database/etc).
64
+ */
65
+ filesUpdate?: Record<string, FileData> | null;
66
+ /** Metadata for the write operation, attached to the ToolMessage */
67
+ metadata?: Record<string, unknown>;
68
+ }
69
+ /**
70
+ * Result from backend edit operations.
71
+ *
72
+ * Checkpoint backends populate filesUpdate with {file_path: file_data} for LangGraph state.
73
+ * External backends set filesUpdate to null (already persisted to disk/S3/database/etc).
74
+ */
75
+ export interface EditResult {
76
+ /** Error message on failure, undefined on success */
77
+ error?: string;
78
+ /** File path of edited file, undefined on failure */
79
+ path?: string;
80
+ /**
81
+ * State update dict for checkpoint backends, null for external storage.
82
+ * Checkpoint backends populate this with {file_path: file_data} for LangGraph state.
83
+ * External backends set null (already persisted to disk/S3/database/etc).
84
+ */
85
+ filesUpdate?: Record<string, FileData> | null;
86
+ /** Number of replacements made, undefined on failure */
87
+ occurrences?: number;
88
+ /** Metadata for the edit operation, attached to the ToolMessage */
89
+ metadata?: Record<string, unknown>;
90
+ }
91
+ /**
92
+ * Result of code execution.
93
+ * Simplified schema optimized for LLM consumption.
94
+ */
95
+ export interface ExecuteResponse {
96
+ /** Combined stdout and stderr output of the executed command */
97
+ output: string;
98
+ /** The process exit code. 0 indicates success, non-zero indicates failure */
99
+ exitCode: number | null;
100
+ /** Whether the output was truncated due to backend limitations */
101
+ truncated: boolean;
102
+ }
103
+ /**
104
+ * Standardized error codes for file upload/download operations.
105
+ */
106
+ export type FileOperationError = "file_not_found" | "permission_denied" | "is_directory" | "invalid_path";
107
+ /**
108
+ * Result of a single file download operation.
109
+ */
110
+ export interface FileDownloadResponse {
111
+ /** The file path that was requested */
112
+ path: string;
113
+ /** File contents as Uint8Array on success, null on failure */
114
+ content: Uint8Array | null;
115
+ /** Standardized error code on failure, null on success */
116
+ error: FileOperationError | null;
117
+ }
118
+ /**
119
+ * Result of a single file upload operation.
120
+ */
121
+ export interface FileUploadResponse {
122
+ /** The file path that was requested */
123
+ path: string;
124
+ /** Standardized error code on failure, null on success */
125
+ error: FileOperationError | null;
126
+ }
127
+ /**
128
+ * Protocol for pluggable memory backends (single, unified).
129
+ *
130
+ * Backends can store files in different locations (state, filesystem, database, etc.)
131
+ * and provide a uniform interface for file operations.
132
+ *
133
+ * All file data is represented as objects with the FileData structure.
134
+ *
135
+ * Methods can return either direct values or Promises, allowing both
136
+ * synchronous and asynchronous implementations.
137
+ */
138
+ export interface BackendProtocol {
139
+ /**
140
+ * Structured listing with file metadata.
141
+ *
142
+ * Lists files and directories in the specified directory (non-recursive).
143
+ * Directories have a trailing / in their path and is_dir=true.
144
+ *
145
+ * @param path - Absolute path to directory
146
+ * @returns List of FileInfo objects for files and directories directly in the directory
147
+ */
148
+ lsInfo(path: string): MaybePromise<FileInfo[]>;
149
+ /**
150
+ * Read file content with line numbers or an error string.
151
+ *
152
+ * @param filePath - Absolute file path
153
+ * @param offset - Line offset to start reading from (0-indexed), default 0
154
+ * @param limit - Maximum number of lines to read, default 500
155
+ * @returns Formatted file content with line numbers, or error message
156
+ */
157
+ read(filePath: string, offset?: number, limit?: number): MaybePromise<string>;
158
+ /**
159
+ * Structured search results or error string for invalid input.
160
+ *
161
+ * Searches file contents for a regex pattern.
162
+ *
163
+ * @param pattern - Regex pattern to search for
164
+ * @param path - Base path to search from (default: null)
165
+ * @param glob - Optional glob pattern to filter files (e.g., "*.py")
166
+ * @returns List of GrepMatch objects or error string for invalid regex
167
+ */
168
+ grepRaw(pattern: string, path?: string | null, glob?: string | null): MaybePromise<GrepMatch[] | string>;
169
+ /**
170
+ * Structured glob matching returning FileInfo objects.
171
+ *
172
+ * @param pattern - Glob pattern (e.g., `*.py`, `**\/*.ts`)
173
+ * @param path - Base path to search from (default: "/")
174
+ * @returns List of FileInfo objects matching the pattern
175
+ */
176
+ globInfo(pattern: string, path?: string): MaybePromise<FileInfo[]>;
177
+ /**
178
+ * Create a new file.
179
+ *
180
+ * @param filePath - Absolute file path
181
+ * @param content - File content as string
182
+ * @returns WriteResult with error populated on failure
183
+ */
184
+ write(filePath: string, content: string): MaybePromise<WriteResult>;
185
+ /**
186
+ * Edit a file by replacing string occurrences.
187
+ *
188
+ * @param filePath - Absolute file path
189
+ * @param oldString - String to find and replace
190
+ * @param newString - Replacement string
191
+ * @param replaceAll - If true, replace all occurrences (default: false)
192
+ * @returns EditResult with error, path, filesUpdate, and occurrences
193
+ */
194
+ edit(filePath: string, oldString: string, newString: string, replaceAll?: boolean): MaybePromise<EditResult>;
195
+ /**
196
+ * Upload multiple files.
197
+ *
198
+ * @param files - List of [path, content] tuples to upload
199
+ * @returns List of FileUploadResponse objects, one per input file
200
+ */
201
+ uploadFiles(files: Array<[string, Uint8Array]>): MaybePromise<FileUploadResponse[]>;
202
+ /**
203
+ * Download multiple files.
204
+ *
205
+ * @param paths - List of file paths to download
206
+ * @returns List of FileDownloadResponse objects, one per input path
207
+ */
208
+ downloadFiles(paths: string[]): MaybePromise<FileDownloadResponse[]>;
209
+ }
210
+ /**
211
+ * Protocol for sandboxed backends with isolated runtime.
212
+ * Sandboxed backends run in isolated environments (e.g., containers)
213
+ * and communicate via defined interfaces.
214
+ */
215
+ export interface SandboxBackendProtocol extends BackendProtocol {
216
+ /**
217
+ * Execute a command in the sandbox.
218
+ *
219
+ * @param command - Full shell command string to execute
220
+ * @returns ExecuteResponse with combined output, exit code, and truncation flag
221
+ */
222
+ execute(command: string): MaybePromise<ExecuteResponse>;
223
+ /** Unique identifier for the sandbox backend instance */
224
+ readonly id: string;
225
+ }
226
+ /**
227
+ * Type guard to check if a backend supports execution.
228
+ *
229
+ * @param backend - Backend instance to check
230
+ * @returns True if the backend implements SandboxBackendProtocol
231
+ */
232
+ export declare function isSandboxBackend(backend: BackendProtocol): backend is SandboxBackendProtocol;
233
+ /**
234
+ * State and store container for backend initialization.
235
+ *
236
+ * This provides a clean interface for what backends need to access:
237
+ * - state: Current agent state (with files, messages, etc.)
238
+ * - store: Optional persistent store for cross-conversation data
239
+ *
240
+ * Different contexts build this differently:
241
+ * - Tools: Extract state via getCurrentTaskInput(config)
242
+ * - Middleware: Use request.state directly
243
+ */
244
+ export interface StateAndStore {
245
+ /** Current agent state with files, messages, etc. */
246
+ state: unknown;
247
+ /** Optional BaseStore for persistent cross-conversation storage */
248
+ /** Optional assistant ID for per-assistant isolation in store */
249
+ assistantId?: string;
250
+ }
251
+ /**
252
+ * Factory function type for creating backend instances.
253
+ *
254
+ * Backends receive StateAndStore which contains the current state
255
+ * and optional store, extracted from the execution context.
256
+ *
257
+ * @example
258
+ * ```typescript
259
+ * // Using in middleware
260
+ * const middleware = createFilesystemMiddleware({
261
+ * backend: (stateAndStore) => new StateBackend(stateAndStore)
262
+ * });
263
+ * ```
264
+ */
265
+ export type BackendFactory = (stateAndStore: StateAndStore) => BackendProtocol;
@@ -0,0 +1,70 @@
1
+ /**
2
+ * BaseSandbox: Abstract base class for sandbox backends with command execution.
3
+ *
4
+ * This class provides default implementations for all SandboxBackendProtocol
5
+ * methods using shell commands executed via execute(). Concrete implementations
6
+ * only need to implement the execute() method.
7
+ *
8
+ * Requires Node.js 20+ on the sandbox host.
9
+ */
10
+ import type { EditResult, ExecuteResponse, FileDownloadResponse, FileInfo, FileUploadResponse, GrepMatch, MaybePromise, SandboxBackendProtocol, WriteResult } from "./protocol";
11
+ /**
12
+ * Base sandbox implementation with execute() as the only abstract method.
13
+ *
14
+ * This class provides default implementations for all SandboxBackendProtocol
15
+ * methods using shell commands executed via execute(). Concrete implementations
16
+ * only need to implement the execute() method.
17
+ *
18
+ * Requires Node.js 20+ on the sandbox host.
19
+ */
20
+ export declare abstract class BaseSandbox implements SandboxBackendProtocol {
21
+ /** Unique identifier for the sandbox backend */
22
+ abstract readonly id: string;
23
+ /**
24
+ * Execute a command in the sandbox.
25
+ * This is the only method concrete implementations must provide.
26
+ */
27
+ abstract execute(command: string): MaybePromise<ExecuteResponse>;
28
+ /**
29
+ * Upload multiple files to the sandbox.
30
+ * Implementations must support partial success.
31
+ */
32
+ abstract uploadFiles(files: Array<[string, Uint8Array]>): MaybePromise<FileUploadResponse[]>;
33
+ /**
34
+ * Download multiple files from the sandbox.
35
+ * Implementations must support partial success.
36
+ */
37
+ abstract downloadFiles(paths: string[]): MaybePromise<FileDownloadResponse[]>;
38
+ /**
39
+ * List files and directories in the specified directory (non-recursive).
40
+ *
41
+ * @param path - Absolute path to directory
42
+ * @returns List of FileInfo objects for files and directories directly in the directory.
43
+ */
44
+ lsInfo(path: string): Promise<FileInfo[]>;
45
+ /**
46
+ * Read file content with line numbers.
47
+ *
48
+ * @param filePath - Absolute file path
49
+ * @param offset - Line offset to start reading from (0-indexed)
50
+ * @param limit - Maximum number of lines to read
51
+ * @returns Formatted file content with line numbers, or error message
52
+ */
53
+ read(filePath: string, offset?: number, limit?: number): Promise<string>;
54
+ /**
55
+ * Structured search results or error string for invalid input.
56
+ */
57
+ grepRaw(pattern: string, path?: string, glob?: string | null): Promise<GrepMatch[] | string>;
58
+ /**
59
+ * Structured glob matching returning FileInfo objects.
60
+ */
61
+ globInfo(pattern: string, path?: string): Promise<FileInfo[]>;
62
+ /**
63
+ * Create a new file with content.
64
+ */
65
+ write(filePath: string, content: string): Promise<WriteResult>;
66
+ /**
67
+ * Edit a file by replacing string occurrences.
68
+ */
69
+ edit(filePath: string, oldString: string, newString: string, replaceAll?: boolean): Promise<EditResult>;
70
+ }
@@ -0,0 +1,2 @@
1
+ export declare const SANDBOX_PROVIDER = "SANDBOX_PROVIDER";
2
+ export declare const SandboxProviderStrategy: (provider: string) => <TFunction extends Function, Y>(target: object | TFunction, propertyKey?: string | symbol, descriptor?: TypedPropertyDescriptor<Y>) => void;
@@ -0,0 +1,38 @@
1
+ import { TSandboxProviderMeta } from "@metad/contracts";
2
+ import { SandboxBackendProtocol } from "./protocol";
3
+ export type SandboxProviderCreateOptions = {
4
+ /**
5
+ * Working space directory for the sandbox instance
6
+ */
7
+ workingDirectory?: string;
8
+ /**
9
+ * Sandbox container environment identifier
10
+ */
11
+ environmentId?: string;
12
+ /**
13
+ * Tenant identifier
14
+ */
15
+ tenantId?: string;
16
+ /**
17
+ * User identifier
18
+ */
19
+ userId?: string;
20
+ /**
21
+ * Project identifier
22
+ */
23
+ projectId?: string;
24
+ };
25
+ export interface ISandboxProvider<T extends SandboxBackendProtocol = SandboxBackendProtocol> {
26
+ type: string;
27
+ meta: TSandboxProviderMeta;
28
+ /**
29
+ * Create a new sandbox instance
30
+ *
31
+ * @param options
32
+ */
33
+ create(options?: SandboxProviderCreateOptions): Promise<T>;
34
+ /**
35
+ * Get default working directory for the sandbox instances
36
+ */
37
+ getDefaultWorkingDir(): string;
38
+ }
@@ -0,0 +1,6 @@
1
+ import { DiscoveryService, Reflector } from '@nestjs/core';
2
+ import { BaseStrategyRegistry } from '../strategy';
3
+ import { ISandboxProvider } from './sandbox.interface';
4
+ export declare class SandboxProviderRegistry extends BaseStrategyRegistry<ISandboxProvider> {
5
+ constructor(discoveryService: DiscoveryService, reflector: Reflector);
6
+ }
@@ -1,5 +1,5 @@
1
1
  import { DynamicStructuredTool } from '@langchain/core/tools';
2
- import { I18nObject } from '@metad/contracts';
2
+ import { I18nObject, IconDefinition } from '@metad/contracts';
3
3
  import { ZodSchema } from 'zod';
4
4
  import { BuiltinToolset } from './builtin';
5
5
  export interface IToolsetStrategy<TConfig = any> {
@@ -13,11 +13,7 @@ export interface IToolsetStrategy<TConfig = any> {
13
13
  label: I18nObject;
14
14
  description?: I18nObject;
15
15
  configSchema: any;
16
- icon?: {
17
- svg?: string;
18
- png?: string;
19
- color?: string;
20
- };
16
+ icon?: IconDefinition;
21
17
  };
22
18
  /**
23
19
  * Validate the configuration
@@ -1,6 +1,8 @@
1
1
  import { PluginMeta } from '@metad/contracts';
2
2
  import type { DynamicModule, INestApplicationContext } from '@nestjs/common';
3
+ import { ModuleRef } from '@nestjs/core';
3
4
  import type { ZodSchema } from 'zod';
5
+ import type { Permissions } from './core/permissions';
4
6
  export declare const ORGANIZATION_METADATA_KEY = "xpert:organizationId";
5
7
  export declare const PLUGIN_METADATA_KEY = "xpert:pluginName";
6
8
  export declare const GLOBAL_ORGANIZATION_SCOPE = "global";
@@ -32,11 +34,14 @@ export interface PluginConfigSpec<T extends object = any> {
32
34
  export interface XpertPlugin<TConfig extends object = any> extends PluginLifecycle, PluginHealth {
33
35
  meta: PluginMeta;
34
36
  config?: PluginConfigSpec<TConfig>;
37
+ /** Declares the required system-level permissions for this plugin. */
38
+ permissions?: Permissions;
35
39
  /** Returns the DynamicModule to be mounted to the main application (can be set as global) */
36
40
  register(ctx: PluginContext<TConfig>): DynamicModule;
37
41
  }
38
42
  export interface PluginContext<TConfig extends object = any> {
39
- app: INestApplicationContext;
43
+ module: ModuleRef;
44
+ app?: INestApplicationContext;
40
45
  logger: PluginLogger;
41
46
  config: TConfig;
42
47
  /** Helper method to access other Providers in the container */
@@ -49,3 +54,4 @@ export interface PluginLogger {
49
54
  warn(msg: string, meta?: any): void;
50
55
  error(msg: string, meta?: any): void;
51
56
  }
57
+ export type PromiseOrValue<T> = T | Promise<T>;
@@ -1,6 +1,7 @@
1
1
  import { Runnable } from '@langchain/core/runnables';
2
2
  import { BaseChannel } from '@langchain/langgraph';
3
- import { IEnvironment, IWorkflowNode, TWorkflowNodeMeta, TXpertGraph, TXpertParameter, TXpertTeamNode } from '@metad/contracts';
3
+ import { IEnvironment, IWorkflowNode, TWorkflowNodeMeta, TXpertGraph, TWorkflowVarGroup, TXpertParameter, TXpertTeamNode } from '@metad/contracts';
4
+ import { PromiseOrValue } from '../../types';
4
5
  export type TWorkflowNodeParams<TConfig = any> = {
5
6
  xpertId: string;
6
7
  agentKey?: string;
@@ -36,6 +37,7 @@ export interface IWorkflowNodeStrategy<TConfig = any, TResult = any> {
36
37
  xpertId: string;
37
38
  environment: IEnvironment;
38
39
  isDraft: boolean;
39
- }): TWorkflowNodeResult;
40
+ }): PromiseOrValue<TWorkflowNodeResult>;
41
+ inputVariables?(entity: IWorkflowNode, variables?: TWorkflowVarGroup[]): TXpertParameter[];
40
42
  outputVariables(entity: IWorkflowNode): TXpertParameter[];
41
43
  }
@@ -1,4 +1,9 @@
1
1
  import { TWorkflowTriggerMeta, TXpertTeamNode } from '@metad/contracts';
2
+ export type TWorkflowTriggerBootstrapMode = 'replay_publish' | 'skip';
3
+ export type TWorkflowTriggerBootstrapConfig = {
4
+ mode: TWorkflowTriggerBootstrapMode;
5
+ critical?: boolean;
6
+ };
2
7
  export type TWorkflowTriggerParams<T> = {
3
8
  xpertId: string;
4
9
  agentKey?: string;
@@ -7,6 +12,14 @@ export type TWorkflowTriggerParams<T> = {
7
12
  };
8
13
  export interface IWorkflowTriggerStrategy<T> {
9
14
  meta: TWorkflowTriggerMeta;
15
+ /**
16
+ * Controls how this trigger should be recovered during system bootstrap.
17
+ *
18
+ * Default when omitted:
19
+ * - mode: "replay_publish"
20
+ * - critical: false
21
+ */
22
+ bootstrap?: TWorkflowTriggerBootstrapConfig;
10
23
  validate(payload: TWorkflowTriggerParams<T>): Promise<any[]>;
11
24
  /**
12
25
  * Initialize the trigger when publish xpert workflow