@77-zhike/app-sdk 0.2.0-d7b1.12 → 0.2.0-d7b1.13
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 +8 -0
- package/package.json +2 -2
- package/src/server/agents/index.d.ts +22 -0
- package/src/server/agents/index.js +30 -0
- package/src/server/index.d.ts +1 -0
- package/src/server/index.js +1 -0
- package/src/toolchain/agents/discovery.js +99 -0
- package/src/toolchain/agents/manifest.js +62 -0
- package/src/toolchain/real-build.js +21 -7
- package/src/toolchain/source-discovery.js +6 -2
- package/src/ui/components.generated.js +3 -3
- package/src/ui/conversation.d.ts +33 -0
- package/src/ui/factory.js +4 -0
- package/src/ui/index.d.ts +62 -0
- package/src/ui/index.js +1 -1
package/README.md
CHANGED
|
@@ -253,3 +253,11 @@ Chart 仅接受纯数据 `labels` 与 `series`,不接受脚本、HTML 或任
|
|
|
253
253
|
### 精确数字的表格录入
|
|
254
254
|
|
|
255
255
|
`form.TextInput` 可选 `labelHidden` 和 `inputMode="numeric" | "decimal"`。隐藏标题仍保留与控件关联的读屏标签,默认标题继续显示,字段错误和说明仍显示。`inputMode` 只提示键盘,不转换、过滤或格式化值,不替代业务校验;需要保留十进制字符串或未完成输入时使用,数值型字段继续使用 `NumberInput`。
|
|
256
|
+
|
|
257
|
+
## App 对话输入部件
|
|
258
|
+
|
|
259
|
+
`Conversation.Root` 内自由组合 Messages、History、NewButton、Status、Composer。History 默认使用与 automation 相同的图标弹出列表;Composer 默认带附件/图片上传和语音回填,转写后仍需用户发送。输入能力由 Host 提供,不把 File/音频字节或凭据交给 App Worker。
|
|
260
|
+
|
|
261
|
+
附件只读当前 App 会话中用户提交的文件,不扩展自定义 Tool 的权限。新 App 业务 Tool 仍在 agent 目录用 `.tools.ts` 合并定义并由 Integration Runtime 执行。元数据 Schema 必须为静态字面量,execute 可导入项目自己的业务校验函数。
|
|
262
|
+
|
|
263
|
+
真实表单协作可参考 `built-in-apps/opportunity-quotes`:页面以 SDK 布局并列 Form 与 Conversation,callback 接收建议,用户确认后更新本地草稿;正式保存沿原入口。NativeDOM 内仍只允许原有控件,不直接放 Conversation;可以在 Conversation 内用独立 NativeDOM 展示本地建议确认区。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@77-zhike/app-sdk",
|
|
3
|
-
"version": "0.2.0-d7b1.
|
|
3
|
+
"version": "0.2.0-d7b1.13",
|
|
4
4
|
"description": "智客 Integration App 一期 SDK 与本地 Toolchain",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -67,5 +67,5 @@
|
|
|
67
67
|
"optional": true
|
|
68
68
|
}
|
|
69
69
|
},
|
|
70
|
-
"gitHead": "
|
|
70
|
+
"gitHead": "f2a667ec95a8d1787cf0c0655787266317069b55"
|
|
71
71
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** 静态信息进入不可变 Manifest;工具集合由同目录 .tools.ts 唯一决定。 */
|
|
2
|
+
export interface AppAgentDefinition {
|
|
3
|
+
key: string;
|
|
4
|
+
name: string;
|
|
5
|
+
/** App 提供的系统提示词,最多 16KiB UTF-8,不交付 Client Worker。 */
|
|
6
|
+
systemPrompt: string;
|
|
7
|
+
}
|
|
8
|
+
export type ToolSchema = Readonly<Record<string, unknown>>;
|
|
9
|
+
export interface AppToolDefinition<Input, Output> {
|
|
10
|
+
key: string;
|
|
11
|
+
name: string;
|
|
12
|
+
description: string;
|
|
13
|
+
/** 有界 JSON Schema;平台在模型调用和结果交付时再次严格验证。 */
|
|
14
|
+
inputSchema: ToolSchema;
|
|
15
|
+
outputSchema: ToolSchema;
|
|
16
|
+
/** 默认 none;output 只允许成功且通过校验的结果进入实时 callback。 */
|
|
17
|
+
clientResult?: 'none' | 'output';
|
|
18
|
+
/** 仅在所属安装的服务端执行环境运行,凭据沿用现有 Server SDK。 */
|
|
19
|
+
execute(input: Input): Output | Promise<Output>;
|
|
20
|
+
}
|
|
21
|
+
export function defineAgent(definition: AppAgentDefinition): Readonly<AppAgentDefinition>;
|
|
22
|
+
export function defineTool<Input = Record<string, unknown>, Output = unknown>(definition: AppToolDefinition<Input, Output>): Readonly<AppToolDefinition<Input, Output>>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const KEY = /^[a-z][a-z0-9-]{0,63}$/;
|
|
2
|
+
|
|
3
|
+
function fields(value, required, optional = []) {
|
|
4
|
+
if (!value || typeof value !== "object" || Array.isArray(value) ||
|
|
5
|
+
required.some(key => !Object.hasOwn(value, key)) ||
|
|
6
|
+
Object.keys(value).some(key => ![...required, ...optional].includes(key))) {
|
|
7
|
+
throw new TypeError("agent_definition_invalid");
|
|
8
|
+
}
|
|
9
|
+
if (typeof value.key !== "string" || value.key.trim() !== value.key || !KEY.test(value.key) || typeof value.name !== "string" ||
|
|
10
|
+
!value.name.trim() || value.name.length > 80) throw new TypeError("agent_definition_invalid");
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function defineAgent(definition) {
|
|
14
|
+
fields(definition, ["key", "name", "systemPrompt"]);
|
|
15
|
+
if (typeof definition.systemPrompt !== "string" || !definition.systemPrompt.trim() ||
|
|
16
|
+
new TextEncoder().encode(definition.systemPrompt).length > 16384) {
|
|
17
|
+
throw new TypeError("agent_definition_invalid");
|
|
18
|
+
}
|
|
19
|
+
return Object.freeze({ ...definition });
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function defineTool(definition) {
|
|
23
|
+
fields(definition, ["key", "name", "description", "inputSchema", "outputSchema", "execute"], ["clientResult"]);
|
|
24
|
+
if (typeof definition.execute !== "function" || typeof definition.description !== "string" ||
|
|
25
|
+
!definition.description.trim() || definition.description.length > 1200 ||
|
|
26
|
+
![undefined, "none", "output"].includes(definition.clientResult)) {
|
|
27
|
+
throw new TypeError("agent_tool_definition_invalid");
|
|
28
|
+
}
|
|
29
|
+
return Object.freeze({ ...definition, clientResult: definition.clientResult ?? "none" });
|
|
30
|
+
}
|
package/src/server/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { defineAgent, defineTool, type AppAgentDefinition, type AppToolDefinition, type ToolSchema } from "./agents/index.js";
|
|
1
2
|
import type { JsonValue } from "../index.js";
|
|
2
3
|
export { defineWorkflowStep, defineWorkflowStepExecute } from "./steps/index.js";
|
|
3
4
|
export type { WorkflowObjectSchema, WorkflowScalarSchema, WorkflowStepDefinition, WorkflowStepOutcome, WorkflowStepResult, WorkflowSchemaValue } from "./steps/index.js";
|
package/src/server/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { defineAgent, defineTool } from "./agents/index.js";
|
|
1
2
|
const SERVER_FUNCTION_MARKER = Symbol.for("zhike.server-function.v1");
|
|
2
3
|
export { defineWorkflowStep, defineWorkflowStepExecute } from "./steps/index.js";
|
|
3
4
|
export { defineWorkflowTrigger, defineWorkflowTriggerActivate, defineWorkflowTriggerOnEvent, defineWorkflowTriggerDeactivate } from "./triggers/index.js";
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
import { posix } from 'node:path';
|
|
3
|
+
import { ZhikeCliError } from '../../errors.js';
|
|
4
|
+
import { assertAgentManifest } from './manifest.js';
|
|
5
|
+
|
|
6
|
+
const AGENT_PATH = /^app\/agents\/([a-z][a-z0-9-]{0,63})\/agent\.ts$/;
|
|
7
|
+
const TOOL_PATH = /^app\/agents\/([a-z][a-z0-9-]{0,63})\/([a-z][a-z0-9-]{0,63})\.tools\.ts$/;
|
|
8
|
+
function invalid(path, message) { throw new ZhikeCliError('zhike_agent_invalid', `${path}: ${message}`); }
|
|
9
|
+
function literal(node, path, depth = 0) {
|
|
10
|
+
if (depth > 24) invalid(path, '静态声明嵌套过深');
|
|
11
|
+
if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) return node.text;
|
|
12
|
+
if (ts.isNumericLiteral(node)) return Number(node.text);
|
|
13
|
+
if (ts.isPrefixUnaryExpression(node) && node.operator === ts.SyntaxKind.MinusToken && ts.isNumericLiteral(node.operand)) return -Number(node.operand.text);
|
|
14
|
+
if (node.kind === ts.SyntaxKind.TrueKeyword) return true;
|
|
15
|
+
if (node.kind === ts.SyntaxKind.FalseKeyword) return false;
|
|
16
|
+
if (node.kind === ts.SyntaxKind.NullKeyword) return null;
|
|
17
|
+
if (ts.isArrayLiteralExpression(node)) return node.elements.map(item => literal(item, path, depth + 1));
|
|
18
|
+
if (ts.isObjectLiteralExpression(node)) {
|
|
19
|
+
const result = Object.create(null);
|
|
20
|
+
for (const property of node.properties) {
|
|
21
|
+
if (!ts.isPropertyAssignment(property) || !(ts.isIdentifier(property.name) || ts.isStringLiteral(property.name))) invalid(path, '元数据必须为静态 JSON 字面量');
|
|
22
|
+
const key = property.name.text;
|
|
23
|
+
if (Object.hasOwn(result, key) || ['__proto__', 'prototype', 'constructor'].includes(key)) invalid(path, '重复或保留字段');
|
|
24
|
+
result[key] = literal(property.initializer, path, depth + 1);
|
|
25
|
+
}
|
|
26
|
+
return result;
|
|
27
|
+
}
|
|
28
|
+
invalid(path, '元数据不能读取变量、函数或运行时代码');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function definition(file, api) {
|
|
32
|
+
const { sourceFile, relativePath } = file;
|
|
33
|
+
const imported = sourceFile.statements.some(statement => ts.isImportDeclaration(statement) &&
|
|
34
|
+
statement.moduleSpecifier.text === '@77-zhike/app-sdk/server' &&
|
|
35
|
+
statement.importClause?.namedBindings && ts.isNamedImports(statement.importClause.namedBindings) &&
|
|
36
|
+
statement.importClause.namedBindings.elements.some(item => !item.propertyName && item.name.text === api));
|
|
37
|
+
const exports = sourceFile.statements.filter(statement => ts.isExportAssignment(statement) && !statement.isExportEquals);
|
|
38
|
+
const call = exports[0]?.expression;
|
|
39
|
+
if (!imported || exports.length !== 1 || !call || !ts.isCallExpression(call) ||
|
|
40
|
+
!ts.isIdentifier(call.expression) || call.expression.text !== api || call.arguments.length !== 1 ||
|
|
41
|
+
!ts.isObjectLiteralExpression(call.arguments[0])) invalid(relativePath, `必须直接默认导出 ${api}({...})`);
|
|
42
|
+
const value = Object.create(null);
|
|
43
|
+
for (const property of call.arguments[0].properties) {
|
|
44
|
+
if (!property.name || !(ts.isIdentifier(property.name) || ts.isStringLiteral(property.name))) invalid(relativePath, '声明禁止 spread 或动态属性');
|
|
45
|
+
const key = property.name.text;
|
|
46
|
+
if (Object.hasOwn(value, key)) invalid(relativePath, '重复声明字段');
|
|
47
|
+
if (api === 'defineTool' && key === 'execute') {
|
|
48
|
+
const handler = ts.isMethodDeclaration(property) ? property : ts.isPropertyAssignment(property) ? property.initializer : null;
|
|
49
|
+
if (!handler || !(ts.isMethodDeclaration(handler) || ts.isArrowFunction(handler) || ts.isFunctionExpression(handler)) || handler.parameters.length > 1) invalid(relativePath, 'execute 必须是仅接收业务 input 的函数');
|
|
50
|
+
value[key] = true;
|
|
51
|
+
} else {
|
|
52
|
+
if (!ts.isPropertyAssignment(property)) invalid(relativePath, '元数据必须为静态字段');
|
|
53
|
+
value[key] = literal(property.initializer, relativePath);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return value;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function discoverAgents(files) {
|
|
60
|
+
const agents = new Map();
|
|
61
|
+
for (const file of files) {
|
|
62
|
+
const match = file.relativePath.match(AGENT_PATH);
|
|
63
|
+
if (!match) continue;
|
|
64
|
+
const value = definition(file, 'defineAgent');
|
|
65
|
+
if (value.key !== match[1] || Object.keys(value).some(key => !['key', 'name', 'systemPrompt'].includes(key))) invalid(file.relativePath, 'Agent key 必须等于目录且只接受 key/name/systemPrompt');
|
|
66
|
+
agents.set(value.key, { ...value, relativePath: file.relativePath, tools: [] });
|
|
67
|
+
}
|
|
68
|
+
if (agents.size > 16) invalid("app/agents", "一个 App 最多 16 个 Agent");
|
|
69
|
+
for (const file of files) {
|
|
70
|
+
const match = file.relativePath.match(TOOL_PATH);
|
|
71
|
+
if (file.relativePath.endsWith('.tools.ts') && !match) invalid(file.relativePath, '工具必须位于 Agent 的直接子目录');
|
|
72
|
+
if (/^app\/agents\/.+\/agent\.(?:ts|tsx)$/.test(file.relativePath) && !AGENT_PATH.test(file.relativePath)) invalid(file.relativePath, 'Agent 入口必须是直接子目录 agent.ts');
|
|
73
|
+
for (const statement of file.sourceFile.statements) {
|
|
74
|
+
if (!(ts.isImportDeclaration(statement) || ts.isExportDeclaration(statement)) || !statement.moduleSpecifier || !ts.isStringLiteral(statement.moduleSpecifier)) continue;
|
|
75
|
+
const specifier = statement.moduleSpecifier.text;
|
|
76
|
+
if (!specifier.startsWith('.')) continue;
|
|
77
|
+
const target = posix.normalize(posix.join(posix.dirname(file.relativePath), specifier)).replace(/\.js$/, '.ts');
|
|
78
|
+
const tool = (target.endsWith(".ts") ? target : `${target}.ts`).match(TOOL_PATH);
|
|
79
|
+
if (tool && (!match || match[1] !== tool[1])) invalid(file.relativePath, '不能跨 Agent 导入工具声明,请抽取普通 helper');
|
|
80
|
+
}
|
|
81
|
+
if (!match) continue;
|
|
82
|
+
const owner = agents.get(match[1]);
|
|
83
|
+
if (!owner) invalid(file.relativePath, '工具缺少所属 agent.ts');
|
|
84
|
+
const value = definition(file, 'defineTool');
|
|
85
|
+
if (value.key !== match[2] || value.execute !== true) invalid(file.relativePath, 'Tool key 必须等于文件前缀且提供 execute');
|
|
86
|
+
delete value.execute;
|
|
87
|
+
owner.tools.push({ ...value, clientResult: value.clientResult ?? 'none', artifact: 'server',
|
|
88
|
+
entry: `agent-tool/${match[1]}/${match[2]}`, relativePath: file.relativePath });
|
|
89
|
+
}
|
|
90
|
+
return [...agents.values()].sort((a, b) => a.key.localeCompare(b.key)).map(agent => {
|
|
91
|
+
agent.tools.sort((a, b) => a.key.localeCompare(b.key));
|
|
92
|
+
try { assertAgentManifest(agentManifest(agent)); } catch { invalid(agent.relativePath, 'Agent/Tool 元数据、Schema 或归属无效'); }
|
|
93
|
+
return Object.freeze(agent);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function agentManifest({ relativePath, tools, ...agent }) {
|
|
98
|
+
return { ...agent, tools: tools.map(({ relativePath: path, ...tool }) => tool) };
|
|
99
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
const KEY = /^[a-z][a-z0-9-]{0,63}$/;
|
|
2
|
+
const FIELD = /^[A-Za-z][A-Za-z0-9_]{0,63}$/;
|
|
3
|
+
const RESERVED = new Set(['tenant_id', 'tenantId', 'member_id', 'memberId', 'installation_id', 'installationId',
|
|
4
|
+
'app_id', 'appId', 'version_id', 'versionId', 'run_id', 'executionId', 'tool_call_id', 'constructor', 'prototype']);
|
|
5
|
+
const SCHEMA_KEYS = ['type', 'properties', 'required', 'additionalProperties', 'items', 'enum', 'const',
|
|
6
|
+
'minLength', 'maxLength', 'pattern', 'minimum', 'maximum', 'minItems', 'maxItems', 'title', 'description'];
|
|
7
|
+
function invalid() { throw new TypeError('app_manifest_agent_invalid'); }
|
|
8
|
+
function record(value) { if (!value || typeof value !== 'object' || Array.isArray(value)) invalid(); }
|
|
9
|
+
function keys(value, allowed) { if (Object.keys(value).some(key => !allowed.includes(key))) invalid(); }
|
|
10
|
+
function text(value, max) { if (typeof value !== 'string' || !value.trim() || value.length > max) invalid(); }
|
|
11
|
+
|
|
12
|
+
export function assertAgentSchema(value) {
|
|
13
|
+
function visit(schema, depth = 0) {
|
|
14
|
+
record(schema); keys(schema, SCHEMA_KEYS);
|
|
15
|
+
if (depth > 6 || !['object', 'array', 'string', 'integer', 'number', 'boolean', 'null'].includes(schema.type)) invalid();
|
|
16
|
+
if (schema.type === 'object') {
|
|
17
|
+
record(schema.properties);
|
|
18
|
+
if (schema.additionalProperties !== false || Object.keys(schema.properties).length > 32) invalid();
|
|
19
|
+
const required = schema.required ?? [];
|
|
20
|
+
if (!Array.isArray(required) || new Set(required).size !== required.length ||
|
|
21
|
+
required.some(key => typeof key !== 'string' || !Object.hasOwn(schema.properties, key))) invalid();
|
|
22
|
+
for (const [key, child] of Object.entries(schema.properties)) {
|
|
23
|
+
if (key.trim() !== key || !FIELD.test(key) || RESERVED.has(key)) invalid();
|
|
24
|
+
visit(child, depth + 1);
|
|
25
|
+
}
|
|
26
|
+
} else if (schema.type === 'array') visit(schema.items, depth + 1);
|
|
27
|
+
else if (schema.properties !== undefined || schema.items !== undefined || schema.required !== undefined ||
|
|
28
|
+
schema.additionalProperties !== undefined) invalid();
|
|
29
|
+
for (const key of ['minLength', 'maxLength', 'minItems', 'maxItems']) {
|
|
30
|
+
if (schema[key] !== undefined && (!Number.isSafeInteger(schema[key]) || schema[key] < 0 || schema[key] > 8192)) invalid();
|
|
31
|
+
}
|
|
32
|
+
for (const [min, max] of [['minLength', 'maxLength'], ['minItems', 'maxItems'], ['minimum', 'maximum']]) {
|
|
33
|
+
if (schema[min] !== undefined && schema[max] !== undefined && schema[min] > schema[max]) invalid();
|
|
34
|
+
}
|
|
35
|
+
for (const key of ['minimum', 'maximum']) if (schema[key] !== undefined &&
|
|
36
|
+
(typeof schema[key] !== 'number' || !Number.isFinite(schema[key]))) invalid();
|
|
37
|
+
if (schema.enum !== undefined && (!Array.isArray(schema.enum) || !schema.enum.length || schema.enum.length > 64 ||
|
|
38
|
+
schema.enum.some(item => item !== null && (!['string', 'boolean', 'number'].includes(typeof item) || typeof item === 'number' && !Number.isFinite(item))))) invalid();
|
|
39
|
+
if (schema.const !== undefined && schema.const !== null && (!['string', 'boolean', 'number'].includes(typeof schema.const) || typeof schema.const === 'number' && !Number.isFinite(schema.const))) invalid();
|
|
40
|
+
for (const key of ['title', 'description']) if (schema[key] !== undefined) text(schema[key], 1200);
|
|
41
|
+
if (schema.pattern !== undefined) { text(schema.pattern, 256); try { new RegExp(schema.pattern); } catch { invalid(); } }
|
|
42
|
+
}
|
|
43
|
+
visit(value);
|
|
44
|
+
if (value.type !== 'object' || new TextEncoder().encode(JSON.stringify(value)).length > 16384) invalid();
|
|
45
|
+
return value;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function assertAgentManifest(value) {
|
|
49
|
+
record(value); keys(value, ['key', 'name', 'systemPrompt', 'tools']);
|
|
50
|
+
if (typeof value.key !== "string" || value.key.trim() !== value.key || !KEY.test(value.key)) invalid();
|
|
51
|
+
text(value.name, 80); text(value.systemPrompt, 16384);
|
|
52
|
+
if (new TextEncoder().encode(value.systemPrompt).length > 16384 || !Array.isArray(value.tools) || value.tools.length > 32) invalid();
|
|
53
|
+
const seen = new Set();
|
|
54
|
+
for (const tool of value.tools) {
|
|
55
|
+
record(tool); keys(tool, ['artifact', 'key', 'entry', 'name', 'description', 'inputSchema', 'outputSchema', 'clientResult']);
|
|
56
|
+
if (typeof tool.key !== "string" || tool.key.trim() !== tool.key || !KEY.test(tool.key) || seen.has(tool.key) || tool.artifact !== 'server' ||
|
|
57
|
+
tool.entry !== `agent-tool/${value.key}/${tool.key}` || !['none', 'output'].includes(tool.clientResult)) invalid();
|
|
58
|
+
seen.add(tool.key); text(tool.name, 80); text(tool.description, 1200);
|
|
59
|
+
assertAgentSchema(tool.inputSchema); assertAgentSchema(tool.outputSchema);
|
|
60
|
+
}
|
|
61
|
+
return value;
|
|
62
|
+
}
|
|
@@ -6,6 +6,7 @@ import { dirname, relative, resolve, sep } from "node:path";
|
|
|
6
6
|
import { build } from "esbuild";
|
|
7
7
|
import ts from "typescript";
|
|
8
8
|
|
|
9
|
+
import { agentManifest } from "./agents/discovery.js";
|
|
9
10
|
import { serializeWebhookResponse } from "./webhook-response.js";
|
|
10
11
|
|
|
11
12
|
import { TOOLING_VERSION } from "../config.js";
|
|
@@ -42,7 +43,7 @@ export async function buildAppBundle({
|
|
|
42
43
|
sources.serverFunctions.length > 0 ||
|
|
43
44
|
sources.webhookHandlers.length > 0 ||
|
|
44
45
|
sources.workflowSteps.length > 0 ||
|
|
45
|
-
sources.workflowTriggers.length > 0
|
|
46
|
+
sources.workflowTriggers.length > 0 || sources.agents.length > 0
|
|
46
47
|
? await buildServerArtifact(projectDirectory, sources) : null;
|
|
47
48
|
} catch (error) {
|
|
48
49
|
const policyError = error.errors?.find(item => item.detail instanceof ZhikeCliError)?.detail;
|
|
@@ -95,7 +96,7 @@ export async function buildAppBundle({
|
|
|
95
96
|
});
|
|
96
97
|
}
|
|
97
98
|
|
|
98
|
-
async function assertTypeScriptProgram(projectDirectory, { sourceFiles, serverFunctions }) {
|
|
99
|
+
async function assertTypeScriptProgram(projectDirectory, { sourceFiles, serverFunctions, agents }) {
|
|
99
100
|
const paths = {
|
|
100
101
|
"@77-zhike/app-sdk": [resolve(SDK_SOURCE_ROOT, "index.d.ts")],
|
|
101
102
|
"@77-zhike/app-sdk/client": [resolve(SDK_SOURCE_ROOT, "client", "index.d.ts")],
|
|
@@ -125,11 +126,15 @@ async function assertTypeScriptProgram(projectDirectory, { sourceFiles, serverFu
|
|
|
125
126
|
const rootNames = sourceFiles.map((path) => resolve(projectDirectory, "src", path));
|
|
126
127
|
// 仅供 TypeScript 检查,不落盘、不进 Artifact;复用原包装的参数/结果合同。
|
|
127
128
|
const contractPath = resolve(projectDirectory, ".zhike/server-function-contracts.ts");
|
|
129
|
+
const handlers = [
|
|
130
|
+
...serverFunctions.map(item => ({ ...item, member: '' })),
|
|
131
|
+
...agents.flatMap(agent => agent.tools.map(item => ({ ...item, member: '.execute' }))),
|
|
132
|
+
];
|
|
128
133
|
const contractSource = [
|
|
129
134
|
'import type { ServerFunction } from "@77-zhike/app-sdk/server";',
|
|
130
|
-
...
|
|
135
|
+
...handlers.flatMap(({ relativePath, member }, index) => [
|
|
131
136
|
`import handler${index} from ${JSON.stringify(`../src/${relativePath.slice(0, -3)}`)};`,
|
|
132
|
-
`type Contract${index} = ServerFunction<Parameters<typeof handler${index}>, Awaited<ReturnType<typeof handler${index}>>>;`,
|
|
137
|
+
`type Contract${index} = ServerFunction<Parameters<typeof handler${index}${member}>, Awaited<ReturnType<typeof handler${index}${member}>>>;`,
|
|
133
138
|
]),
|
|
134
139
|
].join("\n");
|
|
135
140
|
const host = ts.createCompilerHost(options);
|
|
@@ -138,14 +143,14 @@ async function assertTypeScriptProgram(projectDirectory, { sourceFiles, serverFu
|
|
|
138
143
|
resolve(fileName) === contractPath
|
|
139
144
|
? ts.createSourceFile(fileName, contractSource, languageVersion, true)
|
|
140
145
|
: getSourceFile(fileName, languageVersion, onError, shouldCreateNewSourceFile);
|
|
141
|
-
if (
|
|
146
|
+
if (handlers.length) rootNames.push(contractPath);
|
|
142
147
|
const program = ts.createProgram({ rootNames, options, host });
|
|
143
148
|
const diagnostics = ts.getPreEmitDiagnostics(program);
|
|
144
149
|
if (diagnostics.length === 0) return;
|
|
145
150
|
const diagnostic = diagnostics[0];
|
|
146
151
|
const contractLine = diagnostic.file?.fileName === contractPath
|
|
147
152
|
? diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start || 0).line : -1;
|
|
148
|
-
const contractOwner = contractLine > 0 ?
|
|
153
|
+
const contractOwner = contractLine > 0 ? handlers[Math.floor((contractLine - 1) / 2)] : null;
|
|
149
154
|
const location = contractOwner ? `src/${contractOwner.relativePath}(参数/返回类型)` : diagnostic.file
|
|
150
155
|
? `${relative(projectDirectory, diagnostic.file.fileName).split(sep).join("/")}:${
|
|
151
156
|
diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start || 0).line + 1
|
|
@@ -189,7 +194,12 @@ async function buildServerArtifact(projectDirectory, sources) {
|
|
|
189
194
|
const hasConnectionLifecycle = sources.lifecycleEvents.some(
|
|
190
195
|
({ event }) => event === "connection-added" || event === "connection-removed",
|
|
191
196
|
);
|
|
197
|
+
const tools = sources.agents.flatMap(agent => agent.tools);
|
|
198
|
+
const toolImports = tools.map((tool, index) => `import agentTool${index} from "./src/${tool.relativePath}";`);
|
|
199
|
+
const agentToolDeclarations = `const agentTools = new Map([${tools.map((tool, index) => `[${JSON.stringify(tool.entry)}, agentTool${index}]`).join(",")}]);`;
|
|
200
|
+
const agentToolDispatch = ` if (request.kind === "agent_tool") { const tool = agentTools.get(request.entryKey); if (!tool) throw new Error("runtime_agent_tool_not_found"); return tool.execute(Object.freeze({ ...request.input })); }\n`;
|
|
192
201
|
const imports = [
|
|
202
|
+
...toolImports,
|
|
193
203
|
...(hasConnectionLifecycle
|
|
194
204
|
? ['import { getWorkspaceConnection as getLifecycleConnection } from "@77-zhike/app-sdk/server";']
|
|
195
205
|
: []),
|
|
@@ -244,7 +254,7 @@ async function buildServerArtifact(projectDirectory, sources) {
|
|
|
244
254
|
const triggerDispatch = sources.workflowTriggers.length > 0
|
|
245
255
|
? ` if (request.kind === "workflow_trigger") {\n const handler = workflowTriggers.get(request.entryKey);\n if (!handler) throw new Error("runtime_workflow_trigger_not_found");\n const result = await handler(Object.freeze({ ...request.params }));\n return request.entryKey.endsWith("/deactivate") ? null : result;\n }\n`
|
|
246
256
|
: "";
|
|
247
|
-
const stdin = `${imports}\n${serializeWebhookResponse.toString()}\nconst lifecycleEvents = new Map([${lifecycleEntries}]);\nconst serverFunctions = new Map([${serverEntries}]);\nconst webhookHandlers = new Map([${webhookEntries}]);\nconst workflowSteps = new Map([${workflowEntries}]);\n${triggerDeclarations}
|
|
257
|
+
const stdin = `${imports}\n${serializeWebhookResponse.toString()}\nconst lifecycleEvents = new Map([${lifecycleEntries}]);\nconst serverFunctions = new Map([${serverEntries}]);\nconst webhookHandlers = new Map([${webhookEntries}]);\nconst workflowSteps = new Map([${workflowEntries}]);\n${triggerDeclarations}${agentToolDeclarations}\nexport async function dispatchServerInvocation(request) {\n if (!request || typeof request !== "object") throw new Error("runtime_invocation_invalid");\n if (request.kind === "lifecycle_event") {\n const definition = lifecycleEvents.get(request.entryKey);\n if (!definition) throw new Error("runtime_lifecycle_event_not_found");\n const params = definition.event === "app-installed" || definition.event === "app-uninstalled" ? request.context : Object.freeze({ connection: getLifecycleConnection() });\n await definition.handler(params);\n return null;\n }\n if (request.kind === "server_function") {\n const handler = serverFunctions.get(request.entryKey);\n if (!handler) throw new Error("runtime_server_function_not_found");\n return handler(...request.args);\n }\n if (request.kind === "workflow_step") {\n const handler = workflowSteps.get(request.entryKey);\n if (!handler) throw new Error("runtime_workflow_step_not_found");\n return handler(Object.freeze({ config: request.config }));\n }\n${triggerDispatch}${agentToolDispatch} if (request.kind === "webhook_handler") {\n const handler = webhookHandlers.get(request.entryKey);\n if (!handler) throw new Error("runtime_webhook_handler_not_found");\n const input = request.webRequest;\n const webRequest = new Request(input.url, { method: input.method, headers: input.headers, body: ["GET", "HEAD"].includes(input.method) ? undefined : input.body });\n const response = await handler(webRequest, Object.freeze({ ...request.context }));\n if (!(response instanceof Response)) throw new Error("runtime_webhook_response_invalid");\n return serializeWebhookResponse(response);\n }\n throw new Error("runtime_invocation_kind_invalid");\n}\n`;
|
|
248
258
|
const result = await build({
|
|
249
259
|
absWorkingDir: projectDirectory,
|
|
250
260
|
bundle: true,
|
|
@@ -400,6 +410,7 @@ function createManifest({ clientBytes, serverBytes, sources }) {
|
|
|
400
410
|
event,
|
|
401
411
|
key,
|
|
402
412
|
})),
|
|
413
|
+
...(sources.agents.length ? { agents: sources.agents.map(agentManifest) } : {}),
|
|
403
414
|
serverFunctions: sources.serverFunctions.map(({ key }) => ({
|
|
404
415
|
artifact: "server",
|
|
405
416
|
key,
|
|
@@ -430,6 +441,9 @@ function createServerDefinitionsDigest(sources) {
|
|
|
430
441
|
return sha256(
|
|
431
442
|
canonicalJsonBytes({
|
|
432
443
|
lifecycleEvents: sources.lifecycleEvents.map(({ event, key }) => ({ event, key })),
|
|
444
|
+
...(sources.agents.length ? { agents: sources.agents.map(({ key, tools }) => ({
|
|
445
|
+
key, tools: tools.map(({ key: toolKey, entry }) => ({ key: toolKey, entry })),
|
|
446
|
+
})) } : {}),
|
|
433
447
|
serverFunctions: sources.serverFunctions.map(({ key }) => ({ key })),
|
|
434
448
|
webhookHandlers: sources.webhookHandlers.map(({ key, methods }) => ({ key, methods })),
|
|
435
449
|
...(sources.workflowSteps.length > 0 ? { workflowSteps: sources.workflowSteps.map(({ key, entry }) => ({ key, entry })) } : {}),
|
|
@@ -5,6 +5,7 @@ import { posix, relative, resolve, sep } from "node:path";
|
|
|
5
5
|
import ts from "typescript";
|
|
6
6
|
|
|
7
7
|
import { ZhikeCliError } from "../errors.js";
|
|
8
|
+
import { discoverAgents } from "./agents/discovery.js";
|
|
8
9
|
import { discoverWorkflowBlock } from "./workflow-blocks/discovery.js";
|
|
9
10
|
import { assertAllowedPackageImport } from "./dependency-policy.js";
|
|
10
11
|
|
|
@@ -50,6 +51,7 @@ export async function discoverAppSources(projectDirectory) {
|
|
|
50
51
|
}
|
|
51
52
|
const sourceFilesByPath = new Map(parsedFiles.map(file => [file.relativePath, file.sourceFile]));
|
|
52
53
|
|
|
54
|
+
const agents = discoverAgents(parsedFiles);
|
|
53
55
|
const frontendExtensions = [];
|
|
54
56
|
const lifecycleEvents = [];
|
|
55
57
|
const serverFunctions = [];
|
|
@@ -138,7 +140,8 @@ export async function discoverAppSources(projectDirectory) {
|
|
|
138
140
|
serverFunctions.length === 0 &&
|
|
139
141
|
webhookHandlers.length === 0 &&
|
|
140
142
|
workflowSteps.length === 0 &&
|
|
141
|
-
workflowTriggers.length === 0
|
|
143
|
+
workflowTriggers.length === 0 &&
|
|
144
|
+
agents.length === 0
|
|
142
145
|
) {
|
|
143
146
|
throw toolchainError(
|
|
144
147
|
"zhike_source_entry_missing",
|
|
@@ -149,6 +152,7 @@ export async function discoverAppSources(projectDirectory) {
|
|
|
149
152
|
throw toolchainError("zhike_settings_duplicate", "一个 App 至多声明一个 Settings");
|
|
150
153
|
}
|
|
151
154
|
return Object.freeze({
|
|
155
|
+
agents: Object.freeze(agents),
|
|
152
156
|
frontendExtensions: Object.freeze(sortByKey(frontendExtensions)),
|
|
153
157
|
lifecycleEvents: Object.freeze(sortByKey(lifecycleEvents)),
|
|
154
158
|
serverFunctions: Object.freeze(sortByKey(serverFunctions)),
|
|
@@ -572,7 +576,7 @@ export function validateImports(sourceFile, relativePath, options = {}) {
|
|
|
572
576
|
const allowsStandardFetch =
|
|
573
577
|
options.target === "server" || (!options.target && (
|
|
574
578
|
relativePath.startsWith("server/") ||
|
|
575
|
-
relativePath.startsWith("app/blocks/") ||
|
|
579
|
+
relativePath.startsWith("app/blocks/") || relativePath.startsWith("app/agents/") ||
|
|
576
580
|
/^app\/events\/.+\.event\.ts$/.test(relativePath) ||
|
|
577
581
|
/^app\/webhooks\/.+\.webhook\.ts$/.test(relativePath)));
|
|
578
582
|
const target = allowsStandardFetch ? "server" : "client";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// 此文件由 scripts/generate-components.mjs 生成,请修改产品能力声明。
|
|
2
|
-
export const componentTypes = Object.freeze(["NativeDOM","Icon","Stack","SplitLayout","SplitLayoutMain","SplitLayoutAside","SplitLayoutActions","Section","Banner","Badge","LoadingState","Skeleton","Card","Grid","EmptyState","ZhikeLink","Button","SearchInput","FilterSelect","Switch","LookupCell","Tabs","TabsList","TabsTrigger","TabsContent","Table","TableHeader","TableBody","TableRow","TableCell","Avatar","DescriptionList","DescriptionListItem","DescriptionListMenu","DescriptionListMenuItem","Divider","Chart","DashboardSurface","DashboardLayout","DashboardPanel","MetricReadout","AnalysisView","Json","Link","StatusBadge","TextBlock","TypographyTitle","TypographyBody","TypographyCaption","TableHeaderCell","WidgetTextWidget","WidgetTitle","WidgetTextPrimary","WidgetTextSecondary","WidgetLoading","WidgetDecoration"]);
|
|
3
|
-
export const publicComponentNames = Object.freeze(["NativeDOM","Icon","Stack","SplitLayout","SplitLayoutMain","SplitLayoutAside","SplitLayoutActions","Section","Banner","Badge","LoadingState","Skeleton","Card","Grid","EmptyState","ZhikeLink","Button","SearchInput","FilterSelect","Switch","LookupCell","Tabs","TabsList","TabsTrigger","TabsContent","Table","TableHeader","TableBody","TableRow","TableCell","Avatar","DescriptionList","DescriptionListItem","DescriptionListMenu","DescriptionListMenuItem","Divider","Chart","DashboardSurface","DashboardLayout","DashboardPanel","MetricReadout","AnalysisView","Json","Link","StatusBadge","TextBlock","TypographyTitle","TypographyBody","TypographyCaption","TableHeaderCell","WidgetTextWidget","WidgetTitle","WidgetTextPrimary","WidgetTextSecondary","WidgetLoading","WidgetDecoration"]);
|
|
4
|
-
export const legacyComponentTypes = Object.freeze(["NativeDOM","Text","Icon","Stack","SplitLayout","SplitLayoutMain","SplitLayoutAside","SplitLayoutActions","Section","Banner","Badge","LoadingState","Skeleton","Card","Grid","EmptyState","ZhikeLink","Button","SearchInput","FilterSelect","Switch","LookupCell","Tabs","TabsList","TabsTrigger","TabsContent","Table","TableHeader","TableBody","TableRow","TableCell","Avatar","DescriptionList","DescriptionListItem","DescriptionListMenu","DescriptionListMenuItem","Divider","Chart","DashboardSurface","DashboardLayout","DashboardPanel","MetricReadout","AnalysisView","Json","Link","StatusBadge","TextBlock","TypographyTitle","TypographyBody","TypographyCaption","TableHeaderCell","WidgetTextWidget","WidgetTitle","WidgetTextPrimary","WidgetTextSecondary","WidgetLoading","WidgetDecoration"]);
|
|
2
|
+
export const componentTypes = Object.freeze(["Conversation","ConversationRoot","ConversationMessages","ConversationComposer","ConversationHistory","ConversationNewButton","ConversationStopButton","ConversationStatus","NativeDOM","Icon","Stack","SplitLayout","SplitLayoutMain","SplitLayoutAside","SplitLayoutActions","Section","Banner","Badge","LoadingState","Skeleton","Card","Grid","EmptyState","ZhikeLink","Button","SearchInput","FilterSelect","Switch","LookupCell","Tabs","TabsList","TabsTrigger","TabsContent","Table","TableHeader","TableBody","TableRow","TableCell","Avatar","DescriptionList","DescriptionListItem","DescriptionListMenu","DescriptionListMenuItem","Divider","Chart","DashboardSurface","DashboardLayout","DashboardPanel","MetricReadout","AnalysisView","Json","Link","StatusBadge","TextBlock","TypographyTitle","TypographyBody","TypographyCaption","TableHeaderCell","WidgetTextWidget","WidgetTitle","WidgetTextPrimary","WidgetTextSecondary","WidgetLoading","WidgetDecoration"]);
|
|
3
|
+
export const publicComponentNames = Object.freeze(["Conversation","ConversationRoot","ConversationMessages","ConversationComposer","ConversationHistory","ConversationNewButton","ConversationStopButton","ConversationStatus","NativeDOM","Icon","Stack","SplitLayout","SplitLayoutMain","SplitLayoutAside","SplitLayoutActions","Section","Banner","Badge","LoadingState","Skeleton","Card","Grid","EmptyState","ZhikeLink","Button","SearchInput","FilterSelect","Switch","LookupCell","Tabs","TabsList","TabsTrigger","TabsContent","Table","TableHeader","TableBody","TableRow","TableCell","Avatar","DescriptionList","DescriptionListItem","DescriptionListMenu","DescriptionListMenuItem","Divider","Chart","DashboardSurface","DashboardLayout","DashboardPanel","MetricReadout","AnalysisView","Json","Link","StatusBadge","TextBlock","TypographyTitle","TypographyBody","TypographyCaption","TableHeaderCell","WidgetTextWidget","WidgetTitle","WidgetTextPrimary","WidgetTextSecondary","WidgetLoading","WidgetDecoration"]);
|
|
4
|
+
export const legacyComponentTypes = Object.freeze(["Conversation","ConversationRoot","ConversationMessages","ConversationComposer","ConversationHistory","ConversationNewButton","ConversationStopButton","ConversationStatus","NativeDOM","Text","Icon","Stack","SplitLayout","SplitLayoutMain","SplitLayoutAside","SplitLayoutActions","Section","Banner","Badge","LoadingState","Skeleton","Card","Grid","EmptyState","ZhikeLink","Button","SearchInput","FilterSelect","Switch","LookupCell","Tabs","TabsList","TabsTrigger","TabsContent","Table","TableHeader","TableBody","TableRow","TableCell","Avatar","DescriptionList","DescriptionListItem","DescriptionListMenu","DescriptionListMenuItem","Divider","Chart","DashboardSurface","DashboardLayout","DashboardPanel","MetricReadout","AnalysisView","Json","Link","StatusBadge","TextBlock","TypographyTitle","TypographyBody","TypographyCaption","TableHeaderCell","WidgetTextWidget","WidgetTitle","WidgetTextPrimary","WidgetTextSecondary","WidgetLoading","WidgetDecoration"]);
|
|
5
5
|
export const badgeColors = Object.freeze(["amber","blue","cyan","green","grey","lavender","lime","orange","pink","purple","red","yellow"]);
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** 实时事件身份;executionId 是服务端实际运行 ID。 */
|
|
2
|
+
export interface ConversationEventIdentity {
|
|
3
|
+
eventId: string;
|
|
4
|
+
conversationId: string;
|
|
5
|
+
turnId: string;
|
|
6
|
+
executionId: string;
|
|
7
|
+
}
|
|
8
|
+
export interface ConversationCreatedEvent { eventId: string; conversationId: string; }
|
|
9
|
+
export type TurnStartedEvent = ConversationEventIdentity;
|
|
10
|
+
export type TurnFinishedEvent = ConversationEventIdentity & {
|
|
11
|
+
status: 'completed' | 'cancelled' | 'failed';
|
|
12
|
+
error?: { code: string; message: string };
|
|
13
|
+
};
|
|
14
|
+
export type ToolCallEvent = ConversationEventIdentity & {
|
|
15
|
+
toolCallId: string;
|
|
16
|
+
tool: { kind: 'app'; key: string; name: string };
|
|
17
|
+
phase: 'started' | 'succeeded' | 'failed' | 'cancelled';
|
|
18
|
+
/** 仅显式 clientResult=output 且经过平台校验时存在。 */
|
|
19
|
+
result?: import('./index.js').JsonValue;
|
|
20
|
+
error?: { code: string; message: string };
|
|
21
|
+
};
|
|
22
|
+
export interface ConversationErrorEvent {
|
|
23
|
+
eventId: string;
|
|
24
|
+
phase: 'request' | 'transport' | 'execution';
|
|
25
|
+
code: string;
|
|
26
|
+
message: string;
|
|
27
|
+
/** 必须先重新读取状态,再由用户决定是否重试。 */
|
|
28
|
+
retryable: boolean;
|
|
29
|
+
requestId?: string;
|
|
30
|
+
conversationId?: string;
|
|
31
|
+
turnId?: string;
|
|
32
|
+
executionId?: string;
|
|
33
|
+
}
|
package/src/ui/factory.js
CHANGED
|
@@ -53,6 +53,10 @@ export function createUiComponents(React, { legacy = false, useOwner = () => nul
|
|
|
53
53
|
}
|
|
54
54
|
return React.createElement(type, props);
|
|
55
55
|
}]));
|
|
56
|
+
if (components.Conversation) Object.assign(components.Conversation, { Root: components.ConversationRoot,
|
|
57
|
+
Messages: components.ConversationMessages, Composer: components.ConversationComposer,
|
|
58
|
+
History: components.ConversationHistory, NewButton: components.ConversationNewButton,
|
|
59
|
+
StopButton: components.ConversationStopButton, Status: components.ConversationStatus });
|
|
56
60
|
Object.assign(components.DescriptionList, { Item: components.DescriptionListItem, Menu: components.DescriptionListMenu });
|
|
57
61
|
components.DescriptionListMenu.Item = components.DescriptionListMenuItem;
|
|
58
62
|
Object.assign(components.Table, { Header: components.TableHeader, HeaderCell: components.TableHeaderCell, Body: components.TableBody, Row: components.TableRow, Cell: components.TableCell });
|
package/src/ui/index.d.ts
CHANGED
|
@@ -8,6 +8,63 @@ export interface ChartData { labels: string[]; series: { id: string; label: stri
|
|
|
8
8
|
export type AppIconName = "a-arrow-down" | "a-arrow-up" | "a-large-small" | "accessibility" | "activity" | "activity-square" | "ad" | "air-vent" | "airplay" | "alarm-check" | "alarm-clock" | "alarm-clock-check" | "alarm-clock-minus" | "alarm-clock-off" | "alarm-clock-plus" | "alarm-minus" | "alarm-plus" | "alarm-smoke" | "album" | "alert-circle" | "alert-octagon" | "alert-triangle" | "align-center" | "align-center-horizontal" | "align-center-vertical" | "align-end-horizontal" | "align-end-vertical" | "align-horizontal-distribute-center" | "align-horizontal-distribute-end" | "align-horizontal-distribute-start" | "align-horizontal-justify-center" | "align-horizontal-justify-end" | "align-horizontal-justify-start" | "align-horizontal-space-around" | "align-horizontal-space-between" | "align-justify" | "align-left" | "align-right" | "align-start-horizontal" | "align-start-vertical" | "align-vertical-distribute-center" | "align-vertical-distribute-end" | "align-vertical-distribute-start" | "align-vertical-justify-center" | "align-vertical-justify-end" | "align-vertical-justify-start" | "align-vertical-space-around" | "align-vertical-space-between" | "ambulance" | "ampersand" | "ampersands" | "amphora" | "anchor" | "angle" | "angry" | "annoyed" | "antenna" | "anvil" | "aperture" | "app-window" | "app-window-mac" | "apple" | "archive" | "archive-restore" | "archive-x" | "area-chart" | "armchair" | "arrow-big-down" | "arrow-big-down-dash" | "arrow-big-left" | "arrow-big-left-dash" | "arrow-big-right" | "arrow-big-right-dash" | "arrow-big-up" | "arrow-big-up-dash" | "arrow-down" | "arrow-down-0-1" | "arrow-down-01" | "arrow-down-1-0" | "arrow-down-10" | "arrow-down-a-z" | "arrow-down-az" | "arrow-down-circle" | "arrow-down-from-line" | "arrow-down-left" | "arrow-down-left-from-circle" | "arrow-down-left-from-square" | "arrow-down-left-square" | "arrow-down-narrow-wide" | "arrow-down-right" | "arrow-down-right-from-circle" | "arrow-down-right-from-square" | "arrow-down-right-square" | "arrow-down-square" | "arrow-down-to-dot" | "arrow-down-to-line" | "arrow-down-up" | "arrow-down-wide-narrow" | "arrow-down-z-a" | "arrow-down-za" | "arrow-left" | "arrow-left-circle" | "arrow-left-from-line" | "arrow-left-right" | "arrow-left-square" | "arrow-left-to-line" | "arrow-right" | "arrow-right-circle" | "arrow-right-from-line" | "arrow-right-left" | "arrow-right-square" | "arrow-right-to-line" | "arrow-up" | "arrow-up-0-1" | "arrow-up-01" | "arrow-up-1-0" | "arrow-up-10" | "arrow-up-a-z" | "arrow-up-az" | "arrow-up-circle" | "arrow-up-down" | "arrow-up-from-dot" | "arrow-up-from-line" | "arrow-up-left" | "arrow-up-left-from-circle" | "arrow-up-left-from-square" | "arrow-up-left-square" | "arrow-up-narrow-wide" | "arrow-up-right" | "arrow-up-right-from-circle" | "arrow-up-right-from-square" | "arrow-up-right-square" | "arrow-up-square" | "arrow-up-to-line" | "arrow-up-wide-narrow" | "arrow-up-z-a" | "arrow-up-za" | "arrows-up-from-line" | "asterisk" | "asterisk-square" | "astroid" | "at-sign" | "atom" | "audio-lines" | "audio-lines-off" | "audio-lines-x" | "audio-waveform" | "award" | "axe" | "axis-3-d" | "axis-3d" | "baby" | "backpack" | "badge" | "badge-alert" | "badge-cent" | "badge-check" | "badge-dollar-sign" | "badge-euro" | "badge-help" | "badge-indian-rupee" | "badge-info" | "badge-japanese-yen" | "badge-minus" | "badge-percent" | "badge-plus" | "badge-pound-sterling" | "badge-question-mark" | "badge-russian-ruble" | "badge-swiss-franc" | "badge-turkish-lira" | "badge-x" | "baggage-claim" | "balloon" | "ban" | "banana" | "bandage" | "banknote" | "banknote-arrow-down" | "banknote-arrow-up" | "banknote-check" | "banknote-x" | "bar-chart" | "bar-chart-2" | "bar-chart-3" | "bar-chart-4" | "bar-chart-big" | "bar-chart-horizontal" | "bar-chart-horizontal-big" | "barcode" | "barrel" | "baseline" | "bath" | "battery" | "battery-charging" | "battery-full" | "battery-low" | "battery-medium" | "battery-plus" | "battery-warning" | "beaker" | "bean" | "bean-off" | "bed" | "bed-double" | "bed-single" | "beef" | "beef-off" | "beer" | "beer-off" | "bell" | "bell-check" | "bell-dot" | "bell-electric" | "bell-minus" | "bell-off" | "bell-plus" | "bell-ring" | "between-horizonal-end" | "between-horizonal-start" | "between-horizontal-end" | "between-horizontal-start" | "between-vertical-end" | "between-vertical-start" | "biceps-flexed" | "bike" | "binary" | "binoculars" | "biohazard" | "bird" | "birdhouse" | "bitcoin" | "blend" | "blender" | "blinds" | "blocks" | "bluetooth" | "bluetooth-connected" | "bluetooth-off" | "bluetooth-searching" | "bold" | "bolt" | "bomb" | "bone" | "bone-fracture" | "book" | "book-a" | "book-alert" | "book-audio" | "book-check" | "book-copy" | "book-dashed" | "book-down" | "book-headphones" | "book-heart" | "book-image" | "book-key" | "book-lock" | "book-marked" | "book-minus" | "book-open" | "book-open-check" | "book-open-text" | "book-plus" | "book-search" | "book-template" | "book-text" | "book-type" | "book-up" | "book-up-2" | "book-user" | "book-x" | "bookmark" | "bookmark-check" | "bookmark-minus" | "bookmark-off" | "bookmark-plus" | "bookmark-x" | "boom-box" | "bot" | "bot-message-square" | "bot-off" | "bottle-wine" | "bow-arrow" | "box" | "box-select" | "boxes" | "braces" | "brackets" | "brain" | "brain-circuit" | "brain-cog" | "brick-wall" | "brick-wall-fire" | "brick-wall-shield" | "briefcase" | "briefcase-business" | "briefcase-conveyor-belt" | "briefcase-medical" | "bring-to-front" | "broccoli" | "broom" | "broom-sparkles" | "brush" | "brush-cleaning" | "bubbles" | "bug" | "bug-off" | "bug-play" | "building" | "building-2" | "bus" | "bus-front" | "cable" | "cable-car" | "cake" | "cake-slice" | "calculator" | "calendar" | "calendar-1" | "calendar-arrow-down" | "calendar-arrow-up" | "calendar-check" | "calendar-check-2" | "calendar-clock" | "calendar-cog" | "calendar-days" | "calendar-fold" | "calendar-heart" | "calendar-minus" | "calendar-minus-2" | "calendar-off" | "calendar-plus" | "calendar-plus-2" | "calendar-range" | "calendar-search" | "calendar-sync" | "calendar-x" | "calendar-x-2" | "calendars" | "camera" | "camera-off" | "candlestick-chart" | "candy" | "candy-cane" | "candy-off" | "cannabis" | "cannabis-off" | "captions" | "captions-off" | "car" | "car-battery" | "car-front" | "car-taxi-front" | "caravan" | "card-sim" | "carrot" | "case-lower" | "case-sensitive" | "case-upper" | "cassette-tape" | "cast" | "castle" | "cat" | "cctv" | "cctv-off" | "chart-area" | "chart-bar" | "chart-bar-big" | "chart-bar-decreasing" | "chart-bar-increasing" | "chart-bar-stacked" | "chart-candlestick" | "chart-column" | "chart-column-big" | "chart-column-decreasing" | "chart-column-increasing" | "chart-column-stacked" | "chart-gantt" | "chart-line" | "chart-network" | "chart-no-axes-column" | "chart-no-axes-column-decreasing" | "chart-no-axes-column-increasing" | "chart-no-axes-combined" | "chart-no-axes-gantt" | "chart-pie" | "chart-scatter" | "chart-spline" | "check" | "check-check" | "check-circle" | "check-circle-2" | "check-line" | "check-square" | "check-square-2" | "chef-hat" | "cherry" | "chess-bishop" | "chess-king" | "chess-knight" | "chess-pawn" | "chess-queen" | "chess-rook" | "chevron-down" | "chevron-down-circle" | "chevron-down-square" | "chevron-first" | "chevron-last" | "chevron-left" | "chevron-left-circle" | "chevron-left-square" | "chevron-right" | "chevron-right-circle" | "chevron-right-square" | "chevron-up" | "chevron-up-circle" | "chevron-up-square" | "chevrons-down" | "chevrons-down-up" | "chevrons-left" | "chevrons-left-right" | "chevrons-left-right-ellipsis" | "chevrons-right" | "chevrons-right-left" | "chevrons-up" | "chevrons-up-down" | "church" | "cigarette" | "cigarette-off" | "circle" | "circle-alert" | "circle-arrow-down" | "circle-arrow-left" | "circle-arrow-out-down-left" | "circle-arrow-out-down-right" | "circle-arrow-out-up-left" | "circle-arrow-out-up-right" | "circle-arrow-right" | "circle-arrow-up" | "circle-check" | "circle-check-big" | "circle-chevron-down" | "circle-chevron-left" | "circle-chevron-right" | "circle-chevron-up" | "circle-dashed" | "circle-divide" | "circle-dollar-sign" | "circle-dot" | "circle-dot-dashed" | "circle-ellipsis" | "circle-equal" | "circle-euro" | "circle-fading-arrow-up" | "circle-fading-plus" | "circle-gauge" | "circle-help" | "circle-minus" | "circle-off" | "circle-parking" | "circle-parking-off" | "circle-pause" | "circle-percent" | "circle-pile" | "circle-play" | "circle-plus" | "circle-pound-sterling" | "circle-power" | "circle-question-mark" | "circle-slash" | "circle-slash-2" | "circle-slashed" | "circle-small" | "circle-star" | "circle-stop" | "circle-user" | "circle-user-round" | "circle-x" | "circuit-board" | "citrus" | "clapperboard" | "clipboard" | "clipboard-check" | "clipboard-clock" | "clipboard-copy" | "clipboard-edit" | "clipboard-list" | "clipboard-minus" | "clipboard-paste" | "clipboard-pen" | "clipboard-pen-line" | "clipboard-plus" | "clipboard-signature" | "clipboard-type" | "clipboard-x" | "clock" | "clock-1" | "clock-10" | "clock-11" | "clock-12" | "clock-2" | "clock-3" | "clock-4" | "clock-5" | "clock-6" | "clock-7" | "clock-8" | "clock-9" | "clock-alert" | "clock-arrow-down" | "clock-arrow-left" | "clock-arrow-right" | "clock-arrow-up" | "clock-check" | "clock-fading" | "clock-plus" | "closed-caption" | "cloud" | "cloud-alert" | "cloud-backup" | "cloud-check" | "cloud-cog" | "cloud-download" | "cloud-drizzle" | "cloud-fog" | "cloud-hail" | "cloud-lightning" | "cloud-moon" | "cloud-moon-rain" | "cloud-off" | "cloud-rain" | "cloud-rain-wind" | "cloud-snow" | "cloud-sun" | "cloud-sun-rain" | "cloud-sync" | "cloud-upload" | "cloudy" | "clover" | "club" | "code" | "code-2" | "code-square" | "code-xml" | "coffee" | "cog" | "coins" | "columns" | "columns-2" | "columns-3" | "columns-3-cog" | "columns-4" | "columns-settings" | "combine" | "command" | "compass" | "component" | "computer" | "concierge-bell" | "cone" | "construction" | "contact" | "contact-2" | "contact-round" | "container" | "contrast" | "cookie" | "cooking-pot" | "copy" | "copy-check" | "copy-minus" | "copy-plus" | "copy-slash" | "copy-x" | "copyleft" | "copyright" | "corner-down-left" | "corner-down-right" | "corner-left-down" | "corner-left-up" | "corner-right-down" | "corner-right-up" | "corner-up-left" | "corner-up-right" | "cpu" | "creative-commons" | "credit-card" | "croissant" | "crop" | "cross" | "crosshair" | "crown" | "cuboid" | "cup-soda" | "curly-braces" | "currency" | "cylinder" | "dam" | "database" | "database-arrow-down" | "database-arrow-up" | "database-backup" | "database-check" | "database-minus" | "database-plus" | "database-search" | "database-x" | "database-zap" | "decimals-arrow-left" | "decimals-arrow-right" | "delete" | "dessert" | "diameter" | "diamond" | "diamond-minus" | "diamond-percent" | "diamond-plus" | "dice-1" | "dice-2" | "dice-3" | "dice-4" | "dice-5" | "dice-6" | "dices" | "diff" | "disc" | "disc-2" | "disc-3" | "disc-album" | "divide" | "divide-circle" | "divide-square" | "dna" | "dna-off" | "dock" | "dog" | "dollar-sign" | "donut" | "door-closed" | "door-closed-locked" | "door-open" | "dot" | "dot-square" | "download" | "download-cloud" | "drafting-compass" | "drama" | "drill" | "drone" | "droplet" | "droplet-off" | "droplets" | "drum" | "drumstick" | "dumbbell" | "ear" | "ear-off" | "earth" | "earth-lock" | "eclipse" | "edit" | "edit-2" | "edit-3" | "egg" | "egg-fried" | "egg-off" | "eject" | "ellipse" | "ellipsis" | "ellipsis-vertical" | "equal" | "equal-approximately" | "equal-not" | "equal-square" | "eraser" | "ethernet-port" | "euro" | "ev-charger" | "expand" | "external-link" | "eye" | "eye-closed" | "eye-dashed" | "eye-off" | "face-angry" | "face-expressionless" | "face-grinning" | "face-neutral" | "face-slightly-frowning" | "face-slightly-smiling" | "face-slightly-smiling-plus" | "factory" | "fan" | "fast-forward" | "feather" | "fence" | "ferris-wheel" | "file" | "file-archive" | "file-audio" | "file-audio-2" | "file-axis-3-d" | "file-axis-3d" | "file-badge" | "file-badge-2" | "file-bar-chart" | "file-bar-chart-2" | "file-box" | "file-braces" | "file-braces-corner" | "file-chart-column" | "file-chart-column-increasing" | "file-chart-line" | "file-chart-pie" | "file-check" | "file-check-2" | "file-check-corner" | "file-clock" | "file-code" | "file-code-2" | "file-code-corner" | "file-cog" | "file-cog-2" | "file-diff" | "file-digit" | "file-down" | "file-edit" | "file-exclamation-point" | "file-headphone" | "file-heart" | "file-image" | "file-input" | "file-json" | "file-json-2" | "file-key" | "file-key-2" | "file-line-chart" | "file-lock" | "file-lock-2" | "file-minus" | "file-minus-2" | "file-minus-corner" | "file-music" | "file-output" | "file-pen" | "file-pen-line" | "file-pie-chart" | "file-play" | "file-plus" | "file-plus-2" | "file-plus-corner" | "file-question" | "file-question-mark" | "file-scan" | "file-search" | "file-search-2" | "file-search-corner" | "file-signal" | "file-signature" | "file-sliders" | "file-spreadsheet" | "file-stack" | "file-symlink" | "file-terminal" | "file-text" | "file-type" | "file-type-2" | "file-type-corner" | "file-up" | "file-user" | "file-video" | "file-video-2" | "file-video-camera" | "file-volume" | "file-volume-2" | "file-warning" | "file-x" | "file-x-2" | "file-x-corner" | "files" | "film" | "filter" | "filter-x" | "fingerprint" | "fingerprint-pattern" | "fire-extinguisher" | "fish" | "fish-off" | "fish-symbol" | "fishing-hook" | "fishing-rod" | "flag" | "flag-off" | "flag-triangle-left" | "flag-triangle-right" | "flame" | "flame-kindling" | "flashlight" | "flashlight-off" | "flask-conical" | "flask-conical-off" | "flask-round" | "flip-horizontal" | "flip-horizontal-2" | "flip-vertical" | "flip-vertical-2" | "flower" | "flower-2" | "focus" | "fold-horizontal" | "fold-vertical" | "folder" | "folder-archive" | "folder-bookmark" | "folder-check" | "folder-clock" | "folder-closed" | "folder-code" | "folder-cog" | "folder-cog-2" | "folder-dot" | "folder-down" | "folder-edit" | "folder-git" | "folder-git-2" | "folder-heart" | "folder-input" | "folder-kanban" | "folder-key" | "folder-lock" | "folder-minus" | "folder-open" | "folder-open-dot" | "folder-output" | "folder-pen" | "folder-plus" | "folder-root" | "folder-search" | "folder-search-2" | "folder-symlink" | "folder-sync" | "folder-tree" | "folder-up" | "folder-x" | "folders" | "footprints" | "fork-knife" | "fork-knife-crossed" | "forklift" | "form" | "form-input" | "forward" | "frame" | "frown" | "fuel" | "fullscreen" | "function-square" | "funnel" | "funnel-plus" | "funnel-x" | "gallery-horizontal" | "gallery-horizontal-end" | "gallery-thumbnails" | "gallery-vertical" | "gallery-vertical-end" | "gamepad" | "gamepad-2" | "gamepad-directional" | "gantt-chart" | "gantt-chart-square" | "gauge" | "gauge-circle" | "gavel" | "gem" | "georgian-lari" | "ghost" | "gift" | "git-branch" | "git-branch-minus" | "git-branch-plus" | "git-commit" | "git-commit-horizontal" | "git-commit-vertical" | "git-compare" | "git-compare-arrows" | "git-fork" | "git-graph" | "git-merge" | "git-merge-conflict" | "git-pull-request" | "git-pull-request-arrow" | "git-pull-request-closed" | "git-pull-request-create" | "git-pull-request-create-arrow" | "git-pull-request-draft" | "glass-water" | "glasses" | "globe" | "globe-2" | "globe-check" | "globe-lock" | "globe-off" | "globe-x" | "goal" | "gpu" | "grab" | "graduation-cap" | "grape" | "grid" | "grid-2-x-2" | "grid-2-x-2-check" | "grid-2-x-2-plus" | "grid-2-x-2-x" | "grid-2x2" | "grid-2x2-check" | "grid-2x2-plus" | "grid-2x2-x" | "grid-3-x-3" | "grid-3x2" | "grid-3x3" | "grip" | "grip-horizontal" | "grip-vertical" | "group" | "guitar" | "ham" | "hamburger" | "hammer" | "hand" | "hand-coins" | "hand-fist" | "hand-grab" | "hand-heart" | "hand-helping" | "hand-metal" | "hand-platter" | "handbag" | "handshake" | "hard-drive" | "hard-drive-download" | "hard-drive-upload" | "hard-hat" | "hash" | "hat-glasses" | "haze" | "hd" | "hdmi-port" | "heading" | "heading-1" | "heading-2" | "heading-3" | "heading-4" | "heading-5" | "heading-6" | "headphone-off" | "headphones" | "headset" | "heart" | "heart-crack" | "heart-handshake" | "heart-minus" | "heart-off" | "heart-plus" | "heart-pulse" | "heart-x" | "heater" | "helicopter" | "help-circle" | "helping-hand" | "hexagon" | "highlighter" | "history" | "home" | "hop" | "hop-off" | "hospital" | "hotel" | "hourglass" | "house" | "house-heart" | "house-plug" | "house-plus" | "house-wifi" | "ice-cream" | "ice-cream-2" | "ice-cream-bowl" | "ice-cream-cone" | "id-card" | "id-card-lanyard" | "image" | "image-down" | "image-minus" | "image-off" | "image-play" | "image-plus" | "image-up" | "image-upscale" | "images" | "import" | "inbox" | "indent" | "indent-decrease" | "indent-increase" | "indian-rupee" | "infinity" | "info" | "inspect" | "inspection-panel" | "italic" | "iteration-ccw" | "iteration-cw" | "japanese-yen" | "joystick" | "kanban" | "kanban-square" | "kanban-square-dashed" | "kayak" | "key" | "key-round" | "key-square" | "keyboard" | "keyboard-music" | "keyboard-off" | "lamp" | "lamp-ceiling" | "lamp-desk" | "lamp-floor" | "lamp-wall-down" | "lamp-wall-up" | "land-plot" | "landmark" | "languages" | "laptop" | "laptop-2" | "laptop-minimal" | "laptop-minimal-check" | "lasso" | "lasso-select" | "laugh" | "layer-arrow-down" | "layer-arrow-up" | "layers" | "layers-2" | "layers-3" | "layers-arrow-down" | "layers-arrow-up" | "layers-minus" | "layers-plus" | "layout" | "layout-dashboard" | "layout-freeform" | "layout-grid" | "layout-list" | "layout-panel-left" | "layout-panel-top" | "layout-template" | "leaf" | "leafy-green" | "lectern" | "lens-concave" | "lens-convex" | "letter-text" | "library" | "library-big" | "library-square" | "life-buoy" | "ligature" | "lightbulb" | "lightbulb-off" | "line-chart" | "line-dot-right-horizontal" | "line-squiggle" | "line-style" | "link" | "link-2" | "link-2-off" | "list" | "list-check" | "list-checks" | "list-chevrons-down-up" | "list-chevrons-up-down" | "list-clock" | "list-collapse" | "list-end" | "list-filter" | "list-filter-plus" | "list-indent-decrease" | "list-indent-increase" | "list-minus" | "list-music" | "list-ordered" | "list-plus" | "list-restart" | "list-sort-ascending" | "list-sort-descending" | "list-start" | "list-todo" | "list-tree" | "list-video" | "list-x" | "loader" | "loader-2" | "loader-circle" | "loader-pinwheel" | "locate" | "locate-fixed" | "locate-off" | "location-edit" | "lock" | "lock-keyhole" | "lock-keyhole-open" | "lock-open" | "log-in" | "log-out" | "logs" | "lollipop" | "luggage" | "m-square" | "magnet" | "mail" | "mail-badge" | "mail-check" | "mail-minus" | "mail-open" | "mail-plus" | "mail-question" | "mail-question-mark" | "mail-search" | "mail-warning" | "mail-x" | "mailbox" | "mails" | "map" | "map-minus" | "map-pin" | "map-pin-check" | "map-pin-check-inside" | "map-pin-house" | "map-pin-minus" | "map-pin-minus-inside" | "map-pin-off" | "map-pin-pen" | "map-pin-plus" | "map-pin-plus-inside" | "map-pin-search" | "map-pin-x" | "map-pin-x-inside" | "map-pinned" | "map-plus" | "mars" | "mars-stroke" | "martini" | "maximize" | "maximize-2" | "medal" | "megaphone" | "megaphone-off" | "meh" | "memory-stick" | "menu" | "menu-square" | "merge" | "message-circle" | "message-circle-check" | "message-circle-code" | "message-circle-dashed" | "message-circle-heart" | "message-circle-more" | "message-circle-off" | "message-circle-plus" | "message-circle-question" | "message-circle-question-mark" | "message-circle-reply" | "message-circle-warning" | "message-circle-x" | "message-square" | "message-square-check" | "message-square-code" | "message-square-dashed" | "message-square-diff" | "message-square-dot" | "message-square-heart" | "message-square-lock" | "message-square-more" | "message-square-off" | "message-square-plus" | "message-square-quote" | "message-square-reply" | "message-square-share" | "message-square-text" | "message-square-warning" | "message-square-x" | "messages-square" | "metronome" | "mic" | "mic-2" | "mic-audio-lines" | "mic-off" | "mic-signal" | "mic-vocal" | "microchip" | "microscope" | "microwave" | "midi-port" | "milestone" | "milk" | "milk-off" | "minimize" | "minimize-2" | "minus" | "minus-circle" | "minus-square" | "mirror-rectangular" | "mirror-round" | "monitor" | "monitor-check" | "monitor-cloud" | "monitor-cog" | "monitor-dot" | "monitor-down" | "monitor-off" | "monitor-pause" | "monitor-play" | "monitor-smartphone" | "monitor-speaker" | "monitor-stop" | "monitor-up" | "monitor-x" | "moon" | "moon-star" | "mop" | "mop-sparkles" | "more-horizontal" | "more-vertical" | "mosque" | "motorbike" | "mountain" | "mountain-snow" | "mouse" | "mouse-left" | "mouse-off" | "mouse-pointer" | "mouse-pointer-2" | "mouse-pointer-2-off" | "mouse-pointer-ban" | "mouse-pointer-click" | "mouse-pointer-square-dashed" | "mouse-right" | "move" | "move-3-d" | "move-3d" | "move-diagonal" | "move-diagonal-2" | "move-down" | "move-down-left" | "move-down-right" | "move-horizontal" | "move-left" | "move-right" | "move-up" | "move-up-left" | "move-up-right" | "move-vertical" | "music" | "music-2" | "music-3" | "music-4" | "navigation" | "navigation-2" | "navigation-2-off" | "navigation-off" | "network" | "newspaper" | "nfc" | "non-binary" | "notebook" | "notebook-pen" | "notebook-tabs" | "notebook-text" | "notepad-text" | "notepad-text-dashed" | "nut" | "nut-off" | "octagon" | "octagon-alert" | "octagon-minus" | "octagon-pause" | "octagon-x" | "omega" | "option" | "orbit" | "origami" | "outdent" | "package" | "package-2" | "package-check" | "package-minus" | "package-open" | "package-plus" | "package-search" | "package-x" | "paint-bucket" | "paint-roller" | "paintbrush" | "paintbrush-2" | "paintbrush-vertical" | "palette" | "palmtree" | "panda" | "panel-bottom" | "panel-bottom-close" | "panel-bottom-dashed" | "panel-bottom-inactive" | "panel-bottom-open" | "panel-left" | "panel-left-close" | "panel-left-dashed" | "panel-left-inactive" | "panel-left-open" | "panel-left-right-dashed" | "panel-right" | "panel-right-close" | "panel-right-dashed" | "panel-right-inactive" | "panel-right-open" | "panel-top" | "panel-top-bottom-dashed" | "panel-top-close" | "panel-top-dashed" | "panel-top-inactive" | "panel-top-open" | "panels-left-bottom" | "panels-left-right" | "panels-right-bottom" | "panels-top-bottom" | "panels-top-left" | "paper-bag" | "paperclip" | "parasol" | "parentheses" | "parking-circle" | "parking-circle-off" | "parking-meter" | "parking-square" | "parking-square-off" | "party-popper" | "pause" | "pause-circle" | "pause-octagon" | "paw-print" | "pc-case" | "pen" | "pen-box" | "pen-line" | "pen-off" | "pen-square" | "pen-tool" | "pencil" | "pencil-line" | "pencil-off" | "pencil-ruler" | "pencil-sparkles" | "pentagon" | "percent" | "percent-circle" | "percent-diamond" | "percent-square" | "person-standing" | "phi" | "philippine-peso" | "phone" | "phone-call" | "phone-forwarded" | "phone-incoming" | "phone-missed" | "phone-off" | "phone-outgoing" | "pi" | "pi-square" | "piano" | "pickaxe" | "picture-in-picture" | "picture-in-picture-2" | "pie-chart" | "piggy-bank" | "pilcrow" | "pilcrow-left" | "pilcrow-right" | "pilcrow-square" | "pill" | "pill-bottle" | "pin" | "pin-off" | "pipette" | "pizza" | "plane" | "plane-landing" | "plane-takeoff" | "play" | "play-circle" | "play-off" | "play-square" | "plug" | "plug-2" | "plug-zap" | "plug-zap-2" | "plus" | "plus-circle" | "plus-square" | "pocket-knife" | "podcast" | "podium" | "pointer" | "pointer-off" | "popcorn" | "popsicle" | "pound-sterling" | "power" | "power-circle" | "power-off" | "power-square" | "presentation" | "printer" | "printer-check" | "printer-x" | "projector" | "proportions" | "puzzle" | "pyramid" | "qr-code" | "quote" | "rabbit" | "radar" | "radiation" | "radical" | "radio" | "radio-off" | "radio-receiver" | "radio-tower" | "radius" | "rainbow" | "rat" | "ratio" | "receipt" | "receipt-cent" | "receipt-euro" | "receipt-indian-rupee" | "receipt-japanese-yen" | "receipt-pound-sterling" | "receipt-russian-ruble" | "receipt-swiss-franc" | "receipt-text" | "receipt-turkish-lira" | "rectangle-circle" | "rectangle-ellipsis" | "rectangle-goggles" | "rectangle-horizontal" | "rectangle-vertical" | "recycle" | "redo" | "redo-2" | "redo-dot" | "refresh-ccw" | "refresh-ccw-dot" | "refresh-cw" | "refresh-cw-off" | "refrigerator" | "regex" | "remove-formatting" | "repeat" | "repeat-1" | "repeat-2" | "repeat-off" | "replace" | "replace-all" | "reply" | "reply-all" | "rewind" | "ribbon" | "road" | "rocket" | "rocking-chair" | "roller-coaster" | "rose" | "rotate-3-d" | "rotate-3d" | "rotate-ccw" | "rotate-ccw-clock" | "rotate-ccw-key" | "rotate-ccw-square" | "rotate-cw" | "rotate-cw-fading-clock" | "rotate-cw-square" | "route" | "route-off" | "router" | "rows" | "rows-2" | "rows-3" | "rows-4" | "rss" | "ruler" | "ruler-dimension-line" | "russian-ruble" | "sailboat" | "salad" | "sandwich" | "satellite" | "satellite-dish" | "saudi-riyal" | "save" | "save-all" | "save-check" | "save-off" | "save-pen" | "save-plus" | "scale" | "scale-3-d" | "scale-3d" | "scaling" | "scan" | "scan-barcode" | "scan-box" | "scan-eye" | "scan-face" | "scan-heart" | "scan-line" | "scan-qr-code" | "scan-search" | "scan-square" | "scan-text" | "scatter-chart" | "school" | "school-2" | "scissors" | "scissors-line-dashed" | "scissors-square" | "scissors-square-dashed-bottom" | "scooter" | "screen-share" | "screen-share-off" | "scroll" | "scroll-text" | "search" | "search-alert" | "search-check" | "search-code" | "search-slash" | "search-x" | "section" | "send" | "send-horizonal" | "send-horizontal" | "send-to-back" | "separator-horizontal" | "separator-vertical" | "server" | "server-cog" | "server-crash" | "server-off" | "server-plus" | "settings" | "settings-2" | "shapes" | "share" | "share-2" | "sheet" | "shell" | "shelving-unit" | "shield" | "shield-alert" | "shield-ban" | "shield-check" | "shield-close" | "shield-cog" | "shield-cog-corner" | "shield-ellipsis" | "shield-half" | "shield-keyhole" | "shield-lock" | "shield-minus" | "shield-off" | "shield-plus" | "shield-question" | "shield-question-mark" | "shield-user" | "shield-x" | "ship" | "ship-wheel" | "shirt" | "shopping-bag" | "shopping-basket" | "shopping-cart" | "shovel" | "shower-head" | "shredder" | "shrimp" | "shrink" | "shrub" | "shuffle" | "sidebar" | "sidebar-close" | "sidebar-open" | "sigma" | "sigma-square" | "signal" | "signal-high" | "signal-low" | "signal-medium" | "signal-zero" | "signature" | "signpost" | "signpost-big" | "siren" | "skip-back" | "skip-forward" | "skull" | "slash" | "slash-square" | "slice" | "sliders" | "sliders-horizontal" | "sliders-vertical" | "smartphone" | "smartphone-charging" | "smartphone-nfc" | "smile" | "smile-plus" | "snail" | "snowflake" | "soap-dispenser-droplet" | "sofa" | "solar-panel" | "sort-asc" | "sort-desc" | "soup" | "space" | "spade" | "sparkle" | "sparkles" | "speaker" | "speech" | "spell-check" | "spell-check-2" | "spline" | "spline-pointer" | "split" | "split-square-horizontal" | "split-square-vertical" | "spool" | "sport-shoe" | "spotlight" | "spray-can" | "sprout" | "square" | "square-activity" | "square-arrow-down" | "square-arrow-down-left" | "square-arrow-down-right" | "square-arrow-left" | "square-arrow-out-down-left" | "square-arrow-out-down-right" | "square-arrow-out-up-left" | "square-arrow-out-up-right" | "square-arrow-right" | "square-arrow-right-enter" | "square-arrow-right-exit" | "square-arrow-up" | "square-arrow-up-left" | "square-arrow-up-right" | "square-asterisk" | "square-bottom-dashed-scissors" | "square-centerline-dashed-horizontal" | "square-centerline-dashed-vertical" | "square-chart-gantt" | "square-check" | "square-check-big" | "square-chevron-down" | "square-chevron-left" | "square-chevron-right" | "square-chevron-up" | "square-code" | "square-dashed" | "square-dashed-bottom" | "square-dashed-bottom-code" | "square-dashed-kanban" | "square-dashed-mouse-pointer" | "square-dashed-text" | "square-dashed-top-solid" | "square-dimensions" | "square-divide" | "square-dot" | "square-equal" | "square-function" | "square-gantt-chart" | "square-kanban" | "square-library" | "square-m" | "square-menu" | "square-minus" | "square-mouse-pointer" | "square-off" | "square-parking" | "square-parking-off" | "square-pause" | "square-pen" | "square-percent" | "square-pi" | "square-pilcrow" | "square-play" | "square-plus" | "square-power" | "square-radical" | "square-round-corner" | "square-scissors" | "square-sigma" | "square-slash" | "square-split-horizontal" | "square-split-vertical" | "square-square" | "square-stack" | "square-star" | "square-stop" | "square-terminal" | "square-text" | "square-user" | "square-user-round" | "square-x" | "squares-exclude" | "squares-intersect" | "squares-subtract" | "squares-unite" | "squircle" | "squircle-dashed" | "squirrel" | "stamp" | "star" | "star-check" | "star-half" | "star-minus" | "star-off" | "star-plus" | "star-x" | "stars" | "step-back" | "step-forward" | "stethoscope" | "sticker" | "sticky-note" | "sticky-note-check" | "sticky-note-minus" | "sticky-note-off" | "sticky-note-plus" | "sticky-note-x" | "sticky-notes" | "stone" | "stop-circle" | "store" | "stretch-horizontal" | "stretch-vertical" | "strikethrough" | "subscript" | "subtitles" | "summary" | "sun" | "sun-dim" | "sun-medium" | "sun-moon" | "sun-snow" | "sunrise" | "sunset" | "superscript" | "swatch-book" | "swiss-franc" | "switch-camera" | "sword" | "swords" | "syringe" | "table" | "table-2" | "table-cells-merge" | "table-cells-split" | "table-columns-split" | "table-config" | "table-of-contents" | "table-properties" | "table-rows-split" | "tablet" | "tablet-smartphone" | "tablets" | "tag" | "tag-plus" | "tag-x" | "tags" | "tally-1" | "tally-2" | "tally-3" | "tally-4" | "tally-5" | "tangent" | "target" | "telescope" | "tent" | "tent-tree" | "terminal" | "terminal-square" | "test-tube" | "test-tube-2" | "test-tube-diagonal" | "test-tubes" | "text" | "text-align-center" | "text-align-end" | "text-align-justify" | "text-align-start" | "text-cursor" | "text-cursor-input" | "text-initial" | "text-quote" | "text-search" | "text-select" | "text-selection" | "text-wrap" | "theater" | "thermometer" | "thermometer-snowflake" | "thermometer-sun" | "thumbs-down" | "thumbs-up" | "ticket" | "ticket-check" | "ticket-minus" | "ticket-percent" | "ticket-plus" | "ticket-slash" | "ticket-x" | "tickets" | "tickets-plane" | "timeline" | "timer" | "timer-off" | "timer-reset" | "toggle-left" | "toggle-right" | "toilet" | "tool-case" | "toolbox" | "tornado" | "torus" | "touchpad" | "touchpad-off" | "towel-rack" | "tower-control" | "toy-brick" | "tractor" | "traffic-cone" | "train" | "train-front" | "train-front-tunnel" | "train-track" | "tram-front" | "transgender" | "trash" | "trash-2" | "tree-deciduous" | "tree-palm" | "tree-pine" | "trees" | "trending-down" | "trending-up" | "trending-up-down" | "triangle" | "triangle-alert" | "triangle-dashed" | "triangle-right" | "trophy" | "truck" | "truck-electric" | "turkish-lira" | "turntable" | "turtle" | "tv" | "tv-2" | "tv-minimal" | "tv-minimal-play" | "type" | "type-outline" | "umbrella" | "umbrella-off" | "underline" | "undo" | "undo-2" | "undo-dot" | "unfold-horizontal" | "unfold-vertical" | "ungroup" | "university" | "unlink" | "unlink-2" | "unlock" | "unlock-keyhole" | "unplug" | "upload" | "upload-cloud" | "usb" | "usb-c-port" | "user" | "user-2" | "user-check" | "user-check-2" | "user-circle" | "user-circle-2" | "user-cog" | "user-cog-2" | "user-key" | "user-lock" | "user-minus" | "user-minus-2" | "user-pen" | "user-plus" | "user-plus-2" | "user-round" | "user-round-arrow-left" | "user-round-check" | "user-round-cog" | "user-round-key" | "user-round-minus" | "user-round-pen" | "user-round-plus" | "user-round-search" | "user-round-x" | "user-search" | "user-shield" | "user-square" | "user-square-2" | "user-star" | "user-x" | "user-x-2" | "users" | "users-2" | "users-round" | "utensils" | "utensils-crossed" | "utility-pole" | "van" | "variable" | "vault" | "vector-square" | "vegan" | "venetian-mask" | "venus" | "venus-and-mars" | "verified" | "vibrate" | "vibrate-off" | "video" | "video-off" | "videotape" | "view" | "voicemail" | "volleyball" | "volume" | "volume-1" | "volume-2" | "volume-off" | "volume-x" | "vote" | "wallet" | "wallet-2" | "wallet-cards" | "wallet-minimal" | "wallpaper" | "wand" | "wand-2" | "wand-sparkles" | "warehouse" | "washing-machine" | "watch" | "waves" | "waves-arrow-down" | "waves-arrow-up" | "waves-horizontal" | "waves-ladder" | "waves-vertical" | "waypoints" | "webcam" | "webcam-off" | "webhook" | "webhook-off" | "weight" | "weight-tilde" | "wheat" | "wheat-off" | "whole-word" | "wifi" | "wifi-cog" | "wifi-high" | "wifi-low" | "wifi-off" | "wifi-pen" | "wifi-sync" | "wifi-zero" | "wind" | "wind-arrow-down" | "wine" | "wine-off" | "workflow" | "worm" | "wrap-text" | "wrench" | "wrench-off" | "x" | "x-circle" | "x-line-top" | "x-octagon" | "x-square" | "zap" | "zap-off" | "zodiac-aquarius" | "zodiac-aries" | "zodiac-cancer" | "zodiac-capricorn" | "zodiac-gemini" | "zodiac-leo" | "zodiac-libra" | "zodiac-ophiuchus" | "zodiac-pisces" | "zodiac-sagittarius" | "zodiac-scorpio" | "zodiac-taurus" | "zodiac-virgo" | "zoom-in" | "zoom-out";
|
|
9
9
|
export type JsonValue = null | boolean | number | string | JsonValue[] | { [key: string]: JsonValue };
|
|
10
10
|
export interface BannerAction { label: string; variant: "primary" | "secondary"; onTrigger: () => void | Promise<void>; }
|
|
11
|
+
export interface ConversationProps {
|
|
12
|
+
agentId: string;
|
|
13
|
+
scenario: string;
|
|
14
|
+
context: string;
|
|
15
|
+
title?: string;
|
|
16
|
+
placeholder?: string;
|
|
17
|
+
onConversationCreated?: (event: import("./conversation.js").ConversationCreatedEvent) => void | Promise<void>;
|
|
18
|
+
onTurnStarted?: (event: import("./conversation.js").TurnStartedEvent) => void | Promise<void>;
|
|
19
|
+
onTurnFinished?: (event: import("./conversation.js").TurnFinishedEvent) => void | Promise<void>;
|
|
20
|
+
onToolCall?: (event: import("./conversation.js").ToolCallEvent) => void | Promise<void>;
|
|
21
|
+
onError?: (event: import("./conversation.js").ConversationErrorEvent) => void | Promise<void>;
|
|
22
|
+
style?: AppStyle;
|
|
23
|
+
}
|
|
24
|
+
export const Conversation: ComponentType<ConversationProps> & { Root: typeof ConversationRoot; Messages: typeof ConversationMessages; Composer: typeof ConversationComposer; History: typeof ConversationHistory; NewButton: typeof ConversationNewButton; StopButton: typeof ConversationStopButton; Status: typeof ConversationStatus };
|
|
25
|
+
export interface ConversationRootProps {
|
|
26
|
+
agentId: string;
|
|
27
|
+
scenario: string;
|
|
28
|
+
context: string;
|
|
29
|
+
title?: string;
|
|
30
|
+
placeholder?: string;
|
|
31
|
+
onConversationCreated?: (event: import("./conversation.js").ConversationCreatedEvent) => void | Promise<void>;
|
|
32
|
+
onTurnStarted?: (event: import("./conversation.js").TurnStartedEvent) => void | Promise<void>;
|
|
33
|
+
onTurnFinished?: (event: import("./conversation.js").TurnFinishedEvent) => void | Promise<void>;
|
|
34
|
+
onToolCall?: (event: import("./conversation.js").ToolCallEvent) => void | Promise<void>;
|
|
35
|
+
onError?: (event: import("./conversation.js").ConversationErrorEvent) => void | Promise<void>;
|
|
36
|
+
style?: AppStyle;
|
|
37
|
+
children?: ReactNode;
|
|
38
|
+
}
|
|
39
|
+
export const ConversationRoot: ComponentType<ConversationRootProps>;
|
|
40
|
+
export interface ConversationMessagesProps {
|
|
41
|
+
fill?: boolean;
|
|
42
|
+
emptyTitle?: string;
|
|
43
|
+
emptyDescription?: string;
|
|
44
|
+
}
|
|
45
|
+
export const ConversationMessages: ComponentType<ConversationMessagesProps>;
|
|
46
|
+
export interface ConversationComposerProps {
|
|
47
|
+
label?: string;
|
|
48
|
+
placeholder?: string;
|
|
49
|
+
}
|
|
50
|
+
export const ConversationComposer: ComponentType<ConversationComposerProps>;
|
|
51
|
+
export interface ConversationHistoryProps {
|
|
52
|
+
label?: string;
|
|
53
|
+
}
|
|
54
|
+
export const ConversationHistory: ComponentType<ConversationHistoryProps>;
|
|
55
|
+
export interface ConversationNewButtonProps {
|
|
56
|
+
label?: string;
|
|
57
|
+
iconOnly?: boolean;
|
|
58
|
+
}
|
|
59
|
+
export const ConversationNewButton: ComponentType<ConversationNewButtonProps>;
|
|
60
|
+
export interface ConversationStopButtonProps {
|
|
61
|
+
label?: string;
|
|
62
|
+
}
|
|
63
|
+
export const ConversationStopButton: ComponentType<ConversationStopButtonProps>;
|
|
64
|
+
export interface ConversationStatusProps {
|
|
65
|
+
|
|
66
|
+
}
|
|
67
|
+
export const ConversationStatus: ComponentType<ConversationStatusProps>;
|
|
11
68
|
export interface NativeDOMProps {
|
|
12
69
|
label: string;
|
|
13
70
|
styles?: string;
|
|
@@ -31,6 +88,10 @@ export interface StackProps {
|
|
|
31
88
|
}
|
|
32
89
|
export const Stack: ComponentType<StackProps>;
|
|
33
90
|
export interface SplitLayoutProps {
|
|
91
|
+
resizable?: boolean;
|
|
92
|
+
fillHeight?: boolean;
|
|
93
|
+
asideHidden?: boolean;
|
|
94
|
+
persistenceKey?: string;
|
|
34
95
|
children?: ReactNode;
|
|
35
96
|
}
|
|
36
97
|
export const SplitLayout: ComponentType<SplitLayoutProps> & { Main: typeof SplitLayoutMain; Aside: typeof SplitLayoutAside; Actions: typeof SplitLayoutActions };
|
|
@@ -339,5 +400,6 @@ export interface WidgetDecorationProps {
|
|
|
339
400
|
children: ReactNode;
|
|
340
401
|
}
|
|
341
402
|
export const WidgetDecoration: ComponentType<WidgetDecorationProps>;
|
|
403
|
+
export type { ConversationCreatedEvent, TurnStartedEvent, TurnFinishedEvent, ToolCallEvent, ConversationErrorEvent } from "./conversation.js";
|
|
342
404
|
export const Typography: { Title: typeof TypographyTitle; Body: typeof TypographyBody; Caption: typeof TypographyCaption };
|
|
343
405
|
export const Widget: { TextWidget: typeof WidgetTextWidget; Title: typeof WidgetTitle; Text: { Primary: typeof WidgetTextPrimary; Secondary: typeof WidgetTextSecondary }; Loading: typeof WidgetLoading; Decoration: typeof WidgetDecoration };
|
package/src/ui/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// 此文件由 scripts/generate-components.mjs 生成,请修改产品能力声明。
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import { createUiComponents } from "./factory.js";
|
|
4
|
-
export const { NativeDOM, Icon, Stack, SplitLayout, SplitLayoutMain, SplitLayoutAside, SplitLayoutActions, Section, Banner, Badge, LoadingState, Skeleton, Card, Grid, EmptyState, ZhikeLink, Button, SearchInput, FilterSelect, Switch, LookupCell, Tabs, TabsList, TabsTrigger, TabsContent, Table, TableHeader, TableBody, TableRow, TableCell, Avatar, DescriptionList, DescriptionListItem, DescriptionListMenu, DescriptionListMenuItem, Divider, Chart, DashboardSurface, DashboardLayout, DashboardPanel, MetricReadout, AnalysisView, Json, Link, StatusBadge, TextBlock, TypographyTitle, TypographyBody, TypographyCaption, TableHeaderCell, WidgetTextWidget, WidgetTitle, WidgetTextPrimary, WidgetTextSecondary, WidgetLoading, WidgetDecoration, Typography, Widget } = createUiComponents(React);
|
|
4
|
+
export const { Conversation, ConversationRoot, ConversationMessages, ConversationComposer, ConversationHistory, ConversationNewButton, ConversationStopButton, ConversationStatus, NativeDOM, Icon, Stack, SplitLayout, SplitLayoutMain, SplitLayoutAside, SplitLayoutActions, Section, Banner, Badge, LoadingState, Skeleton, Card, Grid, EmptyState, ZhikeLink, Button, SearchInput, FilterSelect, Switch, LookupCell, Tabs, TabsList, TabsTrigger, TabsContent, Table, TableHeader, TableBody, TableRow, TableCell, Avatar, DescriptionList, DescriptionListItem, DescriptionListMenu, DescriptionListMenuItem, Divider, Chart, DashboardSurface, DashboardLayout, DashboardPanel, MetricReadout, AnalysisView, Json, Link, StatusBadge, TextBlock, TypographyTitle, TypographyBody, TypographyCaption, TableHeaderCell, WidgetTextWidget, WidgetTitle, WidgetTextPrimary, WidgetTextSecondary, WidgetLoading, WidgetDecoration, Typography, Widget } = createUiComponents(React);
|