@xpert-ai/plugin-sdk 3.21.0 → 3.21.1
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/{README.md → docs/README.md} +10 -8
- package/docs/en/KNOWLEDGEBASE_API.md +42 -0
- package/docs/en/PERMISSIONS.md +173 -0
- package/{RESOURCE-CARDS.md → docs/en/RESOURCE-CARDS.md} +5 -5
- package/docs/en/SCHEMA_SPECIFICATION.md +325 -0
- package/{TOOL-IMAGES.md → docs/en/TOOL-IMAGES.md} +1 -1
- package/docs/en/structured-knowledge-graph.md +60 -0
- package/docs/en/video-generation-protocol.md +86 -0
- package/docs/en/view-extension-protocol.md +413 -0
- package/index.cjs.js +14 -0
- package/index.esm.js +14 -1
- package/package.json +1 -1
- package/src/lib/rag/capability/index.d.ts +1 -0
- package/src/lib/rag/capability/knowledgebase-catalog.d.ts +78 -0
- package/src/lib/rag/capability/knowledgebase.d.ts +65 -0
- package/PERMISSIONS.md +0 -181
- package/SCHEMA_SPECIFICATION.md +0 -335
- /package/{CHANGELOG.md → docs/CHANGELOG.md} +0 -0
- /package/{MIDDLEWARE_APPS.md → docs/en/MIDDLEWARE_APPS.md} +0 -0
- /package/{RESOURCE-CARDS-VALIDATION.md → docs/en/RESOURCE-CARDS-VALIDATION.md} +0 -0
- /package/{runtime-capabilities.md → docs/en/runtime-capabilities.md} +0 -0
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
## Runtime capabilities
|
|
4
4
|
|
|
5
|
-
See [platform capabilities and scoped factories](./runtime-capabilities.md) for domain registration, execution-scoped APIs and usage outside Agent middleware.
|
|
5
|
+
See [platform capabilities and scoped factories](./en/runtime-capabilities.md) for domain registration, execution-scoped APIs and usage outside Agent middleware.
|
|
6
|
+
|
|
7
|
+
See [knowledgebase APIs](./en/KNOWLEDGEBASE_API.md) for resource discovery, readiness, permissions and migration from legacy listing.
|
|
6
8
|
|
|
7
9
|
## Building
|
|
8
10
|
|
|
@@ -14,11 +16,11 @@ Run `nx test plugin-sdk` to execute the unit tests via [Jest](https://jestjs.io)
|
|
|
14
16
|
|
|
15
17
|
## Schema config
|
|
16
18
|
|
|
17
|
-
[Schema UI
|
|
19
|
+
[Schema UI Extension Specification](./en/SCHEMA_SPECIFICATION.md)
|
|
18
20
|
|
|
19
21
|
## Permissions
|
|
20
22
|
|
|
21
|
-
[
|
|
23
|
+
[Plugin Permission Design Guide](./en/PERMISSIONS.md)
|
|
22
24
|
|
|
23
25
|
## Decorator-driven business Tools
|
|
24
26
|
|
|
@@ -115,13 +117,13 @@ For completed operations, `prepareToolResult(() => project(result), () => minima
|
|
|
115
117
|
|
|
116
118
|
For a host-native MCP App, declare each static HTML bundle once in the Provider's `apps` array, then bind a Tool with `mcp.app.resourceKey` and include `app` visibility. The App key must exist in the same Provider and its entry must be a relative `.html` path inside the packaged plugin. The host publishes the bundle as a `ui://` resource; plugins must not create a stdio server or put CSP/credentials in Tool results.
|
|
117
119
|
|
|
118
|
-
Agent middleware can also expose these Apps without a published Toolset. See [middleware Apps and post-tool continuation](./MIDDLEWARE_APPS.md) for `app` bindings and `interruptAfter` checkpoints.
|
|
120
|
+
Agent middleware can also expose these Apps without a published Toolset. See [middleware Apps and post-tool continuation](./en/MIDDLEWARE_APPS.md) for `app` bindings and `interruptAfter` checkpoints.
|
|
119
121
|
|
|
120
122
|
The host owns the public MCP endpoint identity. It combines the plugin's stable `artifactNamespace`, the Provider key, and an opaque scope hash; client names and product-specific identifiers do not belong in the slug. A tenant- or system-level plugin has one tenant-scoped Publication and capability snapshot, while each organization receives an independent access grant and organization-bound credential. An organization-level plugin receives a dedicated organization-scoped Publication.
|
|
121
123
|
|
|
122
124
|
## View extensions
|
|
123
125
|
|
|
124
|
-
[View Extension Protocol](./
|
|
126
|
+
[View Extension Protocol](./en/view-extension-protocol.md)
|
|
125
127
|
|
|
126
128
|
## Browser collaboration client
|
|
127
129
|
|
|
@@ -159,7 +161,7 @@ containing these interfaces. They are not part of the published SDK 3.18.3 basel
|
|
|
159
161
|
|
|
160
162
|
## Conversation resource receipts
|
|
161
163
|
|
|
162
|
-
See [RESOURCE-CARDS.md](./RESOURCE-CARDS.md) for the public protocol, tool/middleware emitter, transactional Project provider example, and coordinated release order.
|
|
164
|
+
See [RESOURCE-CARDS.md](./en/RESOURCE-CARDS.md) for the public protocol, tool/middleware emitter, transactional Project provider example, and coordinated release order.
|
|
163
165
|
|
|
164
166
|
## Project task business types
|
|
165
167
|
|
|
@@ -175,7 +177,7 @@ export class ExampleTasks implements IProjectTaskProvider {
|
|
|
175
177
|
{
|
|
176
178
|
key: 'example.tasks.illustration',
|
|
177
179
|
presentation: {
|
|
178
|
-
label: { en_US: 'Construction images'
|
|
180
|
+
label: { en_US: 'Construction images' },
|
|
179
181
|
icon: 'Images'
|
|
180
182
|
}
|
|
181
183
|
}
|
|
@@ -210,4 +212,4 @@ Deploy matching contracts, SDK and host support before a plugin starts emitting
|
|
|
210
212
|
|
|
211
213
|
## Tool image references
|
|
212
214
|
|
|
213
|
-
See [TOOL-IMAGES.md](./TOOL-IMAGES.md) for `ToolImagesRuntimeCapability`, reference-only tool results, temporary visual model inputs, execution scope, and recovery rules. Never persist the messages returned by `prepareModelInput`.
|
|
215
|
+
See [TOOL-IMAGES.md](./en/TOOL-IMAGES.md) for `ToolImagesRuntimeCapability`, reference-only tool results, temporary visual model inputs, execution scope, and recovery rules. Never persist the messages returned by `prepareModelInput`.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Knowledgebase resource discovery
|
|
2
|
+
|
|
3
|
+
`platform.knowledgebase` separates catalog discovery, metadata, permission inspection and content retrieval. All new catalog methods use the authenticated runtime's tenant, organization and actor. Inputs cannot select another identity or organization.
|
|
4
|
+
|
|
5
|
+
| Method | Responsibility |
|
|
6
|
+
| ----------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
|
7
|
+
| `query` | Discover resources with explicit scope, metadata filters, required actions and cursor pagination. |
|
|
8
|
+
| `get` | Read one resource's safe metadata, supported ingestion capability, configuration and processing readiness. |
|
|
9
|
+
| `getAccess` | Inspect named actions for up to 100 resource IDs. Missing and inaccessible IDs both return `unavailable`. |
|
|
10
|
+
| `search` | Retrieve indexed content; its existing contract is unchanged. |
|
|
11
|
+
| `list` | Deprecated for new integrations; preserves the old scope, shared-library behavior and array result. Use `query` in new code. |
|
|
12
|
+
|
|
13
|
+
The draft-only `listWritable` method has been removed. Destination discovery uses `query` with required actions.
|
|
14
|
+
|
|
15
|
+
Document lifecycle methods remain on `platform.knowledgebase.documents`; administrative provisioning remains on `platform.knowledgebase.provisioning`. Resource discovery does not create or connect libraries.
|
|
16
|
+
|
|
17
|
+
## Discover a destination
|
|
18
|
+
|
|
19
|
+
Feature-detect `query`, `get` and `getAccess` before using them on an older host. A workflow requiring write authorization must fail explicitly when these methods are absent; the old `list` is not an authorization substitute.
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
const actions: KnowledgebaseAction[] = ['documents.create', 'documents.process']
|
|
23
|
+
const page = await api.query({
|
|
24
|
+
scope: { kind: 'workspace', workspaceId, relation: 'owned' },
|
|
25
|
+
filter: {
|
|
26
|
+
visibility: 'organization',
|
|
27
|
+
applicationTags: { allOf: [imageLibraryTag] }
|
|
28
|
+
},
|
|
29
|
+
access: { requireAll: actions },
|
|
30
|
+
page: { limit: 100, cursor }
|
|
31
|
+
})
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
- `owned` restricts results to the selected workspace. `available` also considers organization/public resources in the current organization, subject to point-read authorization. It does not grant access to another workspace or include tenant libraries implicitly.
|
|
35
|
+
- `organization` searches the current organization. `tenant` searches tenant-owned public libraries. No scope bypasses resource permissions.
|
|
36
|
+
- Text filtering is a literal substring of name/description; `applicationTags.allOf` requires every tag. Publication and visibility are separate filters.
|
|
37
|
+
- Page limits are 1–100 (default 20), with stable ascending ID keysets. Follow `nextCursor` even after a short or empty page; each request scans at most 1,000 rows. Only `null` confirms exhaustion.
|
|
38
|
+
- Cursors are bound to tenant, organization, actor, scope, filters and required actions. Changing these requires restarting the query. Permissions are evaluated again on every page. Pagination is not a database snapshot; insertions before the current ID may appear only in a fresh query.
|
|
39
|
+
|
|
40
|
+
Before starting paid work, inspect `getAccess` for every required action and `get` for readiness. `configuration.embeddingConfigured` means an embedding model binding exists, not that an external provider is currently healthy. Recheck access before saving, and retain normal authorization on actual document writes; an earlier check never authorizes a later write.
|
|
41
|
+
|
|
42
|
+
Catalog responses expose neither provider credentials nor model bindings. Current document/chunk mutations use the platform's existing knowledgebase write policy; exposing distinct action names allows future permission refinement without adding action-specific list methods.
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# Plugin Permission Design Guide
|
|
2
|
+
|
|
3
|
+
Declare model requirements in a strategy's `meta.permissions` and expose provider/model selection in `configSchema`. The host resolves the user's configuration and credentials, creates the appropriate model client, and injects it into `config.client` before calling `understandImages`.
|
|
4
|
+
|
|
5
|
+
The following design illustrates how `OpenAIGPT4VStrategy` can request a host-provided client instead of constructing its own OpenAI, Anthropic or other vision-model client.
|
|
6
|
+
|
|
7
|
+
## Strategy definition
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { Injectable } from '@nestjs/common'
|
|
11
|
+
import { Document } from 'langchain/document'
|
|
12
|
+
import {
|
|
13
|
+
ImageUnderstandingStrategy,
|
|
14
|
+
IImageUnderstandingStrategy,
|
|
15
|
+
TImageUnderstandingFile,
|
|
16
|
+
TImageUnderstandingResult
|
|
17
|
+
} from './strategy.interface'
|
|
18
|
+
|
|
19
|
+
@Injectable()
|
|
20
|
+
@ImageUnderstandingStrategy('openai-gpt4v')
|
|
21
|
+
export class OpenAIGPT4VStrategy implements IImageUnderstandingStrategy<any> {
|
|
22
|
+
readonly meta = {
|
|
23
|
+
name: 'openai-gpt4v',
|
|
24
|
+
label: { en: 'OpenAI GPT-4 Vision' },
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Declare the plugin's requirement for "llm" access,
|
|
28
|
+
* with OpenAI as the provider and vision as the capability.
|
|
29
|
+
* The host uses config.provider and config.model to create the client
|
|
30
|
+
* and inject it into config.client.
|
|
31
|
+
*/
|
|
32
|
+
permissions: [
|
|
33
|
+
{
|
|
34
|
+
type: 'llm',
|
|
35
|
+
provider: 'openai',
|
|
36
|
+
capability: 'vision'
|
|
37
|
+
}
|
|
38
|
+
],
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The configuration schema requires provider and model.
|
|
42
|
+
* The host uses these settings and the user's API key
|
|
43
|
+
* to create and inject the client.
|
|
44
|
+
*/
|
|
45
|
+
configSchema: {
|
|
46
|
+
type: 'object',
|
|
47
|
+
properties: {
|
|
48
|
+
provider: {
|
|
49
|
+
type: 'string',
|
|
50
|
+
enum: ['openai'],
|
|
51
|
+
description: 'Model provider'
|
|
52
|
+
},
|
|
53
|
+
model: {
|
|
54
|
+
type: 'string',
|
|
55
|
+
default: 'gpt-4-vision-preview',
|
|
56
|
+
description: 'Model name'
|
|
57
|
+
},
|
|
58
|
+
prompt: {
|
|
59
|
+
type: 'string',
|
|
60
|
+
default: 'Describe this image in detail.',
|
|
61
|
+
description: 'Prompt for the image understanding task'
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
required: ['provider', 'model']
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
icon: {
|
|
68
|
+
svg: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><circle cx="10" cy="10" r="8" stroke="black" fill="none"/><text x="6" y="14">VLM</text></svg>',
|
|
69
|
+
color: '#10a37f'
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async validateConfig(config: any): Promise<void> {
|
|
74
|
+
if (!config.client) {
|
|
75
|
+
throw new Error('Missing injected LLM client in config. Core system must inject client.')
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async understandImages(files: TImageUnderstandingFile[], config: any): Promise<TImageUnderstandingResult[]> {
|
|
80
|
+
const client = config.client // Injected by the host.
|
|
81
|
+
const results: TImageUnderstandingResult[] = []
|
|
82
|
+
|
|
83
|
+
for (const file of files) {
|
|
84
|
+
const description = await this.runGPT4V(client, file.path, config)
|
|
85
|
+
|
|
86
|
+
const doc = new Document({
|
|
87
|
+
pageContent: description,
|
|
88
|
+
metadata: {
|
|
89
|
+
chunkId: `img-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
|
|
90
|
+
parentChunkId: file.parentChunkId,
|
|
91
|
+
imagePath: file.path,
|
|
92
|
+
source: file.filename,
|
|
93
|
+
type: 'vlm',
|
|
94
|
+
engine: config.model
|
|
95
|
+
}
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
results.push({
|
|
99
|
+
docs: [doc],
|
|
100
|
+
metadata: { engine: config.model, file: file.filename }
|
|
101
|
+
})
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return results
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
private async runGPT4V(client: any, imagePath: string, config: any): Promise<string> {
|
|
108
|
+
// The host has already created this OpenAI client.
|
|
109
|
+
const response = await client.chat.completions.create({
|
|
110
|
+
model: config.model,
|
|
111
|
+
messages: [
|
|
112
|
+
{
|
|
113
|
+
role: 'user',
|
|
114
|
+
content: [
|
|
115
|
+
{ type: 'text', text: config.prompt || 'Describe this image in detail.' },
|
|
116
|
+
{ type: 'image_url', image_url: { url: imagePath } }
|
|
117
|
+
]
|
|
118
|
+
}
|
|
119
|
+
],
|
|
120
|
+
max_tokens: 500
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
return response.choices[0]?.message?.content || ''
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Host processing
|
|
131
|
+
|
|
132
|
+
- Read the plugin's `meta.permissions` to identify the requirement:
|
|
133
|
+
|
|
134
|
+
```json
|
|
135
|
+
{ "type": "llm", "provider": "openai", "capability": "vision" }
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
- Use the user's `config.provider = "openai"` and `config.model = "gpt-4-vision-preview"`
|
|
139
|
+
to instantiate `OpenAI({ apiKey: userApiKey })`.
|
|
140
|
+
- Inject the client into `config.client`.
|
|
141
|
+
- Call `strategy.understandImages(files, config)`.
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Usage example
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
const strategy = this.imageUnderstandingRegistry.get('openai-gpt4v')
|
|
149
|
+
const result = await strategy.understandImages(
|
|
150
|
+
[
|
|
151
|
+
{
|
|
152
|
+
path: 'https://example.com/chart.png',
|
|
153
|
+
filename: 'chart.png',
|
|
154
|
+
extname: 'png',
|
|
155
|
+
parentChunkId: 'uuid-123'
|
|
156
|
+
}
|
|
157
|
+
],
|
|
158
|
+
{
|
|
159
|
+
provider: 'openai',
|
|
160
|
+
model: 'gpt-4-vision-preview',
|
|
161
|
+
prompt: 'Describe this image in detail in English.',
|
|
162
|
+
client: openaiClient // Injected by the host.
|
|
163
|
+
}
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
console.log(result[0].docs[0].pageContent)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
The plugin declares its permission requirements and provider/model configuration; the host supplies the appropriate client without requiring plugin-specific OpenAI initialization logic.
|
|
172
|
+
|
|
173
|
+
A shared permission-request interface, such as `ILLMPermissionRequest`, can give OCR, vision-model and embedding plugins a common way to declare dependencies.
|
|
@@ -205,15 +205,15 @@ For example, add this `content` property to the card passed to `emitResourceCard
|
|
|
205
205
|
|
|
206
206
|
```ts
|
|
207
207
|
content: [
|
|
208
|
-
{ kind: 'fields', fields: [{ label: '
|
|
208
|
+
{ kind: 'fields', fields: [{ label: 'Status', value: 'Completed' }] },
|
|
209
209
|
{
|
|
210
210
|
kind: 'image-gallery',
|
|
211
|
-
title: '
|
|
211
|
+
title: 'Construction images',
|
|
212
212
|
images: [
|
|
213
213
|
{
|
|
214
214
|
id: 'site-layout',
|
|
215
|
-
title: '
|
|
216
|
-
alt: '
|
|
215
|
+
title: 'Construction site layout',
|
|
216
|
+
alt: 'Work zones, entrances, exits and transport routes',
|
|
217
217
|
file: {
|
|
218
218
|
viewKey: 'bid.view-provider__bid.studio',
|
|
219
219
|
fileKey: 'bid-project-image',
|
|
@@ -358,4 +358,4 @@ The built-in `platform.agent-invocation/execution` provider owns direct Coding i
|
|
|
358
358
|
|
|
359
359
|
The card opens `platform.coding-execution__execution` with the exact invocation ID. Public CLI activity is written through the optional Runtime `context.activity` recorder and queried by the View provider. Resource-card refresh contains only presentation/state/target updates; it does not transport command output or invoke a CLI. Final summary cards are suppressed only when a Coding execution card already covers the run; independently delivered files retain their own cards.
|
|
360
360
|
|
|
361
|
-
See [Coding Execution View](
|
|
361
|
+
See [Coding Execution View](../../../server-ai/src/agent-invocation/execution-view/README.md) for the capability, authorization, storage, retention and navigation contract.
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
# Schema UI Extension Specification
|
|
2
|
+
|
|
3
|
+
Use a common UI extension across plugin configuration schemas so frontend renderers can apply consistent presentation and interaction rules.
|
|
4
|
+
|
|
5
|
+
Extend JSON Schema with the reserved `x-ui` field:
|
|
6
|
+
|
|
7
|
+
```json
|
|
8
|
+
"x-ui": { ... }
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
The frontend renderer uses `x-ui` to select components, present fields and apply dynamic dependencies.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 1. Basic fields
|
|
16
|
+
|
|
17
|
+
| Field | Type | Description |
|
|
18
|
+
| -------------- | ------ | -------------------------------------------------------------------------------------------------------------------- |
|
|
19
|
+
| `component` | string | UI component type, such as `textInput`, `textarea`, `select`, `switch`, `slider`, `prompt-editor`, `ai-model-select` |
|
|
20
|
+
| `inputs` | object | Additional input properties for a custom component |
|
|
21
|
+
| `label` | string | Displayed field label |
|
|
22
|
+
| `description` | string | Help text; takes precedence over `schema.description` |
|
|
23
|
+
| `help` | string | Additional help, displayed as a help icon or tooltip when appropriate |
|
|
24
|
+
| `placeholder` | string | Input placeholder |
|
|
25
|
+
| `defaultValue` | any | Default value; takes precedence over `schema.default` |
|
|
26
|
+
| `order` | number | Display order in the UI |
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 2. Data sources
|
|
31
|
+
|
|
32
|
+
| Field | Type | Description |
|
|
33
|
+
| ------------ | ------ | -------------------------------------------------------------------------------------------------------------------------- |
|
|
34
|
+
| `options` | array | Static options for selects or multi-selects, such as `[{ label: 'OpenAI', value: 'openai' }]` |
|
|
35
|
+
| `enumLabels` | object | Map enum values to labels, for example `{ openai: 'OpenAI', azure: 'Azure OpenAI' }`, overriding the displayed enum labels |
|
|
36
|
+
| `dataSource` | string | Dynamic option source identifier, such as `"system.providers"`, `"system.models"` |
|
|
37
|
+
| `dependency` | string | Another field whose value filters the options, such as `"provider"` |
|
|
38
|
+
| `mapping` | object | Field mapping, for example `{ label: 'name', value: 'id' }` |
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 3. Validation and interaction
|
|
43
|
+
|
|
44
|
+
| Field | Type | Description |
|
|
45
|
+
| ------------- | ------- | ---------------------------------------------------------------------------------- |
|
|
46
|
+
| `required` | boolean | Whether the field is required; takes precedence over `schema.required` |
|
|
47
|
+
| `visibleWhen` | object | Display the field only when conditions match, for example `{ provider: 'openai' }` |
|
|
48
|
+
| `enabledWhen` | object | Enable the field when conditions match, for example `{ useCustomPrompt: true }` |
|
|
49
|
+
| `maxLength` | number | Maximum input length |
|
|
50
|
+
| `minLength` | number | Minimum input length |
|
|
51
|
+
| `regex` | string | Custom regular-expression validation rule |
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 4. Specialized components
|
|
56
|
+
|
|
57
|
+
### `modelProviderSelect`
|
|
58
|
+
|
|
59
|
+
- Select a model provider, such as OpenAI, Anthropic, Azure or Ollama.
|
|
60
|
+
- `dataSource = "system.providers"`
|
|
61
|
+
|
|
62
|
+
### `modelSelect`
|
|
63
|
+
|
|
64
|
+
- Select a specific model.
|
|
65
|
+
- Depends on `provider`.
|
|
66
|
+
- `dataSource = "system.models"`
|
|
67
|
+
- `dependency = "provider"`
|
|
68
|
+
|
|
69
|
+
### `promptEditor`
|
|
70
|
+
|
|
71
|
+
- Edit prompts with multiline input, syntax highlighting and variable interpolation.
|
|
72
|
+
|
|
73
|
+
### `jsonEditor`
|
|
74
|
+
|
|
75
|
+
- Edit JSON objects with format validation.
|
|
76
|
+
|
|
77
|
+
### `codeEditor`
|
|
78
|
+
|
|
79
|
+
- Edit code with syntax highlighting, such as JavaScript, TypeScript or Python.
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## 5. Example schema
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
configSchema: {
|
|
87
|
+
type: 'object',
|
|
88
|
+
properties: {
|
|
89
|
+
provider: {
|
|
90
|
+
type: 'string',
|
|
91
|
+
description: 'Model provider',
|
|
92
|
+
enum: ['openai', 'anthropic', 'azure', 'ollama'],
|
|
93
|
+
'x-ui': {
|
|
94
|
+
component: 'modelProviderSelect',
|
|
95
|
+
label: 'Provider',
|
|
96
|
+
order: 1,
|
|
97
|
+
dataSource: 'system.providers'
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
model: {
|
|
101
|
+
type: 'string',
|
|
102
|
+
description: 'Model name',
|
|
103
|
+
default: 'gpt-4-vision-preview',
|
|
104
|
+
'x-ui': {
|
|
105
|
+
component: 'modelSelect',
|
|
106
|
+
label: 'Model',
|
|
107
|
+
order: 2,
|
|
108
|
+
dependency: 'provider',
|
|
109
|
+
dataSource: 'system.models'
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
prompt: {
|
|
113
|
+
type: 'string',
|
|
114
|
+
default: 'Describe this image in detail.',
|
|
115
|
+
description: 'Prompt',
|
|
116
|
+
'x-ui': {
|
|
117
|
+
component: 'promptEditor',
|
|
118
|
+
label: 'Prompt',
|
|
119
|
+
order: 3,
|
|
120
|
+
placeholder: 'Enter a prompt; {{variables}} placeholders are supported'
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
temperature: {
|
|
124
|
+
type: 'number',
|
|
125
|
+
default: 0.7,
|
|
126
|
+
'x-ui': {
|
|
127
|
+
component: 'slider',
|
|
128
|
+
label: 'Temperature',
|
|
129
|
+
order: 4,
|
|
130
|
+
min: 0,
|
|
131
|
+
max: 1,
|
|
132
|
+
step: 0.1
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
advanced: {
|
|
136
|
+
type: 'object',
|
|
137
|
+
'x-ui': {
|
|
138
|
+
component: 'jsonEditor',
|
|
139
|
+
label: 'Advanced Config',
|
|
140
|
+
order: 5,
|
|
141
|
+
visibleWhen: { provider: 'openai' }
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
required: ['provider', 'model']
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
With these conventions:
|
|
152
|
+
|
|
153
|
+
- Renderers select the component from `x-ui.component`; the remaining `x-ui` properties drive its behavior.
|
|
154
|
+
- Plugin developers declare a schema to obtain a consistent configuration experience.
|
|
155
|
+
- The same conventions can support embedding, OCR, vision-model and vector-store plugins.
|
|
156
|
+
|
|
157
|
+
## Representing secret input fields
|
|
158
|
+
|
|
159
|
+
Secret fields, such as API keys, tokens and passwords, need explicit UI handling:
|
|
160
|
+
|
|
161
|
+
1. Render a password input (`type="password"`) or masked value.
|
|
162
|
+
2. Represent a stored secret with `"******"` or an empty placeholder instead of returning its plaintext value.
|
|
163
|
+
3. Mark secret fields in the schema so renderers can recognize them.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Secret-field extension
|
|
168
|
+
|
|
169
|
+
Set `component: "secretInput"` in `x-ui` and support these properties:
|
|
170
|
+
|
|
171
|
+
| Field | Type | Description |
|
|
172
|
+
| ------------- | ------- | --------------------------------------------------------------------------------- |
|
|
173
|
+
| `component` | string | Set to `"secretInput"` to render a password input |
|
|
174
|
+
| `label` | string | Field label |
|
|
175
|
+
| `description` | string | Field description |
|
|
176
|
+
| `placeholder` | string | Placeholder, such as `Enter API key` |
|
|
177
|
+
| `revealable` | boolean | Whether a button may temporarily reveal the value |
|
|
178
|
+
| `maskSymbol` | string | Mask character (default: `*`) |
|
|
179
|
+
| `persist` | boolean | Whether to persist the value; false means runtime-only use without saving to disk |
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## Example schema
|
|
184
|
+
|
|
185
|
+
```ts
|
|
186
|
+
configSchema: {
|
|
187
|
+
type: 'object',
|
|
188
|
+
properties: {
|
|
189
|
+
apiKey: {
|
|
190
|
+
type: 'string',
|
|
191
|
+
description: 'OpenAI API Key',
|
|
192
|
+
'x-ui': {
|
|
193
|
+
component: 'secretInput',
|
|
194
|
+
label: 'API Key',
|
|
195
|
+
placeholder: 'Enter your OpenAI API key',
|
|
196
|
+
revealable: true,
|
|
197
|
+
maskSymbol: '*',
|
|
198
|
+
persist: true
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
provider: {
|
|
202
|
+
type: 'string',
|
|
203
|
+
enum: ['openai', 'anthropic', 'azure'],
|
|
204
|
+
'x-ui': {
|
|
205
|
+
component: 'modelProviderSelect',
|
|
206
|
+
label: 'Provider'
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
},
|
|
210
|
+
required: ['apiKey', 'provider']
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## Frontend presentation
|
|
217
|
+
|
|
218
|
+
- Render `apiKey` as a password input, masked by default.
|
|
219
|
+
- When `revealable: true`, provide a reveal/hide toggle.
|
|
220
|
+
- During editing, `"******"` indicates an existing value. Leaving it unchanged preserves that value.
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## Secret handling
|
|
225
|
+
|
|
226
|
+
- When the form submits `apiKey === "******"`, preserve the stored value.
|
|
227
|
+
- Replace the stored value when a new value is submitted.
|
|
228
|
+
- Omit secret fields from logs and configuration exports.
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
A shared interface such as `ISchemaSecretField` makes secret-specific behavior explicit.
|
|
233
|
+
|
|
234
|
+
## Shared interface
|
|
235
|
+
|
|
236
|
+
Secret fields share the base UI contract while declaring the additional handling required for sensitive values.
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
### Interface design
|
|
241
|
+
|
|
242
|
+
```ts
|
|
243
|
+
/**
|
|
244
|
+
* Base UI schema field definition
|
|
245
|
+
*/
|
|
246
|
+
export interface ISchemaUIBase {
|
|
247
|
+
component: string // UI component type
|
|
248
|
+
label?: string // Field label
|
|
249
|
+
description?: string // Field description
|
|
250
|
+
placeholder?: string // Input placeholder
|
|
251
|
+
order?: number // UI display order
|
|
252
|
+
required?: boolean // Whether the field is required
|
|
253
|
+
visibleWhen?: Record<string, any> // Conditional visibility
|
|
254
|
+
enabledWhen?: Record<string, any> // Conditional enablement
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Secret field extension
|
|
259
|
+
*/
|
|
260
|
+
export interface ISchemaSecretField extends ISchemaUIBase {
|
|
261
|
+
component: 'secretInput' // Fixed component type
|
|
262
|
+
revealable?: boolean // Whether the reveal button is available
|
|
263
|
+
maskSymbol?: string // Mask character (default: *)
|
|
264
|
+
persist?: boolean // Whether to persist; false means runtime-only use
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Secret fields inherit the same base contract as ordinary fields, with additional properties for handling sensitive data.
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
### Usage example
|
|
273
|
+
|
|
274
|
+
```ts
|
|
275
|
+
configSchema: {
|
|
276
|
+
type: 'object',
|
|
277
|
+
properties: {
|
|
278
|
+
apiKey: {
|
|
279
|
+
type: 'string',
|
|
280
|
+
description: 'OpenAI API Key',
|
|
281
|
+
'x-ui': <ISchemaSecretField>{
|
|
282
|
+
component: 'secretInput',
|
|
283
|
+
label: 'API Key',
|
|
284
|
+
placeholder: 'Enter your OpenAI API key',
|
|
285
|
+
revealable: true,
|
|
286
|
+
maskSymbol: '*',
|
|
287
|
+
persist: true
|
|
288
|
+
}
|
|
289
|
+
},
|
|
290
|
+
provider: {
|
|
291
|
+
type: 'string',
|
|
292
|
+
enum: ['openai', 'anthropic', 'azure'],
|
|
293
|
+
'x-ui': {
|
|
294
|
+
component: 'modelProviderSelect',
|
|
295
|
+
label: 'Provider'
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
},
|
|
299
|
+
required: ['apiKey', 'provider']
|
|
300
|
+
}
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
### Frontend behavior
|
|
306
|
+
|
|
307
|
+
1. **Rendering:**
|
|
308
|
+
- Render `secretInput` as a password field (`type=password`).
|
|
309
|
+
- Add a reveal toggle when `revealable: true`.
|
|
310
|
+
|
|
311
|
+
2. **Loading configuration:**
|
|
312
|
+
- Treat `******` as an existing stored value without displaying the original content.
|
|
313
|
+
|
|
314
|
+
3. **Saving configuration:**
|
|
315
|
+
- Preserve the stored value when the submitted value remains `******`.
|
|
316
|
+
- Replace the stored value when a new value is submitted.
|
|
317
|
+
|
|
318
|
+
4. **Exporting configuration or logs:**
|
|
319
|
+
- Omit secret fields or output `******` to avoid disclosure.
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
This makes `secretInput` a first-class, schema-driven UI component alongside `textInput` and `select`.
|
|
324
|
+
|
|
325
|
+
An `ISchemaUIComponent` union can describe the complete set of supported components, including selects, sliders, secret inputs and prompt editors.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Tool images with immutable references
|
|
2
2
|
|
|
3
3
|
For the API responsibilities, image lifecycle, validation limits and server-only
|
|
4
|
-
text-result policy, see the [tool images feature guide](
|
|
4
|
+
text-result policy, see the [tool images feature guide](../../../../docs/tool-images.md).
|
|
5
5
|
|
|
6
6
|
Use `ToolImagesRuntimeCapability` inside an Agent middleware when a tool returns
|
|
7
7
|
an image for visual inspection. The host stores validated image bytes in
|