feat(doc): add yao doc CLI commands and YAML documentation for all packages

Implement yao doc process list/inspect/validate and yao doc runtime
list/inspect/validate commands. Validate uses engine addressing logic
(process.Of) and checks dynamic-ID group registries (model, store, fs,
task, schedule) to verify resources actually exist.

- cmd/doc/: CLI command tree with process and runtime subcommands
- cmd/root.go: wire docCmd into rootCmd
- 27 process doc.yml + doc.go pairs across yao packages
- cmd/doc/doc_test.go: integration tests

Made-with: Cursor
This commit is contained in:
Max 2026-04-23 21:37:43 +08:00
parent 4d22a9a655
commit efc84fbb97
60 changed files with 5444 additions and 0 deletions

11
agent/caller/doc.go Normal file
View file

@ -0,0 +1,11 @@
package caller
import (
_ "embed"
"github.com/yaoapp/gou/doc"
)
//go:embed doc.yml
var docYAML []byte
func init() { doc.LoadYAML(docYAML) }

13
agent/caller/doc.yml Normal file
View file

@ -0,0 +1,13 @@
group: agent
type: process
entries:
- name: Call
desc: Call an agent from contexts without agent.Context, enabling agent-to-agent communication
args:
- name: request
type: object
required: true
desc: "Request object with fields: assistant_id (string, required), messages (array of message objects, required), model (string, connector override), skip (object, skip config), metadata (object, passed to hooks), locale (string), route (string), chat_id (string, auto-generated if empty), timeout (number, seconds, default 600)"
return:
type: object
desc: "Result object: { agent_id (string), response (object, full agent response), content (string, extracted text), error (string, error message if failed) }"

11
agent/llm/doc.go Normal file
View file

@ -0,0 +1,11 @@
package llm
import (
_ "embed"
"github.com/yaoapp/gou/doc"
)
//go:embed doc.yml
var docYAML []byte
func init() { doc.LoadYAML(docYAML) }

25
agent/llm/doc.yml Normal file
View file

@ -0,0 +1,25 @@
group: llm
type: process
entries:
- name: ChatCompletions
desc: Universal LLM chat completions that auto-detects connector type and routes accordingly
args:
- name: connector
type: string
required: true
desc: Connector ID (supports any type, e.g. openai, anthropic)
- name: messages
type: array
required: true
desc: "Message array in OpenAI format: each element is an object with role, content (string or multimodal array), and optional name, tool_call_id, tool_calls"
- name: opts
type: object
required: false
desc: "Completion options: temperature, max_tokens, and other model parameters"
- name: callback
type: function
required: false
desc: "Streaming callback function that receives data chunks; signature: func(data []byte) int"
return:
type: object
desc: "OpenAI-compatible response: { id, object, created, model, choices: [{ index, message: { role, content, tool_calls? }, finish_reason }], usage? }"

11
agent/robot/doc.go Normal file
View file

@ -0,0 +1,11 @@
package robot
import (
_ "embed"
"github.com/yaoapp/gou/doc"
)
//go:embed doc.yml
var docYAML []byte
func init() { doc.LoadYAML(docYAML) }

80
agent/robot/doc.yml Normal file
View file

@ -0,0 +1,80 @@
group: robot
type: process
entries:
- name: get
desc: Get a robot's details by member ID
args:
- name: memberID
type: string
required: true
desc: The member ID of the robot to retrieve
return:
type: object
desc: Robot detail object
- name: list
desc: List all robots with optional filtering and pagination
args:
- name: filter
type: object
required: false
desc: "Filter options: page (number), pagesize (number), status (string), search (string, keywords), team_id (string)"
return:
type: object
desc: Paginated list of robots
- name: status
desc: Get the current status of a robot by member ID
args:
- name: memberID
type: string
required: true
desc: The member ID of the robot
return:
type: object
desc: Robot status object
- name: executions
desc: List executions for a robot with optional filtering and pagination
args:
- name: memberID
type: string
required: true
desc: The member ID of the robot
- name: filter
type: object
required: false
desc: "Filter options: page (number), pagesize (number), status (string, execution status), trigger (string, trigger type)"
return:
type: object
desc: Paginated list of execution records
- name: execution
desc: Get a specific execution record by member ID and execution ID
args:
- name: memberID
type: string
required: true
desc: The member ID of the robot (reserved for permission scoping)
- name: executionID
type: string
required: true
desc: The execution ID to retrieve
return:
type: object
desc: Execution status and details
- name: updateChatTitle
desc: Update the title of a chat session
args:
- name: chatID
type: string
required: true
desc: The chat session ID to update
- name: title
type: string
required: true
desc: The new title for the chat session
return:
type: "null"
desc: Returns null on success

11
attachment/doc.go Normal file
View file

@ -0,0 +1,11 @@
package attachment
import (
_ "embed"
"github.com/yaoapp/gou/doc"
)
//go:embed doc.yml
var docYAML []byte
func init() { doc.LoadYAML(docYAML) }

177
attachment/doc.yml Normal file
View file

@ -0,0 +1,177 @@
group: attachment
type: process
desc: "File attachment management processes for uploading, reading, listing, and managing files"
entries:
- name: Save
desc: Save a file from base64 data URI or plain base64 string
args:
- name: uploaderID
type: string
required: true
desc: "Uploader/manager ID (e.g. \"default\", \"__yao.attachment\")"
- name: content
type: string
required: true
desc: "Base64 data URI (e.g. \"data:image/png;base64,xxxx\") or plain base64 string"
- name: filename
type: string
required: false
desc: "Original filename; auto-generated from content type if omitted"
- name: option
type: object
required: false
desc: "Upload options: groups (array), gzip (bool), compress_image (bool), compress_size (number), public (bool), share (string: \"private\" or \"team\")"
return:
type: object
desc: "File object with file_id, path, bytes, created_at, filename, content_type, and status fields"
- name: Read
desc: Read file content as a base64 data URI
args:
- name: uploaderID
type: string
required: true
desc: "Uploader/manager ID"
- name: fileID
type: string
required: true
desc: "File ID to read"
return:
type: string
desc: "Base64 data URI string (e.g. \"data:image/png;base64,xxxx\")"
- name: Info
desc: Get file metadata information
args:
- name: uploaderID
type: string
required: true
desc: "Uploader/manager ID"
- name: fileID
type: string
required: true
desc: "File ID to query"
return:
type: object
desc: "File object with file_id, path, bytes, created_at, filename, content_type, and status fields"
- name: List
desc: List files with pagination and filtering
args:
- name: uploaderID
type: string
required: true
desc: "Uploader/manager ID"
- name: option
type: object
required: false
desc: "List options: page (number), page_size (number, max 100), filters (object), order_by (string), select (array of field names)"
return:
type: object
desc: "Paginated result with files (array), total (number), page (number), page_size (number), and total_pages (number)"
- name: Delete
desc: Delete a file by ID
args:
- name: uploaderID
type: string
required: true
desc: "Uploader/manager ID"
- name: fileID
type: string
required: true
desc: "File ID to delete"
return:
type: bool
desc: "True on success"
- name: Exists
desc: Check if a file exists
args:
- name: uploaderID
type: string
required: true
desc: "Uploader/manager ID"
- name: fileID
type: string
required: true
desc: "File ID to check"
return:
type: bool
desc: "True if the file exists"
- name: URL
desc: Get the URL for a file
args:
- name: uploaderID
type: string
required: true
desc: "Uploader/manager ID"
- name: fileID
type: string
required: true
desc: "File ID"
return:
type: string
desc: "File URL string"
- name: SaveText
desc: Save parsed text content for a file
args:
- name: uploaderID
type: string
required: true
desc: "Uploader/manager ID"
- name: fileID
type: string
required: true
desc: "File ID to save text for"
- name: text
type: string
required: true
desc: "Text content to save"
return:
type: bool
desc: "True on success"
- name: GetText
desc: Get parsed text content for a file
args:
- name: uploaderID
type: string
required: true
desc: "Uploader/manager ID"
- name: fileID
type: string
required: true
desc: "File ID to get text for"
- name: fullContent
type: bool
required: false
desc: "If true, return full content; if false (default), return preview (first 2000 chars)"
return:
type: string
desc: "Text content string"
- name: Zip
desc: Package multiple attachment files into a zip archive and upload it
args:
- name: uploaderID
type: string
required: true
desc: "Uploader/manager ID (e.g. \"__yao.attachment\")"
- name: fileIDs
type: array
required: true
desc: "Array of file ID strings to include in the zip"
- name: zipFilename
type: string
required: true
desc: "Output zip filename (e.g. \"archive.zip\"); .zip extension added automatically if missing"
- name: option
type: object
required: false
desc: "Upload options for the zip file: groups (array), gzip (bool), public (bool), share (string)"
return:
type: object
desc: "Uploaded zip file object with file_id, filename, bytes, and other file metadata"

74
cmd/doc/doc.go Normal file
View file

@ -0,0 +1,74 @@
package doc
import (
"encoding/json"
"fmt"
"os"
"strings"
"github.com/yaoapp/gou/doc"
)
var jsonOutput bool
func printJSON(v any) {
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
enc.Encode(v)
}
func formatArgs(args []doc.TypeValue) string {
if len(args) == 0 {
return "()"
}
parts := make([]string, 0, len(args))
for _, a := range args {
s := a.Name + " " + a.Type
if !a.Required {
s += "?"
}
parts = append(parts, s)
}
return "(" + strings.Join(parts, ", ") + ")"
}
func formatReturn(ret *doc.TypeValue) string {
if ret == nil {
return "void"
}
return ret.Type
}
func init() {
ProcessCmd.AddCommand(processListCmd)
ProcessCmd.AddCommand(processValidateCmd)
ProcessCmd.AddCommand(processInspectCmd)
RuntimeCmd.AddCommand(runtimeListCmd)
RuntimeCmd.AddCommand(runtimeValidateCmd)
RuntimeCmd.AddCommand(runtimeInspectCmd)
processListCmd.Flags().StringVarP(&groupFlag, "group", "g", "", "Filter by group")
processListCmd.Flags().StringVarP(&searchFlag, "search", "s", "", "Search keyword")
processListCmd.Flags().BoolVar(&jsonOutput, "json", false, "Output as JSON")
processListCmd.Flags().BoolVar(&showAll, "all", false, "Include undocumented processes")
processValidateCmd.Flags().BoolVar(&jsonOutput, "json", false, "Output as JSON")
processInspectCmd.Flags().BoolVar(&jsonOutput, "json", false, "Output as JSON")
runtimeListCmd.Flags().StringVarP(&typeFlag, "type", "t", "", "Filter by type: object, function, class")
runtimeListCmd.Flags().StringVarP(&searchFlag, "search", "s", "", "Search keyword")
runtimeListCmd.Flags().BoolVar(&jsonOutput, "json", false, "Output as JSON")
runtimeValidateCmd.Flags().BoolVar(&jsonOutput, "json", false, "Output as JSON")
runtimeInspectCmd.Flags().BoolVar(&jsonOutput, "json", false, "Output as JSON")
}
var groupFlag string
var searchFlag string
var typeFlag string
var showAll bool
func errExit(format string, a ...any) {
fmt.Fprintf(os.Stderr, format+"\n", a...)
os.Exit(1)
}

345
cmd/doc/doc_test.go Normal file
View file

