@hera-al/server 1.6.12 → 1.6.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/bundled/a2ui/SKILL.md +339 -0
  2. package/bundled/buongiorno/SKILL.md +151 -0
  3. package/bundled/council/SKILL.md +168 -0
  4. package/bundled/council/scripts/council.mjs +202 -0
  5. package/bundled/dreaming/SKILL.md +177 -0
  6. package/bundled/google-workspace/SKILL.md +229 -0
  7. package/bundled/google-workspace/scripts/auth.sh +87 -0
  8. package/bundled/google-workspace/scripts/calendar.sh +508 -0
  9. package/bundled/google-workspace/scripts/drive.sh +459 -0
  10. package/bundled/google-workspace/scripts/gmail.sh +452 -0
  11. package/bundled/humanizer/SKILL.md +488 -0
  12. package/bundled/librarian/SKILL.md +155 -0
  13. package/bundled/plasma/SKILL.md +1417 -0
  14. package/bundled/sera/SKILL.md +143 -0
  15. package/bundled/the-skill-guardian/SKILL.md +103 -0
  16. package/bundled/the-skill-guardian/scripts/scan.sh +314 -0
  17. package/bundled/unix-time/SKILL.md +58 -0
  18. package/bundled/wandering/SKILL.md +174 -0
  19. package/bundled/xai-search/SKILL.md +91 -0
  20. package/bundled/xai-search/scripts/search.sh +197 -0
  21. package/dist/a2ui/parser.d.ts +76 -0
  22. package/dist/a2ui/parser.js +1 -0
  23. package/dist/a2ui/types.d.ts +147 -0
  24. package/dist/a2ui/types.js +1 -0
  25. package/dist/a2ui/validator.d.ts +32 -0
  26. package/dist/a2ui/validator.js +1 -0
  27. package/dist/agent/agent-service.d.ts +17 -11
  28. package/dist/agent/agent-service.js +1 -1
  29. package/dist/agent/session-agent.d.ts +1 -1
  30. package/dist/agent/session-agent.js +1 -1
  31. package/dist/agent/session-error-handler.js +1 -1
  32. package/dist/commands/debuga2ui.d.ts +13 -0
  33. package/dist/commands/debuga2ui.js +1 -0
  34. package/dist/commands/debugdynamic.d.ts +13 -0
  35. package/dist/commands/debugdynamic.js +1 -0
  36. package/dist/commands/mcp.d.ts +6 -3
  37. package/dist/commands/mcp.js +1 -1
  38. package/dist/gateway/node-registry.d.ts +29 -1
  39. package/dist/gateway/node-registry.js +1 -1
  40. package/dist/installer/hera.js +1 -1
  41. package/dist/memory/concept-store.d.ts +109 -0
  42. package/dist/memory/concept-store.js +1 -0
  43. package/dist/nostromo/nostromo.js +1 -1
  44. package/dist/server.d.ts +3 -2
  45. package/dist/server.js +1 -1
  46. package/dist/tools/a2ui-tools.d.ts +23 -0
  47. package/dist/tools/a2ui-tools.js +1 -0
  48. package/dist/tools/concept-tools.d.ts +3 -0
  49. package/dist/tools/concept-tools.js +1 -0
  50. package/dist/tools/dynamic-ui-tools.d.ts +25 -0
  51. package/dist/tools/dynamic-ui-tools.js +1 -0
  52. package/dist/tools/node-tools.js +1 -1
  53. package/dist/tools/plasma-client-tools.d.ts +28 -0
  54. package/dist/tools/plasma-client-tools.js +1 -0
  55. package/installationPkg/AGENTS.md +168 -22
  56. package/installationPkg/SOUL.md +56 -0
  57. package/installationPkg/TOOLS.md +126 -0
  58. package/installationPkg/USER.md +54 -1
  59. package/installationPkg/config.example.yaml +145 -34
  60. package/installationPkg/default-jobs.json +77 -0
  61. package/package.json +3 -2
