Files
陌渊 c7510cd1a1 fix(datasource): trim whitespace from batch IDs and fix result/processCode docs
- Add trimNonEmpty for --table-ids in +datasource-sync and --task-ids in
  +datasource-sync-status, matching the existing field-ids pattern
- Add 4 test cases: whitespace-only rejection and trim-through for both
- Fix usage guide: typical workflow and notes no longer equate result
  with processCode; correctly describe result as JSON to parse for
  approvals[].processCode/name/iconUrl/url
2026-08-21 16:19:43 +08:00

535 lines
36 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Copyright 2026 Alibaba Group
// 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
//
// http://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.
// This file declares the 7 datasource shortcuts for the aitable service:
// create / update / sync / sync-status / get-config / list-sources /
// get-fields. Each maps 1:1 onto a datasource MCP tool on the "aitable"
// server. datasource-type is passed through without CLI-side enum
// validation; source-config is validated as a JSON object but passed
// through as a raw string (MCP types it as string).
package aitable
import (
"fmt"
"github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/corecmd"
"github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/corecmd/contract"
"github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/shortcut"
)
// ─────────────────────────────────────────────────────────────
// datasource: 数据源同步管理(server: aitable)
// ─────────────────────────────────────────────────────────────
// DatasourceCreate 为指定 AI 表格创建数据源同步配置(create_datasource)。
var DatasourceCreate = shortcut.Shortcut{
Service: "aitable",
Command: "+datasource-create",
Product: serverMain,
Description: "为指定 AI 表格创建数据源同步配置,创建一张数据源表并触发首次全量同步。返回新建数据源表 ID 和同步任务 ID。",
Intent: "当用户需要将外部数据源(如审批数据)接入 AI 表格时使用。创建后返回的表 ID 可用于后续同步、更新配置或查询状态。",
Risk: shortcut.RiskWrite,
Safety: contract.SafetySpec{
Effect: "write", Risk: "medium",
Confirmation: "not_required", Idempotency: "non_idempotent",
},
Contract: corecmd.ContractDecl{
Identity: contract.ToolIdentitySpec{
ProductID: "aitable",
Name: "shortcut_datasource_create",
CanonicalPath: "aitable.shortcut_datasource_create",
CLIPath: "aitable +datasource-create",
PrimaryCLIPath: "aitable +datasource-create",
},
Description: "为指定 AI 表格创建数据源同步配置,创建一张数据源表并触发首次全量同步。返回新建数据源表 ID 和同步任务 ID。",
Interface: &contract.InterfaceSpec{
Mode: "composite",
Availability: "available",
Reason: "Reviewed built-in shortcut adapter: the executable CLI owns validation, optional multi-step orchestration, output projection, and confirmation; the complete command contract is not represented by one pinned MCP interface_ref.",
},
Selection: contract.SelectionSpec{
AgentSummary: "为指定 AI 表格创建数据源同步配置,创建一张数据源表并触发首次全量同步。返回新建数据源表 ID 和同步任务 ID。",
UseWhen: []string{"当用户需要将外部数据源(如审批数据)接入 AI 表格时使用。创建后返回的表 ID 可用于后续同步、更新配置或查询状态。"},
AvoidWhen: []string{
"目标 Base 已有数据源表且仅需更新配置时(改用 +datasource-update)",
"仅需触发已有数据源表的同步时(改用 +datasource-sync)",
},
Examples: []string{
`dws aitable +datasource-create --base-id BASE123 --datasource-type OA --source-config '{"processCode":"PROC-XXXX","name":"采购申请","dataType":"recent_time","recentDays":"30d","iconUrl":"https://example.com/icon.png","url":"https://example.com/oa"}'`,
`dws aitable +datasource-create --base-id BASE123 --datasource-type OA --source-config '{"processCode":"PROC-XXXX","name":"采购申请","dataType":"time_range","startDate":"2025-01-01","endDate":"2025-12-31","iconUrl":"https://example.com/icon.png","url":"https://example.com/oa"}' --auto`,
},
},
},
Flags: []shortcut.Flag{
{Name: "base-id", Type: shortcut.FlagString, Desc: "目标 Base ID(通过 +base-list / +base-search 获取)", Required: true},
{Name: "datasource-type", Type: shortcut.FlagString, Desc: "数据源类型,目前支持审批(OA)", Required: true},
{Name: "source-config", Type: shortcut.FlagString, Desc: "源配置 JSON 字符串。字段分为两类:须从 +datasource-list-sources 结果原样透传的字段(必填):processCode(审批流程编码)、name(展示名称)、iconUrl(图标 URL)、url(跳转链接);调用方自行设置的字段:dataType(必填,time_range/start_time/recent_time)、recentDays(dataType=recent_time 时有效,7d/30d/1y,默认 30d)、startDate(dataType=time_range/start_time 时有效,yyyy-MM-dd,默认 30 天前)、endDate(dataType=time_range 时有效,yyyy-MM-dd,默认当天)、keepRemovedFields(是否保留已删除字段,默认 false)。约定:syncAll 固定为 true;splitParentTableField 与 enableDataSyncOaDetailList 为下游内部字段,无需传入", Required: true},
{Name: "auto", Type: shortcut.FlagBool, Desc: "是否开启自动同步,默认 false;创建新数据源表时该字段始终下发给下游"},
{Name: "field-ids", Type: shortcut.FlagStringSlice, Desc: "需要同步的字段 ID 列表,不传时保持现有配置(创建时默认为全部字段)"},
{Name: "auto-sync-setting", Type: shortcut.FlagString, Desc: "自动同步频率配置 JSON 字符串,仅在 --auto=true 时生效。字段:syncType(必填,hourly=按小时间隔,scheduled=定时触发)、hourlyInterval(syncType=hourly 时必填,正整数小时)、scheduleType(syncType=scheduled 时必填,daily/weekly/monthly)、timeValue(syncType=scheduled 时必填,HH:mm)、selectedMonthDays(scheduleType=monthly 时必填,每月几号触发,1-31)、selectedWeekdays(scheduleType=weekly 时必填,每周哪几天触发,1=周一…7=周日)、skipNonWorkingDay(可选,默认 false)。不传时使用下游默认自动同步策略"},
},
Tips: []string{
`dws aitable +datasource-create --base-id BASE123 --datasource-type OA --source-config '{"processCode":"PROC-XXXX","name":"采购申请","dataType":"recent_time","recentDays":"30d","iconUrl":"https://example.com/icon.png","url":"https://example.com/oa"}'`,
`dws aitable +datasource-create --base-id BASE123 --datasource-type OA --source-config '{"processCode":"PROC-XXXX","name":"采购申请","dataType":"time_range","startDate":"2025-01-01","endDate":"2025-12-31","iconUrl":"https://example.com/icon.png","url":"https://example.com/oa"}' --auto`,
},
Execute: func(rt *shortcut.RuntimeContext) error {
if _, err := parseJSONObject("source-config", rt.Str("source-config")); err != nil {
return err
}
params := map[string]any{
"baseId": rt.Str("base-id"),
"datasourceType": rt.Str("datasource-type"),
"sourceConfig": rt.Str("source-config"),
}
params["auto"] = rt.Bool("auto")
if rt.Changed("field-ids") {
raw := rt.StrSlice("field-ids")
cleaned := trimNonEmpty(raw)
if len(cleaned) == 0 {
return fmt.Errorf("--field-ids 显式提供时不能为空,如需保持默认请勿传入")
}
params["fieldIds"] = cleaned
}
if rt.Changed("auto-sync-setting") {
v := rt.Str("auto-sync-setting")
if v == "" {
return fmt.Errorf("--auto-sync-setting 显式提供时不能为空,如需保持默认请勿传入")
}
if _, err := parseJSONObject("auto-sync-setting", v); err != nil {
return err
}
params["autoSyncSetting"] = v
}
data, err := rt.CallMCPData(serverMain, "create_datasource", params)
if err != nil {
return err
}
return rt.Output(data)
},
}
// DatasourceUpdate 更新已有数据源表的同步配置(update_datasource_config)。
var DatasourceUpdate = shortcut.Shortcut{
Service: "aitable",
Command: "+datasource-update",
Product: serverMain,
Description: "更新指定 AI 表格中已有数据源表的同步配置,支持更新源配置、自动同步开关和同步字段选择。更新后触发一次同步。仅适用于数据源表。",
Intent: "当用户需要修改已有数据源表的配置(如更换审批模板、调整同步字段、开关自动同步)时使用。",
Risk: shortcut.RiskWrite,
Safety: contract.SafetySpec{
Effect: "write", Risk: "medium",
Confirmation: "not_required", Idempotency: "non_idempotent",
},
Contract: corecmd.ContractDecl{
Identity: contract.ToolIdentitySpec{
ProductID: "aitable",
Name: "shortcut_datasource_update",
CanonicalPath: "aitable.shortcut_datasource_update",
CLIPath: "aitable +datasource-update",
PrimaryCLIPath: "aitable +datasource-update",
},
Description: "更新指定 AI 表格中已有数据源表的同步配置,支持更新源配置、自动同步开关和同步字段选择。更新后触发一次同步。仅适用于数据源表。",
Interface: &contract.InterfaceSpec{
Mode: "composite",
Availability: "available",
Reason: "Reviewed built-in shortcut adapter: the executable CLI owns validation, optional multi-step orchestration, output projection, and confirmation; the complete command contract is not represented by one pinned MCP interface_ref.",
},
Selection: contract.SelectionSpec{
AgentSummary: "更新指定 AI 表格中已有数据源表的同步配置,支持更新源配置、自动同步开关和同步字段选择。更新后触发一次同步。仅适用于数据源表。",
UseWhen: []string{"当用户需要修改已有数据源表的配置(如更换审批模板、调整同步字段、开关自动同步)时使用。"},
AvoidWhen: []string{
"需要创建新数据源表时(改用 +datasource-create)",
"仅需触发同步不改配置时(改用 +datasource-sync)",
},
Examples: []string{
`dws aitable +datasource-update --base-id BASE123 --table-id TBL456 --auto`,
`dws aitable +datasource-update --base-id BASE123 --table-id TBL456 --source-config '{"processCode":"PROC-YYYY","name":"出差申请","dataType":"recent_time","recentDays":"30d","iconUrl":"https://example.com/icon.png","url":"https://example.com/oa"}'`,
},
},
},
Flags: []shortcut.Flag{
{Name: "base-id", Type: shortcut.FlagString, Desc: "目标 Base ID", Required: true},
{Name: "table-id", Type: shortcut.FlagString, Desc: "已存在的数据源表 ID(通过 +base-get / +table-list 获取,仅允许传入 sync=true 的数据源表)", Required: true},
{Name: "source-config", Type: shortcut.FlagString, Desc: "可选。新的源配置 JSON 字符串。不传时保持原有配置不变;传入时整体覆盖。字段分为两类:须从 +datasource-list-sources 结果原样透传的字段(必填):processCode(审批流程编码)、name(展示名称)、iconUrl(图标 URL)、url(跳转链接);调用方自行设置的字段:dataType(必填,time_range/start_time/recent_time)、recentDays(dataType=recent_time 时有效,7d/30d/1y,默认 30d)、startDate(dataType=time_range/start_time 时有效,yyyy-MM-dd,默认 30 天前)、endDate(dataType=time_range 时有效,yyyy-MM-dd,默认当天)、keepRemovedFields(默认 false)。约定:syncAll 固定为 true;splitParentTableField 与 enableDataSyncOaDetailList 为下游内部字段,无需传入"},
{Name: "auto", Type: shortcut.FlagBool, Desc: "可选。是否开启自动同步;仅显式设置时下发给下游,省略时保持原有自动同步开关不变"},
{Name: "field-ids", Type: shortcut.FlagStringSlice, Desc: "需要同步的字段 ID 列表,不传时保持现有配置(创建时默认为全部字段)"},
{Name: "auto-sync-setting", Type: shortcut.FlagString, Desc: "可选。自动同步频率配置 JSON 字符串,仅在显式设置 --auto=true 时生效;省略时保持原有自动同步频率配置。字段:syncType(必填,hourly=按小时间隔,scheduled=定时触发)、hourlyInterval(syncType=hourly 时必填,正整数小时)、scheduleType(syncType=scheduled 时必填,daily/weekly/monthly)、timeValue(syncType=scheduled 时必填,HH:mm)、selectedMonthDays(scheduleType=monthly 时必填,每月几号触发,1-31)、selectedWeekdays(scheduleType=weekly 时必填,每周哪几天触发,1=周一…7=周日)、skipNonWorkingDay(可选,默认 false)"},
},
Tips: []string{
`dws aitable +datasource-update --base-id BASE123 --table-id TBL456 --auto`,
`dws aitable +datasource-update --base-id BASE123 --table-id TBL456 --source-config '{"processCode":"PROC-YYYY","name":"出差申请","dataType":"recent_time","recentDays":"30d","iconUrl":"https://example.com/icon.png","url":"https://example.com/oa"}'`,
},
Execute: func(rt *shortcut.RuntimeContext) error {
params := map[string]any{
"baseId": rt.Str("base-id"),
"tableId": rt.Str("table-id"),
}
if rt.Changed("source-config") {
if _, err := parseJSONObject("source-config", rt.Str("source-config")); err != nil {
return err
}
params["sourceConfig"] = rt.Str("source-config")
}
if rt.Changed("auto") {
params["auto"] = rt.Bool("auto")
}
if rt.Changed("field-ids") {
raw := rt.StrSlice("field-ids")
cleaned := trimNonEmpty(raw)
if len(cleaned) == 0 {
return fmt.Errorf("--field-ids 显式提供时不能为空,如需保持默认请勿传入")
}
params["fieldIds"] = cleaned
}
if rt.Changed("auto-sync-setting") {
v := rt.Str("auto-sync-setting")
if v == "" {
return fmt.Errorf("--auto-sync-setting 显式提供时不能为空,如需保持默认请勿传入")
}
if _, err := parseJSONObject("auto-sync-setting", v); err != nil {
return err
}
params["autoSyncSetting"] = v
}
if !rt.Changed("source-config") && !rt.Changed("auto") && !rt.Changed("field-ids") && !rt.Changed("auto-sync-setting") {
return fmt.Errorf("至少需要一个配置变更:--source-config、--auto、--field-ids 或 --auto-sync-setting;仅触发同步请使用 +datasource-sync")
}
data, err := rt.CallMCPData(serverMain, "update_datasource_config", params)
if err != nil {
return err
}
return rt.Output(data)
},
}
// DatasourceSync 对数据源表触发一次手动同步(run_datasource_sync)。
var DatasourceSync = shortcut.Shortcut{
Service: "aitable",
Command: "+datasource-sync",
Product: serverMain,
Description: "对指定 AI 表格中的数据源表触发一次手动同步。单次最多 5 张表,每张表独立提交,部分失败不影响其他表。该工具仅触发任务即返回,不会等待同步完成。返回结果包含文档链接,用户可打开文档查看同步进度与最终数据。同步运行中(errorCode=4014)属于幂等冲突,会被标记为 failed 并允许调用方稍后重试。非数据源表(sync=false)不能用此工具触发同步,会以参数错误返回。",
Intent: "当用户需要手动触发已有数据源表的同步(而非创建或更新配置)时使用。同步任务 ID 可通过 +datasource-sync-status 查询结果。",
Risk: shortcut.RiskWrite,
Safety: contract.SafetySpec{
Effect: "write", Risk: "medium",
Confirmation: "not_required", Idempotency: "non_idempotent",
},
Contract: corecmd.ContractDecl{
Identity: contract.ToolIdentitySpec{
ProductID: "aitable",
Name: "shortcut_datasource_sync",
CanonicalPath: "aitable.shortcut_datasource_sync",
CLIPath: "aitable +datasource-sync",
PrimaryCLIPath: "aitable +datasource-sync",
},
Description: "对指定 AI 表格中的数据源表触发一次手动同步。单次最多 5 张表,每张表独立提交,部分失败不影响其他表。该工具仅触发任务即返回,不会等待同步完成。返回结果包含文档链接,用户可打开文档查看同步进度与最终数据。同步运行中(errorCode=4014)属于幂等冲突,会被标记为 failed 并允许调用方稍后重试。非数据源表(sync=false)不能用此工具触发同步,会以参数错误返回。",
Interface: &contract.InterfaceSpec{
Mode: "composite",
Availability: "available",
Reason: "Reviewed built-in shortcut adapter: the executable CLI owns validation, optional multi-step orchestration, output projection, and confirmation; the complete command contract is not represented by one pinned MCP interface_ref.",
},
Selection: contract.SelectionSpec{
AgentSummary: "对指定 AI 表格中的数据源表触发一次手动同步。单次最多 5 张表,每张表独立提交,部分失败不影响其他表。该工具仅触发任务即返回,不会等待同步完成。返回结果包含文档链接,用户可打开文档查看同步进度与最终数据。同步运行中(errorCode=4014)属于幂等冲突,会被标记为 failed 并允许调用方稍后重试。非数据源表(sync=false)不能用此工具触发同步,会以参数错误返回。",
UseWhen: []string{"当用户需要手动触发已有数据源表的同步(而非创建或更新配置)时使用。同步任务 ID 可通过 +datasource-sync-status 查询结果。"},
AvoidWhen: []string{
"需要创建新数据源表时(改用 +datasource-create)",
"需要更新配置时(改用 +datasource-update)",
},
Examples: []string{
`dws aitable +datasource-sync --base-id BASE123 --table-ids TBL1,TBL2`,
`dws aitable +datasource-sync --base-id BASE123 --table-ids TBL1`,
},
},
},
Flags: []shortcut.Flag{
{Name: "base-id", Type: shortcut.FlagString, Desc: "目标 Base ID", Required: true},
{Name: "table-ids", Type: shortcut.FlagStringSlice, Desc: "待触发同步的数据源表 ID 列表(通过 +base-get / +table-list 获取,仅允许 sync=true 的表,1-5 个)", Required: true},
},
Tips: []string{
`dws aitable +datasource-sync --base-id BASE123 --table-ids TBL1,TBL2`,
`dws aitable +datasource-sync --base-id BASE123 --table-ids TBL1`,
},
Execute: func(rt *shortcut.RuntimeContext) error {
rawTableIDs := rt.StrSlice("table-ids")
tableIDs := trimNonEmpty(rawTableIDs)
if len(tableIDs) < 1 || len(tableIDs) > 5 {
return fmt.Errorf("--table-ids requires 1-5 table IDs, got %d", len(tableIDs))
}
params := map[string]any{
"baseId": rt.Str("base-id"),
"tableIds": tableIDs,
}
data, err := rt.CallMCPData(serverMain, "run_datasource_sync", params)
if err != nil {
return err
}
return rt.Output(data)
},
}
// DatasourceSyncStatus 查询数据源表同步任务状态(get_datasource_sync_status)。
var DatasourceSyncStatus = shortcut.Shortcut{
Service: "aitable",
Command: "+datasource-sync-status",
Product: serverMain,
Description: "按任务 ID 查询指定数据源表的同步任务状态。与 +datasource-sync / +datasource-create / +datasource-update 配对使用:这些指令触发同步后返回 taskId,本指令通过 taskId 查询最终结果。支持批量查询(单次最多 5 个 taskId),整体仍返回 success;需遍历 tasks 数组按单条 status 判断真实结果。任务状态包括:RUNNING(同步进行中)、FINISHED(同步完成)、FAILED(同步失败)。失败时会返回 errorCode 和 errorMessage 供排查。",
Intent: "当用户触发同步后需要按 taskId 查询同步是否完成、成功或失败时使用。支持批量查询(单次最多 5 个任务 ID)。",
Risk: shortcut.RiskRead,
Safety: contract.SafetySpec{
Effect: "read", Risk: "low",
Confirmation: "not_required", Idempotency: "idempotent",
},
Contract: corecmd.ContractDecl{
Identity: contract.ToolIdentitySpec{
ProductID: "aitable",
Name: "shortcut_datasource_sync_status",
CanonicalPath: "aitable.shortcut_datasource_sync_status",
CLIPath: "aitable +datasource-sync-status",
PrimaryCLIPath: "aitable +datasource-sync-status",
},
Description: "按任务 ID 查询指定数据源表的同步任务状态。与 +datasource-sync / +datasource-create / +datasource-update 配对使用:这些指令触发同步后返回 taskId,本指令通过 taskId 查询最终结果。支持批量查询(单次最多 5 个 taskId),整体仍返回 success;需遍历 tasks 数组按单条 status 判断真实结果。任务状态包括:RUNNING(同步进行中)、FINISHED(同步完成)、FAILED(同步失败)。失败时会返回 errorCode 和 errorMessage 供排查。",
Interface: &contract.InterfaceSpec{
Mode: "composite",
Availability: "available",
Reason: "Reviewed built-in shortcut adapter: the executable CLI owns validation, optional multi-step orchestration, output projection, and confirmation; the complete command contract is not represented by one pinned MCP interface_ref.",
},
Selection: contract.SelectionSpec{
AgentSummary: "按任务 ID 查询指定数据源表的同步任务状态。与 +datasource-sync / +datasource-create / +datasource-update 配对使用:这些指令触发同步后返回 taskId,本指令通过 taskId 查询最终结果。支持批量查询(单次最多 5 个 taskId),整体仍返回 success;需遍历 tasks 数组按单条 status 判断真实结果。任务状态包括:RUNNING(同步进行中)、FINISHED(同步完成)、FAILED(同步失败)。失败时会返回 errorCode 和 errorMessage 供排查。",
UseWhen: []string{"当用户触发同步后需要按 taskId 查询同步是否完成、成功或失败时使用。支持批量查询(单次最多 5 个任务 ID)。"},
AvoidWhen: []string{
"需要触发同步时(改用 +datasource-sync)",
},
Examples: []string{
`dws aitable +datasource-sync-status --base-id BASE123 --table-id TBL456 --task-ids TASK1,TASK2`,
},
},
},
Flags: []shortcut.Flag{
{Name: "base-id", Type: shortcut.FlagString, Desc: "目标 Base ID", Required: true},
{Name: "table-id", Type: shortcut.FlagString, Desc: "数据源表 ID(通过 +base-get / +table-list 获取,仅允许传入 sync=true 的表)", Required: true},
{Name: "task-ids", Type: shortcut.FlagStringSlice, Desc: "待查询的同步任务 ID 列表(由 +datasource-sync / +datasource-create / +datasource-update 返回)。单次最多 5 个,超出请拆分多次调用。", Required: true},
},
Tips: []string{
`dws aitable +datasource-sync-status --base-id BASE123 --table-id TBL456 --task-ids TASK1,TASK2`,
},
Execute: func(rt *shortcut.RuntimeContext) error {
params := map[string]any{
"baseId": rt.Str("base-id"),
"tableId": rt.Str("table-id"),
}
rawTaskIDs := rt.StrSlice("task-ids")
taskIDs := trimNonEmpty(rawTaskIDs)
if len(taskIDs) < 1 || len(taskIDs) > 5 {
return fmt.Errorf("--task-ids requires 1-5 task IDs, got %d", len(taskIDs))
}
params["taskIds"] = taskIDs
data, err := rt.CallMCPData(serverMain, "get_datasource_sync_status", params)
if err != nil {
return err
}
return rt.Output(data)
},
}
// DatasourceGetConfig 获取数据源表的同步配置信息(get_datasource_config)。
var DatasourceGetConfig = shortcut.Shortcut{
Service: "aitable",
Command: "+datasource-get-config",
Product: serverMain,
Description: "获取指定数据源表的同步配置信息,包括源配置、是否全量同步、是否自动同步、同步状态等。仅适用于数据源表(sync=true),普通表会返回错误。仅支持 OA 审批数据源(datasourceType=OA),其他数据源类型暂不支持,待后续开放。返回的 sourceConfig 包含数据源连接信息(如审批模板 ID、源表 ID 等)。",
Intent: "当用户需要查看已有数据源表的配置详情(如确认当前同步的审批模板、字段选择、自动同步状态)时使用。",
Risk: shortcut.RiskRead,
Safety: contract.SafetySpec{
Effect: "read", Risk: "low",
Confirmation: "not_required", Idempotency: "idempotent",
},
Contract: corecmd.ContractDecl{
Identity: contract.ToolIdentitySpec{
ProductID: "aitable",
Name: "shortcut_datasource_get_config",
CanonicalPath: "aitable.shortcut_datasource_get_config",
CLIPath: "aitable +datasource-get-config",
PrimaryCLIPath: "aitable +datasource-get-config",
},
Description: "获取指定数据源表的同步配置信息,包括源配置、是否全量同步、是否自动同步、同步状态等。仅适用于数据源表(sync=true),普通表会返回错误。仅支持 OA 审批数据源(datasourceType=OA),其他数据源类型暂不支持,待后续开放。返回的 sourceConfig 包含数据源连接信息(如审批模板 ID、源表 ID 等)。",
Interface: &contract.InterfaceSpec{
Mode: "composite",
Availability: "available",
Reason: "Reviewed built-in shortcut adapter: the executable CLI owns validation, optional multi-step orchestration, output projection, and confirmation; the complete command contract is not represented by one pinned MCP interface_ref.",
},
Selection: contract.SelectionSpec{
AgentSummary: "获取指定数据源表的同步配置信息,包括源配置、是否全量同步、是否自动同步、同步状态等。仅适用于数据源表(sync=true),普通表会返回错误。仅支持 OA 审批数据源(datasourceType=OA),其他数据源类型暂不支持,待后续开放。返回的 sourceConfig 包含数据源连接信息(如审批模板 ID、源表 ID 等)。",
UseWhen: []string{"当用户需要查看已有数据源表的配置详情(如确认当前同步的审批模板、字段选择、自动同步状态)时使用。"},
AvoidWhen: []string{
"需要更新配置时(改用 +datasource-update)",
"需要查询同步任务状态时(改用 +datasource-sync-status)",
},
Examples: []string{
`dws aitable +datasource-get-config --base-id BASE123 --table-id TBL456`,
},
},
},
Flags: []shortcut.Flag{
{Name: "base-id", Type: shortcut.FlagString, Desc: "目标 Base ID", Required: true},
{Name: "table-id", Type: shortcut.FlagString, Desc: "数据源表 ID(通过 +base-get / +table-list 获取,仅允许传入 sync=true 的表)", Required: true},
},
Tips: []string{
`dws aitable +datasource-get-config --base-id BASE123 --table-id TBL456`,
},
Execute: func(rt *shortcut.RuntimeContext) error {
params := map[string]any{
"baseId": rt.Str("base-id"),
"tableId": rt.Str("table-id"),
}
data, err := rt.CallMCPData(serverMain, "get_datasource_config", params)
if err != nil {
return err
}
return rt.Output(data)
},
}
// DatasourceListSources 列出指定数据源类型可用的来源(list_datasource_sources)。
var DatasourceListSources = shortcut.Shortcut{
Service: "aitable",
Command: "+datasource-list-sources",
Product: serverMain,
Description: "列出指定 Base 下可用的数据源条目。仅支持 OA 审批数据源(datasourceType=OA)。返回的每条条目包含 result 字段(下游原始 JSON 字符串)和 sourceType 字段(OA 审批对应 2,仅供参考)。OA 审批场景下 result 为包含 approvals 数组的 JSON 字符串,每个 approval 包含 processCode、name、iconUrl、url、keepRemovedFields、splitParentTableField 等字段。须原样透传至 sourceConfig 的字段(仅以下 4 个):processCode、name、iconUrl、url;调用方自行设置的字段(即使 result 中有值也不透传):keepRemovedFields、splitParentTableField;enableDataSyncOaDetailList 为下游内部字段,无需传入 sourceConfig。调用方应自行解析 result,提取目标模板字段后构造 sourceConfig 传入 +datasource-create。",
Intent: "当用户需要查看某类数据源(如审批)的可用来源信息、获取 result/processCode 以便创建或更新数据源配置时使用。",
Risk: shortcut.RiskRead,
Safety: contract.SafetySpec{
Effect: "read", Risk: "low",
Confirmation: "not_required", Idempotency: "idempotent",
},
Contract: corecmd.ContractDecl{
Identity: contract.ToolIdentitySpec{
ProductID: "aitable",
Name: "shortcut_datasource_list_sources",
CanonicalPath: "aitable.shortcut_datasource_list_sources",
CLIPath: "aitable +datasource-list-sources",
PrimaryCLIPath: "aitable +datasource-list-sources",
},
Description: "列出指定 Base 下可用的数据源条目。仅支持 OA 审批数据源(datasourceType=OA)。返回的每条条目包含 result 字段(下游原始 JSON 字符串)和 sourceType 字段(OA 审批对应 2,仅供参考)。OA 审批场景下 result 为包含 approvals 数组的 JSON 字符串,每个 approval 包含 processCode、name、iconUrl、url、keepRemovedFields、splitParentTableField 等字段。须原样透传至 sourceConfig 的字段(仅以下 4 个):processCode、name、iconUrl、url;调用方自行设置的字段(即使 result 中有值也不透传):keepRemovedFields、splitParentTableField;enableDataSyncOaDetailList 为下游内部字段,无需传入 sourceConfig。调用方应自行解析 result,提取目标模板字段后构造 sourceConfig 传入 +datasource-create。",
Interface: &contract.InterfaceSpec{
Mode: "composite",
Availability: "available",
Reason: "Reviewed built-in shortcut adapter: the executable CLI owns validation, optional multi-step orchestration, output projection, and confirmation; the complete command contract is not represented by one pinned MCP interface_ref.",
},
Selection: contract.SelectionSpec{
AgentSummary: "列出指定 Base 下可用的数据源条目。仅支持 OA 审批数据源(datasourceType=OA)。返回的每条条目包含 result 字段(下游原始 JSON 字符串)和 sourceType 字段(OA 审批对应 2,仅供参考)。OA 审批场景下 result 为包含 approvals 数组的 JSON 字符串,每个 approval 包含 processCode、name、iconUrl、url、keepRemovedFields、splitParentTableField 等字段。须原样透传至 sourceConfig 的字段(仅以下 4 个):processCode、name、iconUrl、url;调用方自行设置的字段(即使 result 中有值也不透传):keepRemovedFields、splitParentTableField;enableDataSyncOaDetailList 为下游内部字段,无需传入 sourceConfig。调用方应自行解析 result,提取目标模板字段后构造 sourceConfig 传入 +datasource-create。",
UseWhen: []string{"当用户需要查看某类数据源(如审批)的可用来源信息、获取 result/processCode 以便创建或更新数据源配置时使用。"},
AvoidWhen: []string{
"需要创建数据源表时(改用 +datasource-create)",
"需要获取数据源字段结构时(改用 +datasource-get-fields)",
},
Examples: []string{
`dws aitable +datasource-list-sources --base-id BASE123 --datasource-type OA`,
},
},
},
Flags: []shortcut.Flag{
{Name: "base-id", Type: shortcut.FlagString, Desc: "目标 Base ID", Required: true},
{Name: "datasource-type", Type: shortcut.FlagString, Desc: "数据源类型,目前支持审批(OA)", Required: true},
},
Tips: []string{
`dws aitable +datasource-list-sources --base-id BASE123 --datasource-type OA`,
},
Execute: func(rt *shortcut.RuntimeContext) error {
params := map[string]any{
"baseId": rt.Str("base-id"),
"datasourceType": rt.Str("datasource-type"),
}
data, err := rt.CallMCPData(serverMain, "list_datasource_sources", params)
if err != nil {
return err
}
return rt.Output(data)
},
}
// DatasourceGetFields 获取指定数据源来源的可同步字段列表(get_datasource_fields)。
var DatasourceGetFields = shortcut.Shortcut{
Service: "aitable",
Command: "+datasource-get-fields",
Product: serverMain,
Description: "获取指定数据源下可供同步的字段列表,用于在 +datasource-create / +datasource-update 中决定同步哪些字段。传入从 +datasource-list-sources 获取的 sourceConfig。仅支持 OA 审批数据源(datasourceType=OA),其他数据源类型暂不支持,待后续开放。",
Intent: "当用户需要查看某数据源来源有哪些可同步字段、以便在创建或更新数据源时指定 field-ids 时使用。",
Risk: shortcut.RiskRead,
Safety: contract.SafetySpec{
Effect: "read", Risk: "low",
Confirmation: "not_required", Idempotency: "idempotent",
},
Contract: corecmd.ContractDecl{
Identity: contract.ToolIdentitySpec{
ProductID: "aitable",
Name: "shortcut_datasource_get_fields",
CanonicalPath: "aitable.shortcut_datasource_get_fields",
CLIPath: "aitable +datasource-get-fields",
PrimaryCLIPath: "aitable +datasource-get-fields",
},
Description: "获取指定数据源下可供同步的字段列表,用于在 +datasource-create / +datasource-update 中决定同步哪些字段。传入从 +datasource-list-sources 获取的 sourceConfig。仅支持 OA 审批数据源(datasourceType=OA),其他数据源类型暂不支持,待后续开放。",
Interface: &contract.InterfaceSpec{
Mode: "composite",
Availability: "available",
Reason: "Reviewed built-in shortcut adapter: the executable CLI owns validation, optional multi-step orchestration, output projection, and confirmation; the complete command contract is not represented by one pinned MCP interface_ref.",
},
Selection: contract.SelectionSpec{
AgentSummary: "获取指定数据源下可供同步的字段列表,用于在 +datasource-create / +datasource-update 中决定同步哪些字段。传入从 +datasource-list-sources 获取的 sourceConfig。仅支持 OA 审批数据源(datasourceType=OA),其他数据源类型暂不支持,待后续开放。",
UseWhen: []string{"当用户需要查看某数据源来源有哪些可同步字段、以便在创建或更新数据源时指定 field-ids 时使用。"},
AvoidWhen: []string{
"需要列出可用来源时(改用 +datasource-list-sources)",
"需要创建数据源表时(改用 +datasource-create)",
},
Examples: []string{
`dws aitable +datasource-get-fields --base-id BASE123 --datasource-type OA --source-config '{"processCode":"PROC-XXXX","name":"采购申请","dataType":"recent_time","recentDays":"30d","iconUrl":"https://example.com/icon.png","url":"https://example.com/oa"}'`,
},
},
},
Flags: []shortcut.Flag{
{Name: "base-id", Type: shortcut.FlagString, Desc: "目标 Base ID", Required: true},
{Name: "datasource-type", Type: shortcut.FlagString, Desc: "数据源类型,目前支持审批(OA)", Required: true},
{Name: "source-config", Type: shortcut.FlagString, Desc: "源配置 JSON 字符串。结构同 +datasource-create 的 --source-config,需含 processCode、name、iconUrl、url、dataType 及对应时间字段", Required: true},
},
Tips: []string{
`dws aitable +datasource-get-fields --base-id BASE123 --datasource-type OA --source-config '{"processCode":"PROC-XXXX","name":"采购申请","dataType":"recent_time","recentDays":"30d","iconUrl":"https://example.com/icon.png","url":"https://example.com/oa"}'`,
},
Execute: func(rt *shortcut.RuntimeContext) error {
if _, err := parseJSONObject("source-config", rt.Str("source-config")); err != nil {
return err
}
params := map[string]any{
"baseId": rt.Str("base-id"),
"datasourceType": rt.Str("datasource-type"),
"sourceConfig": rt.Str("source-config"),
}
data, err := rt.CallMCPData(serverMain, "get_datasource_fields", params)
if err != nil {
return err
}
return rt.Output(data)
},
}
func init() {
shortcut.Register(withReviewedAITableShortcutContracts(
DatasourceCreate,
DatasourceUpdate,
DatasourceSync,
DatasourceSyncStatus,
DatasourceGetConfig,
DatasourceListSources,
DatasourceGetFields,
)...)
}