@ -0,0 +1,345 @@
package doc
import (
"testing"
"github.com/yaoapp/gou/doc"
)
const sampleProcessYAML = `
group: test
type: process
entries:
- name: test.hello
desc: Greet someone
args:
- name: name
type: string
required: true
return:
type: string
- name: test.add
desc: Add two numbers
args:
- name: a
type: number
required: true
- name: b
type: number
required: true
return:
type: number
`
const sampleShortNameYAML = `
group: http
type: process
entries:
- name: get
desc: Send HTTP GET
args:
- name: url
type: string
required: true
return:
type: object
- name: post
desc: Send HTTP POST
args:
- name: url
type: string
required: true
return:
type: object
`
const sampleSubGroupYAML = `
group: utils
type: process
entries:
- name: throw.Forbidden
desc: Throw 403
return:
type: void
`
const sampleRuntimeYAML = `
group: objects
type: js_object
entries:
- name: log
desc: Logging utility
methods:
- name: Info
desc: Log info
args:
- name: msg
type: string
required: true
return:
type: void
`
const sampleClassYAML = `
group: objects
type: js_class
entries:
- name: FS
desc: File system operations
args:
- name: name
type: string
methods:
- name: ReadFile
desc: Read file
args:
- name: path
type: string
required: true
return:
type: string
`
const sampleFunctionYAML = `
group: functions
type: js_function
entries:
- name: Process
desc: Execute a Yao process
args:
- name: name
type: string
required: true
return:
type: any
`
func setupTestData(t *testing.T) {
t.Helper()
doc.Reset()
for _, yaml := range []string{
sampleProcessYAML, sampleShortNameYAML, sampleSubGroupYAML,
sampleRuntimeYAML, sampleClassYAML, sampleFunctionYAML,
} {
if err := doc.LoadYAML([]byte(yaml)); err != nil {
t.Fatalf("LoadYAML failed: %v", err)
}
}
}
func TestNormalisedNames(t *testing.T) {
setupTestData(t)
// "test.hello" already has prefix → stays "test.hello"
e, ok := doc.Get(doc.TypeProcess, "test.hello")
if !ok {
t.Fatal("test.hello not found")
}
if e.Name != "test.hello" {
t.Errorf("name = %q, want test.hello", e.Name)
}
// short name "get" with group "http" → normalised to "http.get"
e, ok = doc.Get(doc.TypeProcess, "http.get")
if !ok {
t.Fatal("http.get not found — short name was not normalised")
}
if e.Name != "http.get" {
t.Errorf("name = %q, want http.get", e.Name)
}
// sub-group name "throw.Forbidden" with group "utils" → "utils.throw.Forbidden"
e, ok = doc.Get(doc.TypeProcess, "utils.throw.Forbidden")
if !ok {
t.Fatal("utils.throw.Forbidden not found")
}
if e.Name != "utils.throw.Forbidden" {
t.Errorf("name = %q, want utils.throw.Forbidden", e.Name)
}
}
func TestProcessListCommand(t *testing.T) {
setupTestData(t)
entries := doc.List(doc.TypeProcess)
if len(entries) != 5 {
t.Errorf("expected 5 process entries, got %d", len(entries))
}
}
func TestProcessListWithGroupFilter(t *testing.T) {
setupTestData(t)
entries := doc.List(doc.TypeProcess, doc.ListOption{Group: "http"})
if len(entries) != 2 {
t.Errorf("expected 2 http entries, got %d", len(entries))
}
entries = doc.List(doc.TypeProcess, doc.ListOption{Group: "nonexistent"})
if len(entries) != 0 {
t.Errorf("expected 0, got %d", len(entries))
}
}
func TestProcessListWithSearch(t *testing.T) {
setupTestData(t)
entries := doc.List(doc.TypeProcess, doc.ListOption{Search: "hello"})
if len(entries) != 1 {
t.Fatalf("expected 1, got %d", len(entries))
}
if entries[0].Name != "test.hello" {
t.Errorf("expected test.hello, got %s", entries[0].Name)
}
}
func TestProcessGet_FullName(t *testing.T) {
setupTestData(t)
e, ok := doc.Get(doc.TypeProcess, "http.post")
if !ok {
t.Fatal("http.post not found")
}
if e.Desc != "Send HTTP POST" {
t.Errorf("desc = %q", e.Desc)
}
}
func TestProcessValidate_OK(t *testing.T) {
setupTestData(t)
r := doc.Validate(doc.TypeProcess, "test.hello")
if !r.Valid {
t.Fatal("expected valid")
}
if r.Status != "ok" {
t.Errorf("status = %q", r.Status)
}
}
func TestProcessValidate_FullName(t *testing.T) {
setupTestData(t)
r := doc.Validate(doc.TypeProcess, "http.get")
if !r.Valid {
t.Fatal("expected valid for http.get")
}
}
func TestProcessValidate_NotFound(t *testing.T) {
setupTestData(t)
r := doc.Validate(doc.TypeProcess, "does.not.exist")
if r.Valid {
t.Fatal("expected not valid")
}
}
func TestProcessValidate_Suggestions(t *testing.T) {
setupTestData(t)
r := doc.Validate(doc.TypeProcess, "test.hell")
if r.Valid {
t.Fatal("expected not valid")
}
found := false
for _, s := range r.Suggestion {
if s == "test.hello" {
found = true
}
}
if !found {
t.Errorf("expected test.hello in suggestions: %v", r.Suggestion)
}
}
func TestRuntimeList(t *testing.T) {
setupTestData(t)
objects := doc.List(doc.TypeJSObject)
if len(objects) != 1 {
t.Errorf("expected 1 object, got %d", len(objects))
}
classes := doc.List(doc.TypeJSClass)
if len(classes) != 1 {
t.Errorf("expected 1 class, got %d", len(classes))
}
functions := doc.List(doc.TypeJSFunction)
if len(functions) != 1 {
t.Errorf("expected 1 function, got %d", len(functions))
}
}
func TestRuntimeValidate_Object(t *testing.T) {
setupTestData(t)
r := doc.Validate(doc.TypeJSObject, "log")
if !r.Valid {
t.Fatal("expected valid")
}
}
func TestRuntimeValidate_Class(t *testing.T) {
setupTestData(t)
r := doc.Validate(doc.TypeJSClass, "FS")
if !r.Valid {
t.Fatal("expected valid")
}
}
func TestRuntimeValidate_Function(t *testing.T) {
setupTestData(t)
r := doc.Validate(doc.TypeJSFunction, "Process")
if !r.Valid {
t.Fatal("expected valid")
}
}
func TestFindRuntime(t *testing.T) {
setupTestData(t)
e := findRuntime("log")
if e == nil {
t.Fatal("expected to find log")
}
e = findRuntime("FS")
if e == nil {
t.Fatal("expected to find FS")
}
e = findRuntime("nonexistent")
if e != nil {
t.Fatal("expected nil")
}
}
func TestFormatArgs(t *testing.T) {
args := []doc.TypeValue{
{Name: "name", Type: "string", Required: true},
{Name: "options", Type: "object"},
}
s := formatArgs(args)
if s != "(name string, options object?)" {
t.Errorf("formatArgs = %q", s)
}
s = formatArgs(nil)
if s != "()" {
t.Errorf("formatArgs nil = %q", s)
}
}
func TestFormatReturn(t *testing.T) {
if formatReturn(nil) != "void" {
t.Error("nil should return void")
}
tv := &doc.TypeValue{Type: "string"}
if formatReturn(tv) != "string" {
t.Error("string type mismatch")
}
}

298
cmd/doc/process.go Normal file
View file

@ -0,0 +1,298 @@
package doc
import (
"fmt"
"strings"
"github.com/spf13/cobra"
"github.com/yaoapp/gou/doc"
"github.com/yaoapp/gou/fs"
"github.com/yaoapp/gou/model"
"github.com/yaoapp/gou/process"
"github.com/yaoapp/gou/schedule"
"github.com/yaoapp/gou/store"
"github.com/yaoapp/gou/task"
)
// ProcessCmd is the parent command for process documentation.
var ProcessCmd = &cobra.Command{
Use: "process",
Short: "Process documentation",
Long: "List, inspect and validate Yao process documentation",
Run: func(cmd *cobra.Command, args []string) { cmd.Help() },
}
var processListCmd = &cobra.Command{
Use: "list",
Short: "List documented processes",
Long: `List all documented processes in flat format (one per line).
Designed for grep/pipe usage:
yao doc process list | grep model
yao doc process list --group http`,
Run: func(cmd *cobra.Command, args []string) {
opts := doc.ListOption{Group: groupFlag, Search: searchFlag}
entries := doc.List(doc.TypeProcess, opts)
if jsonOutput {
printJSON(entries)
return
}
for _, e := range entries {
fmt.Printf("%-45s %s\n", doc.CallableName(e), e.Desc)
}
if showAll {
undoc := doc.AutoDiscover()
if len(undoc) > 0 {
fmt.Printf("\nUNDOCUMENTED: %d processes\n", len(undoc))
for _, name := range undoc {
fmt.Printf("%-45s (no documentation)\n", name)
}
}
}
},
}
var processInspectCmd = &cobra.Command{
Use: "inspect [process-name]",
Short: "Show detailed info for a process",
Long: `Show full documentation for a single process, including arguments,
return type, field descriptions, and examples.
yao doc process inspect http.get
yao doc process inspect models.user.Find`,
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
name := args[0]
e, ok := doc.Get(doc.TypeProcess, name)
if !ok {
fmt.Fprintf(cmd.ErrOrStderr(), "Process %q not found.\n", name)
result := doc.Validate(doc.TypeProcess, name)
if len(result.Suggestion) > 0 {
fmt.Fprintln(cmd.ErrOrStderr(), "Did you mean:")
for _, s := range result.Suggestion {
fmt.Fprintf(cmd.ErrOrStderr(), " - %s\n", s)
}
}
return
}
if jsonOutput {
printJSON(e)
return
}
printProcessDetail(e)
},
}
var processValidateCmd = &cobra.Command{
Use: "validate [process-name]",
Short: "Validate a process name",
Long: `Validate a process call using the engine's addressing logic,
check that the referenced resource exists, and show documentation.
Examples:
yao doc process validate models.user.Find
yao doc process validate http.get
yao doc process validate stores.cache.set`,
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
name := args[0]
p, err := process.Of(name)
if err != nil {
printError(cmd, name, err.Error())
return
}
if process.Handlers[p.Handler] == nil {
printError(cmd, name, fmt.Sprintf("handler %q not registered", p.Handler))
return
}
if reason := checkID(p); reason != "" {
printError(cmd, name, reason)
return
}
docResult := doc.Validate(doc.TypeProcess, name)
if jsonOutput {
out := map[string]interface{}{
"name": name,
"valid": true,
"handler": p.Handler,
"group": p.Group,
"id": p.ID,
"method": p.Method,
"documented": docResult.Valid,
}
if docResult.Entry != nil {
out["entry"] = docResult.Entry
}
printJSON(out)
return
}
fmt.Printf("✓ %s — valid\n", name)
fmt.Printf(" Handler: %s\n", p.Handler)
fmt.Printf(" Group: %s\n", p.Group)
if p.ID != "" {
fmt.Printf(" ID: %s\n", p.ID)
}
fmt.Printf(" Method: %s\n", p.Method)
fmt.Println()
if docResult.Valid && docResult.Entry != nil {
printProcessDetail(docResult.Entry)
} else {
fmt.Printf("⚠ no documentation found for %s\n", name)
}
},
}
// checkID validates the <id> segment for dynamic-ID groups by looking up the
// actual runtime registry. Returns an error message or "" if OK.
func checkID(p *process.Process) string {
switch p.Group {
case "models":
if p.ID == "" {
return fmt.Sprintf("missing <id>, correct format: models.<id>.%s", p.Method)
}
if !model.Exists(p.ID) {
return fmt.Sprintf("model %q not loaded", p.ID)
}
case "schemas":
if p.ID == "" {
return fmt.Sprintf("missing <id>, correct format: schemas.<id>.%s", p.Method)
}
case "stores":
if p.ID == "" {
return fmt.Sprintf("missing <id>, correct format: stores.<id>.%s", p.Method)
}
if _, has := store.Pools[p.ID]; !has {
return fmt.Sprintf("store %q not loaded", p.ID)
}
case "fs":
if p.ID == "" {
return fmt.Sprintf("missing <id>, correct format: fs.<id>.%s", p.Method)
}
if _, has := fs.FileSystems[p.ID]; !has {
return fmt.Sprintf("filesystem %q not registered", p.ID)
}
case "tasks":
if p.ID == "" {
return fmt.Sprintf("missing <id>, correct format: tasks.<id>.%s", p.Method)
}
if _, has := task.Tasks[p.ID]; !has {
return fmt.Sprintf("task %q not loaded", p.ID)
}
case "schedules":
if p.ID == "" {
return fmt.Sprintf("missing <id>, correct format: schedules.<id>.%s", p.Method)
}
if _, has := schedule.Schedules[p.ID]; !has {
return fmt.Sprintf("schedule %q not loaded", p.ID)
}
}
return ""
}
func printError(cmd *cobra.Command, name, msg string) {
if jsonOutput {
printJSON(map[string]interface{}{
"name": name,
"valid": false,
"error": msg,
})
return
}
fmt.Fprintf(cmd.ErrOrStderr(), "✗ %s — %s\n", name, msg)
}
func printProcessDetail(e *doc.Entry) {
fmt.Printf("Process: %s\n", doc.CallableName(e))
fmt.Printf("Group: %s\n", e.Group)
fmt.Printf("Desc: %s\n", e.Desc)
fmt.Println()
if len(e.Args) > 0 {
fmt.Println("Arguments:")
for i, a := range e.Args {
req := "required"
if !a.Required {
req = "optional"
}
fmt.Printf(" [%d] %s (%s, %s)\n", i, a.Name, a.Type, req)
if a.Desc != "" {
fmt.Printf(" %s\n", a.Desc)
}
if a.Example != nil {
fmt.Printf(" Example: %v\n", a.Example)
}
printTypeFields(a.Fields, 6)
}
fmt.Println()
}
fmt.Println("Returns:")
if e.Return == nil {
fmt.Println(" void")
} else {
printTypeValue(e.Return, 2)
}
}
func printTypeValue(tv *doc.TypeValue, indent int) {
pad := strings.Repeat(" ", indent)
fmt.Printf("%s%s", pad, tv.Type)
if tv.Desc != "" {
fmt.Printf(" — %s", tv.Desc)
}
fmt.Println()
if tv.Example != nil {
fmt.Printf("%sExample: %v\n", pad, tv.Example)
}
if len(tv.Fields) > 0 {
printTypeFields(tv.Fields, indent)
}
if tv.Items != nil {
fmt.Printf("%sItems:\n", pad)
printTypeValue(tv.Items, indent+2)
}
if len(tv.Variants) > 0 {
for i, v := range tv.Variants {
fmt.Printf("%sVariant %d: ", pad, i+1)
desc := v.Type
if v.Desc != "" {
desc += " — " + v.Desc
}
fmt.Println(desc)
}
}
}
func printTypeFields(fields []doc.TypeValue, indent int) {
if len(fields) == 0 {
return
}
pad := strings.Repeat(" ", indent)
fmt.Printf("%sFields:\n", pad)
for _, f := range fields {
req := ""
if f.Required {
req = ", required"
}
fmt.Printf("%s .%-20s %s%s\n", pad, f.Name, f.Type, req)
if f.Desc != "" {
fmt.Printf("%s %s\n", pad, f.Desc)
}
}
}

182
cmd/doc/runtime.go Normal file
View file

