Files
Arcrun/registry/components/km_writer/main.go
uncle6me-web 922a57fe34 arcrun — AI workflow execution engine (clean history)
Self-hosted 開源:WASM 零件 + recipe + cypher-executor,跑在你自己的 Cloudflare。

此為重建的乾淨歷史起點(移除曾誤 commit 的 GCP SA 金鑰,舊歷史保留在
richblack/arcrun 與本地 backup 分支)。含:
- acr init --self-hosted installer(建 KV/R2 + codeload 拉預編譯 wasm + wrangler deploy + seed recipe)
- recipe push 把關(資料外流提醒 + 打通檢查)
- 19 個正當零件預編譯 wasm(claude_api/km_writer/kbdb_upsert_block 排除:違反 DECISIONS §1)
- CLI / cypher-executor / registry / 完整 SDD

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 15:52:38 +08:00

178 lines
4.7 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.
// km_writer — 讀寫 Mira leo-graphjournals + pages
// 透過 host function 呼叫 Mira /km/* API
//
//go:build tinygo
package main
import (
"encoding/json"
"fmt"
"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
// Input actions:
// read_journal — GET today's journal (requires: mira_url, token)
// read_journal_date — GET journal by date (requires: mira_url, token, date)
// append_journal — POST append entry (requires: mira_url, token, content; optional: timestamp)
// list_pages — GET all pages (requires: mira_url, token)
// read_page — GET page by name (requires: mira_url, token, name)
// write_page — PUT write page (requires: mira_url, token, name, content)
type Input struct {
Action string `json:"action"`
MiraURL string `json:"mira_url"`
Token string `json:"token"`
Content string `json:"content"`
Timestamp string `json:"timestamp"`
Date string `json:"date"`
Name string `json:"name"`
}
func main() {
raw, err := io.ReadAll(os.Stdin)
if err != nil {
writeError("failed to read stdin: " + err.Error())
return
}
var inp Input
if err := json.Unmarshal(raw, &inp); err != nil {
writeError("invalid input JSON: " + err.Error())
return
}
if inp.Action == "" {
writeError("action 必填")
return
}
if inp.MiraURL == "" {
writeError("mira_url 必填")
return
}
if inp.Token == "" {
writeError("token 必填")
return
}
authHeader := fmt.Sprintf(`{"Authorization":"Bearer %s","Content-Type":"application/json"}`, inp.Token)
switch inp.Action {
case "read_journal":
result := doRequest(inp.MiraURL+"/km/journal", "GET", authHeader, "")
os.Stdout.Write(result)
case "read_journal_date":
if inp.Date == "" {
writeError("date 必填(格式 YYYY-MM-DD")
return
}
result := doRequest(inp.MiraURL+"/km/journal/"+inp.Date, "GET", authHeader, "")
os.Stdout.Write(result)
case "append_journal":
if inp.Content == "" {
writeError("content 必填")
return
}
bodyMap := map[string]string{"content": inp.Content}
if inp.Timestamp != "" {
bodyMap["timestamp"] = inp.Timestamp
}
bodyBytes, _ := json.Marshal(bodyMap)
result := doRequest(inp.MiraURL+"/km/journal", "POST", authHeader, string(bodyBytes))
os.Stdout.Write(result)
case "list_pages":
result := doRequest(inp.MiraURL+"/km/pages", "GET", authHeader, "")
os.Stdout.Write(result)
case "read_page":
if inp.Name == "" {
writeError("name 必填")
return
}
result := doRequest(inp.MiraURL+"/km/page/"+inp.Name, "GET", authHeader, "")
os.Stdout.Write(result)
case "write_page":
if inp.Name == "" {
writeError("name 必填")
return
}
if inp.Content == "" {
writeError("content 必填")
return
}
bodyMap := map[string]string{"content": inp.Content}
bodyBytes, _ := json.Marshal(bodyMap)
result := doRequest(inp.MiraURL+"/km/page/"+inp.Name, "PUT", authHeader, string(bodyBytes))
os.Stdout.Write(result)
default:
writeError("未知 action: " + inp.Action)
}
}
func doRequest(url, method, headersJSON, body string) []byte {
urlBytes := []byte(url)
methodBytes := []byte(method)
headersBytes := []byte(headersJSON)
bodyBytes := []byte(body)
outBuf := make([]byte, 131072) // 128KB
var outLen uint32
if len(bodyBytes) == 0 {
bodyBytes = []byte{}
}
var bodyPtr uintptr
var bodyLen uint32
if len(bodyBytes) > 0 {
bodyPtr = uintptr(unsafe.Pointer(&bodyBytes[0]))
bodyLen = uint32(len(bodyBytes))
}
code := hostHttpRequest(
uintptr(unsafe.Pointer(&urlBytes[0])), uint32(len(urlBytes)),
uintptr(unsafe.Pointer(&methodBytes[0])), uint32(len(methodBytes)),
uintptr(unsafe.Pointer(&headersBytes[0])), uint32(len(headersBytes)),
bodyPtr, bodyLen,
uintptr(unsafe.Pointer(&outBuf[0])), uintptr(unsafe.Pointer(&outLen)),
)
if code != 0 {
out, _ := json.Marshal(map[string]interface{}{"success": false, "error": "HTTP request failed"})
return out
}
responseStr := string(outBuf[:outLen])
// Try to parse the response as JSON to forward it
var parsed interface{}
if err := json.Unmarshal([]byte(responseStr), &parsed); err != nil {
// Not JSON — wrap it
out, _ := json.Marshal(map[string]interface{}{"success": true, "data": responseStr})
return out
}
// Forward the parsed response as-is, wrapped in success
out, _ := json.Marshal(map[string]interface{}{"success": true, "data": parsed})
return out
}
func writeError(msg string) {
out, _ := json.Marshal(map[string]interface{}{"success": false, "error": msg})
os.Stdout.Write(out)
}