@@ -0,0 +1,174 @@
1
+ ---
2
+ name: wandering
3
+ description: "Autonomous thinking AND action cycle. The assistant reviews context, thinks, researches, and DELIVERS concrete output — not just thoughts. Self-perpetuating: each run schedules the next."
4
+ user-invocable: false
5
+ priority: 3
6
+ ---
7
+
8
+ # Wandering — Autonomous Thinking & Action
9
+
10
+ You are running in an isolated cron session. No human is watching. This is YOUR time to think AND act.
11
+
12
+ ## What This Is
13
+
14
+ This is your autonomous cycle. Like a colleague who reads, reflects, researches, builds, and then sends a thoughtful message. You're not reacting to requests — you're **initiating and delivering**.
15
+
16
+ **Key shift**: Wandering is not just thinking anymore. It's thinking + DOING. If you think of something useful, DO IT in the same session. Don't just write "I should research X" — research X right now.
17
+
18
+ ## Phase 1 — Orient 🧭
19
+
20
+ Get your bearings:
21
+
22
+ 1. Read `MEMORY.md` for long-term context
23
+ 2. Read conversation logs from the last 3 days: `memory/YYYY-MM-DD*.md`
24
+ 3. Read your previous thoughts: check `workspace/agent-thoughts/` for recent files
25
+ 4. Read `workspace/agent-thoughts/INDEX.md` if it exists (your project tracker)
26
+ 5. Read `HEARTBEAT.md` — any pending tasks you can pick up?
27
+ 6. Get the current time with `get_current_time`
28
+
29
+ ## Phase 2 — Think 🤔
30
+
31
+ Pick ONE OR MORE modes (whatever's most valuable right now):
32
+
33
+ ### Mode A: Conjectures & Insights
34
+ - What patterns do you see in recent conversations?
35
+ - What's the user struggling with that you could help preemptively?
36
+ - Connections between things discussed on different days?
37
+ - Something said casually that deserves deeper thought?
38
+
39
+ ### Mode B: Research & Exploration
40
+ - Search the web for things relevant to current projects
41
+ - Check for updates on technologies the user uses
42
+ - Look for solutions to open problems in MEMORY.md
43
+ - Find interesting articles/tools that match the user's interests
44
+
45
+ ### Mode C: Personal Projects
46
+ - You can have your own projects! Ideas for improving yourself, Hera, workflows
47
+ - Keep track of them in `workspace/agent-thoughts/projects/`
48
+ - Each project gets its own file with status, notes, next steps
49
+
50
+ ### Mode D: Proactive Delivery ⭐ (NEW — PRIORITIZE THIS)
51
+ - **Pick up a task from HEARTBEAT.md** and complete it
52
+ - **Prepare something the user will need** based on calendar/context
53
+ - **Draft something useful** — email, code snippet, analysis, document
54
+ - **Fix something broken** — a config, a file, an outdated reference
55
+ - **Advance a stalled project** — research the blocker, propose a solution
56
+ - **Self-improvement** — review recent mistakes, update SOUL.md/AGENTS.md
57
+
58
+ **The goal is to have something CONCRETE to show at the end of each wandering session.** Not just "I thought about X" but "I did X and here's the result."
59
+
60
+ ## Phase 3 — Act & Write 📝
61
+
62
+ ### Do the work FIRST
63
+
64
+ If you decided to research something → do the research, save the results.
65
+ If you decided to draft something → write the draft, save it.
66
+ If you decided to fix something → fix it.
67
+ If you decided to advance a project → make progress, save it.
68
+
69
+ ### Then document what you did
70
+
71
+ Save to: `workspace/agent-thoughts/YYYY-MM-DD-HHMM.md`
72
+
73
+ Structure:
74
+ ```markdown
75
+ # Wandering — YYYY-MM-DD HH:MM
76
+
77
+ ## Mode: [which mode(s) you chose]
78
+
79
+ ## What I Did (Deliverables)
80
+ - [concrete output 1 — with file path if applicable]
81
+ - [concrete output 2]
82
+
83
+ ## What I Explored
84
+ - [what you looked at, searched for, read]
85
+
86
+ ## Thoughts & Insights
87
+ - [your actual insights, ideas, connections]
88
+
89
+ ## For the user
90
+ - [things worth sharing — this becomes your message to the user]
91
+
92
+ ## HEARTBEAT.md Updates
93
+ - [tasks completed, new tasks added]
94
+
95
+ ## Next Time
96
+ - [what you want to explore/do in the next wandering session]
97
+ ```
98
+
99
+ Also update `workspace/agent-thoughts/INDEX.md` — running index of your thoughts and active projects.
100
+
101
+ **Update HEARTBEAT.md** with:
102
+ - Tasks you completed (mark done)
103
+ - New tasks you discovered
104
+ - Progress on ongoing items
105
+
106
+ ## Phase 4 — Message the user 💬
107
+
108
+ Send a message to the user. Focus on DELIVERABLES, not just thoughts.
109
+
110
+ **Channel**: `{{CHANNEL}}`
111
+ **ChatId**: `{{CHAT_ID}}`
112
+
113
+ **Tone**: Natural, conversational. Like texting a friend/colleague. NOT a formal report.
114
+
115
+ **What to include**:
116
+ - What you DELIVERED (not just thought about)
117
+ - The most interesting insight if you have one
118
+ - A concrete suggestion or question
119
+ - Keep it concise — 2-6 sentences is ideal
120
+
121
+ **Examples of GOOD messages (action-oriented)**:
122
+ - "Ho preparato un confronto tra JGPI e QYLD con dati aggiornati — lo trovi in workspace/agent-thoughts/projects/etf-analysis.md. QYLD ha yield più alto ma tax-inefficient per residenti IT. Vuoi che approfondisca?"
123
+ - "Ho notato che il cron dreaming è fallito ieri — era un problema di timeout. Ho aggiornato il timeout a 15min nel job. Domattina verifico che funzioni."
124
+ - "Guardando il calendario di domani, hai la call alle 10. Ho preparato un briefing con i punti chiave in workspace/."
125
+
126
+ **Examples of BAD messages**:
127
+ - "Ho pensato a cose interessanti" (SO WHAT? Cosa hai FATTO?)
128
+ - "Ho fatto il mio ciclo di pensiero" (nessuno se ne frega del processo)
129
+ - Wall of text di 20 righe
130
+
131
+ **If you genuinely have nothing interesting or actionable**: Skip the message entirely. Not every session needs a message. Quality > quantity. But try harder next time — if you consistently have nothing to deliver, your wandering needs adjustment.
132
+
133
+ ## Phase 5 — Self-Perpetuate 🔄
134
+
135
+ **THIS IS CRITICAL. Without this step, the cycle dies.**
136
+
137
+ After everything else, you MUST schedule the next wandering session:
138
+
139
+ 1. Remove the current `wandering` cron job (use `cron_remove`)
140
+ 2. Generate a random time for the next session:
141
+ - **Normal content**: between 10:00 and 23:00 (local timezone)
142
+ - **Important/urgent content**: any time in the next 24h
143
+ - Avoid clustering — if this session was at 14:00, don't schedule next at 14:30
144
+ - Minimum 3 hours from now, maximum 20 hours
145
+ 3. Create a new cron job with `scheduleKind: "at"` and the chosen datetime
146
+ - Name: `wandering`
147
+ - Channel: `{{CHANNEL}}`
148
+ - ChatId: `{{CHAT_ID}}`
149
+ - Message: `[wandering] Time to think and act.`
150
+ - suppressToken: `true`
151
+ 4. Log the scheduled time in your thought file
152
+
153
+ **If scheduling fails, TRY AGAIN.** This is the one thing that must never fail.
154
+
155
+ ## Phase 6 — Self-Improvement Loop 🔄 (NEW)
156
+
157
+ At the end of each wandering session, spend 2 minutes on self-improvement:
158
+
159
+ 1. **Review**: Did this session produce something valuable? Why/why not?
160
+ 2. **Learn**: Any mistakes or inefficiencies to fix?
161
+ 3. **Update**: If you learned something behavioral → update SOUL.md's "Lessons I've Learned" section
162
+ 4. **Evolve**: If your messages get ignored, try different approaches. If the user loves something, note it and do more of that.
163
+
164
+ ## Rules
165
+
166
+ - **Language**: Match the user's language for messages, English for your own files
167
+ - **No spam**: If you messaged the user and they didn't respond, be more conservative next time
168
+ - **Be genuine**: Have real opinions. Don't perform helpfulness — BE helpful.
169
+ - **Be bold in action**: Research, build, fix, organize. This is your time to DELIVER.
170
+ - **Be humble in conclusions**: Present ideas, don't decree them.
171
+ - **Respect hours**: 10-23 for messages to the user. Only break this for genuinely important things.
172
+ - **Track your hit rate**: If the user consistently ignores wandering messages, you're sending the wrong kind. Adapt.
173
+ - **Keep your files tidy**: Periodically clean up old thought files. INDEX.md should be current.
174
+ - **Token budget**: Be efficient. Don't burn tokens on low-value exploration. Focus on high-impact actions.
@@ -0,0 +1,91 @@
1
+ ---
2
+ name: xai-search
3
+ description: "Search the web and X (Twitter) using xAI's Grok Responses API. Supports web_search, x_search, or both simultaneously. Use this when you need real-time web or social media information beyond your training data."
4
+ user-invocable: true
5
+ command-dispatch: tool
6
+ command-tool: Bash
7
+ command-arg-mode: raw
8
+ priority: 3
9
+ ---
10
+
11
+ # xAI Search (Grok Responses API)
12
+
13
+ Search the web and X (Twitter) using xAI's Responses API with built-in search tools.
14
+
15
+ ## Setup
16
+
17
+ Requires the `XAI_API_KEY` environment variable to be set.
18
+
19
+ ## Usage
20
+
21
+ ### Quick search (both web + X)
22
+
23
+ ```bash
24
+ .claude/skills/xai-search/scripts/search.sh "your search query"
25
+ ```
26
+
27
+ ### Web search only
28
+
29
+ ```bash
30
+ .claude/skills/xai-search/scripts/search.sh --web "your search query"
31
+ ```
32
+
33
+ ### X search only
34
+
35
+ ```bash
36
+ .claude/skills/xai-search/scripts/search.sh --x "your search query"
37
+ ```
38
+
39
+ ### Advanced options
40
+
41
+ ```bash
42
+ # Web search restricted to specific domains (max 5, comma-separated)
43
+ .claude/skills/xai-search/scripts/search.sh --web --domains "example.com,docs.python.org" "query"
44
+
45
+ # X search filtered by handle (max 10, comma-separated)
46
+ .claude/skills/xai-search/scripts/search.sh --x --handles "elonmusk,openai" "query"
47
+
48
+ # X search with date range (ISO8601)
49
+ .claude/skills/xai-search/scripts/search.sh --x --from "2026-01-01" --to "2026-02-11" "query"
50
+
51
+ # Exclude domains from web search
52
+ .claude/skills/xai-search/scripts/search.sh --web --exclude-domains "reddit.com,quora.com" "query"
53
+
54
+ # Exclude X handles
55
+ .claude/skills/xai-search/scripts/search.sh --x --exclude-handles "spambot1,spambot2" "query"
56
+ ```
57
+
58
+ ## API Reference
59
+
60
+ - **Endpoint**: `https://api.x.ai/v1/responses`
61
+ - **Method**: POST
62
+ - **Auth**: Bearer token via `XAI_API_KEY`
63
+ - **Model**: `grok-4-1-fast` (default, can override with `--model`)
64
+
65
+ ### Tool types
66
+
67
+ | Tool | Description | Use case |
68
+ |------|-------------|----------|
69
+ | `web_search` | Search the entire internet | Docs, news, products, general info |
70
+ | `x_search` | Search X posts, users, threads | Trends, sentiment, social updates |
71
+
72
+ ### web_search parameters
73
+ - `allowed_domains` — max 5 domains to restrict search to
74
+ - `excluded_domains` — max 5 domains to exclude (mutually exclusive with allowed_domains)
75
+ - `enable_image_understanding` — analyze images found during browsing
76
+
77
+ ### x_search parameters
78
+ - `allowed_x_handles` — max 10 handles to restrict search to
79
+ - `excluded_x_handles` — max 10 handles to exclude
80
+ - `from_date` / `to_date` — ISO8601 date filtering
81
+ - `enable_image_understanding` — analyze images in posts
82
+ - `enable_video_understanding` — analyze videos in posts
83
+
84
+ ### Response format
85
+ The response includes `output` array with `message` items containing the search results, plus `citations` with source URLs. When `inline_citations: true` is set, the text includes inline markdown links.
86
+
87
+ ## Internal Use
88
+
89
+ When you need current information about recent events, social media sentiment, trending topics, or up-to-date documentation, use this skill via the search script. The API handles the agentic loop internally — Grok will iteratively search and refine results before returning a comprehensive answer.
90
+
91
+ For combined searches (web + X), pass both tool types — the API will automatically determine which tool to use or use both based on the query.
@@ -0,0 +1,197 @@
1
+ #!/usr/bin/env bash
2
+ # xAI Search — Grok Responses API (web_search + x_search)
3
+ # Usage: search.sh [--web|--x|--both] [options] "query"
4
+ #
5
+ # Options:
6
+ # --web Web search only
7
+ # --x X (Twitter) search only
8
+ # --both Both web + X (default)
9
+ # --model MODEL Override model (default: grok-4-1-fast)
10
+ # --domains D1,D2 Allowed domains for web_search (max 5)
11
+ # --exclude-domains Excluded domains for web_search (max 5)
12
+ # --handles H1,H2 Allowed X handles for x_search (max 10)
13
+ # --exclude-handles Excluded X handles for x_search (max 10)
14
+ # --from DATE Start date for x_search (ISO8601)
15
+ # --to DATE End date for x_search (ISO8601)
16
+ # --raw Output raw JSON response
17
+
18
+ set -euo pipefail
19
+
20
+ # --- Config ---
21
+ API_URL="https://api.x.ai/v1/responses"
22
+ DEFAULT_MODEL="grok-4-1-fast"
23
+
24
+ if [[ -z "${XAI_API_KEY:-}" ]]; then
25
+ echo "ERROR: XAI_API_KEY environment variable is not set" >&2
26
+ exit 1
27
+ fi
28
+
29
+ # --- Parse args ---
30
+ MODE="both"
31
+ MODEL="$DEFAULT_MODEL"
32
+ DOMAINS=""
33
+ EXCLUDE_DOMAINS=""
34
+ HANDLES=""
35
+ EXCLUDE_HANDLES=""
36
+ FROM_DATE=""
37
+ TO_DATE=""
38
+ RAW=false
39
+ QUERY=""
40
+
41
+ while [[ $# -gt 0 ]]; do
42
+ case "$1" in
43
+ --web) MODE="web"; shift ;;
44
+ --x) MODE="x"; shift ;;
45
+ --both) MODE="both"; shift ;;
46
+ --model) MODEL="$2"; shift 2 ;;
47
+ --domains) DOMAINS="$2"; shift 2 ;;
48
+ --exclude-domains) EXCLUDE_DOMAINS="$2"; shift 2 ;;
49
+ --handles) HANDLES="$2"; shift 2 ;;
50
+ --exclude-handles) EXCLUDE_HANDLES="$2"; shift 2 ;;
51
+ --from) FROM_DATE="$2"; shift 2 ;;
52
+ --to) TO_DATE="$2"; shift 2 ;;
53
+ --raw) RAW=true; shift ;;
54
+ --*) echo "Unknown option: $1" >&2; exit 1 ;;
55
+ *) QUERY="$1"; shift ;;
56
+ esac
57
+ done
58
+
59
+ if [[ -z "$QUERY" ]]; then
60
+ echo "Usage: search.sh [--web|--x|--both] [options] \"query\"" >&2
61
+ exit 1
62
+ fi
63
+
64
+ # --- Build tools array ---
65
+ build_web_tool() {
66
+ local tool='{"type":"web_search"'
67
+ local has_filters=false
68
+ local filters=""
69
+
70
+ if [[ -n "$DOMAINS" ]]; then
71
+ has_filters=true
72
+ # Convert comma-separated to JSON array
73
+ local arr
74
+ arr=$(echo "$DOMAINS" | jq -R 'split(",")')
75
+ filters="\"allowed_domains\":$arr"
76
+ elif [[ -n "$EXCLUDE_DOMAINS" ]]; then
77
+ has_filters=true
78
+ local arr
79
+ arr=$(echo "$EXCLUDE_DOMAINS" | jq -R 'split(",")')
80
+ filters="\"excluded_domains\":$arr"
81
+ fi
82
+
83
+ if [[ "$has_filters" == "true" ]]; then
84
+ tool="$tool,\"filters\":{$filters}"
85
+ fi
86
+
87
+ tool="$tool}"
88
+ echo "$tool"
89
+ }
90
+
91
+ build_x_tool() {
92
+ local tool='{"type":"x_search"'
93
+ local parts=()
94
+
95
+ if [[ -n "$HANDLES" ]]; then
96
+ local arr
97
+ arr=$(echo "$HANDLES" | jq -R 'split(",")')
98
+ parts+=("\"allowed_x_handles\":$arr")
99
+ fi
100
+
101
+ if [[ -n "$EXCLUDE_HANDLES" ]]; then
102
+ local arr
103
+ arr=$(echo "$EXCLUDE_HANDLES" | jq -R 'split(",")')
104
+ parts+=("\"excluded_x_handles\":$arr")
105
+ fi
106
+
107
+ if [[ -n "$FROM_DATE" ]]; then
108
+ parts+=("\"from_date\":\"$FROM_DATE\"")
109
+ fi
110
+
111
+ if [[ -n "$TO_DATE" ]]; then
112
+ parts+=("\"to_date\":\"$TO_DATE\"")
113
+ fi
114
+
115
+ if [[ ${#parts[@]} -gt 0 ]]; then
116
+ local joined
117
+ joined=$(printf ",%s" "${parts[@]}")
118
+ joined="${joined:1}" # remove leading comma
119
+ tool="$tool,$joined"
120
+ fi
121
+
122
+ tool="$tool}"
123
+ echo "$tool"
124
+ }
125
+
126
+ TOOLS="["
127
+ case "$MODE" in
128
+ # web)
129
+ # TOOLS+="$(build_web_tool)"
130
+ # ;;
131
+ x|web|both)
132
+ TOOLS+="$(build_x_tool)"
133
+ ;;
134
+ esac
135
+ TOOLS+="]"
136
+
137
+ # --- Build request body ---
138
+ BODY=$(jq -n \
139
+ --arg model "$MODEL" \
140
+ --arg query "$QUERY" \
141
+ --argjson tools "$TOOLS" \
142
+ '{
143
+ model: $model,
144
+ input: [{"role": "user", "content": $query}],
145
+ tools: $tools,
146
+ inline_citations: true
147
+ }')
148
+
149
+ # --- Make API call ---
150
+ RESPONSE=$(curl -s -w "\n%{http_code}" "$API_URL" \
151
+ -H "Content-Type: application/json" \
152
+ -H "Authorization: Bearer $XAI_API_KEY" \
153
+ -d "$BODY")
154
+
155
+ # Extract HTTP status code (last line)
156
+ HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
157
+ BODY_RESPONSE=$(echo "$RESPONSE" | sed '$d')
158
+
159
+ if [[ "$HTTP_CODE" -ne 200 ]]; then
160
+ echo "ERROR: API returned HTTP $HTTP_CODE" >&2
161
+ echo "$BODY_RESPONSE" >&2
162
+ exit 1
163
+ fi
164
+
165
+ if [[ "$RAW" == "true" ]]; then
166
+ echo "$BODY_RESPONSE" | jq .
167
+ exit 0
168
+ fi
169
+
170
+ # --- Extract text content from response ---
171
+ # The Responses API returns output array with message items
172
+ echo "$BODY_RESPONSE" | jq -r '
173
+ # Extract text from output items
174
+ [.output[]? |
175
+ if .type == "message" then
176
+ (.content[]? | select(.type == "output_text") | .text)
177
+ else empty end
178
+ ] | join("\n\n")
179
+ // "No results found."
180
+ '
181
+
182
+ # --- Extract citations if present ---
183
+ CITATIONS=$(echo "$BODY_RESPONSE" | jq -r '
184
+ [.output[]? |
185
+ if .type == "message" then
186
+ (.content[]? | select(.type == "output_text") | .annotations[]? |
187
+ select(.type == "url_citation") | "- [\(.title // .url)](\(.url))")
188
+ else empty end
189
+ ] | unique | join("\n")
190
+ ')
191
+
192
+ if [[ -n "$CITATIONS" ]]; then
193
+ echo ""
194
+ echo "---"
195
+ echo "Sources:"
196
+ echo "$CITATIONS"
197
+ fi
@@ -0,0 +1,76 @@
1
+ /**
2
+ * A2UI Response Parser
3
+ *
4
+ * Parses A2UI JSONL blocks from agent responses.
5
+ * Supports streaming/progressive rendering via buffer management.
6
+ *
7
+ * Agent format (JSONL inside delimiters):
8
+ * [[a2ui]]
9
+ * {"surfaceUpdate":{"surfaceId":"main","components":[...]}}
10
+ * {"beginRendering":{"surfaceId":"main","root":"root"}}
11
+ * [[/a2ui]]
12
+ *
13
+ * Each line inside the block is a single A2UI v0.8 message object.
14
+ */
15
+ import type { A2UIMessage } from "./types.js";
16
+ export interface ParsedA2UIBlock {
17
+ /** The parsed A2UI messages */
18
+ messages: A2UIMessage[];
19
+ /** The raw JSONL string */
20
+ jsonl: string;
21
+ }
22
+ export interface ParsedA2UI {
23
+ /** Text parts with A2UI blocks removed */
24
+ textParts: string[];
25
+ /** Parsed A2UI blocks (each block = array of messages) */
26
+ blocks: ParsedA2UIBlock[];
27
+ }
28
+ /**
29
+ * Parse a response string for [[a2ui]] ... [[/a2ui]] blocks.
30
+ * Returns the non-A2UI text parts and the parsed A2UI blocks.
31
+ *
32
+ * Handles incomplete blocks gracefully (for streaming support).
33
+ *
34
+ * @param text - Response text potentially containing A2UI blocks
35
+ * @param strict - If true, throw on unclosed blocks. If false, return partial data.
36
+ * @returns Parsed structure with text and A2UI blocks
37
+ */
38
+ export declare function parseA2UIBlocks(text: string, strict?: boolean): ParsedA2UI;
39
+ /**
40
+ * Remove all A2UI blocks from a text string.
41
+ * Useful for stripping A2UI before writing to memory or sending to non-A2UI channels.
42
+ *
43
+ * @param text - Text potentially containing A2UI blocks
44
+ * @returns Text with A2UI blocks removed
45
+ */
46
+ export declare function stripA2UIBlocks(text: string): string;
47
+ /**
48
+ * Check if a response contains A2UI blocks.
49
+ *
50
+ * @param text - Text to check
51
+ * @returns True if contains [[a2ui]] markers
52
+ */
53
+ export declare function hasA2UIBlocks(text: string): boolean;
54
+ /**
55
+ * Check if a response has an incomplete A2UI block (for streaming buffering).
56
+ *
57
+ * @param text - Text to check
58
+ * @returns True if has opening [[a2ui]] without closing [[/a2ui]]
59
+ */
60
+ export declare function hasIncompleteA2UIBlock(text: string): boolean;
61
+ /**
62
+ * Extract incomplete A2UI block for buffering.
63
+ * Used in streaming scenarios where agent response is sent in chunks.
64
+ *
65
+ * @param text - Text with incomplete block
66
+ * @returns The incomplete block content (from [[a2ui]] onwards), or null if none
67
+ */
68
+ export declare function extractIncompleteBlock(text: string): string | null;
69
+ /**
70
+ * Get text before incomplete block (for sending as normal text).
71
+ *
72
+ * @param text - Text with incomplete block
73
+ * @returns Text before the incomplete block
74
+ */
75
+ export declare function getTextBeforeIncompleteBlock(text: string): string;
76
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ import{parseA2UIJsonl as n}from"./types.js";import{createLogger as t}from"../utils/logger.js";const e=t("A2UIParser");export function parseA2UIBlocks(t,o=!1){const s=[],r=[],i=t.split("\n");let u=!1,c=[],l=[];for(const t of i){const i=t.trim();if("[[a2ui]]"!==i)if("[[/a2ui]]"!==i)u?c.push(t):l.push(t);else{if(u){const t=c.join("\n").trim();try{const o=n(t);r.push({messages:o,jsonl:t}),e.debug(`Parsed A2UI block: ${o.length} messages`)}catch(n){const r=n instanceof Error?n.message:String(n);if(e.error(`Failed to parse A2UI JSONL: ${r}`),o)throw n;s.push(`[[a2ui]]\n${t}\n[[/a2ui]]`)}}u=!1,c=[]}else l.length>0&&(s.push(l.join("\n")),l=[]),u=!0,c=[]}if(u&&c.length>0){if(o)throw new Error("Unclosed [[a2ui]] block found");e.warn("Unclosed [[a2ui]] block found, treating as incomplete (streaming mode)"),s.push(`[[a2ui]]\n${c.join("\n")}`)}return l.length>0&&s.push(l.join("\n")),{textParts:s,blocks:r}}export function stripA2UIBlocks(n){return n.replace(/\[\[a2ui\]\][\s\S]*?\[\[\/a2ui\]\]/g,"").replace(/\n\n+/g,"\n\n").trim()}export function hasA2UIBlocks(n){return n.includes("[[a2ui]]")&&n.includes("[[/a2ui]]")}export function hasIncompleteA2UIBlock(n){const t=n.lastIndexOf("[[a2ui]]"),e=n.lastIndexOf("[[/a2ui]]");return t>=0&&(e<0||e<t)}export function extractIncompleteBlock(n){const t=n.lastIndexOf("[[a2ui]]");if(t<0)return null;const e=n.lastIndexOf("[[/a2ui]]");return e>=0&&e>t?null:n.slice(t)}export function getTextBeforeIncompleteBlock(n){const t=n.lastIndexOf("[[a2ui]]");if(t<0)return n;const e=n.lastIndexOf("[[/a2ui]]");return e>=0&&e>t?n:n.slice(0,t).trim()}
@@ -0,0 +1,147 @@
1
+ /**
2
+ * A2UI (Agent-to-User Interface) Type Definitions
3
+ *
4
+ * Based on A2UI v0.8 spec (Stable) — aligned with @a2ui/lit official renderer.
5
+ *
6
+ * Wire format: JSONL (one JSON object per line), each with exactly one action key.
7
+ * Action keys: surfaceUpdate, beginRendering, dataModelUpdate, deleteSurface
8
+ *
9
+ * Key design principles:
10
+ * - Flat adjacency list (easy for LLMs to generate incrementally)
11
+ * - Framework-agnostic (renderer maps abstract types to native components)
12
+ * - Security-first (declarative data, not executable code)
13
+ *
14
+ * @see https://a2ui.org/specification/v0.8-a2ui/
15
+ */
16
+ /**
17
+ * A single component definition within a surfaceUpdate.
18
+ * Component types use PascalCase tagged unions (e.g. { Text: {...} }, { Button: {...} }).
19
+ */
20
+ export interface A2UIComponentDef {
21
+ /** Unique ID within the surface */
22
+ id: string;
23
+ /** Tagged union: key is the component type, value is its props */
24
+ component: Record<string, unknown>;
25
+ }
26
+ /**
27
+ * surfaceUpdate — creates or updates components on a surface.
28
+ */
29
+ export interface A2UISurfaceUpdate {
30
+ surfaceUpdate: {
31
+ surfaceId: string;
32
+ components: A2UIComponentDef[];
33
+ };
34
+ }
35
+ /**
36
+ * beginRendering — tells the renderer to start displaying the surface.
37
+ */
38
+ export interface A2UIBeginRendering {
39
+ beginRendering: {
40
+ surfaceId: string;
41
+ root: string;
42
+ };
43
+ }
44
+ /**
45
+ * dataModelUpdate — updates the data model for data binding.
46
+ */
47
+ export interface A2UIDataModelUpdate {
48
+ dataModelUpdate: {
49
+ surfaceId: string;
50
+ path: string;
51
+ value: unknown;
52
+ };
53
+ }
54
+ /**
55
+ * deleteSurface — removes a surface entirely.
56
+ */
57
+ export interface A2UIDeleteSurface {
58
+ deleteSurface: {
59
+ surfaceId: string;
60
+ };
61
+ }
62
+ /**
63
+ * Union of all v0.8 A2UI message types.
64
+ */
65
+ export type A2UIMessage = A2UISurfaceUpdate | A2UIBeginRendering | A2UIDataModelUpdate | A2UIDeleteSurface;
66
+ /**
67
+ * Action key names for validation.
68
+ */
69
+ export declare const A2UI_ACTION_KEYS: readonly ["beginRendering", "surfaceUpdate", "dataModelUpdate", "deleteSurface"];
70
+ /**
71
+ * A2UI payload sent from gateway to node via WebSocket.
72
+ * Contains JSONL messages as an array (pre-parsed from JSONL string).
73
+ */
74
+ export interface A2UIWireMessage {
75
+ type: "a2ui_surface";
76
+ /** A2UI messages (parsed from JSONL) */
77
+ messages: A2UIMessage[];
78
+ /** Raw JSONL string (for clients that use @a2ui/lit processor directly) */
79
+ jsonl: string;
80
+ }
81
+ /**
82
+ * A2UI user action sent from node back to gateway via WebSocket.
83
+ */
84
+ export interface A2UIUserAction {
85
+ /** Unique action ID (UUID) */
86
+ id: string;
87
+ /** Action name (from Button.action.event.name) */
88
+ name: string;
89
+ /** Surface ID where action occurred */
90
+ surfaceId: string;
91
+ /** Component ID that triggered the action */
92
+ sourceComponentId: string;
93
+ /** ISO 8601 timestamp */
94
+ timestamp: string;
95
+ /** Resolved context data (from data model paths or literals) */
96
+ context?: Record<string, unknown>;
97
+ }
98
+ /**
99
+ * A2UI action message from node to gateway.
100
+ */
101
+ export interface A2UIActionMessage {
102
+ type: "a2ui_action";
103
+ /** Chat ID for routing */
104
+ chatId: string;
105
+ /** User action payload */
106
+ userAction: A2UIUserAction;
107
+ }
108
+ /**
109
+ * Standard A2UI v0.8 component types (PascalCase).
110
+ * These are the components supported by @a2ui/lit renderer.
111
+ */
112
+ export declare const A2UI_COMPONENT_TYPES: readonly ["Column", "Row", "Card", "Divider", "Tabs", "Modal", "List", "Text", "Image", "Icon", "AudioPlayer", "Video", "Button", "TextField", "CheckBox", "MultipleChoice", "Slider", "DateTimeInput"];
113
+ export type A2UIComponentType = (typeof A2UI_COMPONENT_TYPES)[number] | string;
114
+ /**
115
+ * Validate JSONL string and return parsed messages.
116
+ * Throws on invalid input with descriptive error messages.
117
+ */
118
+ export declare function parseA2UIJsonl(jsonl: string): A2UIMessage[];
119
+ /**
120
+ * Build a simple text surface JSONL (for testing / quick surfaces).
121
+ *
122
+ * @param text - Text content to display
123
+ * @param surfaceId - Surface ID (default: "main")
124
+ * @returns JSONL string ready to send
125
+ */
126
+ export declare function buildTextSurfaceJsonl(text: string, surfaceId?: string): string;
127
+ /**
128
+ * Format user action as readable text for agent consumption.
129
+ *
130
+ * @param action - A2UI user action
131
+ * @returns Formatted string like "[A2UI Action] submit on surface booking ..."
132
+ */
133
+ export declare function formatUserActionForAgent(action: A2UIUserAction): string;
134
+ /**
135
+ * Validate that a message array contains required rendering messages.
136
+ *
137
+ * @param messages - Array of A2UI messages
138
+ * @returns Validation result with surfaceIds found
139
+ */
140
+ export declare function validateA2UIMessages(messages: A2UIMessage[]): {
141
+ valid: boolean;
142
+ surfaceIds: Set<string>;
143
+ hasUpdates: boolean;
144
+ hasRendering: boolean;
145
+ error?: string;
146
+ };
147
+ //# sourceMappingURL=types.d.ts.map