@@ -5,7 +5,9 @@ package doc
55
66import (
77 "context"
8+ "encoding/json"
89 "fmt"
10+ "strings"
911
1012 "github.com/larksuite/cli/errs"
1113 "github.com/larksuite/cli/shortcuts/common"
@@ -22,12 +24,15 @@ var validCommandsV2 = map[string]bool{
2224 "append" : true ,
2325}
2426
27+ const docsUpdateReferenceMapFlagDesc = "结构化 `reference_map` JSON object;当 `--content` 使用正文外部载荷 / 引用映射时与内容一起传给服务,支持直接 JSON、`@reference-map.json`(相对路径)或 `-` 从 stdin 读取。通常用于回写已有 `document.reference_map`。"
28+
2529// v2UpdateFlags returns the flag definitions for the v2 (OpenAPI) update path.
2630func v2UpdateFlags () []common.Flag {
2731 return []common.Flag {
2832 {Name : "command" , Desc : "operation; requirements: str_replace(--pattern), block_delete(--block-id, comma-separated for batch), block_insert_after/block_replace(--block-id,--content), block_copy_insert_after/block_move_after(--block-id,--src-block-ids), overwrite/append(--content)" , Enum : validCommandsV2Keys ()},
2933 {Name : "doc-format" , Desc : "content format for --content; xml is default for precise rich edits, markdown for user-provided Markdown or plain append/overwrite" , Default : "xml" , Enum : []string {"xml" , "markdown" }},
3034 {Name : "content" , Desc : "replacement or inserted content; XML by default or Markdown when --doc-format markdown; empty with str_replace deletes match. " + docsContentSkillHelp + "; use --help for the latest command flags" , Input : []string {common .File , common .Stdin }},
35+ {Name : "reference-map" , Desc : docsUpdateReferenceMapFlagDesc , Input : []string {common .File , common .Stdin }},
3136 {Name : "pattern" , Desc : "str_replace match pattern; XML mode is inline text, Markdown mode can match multiline text" },
3237 {Name : "block-id" , Desc : "target block ID(s) for block operations (comma-separated for batch delete); -1 means document end where supported" },
3338 {Name : "src-block-ids" , Desc : "comma-separated source block ids for block_copy_insert_after and block_move_after" },
@@ -54,6 +59,9 @@ func validateUpdateV2(_ context.Context, runtime *common.RuntimeContext) error {
5459 return errs .NewValidationError (errs .SubtypeInvalidArgument , "invalid --command %q, valid: str_replace | block_delete | block_insert_after | block_copy_insert_after | block_replace | block_move_after | overwrite | append" , cmd ).WithParam ("--command" )
5560 }
5661 content := runtime .Str ("content" )
62+ if err := validateUpdateReferenceMap (runtime , cmd , content ); err != nil {
63+ return err
64+ }
5765 pattern := runtime .Str ("pattern" )
5866 blockID := runtime .Str ("block-id" )
5967 srcBlockIDs := runtime .Str ("src-block-ids" )
@@ -113,7 +121,7 @@ func validateUpdateV2(_ context.Context, runtime *common.RuntimeContext) error {
113121func dryRunUpdateV2 (_ context.Context , runtime * common.RuntimeContext ) * common.DryRunAPI {
114122 // Validate has already accepted --doc; parseDocumentRef cannot fail here.
115123 ref , _ := parseDocumentRef (runtime .Str ("doc" ))
116- body := buildUpdateBody (runtime )
124+ body , _ := buildUpdateBodyWithReferenceMap (runtime )
117125 apiPath := fmt .Sprintf ("/open-apis/docs_ai/v1/documents/%s" , ref .Token )
118126 return common .NewDryRunAPI ().
119127 PUT (apiPath ).
@@ -126,7 +134,10 @@ func executeUpdateV2(_ context.Context, runtime *common.RuntimeContext) error {
126134 ref , _ := parseDocumentRef (runtime .Str ("doc" ))
127135
128136 apiPath := fmt .Sprintf ("/open-apis/docs_ai/v1/documents/%s" , ref .Token )
129- body := buildUpdateBody (runtime )
137+ body , err := buildUpdateBodyWithReferenceMap (runtime )
138+ if err != nil {
139+ return err
140+ }
130141
131142 data , err := doDocAPI (runtime , "PUT" , apiPath , body )
132143 if err != nil {
@@ -138,6 +149,24 @@ func executeUpdateV2(_ context.Context, runtime *common.RuntimeContext) error {
138149}
139150
140151func buildUpdateBody (runtime * common.RuntimeContext ) map [string ]interface {} {
152+ body , _ := buildUpdateBodyWithReferenceMap (runtime )
153+ return body
154+ }
155+
156+ func buildUpdateBodyWithReferenceMap (runtime * common.RuntimeContext ) (map [string ]interface {}, error ) {
157+ body := buildUpdateBodyBase (runtime )
158+ if ! runtime .Changed ("reference-map" ) {
159+ return body , nil
160+ }
161+ refMap , err := parseUpdateReferenceMap (runtime .Str ("reference-map" ))
162+ if err != nil {
163+ return body , err
164+ }
165+ body ["reference_map" ] = refMap
166+ return body , nil
167+ }
168+
169+ func buildUpdateBodyBase (runtime * common.RuntimeContext ) map [string ]interface {} {
141170 cmd := runtime .Str ("command" )
142171
143172 // append is a shorthand for block_insert_after with block_id "-1" (end of document)
@@ -169,3 +198,40 @@ func buildUpdateBody(runtime *common.RuntimeContext) map[string]interface{} {
169198 injectDocsScene (runtime , body )
170199 return body
171200}
201+
202+ func validateUpdateReferenceMap (runtime * common.RuntimeContext , command string , content string ) error {
203+ if ! runtime .Changed ("reference-map" ) {
204+ return nil
205+ }
206+ if ! updateCommandAcceptsReferenceMap (command ) {
207+ return errs .NewValidationError (errs .SubtypeInvalidArgument , "--reference-map is only supported with update commands that send --content" ).WithParam ("--reference-map" )
208+ }
209+ if content == "" {
210+ return errs .NewValidationError (errs .SubtypeInvalidArgument , "--reference-map requires --content that uses matching sidecar refs" ).WithParam ("--reference-map" )
211+ }
212+ _ , err := parseUpdateReferenceMap (runtime .Str ("reference-map" ))
213+ return err
214+ }
215+
216+ func updateCommandAcceptsReferenceMap (command string ) bool {
217+ switch command {
218+ case "str_replace" , "block_insert_after" , "block_replace" , "overwrite" , "append" :
219+ return true
220+ default :
221+ return false
222+ }
223+ }
224+
225+ func parseUpdateReferenceMap (raw string ) (map [string ]interface {}, error ) {
226+ if strings .TrimSpace (raw ) == "" {
227+ return nil , errs .NewValidationError (errs .SubtypeInvalidArgument , "--reference-map must be a non-empty JSON object" ).WithParam ("--reference-map" )
228+ }
229+ var refMap map [string ]interface {}
230+ if err := json .Unmarshal ([]byte (raw ), & refMap ); err != nil {
231+ return nil , errs .NewValidationError (errs .SubtypeInvalidArgument , "--reference-map must be a valid JSON object: %v" , err ).WithParam ("--reference-map" ).WithCause (err )
232+ }
233+ if refMap == nil {
234+ return nil , errs .NewValidationError (errs .SubtypeInvalidArgument , "--reference-map must be a JSON object, got null" ).WithParam ("--reference-map" )
235+ }
236+ return refMap , nil
237+ }
0 commit comments