// kbdb_patch_block — PATCH 一個既有 block 的部分欄位 // 對應 KBDB endpoint: PATCH /blocks/{id} // SDD: matrix/kbdb/.agents/specs/blocks-edit-api/design.md §2 // //go:build tinygo package main import ( "encoding/json" "io" "os" "unsafe" ) //go:wasmimport u6u http_request func hostHttpRequest( urlPtr uintptr, urlLen uint32, methodPtr uintptr, methodLen uint32, headersPtr uintptr, headersLen uint32, bodyPtr uintptr, bodyLen uint32, outPtr uintptr, outLenPtr uintptr, ) uint32 type Input struct { KBDBUrl string `json:"kbdb_url"` // optional APIKey string `json:"api_key"` // 必填 BlockID string `json:"block_id"` // 必填 Content *string `json:"content"` // optional(pointer 區分「未傳」vs「設空字串」) Tags []string `json:"tags"` // optional 完整覆寫 Refs []string `json:"refs"` // optional 完整覆寫 Source *string `json:"source"` // optional Metadata map[string]interface{} `json:"metadata_json"` // optional } var dummy [1]byte func safePtr(b []byte) (uintptr, uint32) { if len(b) == 0 { return uintptr(unsafe.Pointer(&dummy[0])), 0 } return uintptr(unsafe.Pointer(&b[0])), uint32(len(b)) } func main() { raw, err := io.ReadAll(os.Stdin) if err != nil { writeError("failed to read stdin: " + err.Error()) return } var input Input if err := json.Unmarshal(raw, &input); err != nil { writeError("invalid input JSON: " + err.Error()) return } if input.APIKey == "" { writeError("api_key 必填") return } if input.BlockID == "" { writeError("block_id 必填") return } // 至少要有一個欄位(避免 KBDB 回 400) if input.Content == nil && input.Tags == nil && input.Refs == nil && input.Source == nil && input.Metadata == nil { writeError("至少要傳一個更新欄位(content / tags / refs / source / metadata_json)") return } kbdbURL := input.KBDBUrl if kbdbURL == "" { kbdbURL = "https://kbdb.finally.click" } // 構造 PATCH body:只放有值的欄位(pointer 控制) body := make(map[string]interface{}) if input.Content != nil { body["content"] = *input.Content } if input.Tags != nil { body["tags"] = input.Tags } if input.Refs != nil { body["refs"] = input.Refs } if input.Source != nil { body["source"] = *input.Source } if input.Metadata != nil { body["metadata_json"] = input.Metadata } bodyBytes, _ := json.Marshal(body) headers := map[string]string{ "Content-Type": "application/json", "Authorization": "Bearer " + input.APIKey, } headersBytes, _ := json.Marshal(headers) url := kbdbURL + "/blocks/" + input.BlockID urlBytes := []byte(url) methodBytes := []byte("PATCH") outBuf := make([]byte, 65536) var outLen uint32 urlPtr, urlLen := safePtr(urlBytes) methodPtr, methodLen := safePtr(methodBytes) headersPtr, headersLen := safePtr(headersBytes) bodyPtr, bodyLenU := safePtr(bodyBytes) result := hostHttpRequest( urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLenU, uintptr(unsafe.Pointer(&outBuf[0])), uintptr(unsafe.Pointer(&outLen)), ) if result != 0 { writeError("KBDB PATCH request failed (host_http_request returned non-zero)") return } respStr := string(outBuf[:outLen]) var kbdbResp map[string]interface{} if err := json.Unmarshal([]byte(respStr), &kbdbResp); err != nil { writeError("KBDB returned non-JSON: " + respStr) return } if _, hasErr := kbdbResp["error"]; hasErr { out, _ := json.Marshal(map[string]interface{}{ "success": false, "error": kbdbResp["error"], }) os.Stdout.Write(out) return } out, _ := json.Marshal(map[string]interface{}{ "success": true, "data": kbdbResp, }) os.Stdout.Write(out) } func writeError(msg string) { out, _ := json.Marshal(map[string]interface{}{"success": false, "error": msg}) os.Stdout.Write(out) }