Skip to main content

create-plugin

Create a TIS plugin conforming to TIS plugin specifications

Quellinformationen

Repository
datavane/tis
Letzte Quellaktivität
4. Oktober 2026 um 14:43
Erkannte Sprache von SKILL.md
Mehrsprachig
Sterne
1.425
Forks
302

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
create-plugin
description
Create a TIS plugin conforming to TIS plugin specifications
# TIS Plugin Creator This skill helps you create a well-structured TIS (Data Integration Service) plugin that conforms to all TIS plugin specifications. ## Core Concepts ### 顶级插件 (Top-Level Plugin) 顶级插件是独立的主体,有独立的概念意义(可类比为一辆功能正常的车)。 **特征**: - 不被任何其他插件所聚合 - 直接或间接实现 `com.qlangtech.tis.extension.Describable` 接口 - **必须实现 `com.qlangtech.tis.plugin.IdentityName` 接口** (`tis-builder-api/.../plugin/IdentityName.java`) - 例如:`DeepSeekProvider` (LLM 提供者)、`DataxIcebergWriter` (数据写入器) ### 聚合属性插件 (Aggregated Property Plugin) 聚合属性插件单独存在没有意义,必须聚合在其他插件中才有意义(可类比为车上的轮胎)。 **特征**: - 作为其他插件的 `@FormField` 属性类型存在 - 直接或间接实现 `com.qlangtech.tis.extension.Describable` 接口 - 内部有 `@TISExtension` 标注的 Descriptor 类 - **不实现 `IdentityName` 接口** - Descriptor 通常继承父类的 `BasicDescriptor` - 例如:`TemperatureSampling` (作为 `LLMProvider.sampling` 属性)、`HadoopCatalog` (作为 `DataxIcebergWriter.catalog` 属性) **代码对比**: ```java // 顶级插件示例 public class DeepSeekProvider extends LLMProvider implements IdentityName { @FormField(ordinal = 0, identity = true) public String name; // IdentityName 要求的标识字段 @TISExtension public static class DftDesc extends Descriptor<DeepSeekProvider> { // 可以覆盖 httpProcess() (如果前端有需求) } } // LLMProvider 父类(展示聚合属性插件如何被使用) public abstract class LLMProvider implements Describable<LLMProvider>, IdentityName { // ↓ 这是聚合属性字段 —— Sampling 类型是 Describable,有多个子类型实现 @FormField(ordinal = 128, validate = {Validator.require}) public Sampling sampling; // 前端可以选择 TemperatureSampling / TopPSampling / TopKSampling 等 } // 聚合属性插件示例 public class TemperatureSampling extends Sampling { // 注意:未实现 IdentityName 接口 @FormField(ordinal = 0, validate = {Validator.require}) public Double temperature; // 温度参数 @TISExtension public static class DefaultDescriptor extends BasicDescriptor { // BasicDescriptor 定义在父类 Sampling 中 // 不要覆盖 httpProcess() —— 聚合属性插件不暴露独立 HTTP 端点 @Override public String shortComment() { return "温度采样策略"; } } } ``` **关系说明**: - `DeepSeekProvider` 是顶级插件,实现 `IdentityName`,用户创建实例时命名 - `LLMProvider.sampling` 字段类型为 `Sampling`(抽象基类) - `TemperatureSampling` 是 `Sampling` 的一个具体实现,作为聚合属性插件嵌入在 `LLMProvider` 中 - 前端展示 `DeepSeekProvider` 表单时,`sampling` 字段会渲染为下拉选择器,用户可选 `TemperatureSampling` / `TopPSampling` 等子类型 ## What This Skill Does When invoked, this skill will: 1. Analyze the user-provided context to understand the plugin's functionality 2. Design the plugin structure with appropriate properties (general or aggregated) 3. Generate the complete plugin implementation including: - Main plugin class implementing `Describable` - Inner `Descriptor` class with `@TISExtension` - Properties with proper `@FormField` annotations - Property validation methods - Corresponding `.json` property descriptor file - Optional `.md` help documentation ## TIS Plugin Specifications ### Core Requirements Every TIS plugin MUST satisfy: 1. **Implement Describable Interface** - Plugin class must implement `com.qlangtech.tis.extension.Describable` (directly or via parent) 2. **Inner Descriptor Class** - Must have a `public` inner class extending `com.qlangtech.tis.extension.Descriptor` - Annotated with `@TISExtension` from `com.qlangtech.tis.extension.TISExtension` 3. **Property Requirements** - All properties must be `public` - Must be annotated with `@FormField` 4. **Property Descriptor Files** - A `.json` file in the same package under `resources/` directory - Optional `.md` file for rich markdown help content - **IMPORTANT: parent classes also need `.json`!** Even if a class is `abstract` and has no `@TISExtension` Descriptor of its own, if it declares `@FormField` fields (public fields with `@FormField` annotation), it MUST have its own `.json` file at the matching resource path. These fields' help/placeholder/dftVal are inherited by concrete subclasses; TIS looks up the `.json` for each class in the hierarchy independently. 5. **Descriptor 命名:`getDisplayName()` 禁止返回中文(CRITICAL)** - `Descriptor#getDisplayName()` 是插件的机器可读短名,**必须由纯字母组成**:不得包含中文、空格以及任何标点符号 - 需要表达中文功能说明时,让 Descriptor 实现 `com.qlangtech.tis.extension.DescriptorUseableShortComment` 接口 (`tis-plugin/src/main/java/com/qlangtech/tis/extension/DescriptorUseableShortComment.java`), 把原来的中文内容移到 `shortComment()` 的返回值,`getDisplayName()` 改写成对应的英文短名 - 命名规则:**下划线分隔的帕斯卡命名**(每个单词首字母大写,单词之间用 `_` 分隔); 全大写缩写保持全大写(`LLM` / `URL` / `AIP`);单个单词时无需下划线 - 示例对照: | 类名 | ✅ `getDisplayName()` | ✅ `shortComment()` | |---|---|---| | `CloseOverlayConfig.DefaultDescriptor` | `Close_Overlay` | `关闭浮层` | | `DisableAutoRefreshConfig.DefaultDescriptor` | `Disable_Auto_Refresh` | `关闭自动刷新` | | `StreamLlmConfig.DefaultDescriptor` | `Stream_LLM` | `调用大模型` | | `RecomputeConfig.DefaultDescriptor` | `Recompute` | `重算变量` | | `UrlClickAction.DefaultDescriptor` | `URL` | `跳转链接` | - ❌ 反例:`return "关闭浮层";`(中文)、`return "Close Overlay";`(含空格)、`return "closeOverlay";`(单词首字母未大写) - 本规则对**所有** Descriptor 子类生效,顶级插件 (Top-Level Plugin) 与聚合属性插件 (Aggregated Property Plugin) 一视同仁 ### Property Types #### General Properties Basic Java types: - `Boolean` / `boolean` - `Integer` / `int` - `String` - `Long` / `long` - `java.util.Date` - `com.qlangtech.tis.plugin.MemorySize` - Duration types #### Aggregated Properties Properties that are themselves `Describable` plugins, providing polymorphic capability. Example: `ClusterType` in `TISFlinkCDCStreamFactory`. **CRITICAL - @FormField for Aggregated Properties**: - **NEVER specify `type` attribute in @FormField for aggregated properties** - TIS automatically detects aggregated properties (properties implementing `Describable`) - Adding `type = FormFieldType.SELECTABLE` will cause TIS runtime errors **Correct** ✅: ```java @FormField(ordinal = 0, validate = {Validator.require}) public OntologyActionRule sideEffectRule; ``` **Wrong** ❌: ```java @FormField(ordinal = 0, type = FormFieldType.SELECTABLE, validate = {Validator.require}) public OntologyActionRule sideEffectRule; // This will fail at runtime! ``` **IMPORTANT**: Each concrete implementation class of a 聚合属性插件 (Aggregated Property Plugin) is a full plugin and MUST have: - Its own Java class with `@FormField` properties - Its own `@TISExtension` Descriptor - **Descriptor MUST implement `DescriptorUseableShortComment` interface** (from `tis-plugin/src/main/java/com/qlangtech/tis/extension/DescriptorUseableShortComment.java`) - Implement `shortComment()` method returning a **brief Chinese description** of the plugin's function - **Requirements for shortComment()**: - Use Chinese language (中文) - **Maximum 10 characters** (10个字以内) - **NO punctuation marks** (no periods, commas, etc.) - Will be displayed in the frontend UI to help users understand the plugin at a glance - Example: "Hadoop文件系统管理" or "Hive元数据存储" - 🔴 **同一个 Descriptor 的 `getDisplayName()` 不得返回中文**:中文说明只出现在 `shortComment()`, `getDisplayName()` 必须返回纯字母的英文短名(如 `Hadoop_Catalog`)。详见 "Core Requirements" 第 5 条 - Its own `.json` descriptor file in resources (same package path) - Optional `.md` help file if properties are complex **IdentityName Interface Rule (CRITICAL)**: - **聚合属性插件 (Aggregated Property Plugin) implementation classes generally DO NOT need to implement `IdentityName` interface** - IdentityName is typically used for 顶级插件 (Top-Level Plugin), not nested 聚合属性插件 - Reference: `tis-builder-api/src/main/java/com/qlangtech/tis/plugin/IdentityName.java` - **If a plugin implements `IdentityName` interface, it MUST have an identity property**: - One `@FormField` property MUST be marked with `identity = true` - Example: `@FormField(ordinal = 0, identity = true, validate = {Validator.require, Validator.identity})` - Without this, TIS will fail to start with an error - The identity property acts as the unique identifier for the plugin instance - **When to implement IdentityName**: - 顶级插件 (Top-Level Plugin) that users create multiple instances of (data sources, writers, readers) - Plugins that need to be referenced by name across the system - NOT for 聚合属性插件 (Aggregated Property Plugin) embedded within other plugins **Parent Class Requirements for 聚合属性插件 (Aggregated Property Plugin)**: - If a 聚合属性插件 type (e.g., `IcebergCatalog`) will have multiple concrete implementations, the **parent abstract class MUST define a `BasicDescriptor`**: - Must be a **protected abstract static** inner class - Must extend `Descriptor<ParentClassName>` - All concrete implementation classes' Descriptors MUST extend this `BasicDescriptor` - Example structure in parent class: ```java public abstract class IcebergCatalog implements Describable<IcebergCatalog> { // properties... protected abstract static class BasicDescriptor extends Descriptor<IcebergCatalog> { // common descriptor logic for all implementations } } ``` - Example in implementation class: ```java public class HadoopCatalog extends IcebergCatalog { // properties... @TISExtension() public static class DefaultDescriptor extends BasicDescriptor implements DescriptorUseableShortComment { @Override public String shortComment() { return "基于HDFS文件系统"; } @Override public String getDisplayName() { // 纯字母英文短名,下划线分隔帕斯卡命名;中文一律放 shortComment() return "Hadoop_Catalog"; } } } ``` Example: If `DataxIcebergWriter` has a 聚合属性插件 (Aggregated Property Plugin) `IcebergCatalog catalog`, and `HadoopCatalog` extends `IcebergCatalog`, then you need: - `IcebergCatalog.java` (abstract parent with protected abstract static BasicDescriptor inner class) - `HadoopCatalog.java` (with its own @FormField properties, Descriptor extends BasicDescriptor) - `HadoopCatalog.json` (describing HadoopCatalog's own properties) - Descriptor implements `DescriptorUseableShortComment` with `shortComment()` returning Chinese text (≤10 chars, no punctuation) - Optional `HadoopCatalog.md` (if properties are complex) - **DO NOT implement IdentityName** unless this is a 顶级插件 (Top-Level Plugin) (it's not in this case) ### @FormField Annotation Attributes - **identity**: Unique identifier for the plugin instance (acts as primary key) - **ordinal**: Display order in UI form (lower = higher priority, semantically related fields should be adjacent) - **advance**: Mark as advanced setting (must have default value, can be hidden) - **validate**: Frontend validation rules (see Validator options below) - **type**: Field type (see FormFieldType options below) ### Validator Options Reference: `tis-plugin/src/main/java/com/qlangtech/tis/plugin/annotation/Validator.java` - `require`: Required field - `user_name`: Username format (letters, numbers, underscore, dot, dash) - `email`: Email format - `forbid_start_with_number`: Cannot start with number - `identity`: Primary key format - `integer`: Integer format - `host`: Internet domain with optional port (e.g., `192.168.28.200:7070`) - `hostWithoutPort`: Domain without port - `url`: URL starting with http/https - `db_col_name`: Database column name format - `relative_path`: File system relative path - `absolute_path`: Unix absolute path - `none_blank`: Non-empty content ### FormFieldType Options Reference: `tis-plugin/src/main/java/com/qlangtech/tis/plugin/annotation/FormFieldType.java` - `MULTI_SELECTABLE`: Multi-select, property type `List<IdentityName>` or `List<String>` - `INPUTTEXT`: Single-line text input, property type `String` - `SELECTABLE`: Single-select dropdown (register options via `registerSelectOptions()` in Descriptor) - `PASSWORD`: Password input - `FILE`: File upload (only one per form, plugin must implement `ITmpFileStore`) - `TEXTAREA`: Multi-line text input (for SQL scripts, XML, etc.) - `DATE`: Date picker - `JDBCColumn`: JDBC column type - `INT_NUMBER`: Integer number input - `ENUM`: Enumeration selection - `DateTime`: Date-time (UTC, property type `long` or `java.util.Date`) - `DECIMAL_NUMBER`: Decimal number - `DURATION_OF_SECOND`: Duration in seconds - `DURATION_OF_MINUTE`: Duration in minutes - `DURATION_OF_HOUR`: Duration in hours - `MEMORY_SIZE_OF_BYTE`: Memory size in bytes - `MEMORY_SIZE_OF_KIBI`: Memory size in KB - `MEMORY_SIZE_OF_MEGA`: Memory size in MB ### FormFieldType 选用原则 #### 原则一:禁止 JSON 字符串输入 结构化数据不得使用 `TEXTAREA` 让用户填写 JSON 字符串,必须使用 TIS 的结构化表单机制: | 场景 | 正确做法 | 错误做法 | |---|---|---| | 列表化结构对象(如表格列配置) | `@SubForm(desClazz = XxxConfig.class)` + `List<XxxConfig>` | `@FormField(type = FormFieldType.TEXTAREA)` 手写 `[{...}]` | | 单个结构对象 | 字段类型声明为 `Describable` 子类,不指定 type(TIS 自动检测) | `@FormField(type = FormFieldType.TEXTAREA)` 手写 `{...}` | ```java // ✅ 正确:使用 @SubForm @SubForm(desClazz = WidgetColumnConfig.class, atLeastOne = false, idListGetScript = "return java.util.Collections.emptyList();") public List<WidgetColumnConfig> columns; // ❌ 错误:让用户手写 JSON @FormField(type = FormFieldType.TEXTAREA) public String columns; ``` #### 原则二:固定取值用 ENUM,动态选项用 SELECTABLE - **`ENUM`**:字段的取值集合同定有限,在 Java 代码中用枚举类硬编码。如:聚合方式(sum/count/avg/min/max)、对齐方式(left/center/right)、级别(1/2/3/4)、颜色选择(20种常用颜色)。 - **`SELECTABLE`**:选项来自运行时外部数据源,通过 `registerSelectOptions()` 或 `doGetOptions()` 动态供给。如:当前 module 的变量列表、数据库表名列。 ```java // ✅ 正确:固定取值用 ENUM + Java 枚举类 @FormField(type = FormFieldType.ENUM, ordinal = 3, required = true) public AggregationType aggregation; public enum AggregationType { sum("求和"), count("计数"), avg("平均值"), min("最小值"), max("最大值"); public final String label; AggregationType(String label) { this.label = label; } } // ❌ 错误:固定取值用 SELECTABLE(误导为动态选项) @FormField(type = FormFieldType.SELECTABLE, ordinal = 3) public String aggregation; // ❌ 错误:固定取值用 INPUTTEXT(用户不知道合法值) @FormField(type = FormFieldType.INPUTTEXT, ordinal = 3) public String aggregation; ``` #### 原则三:颜色类枚举附带 hex 色值 枚举字段为颜色选择时,在 `.json` resource 中为每个枚举项附带 `hex` 色值,用以前端渲染颜色预览圆点: ```json { "color": { "help": "选择文本颜色", "dftVal": "inherit", "enum": [ { "label": "红色", "val": "red", "hex": "#f5222d" }, { "label": "蓝色", "val": "blue", "hex": "#1890ff" } ] } } ``` #### 原则四:SELECTABLE 字段必须在 Descriptor 中注册选项
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen