@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,459 @@
1
+ #!/usr/bin/env bash
2
+ # Google Drive API client — REST API v3 with OAuth2
3
+ # Usage: drive.sh <command> [options]
4
+ #
5
+ # Commands:
6
+ # list [--max N] [--folder ID] List files
7
+ # search "query" [--max N] Search files (Drive query syntax)
8
+ # info <fileId> Get file metadata
9
+ # read <fileId> Read/export file content (text)
10
+ # download <fileId> --output PATH Download binary file
11
+ # upload PATH [--folder ID] [--name N] Upload a file
12
+ # create-doc --name N [--content T] Create a Google Doc
13
+ # move <fileId> --to FOLDER_ID Move file to folder
14
+ # rename <fileId> --name NEW_NAME Rename a file
15
+ # share <fileId> [options] Share a file
16
+ # trash <fileId> Move to trash
17
+
18
+ set -euo pipefail
19
+
20
+ # --- Config ---
21
+ API_BASE="https://www.googleapis.com/drive/v3"
22
+ UPLOAD_BASE="https://www.googleapis.com/upload/drive/v3"
23
+ TOKEN_FILE="${HOME}/.gmab-google-token.json"
24
+
25
+ # --- Token management ---
26
+ get_access_token() {
27
+ local client_id="${GOOGLE_CLIENT_ID:-}"
28
+ local client_secret="${GOOGLE_CLIENT_SECRET:-}"
29
+ local refresh_token="${GOOGLE_REFRESH_TOKEN:-}"
30
+
31
+ # Try token file if env vars not set
32
+ if [[ -z "$refresh_token" && -f "$TOKEN_FILE" ]]; then
33
+ client_id=$(jq -r '.client_id // empty' "$TOKEN_FILE" 2>/dev/null || true)
34
+ client_secret=$(jq -r '.client_secret // empty' "$TOKEN_FILE" 2>/dev/null || true)
35
+ refresh_token=$(jq -r '.refresh_token // empty' "$TOKEN_FILE" 2>/dev/null || true)
36
+ fi
37
+
38
+ if [[ -z "$client_id" || -z "$client_secret" || -z "$refresh_token" ]]; then
39
+ echo "ERROR: Google credentials not configured." >&2
40
+ echo "Set GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, GOOGLE_REFRESH_TOKEN" >&2
41
+ echo "Or run scripts/google/auth.sh to set up OAuth2." >&2
42
+ exit 1
43
+ fi
44
+
45
+ # Check cached token
46
+ if [[ -f "$TOKEN_FILE" ]]; then
47
+ local cached_token cached_expiry
48
+ cached_token=$(jq -r '.access_token // empty' "$TOKEN_FILE" 2>/dev/null || true)
49
+ cached_expiry=$(jq -r '.expires_at // 0' "$TOKEN_FILE" 2>/dev/null || true)
50
+ local now
51
+ now=$(date +%s)
52
+ if [[ -n "$cached_token" && "$cached_expiry" -gt "$now" ]]; then
53
+ echo "$cached_token"
54
+ return
55
+ fi
56
+ fi
57
+
58
+ # Refresh the token
59
+ local response
60
+ response=$(curl -s "https://oauth2.googleapis.com/token" \
61
+ -d "client_id=$client_id" \
62
+ -d "client_secret=$client_secret" \
63
+ -d "refresh_token=$refresh_token" \
64
+ -d "grant_type=refresh_token")
65
+
66
+ local access_token
67
+ access_token=$(echo "$response" | jq -r '.access_token // empty')
68
+ local expires_in
69
+ expires_in=$(echo "$response" | jq -r '.expires_in // 3600')
70
+
71
+ if [[ -z "$access_token" ]]; then
72
+ echo "ERROR: Failed to refresh access token" >&2
73
+ echo "$response" >&2
74
+ exit 1
75
+ fi
76
+
77
+ # Cache token
78
+ local expires_at
79
+ expires_at=$(($(date +%s) + expires_in - 60))
80
+
81
+ if [[ -f "$TOKEN_FILE" ]]; then
82
+ local tmp
83
+ tmp=$(jq --arg at "$access_token" --argjson ea "$expires_at" \
84
+ '. + {access_token: $at, expires_at: $ea}' "$TOKEN_FILE")
85
+ echo "$tmp" > "$TOKEN_FILE"
86
+ else
87
+ jq -n \
88
+ --arg ci "$client_id" \
89
+ --arg cs "$client_secret" \
90
+ --arg rt "$refresh_token" \
91
+ --arg at "$access_token" \
92
+ --argjson ea "$expires_at" \
93
+ '{client_id: $ci, client_secret: $cs, refresh_token: $rt, access_token: $at, expires_at: $ea}' \
94
+ > "$TOKEN_FILE"
95
+ fi
96
+ chmod 600 "$TOKEN_FILE"
97
+
98
+ echo "$access_token"
99
+ }
100
+
101
+ api_get() {
102
+ local url="$1"
103
+ local token
104
+ token=$(get_access_token)
105
+ curl -s -H "Authorization: Bearer $token" "$url"
106
+ }
107
+
108
+ api_post() {
109
+ local url="$1"
110
+ local data="${2:-}"
111
+ local token
112
+ token=$(get_access_token)
113
+ if [[ -n "$data" ]]; then
114
+ curl -s -H "Authorization: Bearer $token" \
115
+ -H "Content-Type: application/json" \
116
+ -d "$data" "$url"
117
+ else
118
+ curl -s -X POST -H "Authorization: Bearer $token" "$url"
119
+ fi
120
+ }
121
+
122
+ api_patch() {
123
+ local url="$1"
124
+ local data="$2"
125
+ local token
126
+ token=$(get_access_token)
127
+ curl -s -X PATCH -H "Authorization: Bearer $token" \
128
+ -H "Content-Type: application/json" \
129
+ -d "$data" "$url"
130
+ }
131
+
132
+ api_download() {
133
+ local url="$1"
134
+ local output="$2"
135
+ local token
136
+ token=$(get_access_token)
137
+ curl -s -H "Authorization: Bearer $token" -o "$output" "$url"
138
+ }
139
+
140
+ urlencode() {
141
+ python3 -c "import sys, urllib.parse; print(urllib.parse.quote(sys.stdin.read().strip()))" <<< "$1" 2>/dev/null || echo "$1"
142
+ }
143
+
144
+ # --- Commands ---
145
+ cmd_list() {
146
+ local max=20 folder=""
147
+ while [[ $# -gt 0 ]]; do
148
+ case "$1" in
149
+ --max) max="$2"; shift 2 ;;
150
+ --folder) folder="$2"; shift 2 ;;
151
+ *) shift ;;
152
+ esac
153
+ done
154
+
155
+ local query="trashed=false"
156
+ if [[ -n "$folder" ]]; then
157
+ query="'${folder}' in parents and trashed=false"
158
+ fi
159
+
160
+ local encoded_q
161
+ encoded_q=$(urlencode "$query")
162
+
163
+ api_get "${API_BASE}/files?pageSize=${max}&q=${encoded_q}&fields=files(id,name,mimeType,modifiedTime,size,parents)&orderBy=modifiedTime%20desc" | \
164
+ jq '[.files[]? | {id, name, mimeType, modifiedTime, size, parents}]'
165
+ }
166
+
167
+ cmd_search() {
168
+ local query="$1"; shift
169
+ local max=20
170
+ while [[ $# -gt 0 ]]; do
171
+ case "$1" in
172
+ --max) max="$2"; shift 2 ;;
173
+ *) shift ;;
174
+ esac
175
+ done
176
+
177
+ local full_query="${query} and trashed=false"
178
+ local encoded_q
179
+ encoded_q=$(urlencode "$full_query")
180
+
181
+ api_get "${API_BASE}/files?pageSize=${max}&q=${encoded_q}&fields=files(id,name,mimeType,modifiedTime,size,parents)&orderBy=modifiedTime%20desc" | \
182
+ jq '[.files[]? | {id, name, mimeType, modifiedTime, size, parents}]'
183
+ }
184
+
185
+ cmd_info() {
186
+ local file_id="$1"
187
+ api_get "${API_BASE}/files/${file_id}?fields=id,name,mimeType,modifiedTime,createdTime,size,parents,webViewLink,webContentLink,shared,owners,permissions" | jq .
188
+ }
189
+
190
+ cmd_read() {
191
+ local file_id="$1"
192
+
193
+ # First get the mime type to determine export format
194
+ local info
195
+ info=$(api_get "${API_BASE}/files/${file_id}?fields=mimeType,name")
196
+ local mime
197
+ mime=$(echo "$info" | jq -r '.mimeType')
198
+ local name
199
+ name=$(echo "$info" | jq -r '.name')
200
+
201
+ echo "# File: $name ($mime)" >&2
202
+
203
+ case "$mime" in
204
+ application/vnd.google-apps.document)
205
+ api_get "${API_BASE}/files/${file_id}/export?mimeType=text/plain"
206
+ ;;
207
+ application/vnd.google-apps.spreadsheet)
208
+ api_get "${API_BASE}/files/${file_id}/export?mimeType=text/csv"
209
+ ;;
210
+ application/vnd.google-apps.presentation)
211
+ api_get "${API_BASE}/files/${file_id}/export?mimeType=text/plain"
212
+ ;;
213
+ text/*|application/json|application/xml|application/javascript)
214
+ api_get "${API_BASE}/files/${file_id}?alt=media"
215
+ ;;
216
+ *)
217
+ echo "Binary file — use 'download' command instead." >&2
218
+ echo "MIME type: $mime"
219
+ ;;
220
+ esac
221
+ }
222
+
223
+ cmd_download() {
224
+ local file_id="$1"; shift
225
+ local output=""
226
+ while [[ $# -gt 0 ]]; do
227
+ case "$1" in
228
+ --output|-o) output="$2"; shift 2 ;;
229
+ *) shift ;;
230
+ esac
231
+ done
232
+
233
+ if [[ -z "$output" ]]; then
234
+ # Auto-name from file metadata
235
+ local info
236
+ info=$(api_get "${API_BASE}/files/${file_id}?fields=name")
237
+ output=$(echo "$info" | jq -r '.name')
238
+ fi
239
+
240
+ # Check if it's a Google Workspace file (needs export)
241
+ local info
242
+ info=$(api_get "${API_BASE}/files/${file_id}?fields=mimeType")
243
+ local mime
244
+ mime=$(echo "$info" | jq -r '.mimeType')
245
+
246
+ case "$mime" in
247
+ application/vnd.google-apps.document)
248
+ api_download "${API_BASE}/files/${file_id}/export?mimeType=application/pdf" "$output"
249
+ ;;
250
+ application/vnd.google-apps.spreadsheet)
251
+ api_download "${API_BASE}/files/${file_id}/export?mimeType=application/pdf" "$output"
252
+ ;;
253
+ application/vnd.google-apps.presentation)
254
+ api_download "${API_BASE}/files/${file_id}/export?mimeType=application/pdf" "$output"
255
+ ;;
256
+ *)
257
+ api_download "${API_BASE}/files/${file_id}?alt=media" "$output"
258
+ ;;
259
+ esac
260
+
261
+ echo "Downloaded to: $output"
262
+ }
263
+
264
+ cmd_upload() {
265
+ local file_path="$1"; shift
266
+ local folder="" name=""
267
+ while [[ $# -gt 0 ]]; do
268
+ case "$1" in
269
+ --folder) folder="$2"; shift 2 ;;
270
+ --name) name="$2"; shift 2 ;;
271
+ *) shift ;;
272
+ esac
273
+ done
274
+
275
+ if [[ ! -f "$file_path" ]]; then
276
+ echo "ERROR: File not found: $file_path" >&2
277
+ exit 1
278
+ fi
279
+
280
+ [[ -z "$name" ]] && name=$(basename "$file_path")
281
+
282
+ # Detect MIME type
283
+ local mime
284
+ mime=$(file --mime-type -b "$file_path")
285
+
286
+ # Build metadata
287
+ local metadata
288
+ if [[ -n "$folder" ]]; then
289
+ metadata=$(jq -n --arg name "$name" --arg folder "$folder" '{name: $name, parents: [$folder]}')
290
+ else
291
+ metadata=$(jq -n --arg name "$name" '{name: $name}')
292
+ fi
293
+
294
+ local token
295
+ token=$(get_access_token)
296
+
297
+ # Multipart upload
298
+ local boundary="gmab_upload_boundary"
299
+ local tmpfile
300
+ tmpfile=$(mktemp)
301
+
302
+ {
303
+ printf -- "--%s\r\nContent-Type: application/json; charset=UTF-8\r\n\r\n%s\r\n" "$boundary" "$metadata"
304
+ printf -- "--%s\r\nContent-Type: %s\r\n\r\n" "$boundary" "$mime"
305
+ cat "$file_path"
306
+ printf "\r\n--%s--\r\n" "$boundary"
307
+ } > "$tmpfile"
308
+
309
+ curl -s -X POST \
310
+ -H "Authorization: Bearer $token" \
311
+ -H "Content-Type: multipart/related; boundary=$boundary" \
312
+ --data-binary "@$tmpfile" \
313
+ "${UPLOAD_BASE}/files?uploadType=multipart&fields=id,name,mimeType,webViewLink" | jq .
314
+
315
+ rm -f "$tmpfile"
316
+ }
317
+
318
+ cmd_create_doc() {
319
+ local name="" content="" folder=""
320
+ while [[ $# -gt 0 ]]; do
321
+ case "$1" in
322
+ --name) name="$2"; shift 2 ;;
323
+ --content) content="$2"; shift 2 ;;
324
+ --folder) folder="$2"; shift 2 ;;
325
+ *) shift ;;
326
+ esac
327
+ done
328
+
329
+ if [[ -z "$name" ]]; then
330
+ echo "ERROR: --name is required" >&2
331
+ exit 1
332
+ fi
333
+
334
+ local metadata
335
+ if [[ -n "$folder" ]]; then
336
+ metadata=$(jq -n --arg name "$name" --arg folder "$folder" \
337
+ '{name: $name, mimeType: "application/vnd.google-apps.document", parents: [$folder]}')
338
+ else
339
+ metadata=$(jq -n --arg name "$name" \
340
+ '{name: $name, mimeType: "application/vnd.google-apps.document"}')
341
+ fi
342
+
343
+ local result
344
+ result=$(api_post "${API_BASE}/files?fields=id,name,mimeType,webViewLink" "$metadata")
345
+ echo "$result" | jq .
346
+
347
+ # If content provided, update the document
348
+ if [[ -n "$content" ]]; then
349
+ local file_id
350
+ file_id=$(echo "$result" | jq -r '.id')
351
+ # For Google Docs, we need to use the Docs API to insert content
352
+ # Simpler approach: create as plain text then convert
353
+ echo "Note: Document created. Content insertion for Google Docs requires the Docs API." >&2
354
+ echo "Consider uploading a .txt file with --mime application/vnd.google-apps.document instead." >&2
355
+ fi
356
+ }
357
+
358
+ cmd_move() {
359
+ local file_id="$1"; shift
360
+ local to_folder=""
361
+ while [[ $# -gt 0 ]]; do
362
+ case "$1" in
363
+ --to) to_folder="$2"; shift 2 ;;
364
+ *) shift ;;
365
+ esac
366
+ done
367
+
368
+ if [[ -z "$to_folder" ]]; then
369
+ echo "ERROR: --to folder ID is required" >&2
370
+ exit 1
371
+ fi
372
+
373
+ # Get current parents
374
+ local info
375
+ info=$(api_get "${API_BASE}/files/${file_id}?fields=parents")
376
+ local current_parents
377
+ current_parents=$(echo "$info" | jq -r '.parents[]? // empty' | paste -sd, -)
378
+
379
+ local token
380
+ token=$(get_access_token)
381
+ curl -s -X PATCH \
382
+ -H "Authorization: Bearer $token" \
383
+ -H "Content-Type: application/json" \
384
+ "${API_BASE}/files/${file_id}?addParents=${to_folder}&removeParents=${current_parents}&fields=id,name,parents" | jq .
385
+ }
386
+
387
+ cmd_rename() {
388
+ local file_id="$1"; shift
389
+ local new_name=""
390
+ while [[ $# -gt 0 ]]; do
391
+ case "$1" in
392
+ --name) new_name="$2"; shift 2 ;;
393
+ *) shift ;;
394
+ esac
395
+ done
396
+
397
+ if [[ -z "$new_name" ]]; then
398
+ echo "ERROR: --name is required" >&2
399
+ exit 1
400
+ fi
401
+
402
+ api_patch "${API_BASE}/files/${file_id}?fields=id,name" \
403
+ "$(jq -n --arg name "$new_name" '{name: $name}')" | jq .
404
+ }
405
+
406
+ cmd_share() {
407
+ local file_id="$1"; shift
408
+ local email="" role="reader" anyone=false
409
+ while [[ $# -gt 0 ]]; do
410
+ case "$1" in
411
+ --email) email="$2"; shift 2 ;;
412
+ --role) role="$2"; shift 2 ;;
413
+ --anyone) anyone=true; shift ;;
414
+ *) shift ;;
415
+ esac
416
+ done
417
+
418
+ local data
419
+ if [[ "$anyone" == "true" ]]; then
420
+ data=$(jq -n --arg role "$role" '{type: "anyone", role: $role}')
421
+ elif [[ -n "$email" ]]; then
422
+ data=$(jq -n --arg email "$email" --arg role "$role" '{type: "user", emailAddress: $email, role: $role}')
423
+ else
424
+ echo "ERROR: --email or --anyone is required" >&2
425
+ exit 1
426
+ fi
427
+
428
+ api_post "${API_BASE}/files/${file_id}/permissions" "$data" | jq .
429
+ }
430
+
431
+ cmd_trash() {
432
+ local file_id="$1"
433
+ api_patch "${API_BASE}/files/${file_id}" '{"trashed": true}' | jq .
434
+ }
435
+
436
+ # --- Dispatch ---
437
+ COMMAND="${1:-}"
438
+ shift || true
439
+
440
+ case "$COMMAND" in
441
+ list) cmd_list "$@" ;;
442
+ search) cmd_search "$@" ;;
443
+ info) cmd_info "$@" ;;
444
+ read) cmd_read "$@" ;;
445
+ download) cmd_download "$@" ;;
446
+ upload) cmd_upload "$@" ;;
447
+ create-doc) cmd_create_doc "$@" ;;
448
+ move) cmd_move "$@" ;;
449
+ rename) cmd_rename "$@" ;;
450
+ share) cmd_share "$@" ;;
451
+ trash) cmd_trash "$@" ;;
452
+ *)
453
+ echo "Usage: drive.sh <command> [options]" >&2
454
+ echo "" >&2
455
+ echo "Commands: list, search, info, read, download, upload," >&2
456
+ echo " create-doc, move, rename, share, trash" >&2
457
+ exit 1
458
+ ;;
459
+ esac