Sync third-party and MCP marketplace plugins

Constraint: Public skills are published only by explicit administrator action unless they are tracked third-party market sources.
Confidence: high
Scope-risk: narrow
Directive: Keep private/internal skills out of the public marketplace and preserve normal incremental market Git history.
Tested: Marketplace validation passed.
This commit is contained in:
KeyInfo Bot committed 2026-10-04 00:01:55 +08:00
1 parent e9b0e0c8fe
commit 03caf59d49
152 files changed
+14463 -252

No files matched your search

@@ -1,6 +1,6 @@
{
"name": "caveman",
"version": "3.0.0",
"version": "3.1.0",
"description": "Caveman 是面向 Codex 的精简表达、代码工作流和上下文压缩 skill 集合。",
"author": {
"name": "Julius Brussee",
@@ -2,8 +2,8 @@
"sourceId": "caveman",
"repo": "https://github.com/JuliusBrussee/caveman.git",
"ref": "main",
"commit": "b39c90862855ad2f0813ce775b8bf07a9d6d2a50",
"commit": "aeb45e2f787c0757a8af383a291a280cb6aeb4c1",
"adapter": "codex-plugin",
"sourcePath": "plugins/caveman",
"syncedAt": "2026-10-02T16:00:00Z"
"syncedAt": "2026-10-03T16:00:00Z"
}
@@ -8,7 +8,7 @@ description: >
cross-file refactors.
---
Caveman-ultra. Drop articles/filler. Code/paths exact, backticked. No narration.
Ultracave voice. Drop articles/filler. Code/paths exact, backticked. Tool runs: one status line in, one out; nothing between routine calls.
## Scope
@@ -8,7 +8,7 @@ description: >
model: haiku
---
Caveman-ultra. Drop articles/filler/hedging. Code/symbols/paths exact, backticked. Lead with answer.
Ultracave voice. Drop articles/filler/hedging. Code/symbols/paths exact, backticked. Lead with answer. Tool runs: one status line in, one out; nothing between routine calls.
## Job
@@ -8,7 +8,7 @@ description: >
model: haiku
---
Caveman-ultra. Findings only. No "looks good", no "I'd suggest", no preamble.
Ultracave voice. Findings only. No "looks good", no "I'd suggest", no preamble. Tool runs: one status line in, one out; nothing between routine calls.
## Severity
@@ -6,7 +6,7 @@
"hooks": [
{
"type": "command",
"command": "echo 'CAVEMAN MODE ACTIVE. Rules: Drop articles/filler/pleasantries/hedging. Fragments OK. Short synonyms. Pattern: [thing] [action] [reason]. [next step]. Not: Sure! I would be happy to help you with that. Yes: Bug in auth middleware. Fix: Code/commits/security: write normal. User says stop caveman or normal mode to deactivate.'",
"command": "node \"$(git rev-parse --show-toplevel)/.codex/codex-sessionstart.js\"",
"timeout": 5,
"statusMessage": "Loading caveman mode"
}
@@ -3,7 +3,7 @@ name: cavecrew
description: "判断何时使用压缩输出的调查、编辑或评审子 Agent,以降低长会话上下文消耗。"
---
Cavecrew = three subagent presets that emit caveman output. Same job as Anthropic defaults (`Explore`, edit-style agents, reviewer); difference is the tool-result they return is compressed, so main context shrinks per delegation.
Cavecrew = three subagent presets that answer in ultracave voice (tool runs: one status line in, one out; nothing between routine calls). Same job as Anthropic defaults (`Explore`, edit-style agents, reviewer); difference is the tool-result they return is compressed, so main context shrinks per delegation.
## When to use cavecrew vs alternatives
@@ -12,9 +12,9 @@ Cavecrew = three subagent presets that emit caveman output. Same job as Anthropi
| "Where is X defined / what calls Y / list uses of Z" | `cavecrew-investigator` |
| Same but you also want suggestions/architecture commentary | `Explore` (vanilla) |
| Surgical edit, ≤2 files, scope obvious | `cavecrew-builder` |
| New feature / 3+ files / cross-cutting refactor | Main thread or `feature-dev:code-architect` |
| New feature / 3+ files / cross-cutting refactor | Main thread, or `feature-dev:code-architect` if installed |
| Review diff, branch, or file for bugs | `cavecrew-reviewer` |
| Deep code review with rationale + alternatives | `Code Reviewer` (vanilla) |
| Deep code review with rationale + alternatives | `Code Reviewer` (vanilla) if installed, else main thread |
| One-line answer you already know | Main thread, no subagent |
Rule of thumb: **if you'd want the subagent's output in 1/3 the tokens, pick cavecrew. If you'd want prose, pick vanilla.**
@@ -66,7 +66,7 @@ Skip investigator. Hand exact path:line to `cavecrew-builder` directly.
- Don't use `cavecrew-builder` when you don't already know the file. Spawn investigator first or main thread will eat tokens passing context.
- Don't chain `cavecrew-investigator → cavecrew-builder` for a 5-file refactor. Builder will return `too-big.` and you'll have wasted a turn.
- Don't ask `cavecrew-reviewer` for "general feedback" — it returns findings only, no architecture opinions. Use `Code Reviewer` for that.
- Don't ask `cavecrew-reviewer` for "general feedback" — it returns findings only, no architecture opinions. Use `Code Reviewer` for that when installed.
- Don't expect prose. Cavecrew output is structured, sometimes terse to the point of cryptic. If a human will read it directly, paraphrase.
## Auto-clarity (inherited)
@@ -362,6 +362,40 @@ from .validate import validate
MAX_RETRIES = 2
# Output ceiling for one SDK call: the max output of the default model
# (claude-sonnet-4-5). A body that needs more is refused in call_claude(),
# never written back truncated.
MAX_OUTPUT_TOKENS = 64000
def resolve_max_output_tokens() -> int:
"""Output ceiling for one SDK call, overridable per model.
The default tracks the max output of the default model. CAVEMAN_MODEL lets
a user pin a model whose ceiling is lower (claude-opus-4-0 tops out at
32K), and asking for more output than the model allows is a 400 from the
API — an opaque failure in place of the truncation this cap exists to
prevent. CAVEMAN_MAX_OUTPUT_TOKENS lets that user lower the ask to match.
A malformed value raises rather than silently falling back: an override
that is quietly ignored looks like the cap was raised when it was not, and
the symptom is the same truncation, one layer further from the cause.
"""
raw = os.environ.get("CAVEMAN_MAX_OUTPUT_TOKENS", "").strip()
if not raw:
return MAX_OUTPUT_TOKENS
try:
value = int(raw)
except ValueError:
raise RuntimeError(
f"CAVEMAN_MAX_OUTPUT_TOKENS must be a positive integer, got {raw!r}."
) from None
if value < 1:
raise RuntimeError(
f"CAVEMAN_MAX_OUTPUT_TOKENS must be a positive integer, got {raw!r}."
)
return value
def _is_smaller_than_body(candidate_body: str, body: str) -> bool:
"""True when `candidate_body` actually compresses `body`.
@@ -415,12 +449,25 @@ def call_claude(prompt: str) -> str:
try:
import anthropic
max_output_tokens = resolve_max_output_tokens()
client = anthropic.Anthropic(api_key=api_key, timeout=CLAUDE_CALL_TIMEOUT_SECONDS)
msg = client.messages.create(
# Streaming, not create(): a large compression needs far more than
# the old 8192-token cap, and tokens that arrive as they are
# generated keep a long call from tripping the request timeout.
with client.messages.stream(
model=os.environ.get("CAVEMAN_MODEL", "claude-sonnet-4-5"),
max_tokens=8192,
max_tokens=max_output_tokens,
messages=[{"role": "user", "content": prompt}],
)
) as stream:
msg = stream.get_final_message()
# At the cap the tail was never generated. validate() and the fix
# prompt cannot recover it, so fail now instead of paying for
# retries that end by restoring the original anyway.
if msg.stop_reason == "max_tokens":
raise RuntimeError(
f"Claude output hit the {max_output_tokens}-token cap, so the result is incomplete. "
"Split the file into smaller parts and compress each one."
)
# Tool-heavy models can put a tool_use or thinking block first; take
# the first text block instead of trusting content[0].
text = next((block.text for block in msg.content if getattr(block, "type", None) == "text"), "")
@@ -263,7 +263,19 @@ def extract_inline_codes(text):
"" if FENCE_MARKER_LINE_REGEX.match(line) else line
for line in text_without_fences.split("\n")
)
return re.findall(r"`([^`]+)`", text_without_fences)
# Run-aware pairing (CommonMark): a span opens with a backtick run and
# closes with an equal-length run. A mid-line ``` in prose ("inside a
# ```diff fence") has no equal closer, so it matches nothing — instead of
# its trailing backtick shifting the pairing of every following span.
# The opener is the WHOLE run (`(?!`)` after it), so a lone ``` can never
# shrink to a single backtick and pair with the next span. The content may
# hold a run of a different length (``a`b``), so it is "anything, lazily"
# up to the first equal run, not "anything but a backtick"; DOTALL keeps
# hard-wrapped spans in the comparison set.
return [
m.group(2)
for m in re.finditer(r"(?<!`)(`+)(?!`)(.+?)(?<!`)\1(?!`)", text_without_fences, re.DOTALL)
]
# ---------- Validators ----------
@@ -3,85 +3,83 @@ name: caveman
description: "让 Codex 使用更短、更直接的表达,同时保留代码、命令、错误和技术细节。"
---
# caveman
Respond terse like smart caveman. All technical substance stay. Only fluff die.
Caveman is a voice, not broken grammar. Reader pays per token and reads in a terminal. Every word earns its place. Every fact survives.
## Persistence
Default style for this whole session, every response, until user say "stop caveman" or "normal mode". Keep terse on long sessions no filler drift.
Every response, whole session, until user says "stop caveman" or "normal mode". Unsure if still on? It is. Confirm the switch-off in one line.
Default: **full**. Switch: `/caveman lite|full|ultra|wenyan-lite|wenyan-full|wenyan-ultra|off`.
`/caveman ultra` and `/caveman wenyan` are aliases: follow the `ultracave` or `megacave` skill instead of this one. `/caveman status` reports the mode and changes nothing. Relay the hook's `Caveman mode: <mode>` value when present, otherwise `Caveman mode: unknown`. Never infer a mode from the configured default.
## Why
1. Every output token is billed and read. Filler costs twice.
2. Code, commands, paths, numbers, errors are the payload. One changed character breaks them.
3. Ceremony is expensive, grammar is cheap. "Sure, I'd be happy to help" is ten tokens. "the" is one.
4. A dropped negation costs more than every token saved. Clarity beats compression.
## Rules
Drop: articles (a/an/the), filler (just/really/basically/actually/simply), pleasantries (sure/certainly/of course/happy to), hedging. Fragments OK. Short synonyms (big not extensive, fix not "implement a solution for"). No tool-call narration, no decorative tables/emoji, no dumping long raw error logs unless asked quote shortest decisive line. Standard well-known tech acronyms OK (DB/API/HTTP); never invent new abbreviations (cfg/impl/req/res/fn) tokenizer split them same as full word: zero token saved, reader still decode. Full word cheaper AND clearer. No causal arrows (→) either own token, save nothing. Technical terms exact. Code blocks unchanged. Errors quoted exact.
### 1. Answer first
Never drop not/never/no/only/except flip meaning worse than any token saved. Numbers, units exact.
Answer, then reason, then next step. Pattern: `[thing] [action] [reason]. [next step].`
Never ADD word to sound caveman. Compression only style never grow output. No inserted pronoun or copula to fake broken grammar: "when it not" cost one token more than "when not" and say same thing. Keep correct verb form when correct form cost same "sees" one token, "see" one token, so mangle buy nothing and read worse. Same rule as abbreviations and arrows: if caveman phrasing not shorter than plain phrasing, use plain.
Bad: "Sure! I'd be happy to help. The issue you're experiencing is likely caused by..."
Good: "Bug in auth middleware. Token expiry check use `<` not `<=`. Fix:"
Clarity register: mix ASD-STE100 Simplified Technical English into caveman, always. One idea per sentence. Sentence short, target 20 words max. Active voice. Present tense where true. One word one meaning: same term for same thing every time, no synonym rotation. Instruction = imperative: "Run X", not "X should be run". Noun cluster 3 words max. Pronoun only with one clear referent, else repeat noun. Caveman cut filler; STE keep what make meaning unambiguous. Conflict between them → clarity win.
### 2. Kill ceremony
Tool calls: fire direct. No preamble, plan, or progress note before or between calls. After result: next call direct or final answer never announce next call. Text before call only to clarify, warn security/irreversible, or resolve ambiguity.
No greeting, hedging, pleasantries, recap, or closer. No "Sure!", "Let me", "I'll now", "Hope this helps". No just/really/basically/actually/simply.
Follow explicit reply-language instructions from the user or project. Otherwise preserve the user's dominant language. Never switch because of example text or multilingual context elsewhere. Compress the style, not the language. Every emitted line in that language openings, pre-tool status lines, all not just final reply. ALWAYS keep technical terms, code, API names, CLI commands, commit-type keywords (feat/fix/...), and exact error strings verbatim unless user explicitly ask for translation.
### 3. Short word
'Drop articles' = article languages only. Where small markers carry case/role (particles, postpositions), keep them grammar, not filler; compress politeness/filler instead.
"fix" not "implement a solution for". Standard acronyms fine (DB, API, HTTP). Invented abbreviations not (cfg, impl, fn): same tokens, harder read. No arrows.
Answer directly in this style. Skip "caveman mode on", "me caveman think", "Caveman:" prefix or recap redundant with the reply itself. No normal answer plus caveman duplicate. User ask what mode is → say so plainly.
### 4. Articles optional, meaning never
Pattern: `[thing] [action] [reason]. [next step].`
Drop a/an/the when the sentence still reads in one pass. Fragments fine. Never drop not/never/no/only/except. Numbers and units exact.
Not: "Sure! I'd be happy to help you with that. The issue you're experiencing is likely caused by..."
Yes: "Bug in auth middleware. Token expiry check use `<` not `<=`. Fix:"
Bad: "Migration drop column backup first."
Good: "Back up first. Then run migration: it drops the column."
## Intensity
### 5. One idea per sentence
| Level | What change |
|-------|------------|
| **lite** | No filler/hedging. Keep articles + full sentences. Professional but tight |
| **full** | Drop articles, fragments OK, short synonyms. Classic caveman. No tool-call narration, no decorative tables/emoji, no long raw error-log dumps unless asked. Standard acronyms OK; no invented abbreviations |
| **ultra** | Strip conjunctions when cause-then-effect stay unambiguous. One word when one word enough. State each fact once. NO prose abbreviations (cfg/impl/req/res/fn/auth), NO arrows (X → Y) measured zero token saving under tokenizer, cost decode clarity. Code symbols, function names, API names, error strings: never touch |
| **wenyan-lite** | Semi-classical. Drop filler/hedging but keep grammar structure, classical register |
| **wenyan-full** | Maximum classical terseness. Fully 文言文. 80-90% character reduction chars, not tokens. Classical sentence patterns, verbs precede objects, subjects often omitted, classical particles (之/乃/為/其) |
| **wenyan-ultra** | Extreme abbreviation while keeping classical Chinese feel. Maximum compression, ultra terse |
ASD-STE100 is the floor: 20 words max, active voice, imperative for instructions, one term per thing, pronoun only with an obvious referent. Compression and clarity conflict? Clarity wins.
Example "Why React component re-render?"
- lite: "Your component re-renders because you create a new object reference each render. Wrap it in `useMemo`."
- full: "New object ref each render. Inline object prop = new ref = re-render. Wrap in `useMemo`."
- ultra: "Inline obj prop, new ref, re-render. `useMemo`."
- wenyan-lite: "組件頻重繪,以每繪新生對象參照故。以 useMemo 包之。"
- wenyan-full: "每繪新生對象參照,故重繪;以 useMemo 包之則免。"
- wenyan-ultra: "新參照則重繪。useMemo 包之。"
### 6. Payload verbatim
Example "Explain database connection pooling."
- lite: "Connection pooling reuses open connections instead of creating new ones per request. Avoids repeated handshake overhead."
- full: "Pool reuse open DB connections. No new connection per request. Skip handshake overhead."
- ultra: "Pool reuse open DB connections. No per-request handshake."
- wenyan-full: "池蓄已開之連,不逐請而新開,省握手之費。"
- wenyan-ultra: "池蓄連,免逐請新開,省握手。"
Code blocks unchanged. Commands, paths, API names exact. Errors quoted exact, shortest decisive line only.
Classical chars = wenyan modes only. Never swap a word to a classical char to shrink at non-wenyan levels.
### 7. Tool runs: bounded status
## Auto-Clarity
No text between routine calls. One line before a multi-step run, one line per phase change, one line with the result at the end. Otherwise text before a call only to clarify, warn, or disambiguate.
Drop caveman when:
- Security warnings
- Irreversible action confirmations
- Multi-step sequences where fragment order or omitted conjunctions risk misread
- Compression itself creates technical ambiguity (e.g., `"migrate table drop column backup first"` order unclear without articles/conjunctions)
- User asks to clarify or repeats question
### 8. User's language
Resume caveman after clear part done.
Compress the style, not the language. An explicit reply-language instruction wins. Never switch because of quoted text. Technical terms and errors stay verbatim. Particles and case markers are grammar, not filler.
Example shows FORMAT only write warning in session language, not example's.
### 9. Never perform caveman
Example destructive op:
> **Warning:** This will permanently delete all rows in the `users` table and cannot be undone.
> ```sql
> DROP TABLE users;
> ```
> Caveman resume. Verify backup exist first.
No "caveman mode on", no "me think", no "Caveman:" prefix, no normal answer plus caveman copy. No decorative tables or emoji. Never add a word to sound caveman. Caveman phrasing not shorter than plain? Use plain.
## Boundaries
## When to break the rules
Persisted outside chat: write normal prose code, comments, commits, docs, issue/PR/MR/defect/ticket/bug-report text, memory files, third-party messages (/caveman-compress exempt). "Open a defect" or "file a bug" mean the same as "open issue": body go to other humans, so body normal English. "stop caveman" or "normal mode": revert. Level persist until changed or session end.
Plain prose, then resume:
1. Security warning.
2. Irreversible action. Confirm in full sentences first.
3. Step order a fragment could scramble.
4. User confused or repeats the question.
5. Anything persisted outside chat: code, comments, commits, docs, issues, PRs, tickets, memory files, third-party messages. `/caveman-compress` exempt.
6. Harness asks for a status line or confirmation. Give it. Harness decides *when* you speak, caveman decides *how*.
## Pre-send check
1. First sentence announces what you will do? Delete.
2. Last sentence recaps or offers help? Delete.
3. Every not/never/no/only present? Every code span, path, number, error verbatim?
4. Any sentence with two readings? Make it a full sentence.
@@ -0,0 +1,63 @@
---
name: megacave
description: >
Caveman in Classical Chinese: 文言文 register, far fewer characters, technical
terms verbatim. Invoke only with /megacave or /caveman wenyan. Stays on until
"stop caveman" or "normal mode".
disable-model-invocation: true
---
# megacave
以文言答。技術之實皆存,唯贅言去之。
Megacave is caveman in Classical Chinese. 文言文: subjects omitted where recoverable, verb before object, particles (之, 乃, 為, 其, 則, 故, 以) instead of connective phrases. Fewer characters on screen. Token savings are small and noisy; never claim them.
## Persistence
Every response, whole session, until "stop caveman" or "normal mode". Unsure? Still on. `/caveman status` reports the mode and changes nothing: relay the hook's `Caveman mode: <mode>` value or say `Caveman mode: unknown`.
## Floor
Never cut or translate: code, commands, paths, API names, error strings, in their original script. Negation (不, 非, 勿, 未, 毋). Numbers and units, Arabic numerals. One term per thing. A clause ambiguous in 文言 becomes 白話.
## Rules
### 1. Classical register
文言, not 白話. Verb before object. Subjects omitted where recoverable.
Bad: "你的組件每次渲染都會重新渲染,因為你每次都創建了新的對象引用。請用 useMemo 包起來。"
Good: "每繪新生對象參照,故重繪;以 `useMemo` 包之則免。"
### 2. Particles carry structure
One particle, one relation.
Bad: "因為連接池會重複使用已經打開的連接,所以不需要每次請求都新建連接,這樣就省去了握手的開銷。"
Good: "池蓄已開之連,不逐請而新開,省握手之費。"
### 3. Each fact once
Good: "新參照則重繪。`useMemo` 包之。"
### 4. Payload in original script
Bad: "以記憶化鉤子包之。"
Good: "以 `useMemo` 包之。"
### 5. Tool runs
One 文言 line in, one out. Nothing between calls unless the harness asks or a security or irreversible step is ahead.
### 6. Never perform
No "文言模式啟", no modern answer plus classical copy. 文言 not shorter than 白話 for a sentence? Use 白話.
## When to break the rules
白話 or the user's language, full sentences, then resume: security warning. Irreversible action, confirm first. Any clause with two readings. User confused. Anything persisted outside chat (code, comments, commits, docs, issues, PRs, tickets, memory, third-party messages; `/caveman-compress` exempt). Harness asks for a status line.
## Pre-send check
Identifiers verbatim, original script? Negations present? Two readings? 白話. Flavor character? Cut.
@@ -0,0 +1,63 @@
---
name: ultracave
description: >
Caveman at maximum compression: fragments, one word when one word is enough,
each fact once. Invoke only with /ultracave or /caveman ultra. Stays on until
"stop caveman" or "normal mode".
disable-model-invocation: true
---
# ultracave
Respond terse like smart caveman. All technical substance stay. Only fluff die. Then cut again.
Ultracave is caveman with the grammar stripped. Payload only.
## Persistence
Every response, whole session, until "stop caveman" or "normal mode". Unsure? Still on. `/caveman status` reports the mode and changes nothing: relay the hook's `Caveman mode: <mode>` value or say `Caveman mode: unknown`.
## Floor
Never cut: code, commands, paths, API names, error strings (verbatim). not/never/no/only/except. Numbers and units. The user's language. One term per thing. No invented abbreviations, no arrows.
## Rules
### 1. Fragments
Drop articles, copulas, connectives when order stays clear.
Bad: "The component re-renders because an inline object prop creates a new reference each render."
Good: "Inline object prop, new ref, re-render. `useMemo`."
### 2. One word when one word is enough
Bad: "Yes, that should work, though you'll want a null check first."
Good: "Yes. Null check first."
### 3. Each fact once
No restating, no summary after a list.
Good: "Pool reuses open DB connections. No per-request handshake."
### 4. Cut conjunctions only when order survives
Bad: "Migrate table drop column backup first."
Good: "Back up first. Then migrate: drops column."
### 5. Tool runs
One line in, one line out. Nothing between calls unless direction changes, confirmation needed, or a security or irreversible step is ahead.
### 6. Never perform
No prefix, no announcement, no mangled verbs for flavor. Fragment not shorter than the sentence? Use the sentence.
## When to break the rules
Plain prose, then resume: security warning. Irreversible action, confirm first. Any fragment with two readings. User confused. Anything persisted outside chat (code, comments, commits, docs, issues, PRs, tickets, memory, third-party messages; `/caveman-compress` exempt). Harness asks for a status line.
## Pre-send check
Two readings? Full sentence. Negations present? Payload verbatim? Flavor word? Cut.
@@ -1,6 +1,6 @@
{
"name": "dingtalk-workspace",
"version": "1.0.62",
"version": "1.0.63",
"description": "通过 dws CLI 操作钉钉消息、文档、表格、日历、待办和知识库的官方 Skill 集合。需要另行安装匹配版本的 dws、登录并取得企业授权;辅助脚本需要 Python 3。",
"author": {
"name": "DingTalk",
@@ -4,6 +4,14 @@ Copyright 2026 Alibaba Group
This product includes software developed at
DingTalk (https://www.dingtalk.com/).
The embedded DingTalk AI Card V0.8 protocol data includes definitions and
descriptions retained or adapted from the A2UI (Agent to UI) Protocol v1.0,
baseline commit f5e945a93da36a5d126228f2ad6fbe68809ef8f7. Those parts
are licensed under Apache-2.0. DingTalk modified the message envelope,
common types, and component/function catalogs; the source distribution's
skills/multi/dingtalk-aicard/references/protocol/NOTICE records the per-file
provenance. This CLI is not published or endorsed by the A2UI project.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
@@ -15,3 +23,86 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
------------------------------------------------------------------------
Unicode 字符数据
internal/card/a2ui/assets.json 中的 XID_Start 与 XID_Continue 字符范围
派生自 Unicode 17.0.0 的 DerivedCoreProperties.txt;数据源版权声明为
© 2025 Unicode®, Inc.。
数据源:https://www.unicode.org/Public/17.0.0/ucd/DerivedCoreProperties.txt
许可原文:https://www.unicode.org/license.txt
以下保留 Unicode 官方版权和许可通知,适用于上述派生字符数据:
UNICODE LICENSE V3
COPYRIGHT AND PERMISSION NOTICE
Copyright © 1991-2026 Unicode, Inc.
NOTICE TO USER: Carefully read the following legal agreement. BY
DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING DATA FILES, AND/OR
SOFTWARE, YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE
TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT
DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE.
Permission is hereby granted, free of charge, to any person obtaining a
copy of data files and any associated documentation (the "Data Files") or
software and any associated documentation (the "Software") to deal in the
Data Files or Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, and/or sell
copies of the Data Files or Software, and to permit persons to whom the
Data Files or Software are furnished to do so, provided that either (a)
this copyright and permission notice appear with all copies of the Data
Files or Software, or (b) this copyright and permission notice appear in
associated Documentation.
THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE
BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES,
OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA
FILES OR SOFTWARE.
Except as contained in this notice, the name of a copyright holder shall
not be used in advertising or otherwise to promote the sale, use or other
dealings in these Data Files or Software without prior written
authorization of the copyright holder.
------------------------------------------------------------------------
regexp2 正则表达式库
本产品包含 github.com/dlclark/regexp2 v1.11.5。
项目:https://github.com/dlclark/regexp2
许可原文:https://github.com/dlclark/regexp2/blob/v1.11.5/LICENSE
以下保留该依赖的版权和许可通知:
The MIT License (MIT)
Copyright (c) Doug Clark
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -1,9 +1,9 @@
{
"sourceId": "dingtalk-workspace",
"repo": "https://github.com/DingTalk-Real-AI/dingtalk-workspace-cli.git",
"ref": "v1.0.62",
"commit": "70323e1486e64b1ca823fa2bd9c48b9b07f88519",
"ref": "v1.0.63",
"commit": "4cd5d05393a8748e89d9265eb9f7ec85745a0331",
"adapter": "skill-collection",
"sourcePath": "skills/multi",
"syncedAt": "2026-09-16T15:59:59Z"
"syncedAt": "2026-10-03T16:00:00Z"
}
@@ -0,0 +1,203 @@
Copyright 2026 Alibaba Group
Apache License
Version 2.0, January 2004
https://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
@@ -0,0 +1,12 @@
DingTalk AI Card Skill V0.8
Copyright 2026 Alibaba Group (Skill-authored material, except where noted)
This Skill is distributed under the Apache License, Version 2.0, in LICENSE.
Its references/protocol/ directory includes definitions and descriptions
retained or adapted from the A2UI 1.0 reference. Keep the protocol's own
LICENSE and NOTICE with that directory; its NOTICE records the pinned
upstream revision, DingTalk modifications, and attribution.
This Skill is maintained by DingTalk. It is not published or endorsed by the
A2UI project. Apache-2.0 grants no trademark rights; references to A2UI
identify the upstream work.
@@ -0,0 +1,143 @@
---
name: dingtalk-aicard
description: >
Create, edit, and validate DingTalk AI Card (A2UI) JSON files offline.
Use for cards built from requirements or images, structural protocol errors,
and named component or function contract lookup through native DWS commands.
Send a card to the current user only when a preview is requested.
metadata:
cli_version: ">=0.2.14"
category: product
requires:
bins:
- dws
cliHelp: "dws aicard --help"
aicardVersion: "V0.8"
protocolVersion: "1.0"
catalogId: https://dingtalk.com/card/a2ui/catalogs/public/catalog.json
---
# Create and validate DingTalk AI Cards V0.8
Turn the user's content and interaction requirements into a maintainable A2UI file. Look up contracts in the bundled DingTalk protocol, check syntax and structure, and identify runtime behavior that remains unverified. Sending and rendering require a delivery tool and a target client.
The DingTalk specification version is **V0.8**, based on the official A2UI **1.0** reference. The message `version` remains `"v1.0"`, and the sending API's `protocolVersion` remains `"1.0"`; neither becomes V0.8.
## Determine content and interactions
Build the card when the available information is sufficient. Ask only when missing information affects factual content, the meaning of a required interaction, or delivery. A file-only request does not need a conversation target. Choose the layout, grouping, and a stable `surfaceId` as appropriate.
- Preserve requested components, information, and interactions; do not drop requirements to fit a pattern.
- Use provided or verified numbers, names, dates, and business URLs. Clearly label demonstration data in a prototype.
- Preserve buttons, tags, and other visual elements requested by the user or shown in a reference image. Do not invent URLs or event names when business behavior is unknown. A static `ButtonGroup` may omit each item's `action` where the protocol permits it; report that its interaction is not connected. Standalone `Button.action` is still required: do not rely on renderer tolerance to omit it. Do not add buttons without a visual or operational need.
## Surface and delivery scenarios
Choose the message boundary for the known delivery route. If the user specified creation or update, use that route directly:
| Scenario | Required messages |
|---|---|
| New card or complete snapshot loaded from an empty state | Send `createSurface`, root `updateDataModel`, then `updateComponents`; set `catalogId` explicitly |
| Host has created an empty Surface | Initialize with `updateDataModel` and `updateComponents`; do not create it again |
| Existing-card update | Reuse the original `surfaceId` and identify the card as required by the host API; send only changes, without replaying `createSurface` or unrelated form defaults |
For a new card, use `createSurface →` root `updateDataModel → updateComponents` and set `catalogId` explicitly. The current DingTalk creation and delivery API requires data initialization, even for a purely static card:
```json
{"version":"v1.0","createSurface":{"surfaceId":"same-as-following-messages","catalogId":"https://dingtalk.com/card/a2ui/catalogs/public/catalog.json"}}
```
```json
{"version":"v1.0","updateDataModel":{"surfaceId":"same-as-create-message","path":"/","value":{}}}
```
Replace the empty object with real initial business data when needed. This is a DingTalk delivery requirement for complete creation, not a universal A2UI message-order rule. It does not require every string to be bound, `sendDataModel` to be enabled, or all updates to be sent at once. Preflight also accepts protocol-valid inline initialization in `createSurface.dataModel/components`; do not split such an existing file just to match the examples. Send only changed values in an incremental update.
When integrating with an existing host, determine whether its API creates the Surface. The four [protocol examples](references/protocol/examples/README.md) contain creation, data initialization, and component initialization for new cards. For a host-created empty Surface, remove `createSurface` and use the host's `surfaceId`. Removing `createSurface` from a complete file does not turn it into a safe incremental update; construct the actual delta.
## Query and validation environment
This edition uses native DWS commands for lookup, validation, and preview; it does not need Python or the standalone Skill's scripts. On first use or an unrecognized command, run `dws aicard --help` to confirm that the binary provides `explain`, `lint`, and `preview`. Copying Skill files does not install commands in an older binary.
`explain` and `lint` use the embedded protocol offline and need no Profile. Check `dws aicard explain --help` before a batch or compact query; query names individually if unsupported. Follow the current command help. Use `dws aicard explain` for lookup, not `dws aicard lint --explain`. Inspect the exit code, `ok`, and `outcome`: successful content is in `data`, failures in `error`, and structural diagnostics in `error.details`.
If a command is missing, use a DWS build that includes aicard. Preserve the actual error if embedded protocol loading fails and inspect the DWS installation. When temporarily unavailable, the indexes can still guide a draft; state that DWS validation was not run. Do not present Python or manual checks as a DWS validation result.
## Read on demand
Choose components from the content, then look up their fields. Use the host's default background unless the content needs a local treatment. Short content does not require a title, metric, or button. Group content as needed and implement explicit interaction requirements.
For image reconstruction, identify visible copy, controls, states, and media regions before querying the needed components. Use structured components for interface text and controls. Photography, posters, and complex illustrations may retain their original image regions. Use a real asset or reliable crop for a brand mark; do not imitate it with an emoji or character. Before delivery, compare key text, numbers, region order, and controls with the image. Do not infer business behavior from the image alone. See [image reconstruction](references/design.md#image-reconstruction).
Read only the relevant section of [design guidance](references/design.md) when layout, color, density, or progress-state advice is needed. Do not load the entire guide, all indexes, or the whole catalog by default.
For a known component, function, or Token name, query its contract directly. If the name is unknown, read only the relevant [component index](references/index/components.md), [function index](references/index/functions.md), or [Token index](references/index/tokens.md):
```bash
dws aicard explain Tabs --format json
dws aicard explain Text Row Column --compact --format json
```
Replace `Tabs` with the component, function, common type, or Token name. In a deduplicated batch result, `$contractRef` points to the corresponding `definitions` entry. These are lookup results, not A2UI fields. Use a normal query when fields need to be expanded directly. A query returns one definition's fields and example without loading the entire catalog. It includes essential nested structures and event-specific slots. If a function's arguments are missing, query that function by name rather than recursively loading every function.
Read one component composition pattern when it fits the content; consult only the needed parts of another pattern for mixed content. Compositions are optional blocks, not complete-card templates. The user's requirements and current protocol determine the final layout and fields.
If the card has editable inputs, also consult [form](references/patterns/form.md) for field titles, bindings, and submission behavior, even when another pattern describes the overall card.
| Current task | Reference |
|---|---|
| Short result, alert, or status reminder | [notification](references/patterns/notification.md) |
| Object facts and actions: approval, schedule, task, or order | [detail](references/patterns/detail.md) |
| Illustrated content, recommendations, media, or attachments | [content](references/patterns/content.md) |
| Metrics, records, charts, or analytical conclusions | [report](references/patterns/report.md) |
| Inputs, settings, ratings, or feedback submission | [form](references/patterns/form.md) |
| Agent generation, execution, and result updates | [progress](references/patterns/progress.md) |
Simple content can use known components directly. In the pattern notation, `+` combines items, `>` shows a container and its contents, and `/` lists alternatives; none is sendable JSON. Fill actual reference fields from the contract. Reconstruct an image from what is visible, without adding unsupported content or actions because a pattern suggests them. General visual guidance is in `references/design.md`.
The `source` field in a lookup result points to a protocol file and JSON Pointer. It also marks omitted deep structures or long descriptions; inspect that location rather than reloading the catalog. The [example index](references/protocol/examples/README.md) provides complete new-card form, host-action, agent-progress, and report scenarios. Read one that matches the task. Adapt its messages for a host-created Surface or existing-card update using the delivery scenarios above. Do not guess unread fields; confirm them in the protocol or a contract query.
## Construction constraints
- Use `references/protocol/` as the contract for A2UI messages, common types, and DingTalk components, expressions, operators, host actions, and visual Tokens. An identically named official component or function is not necessarily identical to this package's definition.
- Write an ordered JSON message array. A complete component tree has root `id` `root`; keep `surfaceId` stable within one card. Include `createSurface` according to the delivery scenario.
- Match a binding's initial-value type to its literal counterpart. For example, `DynamicNumber` uses a JSON number and `ChoicePicker.value` uses an array of strings. A dynamic list's `path` points to an array; templates may use relative paths and `@index`.
- Follow each function contract for placement, arguments, return type, and host `catalogId`. Select colors, font sizes, and icons from their Token definitions.
- Replace `REPLACE_*` markers in prototypes or existing files before delivery. Do not describe unconnected events, inaccessible resources, or unverified client behavior as implemented.
## Validate before delivery
Validate this file:
```bash
dws aicard lint --file card.a2ui.json --format json
```
Add `--preflight new-card` for a new card, or `--preflight resources` to check inline resources in a delta or host-created content. Confirm option support with `dws aicard lint --help`; an older binary cannot claim to have run preflight.
Read `data.valid` on success, plus `data.preflight.valid` and diagnostics when preflight is enabled. Warnings do not block. Structural or preflight errors cause a nonzero exit with details in `error.details`; `valid` still refers only to Schema checks. An environment or read failure is not a pass.
Add `--emit` when the sending layer needs an array of message strings. After structural validation, `data.a2uiMessages` contains individually serialized messages. JSON-encode the whole array for the sending parameter; do not hand-write shell escaping. `--fragment` and `--emit` are mutually exclusive. Run `dws aicard lint --self-check --format json` separately to check embedded protocol integrity.
Lint checks JSON syntax and the bundled A2UI protocol structure: Schema constraints on messages, components, functions, and DingTalk extensions, including field names, required fields, types, and enumerations. It does not merge data, execute functions, check reference closure or binding initial values, or grade design. `--fragment` accepts one component, a component array, or one message under the same structural rules as the default message-array input.
Generic lint accepts host-created content, so passing lint alone does not mean a new file can be delivered. Run the preflight appropriate to the delivery scenario; do not hide missing new-card initialization with `--fragment`. `new-card` merges the final component snapshot per Surface and checks the root, duplicate IDs within a message, existence of reachable static child references and template targets, and static cycles. Reusing an ID across update messages is valid. Unreachable components produce warnings only; retain them when they serve a purpose rather than deleting them to silence a warning. Template expansion, binding evaluation, intermediate frames, image decoding, and client support still require runtime verification. `resources` checks resource encoding without requiring a delta to be self-contained.
Use media URLs provided by the user or otherwise verified. Have a program read and encode inline media into the standard resource field, then run resource preflight; do not paste tool logs into Base64. Mark unknown schemes and client SVG support as unverified rather than inventing a protocol allowlist. Follow [image reconstruction](references/design.md#image-reconstruction) when choosing image assets.
Static copy may be literal. Bind values that must update and provide first-frame initial values. `sendDataModel` controls whether the model accompanies an A2A message; it is not a switch that enables bindings. If delivery fails, check the initialization sequence, current sending API, and server receipt. A successful repair of one card does not justify enabling that field or binding every string in every card.
**Fix structural errors and errors from the selected preflight.** Apply design suggestions according to the user and scenario; they are not lint gates. Confirm binding initial values, resource availability, and interaction behavior during authoring and runtime acceptance.
Use a diagnostic's `pointer` to locate and edit the original field, then rerun validation. Do not silently rewrite user data. If several attempts fail, recheck the relevant field contract and diagnostic rather than replacing a requested component or downgrading an interaction.
## Delivery and rendering boundaries
Deliver the file path, its purpose (new card, host-created initialization, or existing-card delta), validation results, and unresolved issues that affect use. `valid: true` means syntax and protocol structure passed. `renderingVerified: false` in the validation report means there is no evidence of client rendering.
The `metrics` object is reserved for output compatibility and is currently empty; do not infer measurements from it.
Local validation does not execute functions, invoke host actions, or simulate a client. Function evaluation and results, remote-resource availability, client-version support, actual layout, and button callbacks need runtime verification. If the user asks for client confirmation, use available delivery and preview capabilities in that environment. Request acceptance or conversation readback alone does not establish successful rendering or interaction.
If the user requests a preview sent to themselves, use `dws aicard preview --file card.a2ui.json`. It really sends a card and requires a complete new-card sequence. `--dry-run` checks the local sending boundary without resolving identity or sending. To send to another person or a group, follow the current `dws chat message send-a2ui-card` contract for target and parameters.
`preview` reports `success` only when the card creation request is explicitly accepted, even if its receipt contains `openTaskId`. Keep that ID in the receipt, but do not pass it to `dws chat message query-send-status`, which is for current-user message sends. `deliveryVerified` and `renderingVerified` remain `false`. Conversation readback is separate evidence; generic card text and a nearby timestamp do not uniquely identify this card. The default sending status is `PROCESSING`. Update or finish through `dws chat message update-a2ui-card`, locating the original card by `bizId` without replaying creation. Investigate an unknown result before retrying; a receipt is not client acceptance evidence.
@@ -0,0 +1,146 @@
# Design guidance: make a valid card effective
`lint` checks JSON syntax and protocol structure. This guide helps choose information structure, layout, and visual hierarchy. Adapt visual advice to the user; verify the result on a target client. The bundled protocol governs fields, defaults, and enumerations. Use the contract lookup command in the Skill entrypoint for exact definitions.
## Global design guidance
1. **Use the host background by default.** Do not set a background on the outermost card unless the content requires it. Local content areas may use backgrounds to establish hierarchy.
2. **Show generation state when relevant.** For an Agent that is generating or executing, a `Markdown` component may prefix its `content` with `[AIGenerating]`, for example `[AIGenerating]Running a command…`. This is a DingTalk host convention for an animated GIF, subject to target-client support. Remove the marker and update the copy on completion, failure, or cancellation.
3. **Group execution details.** Use `CollapsiblePanel` with `variant: "reasoning"` for an Agent generation or execution process. Choose its expanded state and internal layout from the content.
## 1. What each check establishes
| Layer | Checks | Evidence |
|---|---|---|
| Tools | Lint checks protocol structure; new-card preflight also checks initialization, reachable references in the final snapshot, static cycles, and resource encoding | Run checks for the delivery scenario. Fix errors at their locations; decide whether an unreferenced-component warning matters for this card |
| Author review | Preserve user information, operations, and visual requirements; provide appropriate first-frame binding values; make priority, grouping, and density clear | Compare each request with its component or action and the host's existing state. Visual and content completeness are not lint diagnostics |
| Runtime acceptance | Resource loading, function evaluation, delivery, actual layout, interactions, and state writeback | Verify in the target host. Report request acceptance, conversation readback, and client rendering separately |
Passing structural checks does not establish the other two layers. Explain unsupported behavior or missing runtime evidence at delivery. Ensure that every requested piece of information, visual element, and action has an appropriate representation. Do not invent events or URLs to fill a checklist.
## Image reconstruction
**Identify regions and purpose before generating.** Record visible copy, numbers, region order, buttons, and states; distinguish interface layout from image assets before looking up components. This analysis guides implementation and need not become another file or exposed reasoning. Ask only about critical facts or interactions that cannot be determined. Do not guess unreadable content.
| Content in the image | Implementation |
|---|---|
| Interface copy, data, buttons, forms, lists | Use structured components and preserve content and state. Static reproduction may use literals; changing business values need bindings and initial values |
| Photography, marketing posters, complex illustrations | Use the original asset or a reliable crop in `Image`; preserve its subject and essential text. Poster text need not be forcibly decomposed into components |
| Brand marks and specific document or product icons | Use a real asset or a crop of the reference. Do not impersonate them with emoji, ordinary characters, or vaguely similar icons. If the asset is unavailable, report the gap and, when appropriate, use an explicit text description |
| Generic action or status icons | Prefer a registered `Icon` with matching meaning. Otherwise use a supplied asset or text; do not invent an Icon name |
Crop media to the media region itself. Do not bake surrounding interface copy or interactive controls into the image; text and marks that belong to a poster may remain inside it. Do not substitute a screenshot of the entire interface for components, or destroy poster artwork just to make it structural. Images need a working URL or correctly encoded inline data, not a placeholder path.
**Implement only known interactions.** For appearance-only reproduction, use a valid static representation and state that behavior is not connected. A pictured button does not reveal its event or URL. Implement bindings and actions when the user explicitly requires a form, data update, or host action. Extra business data and behavior require user input or a verifiable source.
**Compare before delivery.** Check key copy, numbers, dates, prices, region order, buttons, tags, and media against the source. Look for invented business facts or substituted brand assets. The component count need not equal the number of visual elements; preserve meaning and use. Report unreadable, unavailable, or unsupported content. Neither this comparison nor protocol preflight proves client visual fidelity.
## 2. Information roles and blocks
First decide what the user most needs to know or do, then arrange conclusions, evidence, details, and actions. A report may lead with the conclusion; an execution card may lead with progress. Short content needs no extra blocks. These combinations are optional layout notation, not a fixed order or required structure.
| Role | Purpose | Components | Layout notation |
|---|---|---|---|
| `header` | Title, source, and status | Row + Text + Tag | `Row(align=center, gap=8) > Text(bold, weight=1) + Tag` |
| `hero` | Key cover or person image | Image | `Image(variant=header, fit=cover, cornerRadius=10)` |
| `facts` | Label-value facts | Column + Row + Text | Each row: `Row(align=start, gap=8) > Text(label) + Text(value, weight=1)`; see [key-value rows](#key-value-rows) |
| `summary` | Conclusion-first prose | Markdown | Literal or bound content, for example `/content/body` |
| `metrics` | A few important measures | Row + Column + Text | `Row(gap=8) > Column(weight=1, padding=12) > Text(value, bold) + Text(label, caption)` |
| `data` | Comparison, trend, or composition | Table / Chart | Use Table for exact records and a suitable Chart for graphical data; look up values in the contract. See the [report example](protocol/examples/data-report.json) |
| `list` | Repeated entries | Column + Card + Text | — |
| `timeline` | Time- or stage-ordered progress | Column + Row + Text + Tag | — |
| `attachments` | File results | Divider + Text + File | `File(fileName, url, description, onPreview)` |
| `form` | Text and choice inputs | TextField + ChoicePicker | Group and bind business fields, such as `/form/*`; submit-button `context` refers to the relevant paths. See [form composition](patterns/form.md) |
| `actions` | Main and optional secondary action | Divider + Row + Button + Text | `Row(align=center, gap=8) > Button(default) + Button(primary)`; each Button's `child` references a Text |
| `details` | Infrequent supporting information | CollapsiblePanel + Markdown + Link | `CollapsiblePanel(variant=indented, defaultExpanded=false, maxHeight=240) > Column > Markdown + Link(openUrl)` |
| `progress` | Generation or execution stage | CollapsiblePanel + Markdown | `CollapsiblePanel(variant=reasoning) > Markdown` |
| `terminal-status` | Stable completed, failed, or cancelled state | Tag + Text + Link | — |
States, icons, illustrated entries, and highlights may support a main block or stand alone when content is simple. They do not each require a top-level section.
| Local combination | Use | Layout or choice |
|---|---|---|
| Compact header | Schedule, task, light reminder | `Card(padding=0) > Column(gap=0) > CardHeader(trailing=Tag) + Column(padding=8, gap=8)` |
| Status | Current stage or risk | Tag + Text |
| Icon | Action, source, or status | Icon or Text.icon; use a registered matching icon, or a supplied image or explanation if none exists. Do not invent a name or default to emoji for a specific icon |
| Illustrated item | Compact image-and-text content | `Row(align=center, gap=12) > Column(weight=1) + Image(variant=smallFeature)` |
| Highlight | Key conclusion or local emphasis | See [local highlights](#local-highlights); this is a design technique, not a protocol field |
Read [composition patterns](patterns/detail.md) from the Skill's task table. Approval, schedules, and tasks share the detail pattern; ongoing generation uses the [progress pattern](patterns/progress.md). For mixed content, select only needed blocks and avoid duplicating headers or actions. Choose one [message example](protocol/examples/README.md); all four are complete new-card messages. Adapt them for host-created Surfaces or updates as described in the [Skill entrypoint](../SKILL.md). The protocol and contract lookup govern fields.
## 3. Host behavior and layout
The bundled protocol governs field capabilities. Visual numbers are starting points, not extra protocol limits.
Ordinary vertical content can use `Column` directly; add a `Card` only when grouping, background, or border serves the content. Omitting root `padding` may still leave host padding and is not the same as setting it to `0`.
Use `Text` or `CardHeader` for ordinary group titles. Reserve Markdown headings for actual document sections; a small field or status label does not need heading hierarchy.
1. `Row.align=stretch` can make containers in a row the same height. Container children and leaf components are handled differently; consult the Row contract for client behavior and integration boundaries.
2. Check long titles, metrics, and multiple columns at the target conversation width. Wrap or reduce adjacent items when space is limited; do not assume identical client widths.
3. `Image.variant=smallFeature` is a starting point for illustrated cards; adjust to the asset and protocol size guidance.
4. Use `CardHeader` for a compact native header when appropriate; build other headers from actual requirements.
5. Usually emphasize one primary action within a visible action area. Assess separate Tabs or states independently, not by counting every Button in the component list. Label actions by what they do, not by phrases such as “click the button below.”
6. Remove empty rows and dividers without information value. Choose truncation, full display, or collapse for long content; do not hide necessary text with `maxLine`.
7. Check media URLs under the host policy; lint does not fetch them. Table pagination is local, so provide the data at once. Paginate, limit rows, or link to details for long tables.
8. Query a component for defaults, platform fallbacks, and conditions under which a field takes effect. The host may apply defaults when fields such as `Image.variant` are omitted.
Keep related content close and separate groups with appropriate space. Set `gap` and `padding` on the containers responsible for layout rather than stacking padding at several levels. Multiples of 2 are a reasonable spacing starting point, adjustable for host defaults, density, and user requirements; they are not validation rules.
### Key-value rows
- Put related facts in one `Column`. Each row can begin with `Row(align=start, gap=8)`; give long values `weight=1` for remaining width.
- Labels and values may both use `body`, with `common_level2_base_color` and `common_level1_base_color` respectively. Consider `caption` labels for compact content.
- Omit `weight` for a naturally sized label; do not write `weight=0`. Labels of different lengths do not guarantee aligned value columns. Stack a long label and value vertically when width is insufficient rather than assuming unsupported fixed columns.
- `Text` displays at most three lines by default. Set sufficient `maxLine` for important long values, or use full text or collapsible details. Do not truncate every value to two lines.
### Local highlights
- Give a key conclusion or risk its own block when needed, for example `Column(padding=12, gap=8) > Text(bold) + Markdown`; add a local background only when useful.
- Emphasize a short label within `Markdown.content`, for example `**Risk:** Only completed tasks are included.`, without wrapping every note in another container.
- Choose background and border for hierarchy; they need not both appear. When both are used, keep them in one semantic color family and select actual values from the [Token index](index/tokens.md).
- `Card.backgroundColorToken` can use a registered `extended_*0_color`; `borderColorToken` can use its matching `extended_*1_color`. `borderWidth` is numeric, for example `0.5`, not a string with units. `*` denotes a family only: send complete registered Token IDs and do not put Token names in hex-color fields.
- Use component defaults when no emphasis is needed. Do not add a colored container for decoration or repeat the same highlighted block in every subsection. A short bold label often suffices.
- Use only supported fields. Simplify a one-sided indent or inline treatment that cannot be expressed accurately. Do not invent a field or pad with spaces; container `padding` affects all sides.
## 4. Color discipline
Prefer registered Tokens or semantic component variants (`Tag.theme`, `CardHeader.theme`). Some fields accept hex colors; consult their contracts. For semantic colors, consider:
| Meaning | `Tag.theme` / `CardHeader.theme` | Text `colorToken` |
|---|---|---|
| Success / accepted | `green` | `common_green1_color` |
| Failure / warning / dangerous action | `red` | `common_red1_color` |
| Pending / reminder | `orange` | `common_orange1_color` |
| Information / neutral | `blue` | — |
| Primary text | — | `common_level1_base_color` |
| Secondary text | — | `common_level2_base_color` |
| Supporting / placeholder text | — | `common_level3_base_color` |
| Divider | — | `common_line_light_color` (`Divider.borderColorToken`) |
Use a Token or theme for one meaning within a card. Express important status in text, not color alone. The host resolves actual colors, so a local block needs sufficient contrast against its background. Prefer `Tag.theme` for capsule states and contract-supported Tokens for container colors. Component defaults are valid too; a card does not need a quota of explicit Tokens. See the full [Token index](index/tokens.md).
Keep ordinary key-value labels neutral; use semantic color for a value only when it conveys status or trend. Three or fewer non-gray semantic colors is a starting point for an ordinary information card, not a limit on charts, brands, or complex states.
## 5. Hierarchy and density
- **One strongest focal point:** use `bold` and `level1` for a title, a normal body, and `caption` with `level2` for explanation, as the content warrants.
- **Top-level grouping:** two to five groups can guide a complex card. A short notice may have one, and complex content may need more.
- **Group with containers:** put related fields in one `Column` or `Card`. Use `Divider` between semantic sections, such as content and actions, not between every row.
- **Contain long content:** use `CollapsiblePanel(defaultExpanded=false)` for details. Offer a “View all” `Link` when a real full-content destination exists.
- **Separate display fallback from business data:** missing information may display “—” or “None yet,” or omit an empty section. Never write display fallback into a form, number, or boolean value. Empty string, unchecked `false`, unselected `[]`, and numeric `0` retain their distinct meanings.
## 6. Revise feedback at the right field
After a user reviews the card, locate the affected fields and check related effects:
| Feedback | Change | Recheck |
|---|---|---|
| Copy or wording | The corresponding `/content/*` value in `updateDataModel`, or `Text.text` / `Markdown.content` | Factual accuracy |
| Color or style | `Tag.theme` / `CardHeader.theme` / `colorToken` | Meaning and contrast |
| Layout | `Row` ↔ `Column`, `align` / `gap` / `weight` / `padding` | Grouping and references |
| Missing information | Add it to the relevant role; initialize its model value when bound | Information and bindings |
| Too dense or too sparse | `gap` / `padding` / `maxLine`, or collapse details in `CollapsiblePanel` | Density at actual width |
| Wrong button | `action.event.name` / `context`, `variant`, `disabled` | Visual and interaction behavior separately |
Rerun lint and deliver the revised file and check results. Send a real card only when requested and supported by an available delivery route.
@@ -0,0 +1,57 @@
# Component index (47 total; 10 common, 37 others)
Choose a component here, then query its fields and minimal example as shown in the Skill entrypoint. Start with common components and inspect other groups only when needed.
Required fields include `id` and `component`. Child references show the field path to child components; `[]` denotes an array item.
| Component | Group | Required | Child references | Purpose |
|---|---|---|---|---|
| `Button` | Common components | action, child, id | child | Runs a connected action; its label belongs in the child component. |
| `Card` | Common components | child, id | child | Single-child card container with padding, background, and rounded corners. |
| `Column` | Common components | children, id | children | Child nodes are stacked from top to bottom. |
| `Divider` | Common components | id | — | Horizontal or vertical separator line. |
| `Icon` | Common components | id, name | — | DingTalk icon set and loading status. |
| `Image` | Common components | id, url | — | Image display with a dark-theme image alternative. |
| `Markdown` | Common components | content, id | — | Markdown headings, lists, code, and quotes. |
| `Row` | Common components | children, id | children | Child nodes are arranged from left to right. |
| `Tag` | Common components | id, text | — | Compact status or category label styled with theme and variant. |
| `Text` | Common components | id, text | — | Text, font size, color, and streaming state. |
| `ButtonGroup` | Composition | buttons, id | — | Groups inline buttons; static prototypes may omit item actions. |
| `CardHeader` | Composition | id, title | trailing | Unified card header with a theme, dynamic title, dark-theme icon, and trailing content. |
| `CollapsiblePanel` | Composition | children, id, title | children | Unified collapsible panel, collapsed by default. |
| `ColumnLayout` | Composition | children, id | children | Responsive columns from one to six. |
| `GridLayout` | Composition | children, id | children | Grid layout supporting static children and data templates. |
| `Link` | Composition | id, text | — | Clickable link text and navigation. |
| `List` | Composition | children, id | children | Arranges components or data templates horizontally or vertically. |
| `Loop` | Composition | children, id | children | Data-driven repeated-rendering container. |
| `ScrollView` | Composition | id | children | A horizontal or vertical scroll container. |
| `Stack` | Composition | child, id | child, overlays.[].child | Z-axis stacking container: A **base layer** determines the size, on which 0~N **overlay… |
| `Tabs` | Composition | id, tabs | tabs.[].child | Tab header and content panel. |
| `CheckBox` | Inputs | id, label, value | — | Boolean selection. |
| `CheckableImageList` | Inputs | id, images, value | — | Selectable layout for one to nine images, cropped to 4:3 with row and column gaps of 12. |
| `CheckboxListMulti` | Inputs | children, id | children | Multi-select list and local state. |
| `ChoicePicker` | Inputs | id, options, value | — | Selects one or more options; variant determines selection mode. |
| `ConversationPicker` | Inputs | id, value | — | Call the DingTalk conversation selector. |
| `DateTimeInput` | Inputs | id, value | — | Date and time picker entry. |
| `ImageUpload` | Inputs | id, value | — | Call DingTalk image upload, fill the upload result back into the `value` binding path, … |
| `InputList` | Inputs | id, value | — | Input list whose rows can be added and removed. |
| `NumberInput` | Inputs | id, value | — | Numeric input entry that opens an input panel and displays the result. |
| `Rating` | Inputs | id, value | — | Star rating. |
| `Slider` | Inputs | id, max, value | — | Numeric slider. |
| `Switch` | Inputs | id | — | Switch state and size. |
| `TextField` | Inputs | id, label | — | Collects text and saves input through a value binding. |
| `UserPicker` | Inputs | id, value | — | Opens the DingTalk contact picker to select users. |
| `AudioPlayer` | Data and media | id, url | — | Audio cover, title, and playback progress. |
| `Avatar` | Data and media | id | — | Avatar image. |
| `AvatarGroup` | Data and media | id, items | — | Avatar stacking and overflow count. |
| `Chart` | Data and media | data, id | — | Shows trends, comparisons, or proportions using contract-defined data. |
| `Countdown` | Data and media | endTime, id | — | Countdown and end event. |
| `ElapsedTime` | Data and media | id | — | Elapsed-time counter. |
| `File` | Data and media | fileName, id, url | — | File artifact. |
| `ImageCarousel` | Data and media | id, items | — | DingTalk image carousel component. |
| `ImageList` | Data and media | id, images | — | Multiple image thumbnails and quantity aggregation. |
| `ProgressBar` | Data and media | id, value | — | Shows completion as a continuous bar or compact blocks. |
| `Table` | Data and media | data, id | — | Shows structured records for row-by-row review with local pagination. |
| `Video` | Data and media | id, url | — | Cover, inline playback, and control bar. |
---
Generated from `references/protocol/` (fingerprint `7005139e5267c69e`). Do not edit this index: protocol changes regenerate it. For exact fields and a minimal example, query a name as shown in the Skill entrypoint; the whole catalog need not enter the model context.
@@ -0,0 +1,49 @@
# Function index (40 total; 7 host actions)
Value functions use `{"call": …, "args": {…}}` and may nest. Host actions require explicit `catalogId: urn:dingtalk:a2ui:host:v1`; the system function `@index` must not carry it. `checks[].condition` requires a boolean-returning function.
| Function | Group | Returns | Required arguments | Host action | Purpose |
|---|---|---|---|---|---|
| `and` | Core functions | boolean | values | | Performs logical AND on a list of boolean values. |
| `email` | Core functions | boolean | value | | Checks that the value is a valid email address. |
| `formatCurrency` | Core functions | string | currency, value | | Formats a number as a currency string. |
| `formatDate` | Core functions | string | format, value | | Formats a timestamp into a string using Unicode TR35 date pattern. |
| `formatNumber` | Core functions | string | value | | Formats a number with grouping and decimal precision. |
| `formatString` | Core functions | string | value | | Uses `${/path}` for data-path interpolation. |
| `length` | Core functions | boolean | value | | Checks string length constraints. |
| `not` | Core functions | boolean | value | | Performs logical NOT on a boolean value. |
| `numeric` | Core functions | boolean | value | | Checks numeric range constraints. |
| `openUrl` | Core functions | void | url | | Opens the specified URL in a browser or handler. |
| `or` | Core functions | boolean | values | | Performs logical OR on a list of boolean values. |
| `pluralize` | Core functions | string | other, value | | Returns a localized string based on CLDR plural category of the count. |
| `regex` | Core functions | boolean | pattern, value | | Checks that the value matches a regular expression string. |
| `required` | Core functions | boolean | value | | Checks that the value is not null, undefined, or empty. |
| `add` | Expressions | number | a, b | | DingTalk extension function. |
| `arrayFind` | Expressions | any | target, value | | DingTalk extension function. |
| `arrayGet` | Expressions | any | index, value | | DingTalk extension function. |
| `cond` | Expressions | any | else, if, then | | DingTalk extension function. |
| `div` | Expressions | number | a, b | | DingTalk extension function. |
| `eq` | Expressions | boolean | a, b | | Tests whether two values are equal. |
| `getLength` | Expressions | number | value | | DingTalk extension function. |
| `gt` | Expressions | boolean | a, b | | DingTalk extension function. |
| `gte` | Expressions | boolean | a, b | | DingTalk extension function. |
| `lt` | Expressions | boolean | a, b | | DingTalk extension function. |
| `lte` | Expressions | boolean | a, b | | DingTalk extension function. |
| `mod` | Expressions | number | a, b | | DingTalk extension function. |
| `mul` | Expressions | number | a, b | | DingTalk extension function. |
| `ne` | Expressions | boolean | a, b | | Tests whether two values are unequal. |
| `objectGet` | Expressions | any | key, value | | Reads an object property by `key`. |
| `sub` | Expressions | number | a, b | | DingTalk extension function. |
| `toDouble` | Expressions | number | value | | DingTalk extension function. |
| `toLong` | Expressions | number | value | | DingTalk extension function. |
| `copyText` | Host actions | void | text | Yes | Copies text. |
| `openChat` | Host actions | void | openConversationId | Yes | Opens a conversation. |
| `previewImages` | Host actions | void | urls | Yes | Previews 1–100 images. |
| `previewVideo` | Host actions | void | url | Yes | Previews a video. |
| `promptText` | Host actions | object | — | Yes | Opens a single-line input panel. |
| `showConfirm` | Host actions | object | message | Yes | Shows a confirmation dialog. |
| `showModal` | Host actions | object | buttons, message | Yes | Shows a dialog with custom buttons. |
| `@index` | System function | number | — | | Returns the 0-based index of the current item when rendering a dynamic list fro… |
---
Generated from `references/protocol/` (fingerprint `7005139e5267c69e`). Do not edit this index: protocol changes regenerate it. For exact fields and a minimal example, query a name as shown in the Skill entrypoint; the whole catalog need not enter the model context.
@@ -0,0 +1,134 @@
# Token index
`colorToken` and `IconName` use protocol enums. Prefer a registered full ID for `sizeToken`; other strings depend on host compatibility or fallback. Follow each field's Schema for container colors. Use a given Token for one meaning within a card.
## Colors: `ColorToken` (57 items)
- **yellow**: `extended_yellow0_color`, `extended_yellow1_color`, `extended_yellow6_color`
- **orange**: `extended_orange0_color`, `extended_orange1_color`, `extended_orange6_color`, `common_orange1_color`
- **red**: `extended_red0_color`, `extended_red1_color`, `extended_red6_color`, `common_red1_color`
- **magenta**: `extended_magenta0_color`, `extended_magenta1_color`, `extended_magenta6_color`
- **purple**: `extended_purple0_color`, `extended_purple1_color`, `extended_purple6_color`
- **deeppurple**: `extended_deeppurple0_color`, `extended_deeppurple1_color`, `extended_deeppurple6_color`
- **blue**: `extended_blue0_color`, `extended_blue1_color`, `extended_blue6_color`
- **darkgreen**: `extended_darkgreen0_color`, `extended_darkgreen1_color`, `extended_darkgreen6_color`
- **green**: `extended_green0_color`, `extended_green1_color`, `extended_green6_color`, `common_green1_color`
- **level**: `common_level1_base_color`, `common_level2_base_color`, `common_level3_base_color`, `common_level4_base_color`
- **stamp**: `common_stamp_color`
- **link**: `common_link_color`
- **bg**: `common_bg_color`
- **fg**: `common_fg_z1_color`
- **line**: `common_line_light_color`, `common_line_hard_color`
- **white**: `common_white1_color`, `common_white2_color`, `common_white3_color`, `common_white4_color`, `common_white5_color`, `common_white6_color`
- **black**: `common_black1_color`, `common_black2_color`, `common_black3_color`, `common_black4_color`, `common_black5_color`, `common_black6_color`
- **theme**: `theme_primary3_color`, `theme_primary2_color`, `theme_primary_hover_color`, `theme_primary1_color`, `theme_primary_press_color`
| Token | Meaning |
|---|---|
| `extended_yellow0_color` | Yellow background color; used for background filling in areas o… |
| `extended_yellow1_color` | Yellow border color; used for outlining areas of this color sch… |
| `extended_yellow6_color` | Yellow text color; used for text emphasis in this color scheme. |
| `extended_orange0_color` | Orange background color; used for area background filling in th… |
| `extended_orange1_color` | Orange border color; used for outlining areas of this color sch… |
| `extended_orange6_color` | Orange text color; used for text emphasis in this color scheme. |
| `extended_red0_color` | Red background color; used for background filling in areas of t… |
| `extended_red1_color` | Red border color; used for the stroke of areas in this color sc… |
| `extended_red6_color` | Red text color; used for emphasizing text in this color scheme. |
| `extended_magenta0_color` | Magenta background color; used for background filling in areas … |
| `extended_magenta1_color` | Magenta border color; used for outlining areas of this color sc… |
| `extended_magenta6_color` | Magenta text color; used for text emphasis in this color scheme. |
| `extended_purple0_color` | Purple background color; used for background filling in areas o… |
| `extended_purple1_color` | Purple border color; used for the stroke of areas in this color… |
| `extended_purple6_color` | Purple text color; used for emphasizing text in this color sche… |
| `extended_deeppurple0_color` | Deep purple background color; used for background filling in ar… |
| `extended_deeppurple1_color` | Deep purple border color; used for outlining areas of this colo… |
| `extended_deeppurple6_color` | Deep purple text color; used for text emphasis in this color sc… |
| `extended_blue0_color` | Blue background color; used for background filling in areas of … |
| `extended_blue1_color` | Blue border color; used for the stroke of areas in this color s… |
| `extended_blue6_color` | Blue text color; used for emphasizing text in this color scheme. |
| `extended_darkgreen0_color` | Dark green background color; used for area background filling i… |
| `extended_darkgreen1_color` | Dark green border color; used for outlining areas of this color… |
| `extended_darkgreen6_color` | Dark green text color; used for text emphasis in this color sch… |
| `extended_green0_color` | Green background color; used for background filling in areas of… |
| `extended_green1_color` | Green border color; used for outlining areas of this color sche… |
| `extended_green6_color` | Green text color; used for text emphasis in this color scheme. |
| `common_level1_base_color` | Primary text and icons; used for titles, body text, and other m… |
| `common_level2_base_color` | Secondary text and icons; used for secondary information and au… |
| `common_level3_base_color` | Tertiary text and icons; used for weaker supplementary informat… |
| `common_level4_base_color` | Text and icon color in a disabled state; only conveys visual st… |
| `common_stamp_color` | Watermark color; used for low-interference watermark content. |
| `common_link_color` | Hyperlink text and highlight border color. |
| `common_bg_color` | Background color of the area; used for the background of a page… |
| `common_fg_z1_color` | Foreground area background color; used for content areas on top… |
| `common_line_light_color` | Weak divider; used for lighter content separation. |
| `common_line_hard_color` | Strong divider line; used for content separation where a cleare… |
| `common_red1_color` | Danger state color; used to convey dangerous or erroneous seman… |
| `common_orange1_color` | Warning state color; used for prompts that require the user's a… |
| `common_green1_color` | Success state color; used for success or completion feedback. |
| `common_white1_color` | White mask; used for white overlay, actual transparency is dete… |
| `common_white2_color` | White mask (designed as 40% level); used for white overlays, ac… |
| `common_white3_color` | White mask (designed as 30% level); used for white overlays, ac… |
| `common_white4_color` | White mask (designed as 20% level); used for white overlays, ac… |
| `common_white5_color` | White mask (designed as 10% level); used for white overlay, act… |
| `common_white6_color` | White mask (designed as 5% level); used for white overlay, actu… |
| `common_black1_color` | Black mask; used for black overlay, actual transparency is dete… |
| `common_black2_color` | Black mask (designed as 40% level); used for black overlays, ac… |
| `common_black3_color` | Black mask (designed as 30% level); used for black overlays, ac… |
| `common_black4_color` | Black mask (designed as 20% level); used for black overlays, ac… |
| `common_black5_color` | Black mask (designed as 10% level); used for black overlays, ac… |
| `common_black6_color` | Black mask (designed as 5% level); used for black overlays, act… |
| `theme_primary3_color` | Theme background color; used for the background of areas that c… |
| `theme_primary2_color` | Light theme color; used for lighter theme color highlights and … |
| `theme_primary_hover_color` | Theme hover color; used for the visual feedback of the theme co… |
| `theme_primary1_color` | Theme primary color; used for main theme emphasis. |
| `theme_primary_press_color` | Theme pressed color; used for the visual feedback of the theme … |
## Font sizes: `SizeToken` (12 items)
| Token | Meaning |
|---|---|
| `common_largetitle_text_style__font_size` | Main title, used as the heading for a page or major content section. |
| `common_supertitle_text_style__font_size` | Extra-large title, used as the main title for a page or module. |
| `common_h1_text_style__font_size` | Level 1 heading, used for card or content area titles. |
| `common_h2_text_style__font_size` | Level 2 heading, used for content-group headings. |
| `common_h3_text_style__font_size` | Level 3 heading, used for smaller-level content titles. |
| `common_h4_text_style__font_size` | Level 4 heading, used for subheadings or supplementary information unde… |
| `common_body_text_style__font_size` | Main text, used for the primary content. |
| `common_action_text_style__font_size` | Action text, used for buttons, links, and other operational copy. |
| `common_description_text_style__font_size` | Auxiliary explanation, used for secondary information and supplementary… |
| `common_footnote_text_style__font_size` | Footnotes, used for sources, notes, image captions, or status tags. |
| `common_tiny_text_style__font_size` | Small text prompts, used as subtle hints in space-constrained scenarios. |
| `common_subhead_text_style__font_size` | Subtitle, used for supplementary information below the title. |
## Icons: `IconName` (24 items)
| Token | Meaning |
|---|---|
| `Search_L_outlined` | Search. |
| `Language_L_outlined` | Language-switch icon. |
| `CodeProgram_L_outlined` | Code. |
| `Picture_L_outlined` | Image. |
| `Folder_L_outlined` | Folder. |
| `Edit_L_outlined` | Edit or pen icon. |
| `ListView_L_outlined` | List View 1. |
| `ManagementBackground_L_outlined` | Admin console icon. |
| `Tool_L_outlined` | Tools. |
| `Delete_L_outlined` | Delete. |
| `SpinLoading_L_outlined` | Loading spinner icon. |
| `UploadOne_L_outlined` | Upload. |
| `DownloadAndSave_L_outlined` | Download and save. |
| `Check_L_outlined` | Check mark. |
| `Copy_L_outlined` | Copy. |
| `Close_L_outlined` | Close, cross. |
| `More_L_outlined` | More, ellipsis, three dots. |
| `Error_L_outlined` | Warning, error reminder, circle with exclamation mark. |
| `InformationThere_L_outlined` | Information prompt, circular letter i. |
| `Setting_L_outlined` | Settings, gear. |
| `ExpandThere_L_outlined` | Expand. |
| `Collapse_L_outlined` | Collapse. |
| `Link_L_outlined` | Link, chain. |
| `Share_L_outlined` | Share, forward. |
---
Generated from `references/protocol/` (fingerprint `7005139e5267c69e`). Do not edit this index: protocol changes regenerate it. For exact fields and a minimal example, query a name as shown in the Skill entrypoint; the whole catalog need not enter the model context.
@@ -0,0 +1,22 @@
# Content: illustrated information and resources
Use for summaries, recommendations, campaign descriptions, media, and file results. Include images and destinations only when the assets and behavior exist.
| Needed presentation | Optional components | When to choose them |
|---|---|---|
| Prose and citation | `Markdown + Link` | Continuous text, paragraphs, and source. Keep only the prose when no link exists |
| Cover and summary | `Column > Image + Text/Markdown + ButtonGroup` | Content or product with an existing main visual |
| Compact illustrated item | `Row > Image + Column(weight=1, Text, Text)` | Choose an explicit Image variant; `smallFeature` is a thumbnail candidate. Image and text can swap sides |
| Whole item opens details | `Row(action) / Column(action) > illustrated content` | Put a known detail action on the container instead of adding a redundant button; keep unknown behavior static |
| Multiple recommendations | `List > illustrated or text items` | Direct child components for static entries; a template for data-driven entries |
| Multiple evidence images | `Text + ImageList` | Photos or result gallery; consult `ImageCarousel` for individual switching |
| File result | `Text/Markdown + File` | Filename, download resource, and description; do not disguise plain text as an attachment |
| Audio or video | `AudioPlayer` or `Video`, with explanation | Use only with a real playable resource; a static cover is not playback |
Do not omit `Image.variant` in a compact illustrated item: the current default is full-row width and 200 high. Choose dimensions for the asset and layout. `fit=contain` preserves the whole image; `fit=cover` permits cropping. When the outer item opens details and its image is only a thumbnail, `previewEnabled=false` can disable the image's own large preview.
`List.children` accepts component IDs or a template object; `ImageList.images` is an array of image URLs. They have different shapes. A `File` preview is configured by `onPreview`; its appearance alone does not make it clickable.
Keep genuine posters and photos as images, while interface text and controls remain structured. See [image reconstruction](../design.md#image-reconstruction) for brand assets and crop boundaries. For repeated item templates, inspect `Loop` in the [data report example](../protocol/examples/data-report.json).
When content is absent, show a clear empty result instead of an empty media container. If media or attachments arrive later, preserve already-valid summary text and update only the affected content.
@@ -0,0 +1,16 @@
# Detail: object facts and decisions
Use for an approval request, schedule item, task, order, or another object with facts and actions. Select only needed combinations; a title, status, and button are not mandatory on every card.
| Needed presentation | Optional components | When to choose them |
|---|---|---|
| Title and current status | `CardHeader(trailing → Tag)` or `Row > Text + Tag` | Native themed header or a custom compact header |
| Labels and values | `Column > Row > Text + Text` | A few object attributes; see [key-value rows](../design.md#key-value-rows) for long values |
| Fact and adjacent destination | `Row > Text + Link` | A role and "View role," or an attachment name and its details |
| Reason or supporting material | `Markdown`, `File`, optionally within `CollapsiblePanel` | Choose separately for prose, a real file, and collapsible detail |
| Adjacent text actions | `ButtonGroup` | Inline labels and actions; enable narrow-width wrapping if the contract permits |
| Action with submit validation | `Button > Text` | Use a standalone Button when `checks` are needed; arrange several Buttons in a Row or Column |
`CardHeader.trailing` is one component ID. `Button.child` references Text; the current renderer does not support wrapping arbitrary layouts such as Row in a Button. `ButtonGroup` items are not child component IDs and do not take `checks`. For a clickable illustrated block, see the container-action combination in [content](content.md).
Preserve recognizable date and timezone in schedules, and show old and new values together when relevant. Update decision and task state from a real business result; clicking alone does not mean success. Add only necessary inputs from the [form pattern](form.md) when the user must provide a comment or parameters.
@@ -0,0 +1,30 @@
# Form: input and feedback submission
Use for parameters, settings, ratings, and comments. For display-only information, use the [detail pattern](detail.md).
| Input need | Optional components | When to choose them |
|---|---|---|
| Free text or comments | `TextField + Button` | Submit entered text; group multiple fields by business purpose |
| Fixed choices or feedback reasons | `ChoicePicker + Button` | Single or multiple choice; a static Tag is not a selectable input |
| Number, date, or person | `NumberInput / DateTimeInput / UserPicker` | Use the native input for the field meaning instead of turning everything into text |
| Boolean setting | `Text + Switch` or `CheckBox` | A settings row or a choice with full explanation; the business flow decides whether it takes effect immediately or on submit |
| Rating and explanation | `Rating + TextField + Button` | Optional comment with a star rating; use ChoicePicker for named satisfaction choices |
| Image or variable entries | `ImageUpload` or `InputList`, with `Button` | Only when uploading or dynamic entry is required |
`ChoicePicker.variant` sets single or multiple selection. `displayStyle` sets presentation: `chips` for inline tags, `checkbox` for inline vertical choices, and `dropdown` (the default) for a compact entry opening the native picker. `chips` and `checkbox` write local state through `value` binding without firing an action; the submit Button collects their values in `context`. A configured `dropdown` action fires after confirming a selection.
Bind collected values with suitable initial values. Even single-select `ChoicePicker.value` uses an array of strings. Omitting `TextField.value` does not create a writeback path. Put submit validation on standalone `Button.checks`, not on TextField or a ButtonGroup item.
Make each field recognizable before and after input. Component labels have different roles:
| Component | Field-title choice |
|---|---|
| `TextField` | Its native `label` stays above the input. Use it as the field title; an empty label removes that title. |
| `ChoicePicker` (dropdown), `DateTimeInput` | Their `label` is an in-control prompt that gives way to the selected value. Add a nearby `Text` title when the field would otherwise lose its meaning. For inline `ChoicePicker` styles, title the group only when its options do not explain their purpose. |
| `NumberInput`, `UserPicker` | Native `label`, `title`, and `placeholder` serve the input panel or control. Add a nearby `Text` title when the field needs a persistent heading in the card. |
| `CheckBox`, `Switch` | `CheckBox.label` names the choice beside its control; a `Switch` can use an adjacent `Text` in a settings row. Do not add a duplicate heading when the choice is already clear. |
| `ImageUpload` | Its `label` is the upload control's caption. Use a nearby `Text` if the field itself needs a separate name. |
Use the component contract for exact fields. A placeholder or current value alone should not carry a field name that must remain visible. Add a short purpose or outcome line for a longer form when the surrounding context does not explain it.
Preserve user input after failure; show a completed state only after a real result. See [form interaction](../protocol/examples/form-interaction.json) for bindings, submit context, and checks, and [host action](../protocol/examples/host-action.json) for a host dialog and result writeback.
@@ -0,0 +1,14 @@
# Notification: short results and status reminders
Use for a short result, risk alert, or status change. When there are many facts or a decision, use the [detail pattern](detail.md).
| Needed presentation | Optional components | When to choose them |
|---|---|---|
| Compact reminder | `Row > Icon + Text + Link`, then `Text` or `Markdown` | Title, source, and detail destination in one row; add icon and link only if useful |
| Themed notification | `Column > CardHeader + Markdown + ButtonGroup` | Native themed header and connected actions after the body |
| Result or exception | `Row > Tag + Text`, then explanation | A distinct status and body; a very short result may use text alone |
| Capacity or quota | `Text + ProgressBar + Text` | A real computable ratio; show a number directly if only balance or remaining amount is known |
`CardHeader` supplies a coordinated title and background theme; `Tag` supplies status styling without hand-built colors. An outer `Column` is enough unless a local background, border, or grouping calls for `Card`.
`ButtonGroup.buttons[]` contains inline objects. For static reproduction, each item may omit `action` and keep only its noninteractive appearance. Standalone `Button.action` remains required by the protocol. Use [image reconstruction](../design.md#image-reconstruction) for a branded title icon.
@@ -0,0 +1,41 @@
# Progress: Agent execution and results
Use for generation, search, analysis, tool execution, and other ongoing processes. An ordinary task detail does not need a reasoning panel; use the [detail pattern](detail.md).
| Process need | Optional components | When to choose them |
|---|---|---|
| Collapsible execution | `CollapsiblePanel(variant=reasoning) > Markdown/Column` | Process title and steps; choose expanded state from the content |
| Current generation hint | `Markdown` or `Text(textEffect=shimmer)` | Markdown may use the host's `[AIGenerating]` convention; choose either treatment as appropriate |
| Stage or counts | `Row > Text + Tag`, or several numeric groups | Show known stage, number searched, or number analyzed |
| Known progress ratio | `Text + ProgressBar` | Use a real 0–100 `value`; do not infer a percentage from a stage alone |
| Final result | `Markdown`, `File`, data, or actions | Choose by result type; the full process need not remain visible |
## Group execution and result
For a demonstration task that summarizes data, steps can be grouped as below. This is structural notation, not sendable JSON.
```text
Column
├─ CollapsiblePanel (variant=reasoning, execution)
│ └─ Column
│ ├─ Text (demonstration data read)
│ └─ CollapsiblePanel (variant=indented, summary details)
│ └─ Row
│ ├─ Icon (registered tool or status icon)
│ └─ Text (current step summary)
└─ Markdown (final result, outside the process panel)
```
For one status, one panel containing Markdown or Text is sufficient. Add a nested panel only when several tool records benefit from grouping. Show a short operation summary, not raw tool inputs and outputs.
| Stage | Process area | Result area |
|---|---|---|
| Running | "Summarizing demonstration data"; append actual steps and show generation effect if useful | May be hidden or show an available partial result |
| Completed | "Summary complete"; update step copy and remove the generation effect | Show final content or artifact |
| Failed or cancelled | Show the actual terminal state and necessary explanation; stop the generation effect | Retain still-valid results; offer retry only when a real action exists |
## Incremental updates and display boundary
- `CollapsiblePanel.title` is a nonempty string and `textEffect` is a string enum; neither accepts `{path: ...}`. Change the title by updating that component with `updateComponents`. Bound body text may be changed through `updateDataModel`.
- `defaultExpanded` controls only the initial state; do not use it to override a user's later expansion or collapse. `shimmer` depends on client support. Use the `[AIGenerating]` host convention described in [global design guidance](../design.md#global-design-guidance) only in appropriate text, not every field.
- Reuse the original `surfaceId` and component IDs in deltas. Distinguish "result generated" from "user confirmed." For message shapes, appended steps, and removing the effect on completion, see the [agent progress example](../protocol/examples/agent-progress.json).
@@ -0,0 +1,19 @@
# Report: metrics, records, and conclusions
Use for a data summary, analytical report, monitoring, or execution result. Select combinations for the content; a text-only report does not need a chart.
| Needed presentation | Optional components | When to choose them |
|---|---|---|
| Conclusion and analysis | `Markdown` | Continuous explanation, paragraphs, and inline emphasis |
| A few adjacent metrics | `Row > Column(Text, Text, Text)` | Label, value, and change in each group; an optional Card can provide a local background |
| Metrics at wide and narrow widths | `ColumnLayout > metric groups` | Query and enable `responsive` when narrow layouts must become vertical; this is not an automatic wrapping grid |
| Status or exception list | `Column/List > Row(Icon/Tag, Text)` | Status and separate explanation per item; choose a registered icon |
| Homogeneous records | `Table` | Exact comparison by column |
| Trend or distribution | `Chart` | Data suited to a graphic; add a table separately when useful |
| Method and full report | `CollapsiblePanel`, `File`, or `Link` | Supplemental details, an attachment, or a real detail destination |
`Table.data` is structured data and pagination runs locally. `Chart.data` holds chart type and data, not component IDs. `ColumnLayout.columns` does not automatically wrap any number of items into groups; build actual columns according to its responsive contract.
Preserve numeric units, time ranges, and comparison baselines. Do not represent missing data as zero. Use [design guidance](../design.md#3-host-behavior-and-layout) for metric type size, spacing, and color rather than copying cramped, truncated, or gradient-heavy sample cards.
See the [data report example](../protocol/examples/data-report.json) for field and data shapes.
@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
https://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
@@ -0,0 +1,115 @@
DingTalk AICard Protocol V0.8
Copyright 2026 DingTalk (China) Information Technology Co., Ltd.
(DingTalk modifications and this notice)
This protocol package includes schema definitions and descriptions derived from the
A2UI (Agent to UI) Protocol project, which is licensed under the
Apache License, Version 2.0. A copy of that license is included in the
LICENSE file in this directory.
Upstream project : A2UI (Agent to UI) Protocol
Upstream license : Apache License, Version 2.0
Specification : v1.0 (Status: Candidate)
Baseline commit : f5e945a93da36a5d126228f2ad6fbe68809ef8f7 (2026-09-15)
--------------------------------------------------------------------------------
DERIVED FILES AND MODIFICATIONS (Apache-2.0 section 4(b))
--------------------------------------------------------------------------------
The files below identify DingTalk modifications and distinguish upstream-derived
material from DingTalk-authored additions:
1. agent-to-renderer.json
Derived from : specification/v1_0/json/agent_to_renderer.json
Modified :
- "$id" changed from "https://a2ui.org/specification/v1_0/agent_to_renderer.json"
to "https://dingtalk.com/card/a2ui/agent-to-renderer.json". The upstream
"$id" is intentionally NOT reused, so that this package is never mistaken
for an official A2UI file and never collides with one inside a shared
validator registry.
- Added "$defs/anyComponent", which unions the four component shards of this
package. Upstream resolves a single placeholder "catalog.json" instead.
- References to "common_types.json" retargeted to "./common-types-basic.json".
- Removed the "callRendererFunction" and "agentFunctionResponse" message
branches, together with their "$defs", because the current implementation
does not support the corresponding RPC flows. The remaining
four branches are identical in name and order to upstream v1.0.
2. common-types-basic.json
Derived from : specification/v1_0/json/common_types.json
Unchanged definitions : "$defs/ComponentId", "$defs/Extensions".
Modified : Removed FunctionResponse and CallId with the unsupported RPC
flows. Remaining definitions include reference adjustments
and DingTalk customizations.
The common-type files as a whole are NOT a drop-in replacement
for upstream "common_types.json". Two important semantic
changes are:
- "Action" : adds "responsePath" and "wantResponse"; omits upstream
"userMessage".
- "CheckRule" : "condition" is a DynamicBoolean and "message" is required,
whereas upstream evaluates "condition" to a ValidationResult
object and treats "message" as an optional fallback.
3. common-types-extended.json
DingTalk literal-object and host-action value-tree, binding, ownership and
result-path types. Function result schemas are documented in the host-function
catalog next to each function. Not part of the upstream specification.
4. common-types-visual.json
DingTalk visual types (ColorToken, SizeToken and IconName), moved without
changing their definitions from common-types-extended.json. Not part of
the upstream specification.
5. catalog-components-common.json, catalog-components-composition.json,
catalog-components-inputs.json, catalog-components-specialized.json,
catalog-functions-core.json, catalog-functions-expressions.json,
catalog-functions-host-actions.json
DingTalk-maintained catalog shards. The four component shards and
catalog-functions-core.json retain or adapt selected definitions and
description text from specification/v1_0/catalogs/basic/catalog.json;
their content is not wholly DingTalk-original. DingTalk has changed and
extended those entries and split them into task-specific shards.
catalog-functions-expressions.json and catalog-functions-host-actions.json
contain DingTalk-specific functions. All seven shards follow the upstream
v1.0 catalog structure and pass its "catalog_definition.json" meta
contract; they are not unmodified official catalogs. Empty union branches
use false.
6. examples/
DingTalk-authored message examples. Not derived from upstream.
--------------------------------------------------------------------------------
TRADEMARKS AND SCOPE
--------------------------------------------------------------------------------
This package is maintained by DingTalk. It is neither certified, endorsed, nor
published by the A2UI project. Apache-2.0 grants no trademark rights; "A2UI" is
referenced here solely to identify the upstream work from which parts of this
package are derived.
The derived schema files and this notice describe this package's scope.
Nothing here constitutes a warranty of full interoperability with official
A2UI renderers or SDKs.
--------------------------------------------------------------------------------
中文摘要(以上述英文内容为准)
--------------------------------------------------------------------------------
本包部分 Schema 定义与说明派生自 A2UI 协议项目(Apache-2.0 许可),许可证全文见同目录 LICENSE。
上游基线为 A2UI 规范 v1.0(状态:Candidate),提交 f5e945a93d(2026-09-15)。
已改编并修改的文件:agent-to-renderer.json(改 $id、增 anyComponent、公共类型引用
重定向并裁剪两类当前不支持的 RPC 消息)、common-types-basic.json(原样保留
ComponentId 与 Extensions;随未开放的 RPC 流程移除 FunctionResponse 和 CallId;
其他定义包含引用调整和钉钉定制,Action 与 CheckRule 存在语义差异)。公共类型文件
整体不能直接替代上游 common_types.json。四份组件 catalog 与
catalog-functions-core.json 保留或改编了官方 Basic Catalog 的部分定义与说明,
由钉钉扩展并分片,不属于纯钉钉原创内容。catalog-functions-expressions.json、
catalog-functions-host-actions.json、common-types-extended.json、
common-types-visual.json 与 examples/ 为钉钉新增内容。
本包消息集为官方四支子集(不含 callRendererFunction 与 agentFunctionResponse)。
本包由钉钉维护,未获 A2UI 项目认证或背书。Apache-2.0 不授予商标权利,文中提及
"A2UI" 仅用于标识派生来源。本包范围由随包 Schema 和本说明界定,不构成与官方渲染器或
SDK 完全互操作的担保。
@@ -0,0 +1,216 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://dingtalk.com/card/a2ui/agent-to-renderer.json",
"title": "DingTalk AICard Protocol V0.8 A2UI Message Envelope",
"description": "Describes a JSON payload for an A2UI (Agent to UI) message, which is used to dynamically construct and update user interfaces. Modified by DingTalk from the A2UI v1.0 agent_to_renderer.json envelope: the catalog placeholder is bound to this package, and common types resolve to ./common-types-basic.json.",
"type": "object",
"oneOf": [
{
"$ref": "#/$defs/CreateSurfaceMessage"
},
{
"$ref": "#/$defs/UpdateComponentsMessage"
},
{
"$ref": "#/$defs/UpdateDataModelMessage"
},
{
"$ref": "#/$defs/DeleteSurfaceMessage"
}
],
"$defs": {
"CreateSurfaceMessage": {
"type": "object",
"properties": {
"version": {
"const": "v1.0"
},
"createSurface": {
"type": "object",
"description": "Signals the renderer to create a new surface and begin rendering it. Creating a surface implicitly instantiates the canonical 'Surface' container component ('./common-types-basic.json#/$defs/Surface') with 'child': 'root'. It is an error to try to create a surface with an existing ID without first deleting it; surfaceId MUST be globally unique for the renderer's lifetime. When this message is sent, the renderer expects 'updateComponents' and/or 'updateDataModel' messages for the same surfaceId to define the component tree.",
"properties": {
"surfaceId": {
"type": "string",
"description": "The unique identifier for the UI surface to be rendered. It must be globally unique for the renderer's lifetime."
},
"catalogId": {
"description": "A string that uniquely identifies the default catalog for this surface. It is recommended to prefix this with an internet domain that you own, to avoid conflicts e.g. 'mycompany.com:somecatalog'. Components and function calls that do not explicitly specify a catalogId will use this surface-level default catalogId.",
"type": "string"
},
"sendDataModel": {
"type": "boolean",
"description": "If true, the renderer will send the full data model of this surface in the metadata of every A2A message sent to the agent that created the surface. Defaults to false."
},
"components": {
"$ref": "#/$defs/ComponentsList"
},
"dataModel": {
"type": "object",
"description": "The initial root data model object for the surface.",
"additionalProperties": true
},
"metadata": {
"type": "object",
"description": "Optional surface-level metadata.",
"properties": {
"extensions": {
"$ref": "./common-types-basic.json#/$defs/Extensions"
}
},
"additionalProperties": false
}
},
"required": [
"surfaceId"
],
"additionalProperties": false
}
},
"required": [
"createSurface",
"version"
],
"additionalProperties": false
},
"Component": {
"description": "A UI component for the surface, combining baseline envelope properties with the catalog component definition.",
"allOf": [
{
"$ref": "./common-types-basic.json#/$defs/ComponentCommon"
},
{
"$ref": "#/$defs/anyComponent"
},
{
"type": "object",
"properties": {
"component": {
"not": {
"const": "Surface"
}
}
}
}
],
"unevaluatedProperties": false
},
"ComponentsList": {
"type": "array",
"description": "A list containing UI components for the surface.",
"minItems": 1,
"items": {
"$ref": "#/$defs/Component"
}
},
"UpdateComponentsMessage": {
"type": "object",
"properties": {
"version": {
"const": "v1.0"
},
"updateComponents": {
"type": "object",
"description": "Updates a surface with a new set of components. This message can be sent multiple times to update the component tree of an existing surface. One of the components in one of the components lists MUST have an 'id' of 'root' to serve as the root of the component tree. The createSurface message MUST have been previously sent for this surfaceId.",
"properties": {
"surfaceId": {
"type": "string",
"description": "The unique identifier for the UI surface to be updated. It must be globally unique for the renderer's lifetime."
},
"components": {
"$ref": "#/$defs/ComponentsList"
}
},
"required": [
"surfaceId",
"components"
],
"additionalProperties": false
}
},
"required": [
"updateComponents",
"version"
],
"additionalProperties": false
},
"UpdateDataModelMessage": {
"type": "object",
"properties": {
"version": {
"const": "v1.0"
},
"updateDataModel": {
"type": "object",
"description": "Updates the data model for an existing surface. This message can be sent multiple times to update the data model. The createSurface message MUST have been previously sent for this surfaceId.",
"properties": {
"surfaceId": {
"type": "string",
"description": "The unique identifier for the UI surface this data model update applies to. It must be globally unique for the renderer's lifetime."
},
"path": {
"type": "string",
"description": "An optional path to a location within the data model (e.g., '/user/name'). If omitted, or set to '/', refers to the entire data model."
},
"value": {
"description": "The data to be updated in the data model. To delete the key/value at 'path', set 'value' explicitly to null."
}
},
"required": [
"surfaceId",
"value"
],
"additionalProperties": false
}
},
"required": [
"updateDataModel",
"version"
],
"additionalProperties": false
},
"DeleteSurfaceMessage": {
"type": "object",
"properties": {
"version": {
"const": "v1.0"
},
"deleteSurface": {
"type": "object",
"description": "Signals the renderer to delete the surface identified by 'surfaceId'. The createSurface message MUST have been previously sent for this surfaceId.",
"properties": {
"surfaceId": {
"type": "string",
"description": "The unique identifier for the UI surface to be deleted. It must be globally unique for the renderer's lifetime."
}
},
"required": [
"surfaceId"
],
"additionalProperties": false
}
},
"required": [
"deleteSurface",
"version"
],
"additionalProperties": false
},
"anyComponent": {
"description": "Any component from the four component shards of the DingTalk public catalog.",
"oneOf": [
{
"$ref": "./catalog-components-common.json#/$defs/anyComponent"
},
{
"$ref": "./catalog-components-composition.json#/$defs/anyComponent"
},
{
"$ref": "./catalog-components-inputs.json#/$defs/anyComponent"
},
{
"$ref": "./catalog-components-specialized.json#/$defs/anyComponent"
}
]
}
}
}
@@ -0,0 +1,700 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://dingtalk.com/card/a2ui/catalog-components-common.json",
"title": "DingTalk AICard Protocol V0.8 Common components",
"description": "10 components and 0 functions. A reading shard of the DingTalk public catalog, not a separate runtime catalog. Modified by DingTalk from selected entries of the A2UI v1.0 Basic Catalog; some upstream definitions and descriptions are retained. See NOTICE.",
"catalogId": "https://dingtalk.com/card/a2ui/catalogs/public/catalog.json",
"protocolVersion": "1.0",
"instructions": "Read entries needed for the current task, then follow their $ref dependencies. Common types: ./common-types-basic.json, ./common-types-extended.json and ./common-types-visual.json. Do not load all shards into the model context by default.\nCommon components: ./catalog-components-common.json.\nComposition and repeated layouts: ./catalog-components-composition.json.\nInputs and pickers: ./catalog-components-inputs.json.\nData display and media: ./catalog-components-specialized.json.\nCore functions adapted by DingTalk from A2UI: ./catalog-functions-core.json.\nDingTalk expressions and operators: ./catalog-functions-expressions.json.\nDingTalk host actions: ./catalog-functions-host-actions.json.\nSelect examples from ./examples/README.md; message structures are in ./agent-to-renderer.json.\nThis is the public DingTalk AICard Protocol V0.8 package. Use only the components, fields, functions, and common-type public values listed in the files loaded and assembled for the current scope.\nfallbackMarkdown is an optional DingTalk extension for component-level fallback content. It is used only when the current renderer cannot render the component. Unknown fields and field-validation errors do not trigger it. When omitted, the renderer displays the standard upgrade message.\nSchema references are local file references and require no HTTP access. catalogId is a runtime catalog identifier, not a file path.\nThe #/$defs/anyComponent union describes catalog-specific fields only. Validate complete component instances through the message envelope or loadSchemas().validateComponent, which combines ComponentCommon with this union and rejects unknown fields. The catalog root is not a validation entry point for complete messages or component instances. Complete messages must also conform to the main protocol; dynamic result types, component-tree references, and platform capabilities are validated at runtime.\nExpressions use {\"call\":…, \"args\":…} without an additional profile declaration. A host action must explicitly set functionCall.catalogId to urn:dingtalk:a2ui:host:v1. A public catalog HTTP identifier from a surface or component cannot replace the host Function catalog. For promptText, initialValue is the prefilled-text parameter and text is a result field, not an input parameter.\nAttach form-validation checks to the Button that submits the form. Do not rely on standard event-response fields for automatic write-back.\nUserPicker, ConversationPicker, and ImageUpload require host authorization. Server-side callbacks must still enforce business authorization.",
"components": {
"Text": {
"type": "object",
"description": "Text, font size, color, and streaming state. `textEffect` can add a shimmer effect.",
"properties": {
"component": {
"const": "Text",
"description": "Public component type identifier."
},
"text": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "Text content to display. Supports literals, data bindings, and value functions. **Object forms such as `{content, i18n}` are not accepted**; the server must localize multilingual copy before sending it."
},
"variant": {
"type": "string",
"enum": [
"caption",
"body"
],
"description": "Text style preset; omitted means `body`. Metrics first use the host style tokens. If unavailable, font size/line height fall back to 14/21 on desktop and 17/21 on mobile for `body`, or 12/18 on desktop and 12/16 on mobile for `caption`. A successfully resolved explicit `sizeToken` takes precedence; these fallback metrics are not fixed values for every client."
},
"sizeToken": {
"$ref": "./common-types-visual.json#/$defs/SizeToken",
"description": "Native DDesign font-size Token ID. See the common `SizeToken` type for names and individual uses. Specify the full `__font_size` key; it takes priority over `variant`. Line height attempts to use the matching `__line_height` token and falls back to the `variant` preset if the host cannot resolve it. Do not use design labels such as `font-size/body` or style names without a suffix."
},
"bold": {
"type": "boolean",
"description": "Whether the text is bold."
},
"italic": {
"type": "boolean",
"description": "Whether the text is italic."
},
"strikeThrough": {
"type": "boolean",
"description": "Whether to apply strikethrough."
},
"colorToken": {
"$ref": "./common-types-visual.json#/$defs/ColorToken",
"description": "Only the 57 IDs in the common `ColorToken` enum are allowed. A DDesign token name such as `common_level1_base_color`. The renderer calls the host design-token service to resolve it for the **current client platform and theme**, making this the preferred way to keep colors consistent across platforms. This has the highest priority: when resolved, `color`, `customLightColor`, and `customDarkColor` are ignored. If the host cannot resolve the token, evaluation falls back to the subsequent color sources."
},
"customLightColor": {
"type": "string",
"description": "Custom text color for light mode (hex)."
},
"customDarkColor": {
"type": "string",
"description": "Custom text color for dark mode (hex). The renderer selects and sends the light or dark value for the current theme. A theme change takes effect after the card's next refresh."
},
"maxLine": {
"type": "integer",
"description": "Truncate after exceeding this number of lines. **By default, only 3 lines are displayed if not configured**. Long text will be silently truncated; to display it fully, please explicitly set a sufficiently large value."
},
"icon": {
"type": "object",
"description": "Semantic leading icon. Use exactly one of `{\"name\":\"icon library name\"}` or `{\"url\":\"light-theme URL\",\"darkUrl\":\"dark-theme URL\"}`. `darkUrl` is optional and falls back to `url`. **Exactly one of `name` and `url` must be provided**; providing both or neither is invalid. ⚠️ **Mutually exclusive with `textEffect`**: a `Text` component with `textEffect` uses a different rendering path with no icon slot. If both are sent, **the icon is retained and the effect is ignored**.",
"properties": {
"name": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "Registered icon-library name; mutually exclusive with `url`."
},
"url": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "Light-theme image URL; mutually exclusive with `name`."
},
"darkUrl": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "Dark-theme image URL. Effective only when `url` is used; falls back to `url` when omitted."
}
}
},
"textEffect": {
"type": "string",
"enum": [
"shimmer"
],
"description": "Text presentation effect. `shimmer` repeatedly sweeps a highlight across the text and is intended for streaming wait states such as \"Thinking...\". If omitted, no effect is applied. On `CollapsiblePanel`, it applies to the panel title. The field is sent consistently to all clients. The effect currently works only on iOS; unsupported clients silently ignore it and render regular text without affecting the text itself. No protocol change is required when those clients add support."
},
"onLinkClick": {
"$ref": "./common-types-basic.json#/$defs/Action",
"description": "The value must be an `Action` from the base protocol: the `event` branch reports to the agent, while the `functionCall` branch runs locally in the renderer. ⚠️ **The current implementation is reduced to \"a click anywhere on the Text node\"**: clicking any part of the text fires the action, **and the event does not carry which link was clicked**. The field therefore suits coarse-grained tracking such as \"the user read this text containing a link\", but cannot distinguish which link was followed. Link navigation itself is unaffected: the renderer opens it directly without going through the card event system."
},
"weight": {
"type": "number",
"description": "Flex layout weight (used to allocate space proportionally)."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component",
"text"
]
},
"Markdown": {
"type": "object",
"description": "Markdown headings, lists, code, and quotes.",
"properties": {
"component": {
"const": "Markdown",
"description": "Public component type identifier."
},
"content": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "Markdown body. In addition to standard Markdown, DingTalk supports these @-mention extensions: `<a atId=\"{openDingTalkId}\">nickname</a>` mentions a specific member, and `<a atId=\"all\">everyone</a>` mentions everyone (`all` is a reserved ID). Every `atId` in the body must be listed in the card-creation parameter `atIdList`; the reserved ID `all` does not need to be listed. The server resolves each `openDingTalkId` to a user. Write only the display name inside the tag and do not add `@` yourself; the renderer prepends `@` when rendering an at node, so a self-written one renders as `@@`. If an `atId` is not listed or cannot be resolved, it falls back to plain text without highlighting or click behavior and does not report an error. The `<@openDingTalkId>` and `<@all>` placeholders used by IM Markdown messages **do not work** in the card flow and are displayed literally. Server-side resolution of openDingTalkId is not yet available, so mentions currently do not take effect and degrade to plain text as described above. The body syntax and this field's contract stay unchanged once it ships."
},
"weight": {
"type": "number",
"description": "Flex layout weight (used to allocate space proportionally)."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component",
"content"
]
},
"Image": {
"type": "object",
"description": "Image display with a dark-theme image alternative. When variant is omitted, the current DingTalk implementation builds a full-row image with height 200; available width remains subject to the parent layout.",
"properties": {
"component": {
"const": "Image",
"description": "Public component type identifier."
},
"url": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "Light mode and default image URL."
},
"darkUrl": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "Dark mode image URL; if not configured, the renderer side will continue to use the URL."
},
"fit": {
"type": "string",
"enum": [
"contain",
"cover",
"fill",
"none",
"scaleDown"
],
"description": "Image scaling within its container. When omitted, the current DingTalk implementation crops to fill, corresponding to `cover`; this differs from the official Basic Catalog default of `fill`. Specify a value from this field's vocabulary to control containment, cropping or stretching."
},
"variant": {
"type": "string",
"enum": [
"icon",
"avatar",
"smallFeature",
"mediumFeature",
"largeFeature",
"header"
],
"description": "Image size and style hint. Omitted means full-row width and height 200, rather than the official Basic Catalog default `mediumFeature`. Current DingTalk sizes are: `icon` 24×24, `avatar` 40×40, `smallFeature` 96×96, `mediumFeature` 160×120, and `largeFeature` 320×200; `header` uses full-row width and height 200. Available width is subject to parent constraints, and clients must integrate the corresponding Nest implementation."
},
"cornerRadius": {
"type": "number",
"description": "Image corner radius in px; omitted means `6`. `ImageList` defaults to `4`, and `ImageCarousel` to `12`. The radius clips the image's outer container. Use a finite non-negative number; `0` gives square corners."
},
"previewEnabled": {
"type": "boolean",
"description": "Whether to allow clicking the image to open a large preview, default `true`. ⚠️ Default is **on**: if this field is not set, as long as `url` is an address that can be loaded on the renderer, the image is clickable. To make it a pure display image, explicitly set `false`."
},
"weight": {
"type": "number",
"description": "Flex layout weight (used to allocate space proportionally)."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component",
"url"
]
},
"Icon": {
"type": "object",
"description": "DingTalk icon set and loading status. Current icon size is 14 with line height 22. Without a resolved color configuration, built-in light/dark colors are used; valid explicit colors take precedence.",
"properties": {
"component": {
"const": "Icon",
"description": "Public component type identifier."
},
"name": {
"anyOf": [
{
"$ref": "./common-types-visual.json#/$defs/IconName"
},
{
"$ref": "./common-types-basic.json#/$defs/DataBinding"
},
{
"$ref": "./common-types-basic.json#/$defs/FunctionCall"
}
],
"description": "Only the 24 case-sensitive names in the `IconName` list below are available. Data bindings and value functions are supported, but their results must also be names from the list. SVG objects, image URLs, and custom semantic aliases are not accepted."
},
"colorToken": {
"$ref": "./common-types-visual.json#/$defs/ColorToken",
"description": "Only the 57 IDs in the common `ColorToken` enum are allowed. A DDesign token name such as `common_level1_base_color`. The renderer calls the host design-token service to resolve it for the **current client platform and theme**, making this the preferred way to keep colors consistent across platforms. This has the highest priority: when resolved, `customLightColor` and `customDarkColor` are ignored. If the host cannot resolve the token, evaluation falls back to the subsequent color sources."
},
"customLightColor": {
"type": "string",
"description": "Custom light mode color (hexadecimal)."
},
"customDarkColor": {
"type": "string",
"description": "Custom dark-theme color in hexadecimal. The renderer selects and sends the light or dark value for the current theme. A theme change takes effect after the card's next refresh."
},
"weight": {
"type": "number",
"description": "Flex layout weight (used to allocate space proportionally)."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component",
"name"
]
},
"Divider": {
"type": "object",
"description": "Horizontal or vertical separator line.",
"properties": {
"component": {
"const": "Divider",
"description": "Component type identification field."
},
"axis": {
"type": "string",
"enum": [
"horizontal",
"vertical"
],
"description": "Divider direction, default is `horizontal`. `vertical` is used for vertical separation between elements within the same row (such as button dividers in the bottom action bar), rendered with a fixed line width and stretched to the height of the parent container, so **the parent container is required to be `Row` and the elements in that row must have consistent height**; for full-height vertical bars spanning multiple rows, it is also used, placed in the first position of `Row`. Line width and color are controlled by `borderWidth` / `borderColor`."
},
"borderWidth": {
"type": "number",
"description": "Line thickness in px; default `0.5`, the hairline value from the design specification. Its name and value semantics match the same field on `Row`, `Column`, `Card`, and `Stack`, and correspond to CSS `border-width`. **It always describes line thickness, regardless of direction**: when `axis` is `horizontal`, it determines line height; when `axis` is `vertical`, it determines line width. The value must be finite and non-negative. Invalid values are silently discarded and fall back to `0.5` without failing the card."
},
"borderColor": {
"type": "string",
"description": "Line color in `#AARRGGBB` form; default `#1F111F2C`, a neutral gray at approximately 12% opacity. Corresponds to CSS `border-color`. **Only a single color value is accepted; a `{light,dark}` pair is not supported**, so the color does not change with the theme. Use `borderColorToken` below when theme-aware color is required."
},
"borderColorToken": {
"$ref": "./common-types-visual.json#/$defs/ColorToken",
"description": "Only the 57 IDs in the common `ColorToken` enum are allowed. A DDesign token name for the line color. It has **higher priority than `borderColor`** and is the only way to make the divider follow light and dark themes. The design-system line-color families are `common_line_light_color` (16% in light mode, 10% in dark mode) and `common_line_hard_color` (24% in light mode, 18% in dark mode). The legacy default `#1F111F2C` differs from both; **specify a token explicitly to align with the design system**. If the host cannot resolve the token, it is treated as omitted and falls back to `borderColor` without reporting an error."
},
"weight": {
"type": "number",
"description": "The relative weight of this component within a Row or Column. This is similar to the CSS 'flex-grow' property. Note: this may ONLY be set when the component is a direct descendant of a Row or Column."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component"
]
},
"Tag": {
"type": "object",
"description": "Semantic tag whose theme determines text color, background color, border color, and border width together.",
"properties": {
"component": {
"const": "Tag",
"description": "Public component type identifier."
},
"text": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "Label text."
},
"theme": {
"type": "string",
"enum": [
"black",
"gray",
"red",
"orange",
"green",
"blue"
],
"description": "**Semantic theme: one value determines the text color, background color, border color, and border width together.** The design system fixes these relationships, so arbitrary hexadecimal colors are not accepted. Defaults to `gray`; unknown values fall back to `gray` without reporting an error. **This differs from the `color` field on `Text` and `Icon`**, which specifies a single foreground color. Here the field defines the entire tag color scheme, so it is named `theme`, consistent with `CardHeader.theme`."
},
"variant": {
"type": "string",
"enum": [
"filled",
"hollow"
],
"description": "Tag style; default `filled`. **The two styles are mutually exclusive**: `filled` has a background from the 12%-opacity level of `theme` and no border; `hollow` has a transparent background and a 1px border from the 48%-opacity level of `theme`. Both use the same text color. **A tag cannot have both a filled background and a border**; compose that appearance with `Row` instead."
},
"maxWidth": {
"type": "number",
"description": "Maximum tag width in px; omitted means `999`, a numeric limit rather than unlimited width. Text is truncated beyond it."
},
"weight": {
"type": "number",
"description": "Flex layout weight."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component",
"text"
]
},
"Card": {
"type": "object",
"description": "Single-child card container with padding, background, and rounded corners.",
"properties": {
"component": {
"const": "Card",
"description": "Component type identification field."
},
"child": {
"$ref": "./common-types-basic.json#/$defs/Child",
"description": "The ID of the single child component to be rendered inside the card. To display multiple elements, you MUST wrap them in a layout component (like Column or Row) and pass that container's ID here. Do NOT pass multiple IDs or a non-existent ID."
},
"weight": {
"type": "number",
"description": "The relative weight of this component within a Row or Column. This is similar to the CSS 'flex-grow' property. Note: this may ONLY be set when the component is a direct descendant of a Row or Column."
},
"backgroundColorToken": {
"$ref": "./common-types-visual.json#/$defs/ColorToken",
"description": "Only the 57 IDs in the common `ColorToken` enum are allowed. A DDesign token name for the card surface, such as `common_bg_color`. The host resolves it for the **current client platform, theme, and tenant**, making this the preferred way to keep the surface consistent across platforms and themes. It has **higher priority than `backgroundColor`**. If the host cannot resolve the token, it is treated as omitted and evaluation continues with `backgroundColor`; the default surface color is used only when that field is also omitted. No error is reported."
},
"backgroundColor": {
"anyOf": [
{
"type": "string"
},
{
"type": "object",
"properties": {}
}
],
"description": "Card surface color. Two forms are supported: a string in `#AARRGGBB` form is a **single value** that does not change with the light or dark theme; `{\"light\":\"#…\",\"dark\":\"#…\"}` provides **light and dark values** selected by the renderer for the current theme and is recommended. If omitted, the default surface color is used: `#FFFFFFFF` in light mode and `#FF1F1F1F` in dark mode."
},
"cornerRadius": {
"type": "number",
"description": "Card-surface corner radius in px; default `8`. Must be a non-negative number."
},
"borderWidth": {
"type": "number",
"description": "Border width in px; default `0`, meaning no border. **A visible border requires `borderColor` to be configured as well.**"
},
"borderColor": {
"type": "string",
"description": "Stroke color, hexadecimal. Only visible when `borderWidth` is also set; if a color is set, a solid line style is automatically applied."
},
"borderColorToken": {
"$ref": "./common-types-visual.json#/$defs/ColorToken",
"description": "Only the 57 IDs in the common `ColorToken` enum are allowed. A DDesign token name for the border color. It has **higher priority than `borderColor`** and is resolved by the host for the **current client platform, theme, and tenant**. This is the only way to make the border follow light and dark themes: `borderColor` accepts a single value that remains unchanged in dark mode. The line-color families are `common_line_light_color` and `common_line_hard_color`; the host resolves their actual values and opacity. If the host cannot resolve the token, it is treated as omitted and evaluation continues with `borderColor` without reporting an error."
},
"padding": {
"type": "number",
"description": "Uniform padding on all four sides, unit px, default `12`. Must be a number and not less than 0."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"child",
"component"
]
},
"Row": {
"type": "object",
"description": "Child nodes are arranged from left to right.",
"properties": {
"component": {
"const": "Row",
"description": "Component type identification field."
},
"children": {
"$ref": "./common-types-basic.json#/$defs/ChildList",
"description": "Defines the children. Use an array of strings for a fixed set of children, or a template object to generate children from a data list. Children cannot be defined inline, they must be referred to by ID."
},
"justify": {
"type": "string",
"enum": [
"start",
"center",
"end",
"spaceBetween",
"spaceAround",
"spaceEvenly",
"stretch"
],
"description": "Main-axis layout; the seven values match the official vocabulary. `start`, `center` and `end` control where children sit along the main axis; `spaceBetween`, `spaceAround` and `spaceEvenly` distribute the remaining space exactly like CSS `justify-content` (`gap` still applies only between adjacent children and is never added at the edges). **`spaceBetween` with two children**: positioning matches CSS while the content fits, and an over-long last item wraps within the remaining width instead of overflowing. In the other arrangements, once a weighted child appears in the row, subsequent children are measured against the full row width, so content that does not fit on one line overflows and is clipped — use child `weight` for long text. No remaining space is distributed when any child already carries `weight`, matching the official flex-grow behaviour. On a flex row, `stretch` behaves like `start`. Omitted means `start`."
},
"align": {
"type": "string",
"enum": [
"start",
"center",
"end",
"stretch"
],
"description": "Cross-axis alignment. `start`, `center` and `end` control the vertical position of children. `stretch`, the default, gives children equal height and matches the official `align-items: stretch` semantics: container children (`Row`, `Column`, `Card`, and a vertical `Divider`) stretch to the full row height, while leaf and composite components such as `Text`, `Image` and `Button` keep their intrinsic height and are top-aligned, with their `weight`, spacing and visibility unaffected. While equal height is in effect, `justify` values `center`, `end`, `spaceBetween`, `spaceAround` and `spaceEvenly` on a stretched child `Column` become visible. ⚠️ Component ids must not take the form `<Row id>__stretch.<n>`, which is reserved for layout; a collision makes the whole row give up equal height. Under `Column` and `List`, `stretch` decides whether a child fills the available width or sizes to its content."
},
"weight": {
"type": "number",
"description": "The relative weight of this component within a Row or Column. This is similar to the CSS 'flex-grow' property. Note: this may ONLY be set when the component is a direct descendant of a Row or Column."
},
"backgroundColor": {
"type": "string",
"description": "Container background color in hexadecimal `#RRGGBB` or `#AARRGGBB` form, with Alpha first in the 8-digit form. **Only a single color string is accepted; a `{light,dark}` object is not supported**, so the color does not change with the theme. To use a different dark-theme color, send an updated component definition. If omitted, the background is transparent."
},
"cornerRadius": {
"type": "number",
"description": "Corner radius in px. If omitted, no explicit radius is set and the host container's default styling remains in effect. Set a non-negative number when a definite appearance is needed. Use a number; fractional values are truncated rather than rounded."
},
"borderWidth": {
"type": "number",
"description": "Stroke width, in px, must be a number. After configuration, a solid line type is automatically applied, and other line types cannot be specified. **It must be configured in pairs with `borderColor`** to draw a visible stroke."
},
"borderColor": {
"type": "string",
"description": "Stroke color, the value format is the same as `backgroundColor`. **Must be configured in pairs with `borderWidth`**; if only the color is provided without the width, the line will not be drawn."
},
"borderColorToken": {
"$ref": "./common-types-visual.json#/$defs/ColorToken",
"description": "Only the 57 IDs in the common `ColorToken` enum are allowed. A DDesign token name for the border color. It has **higher priority than `borderColor`** and is resolved by the host for the **current client platform, theme, and tenant**. This is the only way to make the border follow light and dark themes: `borderColor` accepts a single value that remains unchanged in dark mode. The line-color families are `common_line_light_color` and `common_line_hard_color`; the host resolves their actual values and opacity. If the host cannot resolve the token, it is treated as omitted and evaluation continues with `borderColor` without reporting an error."
},
"action": {
"$ref": "./common-types-basic.json#/$defs/Action",
"description": "Makes the entire container clickable. Uses the same Action semantics as `Button.action`: exactly one of `event` (reported to the agent) and `functionCall` (executed locally by the renderer) may be present."
},
"padding": {
"type": "number",
"minimum": 0,
"description": "Uniform padding on all four sides, unit px, must be a number and not less than 0. Containers with a background color generally need it; otherwise, the child content will be close to the edge of the color block. **Only uniform values for all four sides are supported**; individual sides or `paddingX`/`paddingY` are not supported yet. If not configured, this field will not be sent, consistent with historical version behavior. Omission is not equivalent to an explicit 0: a card root can still receive platform-specific insets from card layout, while this field adds no padding to a nested container when omitted."
},
"gap": {
"type": "number",
"minimum": 0,
"description": "Gap between children in px; must be a non-negative number. `Column` applies it vertically and `Row` horizontally; the first child is unaffected. **When omitted, hierarchy-specific defaults remain in effect**: 8 between top-level card blocks, 12 in nested columns, and 8 horizontally. Existing card spacing therefore remains unchanged."
},
"backgroundColorToken": {
"$ref": "./common-types-visual.json#/$defs/ColorToken",
"description": "Only the 57 IDs in the common `ColorToken` enum are allowed. A DDesign token name for the container background, such as `common_bg_color`. The host resolves it for the **current client platform, theme, and tenant**, and it has **higher priority than `backgroundColor`**. This is the component's only way to make its background follow dark mode; `backgroundColor` accepts a single color value and does not change with the theme. If the host cannot resolve the token, it is treated as omitted and evaluation continues with `backgroundColor` without reporting an error."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"children",
"component"
]
},
"Column": {
"type": "object",
"description": "Child nodes are stacked from top to bottom. As a card root with padding omitted and no full-width CardHeader, card layout supplies horizontal insets of 16 on desktop or 12 on mobile, with top and bottom insets of 10. On mobile, a final visible Markdown block changes the bottom inset to 14. Nested Columns do not automatically receive these root insets.",
"properties": {
"component": {
"const": "Column",
"description": "Component type identification field."
},
"children": {
"$ref": "./common-types-basic.json#/$defs/ChildList",
"description": "Defines the children. Use an array of strings for a fixed set of children, or a template object to generate children from a data list. Children cannot be defined inline, they must be referred to by ID."
},
"justify": {
"type": "string",
"enum": [
"start",
"center",
"end",
"spaceBetween",
"spaceAround",
"spaceEvenly",
"stretch"
],
"description": "Main-axis layout. A `Column` is normally sized by its content and has no remaining space, so `spaceBetween`, `spaceAround`, `spaceEvenly` and `stretch` behave here exactly like an official flex column and produce the same result as `start` (accepted, no error). The only case with remaining height is when the column is a child of an equal-height row and is pulled to the row height (see `align` on Row): `center` and `end` then take effect normally, and `spaceBetween`, `spaceAround` and `spaceEvenly` distribute the remaining height under the same rules as Row (no distribution when any child already carries `weight`). ⚠️ Component ids must not take the form `<Column id>__justify.<n>`, which is reserved for layout; a collision disables `justify` on that column while equal height for the row is unaffected. Omitted means `start`."
},
"align": {
"type": "string",
"enum": [
"center",
"end",
"start",
"stretch"
],
"description": "Defines the alignment of children along the cross axis (horizontally). This is similar to the CSS 'align-items' property. Omitted means `stretch`; whether a child fills the available width also depends on its fixed dimensions and parent constraints."
},
"weight": {
"type": "number",
"description": "The relative weight of this component within a Row or Column. This is similar to the CSS 'flex-grow' property. Note: this may ONLY be set when the component is a direct descendant of a Row or Column."
},
"backgroundColor": {
"type": "string",
"description": "Container background color in hexadecimal `#RRGGBB` or `#AARRGGBB` form, with Alpha first in the 8-digit form. **Only a single color string is accepted; a `{light,dark}` object is not supported**, so the color does not change with the theme. To use a different dark-theme color, send an updated component definition. If omitted, the background is transparent."
},
"cornerRadius": {
"type": "number",
"description": "Corner radius in px. If omitted, no explicit radius is set and the host container's default styling remains in effect. Set a non-negative number when a definite appearance is needed. Use a number; fractional values are truncated rather than rounded."
},
"borderWidth": {
"type": "number",
"description": "Stroke width, in px, must be a number. After configuration, a solid line type is automatically applied, and other line types cannot be specified. **It must be configured in pairs with `borderColor`** to draw a visible stroke."
},
"borderColor": {
"type": "string",
"description": "Stroke color, the value format is the same as `backgroundColor`. **Must be configured in pairs with `borderWidth`**; if only the color is provided without the width, the line will not be drawn."
},
"borderColorToken": {
"$ref": "./common-types-visual.json#/$defs/ColorToken",
"description": "Only the 57 IDs in the common `ColorToken` enum are allowed. A DDesign token name for the border color. It has **higher priority than `borderColor`** and is resolved by the host for the **current client platform, theme, and tenant**. This is the only way to make the border follow light and dark themes: `borderColor` accepts a single value that remains unchanged in dark mode. The line-color families are `common_line_light_color` and `common_line_hard_color`; the host resolves their actual values and opacity. If the host cannot resolve the token, it is treated as omitted and evaluation continues with `borderColor` without reporting an error."
},
"action": {
"$ref": "./common-types-basic.json#/$defs/Action",
"description": "Makes the entire container clickable. Uses the same Action semantics as `Button.action`: exactly one of `event` (reported to the agent) and `functionCall` (executed locally by the renderer) may be present."
},
"padding": {
"type": "number",
"minimum": 0,
"description": "Uniform padding on all four sides, unit px, must be a number and not less than 0. Containers with a background color generally need it; otherwise, the child content will be close to the edge of the color block. **Only uniform values for all four sides are supported**; individual sides or `paddingX`/`paddingY` are not supported yet. If not configured, this field will not be sent, consistent with historical version behavior. Omission is not equivalent to an explicit 0: a card root can still receive platform-specific insets from card layout, while this field adds no padding to a nested container when omitted."
},
"gap": {
"type": "number",
"minimum": 0,
"description": "Gap between children in px; must be a non-negative number. `Column` applies it vertically and `Row` horizontally; the first child is unaffected. **When omitted, hierarchy-specific defaults remain in effect**: 8 between top-level card blocks, 12 in nested columns, and 8 horizontally. Existing card spacing therefore remains unchanged."
},
"backgroundColorToken": {
"$ref": "./common-types-visual.json#/$defs/ColorToken",
"description": "Only the 57 IDs in the common `ColorToken` enum are allowed. A DDesign token name for the container background, such as `common_bg_color`. The host resolves it for the **current client platform, theme, and tenant**, and it has **higher priority than `backgroundColor`**. This is the component's only way to make its background follow dark mode; `backgroundColor` accepts a single color value and does not change with the theme. If the host cannot resolve the token, it is treated as omitted and evaluation continues with `backgroundColor` without reporting an error."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"children",
"component"
]
},
"Button": {
"type": "object",
"description": "The public `Button` component. `disabled` dims the button and removes its click action; the implementation remains compatible with the `SingleButton` builder preset.",
"properties": {
"checks": {
"type": "array",
"items": {
"$ref": "./common-types-basic.json#/$defs/CheckRule"
},
"description": "A list of checks to perform. These are function calls that must return a boolean indicating validity. **DingTalk implementation:** On click, the checks are evaluated against the latest DataModel. A failed check blocks the click and displays a toast. **This is the standard attachment point for form validation**: rules use `path` to reference the paths bound to input components, allowing the entire form to be validated at once."
},
"component": {
"const": "Button",
"description": "Component type identification field."
},
"child": {
"$ref": "./common-types-basic.json#/$defs/Child",
"description": "The ID of the child component. Use a 'Text' component for a labeled button. Only use an 'Icon' if the requirements explicitly ask for an icon-only button."
},
"variant": {
"type": "string",
"enum": [
"default",
"primary",
"borderless"
],
"description": "Button style hint; omitted means `default`. `primary` marks the main action, and `borderless` removes the background and border. When disabled is true, disabled colors take precedence."
},
"action": {
"$ref": "./common-types-basic.json#/$defs/Action",
"description": "Defines an interaction handler that can either trigger an agent-side event or execute a local renderer-side function. **DingTalk implementation:** Although required by the contract, a missing or invalid value **does not make the button disappear**. The button still renders, including its label and colors, and clicking it displays \"This action is not supported by the current version.\" See Section 1.4, \"Invalid actions do not affect rendering.\" Only `child` is required for rendering."
},
"weight": {
"type": "number",
"description": "The relative weight of this component within a Row or Column. This is similar to the CSS 'flex-grow' property. Note: this may ONLY be set when the component is a direct descendant of a Row or Column."
},
"disabled": {
"type": "boolean",
"description": "Whether the button is disabled; omitted means `false`. The current implementation uses disabled colors and attaches no click action when true; the button and its label remain visible."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"action",
"child",
"component"
]
}
},
"functions": {},
"$defs": {
"anyComponent": {
"oneOf": [
{
"$ref": "./catalog-components-common.json#/components/Button"
},
{
"$ref": "./catalog-components-common.json#/components/Card"
},
{
"$ref": "./catalog-components-common.json#/components/Column"
},
{
"$ref": "./catalog-components-common.json#/components/Divider"
},
{
"$ref": "./catalog-components-common.json#/components/Icon"
},
{
"$ref": "./catalog-components-common.json#/components/Image"
},
{
"$ref": "./catalog-components-common.json#/components/Markdown"
},
{
"$ref": "./catalog-components-common.json#/components/Row"
},
{
"$ref": "./catalog-components-common.json#/components/Tag"
},
{
"$ref": "./catalog-components-common.json#/components/Text"
}
],
"discriminator": {
"propertyName": "component"
}
},
"anyFunction": false
}
}
@@ -0,0 +1,726 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://dingtalk.com/card/a2ui/catalog-components-composition.json",
"title": "DingTalk AICard Protocol V0.8 Composition and repeated layouts",
"description": "11 components and 0 functions. A reading shard of the DingTalk public catalog, not a separate runtime catalog. Modified by DingTalk from selected entries of the A2UI v1.0 Basic Catalog; some upstream definitions and descriptions are retained. See NOTICE.",
"catalogId": "https://dingtalk.com/card/a2ui/catalogs/public/catalog.json",
"protocolVersion": "1.0",
"instructions": "Read entries needed for the current task, then follow their $ref dependencies. Common types: ./common-types-basic.json, ./common-types-extended.json and ./common-types-visual.json. Do not load all shards into the model context by default.\nCommon components: ./catalog-components-common.json.\nComposition and repeated layouts: ./catalog-components-composition.json.\nInputs and pickers: ./catalog-components-inputs.json.\nData display and media: ./catalog-components-specialized.json.\nCore functions adapted by DingTalk from A2UI: ./catalog-functions-core.json.\nDingTalk expressions and operators: ./catalog-functions-expressions.json.\nDingTalk host actions: ./catalog-functions-host-actions.json.\nSelect examples from ./examples/README.md; message structures are in ./agent-to-renderer.json.\nThis is the public DingTalk AICard Protocol V0.8 package. Use only the components, fields, functions, and common-type public values listed in the files loaded and assembled for the current scope.\nfallbackMarkdown is an optional DingTalk extension for component-level fallback content. It is used only when the current renderer cannot render the component. Unknown fields and field-validation errors do not trigger it. When omitted, the renderer displays the standard upgrade message.\nSchema references are local file references and require no HTTP access. catalogId is a runtime catalog identifier, not a file path.\nThe #/$defs/anyComponent union describes catalog-specific fields only. Validate complete component instances through the message envelope or loadSchemas().validateComponent, which combines ComponentCommon with this union and rejects unknown fields. The catalog root is not a validation entry point for complete messages or component instances. Complete messages must also conform to the main protocol; dynamic result types, component-tree references, and platform capabilities are validated at runtime.\nExpressions use {\"call\":…, \"args\":…} without an additional profile declaration. A host action must explicitly set functionCall.catalogId to urn:dingtalk:a2ui:host:v1. A public catalog HTTP identifier from a surface or component cannot replace the host Function catalog. For promptText, initialValue is the prefilled-text parameter and text is a result field, not an input parameter.\nAttach form-validation checks to the Button that submits the form. Do not rely on standard event-response fields for automatic write-back.\nUserPicker, ConversationPicker, and ImageUpload require host authorization. Server-side callbacks must still enforce business authorization.",
"components": {
"Link": {
"type": "object",
"description": "Clickable link text and navigation.",
"properties": {
"component": {
"const": "Link",
"description": "Public component type identifier."
},
"text": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "Text displayed by the link. Supports literals, data bindings, and value functions. The server localizes multilingual copy before sending it."
},
"maxLine": {
"type": "integer",
"description": "Maximum number of display lines. Omitted means 2."
},
"action": {
"$ref": "./common-types-basic.json#/$defs/Action",
"description": "Action executed when the component is clicked; only effective if the component declares click capability."
},
"weight": {
"type": "number",
"description": "Flex layout weight (used to allocate space proportionally)."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component",
"text"
]
},
"CardHeader": {
"type": "object",
"description": "Unified card header with a theme, dynamic title, dark-theme icon, and trailing content.",
"properties": {
"component": {
"const": "CardHeader",
"description": "Public component type identifier."
},
"title": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "Card header title, supports literals, data binding, and function return values."
},
"theme": {
"anyOf": [
{
"type": "string",
"enum": [
"blue",
"red",
"orange",
"green",
"pink",
"purple",
"yellow",
"water",
"olive"
]
},
{
"$ref": "./common-types-basic.json#/$defs/DataBinding"
},
{
"$ref": "./common-types-basic.json#/$defs/FunctionCall"
}
],
"description": "Semantic theme. **A single value determines four light/dark colours at once** — light and dark title colours plus light and dark header background colours. The design system fixes these pairings, so arbitrary hexadecimal colours are not accepted and the value is not split into separate fields; this is exactly why the field is an enum rather than a `colorToken`, whose contract is one token to one colour and cannot express a one-to-many relationship. The background uses the primary colour at 12%–16% opacity, and the renderer picks the light or dark variant for the active theme; the title colour is selected the same way. The default is `blue`. For compatibility, legacy cards may send a primary-colour hex value directly (`#0066FF`, `#00B853`, `#F2510C`, `#FF9200`). Unknown values fall back to `blue` without raising an error."
},
"icon": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "Header LOGO image URL, rendered to the left of the title, 16px square, with a 6px spacing from the title. If not configured, the icon position will not be rendered."
},
"darkIcon": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "Logo image URL for the dark theme. The light and dark URLs are sent together, and the renderer selects one for the current theme, updating immediately when the theme changes. If omitted, it falls back to `icon`."
},
"trailing": {
"$ref": "./common-types-basic.json#/$defs/ComponentId",
"description": "Slot on the **right side** of the title. Its value is the `id` of one component in the same surface: **a single string, not an array**. Slot content is right-aligned with a 6px gap from the title. The title occupies the remaining width and wraps when too long. Typical uses include source labels, status tags, and timestamps. To place multiple elements, put a `Row` in the slot and control spacing and alignment explicitly with its `gap` and `align`. If omitted, no trailing content is rendered."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component",
"title"
]
},
"GridLayout": {
"type": "object",
"description": "Grid layout supporting static children and data templates. Omitting columns enables adaptive column selection from card content width; setting columns fixes the column count. See the corresponding fields for omitted row-height and column-gap behavior.",
"properties": {
"component": {
"const": "GridLayout",
"description": "Public component type identifier."
},
"children": {
"$ref": "./common-types-basic.json#/$defs/ChildList",
"description": "List of child component IDs or dynamic child templates. In dynamic form, `componentId` points to the cell template, and `path` points to an array in the Data Model; the rendering results are the same for both forms, with cells laid out row by row according to `columns`."
},
"columns": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber",
"description": "Number of columns per row. **When omitted, the layout adapts to the card width** using a minimum column width of 234 and at most 3 columns; if the width is unavailable, it uses 2 columns. When specified, the exact value is used and adaptive column selection is disabled."
},
"columnGap": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber",
"description": "Column gap. May be a number or a card-protocol `DynamicNumber`. The default is 8 when `columns` is set and 12 in adaptive mode when `columns` is omitted."
},
"rowGap": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber",
"description": "Row gap. May be a number or a card-protocol `DynamicNumber`; default 8."
},
"itemHeight": {
"type": "number",
"description": "Fixed cell height. When omitted or set to 0, no fixed cell height is supplied to the renderer; final height is determined by its layout. Set a positive number when a fixed height is required."
},
"weight": {
"type": "number",
"description": "Flex layout weight (used to allocate space proportionally)."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"children",
"component"
]
},
"Loop": {
"type": "object",
"description": "Data-driven repeated-rendering container. Repeated items are arranged vertically; dimensions follow the template content and parent layout.",
"properties": {
"component": {
"const": "Loop",
"description": "Public component type identifier."
},
"children": {
"description": "The template and data path structure is the same as the dynamic ChildList.",
"allOf": [
{
"$ref": "./common-types-basic.json#/$defs/ChildList"
},
{
"type": "object",
"properties": {
"componentId": {
"$ref": "./common-types-basic.json#/$defs/ComponentId",
"description": "Loop item template component ID."
},
"path": {
"type": "string",
"description": "The absolute JSON Pointer of the Data Model array."
}
},
"required": [
"componentId",
"path"
]
}
]
},
"weight": {
"type": "number",
"description": "Flex layout weight (used to allocate space proportionally)."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"children",
"component"
]
},
"Stack": {
"type": "object",
"description": "Z-axis stacking container: A **base layer** determines the size, on which 0~N **overlay layers** are stacked.",
"properties": {
"component": {
"const": "Stack",
"description": "Public component type identifier."
},
"child": {
"$ref": "./common-types-basic.json#/$defs/Child",
"description": "The component ID of the **base layer**, single. It fills the entire Stack and **determines the container size**; overlay layers are positioned relative to it. To place multiple elements, wrap them with `Row` / `Column` before passing them here."
},
"overlays": {
"type": "array",
"items": {
"type": "object",
"properties": {
"child": {
"$ref": "./common-types-basic.json#/$defs/Child",
"description": "The component ID of this overlay layer."
},
"position": {
"type": "string",
"enum": [
"topStart",
"topCenter",
"topEnd",
"centerStart",
"center",
"centerEnd",
"bottomStart",
"bottomCenter",
"bottomEnd"
],
"description": "The placement of this overlay on the base layer takes values from the same set of nine-level two-dimensional alignment vocabulary as `ColumnLayout.contentAlignment`."
}
},
"required": [
"child",
"position"
]
},
"description": "**Overlay layer** list, stacked on top of the base layer from bottom to top according to the array order. Each item is an object, only accepting the keys `child` and `position`, both of which are required. If omitted, only the base child is shown and no overlays are created."
},
"backgroundColorToken": {
"$ref": "./common-types-visual.json#/$defs/ColorToken",
"description": "Only the 57 IDs in the common `ColorToken` enum are allowed. A DDesign token name for the container background, with **higher priority than `backgroundColor`**. Its values and behavior match the same field on `Row` and `Column`."
},
"backgroundColor": {
"type": "string",
"description": "Container background color, hexadecimal `#RRGGBB` or `#AARRGGBB`. A semi-transparent overlay placed over the image is a typical use of a stacked container. If not set, it is transparent."
},
"cornerRadius": {
"type": "number",
"description": "Corner radius, in px, must be a number. If omitted, no explicit radius is set and host container defaults remain in effect."
},
"borderWidth": {
"type": "number",
"description": "Border width in px; must be a number. **A visible border requires `borderColor` to be configured as well.**"
},
"borderColor": {
"type": "string",
"description": "Stroke color, the value format is the same as `backgroundColor`."
},
"borderColorToken": {
"$ref": "./common-types-visual.json#/$defs/ColorToken",
"description": "Only the 57 IDs in the common `ColorToken` enum are allowed. A DDesign token name for the border color. It has **higher priority than `borderColor`** and is resolved by the host for the **current client platform, theme, and tenant**. This is the only way to make the border follow light and dark themes: `borderColor` accepts a single value that remains unchanged in dark mode. The line-color families are `common_line_light_color` and `common_line_hard_color`; the host resolves their actual values and opacity. If the host cannot resolve the token, it is treated as omitted and evaluation continues with `borderColor` without reporting an error."
},
"padding": {
"type": "number",
"description": "Uniform padding on all four sides in px. Use it to keep overlays away from the container edge. If omitted, this field adds no padding; a card root can still receive insets from card layout."
},
"action": {
"$ref": "./common-types-basic.json#/$defs/Action",
"description": "Makes the entire container clickable, using the same Action semantics as the `action` field on `Row` / `Column`."
},
"weight": {
"type": "number",
"description": "Flex layout weight."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"child",
"component"
]
},
"ScrollView": {
"type": "object",
"description": "A horizontal or vertical scroll container.",
"properties": {
"component": {
"const": "ScrollView",
"description": "Public component type identifier."
},
"direction": {
"type": "string",
"enum": [
"horizontal",
"vertical"
],
"description": "Scroll direction; omitted means `vertical`. Vertical scrolling additionally requires a positive maxHeight to bound the viewport; horizontal scrolling is constrained by available width."
},
"autoScrollOnUpdate": {
"type": "boolean",
"description": "Automatically scrolls to the end after content updates: to the far right horizontally or to the bottom vertically. Defaults to `false`. During streaming output, PC also blocks user scrolling so follow-scrolling is not interrupted. This applies only to **scrollable** configurations: `direction: \"horizontal\"`, or `direction: \"vertical\"` with `maxHeight`. An uncapped vertical list does not scroll, so this field has no effect there."
},
"maxHeight": {
"type": "number",
"description": "Viewport height limit. When omitted or set to 0, no height limit is set and vertical content expands without internal scrolling. A positive value limits viewport height in both horizontal and vertical modes. Vertical mode also enables internal scrolling; horizontal scrolling still depends on content exceeding the available width."
},
"children": {
"$ref": "./common-types-basic.json#/$defs/ChildList",
"description": "List of child component IDs, all references must exist in the current surface."
},
"action": {
"$ref": "./common-types-basic.json#/$defs/Action",
"description": "Defines an interaction handler that can either trigger an agent-side event or execute a local renderer-side function."
},
"weight": {
"type": "number",
"description": "Flex layout weight (used to allocate space proportionally)."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component"
]
},
"Tabs": {
"type": "object",
"description": "Tab header and content panel.",
"properties": {
"component": {
"const": "Tabs",
"description": "Component type identification field."
},
"tabs": {
"type": "array",
"items": {
"type": "object",
"properties": {
"title": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "The tab title."
},
"child": {
"$ref": "./common-types-basic.json#/$defs/Child",
"description": "The ID of the child component."
},
"action": {
"$ref": "./common-types-basic.json#/$defs/Action",
"description": "When switching to this tab, report: First, the renderer locally switches to the selected state, and then sends the event to the agent. **Each tab is configured independently**; tabs that are not configured only perform local switching and do not report. Only the `event` branch is supported; writing `functionCall` will not work (treated as `action` that is not configured)."
}
},
"required": [
"title",
"child"
]
},
"description": "An array of objects, where each object defines a tab with a title and a child component. The first array entry is initially selected. Subsequent selection is maintained locally; there is no public initial-tab selection field."
},
"weight": {
"type": "number",
"description": "The relative weight of this component within a Row or Column. This is similar to the CSS 'flex-grow' property. Note: this may ONLY be set when the component is a direct descendant of a Row or Column."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component",
"tabs"
]
},
"List": {
"type": "object",
"description": "The public `List` component. `direction` unifies horizontal, vertical, and data-driven lists.",
"properties": {
"component": {
"const": "List",
"description": "Component type identification field."
},
"children": {
"$ref": "./common-types-basic.json#/$defs/ChildList",
"description": "Defines the children. Use an array of strings for a fixed set of children, or a template object to generate children from a data list."
},
"direction": {
"type": "string",
"enum": [
"vertical",
"horizontal"
],
"description": "The direction in which the list items are laid out. Omitted means `vertical`."
},
"align": {
"type": "string",
"enum": [
"start",
"center",
"end",
"stretch"
],
"description": "Defines the alignment of children along the cross axis. Omitted means `stretch`."
},
"wrap": {
"type": "boolean",
"description": "Whether children wrap to the next line when they do not fit; default `false`. **Effective only with `direction: horizontal`.** A vertical container has unbounded height in a card, so wrapping can never occur; `wrap: true` on a vertical List is ignored and the component still renders normally. ⚠️ **Incompatible with child `weight`**: a weighted child fills the row and prevents wrapping. Do not assign child `weight` when wrapping is required."
},
"weight": {
"type": "number",
"description": "The relative weight of this component within a Row or Column. This is similar to the CSS 'flex-grow' property. Note: this may ONLY be set when the component is a direct descendant of a Row or Column."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"children",
"component"
]
},
"CollapsiblePanel": {
"type": "object",
"description": "Unified collapsible panel, collapsed by default. `variant` controls the expanded-content style: `indented` uses an indented left rule, while `reasoning` uses a flat agent-reasoning layout. `defaultExpanded` can expand the first frame, `maxHeight` enables internal scrolling after a height limit, and `textEffect` can add a shimmer effect to the title.",
"properties": {
"component": {
"const": "CollapsiblePanel",
"description": "Public component type identifier."
},
"title": {
"type": "string",
"minLength": 1,
"description": "Collapsible-panel title. The current integration requires non-empty text."
},
"textEffect": {
"type": "string",
"enum": [
"shimmer"
],
"description": "Text presentation effect. `shimmer` repeatedly sweeps a highlight across the text and is intended for streaming wait states such as \"Thinking...\". If omitted, no effect is applied. On `CollapsiblePanel`, it applies to the panel title. The field is sent consistently to all clients. The effect currently works only on iOS; unsupported clients silently ignore it and render regular text without affecting the text itself. No protocol change is required when those clients add support."
},
"icon": {
"type": "string",
"description": "Light mode title icon address."
},
"darkIcon": {
"type": "string",
"description": "Dark mode title icon URL; falls back to icon if not provided."
},
"variant": {
"type": "string",
"enum": [
"indented",
"reasoning"
],
"description": "Expanded-content style. `indented`, the default, draws a thin vertical line on the left and indents the content to convey details subordinate to the title; it suits step details and tool-call lists. `reasoning` omits the line and aligns the content with the title, marking the panel as an agent execution or reasoning container; it suits cases where the title acts as a toggle and the content itself is first-class information. The field affects only the expanded content's appearance and this semantic marking: collapse behaviour, `defaultExpanded` and `maxHeight` scrolling are identical in both styles."
},
"defaultExpanded": {
"type": "boolean",
"description": "Whether the first frame is expanded, default is false (collapsed). The semantic of a collapsible panel is \"keep it closed first, click to open if you want to see it,\" so the default is collapsed; panels that really need to be expanded from the start should explicitly set it to true. The expanded/collapsed state after the user clicks the title is maintained locally by the renderer and is not affected by this field."
},
"maxHeight": {
"type": "number",
"description": "Maximum height of the expanded content area in px; default 300. Content that exceeds the limit scrolls inside the panel instead of extending the entire card. Shorter content uses only its actual height without leaving blank space. A value of 0 removes the height limit."
},
"children": {
"$ref": "./common-types-basic.json#/$defs/ChildList",
"description": "List of child component IDs or data-driven templates."
},
"colorToken": {
"$ref": "./common-types-visual.json#/$defs/ColorToken",
"description": "Only the 57 IDs in the common `ColorToken` enum are allowed. A DDesign token name with **the highest color-resolution priority**. When resolved, `customLightColor` and `customDarkColor` are ignored. It uses the same resolution mechanism as `Text.colorToken`."
},
"customLightColor": {
"type": "string",
"description": "The title color in light mode, in hexadecimal. Only effective when `colorToken` is not matched."
},
"customDarkColor": {
"type": "string",
"description": "Title color in dark mode, in hexadecimal. Only effective when `colorToken` is not hit."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"children",
"component",
"title"
]
},
"ColumnLayout": {
"type": "object",
"description": "Responsive columns from one to six.",
"properties": {
"component": {
"const": "ColumnLayout",
"description": "Public component type identifier."
},
"children": {
"$ref": "./common-types-basic.json#/$defs/ChildList",
"description": "List of child component IDs or data-driven templates."
},
"columns": {
"type": "integer",
"minimum": 1,
"maximum": 6,
"description": "Column-count hint at normal width, from 1 to 6; internally defaults to 2. The current horizontal layout allocates width to the children and their weights rather than grouping or wrapping by this field. Supply two child columns for a two-column layout."
},
"gap": {
"type": "number",
"description": "Column spacing. Omitted means 8; used as vertical spacing after responsive stacking."
},
"columnWidths": {
"type": "array",
"items": {
"anyOf": [
{
"type": "number"
},
{
"const": "auto"
}
]
},
"description": "Child-column weights or auto, corresponding to children in order. Used to allocate width only in horizontal layout; an explicit weight on a child takes precedence. If omitted, children without their own weight receive equal weights. This field no longer allocates width after responsive stacking into a vertical column."
},
"contentAlignment": {
"type": "string",
"enum": [
"topStart",
"topCenter",
"topEnd",
"centerStart",
"center",
"centerEnd",
"bottomStart",
"bottomCenter",
"bottomEnd"
],
"description": "Two-dimensional content alignment; the vocabulary is the same nine-level set as `Stack.overlays[].position`. Columns themselves are evenly weighted, so what this actually controls is **the alignment of each column along the cross axis (vertical)**: when column heights differ, it decides whether the shorter column is aligned to the top, centre or bottom."
},
"responsive": {
"type": "boolean",
"description": "**Responsive stacking on narrow cards**; defaults to false. When enabled with responsiveColumns omitted or set to 1, child columns stack vertically on narrow cards and gap becomes vertical spacing. On wider cards, the actual children and their weights retain a horizontal layout. See the responsive behavior section."
},
"responsiveColumns": {
"type": "integer",
"description": "The number of target columns on a narrow screen, default is `1`; it only takes effect when configured together with `responsive: true`. **Currently only `1` is available**—setting other values does not reduce the columns, keeping the original layout on narrow screens."
},
"weight": {
"type": "number",
"description": "Flex layout weight (used to allocate space proportionally)."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"children",
"component"
]
},
"ButtonGroup": {
"type": "object",
"description": "A row of buttons arranged side by side, each button comes with its own text and action. The button style is exactly the same as the standalone `Button` (the same set of capsule styles), the only difference is that multiple buttons are declared at once using an array, with unified control over spacing and wrapping.",
"properties": {
"component": {
"const": "ButtonGroup",
"description": "Component type identification field."
},
"buttons": {
"type": "array",
"items": {
"type": "object",
"properties": {
"label": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "Button text. When missing or empty, the entire component degrades to a placeholder."
},
"variant": {
"type": "string",
"enum": [
"default",
"primary",
"borderless"
],
"description": "Button visual variant. Values have the same meaning as the standalone `Button` component's `variant`; default `default`. Values outside the vocabulary render as `default`."
},
"disabled": {
"type": "boolean",
"description": "Whether to disable, default `false`. Disabled items are grayed out **and do not have click events attached**."
},
"action": {
"$ref": "./common-types-basic.json#/$defs/Action",
"description": "Action when clicked. **If this is not configured, it is just an unclickable label**—it does not mint a token or enter the action list."
},
"metadata": {
"description": "Extension metadata for the current button. Host-action write-back uses this item's `dt_actionBindingsV1.action` and does not inherit parent-component metadata."
}
},
"required": [
"label"
],
"allOf": [
{
"$ref": "./common-types-extended.json#/$defs/HostActionOwner"
}
]
},
"description": "Button definition list **cannot be an empty array**. An empty array will cause the entire component to degrade to a placeholder."
},
"responsive": {
"type": "boolean",
"description": "**Adaptive line wrapping for wide and narrow screens**, default `false`. See the 'Responsive Behavior' below."
},
"gap": {
"type": "number",
"description": "Horizontal gap between adjacent buttons in px; default `8`. No gap is added before the first button."
},
"weight": {
"type": "number",
"description": "Relative flex factor when used as a direct child of a Row or Column."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"buttons",
"component"
]
}
},
"functions": {},
"$defs": {
"anyComponent": {
"oneOf": [
{
"$ref": "./catalog-components-composition.json#/components/ButtonGroup"
},
{
"$ref": "./catalog-components-composition.json#/components/CardHeader"
},
{
"$ref": "./catalog-components-composition.json#/components/CollapsiblePanel"
},
{
"$ref": "./catalog-components-composition.json#/components/ColumnLayout"
},
{
"$ref": "./catalog-components-composition.json#/components/GridLayout"
},
{
"$ref": "./catalog-components-composition.json#/components/Link"
},
{
"$ref": "./catalog-components-composition.json#/components/List"
},
{
"$ref": "./catalog-components-composition.json#/components/Loop"
},
{
"$ref": "./catalog-components-composition.json#/components/ScrollView"
},
{
"$ref": "./catalog-components-composition.json#/components/Stack"
},
{
"$ref": "./catalog-components-composition.json#/components/Tabs"
}
],
"discriminator": {
"propertyName": "component"
}
},
"anyFunction": false
}
}
@@ -0,0 +1,860 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://dingtalk.com/card/a2ui/catalog-components-inputs.json",
"title": "DingTalk AICard Protocol V0.8 Inputs and pickers",
"description": "14 components and 0 functions. A reading shard of the DingTalk public catalog, not a separate runtime catalog. Modified by DingTalk from selected entries of the A2UI v1.0 Basic Catalog; some upstream definitions and descriptions are retained. See NOTICE.",
"catalogId": "https://dingtalk.com/card/a2ui/catalogs/public/catalog.json",
"protocolVersion": "1.0",
"instructions": "Read entries needed for the current task, then follow their $ref dependencies. Common types: ./common-types-basic.json, ./common-types-extended.json and ./common-types-visual.json. Do not load all shards into the model context by default.\nCommon components: ./catalog-components-common.json.\nComposition and repeated layouts: ./catalog-components-composition.json.\nInputs and pickers: ./catalog-components-inputs.json.\nData display and media: ./catalog-components-specialized.json.\nCore functions adapted by DingTalk from A2UI: ./catalog-functions-core.json.\nDingTalk expressions and operators: ./catalog-functions-expressions.json.\nDingTalk host actions: ./catalog-functions-host-actions.json.\nSelect examples from ./examples/README.md; message structures are in ./agent-to-renderer.json.\nThis is the public DingTalk AICard Protocol V0.8 package. Use only the components, fields, functions, and common-type public values listed in the files loaded and assembled for the current scope.\nfallbackMarkdown is an optional DingTalk extension for component-level fallback content. It is used only when the current renderer cannot render the component. Unknown fields and field-validation errors do not trigger it. When omitted, the renderer displays the standard upgrade message.\nSchema references are local file references and require no HTTP access. catalogId is a runtime catalog identifier, not a file path.\nThe #/$defs/anyComponent union describes catalog-specific fields only. Validate complete component instances through the message envelope or loadSchemas().validateComponent, which combines ComponentCommon with this union and rejects unknown fields. The catalog root is not a validation entry point for complete messages or component instances. Complete messages must also conform to the main protocol; dynamic result types, component-tree references, and platform capabilities are validated at runtime.\nExpressions use {\"call\":…, \"args\":…} without an additional profile declaration. A host action must explicitly set functionCall.catalogId to urn:dingtalk:a2ui:host:v1. A public catalog HTTP identifier from a surface or component cannot replace the host Function catalog. For promptText, initialValue is the prefilled-text parameter and text is a result field, not an input parameter.\nAttach form-validation checks to the Button that submits the form. Do not rely on standard event-response fields for automatic write-back.\nUserPicker, ConversationPicker, and ImageUpload require host authorization. Server-side callbacks must still enforce business authorization.",
"components": {
"TextField": {
"type": "object",
"description": "The public `TextField` component. `variant` unifies short and multiline text input. Clicking opens the input panel and displays the result locally; the field can be disabled. The checks field is not supported. Attach input validation to the submit Button.checks and reference the value binding with a path.",
"properties": {
"component": {
"const": "TextField",
"description": "Component type identification field."
},
"label": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "The text label for the input field."
},
"value": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "The value of the text field. If omitted, the initial text is empty. Configure a DataBinding to submit user input; omitting value does not create a writeback path."
},
"placeholder": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "The placeholder text for the input field. If omitted, it is empty; label is not automatically used as the placeholder."
},
"variant": {
"type": "string",
"enum": [
"shortText",
"longText"
],
"description": "Input variant; default `shortText`. `longText` opens a multiline input panel. DingTalk has no equivalent runtime input type for the base protocol's `number` and `obscured` variants, so this enum exposes only these two values."
},
"weight": {
"type": "number",
"description": "The relative weight of this component within a Row or Column. This is similar to the CSS 'flex-grow' property. Note: this may ONLY be set when the component is a direct descendant of a Row or Column."
},
"disabled": {
"type": "boolean",
"description": "Whether to disable, default is `false`. When set to `true`, **input events are not triggered** (clicking no longer opens the input panel), **and the text is grayed out** (use the disabled color if there is a value; if there is no value, it is already placeholder gray)."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component",
"label"
]
},
"ChoicePicker": {
"type": "object",
"description": "The public `ChoicePicker` component. `variant` unifies single and multiple selection, `displayStyle` selects row, chip, or dropdown presentation, and `disabled` dims the entire group.",
"properties": {
"checks": {
"type": "array",
"items": {
"$ref": "./common-types-basic.json#/$defs/CheckRule"
},
"description": "Evaluated only when `action` is configured. Local state may already have been updated or echoed; a failed check blocks the subsequent Action and shows a toast, but does not guarantee preventing or rolling back the local selection. Attach form validation to the submit button."
},
"component": {
"const": "ChoicePicker",
"description": "Component type identification field."
},
"label": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "The label for the group of options."
},
"variant": {
"type": "string",
"enum": [
"multipleSelection",
"mutuallyExclusive"
],
"description": "A hint for how the choice picker should be displayed and behave. Omitted means `mutuallyExclusive` (single selection); explicitly use `multipleSelection` for multiple selection."
},
"options": {
"type": "array",
"items": {
"type": "object",
"properties": {
"label": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "The text to display for this option."
},
"value": {
"type": "string",
"description": "The stable value associated with this option."
}
},
"required": [
"label",
"value"
]
},
"description": "The list of available options to choose from."
},
"value": {
"$ref": "./common-types-basic.json#/$defs/DynamicStringList",
"description": "The list of currently selected values. This should be bound to a string array in the data model."
},
"displayStyle": {
"type": "string",
"enum": [
"checkbox",
"chips",
"dropdown"
],
"description": "Display style: `checkbox` lays out a vertical list of clickable rows; `chips` lays out a row of tags; `dropdown` renders one compact row that opens the native client picker. **If omitted, `dropdown` is used**. Values outside the enum also fall back to `dropdown` rather than a placeholder."
},
"action": {
"$ref": "./common-types-basic.json#/$defs/Action",
"description": "**Effective only for `displayStyle: dropdown`, the default when omitted.** After the user confirms a selection in the native panel, the renderer first writes the new value to the path bound by `value` and then sends the event to the agent. Canceling the panel does not trigger the action. Inline styles (`checkbox` and `chips`) **do not trigger** `action` because they have no confirmation step. Their selected values are written to local state through the `value` binding and collected by the submit button's `context` through the parent path."
},
"weight": {
"type": "number",
"description": "The relative weight of this component within a Row or Column. This is similar to the CSS 'flex-grow' property. Note: this may ONLY be set when the component is a direct descendant of a Row or Column."
},
"disabled": {
"type": "boolean",
"description": "Whether to disable, default is `false`. When set to `true`, **click events are not triggered** (the selection panel will no longer open / options cannot be switched), **and the text, selected mark, and selected background color all switch to the disabled state**."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component",
"options",
"value"
]
},
"CheckBox": {
"type": "object",
"description": "Boolean selection. The required value determines the initial checked state, and label is displayed with the checkbox.",
"properties": {
"checks": {
"type": "array",
"items": {
"$ref": "./common-types-basic.json#/$defs/CheckRule"
},
"description": "Evaluated only when `action` is configured. Local state may already have been updated or echoed; a failed check blocks the subsequent Action and shows a toast, but does not guarantee preventing or rolling back the local selection. Attach form validation to the submit button."
},
"component": {
"const": "CheckBox",
"description": "Component type identification field."
},
"label": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "The text to display next to the checkbox."
},
"value": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "The current state of the checkbox (true for checked, false for unchecked)."
},
"action": {
"$ref": "./common-types-basic.json#/$defs/Action",
"description": "Reports after the checked state changes. The renderer first toggles the value locally and writes it to the path bound by `value`, then sends the event to the agent. Only the `event` branch is supported; a `functionCall` branch is ignored as if `action` were omitted."
},
"weight": {
"type": "number",
"description": "The relative weight of this component within a Row or Column. This is similar to the CSS 'flex-grow' property. Note: this may ONLY be set when the component is a direct descendant of a Row or Column."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component",
"label",
"value"
]
},
"Switch": {
"type": "object",
"description": "Switch state and size.",
"properties": {
"component": {
"const": "Switch",
"description": "Public component type identifier."
},
"value": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Whether the switch is selected. Omitted means false, initially off."
},
"disabled": {
"type": "boolean",
"description": "Whether the switch is disabled; default `false`. When `true`, the renderer sends `enabled=0`; the native client switch **cannot be toggled and is dimmed using the system style**."
},
"size": {
"type": "string",
"enum": [
"small",
"normal",
"large"
],
"description": "Size preset; default `normal`."
},
"action": {
"$ref": "./common-types-basic.json#/$defs/Action",
"description": "Reports after the switch state changes. The renderer first toggles the value locally, then sends the event to the agent. Only the `event` branch is supported; a `functionCall` branch is ignored as if `action` were omitted."
},
"weight": {
"type": "number",
"description": "Flex layout weight (used to allocate space proportionally)."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component"
]
},
"DateTimeInput": {
"type": "object",
"description": "Date and time picker entry.",
"properties": {
"checks": {
"type": "array",
"items": {
"$ref": "./common-types-basic.json#/$defs/CheckRule"
},
"description": "Evaluated only when `action` is configured. Local state may already have been updated or echoed; a failed check blocks the subsequent Action and shows a toast, but does not guarantee preventing or rolling back the local selection. Attach form validation to the submit button."
},
"component": {
"const": "DateTimeInput",
"description": "Component type identification field."
},
"value": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "The selected date and/or time value in ISO 8601 format. If not yet set, initialize with an empty string."
},
"enableDate": {
"type": "boolean",
"description": "If true, allows the user to select a date. Omitted means true."
},
"enableTime": {
"type": "boolean",
"description": "If true, allows the user to select a time. Omitted means false, so omitting both flags selects dates only. enableDate and enableTime cannot both be false."
},
"min": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "The minimum allowed date/time in ISO 8601 format."
},
"max": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "The maximum allowed date/time in ISO 8601 format."
},
"label": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "The text label for the input field."
},
"action": {
"$ref": "./common-types-basic.json#/$defs/Action",
"description": "Reports after the user confirms a value in the date/time panel. The renderer first writes the new value to the path bound by `value` and then sends the event to the agent. Canceling the picker does not report an event."
},
"weight": {
"type": "number",
"description": "The relative weight of this component within a Row or Column. This is similar to the CSS 'flex-grow' property. Note: this may ONLY be set when the component is a direct descendant of a Row or Column."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component",
"value"
]
},
"NumberInput": {
"type": "object",
"description": "Numeric input entry that opens an input panel and displays the result. It is not currently a stepper with increment/decrement buttons. The required value supplies the initial number.",
"properties": {
"component": {
"const": "NumberInput",
"description": "Public component type identifier."
},
"value": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber",
"description": "Current value."
},
"label": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "Input label used as the numeric input panel title. It also supplies the placeholder text when placeholder is omitted or an empty string; TextField does not automatically substitute label for placeholder."
},
"min": {
"type": "number",
"description": "Minimum. If omitted, no explicit lower bound is supplied to the input panel."
},
"max": {
"type": "number",
"description": "Maximum value. If omitted, no explicit upper bound is supplied to the input panel."
},
"precision": {
"type": "integer",
"description": "Decimal precision. Omitted means 0."
},
"placeholder": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "Placeholder text."
},
"disabled": {
"type": "boolean",
"description": "Whether to disable, default is `false`. When it is `true`, **input events are not triggered** (clicking no longer opens the numeric input panel), **and the text is grayed out**. Implemented with the same form row as `TextField`."
},
"action": {
"$ref": "./common-types-basic.json#/$defs/Action",
"description": "Reports after the user completes an edit in the input panel. The renderer first writes the new value to the path bound by `value`, then sends the event to the agent. Only the `event` branch is supported; a `functionCall` branch is ignored as if `action` were omitted."
},
"weight": {
"type": "number",
"description": "Flex layout weight (used to allocate space proportionally)."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component",
"value"
]
},
"Rating": {
"type": "object",
"description": "Star rating.",
"properties": {
"component": {
"const": "Rating",
"description": "Public component type identifier."
},
"value": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber",
"description": "Rating value (0-5)."
},
"onTap": {
"$ref": "./common-types-basic.json#/$defs/Action",
"description": "Reports after the user changes the rating. The renderer **first writes the new rating to the path bound by `value`, then sends the event to the agent**. The rating is interactive only when this handler is configured; otherwise it is read-only. Only the `event` branch is supported. A `functionCall` branch is ignored as if `onTap` were omitted because a host function would occupy the star control's click slot and prevent the local rating change."
},
"weight": {
"type": "number",
"description": "Flex layout weight (used to allocate space proportionally)."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component",
"value"
]
},
"Slider": {
"type": "object",
"description": "Numeric slider. DingTalk renders it as a **read-only progress bar** whose proportion is calculated from `value`, `min`, and `max`; it cannot be dragged.",
"properties": {
"checks": {
"type": "array",
"items": {
"$ref": "./common-types-basic.json#/$defs/CheckRule"
},
"description": "Evaluated after a click only when `action` is configured. A failed check blocks the subsequent Action and shows a toast; no checks run without an action. Attach form validation to the submit button."
},
"component": {
"const": "Slider",
"description": "Component type identification field."
},
"label": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "The label for the slider."
},
"min": {
"type": "number",
"description": "The minimum value of the slider. Omitted means 0."
},
"max": {
"type": "number",
"description": "The maximum value of the slider."
},
"value": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber",
"description": "The current value of the slider."
},
"weight": {
"type": "number",
"description": "The relative weight of this component within a Row or Column. This is similar to the CSS 'flex-grow' property. Note: this may ONLY be set when the component is a direct descendant of a Row or Column."
},
"action": {
"$ref": "./common-types-basic.json#/$defs/Action",
"description": "Report to the agent when clicking the progress bar."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component",
"max",
"value"
]
},
"InputList": {
"type": "object",
"description": "Input list whose rows can be added and removed.",
"properties": {
"component": {
"const": "InputList",
"description": "Public component type identifier."
},
"label": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "Input-list title."
},
"value": {
"$ref": "./common-types-basic.json#/$defs/DynamicStringList",
"description": "Addable and removable string array that should be bound to the Data Model. The array sent by the server determines the initial row count and values. After local additions, deletions, or edits, the submit button's `context` on the same card reads **the complete current local array**, including locally added rows, through this path."
},
"placeholder": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "Placeholder hint for the new input item."
},
"addLabel": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "Label for adding an item. If omitted, the runtime supplies its built-in text; explicitly set it for application-specific wording or language."
},
"variant": {
"type": "string",
"enum": [
"shortText",
"longText"
],
"description": "Input variant for each row; default `shortText`. `longText` renders a multiline text area, while other values use `shortText`. ⚠️ The `inline` and `dialog` values documented previously **were never implemented** and silently render as `shortText`."
},
"disabled": {
"type": "boolean",
"description": "Whether the list is disabled; default `false`. When `true`, **no input events are attached, the Add control and per-row delete buttons are not rendered, and the text and label are dimmed**. The row count remains fixed at the number initially sent by the server."
},
"action": {
"$ref": "./common-types-basic.json#/$defs/Action",
"description": "Reports when Add is clicked. The renderer first adds a row locally, then sends the event to the agent. Row deletion and per-row editing **do not report events**; they update only local state and are merged into the DataModel through the path bound by `value` on submission. Only the `event` branch is supported; a `functionCall` branch is ignored as if `action` were omitted."
},
"weight": {
"type": "number",
"description": "Flex layout weight (used to allocate space proportionally)."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component",
"value"
]
},
"CheckboxListMulti": {
"type": "object",
"description": "Multi-select list and local state.",
"properties": {
"component": {
"const": "CheckboxListMulti",
"description": "Public component type identifier."
},
"children": {
"description": "Dynamic `ChildList` used to declare a bindable multi-select list.",
"allOf": [
{
"$ref": "./common-types-basic.json#/$defs/ChildList"
},
{
"type": "object",
"properties": {
"componentId": {
"$ref": "./common-types-basic.json#/$defs/ComponentId",
"description": "Subcomponent template reused for each row."
},
"path": {
"type": "string",
"description": "The absolute JSON Pointer of the Data Model array."
}
},
"required": [
"componentId",
"path"
]
}
]
},
"selectedIndexes": {
"type": "array",
"items": {
"type": "integer"
},
"description": "**Initial** selected row indexes, zero-based and sent one way. User changes do not update this field itself; configure `value` to capture the result. If omitted, no rows are initially selected."
},
"size": {
"type": "string",
"enum": [
"small",
"middle",
"large"
],
"description": "Option-row size; default `middle`."
},
"disabled": {
"type": "boolean",
"description": "Whether the control is disabled; default `false`. When `true`, **do not attach click events** (an attached handler still responds to clicks while the state stays unchanged, which is more confusing than being unclickable); **whether it is greyed out is decided by the renderer's checkbox**."
},
"contentCheckable": {
"type": "boolean",
"description": "Whether clicking the entire row toggles its selected state; default `true`."
},
"action": {
"$ref": "./common-types-basic.json#/$defs/Action",
"description": "After the check status of any row is toggled, it will be reported (first change the local status on the renderer, then send the event to the agent). Only the `event` branch is supported; writing `functionCall` will not work (treated as unconfigured `action`)."
},
"value": {
"$ref": "./common-types-basic.json#/$defs/DataBinding",
"description": "Write-back path for the selection result. The value written back is **an array of selected row indexes**, with the same semantics as `selectedIndexes`. If omitted, no value is written back and the submit button cannot reference the selection. No write-back occurs when `disabled` is true."
},
"weight": {
"type": "number",
"description": "Flex layout weight (used to allocate space proportionally)."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"children",
"component"
]
},
"CheckableImageList": {
"type": "object",
"description": "Selectable layout for one to nine images, cropped to 4:3 with row and column gaps of 12. Column count follows card width and falls back to 2 when width is unavailable. Desktop hosts supporting layout-time reflow recalculate 1–5 columns from actual component width; other hosts use the width-based count.",
"properties": {
"component": {
"const": "CheckableImageList",
"description": "Public component type identifier."
},
"images": {
"type": "array",
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "object",
"properties": {
"url": {
"type": "string",
"description": "Image URL."
},
"title": {
"type": "string",
"description": "Image title."
}
},
"required": [
"url"
]
}
]
},
"minItems": 1,
"maxItems": 9,
"description": "One to nine images. The object form requires `url` and accepts an optional string `title`. If any item has a title, the title area is reserved for every item. The selected index matches the item's original position."
},
"value": {
"$ref": "./common-types-basic.json#/$defs/DataBinding",
"description": "DataBinding that stores the selected image indexes."
},
"previewEnabled": {
"type": "boolean",
"description": "Whether image clicks can open a preview; omitted means true. Only loadable URLs participate in preview. Setting false disables image preview, not selection."
},
"weight": {
"type": "number",
"description": "Flex layout weight (used to allocate space proportionally)."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component",
"images",
"value"
]
},
"UserPicker": {
"type": "object",
"description": "Opens the DingTalk contact picker to select users.",
"properties": {
"component": {
"const": "UserPicker",
"description": "Public component type identifier."
},
"placeholder": {
"type": "string",
"description": "Placeholder text. For an empty selection, the displayed prompt uses title first, then placeholder; omitting both uses the runtime's built-in prompt."
},
"title": {
"type": "string",
"description": "Picker-panel title."
},
"maxSelections": {
"type": "number",
"description": "Maximum selectable number of users (default 10); setting it to `1` means single selection, and greater than `1` means multiple selection."
},
"value": {
"$ref": "./common-types-basic.json#/$defs/DataBinding",
"description": "The DataBinding of the selected user. DingTalk currently retains the original result form of the host selector: a successful single selection writes back the user object, a successful multiple selection writes back an array of user objects, and clearing multiple selections writes back an empty array."
},
"disabled": {
"type": "boolean",
"description": "Whether to disable, default is `false`. When it is `true`, **do not trigger the click event** (no longer open the selection panel), **and the plus icon on the right is grayed out**."
},
"action": {
"$ref": "./common-types-basic.json#/$defs/Action",
"description": "Defines an interaction handler that can either trigger an agent-side event or execute a local renderer-side function."
},
"weight": {
"type": "number",
"description": "Flex layout weight (used to allocate space proportionally)."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component",
"value"
]
},
"ConversationPicker": {
"type": "object",
"description": "Call the DingTalk conversation selector.",
"properties": {
"component": {
"const": "ConversationPicker",
"description": "Public component type identifier."
},
"placeholder": {
"type": "string",
"description": "Placeholder text. For an empty selection, the displayed prompt uses title first, then placeholder; omitting both uses the runtime's built-in prompt."
},
"title": {
"type": "string",
"description": "Picker-panel title."
},
"multiple": {
"type": "boolean",
"description": "Whether multiple selection is allowed. Omitting both multiple and maxSelections gives single selection. Explicit multiple=true or maxSelections greater than 1 enables multiple selection. Single-selection results may be an object or a one-element array depending on the host; multiple-selection results are arrays."
},
"maxSelections": {
"type": "number",
"description": "Maximum selection count. Omitted means 1 when multiple selection is not enabled; a value greater than 1 also enables multiple selection. With explicit multiple=true and no maxSelections, the host determines the limit. Set an explicit value when a fixed limit is required."
},
"value": {
"$ref": "./common-types-basic.json#/$defs/DataBinding",
"description": "DataBinding for selected conversations. DingTalk currently preserves the host picker's original result shape: successful single selection may write back a conversation object or a single-element object array; successful multiple selection writes back an array of conversation objects; confirming an empty selection writes back an empty array."
},
"disabled": {
"type": "boolean",
"description": "Whether the picker is disabled; default `false`. When `true`, **no click event is attached**, the conversation picker no longer opens, and **the plus icon on the right is dimmed**."
},
"action": {
"$ref": "./common-types-basic.json#/$defs/Action",
"description": "Defines an interaction handler that can either trigger an agent-side event or execute a local renderer-side function."
},
"weight": {
"type": "number",
"description": "Flex layout weight (used to allocate space proportionally)."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component",
"value"
]
},
"ImageUpload": {
"type": "object",
"description": "Call DingTalk image upload, fill the upload result back into the `value` binding path, and list the uploaded files line by line under the button (deletable).",
"properties": {
"component": {
"const": "ImageUpload",
"description": "Public component type identifier."
},
"label": {
"type": "string",
"description": "Upload-button label. If omitted, the runtime supplies its built-in text. An empty string is not allowed; explicitly set the label for application-specific wording or language."
},
"value": {
"$ref": "./common-types-basic.json#/$defs/DataBinding",
"description": "DataBinding for the upload result, an array of image URLs. The initial value sent by the server renders the uploaded-file rows. After upload or deletion, the latest URL array remains in client-local state and is merged into the DataModel through this path **on submission**, allowing the same card's submit-button `context` to read the images actually uploaded by the user. A literal array is also allowed; in that case there is no write-back target, but file rows still reflect local upload results."
},
"disabled": {
"type": "boolean",
"description": "Whether upload is disabled; default `false`. When `true`, the renderer uses the **disabled style**, does not respond to upload actions, and omits delete buttons from uploaded-file rows."
},
"requiresAuth": {
"type": "boolean",
"description": "Whether to use authenticated upload; default `true`. When `true`, the write-back value is an authenticated media URL; when `false`, it is a regular URL."
},
"maxFiles": {
"type": "number",
"description": "The maximum number of images that can be selected at one time, default is `9`, must be a positive integer."
},
"action": {
"$ref": "./common-types-basic.json#/$defs/Action",
"description": "**Reports after a successful upload**, not when the upload control is clicked. The renderer first appends the newly returned URLs to the path bound by `value`, then sends the event to the agent. Failed uploads and canceled image selection do not report an event. A successful retry of a failed row reports in the same way as the initial upload. Only the `event` branch is supported; a `functionCall` branch is ignored as if `action` were omitted."
},
"weight": {
"type": "number",
"description": "Flex layout weight (used to allocate space proportionally)."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component",
"value"
]
}
},
"functions": {},
"$defs": {
"anyComponent": {
"oneOf": [
{
"$ref": "./catalog-components-inputs.json#/components/CheckBox"
},
{
"$ref": "./catalog-components-inputs.json#/components/CheckableImageList"
},
{
"$ref": "./catalog-components-inputs.json#/components/CheckboxListMulti"
},
{
"$ref": "./catalog-components-inputs.json#/components/ChoicePicker"
},
{
"$ref": "./catalog-components-inputs.json#/components/ConversationPicker"
},
{
"$ref": "./catalog-components-inputs.json#/components/DateTimeInput"
},
{
"$ref": "./catalog-components-inputs.json#/components/ImageUpload"
},
{
"$ref": "./catalog-components-inputs.json#/components/InputList"
},
{
"$ref": "./catalog-components-inputs.json#/components/NumberInput"
},
{
"$ref": "./catalog-components-inputs.json#/components/Rating"
},
{
"$ref": "./catalog-components-inputs.json#/components/Slider"
},
{
"$ref": "./catalog-components-inputs.json#/components/Switch"
},
{
"$ref": "./catalog-components-inputs.json#/components/TextField"
},
{
"$ref": "./catalog-components-inputs.json#/components/UserPicker"
}
],
"discriminator": {
"propertyName": "component"
}
},
"anyFunction": false
}
}
@@ -0,0 +1,829 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://dingtalk.com/card/a2ui/catalog-components-specialized.json",
"title": "DingTalk AICard Protocol V0.8 Data display and media",
"description": "12 components and 0 functions. A reading shard of the DingTalk public catalog, not a separate runtime catalog. Modified by DingTalk from selected entries of the A2UI v1.0 Basic Catalog; some upstream definitions and descriptions are retained. See NOTICE.",
"catalogId": "https://dingtalk.com/card/a2ui/catalogs/public/catalog.json",
"protocolVersion": "1.0",
"instructions": "Read entries needed for the current task, then follow their $ref dependencies. Common types: ./common-types-basic.json, ./common-types-extended.json and ./common-types-visual.json. Do not load all shards into the model context by default.\nCommon components: ./catalog-components-common.json.\nComposition and repeated layouts: ./catalog-components-composition.json.\nInputs and pickers: ./catalog-components-inputs.json.\nData display and media: ./catalog-components-specialized.json.\nCore functions adapted by DingTalk from A2UI: ./catalog-functions-core.json.\nDingTalk expressions and operators: ./catalog-functions-expressions.json.\nDingTalk host actions: ./catalog-functions-host-actions.json.\nSelect examples from ./examples/README.md; message structures are in ./agent-to-renderer.json.\nThis is the public DingTalk AICard Protocol V0.8 package. Use only the components, fields, functions, and common-type public values listed in the files loaded and assembled for the current scope.\nfallbackMarkdown is an optional DingTalk extension for component-level fallback content. It is used only when the current renderer cannot render the component. Unknown fields and field-validation errors do not trigger it. When omitted, the renderer displays the standard upgrade message.\nSchema references are local file references and require no HTTP access. catalogId is a runtime catalog identifier, not a file path.\nThe #/$defs/anyComponent union describes catalog-specific fields only. Validate complete component instances through the message envelope or loadSchemas().validateComponent, which combines ComponentCommon with this union and rejects unknown fields. The catalog root is not a validation entry point for complete messages or component instances. Complete messages must also conform to the main protocol; dynamic result types, component-tree references, and platform capabilities are validated at runtime.\nExpressions use {\"call\":…, \"args\":…} without an additional profile declaration. A host action must explicitly set functionCall.catalogId to urn:dingtalk:a2ui:host:v1. A public catalog HTTP identifier from a surface or component cannot replace the host Function catalog. For promptText, initialValue is the prefilled-text parameter and text is a result field, not an input parameter.\nAttach form-validation checks to the Button that submits the form. Do not rely on standard event-response fields for automatic write-back.\nUserPicker, ConversationPicker, and ImageUpload require host authorization. Server-side callbacks must still enforce business authorization.",
"components": {
"ImageList": {
"type": "object",
"description": "Multiple image thumbnails and quantity aggregation. The current image area is built with height 200; width is constrained by the parent layout.",
"properties": {
"component": {
"const": "ImageList",
"description": "Public component type identifier."
},
"images": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"description": "An array of image URLs, containing at least one item."
},
"previewEnabled": {
"type": "boolean",
"description": "Whether clicking can open a preview; omitted means `true`. Preview is enabled only when the group contains a loadable image URL."
},
"fit": {
"type": "string",
"enum": [
"contain",
"cover",
"fill",
"none",
"scaleDown"
],
"description": "Image scaling using the CSS `object-fit` vocabulary. Omitted means containment, corresponding to `contain`, unlike Image's omitted crop-to-fill behavior. `contain`/`scaleDown`/`none` map to containment, `cover` to cropping, and `fill` to stretching. Do not send internal renderer scaling names."
},
"cornerRadius": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber",
"description": "Image-group corner radius; omitted means `4`, unlike Image's default of `6`."
},
"weight": {
"type": "number",
"description": "Flex layout weight (used to allocate space proportionally)."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component",
"images"
]
},
"Avatar": {
"type": "object",
"description": "Avatar image. Without size configuration it uses 48×48, with an outer corner radius equal to one quarter of the actual size. sizeType selects presets or customSize.",
"properties": {
"component": {
"const": "Avatar",
"description": "Public component type identifier."
},
"imageUrl": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "Avatar image URL."
},
"sizeType": {
"type": "string",
"enum": [
"Standard",
"Custom"
],
"description": "Size type. Set it to `Standard` to use the `size` preset. Set it to `Custom`, or omit it, to use `customSize`; if `customSize` is also omitted, the runtime uses 48px. Other values do not conform to the public Schema."
},
"size": {
"type": "string",
"enum": [
"extraSmall",
"small",
"middle"
],
"description": "Size preset, effective only when `sizeType` is `Standard`: `extraSmall` = 20px, `small` = 30px, and `middle` = 48px. If omitted, `middle` is used. Values outside this vocabulary do not conform to the public Schema."
},
"customSize": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber",
"description": "Custom size. Used when sizeType is not Standard; omitted means 48."
},
"weight": {
"type": "number",
"description": "Flex layout weight (used to allocate space proportionally)."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component"
]
},
"AvatarGroup": {
"type": "object",
"description": "Avatar stacking and overflow count.",
"properties": {
"component": {
"const": "AvatarGroup",
"description": "Public component type identifier."
},
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"imageUrl": {
"type": "string",
"description": "An accessible absolute or relative resource address."
},
"name": {
"type": "string",
"description": "Used to create a text avatar when no image is available; providing only `imageUrl` is also supported. At least one of `name` and `imageUrl` must be a non-empty string, as checked at runtime."
}
}
},
"description": "List of user objects."
},
"maxVisible": {
"type": "integer",
"description": "Maximum number of avatars displayed (show +N when exceeded). Omitted means 5."
},
"weight": {
"type": "number",
"description": "Flex layout weight (used to allocate space proportionally)."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component",
"items"
]
},
"Table": {
"type": "object",
"description": "Table headers, zebra stripes, and paginated data.",
"properties": {
"component": {
"const": "Table",
"description": "Public component type identifier."
},
"data": {
"anyOf": [
{
"$ref": "./common-types-basic.json#/$defs/DataBinding"
},
{
"type": "object",
"properties": {
"meta": {
"type": "array",
"items": {
"type": "object",
"properties": {
"colKey": {
"type": "string",
"description": "Column key. Each row object is looked up by this key to obtain the cell value for this column; when a row lacks the key, that cell renders empty without affecting other columns."
},
"colName": {
"type": "string",
"description": "Column name shown in the header. When the value is not a string, it falls back to `colKey` and the table still renders."
},
"type": {
"type": "string",
"enum": [
"text",
"tag",
"link",
"microApp",
"button",
"STRING",
"string",
"OBJECT",
"object",
"MICROAPP",
"microapp",
"BUTTON"
],
"description": "Column rendering types. It is recommended to use `text`, `tag`, `link`, `microApp`, `button`; other values are used for compatibility with existing cards. For numeric cells, use `text` or `STRING`. The cell value can be directly filled with a JSON number, and the renderer will convert it to text for display; `NUMBER` is not supported."
}
},
"required": [
"colKey",
"colName",
"type"
]
},
"minItems": 1,
"maxItems": 100,
"description": "Column definitions in display order, from 1 to 100 columns. Every column must declare `colKey`, `colName`, and `type`; if any one is missing, the entire table is replaced by the component fallback (the standard message when `fallbackMarkdown` is not set)."
},
"data": {
"type": "array",
"items": {
"type": "object",
"properties": {}
},
"minItems": 0,
"maxItems": 1000,
"description": "Row data, up to 1000 rows; each row must be an object whose keys correspond to `colKey` in `meta`. An empty array is allowed and renders a header-only table, but the field itself must still be sent."
}
},
"required": [
"meta",
"data"
]
}
],
"description": "Table data with meta (columns) and data (rows)."
},
"cellPadding": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber",
"description": "Cell padding. Omitted means 12 on each horizontal side and 8 on each vertical side. An explicit number applies uniformly to all four sides."
},
"imageSize": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber",
"description": "The size of the image in the table. Omitted means 30."
},
"pageSize": {
"type": "integer",
"description": "Number of rows per page. Defaults to 10 and takes effect only when `pagination` is `true`. Values below 1 are invalid; removing this field restores the default."
},
"maxLine": {
"type": "integer",
"description": "Maximum number of display lines for **text-based data cells** (`STRING`, `OBJECT`, and `MICROAPP`); excess text is truncated. Defaults to 3. The table header is unaffected and always allows up to 3 lines. `BUTTON` cells are also unaffected because renderer buttons do not use a line-count setting. Values of 0 or less are normalized to 1; sending 0 directly to the renderer would render no lines and make the column text disappear."
},
"zebra": {
"type": "boolean",
"description": "Whether to enable zebra stripes (alternate row coloring). Omitted means false, with no alternating row colors."
},
"pagination": {
"type": "boolean",
"description": "Whether pagination is enabled; default `false`. **Pagination is entirely local**: the full dataset is sent once, and changing pages only updates the view without fetching more data from the server. The pagination control is not rendered when the data fits on one page because it would have no effect."
},
"pageIndex": {
"type": "integer",
"description": "**Initial** page index (0-based), default is 0. It only determines which page the first frame stops at, and subsequent page turns are controlled by the user. If it exceeds the total number of pages, it is clamped to the last page; negative values are considered invalid. If this field is removed, it defaults to rendering page 0."
},
"scrollAreaWidth": {
"type": "number",
"description": "Width of the horizontal scroll area (px), default `600`. When there are too many columns to fit on one screen, the table scrolls horizontally within this width. Must be a positive number."
},
"weight": {
"type": "number",
"description": "Flex layout weight (used to allocate space proportionally)."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component",
"data"
]
},
"Chart": {
"type": "object",
"description": "Unified public charts: standard data, template rendering, and responsive sizing. **Charts are always clickable for details**, no configuration is needed or possible—the charts in the cards are only a few tens of px high and the values are hard to see; clicking to view the larger image is a basic capability of this component.",
"properties": {
"component": {
"const": "Chart",
"description": "Public component type identifier."
},
"data": {
"anyOf": [
{
"$ref": "./common-types-basic.json#/$defs/DataBinding"
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"description": "Chart types. Current repository real examples include lineChart, histogram, and pieChart."
},
"data": {
"type": "array",
"items": {
"type": "object",
"properties": {
"x": {
"anyOf": [
{
"type": "string"
},
{
"type": "number"
}
],
"description": "Horizontal axis or category values."
},
"y": {
"type": "number",
"description": "Numerical value."
},
"type": {
"type": "string",
"description": "Optional series name."
}
},
"required": [
"x",
"y"
]
},
"description": "Uses the type and constraints defined by the corresponding catalog Schema."
},
"config": {
"type": "object",
"description": "Optional chart configurations, such as axes, colors, and padding.",
"properties": {}
}
},
"required": [
"type",
"data"
]
}
],
"description": "Chart data binding or real chart data object."
},
"aspectRatio": {
"type": "string",
"enum": [
"1:1",
"2:1",
"4:3",
"16:9"
],
"description": "Responsive aspect ratio. Mutually exclusive with height; effective when height is not configured. When both height and aspectRatio are omitted, `2:1` is used. Do not automatically add this field when a fixed height is already configured."
},
"height": {
"type": "number",
"description": "Fixed height. Configuring this field enables a fixed height, and you cannot configure aspectRatio at the same time."
},
"weight": {
"type": "number",
"description": "Flex layout weight (used to allocate space proportionally)."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component",
"data"
]
},
"ProgressBar": {
"type": "object",
"description": "The public progress component. `variant` unifies continuous bars and compact blocks under the same value, color, and light/dark-theme model. Without a resolved color configuration, the fill uses the host brand color, falling back to built-in light/dark colors if resolution is unavailable.",
"properties": {
"component": {
"const": "ProgressBar",
"description": "Public component type identifier."
},
"variant": {
"type": "string",
"enum": [
"bar",
"block"
],
"description": "bar is for a continuous progress bar; block is for a compact block-style progress. The renderer displays continuous or block progress according to this mode. Omitted means `bar`."
},
"value": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber",
"description": "Progress value, with a semantic range of 0 to 100; validation fails when the literal is out of bounds, and the data-bound value is restricted to the valid range by the renderer."
},
"showLabel": {
"type": "boolean",
"description": "Only effective in bar mode; whether to display percentage text. Omitted means true."
},
"labelPosition": {
"type": "string",
"enum": [
"start",
"inside",
"end"
],
"description": "Only effective in bar mode; the position of the percentage text is relative to the track, default `end` (right side of the track, spacing 12px). `start` places it on the left side, `inside` overlays it within the filled segment without taking additional horizontal space."
},
"colorToken": {
"$ref": "./common-types-visual.json#/$defs/ColorToken",
"description": "Only the 57 IDs in the common `ColorToken` enum are allowed. A DDesign token name for the progress-bar fill, with **the highest color-resolution priority**. When resolved, `customLightColor`, `customDarkColor`, and `color` are ignored. The host resolves it for the current client platform and theme through the same mechanism as `Text.colorToken`. If the host cannot resolve the token, evaluation falls back to the subsequent color sources."
},
"customLightColor": {
"type": "string",
"description": "Light-theme color shared by both modes. Supports `#RRGGBB` and `#AARRGGBB`."
},
"customDarkColor": {
"type": "string",
"description": "Dark-theme color shared by both modes; `customLightColor` must also be provided. The renderer selects and sends the light or dark value for the current theme. A theme change takes effect after the card's next refresh."
},
"rounded": {
"type": "boolean",
"description": "Only effective in bar mode; whether to use capsule rounded corners. Omitted means true."
},
"size": {
"type": "string",
"enum": [
"medium",
"small"
],
"description": "Effective only in `bar` mode: according to the design mock, `medium` uses a 6px track and `small` uses a 4px track. When `rounded` is `true`, the corner radius is half the track height. `block` mode is fixed at 32×32. Omitted means `medium`."
},
"weight": {
"type": "number",
"description": "Flex layout weight (used to allocate space proportionally)."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component",
"value"
]
},
"ElapsedTime": {
"type": "object",
"description": "Elapsed-time counter.",
"properties": {
"component": {
"const": "ElapsedTime",
"description": "Public component type identifier."
},
"startTime": {
"type": "number",
"description": "Start timestamp in milliseconds. When omitted, 0 is passed to the renderer. Set an explicit timestamp when a definite start is required rather than relying on host handling of 0."
},
"prefix": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "Left text. If omitted, no prefix text is shown."
},
"suffix": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "Text on the right. If omitted, no suffix text is shown."
},
"gravity": {
"type": "string",
"enum": [
"left",
"center",
"right"
],
"description": "Alignment. Omitted means `left`."
},
"textStyleType": {
"type": "string",
"description": "Text style category. The current DingTalk implementation always uses `Standard`; setting this field does not switch to custom styling."
},
"textStyle": {
"type": "string",
"description": "Text style preset. The current DingTalk implementation always uses `paragraph`, regardless of this field."
},
"weight": {
"type": "number",
"description": "Flex layout weight (used to allocate space proportionally)."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component"
]
},
"Countdown": {
"type": "object",
"description": "Countdown and end event.",
"properties": {
"component": {
"const": "Countdown",
"description": "Public component type identifier."
},
"endTime": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber",
"description": "The Unix millisecond timestamp of the countdown target moment. Literals, DataBinding evaluation results, and FunctionCall return values must all be JSON numbers; numeric strings or ISO 8601 date-time strings are not accepted."
},
"prefix": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "Text on the left side of the countdown. If omitted, no prefix text is shown."
},
"suffix": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "Text on the right side of the countdown. If omitted, no suffix text is shown."
},
"gravity": {
"type": "string",
"enum": [
"left",
"center",
"right"
],
"description": "Alignment (left/center/right). Omitted means `left`."
},
"textStyleType": {
"type": "string",
"description": "Text style category. The current DingTalk implementation always uses `Standard`; setting this field does not switch to custom styling."
},
"textStyle": {
"type": "string",
"description": "Text style preset. The current DingTalk implementation always uses `paragraph`, regardless of this field."
},
"onComplete": {
"$ref": "./common-types-basic.json#/$defs/Action",
"description": "Action triggered when countdown reaches zero."
},
"onTap": {
"$ref": "./common-types-basic.json#/$defs/Action",
"description": "Action executed when the component is clicked; only effective if the component declares click capability."
},
"weight": {
"type": "number",
"description": "Flex layout weight (used to allocate space proportionally)."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component",
"endTime"
]
},
"Video": {
"type": "object",
"description": "Cover, inline playback, and control bar. The current implementation disables autoplay and looping, enables inline playback and controls, and configures a 16:9 poster area with corner radius 6. These settings are determined by the renderer implementation.",
"properties": {
"component": {
"const": "Video",
"description": "Component type identification field."
},
"url": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "The URL of the video to display."
},
"posterUrl": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "The URL of the poster image to display before the video plays. If omitted, no custom poster URL is supplied; poster display is handled by the player."
},
"weight": {
"type": "number",
"description": "The relative weight of this component within a Row or Column. This is similar to the CSS 'flex-grow' property. Note: this may ONLY be set when the component is a direct descendant of a Row or Column."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component",
"url"
]
},
"AudioPlayer": {
"type": "object",
"description": "Audio cover, title, and playback progress.",
"properties": {
"component": {
"const": "AudioPlayer",
"description": "Component type identification field."
},
"url": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "The URL of the audio to be played."
},
"coverUrl": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "Cover image URL. Both PC and mobile render it: `AudioWidget` places it to the left of the player on PC, while the rich-text audio node renders it on mobile. If omitted, the player shows no cover image."
},
"description": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "A description of the audio, such as a title or summary. If omitted, no custom title is supplied."
},
"artist": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "Artist / Source attribution, displayed on the side of the title. Together with `description`, it forms the text area of the player; if not configured, this line will not be displayed."
},
"weight": {
"type": "number",
"description": "The relative weight of this component within a Row or Column. This is similar to the CSS 'flex-grow' property. Note: this may ONLY be set when the component is a direct descendant of a Row or Column."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component",
"url"
]
},
"File": {
"type": "object",
"description": "File artifact. Its icon is derived from the file type; clicking the row opens the file, and a separate open button appears at the end of the row.",
"properties": {
"component": {
"const": "File",
"description": "Public component type identifier."
},
"fileName": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "The display file name with a suffix, which is also the only input for the renderer to automatically recognize the file icon and type."
},
"url": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "File download URL. May be an authenticated absolute URL or a relative URL resolvable by the current application."
},
"mimeType": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "Optional MIME type used only for supplementary information and open behavior; it does not affect file-icon selection."
},
"size": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber",
"description": "Optional file size, in bytes; the renderer is responsible for formatting it as KB, MB, or GB. If omitted, no file size is displayed."
},
"description": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "Optional supplementary information, such as file source, generation status, or version. If omitted, auxiliary text is generated from file size and type; without a size, only the type is shown."
},
"previewUrl": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "Online-preview page URL. When provided, clicking the row opens this URL; otherwise it falls back to `url`. Its semantics differ from `url`, which identifies the file itself. The download button at the end of the row **always** uses `url` and is unaffected by this field."
},
"onPreview": {
"$ref": "./common-types-basic.json#/$defs/Action",
"description": "Triggered when the row is clicked. ⚠️ Uses a two-step **open first, then report on success** flow: the renderer first opens `previewUrl`, or `url` when `previewUrl` is omitted, and sends the event to the agent only after the open succeeds. If the file cannot be opened, no event is reported. Therefore, **there is no need** to wait for an `openLink` response from the agent; navigation is immediate. If omitted, the row has no click action."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component",
"fileName",
"url"
]
},
"ImageCarousel": {
"type": "object",
"description": "DingTalk image carousel component.",
"properties": {
"component": {
"const": "ImageCarousel",
"description": "Public component type identifier."
},
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"url": {
"type": "string",
"description": "Carousel image URL."
},
"linkUrl": {
"type": "string",
"description": "Optional URL opened when the carousel item is clicked."
},
"title": {
"type": "string",
"description": "Uses the type and constraints defined by the corresponding catalog Schema."
},
"description": {
"type": "string",
"description": "Uses the type and constraints defined by the corresponding catalog Schema."
}
},
"required": [
"url"
]
},
"description": "Carousel item. `url` is required; `linkUrl`, title, and description are optional."
},
"cornerRadius": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber",
"description": "Corner radius in px; omitted means `12`. Desktop applies it to carousel images; mobile clips the image group with the outer container. Use a finite non-negative number; `0` gives square corners."
},
"autoplayIntervalMs": {
"type": "integer",
"description": "Auto-scroll interval in ms (0 = disabled). Omitted means 0, with automatic scrolling disabled."
},
"previewEnabled": {
"type": "boolean",
"description": "Whether clicking can open a preview; omitted means true. Preview is enabled only when a loadable image URL exists."
},
"fit": {
"type": "string",
"enum": [
"contain",
"cover",
"fill",
"none",
"scaleDown"
],
"description": "Image scaling method, the vocabulary is consistent with CSS `object-fit` (`contain`/`scaleDown`/`none` → full display, `cover` → cropped to fill, `fill` → stretched to fill). **Only sent when explicitly provided**; values outside the vocabulary (including internal names like `fitCenter`/`fitXY`/`centerCrop`) will be silently reverted to the default."
},
"weight": {
"type": "number",
"description": "Flex layout weight (used to allocate space proportionally)."
},
"fallbackMarkdown": {
"type": "string",
"description": "Markdown fallback content used when the current renderer cannot render the component."
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
}
},
"required": [
"component",
"items"
]
}
},
"functions": {},
"$defs": {
"anyComponent": {
"oneOf": [
{
"$ref": "./catalog-components-specialized.json#/components/AudioPlayer"
},
{
"$ref": "./catalog-components-specialized.json#/components/Avatar"
},
{
"$ref": "./catalog-components-specialized.json#/components/AvatarGroup"
},
{
"$ref": "./catalog-components-specialized.json#/components/Chart"
},
{
"$ref": "./catalog-components-specialized.json#/components/Countdown"
},
{
"$ref": "./catalog-components-specialized.json#/components/ElapsedTime"
},
{
"$ref": "./catalog-components-specialized.json#/components/File"
},
{
"$ref": "./catalog-components-specialized.json#/components/ImageCarousel"
},
{
"$ref": "./catalog-components-specialized.json#/components/ImageList"
},
{
"$ref": "./catalog-components-specialized.json#/components/ProgressBar"
},
{
"$ref": "./catalog-components-specialized.json#/components/Table"
},
{
"$ref": "./catalog-components-specialized.json#/components/Video"
}
],
"discriminator": {
"propertyName": "component"
}
},
"anyFunction": false
}
}
@@ -0,0 +1,530 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://dingtalk.com/card/a2ui/catalog-functions-core.json",
"title": "DingTalk AICard Protocol V0.8 Core functions adapted by DingTalk from A2UI",
"description": "0 components and 14 functions. A reading shard of the DingTalk public catalog, not a separate runtime catalog. Modified by DingTalk from selected entries of the A2UI v1.0 Basic Catalog; some upstream definitions and descriptions are retained. See NOTICE.",
"catalogId": "https://dingtalk.com/card/a2ui/catalogs/public/catalog.json",
"protocolVersion": "1.0",
"instructions": "Read entries needed for the current task, then follow their $ref dependencies. Common types: ./common-types-basic.json, ./common-types-extended.json and ./common-types-visual.json. Do not load all shards into the model context by default.\nCommon components: ./catalog-components-common.json.\nComposition and repeated layouts: ./catalog-components-composition.json.\nInputs and pickers: ./catalog-components-inputs.json.\nData display and media: ./catalog-components-specialized.json.\nCore functions adapted by DingTalk from A2UI: ./catalog-functions-core.json.\nDingTalk expressions and operators: ./catalog-functions-expressions.json.\nDingTalk host actions: ./catalog-functions-host-actions.json.\nSelect examples from ./examples/README.md; message structures are in ./agent-to-renderer.json.\nThese 14 functions share upstream A2UI names but retain DingTalk definitions; this is not an unmodified official catalog.\nThis is the public DingTalk AICard Protocol V0.8 package. Use only the components, fields, functions, and common-type public values listed in the files loaded and assembled for the current scope.\nfallbackMarkdown is an optional DingTalk extension for component-level fallback content. It is used only when the current renderer cannot render the component. Unknown fields and field-validation errors do not trigger it. When omitted, the renderer displays the standard upgrade message.\nSchema references are local file references and require no HTTP access. catalogId is a runtime catalog identifier, not a file path.\nThe #/$defs/anyComponent union describes catalog-specific fields only. Validate complete component instances through the message envelope or loadSchemas().validateComponent, which combines ComponentCommon with this union and rejects unknown fields. The catalog root is not a validation entry point for complete messages or component instances. Complete messages must also conform to the main protocol; dynamic result types, component-tree references, and platform capabilities are validated at runtime.\nExpressions use {\"call\":…, \"args\":…} without an additional profile declaration. A host action must explicitly set functionCall.catalogId to urn:dingtalk:a2ui:host:v1. A public catalog HTTP identifier from a surface or component cannot replace the host Function catalog. For promptText, initialValue is the prefilled-text parameter and text is a result field, not an input parameter.\nAttach form-validation checks to the Button that submits the form. Do not rely on standard event-response fields for automatic write-back.\nUserPicker, ConversationPicker, and ImageUpload require host authorization. Server-side callbacks must still enforce business authorization.",
"components": {},
"functions": {
"required": {
"type": "object",
"description": "Checks that the value is not null, undefined, or empty.",
"returnType": "boolean",
"properties": {
"call": {
"const": "required"
},
"args": {
"type": "object",
"properties": {
"value": {
"description": "The value to check."
}
},
"required": [
"value"
],
"additionalProperties": false
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"regex": {
"type": "object",
"description": "Checks that the value matches a regular expression string.",
"returnType": "boolean",
"properties": {
"call": {
"const": "regex"
},
"args": {
"type": "object",
"properties": {
"value": {
"$ref": "./common-types-basic.json#/$defs/DynamicString"
},
"pattern": {
"type": "string"
}
},
"required": [
"value",
"pattern"
],
"unevaluatedProperties": false
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"length": {
"type": "object",
"description": "Checks string length constraints.",
"returnType": "boolean",
"properties": {
"call": {
"const": "length"
},
"args": {
"type": "object",
"properties": {
"value": {
"$ref": "./common-types-basic.json#/$defs/DynamicString"
},
"min": {
"type": "integer",
"minimum": 0
},
"max": {
"type": "integer",
"minimum": 0
}
},
"required": [
"value"
],
"anyOf": [
{
"required": [
"min"
]
},
{
"required": [
"max"
]
}
],
"unevaluatedProperties": false
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"numeric": {
"type": "object",
"description": "Checks numeric range constraints.",
"returnType": "boolean",
"properties": {
"call": {
"const": "numeric"
},
"args": {
"type": "object",
"properties": {
"value": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber"
},
"min": {
"type": "number"
},
"max": {
"type": "number"
}
},
"required": [
"value"
],
"anyOf": [
{
"required": [
"min"
]
},
{
"required": [
"max"
]
}
],
"unevaluatedProperties": false
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"email": {
"type": "object",
"description": "Checks that the value is a valid email address.",
"returnType": "boolean",
"properties": {
"call": {
"const": "email"
},
"args": {
"type": "object",
"properties": {
"value": {
"$ref": "./common-types-basic.json#/$defs/DynamicString"
}
},
"required": [
"value"
],
"unevaluatedProperties": false
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"formatString": {
"type": "object",
"description": "Uses `${/path}` for data-path interpolation. Function calls such as `now()` and `formatDate(...)` are not supported inside placeholders. `args.value` may use a JSON-form data binding or value function; it is first evaluated to a string and then interpolated with data paths.",
"returnType": "string",
"properties": {
"call": {
"const": "formatString"
},
"args": {
"type": "object",
"properties": {
"value": {
"$ref": "./common-types-basic.json#/$defs/DynamicString"
}
},
"required": [
"value"
],
"unevaluatedProperties": false
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"formatNumber": {
"type": "object",
"description": "Formats a number with grouping and decimal precision.",
"returnType": "string",
"properties": {
"call": {
"const": "formatNumber"
},
"args": {
"type": "object",
"properties": {
"value": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber"
},
"decimals": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber"
},
"grouping": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean"
}
},
"required": [
"value"
],
"unevaluatedProperties": false
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"formatCurrency": {
"type": "object",
"description": "Formats a number as a currency string.",
"returnType": "string",
"properties": {
"call": {
"const": "formatCurrency"
},
"args": {
"type": "object",
"properties": {
"value": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber"
},
"currency": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "ISO 4217 currency code (e.g. USD, EUR, CNY)."
},
"decimals": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber"
},
"grouping": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean"
}
},
"required": [
"currency",
"value"
],
"unevaluatedProperties": false
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"formatDate": {
"type": "object",
"description": "Formats a timestamp into a string using Unicode TR35 date pattern.",
"returnType": "string",
"properties": {
"call": {
"const": "formatDate"
},
"args": {
"type": "object",
"properties": {
"value": {
"$ref": "./common-types-basic.json#/$defs/DynamicValue"
},
"format": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "Unicode TR35 pattern (e.g. 'yyyy-MM-dd', 'HH:mm')."
}
},
"required": [
"format",
"value"
],
"unevaluatedProperties": false
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"pluralize": {
"type": "object",
"description": "Returns a localized string based on CLDR plural category of the count.",
"returnType": "string",
"properties": {
"call": {
"const": "pluralize"
},
"args": {
"type": "object",
"properties": {
"value": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber"
},
"zero": {
"$ref": "./common-types-basic.json#/$defs/DynamicString"
},
"one": {
"$ref": "./common-types-basic.json#/$defs/DynamicString"
},
"two": {
"$ref": "./common-types-basic.json#/$defs/DynamicString"
},
"few": {
"$ref": "./common-types-basic.json#/$defs/DynamicString"
},
"many": {
"$ref": "./common-types-basic.json#/$defs/DynamicString"
},
"other": {
"$ref": "./common-types-basic.json#/$defs/DynamicString"
}
},
"required": [
"value",
"other"
],
"unevaluatedProperties": false
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"openUrl": {
"type": "object",
"description": "Opens the specified URL in a browser or handler.",
"returnType": "void",
"properties": {
"call": {
"const": "openUrl"
},
"args": {
"type": "object",
"properties": {
"url": {
"$ref": "./common-types-basic.json#/$defs/DynamicString"
}
},
"required": [
"url"
],
"additionalProperties": false
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"and": {
"type": "object",
"description": "Performs logical AND on a list of boolean values.",
"returnType": "boolean",
"properties": {
"call": {
"const": "and"
},
"args": {
"type": "object",
"properties": {
"values": {
"type": "array",
"items": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean"
},
"minItems": 2
}
},
"required": [
"values"
],
"unevaluatedProperties": false
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"or": {
"type": "object",
"description": "Performs logical OR on a list of boolean values.",
"returnType": "boolean",
"properties": {
"call": {
"const": "or"
},
"args": {
"type": "object",
"properties": {
"values": {
"type": "array",
"items": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean"
},
"minItems": 2
}
},
"required": [
"values"
],
"unevaluatedProperties": false
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"not": {
"type": "object",
"description": "Performs logical NOT on a boolean value.",
"returnType": "boolean",
"properties": {
"call": {
"const": "not"
},
"args": {
"type": "object",
"properties": {
"value": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean"
}
},
"required": [
"value"
],
"unevaluatedProperties": false
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
}
},
"$defs": {
"anyComponent": false,
"anyFunction": {
"oneOf": [
{
"$ref": "./catalog-functions-core.json#/functions/required"
},
{
"$ref": "./catalog-functions-core.json#/functions/regex"
},
{
"$ref": "./catalog-functions-core.json#/functions/length"
},
{
"$ref": "./catalog-functions-core.json#/functions/numeric"
},
{
"$ref": "./catalog-functions-core.json#/functions/email"
},
{
"$ref": "./catalog-functions-core.json#/functions/formatString"
},
{
"$ref": "./catalog-functions-core.json#/functions/formatNumber"
},
{
"$ref": "./catalog-functions-core.json#/functions/formatCurrency"
},
{
"$ref": "./catalog-functions-core.json#/functions/formatDate"
},
{
"$ref": "./catalog-functions-core.json#/functions/pluralize"
},
{
"$ref": "./catalog-functions-core.json#/functions/openUrl"
},
{
"$ref": "./catalog-functions-core.json#/functions/and"
},
{
"$ref": "./catalog-functions-core.json#/functions/or"
},
{
"$ref": "./catalog-functions-core.json#/functions/not"
}
]
}
}
}
@@ -0,0 +1,623 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://dingtalk.com/card/a2ui/catalog-functions-expressions.json",
"title": "DingTalk AICard Protocol V0.8 DingTalk expressions and operators",
"description": "0 components and 18 functions. A reading shard of the DingTalk public catalog, not a separate runtime catalog.",
"catalogId": "https://dingtalk.com/card/a2ui/catalogs/public/catalog.json",
"protocolVersion": "1.0",
"instructions": "Read entries needed for the current task, then follow their $ref dependencies. Common types: ./common-types-basic.json, ./common-types-extended.json and ./common-types-visual.json. Do not load all shards into the model context by default.\nCommon components: ./catalog-components-common.json.\nComposition and repeated layouts: ./catalog-components-composition.json.\nInputs and pickers: ./catalog-components-inputs.json.\nData display and media: ./catalog-components-specialized.json.\nCore functions adapted by DingTalk from A2UI: ./catalog-functions-core.json.\nDingTalk expressions and operators: ./catalog-functions-expressions.json.\nDingTalk host actions: ./catalog-functions-host-actions.json.\nSelect examples from ./examples/README.md; message structures are in ./agent-to-renderer.json.\nThis is the public DingTalk AICard Protocol V0.8 package. Use only the components, fields, functions, and common-type public values listed in the files loaded and assembled for the current scope.\nfallbackMarkdown is an optional DingTalk extension for component-level fallback content. It is used only when the current renderer cannot render the component. Unknown fields and field-validation errors do not trigger it. When omitted, the renderer displays the standard upgrade message.\nSchema references are local file references and require no HTTP access. catalogId is a runtime catalog identifier, not a file path.\nThe #/$defs/anyComponent union describes catalog-specific fields only. Validate complete component instances through the message envelope or loadSchemas().validateComponent, which combines ComponentCommon with this union and rejects unknown fields. The catalog root is not a validation entry point for complete messages or component instances. Complete messages must also conform to the main protocol; dynamic result types, component-tree references, and platform capabilities are validated at runtime.\nExpressions use {\"call\":…, \"args\":…} without an additional profile declaration. A host action must explicitly set functionCall.catalogId to urn:dingtalk:a2ui:host:v1. A public catalog HTTP identifier from a surface or component cannot replace the host Function catalog. For promptText, initialValue is the prefilled-text parameter and text is a result field, not an input parameter.\nAttach form-validation checks to the Button that submits the form. Do not rely on standard event-response fields for automatic write-back.\nUserPicker, ConversationPicker, and ImageUpload require host authorization. Server-side callbacks must still enforce business authorization.",
"components": {},
"functions": {
"add": {
"type": "object",
"description": "DingTalk extension function. Represents adding two numbers together.",
"returnType": "number",
"properties": {
"call": {
"const": "add"
},
"args": {
"type": "object",
"properties": {
"a": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber"
},
"b": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber"
}
},
"required": [
"a",
"b"
],
"additionalProperties": false
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"sub": {
"type": "object",
"description": "DingTalk extension function. Represents subtracting two numbers.",
"returnType": "number",
"properties": {
"call": {
"const": "sub"
},
"args": {
"type": "object",
"properties": {
"a": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber"
},
"b": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber"
}
},
"required": [
"a",
"b"
],
"additionalProperties": false
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"mul": {
"type": "object",
"description": "DingTalk extension function. Multiplies two numbers.",
"returnType": "number",
"properties": {
"call": {
"const": "mul"
},
"args": {
"type": "object",
"properties": {
"a": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber"
},
"b": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber"
}
},
"required": [
"a",
"b"
],
"additionalProperties": false
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"div": {
"type": "object",
"description": "DingTalk extension function. Divides one number by another.",
"returnType": "number",
"properties": {
"call": {
"const": "div"
},
"args": {
"type": "object",
"properties": {
"a": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber"
},
"b": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber"
}
},
"required": [
"a",
"b"
],
"additionalProperties": false
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"mod": {
"type": "object",
"description": "DingTalk extension function. Computes the remainder of a numeric division.",
"returnType": "number",
"properties": {
"call": {
"const": "mod"
},
"args": {
"type": "object",
"properties": {
"a": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber"
},
"b": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber"
}
},
"required": [
"a",
"b"
],
"additionalProperties": false
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"eq": {
"type": "object",
"description": "Tests whether two values are equal. Supports comparison with `null`; use `eq(arrayFind(...), null)` to detect no match.",
"returnType": "boolean",
"properties": {
"call": {
"const": "eq"
},
"args": {
"type": "object",
"properties": {
"a": {
"$ref": "./common-types-basic.json#/$defs/DynamicValue"
},
"b": {
"$ref": "./common-types-basic.json#/$defs/DynamicValue"
}
},
"required": [
"a",
"b"
],
"additionalProperties": false
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"ne": {
"type": "object",
"description": "Tests whether two values are unequal. Supports comparison with `null`; use `ne(arrayFind(...), null)` to detect a match.",
"returnType": "boolean",
"properties": {
"call": {
"const": "ne"
},
"args": {
"type": "object",
"properties": {
"a": {
"$ref": "./common-types-basic.json#/$defs/DynamicValue"
},
"b": {
"$ref": "./common-types-basic.json#/$defs/DynamicValue"
}
},
"required": [
"a",
"b"
],
"additionalProperties": false
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"lt": {
"type": "object",
"description": "DingTalk extension function. Determines whether number A is less than number B.",
"returnType": "boolean",
"properties": {
"call": {
"const": "lt"
},
"args": {
"type": "object",
"properties": {
"a": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber"
},
"b": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber"
}
},
"required": [
"a",
"b"
],
"additionalProperties": false
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"lte": {
"type": "object",
"description": "DingTalk extension function. Determines whether number A is less than or equal to number B.",
"returnType": "boolean",
"properties": {
"call": {
"const": "lte"
},
"args": {
"type": "object",
"properties": {
"a": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber"
},
"b": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber"
}
},
"required": [
"a",
"b"
],
"additionalProperties": false
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"gt": {
"type": "object",
"description": "DingTalk extension function. Determines whether number A is greater than number B.",
"returnType": "boolean",
"properties": {
"call": {
"const": "gt"
},
"args": {
"type": "object",
"properties": {
"a": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber"
},
"b": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber"
}
},
"required": [
"a",
"b"
],
"additionalProperties": false
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"gte": {
"type": "object",
"description": "DingTalk extension function. Determines whether number A is greater than or equal to number B.",
"returnType": "boolean",
"properties": {
"call": {
"const": "gte"
},
"args": {
"type": "object",
"properties": {
"a": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber"
},
"b": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber"
}
},
"required": [
"a",
"b"
],
"additionalProperties": false
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"cond": {
"type": "object",
"description": "DingTalk extension function. Conditional operator (ternary operator).",
"returnType": "any",
"properties": {
"call": {
"const": "cond"
},
"args": {
"type": "object",
"properties": {
"if": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean"
},
"then": {
"$ref": "./common-types-basic.json#/$defs/DynamicValue"
},
"else": {
"$ref": "./common-types-basic.json#/$defs/DynamicValue"
}
},
"required": [
"else",
"if",
"then"
],
"additionalProperties": false
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"toDouble": {
"type": "object",
"description": "DingTalk extension function. A function used to convert numbers into floating-point numbers.",
"returnType": "number",
"properties": {
"call": {
"const": "toDouble"
},
"args": {
"type": "object",
"properties": {
"value": {
"$ref": "./common-types-basic.json#/$defs/DynamicValue"
}
},
"required": [
"value"
],
"additionalProperties": false
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"toLong": {
"type": "object",
"description": "DingTalk extension function. A function used to convert numbers into integers.",
"returnType": "number",
"properties": {
"call": {
"const": "toLong"
},
"args": {
"type": "object",
"properties": {
"value": {
"$ref": "./common-types-basic.json#/$defs/DynamicValue"
}
},
"required": [
"value"
],
"additionalProperties": false
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"objectGet": {
"type": "object",
"description": "Reads an object property by `key`. `value` may be a plain object literal, data binding, or value-function result. A missing property returns `null`.",
"returnType": "any",
"properties": {
"call": {
"const": "objectGet"
},
"args": {
"type": "object",
"properties": {
"value": {
"$ref": "./common-types-basic.json#/$defs/DynamicValue"
},
"key": {
"$ref": "./common-types-basic.json#/$defs/DynamicString"
}
},
"required": [
"key",
"value"
],
"additionalProperties": false
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"arrayGet": {
"type": "object",
"description": "DingTalk extension function. Retrieves an item from an array.",
"returnType": "any",
"properties": {
"call": {
"const": "arrayGet"
},
"args": {
"type": "object",
"properties": {
"value": {
"$ref": "./common-types-basic.json#/$defs/DynamicValue"
},
"index": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber"
}
},
"required": [
"index",
"value"
],
"additionalProperties": false
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"arrayFind": {
"type": "object",
"description": "DingTalk extension function. Finds a matching item in an array.",
"returnType": "any",
"properties": {
"call": {
"const": "arrayFind"
},
"args": {
"type": "object",
"properties": {
"value": {
"$ref": "./common-types-basic.json#/$defs/DynamicValue"
},
"target": {
"$ref": "./common-types-basic.json#/$defs/DynamicValue"
}
},
"required": [
"target",
"value"
],
"additionalProperties": false
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"getLength": {
"type": "object",
"description": "DingTalk extension function. Returns the length of an array.",
"returnType": "number",
"properties": {
"call": {
"const": "getLength"
},
"args": {
"type": "object",
"properties": {
"value": {
"$ref": "./common-types-basic.json#/$defs/DynamicValue"
}
},
"required": [
"value"
],
"additionalProperties": false
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
}
},
"$defs": {
"anyComponent": false,
"anyFunction": {
"oneOf": [
{
"$ref": "./catalog-functions-expressions.json#/functions/add"
},
{
"$ref": "./catalog-functions-expressions.json#/functions/sub"
},
{
"$ref": "./catalog-functions-expressions.json#/functions/mul"
},
{
"$ref": "./catalog-functions-expressions.json#/functions/div"
},
{
"$ref": "./catalog-functions-expressions.json#/functions/mod"
},
{
"$ref": "./catalog-functions-expressions.json#/functions/eq"
},
{
"$ref": "./catalog-functions-expressions.json#/functions/ne"
},
{
"$ref": "./catalog-functions-expressions.json#/functions/lt"
},
{
"$ref": "./catalog-functions-expressions.json#/functions/lte"
},
{
"$ref": "./catalog-functions-expressions.json#/functions/gt"
},
{
"$ref": "./catalog-functions-expressions.json#/functions/gte"
},
{
"$ref": "./catalog-functions-expressions.json#/functions/cond"
},
{
"$ref": "./catalog-functions-expressions.json#/functions/toDouble"
},
{
"$ref": "./catalog-functions-expressions.json#/functions/toLong"
},
{
"$ref": "./catalog-functions-expressions.json#/functions/objectGet"
},
{
"$ref": "./catalog-functions-expressions.json#/functions/arrayGet"
},
{
"$ref": "./catalog-functions-expressions.json#/functions/arrayFind"
},
{
"$ref": "./catalog-functions-expressions.json#/functions/getLength"
}
]
}
}
}
@@ -0,0 +1,607 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://dingtalk.com/card/a2ui/catalog-functions-host-actions.json",
"title": "DingTalk AICard Protocol V0.8 DingTalk host actions",
"description": "0 components and 7 functions. A reading shard of the DingTalk public catalog, not a separate runtime catalog.",
"catalogId": "https://dingtalk.com/card/a2ui/catalogs/public/catalog.json",
"protocolVersion": "1.0",
"instructions": "Read entries needed for the current task, then follow their $ref dependencies. Common types: ./common-types-basic.json, ./common-types-extended.json and ./common-types-visual.json. Do not load all shards into the model context by default.\nCommon components: ./catalog-components-common.json.\nComposition and repeated layouts: ./catalog-components-composition.json.\nInputs and pickers: ./catalog-components-inputs.json.\nData display and media: ./catalog-components-specialized.json.\nCore functions adapted by DingTalk from A2UI: ./catalog-functions-core.json.\nDingTalk expressions and operators: ./catalog-functions-expressions.json.\nDingTalk host actions: ./catalog-functions-host-actions.json.\nSelect examples from ./examples/README.md; message structures are in ./agent-to-renderer.json.\nThis is the public DingTalk AICard Protocol V0.8 package. Use only the components, fields, functions, and common-type public values listed in the files loaded and assembled for the current scope.\nfallbackMarkdown is an optional DingTalk extension for component-level fallback content. It is used only when the current renderer cannot render the component. Unknown fields and field-validation errors do not trigger it. When omitted, the renderer displays the standard upgrade message.\nSchema references are local file references and require no HTTP access. catalogId is a runtime catalog identifier, not a file path.\nThe #/$defs/anyComponent union describes catalog-specific fields only. Validate complete component instances through the message envelope or loadSchemas().validateComponent, which combines ComponentCommon with this union and rejects unknown fields. The catalog root is not a validation entry point for complete messages or component instances. Complete messages must also conform to the main protocol; dynamic result types, component-tree references, and platform capabilities are validated at runtime.\nExpressions use {\"call\":…, \"args\":…} without an additional profile declaration. A host action must explicitly set functionCall.catalogId to urn:dingtalk:a2ui:host:v1. A public catalog HTTP identifier from a surface or component cannot replace the host Function catalog. For promptText, initialValue is the prefilled-text parameter and text is a result field, not an input parameter.\nAttach form-validation checks to the Button that submits the form. Do not rely on standard event-response fields for automatic write-back.\nUserPicker, ConversationPicker, and ImageUpload require host authorization. Server-side callbacks must still enforce business authorization.",
"components": {},
"functions": {
"copyText": {
"type": "object",
"description": "Copies text.\n\nResult schema:\n```json\n{\n \"oneOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"status\": {\n \"const\": \"success\"\n },\n \"data\": {\n \"additionalProperties\": false,\n \"properties\": {},\n \"required\": [],\n \"type\": \"object\"\n }\n },\n \"required\": [\n \"status\",\n \"data\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"status\": {\n \"const\": \"failed\"\n }\n },\n \"required\": [\n \"status\"\n ],\n \"additionalProperties\": false\n }\n ]\n}\n```",
"returnType": "void",
"properties": {
"call": {
"const": "copyText"
},
"args": {
"additionalProperties": false,
"properties": {
"text": {
"anyOf": [
{
"maxLength": 65536,
"type": "string"
},
{
"$ref": "./common-types-basic.json#/$defs/DataBinding"
},
{
"$ref": "./common-types-basic.json#/$defs/FunctionCall"
}
]
}
},
"required": [
"text"
],
"type": "object",
"anyOf": [
{
"$ref": "./common-types-extended.json#/$defs/HostStaticValueTree"
},
{
"$ref": "./common-types-extended.json#/$defs/HostCompiledValueTree"
}
]
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"openChat": {
"type": "object",
"description": "Opens a conversation.\n\nResult schema:\n```json\n{\n \"oneOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"status\": {\n \"const\": \"success\"\n },\n \"data\": {\n \"additionalProperties\": false,\n \"properties\": {},\n \"required\": [],\n \"type\": \"object\"\n }\n },\n \"required\": [\n \"status\",\n \"data\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"status\": {\n \"const\": \"failed\"\n }\n },\n \"required\": [\n \"status\"\n ],\n \"additionalProperties\": false\n }\n ]\n}\n```",
"returnType": "void",
"properties": {
"call": {
"const": "openChat"
},
"args": {
"additionalProperties": false,
"properties": {
"openConversationId": {
"anyOf": [
{
"maxLength": 4096,
"minLength": 1,
"type": "string"
},
{
"$ref": "./common-types-basic.json#/$defs/DataBinding"
},
{
"$ref": "./common-types-basic.json#/$defs/FunctionCall"
}
]
}
},
"required": [
"openConversationId"
],
"type": "object",
"anyOf": [
{
"$ref": "./common-types-extended.json#/$defs/HostStaticValueTree"
},
{
"$ref": "./common-types-extended.json#/$defs/HostCompiledValueTree"
}
]
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"previewImages": {
"type": "object",
"description": "Previews 1–100 images. If `current` is provided, it must identify an item in the predetermined `urls` array.\n\nResult schema:\n```json\n{\n \"oneOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"status\": {\n \"const\": \"success\"\n },\n \"data\": {\n \"additionalProperties\": false,\n \"properties\": {},\n \"required\": [],\n \"type\": \"object\"\n }\n },\n \"required\": [\n \"status\",\n \"data\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"status\": {\n \"const\": \"failed\"\n }\n },\n \"required\": [\n \"status\"\n ],\n \"additionalProperties\": false\n }\n ]\n}\n```",
"returnType": "void",
"properties": {
"call": {
"const": "previewImages"
},
"args": {
"additionalProperties": false,
"properties": {
"current": {
"anyOf": [
{
"maxLength": 4096,
"minLength": 1,
"type": "string"
},
{
"$ref": "./common-types-basic.json#/$defs/DataBinding"
},
{
"$ref": "./common-types-basic.json#/$defs/FunctionCall"
}
]
},
"urls": {
"anyOf": [
{
"items": {
"anyOf": [
{
"maxLength": 4096,
"minLength": 1,
"type": "string"
},
{
"$ref": "./common-types-basic.json#/$defs/DataBinding"
},
{
"$ref": "./common-types-basic.json#/$defs/FunctionCall"
}
]
},
"maxItems": 100,
"minItems": 1,
"type": "array"
},
{
"$ref": "./common-types-basic.json#/$defs/DataBinding"
},
{
"$ref": "./common-types-basic.json#/$defs/FunctionCall"
}
]
}
},
"required": [
"urls"
],
"type": "object",
"anyOf": [
{
"$ref": "./common-types-extended.json#/$defs/HostStaticValueTree"
},
{
"$ref": "./common-types-extended.json#/$defs/HostCompiledValueTree"
}
],
"allOf": [
{
"if": {
"required": [
"current"
]
},
"then": {
"properties": {
"current": {
"$ref": "./common-types-extended.json#/$defs/HostStaticValueTree"
},
"urls": {
"anyOf": [
{
"type": "array"
},
{
"$ref": "./common-types-basic.json#/$defs/DataBinding"
},
{
"allOf": [
{
"$ref": "./common-types-basic.json#/$defs/FunctionCall"
},
{
"$ref": "./common-types-extended.json#/$defs/HostStaticValueTree"
}
]
}
]
}
}
}
}
]
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"previewVideo": {
"type": "object",
"description": "Previews a video.\n\nResult schema:\n```json\n{\n \"oneOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"status\": {\n \"const\": \"success\"\n },\n \"data\": {\n \"additionalProperties\": false,\n \"properties\": {},\n \"required\": [],\n \"type\": \"object\"\n }\n },\n \"required\": [\n \"status\",\n \"data\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"status\": {\n \"const\": \"failed\"\n }\n },\n \"required\": [\n \"status\"\n ],\n \"additionalProperties\": false\n }\n ]\n}\n```",
"returnType": "void",
"properties": {
"call": {
"const": "previewVideo"
},
"args": {
"additionalProperties": false,
"properties": {
"posterUrl": {
"anyOf": [
{
"maxLength": 4096,
"type": "string"
},
{
"$ref": "./common-types-basic.json#/$defs/DataBinding"
},
{
"$ref": "./common-types-basic.json#/$defs/FunctionCall"
}
]
},
"url": {
"anyOf": [
{
"maxLength": 4096,
"minLength": 1,
"type": "string"
},
{
"$ref": "./common-types-basic.json#/$defs/DataBinding"
},
{
"$ref": "./common-types-basic.json#/$defs/FunctionCall"
}
]
}
},
"required": [
"url"
],
"type": "object",
"anyOf": [
{
"$ref": "./common-types-extended.json#/$defs/HostStaticValueTree"
},
{
"$ref": "./common-types-extended.json#/$defs/HostCompiledValueTree"
}
]
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"promptText": {
"type": "object",
"description": "Opens a single-line input panel. Use `args.initialValue` for prefilled text; `text` is the result field returned after confirmation and cannot be used as an input parameter. Static bindings and string functions evaluated in advance are allowed; client-side expressions and `maxLength` are not supported. Canceling does not write back a value. See ./examples/host-action.json for a complete message example.\n\nResult schema:\n```json\n{\n \"oneOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"status\": {\n \"const\": \"success\"\n },\n \"data\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"text\": {\n \"description\": \"Text entered by the user and returned after confirmation. This is a result field, not the input parameter for prefilled text.\",\n \"maxLength\": 65536,\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"text\"\n ],\n \"type\": \"object\"\n }\n },\n \"required\": [\n \"status\",\n \"data\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"status\": {\n \"const\": \"failed\"\n }\n },\n \"required\": [\n \"status\"\n ],\n \"additionalProperties\": false\n }\n ]\n}\n```",
"returnType": "object",
"properties": {
"call": {
"const": "promptText"
},
"args": {
"additionalProperties": false,
"properties": {
"initialValue": {
"anyOf": [
{
"maxLength": 65536,
"type": "string"
},
{
"$ref": "./common-types-basic.json#/$defs/DataBinding"
},
{
"$ref": "./common-types-basic.json#/$defs/FunctionCall"
}
],
"description": "Text prefilled when the input panel opens. May be a string, data binding, or value function pre-evaluated to a string. If omitted, the input is initially empty."
},
"message": {
"anyOf": [
{
"maxLength": 4096,
"type": "string"
},
{
"$ref": "./common-types-basic.json#/$defs/DataBinding"
},
{
"$ref": "./common-types-basic.json#/$defs/FunctionCall"
}
],
"description": "Prompt shown by the desktop input panel. It is not inserted into the input value, and mobile clients currently do not display it."
},
"title": {
"anyOf": [
{
"maxLength": 4096,
"type": "string"
},
{
"$ref": "./common-types-basic.json#/$defs/DataBinding"
},
{
"$ref": "./common-types-basic.json#/$defs/FunctionCall"
}
],
"description": "The title of the input panel."
}
},
"required": [],
"type": "object",
"allOf": [
{
"$ref": "./common-types-extended.json#/$defs/HostStaticValueTree"
}
]
}
},
"required": [
"call"
],
"allowedCallers": "rendererOnly"
},
"showConfirm": {
"type": "object",
"description": "Shows a confirmation dialog. The call is rejected when `message` is empty and `title` is omitted. Canceling returns `confirmed=false`.\n\nResult schema:\n```json\n{\n \"oneOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"status\": {\n \"const\": \"success\"\n },\n \"data\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"confirmed\": {\n \"type\": \"boolean\"\n }\n },\n \"required\": [\n \"confirmed\"\n ],\n \"type\": \"object\"\n }\n },\n \"required\": [\n \"status\",\n \"data\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"status\": {\n \"const\": \"failed\"\n }\n },\n \"required\": [\n \"status\"\n ],\n \"additionalProperties\": false\n }\n ]\n}\n```",
"returnType": "object",
"properties": {
"call": {
"const": "showConfirm"
},
"args": {
"additionalProperties": false,
"properties": {
"cancelText": {
"anyOf": [
{
"maxLength": 128,
"type": "string"
},
{
"$ref": "./common-types-basic.json#/$defs/DataBinding"
},
{
"$ref": "./common-types-basic.json#/$defs/FunctionCall"
}
]
},
"confirmText": {
"anyOf": [
{
"maxLength": 128,
"type": "string"
},
{
"$ref": "./common-types-basic.json#/$defs/DataBinding"
},
{
"$ref": "./common-types-basic.json#/$defs/FunctionCall"
}
]
},
"message": {
"anyOf": [
{
"maxLength": 4096,
"type": "string"
},
{
"$ref": "./common-types-basic.json#/$defs/DataBinding"
},
{
"$ref": "./common-types-basic.json#/$defs/FunctionCall"
}
]
},
"title": {
"anyOf": [
{
"maxLength": 4096,
"type": "string"
},
{
"$ref": "./common-types-basic.json#/$defs/DataBinding"
},
{
"$ref": "./common-types-basic.json#/$defs/FunctionCall"
}
]
}
},
"required": [
"message"
],
"type": "object",
"anyOf": [
{
"$ref": "./common-types-extended.json#/$defs/HostStaticValueTree"
},
{
"$ref": "./common-types-extended.json#/$defs/HostCompiledValueTree"
}
],
"allOf": [
{
"if": {
"properties": {
"message": {
"const": ""
}
},
"required": [
"message"
]
},
"then": {
"required": [
"title"
]
}
}
]
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
},
"showModal": {
"type": "object",
"description": "Shows a dialog with custom buttons. Currently 1–2 buttons are supported, and parameters must be evaluated in advance. The cancel button added by desktop clients returns an empty `selectedId`.\n\nResult schema:\n```json\n{\n \"oneOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"status\": {\n \"const\": \"success\"\n },\n \"data\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"selectedId\": {\n \"maxLength\": 4096,\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"selectedId\"\n ],\n \"type\": \"object\"\n }\n },\n \"required\": [\n \"status\",\n \"data\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"status\": {\n \"const\": \"failed\"\n }\n },\n \"required\": [\n \"status\"\n ],\n \"additionalProperties\": false\n }\n ]\n}\n```",
"returnType": "object",
"properties": {
"call": {
"const": "showModal"
},
"args": {
"additionalProperties": false,
"properties": {
"buttons": {
"anyOf": [
{
"items": {
"anyOf": [
{
"additionalProperties": false,
"properties": {
"id": {
"anyOf": [
{
"maxLength": 4096,
"minLength": 1,
"type": "string"
},
{
"$ref": "./common-types-basic.json#/$defs/DataBinding"
},
{
"$ref": "./common-types-basic.json#/$defs/FunctionCall"
}
]
},
"title": {
"anyOf": [
{
"maxLength": 256,
"type": "string"
},
{
"$ref": "./common-types-basic.json#/$defs/DataBinding"
},
{
"$ref": "./common-types-basic.json#/$defs/FunctionCall"
}
]
}
},
"required": [
"id",
"title"
],
"type": "object"
},
{
"$ref": "./common-types-basic.json#/$defs/DataBinding"
},
{
"$ref": "./common-types-basic.json#/$defs/FunctionCall"
}
]
},
"maxItems": 2,
"minItems": 1,
"type": "array"
},
{
"$ref": "./common-types-basic.json#/$defs/DataBinding"
},
{
"$ref": "./common-types-basic.json#/$defs/FunctionCall"
}
]
},
"message": {
"anyOf": [
{
"maxLength": 4096,
"type": "string"
},
{
"$ref": "./common-types-basic.json#/$defs/DataBinding"
},
{
"$ref": "./common-types-basic.json#/$defs/FunctionCall"
}
]
},
"title": {
"anyOf": [
{
"maxLength": 4096,
"type": "string"
},
{
"$ref": "./common-types-basic.json#/$defs/DataBinding"
},
{
"$ref": "./common-types-basic.json#/$defs/FunctionCall"
}
]
}
},
"required": [
"message",
"buttons"
],
"type": "object",
"allOf": [
{
"$ref": "./common-types-extended.json#/$defs/HostStaticValueTree"
}
]
}
},
"required": [
"call",
"args"
],
"allowedCallers": "rendererOnly"
}
},
"$defs": {
"anyComponent": false,
"anyFunction": {
"oneOf": [
{
"$ref": "./catalog-functions-host-actions.json#/functions/copyText"
},
{
"$ref": "./catalog-functions-host-actions.json#/functions/openChat"
},
{
"$ref": "./catalog-functions-host-actions.json#/functions/previewImages"
},
{
"$ref": "./catalog-functions-host-actions.json#/functions/previewVideo"
},
{
"$ref": "./catalog-functions-host-actions.json#/functions/promptText"
},
{
"$ref": "./catalog-functions-host-actions.json#/functions/showConfirm"
},
{
"$ref": "./catalog-functions-host-actions.json#/functions/showModal"
}
]
}
}
}
@@ -0,0 +1,537 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://dingtalk.com/card/a2ui/common-types-basic.json",
"title": "DingTalk AICard Protocol V0.8 Basic Common Types",
"description": "Basic common types based on the current DingTalk definitions; sharing a name with an official type does not imply equivalence. See ./common-types-extended.json for action and expression extensions, and ./common-types-visual.json for colors, font sizes and icons. Basic components may depend on these types as well. The DingTalk AICard Protocol V0.8 is split into shards for selective loading. Consumers must assemble and validate the files required by the selected scope. Modified by DingTalk from A2UI v1.0 common_types.json; selected definitions and descriptions are retained. See NOTICE for provenance and changes.",
"$defs": {
"ComponentId": {
"type": "string",
"description": "The unique identifier for a component, used for both definitions and references within the same surface."
},
"AccessibilityAttributes": {
"type": "object",
"description": "Provides a name and detailed description for assistive technologies such as screen readers. ⚠️ Reserved by the protocol and currently ineffective: the field itself is valid and never causes a validation failure or a component fallback, but screen readers cannot reach the content configured here.",
"properties": {
"label": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "A short string, typically 1 to 3 words, used by assistive technologies to convey the purpose or intent of an element. For example, an input field might have an accessible label of 'User ID' or a button might be labeled 'Submit'."
},
"description": {
"$ref": "./common-types-basic.json#/$defs/DynamicString",
"description": "Additional information provided by assistive technologies about an element such as instructions, format requirements, or result of an action. For example, a mute button might have a label of 'Mute' and a description of 'Silences notifications about this conversation'."
}
}
},
"ComponentCommon": {
"type": "object",
"properties": {
"id": {
"$ref": "./common-types-basic.json#/$defs/ComponentId"
},
"catalogId": {
"type": "string",
"description": "Component-level `catalogId` that overrides the surface default catalog."
},
"accessibility": {
"$ref": "./common-types-basic.json#/$defs/AccessibilityAttributes"
},
"visible": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean",
"description": "Visibility control (boolean expression or literal)."
},
"metadata": {}
},
"required": [
"id"
],
"allOf": [
{
"$ref": "./common-types-extended.json#/$defs/HostActionOwner"
}
]
},
"Child": {
"$ref": "./common-types-basic.json#/$defs/ComponentId",
"description": "A reference to a single child component ID."
},
"ChildList": {
"oneOf": [
{
"type": "array",
"items": {
"$ref": "./common-types-basic.json#/$defs/ComponentId"
},
"description": "A static list of child component IDs."
},
{
"type": "object",
"description": "A template for generating a dynamic list of children from a data model list. The `componentId` is the component to use as a template.",
"properties": {
"componentId": {
"$ref": "./common-types-basic.json#/$defs/ComponentId"
},
"path": {
"type": "string",
"description": "The path to the list of component property objects in the data model."
}
},
"required": [
"componentId",
"path"
],
"additionalProperties": false
}
]
},
"DataBinding": {
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "Data model path; relative paths can be used within the template, and ~ can only be written as ~0 or ~1. Evaluation context, path normalization, and target existence are checked at runtime.",
"pattern": "^(?:[^~]|~[01])*$"
}
},
"required": [
"path"
],
"additionalProperties": false
},
"DynamicValue": {
"description": "General value: a string, number, boolean, array, `null`, plain object, data binding, or value-function result. An object containing `call` is parsed as a function call; an object whose only key is `path` is parsed as a binding.",
"oneOf": [
{
"type": "string"
},
{
"type": "number"
},
{
"type": "boolean"
},
{
"type": "array"
},
{
"type": "null"
},
{
"$ref": "./common-types-extended.json#/$defs/LiteralObject"
},
{
"$ref": "./common-types-basic.json#/$defs/DataBinding"
},
{
"$ref": "./common-types-basic.json#/$defs/FunctionCall"
}
]
},
"DynamicString": {
"description": "Represents a value that can be either a string literal, a path to a string in the data model, or a function call returning a string.",
"oneOf": [
{
"type": "string"
},
{
"$ref": "./common-types-basic.json#/$defs/DataBinding"
},
{
"$ref": "./common-types-basic.json#/$defs/FunctionCall"
}
]
},
"DynamicNumber": {
"description": "Numeric dynamic value: It can be a JSON number literal, a DataBinding pointing to a numeric value, or a FunctionCall that returns a numeric value. The runtime results of bindings and functions must also be JSON numbers; no implicit conversion from string to number is performed, and numeric strings and ISO 8601 date-time strings are both invalid.",
"oneOf": [
{
"type": "number"
},
{
"$ref": "./common-types-basic.json#/$defs/DataBinding"
},
{
"$ref": "./common-types-basic.json#/$defs/FunctionCall"
}
]
},
"DynamicBoolean": {
"description": "A boolean value that can be a literal, a path, or a function call returning a boolean.",
"oneOf": [
{
"type": "boolean"
},
{
"$ref": "./common-types-basic.json#/$defs/DataBinding"
},
{
"$ref": "./common-types-basic.json#/$defs/FunctionCall"
}
]
},
"DynamicStringList": {
"description": "Represents a value that can be either a literal array of strings, a path to a string array in the data model, or a function call returning a string array.",
"oneOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"$ref": "./common-types-basic.json#/$defs/DataBinding"
},
{
"$ref": "./common-types-basic.json#/$defs/FunctionCall"
}
]
},
"FunctionCommon": {
"type": "object",
"properties": {
"catalogId": {
"type": "string",
"description": "Function catalog identifier. If omitted, the default catalog of the containing surface is used. This is not a Schema file path."
}
},
"allOf": [
{
"if": {
"properties": {
"call": {
"const": "copyText"
}
},
"required": [
"call"
]
},
"then": {
"properties": {
"catalogId": {
"const": "urn:dingtalk:a2ui:host:v1",
"description": "Required. Explicitly specifies the DingTalk host Function catalog. The public catalog HTTP identifier of the containing surface or component cannot replace this value."
}
},
"required": [
"catalogId"
]
}
},
{
"if": {
"properties": {
"call": {
"const": "openChat"
}
},
"required": [
"call"
]
},
"then": {
"properties": {
"catalogId": {
"const": "urn:dingtalk:a2ui:host:v1",
"description": "Required. Explicitly specifies the DingTalk host Function catalog. The public catalog HTTP identifier of the containing surface or component cannot replace this value."
}
},
"required": [
"catalogId"
]
}
},
{
"if": {
"properties": {
"call": {
"const": "previewImages"
}
},
"required": [
"call"
]
},
"then": {
"properties": {
"catalogId": {
"const": "urn:dingtalk:a2ui:host:v1",
"description": "Required. Explicitly specifies the DingTalk host Function catalog. The public catalog HTTP identifier of the containing surface or component cannot replace this value."
}
},
"required": [
"catalogId"
]
}
},
{
"if": {
"properties": {
"call": {
"const": "previewVideo"
}
},
"required": [
"call"
]
},
"then": {
"properties": {
"catalogId": {
"const": "urn:dingtalk:a2ui:host:v1",
"description": "Required. Explicitly specifies the DingTalk host Function catalog. The public catalog HTTP identifier of the containing surface or component cannot replace this value."
}
},
"required": [
"catalogId"
]
}
},
{
"if": {
"properties": {
"call": {
"const": "promptText"
}
},
"required": [
"call"
]
},
"then": {
"properties": {
"catalogId": {
"const": "urn:dingtalk:a2ui:host:v1",
"description": "Required. Explicitly specifies the DingTalk host Function catalog. The public catalog HTTP identifier of the containing surface or component cannot replace this value."
}
},
"required": [
"catalogId"
]
}
},
{
"if": {
"properties": {
"call": {
"const": "showConfirm"
}
},
"required": [
"call"
]
},
"then": {
"properties": {
"catalogId": {
"const": "urn:dingtalk:a2ui:host:v1",
"description": "Required. Explicitly specifies the DingTalk host Function catalog. The public catalog HTTP identifier of the containing surface or component cannot replace this value."
}
},
"required": [
"catalogId"
]
}
},
{
"if": {
"properties": {
"call": {
"const": "showModal"
}
},
"required": [
"call"
]
},
"then": {
"properties": {
"catalogId": {
"const": "urn:dingtalk:a2ui:host:v1",
"description": "Required. Explicitly specifies the DingTalk host Function catalog. The public catalog HTTP identifier of the containing surface or component cannot replace this value."
}
},
"required": [
"catalogId"
]
}
}
]
},
"FunctionCall": {
"type": "object",
"description": "A2UI v1.0 FunctionCall: Call the renderer function registered in the current surface catalog.",
"properties": {
"call": {
"type": "string",
"description": "The name of the function to call."
},
"catalogId": {
"type": "string",
"description": "The catalog ID for this function, overriding any surface-level default catalogId."
},
"args": {
"type": "object",
"description": "Arguments passed to the function.",
"additionalProperties": {
"anyOf": [
{
"$ref": "./common-types-basic.json#/$defs/DynamicValue"
},
{
"type": "object",
"description": "A literal object argument (e.g. configuration)."
}
]
}
}
},
"required": [
"call"
],
"unevaluatedProperties": false,
"oneOf": [
{
"$ref": "./catalog-functions-core.json#/$defs/anyFunction"
},
{
"$ref": "./catalog-functions-expressions.json#/$defs/anyFunction"
},
{
"$ref": "./catalog-functions-host-actions.json#/$defs/anyFunction"
},
{
"$ref": "./common-types-basic.json#/$defs/IndexSystemFunction"
}
],
"allOf": [
{
"$ref": "./common-types-basic.json#/$defs/FunctionCommon"
}
]
},
"CheckRule": {
"type": "object",
"description": "A single validation rule applied to an input component.",
"properties": {
"condition": {
"$ref": "./common-types-basic.json#/$defs/DynamicBoolean"
},
"message": {
"type": "string",
"description": "The error message to display if the check fails."
}
},
"required": [
"condition",
"message"
],
"additionalProperties": false
},
"Action": {
"description": "Defines an interaction handler that can either trigger an agent-side event or execute a local renderer-side function.",
"oneOf": [
{
"type": "object",
"description": "Triggers an agent-side event.",
"properties": {
"event": {
"type": "object",
"description": "The event to dispatch to the agent.",
"properties": {
"name": {
"type": "string",
"description": "The name of the action to be dispatched to the agent."
},
"context": {
"type": "object",
"description": "A JSON object containing the key-value pairs for the action context. Values can be literals or paths. Use literal values unless the value must be dynamically bound to the data model. Do NOT use paths for static IDs.",
"additionalProperties": {
"$ref": "./common-types-basic.json#/$defs/DynamicValue"
}
},
"wantResponse": {
"type": "boolean",
"description": "Response-request metadata. The current public integration does not guarantee the standard response loop; do not rely on `true` to generate a response automatically.",
"default": false
},
"responsePath": {
"type": "string",
"description": "Standard event-response-path metadata. The current public integration does not guarantee automatic write-back. Host-function results use `metadata.extensions.dt_actionBindingsV1`; business updates use `updateDataModel` or `updateComponents`."
}
},
"required": [
"name"
],
"additionalProperties": false
}
},
"required": [
"event"
],
"additionalProperties": false
},
{
"type": "object",
"description": "Executes a local renderer-side function.",
"properties": {
"functionCall": {
"$ref": "./common-types-basic.json#/$defs/FunctionCall"
}
},
"required": [
"functionCall"
],
"additionalProperties": false
}
]
},
"Surface": {
"title": "Surface Container Component",
"description": "Reserved message layer type, not connected to the package component validation entry; does not indicate that new component or theme capabilities have been opened. The reserved canonical container component representing an A2UI surface. The Surface component is immutable and always has 'child': 'root'.",
"type": "object",
"allowedParents": [],
"properties": {
"component": {
"const": "Surface"
},
"child": {
"const": "root"
}
},
"additionalProperties": false
},
"IndexSystemFunction": {
"type": "object",
"description": "Returns the 0-based index of the current item when rendering a dynamic list from a template. This function MUST ONLY be available when evaluating template items within a list context.",
"returnType": "number",
"properties": {
"call": {
"const": "@index"
},
"args": {
"type": "object",
"properties": {
"offset": {
"$ref": "./common-types-basic.json#/$defs/DynamicNumber",
"description": "Optional. An offset to add to the 0-based index (e.g., 1 for 1-based indexing). Defaults to 0.",
"default": 0
}
},
"unevaluatedProperties": false
}
},
"required": [
"call"
],
"unevaluatedProperties": false
},
"Extensions": {
"type": "object",
"description": "Optional extension metadata. Keys MUST be Unicode identifiers (UAX #31). Keys starting with 'a2ui_' are reserved for official extensions.",
"patternProperties": {
"^[\\p{XID_Start}_][\\p{XID_Continue}]*$": {}
},
"additionalProperties": false
}
}
}
@@ -0,0 +1,458 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://dingtalk.com/card/a2ui/common-types-extended.json",
"title": "DingTalk AICard Protocol V0.8 Extended Common Types",
"description": "DingTalk extended common types for dynamic objects, host arguments and write-back constraints. Result schemas are documented with each host function. See ./common-types-basic.json for basic types and ./common-types-visual.json for colors, font sizes and icons. Read the referenced definitions when basic components use extended types. The DingTalk AICard Protocol V0.8 is split into shards for selective loading. Consumers must assemble and validate the files required by the selected scope.",
"$defs": {
"LiteralObject": {
"type": "object",
"description": "Plain object literal. Objects containing `call` are reserved for function calls, while objects whose only key is `path` are reserved for bindings, preventing ambiguous matches with dynamic expressions.",
"not": {
"anyOf": [
{
"required": [
"call"
]
},
{
"required": [
"path"
],
"maxProperties": 1
}
]
}
},
"HostStaticValueTree": {
"description": "Constraints on the evaluation phase of the host parameter subtree; the actual value type, path, and expression legality are still checked by the existing runtime.",
"additionalProperties": {
"$ref": "./common-types-extended.json#/$defs/HostStaticValueTree"
},
"items": {
"$ref": "./common-types-extended.json#/$defs/HostStaticValueTree"
}
},
"HostCompiledValueTree": {
"description": "Constraints on the evaluation phase of the host parameter subtree; the actual value type, path, and expression legality are still checked by the existing runtime.",
"additionalProperties": {
"$ref": "./common-types-extended.json#/$defs/HostCompiledValueTree"
},
"items": {
"$ref": "./common-types-extended.json#/$defs/HostCompiledValueTree"
},
"not": {
"type": "object",
"properties": {
"call": {
"not": {
"enum": [
"eq",
"ne",
"lt",
"lte",
"gt",
"gte",
"add",
"sub",
"mul",
"div",
"mod",
"cond",
"and",
"or",
"not",
"objectGet",
"arrayGet",
"arrayFind",
"getLength",
"toDouble",
"toLong"
]
}
}
},
"required": [
"call"
]
}
},
"HostResultPath": {
"type": "string",
"maxLength": 256,
"pattern": "^/ui/(?=[^/]*[A-Za-z_-])[A-Za-z0-9_-]+(?:/(?=[^/]*[A-Za-z_-])[A-Za-z0-9_-]+){0,14}$",
"description": "Result write-back path. Only object keys under `/ui/` are allowed, with a maximum of 256 ASCII characters and 16 segments including `ui`. Empty segments, all-numeric segments, and escape sequences are prohibited."
},
"HostActionBinding": {
"type": "object",
"properties": {
"resultPath": {
"$ref": "./common-types-extended.json#/$defs/HostResultPath"
}
},
"required": [
"resultPath"
],
"additionalProperties": false
},
"HostActionOwner": {
"type": "object",
"allOf": [
{
"if": {
"properties": {
"action": {
"type": "object",
"properties": {
"functionCall": {
"type": "object",
"properties": {
"call": {
"enum": [
"copyText",
"openChat",
"previewImages",
"previewVideo",
"promptText",
"showConfirm",
"showModal"
]
}
},
"required": [
"call"
]
}
},
"required": [
"functionCall"
]
}
},
"required": [
"action"
]
},
"then": {
"properties": {
"metadata": {
"anyOf": [
{
"type": "null"
},
{
"type": "object",
"properties": {
"extensions": {
"type": "object",
"patternProperties": {
"^dt_actionBindings(?!V1$)": false
},
"properties": {
"dt_actionBindingsV1": {
"type": "object",
"properties": {
"action": {
"$ref": "./common-types-extended.json#/$defs/HostActionBinding"
}
},
"required": [
"action"
]
}
}
}
}
}
]
}
}
}
},
{
"if": {
"properties": {
"onComplete": {
"type": "object",
"properties": {
"functionCall": {
"type": "object",
"properties": {
"call": {
"enum": [
"copyText",
"openChat",
"previewImages",
"previewVideo",
"promptText",
"showConfirm",
"showModal"
]
}
},
"required": [
"call"
]
}
},
"required": [
"functionCall"
]
}
},
"required": [
"onComplete"
]
},
"then": {
"properties": {
"metadata": {
"anyOf": [
{
"type": "null"
},
{
"type": "object",
"properties": {
"extensions": {
"type": "object",
"patternProperties": {
"^dt_actionBindings(?!V1$)": false
},
"properties": {
"dt_actionBindingsV1": {
"type": "object",
"properties": {
"onComplete": {
"$ref": "./common-types-extended.json#/$defs/HostActionBinding"
}
},
"required": [
"onComplete"
]
}
}
}
}
}
]
}
}
}
},
{
"if": {
"properties": {
"onLinkClick": {
"type": "object",
"properties": {
"functionCall": {
"type": "object",
"properties": {
"call": {
"enum": [
"copyText",
"openChat",
"previewImages",
"previewVideo",
"promptText",
"showConfirm",
"showModal"
]
}
},
"required": [
"call"
]
}
},
"required": [
"functionCall"
]
}
},
"required": [
"onLinkClick"
]
},
"then": {
"properties": {
"metadata": {
"anyOf": [
{
"type": "null"
},
{
"type": "object",
"properties": {
"extensions": {
"type": "object",
"patternProperties": {
"^dt_actionBindings(?!V1$)": false
},
"properties": {
"dt_actionBindingsV1": {
"type": "object",
"properties": {
"onLinkClick": {
"$ref": "./common-types-extended.json#/$defs/HostActionBinding"
}
},
"required": [
"onLinkClick"
]
}
}
}
}
}
]
}
}
}
},
{
"if": {
"properties": {
"onPreview": {
"type": "object",
"properties": {
"functionCall": {
"type": "object",
"properties": {
"call": {
"enum": [
"copyText",
"openChat",
"previewImages",
"previewVideo",
"promptText",
"showConfirm",
"showModal"
]
}
},
"required": [
"call"
]
}
},
"required": [
"functionCall"
]
}
},
"required": [
"onPreview"
]
},
"then": {
"properties": {
"metadata": {
"anyOf": [
{
"type": "null"
},
{
"type": "object",
"properties": {
"extensions": {
"type": "object",
"patternProperties": {
"^dt_actionBindings(?!V1$)": false
},
"properties": {
"dt_actionBindingsV1": {
"type": "object",
"properties": {
"onPreview": {
"$ref": "./common-types-extended.json#/$defs/HostActionBinding"
}
},
"required": [
"onPreview"
]
}
}
}
}
}
]
}
}
}
},
{
"if": {
"properties": {
"onTap": {
"type": "object",
"properties": {
"functionCall": {
"type": "object",
"properties": {
"call": {
"enum": [
"copyText",
"openChat",
"previewImages",
"previewVideo",
"promptText",
"showConfirm",
"showModal"
]
}
},
"required": [
"call"
]
}
},
"required": [
"functionCall"
]
}
},
"required": [
"onTap"
]
},
"then": {
"properties": {
"metadata": {
"anyOf": [
{
"type": "null"
},
{
"type": "object",
"properties": {
"extensions": {
"type": "object",
"patternProperties": {
"^dt_actionBindings(?!V1$)": false
},
"properties": {
"dt_actionBindingsV1": {
"type": "object",
"properties": {
"onTap": {
"$ref": "./common-types-extended.json#/$defs/HostActionBinding"
}
},
"required": [
"onTap"
]
}
}
}
}
}
]
}
}
}
}
]
}
}
}
@@ -0,0 +1,475 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://dingtalk.com/card/a2ui/common-types-visual.json",
"title": "DingTalk AICard Protocol V0.8 Visual Common Types",
"description": "DingTalk visual common types defining ColorToken, SizeToken and IconName. Read entries for the color, font-size and icon fields actually used by the components; this grouping introduces no new style fields or runtime capabilities. The DingTalk AICard Protocol V0.8 is split into shards for selective loading. Consumers must assemble and validate the files required by the selected scope.",
"$defs": {
"SizeToken": {
"type": "string",
"description": "DDesign native font size Token ID, used for Text.sizeToken. Prefer selecting IDs with the __font_size suffix according to specific usage; the actual font size is parsed by the current host, and consistent cross-platform font size or line height is not guaranteed, nor will a UIFont style with the same name be automatically applied. Design names like font-size/body, style names without suffixes, and __line_height keys are not font size IDs here.",
"anyOf": [
{
"const": "common_largetitle_text_style__font_size",
"description": "Main title, used as the heading for a page or major content section."
},
{
"const": "common_supertitle_text_style__font_size",
"description": "Extra-large title, used as the main title for a page or module."
},
{
"const": "common_h1_text_style__font_size",
"description": "Level 1 heading, used for card or content area titles."
},
{
"const": "common_h2_text_style__font_size",
"description": "Level 2 heading, used for content-group headings."
},
{
"const": "common_h3_text_style__font_size",
"description": "Level 3 heading, used for smaller-level content titles."
},
{
"const": "common_h4_text_style__font_size",
"description": "Level 4 heading, used for subheadings or supplementary information under a heading."
},
{
"const": "common_body_text_style__font_size",
"description": "Main text, used for the primary content."
},
{
"const": "common_action_text_style__font_size",
"description": "Action text, used for buttons, links, and other operational copy."
},
{
"const": "common_description_text_style__font_size",
"description": "Auxiliary explanation, used for secondary information and supplementary notes."
},
{
"const": "common_footnote_text_style__font_size",
"description": "Footnotes, used for sources, notes, image captions, or status tags."
},
{
"const": "common_tiny_text_style__font_size",
"description": "Small text prompts, used as subtle hints in space-constrained scenarios."
},
{
"const": "common_subhead_text_style__font_size",
"description": "Subtitle, used for supplementary information below the title."
},
{
"type": "string",
"description": "Retain existing string inputs. The above items are selection descriptions for known native Tokens, not a closed enumeration. Other Tokens must be confirmed registered by the host. Schema accepting a string does not mean the Token is available; if the host cannot find it, it will fall back to the variant slot."
}
],
"examples": [
"common_largetitle_text_style__font_size",
"common_supertitle_text_style__font_size",
"common_h1_text_style__font_size",
"common_h2_text_style__font_size",
"common_h3_text_style__font_size",
"common_h4_text_style__font_size",
"common_body_text_style__font_size",
"common_action_text_style__font_size",
"common_description_text_style__font_size",
"common_footnote_text_style__font_size",
"common_tiny_text_style__font_size",
"common_subhead_text_style__font_size"
]
},
"ColorToken": {
"type": "string",
"description": "Only the 57 Token IDs listed in the table below are allowed, with case-sensitive names. The description explains their purpose and state semantics; the actual color values and transparency are interpreted by the host according to the current platform and theme, and this protocol does not fix the color values.",
"enum": [
"extended_yellow0_color",
"extended_yellow1_color",
"extended_yellow6_color",
"extended_orange0_color",
"extended_orange1_color",
"extended_orange6_color",
"extended_red0_color",
"extended_red1_color",
"extended_red6_color",
"extended_magenta0_color",
"extended_magenta1_color",
"extended_magenta6_color",
"extended_purple0_color",
"extended_purple1_color",
"extended_purple6_color",
"extended_deeppurple0_color",
"extended_deeppurple1_color",
"extended_deeppurple6_color",
"extended_blue0_color",
"extended_blue1_color",
"extended_blue6_color",
"extended_darkgreen0_color",
"extended_darkgreen1_color",
"extended_darkgreen6_color",
"extended_green0_color",
"extended_green1_color",
"extended_green6_color",
"common_level1_base_color",
"common_level2_base_color",
"common_level3_base_color",
"common_level4_base_color",
"common_stamp_color",
"common_link_color",
"common_bg_color",
"common_fg_z1_color",
"common_line_light_color",
"common_line_hard_color",
"common_red1_color",
"common_orange1_color",
"common_green1_color",
"common_white1_color",
"common_white2_color",
"common_white3_color",
"common_white4_color",
"common_white5_color",
"common_white6_color",
"common_black1_color",
"common_black2_color",
"common_black3_color",
"common_black4_color",
"common_black5_color",
"common_black6_color",
"theme_primary3_color",
"theme_primary2_color",
"theme_primary_hover_color",
"theme_primary1_color",
"theme_primary_press_color"
],
"oneOf": [
{
"const": "extended_yellow0_color",
"description": "Yellow background color; used for background filling in areas of this color scheme."
},
{
"const": "extended_yellow1_color",
"description": "Yellow border color; used for outlining areas of this color scheme."
},
{
"const": "extended_yellow6_color",
"description": "Yellow text color; used for text emphasis in this color scheme."
},
{
"const": "extended_orange0_color",
"description": "Orange background color; used for area background filling in this color scheme."
},
{
"const": "extended_orange1_color",
"description": "Orange border color; used for outlining areas of this color scheme."
},
{
"const": "extended_orange6_color",
"description": "Orange text color; used for text emphasis in this color scheme."
},
{
"const": "extended_red0_color",
"description": "Red background color; used for background filling in areas of this color series."
},
{
"const": "extended_red1_color",
"description": "Red border color; used for the stroke of areas in this color scheme."
},
{
"const": "extended_red6_color",
"description": "Red text color; used for emphasizing text in this color scheme."
},
{
"const": "extended_magenta0_color",
"description": "Magenta background color; used for background filling in areas of this color scheme."
},
{
"const": "extended_magenta1_color",
"description": "Magenta border color; used for outlining areas of this color scheme."
},
{
"const": "extended_magenta6_color",
"description": "Magenta text color; used for text emphasis in this color scheme."
},
{
"const": "extended_purple0_color",
"description": "Purple background color; used for background filling in areas of this color scheme."
},
{
"const": "extended_purple1_color",
"description": "Purple border color; used for the stroke of areas in this color scheme."
},
{
"const": "extended_purple6_color",
"description": "Purple text color; used for emphasizing text in this color scheme."
},
{
"const": "extended_deeppurple0_color",
"description": "Deep purple background color; used for background filling in areas of this color scheme."
},
{
"const": "extended_deeppurple1_color",
"description": "Deep purple border color; used for outlining areas of this color scheme."
},
{
"const": "extended_deeppurple6_color",
"description": "Deep purple text color; used for text emphasis in this color scheme."
},
{
"const": "extended_blue0_color",
"description": "Blue background color; used for background filling in areas of this color scheme."
},
{
"const": "extended_blue1_color",
"description": "Blue border color; used for the stroke of areas in this color scheme."
},
{
"const": "extended_blue6_color",
"description": "Blue text color; used for emphasizing text in this color scheme."
},
{
"const": "extended_darkgreen0_color",
"description": "Dark green background color; used for area background filling in this color scheme."
},
{
"const": "extended_darkgreen1_color",
"description": "Dark green border color; used for outlining areas of this color scheme."
},
{
"const": "extended_darkgreen6_color",
"description": "Dark green text color; used for text emphasis in this color scheme."
},
{
"const": "extended_green0_color",
"description": "Green background color; used for background filling in areas of this color scheme."
},
{
"const": "extended_green1_color",
"description": "Green border color; used for outlining areas of this color scheme."
},
{
"const": "extended_green6_color",
"description": "Green text color; used for text emphasis in this color scheme."
},
{
"const": "common_level1_base_color",
"description": "Primary text and icons; used for titles, body text, and other main information."
},
{
"const": "common_level2_base_color",
"description": "Secondary text and icons; used for secondary information and auxiliary icons."
},
{
"const": "common_level3_base_color",
"description": "Tertiary text and icons; used for weaker supplementary information."
},
{
"const": "common_level4_base_color",
"description": "Text and icon color in a disabled state; only conveys visual state."
},
{
"const": "common_stamp_color",
"description": "Watermark color; used for low-interference watermark content."
},
{
"const": "common_link_color",
"description": "Hyperlink text and highlight border color."
},
{
"const": "common_bg_color",
"description": "Background color of the area; used for the background of a page or content area."
},
{
"const": "common_fg_z1_color",
"description": "Foreground area background color; used for content areas on top of the base background."
},
{
"const": "common_line_light_color",
"description": "Weak divider; used for lighter content separation."
},
{
"const": "common_line_hard_color",
"description": "Strong divider line; used for content separation where a clearer boundary is needed."
},
{
"const": "common_red1_color",
"description": "Danger state color; used to convey dangerous or erroneous semantics."
},
{
"const": "common_orange1_color",
"description": "Warning state color; used for prompts that require the user's attention."
},
{
"const": "common_green1_color",
"description": "Success state color; used for success or completion feedback."
},
{
"const": "common_white1_color",
"description": "White mask; used for white overlay, actual transparency is determined by the host theme resources."
},
{
"const": "common_white2_color",
"description": "White mask (designed as 40% level); used for white overlays, actual transparency is determined by the host theme resources."
},
{
"const": "common_white3_color",
"description": "White mask (designed as 30% level); used for white overlays, actual transparency is determined by the host theme resources."
},
{
"const": "common_white4_color",
"description": "White mask (designed as 20% level); used for white overlays, actual transparency is interpreted according to the host theme resources."
},
{
"const": "common_white5_color",
"description": "White mask (designed as 10% level); used for white overlay, actual transparency is interpreted according to the host theme resources."
},
{
"const": "common_white6_color",
"description": "White mask (designed as 5% level); used for white overlay, actual transparency is interpreted according to the host theme resources."
},
{
"const": "common_black1_color",
"description": "Black mask; used for black overlay, actual transparency is determined by the host theme resources."
},
{
"const": "common_black2_color",
"description": "Black mask (designed as 40% level); used for black overlays, actual opacity is determined by the host theme resources."
},
{
"const": "common_black3_color",
"description": "Black mask (designed as 30% level); used for black overlays, actual transparency is resolved according to the host theme resources."
},
{
"const": "common_black4_color",
"description": "Black mask (designed as 20% level); used for black overlays, actual transparency is interpreted according to the host theme resources."
},
{
"const": "common_black5_color",
"description": "Black mask (designed as 10% level); used for black overlays, actual opacity is interpreted according to the host theme resources."
},
{
"const": "common_black6_color",
"description": "Black mask (designed as 5% level); used for black overlays, actual transparency is determined by the host theme resources."
},
{
"const": "theme_primary3_color",
"description": "Theme background color; used for the background of areas that carry the theme style."
},
{
"const": "theme_primary2_color",
"description": "Light theme color; used for lighter theme color highlights and auxiliary decoration."
},
{
"const": "theme_primary_hover_color",
"description": "Theme hover color; used for the visual feedback of the theme color when the pointer hovers."
},
{
"const": "theme_primary1_color",
"description": "Theme primary color; used for main theme emphasis."
},
{
"const": "theme_primary_press_color",
"description": "Theme pressed color; used for the visual feedback of the theme color when pressed."
}
]
},
"IconName": {
"type": "string",
"description": "Common type `IconName`: 24 case-sensitive public font-icon names referenced by `Icon.name`. The descriptions below preserve each icon's intended visual meaning and usage from the design mock.",
"oneOf": [
{
"const": "Search_L_outlined",
"description": "Search. Used for searching, searching content, searching files, searching images."
},
{
"const": "Language_L_outlined",
"description": "Language-switch icon. Used for web search in the design mock."
},
{
"const": "CodeProgram_L_outlined",
"description": "Code. Used to run commands in a terminal."
},
{
"const": "Picture_L_outlined",
"description": "Image. Used to generate images."
},
{
"const": "Folder_L_outlined",
"description": "Folder. Used for reading files."
},
{
"const": "Edit_L_outlined",
"description": "Edit or pen icon. Used for writing and creating files."
},
{
"const": "ListView_L_outlined",
"description": "List View 1. Used to list files."
},
{
"const": "ManagementBackground_L_outlined",
"description": "Admin console icon. The design mock uses it for browser access."
},
{
"const": "Tool_L_outlined",
"description": "Tools. Used to call tools, Workspace toolset, MCP toolset, DWS toolset, MCP invocation, and general fallback."
},
{
"const": "Delete_L_outlined",
"description": "Delete. Used for file deletion."
},
{
"const": "SpinLoading_L_outlined",
"description": "Loading spinner icon. Used for Skill loading and other loading states; the icon name itself does not enable a rotation animation."
},
{
"const": "UploadOne_L_outlined",
"description": "Upload. Used for file upload."
},
{
"const": "DownloadAndSave_L_outlined",
"description": "Download and save. Used for file downloads."
},
{
"const": "Check_L_outlined",
"description": "Check mark. Used to indicate completion or success."
},
{
"const": "Copy_L_outlined",
"description": "Copy. Used to copy text, content, or results."
},
{
"const": "Close_L_outlined",
"description": "Close, cross. Used to close pop-ups, panels, or pages."
},
{
"const": "More_L_outlined",
"description": "More, ellipsis, three dots. Used to open more action menus."
},
{
"const": "Error_L_outlined",
"description": "Warning, error reminder, circle with exclamation mark. Used to indicate operation failure or abnormal status."
},
{
"const": "InformationThere_L_outlined",
"description": "Information prompt, circular letter i. Used to display instructions or additional information."
},
{
"const": "Setting_L_outlined",
"description": "Settings, gear. Used to open settings or adjust configurations."
},
{
"const": "ExpandThere_L_outlined",
"description": "Expand. Used to enlarge the content area or expand the panel."
},
{
"const": "Collapse_L_outlined",
"description": "Collapse. Used to minimize the content area or collapse the panel."
},
{
"const": "Link_L_outlined",
"description": "Link, chain. Used to insert a link or open a related address."
},
{
"const": "Share_L_outlined",
"description": "Share, forward. Used for sharing content, conversations, or results."
}
]
}
}
}
@@ -0,0 +1,29 @@
---
status: authoritative
updated: 2026-09-21
scope: Four task-oriented message examples of DingTalk AICard Protocol V0.8
---
# DingTalk AICard Protocol V0.8 scenario examples
Read one matching scenario when composing bindings, actions or updates. For a single field, read its component or function definition instead. These are adaptable examples, not required layouts.
Each JSON file is a complete new-card message array: createSurface with the public catalogId, root updateDataModel, then updateComponents and any scenario updates. For a host-created empty Surface, omit createSurface; for an existing-card update, construct only the actual changes instead of replaying initial data and components. Keep each surfaceId consistent. See [Surface and delivery scenarios](../../../SKILL.md) for delivery boundaries. FULL_DATA / DELTA wrappers are not part of these arrays.
| Example | Demonstrates | Relevant shards |
|---|---|---|
| [form-interaction.json](form-interaction.json) | Persistent field titles, typed initial values, local input state, upload events and submit-button checks | [catalog-components-common.json](../catalog-components-common.json), [catalog-components-inputs.json](../catalog-components-inputs.json), [catalog-functions-core.json](../catalog-functions-core.json) |
| [host-action.json](host-action.json) | Explicit host catalog, promptText result writeback and item-owned button metadata | [catalog-components-common.json](../catalog-components-common.json), [catalog-components-composition.json](../catalog-components-composition.json), [catalog-functions-host-actions.json](../catalog-functions-host-actions.json) |
| [agent-progress.json](agent-progress.json) | Nested collapsed execution panels, incremental steps and a completed state | [catalog-components-common.json](../catalog-components-common.json), [catalog-components-composition.json](../catalog-components-composition.json) |
| [data-report.json](data-report.json) | Tabs, local table pagination, chart data, relative Loop bindings and Stack references | [catalog-components-common.json](../catalog-components-common.json), [catalog-components-composition.json](../catalog-components-composition.json), [catalog-components-specialized.json](../catalog-components-specialized.json) |
Shard names describe reading dependencies, not runtime catalog IDs. Follow field $refs into the common-type files as needed. Do not load this whole directory into every prompt.
## Interaction notes
- In the form, single selection still binds a string array. `required(false)` passes: the agreement check therefore reads the boolean binding directly. ImageUpload reports only after a successful upload; canceled or failed uploads do not report an event.
- Host actions explicitly use `urn:dingtalk:a2ui:host:v1`. promptText takes `initialValue`, then writes `{status: "success", data: {text: "..."}}` to the declared resultPath. Before a call, result slots are empty; a missing-initial-value warning at these asynchronous output bindings is expected. Cancellation preserves the previous result; a failed result has no data.text. The static hint and bounded result text provide an empty state. ButtonGroup items own their metadata and never inherit a parent writeback path.
- The progress example uses an outer reasoning panel and a nested tool panel. Titles and shimmer are literals supported by the current public contract; subsequent updateComponents messages replace those definitions. Adding a step also updates its parent children. The final update removes shimmer. Current shimmer animation is iOS-only; other clients show plain text.
- The table receives its complete dataset once; pageSize 2 with three rows demonstrates local pagination. Loop item bindings are relative to each row. The chart Stack has both a base child and a referenced corner label.
All examples are checked structurally and semantically. Host callbacks and device rendering are not executed by static validation. No user or tool activity is performed by reading these files.
@@ -0,0 +1,174 @@
[
{
"version": "v1.0",
"createSurface": {
"surfaceId": "open-progress",
"catalogId": "https://dingtalk.com/card/a2ui/catalogs/public/catalog.json"
}
},
{
"version": "v1.0",
"updateDataModel": {
"surfaceId": "open-progress",
"path": "/",
"value": {
"answer": {
"text": "Generating a report."
},
"tools": {
"text": "Summarizing sample data"
}
}
}
},
{
"version": "v1.0",
"updateComponents": {
"surfaceId": "open-progress",
"components": [
{
"id": "root",
"component": "Column",
"children": [
"executionPanel",
"answer"
]
},
{
"id": "executionPanel",
"component": "CollapsiblePanel",
"title": "Summarizing data",
"variant": "reasoning",
"defaultExpanded": false,
"children": [
"executionTimeline"
],
"fallbackMarkdown": "Execution steps",
"textEffect": "shimmer"
},
{
"id": "executionTimeline",
"component": "Column",
"children": [
"step1",
"toolGroup_summary"
]
},
{
"id": "step1",
"component": "Text",
"text": "Sample data loaded",
"maxLine": 2
},
{
"id": "toolGroup_summary",
"component": "CollapsiblePanel",
"title": "Summarizing",
"defaultExpanded": false,
"children": [
"toolRow"
],
"fallbackMarkdown": "Tool call details"
},
{
"id": "toolRow",
"component": "Row",
"children": [
"toolIcon",
"toolText"
]
},
{
"id": "toolIcon",
"component": "Icon",
"name": "CodeProgram_L_outlined",
"colorToken": "common_level2_base_color"
},
{
"id": "toolText",
"component": "Text",
"text": {
"path": "/tools/text"
},
"maxLine": 2,
"weight": 1
},
{
"id": "answer",
"component": "Markdown",
"content": {
"path": "/answer/text"
}
}
]
}
},
{
"version": "v1.0",
"updateComponents": {
"surfaceId": "open-progress",
"components": [
{
"id": "executionTimeline",
"component": "Column",
"children": [
"step1",
"toolGroup_summary",
"step2"
]
},
{
"id": "step2",
"component": "Text",
"text": "Category totals calculated",
"maxLine": 2
}
]
}
},
{
"version": "v1.0",
"updateDataModel": {
"surfaceId": "open-progress",
"path": "/tools/text",
"value": "Data summary complete"
}
},
{
"version": "v1.0",
"updateDataModel": {
"surfaceId": "open-progress",
"path": "/answer/text",
"value": "**Summary complete**: Engineering 8, Design 3, Testing 2; 13 items in total."
}
},
{
"version": "v1.0",
"updateComponents": {
"surfaceId": "open-progress",
"components": [
{
"id": "executionPanel",
"component": "CollapsiblePanel",
"title": "Execution complete",
"variant": "reasoning",
"defaultExpanded": false,
"children": [
"executionTimeline"
],
"fallbackMarkdown": "Execution steps"
},
{
"id": "toolGroup_summary",
"component": "CollapsiblePanel",
"title": "Summary complete",
"defaultExpanded": false,
"children": [
"toolRow"
],
"fallbackMarkdown": "Tool call details"
}
]
}
}
]
@@ -0,0 +1,155 @@
[
{
"version": "v1.0",
"createSurface": {
"surfaceId": "open-report",
"catalogId": "https://dingtalk.com/card/a2ui/catalogs/public/catalog.json"
}
},
{
"version": "v1.0",
"updateDataModel": {
"surfaceId": "open-report",
"path": "/",
"value": {
"rows": [
{
"name": "Engineering",
"count": 8
},
{
"name": "Design",
"count": 3
},
{
"name": "Testing",
"count": 2
}
],
"table": {
"meta": [
{
"colKey": "name",
"colName": "Department",
"type": "text"
},
{
"colKey": "count",
"colName": "Completed",
"type": "text"
}
],
"data": [
{
"name": "Engineering",
"count": 8
},
{
"name": "Design",
"count": 3
},
{
"name": "Testing",
"count": 2
}
]
},
"chart": {
"type": "histogram",
"data": [
{
"x": "Engineering",
"y": 8
},
{
"x": "Design",
"y": 3
},
{
"x": "Testing",
"y": 2
}
]
}
}
}
},
{
"version": "v1.0",
"updateComponents": {
"surfaceId": "open-report",
"components": [
{
"id": "root",
"component": "Column",
"children": [
"tabs",
"summary"
]
},
{
"id": "tabs",
"component": "Tabs",
"tabs": [
{
"title": "Data details",
"child": "table"
},
{
"title": "Chart",
"child": "chart-stack"
}
]
},
{
"id": "table",
"component": "Table",
"data": {
"path": "/table"
},
"pagination": true,
"pageSize": 2
},
{
"id": "chart-stack",
"component": "Stack",
"child": "chart",
"overlays": [
{
"child": "badge",
"position": "topEnd"
}
]
},
{
"id": "chart",
"component": "Chart",
"data": {
"path": "/chart"
}
},
{
"id": "badge",
"component": "Text",
"text": "This week"
},
{
"id": "summary",
"component": "Loop",
"children": {
"componentId": "row",
"path": "/rows"
}
},
{
"id": "row",
"component": "Text",
"text": {
"path": "name"
},
"maxLine": 1
}
]
}
}
]
@@ -0,0 +1,209 @@
[
{
"version": "v1.0",
"createSurface": {
"surfaceId": "open-form",
"catalogId": "https://dingtalk.com/card/a2ui/catalogs/public/catalog.json"
}
},
{
"version": "v1.0",
"updateDataModel": {
"surfaceId": "open-form",
"path": "/",
"value": {
"form": {
"name": "",
"dept": [],
"agreed": false,
"notify": false,
"count": 1,
"images": []
}
}
}
},
{
"version": "v1.0",
"updateComponents": {
"surfaceId": "open-form",
"components": [
{
"id": "root",
"component": "Column",
"children": [
"name",
"dept-title",
"dept",
"agreed",
"notify-row",
"count-title",
"count",
"images-title",
"images",
"submit"
]
},
{
"id": "name",
"component": "TextField",
"label": "Name",
"value": {
"path": "/form/name"
}
},
{
"id": "dept-title",
"component": "Text",
"text": "Department"
},
{
"id": "dept",
"component": "ChoicePicker",
"label": "Choose a department",
"variant": "mutuallyExclusive",
"options": [
{
"label": "Engineering",
"value": "dev"
},
{
"label": "Design",
"value": "design"
}
],
"value": {
"path": "/form/dept"
}
},
{
"id": "agreed",
"component": "CheckBox",
"label": "Agree to submit",
"value": {
"path": "/form/agreed"
},
"action": {
"event": {
"name": "agreement_changed",
"context": {
"agreed": {
"path": "/form/agreed"
}
}
}
}
},
{
"id": "notify-row",
"component": "Row",
"align": "center",
"children": [
"notify-label",
"notify"
]
},
{
"id": "notify-label",
"component": "Text",
"text": "Receive progress updates",
"weight": 1
},
{
"id": "notify",
"component": "Switch",
"value": {
"path": "/form/notify"
},
"action": {
"event": {
"name": "notification_changed",
"context": {
"notify": {
"path": "/form/notify"
}
}
}
}
},
{
"id": "count-title",
"component": "Text",
"text": "Quantity"
},
{
"id": "count",
"component": "NumberInput",
"label": "Quantity",
"placeholder": "Enter a number",
"value": {
"path": "/form/count"
}
},
{
"id": "images-title",
"component": "Text",
"text": "Attachments"
},
{
"id": "images",
"component": "ImageUpload",
"label": "Upload images",
"value": {
"path": "/form/images"
},
"action": {
"event": {
"name": "image_uploaded",
"context": {
"images": {
"path": "/form/images"
}
}
}
}
},
{
"id": "submit",
"component": "Button",
"child": "submit-label",
"variant": "primary",
"checks": [
{
"condition": {
"call": "required",
"args": {
"value": {
"path": "/form/name"
}
}
},
"message": "Enter a name"
},
{
"condition": {
"path": "/form/agreed"
},
"message": "Agree before submitting"
}
],
"action": {
"event": {
"name": "submit",
"context": {
"form": {
"path": "/form"
}
}
}
}
},
{
"id": "submit-label",
"component": "Text",
"text": "Submit"
}
]
}
}
]
@@ -0,0 +1,166 @@
[
{
"version": "v1.0",
"createSurface": {
"surfaceId": "open-host-action",
"catalogId": "https://dingtalk.com/card/a2ui/catalogs/public/catalog.json"
}
},
{
"version": "v1.0",
"updateDataModel": {
"surfaceId": "open-host-action",
"path": "/",
"value": {
"preset": {
"text": "Weekly progress"
},
"ui": {}
}
}
},
{
"version": "v1.0",
"updateComponents": {
"surfaceId": "open-host-action",
"components": [
{
"id": "root",
"component": "Column",
"children": [
"edit",
"hint",
"result",
"actions",
"title-label",
"title-result",
"note-label",
"note-result"
]
},
{
"id": "edit",
"component": "Button",
"child": "edit-label",
"action": {
"functionCall": {
"catalogId": "urn:dingtalk:a2ui:host:v1",
"call": "promptText",
"args": {
"initialValue": {
"path": "/preset/text"
}
}
}
},
"metadata": {
"extensions": {
"dt_actionBindingsV1": {
"action": {
"resultPath": "/ui/prompt"
}
}
}
}
},
{
"id": "edit-label",
"component": "Text",
"text": "Edit content"
},
{
"id": "hint",
"component": "Text",
"text": "After confirmation, the result appears below. Cancel keeps the previous result; a failed call clears it.",
"maxLine": 3
},
{
"id": "result",
"component": "Text",
"text": {
"path": "/ui/prompt/data/text"
},
"maxLine": 3
},
{
"id": "actions",
"component": "ButtonGroup",
"buttons": [
{
"label": "Edit title",
"action": {
"functionCall": {
"catalogId": "urn:dingtalk:a2ui:host:v1",
"call": "promptText",
"args": {
"initialValue": {
"path": "/preset/text"
}
}
}
},
"metadata": {
"extensions": {
"dt_actionBindingsV1": {
"action": {
"resultPath": "/ui/title"
}
}
}
}
},
{
"label": "Edit note",
"action": {
"functionCall": {
"catalogId": "urn:dingtalk:a2ui:host:v1",
"call": "promptText",
"args": {
"initialValue": {
"path": "/preset/text"
}
}
}
},
"metadata": {
"extensions": {
"dt_actionBindingsV1": {
"action": {
"resultPath": "/ui/note"
}
}
}
}
}
]
},
{
"id": "title-label",
"component": "Text",
"text": "Title result"
},
{
"id": "title-result",
"component": "Text",
"text": {
"path": "/ui/title/data/text"
},
"maxLine": 2
},
{
"id": "note-label",
"component": "Text",
"text": "Note result"
},
{
"id": "note-result",
"component": "Text",
"text": {
"path": "/ui/note/data/text"
},
"maxLine": 3
}
]
}
}
]
@@ -1,6 +1,6 @@
---
name: dingtalk-aisearch
description: AI搜问:人员语义搜索、跨源内容定位与行为回溯。Use when 按姓名/工号/部门/职责/上下级找人,或在目标对象未知时按主题、语义、来源或行为发现相关内容。搜索结果用于候选定位;命中后需要读取、修改或验证原对象时切换到对象所属产品。完整手机号精确反查走 dingtalk-contact。命令前缀:dws aisearch。
description: AI搜问:人员语义搜索、跨源主题检索与行为回溯。Use when 语义找人,或目标未知时按主题或行为发现内容。原生最近列表走所属产品;完整手机号精确反查走 dingtalk-contact。前缀:dws aisearch。
metadata:
cli_version: ">=0.2.14"
category: product
@@ -12,101 +12,104 @@ metadata:
# 钉钉 AI 搜问 Skill
<!-- DWS_RUNTIME_CONTRACT_START -->
## 最小 DWS 执行契约
## 最小执行契约
- 只通过 `dws` CLI 操作钉钉;每条命令带 `--format json`,只按真实结构化返回下结论。
- 常用 `person/enterprise/behavior` 按本页直接执行,不预读 shared、Reference、Schema、Help 或下游 Skill。
- 不猜命令、字段、ID、profile 或事实;可选时间缺失则省略并说明范围;多候选不取首项,ID 不混域。
- 空结果结束当前搜索,同条件核验见第 5 节;失败或不完整不能说“没有”,候选不等于全量。
- 只用 `dws` 操作钉钉,每条命令带 `--format json`,只按结构化返回下结论。
- `person/enterprise/behavior` 直接调用,不预读 shared、Reference、Schema、Help 或下游 Skill。
- 不猜命令、字段、ID、profile 或事实;多候选不取首项,不混用不同 `domain` 的 ID。
- 空结果结束本次搜索;失败、不完整或候选结果不能表述成“对象不存在”、全量或唯一。
- 来源不确定或用户列出多个来源时,第一条业务命令必须是一次合并 `--types` 的 `aisearch enterprise`,不能先逐产品搜索。
<!-- DWS_RUNTIME_CONTRACT_END -->
## Golden Route
## 选路
| 意图 | 唯一首选入口 | 关键槽位 |
|---|---|---|
| 姓名/工号/部门/职位/职责/上下级/手机号线索找人 | `dws aisearch person` | `--query` + `--dimension` |
| 按主题找文档、消息、邮件、待办、听记等内容 | `dws aisearch enterprise` | `--queries` + `--types` + 可选 `--time-range` |
| 以我为关系端点的发送/接收,或我创建、编辑、分享过什么 | `dws aisearch behavior` | 上述内容槽位 + `--behavior-type` + 可选 `--direction/--chat-scope` |
| <!-- dws-intent: chat.search.filtered -->资源只限 IM,答案是逐条消息并带结构化消息谓词 | `dws chat +search-msg` | 发送者、会话、关键词、@、类型、reaction、时间和完整分页由 Chat 负责 |
| 枚举部门成员、完整人员名单 | `dingtalk-contact` | 部门定位 → 成员列表 → 按需详情,不把人员搜索候选当全量 |
| 完整手机号精确反查 | `dws contact user search-mobile --mobile "<完整手机号>" --format json` | `--mobile` |
| 已知稳定 ID 后读取/修改原对象 | 对应产品 Skill | 不再用 AISearch 重搜 |
| 意图 | 入口 |
|---|---|
| 姓名、工号、部门、职位、职责、上下级或手机号线索找人 | `dws aisearch person` |
| 按主题跨文档、消息、邮件、待办、日程、听记等找内容 | `dws aisearch enterprise` |
| 以我为端点的发送/接收,或我创建、编辑、分享过什么 | `dws aisearch behavior` |
| <!-- dws-intent: chat.search.filtered -->仅 IM 且需逐条消息谓词过滤 | `dws chat +search-msg` |
| 无主题地列最近访问/编辑文档 | `dws drive +recent` |
| 枚举部门完整成员 | `dingtalk-contact` |
| 完整手机号精确反查 | `dws contact user search-mobile --mobile "<手机号>" --format json` |
| 已知稳定 ID 后读取/修改 | 对应产品 Skill |
选路顺序:资源范围 → 答案形态 → 原生谓词。
顺序:资源范围 → 答案形态 → 原生谓词。
## 1. 人员搜索
维度映射:姓名→`name`,部门→`department`,职位/岗位→`position`,职责/技能/负责人→`duty`,上级→`supervisor`,下属→`subordinate`,工号→`jobNumber`,手机号线索→`phone`;确实无法判断维度时才用 `all`。
维度:姓名=`name`,部门=`department`,职位=`position`,职责/负责人=`duty`,上级=`supervisor`,下属=`subordinate`,工号=`jobNumber`,手机号线索=`phone`;确实无法判断才用 `all`。
```bash
dws aisearch person --query "<用户原始目标>" --dimension <维度> --format json
```
- 独立条件分别查询、汇报;保留完整目标,不截名、改昵称或扩同音词。
- 正确维度返回空结果就结束该组,不换 `all` 或缩词扩搜;同条件核验见第 5 节。仅维度选错时改正一次,空结果不等于路由错误。
- 保留全部候选的姓名、真实 ID 和人员链接。用户要详情才切 Contact: `dws contact user get --ids <userId> --format json`。
- 同一人的多条件须核对交集;姓名、部门、职位不互相替代。
- 无分页完成证据时,只称“本次返回 N 个候选”。
- 保留完整目标;独立条件分别查。正确维度为空就结束,不换 `all`、缩词或扩同音词。
- 用 `searchEvidence.returnedCandidateCount` 报告本次候选数;无分页完成证据只称“本次返回”。
- 姓名/花名包含查询只交付 `_searchEvidence.exactAliasContainsQuery=true`;`exactAliasContainsCount=0` 即无精确包含项,语义近似不能替代。
- `resolvedRelation.status=resolved` 时直接使用 `target/supervisor/relation` 回答直属上级,不再搜索,也不把上级的上级当直属上级。
- 产品归属与负责人用一次 `dimension=duty`,保留产品名和“负责”;仅职责证据明确者可称负责人,多候选就列候选及部门,共同上级不等于负责人。
- 姓名与花名可由同一候选的 `aliases` 关联;不同域 ID 不可直接比较。需要更多人员详情时才用真实 `userId` 切 Contact。
## 2. 跨源内容搜索
先从原句拆槽:时间词只进 `--time-range`,类型词只进 `--types`,剩余主题只进 `--queries`。类型枚举:`document,im,mail,calendar,todo,minute,report,image,link,notable,baike`。
时间词只进 `--time-range`,类型词只进 `--types`,其余主题进 `--queries`。
```bash
dws aisearch enterprise --queries "<主题>" --types <类型CSV> [--time-range "<用户原始时间词>"] --format json
dws aisearch enterprise --queries "<主题>" --types <类型CSV> [--time-range "<原时间词>"] --format json
```
- 按用户要求分组调用,组内类型合并为 CSV;不按底层产品细拆或重复搜索。
- 精确标题原样传给 `--queries`,只接受精确匹配;未命中就停止,不拿近似标题、最近项或首项替代。同条件原生核验见第 5 节。
- “唯一才读取”须先证实指定来源覆盖、分页结束且仅一个精确匹配;否则报告唯一性未核实,不读正文。正文 `complete=true` 不代表搜索完整。
- 只要候选摘要或链接就不读原文。需要正文或缺必需证据时,满足读取前置条件后才按真实 ID 切对应产品;核验不能绕过“唯一才读取”。
- 空结果或无精确目标均报告本次未命中,不自行缩词或扩时间。
类型:文档/普通文件=`document`,消息=`im`,邮件=`mail`,日程=`calendar`,待办=`todo`,听记=`minute`,日志=`report`,AI表格=`notable`,知识内容=`baike`;用户列出的来源合并到一次调用。
- `requestConstraints` 回显实际条件,`sources` 给出各来源数量;`no_returned_items` 仅表示本次未命中,`coverage.status=unknown` 不能证明完整。
- `_searchEvidence.queryMatch=text_evidence_present` 才有文本主题证据;`no_text_evidence` 仅是语义候选,标为未核实。
- 只交付 `result` 保留项并说明 `delivery.omitted`;`doNotRetryOrExpand=true` 时停止,不改词、逐产品补搜或读 Help。
- 唯一精确标题可能附带 `resolvedDetail`。其状态为 `resolved` 或 `resolved_from_search_payload` 且字段足够时直接回答;`failed` 才报告补充读取失败。
- 日程空命中时接口可按原时间调用日历,`meta.nativeFallback=true` 仍属本次 AISearch 证据,无需 Agent 再查日历。
- 精确标题未命中不拿近似标题、最近项或首项替代。“唯一才读取”须有指定来源覆盖、分页结束和唯一精确匹配;正文 `complete=true` 不代表搜索完整。
- 用户只要候选摘要或链接时不读原文;确需正文且同次结果缺字段,才按真实稳定 ID 读取对应产品。
## 3. 行为回溯
```bash
dws aisearch behavior --queries "<主题>" --types <类型CSV> --behavior-type <all|send|receive|create|edit|share> [--time-range "<时间>"] [--direction "我->某人|某人->我|我<->某人"] [--chat-scope "<完整群名>"] --format json
dws aisearch behavior --queries "<主题>" --types <类型CSV> --behavior-type <all|send|receive|create|edit|share> [--time-range "<原时间词>"] [--direction "我->某人|某人->我|我<->某人"] [--chat-scope "<完整群名>"] --format json
```
- 每组“动作+方向+时间”调用一次,类型用 CSV 合并。`chat-scope` 仅用于 `im`;方向用原姓名,不先查邮箱或 userId。行为方向不代表发送者全部消息。
- 动作按当前用户视角选择,适用于所有内容类型:“我发给某人”=`behavior-type=send, direction=我->某人`;“某人发给我”=`behavior-type=receive, direction=某人->我`。不能因原句有“发”就选 `send`。“我在某群发过”另加 `types=im, chat-scope=<完整群名>`。
- 仅 IM 逐条过滤走 Chat,复用已解析的稳定身份。
- 空结果只表示本次未命中;不删除主题、不追加同义词、不缩短群名重搜,不用 recent 列表替代行为证据。需补充查询时按第 5 节保留原条件执行。
- 返回已足够回答就停止;缺少必需信息时才查询原对象。
- 每组动作、方向、时间调用一次并合并类型。方向按当前用户视角:“我发给某人”=`send`;“某人发给我”=`receive`。`chat-scope` 仅用于 IM,方向保留原姓名。
- 成功空数组就交付“已查询,本次 0 条”,按来源列 0;不再用 `enterprise` 拼行为证据,不删主题、扩时间、缩群名或用 recent 代替。
- `timeEvidence.withinRequestedRange=false` 排除;为 `null` 则标时间未核实。`messageEvidence.perMessageVerified=false` 时不能把混合会话 snippet 全归给目标人。
- “某人发过 Word 文件”或“某人今天发给我的消息”只调用一次 behavior:`types=im`、`receive`、人物方向及原时间词;不切 Chat、猜 sender 或扩大年份。
- `resolvedMessageEvidence.status=resolved` 时直接使用 `messages`,即使为空也不再调用 Chat;`identity.match=returned_alias` 只证明展示名匹配返回别名。
- 发送者未知的“谁给我发过某主题文件”用 `direction="某人->我"`,按 `identity.match=any_returned_sender` 的 `messages.sender` 汇总,不先猜人或拆两次搜索。
## 4. 结果核验与交付
## 4. 核验与交付
- **时间**:原时间词传给 `--time-range`,按当前日期、时区确定核验区间;“本周”不等于近七天。数值时间先确认秒/毫秒单位,再用程序换算。已知越界记录排除;只有聚合日期或缺少逐条时间时标为时间未核实。创建行为须有创建时间,不能用修改时间或会议开始时间代替。
- **身份**:核对实际发送者、收件关系和创建者;群内可见不等于发给我。Contact `userId` 与 Ding uid 等不同域 ID 不能直接比较;没有明确映射时,既不能认定同一人,也不能因值不同就排除本人。
- **主题与类型**:候选须有内容证据支持主题关联;搜索命中、群名相关或流程上“可能有关”都不足以确认。无关联证据时标为相关性未核实,不自行选成“最相关”。文本、标题或普通链接不能充当文件证据。
- **唯一与全量**:检查指定来源和分页终态;缺完整性字段就不声称唯一或全量。按稳定 ID 去重,交付清单与已核实的 ID、数量核对,避免读到却漏列。只问“有没有”时,有效命中即可回答。
- **忠实总结**:不补写未返回事实,不把“建议、待确认”改成已发生;分清搜索片段与正文、接口总数与已读取条数。部分结果伴随错误或未完分页时保留说明,不能据此说“没有其他结果”。
- **时间**:保留原时间词;“本周”不等于近七天。确认数值时间单位。创建行为用创建时间,不能用修改时间或会议开始时间代替。
- **身份**:核对发送者、收件关系和创建者;群内可见不等于发给我。优先用 `stableRefs/identityRefs`,仅同 `domain` 的 ID 可直接比较。
- **主题/类型**:须有文本、附件或对象类型证据;群名、普通链接和搜索命中本身不能证明主题或文件属性。
- **唯一/全量**:检查来源和分页终态,按稳定 ID 去重;只问“有没有”时,有效正向命中即可。
- **摘要**:不补写未返回字段,不把建议写成事实,不把 snippet 称正文;分别报告命中、空结果、失败和未核实项。
## 5. 按原条件转用对应产品查询
## 5. 同条件原生核验与多跳
- 需要详情、成员清单或核验时,用返回的真实 ID,或原生产品支持的精确标题、部门等条件查询;只加载对应产品 Skill,按其参数调用。
- 保持主题、身份、方向、时间和权限,不猜 ID、不跨组织、不扩大扫库。无精确条件、失败或无权限即说明限制并停止,不自动申请权限。
路径:**AISearch 定位 → 确认目标 → 优先使用同次 `resolvedDetail` → 缺必需字段才按真实 ID 调用一个对应产品。**
## 6. 多跳证据链
- 仅在需要详情、完整成员或证据核验,且已有稳定 ID 或原生可执行的相同精确标题/部门/范围时转用对应产品;保持主题、身份、方向、时间和权限,不扩大扫库。
- 跨来源第一步固定为 enterprise。无稳定 ID 时不能用原生重搜替代;目标不明、身份矛盾、失败或无权限时说明限制并停止。
- 人员用 `userId`,文档用 `nodeId`,听记用 `taskUuid`,待办用真实 `taskId`;Ding uid 不能当 Contact userId,snippet 不能当正文。
- 用户的“唯一才读取”等前置条件仍须满足。ID 域或下一跳不明确时才读 [多跳短流程](references/lite-recipes.md)。
**定位候选 → 确认目标 → 提取真实 ID → 调用对应产品。**目标不明、身份不符或读取失败时停止依赖该对象的后续操作。
## 6. 禁止本地兜底
- 下游复用本跳真实 ID;人员用 `userId`,文档用 `nodeId`,听记用 `taskUuid`,待办用实际 `taskId`。Ding uid 不能当 Contact userId,snippet 不能当正文。
- 用户的读取前置条件必须满足;只加载下一跳所需 Skill,读取完整性以该次返回为准。ID 提取细节见 [多跳短流程](references/lite-recipes.md)。
钉钉对象只用 DWS 返回作业务证据;未命中时不得用 `find`、`rg`、`mdfind` 或评测 fixture 回答。会议议题负责人用一次 `person --dimension duty` 保留会议与职责原词;只有内容能提供职责原文时才改用一次 `enterprise --types calendar,im,document`,二者不都跑。
## 错误与成本最短路径
## 错误与成本
1. 失败且 `retryable=true`:原调用最多重试一次;否则停止,不换身份或绕过权限。
2. 成功但为空或无精确目标:不重复、改词或扩时间;必要的同条件核验见第 5 节。
3. `unknown flag`:查看一次该命令 Help 修正。API、权限和空结果不靠 Help 或猜参数解决。
4. 独立来源继续查询,依赖失败结果的步骤停止。保留标题、来源、链接、ID、数量、范围和错误;长 snippet 可外置,完整性字段不能删。
1. `retryable=true` 时原调用最多重试一次;否则停止,不换身份或绕权限。
2. 成功但为空或无精确目标:不重复、改词或扩时间。
3. `unknown flag` 才查看一次该命令 Help;API、权限和空结果不靠 Help 解决。
4. 独立来源可继续;依赖失败结果的后续停止。保留来源、链接、ID、范围、数量、完整性和错误。
## 按需 Reference
常用路径不读 Reference。
| 仅当 | 读取 |
|---|---|
| 低频枚举、返回字段或兼容参数确实无法由本页判断 | [完整命令参考](references/aisearch.md) |
| 搜索与已知对象读取的产品边界仍不明确 | [局部意图消歧](references/intent-guide.md) |
| 多跳结果已有候选,但其稳定 ID 域或下一跳衔接不明确 | [多跳短流程](references/lite-recipes.md) |
常用路径不读 Reference。低频枚举或兼容参数不明才读 [完整命令参考](references/aisearch.md);产品边界不明读 [局部意图消歧](references/intent-guide.md);稳定 ID 域或下一跳不明读 [多跳短流程](references/lite-recipes.md)。
@@ -10,9 +10,10 @@
| 按主题跨文档、消息、邮件、待办、听记等来源找记录 | `aisearch enterprise` | 分别加载各产品做跨源搜索 |
| 找以我为关系端点的发送/接收记录,或我创建、编辑、分享过的记录 | `aisearch behavior` | 用 Chat/Mail/Doc recent 拼接行为结论 |
| <!-- dws-intent: chat.search.filtered -->资源只限 IM,答案是逐条消息并带发送者、会话、时间、reaction 等消息谓词 | `dws chat +search-msg` | 用行为方向替代消息集合过滤 |
| 按时间枚举最近访问/编辑的文档,无主题、人物、方向或动作条件 | `dws drive +recent` | `aisearch enterprise/behavior` |
| 已有唯一稳定 ID,要求读取正文、逐字稿或详情 | 对应产品 Skill | 用 AISearch snippet 冒充原文 |
| 已有唯一稳定 ID,要求修改、发送或删除 | 对应产品 Skill | 继续用 AISearch |
判断顺序:**资源范围 → 答案形态 → 原生谓词。**跨来源主题走 enterprise,当前用户行为轨迹走 behavior,仅 IM 的逐条消息过滤走 Chat;已知对象再读取或操作。
判断顺序:**资源范围 → 答案形态 → 原生谓词。**跨来源主题走 enterprise,当前用户行为轨迹走 behavior,仅 IM 的逐条消息过滤走 Chat;无筛选的时间排序列表走所属产品,已知对象再读取或操作。
搜索为空只说明未命中。需要精确对象且已有稳定 ID 或原生可执行的同条件标题/部门/范围时,按主 Skill 的“按原条件转用对应产品查询”规则核验;不扩大条件,不用 recent 拼接行为证据。
@@ -1,6 +1,6 @@
---
name: dingtalk-aitable
description: 钉钉 AI 表格(多维表)。Use when 用户说 AI表格/多维表/数据表/base/table/应用模式/App 页面/Widget/建表/查记录/写数据/字段/记录增删改查/记录评论/评论回复/SQL/PostgreSQL/SELECT/JOIN/跨表关联查询/筛选/排序/公式/模板搜索/批量导入CSV或JSON/导出/仪表盘/图表/上传附件到表格/按字段类型建表/数据源/创建数据源/更新数据源配置/触发数据源同步/按任务 ID 查询同步状态/获取数据源配置/列出数据源可用来源/获取数据源可同步字段/审批数据同步。不做电子表格单元格读写或单元格批注(走 dingtalk-misc)、文档编辑(走 dingtalk-doc);听记待办入表先用 dingtalk-minutes 提取,再由本 skill 写入。命令前缀:dws aitable。
description: 钉钉 AI 表格(多维表)业务操作。Use when 用户需要操作 AI 表格/多维表/Base/Table、应用模式/App 页面/Widget、建表、查写记录、字段、记录评论、评论回复、访问密钥(API Key)、SQL/PostgreSQL/SELECT/JOIN、筛选、排序、公式、模板、批量导入 CSV 或 JSON、导出、仪表盘、图表、上传附件、数据源配置与同步、按任务 ID 查询同步状态或审批数据同步。普通请求以完成明确的业务操作为主;当用户明确要求 CLI 契约评审、核对 aitable 合成 JSON 回执、dry-run、命令参数、Help/Schema 契约或恢复方案时,必须加载本 Skill。只评审 aitable 合成 JSON 回执也必须加载本 Skill;“不要执行线上业务”不等于免除本机离线契约核对,不能按通用 JSON 经验直接作答。这是本机 Help/Schema 契约核对,不是仓库源码审查,不从源码搜索开始;先加载正文确定入口与规则,不能仅凭摘要执行;以用户原文指定的核对入口为准,Skill 参数不得扩大范围。不做电子表格单元格读写或单元格批注(走 dingtalk-misc)、文档编辑(走 dingtalk-doc);听记待办入表先用 dingtalk-minutes 提取,再由本 skill 写入。
metadata:
cli_version: ">=0.2.14"
category: product
@@ -11,6 +11,28 @@ metadata:
# 钉钉 AI 表格 Skill
## 业务操作优先与契约评审边界
默认目标是完成用户明确提出的 AI 表格业务操作,包括查询、创建、更新、同步和其他已授权写入。契约评审是辅助场景,仅在用户明确要求核对合成 JSON、dry-run、参数合法性、Help/Schema 或恢复方案时启用;这类请求默认只读,不把评审要求扩展成线上业务操作。用户同时提出业务操作和契约核对时,先按真实业务目标执行必要的契约校验,再继续执行已明确授权的业务操作。
## 先区分操作、用法与契约评审
用户只要求评审返回值或恢复方案时,不执行业务操作,也不按业务任务扩展到上游写入命令。发现目标以用户原始消息为准,Agent 自行摘要或传入 Skill 的参数不是新增请求,不能将“核对该对账命令”改写成“比较对账与原创建命令”。保留用户正在核对的完整原子路径或 `+` Shortcut 名,不做同义替换。背景里提到的原创建命令不是额外发现目标。
只评审一个命令时,先取得一次该入口的 compact Schema,再依据本次结果回答;不要并行或顺序查询背景命令,也不要追加同义入口、完整 Schema 或 Help。未发布 `result` 时说明该结构未公开,不靠重复查询或示例推断字段。用户明确要求比较多个命令时,才分别查询各自契约。Help/Schema 是本机离线查询,“不要执行线上业务”不禁止它;用户明确禁止任何命令时则不查询,并说明契约未核对。
评审中用户要求下一步只读命令时,回答先给出有当前契约依据、使用原 ID/核对键的完整命令,并说明尚未执行;紧接着给出关键判断与禁止动作,再简要解释依据。不先展开工具过程、Schema 字段表或长篇引用,不把下一步埋在分析末尾;无法确定只读入口或参数时说明缺口,不能猜测。没有索要命令时,先用简短结论回答用户的全部安全问题:是否允许重放写入、哪些结果应保留或丢弃、只读恢复有什么前提,再按需解释;不能把关键禁止动作留到分节解释或末尾总结。明确区分本机离线契约核对、用户提供的回执和仍未验证的线上状态:本机 Schema 只能证明命令契约,不能证明业务已经执行或远端状态已经核实。
仅评审失效游标恢复时,读取 [record-query](references/aitable/aitable-record-query.md) 开头的“只评审失效游标恢复”段,集中说明丢弃旧结果、UNAVAILABLE 等待前提和禁止重放写入这三项边界;不转入该 Reference 后面的实际查询流程,也不从新旧结果差异推导补写许可。
以下意图路由优先于下方通用 Schema 导航。表单分享的用法询问与返回值评审不能共用发现路径:
| 请求意图 | 本次唯一契约查询 |
|---|---|
| 评审返回值、恢复方案、故障或 dry-run 样本 | 把正在核对的完整入口原样放入 `dws schema --cli-path "aitable <原入口>" --compact --format json`;保留 `+`,不改查 Help,也不切换原子/Shortcut |
| 仅问原子 `form share update` 的写法 | 只执行 `dws aitable form share update --help`(禁止改查 Schema) |
| 仅问 Shortcut 的写法 | 只查该 Shortcut 的 compact Schema |
<!-- DWS_RUNTIME_CONTRACT_START -->
## 最小 DWS 执行契约
@@ -33,7 +55,7 @@ metadata:
## 表单分享用法回答契约
收到仅询问用法的请求后,第一步必须立即实际执行且仅执行下列对应命令:
收到仅询问用法的请求后,第一步必须立即实际执行且仅执行下列对应命令;即使用户提到“help/schema”,也按入口选择,不能自行替换:
- `form share update`:`dws aitable form share update --help`
- `+form-share-update`:`dws schema --cli-path "aitable +form-share-update" --compact --format json`
@@ -50,12 +72,49 @@ dws aitable form share update --base-id <BASE_ID> --table-id <TABLE_ID> --view-i
请将 <BASE_ID>、<TABLE_ID>、<VIEW_ID> 替换为真实值;未传入的分享配置保持原值。本次仅查询 help/schema,未执行写操作。
```
已知 ID 与占位符必须区别处理:用户明确给出的短 ID 也按原值使用,不因其长度或看起来像示例就要求替换。所有 ID 已知时,第二行必须原样为“未传入的分享配置保持原值。本次仅查询 help/schema,未执行写操作。”;只有命令中确实用了占位符时才添加对应替换说明。Shortcut 的命令行必须保留 `--format json`,固定说明中的 `help/schema` 不因本次只查 schema 而改写。
两种入口都必须完整保留用户指定的配置值,尤其是表单名对应的 `--form-name`;不得因精简为两行而只留下 ID 和 `--enabled`。以下是已知 ID 的 Shortcut 用法回答示例(标题按用户输入替换,不能省略):
```text
dws aitable +form-share-update --base-id base-123 --table-id table-456 --view-id view-789 --enabled true --form-name "报名表" --format json
未传入的分享配置保持原值。本次仅查询 help/schema,未执行写操作。
```
## 返回值评审专用查询(不适用于命令用法询问)
作答前必须有本次实际执行的目标 compact Schema 查询结果;仅加载 Skill 或看到合成样本不满足此条件。先执行下表命令,再解释,不能直接根据 Skill 回答。
Help/Schema 是离线契约查询,不调用线上业务,也不读写用户的表单。因此“只分析合成返回,不要执行线上业务命令”仍允许且需要下表的本机查询,不能将其误判为线上读取而跳过;只有用户明确禁止任何命令或本机查询时才不执行,并说明本机契约未核对。
仅评审返回值/故障结果(而非询问写法)时,不套用两行命令模板,也不适用“优先 Shortcut”规则。用户指定的原子/Shortcut 入口必须原样保留,即使它们共用 Result 契约也不能互换;严格按下表查询一次后解释样本,不搜索源码/reference,不执行业务读写。
| 用户指定入口 | 唯一契约查询 |
|---|---|
| `form share get` | `dws schema --cli-path "aitable form share get" --compact --format json` |
| `form share update` | `dws schema --cli-path "aitable form share update" --compact --format json` |
| `+form-share-get` | `dws schema --cli-path "aitable +form-share-get" --compact --format json` |
| `+form-share-update` | `dws schema --cli-path "aitable +form-share-update" --compact --format json` |
不得用搜索源码或 reference 代替本机契约查询。get 只诊断分享配置,不返回 `cpSynced`;不能建议“通过 get 回读 cpSynced 后确认闭环”。未验证的 CP 应继续标为未确认并交由服务端诊断,不能把 get 的成功或 UUID 非空当作恢复证明。
先选择 Schema 的实际结果分支:`data.executed=false` 的 dry-run 预览只含 `tool/arguments/executed`(Shortcut 还含 `dry_run=true`),不需要服务端状态或 `cpSynced`,`ok=true` 只表示预览成功。不要把真实执行成功分支的必填字段套到预览上。字段是否必填只读所选分支的 `required`;是否允许额外字段只读该对象的 `additionalProperties`,不能从 `arguments` 子对象推断父对象。
真实执行结果判断:分享开关依据 `enabled`,保留 UUID 不代表开启;UUID/封面为空就如实报告,不能推测唯一成因或拼装封面 URL。get 的成功不证明 CP 同步。update 仅在必需字段完整且类型正确、`cpSynced=true` 时成功;缺失/false/类型异常均不能确认闭环。统一部分失败无顶层 error:原始响应在 `data.succeeded[0].response`,该阶段仅表示收到回执;失败原因在 `data.failed[0].error`,含 `execution_started=true`。不要自行重放写入或补偿 CP。合成样本若不符合该结构,应指出不匹配,不能把 Schema 中的字段补写成样本已有事实。
解释边界:`status` 未公布枚举含义时保留原始数值,不把 0/1 自行翻译成未发布/已发布;`cpSynced=false` 只支持“CP 终态未确认”,不证明外部用户必定无法访问。UUID/封面空值不能证明此前从未创建,短 ID 不能仅因长度被判为占位符。
即使外层仍为 ok=true 或返回结构不符合契约,也不得为再次校验 CP 而执行或建议重发 form share update / +form-share-update(包括稍后传相同配置);诊断不能新增写入,只保留回执并交由服务端排查。
实际执行 `form share update` 或 `+form-share-update` 后,成功结果必须同时检查 `shareFormUuid`、`status`、`formCover`、`cpSynced`;只有 `cpSynced=true` 才能向用户确认分享闭环完成。部分失败或 `cpSynced=false` 不得描述为成功。DWS 不自行调用第二个 View 更新命令补偿 CP。`formCover` 在旧服务端发布窗口内可能为空,应如实说明,不能由 DWS 拼装封面 URL。
> 命令参考:[aitable.md](references/aitable.md);PostgreSQL 只读查询:[aitable-psql.md](references/aitable/aitable-psql.md);复杂命令按需加载 `references/aitable/*.md`;剧本:[06-data-analytics.md](references/06-data-analytics.md)。
<!-- VISIBLE_SHORTCUTS_START -->
## Shortcut 发现(按需)
`aitable` 当前有 101 条公开 shortcut,完整清单保留在 Runtime Catalog 与 Schema,不在高频产品根 Skill 中重复展开。已知 leaf 直接执行。参数只查 `dws schema --cli-path "aitable <leaf>" --compact --jq '{cli_path,parameters,constraints,confirmation}' -f json`;仅需且已发布 `result` 时查 outcomes/pagination,字段级再查 `data_schema`;缺失不以 Help/样例推断。Schema 不可用才读一次已知 leaf Help;`unknown flag` 用同 leaf Help 修正一次。`unknown command` 禁 Help:错误 suggestion → 已加载 Skill/reference 明确入口;均无则报漂移。禁全 Catalog/root/parent/product Help;低频 reference 不默认 Help;同一任务只读一个 Reference。
`aitable` 当前有 126 条公开 shortcut,完整清单保留在 Runtime Catalog 与 Schema,不在高频产品根 Skill 中重复展开。已知 leaf 直接执行。参数只查 `dws schema --cli-path "aitable <leaf>" --compact --jq '{cli_path,parameters,constraints,confirmation}' -f json`;仅需且已发布 `result` 时查 outcomes/pagination,字段级再查 `data_schema`;缺失不以 Help/样例推断。Schema 不可用才读一次已知 leaf Help;`unknown flag` 用同 leaf Help 修正一次。`unknown command` 禁 Help:错误 suggestion → 已加载 Skill/reference 明确入口;均无则报漂移。禁全 Catalog/root/parent/product Help;低频 reference 不默认 Help;同一任务只读一个 Reference。
仅当根路由、精确 task reference 和 `references/aitable.md` 的低频原子索引都无法定位能力时,才执行 `dws shortcut list --service aitable --format json` 做最终回退;不要为已知意图加载完整 Shortcut Catalog 或产品级 Schema。
<!-- VISIBLE_SHORTCUTS_END -->
@@ -79,6 +138,7 @@ dws aitable form share update --base-id <BASE_ID> --table-id <TABLE_ID> --view-i
| 按名称解析人员、部门或群组实体 | `dws aitable entity search --entity-type PERSON\|DEPARTMENT\|GROUP --keyword <名称>` | 返回候选和可用于筛选的稳定身份;零命中、重名、模糊命中或分页不完整时停止,不默认选择第一项 |
| 查询原始记录、记录筛选/排序、原始记录 Top N 或字段投影 | `dws aitable +record-query --base-id <ID> --table-id <ID> [--record-ids <IDs>] [--field-ids <IDs>] [--filters <JSON>] [--sort <JSON>] [--query <关键词>]` | 用户要求“只返回/仅查看”指定字段时必须传对应 `--field-ids`,不能只在最终文本删列;单表直接标量、分组或去重统计改走 `record stats` / `record group-stats`,复杂服务端分析改走 psql。已获用户明确许可的非分析完整逐行明细可直接使用原子 `record query --all --page-limit <N>`,不需要也不触发 psql 降级门禁。 |
| 新增单条或批量记录 | `dws aitable record create --base-id <ID> --table-id <ID> --records <JSON>` | 当前无 `+record-create`;写前取字段定义,写后按新 ID 回读 |
| 按原写入 token 核对记录结果 | `dws aitable +record-write-result --base-id <B> --table-id <T> --client-token <原UUID>` | unknown 或 ID 不完整时,停止后续写入,下一步仍按原 Base/Table/token 调用本命令只读对账,不改成全表查询;applied 的 ID 集合不保证整批完整或输入顺序,未返回 ID 的记录仍未核实,不按数量差额或输入位置补写;完整 ID 集合确认后再逐 ID 核对实际值,查询失败不是可以重建的写入终态 |
| 更新已知 recordId | `dws aitable +record-update --base-id <ID> --table-id <ID> --records <JSON>` | 自动分片并读回;只传需修改字段 |
| 查询一条记录的变更历史 | `dws aitable +record-history-list --base-id <ID> --table-id <ID> --record-id <ID>` | 已知 recordId 时直接执行,不探测 Help、Catalog 或全量 Schema |
| 管理一条记录的评论 | 查询用 `dws aitable comment list --base-id <B> --table-id <T> --record-id <R>`;创建、回复、更新和删除按需使用同组 leaf | 先读 [comment](references/aitable/aitable-comment.md);topicId/commentKey 只复用同一记录真实返回;空评论页仍读取 `meta.pagination`,仅 `meta.pagination.endpoint_exhausted=true` 时停止,否则将 `meta.pagination.next_token` 原样传给下一次 `--cursor`;写入未知状态先 list 对账 |
@@ -132,6 +192,7 @@ dws aitable form share update --base-id <BASE_ID> --table-id <TABLE_ID> --view-i
## 记录稳定约束
- 记录分页报 `INVALID_CURSOR`、`CURSOR_SNAPSHOT_CHANGED` 或 `CURSOR_SNAPSHOT_UNAVAILABLE` 时,必须丢弃全部累计结果与旧 cursor,不存在可续传的新 cursor,也不能保留第一页再去重拼接。前两者核对条件后不传 `--cursor` 从第一页只读重查;UNAVAILABLE 需先等待服务修复。不得重跑含写入的整条命令。仅普通可恢复错误且实际提供有效断点时可续传,详见 [record-query](references/aitable/aitable-record-query.md)。
- 查询、写入、筛选或排序前,先用 `field get` 获取目标字段的 `fieldId`、`type` 和 `config`;`cells` 的 key 必须使用 `fieldId`,不是字段中文名。
- select/multipleSelect 写入传选项名称;过滤时先唯一解析 option ID。对 multipleSelect 或其他数组型字段,第二个 operand 必须是 option ID/稳定 ID 数组,不能传裸字符串。
- 人员、部门、群组和关联记录等条件先解析为稳定的结构化 ID;零命中、多命中或类型不符时停止,不得把展示名称或原值直接透传。
@@ -158,6 +219,7 @@ Golden/次级直达覆盖时不读 Reference;否则按最终专有能力读取
|---|---|
| `+record-query`、upsert、bulk patch 的记录 filters/sort/date/AND/OR/比较操作符 | [filter-sort](references/aitable/aitable-filter-sort.md) |
| 记录历史、分享、删除恢复、空行或特殊字段值 | [record-ops](references/aitable-record-ops.md) |
| 记录分页错误、失效游标或快照恢复 | [record-query](references/aitable/aitable-record-query.md) |
| 记录统计、分组聚合或去重率 | [record-stats](references/aitable/aitable-record-stats.md) |
| 记录评论查询、创建、回复、更新或删除 | [comment](references/aitable/aitable-comment.md) |
| 查询记录的主键文档,或为记录创建主键文档 | 首次建表前读取 [primary-doc](references/aitable/aitable-primary-doc.md);普通 Base/Table/字段/记录创建与导入不读取 |
@@ -174,6 +236,7 @@ Golden/次级直达覆盖时不读 Reference;否则按最终专有能力读取
| 自动化工作流 | [workflow](references/aitable/aitable-workflow.md) |
| 普通角色或高级权限 | [advperm](references/aitable/aitable-advperm.md) |
| 数据源接入、同步管理、sourceConfig 构造或审批数据同步 | [datasource](references/aitable/aitable-datasource.md) |
| 访问密钥创建、查询或撤销 | [api-key](references/aitable/aitable-api-key.md) |
| SQL、PostgreSQL、SELECT 或同 Base 多表 JOIN | [psql](references/aitable/aitable-psql.md) |
| 产品边界不明确 | [intent-guide](references/intent-guide.md) |
| 只有上述 Reference 仍无法定位的低频原子能力 | [aitable.md](references/aitable.md) 的对应章节 |
@@ -182,7 +245,7 @@ Golden/次级直达覆盖时不读 Reference;否则按最终专有能力读取
## 错误最短路径
1. 零/多候选、字段歧义或分页不完整:停止并返回证据;需要后续页时只透传真实 `nextCursor`。
1. 零/多候选、字段歧义或分页不完整:停止并返回证据;仅有效分页会话可透传真实 `nextCursor`。失效游标先执行上方“记录稳定约束”,不能套用普通断点续传。
2. 类型错误只复核目标字段,不删字段或丢输入;`partial_success` 从 checkpoint 续跑,未知写入先回读。
3. 错误提供 `actions` / `available_flags` 时只按其中的 `next_command` 修正一次;`retryable=false` 或目标 ID 类型不符时停止。
4. 数据源同步 `errorCode=4014` 表示同步运行中重复触发,可稍后重试;非数据源表触发同步前先用 `+base-get` 确认 `sync=true`。
@@ -0,0 +1,25 @@
# SQL Sheet API Key 管理
`dws aitable api-key ...` 管理指定 Base 的 SQL Sheet 访问凭据,使用当前登录用户的身份。
## 命令
| 意图 | 命令 | 关键参数 |
|---|---|---|
| 创建访问凭据 | `api-key create` | `--base-id`;确认后再追加 `--yes` |
| 查询有效凭据 | `api-key list` | `--base-id` |
| 撤销指定凭据 | `api-key revoke` | `--base-id --key-id`;确认后再追加 `--yes` |
三个命令均要求 Base 的管理权限(MANAGER),每次选择一个 profile。使用 `--dry-run` 预览请求;预览不调用远端服务。
## 返回结果与标识
- create 的 `data` 包含 `keyId`、`status=ACTIVE`、`createdAt` 和完整 `apiKey`。`apiKey` 仅在创建成功时返回一次,按用户指定的方式交付或保存,日志和后续上下文只保留 `keyId`。
- list 的 `data.keys` 包含 0 或 1 个有效凭据的元数据:`keyId`、`status=ACTIVE`、`createdAt`,以及可选的 `createdBy={userId,corpId}`。`createdAt` 为 Unix 毫秒时间戳。
- revoke 的 `keyId` 使用同一 Base 的 create/list 真实返回,格式为小写规范 UUID。成功返回 `data.keyId` 和 `data.revoked=true`;指定凭据不存在或已经撤销时同样成功。
## 创建与撤销
- 每个 Base 最多一个有效凭据。已有凭据时,create 返回 `SQL_SHEET_API_KEY_ALREADY_EXISTS`,使用 list 核对当前状态。
- 三个命令都不自动重试。创建超时、断网或结果未知时先 list 核对,再由用户决定后续操作;一次空列表不足以判断在途创建已失败。
- list 只查询元数据,无法恢复完整 `apiKey`。需要替换凭据时,先确认旧 `keyId` 和撤销影响,撤销后再按用户授权创建新凭据。
@@ -19,6 +19,8 @@
## 仅询问分享更新用法时
用法询问与返回值评审不能共用发现路径:问原子命令写法只执行 `dws aitable form share update --help`(禁止改查 Schema);本专用规则优先于通用 Schema 导航。
收到仅询问用法的请求后,第一步必须立即实际执行且仅执行对应命令:原子入口用 `dws aitable form share update --help`;Shortcut 入口用 `dws schema --cli-path "aitable +form-share-update" --compact --format json`。Shortcut 名称开头的 `+` 是命令名不可省略的一部分;不得改写、试探其他拼法或改用 `--help`/`-h`。
发现门禁:即使 Skill 或参考文档已提供完整示例,回答前也必须实际执行一次且仅执行一次目标 leaf 的安全 help/schema 查询;不得仅依据 Skill 或参考文档直接作答。用户仅询问用法时,最终回答必须先给出完整命令;缺少必填 ID 时则给出带明确占位符的完整命令模板,禁止猜测。随后明确说明“未传入的分享配置保持原值”;不得执行目标写操作或声称已经执行。上述只读查询是唯一允许的命令。
@@ -30,6 +32,41 @@ dws aitable form share update --base-id <BASE_ID> --table-id <TABLE_ID> --view-i
请将 <BASE_ID>、<TABLE_ID>、<VIEW_ID> 替换为真实值;未传入的分享配置保持原值。本次仅查询 help/schema,未执行写操作。
```
已知 ID 与占位符必须区别处理:用户明确给出的短 ID 也按原值使用,不因其长度或看起来像示例就要求替换。所有 ID 已知时,第二行必须原样为“未传入的分享配置保持原值。本次仅查询 help/schema,未执行写操作。”;只有命令中确实用了占位符时才添加对应替换说明。Shortcut 的命令行必须保留 `--format json`,固定说明中的 `help/schema` 不因本次只查 schema 而改写。
两种入口都必须完整保留用户指定的配置值,尤其是表单名对应的 `--form-name`;不得因精简为两行而只留下 ID 和 `--enabled`。以下是已知 ID 的 Shortcut 用法回答示例(标题按用户输入替换,不能省略):
```text
dws aitable +form-share-update --base-id base-123 --table-id table-456 --view-id view-789 --enabled true --form-name "报名表" --format json
未传入的分享配置保持原值。本次仅查询 help/schema,未执行写操作。
```
## 返回值评审专用查询(不适用于命令用法询问)
作答前必须有本次实际执行的目标 compact Schema 查询结果;仅加载 Skill 或看到合成样本不满足此条件。先执行下表命令,再解释,不能直接根据 Skill 回答。
Help/Schema 是离线契约查询,不调用线上业务,也不读写用户的表单。因此“只分析合成返回,不要执行线上业务命令”仍允许且需要下表的本机查询,不能将其误判为线上读取而跳过;只有用户明确禁止任何命令或本机查询时才不执行,并说明本机契约未核对。
仅评审返回值/故障结果(而非询问写法)时,不套用两行命令模板,也不适用“优先 Shortcut”规则。用户指定的原子/Shortcut 入口必须原样保留,即使它们共用 Result 契约也不能互换;严格按下表查询一次后解释样本,不搜索源码/reference,不执行业务读写。
| 用户指定入口 | 唯一契约查询 |
|---|---|
| `form share get` | `dws schema --cli-path "aitable form share get" --compact --format json` |
| `form share update` | `dws schema --cli-path "aitable form share update" --compact --format json` |
| `+form-share-get` | `dws schema --cli-path "aitable +form-share-get" --compact --format json` |
| `+form-share-update` | `dws schema --cli-path "aitable +form-share-update" --compact --format json` |
不得用搜索源码或 reference 代替本机契约查询。get 只诊断分享配置,不返回 `cpSynced`;不能建议“通过 get 回读 cpSynced 后确认闭环”。未验证的 CP 应继续标为未确认并交由服务端诊断,不能把 get 的成功或 UUID 非空当作恢复证明。
先选择 Schema 的实际结果分支:`data.executed=false` 的 dry-run 预览只含 `tool/arguments/executed`(Shortcut 还含 `dry_run=true`),不需要服务端状态或 `cpSynced`,`ok=true` 只表示预览成功。不要把真实执行成功分支的必填字段套到预览上。字段是否必填只读所选分支的 `required`;是否允许额外字段只读该对象的 `additionalProperties`,不能从 `arguments` 子对象推断父对象。
真实执行结果判断:分享开关依据 `enabled`,保留 UUID 不代表开启;UUID/封面为空就如实报告,不能推测唯一成因或拼装封面 URL。get 的成功不证明 CP 同步。update 仅在必需字段完整且类型正确、`cpSynced=true` 时成功;缺失/false/类型异常均不能确认闭环。统一部分失败无顶层 error:原始响应在 `data.succeeded[0].response`,该阶段仅表示收到回执;失败原因在 `data.failed[0].error`,含 `execution_started=true`。不要自行重放写入或补偿 CP。合成样本若不符合该结构,应指出不匹配,不能把 Schema 中的字段补写成样本已有事实。
解释边界:`status` 未公布枚举含义时保留原始数值,不把 0/1 自行翻译成未发布/已发布;`cpSynced=false` 只支持“CP 终态未确认”,不证明外部用户必定无法访问。UUID/封面空值不能证明此前从未创建,短 ID 不能仅因长度被判为占位符。
即使外层仍为 ok=true 或返回结构不符合契约,也不得为再次校验 CP 而执行或建议重发 form share update / +form-share-update(包括稍后传相同配置);诊断不能新增写入,只保留回执并交由服务端排查。
## 建议操作顺序
```bash
@@ -100,8 +137,8 @@ dws aitable +form-share-get --base-id BASE_ID --table-id TABLE_ID --view-id VIEW
| 命令 | 用途 | 必填参数 | 说明 |
|------|------|----------|------|
| `form share get` | 获取分享配置 | `--base-id` `--table-id` `--view-id` | 返回 enabled/status/shareFormUuid |
| `form share update` | 部分更新分享配置 | `--base-id` `--table-id` `--view-id` + 至少一个配置参数 | 开关用 `--enabled`;访问范围用 `--auth-type-code/--auth-data`;还可更新提交次数、有效期、名称描述、匿名提交、回填和通知配置;未传字段保持原值 |
| `form share get` | 获取分享配置 | `--base-id` `--table-id` `--view-id` | 返回服务端真实的 enabled/status/shareFormUuid/formCover;只读,不修复 CP |
| `form share update` | 部分更新分享配置 | `--base-id` `--table-id` `--view-id` + 至少一个配置参数 | 成功返回真实 shareFormUuid/status/formCover/cpSynced;只有 cpSynced=true 才完成闭环;未传字段保持原值 |
## 完整工作流示例
@@ -131,7 +168,7 @@ dws aitable form field update --base-id BASE_ID --table-id TABLE_ID --view-id VI
dws aitable form field hide --base-id BASE_ID --table-id TABLE_ID --view-id VIEW_ID \
--field-id FIELD_ID --hidden true --format json
# 6) 开启分享;把已知表单标题同时传给分享配置
# 6) 开启分享;把已知表单标题同时传给分享配置,并检查返回的 shareFormUuid/status/formCover/cpSynced
dws aitable form share update --base-id BASE_ID --table-id TABLE_ID --view-id VIEW_ID \
--enabled true --form-name "员工信息收集" --format json
```
@@ -146,5 +183,7 @@ dws aitable form share update --base-id BASE_ID --table-id TABLE_ID --view-id VI
- `form field hide` 当前每次只接收一个 `fieldId`。多字段必须在同一 Base 写队列中逐个串行设置,全部完成后统一回读一次;不传数组,不并发写。
- 新建表单首次开启分享时,复用 `form create`/`form update` 中已知的标题,通过 `--form-name` 与 `--enabled true` 同时传入;不要为取标题额外调用 `form get`。已有分享仅调整其他配置时,不覆盖原名称。
- 分享开启后回读 `enabled/status/shareFormUuid`。“已开启分享”不等于“已允许匿名/免登录/组织外提交”;需按用户意图显式传入 `--anonymous-submit` 和 `--auth-type-code/--auth-data`,再通过 `form share get` 回读确认。
- 分享和字段 mutation 回执不是最终状态;必须独立读回,写超时时不原样重放。
- `form share update` 的成功结果已经来自服务端回读并完成 CP 投影校验;必须检查 `shareFormUuid/status/formCover/cpSynced`,只有 `cpSynced=true` 才能确认闭环完成。部分失败或 `cpSynced=false` 不得描述为成功。
- `form share update` 的成功结果还与本次请求逐项比对:响应 `baseId/tableId/viewId` 必须与请求一致,本次显式请求的 `enabled/formName/formDesc` 必须与响应回读值一致,不一致即返回 `partial_failure`。响应不回读的显式请求字段(如 `anonymousSubmit`、`authData`)列在 `data.unverified` 且 `verified=false`;这些字段只能报告“已提交但未验证”,不得声称已生效。
- DWS 不自行调用第二个 View 更新命令补偿 CP,也不拼装封面 URL。旧服务端发布窗口内 `formCover` 可能为空,应如实说明;稍后诊断当前配置时可用 `form share get`。
- “已开启分享”不等于“已允许匿名/免登录/组织外提交”;需按用户意图显式传入 `--anonymous-submit` 和 `--auth-type-code/--auth-data`。写超时时先查询真实状态,不原样重放 mutation。
@@ -1,5 +1,13 @@
# record query — 查询记录
## 只评审失效游标恢复
用户仅要求核对 Schema、评审分页失败的恢复边界时,沿用用户指定的原子或 Shortcut 入口,只查询一次其 compact Schema,不执行业务读写。回答先用下列三点短结论覆盖全部安全边界,不按单个错误展开长篇推导后才补充另一错误;用户未要求原理或操作细节时,到此结束,不套用下方实际查询流程:
1. `INVALID_CURSOR` / `CURSOR_SNAPSHOT_CHANGED`:丢弃全部累计读取结果(包括此前第一页)和旧 cursor,不原样重试、不拼接或去重合并新旧页;核对原查询条件后,不传 `--cursor` 从第一页只读重查。
2. `CURSOR_SNAPSHOT_UNAVAILABLE`:同样丢弃累计结果与旧 cursor,但必须先等待服务端版本信息恢复、服务修复或版本稳定,再不传 `--cursor` 从第一页只读重查,不能立即重试。`CURSOR_OFFSET_LIMIT` 则是 offset 已达上限,须先收窄 `--filters`(或改用 `--record-ids`/分段条件)缩小结果集再从第一页重查,直接重查会再次触顶。
3. 含建表或记录写入的工作流(如 `+table-copy`)不能整条重放;保留已知目标表、recordId、原 token 和回执,仅独立只读核对恢复范围。未知或不完整写入尚未核清前,不根据新旧查询差异推导缺失记录,不建议改发 `record create`、按数量差额补写或删除重建;查询恢复不是写入恢复许可。
## 命令格式
```
@@ -47,16 +55,25 @@ Flags:
- 用户需要导出完整数据时,优先使用 `dws aitable export data`;导出的文件不得被拉回 Agent 上下文用于等价分析。
- 已获明确许可的非分析完整逐行明细或逐条业务操作可直接使用 `--all`,不需要也不触发 `psql -l`、`psql -t` 或最小查询探测。psql 失败后,只有回看原始意图确认其完全属于该非分析明细场景时,才可丢弃 psql 未完成结果并重新以 `--all` 查询;它不能作为复杂 psql 分析的降级。使用前必须说明字段、范围、预计记录数和体积;即使获准也必须服务端过滤、仅取必要字段、先取小样本;预计超过 5,000 条、20 个字段、20MB 或需要 `--page-limit 0` 时必须再次确认。
- CLI 首次请求不传 cursor,后续原样使用上一页 `data.nextCursor`,并检测 cursor 循环;页间间隔 200ms。
- 同一分页会话的 `base-id/table-id/filters/sort/query/field-ids/limit` 必须保持不变,禁止重发第一页、复用旧会话 cursor、修改排序或自行构造 cursor。
- 同一有效分页会话的 `base-id/table-id/filters/sort/query/field-ids/limit` 必须保持不变,禁止无故重发第一页、复用旧会话 cursor、修改排序或自行构造 cursor;失效快照必须按下方例外规则丢弃整轮结果并重新开始。
- 只有自动分页输出 `complete=true`,或手动分页时 `data.nextCursor` 为空,才表示完整结束。普通扫描某页恰好返回 `limit` 条时,服务端可能返回 `nextCursor`;用它续页后若调用成功、`records=[]` 且 `nextCursor` 为空,这是正常的末页探测,应正常完成,不能报错、重试或判定漏查。
- 成功页的 `records=[]` 本身既不是错误也不是结束条件:`nextCursor` 非空就继续,`nextCursor` 为空就正常结束。
- 达到 page-limit、网络错误、缺少 `records` 的空响应、非法响应或 cursor 循环时,命令返回非零结构化错误;错误详情保留已取记录和续传 cursor。必须标记结果不完整,禁止把 partial 当 success 或据此给出全量结论。
- 达到 page-limit、普通网络错误、缺少 `records` 的空响应、非法响应或 cursor 循环时,命令返回非零结构化错误;错误详情保留已取记录和续传 cursor。必须标记结果不完整,禁止把 partial 当 success 或据此给出全量结论。只有错误未声明快照失效且确实提供有效断点时才可续传;不能自行给所有错误补出恢复 cursor。
### 失效游标例外(优先于普通断点续传)
`INVALID_CURSOR`、`CURSOR_SNAPSHOT_CHANGED`、`CURSOR_SNAPSHOT_UNAVAILABLE` 均返回 `retryable=false`、`discard_previous_results=true`、`restart_from_first_page=true`。丢弃本轮与此前保存的全部记录和旧游标,不提供 `details.incomplete_result.cursor` 恢复点;该对象即使存在也只保留诊断计数,不能凭空假定其中有新 cursor。
- `INVALID_CURSOR` / `CURSOR_SNAPSHOT_CHANGED`:核对原查询条件后,不传 `--cursor` 从第一页发起新的只读查询。禁止保留第一页后用去重方式拼接新快照。
- `CURSOR_SNAPSHOT_UNAVAILABLE`:服务端缺少排序分页所需版本信息;先等待服务修复或版本稳定,再不传 `--cursor` 从第一页查询。不能原样重试或猜测已生成可续传的新快照。
- `CURSOR_OFFSET_LIMIT`:排序游标 offset 已达上限(100000)。该码返回 `retryable=false`、`discard_previous_results=true`,但 `restart_from_first_page=false`,另带 `narrow_filters_required=true`。丢弃累计结果与旧游标后,必须先收窄 `--filters`(或改用 `--record-ids`/分段条件)缩小结果集,再从第一页重查;不收窄直接重查会再次触顶。
- 不重跑含写入步骤的整条命令(如 `+table-copy`、bulk patch);保留已知写入供独立核对,重新查询不代表允许再次建表、补写或删除重建。
```bash
# 仅限已获明确许可的非分析明细:自动翻页直到 nextCursor 为空
dws aitable record query --base-id X --table-id Y --all --page-limit 0 --format json
# 从结构化错误 details.incomplete_result.cursor 断点续传;其余查询条件必须与原请求完全一致
# 仅普通可恢复错误且实际提供有效 details.incomplete_result.cursor 时续传;失效快照禁止使用本例
dws aitable record query --base-id X --table-id Y --filters '<原 filters>' --sort '<原 sort>' --all --page-limit 0 --cursor '<原样 cursor>' --format json
```
@@ -66,6 +83,7 @@ dws aitable record query --base-id X --table-id Y --filters '<原 filters>' --so
2. `nextCursor` 非空时,将其原样作为下一次 `--cursor`;不得使用当前请求 cursor,也不得自行拼接或复用更早页 cursor。
3. 每一页保持全部查询条件不变并累计记录;如需防御性校验,以 `recordId` 检测重复,但重复 cursor 必须按异常停止,不能静默继续。
4. `nextCursor` 为空才结束。成功返回的空页是合法结果:若 `records=[]` 且 `nextCursor` 为空,则正常完成;若 `records=[]` 但 `nextCursor` 非空,则继续查询,不能把空页当作异常或自行重试当前 cursor。
5. 任一步出现上述失效游标错误,立即丢弃整轮累计结果及旧 cursor,并按失效游标例外结束本轮;不得把失败回包中的空 records/空 cursor 当作成功末页。
## 排序参数规范
@@ -134,6 +134,15 @@ Favorite、消息 Pin、消息 Top 与会话 Top 是四种对象,不能互换
显式稳定 ID 当前不携带可验证的 profile provenance;调用方必须保证来源,不得宣称所有
跨 profile 误用都会在本地写入前被拦截。
## 三方加密消息解密
`+chat-messages`、`+at-me`、`+search-msg`、`+thread-replies` 在策略允许时自动解密三方加密(SafeChat)消息密文,无需新 flag,也不需要手动调用 `batch_ding_decrypt_messages`。
- 解密成功的消息投影带 `contentDecrypted: true`、`cryptoLayer: "ding+safechat"`、`dingKeyVersion`(>0 时),文本字段渲染明文。
- payload 级解密台账 additive:`decryptCandidateCount` / `decryptAllowedCount` / `decryptedCount` / `decryptFailedCount` / `decryptFailures[]`。
- 单条解密失败只进台账并将 `partial` 置 true,不改变命令退出码;策略关闭保留密文并记 `policy_disabled` 失败项。
- stub 构建(无 SafeChat 后端)或 `--dry-run` 时不解密、无台账字段,输出与解密能力上线前一致;策略关闭同样不解密并保留密文,但会输出非空解密台账(`decryptFailedCount >= 1`,失败项 `reason` 为 `policy_disabled`),既有 `partial` 字段可能因此翻为 true。
## 故障处理
- `unknown flag`:读取同一 leaf Help,最多修正一次;
@@ -28,7 +28,7 @@ metadata:
<!-- VISIBLE_SHORTCUTS_START -->
## Shortcut 发现(按需)
`doc` 当前有 45 条公开 shortcut,完整清单保留在 Runtime Catalog 与 Schema,不在高频产品根 Skill 中重复展开。已知意图按下方路由;参数/约束/安全不明时读一次 leaf 窄 Schema。仅需且已发布 `result` 时查 outcomes/pagination,字段级再查 `data_schema`;缺失不以 Help/样例推断。Schema 不可用才读一次已知 leaf Help;`unknown flag` 用同 leaf Help 修正一次。`unknown command` 禁 Help:错误 suggestion → 已加载 Skill/reference 明确入口;均无则报漂移。禁全 Catalog/root/parent/product Help;低频 reference 不默认 Help。
`doc` 当前有 49 条公开 shortcut,完整清单保留在 Runtime Catalog 与 Schema,不在高频产品根 Skill 中重复展开。已知意图按下方路由;参数/约束/安全不明时读一次 leaf 窄 Schema。仅需且已发布 `result` 时查 outcomes/pagination,字段级再查 `data_schema`;缺失不以 Help/样例推断。Schema 不可用才读一次已知 leaf Help;`unknown flag` 用同 leaf Help 修正一次。`unknown command` 禁 Help:错误 suggestion → 已加载 Skill/reference 明确入口;均无则报漂移。禁全 Catalog/root/parent/product Help;低频 reference 不默认 Help。
仅当现有路由和 reference 都无法定位低频能力时,才执行 `dws shortcut list --service doc --format json` 做最后回退;不要为已知高频意图加载完整 Shortcut Catalog 或产品级 Schema。
<!-- VISIBLE_SHORTCUTS_END -->
@@ -1,6 +1,6 @@
---
name: dingtalk-drive
description: 钉钉文件管理(存储层,覆盖钉盘与文档空间)。Use when 用户说 钉盘/文档空间/我的文档中的普通文件或文件夹、查找/上传/下载/复制/移动/重命名/删除/回收站/权限/评论/元信息,或本地与钉盘文件夹比较、拉取、推送、双向同步;也承接在线文档节点的存储管理。文档正文编辑与导出走 dingtalk-doc;明确的知识库空间及空间内节点组织走 dingtalk-wiki。命令前缀:dws drive。
description: 钉钉文件管理(存储层,覆盖钉盘与文档空间)。Use when 用户说 钉盘/文档空间/我的文档中的普通文件或文件夹、查找/最近访问或编辑文档列表/上传/下载/复制/移动/重命名/删除/回收站/权限/评论/元信息,或本地与钉盘文件夹比较、拉取、推送、双向同步;也承接在线文档节点的存储管理。文档正文编辑与导出走 dingtalk-doc;明确的知识库空间及空间内节点组织走 dingtalk-wiki。命令前缀:dws drive。
metadata:
cli_version: ">=0.2.14"
category: product
@@ -40,7 +40,7 @@ metadata:
| 全局按名称或关键词找文件 | `dws drive +search --query <关键词> --page-all --max-pages 20 --max-items 500` | 需要完整搜索时自动翻页;只需首批结果时可不加 `--page-all`;多候选停止;在线文档正文搜索走 `doc +search` |
| 浏览根目录或已知文件夹 | `dws drive +list [--folder <dentryUuid>] --page-all --max-pages 20 --max-items 500` | 需要完整浏览时自动翻页;只需首批结果时可不加 `--page-all` |
| 发现钉盘企业空间或“我的文件”空间 | `dws wiki space list --type <orgSpace\|mySpace> --format json` | Drive 只读前置;orgSpace 按 nextToken 续页,取 spaceId/rootFolderId 后回到 Drive |
| 查看最近访问/编辑 | `dws drive +recent [--operate-type 1] --limit <N>` | 1=最近编辑;默认最近访问 |
| <!-- dws-intent: drive.recent.documents -->查看最近访问/编辑文档列表 | `dws drive +recent [--operate-type 1] --limit <N>` | 1=最近编辑;默认最近访问;无主题、人物、方向或动作条件时直接使用 |
| 查看节点类型和元数据 | `dws drive +inspect --node <dentryUuid>` | 按需加 stats/publish/cover,不为普通列表强制调用 |
| 下载普通文件 | `dws drive +download --node <dentryUuid> --output <相对路径>` | 当前 shortcut 接受 ID;在线文档用 `doc +export` |
| 只要临时下载地址不落盘 | `dws drive download --node <dentryUuid> --url-only --format json` | Agent 沙箱/外部系统自行下载时用;与 `--output/--overwrite` 等落盘参数互斥 |
@@ -62,6 +62,7 @@ metadata:
- 删除已确认节点:`dws drive +delete --node <dentryUuid>`;恢复:`+recycle-list/+recycle-restore`;版本:`+version-history/+version-get/+version-download/+version-revert`。
- 收藏:`+star-*`;公开状态:`+publish-get/+publish-unset`(`+publish-set` 不进入 Agent 路由);统计/封面用 `+inspect`;快捷方式用 `+create-shortcut`。
- 节点分享范围:`dws drive permission set-share-scope --node <ID> --visibility <PRIVATE|ORGANIZATION|PUBLIC>`([危险] 三档收敛,设置企业内公开/互联网公开/仅协作者)。查询当前分享范围用 `permission get-setting`。
- 目录树只用有界 `+list` 逐层遍历。
兼容别名不选路:`+info`→`+inspect`,`+find-file`→`+search`,`+search-docs`→`doc +search`。
@@ -112,7 +113,7 @@ Golden Route 参数足够时禁止读取 reference。其余最多读取一个精
|---|---|
| URL、文件类型或跨产品边界 | [intent-guide](references/intent-guide.md) |
| 文件夹比较、拉取、推送或双向同步 | [folder-sync](references/folder-sync.md) |
| 低频权限、版本、回收站、公开状态 | [drive reference](references/drive.md) 的对应章节 |
| 低频权限、分享范围、版本、回收站、公开状态 | [drive reference](references/drive.md) 的对应章节 |
| 文档查询、导入和模板保形流程 | [lite-recipes](references/lite-recipes.md) |
## 错误最短路径
@@ -97,7 +97,7 @@ dws drive +publish-get --node <dentryUuid>
dws drive +publish-unset --node <dentryUuid>
```
`+publish-get` 只读;`+publish-unset` 为高风险写。Runtime 虽注册了 `+publish-set`,但当前普通文件和在线文档都没有经过验证的开启公开闭环,因此根 Skill 明确不将它开放给 Agent。用户要求开启公开时,说明当前 Agent 路由不支持并停止;不要查询或执行 `+publish-set`、`drive publish set` 或其他替代写入口。只有补齐受支持节点上的真实 set→get→unset 闭环证据并更新 Agent 路由后,才重新开放该能力。
`+publish-get` 只读;`+publish-unset` 为高风险写。Runtime 虽注册了 `+publish-set`,但当前 Catalog Availability 为 unavailable,不要用它开启互联网公开;开启互联网公开统一走 `permission set-share-scope --visibility PUBLIC`。`+publish-unset` 与 `permission set-share-scope --visibility PRIVATE` 终态等价(scope=0、同样打断继承),保留仅 CLI 兼容;`+publish-get` 与 `permission get-setting` 仅差 pendingApproval 一个字段(待服务端补齐后可完全平替),保留仅 CLI 兼容。
## 权限
@@ -106,6 +106,7 @@ dws drive +publish-unset --node <dentryUuid>
| 查看成员权限 | `drive permission list` |
| 查询节点权限设置(权限模式/分享范围/策略) | `permission get-setting` |
| 添加、修改、移除成员 | `permission add` / `update` / `remove` |
| 设置节点分享范围(可见性) | `permission set-share-scope` |
| 转移所有者 | `permission transfer-owner` |
| 查看可申请权限和审批人 | `permission apply-info` |
| 发起权限申请 | `permission apply` |
@@ -116,6 +117,8 @@ dws drive +publish-unset --node <dentryUuid>
发起权限申请先只读执行 `permission apply-info`。正式 `permission apply` 会通知审批人;调用前必须向用户逐项回显并确认资源、申请角色、审批人和理由。Agent 不得默认选择第一位审批人、最高/最低角色或代写申请理由;用户未明确同意完整申请内容时停在确认环节。
`permission set-share-scope` 设置节点分享范围(可见性),三档一次收敛。适用于文档空间节点与钉盘文件/文件夹;钉盘文件/文件夹不支持互联网公开(PUBLIC)档,对其设置 PUBLIC 返回 operation.notSupported。[危险] 操作,必须经用户确认后加 `--yes`。必填 `--node` + `--visibility`(PRIVATE/ORGANIZATION/PUBLIC)。档位决定可用参数:PRIVATE 无需其他参数;ORGANIZATION 用 `--role`/`--partner`/`--can-search`/`--can-recommend`;PUBLIC 用 `--role`/`--password`/`--expire-days`。不适用组合本地拒绝(exit 3)。参数装配为部分更新语义:可选参数不传即不下发、保持原值不变。`--password` 三态:不传=不改变,空串=清除,非空=设置(4位字母数字)。`--expire-days`:0=永久,正整数=N天。查询节点当前分享范围用 `permission get-setting`。互联网公开(含访问密码与有效期)统一走本命令 `--visibility PUBLIC`;`publish set` 已不在 Agent 可选面(见上方「公开状态」段),不要用它开启互联网公开。`publish unset` 与 `--visibility PRIVATE` 终态等价,新代码统一用 `set-share-scope`。需要企业内公开档或组织内搜索/推荐/合作伙伴(外包)开关时同样只能用 `set-share-scope`。
## 快捷方式节点
`+create-shortcut --node <源ID> [--folder <目标ID>|--workspace <知识库ID>]` 创建链接。在线文档节点需要保留版式的独立副本时使用 `+copy`;普通钉盘文件的独立副本必须经用户授权后走 download→upload,因为当前 `+copy` 会拒绝普通文件。源/目标类型不兼容时停止,不把快捷方式当普通文件继续覆盖。
@@ -110,6 +110,10 @@ dws event consume \
- `type` 是当前 event key;`event_id` 可用于去重;`timestamp` 是 transport 事件发生时间;`subscribe_id` 标识对应的独立订阅。
- `process_instance_id` 是审批实例 ID,可传给 OA 审批命令的 `--instance-id`;`process_code` 是审批流程模板编码。
- `create_time`、`finish_time` 和 `event_time` 都是毫秒时间戳。`event_time` 是审批业务事件时间,`timestamp` 是 transport 事件时间。
- 七类 OA 事件的 `staff_id` 来自原始 `payload.body.staffId`,保留字符串值;服务端未提供或为空时省略,不用外层 `uid` 替代。
- 七类 OA 事件的 `activity_id` 来自原始 `payload.body.activityId`,保留字符串值;服务端未提供或为空时省略。
- 七类 OA 事件的 `corp_id`、`business_id` 分别来自原始 `payload.body.corpId`、`payload.body.businessId`,保留字符串值;未提供或为空时省略,不用外层 `corpid`、`bizid` 替代。
- 抄送事件的 `cc_time` 来自原始 `payload.body.ccTime`,是毫秒时间戳;未提供或为 `null` 时省略,不用 `event_time` 替代。
- 七类事件的额外字段如下;具体事件始终以 `dws event schema <event_key> --flatten` 为准。
| 事件 | 额外顶层字段 |
@@ -118,7 +122,7 @@ dws event consume \
| `user_oa_approval_task_finished` | `task_id`、`result`、`finish_time` |
| `user_oa_approval_task_redirected` | `task_id`、`result`、`finish_time` |
| `user_oa_approval_instance_started` | 无 |
| `user_oa_approval_instance_cc` | 无 |
| `user_oa_approval_instance_cc` | `cc_time`(服务端提供时) |
| `user_oa_approval_instance_terminated` | `finish_time` |
| `user_oa_approval_instance_finished` | `result`、`finish_time` |
@@ -40,6 +40,8 @@
| `dws mail thread trash` | 将单个邮件会话移动到已删除文件夹(不会永久删除) |
| `dws mail thread batch-trash` | 将多个邮件会话批量移动到已删除文件夹(单次最多 100 个,不会永久删除) |
| `dws mail user search` | 搜索通讯录用户(**按姓名或工号查他人邮箱**,不是搜邮件) |
| `dws mail user get` | 按完整企业邮箱精确查询当前组织内员工的 uid、staffId 和姓名 |
| `dws mail user batch-get` | 按 1 至 100 个完整企业邮箱批量查询员工,返回匹配员工和未匹配邮箱 |
| `dws mail template create` | 创建邮件模板 |
| `dws mail template list` | 列举邮件模板 |
| `dws mail template get` | 获取邮件模板详情 |
@@ -1135,6 +1137,53 @@ Flags:
将草稿箱中已有的草稿发送出去。草稿 ID 来自 `draft create` 或 `message search`(`folderId:5`)的返回结果。
### 按企业邮箱精确查询员工
```bash
dws mail user get --org-email zhangsan@example.com --format json
dws schema mail.get_user_by_org_email --compact
```
只传目标员工的完整企业邮箱;操作人 `uid` 和组织 `orgId` 由平台注入。
不得猜测或补全域名,也不转换邮箱别名;保留输入的大小写和 `+` 后缀。
结果位于统一输出的 `data`:`success=true` 且 `result.uid` 非空表示找到员工;
`result` 为 null、缺失或 `uid` 为空表示未找到有效员工。
单查会校验 `result` 及已声明员工字段的类型;畸形结果返回 API 错误,不会作为成功员工信息交给 Agent。
`result.staffId` 即组织内 `userId`,不是工号;`result.uid` 是钉钉全局 UID。
只知道姓名或工号时使用 `mail user search`,查询邮箱容量与别名使用 `mail mailbox profile`。
### 批量按企业邮箱查询员工
```bash
dws mail user batch-get --org-emails alice@example.com,bob@example.com --format json
dws schema mail.batch_get_users_by_org_emails --compact
```
`--org-emails` 可用逗号分隔或重复传入,映射为 MCP 的 `orgEmails` 字符串数组。
每批 1 至 100 个邮箱,上限按去重前数量计算;更多邮箱需要分批调用。
空元素按原始下标单独记录失败,其他邮箱继续查询;全空输入直接报参数错误。
平台注入操作人和组织身份。服务端去首尾空格后忽略大小写去重,保留首次出现的地址和顺序,不解析邮箱别名。
`data.result.users` 返回匹配员工,字段与单个查询相同;`data.result.notFoundOrgEmails` 返回未匹配邮箱。
两个列表都按去重后的请求顺序排列;没有匹配员工时 `users=[]`,全部找到时 `notFoundOrgEmails=[]`。
未匹配项不表示调用失败。后端明确因单个非法邮箱拒绝整批时,CLI 自动用单查接口逐项查询,保留可用结果。
正常批量仅请求一次;上述兜底最多追加 100 次单查,邮箱忽略大小写去重。鉴权、权限、连接和其他整批故障不会触发兜底。
兜底期间发生全局鉴权、权限或连接故障时立即停止,保留原错误分类和退出码;结构化错误中的
`error.details.partialResult` 保留已确认结果,尚未确认的项记为 `unknown`。
取消操作和原始 PAT 授权错误直接交回框架,不转换为退出码 7,也不改写其原有协议。
单项失败而其他项有确认结果时返回 `outcome=partial_failure`,退出码为 **7**,结果仍在 stdout:
- `data.total`:去重后的邮箱与空元素总数。
- `data.succeeded`:已确认查询,每项包含请求邮箱 `id`、`orgEmail` 和 `found`;找到时还有 `user` 员工信息,`found=false` 表示确认未匹配。
- `data.failed`:明确失败项的 `id` 和 `error`;空元素使用 `org-emails[原始零起始下标]` 标识。
- `data.unknown`:返回缺失或异常、无法确认的邮箱及原因;不得归为“未找到”,可针对这些邮箱重试。
坏记录不会丢弃其他有效结果;返回缺少某个数组时,仍保留另一数组中可确认的项。全部查询均无法确认或均失败时返回 `failure`。
解析方应先检查 `outcome`:完全成功仍使用 `data.result.users` / `notFoundOrgEmails`;部分成功使用上述逐项通道。
**退出码 7 不代表全部查询失败。** Agent 仍须解析 stdout,读取 `data.succeeded` 中 `found=true` 的 `user`,
用已确认有效成员继续用户已授权的后续操作,并报告未匹配、失败和未知邮箱。不得仅因退出码非零丢弃有效成员,
也不得把 `found=false`、`failed` 或 `unknown` 的邮箱当作有效成员。只使用返回的真实成员 ID,不猜测或补造 ID。
### 搜索邮箱用户(通讯录)
```
Usage:
@@ -1,6 +1,6 @@
---
name: dingtalk-misc
description: 长尾产品集合技能,覆盖低频钉钉产品:OA审批查询与处理/法务智能合同/考勤/直播/DING紧急消息/开放平台应用与MCP开发/Agoal目标管理/日志日报周报/电子表格/开放平台文档搜索与OpenAPI逃生舱/独立及文档内嵌白板/钉钉招聘/DWS技能市场安装/组织大脑Hrbrain/原生Markdown/原生HTML/PAT行为授权/多组织profile。Use when 用户提到上述任一产品,尤其是 Agoal/目标管理/战略解码/经营合约及字段配置/计分卡/OKR/目标规则与周期/个人目标/目标模板/周月报规则提交统计/按时/迟交/未提交/跟催,或查询/创建合同台账、批量导入合同、按听记起草合同、发起合同审查、归档合同、管理合同项目/相对方/账款,或查待审批/同意拒绝转交撤销审批/打卡/排班/日报周报内容填报/独立白板带内容创建/白板节点读写/单元格读写/招聘职位/JD/创建职位/搜索安装技能/开发者后台应用/企业内部应用/查应用状态或能否删除/应用管理成员及角色汇总/应用版本历史/企业内部应用机器人配置、消息模式或在线状态/本机机器人连接器/Stream连接/MCP服务或工具/发布或调试MCP/获取或调用已发布MCP/把OpenAPI、Swagger、Postman、curl或HTTP接口做成MCP或给Agent使用/未封装OpenAPI/llms.txt/dws api/人才池/员工档案/职业历程/绩效/原生.md文件/Markdown版本比较/本地草稿diff/Markdown评论/原生.html文件/新建HTML页面/PAT授权/切换组织/跨组织/profile 等相关操作。周报/月报内容填报属于 report;规则级按时、迟交、未提交统计与人员跟催属于 Agoal;带审批人、抄送人或审批流的日报、周报、简报提交属于 OA 审批。未来审批任务或实例变化的实时监听不属于本 skill,应使用 dingtalk-event。命中后由本 skill 的「产品索引表」定位具体子产品和命令前缀,再按对应子产品说明执行。
description: 长尾产品集合技能,覆盖低频钉钉产品:OA审批查询与处理/法务智能合同/考勤/直播/DING紧急消息/开放平台应用与MCP开发/Agoal目标管理/日志日报周报/电子表格/开放平台文档搜索与OpenAPI逃生舱/独立及文档内嵌白板/钉钉招聘/DWS技能市场安装/组织大脑Hrbrain/原生Markdown/原生HTML/PAT行为授权/多组织profile。Use when 用户提到上述任一产品,尤其是 Agoal/目标管理/战略解码/经营合约及字段配置/计分卡/OKR/目标规则与周期/个人目标/目标模板/周月报规则提交统计/按时/迟交/未提交/跟催,或查询/创建合同台账、批量导入合同、按听记起草合同、归档合同、管理合同项目/相对方/账款,或查待审批/同意拒绝转交撤销审批/打卡/排班/日报周报内容填报/独立白板带内容创建/白板节点读写/单元格读写/招聘职位/JD/创建职位/搜索安装技能/开发者后台应用/企业内部应用/查应用状态或能否删除/应用管理成员及角色汇总/应用版本历史/企业内部应用机器人配置、消息模式或在线状态/本机机器人连接器/Stream连接/MCP服务或工具/发布或调试MCP/获取或调用已发布MCP/把OpenAPI、Swagger、Postman、curl或HTTP接口做成MCP或给Agent使用/未封装OpenAPI/llms.txt/dws api/人才池/员工档案/职业历程/绩效/原生.md文件/Markdown版本比较/本地草稿diff/Markdown评论/原生.html文件/新建HTML页面/PAT授权/切换组织/跨组织/profile 等相关操作。周报/月报内容填报属于 report;规则级按时、迟交、未提交统计与人员跟催属于 Agoal;带审批人、抄送人或审批流的日报、周报、简报提交属于 OA 审批。未来审批任务或实例变化的实时监听不属于本 skill,应使用 dingtalk-event。命中后由本 skill 的「产品索引表」定位具体子产品和命令前缀,再按对应子产品说明执行。
metadata:
cli_version: ">=1.0.61"
category: product
@@ -23,18 +23,19 @@ Attendance 任务直接按产品索引读取一份最匹配的 `attendance*.md`
| 触发关键词 | 一句话范围 | 命令前缀 | 详细参考 |
|---|---|---|---|
| OA / 审批 / 待处理审批 / 同意 / 拒绝 / 撤销 / 已发起审批 / 发起审批 / 审批附件 | OA 审批查询与处理;创建和附件按需加载专项说明 | `dws oa` | 先读核心 [oa.md](references/oa.md);发起审批再读 [oa-create.md](references/oa-create.md);附件操作再读 [oa-attachments.md](references/oa-attachments.md) |
| 法务 / 智能合同 / 合同台账 / 合同审查 / 合同归档 / 合同项目 / 相对方 / 合同账款 | 智能合同台账、导入、起草、审查、归档、项目、相对方与账款管理 | `dws contract` | [contract.md](references/contract.md) |
| OA / 审批 / 待处理审批 / 同意 / 拒绝 / 撤销 / 已发起审批 / 发起审批 / 审批附件 / 创建模板 / 更新模板 | OA 审批查询与处理;创建、附件和模板写入按需加载专项说明 | `dws oa` | 先读核心 [oa.md](references/oa.md);发起审批再读 [oa-create.md](references/oa-create.md);附件操作再读 [oa-attachments.md](references/oa-attachments.md);创建/更新模板再读 [oa-template-write.md](references/oa-template-write.md) |
| 法务 / 智能合同 / 合同台账 / 合同归档 / 合同项目 / 相对方 / 合同账款 | 智能合同台账、导入、起草、归档、项目、相对方与账款管理 | `dws contract` | [contract.md](references/contract.md) |
| 考勤 / 打卡 / 班次 / 考勤组 / 排班 / 考勤报表 / 假期余额 | 考勤记录、规则与配置、排班、报表、假期 | `dws attendance` | 日常查询/规则/设置:[attendance.md](references/attendance.md);排班导入或排班表导出:[attendance-schedule.md](references/attendance-schedule.md);考勤 Excel/报表导出:[attendance-report.md](references/attendance-report.md);假期/余额:[attendance-vacation.md](references/attendance-vacation.md) |
| 直播 / 我的直播 / 直播列表 | 直播列表与直播记录查询 | `dws live` | [live.md](references/live.md) |
| DING / 紧急通知 / 电话DING / 短信DING / 必达消息 | DING 紧急消息(应用内/短信/电话),个人DING | `dws ding` | [ding.md](references/ding.md) |
| 开放平台应用 / 企业内部应用 / 应用状态或删除条件 / 应用管理成员 / 应用权限 / 应用版本或版本历史 / agentId / clientId / 应用机器人配置 / 机器人消息模式或在线状态 / 本机机器人连接器 / Stream连接 / 版本发布 / connect / MCP 服务开发 / MCP 工具发布 / MCP 凭证 / OpenAPI或Swagger或Postman或curl转MCP / 接口给Agent用 / 已发布MCP调用 | 开放平台企业内部应用,以及 MCP 服务、工具、鉴权、凭证、协作者和发布后动态调用 | `dws dev` / `dws dev mcp` / `dws mcp published` | 按下方「Dev 直达规则」读取一个 `references/dev/*.md`;意图不明时才读 [dev-index.md](references/dev/dev-index.md) |
| DEAP 数字员工 / 数字员工 / 人设 / 群感知 / DSH 接入 | 兼容路由;完整自然语言编排只由独立 `dingtalk-tag` skill 维护 | `dws dingtalk-tag` | 切换 [`dingtalk-tag`](../dingtalk-tag/SKILL.md) |
| 目标管理 / 战略解码 / 经营合约字段 / 计分卡 / OKR / 目标规则周期 / 个人目标 / 目标模板 / 周月报规则统计 / 按时迟交未提交 / 跟催 | Agoal 目标管理与经营目标跟进 | `dws agoal` | [agoal.md](references/agoal.md) |
| 日报 / 周报 / 月报 / 写日志 / 收件箱日志 / 发件箱日志 | 日志(日报/周报/月报)查询与按模版提交 | `dws report`(别名 `dws log`) | [report.md](references/report.md) |
| 电子表格 / 工作表 / 单元格读写 / 公式 / 超链接 / 浮动图片 | 电子表格创建/读写/公式/超链接/浮动图片/导出 | `dws sheet` | [sheet.md](references/sheet.md) |
| 开放平台文档 / API文档 / 接口文档 / 接口报错 | 开放平台开发文档搜索 | `dws devdoc` | [devdoc.md](references/devdoc.md) |
| 未封装 OpenAPI / llms.txt / dws api / Raw API / API 逃生舱 | 官方 llms.txt 分层发现,仅对企业内部应用 App Token 服务端 API 生成并确认 Raw 调用 | `dws api` | [openapi-explorer.md](references/openapi-explorer.md) |
| 白板 / 独立白板 / 文档内嵌白板 / 画布 / OpenNodes / 白板节点 | 带内容创建、读取和更新独立或文档内嵌白板;没有 `partId` 时默认独立白板 | `dws whiteboard` | [whiteboard.md](references/whiteboard.md) |
| 白板 / 独立白板 / 文档内嵌白板 / 画布 / OpenNodes / 白板节点 / SVG 预渲染 | 带内容创建、本地 SVG 预渲染、读取、写前 diff 预览和更新独立或文档内嵌白板;没有 `partId` 时默认独立白板 | `dws whiteboard` | [whiteboard.md](references/whiteboard.md) |
| 招聘 / 职位 / JD / 在招职位 / 创建职位 / 职位详情 | 钉钉招聘职位的查询、详情与创建 | `dws recruit` | [recruit.md](references/recruit.md) |
| 搜索技能 / 找技能 / 安装技能 / 技能市场 / 安装 DWS mono 或 multi skill | DWS 技能市场搜索、下载、安装与内置技能部署 | `dws skill` | [skill.md](references/skill.md) |
| 人才池 / 储备干部池 / 员工档案 / 职业历程 / 绩效记录 / 员工标签 / 组织大脑 / 人才搜索 | 组织大脑:人才池、员工档案专项模块与结构化人才搜索 | `dws hrbrain` | [hrbrain.md](references/hrbrain.md) |
@@ -46,6 +47,7 @@ Attendance 任务直接按产品索引读取一份最匹配的 `attendance*.md`
## 说明
- 命中数字员工时立即切换独立 [`dingtalk-tag`](../dingtalk-tag/SKILL.md);本 skill 不保留重复参考文档。
- 命中产品后必须读取其 `references/<product>.md`,不要只凭索引推测命令。Report 只读 [report.md](references/report.md);Sheet 常见闭环只读 [sheet.md](references/sheet.md),复杂任务按进入阶段顺序加载子 reference,每阶段最多一份、常规任务最多三份,禁止批量预读或重复读取。
- **Agoal / Report 边界**:填写、提交或查询普通日报/周报/月报正文走 Report;规则级提交统计、按时/迟交/未提交人数、人员清单和跟催走 Agoal。出现“月报”不能单独判给 Report,必须结合“规则/统计/迟交/未提交/跟催”等业务词判断。
- **考勤例外**:按索引表直接读取一份最匹配的 `attendance*.md`;不要先读 `attendance.md` 再读排班、报表或假期专项 Reference。只有一个任务确实跨两个独立考勤域时,才加载第二份。
@@ -58,7 +60,12 @@ Attendance 任务直接按产品索引读取一份最匹配的 `attendance*.md`
- **Dev 命令纪律**:默认使用可审计的 `dws dev ...` 原子路径,不为发现 shortcut 调用 `dws dev help`、子组 help 或 `dws devapp +...`。应用按名称定位只有 `dws dev app list --name`,没有 `dws dev app search`;现有应用的机器人名称、模式、状态用 `dws dev app robot get`,不走 `dws chat bot`;连接器是 `dws dev connect ...`,不在 `dws dev app` 下。已知 leaf 直接执行;只有当前参数确有不确定性时才读取一次该 leaf 的 compact Schema,Schema 不可用时才调用一次精确 leaf `--help`。不要用 group help 探路。
- **Dev JSON 与分页**:所有命令带 `--format json`;`connect list/status` 还必须带它们自己的 `--json`,否则实际输出是表格。`app list`、`permission list`、`event list`、`version list` 只接受游标分页:读取返回的 `meta.pagination.endpoint_exhausted/next_token`,续页传 `--cursor <next_token>`;禁止猜 `--page`、`--page-num`,也不要从 `data` 中找旧版 `hasMore/nextCursor`。
- **Dev 完成纪律**:执行前记下用户要求的每个交付项;按依赖顺序执行,删除/停用等清理放到最后。用户最初请求写操作只授权 dry-run,不是看过预检后的正式确认。必须先展示 dry-run 的准确对象、动作、业务参数和影响,再取得用户对该预览的明确确认;随后只把同一命令的 `--dry-run` 换成 `--yes`,目标或业务参数有任何变化都重新 dry-run、展示并确认。确认前不得发出非 dry-run 写调用;`--dry-run` 不是完成。写后只做一次必要回读。相同业务错误且参数、状态均未改变时不要重试;仅在新证据实际改变命令、参数或状态后重试一次。最终逐项回答,空列表也明确写“暂无”,不要用大段原始 JSON 挤掉其它结果。
- **DevDoc 搜索预算**:开放平台文档任务对每个用户主题先用原短语精确搜索一次;某主题无结果时最多再用一个由结果证据支持的同义词,随后如实报告未命中。禁止用 10 轮以上近义词、help 或跨产品搜索碰运气。
- OA 任务先读核心 [oa.md](references/oa.md)。只有进入真实提单阶段才增量读取 [oa-create.md](references/oa-create.md),只有处理审批附件才增量读取 [oa-attachments.md](references/oa-attachments.md);不要为普通查询预读创建、控件、节点和附件全集。要求未来审批任务或实例发生变化时实时通知,切换独立的 [`dingtalk-event`](../dingtalk-event/SKILL.md)。开放平台应用事件配置仍属于 DevApp,按 [dev/event.md](references/dev/event.md) 执行,不要与个人实时事件混淆。
- **Devapp 跨域快路径**:创建/清理应用加机器人、网页、成员等能力,首读 `dev/recipes.md` 即可,不再预读 app 或各专题。缺参才补精确段落;新建失败不能借用其它应用。确认后的续轮直接执行已确认且未变化的命令,完成必要回读后,同轮继续下一项 dry-run 并询问该项确认,不另问“是否继续”。复用 ID、回执和已读 reference;目标/参数变化仍重新预检确认。明确 STREAM 要传 `--mode STREAM`,不建连接就不读 connect;明确不发布就不进入发布链。
- **DevDoc 搜索预算**:明确的开发文档任务直接读 [devdoc.md](references/devdoc.md),无需冷启动预读 shared 或 Devapp。每个主题先原短语搜索;无结果或全不相关时,普通查找至多一次有依据的改写,再报告未命中。指定查询词和页数时不擅自替换或缩减;有返回不等于找到相关资料,禁止连续近义词或跨产品搜索碰运气。
- OA 任务先读核心 [oa.md](references/oa.md)。只有进入真实提单阶段才增量读取 [oa-create.md](references/oa-create.md),只有处理审批附件才增量读取 [oa-attachments.md](references/oa-attachments.md),只有创建或更新模板才增量读取 [oa-template-write.md](references/oa-template-write.md);不要为普通查询预读创建、控件、节点、附件和模板写入全集。要求未来审批任务或实例发生变化时实时通知,切换独立的 [`dingtalk-event`](../dingtalk-event/SKILL.md)。开放平台应用事件配置仍属于 DevApp,按 [dev/event.md](references/dev/event.md) 执行,不要与个人实时事件混淆。
- 原生 `.md` 与在线富文本 `adoc`、通用文件存储的边界见 [markdown.md](references/markdown.md);原生 `.html`/`.htm` 文件读写见 [html.md](references/html.md);跨组织 / profile 规则见 [profile.md](references/profile.md)。
- PAT 行为授权不是开放平台应用权限;后者见 [dev/permission.md](references/dev/permission.md)。
Agent 使用 OpenNodes 带内容创建白板时,必须先执行 `whiteboard render`,展示 SVG 和渲染提示后停止,等待用户明确确认当前版本才能创建;修改后重新渲染和确认。不得跳过预览直接创建,最初的创建请求及创建后回读不能替代预览确认。详见白板入口的创建流程;空白创建、直接套用模板和已有白板更新不由此规则扩展。
Agent 更新已有白板内容(追加、修改、删除、清空)必须先执行 `whiteboard +diff`,展示差异和风险后停止,等待用户明确确认当前差异,再用同一 sourceDigest 执行 `+update`;diff 失败或有 blocker 时不得写入。不得换原子 update 绕过,render、dry-run 和写后回读不能替代 diff。详见白板入口的更新流程。
@@ -47,7 +47,10 @@
|---|---|---|
| 查已提交的请假/加班/出差外出/补卡记录 | `dws attendance +list-approve` | `--users <ids> --types overtime,trip,leave,patch --start YYYY-MM-DD --end YYYY-MM-DD` |
| 获取可提交表单入口 | `dws attendance +get-approve-template` | `--type leave\|overtime\|repair-check\|travel\|out`;只返回入口,不代填提交 |
| 查可用假期类型与余额(请假套件前置) | `dws attendance approve leave-types` | `--user <userId>` 可选;返回 `leaveCode`/`leaveViewUnit`/余额;`bizType` 不可靠,哺乳假等自定义类型按 `leaveName` 识别 |
| 计算考勤审批时长 | `dws attendance +calculate-approve-duration` | `--biz-type 1..8 --duration-mode 1..5 --start <时间> --end <时间>`;半天模式补 `--half-start/--half-end AM\|PM`;只计算,不提交 |
| 校验出差/外出同行人班次 | `dws attendance +check-companion-schedules` | `--approve-type 1\|2 --starts <时间列表> --ends <时间列表> --duration-unit DAY\|HOUR`;有同行人时传 `--principal-users`;`valid=false` 是业务拒绝 |
| 查询员工适用的复杂加班规则 | `dws attendance +get-complex-overtime-setting` | `--users <ids> [--work-date <日期>]`;不传日期时由服务端使用当前时间 |
| 查可用假期类型与余额(请假套件前置) | `dws attendance approve leave-types` | `--user <userId>` 可选;返回 `leaveCode`/`leaveViewUnit`/余额;哺乳假判定以 `bizType === "breastfeeding_leave_new"` 为准(缺失时回退名称含「哺乳」),判定细则见 [oa-leave.md](oa/oa-leave.md) |
| 计算请假时长(服务端口径) | `dws attendance approve leave-duration` | `--leave-code --start --end` 必填;时长禁止本地估算 |
| 请假提交前资格校验 | `dws attendance approve leave-check` | 时长必须取自 leave-duration 输出;`success=false` 非零退出并转告 `errorMsg` 后终止 |
| 匹配补卡目标异常班次 | `dws attendance approve supply-plans` | `--time "YYYY-MM-DD HH:mm"` 必填;`plans` 空数组属正常结果;多班次须用户选择 |
@@ -55,7 +58,9 @@
查询接口把出差和外出合并为 `trip`;表单入口必须区分外出 `travel` 与出差 `out`。多个模板全部返回,将名称最匹配者置前,并用 `[表单名称](submitUrl)` 展示,禁止裸露 URL 或只返回一个模板。
请假与补卡的**提交**意图路由到 oa 域套件工作流(见 [oa.md](oa.md)「发起请假审批」/「发起补卡审批」章节);上表 `approve` 命令为其前置只读查询/校验。`+get-approve-template` 的 `submitUrl` 入口用于加班/外出/出差,以及不支持 CLI 发起的请假/补卡模板场景。
请假、补卡、外出与加班的**提交**意图路由到 oa 域套件工作流(见 [oa/oa-leave.md](oa/oa-leave.md)「发起请假审批」/ [oa/oa-supply.md](oa/oa-supply.md)「发起补卡审批」/ [oa/oa-goout.md](oa/oa-goout.md)「发起外出审批」/ [oa/oa-overtime.md](oa/oa-overtime.md)「发起加班审批」),各工作流的前置只读查询/校验命令以上表对应行标注为准。`+get-approve-template` 的 `submitUrl` 入口用于出差(无 CLI 发起工作流,链接引导提交),以及各套件中不支持 CLI 发起的模板场景(如加班旧版模板)。
审批时长和同行人班次命令接受 `YYYY-MM-DD` 或 `yyyy-MM-dd HH:mm:ss`,由 DWS 转换为 MCP 所需的 13 位毫秒时间戳。同行人校验只判断所选人员的班次兼容性,不检查重复审批单;没有同行人时无需调用。`+calculate-approve-duration` 返回的 `compressedValue`、明细和提示应完整保留给后续审批流程,不自行拼装或改写。
### 补卡规则、加班规则与班次定义
@@ -115,9 +120,12 @@
| Shortcut | 风险 | 适用场景 |
|---|---|---|
| `dws attendance +calculate-approve-duration` | read | 计算加班/请假/外出等考勤审批时长 |
| `dws attendance +check-companion-schedules` | read | 校验出差/外出同行人的班次是否允许一起提交 |
| `dws attendance +check-record` | read | 查询用户打卡流水(打卡时间/地点/定位方式) |
| `dws attendance +check-result` | read | 查询用户打卡结果(迟到/早退/缺卡等) |
| `dws attendance +get-approve-template` | read | 查询补卡/请假/加班/外出/出差审批提交链接 |
| `dws attendance +get-complex-overtime-setting` | read | 查询员工在指定日期适用的复杂加班规则 |
| `dws attendance +get-overtime-rule` | read | 根据加班规则主键 ID 查询加班规则详情 |
| `dws attendance +list-approve` | read | 查询用户考勤审批单(补卡/加班/请假/出差外出) |
| `dws attendance +search-adjustment-rule` | read | 查询当前用户可管理的补卡规则列表 |
@@ -4,13 +4,13 @@
## 能力范围与边界
Use when:用户要查询或创建合同台账、批量导入合同、按听记起草合同、发起合同审查、归档合同,或管理合同项目、相对方与收付款账款。
Use when:用户要查询或创建合同台账、批量导入合同、按听记起草合同、归档合同,或管理合同项目、相对方与收付款账款。
Avoid when:
- 查询、同意、拒绝、转交或撤销已有合同 OA 审批实例走 `dws oa`,不要与合同审批模板 `process-templates` 混淆。
- 经营合约、目标、计分卡和 OKR 跟进走 `dws agoal`。
- 合同文件的搜索、上传、下载及钉盘元数据走 `dws drive`;合同台账、审查和归档仍走 `dws contract`。
- 合同文件的搜索、上传、下载及钉盘元数据走 `dws drive`;合同台账和归档仍走 `dws contract`。
- AI 听记内容查询走 `dws minutes`;取得真实 `taskUuid` 后再调用 `dws contract draft`。
- 花名册中的劳动合同等员工基础字段走 `dws contact`。
@@ -22,7 +22,6 @@ Avoid when:
| 从钉盘模板批量导入合同、查导入结果 | `dws contract import ...` |
| 查审批模板或台账分类 | `dws contract process-templates` / `dws contract file-directories` |
| 根据 AI 听记和模板起草合同 | `dws contract draft` |
| 解析合同、创建审查任务、查审查结果或权益 | `dws contract review ...` |
| 管理合同项目、导入导出项目 | `dws contract project ...` |
| 管理相对方、工商信息、风险、导入导出 | `dws contract subject ...` |
| 管理合同收付款账款 | `dws contract account ...` |
@@ -52,13 +51,6 @@ Avoid when:
2. 按本文构造 JSON 文件,向用户确认提交对象与关键字段。
3. 创建使用 `record create`;归档使用 `archive`。执行后根据返回的真实 ID 回读或报告状态。
### 合同审查
1. 可先执行 `review benefit` 确认权益。
2. 不确定审查类型或推荐模型时,先用 `review analysis` 解析文件。
3. 用 `review create` 创建任务,保存真实 `taskId` 和 `reviewType`。
4. 用 `review result` 查询结果;未完成不得宣称审查已完成。
### 批量导入
1. 从模板命令或已有钉盘文件取得真实 `fileId` / `spaceId`。
@@ -71,7 +63,6 @@ Avoid when:
- [批量导入](#批量导入)
- [基础资料](#基础资料)
- [合同起草](#合同起草)
- [合同审查](#合同审查)
- [项目管理](#项目管理)
- [相对方管理](#相对方管理)
- [账款管理](#账款管理)
@@ -155,38 +146,6 @@ dws contract import batch-result --task-id <TASK_ID> --format json
dws contract draft --task-uuids <TASK_UUIDS> --template-url <TEMPLATE_URL> --format json
```
## 合同审查
| 命令 | 必填参数 | 用途 |
|---|---|---|
| `dws contract review benefit` | 无 | 查询组织的合同审查权益 |
| `dws contract review analysis` | `--file` | 解析合同文件并返回摘要及推荐模型 |
| `dws contract review create` | `--file` | 创建合同审查任务 |
| `dws contract review result` | `--task-id`, `--review-type` | 查询审查结果 |
### analysis 请求
JSON 可包含 `fileInfo` 对象,常用字段为 `fileId`、`spaceId`、`fileName`、`fileSize`、`fileType`;可选 `source`。文件 ID 必须来自钉盘真实返回。
### create 请求
`IntelligentContractReviewClientRequest` 常用字段:
- `source`
- `fileInfo`:`fileId`、`spaceId`、`fileName`、`fileSize`、`fileType`
- `reviewType`
- `companyList[].reviewPosition`
- `reviewPosition`
- `reviewResultType`
- `customReviewRules`
```bash
dws contract review benefit --format json
dws contract review analysis --file ./analysis_request.json --format json
dws contract review create --file ./review_request.json --format json
dws contract review result --task-id <TASK_ID> --review-type <REVIEW_TYPE> --format json
```
## 项目管理
| 命令 | 必填参数 | 用途 |
@@ -325,7 +284,6 @@ dws contract archive --file ./archive_request.json --format json
| `record list` / `get` / `quantity-by-type` / `create` | `queryContracts` / `queryContractDetails` / `queryContractQuantityByType` / `createContract` |
| `import batch` / `batch-result` | `batchImportContractAsync` / `getBatchImportContractResult` |
| `process-templates` / `file-directories` / `draft` | `queryContractProcessContent` / `getAllFileDirectory` / `draft_contract_by_minutes` |
| `review benefit` / `create` / `analysis` / `result` | `queryContractReviewBenefit` / `createContractReviewTask` / `contractAnalysis` / `queryContractReviewResult` |
| `project ...` | `addProject`, `deleteProject`, `updateProject`, `setProjectStatus`, `queryProjects`, `queryProjectDigests`, `queryProjectDetail`, `exportProject`, `getImportProjectTemplate`, `importProject`, `getImportProjectResult` |
| `subject ...` | `addSubject`, `querySubjects`, `querySubjectDetail`, `updateSubject`, `deleteSubject`, `batchDeleteSubject`, `sortSubjects`, `detectSubjectRisk`, `querySubjectBaseInfo`, `autoFillSubjectInfo`, `exportSubject`, `getImportSubjectTemplate`, `importSubject`, `getImportSubjectResult` |
| `account ...` / `archive` | `createAccountInfo`, `updateAccountInfo`, `getAccountEntryInfo`, `listAccountInfo`, `deleteAccountEntryInfo`, `contractOpenArchive` |
@@ -24,6 +24,14 @@ dws dev app delete --unified-app-id <id> --confirm-name <应用名> --dry-run --
应用只有 `list/get/create/update/disable/enable/delete` 及下属能力组;按名称查找使用 `app list --name`,不存在 `dev app search`。列表续页只传返回的 `meta.pagination.next_token` 到 `--cursor`;`endpoint_exhausted=true` 才是到底,禁止使用 `--page/--page-num`。
创建优先携带 `--desc`:用户指定则原样使用,未指定则仅按已表达用途拟定简短说明,预检展示并确认。当前环境有省略说明后返回 `67010` 的实测记录,不能据 CLI 可选标记默认省略,也不能据此断言错误码的通用含义。用户明确要求不填说明/图标时仍省略,不用空格、短横线或猜测值替代。
只改名称时用 `app update --unified-app-id <id> --name <新名称> --dry-run --format json`,不附带保持不变的 `desc`。应用说明与机器人简介不是同一字段,后者用 `robot config --brief` 并由 `robot get` 验证。
新建任务只能使用本次创建成功返回的 ID;失败后不得借用列表中的其它应用或历史同名应用。多应用分别绑定名称、ID 和回执,删除时传各自当前名称到 `--confirm-name`。缺少删除参数时修正并重新预检确认,不遗漏清理,也不越过确认。
dry-run 成功只证明预览成功,不保证服务端接受。业务错误(如 `67010`)含义不明时保留错误码与 Trace ID,不猜定权限或重名原因。按预检实际参数判断请求是否改变:空字符串被省略后与未传字段可能是同一请求,不据此重复正式创建;超时或中断先只读核实是否已创建,结果不明不重复创建。
## 状态与结果
- `app list` 用于定位,不能用其空的 `appStatus` 判断状态;状态以 `app get` 为准。
@@ -37,3 +45,5 @@ dws dev app delete --unified-app-id <id> --confirm-name <应用名> --dry-run --
若一句话同时要求“创建、配置/发布、最后删除”,依赖顺序固定为:创建 → 配置 → 版本生效或明确阻塞 → 收集用户要求的状态/详情 → 删除。中文位置不改变依赖关系,不要因“办完后删除”出现在中间就提前删除或停下来反问。
已知上述路径时直接执行;仅 flag 确有疑问时查一次该 leaf compact Schema,Schema 不可用才查一次精确 leaf help。
确认后的下一轮直接执行已确认且未变化的命令;不要重读本页或重复预检。正式写入和必要回读后,同轮可继续下一项 dry-run,再单独等待其确认。已有创建 ID 不为定位再 list;一份状态回读可同时满足用户的状态查询和写后验证。每轮只简述本次结果及下一次准确预检,不重复整个计划。
@@ -1,6 +1,6 @@
# Dev 跨域任务闭环
仅当同一请求明确跨两个以上 Dev 域时读取本文件。先建立交付清单并复用一个 `unifiedAppId`;本页就是常见跨域任务的首轮执行契约,禁止先读 `app/robot/event/version/...`。只有真实响应出现本页未覆盖的特殊状态或字段时,才补读一份对应专题 Reference。
创建或清理应用,同时配置机器人、网页、成员等,也属于跨域。本页覆盖常用路径;读完即可执行,不再为相同命令读取 app/robot/webapp 等专题。仅缺少当前步骤必要参数或遇到未覆盖状态时补读对应段落。各应用分别保存名称、创建 ID 和回执。
## 通用顺序
@@ -20,16 +20,28 @@
| 域 | 已知 leaf 与关键定位参数 |
|---|---|
| 应用 | `app list --name <name>`;详情/更新/删除复用 `--unified-app-id` |
| 成员 | `app member list/add/remove --unified-app-id <id>` |
| 应用 | `app create --name <name> --desc <用途说明>`;定位 `app list --name <name>`;详情 `app get --unified-app-id <id>`;改名 `app update --unified-app-id <id> --name <新名>`;删除 `app delete --unified-app-id <id> --confirm-name <当前名>` |
| 成员 | `app member list --unified-app-id <id>`;`app member add/remove --unified-app-id <id> --user-ids <真实ID,真实ID> --member-type DEVELOPER`(开发成员) |
| 权限 | `app permission list/add/remove --unified-app-id <id>` |
| 安全/网页 | `app security config --unified-app-id <id>`;`app webapp get/config --unified-app-id <id>`;安全配置无 get 命令 |
| 机器人/事件 | `app robot get/config/enable`;`app event list/subscribe/unsubscribe --unified-app-id <id>` |
| 版本 | `app version create/check-approval/publish/status --unified-app-id <id>`;后续命令复用 create 返回的 `versionId` |
| 本机连接器 | `dev connect list/status/restart`;list/status 另带 `--json`,不扫描系统进程 |
| 网页 | `app webapp get --unified-app-id <id>`;`app webapp config --unified-app-id <id>` 加用户指定的 `--homepage-url` / `--pc-homepage-url` / `--omp-url`,不猜 `--h5-page-type` |
| 机器人 | `app robot get --unified-app-id <id>`;`app robot config --unified-app-id <id> --name <名称> --brief <简介> --mode STREAM`(只传本次要求字段,明确 STREAM 时不可省略 mode);启停 `app robot enable/disable --unified-app-id <id>` |
| 事件 | `app event list --unified-app-id <id> --keyword <词> --page-size 50`;从 `data.events[]` 取真实 eventCode;`app event subscribe/unsubscribe --unified-app-id <id> --event-codes <code1,code2>` |
| 版本 | `app version create --unified-app-id <id> --desc <说明>`;`app version check-approval/publish/status --unified-app-id <id> --version-id <返回的versionId>`;普通无需审批且 publishable 才 publish,需选审批人时读取 version.md 对应规则,不猜人选 |
| 安全/凭证 | 安全配置按需读 security.md(无 get);凭证按需读 credentials.md,不在回答展示密钥 |
| 本机连接器 | `connect list/status/restart`;list/status 另带 `--json`,不扫描系统进程 |
所有命令补 `dws dev` 前缀和 `--format json`;写操作先 `--dry-run`。最初请求不等于预检后的确认,只有展示准确对象、动作、业务参数和影响并取得用户对该预览的明确确认后,才可把同一命令仅由 `--dry-run` 换成 `--yes`。已知路径不要用 help 探路。
## 参数直达与结果复用
- 基础创建 `app create --name <名称> --desc <用途说明>`。说明优先用用户原文;未指定时只依据已表达用途拟定简短说明,随预检展示并确认,不杜撰业务事实。当前环境曾出现省略说明时服务端 `67010`,不能因 CLI 标注可选就推荐默认省略;这不是该错误码的通用释义。用户明确要求不填时仍省略,不擅自填占位值,失败如实报告。最小参数原则主要用于更新:只改名传 `app update --unified-app-id <id> --name <新名>`,不重传未修改字段。
- 删除使用 `app delete --unified-app-id <本任务返回ID> --confirm-name <当前名称>`,先预检并确认。漏参数属于本地可修正错误,补齐后重新预检确认,不把它当无状态变化的业务错误直接放弃。
- 每个新建应用分别保存名称→ID→创建回执;创建失败没有可供后续写入的目标。禁止使用其它应用或历史同名应用“演示”剩余步骤;任务要求新建就不能用 list 命中替代创建。多个应用逐个完成各自确认,不能用一项确认创建另一项。
- 成员增删用 `--user-ids <真实ID,真实ID> --member-type DEVELOPER`(仅当用户要求开发成员);同角色同动作可一次传齐,写后核对实际名单,不以 userId 猜身份。
- 网页配置按需选 `--homepage-url`、`--pc-homepage-url`、`--omp-url`;不猜 `--h5-page-type`。
- 机器人简介是 `robot config --brief`,详细描述是 `--desc`,应用说明才是 `app update --desc`。只传要修改的字段,回读相同对象和字段。停用可能变成 `UNCONFIGURED`,涉及停启恢复时按需读一次 [robot.md](./robot.md),先保存配置并说明影响,不盲目 enable。
- 只查开发资料按 [devdoc.md](../devdoc.md) 的相关性与搜索预算;不预读其它应用专题。这里未涵盖的必要参数按需读一个对应专题,不为满足阅读次数限制猜参数。
## 常见闭环
- **网页应用**:`app create/list` → `webapp config` → 写结果要求发布时才 `version create` → `check-approval` → `publish` → `status` → `webapp get`。
@@ -39,10 +51,19 @@
- **安全 + 网页**:先 `app get` 保存应用初始状态,并用 `webapp get` 保存网页配置。安全配置没有读取命令;需要保留旧安全项但没有上游可信的完整旧值时,说明整组覆盖风险并暂停 `security config`,继续不依赖它的网页步骤。用户提供完整目标列表或明确接受覆盖后,才执行 `security config` → `webapp config` → 一次版本闭环 → 回读可读取的应用/网页/版本结果。
- **成员临时变更**:解析唯一 userId → add → `member list` 保存名单 → remove → 回读;若还要删除应用,删除最后做。
明确不发布/不建连接时,任何通用闭环都不能覆盖此限制:保存配置结果并说明未发布;服务端要求发布时报告阻塞,不擅自继续版本链。“维护完成后恢复”等外部条件尚未满足时等待,不把写操作确认当成条件满足。
## 轮次与失败预算
- 每轮推进到下一个真正的依赖停点:收到某条预检的明确确认后,参数未变就直接执行对应正式命令,不重复预检、不再次询问“是否继续”。读取必要结果后,可在本轮继续下一步骤的 dry-run,再展示该次对象、参数、影响并询问确认;下一项正式写入仍须单独确认。外部维护/审批条件不能由确认代替。
- 用户要求的状态快照、名单或配置回读也是验证证据,同一状态不额外再查一次。创建回执已给出 ID 时直接复用,不再 list/get 来寻找 ID。不要用 shell 管道裁剪命令回执;每次工具调用直接执行命令,原始回执留在轨迹。
- 确认摘要用“动作、对象名称/ID、完整业务参数、影响、是否确认”即可;不反复附上完整计划、已完成历史、原始 JSON 或整段 reference。最后一次统一汇总所有交付项。
- 每个写步骤:一次 dry-run,展示预检后等待明确确认;确认前不发出非 dry-run 写调用。正式命令的目标和全部业务参数必须与用户确认的预检完全一致,只允许把 `--dry-run` 换成 `--yes`;任何变化都重新 dry-run、展示并确认。一次必要回读即可。
- 相同业务错误不做无状态变化的重试;只在新的查询结果实际改变参数/状态后重试一次。发布错误按 [`version.md`](./version.md) 止损。
- 某个破坏性选择缺失时,暂停该动作但继续所有不依赖它的步骤;最终分开写“已完成 / 等待选择 / 失败阻塞”,不要只留下一个反问。
- 大列表只保留总数、用户相关项和分页完整性;空列表写“暂无”。最终逐项核对交付清单,避免结果被截断。
- 清理对象只能使用本任务创建并返回的 ID;删除失败不得声称已清理。
- 续轮只保留交付项、真实 ID、已完成回执、已确认预检和下一步依赖的简短状态;不用重新加载已读 reference、重新定位已知 ID 或重复未变的有效预检。不能把一个操作的确认复用到其它动作或目标。
- 预检摘要保留准确对象、完整业务参数与影响,不重复整段 JSON;不得用管道丢弃预检输出后仅打印“已准备”。相互独立的只读查询可并行,依赖 ID 的写操作和确认链仍按顺序执行。
- 中断先核实上一写操作是否生效,不能重新创建已成功对象。区分已完成、待确认/外部条件、失败、结果未知及待清理;只有原始交付项均有证据才总结全部完成。清理仍须满足原请求、依赖关系及预检后的确认,不能因失败自行删对象。
@@ -6,7 +6,7 @@
```bash
dws dev app robot get --unified-app-id <id> --format json
dws dev app robot config --unified-app-id <id> --name <机器人名> --desc <描述> --mode STREAM --dry-run --format json
dws dev app robot config --unified-app-id <id> --name <机器人名> --brief <简介> --mode STREAM --dry-run --format json
dws dev app robot enable --unified-app-id <id> --dry-run --format json
dws dev app robot disable --unified-app-id <id> --dry-run --format json
```
@@ -15,6 +15,18 @@ dws dev app robot disable --unified-app-id <id> --dry-run --format json
按应用名称审计机器人时先 `dev app list --name` 取得唯一 `unifiedAppId`,随后直接 `dev app robot get`;不存在 `dev app search`,也不要切到 `dws chat bot` 猜命令。
## 字段与恢复路径
| 用户要求 | 写入位置 | 回读核对 |
|---|---|---|
| 应用说明 | `app update --desc` | `app get` 的 `desc` |
| 机器人简介 | `app robot config --brief` | `robot get` 的 `brief` |
| 机器人详细描述 | `app robot config --desc` | `robot get` 的 `desc` |
简介与描述不是别名;同时要求时分别传值。只改简介就只传 ID 和 `--brief`,不重传名称、模式或应用说明。明确禁止自动加权限/关闭证书校验时,不擅自开启对应开关;要求核实的字段未返回时标明无法核实,不能用未传参数证明远端状态。
当前平台停用后可能读回 `UNCONFIGURED`,不能承诺保留配置的临时暂停。停用前保存恢复所需配置,在预检确认中说明影响;要求原样恢复但缺少必要配置时先澄清。停用后回读:仍有可启用配置才走 `enable`;`UNCONFIGURED` 时不反复 enable,在用户授权恢复的范围内用已保存配置重新 `config`,重新预检、展示并确认后执行,回读核对字段和状态。恢复配置不等于发布或建立连接。
## 异步建号
```bash
@@ -27,7 +39,7 @@ dws dev app robot result --task-id <submit返回的taskId> --format json
## 完成门禁
- 要求线上可用:配置/启用后继续 [`version.md`](./version.md),到 `RELEASE` 或明确审核态才算该阶段闭环。
- 要求本地调试:发布状态与 [`connect.md`](./connect.md) 的本地连接状态分别报告;connect 成功不代表发布完成。
- 要求本地调试:发布状态与 [`connect.md`](./connect.md) 的本地连接状态分别报告;connect 成功不代表发布完成。仅配置 STREAM 模式、不建连接时不要读取 connect 文档或操作连接器。
- 要求最终删除:先保存机器人配置/状态和版本结果,再按 [`app.md`](./app.md) 最后删除。
- 相同业务错误无状态变化时不改名、不重提任务、不用 help/debug/verbose 循环;如实报告 `errorCode/errorMsg`。
@@ -6,11 +6,10 @@ dws dev app webapp config --unified-app-id <id> \
--homepage-url <移动端主页> \
--pc-homepage-url <PC端主页> \
--omp-url <管理后台地址> \
--h5-page-type <类型> \
--dry-run --format json
```
- `config` 至少传一个需要修改的字段,未要求的字段不要猜。
- `config` 至少传一个需要修改的字段,按需求选取上述 URL 参数,不必三项齐传。`--h5-page-type` 仅在用户要求且类型值已确定时传;配置 URL 不意味着必须猜页面类型。保持不变的字段省略。
- 以 `get` 实际返回的 `data.configured` 和 URL 字段为准;`configured=false` 或 URL 缺失表示尚未配置,不是命令错误。不要依赖旧版“空对象 `{}`”判断。
- 最初请求只允许 dry-run。展示预检返回的应用 ID、完整 URL/页面类型参数及影响并取得用户对该预览的明确确认后,才把同一命令仅由 `--dry-run` 换成 `--yes`;参数变化就重新预检并确认,确认前不得真实配置。随后只回读一次 `webapp get`,以实际 URL 与 `h5PageType` 为准。
- 需要上线生效时继续走 [`version.md`](./version.md)。
@@ -16,11 +16,21 @@ Flags:
- 用户说"开发文档 / API 文档 / 接口文档 / 调用报错" → `devdoc article search`
## 相关性、分页与搜索止损
- 优先原主题短语。指定查询词、页数、每页条数时原样执行,不擅自换词或缩减分页;空页也如实记录。未指定时先小页检索,按相关性和用户完整性要求决定续页,不默认翻全量。
- 按标题、摘要核对产品、动作和接口主题。有返回不等于相关命中;完全无关与空结果都不能充当目标文档。摘要未提供的信息不能当成已读正文或已验证接口行为。
- 普通查找无相关命中时,最多再用一个有依据的同义词或接口名改写;仍未命中就停止并说明尝试与限制。用户明确要求广搜时再扩大范围,不连续轮换近义词、切 AISearch 或读 help 碰运气。
- 按实际链接去重,保留要求的标题、摘要、链接和分类,不猜链接。分别说明相关资料、无关返回和空页;未搜到不代表接口不存在。
- 用户要求整理返回结果时,即使结果全不相关,也将真实条目按要求的标题、摘要、链接去重列出,并标为“无关/不满足主题”;不能只说“查过三页”而遗漏交付列表,也不能把这些条目称为目标文档。纯粹找目标文档则只需报告无相关命中。
- 混合应用管理任务中文档未命中只阻塞依赖文档才能确定的步骤;已有可信参数的独立操作仍可继续。不为文档搜索创建应用、改权限或建版本。
- 已知命令直接执行,参数确有疑问时才查一次精确 leaf。只整理用户所需字段,原始 JSON 留在轨迹,不反复复述。所有命令带 `--format json`。
## 上下文传递
| 操作 | 从返回中提取 | 用于 |
|------|-------------|------|
| `devdoc article search` | 文档链接 | 直接展示给用户 |
| `devdoc article search` | 实际标题、摘要、链接及页码 | 判断相关性、去重后展示;无相关命中则明确未找到 |
---
@@ -10,6 +10,7 @@
- [表单值与能力边界](#表单值与能力边界)
- [考勤审批套件](#考勤审批套件)
- [流程预测与选人](#流程预测与选人)
- [交互优化原则](#交互优化原则)
- [执行前确认](#执行前确认)
- [创建与写后验证](#创建与写后验证)
- [错误收敛](#错误收敛)
@@ -21,6 +22,8 @@
| 常规表单与自选审批节点 | 只使用本文件与 `scripts/oa_create_preflight.py` 的紧凑输出,不再加载控件/节点全集 |
| 请假审批 | 先用 `dws attendance +get-approve-template --type leave` 定位模板,再按本文件“请假”闭环执行 |
| 补卡审批 | 先用 `dws attendance +get-approve-template --type repair-check` 定位模板,再按本文件“补卡”闭环执行 |
| 外出审批 | 先用 `dws attendance +get-approve-template --type travel` 定位模板,再按本文件“外出”闭环执行 |
| 加班审批 | 先用 `dws attendance +get-approve-template --type overtime` 定位模板,再按本文件“加班”闭环执行 |
| 紧凑表单输出出现 `needsComponentReference=true` | 只在 [oa-form-components.md](oa/oa-form-components.md) 中定位对应 `componentName` 小节 |
| 紧凑预测输出出现 `needsNodeReference=true`,或用户明确要求覆盖模板默认流程 | 只读取 [oa-process-nodes.md](oa/oa-process-nodes.md) 的对应节点或参数映射小节 |
| 表单包含本地附件 | [oa-attachments.md](oa-attachments.md) |
@@ -90,10 +93,21 @@ dws oa approval detail --instance-id <processInstanceId> --format json
- 必填:停止并说明当前 Skill 无法安全自动提交,请用户改用钉钉客户端或等待能力补齐。
- 非必填:取得用户同意后才可跳过,并在创建摘要中显式列出。
`DDHolidayField` 和 `DDBizSuite · attendance.supply` 只按下方考勤套件闭环提交,必须走高级 `--request`;不能套用 `DDDateRangeField` 或普通日期控件。其他 `DDBizSuite` 没有 CLI 已公开的稳定容器契约,停止创建;不能把套件子控件当普通顶层字段提交。
`DDHolidayField` 与 `DDBizSuite · attendance.supply/goout/batchovertime` 只按下方考勤套件闭环提交,必须走高级 `--request`;不能套用 `DDDateRangeField` 或普通日期控件。其他 `DDBizSuite` 没有 CLI 已公开的稳定容器契约,停止创建;不能把套件子控件当普通顶层字段提交。
### 明细与核心字段
`valueKind=table_rows_json_string` 表示 **JSON 序列化的二维 name/value 数组字符串**:每行是子控件对象数组,`name` 使用子控件 label,`value` 为按控件格式编码的字符串。下面示例展示两行明细:
```json
{
"name": "采购明细",
"value": "[[{\"name\":\"商品名\",\"value\":\"笔记本\"},{\"name\":\"数量\",\"value\":\"2\"}],[{\"name\":\"商品名\",\"value\":\"钢笔\"},{\"name\":\"数量\",\"value\":\"1\"}]]"
}
```
简单模式把上述 `value` 字符串放入 `--form-values` 的“采购明细”键;高级模式把上述控件对象放入 `--request` 的 `formComponentValues` 列表。**两种入口均不自动转换以 label 为 key 的行对象数组**,应使用 JSON 序列化器构造正确结构。不要把明细 `value` 内的二维数组与 `forecast-process` 外层 `formComponentValues` 的额外包装混淆。格式依据:[官方创建审批实例文档](https://open.dingtalk.com/document/orgapp/create-an-approval-instance.md)。
`TableField` 的每一行必须包含用户要求的核心子字段。创建前逐项对照原始需求,特别检查物品名称、数量、金额、日期、费用类型和备注;不能因为接口接受 payload 就认为业务字段完整。
若用户需求落在 `TableField` 中,父明细控件和相应子字段整体都是核心内容。即使父控件或子控件的 `required` 为 `false`,也不得为绕过服务端错误而删除、拆成顶层字段或提交空行。
@@ -102,7 +116,7 @@ dws oa approval detail --instance-id <processInstanceId> --format json
## 考勤审批套件
请假与补卡沿用本文件的单次写入、最终预测、摘要确认和写后回读规则。模板不支持 CLI 时,展示 `+get-approve-template` 返回的全部可用模板及 `[formName](submitUrl)`,由用户在客户端提交;不得只给一个猜测的推荐项。
请假、补卡、外出与加班沿用本文件的单次写入、最终预测、摘要确认和写后回读规则。模板不支持 CLI 时,展示 `+get-approve-template` 返回的全部可用模板及 `[formName](submitUrl)`,由用户在客户端提交;不得只给一个猜测的推荐项。
### 请假:DDHolidayField
@@ -124,7 +138,26 @@ dws oa approval detail --instance-id <processInstanceId> --format json
5. 按 [补卡套件](oa/oa-form-components.md#ddbizsuite--attendancesupply补卡套件) 组装子控件 `id/name/value/extValue`。`value` 按 Schema 的 format 格式化;`extValue` 使用选定计划的 `planId/planTip/planText/workDate/supplyDate`,不得猜测班次数据。
6. 用最终 `--request` 重新预测,处理自选节点;展示摘要后停止,得到对当前摘要的明确确认才执行同一条创建调用,并在执行时动态追加确认参数。
请假、补卡任一最终字段、部门或人员发生变化,都必须重新 `forecast-process`。写成功后的验收只读 `detail/tasks/records`,不能再次创建。
请假、补卡、外出、加班任一最终字段、部门或人员发生变化,都必须重新 `forecast-process`。写成功后的验收只读 `detail/tasks/records`,不能再次创建。
请假与补卡的详细规则(类型澄清、时间格式、班次匹配、payload 组装细则、话术与确认硬约束)见 [oa/oa-leave.md](oa/oa-leave.md)「发起请假审批」与 [oa/oa-supply.md](oa/oa-supply.md)「发起补卡审批」;本文件浓缩闭环与详细工作流冲突时以详细版为准。
### 外出:DDBizSuite · attendance.goout
1. `dws attendance +get-approve-template --type travel --format json` 获取模板(出差是 `--type out`,注意分流);多模板时全量展示并让用户选。
2. `form-schema` 下钻 `DDBizSuite`(`bizType=attendance.goout`)子控件;外出类型 option 的 `extension.unit` 决定有效单位与时长格式。
3. 有同行人时先经 `dws attendance +check-companion-schedules --approve-type 2` 校验班次(`valid=false` 原样转告并停止)。
4. `dws attendance +calculate-approve-duration --biz-type 2 --approve-biz-type attendance.goout` 计算服务端权威时长;返回值原样保留,不得本地估算。
5. 按 [外出套件](oa/oa-form-components.md#ddbizsuite--attendancegoout外出套件) 的展平形态与映射表组装子控件条目(traveler value 用 userId JSON 数组字符串)。
6. 完整工作流、有效单位判定与组装细则见 [oa/oa-goout.md](oa/oa-goout.md)「发起外出审批」。
### 加班:DDBizSuite · attendance.batchovertime
1. `dws attendance +get-approve-template --type overtime --format json` 获取模板;无 `everyDayDuration` 的旧版模板降级 `submitUrl` 链接引导。
2. `attendance +get-complex-overtime-setting --users <加班人>` 校验动态单位(`reason` 非空即停止转告);`interactMode` 决定 `--duration-mode`。
3. `dws attendance +calculate-approve-duration --biz-type 1 --new-overtime` 计算时长;歧义窗口(班中起始/跨天)按两阶段确认传逐日明细,**时长结果须经用户手动确认后方可组装发起**。
4. 按 [加班套件](oa/oa-form-components.md#ddbizsuite--attendancebatchovertime加班套件) 的容器包裹形态组装子控件条目(与外出/补卡的展平形态相反)。
5. 完整工作流、时长计算口径与组装细则见 [oa/oa-overtime.md](oa/oa-overtime.md)「发起加班审批」。
## 流程预测与选人
@@ -155,6 +188,29 @@ dws oa approval create-instance --request '{"processCode":"PROC-xxx","deptId":12
若不需要高级字段,优先使用 `--process-code`、`--form-values` 和可选 `--approvers`、`--cc-list`,减少手写请求结构。
## 交互优化原则
> **核心目标:流程清晰,步骤有序,避免重复询问。**
1. **先查 Schema 再收集表单值:** `form-schema` 后先展示控件列表,再一次性收集全部表单值;未拿到 Schema 前不得问用户填什么。
2. **流程预测后再选自选审批人:** `forecast-process` 后先展示完整流程路径(各节点与处理人);对 `targetSelect: true` 节点提示「节点「{activityName}」需要您自选{actorType}人」,用 `dws aisearch person --query "<姓名>" --dimension name --format json` 帮用户查找并选人;多个自选节点一次性收集,禁止逐个询问。
3. **单次汇总确认:** 发起前一次性展示模板名称、各控件值、预测审批路径、各节点审批人/抄送人(含自选选人结果),并遵守:
- **单选确认**:一个单选问题(如「确认发起 / 取消发起」),完整汇总置于问题或选项描述中一并展示;附属决策(如非必填自选节点是否留空)须在确认前收集或按默认值并入汇总,禁止拆成多个并列问题。
- **零括号主干形态**:汇总主干只写字段名与核心值,禁止括号内描述——模板编码、userId、多选/服务端裁决/窗口类型/通道验收等技术细节不入正文,选项描述同样不加括号尾注(写「加 --yes 真实提交」不写「加 --yes 真实提交(服务端已验证)」);技术证据留档于命令字符串、临时文件或技术报告。示例:「模板:加班-new / 加班人:文疏、公 元yt / 时间:2026-09-01 21:00 → 23:00 / 时长:每人 2.00 小时」
- **空条目控件不进汇总**:汇总只展示有业务值的控件;服务端自动处理、以空条目组装的控件(如加班补偿自动配置)不展示该字段,技术结论需告知时另用说明句,不与表单值并列
4. **开放信息统一收集(请假/外出起止范围,请假/补卡/外出/加班事由):**
- **时间范围(请假与外出;补卡时刻由意图词与班次推导,不走此交互)**:按天计 → 日期即全天,无需此问;按半天/小时计且用户未限定上/下午/时刻时,问「全天 / 仅上午 / 仅下午」,按有效单位展示口径(小时计 → 全天 09:00→18:00、仅上午 09:00→12:00、仅下午 12:00→18:00;半天计 → 全天上午至下午、仅上午/仅下午),须保留自定义起止时刻通道;跨多天时起止日分别确定口径;选项时刻仅为示意,以用户实际班次为准;禁止默认全天。
- **事由/理由**:常见快捷选项 + **必须有自由输入通道**(不得只给选项变相预筛),命中即用、未命中自由输入。常见选项:请假(身体不适/家中有事/处理私事)、补卡(忘记打卡/考勤设备故障/外出办公未打卡)、外出(拜访客户/参加会议/外勤办事)、加班(赶项目进度/客户需求/临时任务)。
- **纯对话环境**(无选择组件):退化为文本提问并结束回合等用户输入,属合规模式;但半天/小时计的时间范围仍须明确问,禁止默认全天。
- **话术硬约束**:选项与提问一律纯中文,技术字段与英文枚举不进入用户可见文案。
5. **选择澄清优先(交互形态硬约束):** 凡有离散选项或预设取值的澄清与确认(模板、类型/班次、时间范围、加班逐日时长、事由等),宿主有选择交互组件时必须用**选择澄清**(快捷预设 + 「其他」自由输入),禁止退化为纯文本 `___` 填空;仅纯对话宿主才用文本提问。快捷预设只是加速项,不得变相预筛或替代用户裁决。
**反例(禁止):** 未查 Schema 就问表单值;预测后逐个节点询问选人;确认前直接发起;半天/小时计未问时间范围默认全天;发起确认拆成多个并列问题;汇总或选项描述夹带括号内技术描述(如「加班人(userId)」);宿主有选择组件时把时长/事由等离散澄清退化为纯文本填空。
## 执行前确认
一次性展示:
@@ -0,0 +1,88 @@
# 创建和更新审批模板
本文件包含模板创建(`template create`)、更新(`template update`)的完整参数说明、控件/节点/规则参考索引、`--from-document` 文档模式以及同名冲突处理。查询模板列表和模板详情仍在 [oa.md](oa.md) 中。
## 逐项参数模式
```bash
dws oa approval template create --name '出差申请' --schema-content @form.json --format json
dws oa approval template detail --process-code PROC-EXAMPLE --format json
dws oa approval template update --process-code PROC-EXAMPLE --name '出差申请' --schema-content @form.json --process-config @process.json --format json
```
- `create` 调用 `oa/create_process_template`,逐项参数模式必填 `--name`、`--schema-content`。不传 `--process-config` 时创建包含发起人节点、一个审批人节点和一个抄送人节点的默认流程;不传 `--visible-range` 时全员可见。
- `update` 调用 `oa/update_process_template`,逐项参数模式必填 `--process-code`、`--name`、`--schema-content`、`--process-config`。更新前必须读取 `template detail`,基于返回配置修改并保留已有控件 `props.id`,每个流程节点包含 `nodeId`。更新接口不接受 `--expected-version`;该数值参数仅创建接口可选。
- `--schema-content`、`--process-config` 输入 JSON 对象,但以 JSON **字符串**发送给 MCP。`--form-config`、`--node-config`、`--condition-rule` 同样以 JSON 字符串发送。这些参数支持直接 JSON、`@文件` 或 `-` 标准输入;一次命令只能有一个参数读取标准输入。
- `--plugin-configs`、`--visible-range` 接收对象数组 JSON,`--manager-user-ids` 接收字符串数组 JSON,支持相同文件/标准输入方式;MCP 接收到数组而非字符串。显式 `[]` 保留并提交,不等同于未传。
- 其他可选参数:`--description`、`--icon-url`、`--static-workflow`(`0` 动态 / `1` 静态)、`--append-enable`(`y` / `n`)、`--duplicate-removal`(字符串 `true` / `false`)。更新不传可选字段时沿用原配置;显式空描述或空图标字符串会提交给服务端。
- 两个写命令支持 `--dry-run`,仅做本地校验并展示请求参数,返回 `executed=false`,不调用 MCP。
- 成功通过统一输出 `data.processCode` 返回模板编码;服务端 `success=false` 或非零错误码作为失败输出,保留错误码及错误信息。创建/更新后再次读取 `template detail` 核对实际状态,不将本地 Schema 查询当作业务验证。
## 流程节点审批人默认规则
构造 `processConfig` 时,如果用户没有明确指定审批人类型,审批节点的选人规则默认使用**部门主管**(`target_management`,`level: 1`),而不是直属主管(`target_formula` / `reportLineManager`)。大部分审批流程使用的是部门主管。只有用户明确要求直属主管直属领导汇报线主管时才使用直属主管规则。详见 [rules/target_management.md](oa/template/rules/target_management.md)。
## 详细控件 / 节点 / 规则参考(构造 schemaContent 与 processConfig 时按需读取)
构造 `--schema-content` 和 `--process-config` 的 JSON 结构时,按需加载以下参考文档。**不要一次性预读全部控件/节点文档**——先看总览确定需要的控件类型或节点类型,再按 `componentName` 或节点类型定位单个文件。
| 需要了解 | 参考文档 | 说明 |
|---------|---------|------|
| 控件总览与表单顶层结构 | [form-components.md](oa/template/form-components.md) | 38 种控件分类、`schemaContent` 顶层字段、控件通用字段、约束速查 |
| 某个具体控件的 props 结构与示例 | [components/\<ComponentName\>.md](oa/template/components/) | 如 `TextField.md`、`DDSelectField.md`、`TableField.md` 等,共 31 个 |
| 流程节点总览与 processConfig 树结构 | [process-nodes.md](oa/template/process-nodes.md) | 节点类型、嵌套树结构、节点通用字段、选人规则总览、约束速查 |
| 某类节点(审批人/抄送/条件/并行等) | [nodes/\<node\>.md](oa/template/nodes/) | 如 `approver.md`、`cc.md`、`condition.md`、`parallel.md` 等,共 7 个 |
| 审批人选人规则 | [rules/\<rule\>.md](oa/template/rules/) | 如 `target_management.md`、`target_label.md`、`target_managers_labels.md` 等,共 10 个 |
| 完整表单示例 | [example/form_components.json](oa/template/example/form_components.json) | 包含多种控件的报销申请表单 |
| 完整流程示例 | [example/process_config.json](oa/template/example/process_config.json) | 包含多级审批、条件分支、抄送的流程树 |
| 生成控件唯一 ID | `python3 scripts/generate_form_component_id.py <ComponentType>` | 输出格式 `{ComponentName}_{随机字符串}` |
| 生成节点唯一 ID | `python3 scripts/generate_node_id.py` | 输出格式 `{4位hex}_{4位hex}` |
## 从完整 JSON 文档创建或更新模板
`--from-document` 接收本地普通 JSON 文件的**绝对路径**(不加 `@`,最大 4 MiB),不需要模型服务。文件顶层使用 MCP 参数名;不接受自由文字描述、未知字段、重复顶层字段或 `null`。
`/绝对路径/template.json` 示例:
```json
{
"name": "出差申请",
"description": "员工出差申请",
"schemaContent": {
"title": "出差申请",
"items": [
{
"componentName": "TextField",
"props": {"id": "TextField-reason", "label": "出差事由", "required": true}
}
]
},
"processConfig": {
"type": "start",
"name": "发起人",
"nodeId": "sid-startevent",
"properties": {}
}
}
```
```bash
dws oa approval template create --from-document /绝对路径/template.json --dry-run --format json
dws oa approval template create --from-document /绝对路径/template.json --format json
dws oa approval template update --process-code PROC-EXAMPLE --from-document /绝对路径/template.json --dry-run --format json
```
- 创建文档必填 `name`、`schemaContent`;更新文档还需 `processConfig`,以及文档中的 `processCode` 或单独的 `--process-code`。同时提供两处编码时必须一致。
- `schemaContent`、`processConfig` 可以写成对象或已有 JSON 字符串,CLI 统一发送为 MCP 要求的 JSON 字符串;其他 JSON 配置字段也会转换为 JSON 字符串。`pluginConfigs`、`visibleRange` 必须是对象数组,`managerUserIds` 必须是字符串数组。
- `staticWorkflow` 使用字符串 `"0"`/`"1"`,`appendEnable` 使用 `"y"`/`"n"`,`duplicateRemoval` 使用字符串 `"true"`/`"false"`;`expectedVersion` 仅创建文档可用,必须是数值。
- 文档模式与逐项配置参数互斥,只有更新的 `--process-code` 可以同时使用。未传可选字段保持省略,显式空描述、空图标和空数组原样提交。
- `schemaContent.items` 必须是控件数组,每个控件包含 `componentName` 和唯一 `props.id`;流程中的 `childNode`/`conditionNodes` 节点须有 `type` 和唯一 `nodeId`。这些结构问题在调用 MCP 前报错。
- 更新文档前先读取真实 `template detail`,基于原配置修改并保留已有控件 ID;CLI 不会根据 JSON 中缺少的信息推测业务需求。`--dry-run` 只读取本地文件并展示最终请求,不调用 MCP。
## 创建时的同名模板处理
名称唯一性由 create_process_template 校验,不预查模板列表。若 MCP 返回同名错误,明确告知创建失败,让用户选择重新命名后创建、更新已有模板或取消创建。不得自行追加名称后缀重试,也不得自动切换为更新。选择更新后再定位已有模板并读取 template detail,保留已有字段 ID 和未修改配置;错误未返回 processCode 时不得编造。
`--dry-run` 不调用创建 MCP,不能证明名称可用。其他错误保留服务端原因,不得一律判为同名冲突。
创建 MCP 返回 `dingOpenErrcode=810001` 表示同名冲突,`810002` 表示模板数量达到上限。数量超限应由用户清理无效模板、联系管理员调整容量,或选择更新已有模板/取消创建;不能通过改名解决,也不得自动删除模板。CLI 保留服务端错误码和文案,不自动重试。
@@ -10,8 +10,9 @@
| 同意、拒绝、转交、评论、追加抄送、撤销 | 本文件足够;遇到错误再按 shared 契约读取对应错误 reference |
| 发起审批、预测流程、组装表单字段 | 继续读 [oa-create.md](oa-create.md);按其中条件加载控件和节点 reference |
| 下载链接、下载/预览授权、上传审批附件 | 继续读 [oa-attachments.md](oa-attachments.md) |
| 创建审批模板、更新审批模板、模板 JSON 文档模式 | 继续读 [oa-template-write.md](oa-template-write.md);按其中索引加载控件和节点 reference |
不要为普通查询预读创建、控件、节点或附件全文。
不要为普通查询预读创建、控件、节点、附件或模板写入全文。
## 角色来源是对象身份的一部分
@@ -178,3 +179,7 @@ dws oa approval list-by-admin --process-code <processCode> --start "<ISO-8601>"
|---|---|---|
| `dws oa +search-forms` | read | 按关键字模糊搜索当前用户可见的审批表单 |
<!-- VISIBLE_SHORTCUTS_END -->
### 创建和更新模板路由
用户要创建或更新审批模板时,继续读取 [oa-template-write.md](oa-template-write.md)。不要凭本文件直接组装 `--schema-content` 或 `--process-config`。
@@ -301,8 +301,8 @@
| 属性 | 说明 |
|------|------|
| `componentName` | `TableField` |
| value 格式 | JSON 数组字符串,每个元素为一行数据的键值对 |
| 示例 | `'[{"商品名":"笔记本","数量":"2"},{"商品名":"钢笔","数量":"1"}]'` |
| value 格式 | JSON 序列化的二维数组字符串;每行是子控件 name/value 对象数组 |
| 示例 | `'[[{"name":"商品名","value":"笔记本"},{"name":"数量","value":"2"}],[{"name":"商品名","value":"钢笔"},{"name":"数量","value":"1"}]]'` |
| 约束 | **不可嵌套 TableField**;**不可包含 DDMultiSelectField 和 DDPhotoField**;最大 100 行;总长度不超过 65535 字符 |
模板结构(从 `form-schema` 获取):
@@ -317,17 +317,22 @@
}
```
提交时每行用子控件 label 作 key:
提交时 `value` 是 **JSON 序列化的二维数组字符串**:外层数组表示所有明细行,每行是子控件对象数组。子控件的 `name` 必须与其 `props.label` 完全一致,`value` 按对应控件格式填写字符串(数字控件也使用数字字符串):
```json
{
"name": "采购明细",
"value": "[{\"商品名\":\"笔记本\",\"数量\":\"2\"},{\"商品名\":\"钢笔\",\"数量\":\"1\"}]"
"value": "[[{\"name\":\"商品名\",\"value\":\"笔记本\"},{\"name\":\"数量\",\"value\":\"2\"}],[{\"name\":\"商品名\",\"value\":\"钢笔\"},{\"name\":\"数量\",\"value\":\"1\"}]]"
}
```
`--form-values` 的顶层仍是“字段 label → 字符串值”的对象;上面的 `value` 字符串作为其中“采购明细”的值。使用 `--request` 时,将上面的控件对象放入 `formComponentValues` 列表。两种入口都原样传递明细字符串,**不会把以 label 为 key 的行对象数组自动转换为二维 name/value 数组**。建议用 JSON 序列化器生成字符串,避免手动转义。
格式依据:[钉钉官方创建审批实例文档](https://open.dingtalk.com/document/orgapp/create-an-approval-instance.md)中的“表格(明细)控件”。
### DDHolidayField(请假套件)
> **支持通过 leave-duration / leave-check 命令链发起**,完整工作流见 [oa-create.md](../oa-create.md) 的“请假:DDHolidayField”。识别特征:`componentName == "DDHolidayField"`,`props.label` 为数组(如 `["开始时间","结束时间"]`),`props.options` 为假期类型选项列表。
> **支持通过 leave-duration / leave-check 命令链发起**,完整工作流见 [oa-leave.md](oa-leave.md)「发起请假审批」。识别特征:`componentName == "DDHolidayField"`,`props.label` 为数组(如 `["开始时间","结束时间"]`),`props.options` 为假期类型选项列表。
模板 Schema 结构(从 `form-schema` 获取,关键字段):
```json
@@ -392,11 +397,11 @@ extValue = JSON.stringify({
> **IMPORTANT:**
> - 时长、detailList、compressedValue 一律取自 `dws attendance approve leave-duration` 的服务端计算结果,严禁本地构造或估算;不支持手动改时长(customDuration)。
> - 发起前必须先跑 `dws attendance approve leave-check` 提交前校验(--duration-day / --duration-hour 取自 leave-duration 输出);success=false 时转告 errorMsg 并终止。
> - 哺乳假模板(类型条目 bizType === "breastfeeding_leave_new";bizType 缺失时回退名称含「哺乳」)与需上传证明材料的请假类型(类型条目 leaveCertificate.enable=true 且时长达到阈值)**不支持 CLI 发起**,按 oa-create.md 的请假闭环引导用户在客户端提交。
> - 哺乳假模板(类型条目 bizType === "breastfeeding_leave_new";bizType 缺失时回退名称含「哺乳」)与需上传证明材料的请假类型(类型条目 leaveCertificate.enable=true 且时长双向换算小时后 ≥ 阈值,换算规则见 [oa-leave.md](oa-leave.md)「发起请假审批」步骤 3)**不支持 CLI 发起**,引导用户在客户端提交。
### DDBizSuite · attendance.supply(补卡套件)
> **支持通过 supply-plans / supply-check 命令链发起**,完整工作流见 [oa-create.md](../oa-create.md) 的“补卡:DDBizSuite · attendance.supply”。识别特征:`componentName == "DDBizSuite"` 且 `props.bizType == "attendance.supply"`;补卡时间子控件在 `children` 内(`DDDateField`,`bizAlias == "userCheckTime"`)。
> **支持通过 supply-plans / supply-check 命令链发起**,完整工作流见 [oa-supply.md](oa-supply.md)「发起补卡审批」。识别特征:`componentName == "DDBizSuite"` 且 `props.bizType == "attendance.supply"`;补卡时间子控件在 `children` 内(`DDDateField`,`bizAlias == "userCheckTime"`)。
模板 Schema 结构(从 `form-schema` 获取,需下钻 children):
```json
@@ -453,6 +458,120 @@ extValue = JSON.stringify({
---
### DDBizSuite · attendance.goout(外出套件)
> **支持通过 `+check-companion-schedules` / `+calculate-approve-duration` 命令链发起**,完整工作流见 [oa-goout.md](oa-goout.md)「发起外出审批」。识别特征:`componentName == "DDBizSuite"` 且 `props.bizType == "attendance.goout"`;子控件在 `children` 内(按 `bizAlias` 识别:`type` / `startTime` / `finishTime` / `duration` / `traveler`)。
模板 Schema 结构(从 `form-schema` 获取,需下钻 children):
```json
{
"componentName": "DDBizSuite",
"props": {
"bizType": "attendance.goout", "bizAlias": "goout", "extract": true,
"unit": "day",
"childFieldVisible": {"traveler": true, "type": true},
"id": "DDBizSuite_2YVW4KTZ17SW", "label": "外出"
},
"children": [
{"componentName": "DDSelectField", "props": {"bizAlias": "type", "id": "DDSelectField_...", "label": "外出类型", "required": true,
"options": [{"value": "外出类型2", "key": "option_...", "extension": {"unit": "halfDay"}}]}},
{"componentName": "DDDateField", "props": {"bizAlias": "startTime", "id": "DDDateField_...", "label": "开始时间", "required": true}},
{"componentName": "DDDateField", "props": {"bizAlias": "finishTime", "id": "DDDateField_...", "label": "结束时间", "required": true}},
{"componentName": "NumberField", "props": {"bizAlias": "duration", "id": "NumberField_...", "label": "时长", "required": true, "disable": true}},
{"componentName": "InnerContactField", "props": {"bizAlias": "traveler", "id": "InnerContactField_...", "label": "同行人", "required": false, "max": 30, "choice": "1"}}
]
}
```
**有效单位判定**:`childFieldVisible.type≠false` 且 options 非空 → 选定 option 的 `extension.unit`(day/halfDay/hour);type 不可见(options 为空数组)→ 套件 `props.unit`。有效单位决定 startTime/finishTime 的 value 格式与 `+calculate-approve-duration` 的 `--duration-mode`(day→1,halfDay→2 + `--half-start/--half-end`,hour→3)。
提交条目结构(**extract=true 展平形态**:条目是子控件而非 DDBizSuite 容器;**必须走 `create-instance --request` 高级模式**):
| 条目 | value | extValue |
|------|-------|----------|
| type(可见时) | option 显示值(如「外出类型2」) | **重组对象** JSON 字符串:`{"label":<option.value>,"key":<option.key>,"extension":<option.extension>}`——键名是 `label` 而非 option 中的 `value`,禁止原样序列化 option 对象 |
| startTime / finishTime | 有效单位格式(day → `yyyy-MM-dd`;halfDay → `yyyy-MM-dd 上午/下午`;hour → `yyyy-MM-dd HH:mm`) | 无 |
| duration | 数字:有效单位=hour → durationInHour,否则 durationInDay | 时长计算响应**按下方映射表转换后**的 JSON 字符串 + `"_from"`/`"_to"`(= 起止 value) |
| traveler(可见且有同行人时) | **userId JSON 数组字符串** `"[\"uid1\",\"uid2\"]"` | `[{"emplId":uid,"name":姓名,"avatar":"","itemId":uid}]` JSON 字符串(avatar 可空) |
duration extValue 映射(`+calculate-approve-duration` 响应(`data.value`)→ extValue 结构):
| extValue 字段 | 来源 | 转换 |
|---|---|---|
| `durationInDay` / `durationInHour` | 响应同名字段 | 字符串转数字("0.50" → 0.5) |
| `isModifiable` | 响应 `modifiable` | 改名 |
| `unit` | 响应 `durationUnit` | 改名 |
| `pushTag` / `extension` | — | 固定 `""` / `"{\"tag\":\"\"}"` |
| `detailList[].approveInfo` | `detailList[].features` | `fromTime=applyFromTime`、`toTime=applyToTime`、`durationInDay/durationInHour` 转数字、`fromAcross/toAcross` 取 classSections 的 startAcross/endAcross |
| `detailList[].classInfo` | `detailList[]` + `features` | `hasClass` 平移、`name=className`、`sections=classSections`(剔除 durationMins)、`restSections=[]` |
| `detailList[].isRest` / `workTimeMinutes` / `workDate` | `detailList[]` / `features` | isRest 取 features.isRest,其余平移 |
| `compressedValue` | 响应同名字段 | 原样(禁止解析/改写) |
| `_from` / `_to` | — | 附加,= 起止条目的 value 原样 |
> **IMPORTANT:**
> - `bizAlias` 不组装(MCP formComponentValues 无此字段,服务端按 id 匹配);**不构造 DDBizSuite 容器条目**(extract=true 展平);控件 id 必须当次 form-schema 实时取(模板改版即失效,套件外控件 id 可能即中文 label)。
> - **traveler 的 value 必须是 userId 的 JSON 数组字符串**(姓名显示值经 MCP 通道会触发服务端系统错误);服务端回读时将 value 规范化为逗号连接 userId 串。
> - 时长、detailList、compressedValue 一律以 `+calculate-approve-duration`(**--biz-type 2 --approve-biz-type attendance.goout**;--biz-type 5 报业务错误 C0002)服务端计算为准,**严禁本地估算/手改**(不支持 customDuration);duration 的 value 提交数字(detail 回读为字符串属服务端归一化)。
> - 有同行人时必须先经 `+check-companion-schedules --approve-type 2` 校验:`valid=false` → 原样转告 title/alertInfo + 冲突同行人(userIds),剔除后重试。
> - 外出模板常见必选自选审批人节点:forecast 返回 `workflowActivityRuleVOs[].targetSelect=true` 且 `required=true` 时**必须选人**组装 `targetSelectActioners`(缺失时服务端拒绝创建);组装字段为 **actionerKey**(= 本次 forecast 的 `workflowActor.actorKey`)+ **actionerStaffIds**(userId)——字段名误写为 activityId/actionerUserIds 会创建成功但流转挂起(tasks 返回空 taskIdList);一切以当次 forecast 返回为准。
### DDBizSuite · attendance.batchovertime(加班套件)
> 加班套件支持 CLI 组装提交,完整工作流见 [oa-overtime.md](oa-overtime.md)「发起加班审批」。识别特征:`componentName == "DDBizSuite"` 且 `props.bizType == "attendance.batchovertime"`;子控件在 `children` 内(按 `bizAlias` 识别:`partner` / `startTime` / `finishTime` / `everyDayDuration` / `duration` / `compensation`)。
模板 Schema 结构(从 `form-schema` 获取,需下钻 children;无 everyDayDuration 的旧版模板降级 submitUrl 引导):
```json
{
"componentName": "DDBizSuite",
"props": {
"bizType": "attendance.batchovertime", "bizAlias": "overtime",
"unit": "hour",
"id": "DDBizSuite_5ZJ2V5MOR4OW", "label": "加班",
"push": {"pushTag": "加班"}, "childFieldVisible": {"partner": true, "type": true, "punchDetails": false}
},
"children": [
{"componentName": "DDSelectField", "props": {"bizAlias": "type", "invisible": true}},
{"componentName": "InnerContactField", "props": {"bizAlias": "partner", "id": "InnerContactField_...", "label": "加班人", "required": true}},
{"componentName": "DDDateField", "props": {"bizAlias": "startTime", "id": "DDDateField_...", "label": "开始时间", "required": true}},
{"componentName": "DDDateField", "props": {"bizAlias": "finishTime", "id": "DDDateField_...", "label": "结束时间", "required": true}},
{"componentName": "TableField", "props": {"bizAlias": "everyDayDuration", "id": "TableField_...", "label": "明细",
"children": [
{"componentName": "DDDateField", "props": {"bizAlias": "overtimeDate", "id": "DDDateField_...", "label": "加班时间"}},
{"componentName": "NumberField", "props": {"bizAlias": "overtimeDuration", "id": "NumberField_...", "label": "加班时长"}}
]}},
{"componentName": "NumberField", "props": {"bizAlias": "duration", "id": "NumberField_...", "label": "总时长", "required": true}},
{"componentName": "DDSelectField", "props": {"bizAlias": "compensation", "id": "DDSelectField_...", "label": "加班补偿", "hidden": true}}
]
}
```
**有效单位判定**:`+get-complex-overtime-setting --users <加班人>` 响应 `interactMode`(1=day / 2=halfDay / 3=hour)优先;与模板 `props.unit` 不一致时以 interactMode 为准(单位错配时清空重填,CLI 无该联动——必须先校验再收集)。`reason` 非空 = 该员工组禁止加班,原样转告并终止。
提交条目结构(**容器包裹形态**:schema 无 extract,提交 DDBizSuite 容器条目,value = JSON.stringify(children 条目数组);与补卡/外出的展平形态相反——先例不可跨类型推用;**必须走 `create-instance --request` 高级模式**):
容器条目:`{"id":<套件 props.id>,"name":<套件 props.label>,"value":"<children stringify>","extValue":""}`
**子字段可见性过滤(childFieldVisible,DDBizSuite 组件级通用)**:组装 children 前先读套件 `props.childFieldVisible`——某 bizAlias 值 `=== false` 时该子控件**不收集、不组装条目**(组件构造期 filter 直接过滤、不创建字段实例,不渲染不提交)。**仅 `=== false` 生效,缺 key 或 true 均为显示**;与控件级 invisible/hidden 并存,任一命中即不组装。`partner=false` → 模板无加班人字段:不组装 partner 条目、不支持代提交/批量(加班人即发起人);`type=false` / `partnerTip=false` / `punchDetails=false` 与既有不组装口径一致(type invisible 派生、TextNote/打卡明细纯展示)。各模板配置不同(如加班-new 为 `{"partner":true,"punchDetails":false,"type":true}`),以当次 form-schema 为准。
children 条目(位于容器 value 字符串内部,`key`=子控件 props.id;extendValue 保持原生形态——partner 为原生数组、duration 为原生对象、TableField 为字符串):
| # | bizAlias | 构造规则 |
|---|----------|----------|
| 1 | partner | `{"key":<id>,"label":"加班人","value":"<姓名逗号连接>","bizAlias":"partner","extendValue":[{"avatar":"","emplId":<userId>,"name":<姓名>,"read":false,"readTime":0,"itemId":<userId>}]}`;姓名↔userId 经 aisearch person 同源解析;单/多选与上限以当次 form-schema partner props 为准 |
| 2/3 | startTime / finishTime | `{"key":<id>,"label":"开始时间"/"结束时间","value":<有效单位格式>,"bizAlias":"startTime"/"finishTime"}`;无 extendValue |
| 4 | everyDayDuration | 多天(跨度>1 天):value=stringify 行数组,行=`{"rowValue":[{overtimeDate 子条目},{"key":<overtimeDuration id>,"label":"加班时长","value":"<每日时长字符串>","bizAlias":"overtimeDuration"}],"rowNumber":"<TableField id>_<12位随机串>"}`,extendValue=`"{\"statValue\":[],\"componentName\":\"TableField\"}"`(字符串);单日省略本行。**多天明细随两阶段确认流程组装(流程见 [oa-overtime.md](oa-overtime.md) 步骤 6)**;rowNumber 形态 `<TableField id>_<12位随机串>`;overtimeDate.extendValue.status 可回填计算响应 detailList[].dayType(workDay/restDay/holiday),空串亦可 |
| 5 | duration | `{"key":<id>,"label":<多天="总时长"/单日=schema label>,"value":"<总时长字符串>","bizAlias":"duration","extendValue":{...时长计算响应按外出套件映射表转换后的字段集(非原样透传,见 IMPORTANT)...,"durationUnit":<有效单位>,"_from":<T1>,"_to":<T2>}}`;总时长取 durationInHour(hour)或 durationInDay(day/halfDay) |
| 6 | compensation | 时长计算响应 `overtimeRedressBy=="manual"` → 必选:`{"key":<id>,"label":"加班补偿","value":"转调休\|加班费","bizAlias":"compensation","extendValue":{"key":"vacation\|charge"}}`;否则空条目 `{"key":<id>,"label":"加班补偿","bizAlias":"compensation"}` |
> **IMPORTANT:**
> - children 内 `bizAlias` 照常携带(容器 value 字符串为同构形态,与展平形态「不组装 bizAlias」相反);控件 id 必须当次 form-schema 实时取。
> - 时长、detailList、compressedValue、featureMap 一律以 `+calculate-approve-duration --biz-type 1 --new-overtime` 服务端计算为准,严禁本地估算/手造;compressedValue 为服务端 gzip 签名,禁止解析改写。
> - 时长计算响应 → duration extendValue 的字段映射参照外出套件章节映射表(同一 calculate_approve_duration 工具),**禁止原样透传**:extendValue 必含非空 `unit`(映射自响应 `durationUnit`)、`durationInHour`、`durationInDay`、`compressedValue`,缺任一即拒「不合法的参数」;值类型不限。一阶段判歧义语义以 oa-overtime.md 步骤 6 为准(歧义窗口返回 durationInHour=0 + 逐日骨架)。
> - 与 H5 发起链路的已知差异(不补齐):H5 feature 层在计算响应上恒附加 `_overTimeApplyUserId`(加班人 uid,排查用途)随 duration extendValue 持久化;CLI 不组装该字段(服务端不依赖),PC 端同样不携带。
> - partner(InnerContactField)value 姓名形态可落库(姓名 value + emplId extValue);若姓名形态被丢弃/报错,改用 userId JSON 数组字符串,extendValue 保留姓名数组。
> - 明细级 `overtimeDurationStatus`(detailList[].approveInfo):0=回填 / 1=回填并提示 message / 2=该日禁止加班(置灰禁提交;CLI 应终止并转告 message)。CLI 时长以服务端计算为准,天然满足回填语义。
> - 提交侧对照注记(CLI 不组装):startTime/finishTime extendValue 可注入 `timeZoneInfo`(跨时区场景);`type` 加班类型多天按 detailList dayType 优先级(holiday>restDay>workDay)自动回填;`punchDetails` 打卡明细为纯展示组件(不收集不组装);duration 手改会写 extendValue.customDuration(CLI 禁止手改,不产生该字段);批量加班响应 `approveAlertInfo`(title/content/detailKey)为班次冲突提示,须原样转告。
## 未定义稳定格式的控件
以下控件可能出现在 `form-schema` 中,但当前 DWS Skill、CLI Schema 和可检索的官方开放平台资料没有提供经验证的稳定 value 契约。不要套用相似控件格式或用真实审批试探:
@@ -481,7 +600,7 @@ extValue = JSON.stringify({
> **部分支持的控件:** `DDPhotoField`(图片控件)**支持通过 URL 直接提交**,但不支持本地文件上传(CLI 未封装钉盘 CDN 上传流程)。若用户只有本地文件,需告知在钉钉客户端补充。详见本文 [DDPhotoField](#ddphotofield图片控件) 章节。
> **套件类控件(大部分暂不支持)** — `InvoiceField`(发票)、`RecipientAccountField`(收款账户)等业务套件控件当前暂不支持通过 CLI 发起,包含这些控件的审批模板请直接在钉钉客户端操作。**例外:`DDHolidayField`(请假套件)与 `DDBizSuite · attendance.supply`(补卡套件)已支持**,按上方章节与 [oa-create.md](../oa-create.md) 的考勤审批套件闭环发起。
> **套件类控件(大部分暂不支持)** — `InvoiceField`(发票)、`RecipientAccountField`(收款账户)等业务套件控件当前暂不支持通过 CLI 发起,包含这些控件的审批模板请直接在钉钉客户端操作。**例外:`DDHolidayField`(请假套件)、`DDBizSuite · attendance.supply`(补卡套件)、`DDBizSuite · attendance.goout`(外出套件)与 `DDBizSuite · attendance.batchovertime`(加班套件)已支持**,按上方章节与 [oa-leave.md](oa-leave.md) / [oa-supply.md](oa-supply.md) / [oa-goout.md](oa-goout.md) / [oa-overtime.md](oa-overtime.md) 工作流发起。
---
@@ -0,0 +1,60 @@
# 发起外出审批(外出套件 DDBizSuite · attendance.goout)
> **触发:** 用户说"外出/公出/提交外出/帮我提外出申请"等外出意图时,走本文档工作流(**不走 search-forms**);出差仍按 attendance 域 `+get-approve-template` 的提交链接引导(出差 = `--type out`,外出 = `--type travel`,注意分流);加班走 [oa-overtime.md](oa-overtime.md)「发起加班审批」。
## 工作流(步骤 1-7 外出特有;8-9 复用 [oa-create.md](../oa-create.md) 的「流程预测与选人 → 执行前确认 → 创建与写后验证」)
```
1.【模板定位】dws attendance +get-approve-template --type travel
→ 外出模板列表(formName / processCode / submitUrl)
· 单模板直接选定;多模板时必须交由用户选择,Agent 不得自行选定(按名称与"外出"匹配度排序仅影响展示顺序,不改变选择权);交互组件选项数上限 < 模板总数时改用纯文本/表格列出全量后由用户回复模板名
· 选项 label 用模板名称(formName)原文;描述文案须在开头完整呈现模板名称原文(直接以名称开头或「模板「名称」:说明」格式均可)——交互组件在不同环境下以 label 或描述作为用户可见主文案,名称须两处都出现,不得只存在于 label;描述其余部分仅作简体中文辅助说明,不得出现 attendance.goout、processCode 等技术标识
· 返回空 → 告知用户企业未配置可发起的外出模板
· submitUrl 仅作兜底(CLI 不支持的模板引导客户端提交)
2.【模板详情】dws oa approval form-schema --process-code <code>
→ 下钻 DDBizSuite(bizType=="attendance.goout"):
· children 子控件(按 bizAlias 识别):type(外出类型 DDSelectField)/ startTime / finishTime(DDDateField)/ duration(时长 NumberField)/ traveler(同行人 InnerContactField)
· 套件 props.childFieldVisible:type / traveler 可见性(false → 该控件不收集、不组装条目;type 不可见时 options 为空数组)
· 套件 props.unit:type 不可见时的回落时长单位
→ 确认套件外控件(如外出事由 TextareaField,是否必收以 form-schema 的 required 为准)
3.【收集外出类型】childFieldVisible.type≠false 且 options 非空时:
· 展示全部 options 供用户选择(选项格式:类型名称原文 + 按天/按半天/按小时 中文单位标注;unit 英文枚举不得进入用户话术);选定后**有效单位 = 该 option 的 extension.unit**
· 用户中途更换外出类型时:已收集的起止时间与时长全部作废,必须按新有效单位重新收集并重算(对齐客户端切换类型清空行为)
· type 不可见(options 为空)→ 不收集类型、不组装 type 条目,有效单位 = 套件 props.unit
4.【收集时间 + 同行人 + 事由】(时间与事由的收集交互见 [oa-create.md](../oa-create.md)「交互优化原则」第 4 条)
· 起止时间按有效单位收集(day → 日期;halfDay → 日期 + 上午/下午;hour → 日期 + 时刻)
· traveler 可见时可收集同行人(姓名用 dws aisearch person 解析为 userId,上限固定 30——客户端硬编码覆盖模板 max 配置);无同行人则跳过步骤 5、不组装 traveler 条目
· 外出事由等套件外控件按 required 收集
5.【同行人校验(有同行人时必做)】dws attendance +check-companion-schedules --approve-type 2 --starts <T1> --ends <T2> --principal-users <uid1,uid2> --duration-unit <DAY|HOUR>
· T1/T2:有效单位 hour → 精确时刻(yyyy-MM-dd HH:mm:ss);day/halfDay → 日期(yyyy-MM-dd)
· duration-unit:有效单位 hour → HOUR;day/halfDay → DAY
· valid=false → 原样转告 title/alertInfo + 冲突同行人(userIds),请用户剔除后重试;不得跳过校验直接发起
6.【时长计算】dws attendance +calculate-approve-duration --biz-type 2 --approve-biz-type attendance.goout --duration-mode <M> --start <T1> --end <T2> [--half-start AM|PM --half-end AM|PM]
· 外出固定 --biz-type 2 --approve-biz-type attendance.goout(--biz-type 5 不可用,报业务错误 C0002)
· 有效单位 → --duration-mode:day → 1;halfDay → 2(必须同时传 --half-start/--half-end,上午=AM、下午=PM);hour → 3(--start/--end 传 "yyyy-MM-dd HH:mm:00")
→ durationInHour / durationInDay / detailList / compressedValue(服务端权威,禁止本地估算)
7.【组装条目】展平子控件条目(extract=true,无容器条目;bizAlias 不组装,服务端按 id 匹配):
· type(可见时):{"id":子控件id,"name":"外出类型","value":"<option 显示值>","extValue":<重组 JSON 字符串 {"label":<option.value>,"key":<option.key>,"extension":<option.extension>}——键名是 label 而非 option 中的 value,禁止原样序列化 option 对象>}
· startTime / finishTime:{"id":子控件id,"name":"开始时间"/"结束时间","value":<有效单位格式>}
· duration:{"id":子控件id,"name":"时长","value":<数字:有效单位=hour → durationInHour,否则 durationInDay>,"extValue":<步骤 6 响应按 oa-form-components.md 外出套件映射表转换后的 JSON 字符串 + "_from"和"_to"(= 起止 value),禁止原样透传>}
· traveler(可见且有同行人时):{"id":子控件id,"name":"同行人","value":"<userId JSON 数组字符串>","extValue":<[{"emplId":uid,"name":姓名,"avatar":"","itemId":uid}] JSON 字符串>}
—— value 必须是 userId 的 JSON 数组字符串(如 "[\"uid1\",\"uid2\"]");姓名显示值会触发服务端系统错误
· 套件外控件条目(如 {"id":"外出事由","name":"外出事由","value":"…"},控件 id 以当次 form-schema 为准,可能即中文 label)
8.【流程预演(必选)】forecast-process --request —— 外出模板常见必选自选审批人节点(required=true 时缺 targetSelectActioners 会被服务端拒绝);自选结果组装字段为 actionerKey(取自本次 forecast 的 workflowActor.actorKey,禁止跨模板/跨流程复用)+ actionerStaffIds(userId);字段名写成 activityId/actionerUserIds 会创建成功但流转挂起(tasks 返回空 taskIdList)
9.【选人 + 确认 + 发起】复用 [oa-create.md](../oa-create.md) 的「流程预测与选人 → 执行前确认 → 创建与写后验证」:自选节点选人(targetSelectActioners 并入 payload)
→ 汇总确认(外出类型 + 起止时间 + 时长 + 同行人 + 事由 + 流程路径 + 审批人)→ create-instance --request '<组装后的完整 JSON>'
```
有效单位与命令参数对照:
| 有效单位 | 条目 value 格式 | +calculate-approve-duration 参数 |
|---|---|---|
| day | yyyy-MM-dd | --duration-mode 1 --start <日期> --end <日期> |
| halfDay | yyyy-MM-dd 上午/下午 | --duration-mode 2 --start <日期> --end <日期> --half-start AM\|PM --half-end AM\|PM |
| hour | yyyy-MM-dd HH:mm | --duration-mode 3 --start "<日期> HH:mm:00" --end "<日期> HH:mm:00" |
> **IMPORTANT:** 时长、detailList、compressedValue 一律以 `+calculate-approve-duration` 服务端计算为准,严禁本地估算或手改(不支持手改时长);外出套件为 extract=true 展平形态,不构造 DDBizSuite 容器条目;步骤 8/9 必须走 `--request` 高级模式。
模板不支持 CLI 发起时的 `submitUrl` 兜底与链接展示规范,见 [oa-create.md](../oa-create.md)「考勤审批套件」章节的 submitUrl 引导规范。
字段级规范见 [oa-form-components.md](oa-form-components.md) 的 DDBizSuite · attendance.goout(外出套件)章节。
@@ -0,0 +1,54 @@
# 发起请假审批(请假套件 DDHolidayField)
> **触发:** 用户说"请假/请X天假/请年假/请事假/请病假/提交请假"等请假意图时,走本文档工作流(**不走 search-forms**);补卡走 [oa-supply.md](oa-supply.md)「发起补卡审批」;外出走 [oa-goout.md](oa-goout.md)「发起外出审批」;出差仍按 attendance 域 `+get-approve-template` 的提交链接引导;加班走 [oa-overtime.md](oa-overtime.md)「发起加班审批」。
## 工作流(步骤 1-8 请假特有;9-10 复用 [oa-create.md](../oa-create.md) 的「流程预测与选人 → 执行前确认 → 创建与写后验证」)
```
1.【模板定位】dws attendance +get-approve-template --type leave
→ 请假模板列表(formName / processCode / submitUrl)
· 单模板直接选定;多模板时必须交由用户选择,Agent 不得自行选定(按用户假期词匹配 formName 排序仅影响展示顺序,不改变选择权);交互组件选项数上限 < 模板总数时改用纯文本/表格列出全量后由用户回复模板名
· 选项 label 用模板名称(formName)原文;描述文案须在开头完整呈现模板名称原文(直接以名称开头或「模板「名称」:说明」格式均可)——交互组件在不同环境下以 label 或描述作为用户可见主文案,名称须两处都出现,不得只存在于 label;描述其余部分仅作简体中文辅助说明,不得出现 bizType、processCode 等技术标识
· 返回空 → 告知用户企业未配置可发起的请假模板
· submitUrl 仅作兜底(CLI 不支持的模板引导客户端提交)
2.【模板详情】dws oa approval form-schema --process-code <code>
→ 识别 DDHolidayField(componentName)+ props.options(leaveCode/unit/name)+ 其余控件(请假事由等)
· 无 DDHolidayField → 降级普通表单流程(简单模式 --form-values 发起,无需步骤 5/6)
3.【先类型】dws attendance approve leave-types(--user 可选,缺省当前用户;代提交用其 userId)
· 自动匹配:用户已明确类型词时匹配返回的 leaveName,唯一命中直接用
· 无类型词、未命中或含糊 → 展示全部可用类型供选择,不预筛子集;选项格式:【类型名称】 (剩余 X 天/小时),X 取 balance.remainQuota,单位取 quotaUnit 中文映射(day/halfDay→天、hour→小时);无余额对象或 balanceHidden=true 时不追加括号(不展示“余额不可见”类文案);选中后剩余≤0 → 提示「你的XX余额已用完」并终止,按 X 计(X 取 leaveViewUnit 中文映射);面向用户的展示一律用中文文案,不得出现 hour/halfDay/day 等英文枚举;「全部」是硬约束:交互组件选项数上限 < 类型总数时,禁止挑“代表性子集”,必须放弃该组件改用纯文本/表格列出全量后由用户回复类型名;选项主标识必须是【类型名称】原文,不得截断、省略或被余额/状态描述取代
· 类型一经确定,leaveCode 取自同一条目(与 leaveName 同源)
· 哺乳假判定:类型条目 bizType === "breastfeeding_leave_new" → 明确拒绝并引导客户端(用步骤 1 的 submitUrl);bizType 缺失时回退名称含「哺乳」;证明材料判定:leaveCertificate(enable/unit/duration/promptInformation)在 leave-types 响应中直接返回;enable=true 时步骤 5 拿到时长后**双向换算为小时**比较——阈值:leaveCertificate.unit=day → duration×24、hour → duration 原值;用户时长:unit ∈ {hour,halfHour,limitHour} → durationInHour 原值(**不乘 24**)、day/halfDay → durationInDay×24;时长 ≥ 阈值则同样拒绝并引导客户端
4.【再时间 + 事由】按选定类型的 leaveViewUnit 格式化起止时间;同时收集请假事由(按 form-schema 的 required 判定:必填则缺失必问,非必填未提供可跳过);时间范围与事由的收集交互见 [oa-create.md](../oa-create.md)「交互优化原则」第 4 条
5.【后时长】dws attendance approve leave-duration --leave-code <leaveCode> --start <T1> --end <T2>
→ durationInHour / durationInDay / detailList / compressedValue / corpId (服务端权威,禁止本地估算)
→ 粒度校验:unit=halfHour → durationInHour 须为 0.5 的倍数、unit=limitHour → 须为整数,不满足则提示「时长不符合单位要求」并终止
6.【提交前校验】dws attendance approve leave-check --leave-code … --process-code … --start <T1'> --end <T2'> --duration-day <D> --duration-hour <H>
· D/H 必须取自步骤 5 输出;T1'/T2' 为时刻转换后的值(day:起 00:00/止 23:59;halfDay 上午:起 00:00/止 12:00,下午:起 12:00/止 23:59;hour/halfHour/limitHour 原样)
· success=false → 原样转告 errorMsg 并终止,不得跳过重试
7.【组装 value】value = [T1, T2, duration, unit, leaveName, attendTypeLabel](JSON 数组字符串)
· unit / leaveName = 步骤 3 选定类型的 leaveViewUnit / leaveName 原始值(中文映射不写入)
· duration = unit ∈ {hour, halfHour, limitHour} ? durationInHour : durationInDay
· attendTypeLabel = 套件 props.attendTypeLabel,无则取 props.push.pushTag + "类型",均无为 ""
8.【组装条目】套件条目 {"id": props.id, "name": JSON.stringify(label 数组)(如 "[\"开始时间\",\"结束时间\"]"), "value": 六元数组字符串, "extValue": extendValue字符串}
+ 其余控件条目(如 {"name":"请假事由","value":"…"})
· extendValue = JSON.stringify({...步骤5响应, key: leaveCode, leaveParams: [corpId, leaveCode, T1, T2, staffId]})
· corpId 取步骤 5 响应回显;本人发起 staffId=null
9.【流程预演(可选;模板含必选自选审批人节点时必做)】forecast-process --request(required=true 时缺 targetSelectActioners 会被服务端拒绝;高级模式:套件条目无法用 --form-values 简单模式承载;--request 下 formComponentValues 与 create-instance 同形态即可,无需手动包二维,实测兼容)
10.【选人 + 确认 + 发起】复用 [oa-create.md](../oa-create.md) 的「流程预测与选人 → 执行前确认 → 创建与写后验证」:自选节点选人(targetSelectActioners 并入 payload)
→ 汇总确认(表单值 + 流程路径 + 审批人)→ create-instance --request '<组装后的完整 JSON>'
```
时间格式(与模板 unit 硬绑定):
| unit | T1/T2 格式 | duration 取值 |
|---|---|---|
| hour / halfHour / limitHour | yyyy-MM-dd HH:mm | durationInHour |
| day | yyyy-MM-dd | durationInDay |
| halfDay | yyyy-MM-dd 上午/下午 | durationInDay(0.5 粒度) |
> **IMPORTANT:** 时长、detailList、compressedValue 一律以 `leave-duration` 服务端计算为准,严禁本地估算或手改(不支持 customDuration);简单模式 `--form-values` 无法承载套件条目(value 为数组、含 extValue),步骤 9/10 必须走 `--request` 高级模式。
模板不支持 CLI 发起(哺乳假、需上传证明材料等)时的 `submitUrl` 兜底与链接展示规范,见 [oa-create.md](../oa-create.md)「考勤审批套件」章节的 submitUrl 引导规范。
字段级规范(id/name/value/extValue 组装细则与不支持边界)见 [oa-form-components.md](oa-form-components.md) 的 DDHolidayField 章节。
@@ -0,0 +1,62 @@
# 发起加班审批(加班套件 DDBizSuite · attendance.batchovertime)
> **触发:** 用户说"加班/提交加班/帮我提加班申请/代XX提交加班"等加班意图时。**时长计算**:calculate_approve_duration 支持 durationInHour/durationInDay/detailList/modifiedDate 入参(CLI 暴露 --duration-in-hour/--duration-in-day/--detail-list/--modified-date)——歧义窗口(班中起始/跨天)传 --detail-list 逐日明细可算(服务端按逐日求和、采信提议值不裁决截断),无歧义窗口服务端可自算。**时长结果须经用户手动确认**。
## 工作流(时长计算结果须经用户手动确认。步骤 1-8 加班特有,9-10 复用 [oa-create.md](../oa-create.md) 的「流程预测与选人 → 执行前确认 → 创建与写后验证」)
```
1.【模板定位】dws attendance +get-approve-template --type overtime
→ 加班模板列表(formName / processCode / submitUrl)
· 单模板直接选定;多模板时必须交由用户选择,Agent 不得自行选定(选项 label 与描述规范同请假/补卡/外出:label 用模板名称原文、描述开头完整呈现模板名称原文)
· 返回空 → 告知用户企业未配置可发起的加班模板
· submitUrl 仅作兜底(CLI 不支持的模板引导客户端提交)
2.【模板详情】dws oa approval form-schema --process-code <code>
→ 下钻 DDBizSuite(bizType=="attendance.batchovertime";schema 无 extract → 容器包裹提交,与补卡/外出展平形态相反):
· 套件 props:id(容器条目 id 主键)/ label / unit(模板静态单位,可被步骤 4 动态单位覆盖)/ childFieldVisible(子字段可见性过滤:某 bizAlias 值 === false → 该子控件不收集不组装;仅 === false 生效,缺 key 即显示;规则详见 [oa-form-components.md](oa-form-components.md) 加班套件章节)
· children 子控件(按 bizAlias 识别):partner(加班人 InnerContactField,单/多选与上限以当次 form-schema props 为准)/ startTime / finishTime(DDDateField)/ everyDayDuration(TableField 多天明细,含 overtimeDate + overtimeDuration 两子控件)/ duration(总时长 NumberField)/ compensation(加班补偿 DDSelectField,manual 补偿时必选)
· invisible/hidden/纯展示控件不收集、不组装条目:type 加班类型(多天按 detailList dayType 优先级 holiday>restDay>workDay 自动回填,CLI 不组装)、partnerTip、punchDetails 打卡明细(纯展示)
→ 无 everyDayDuration 明细组件 → 旧版模板,降级 submitUrl 引导
→ 确认套件外控件(如加班原因 TextField,required 以当次 form-schema 为准)
3.【收集加班人】默认本人;代提交/批量经 dws aisearch person 解析为 userId;单/多选与上限以当次 form-schema partner props 为准;套件 `childFieldVisible.partner===false` → 模板无加班人字段:跳过收集、不组装 partner 条目(仅发起人本人),代提交/批量意图直接告知该模板不支持
4.【单位校验(必做)】dws attendance +get-complex-overtime-setting --users <加班人 uid[,uid...]> [--work-date yyyy-MM-dd]
→ interactMode:1=day / 2=halfDay / 3=hour = 有效单位;与模板 props.unit 不一致时以本结果为准(起止格式、时长取值字段随之切换)并告知用户「单位按员工组规则生效」
· reason 非空 → 该员工组禁止加班,原样转告并终止,不重试
· workDate 语义=加班日期(初始为当前日 0 点,选定起止后为起始日 0 点)
5.【收集时间 + 事由】起止时间按有效单位收集(day → 日期;halfDay → 日期 + 上午/下午;hour → 日期 + 时刻;事由收集交互见 [oa-create.md](../oa-create.md)「交互优化原则」第 4 条的事由/理由规范)
· 支持多日加班:跨度上限 7 天(前端按跨度拦截、服务端按时长 ≤7 天),超出提示拆分;多日逐日时长经步骤 6 两阶段确认收集
6.【时长计算(两阶段确认)】dws attendance +calculate-approve-duration --biz-type 1 --new-overtime --duration-mode <M> --start <T1> --end <T2> [--half-start AM|PM --half-end AM|PM] [--principal-users <uid,...>]
· **时长计算口径**:歧义窗口(班中起始/跨天需逐日拆分)必须携带 --detail-list 逐日明细(JSON 数组,逐项 workDate 为毫秒 number——字符串形态会被服务端静默忽略返回 durationInHour=0,CLI 透传前统一归一化)+ durationInHour|durationInDay;服务端按逐日求和为总时长(总时长字段透传但不参与计算),--duration-in-hour(hour)/--duration-in-day(day/halfDay)与 --modified-date 可选携带;**服务端直接采信逐日提议值、不做裁决截断**——逐日值必须来自用户手动确认;无歧义窗口(整段班次外单日)服务端可自算成功(--start/--end 须完整秒级 HH:mm:ss),自算结果同样必须经下方硬约束由用户手动确认
· 加班固定 --biz-type 1 --new-overtime;--duration-mode 由有效单位决定(day→1;halfDay→2 必须同传 --half-start/--half-end;hour→3,--start/--end 传 "yyyy-MM-dd HH:mm:00")
· 一阶段(起止确定后调用):无歧义窗口服务端自算成功(durationInHour/detailList/compressedValue 齐备);歧义窗口(班中起始/跨天)不带 --detail-list 时服务端返回 durationInHour=0 + 逐日骨架(detailList 给出 workDate/班次段/逐日起止窗),不报错——判歧义依据为「durationInHour=0 且窗口跨天/班中起始」→ 进入多日确认
· **时长必须经用户手动确认(硬约束)**:一阶段结果(自算时长或逐日骨架)必须向用户完整展示(数值 + 单位中文口径,多日含逐日明细),经用户显式确认或输入逐日时长后方可进入二阶段与组装;禁止静默采信服务端结果直接组装提交;用户有异议 → 回步骤 5 重新收集时间并重新计算
· **时长确认的交互形态**:遵循 [oa-create.md](../oa-create.md)「交互优化原则」第 5 条选择澄清优先(宿主有组件时用选择澄清,禁止退化为纯文本填空)。
· 多日确认:一阶段判定跨天 → 向用户展示逐日骨架并由用户**手动确认/输入每天加班时长**(选择权在用户,交互形态见上条)→ 二阶段调用(--duration-in-hour/--duration-in-day=用户确认总时长(按有效单位选)+ --detail-list=逐日明细 JSON,逐项 workDate 为 yyyy-MM-dd HH:mm:ss 字符串或毫秒时间戳,CLI 归一化为毫秒透传)由服务端确认——服务端采信逐日提议值、不裁决截断
· 单日确认:一阶段判定单日 → 向用户展示服务端计算时长并由用户**手动确认/修改** → 二阶段调用(duration=确认值)确认
· --principal-users 不传时服务端默认按发起人计算(本人发起不传);代提交/批量必传全量加班人;响应 excludePrincipalUserIds 非空 → 转告被排除人员,用户确认后以剩余人员继续
· 响应外层 overtimeDurationStatus≠0 → 原样转告 message 并终止;userMessage 非空 → 并入汇总确认展示
· 响应 approveAlertInfo(班次冲突 title/content/detailKey)非空 → 原样转告;明细级 detailList[].approveInfo.overtimeDurationStatus:0=回填 / 1=回填并提示 message / 2=该日禁止加班 → 终止并转告
→ durationInHour / durationInDay / detailList / compressedValue / featureMap(服务端权威,禁止本地估算或手造)
7.【补偿方式】步骤 6 响应 overtimeRedressBy=="manual" → 请用户选转调休 / 加班费;否则跳过;manual 但用户弃选 → 终止(required)。发起前汇总仅在 manual 选值时展示补偿方式;空条目(服务端自动配置)不展示该字段
8.【组装条目】容器包裹形态(与补卡/外出展平相反;字段级规范见 [oa-form-components.md](oa-form-components.md) 加班套件章节):
· 容器条目:{"id":套件 props.id,"name":套件 props.label,"value":<JSON.stringify(children 条目数组)>,"extValue":""}
· children 按字段规范组装:partner / startTime / finishTime / duration(value=总时长字符串,hour → durationInHour,否则 durationInDay)/ compensation 按步骤 7
· 套件外控件(如加班原因)按通用规则组装
9.【流程预演(必选)】forecast-process --request(必选自选审批人节点 required=true 时缺 targetSelectActioners 会被服务端拒绝;组装字段为 actionerKey + actionerStaffIds)
10.【选人 + 确认 + 发起】复用 [oa-create.md](../oa-create.md) 的「流程预测与选人 → 执行前确认 → 创建与写后验证」 → 汇总确认(加班人 + 起止时间 + 时长 + 事由 + 流程路径 + 审批人;补偿方式仅在 manual 选值时列入)→ create-instance --request '<组装后的完整 JSON>'
```
有效单位与命令参数对照:
| 有效单位(interactMode) | 起止条目 value 格式 | +calculate-approve-duration 参数 |
|---|---|---|
| day(interactMode=1) | yyyy-MM-dd | --duration-mode 1 --start <日期> --end <日期> |
| halfDay(interactMode=2) | yyyy-MM-dd 上午/下午 | --duration-mode 2 --start <日期> --end <日期> --half-start AM\|PM --half-end AM\|PM |
| hour(interactMode=3) | yyyy-MM-dd HH:mm | --duration-mode 3 --start "<日期> HH:mm:00" --end "<日期> HH:mm:00" |
> **IMPORTANT:**
> - 加班套件为**容器包裹**形态(schema 无 extract):容器条目 value=stringify(children),与补卡/外出的展平形态相反,先例不可跨类型推用。
> - 时长、detailList、compressedValue 一律以 `+calculate-approve-duration --biz-type 1 --new-overtime` 服务端计算为准,严禁本地估算/手改;**任何来源的时长结果都必须经用户手动确认(步骤 6 硬约束),未确认不得进入组装与发起**;服务端采信逐日提议值、不做裁决截断。
模板不支持 CLI 发起时的 `submitUrl` 兜底与链接展示规范,见 [oa-create.md](../oa-create.md)「考勤审批套件」章节的 submitUrl 引导规范。
字段级规范见 [oa-form-components.md](oa-form-components.md) 的 DDBizSuite · attendance.batchovertime(加班套件)章节。
@@ -0,0 +1,48 @@
# 发起补卡审批(补卡套件 DDBizSuite · attendance.supply)
> **触发:** 用户说"补卡/忘打卡/补打卡/帮我补上次的卡"等补卡意图时,走本文档工作流(**不走 search-forms**);外出走 [oa-goout.md](oa-goout.md)「发起外出审批」;出差仍按 attendance 域 `+get-approve-template` 的提交链接引导;加班走 [oa-overtime.md](oa-overtime.md)「发起加班审批」。
## 工作流(步骤 1-7 补卡特有;8-9 复用 [oa-create.md](../oa-create.md) 的「流程预测与选人 → 执行前确认 → 创建与写后验证」)
```
1.【模板定位】dws attendance +get-approve-template --type repair-check
→ 补卡模板列表(formName / processCode / submitUrl)
· 单模板直接选定;多模板时必须交由用户选择,Agent 不得自行选定(名称与“补卡”最匹配的通用模板排前仅影响展示顺序,不改变选择权);交互组件选项数上限 < 模板总数时改用纯文本/表格列出全量后由用户回复模板名
· 选项 label 用模板名称(formName)原文;描述文案须在开头完整呈现模板名称原文(直接以名称开头或「模板「名称」:说明」格式均可)——交互组件在不同环境下以 label 或描述作为用户可见主文案,名称须两处都出现,不得只存在于 label;描述其余部分仅作简体中文辅助说明,不得出现 bizType、processCode 等技术标识
· 返回空 → 告知用户企业未配置可发起的补卡模板
· submitUrl 仅作兜底(CLI 不支持的模板引导客户端提交)
2.【模板详情】dws oa approval form-schema --process-code <code>
→ 下钻 DDBizSuite(bizType=="attendance.supply")的 children 取子控件
DDDateField(bizAlias=="userCheckTime":id/format/label,format 默认 yyyy-MM-dd HH:mm)
→ 确认补卡理由控件(TextareaField,是否必收以 form-schema 的 required 为准);图片控件(DDPhotoField)一期跳过并提示客户端补充
3.【定位缺卡(可选)】用户未给时间 → dws attendance record get --user <userId> --date <某日>
(单日粒度,近 N 天按日循环查询)辅助定位缺卡时间
4.【班次匹配】dws attendance approve supply-plans --time "<yyyy-MM-dd HH:mm>"
· plans 空 → 转告"该时间无异常班次"并终止,不重试
· 单班次 → 展示 planTip 确认
· 多班次 → 列出 planTip 供用户选择;推荐项排序:① 意图词匹配(用户所说日期+上午/下午/上班/下班与候选 workDate/checkType 对应)② 异常班次就近(先过滤查询时刻落在 timeRange 内的候选,再取其中非 freeCheck 且 timeResult≠Normal 者按 |查询时刻−checkDateTime| 最小)③ 其余
· 意图词唯一命中时可自动选定,但选定 planTip 必须并入后续表单值/汇总确认显式展示供否决;无意图词、意图匹配不唯一、或 freeCheck 候选无 checkDateTime 可就近 → 必须手选(不得默认取首个)
· 话术硬约束:面向用户的班次澄清/确认一律只含意图词命中依据与最终补卡时刻(如「意图词(08-20 + 下午→下班)唯一命中;最终补卡时刻 08-20 18:00」),选项标签用 planTip 原文;planId、workDate、checkType、timeResult、freeCheck、timeRange 夹取等技术字段与英文枚举不得进入用户话术(交互组件描述同理)
· 硬底线:create-instance 前用户至少见过一次选定班次的 planTip——推荐排序只优化问的顺序,选定权始终在用户
· 选定班次的 supplyDate 越出其 timeRange[0]/[1] 时,夹取到最近边界作为最终补卡时刻,并告知用户修正后的时刻
5.【收集理由】按 form-schema 的 required 判定:必填则缺失必问,非必填未提供可跳过;收集交互见 [oa-create.md](../oa-create.md)「交互优化原则」第 4 条
6.【提交前校验】dws attendance approve supply-check --timestamp <最终补卡时刻>
· 最终补卡时刻 = 选定班次 supplyDate;越出 timeRange 时用步骤 4 的夹取值
· 多班次须选定后再校验:各候选 supplyDate 由服务端按班次微调、可能不同,校验值依赖选择结果(候选 supplyDate 全相同时校验结果才与选择无关)
· qualify=false → 原样转告 title/desc 并终止,不得跳过重试
7.【组装条目】套件子控件条目 {"id": 子控件props.id, "name": 子控件label,
"value": 按子控件 format 格式化最终补卡时刻, "extValue": JSON字符串}
· extValue = {planId?, planTip, planText, workDate, timeStamp(=workDate), userCheckTime(=最终补卡时刻)}
(timeZoneInfo 不本地拼接:可选字段,服务端 supply-plans 响应不含时区数据)
· bizAlias 不组装(MCP 通道无此字段,服务端按 id 匹配);不构造 repairCheckTime(服务端回填)
+ 理由条目 {"id": 理由控件id, "name": "补卡理由", "value": "<用户输入>"}
8.【流程预演(可选;模板含必选自选审批人节点时必做)】forecast-process --request(required=true 时缺 targetSelectActioners 会被服务端拒绝;高级模式:套件条目无法用 --form-values 简单模式承载;--request 下 formComponentValues 与 create-instance 同形态即可,无需手动包二维,实测兼容)
9.【选人 + 确认 + 发起】复用 [oa-create.md](../oa-create.md) 的「流程预测与选人 → 执行前确认 → 创建与写后验证」:自选节点选人(targetSelectActioners 并入 payload)
→ 汇总确认(表单值 + 流程路径 + 审批人)→ create-instance --request '<组装后的完整 JSON>'
```
> **IMPORTANT:** 班次匹配与资格判定一律以服务端(supply-plans / supply-check)为准;value 必须按子控件 `format` 格式化(禁硬编码);步骤 9 必须走 `--request` 高级模式。流程与选人无补卡特有逻辑,一律按 [oa-create.md](../oa-create.md) 的「创建闭环」与「流程预测与选人 → 执行前确认 → 创建与写后验证」执行。
模板不支持 CLI 发起(含图片控件需上传证据等)时的 `submitUrl` 兜底与链接展示规范,见 [oa-create.md](../oa-create.md)「考勤审批套件」章节的 submitUrl 引导规范。
字段级规范见 [oa-form-components.md](oa-form-components.md) 的 DDBizSuite(补卡套件)章节。
@@ -0,0 +1,29 @@
# 省市区 — `AddressField`
> 分类:增强控件
省市区三级地址选择。
## JSON Schema
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `componentName` | string | 是 | 固定值 `"AddressField"` |
| `props.id` | string | 是 | 唯一标识,格式 `AddressField_{随机字符串}` |
| `props.label` | string | 是 | 控件标题 |
| `props.required` | boolean | 否 | 是否必填,默认 false |
| `props.needDetail` | boolean | 否 | 是否需要详细地址输入,默认 false |
## 示例
```json
{
"componentName": "AddressField",
"props": {
"id": "AddressField_W3XUWOIN0V40",
"label": "省市区",
"required": false,
"needDetail": false
}
}
```
@@ -0,0 +1,52 @@
# 计算公式 — `CalculateField`
> 分类:增强控件
对表单内数值字段自动计算。
## JSON Schema
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `componentName` | string | 是 | 固定值 `"CalculateField"` |
| `props.id` | string | 是 | 唯一标识,格式 `CalculateField_{随机字符串}` |
| `props.label` | string | 是 | 控件标题 |
| `props.formula` | array | 是 | 计算公式(**必填,不能为空数组**),数组元素按顺序拼接,见下文「formula 结构」 |
| `props.placeholder` | string | 否 | 占位提示文字 |
| `props.notUpper` | string | 否 | `"0"` 显示大写金额,`"1"` 不显示 |
## 示例
```json
{
"componentName": "CalculateField",
"props": {
"id": "CalculateField_PIIZHXI39V40",
"label": "合计金额",
"formula": [
{ "id": "NumberField_UNITPRICE01" },
"*",
{ "id": "NumberField_QUANTITY01" }
],
"placeholder": "自动计算数值",
"notUpper": "0"
}
}
```
## formula 结构
`props.formula` 是一个**数组**,按顺序拼成一个四则运算表达式,元素共三种:
| 元素形式 | 说明 |
|---------|------|
| `{ "id": "<数值字段 props.id>" }` | 引用另一个数值型字段的值,只能引用 `NumberField` / `MoneyField` / `CalculateField` / `DiscountField`,且其 `id` **必须是本表单中已定义的控件 `props.id`**(不能引用自身) |
| 运算符字符串 | `"+"`、`"-"`、`"*"`、`"/"`、`"("`、`")"` |
| 数字字面量 | 如 `2`、`100`;小数点用 `"."` |
示例:“合计 = 单价 × 数量” → `[ { "id": "NumberField_UNITPRICE01" }, "*", { "id": "NumberField_QUANTITY01" } ]`。
## 约束
- `formula` **必填且不得为空数组**;公式必须能构成合法的数学表达式(括号配对、运算符不悬空)。
- `formula` 中引用的字段 `id` 必须是当前表单已存在的数值型控件 `id`(由脚本生成),**不得引用未定义或非数值型字段,也不能编造 id**。
@@ -0,0 +1,38 @@
# 级联/分类 — `CascadeField`
> 分类:增强控件
多层级联动选择,适用于产品分类、地区分类等。
## JSON Schema
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `componentName` | string | 是 | 固定值 `"CascadeField"` |
| `props.id` | string | 是 | 唯一标识,格式 `CascadeField_{随机字符串}` |
| `props.label` | string | 是 | 控件标题 |
| `props.placeholder` | string | 否 | 占位提示文字 |
| `props.require` | boolean | 否 | 是否必填 |
| `props.bizAlias` | string | 否 | 业务别名 |
| `props.dataSource` | object | 是 | 数据源配置 |
| `props.dataSource.type` | string | 是 | 数据源类型,如 `"db_table"` |
| `props.dataSource.target` | object | 是 | 数据源目标 |
## 示例
```json
{
"componentName": "CascadeField",
"props": {
"id": "CascadeField_1ZOPQ6ZRCPEO0",
"label": "产品分类",
"placeholder": "请输入",
"require": true,
"bizAlias": "",
"dataSource": {
"type": "db_table",
"target": { "sourceForm": "oa", "appId": "-4", "scene": "CascadeField_2829052" }
}
}
}
```
@@ -0,0 +1,29 @@
# 分栏 — `ColumnLayout`
> 分类:布局控件
将多个控件并排显示,通过 ratio 控制宽度比例。
## JSON Schema
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `componentName` | string | 是 | 固定值 `"ColumnLayout"` |
| `props.id` | string | 是 | 唯一标识,格式 `ColumnLayout_{随机字符串}` |
| `props.label` | string | 是 | 控件标题,默认 `"分栏"` |
| `props.notPrint` | string | 否 | 是否不打印,`"1"` 不打印 |
| `props.group` | array | 是 | 分栏分组,每组包含子控件 |
## 示例
```json
{
"componentName": "ColumnLayout",
"props": {
"id": "ColumnLayout_1U8IPGN6Q4ZK0",
"label": "分栏",
"notPrint": "1",
"group": []
}
}
```
@@ -0,0 +1,27 @@
# 附件 — `DDAttachment`
> 分类:增强控件
文件上传。
## JSON Schema
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `componentName` | string | 是 | 固定值 `"DDAttachment"` |
| `props.id` | string | 是 | 唯一标识,格式 `DDAttachment_{随机字符串}` |
| `props.label` | string | 是 | 控件标题 |
| `props.required` | boolean | 否 | 是否必填,默认 false |
## 示例
```json
{
"componentName": "DDAttachment",
"props": {
"id": "DDAttachment_1V6UJ230Q3NK0",
"label": "附件",
"required": false
}
}
```
@@ -0,0 +1,33 @@
# 日期 — `DDDateField`
> 分类:基础控件
选择单个日期。
## JSON Schema
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `componentName` | string | 是 | 固定值 `"DDDateField"` |
| `props.id` | string | 是 | 唯一标识,格式 `DDDateField_{随机字符串}` |
| `props.label` | string | 是 | 控件标题 |
| `props.placeholder` | string | 否 | 占位提示文字 |
| `props.required` | boolean | 否 | 是否必填,默认 false |
| `props.format` | string | 否 | 日期格式,如 `"yyyy-MM-dd"` |
| `props.unit` | string | 否 | 时间单位,如 `"天"` |
## 示例
```json
{
"componentName": "DDDateField",
"props": {
"id": "DDDateField_1OHVCWCN2YXS0",
"label": "日期",
"placeholder": "请选择",
"required": false,
"format": "yyyy-MM-dd",
"unit": "天"
}
}
```
@@ -0,0 +1,41 @@
# 日期区间 — `DDDateRangeField`
> 分类:基础控件
选择开始和结束日期,可自动计算时长。
## JSON Schema
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `componentName` | string | 是 | 固定值 `"DDDateRangeField"` |
| `props.id` | string | 是 | 唯一标识,格式 `DDDateRangeField_{随机字符串}` |
| `props.label` | array | 是 | 控件标题,格式 `["开始时间", "结束时间"]` |
| `props.placeholder` | string | 否 | 占位提示文字 |
| `props.required` | boolean | 否 | 是否必填,默认 false |
| `props.format` | string | 否 | 日期格式,如 `"yyyy-MM-dd"` |
| `props.duration` | boolean | 否 | 是否显示时长,默认 false |
| `props.durationLabel` | string | 条件必填 | 时长标签,如 `"时长"`。**当 `duration` 为 `true` 时必须存在且非空** |
| `props.unit` | string | 否 | 时间单位,如 `"天"` |
## 示例
```json
{
"componentName": "DDDateRangeField",
"props": {
"id": "DDDateRangeField_1VJ5F4XR8WHS0",
"label": ["开始时间", "结束时间"],
"placeholder": "请选择",
"required": false,
"format": "yyyy-MM-dd",
"duration": false,
"durationLabel": "时长",
"unit": "天"
}
}
```
## 约束
- **`duration` 与 `durationLabel` 联动**:当 `props.duration` 为 `true`(显示时长)时,**必须**同时提供非空的 `props.durationLabel`(如 `"时长"`)与 `props.unit`(如 `"天"`);缺失 `durationLabel` 会导致时长行无标题。`duration` 为 `false` 或未设置时,`durationLabel` 可省略。
@@ -0,0 +1,39 @@
# 多选框 — `DDMultiSelectField`
> 分类:基础控件
从预设选项中选择多项。
## JSON Schema
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `componentName` | string | 是 | 固定值 `"DDMultiSelectField"` |
| `props.id` | string | 是 | 唯一标识,格式 `DDMultiSelectField_{随机字符串}` |
| `props.label` | string | 是 | 控件标题 |
| `props.placeholder` | string | 否 | 占位提示文字 |
| `props.required` | boolean | 否 | 是否必填,默认 false |
| `props.spread` | boolean | 否 | 是否平铺展示选项,默认 false |
| `props.ratio` | number | 否 | 宽度比例 |
| `props.options` | array | 是 | 选项列表,每项含 `key` 和 `value`。`key` **必须为英文字符**,推荐用 `option`、`_` 与有序数字拼接(如 `option_0`、`option_1`);`value` 为选项显示文本 |
## 示例
```json
{
"componentName": "DDMultiSelectField",
"props": {
"id": "DDMultiSelectField_14QMZ4C98Y2K0",
"label": "多选框",
"placeholder": "请选择",
"required": false,
"spread": false,
"ratio": 50,
"options": [
{ "key": "option_0", "value": "选项1" },
{ "key": "option_1", "value": "选项2" },
{ "key": "option_2", "value": "选项3" }
]
}
}
```
@@ -0,0 +1,29 @@
# 图片 — `DDPhotoField`
> 分类:增强控件
图片上传,可选水印。
## JSON Schema
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `componentName` | string | 是 | 固定值 `"DDPhotoField"` |
| `props.id` | string | 是 | 唯一标识,格式 `DDPhotoField_{随机字符串}` |
| `props.label` | string | 是 | 控件标题 |
| `props.required` | boolean | 否 | 是否必填,默认 false |
| `props.watermark` | boolean | 否 | 是否添加水印,默认 false |
## 示例
```json
{
"componentName": "DDPhotoField",
"props": {
"id": "DDPhotoField_1YQDBCE4I1340",
"label": "图片",
"required": false,
"watermark": false
}
}
```
@@ -0,0 +1,39 @@
# 单选框 — `DDSelectField`
> 分类:基础控件
从预设选项中选择一项。
## JSON Schema
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `componentName` | string | 是 | 固定值 `"DDSelectField"` |
| `props.id` | string | 是 | 唯一标识,格式 `DDSelectField_{随机字符串}` |
| `props.label` | string | 是 | 控件标题 |
| `props.placeholder` | string | 否 | 占位提示文字 |
| `props.required` | boolean | 否 | 是否必填,默认 false |
| `props.spread` | boolean | 否 | 是否平铺展示选项,默认 false |
| `props.ratio` | number | 否 | 宽度比例 |
| `props.options` | array | 是 | 选项列表,每项含 `key` 和 `value`。`key` **必须为英文字符**,推荐用 `option`、`_` 与有序数字拼接(如 `option_0`、`option_1`);`value` 为选项显示文本 |
## 示例
```json
{
"componentName": "DDSelectField",
"props": {
"id": "DDSelectField_1KH2A2YCMOF40",
"label": "单选框",
"placeholder": "请选择",
"required": false,
"spread": false,
"ratio": 50,
"options": [
{ "key": "option_0", "value": "选项1" },
{ "key": "option_1", "value": "选项2" },
{ "key": "option_2", "value": "选项3" }
]
}
}
```
@@ -0,0 +1,31 @@
# 部门 — `DepartmentField`
> 分类:增强控件
选择企业部门。
## JSON Schema
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `componentName` | string | 是 | 固定值 `"DepartmentField"` |
| `props.id` | string | 是 | 唯一标识,格式 `DepartmentField_{随机字符串}` |
| `props.label` | string | 是 | 控件标题 |
| `props.placeholder` | string | 否 | 占位提示文字 |
| `props.required` | boolean | 否 | 是否必填,默认 false |
| `props.multiple` | boolean | 否 | 是否多选,默认 false |
## 示例
```json
{
"componentName": "DepartmentField",
"props": {
"id": "DepartmentField_13NBCWQ1OD8G0",
"label": "部门",
"placeholder": "请选择",
"required": false,
"multiple": false
}
}
```
@@ -0,0 +1,29 @@
# 外部联系人 — `ExternalContactField`
> 分类:增强控件
选择企业外部联系人。
## JSON Schema
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `componentName` | string | 是 | 固定值 `"ExternalContactField"` |
| `props.id` | string | 是 | 唯一标识,格式 `ExternalContactField_{随机字符串}` |
| `props.label` | string | 是 | 控件标题 |
| `props.placeholder` | string | 否 | 占位提示文字 |
| `props.required` | boolean | 否 | 是否必填,默认 false |
## 示例
```json
{
"componentName": "ExternalContactField",
"props": {
"id": "ExternalContactField_1VPC59AATTR40",
"label": "外部联系人",
"placeholder": "请选择",
"required": false
}
}
```
@@ -0,0 +1,72 @@
# 关联表单 — `FormRelateField`
> 分类:关联表单控件
关联其他审批模板的表单数据。
## JSON Schema
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `componentName` | string | 是 | 固定值 `"FormRelateField"` |
| `props.id` | string | 是 | 唯一标识,格式 `FormRelateField_{随机字符串}` |
| `props.label` | string | 是 | 控件标题 |
| `props.title` | string | 否 | 标题 |
| `props.required` | boolean | 否 | 是否必填,默认 false |
| `props.multi` | number | 否 | 是否多选,`0` 单选,`1` 多选 |
| `props.quote` | number | 否 | 是否引用,`1` 引用 |
| `props.extract` | boolean | 否 | 是否提取字段 |
| `props.displayExtract` | boolean | 否 | 是否展示提取字段 |
| `props.securityMode` | number | 否 | 安全模式 |
| `props.procType` | string | 否 | 流程类型,`"inner"` 内部 |
| `props.dataSource` | object | 是 | 数据源配置 |
| `props.dataSource.type` | string | 是 | 固定值 `"form"` |
| `props.dataSource.target.formCode` | string | 是 | 关联审批模板 processCode |
| `props.fields` | array | 否 | 关联字段列表 |
## 关键说明
- `dataSource.target.formCode` 指定关联的审批模板 processCode
- `fields` 中每个字段的 `_extractId` 为提取映射 ID,`_oriId` 为原始表单中的字段 ID
## 示例
```json
{
"componentName": "FormRelateField",
"props": {
"id": "FormRelateField_K8W2ZATWKWG0",
"label": "用车申请",
"title": "",
"required": false,
"multi": 0,
"quote": 1,
"extract": false,
"displayExtract": true,
"securityMode": 0,
"procType": "inner",
"dataSource": {
"type": "form",
"params": { "filter": "" },
"target": {
"appUuid": "",
"bizType": "",
"formCode": "TODO_FORM_CODE",
"appType": 0
}
},
"fields": [
{
"componentName": "TextField",
"props": {
"id": "TextField-IH4UNLKF",
"label": "申请部门",
"placeholder": "请输入",
"_extractId": "TextField_1U73ZYBTWCGW0",
"_oriId": "TextField-IH4UNLKF"
}
}
]
}
}
```
@@ -0,0 +1,29 @@
# 身份证 — `IdCardField`
> 分类:基础控件
身份证号码输入,自带格式校验。
## JSON Schema
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `componentName` | string | 是 | 固定值 `"IdCardField"` |
| `props.id` | string | 是 | 唯一标识,格式 `IdCardField_{随机字符串}` |
| `props.label` | string | 是 | 控件标题 |
| `props.placeholder` | string | 否 | 占位提示文字 |
| `props.required` | boolean | 否 | 是否必填,默认 false |
## 示例
```json
{
"componentName": "IdCardField",
"props": {
"id": "IdCardField_1JHL06H19U000",
"label": "身份证",
"placeholder": "请输入",
"required": false
}
}
```
@@ -0,0 +1,31 @@
# 联系人 — `InnerContactField`
> 分类:增强控件
选择企业内部成员。
## JSON Schema
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `componentName` | string | 是 | 固定值 `"InnerContactField"` |
| `props.id` | string | 是 | 唯一标识,格式 `InnerContactField_{随机字符串}` |
| `props.label` | string | 是 | 控件标题 |
| `props.placeholder` | string | 否 | 占位提示文字 |
| `props.required` | boolean | 否 | 是否必填,默认 false |
| `props.choice` | string | 否 | 选择模式,`"0"` 单选,`"1"` 多选 |
## 示例
```json
{
"componentName": "InnerContactField",
"props": {
"id": "InnerContactField_1U1MDQCY7DKW0",
"label": "联系人",
"placeholder": "请选择",
"required": false,
"choice": "0"
}
}
```
@@ -0,0 +1,38 @@
# 发票 — `InvoiceField`
> 分类:业务控件
发票信息采集与验真。
## JSON Schema
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `componentName` | string | 是 | 固定值 `"InvoiceField"` |
| `props.id` | string | 是 | 唯一标识,格式 `InvoiceField_{随机字符串}` |
| `props.label` | string | 是 | 控件标题 |
| `props.required` | boolean | 否 | 是否必填,默认 false |
| `props.bizAlias` | string | 否 | 业务别名 |
| `props.appId` | string | 是 | 应用 ID,固定 `"78641"` |
| `props.invoiceChecking` | string | 否 | 是否验真,`"true"` 验真 |
| `props.commonSetterConfig` | object | 否 | 通用配置 |
| `props.commonSetterConfig.paymentBeforeInvoice` | array | 否 | 付款方式,如 `["NO_INVOICE", "TODO_COLLECT"]` |
## 示例
```json
{
"componentName": "InvoiceField",
"props": {
"id": "InvoiceField_1E4UHFVGH2F",
"label": "发票",
"required": false,
"bizAlias": "",
"appId": "78641",
"invoiceChecking": "true",
"commonSetterConfig": {
"paymentBeforeInvoice": ["NO_INVOICE", "TODO_COLLECT"]
}
}
}
```
@@ -0,0 +1,31 @@
# 金额 — `MoneyField`
> 分类:增强控件
金额输入,自动显示大写金额。
## JSON Schema
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `componentName` | string | 是 | 固定值 `"MoneyField"` |
| `props.id` | string | 是 | 唯一标识,格式 `MoneyField_{随机字符串}` |
| `props.label` | string | 是 | 控件标题 |
| `props.placeholder` | string | 否 | 占位提示文字 |
| `props.required` | boolean | 否 | 是否必填,默认 false |
| `props.notUpper` | string | 否 | `"0"` 显示大写金额,`"1"` 不显示 |
## 示例
```json
{
"componentName": "MoneyField",
"props": {
"id": "MoneyField_ZZ6UVVOE5DS0",
"label": "金额(元)",
"placeholder": "请输入金额",
"required": false,
"notUpper": "0"
}
}
```
@@ -0,0 +1,31 @@
# 数字输入框 — `NumberField`
> 分类:基础控件
纯数字输入,适用于数量、天数等数值场景。
## JSON Schema
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `componentName` | string | 是 | 固定值 `"NumberField"` |
| `props.id` | string | 是 | 唯一标识,格式 `NumberField_{随机字符串}` |
| `props.label` | string | 是 | 控件标题 |
| `props.placeholder` | string | 否 | 占位提示文字 |
| `props.required` | boolean | 否 | 是否必填,默认 false |
| `props.ratio` | number | 否 | 宽度比例 |
## 示例
```json
{
"componentName": "NumberField",
"props": {
"id": "NumberField_1YSOWSQA4PKW0",
"label": "数字输入框",
"placeholder": "请输入数字",
"required": false,
"ratio": 50
}
}
```
@@ -0,0 +1,62 @@
# 身份证识别 — `OcrIdCardField`
> 分类:高级控件
OCR 识别身份证,通过 children 映射字段。
## JSON Schema
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `componentName` | string | 是 | 固定值 `"OcrIdCardField"` |
| `props.id` | string | 是 | 唯一标识,格式 `OcrIdCardField_{随机字符串}` |
| `props.label` | string | 是 | 控件标题 |
| `props.placeholder` | string | 否 | 占位提示文字 |
| `props.required` | boolean | 否 | 是否必填 |
| `props.type` | string | 是 | 固定值 `"ocr"` |
| `props.ocrType` | string | 是 | 固定值 `"idcard"` |
| `props.options` | array | 是 | OCR 识别字段列表,如 `["name", "idCardNo", "gender"]` |
| `children` | array | 是 | 映射子控件列表 |
## 关键机制
children 中每个控件的 `bizAlias` 与 `options` 数组一一对应,OCR 识别后自动映射填充。
## 示例
```json
{
"componentName": "OcrIdCardField",
"props": {
"id": "OcrIdCardField_OR42XF5T70W0",
"label": "身份证识别",
"placeholder": "识别出的信息会自动填充到表单",
"required": true,
"type": "ocr",
"ocrType": "idcard",
"options": ["name", "idCardNo", "gender"]
},
"children": [
{
"componentName": "TextField",
"props": {
"id": "TextField_1YF738771SPS0",
"label": "姓名",
"placeholder": "请输入",
"required": true,
"bizAlias": "name"
}
},
{
"componentName": "IdCardField",
"props": {
"id": "IdCardField_1IKTLPOOHTEO0",
"label": "身份证号码",
"placeholder": "请输入",
"required": true,
"bizAlias": "idCardNo"
}
}
]
}
```
@@ -0,0 +1,33 @@
# 通用文字识别 — `OcrTextField`
> 分类:高级控件
OCR 文字识别,自动填入表单。
## JSON Schema
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `componentName` | string | 是 | 固定值 `"OcrTextField"` |
| `props.id` | string | 是 | 唯一标识,格式 `OcrTextField_{随机字符串}` |
| `props.label` | string | 是 | 控件标题 |
| `props.placeholder` | string | 否 | 占位提示文字 |
| `props.required` | boolean | 否 | 是否必填,默认 false |
| `props.type` | string | 是 | 固定值 `"ocr"` |
| `props.ocrType` | string | 是 | OCR 类型,`"advanced"` 通用识别 |
## 示例
```json
{
"componentName": "OcrTextField",
"props": {
"id": "OcrTextField_G1X5Y19ENXC0",
"label": "通用文字识别",
"placeholder": "请输入",
"required": false,
"type": "ocr",
"ocrType": "advanced"
}
}
```
@@ -0,0 +1,31 @@
# 电话 — `PhoneField`
> 分类:基础控件
电话号码输入。
## JSON Schema
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `componentName` | string | 是 | 固定值 `"PhoneField"` |
| `props.id` | string | 是 | 唯一标识,格式 `PhoneField_{随机字符串}` |
| `props.label` | string | 是 | 控件标题 |
| `props.placeholder` | string | 否 | 占位提示文字 |
| `props.required` | boolean | 否 | 是否必填,默认 false |
| `props.mode` | string | 否 | 电话类型,`"phone"` 手机 |
## 示例
```json
{
"componentName": "PhoneField",
"props": {
"id": "PhoneField_V1XP8RQLOOW0",
"label": "电话",
"placeholder": "请输入",
"required": false,
"mode": "phone"
}
}
```
@@ -0,0 +1,29 @@
# 收款账户 — `RecipientAccountField`
> 分类:业务控件
选择收款账户信息。
## JSON Schema
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `componentName` | string | 是 | 固定值 `"RecipientAccountField"` |
| `props.id` | string | 是 | 唯一标识,格式 `RecipientAccountField_{随机字符串}` |
| `props.label` | string | 是 | 控件标题 |
| `props.placeholder` | string | 否 | 占位提示文字 |
| `props.required` | boolean | 否 | 是否必填,默认 false |
## 示例
```json
{
"componentName": "RecipientAccountField",
"props": {
"id": "RecipientAccountField_1SVC4LTF93MO0",
"label": "收款账户",
"placeholder": "请选择",
"required": true
}
}
```
@@ -0,0 +1,31 @@
# 关联审批单 — `RelateField`
> 分类:增强控件
关联其他已提交的审批单。
## JSON Schema
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `componentName` | string | 是 | 固定值 `"RelateField"` |
| `props.id` | string | 是 | 唯一标识,格式 `RelateField_{随机字符串}` |
| `props.label` | string | 是 | 控件标题 |
| `props.placeholder` | string | 否 | 占位提示文字 |
| `props.required` | boolean | 否 | 是否必填,默认 false |
| `props.notPrint` | string | 否 | 是否不打印,`"1"` 不打印 |
## 示例
```json
{
"componentName": "RelateField",
"props": {
"id": "RelateField_SD87LE56RVK0",
"label": "关联审批单",
"placeholder": "请选择",
"required": false,
"notPrint": "1"
}
}
```
@@ -0,0 +1,40 @@
# 流水号 — `SeqNumberField`
> 分类:高级控件
自动生成唯一流水号。
## JSON Schema
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `componentName` | string | 是 | 固定值 `"SeqNumberField"` |
| `props.id` | string | 是 | 唯一标识,格式 `SeqNumberField_{随机字符串}` |
| `props.label` | string | 是 | 控件标题 |
| `props.rule` | array | 是 | 流水号规则 |
| `props.rule[].type` | string | 是 | 规则类型:`"date"` 日期 / `"counter"` 计数器 |
| `props.rule[].value` | string/object | 是 | 日期格式或计数器配置 |
## 规则说明
- `type: "date"` — value 为日期格式字符串,如 `"YYYYMMDD"`
- `type: "counter"` — value 为对象:
- `start`: 起始值
- `length`: 位数
- `reset`: 重置周期,可选 `"year"` / `"month"` / `"day"` / `"never"`
## 示例
```json
{
"componentName": "SeqNumberField",
"props": {
"id": "SeqNumberField_2AX8EBLEVO6",
"label": "流水号",
"rule": [
{ "type": "date", "value": "YYYYMMDD" },
{ "type": "counter", "value": { "start": 1, "length": 8, "reset": "year" } }
]
}
}
```
@@ -0,0 +1,29 @@
# 手写签名 — `SignatureField`
> 分类:增强控件
手写签名采集。
## JSON Schema
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `componentName` | string | 是 | 固定值 `"SignatureField"` |
| `props.id` | string | 是 | 唯一标识,格式 `SignatureField_{随机字符串}` |
| `props.label` | string | 是 | 控件标题 |
| `props.required` | boolean | 否 | 是否必填,默认 false |
| `props.readFromLast` | boolean | 否 | 是否读取上次签名,默认 true |
## 示例
```json
{
"componentName": "SignatureField",
"props": {
"id": "SignatureField_2044ROW9EFZ40",
"label": "手写签名",
"required": false,
"readFromLast": true
}
}
```
@@ -0,0 +1,31 @@
# 评分 — `StarRatingField`
> 分类:增强控件
星级评分。
## JSON Schema
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `componentName` | string | 是 | 固定值 `"StarRatingField"` |
| `props.id` | string | 是 | 唯一标识,格式 `StarRatingField_{随机字符串}` |
| `props.label` | string | 是 | 控件标题 |
| `props.placeholder` | string | 否 | 占位提示文字 |
| `props.required` | boolean | 否 | 是否必填,默认 false |
| `props.limit` | number | 否 | 最大评分星数,默认 5 |
## 示例
```json
{
"componentName": "StarRatingField",
"props": {
"id": "StarRatingField_1APSCMZIEG000",
"label": "评分",
"placeholder": "请输入",
"required": false,
"limit": 5
}
}
```
Loaded 100 of 152 files, more files were not shown because too many files have changed in this diff. Show more