feat(arcrun): mira wiki page with tag filter + accumulated WIP
- landing/app/mira/wiki: tag=mira-wiki list now shows all wiki paragraphs (depends on KBDB tag filter exposed in matrix/kbdb commit, separate repo) - landing: app/mira hub + feed split + various WIP from prior sessions - registry/components: claude_api / kbdb_create_block / kbdb_get / km_writer / platform_crypto / auth_oauth2 contracts + main.go (accumulated) - .component-builds: pkg-lock updates + index.ts adjustments (WIP) - .agents/specs/arcrun/frontend-redesign: design notes - docs/test_credentials, docs/user_requirements/arcrun-landing-page: WIP docs - cypher-executor: auth-dispatcher / wasi-shim adjustments (WIP) Includes accumulated work from prior sessions plus the wiki UI tag-filter update that surfaces the AI-generated wiki paragraphs at /mira/wiki. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
// 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)
|
||||
}
|
||||
Reference in New Issue
Block a user