@ -0,0 +1,182 @@
package doc
import (
"fmt"
"github.com/spf13/cobra"
"github.com/yaoapp/gou/doc"
)
// RuntimeCmd is the parent command for runtime API documentation.
var RuntimeCmd = &cobra.Command{
Use: "runtime",
Short: "JS runtime API documentation",
Long: "List, inspect and validate JS runtime global objects, functions, and classes",
Run: func(cmd *cobra.Command, args []string) { cmd.Help() },
}
var runtimeListCmd = &cobra.Command{
Use: "list",
Short: "List JS runtime APIs",
Long: `List all documented JS global objects, functions, and classes.
Designed for grep/pipe usage:
yao doc runtime list | grep FS
yao doc runtime list --type class`,
Run: func(cmd *cobra.Command, args []string) {
types := runtimeTypes()
var allEntries []*doc.Entry
for _, t := range types {
opts := doc.ListOption{Search: searchFlag}
allEntries = append(allEntries, doc.List(t, opts)...)
}
if jsonOutput {
printJSON(allEntries)
return
}
for _, e := range allEntries {
tag := string(e.Type)
extra := ""
if len(e.Methods) > 0 {
extra = fmt.Sprintf(" (%d methods)", len(e.Methods))
}
fmt.Printf("%-20s [%-11s] %s%s\n", e.Name, tag, e.Desc, extra)
}
},
}
var runtimeInspectCmd = &cobra.Command{
Use: "inspect [name]",
Short: "Show detailed info for a JS runtime API",
Long: `Show full documentation for a JS global object, function, or class.
yao doc runtime inspect FS
yao doc runtime inspect log
yao doc runtime inspect Process`,
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
name := args[0]
entry := findRuntime(name)
if entry == nil {
fmt.Fprintf(cmd.ErrOrStderr(), "Runtime API %q not found.\n", name)
for _, t := range []doc.EntryType{doc.TypeJSObject, doc.TypeJSClass, doc.TypeJSFunction} {
r := doc.Validate(t, name)
if len(r.Suggestion) > 0 {
fmt.Fprintln(cmd.ErrOrStderr(), "Did you mean:")
for _, s := range r.Suggestion {
fmt.Fprintf(cmd.ErrOrStderr(), " - %s\n", s)
}
break
}
}
return
}
if jsonOutput {
printJSON(entry)
return
}
printRuntimeDetail(entry)
},
}
var runtimeValidateCmd = &cobra.Command{
Use: "validate [name]",
Short: "Validate a JS runtime API name",
Long: "Check if a JS global name is documented (e.g. FS, log, Process)",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
name := args[0]
var result *doc.ValidationResult
for _, t := range []doc.EntryType{doc.TypeJSObject, doc.TypeJSClass, doc.TypeJSFunction} {
r := doc.Validate(t, name)
if r.Valid {
result = r
break
}
if result == nil || len(r.Suggestion) > len(result.Suggestion) {
result = r
}
}
if jsonOutput {
printJSON(result)
return
}
if result.Valid {
fmt.Printf("✓ %s — %s (type: %s)\n", result.Name, result.Message, result.Entry.Type)
} else {
fmt.Printf("✗ %s — %s (status: %s)\n", result.Name, result.Message, result.Status)
if len(result.Suggestion) > 0 {
fmt.Println(" Did you mean:")
for _, s := range result.Suggestion {
fmt.Printf(" - %s\n", s)
}
}
}
},
}
func findRuntime(name string) *doc.Entry {
for _, t := range []doc.EntryType{doc.TypeJSObject, doc.TypeJSClass, doc.TypeJSFunction} {
e, ok := doc.Get(t, name)
if ok {
return e
}
}
return nil
}
func printRuntimeDetail(e *doc.Entry) {
fmt.Printf("Name: %s\n", e.Name)
fmt.Printf("Type: %s\n", e.Type)
fmt.Printf("Desc: %s\n", e.Desc)
if len(e.Args) > 0 {
fmt.Println()
fmt.Println("Constructor Arguments:")
for i, a := range e.Args {
req := "required"
if !a.Required {
req = "optional"
}
fmt.Printf(" [%d] %s (%s, %s)\n", i, a.Name, a.Type, req)
if a.Desc != "" {
fmt.Printf(" %s\n", a.Desc)
}
}
}
if e.Return != nil {
fmt.Println()
fmt.Println("Returns:")
printTypeValue(e.Return, 2)
}
if len(e.Methods) > 0 {
fmt.Println()
fmt.Printf("Methods (%d):\n", len(e.Methods))
for _, m := range e.Methods {
ret := formatReturn(m.Return)
fmt.Printf(" .%-25s %s → %s\n", m.Name+formatArgs(m.Args), m.Desc, ret)
if m.Return != nil && len(m.Return.Fields) > 0 {
printTypeFields(m.Return.Fields, 4)
}
}
}
}
func runtimeTypes() []doc.EntryType {
switch typeFlag {
case "object":
return []doc.EntryType{doc.TypeJSObject}
case "function":
return []doc.EntryType{doc.TypeJSFunction}
case "class":
return []doc.EntryType{doc.TypeJSClass}
default:
return []doc.EntryType{doc.TypeJSObject, doc.TypeJSClass, doc.TypeJSFunction}
}
}

View file

@ -8,6 +8,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/yaoapp/kun/exception" "github.com/yaoapp/kun/exception"
"github.com/yaoapp/yao/cmd/agent" "github.com/yaoapp/yao/cmd/agent"
yaodoc "github.com/yaoapp/yao/cmd/doc"
"github.com/yaoapp/yao/cmd/mcp" "github.com/yaoapp/yao/cmd/mcp"
"github.com/yaoapp/yao/cmd/robot" "github.com/yaoapp/yao/cmd/robot"
"github.com/yaoapp/yao/cmd/sui" "github.com/yaoapp/yao/cmd/sui"
@ -167,6 +168,18 @@ var robotCmd = &cobra.Command{
}, },
} }
var docCmd = &cobra.Command{
Use: "doc",
Short: "Documentation and API reference",
Long: "Browse and validate documentation for processes, JS runtime APIs, and more",
CompletionOptions: cobra.CompletionOptions{
DisableDefaultCmd: true,
},
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
},
}
// Command initialize // Command initialize
func init() { func init() {
@ -192,6 +205,10 @@ func init() {
// Robot // Robot
robotCmd.AddCommand(robot.AddCmd) robotCmd.AddCommand(robot.AddCmd)
// Doc
docCmd.AddCommand(yaodoc.ProcessCmd)
docCmd.AddCommand(yaodoc.RuntimeCmd)
rootCmd.AddCommand( rootCmd.AddCommand(
versionCmd, versionCmd,
migrateCmd, migrateCmd,
@ -210,6 +227,7 @@ func init() {
agentCmd, agentCmd,
mcpCmd, mcpCmd,
robotCmd, robotCmd,
docCmd,
upgradeCmd, upgradeCmd,
) )
// rootCmd.SetHelpCommand(helpCmd) // rootCmd.SetHelpCommand(helpCmd)

11
crypto/doc.go Normal file
View file

@ -0,0 +1,11 @@
package crypto
import (
_ "embed"
"github.com/yaoapp/gou/doc"
)
//go:embed doc.yml
var docYAML []byte
func init() { doc.LoadYAML(docYAML) }

171
crypto/doc.yml Normal file
View file

@ -0,0 +1,171 @@
group: crypto
type: process
entries:
- name: Hash
desc: Compute a cryptographic hash of a string value
args:
- name: algorithm
type: string
required: true
desc: "Hash algorithm: MD4, MD5, SHA1, SHA224, SHA256, SHA384, SHA512, MD5SHA1, RIPEMD160, SHA3_224, SHA3_256, SHA3_384, SHA3_512, SHA512_224, SHA512_256, BLAKE2s_256, BLAKE2b_256, BLAKE2b_384, BLAKE2b_512"
- name: value
type: string
required: true
desc: String value to hash
return:
type: string
desc: Hex-encoded hash string
- name: Hmac
desc: Compute a Keyed-Hash Message Authentication Code (HMAC)
args:
- name: algorithm
type: string
required: true
desc: "Hash algorithm: MD4, MD5, SHA1, SHA224, SHA256, SHA384, SHA512, etc."
- name: value
type: string
required: true
desc: String value to hash
- name: key
type: string
required: true
desc: Secret key for HMAC
- name: encoding
type: string
required: false
desc: "Output encoding: \"base64\" for base64 output (default: hex)"
return:
type: string
desc: HMAC hash string (hex or base64 encoded)
- name: hmacwith
desc: Compute HMAC with advanced encoding options for key, value, and output
args:
- name: option
type: object
required: true
desc: "Encoding options: {key: \"base64\"|\"hex\", value: \"base64\"|\"hex\", output: \"base64\"|\"hex\", algo: \"SHA256\"}"
- name: value
type: string
required: true
desc: Value to hash (encoding specified in option)
- name: key
type: string
required: true
desc: Secret key (encoding specified in option)
return:
type: string
desc: HMAC hash string with specified output encoding
- name: rsa2sign
desc: Create an RSA-SHA2 digital signature
args:
- name: privateKey
type: string
required: true
desc: RSA private key in PEM format
- name: algorithm
type: string
required: true
desc: "Hash algorithm: SHA256, SHA384, SHA512, etc."
- name: value
type: string
required: true
desc: Data to sign
- name: encoding
type: string
required: false
desc: "Output encoding: \"base64\" for base64 output (default: hex)"
return:
type: string
desc: Digital signature string (hex or base64 encoded)
- name: rsa2verify
desc: Verify an RSA-SHA2 digital signature
args:
- name: publicKey
type: string
required: true
desc: RSA public key in PEM format
- name: algorithm
type: string
required: true
desc: "Hash algorithm: SHA256, SHA384, SHA512, etc."
- name: value
type: string
required: true
desc: Original data that was signed
- name: signature
type: string
required: true
desc: Signature to verify (hex or base64 encoded)
- name: encoding
type: string
required: false
desc: "Signature encoding: \"base64\" if signature is base64-encoded (default: hex)"
return:
type: bool
desc: True if signature is valid
- name: aes256encrypt
desc: Encrypt data using AES-256 algorithm
args:
- name: algorithm
type: string
required: true
desc: "AES mode: \"GCM\""
- name: key
type: string
required: true
desc: AES-256 encryption key (32 bytes)
- name: nonce
type: string
required: true
desc: Nonce/IV for encryption
- name: text
type: string
required: true
desc: Plaintext to encrypt
- name: additionalData
type: string
required: false
desc: Additional authenticated data (AAD) for GCM mode
- name: encoding
type: string
required: false
desc: "Output encoding: \"base64\" for base64 output (default: hex)"
return:
type: string
desc: Encrypted ciphertext (hex or base64 encoded)
- name: aes256decrypt
desc: Decrypt data using AES-256 algorithm
args:
- name: algorithm
type: string
required: true
desc: "AES mode: \"GCM\""
- name: key
type: string
required: true
desc: AES-256 decryption key (32 bytes)
- name: nonce
type: string
required: true
desc: Nonce/IV used during encryption
- name: ciphertext
type: string
required: true
desc: Encrypted data to decrypt (hex or base64 encoded)
- name: additionalData
type: string
required: false
desc: Additional authenticated data (AAD) used during encryption
- name: encoding
type: string
required: false
desc: "Input encoding: \"base64\" if ciphertext is base64-encoded (default: hex)"
return:
type: string
desc: Decrypted plaintext

11
engine/doc.go Normal file
View file

@ -0,0 +1,11 @@
package engine
import (
_ "embed"
"github.com/yaoapp/gou/doc"
)
//go:embed doc.yml
var docYAML []byte
func init() { doc.LoadYAML(docYAML) }

92
engine/doc.yml Normal file
View file

@ -0,0 +1,92 @@
group: utils.app
type: process
desc: "Utility and app bootstrap processes for health checks and system inspection"
entries:
# ── utils.app (current) ──────────────────────────────────────────
- name: Ping
desc: Return engine name, version, and application root path
args: []
return:
type: object
desc: "Object with engine, version, and root fields"
- name: Inspect
desc: Return detailed system information including version, CUI, build name, config, and external tools
args: []
return:
type: object
desc: "Object with VERSION, CUI, BUILDNAME, CONFIG, and optionally TOOLS fields"
# ── xiang.main (deprecated, aliased to utils.app) ───────────────
- name: Ping
group: xiang.main
desc: "[Deprecated: use utils.app.Ping] Return engine name, version, and application root path"
args: []
return:
type: object
desc: "Object with engine, version, and root fields"
- name: Inspect
group: xiang.main
desc: "[Deprecated: use utils.app.Inspect] Return detailed system information"
args: []
return:
type: object
desc: "Object with VERSION, CUI, BUILDNAME, CONFIG, and optionally TOOLS fields"
- name: Favicon
group: xiang.main
desc: "[Deprecated] Return the application favicon (currently returns null)"
args: []
return:
type: "null"
desc: "Always returns null"
- name: FileContent
group: xiang.main
desc: "[Deprecated] Return file content from storage (currently returns null)"
args:
- name: filename
type: string
required: false
desc: "File path to read (handler is disabled)"
- name: encode
type: bool
required: false
desc: "Whether to base64 encode the content (handler is disabled)"
return:
type: "null"
desc: "Always returns null"
- name: AppFileContent
group: xiang.main
desc: "[Deprecated] Return application data file content (currently returns null)"
args:
- name: filename
type: string
required: false
desc: "Application data file path to read (handler is disabled)"
- name: encode
type: bool
required: false
desc: "Whether to base64 encode the content (handler is disabled)"
return:
type: "null"
desc: "Always returns null"
# ── xiang.sys (deprecated aliases) ──────────────────────────────
- name: Ping
group: xiang.sys
desc: "[Deprecated: use utils.app.Ping] Alias of xiang.main.Ping"
args: []
return:
type: object
desc: "Object with engine, version, and root fields"
- name: Inspect
group: xiang.sys
desc: "[Deprecated: use utils.app.Inspect] Alias of xiang.main.Inspect"
args: []
return:
type: object
desc: "Object with VERSION, CUI, BUILDNAME, CONFIG, and optionally TOOLS fields"

12
excel/doc.go Normal file
View file

@ -0,0 +1,12 @@
package excel
import (
_ "embed"
"github.com/yaoapp/gou/doc"
)
//go:embed doc.yml
var docYAML []byte
func init() { doc.LoadYAML(docYAML) }

678
excel/doc.yml Normal file
View file

@ -0,0 +1,678 @@
group: excel
type: process
entries:
# File operations
- name: open
desc: Open an Excel file and return a handle for subsequent operations
args:
- name: file
type: string
required: true
desc: File path relative to the data directory
- name: writable
type: bool
required: false
desc: "Whether to open in writable mode (default: false)"
return:
type: string
desc: Handle string for referencing the opened file
- name: close
desc: Close an opened Excel file and release resources
args:
- name: handle
type: string
required: true
desc: File handle from excel.open
return:
type: "null"
desc: Returns null on success
- name: save
desc: Save the current state of an opened Excel file to disk
args:
- name: handle
type: string
required: true
desc: File handle from excel.open
return:
type: "null"
desc: Returns null on success
- name: sheets
desc: Get the list of sheet names in an Excel file
args:
- name: handle
type: string
required: true
desc: File handle from excel.open
return:
type: array
desc: Array of sheet name strings
# Sheet operations
- name: sheet.create
desc: Create a new sheet in an Excel file
args:
- name: handle
type: string
required: true
desc: File handle from excel.open
- name: name
type: string
required: true
desc: Name for the new sheet
return:
type: number
desc: Index of the created sheet
- name: sheet.read
desc: Read all data from a sheet
args:
- name: handle
type: string
required: true
desc: File handle from excel.open
- name: name
type: string
required: true
desc: Sheet name
return:
type: array
desc: 2D array of sheet data
- name: sheet.update
desc: Update a sheet with new data (overwrites existing content)
args:
- name: handle
type: string
required: true
desc: File handle from excel.open
- name: name
type: string
required: true
desc: Sheet name
- name: data
type: array
required: true
desc: 2D array of data to write
return:
type: "null"
desc: Returns null on success
- name: sheet.delete
desc: Delete a sheet from an Excel file
args:
- name: handle
type: string
required: true
desc: File handle from excel.open
- name: name
type: string
required: true
desc: Sheet name to delete
return:
type: "null"
desc: Returns null on success
- name: sheet.copy
desc: Copy a sheet to a new sheet
args:
- name: handle
type: string
required: true
desc: File handle from excel.open
- name: source
type: string
required: true
desc: Source sheet name
- name: target
type: string
required: true
desc: Target sheet name
return:
type: "null"
desc: Returns null on success
- name: sheet.list
desc: List all sheets with their metadata
args:
- name: handle
type: string
required: true
desc: File handle from excel.open
return:
type: array
desc: Array of sheet information objects
- name: sheet.exists
desc: Check if a sheet exists in an Excel file
args:
- name: handle
type: string
required: true
desc: File handle from excel.open
- name: name
type: string
required: true
desc: Sheet name to check
return:
type: bool
desc: True if the sheet exists
- name: sheet.rows
desc: Read a range of rows from a sheet
args:
- name: handle
type: string
required: true
desc: File handle from excel.open
- name: name
type: string
required: true
desc: Sheet name
- name: start
type: number
required: true
desc: Start row index (0-based)
- name: size
type: number
required: true
desc: Number of rows to read
return:
type: array
desc: 2D array of row data
- name: sheet.dimension
desc: Get the dimensions (rows and columns count) of a sheet
args:
- name: handle
type: string
required: true
desc: File handle from excel.open
- name: name
type: string
required: true
desc: Sheet name
return:
type: object
desc: "Object with rows and cols counts (e.g. {rows: 100, cols: 10})"
# Read operations
- name: read.cell
desc: Read the value of a single cell
args:
- name: handle
type: string
required: true
desc: File handle from excel.open
- name: sheet
type: string
required: true
desc: Sheet name
- name: cell
type: string
required: true
desc: "Cell reference (e.g. \"A1\", \"B2\")"
return:
type: string
desc: Cell value as string
- name: read.row
desc: Read all rows from a sheet
args:
- name: handle
type: string
required: true
desc: File handle from excel.open
- name: sheet
type: string
required: true
desc: Sheet name
return:
type: array
desc: 2D array of all row data
- name: read.column
desc: Read all columns from a sheet
args:
- name: handle
type: string
required: true
desc: File handle from excel.open
- name: sheet
type: string
required: true
desc: Sheet name
return:
type: array
desc: 2D array of column data
# Write operations
- name: write.cell
desc: Write a value to a single cell
args:
- name: handle
type: string
required: true
desc: File handle from excel.open
- name: sheet
type: string
required: true
desc: Sheet name
- name: cell
type: string
required: true
desc: "Cell reference (e.g. \"A1\")"
- name: value
type: any
required: true
desc: Value to write
return:
type: "null"
desc: Returns null on success
- name: write.row
desc: Write values to a row starting from a cell
args:
- name: handle
type: string
required: true
desc: File handle from excel.open
- name: sheet
type: string
required: true
desc: Sheet name
- name: cell
type: string
required: true
desc: "Starting cell reference (e.g. \"A1\")"
- name: values
type: array
required: true
desc: Array of values to write across the row
return:
type: "null"
desc: Returns null on success
- name: write.column
desc: Write values to a column starting from a cell
args:
- name: handle
type: string
required: true
desc: File handle from excel.open
- name: sheet
type: string
required: true
desc: Sheet name
- name: cell
type: string
required: true
desc: "Starting cell reference (e.g. \"A1\")"
- name: values
type: array
required: true
desc: Array of values to write down the column
return:
type: "null"
desc: Returns null on success
- name: write.all
desc: Write a 2D array of data starting from a cell
args:
- name: handle
type: string
required: true
desc: File handle from excel.open
- name: sheet
type: string
required: true
desc: Sheet name
- name: cell
type: string
required: true
desc: "Starting cell reference (e.g. \"A1\")"
- name: values
type: array
required: true
desc: 2D array of values (array of row arrays)
return:
type: "null"
desc: Returns null on success
# Style & formatting
- name: set.style
desc: Apply a style to a cell
args:
- name: handle
type: string
required: true
desc: File handle from excel.open
- name: sheet
type: string
required: true
desc: Sheet name
- name: cell
type: string
required: true
desc: "Cell reference (e.g. \"A1\")"
- name: styleID
type: number
required: true
desc: Style ID to apply
return:
type: "null"
desc: Returns null on success
- name: set.formula
desc: Set a formula for a cell
args:
- name: handle
type: string
required: true
desc: File handle from excel.open
- name: sheet
type: string
required: true
desc: Sheet name
- name: cell
type: string
required: true
desc: "Cell reference (e.g. \"A1\")"
- name: formula
type: string
required: true
desc: "Excel formula string (e.g. \"=SUM(A1:A10)\")"
return:
type: "null"
desc: Returns null on success
- name: set.link
desc: Set a hyperlink for a cell
args:
- name: handle
type: string
required: true
desc: File handle from excel.open
- name: sheet
type: string
required: true
desc: Sheet name
- name: cell
type: string
required: true
desc: "Cell reference (e.g. \"A1\")"
- name: link
type: string
required: true
desc: Hyperlink URL
- name: text
type: string
required: true
desc: Link type or display text
return:
type: "null"
desc: Returns null on success
- name: set.richtext
desc: Set rich text content for a cell
args:
- name: handle
type: string
required: true
desc: File handle from excel.open
- name: sheet
type: string
required: true
desc: Sheet name
- name: cell
type: string
required: true
desc: "Cell reference (e.g. \"A1\")"
- name: richText
type: array
required: true
desc: "Array of rich text run objects: [{text: \"...\"}]"
return:
type: "null"
desc: Returns null on success
- name: set.comment
desc: Set a comment on a sheet
args:
- name: handle
type: string
required: true
desc: File handle from excel.open
- name: sheet
type: string
required: true
desc: Sheet name
- name: comment
type: object
required: true
desc: Comment data object
return:
type: "null"
desc: Returns null on success
- name: set.rowheight
desc: Set the height of a row
args:
- name: handle
type: string
required: true
desc: File handle from excel.open
- name: sheet
type: string
required: true
desc: Sheet name
- name: row
type: number
required: true
desc: Row number (1-based)
- name: height
type: number
required: true
desc: Row height in points
return:
type: "null"
desc: Returns null on success
- name: set.columnwidth
desc: Set the width of columns in a range
args:
- name: handle
type: string
required: true
desc: File handle from excel.open
- name: sheet
type: string
required: true
desc: Sheet name
- name: startCol
type: string
required: true
desc: "Start column letter (e.g. \"A\")"
- name: endCol
type: string
required: true
desc: "End column letter (e.g. \"D\")"
- name: width
type: number
required: true
desc: Column width
return:
type: "null"
desc: Returns null on success
- name: set.mergecell
desc: Merge a range of cells
args:
- name: handle
type: string
required: true
desc: File handle from excel.open
- name: sheet
type: string
required: true
desc: Sheet name
- name: start
type: string
required: true
desc: "Top-left cell reference (e.g. \"A1\")"
- name: end
type: string
required: true
desc: "Bottom-right cell reference (e.g. \"D4\")"
return:
type: "null"
desc: Returns null on success
- name: set.unmergecell
desc: Unmerge a range of cells
args:
- name: handle
type: string
required: true
desc: File handle from excel.open
- name: sheet
type: string
required: true
desc: Sheet name
- name: start
type: string
required: true
desc: "Top-left cell reference (e.g. \"A1\")"
- name: end
type: string
required: true
desc: "Bottom-right cell reference (e.g. \"D4\")"
return:
type: "null"
desc: Returns null on success
# Iterator operations
- name: each.openrow
desc: Open a row iterator for streaming row-by-row reading
args:
- name: handle
type: string
required: true
desc: File handle from excel.open
- name: sheet
type: string
required: true
desc: Sheet name
return:
type: string
desc: Iterator ID for use with nextrow/closerow
- name: each.closerow
desc: Close a row iterator and release resources
args:
- name: id
type: string
required: true
desc: Iterator ID from each.openrow
return:
type: "null"
desc: Returns null
- name: each.nextrow
desc: Get the next row from the iterator; returns null when exhausted
args:
- name: id
type: string
required: true
desc: Iterator ID from each.openrow
return:
type: array
desc: Array of cell values for the row, or null if no more rows
- name: each.opencolumn
desc: Open a column iterator for streaming column-by-column reading
args:
- name: handle
type: string
required: true
desc: File handle from excel.open
- name: sheet
type: string
required: true
desc: Sheet name
return:
type: string
desc: Iterator ID for use with nextcolumn/closecolumn
- name: each.closecolumn
desc: Close a column iterator and release resources
args:
- name: id
type: string
required: true
desc: Iterator ID from each.opencolumn
return:
type: "null"
desc: Returns null
- name: each.nextcolumn
desc: Get the next column from the iterator; returns null when exhausted
args:
- name: id
type: string
required: true
desc: Iterator ID from each.opencolumn
return:
type: array
desc: Array of cell values for the column, or null if no more columns
# Conversion utilities
- name: convert.columnnametonumber
desc: "Convert a column letter name to a number (e.g. \"A\" -> 1, \"Z\" -> 26)"
args:
- name: name
type: string
required: true
desc: "Column letter name (e.g. \"A\", \"AB\")"
return:
type: number
desc: Column number (1-based)
- name: convert.columnnumbertoname
desc: "Convert a column number to a letter name (e.g. 1 -> \"A\", 26 -> \"Z\")"
args:
- name: number
type: number
required: true
desc: Column number (1-based)
return:
type: string
desc: Column letter name
- name: convert.cellnametocoordinates
desc: "Convert a cell name to column and row coordinates (e.g. \"B3\" -> [2, 3])"
args:
- name: cell
type: string
required: true
desc: "Cell reference (e.g. \"A1\", \"B3\")"
return:
type: array
desc: "[column, row] coordinates (1-based)"
- name: convert.coordinatestocellname
desc: "Convert column and row coordinates to a cell name (e.g. 2, 3 -> \"B3\")"
args:
- name: col
type: number
required: true
desc: Column number (1-based)
- name: row
type: number
required: true
desc: Row number (1-based)
return:
type: string
desc: "Cell reference string (e.g. \"B3\")"

12
helper/doc.go Normal file
View file

@ -0,0 +1,12 @@
package helper
import (
_ "embed"
"github.com/yaoapp/gou/doc"
)
//go:embed doc.yml
var docYAML []byte
func init() { doc.LoadYAML(docYAML) }

473
helper/doc.yml Normal file
View file

@ -0,0 +1,473 @@
group: xiang.helper
type: process
entries:
# Array operations
- name: ArrayPluck
desc: "[Deprecated: use utils.arr.Pluck] Merge multiple record sets into one by plucking specified columns"
args:
- name: columns
type: array
required: true
desc: Array of column names to pluck
- name: data
type: object
required: true
desc: Map of column names to value arrays
return:
type: array
desc: Merged array of records
- name: ArraySplit
desc: "[Deprecated: use utils.arr.Split] Split an array of records into columns and values"
args:
- name: records
type: array
required: true
desc: Array of record objects
return:
type: object
desc: "Object with columns (string[]) and values (any[][])"
- name: ArrayColumn
desc: "[Deprecated: use utils.arr.Column] Extract values of a specified field from an array of records"
args:
- name: records
type: array
required: true
desc: Array of record objects
- name: name
type: string
required: true
desc: Field name to extract
return:
type: array
desc: Array of field values
- name: ArrayKeep
desc: "[Deprecated: use utils.arr.Keep] Keep only specified keys in each record"
args:
- name: records
type: array
required: true
desc: Array of record objects
- name: columns
type: array
required: true
desc: Array of key names to keep
return:
type: array
desc: Filtered array of records
- name: ArrayTree
desc: "[Deprecated: use utils.arr.Tree] Convert a flat array of records into a tree structure"
args:
- name: records
type: array
required: true
desc: Array of record objects
- name: setting
type: object
required: true
desc: "Tree settings: {primary, parent, children, etc.}"
return:
type: array
desc: Tree-structured array
- name: ArrayUnique
desc: "[Deprecated: use utils.arr.Unique] Remove duplicate values from an array"
args:
- name: array
type: array
required: true
desc: Array to deduplicate
return:
type: array
desc: Array with duplicates removed
- name: ArrayMapSet
desc: "[Deprecated: use utils.arr.MapSet] Set a field value on every map in an array"
args:
- name: records
type: array
required: true
desc: Array of map objects
- name: key
type: string
required: true
desc: Key to set in each map
- name: value
type: any
required: true
desc: Value to set
return:
type: array
desc: Modified array
- name: ArrayIndexes
desc: "[Deprecated: use utils.arr.Indexes] Return the index numbers of an array"
args:
- name: array
type: array
required: true
desc: Input array
return:
type: array
desc: Array of integer indexes
- name: ArrayGet
desc: "[Deprecated: use utils.arr.Get] Get an element at a specified index from an array"
args:
- name: array
type: array
required: true
desc: Input array
- name: index
type: number
required: true
desc: Index to retrieve
return:
type: any
desc: Element at the given index, or null if out of range
# Map operations
- name: MapKeys
desc: "[Deprecated: use utils.map.Keys] Return all keys of a map"
args:
- name: record
type: object
required: true
desc: Input map
return:
type: array
desc: Array of key strings
- name: MapValues
desc: "[Deprecated: use utils.map.Values] Return all values of a map"
args:
- name: record
type: object
required: true
desc: Input map
return:
type: array
desc: Array of values
- name: MapGet
desc: "[Deprecated: use utils.map.Get] Get a value by key from a map (supports dot notation)"
args:
- name: record
type: object
required: true
desc: Input map
- name: key
type: string
required: true
desc: Key name (supports dot notation for nested access)
return:
type: any
desc: Value at the given key
- name: MapSet
desc: "[Deprecated: use utils.map.Set] Set a key-value pair in a map (supports dot notation)"
args:
- name: record
type: object
required: true
desc: Input map
- name: key
type: string
required: true
desc: Key name (supports dot notation for nested access)
- name: value
type: any
required: true
desc: Value to set
return:
type: object
desc: Modified map
- name: MapDel
desc: "[Deprecated: use utils.map.Del] Delete a key from a map"
args:
- name: record
type: object
required: true
desc: Input map
- name: key
type: string
required: true
desc: Key name to delete
return:
type: object
desc: Modified map
- name: MapMultiDel
desc: "[Deprecated: use utils.map.DelMany] Delete multiple keys from a map"
args:
- name: record
type: object
required: true
desc: Input map
- name: keys
type: string
required: true
desc: Keys to delete (variadic)
return:
type: object
desc: Modified map
- name: MapToArray
desc: "[Deprecated: use utils.map.Array] Convert a map to an array of key-value objects"
args:
- name: record
type: object
required: true
desc: Input map
return:
type: array
desc: "Array of {key, value} objects"
# String operations
- name: StrConcat
desc: "[Deprecated: use utils.str.Concat] Concatenate multiple values into a string"
args:
- name: values
type: any
required: true
desc: Values to concatenate (variadic, minimum 2)
return:
type: string
desc: Concatenated string
- name: HexToString
desc: "[Deprecated: use utils.str.Hex] Encode a string or byte array to hexadecimal"
args:
- name: input
type: any
required: true
desc: String or byte array to encode
return:
type: string
desc: Hex-encoded string
# Captcha
- name: Captcha
desc: "[Deprecated: use utils.captcha.Make] Generate a captcha image/audio"
args:
- name: params
type: any
required: true
desc: "URL-style params with width, height, length, type, lang, background"
return:
type: object
desc: "Object with id and content (base64 image/audio data)"
- name: CaptchaValidate
desc: "[Deprecated: use utils.captcha.Verify] Validate a captcha code"
args:
- name: id
type: string
required: true
desc: Captcha ID
- name: code
type: string
required: true
desc: User-entered captcha code
return:
type: bool
desc: True if valid; throws exception if invalid
# Password
- name: PasswordValidate
desc: "[Deprecated: use utils.pwd.Verify] Validate a password against a bcrypt hash"
args:
- name: password
type: string
required: true
desc: Plain text password
- name: passwordHash
type: string
required: true
desc: Bcrypt hash to compare against
return:
type: bool
desc: True if password matches; throws exception if invalid
# JWT
- name: JwtMake
desc: "[Deprecated: use utils.jwt.Make] Generate a JWT token"
args:
- name: id
type: number
required: true
desc: User ID
- name: data
type: object
required: true
desc: Custom claims data
- name: option
type: object
required: false
desc: "Options: {subject, audience, issuer, timeout (seconds), sid, expires_at}"
return:
type: object
desc: "JWT token object with token string and expires_at timestamp"
- name: JwtValidate
desc: "[Deprecated: use utils.jwt.Verify] Validate and parse a JWT token"
args:
- name: token
type: string
required: true
desc: JWT token string
return:
type: object
desc: "Decoded JWT claims: {id, sid, data, ...standard claims}"
# Flow control
- name: For
desc: "[Deprecated: use utils.flow.For] Execute a process in a loop from start to end"
args:
- name: from
type: number
required: true
desc: Start index (inclusive)
- name: to
type: number
required: true
desc: End index (exclusive)
- name: process
type: object
required: true
desc: "Process definition: {process: \"name\", args: [\"::key\", \"::value\"]}"
return:
type: "null"
desc: Returns null
- name: Each
desc: "[Deprecated: use utils.flow.Each] Iterate over a value (array, map, or integer) and execute a process"
args:
- name: data
type: any
required: true
desc: Value to iterate over (array, map, or integer)
- name: process
type: object
required: true
desc: "Process definition: {process: \"name\", args: [\"::key\", \"::value\"]}"
return:
type: "null"
desc: Returns null
- name: Case
desc: "[Deprecated: use utils.flow.Case] Execute the first process whose conditions are met"
args:
- name: cases
type: object
required: true
desc: "Case objects (variadic): {when: [{...conditions}], process: \"name\", args: [...]}"
return:
type: any
desc: Return value from the matched process, or null if no match
- name: IF
desc: "[Deprecated: use utils.flow.IF] Conditional execution with optional else branch"
args:
- name: condition
type: object
required: true
desc: "Primary condition: {when: [{...conditions}], process: \"name\", args: [...]}"
- name: else
type: object
required: false
desc: "Else condition: {when: [{...conditions}], process: \"name\", args: [...]}"
return:
type: any
desc: Return value from the executed process, or null
- name: Throw
desc: "[Deprecated: use utils.flow.Throw] Throw an exception with a message and HTTP status code"
args:
- name: message
type: string
required: true
desc: Error message
- name: code
type: number
required: true
desc: HTTP status code
return:
type: void
desc: Does not return; throws exception
- name: Return
desc: "[Deprecated: use utils.flow.Return] Return all arguments as-is"
args:
- name: values
type: any
required: false
desc: Values to return (variadic)
return:
type: array
desc: Array of all passed arguments
# Environment
- name: EnvGet
desc: "[Deprecated: use utils.env.Get] Get an environment variable value"
args:
- name: name
type: string
required: true
desc: Environment variable name
return:
type: string
desc: Environment variable value
- name: EnvSet
desc: "[Deprecated: use utils.env.Set] Set an environment variable"
args:
- name: name
type: string
required: true
desc: Environment variable name
- name: value
type: string
required: true
desc: Value to set
return:
type: any
desc: Error on failure, null on success
- name: EnvMultiGet
desc: "[Deprecated: use utils.env.GetMany] Get multiple environment variable values"
args:
- name: names
type: string
required: true
desc: Environment variable names (variadic)
return:
type: object
desc: Map of variable names to their values
- name: EnvMultiSet
desc: "[Deprecated: use utils.env.SetMany] Set multiple environment variables"
args:
- name: envs
type: object
required: true
desc: Map of variable names to values
return:
type: any
desc: Error on failure, null on success
# Print
- name: Print
desc: "[Deprecated: use utils.fmt.Print] Print values to stdout (debug dump)"
args:
- name: values
type: any
required: true
desc: Values to print (variadic)
return:
type: "null"
desc: Returns null

12
openai/doc.go Normal file
View file

@ -0,0 +1,12 @@
package openai
import (
_ "embed"
"github.com/yaoapp/gou/doc"
)
//go:embed doc.yml
var docYAML []byte
func init() { doc.LoadYAML(docYAML) }

97
openai/doc.yml Normal file
View file

@ -0,0 +1,97 @@
group: openai
type: process
entries:
- name: tiktoken
desc: Count the number of tokens for a given model and input text
args:
- name: model
type: string
required: true
desc: Model name for tokenization (e.g. "gpt-3.5-turbo", "gpt-4")
- name: input
type: string
required: true
desc: Input text to tokenize
return:
type: number
desc: Number of tokens in the input text
- name: embeddings
desc: Create embedding vectors representing the input text
args:
- name: model
type: string
required: true
desc: AI connector name (e.g. "openai")
- name: input
type: any
required: true
desc: Input text or array of texts to embed
- name: user
type: string
required: false
desc: Unique identifier for the end-user
return:
type: object
desc: Embedding response with vector data
- name: chat.completions
desc: Create a chat completion response for the given messages
args:
- name: model
type: string
required: true
desc: AI connector name (e.g. "openai")
- name: messages
type: array
required: true
desc: "Array of message objects with role and content fields"
- name: options
type: object
required: false
desc: "Additional options: temperature, max_tokens, etc."
- name: callback
type: function
required: false
desc: Callback function for streaming responses; receives each chunk and returns an int status
return:
type: object
desc: Chat completion response object
- name: audio.transcriptions
desc: Transcribe audio from base64-encoded data into text
args:
- name: model
type: string
required: true
desc: AI connector name (e.g. "openai.whisper-1")
- name: dataBase64
type: string
required: true
desc: Base64-encoded audio data
- name: options
type: object
required: false
desc: "Additional options: language, model override, etc."
return:
type: object
desc: "Transcription result (e.g. {\"text\": \"...\"})"
- name: audio.transcriptionsfile
desc: Transcribe audio from a file path using streaming upload (no base64 overhead)
args:
- name: connector
type: string
required: true
desc: AI connector name (e.g. "openai.whisper-1")
- name: filePath
type: string
required: true
desc: Absolute OS file path to the audio file
- name: options
type: object
required: false
desc: "Additional options: language, model override, etc."
return:
type: object
desc: "Transcription result (e.g. {\"text\": \"...\"})"

12
openapi/job/doc.go Normal file
View file

@ -0,0 +1,12 @@
package job
import (
_ "embed"
"github.com/yaoapp/gou/doc"
)
//go:embed doc.yml
var docYAML []byte
func init() { doc.LoadYAML(docYAML) }

166
openapi/job/doc.yml Normal file
View file

@ -0,0 +1,166 @@
group: job
type: process
entries:
# Job Management
- name: jobs.list
desc: List jobs with pagination and optional query parameters
args:
- name: page
type: number
required: false
desc: "Page number (default: 1)"
- name: pagesize
type: number
required: false
desc: "Number of records per page (default: 20)"
- name: params
type: object
required: false
desc: Query parameters with wheres, orders, etc.
return:
type: object
desc: Paginated job list with data array and pagination info
- name: jobs.get
desc: Get a specific job by its ID
args:
- name: jobID
type: string
required: true
desc: Job ID to retrieve
return:
type: object
desc: Job instance details including status, schedule, last_run_at, next_run_at, etc.
- name: jobs.count
desc: Count jobs matching query parameters
args:
- name: params
type: object
required: false
desc: Query parameters with wheres conditions
return:
type: object
desc: "Object with count"
- name: jobs.stop
desc: Stop a running job
args:
- name: jobID
type: string
required: true
desc: Job ID to stop
return:
type: object
desc: "Object with message and job_id"
# Execution Management
- name: executions.list
desc: List executions for a specific job
args:
- name: jobID
type: string
required: true
desc: Job ID to list executions for
return:
type: object
desc: "Object with executions array and count"
- name: executions.get
desc: Get a specific execution by its ID
args:
- name: executionID
type: string
required: true
desc: Execution ID to retrieve
- name: params
type: object
required: false
desc: Optional query parameters
return:
type: object
desc: Execution details including status, progress, started_at, ended_at, duration, etc.
- name: executions.count
desc: Count executions for a specific job
args:
- name: jobID
type: string
required: true
desc: Job ID to count executions for
- name: params
type: object
required: false
desc: Optional query parameters with wheres conditions
return:
type: object
desc: "Object with count"
- name: executions.stop
desc: Stop a running execution (stops the parent job)
args:
- name: executionID
type: string
required: true
desc: Execution ID to stop
return:
type: object
desc: "Object with message, execution_id, and job_id"
# Log Management
- name: logs.list
desc: List logs for a specific job with pagination
args:
- name: jobID
type: string
required: true
desc: Job ID to list logs for
- name: page
type: number
required: false
desc: "Page number (default: 1)"
- name: pagesize
type: number
required: false
desc: "Number of records per page (default: 50)"
- name: params
type: object
required: false
desc: Optional query parameters with wheres conditions (level, execution_id filters)
return:
type: object
desc: Paginated log list with data array and pagination info
# Category Management
- name: categories.list
desc: List job categories with optional filtering
args:
- name: params
type: object
required: false
desc: Query parameters with wheres conditions (enabled, system filters)
return:
type: object
desc: "Object with categories array and count"
- name: categories.get
desc: Get a specific job category by its ID
args:
- name: categoryID
type: string
required: true
desc: Category ID to retrieve
return:
type: object
desc: Category details including name, description, enabled status, etc.
- name: categories.count
desc: Count job categories matching query parameters
args:
- name: params
type: object
required: false
desc: Query parameters with wheres conditions
return:
type: object
desc: "Object with count"

12
openapi/kb/doc.go Normal file
View file

@ -0,0 +1,12 @@
package kb
import (
_ "embed"
"github.com/yaoapp/gou/doc"
)
//go:embed doc.yml
var docYAML []byte
func init() { doc.LoadYAML(docYAML) }

118
openapi/kb/doc.yml Normal file
View file

@ -0,0 +1,118 @@
group: kb
type: process
entries:
# Collection Management
- name: collection.create
desc: Create a new knowledge base collection with embedding configuration
args:
- name: params
type: object
required: true
desc: "Collection parameters: {id, metadata: {name, description}, embedding_provider_id, embedding_option_id, locale, config: {distance, index_type, m, ef_construction, ef_search}}"
return:
type: object
desc: "Object with collection_id and message"
- name: collection.remove
desc: Remove a collection and all its documents
args:
- name: collectionID
type: string
required: true
desc: Collection ID to remove
return:
type: object
desc: "Object with collection_id, removed status, documents_removed count, and message"
- name: collection.get
desc: Retrieve a collection by its ID
args:
- name: collectionID
type: string
required: true
desc: Collection ID to retrieve
return:
type: object
desc: Collection details including metadata, embedding config, status, etc.
- name: collection.exists
desc: Check if a collection exists
args:
- name: collectionID
type: string
required: true
desc: Collection ID to check
return:
type: object
desc: "Object with collection_id and exists (bool)"
- name: collection.list
desc: List collections with pagination and filtering
args:
- name: filter
type: object
required: false
desc: "Filter parameters: {page, pagesize, keywords, status, embedding_provider_id, system, select, sort}"
return:
type: object
desc: Paginated result with data array, page, pagesize, total, pagecnt, next, prev
- name: collection.updatemetadata
desc: Update the metadata of an existing collection
args:
- name: collectionID
type: string
required: true
desc: Collection ID to update
- name: params
type: object
required: true
desc: "Update parameters: {metadata: {name, description}}"
return:
type: object
desc: "Object with collection_id and message"
# Document Management
- name: documents.addfile
desc: Add a document to a collection from an uploaded file
args:
- name: params
type: object
required: true
desc: File upload parameters including collection_id and file data
return:
type: object
desc: Document creation result with document_id
- name: documents.addtext
desc: Add a document to a collection from raw text content
args:
- name: params
type: object
required: true
desc: Text document parameters including collection_id, content, and metadata
return:
type: object
desc: Document creation result with document_id
- name: documents.addurl
desc: Add a document to a collection by fetching content from a URL
args:
- name: params
type: object
required: true
desc: URL document parameters including collection_id and URL
return:
type: object
desc: Document creation result with document_id
- name: documents.getcontents
desc: Retrieve content for one or more documents by their IDs
args:
- name: documentIDs
type: any
required: true
desc: "A single document ID (string) or an array of document IDs"
return:
type: array
desc: Array of objects with document_id, name, content, content_type, etc.

12
openapi/oauth/doc.go Normal file
View file

@ -0,0 +1,12 @@
package oauth
import (
_ "embed"
"github.com/yaoapp/gou/doc"
)
//go:embed doc.yml
var docYAML []byte
func init() { doc.LoadYAML(docYAML) }

48
openapi/oauth/doc.yml Normal file
View file

@ -0,0 +1,48 @@
group: oauth
type: process
entries:
- name: token.Make
desc: Generate an OAuth access token with explicit parameters
args:
- name: clientID
type: string
required: true
desc: OAuth client ID embedded in the token
- name: scope
type: string
required: true
desc: Token scope (space-separated)
- name: subject
type: string
required: true
desc: JWT subject claim
- name: expiresIn
type: number
required: true
desc: Token lifetime in seconds
- name: extraClaims
type: object
required: false
desc: Additional JWT claims (e.g. user_id, team_id)
return:
type: string
desc: The generated access token string
- name: token.MakeByUser
desc: Generate an OAuth access token for a team member by looking up user and team from the database
args:
- name: teamID
type: string
required: true
desc: Team ID
- name: memberID
type: string
required: true
desc: Member ID (business ID)
- name: expiresIn
type: number
required: false
desc: "Token lifetime in seconds (default: 86400 = 24h)"
return:
type: string
desc: The generated access token string

12
openapi/otp/doc.go Normal file
View file

@ -0,0 +1,12 @@
package otp
import (
_ "embed"
"github.com/yaoapp/gou/doc"
)
//go:embed doc.yml
var docYAML []byte
func init() { doc.LoadYAML(docYAML) }

50
openapi/otp/doc.yml Normal file
View file

@ -0,0 +1,50 @@
group: otp
type: process
entries:
- name: create
desc: Create a new OTP code with associated payload data for login or verification
args:
- name: params
type: object
required: true
desc: "OTP creation parameters: team_id, member_id, user_id, expires_in, redirect, scope, token_expires_in, consume"
return:
type: string
desc: The generated OTP code
- name: verify
desc: Verify an OTP code and return its associated payload without consuming it
args:
- name: code
type: string
required: true
desc: The OTP code to verify
return:
type: object
desc: The payload associated with the OTP code (team_id, member_id, user_id, redirect, scope, etc.)
- name: login
desc: Verify an OTP code and perform login, returning access tokens and redirect URL
args:
- name: code
type: string
required: true
desc: The OTP code to authenticate with
- name: locale
type: string
required: false
desc: Locale for login context (e.g. "en", "zh-CN")
return:
type: object
desc: Login result with access_token, id_token, refresh_token, expires_in, redirect, etc.
- name: revoke
desc: Revoke an OTP code, making it no longer usable
args:
- name: code
type: string
required: true
desc: The OTP code to revoke
return:
type: "null"
desc: Returns null on success

12
openapi/user/doc.go Normal file
View file

@ -0,0 +1,12 @@
package user
import (
_ "embed"
"github.com/yaoapp/gou/doc"
)
//go:embed doc.yml
var docYAML []byte
func init() { doc.LoadYAML(docYAML) }

264
openapi/user/doc.yml Normal file
View file

@ -0,0 +1,264 @@
group: user
type: process
entries:
# Profile
- name: profile.get
desc: Get the current user's profile information
args:
- name: options
type: object
required: false
desc: "Optional flags: {team: bool, member: bool, type: bool} to include team, member, or type info"
return:
type: object
desc: User profile data in OIDC format with optional team/member/type info
- name: profile.update
desc: Update the current user's profile information
args:
- name: data
type: object
required: true
desc: "Profile fields to update (name, given_name, family_name, nickname, picture, gender, locale, theme, metadata, etc.)"
return:
type: object
desc: "Object with user_id and message"
# Team Management
- name: team.list
desc: List teams owned by the current user with pagination and filtering
args:
- name: params
type: object
required: true
desc: "Query parameters: {status, name, page, pagesize}"
return:
type: object
desc: Paginated team list with data array and pagination info
- name: team.get
desc: Get details of a specific team the current user is a member of
args:
- name: teamID
type: string
required: true
desc: Team ID to retrieve
return:
type: object
desc: Team details including name, description, logo, owner_id, status, settings
- name: team.create
desc: Create a new team with the current user as owner
args:
- name: data
type: object
required: true
desc: "Team data: {name, description, settings, ...}"
return:
type: object
desc: "Object with team_id of the created team"
- name: team.update
desc: Update an existing team owned by the current user
args:
- name: teamID
type: string
required: true
desc: Team ID to update
- name: data
type: object
required: true
desc: "Fields to update: {name, description, settings, ...}"
return:
type: object
desc: "Object with message"
- name: team.delete
desc: Delete a team owned by the current user (removes all members first)
args:
- name: teamID
type: string
required: true
desc: Team ID to delete
return:
type: object
desc: "Object with message"
# Team Member Management
- name: member.list
desc: List members of a team with advanced filtering and pagination
args:
- name: teamID
type: string
required: true
desc: Team ID
- name: params
type: object
required: true
desc: "Query parameters: {page, pagesize, status, member_type, role_id, email, display_name, order, fields, locale}"
return:
type: object
desc: Paginated member list with data array and pagination info
- name: member.get
desc: Get details of a specific team member
args:
- name: teamID
type: string
required: true
desc: Team ID
- name: memberID
type: string
required: true
desc: Member ID (business key)
return:
type: object
desc: Member details including role, status, display_name, robot config, etc.
- name: member.update
desc: Update a team member (owner only, for role/status changes)
args:
- name: teamID
type: string
required: true
desc: Team ID
- name: memberID
type: string
required: true
desc: Member ID (business key)
- name: data
type: object
required: true
desc: "Fields to update: {role_id, status, settings, last_activity}"
return:
type: object
desc: "Object with message"
- name: member.profile.get
desc: Get a team member's profile (display_name, bio, avatar, email)
args:
- name: teamID
type: string
required: true
desc: Team ID
- name: userID
type: string
required: true
desc: "User ID of the member (not member_id)"
return:
type: object
desc: Member profile data with user_id, team_id, display_name, bio, avatar, email
- name: member.profile.update
desc: Update a team member's own profile (display_name, bio, avatar, email)
args:
- name: teamID
type: string
required: true
desc: Team ID
- name: userID
type: string
required: true
desc: "User ID of the member (not member_id)"
- name: data
type: object
required: true
desc: "Profile fields to update: {display_name, bio, avatar, email}"
return:
type: object
desc: "Object with user_id and message"
- name: member.delete
desc: Remove a member from a team (owner only)
args:
- name: teamID
type: string
required: true
desc: Team ID
- name: memberID
type: string
required: true
desc: Member ID (business key)
return:
type: object
desc: "Object with message"
# Team Invitation Management
- name: team.invitation.list
desc: List pending invitations for a team with pagination
args:
- name: teamID
type: string
required: true
desc: Team ID
- name: params
type: object
required: true
desc: "Query parameters: {status, page, pagesize}"
return:
type: object
desc: Paginated invitation list with data array and pagination info
- name: team.invitation.get
desc: Get details of a specific team invitation
args:
- name: teamID
type: string
required: true
desc: Team ID
- name: invitationID
type: string
required: true
desc: Invitation ID (business key)
return:
type: object
desc: Invitation details including status, role, invited_by, expiry, etc.
- name: team.invitation.create
desc: Create a new team invitation (owner only)
args:
- name: teamID
type: string
required: true
desc: Team ID
- name: data
type: object
required: true
desc: "Invitation data: {user_id, email, member_type, role_id, message, expiry, settings}"
return:
type: object
desc: "Object with invitation_id"
- name: team.invitation.resend
desc: Resend a pending team invitation with a new token and extended expiry
args:
- name: teamID
type: string
required: true
desc: Team ID
- name: invitationID
type: string
required: true
desc: Invitation ID (business key)
- name: locale
type: string
required: false
desc: "Locale for email template (default: \"en\")"
return:
type: object
desc: "Object with message"
- name: team.invitation.delete
desc: Cancel a pending team invitation (owner only)
args:
- name: teamID
type: string
required: true
desc: Team ID
- name: invitationID
type: string
required: true
desc: Invitation ID (business key)
return:
type: object
desc: "Object with message"

17
pipe/doc.go Normal file
View file

@ -0,0 +1,17 @@
package pipe
import (
_ "embed"
"github.com/yaoapp/gou/doc"
)
//go:embed doc.yml
var docYAML []byte
//go:embed doc_pipes.yml
var docPipesYAML []byte
func init() {
doc.LoadYAML(docYAML)
doc.LoadYAML(docPipesYAML)
}

96
pipe/doc.yml Normal file
View file

@ -0,0 +1,96 @@
group: pipe
type: process
entries:
- name: run
desc: Run a loaded pipeline by its registered ID
args:
- name: pipeId
type: string
required: true
desc: Registered pipeline ID
- name: args
type: any
required: false
desc: "Variable arguments passed to the pipeline execution"
return:
type: any
desc: Pipeline execution result
- name: create
desc: Create a new pipeline from a DSL string and run it immediately
args:
- name: dsl
type: string
required: true
desc: Pipeline DSL definition as a YAML/JSON string
- name: args
type: any
required: false
desc: "Variable arguments passed to the pipeline execution"
return:
type: any
desc: Pipeline execution result
- name: createwith
desc: Create a new pipeline from DSL with global data and run it immediately
args:
- name: dsl
type: string
required: true
desc: Pipeline DSL definition as a YAML/JSON string
- name: global
type: object
required: true
desc: Global data map merged with process global context
- name: args
type: any
required: false
desc: "Variable arguments passed to the pipeline execution"
return:
type: any
desc: Pipeline execution result
- name: resume
desc: Resume a paused pipeline context by its context ID
args:
- name: contextId
type: string
required: true
desc: Pipeline context ID to resume
- name: args
type: any
required: false
desc: "Variable arguments passed to the resumed pipeline"
return:
type: any
desc: Resumed pipeline execution result
- name: resumewith
desc: Resume a paused pipeline context with additional global data
args:
- name: contextId
type: string
required: true
desc: Pipeline context ID to resume
- name: global
type: object
required: true
desc: Global data map merged with process global context
- name: args
type: any
required: false
desc: "Variable arguments passed to the resumed pipeline"
return:
type: any
desc: Resumed pipeline execution result
- name: close
desc: Close and clean up a pipeline context
args:
- name: contextId
type: string
required: true
desc: Pipeline context ID to close
return:
type: "null"
desc: Returns null on success

13
pipe/doc_pipes.yml Normal file
View file

@ -0,0 +1,13 @@
group: pipes
type: process
entries:
- name: "*"
desc: "Run a loaded pipeline by ID. Called as pipes.<pipe_id> with the pipe ID as the process name suffix"
args:
- name: args
type: any
required: false
desc: "Variable arguments passed to the pipeline execution"
return:
type: any
desc: Pipeline execution result

11
rss/doc.go Normal file
View file

@ -0,0 +1,11 @@
package rss
import (
_ "embed"
"github.com/yaoapp/gou/doc"
)
//go:embed doc.yml
var docYAML []byte
func init() { doc.LoadYAML(docYAML) }

66
rss/doc.yml Normal file
View file

@ -0,0 +1,66 @@
group: rss
type: process
desc: "RSS/Atom feed parsing, validation, building, discovery, and fetching processes"
entries:
- name: parse
desc: Parse an RSS 2.0 or Atom 1.0 XML string into a unified Feed object with auto-format detection and podcast metadata extraction
args:
- name: data
type: string
required: true
desc: "Feed XML string to parse"
return:
type: object
desc: "Feed object with format, title, link, description, language, updated, items (array), and podcast (object or null) fields"
- name: validate
desc: Check whether a string is a valid RSS 2.0 or Atom 1.0 feed
args:
- name: data
type: string
required: true
desc: "Feed XML string to validate"
return:
type: any
desc: "True (bool) if valid; error description string if invalid"
- name: discover
desc: Extract feed URLs from HTML, Markdown, or plain text content using regex-based detection (no network requests)
args:
- name: text
type: string
required: true
desc: "Text content to scan for feed URLs"
return:
type: array
desc: "Array of FeedLink objects with url, title, and type fields"
- name: build
desc: Generate an XML feed document from a Feed object
args:
- name: feed
type: object
required: true
desc: "Feed object (same structure as rss.parse output)"
- name: format
type: string
required: false
desc: "Output format: \"rss\" (default) or \"atom\""
return:
type: string
desc: "XML feed document string"
- name: fetch
desc: Fetch a remote RSS/Atom feed by URL and return the parsed Feed with HTTP metadata for conditional polling
args:
- name: url
type: string
required: true
desc: "Feed URL to fetch"
- name: options
type: object
required: false
desc: "Fetch options: user_agent (string), timeout (number, seconds), etag (string, for If-None-Match), last_modified (string, for If-Modified-Since)"
return:
type: object
desc: "FetchResult with feed (object or null), status_code (number), etag (string), last_modified (string), and not_modified (bool) fields"

12
seed/doc.go Normal file
View file

@ -0,0 +1,12 @@
package seed
import (
_ "embed"
"github.com/yaoapp/gou/doc"
)
//go:embed doc.yml
var docYAML []byte
func init() { doc.LoadYAML(docYAML) }

21
seed/doc.yml Normal file
View file

@ -0,0 +1,21 @@
group: seeds
type: process
entries:
- name: import
desc: Import seed data from a file (CSV, XLSX, JSON, JSONC/Yao) into a model table
args:
- name: filename
type: string
required: true
desc: "Seed file name relative to the seeds directory (e.g. \"users.csv\", \"data.xlsx\", \"records.json\")"
- name: modelName
type: string
required: true
desc: Target model name to import data into
- name: options
type: object
required: false
desc: "Import options: {chunk_size: number, duplicate: \"ignore\"|\"error\"|\"update\"|\"abort\", mode: \"batch\"|\"each\"}"
return:
type: object
desc: "Import result: {total, success, failure, ignore, errors: [{row, message, code, data}]}"

11
sitemap/doc.go Normal file
View file

@ -0,0 +1,11 @@
package sitemap
import (
_ "embed"
"github.com/yaoapp/gou/doc"
)
//go:embed doc.yml
var docYAML []byte
func init() { doc.LoadYAML(docYAML) }

103
sitemap/doc.yml Normal file
View file

@ -0,0 +1,103 @@
group: sitemap
type: process
desc: "Sitemap parsing, validation, discovery, fetching, and streaming build processes"
entries:
- name: parse
desc: Parse a sitemap XML string into a unified ParseResult, auto-detecting urlset or sitemapindex format
args:
- name: data
type: string
required: true
desc: "Sitemap XML string to parse"
return:
type: object
desc: "ParseResult with type (\"urlset\" or \"sitemapindex\"), urls (array of URL objects), and sitemaps (array of SitemapEntry objects)"
- name: validate
desc: Check whether a string is a valid sitemap XML document
args:
- name: data
type: string
required: true
desc: "Sitemap XML string to validate"
return:
type: any
desc: "True (bool) if valid; error description string if invalid"
- name: parserobo
desc: Extract sitemap URLs from robots.txt content (pure text parsing, no HTTP)
args:
- name: text
type: string
required: true
desc: "robots.txt content"
return:
type: array
desc: "Array of sitemap URL strings"
- name: discover
desc: Discover sitemap files for a domain via robots.txt and well-known paths, recursively expanding sitemapindex files
args:
- name: domain
type: string
required: true
desc: "Domain to discover sitemaps for (e.g. \"example.com\")"
- name: options
type: object
required: false
desc: "Options: user_agent (string), timeout (number, seconds)"
return:
type: object
desc: "DiscoverResult with sitemaps (array of SitemapLink objects with url, source, url_count, content_size, encoding, last_modified, etag) and total_urls (number)"
- name: fetch
desc: Fetch and parse URLs from sitemaps for a domain with pagination support
args:
- name: domain
type: string
required: true
desc: "Domain to fetch sitemaps for (e.g. \"example.com\")"
- name: options
type: object
required: false
desc: "Options: offset (number), limit (number, default/max 50000), user_agent (string), timeout (number, seconds)"
return:
type: object
desc: "FetchResult with urls (array of URL objects with loc, lastmod, changefreq, priority, images, videos, news) and total (number)"
- name: build.open
desc: Open a new streaming sitemap writer and return a UUID handle
args:
- name: options
type: object
required: true
desc: "Build options: dir (string, output directory path, required), base_url (string, URL prefix for index references, required if multiple files)"
return:
type: string
desc: "UUID handle string for use with build.write and build.close"
- name: build.write
desc: Write a batch of URLs to an open sitemap writer, automatically splitting at 50,000 URLs per file
args:
- name: handle
type: string
required: true
desc: "UUID handle from build.open"
- name: urls
type: array
required: true
desc: "Array of URL objects with loc (required), lastmod, changefreq, priority, images, videos, and news fields"
return:
type: "null"
desc: "Returns null on success"
- name: build.close
desc: Finalize the sitemap output, generate a sitemapindex if needed, and clean up the handle
args:
- name: handle
type: string
required: true
desc: "UUID handle from build.open"
return:
type: object
desc: "BuildResult with index (string, sitemap_index.xml path or empty), files (array of file paths), and total (number of URLs written)"

11
sui/api/doc.go Normal file
View file

@ -0,0 +1,11 @@
package api
import (
_ "embed"
"github.com/yaoapp/gou/doc"
)
//go:embed doc.yml
var docYAML []byte
func init() { doc.LoadYAML(docYAML) }

772
sui/api/doc.yml Normal file
View file

@ -0,0 +1,772 @@
group: sui
type: process
entries:
- name: setting
desc: Get the SUI instance settings
args:
- name: instance
type: string
required: true
desc: SUI instance name
return:
type: object
desc: SUI setting object
- name: render
desc: "[Internal] Render an HTML fragment by route. Do not use in scripts or flows, use template.render instead"
args:
- name: context
type: external
required: true
desc: Gin request context (*gin.Context)
- name: route
type: string
required: true
desc: Page route path
- name: payload
type: object
required: true
desc: "Render payload containing name (render target), data (template data), and option (render options)"
return:
type: string
desc: Rendered HTML string
- name: run
desc: "[Internal] Execute a page backend script method. Do not use in scripts or flows"
args:
- name: context
type: external
required: true
desc: Gin request context (*gin.Context)
- name: route
type: string
required: true
desc: Page route path
- name: payload
type: object
required: true
desc: "Execution payload with method (string, required) and args (array, optional)"
return:
type: any
desc: Script execution result
- name: template.get
desc: List all templates in the SUI instance
args:
- name: instance
type: string
required: true
desc: SUI instance name
return:
type: array
desc: Array of template objects
- name: template.find
desc: Find a template by ID
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: templateId
type: string
required: true
desc: Template ID
return:
type: object
desc: Template object
- name: template.asset
desc: Get a template asset file content and MIME type
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: templateId
type: string
required: true
desc: Template ID
- name: path
type: string
required: true
desc: Asset file path within the template
- name: width
type: number
required: false
desc: Optional image width for resizing
- name: height
type: number
required: false
desc: Optional image height for resizing
return:
type: object
desc: "Object with content (asset data) and type (MIME type)"
- name: template.assetupload
desc: Upload an asset file to a template
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: templateId
type: string
required: true
desc: Template ID
- name: file
type: any
required: true
desc: "File data: *gin.Context (form upload with field 'file') or base64-encoded string"
- name: filename
type: string
required: false
desc: "Filename when uploading as base64 string (default: file.png)"
return:
type: any
desc: "Upload result: object with data and header (form upload), or file path string (base64)"
- name: template.render
desc: Compile and render a template page to HTML
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: templateId
type: string
required: true
desc: Template ID
- name: source
type: string
required: true
desc: Page source path
- name: data
type: object
required: true
desc: Template data for rendering
- name: option
type: object
required: false
desc: "Render options with theme, locale, and data fields"
- name: request
type: object
required: false
desc: Override request object for rendering context
return:
type: string
desc: Rendered HTML string
- name: locale.get
desc: Get available locales for a template
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: templateId
type: string
required: true
desc: Template ID
return:
type: array
desc: Array of locale select options, or empty array if none
- name: theme.get
desc: Get available themes for a template
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: templateId
type: string
required: true
desc: Template ID
return:
type: array
desc: Array of theme objects
- name: block.get
desc: List all blocks in a template
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: templateId
type: string
required: true
desc: Template ID
return:
type: array
desc: Array of block objects
- name: block.find
desc: Get the source code of a block by ID
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: templateId
type: string
required: true
desc: Template ID
- name: blockId
type: string
required: true
desc: Block ID (trailing .js suffix is stripped)
return:
type: string
desc: Block source code
- name: block.Media
desc: Get the media asset of a block
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: templateId
type: string
required: true
desc: Template ID
- name: blockId
type: string
required: true
desc: Block ID (trailing .js suffix is stripped)
return:
type: object
desc: "Object with content (media data) and type (MIME type)"
- name: block.export
desc: Export block layout items from a template
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: templateId
type: string
required: true
desc: Template ID
return:
type: array
desc: Array of block layout items
- name: component.get
desc: List all components in a template
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: templateId
type: string
required: true
desc: Template ID
return:
type: array
desc: Array of component objects
- name: component.find
desc: Get the source code of a component by ID
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: templateId
type: string
required: true
desc: Template ID
- name: componentId
type: string
required: true
desc: Component ID (trailing .js suffix is stripped)
return:
type: string
desc: Component source code
- name: page.tree
desc: Get the page tree under a route
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: templateId
type: string
required: true
desc: Template ID
- name: route
type: string
required: false
desc: "Route path (defaults to /index if empty)"
return:
type: object
desc: Page tree structure
- name: page.get
desc: List all pages in a template
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: templateId
type: string
required: true
desc: Template ID
return:
type: array
desc: Array of page objects
- name: page.save
desc: Save a page source to the given route
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: templateId
type: string
required: true
desc: Template ID
- name: route
type: string
required: true
desc: Page route path
- name: source
type: any
required: true
desc: "Page source: RequestSource object, *gin.Context, JSON string, or map"
return:
type: "null"
desc: Returns null on success
- name: page.savetemp
desc: Temporarily save a page source (requires source.uid)
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: templateId
type: string
required: true
desc: Template ID
- name: route
type: string
required: true
desc: Page route path
- name: source
type: any
required: true
desc: "Page source with uid field required: RequestSource object, *gin.Context, JSON string, or map"
return:
type: "null"
desc: Returns null on success
- name: page.create
desc: Create a new empty page and optionally save initial source
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: templateId
type: string
required: true
desc: Template ID
- name: route
type: string
required: true
desc: Page route path
- name: source
type: any
required: false
desc: "Optional initial page source to save"
- name: payload
type: object
required: false
desc: "Optional payload with route (override) and title fields"
return:
type: "null"
desc: Returns null on success
- name: page.duplicate
desc: Duplicate a page to a new route
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: templateId
type: string
required: true
desc: Template ID
- name: sourceRoute
type: string
required: true
desc: Source page route to copy from
- name: payload
type: object
required: false
desc: "Object with route (required, target path) and title (optional)"
return:
type: "null"
desc: Returns null on success
- name: page.rename
desc: Rename (move) a page to a new route
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: templateId
type: string
required: true
desc: Template ID
- name: sourceRoute
type: string
required: true
desc: Current page route
- name: payload
type: object
required: true
desc: "Object with route field (required, new route path)"
return:
type: "null"
desc: Returns null on success
- name: page.remove
desc: Remove a page from the template
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: templateId
type: string
required: true
desc: Template ID
- name: route
type: string
required: true
desc: Page route path to remove
return:
type: "null"
desc: Returns null on success
- name: page.exist
desc: Check if a page exists at the given route
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: templateId
type: string
required: true
desc: Template ID
- name: route
type: string
required: true
desc: Page route path to check
return:
type: bool
desc: True if the page exists
- name: page.asset
desc: Get the CSS or JS/TS asset content of a page
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: templateId
type: string
required: true
desc: Template ID
- name: file
type: string
required: true
desc: "Asset file path (.css, .js, or .ts extension)"
return:
type: object
desc: "Object with content (asset data) and type (MIME type)"
- name: editor.render
desc: Render a page for the editor view
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: templateId
type: string
required: true
desc: Template ID
- name: route
type: string
required: true
desc: Page route path
return:
type: any
desc: Editor render result
- name: editor.source
desc: Get page source code by kind for the editor
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: templateId
type: string
required: true
desc: Template ID
- name: route
type: string
required: true
desc: Page route path
- name: kind
type: string
required: true
desc: "Source kind: page, style, script, or data"
return:
type: any
desc: Source code content for the specified kind
- name: editor.renderaftersavetemp
desc: Temporarily save page source then render for the editor
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: templateId
type: string
required: true
desc: Template ID
- name: route
type: string
required: true
desc: Page route path
- name: source
type: any
required: true
desc: Page source to save temporarily (requires uid)
- name: extra
type: any
required: false
desc: Additional arguments passed to the editor render
return:
type: any
desc: Editor render result
- name: editor.sourceaftersavetemp
desc: Temporarily save page source then get editor source
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: templateId
type: string
required: true
desc: Template ID
- name: route
type: string
required: true
desc: Page route path
- name: source
type: any
required: true
desc: Page source to save temporarily (requires uid)
- name: extra
type: any
required: false
desc: Additional arguments passed to the editor source
return:
type: any
desc: Source code content for the specified kind
- name: media.search
desc: Search media assets in a template
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: driver
type: string
required: true
desc: "Media driver name (e.g., local)"
- name: query
type: any
required: false
desc: "Search query parameters: map or url.Values. Supports page, pagesize, and template fields"
return:
type: any
desc: Media search results
- name: preview.render
desc: Render a page for preview
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: templateId
type: string
required: true
desc: Template ID
- name: route
type: string
required: true
desc: Page route path
- name: referer
type: string
required: false
desc: Optional referer URL
return:
type: string
desc: Preview HTML string
- name: build.all
desc: Build all pages in a template
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: templateId
type: string
required: true
desc: Template ID
- name: option
type: object
required: true
desc: "Build options with ssr (bool), asset_root (string), and data (object) fields"
return:
type: any
desc: Array of warnings if any, otherwise null
- name: build.page
desc: Build a single page in a template
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: templateId
type: string
required: true
desc: Template ID
- name: route
type: string
required: true
desc: Page route path
- name: option
type: object
required: true
desc: "Build options with ssr (bool) and asset_root (string) fields"
- name: extra
type: any
required: false
desc: Reserved
- name: data
type: object
required: false
desc: Additional data for the build
return:
type: any
desc: Array of warnings if any, otherwise null
- name: trans.all
desc: Extract and translate all pages in a template
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: templateId
type: string
required: true
desc: Template ID
- name: option
type: object
required: true
desc: "Translation options with ssr (bool), asset_root (string), and data (object) fields"
return:
type: any
desc: Array of warnings if any, otherwise null
- name: trans.page
desc: Extract and translate a single page
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: templateId
type: string
required: true
desc: Template ID
- name: route
type: string
required: true
desc: Page route path
- name: option
type: object
required: true
desc: "Translation options with ssr (bool) and asset_root (string) fields"
- name: extra
type: any
required: false
desc: Reserved
- name: data
type: object
required: false
desc: Additional data for the translation
return:
type: any
desc: Array of warnings if any, otherwise null
- name: sync.assetfile
desc: "[Deprecated] Sync a single asset file in a template"
args:
- name: instance
type: string
required: true
desc: SUI instance name
- name: templateId
type: string
required: true
desc: Template ID
- name: filename
type: string
required: true
desc: Asset filename to sync
- name: option
type: object
required: true
desc: "Sync options with ssr (bool), asset_root (string), and data (object) fields"
return:
type: "null"
desc: Returns null on success
- name: types.QueryParam
desc: "[Deprecated] Convert various input formats to a query parameter structure"
args:
- name: input
type: any
required: true
desc: "Input data: url.Values, map[string][]string, map[string]interface{}, or any serializable value"
return:
type: any
desc: Converted query parameter structure

11
utils/doc.go Normal file
View file

@ -0,0 +1,11 @@
package utils
import (
_ "embed"
"github.com/yaoapp/gou/doc"
)
//go:embed doc.yml
var docYAML []byte
func init() { doc.LoadYAML(docYAML) }

377
utils/doc.yml Normal file
View file

@ -0,0 +1,377 @@
group: utils
type: process
entries:
# throw
- name: throw.Forbidden
desc: Throw a 403 Forbidden exception
args:
- name: message
type: string
required: false
desc: "Error message (default: \"Access denied\")"
return:
type: void
desc: Does not return; throws exception
- name: throw.Unauthorized
desc: Throw a 401 Unauthorized exception
args:
- name: message
type: string
required: false
desc: "Error message (default: \"Authentication required\")"
return:
type: void
desc: Does not return; throws exception
- name: throw.NotFound
desc: Throw a 404 Not Found exception
args:
- name: message
type: string
required: false
desc: "Error message (default: \"Resource not found\")"
return:
type: void
desc: Does not return; throws exception
- name: throw.BadRequest
desc: Throw a 400 Bad Request exception
args:
- name: message
type: string
required: false
desc: "Error message (default: \"Bad Request\")"
return:
type: void
desc: Does not return; throws exception
- name: throw.InternalError
desc: Throw a 500 Internal Server Error exception
args:
- name: message
type: string
required: false
desc: "Error message (default: \"Internal Error\")"
return:
type: void
desc: Does not return; throws exception
- name: throw.Exception
desc: Throw a custom exception with specified message and HTTP status code
args:
- name: message
type: string
required: true
desc: Error message
- name: code
type: number
required: true
desc: HTTP status code
return:
type: void
desc: Does not return; throws exception
# fmt
- name: fmt.Printf
desc: Print formatted output to stdout
args:
- name: format
type: string
required: true
desc: Format string (Go fmt style)
- name: args
type: any
required: false
desc: Values to format (variadic)
return:
type: "null"
desc: Returns null
- name: fmt.ColorPrintf
desc: Print colored formatted output to stdout
args:
- name: color
type: string
required: true
desc: "Color name: red, green, yellow, blue, magenta, cyan, white, black, hired, higreen, etc."
- name: format
type: string
required: true
desc: Format string (Go fmt style)
- name: args
type: any
required: false
desc: Values to format (variadic)
return:
type: "null"
desc: Returns null
# str
- name: str.Join
desc: Join array elements into a string with a separator
args:
- name: array
type: array
required: true
desc: Array of values to join
- name: separator
type: string
required: true
desc: Separator string
return:
type: string
desc: Joined string
- name: str.JoinPath
desc: Join path segments into a file path
args:
- name: paths
type: string
required: true
desc: Path segments to join (variadic, minimum 2 segments required)
return:
type: string
desc: Joined file path
- name: str.UUID
desc: Generate a new UUID v4 string
args: []
return:
type: string
desc: UUID string (e.g. "550e8400-e29b-41d4-a716-446655440000")
- name: str.Pinyin
desc: Convert Chinese characters to Pinyin
args:
- name: text
type: string
required: true
desc: Chinese text to convert
- name: options
type: object
required: false
desc: "Options: {tone: bool|\"mark\"|\"number\"|\"none\", heteronym: bool, separator: string}"
return:
type: string
desc: Pinyin string
# tree
- name: tree.Flatten
desc: Flatten a tree structure into a flat array
args:
- name: array
type: array
required: true
desc: Tree-structured array to flatten
- name: options
type: object
required: false
desc: "Options: {primary: \"id\", children: \"children\", parent: \"parent\"}"
return:
type: array
desc: Flat array with parent references
# now / time
- name: now.Time
desc: Get the current time as a string
args: []
return:
type: string
desc: "Current time in HH:MM:SS format (e.g. \"15:04:05\")"
- name: now.Date
desc: Get the current date as a string
args: []
return:
type: string
desc: "Current date in YYYY-MM-DD format (e.g. \"2006-01-02\")"
- name: now.DateTime
desc: Get the current date and time as a string
args: []
return:
type: string
desc: "Current datetime in YYYY-MM-DD HH:MM:SS format"
- name: now.Timestamp
desc: Get the current Unix timestamp in seconds
args: []
return:
type: number
desc: Unix timestamp in seconds
- name: now.Timestampms
desc: Get the current Unix timestamp in milliseconds
args: []
return:
type: number
desc: Unix timestamp in milliseconds
# url
- name: url.ParseQuery
desc: Parse a URL query string into key-value pairs
args:
- name: queryString
type: string
required: true
desc: "URL query string (e.g. \"key1=val1&key2=val2\")"
return:
type: object
desc: Parsed query parameters as map of string to string array
- name: url.QueryParam
desc: Convert URL values or map to QueryParam object
args:
- name: values
type: any
required: true
desc: "URL values: url.Values, map[string][]string, or map[string]interface{}"
return:
type: object
desc: QueryParam object
- name: url.ParseURL
desc: Parse a URL string into its components
args:
- name: url
type: string
required: true
desc: URL string to parse
return:
type: object
desc: "Parsed URL with scheme, host, domain, path, port, query, and url fields"
# json
- name: json.Validate
desc: "[Warning: under development] Validate JSON data against rules"
args:
- name: data
type: object
required: true
desc: JSON data to validate
- name: rules
type: array
required: true
desc: "Validation rules (e.g. [{\"haskey\": \"fieldName\"}])"
return:
type: bool
desc: True if validation passes, false otherwise
# jsonschema
- name: jsonschema.ValidateSchema
desc: Validate a JSON Schema structure
args:
- name: schema
type: any
required: true
desc: "JSON Schema to validate (map, string, or bytes)"
return:
type: any
desc: "Null if valid, error message string if invalid"
- name: jsonschema.Validate
desc: Validate data against a JSON Schema
args:
- name: schema
type: any
required: true
desc: "JSON Schema (map, string, or bytes)"
- name: data
type: any
required: true
desc: Data to validate against the schema
return:
type: any
desc: "Null if valid, error message string if invalid"
# captcha (0.10.5+)
- name: captcha.Generate
desc: Generate a captcha image/audio with customizable options
args:
- name: options
type: object
required: true
desc: "Options: {width, height, length, type, lang, background}"
return:
type: object
desc: "Object with id and content (base64 image/audio)"
- name: captcha.Validate
desc: Validate a captcha code
args:
- name: id
type: string
required: true
desc: Captcha ID returned by Generate
- name: code
type: string
required: true
desc: User-entered captcha code
return:
type: bool
desc: True if valid; throws exception if invalid
- name: captcha.Get
desc: Get the captcha code by ID (for testing purposes)
args:
- name: id
type: string
required: true
desc: Captcha ID
return:
type: string
desc: The captcha answer code
# otp (0.10.5+)
- name: otp.Generate
desc: Generate a one-time password (OTP) code
args:
- name: options
type: object
required: true
desc: "Options: {length: number, expiration: number (seconds), type: string}"
return:
type: object
desc: "Object with id and code"
- name: otp.Validate
desc: Validate a one-time password (OTP) code
args:
- name: id
type: string
required: true
desc: OTP ID returned by Generate
- name: code
type: string
required: true
desc: OTP code to validate
- name: clear
type: bool
required: false
desc: "Whether to clear the OTP after validation (default: true)"
return:
type: bool
desc: True if valid; throws exception if invalid or expired
- name: otp.Get
desc: Get the OTP code by ID (for testing purposes)
args:
- name: id
type: string
required: true
desc: OTP ID
return:
type: string
desc: The OTP code
- name: otp.Delete
desc: Delete an OTP code by ID
args:
- name: id
type: string
required: true
desc: OTP ID to delete
return:
type: "null"
desc: Returns null

11
widgets/app/doc.go Normal file
View file

@ -0,0 +1,11 @@
package app
import (
_ "embed"
"github.com/yaoapp/gou/doc"
)
//go:embed doc.yml
var docYAML []byte
func init() { doc.LoadYAML(docYAML) }

84
widgets/app/doc.yml Normal file
View file

@ -0,0 +1,84 @@
group: yao.app
type: process
desc: "Application widget processes for settings, menus, icons, setup, and services"
entries:
- name: setting
desc: Return the application DSL settings with i18n translation applied
args:
- name: payload
type: object
required: false
desc: "Optional object with sid (session ID), lang (language code e.g. \"en-us\"), and now (unix timestamp)"
return:
type: object
desc: "Application DSL object with name, version, description, theme, lang, menu, optional, sid, logo, and favicon fields"
- name: xgen
desc: Return the merged Xgen settings including app config, login config, agent config, tools, and knowledge base
args:
- name: payload
type: object
required: false
desc: "Optional object with sid (session ID), lang (language code e.g. \"en-us\"), and now (unix timestamp)"
return:
type: object
desc: "Xgen settings object with name, description, version, yao, cui, theme, lang, mode, apiPrefix, token, optional, login, agent, tools, openapi, kb, logo, favicon, and sid fields"
- name: menu
desc: Return the application menu list by delegating to the configured menu.process
args:
- name: args
type: any
required: false
desc: "Arguments forwarded to the configured menu process"
return:
type: any
desc: "Menu data returned by the configured menu process"
- name: icons
desc: Return the content of an application icon file from the icons/ directory
args:
- name: name
type: string
required: true
desc: "Icon filename (e.g. \"app.ico\", \"app.png\")"
return:
type: string
desc: "Icon file content as string"
- name: setup
desc: Run the application setup process and return home/admin URLs with translated settings
args:
- name: payload
type: object
required: true
desc: "Setup payload object; may include sid (session ID); include 'error' key to trigger a test error"
return:
type: object
desc: "Object with home (string URL), admin (string URL), and setting (translated app DSL)"
- name: check
desc: Run the application check process for setup validation
args:
- name: payload
type: object
required: true
desc: "Check payload object; include 'error' key to trigger a test error"
return:
type: "null"
desc: "Returns null on success, throws exception on error"
- name: service
desc: Call a named application service script method with arguments
args:
- name: name
type: string
required: true
desc: "Service script name (resolves to __yao_service.<name> V8 script)"
- name: payload
type: object
required: true
desc: "Object with method (string, required) and args (array, optional) fields"
return:
type: any
desc: "Return value from the service method call"

11
widgets/chart/doc.go Normal file
View file

@ -0,0 +1,11 @@
package chart
import (
_ "embed"
"github.com/yaoapp/gou/doc"
)
//go:embed doc.yml
var docYAML []byte
func init() { doc.LoadYAML(docYAML) }

62
widgets/chart/doc.yml Normal file
View file

@ -0,0 +1,62 @@
group: yao.chart
type: process
entries:
- name: setting
desc: Get the setting configuration of a chart widget
args:
- name: chartId
type: string
required: true
desc: Chart widget ID
return:
type: any
desc: Chart setting from the configured action handler
- name: xgen
desc: Get the Xgen UI configuration for a chart widget with permission filtering
args:
- name: chartId
type: string
required: true
desc: Chart widget ID
- name: data
type: object
required: false
desc: Additional data for generating the configuration
return:
type: object
desc: Xgen configuration object with permission-based field exclusions
- name: component
desc: Execute a cloud component query within a chart widget
args:
- name: chartId
type: string
required: true
desc: Chart widget ID
- name: xpath
type: string
required: true
desc: Component XPath (URL-encoded)
- name: method
type: string
required: true
desc: Component method name (URL-encoded)
- name: query
type: object
required: false
desc: Query parameters for the component
return:
type: any
desc: Component query execution result
- name: data
desc: Get the data for a chart widget
args:
- name: chartId
type: string
required: true
desc: Chart widget ID
return:
type: any
desc: Chart data from the configured action handler

11
widgets/component/doc.go Normal file
View file

@ -0,0 +1,11 @@
package component
import (
_ "embed"
"github.com/yaoapp/gou/doc"
)
//go:embed doc.yml
var docYAML []byte
func init() { doc.LoadYAML(docYAML) }

24
widgets/component/doc.yml Normal file
View file

@ -0,0 +1,24 @@
group: yao.component
type: process
entries:
- name: getoptions
desc: Get select options by querying a model or query engine with configurable label/value mapping
args:
- name: params
type: object
required: true
desc: Query parameters map for filtering results
- name: props
type: object
required: true
desc: "Component props containing a query object with engine, from, labelField, valueField, wheres, and other query configuration"
return:
type: array
desc: "Array of option objects with label, value, and optional icon and color fields"
- name: selectoptions
desc: "[Deprecated] Use yao.component.getoptions instead. Always throws a 400 error"
args: []
return:
type: void
desc: Never returns; always throws a deprecation error

11
widgets/dashboard/doc.go Normal file
View file

@ -0,0 +1,11 @@
package dashboard
import (
_ "embed"
"github.com/yaoapp/gou/doc"
)
//go:embed doc.yml
var docYAML []byte
func init() { doc.LoadYAML(docYAML) }

62
widgets/dashboard/doc.yml Normal file
View file

@ -0,0 +1,62 @@
group: yao.dashboard
type: process
entries:
- name: setting
desc: Get the setting configuration of a dashboard widget
args:
- name: dashboardId
type: string
required: true
desc: Dashboard widget ID
return:
type: any
desc: Dashboard setting from the configured action handler
- name: xgen
desc: Get the Xgen UI configuration for a dashboard widget with permission filtering
args:
- name: dashboardId
type: string
required: true
desc: Dashboard widget ID
- name: data
type: object
required: false
desc: Additional data for generating the configuration
return:
type: object
desc: Xgen configuration object with permission-based field exclusions
- name: component
desc: Execute a cloud component query within a dashboard widget
args:
- name: dashboardId
type: string
required: true
desc: Dashboard widget ID
- name: xpath
type: string
required: true
desc: Component XPath (URL-encoded)
- name: method
type: string
required: true
desc: Component method name (URL-encoded)
- name: query
type: object
required: false
desc: Query parameters for the component
return:
type: any
desc: Component query execution result
- name: data
desc: Get the data for a dashboard widget
args:
- name: dashboardId
type: string
required: true
desc: Dashboard widget ID
return:
type: any
desc: Dashboard data from the configured action handler

11
widgets/doc.go Normal file
View file

@ -0,0 +1,11 @@
package widgets
import (
_ "embed"
"github.com/yaoapp/gou/doc"
)
//go:embed doc.yml
var docYAML []byte
func init() { doc.LoadYAML(docYAML) }

37
widgets/doc.yml Normal file
View file

@ -0,0 +1,37 @@
group: widget
type: process
entries:
- name: apis
desc: Get all loaded widget API definitions
args: []
return:
type: any
desc: Map of all registered widget APIs
- name: actions
desc: Get all loaded widget action definitions
args: []
return:
type: any
desc: Map of all registered widget actions
- name: models
desc: Get all loaded widget model definitions
args: []
return:
type: any
desc: Map of all registered widget models
- name: fields
desc: Get all loaded widget field definitions
args: []
return:
type: any
desc: Map of all registered widget fields
- name: filters
desc: Get all loaded widget filter definitions
args: []
return:
type: any
desc: Map of all registered widget filters

11
widgets/expression/doc.go Normal file
View file

@ -0,0 +1,11 @@
package expression
import (
_ "embed"
"github.com/yaoapp/gou/doc"
)
//go:embed doc.yml
var docYAML []byte
func init() { doc.LoadYAML(docYAML) }

View file

@ -0,0 +1,32 @@
group: yao.expression
type: process
entries:
- name: selectoption
desc: Convert input values into an array of label/value select options
args:
- name: input
type: any
required: true
desc: "Comma-separated string, or array of strings/numbers/maps"
- name: labelField
type: string
required: false
desc: "Field name to use as label when input items are maps (default: name)"
- name: valueField
type: string
required: false
desc: "Field name to use as value when input items are maps (default: id)"
return:
type: array
desc: Array of objects with label and value fields
- name: trimspace
desc: Trim leading and trailing whitespace from a string
args:
- name: input
type: string
required: true
desc: String to trim
return:
type: string
desc: Trimmed string

11
widgets/login/doc.go Normal file
View file

@ -0,0 +1,11 @@
package login
import (
_ "embed"
"github.com/yaoapp/gou/doc"
)
//go:embed doc.yml
var docYAML []byte
func init() { doc.LoadYAML(docYAML) }

14
widgets/login/doc.yml Normal file
View file

@ -0,0 +1,14 @@
group: yao.login
type: process
desc: "Login widget processes for user authentication"
entries:
- name: admin
desc: Authenticate an admin user with email or mobile, password, and captcha verification
args:
- name: payload
type: object
required: true
desc: "Login payload with captcha.id (string), captcha.code (string), password (string), and either email (string) or mobile (string); optional sid (string) for session ID"
return:
type: object
desc: "Object with expires_at (number, token expiry unix timestamp), token (string, JWT), user (object with id, name, type, email, mobile, extra, status), and menus (app menu data)"