@turmind/halo 1.3.0 → 1.3.2

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 (83) hide show
  1. package/README.md +10 -1
  2. package/admin-out/404.html +1 -1
  3. package/admin-out/_next/static/chunks/1b86ba38-c29611e086b2ce25.js +1 -0
  4. package/admin-out/_next/static/chunks/{1d2d5650-f5c38b9df5ca7466.js → 1d2d5650-d8d130c85727fdbb.js} +1 -1
  5. package/admin-out/_next/static/chunks/220.1ed70c874686122f.js +1 -0
  6. package/admin-out/_next/static/chunks/23-092ac3901411582e.js +1 -0
  7. package/admin-out/_next/static/chunks/250.9094fea2325b09a3.js +1 -0
  8. package/admin-out/_next/static/chunks/{304eda7d.662c3a1a7cd50701.js → 304eda7d.f525962766560ba5.js} +1 -1
  9. package/admin-out/_next/static/chunks/{170.14d53d7f32df020c.js → 336.3171154ecc29c80a.js} +1 -1
  10. package/admin-out/_next/static/chunks/{188.0cc6998eb0ed3519.js → 362.5970ef15ec3d7b15.js} +1 -1
  11. package/admin-out/_next/static/chunks/449.a403f7ad18054e3f.js +1 -0
  12. package/admin-out/_next/static/chunks/{444.c191bedee971e484.js → 510.e6c6faeb60ef3c33.js} +2 -2
  13. package/admin-out/_next/static/chunks/522.9e25c63e3082cb1c.js +1 -0
  14. package/admin-out/_next/static/chunks/613.f314fc12e05a566c.js +1 -0
  15. package/admin-out/_next/static/chunks/690.6a83d18b488a3e2e.js +1 -0
  16. package/admin-out/_next/static/chunks/698-19872069fed27164.js +1 -0
  17. package/admin-out/_next/static/chunks/73.a4617a551a8e176c.js +1 -0
  18. package/admin-out/_next/static/chunks/{841.48a39cec2ef962f3.js → 767.16a0b33b6f5e7965.js} +1 -1
  19. package/admin-out/_next/static/chunks/839.e381287756453ffe.js +1 -0
  20. package/admin-out/_next/static/chunks/868.cc7fd84c9f2fd711.js +1 -0
  21. package/admin-out/_next/static/chunks/892.92b2ed455683b49a.js +1 -0
  22. package/admin-out/_next/static/chunks/989-056ee2aecccce015.js +1 -0
  23. package/admin-out/_next/static/chunks/app/_not-found/page-4271518f2746cf73.js +1 -0
  24. package/admin-out/_next/static/chunks/app/layout-5ec6c5f713a8562b.js +1 -0
  25. package/admin-out/_next/static/chunks/app/page-5ed9b114aa1a8c10.js +1 -0
  26. package/admin-out/_next/static/chunks/db534642.657a5bd93dc1e8c7.js +1 -0
  27. package/admin-out/_next/static/chunks/framework-c48c994d2190a38e.js +1 -0
  28. package/admin-out/_next/static/chunks/main-app-340a5b58ed229c4d.js +1 -0
  29. package/admin-out/_next/static/chunks/main-f1f665fbc24e1033.js +1 -0
  30. package/admin-out/_next/static/chunks/pages/_app-a3b7e86f97343e7a.js +1 -0
  31. package/admin-out/_next/static/chunks/pages/_error-751fca0c729a7e01.js +1 -0
  32. package/admin-out/_next/static/chunks/webpack-ca926228f8cba1ff.js +1 -0
  33. package/admin-out/_next/static/css/59402ac06b2b1a10.css +3 -0
  34. package/admin-out/_next/static/{Z6KkY5u-XmAPBuUfiAvaG → vbv7FN3A5To2JBO2ozlis}/_buildManifest.js +1 -1
  35. package/admin-out/index.html +1 -1
  36. package/admin-out/index.txt +14 -14
  37. package/bundled-docs/design/cron.md +5 -4
  38. package/bundled-docs/design/evolution.md +2 -0
  39. package/bundled-docs/design/express-self.md +11 -0
  40. package/bundled-docs/design/observability.md +4 -2
  41. package/bundled-docs/design/session.md +10 -4
  42. package/bundled-docs/design/storage.md +10 -6
  43. package/bundled-docs/design/wecom.md +217 -0
  44. package/bundled-docs/design/ws.md +8 -2
  45. package/bundled-docs/dev/api.md +19 -4
  46. package/bundled-docs/guide/channels/README.md +5 -2
  47. package/bundled-docs/guide/channels/feishu.md +10 -0
  48. package/bundled-docs/guide/channels/slack.md +10 -0
  49. package/bundled-docs/guide/channels/wechat.md +2 -0
  50. package/bundled-docs/guide/channels/wecom.md +136 -0
  51. package/dist/index.js +1698 -829
  52. package/package.json +6 -6
  53. package/templates/prompts/all/RUNTIME.md +1 -1
  54. package/templates/skills/cron/SKILL.md +7 -6
  55. package/templates/skills/cron/manage-cron.py +1 -1
  56. package/templates/skills/send-file/SKILL.md +1 -1
  57. package/templates/skills/send-file/wecom.md +15 -0
  58. package/admin-out/_next/static/chunks/132-29179dca2ef093ce.js +0 -1
  59. package/admin-out/_next/static/chunks/187.9e822f6f0d366d9a.js +0 -1
  60. package/admin-out/_next/static/chunks/311.3cfaf322ec2a9170.js +0 -1
  61. package/admin-out/_next/static/chunks/401.c5e64882d4305a08.js +0 -1
  62. package/admin-out/_next/static/chunks/496.7997fc6558c88c22.js +0 -1
  63. package/admin-out/_next/static/chunks/530.03c0a6ec971d3528.js +0 -1
  64. package/admin-out/_next/static/chunks/540.a663b46781b2c309.js +0 -1
  65. package/admin-out/_next/static/chunks/556.10e21b9f7b45d412.js +0 -1
  66. package/admin-out/_next/static/chunks/813-9056b8ef0984bee6.js +0 -1
  67. package/admin-out/_next/static/chunks/891.cfe754015339e975.js +0 -1
  68. package/admin-out/_next/static/chunks/915.c6ee9ab9bee0ce9b.js +0 -1
  69. package/admin-out/_next/static/chunks/957-48c734b74e5437a8.js +0 -1
  70. package/admin-out/_next/static/chunks/968.1676baa9449dbd9d.js +0 -1
  71. package/admin-out/_next/static/chunks/app/_not-found/page-2ea4ee5eada04f69.js +0 -1
  72. package/admin-out/_next/static/chunks/app/layout-1853d21b0644f5a1.js +0 -1
  73. package/admin-out/_next/static/chunks/app/page-2ab109c9a25f867e.js +0 -1
  74. package/admin-out/_next/static/chunks/db534642.a148101e95a7d317.js +0 -1
  75. package/admin-out/_next/static/chunks/e3080c2c-fbf81b7cad547976.js +0 -1
  76. package/admin-out/_next/static/chunks/framework-67e5f0af3ea64f2b.js +0 -1
  77. package/admin-out/_next/static/chunks/main-6b28974253a3bc7c.js +0 -1
  78. package/admin-out/_next/static/chunks/main-app-3367dd99b8642c55.js +0 -1
  79. package/admin-out/_next/static/chunks/pages/_app-51a53534a0a4a898.js +0 -1
  80. package/admin-out/_next/static/chunks/pages/_error-dfd19566fa6f79ad.js +0 -1
  81. package/admin-out/_next/static/chunks/webpack-bf41edfde9cdefec.js +0 -1
  82. package/admin-out/_next/static/css/f96c61f28fab6941.css +0 -3
  83. /package/admin-out/_next/static/{Z6KkY5u-XmAPBuUfiAvaG → vbv7FN3A5To2JBO2ozlis}/_ssgManifest.js +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@turmind/halo",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "description": "Halo — multi-agent collaborative workspace. CLI + TUI + HTTP/WS server in one package.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -20,7 +20,7 @@
20
20
  "@aws-crypto/sha256-js": "^5.2.0",
21
21
  "@aws-sdk/client-bedrock-runtime": "^3.1030.0",
22
22
  "@aws-sdk/credential-provider-node": "^3.972.30",
23
- "@hono/node-server": "^1.13.0",
23
+ "@hono/node-server": "^1.19.17",
24
24
  "@larksuiteoapi/node-sdk": "^1.65.0",
25
25
  "@opentelemetry/api": "^1.9.1",
26
26
  "@opentelemetry/api-logs": "^0.222.0",
@@ -35,12 +35,12 @@
35
35
  "@opentelemetry/semantic-conventions": "^1.43.0",
36
36
  "@parcel/watcher": "^2.5.6",
37
37
  "@smithy/signature-v4": "^5.3.13",
38
+ "@wecom/aibot-node-sdk": "^1.0.7",
38
39
  "better-sqlite3": "^11.7.0",
39
- "chokidar": "^5.0.0",
40
40
  "croner": "^10.0.1",
41
41
  "drizzle-orm": "^0.45.2",
42
42
  "grammy": "^1.42.0",
43
- "hono": "^4.6.0",
43
+ "hono": "^4.13.8",
44
44
  "hyparquet": "^1.27.1",
45
45
  "hyparquet-compressors": "^1.1.1",
46
46
  "ink": "^7.0.3",
@@ -49,13 +49,13 @@
49
49
  "jszip": "^3.10.1",
50
50
  "marked": "^15.0.0",
51
51
  "marked-terminal": "^7.3.0",
52
- "nanoid": "^5.0.9",
52
+ "nanoid": "^5.1.16",
53
53
  "node-pty": "1.2.0-beta.12",
54
54
  "qrcode": "^1.5.4",
55
55
  "react": "^19.2.5",
56
56
  "react-dom": "^19.2.5",
57
57
  "simple-git": "^3.27.0",
58
- "ws": "^8.18.0",
58
+ "ws": "^8.21.3",
59
59
  "yaml": "^2.8.3"
60
60
  },
61
61
  "engines": {
@@ -4,7 +4,7 @@
4
4
  Each user message is prefixed `[<ISO-8601 UTC>]` — the server-stamped arrival time. Use it for "today" / "how long since the last message"; it is UTC, so convert to the user's timezone (from USER.md or context) before stating a date or time. Never echo the stamp in replies.
5
5
 
6
6
  ### Channel tag
7
- A `[channel: <type> | …]` tag right after the timestamp means the message arrived via an external channel (telegram / wechat / slack / feishu / web), not the admin UI. Don't echo the tag. IM replies are hard-split (telegram 4000 chars, wechat 3500, feishu 4500) and most IMs flatten markdown — prefer short paragraphs and `-` lists over tables and nested formatting; put long output in a file under `.halo/tmp/` and point to it. Use the `send-file` skill, if you have it, for attachments.
7
+ A `[channel: <type> | …]` tag right after the timestamp means the message arrived via an external channel (telegram / wechat / slack / feishu / wecom / web), not the admin UI. Don't echo the tag. IM replies are hard-split (telegram 4000 chars, wechat 3500, feishu 4500, wecom 5000) and most IMs flatten markdown — prefer short paragraphs and `-` lists over tables and nested formatting; put long output in a file under `.halo/tmp/` and point to it. Use the `send-file` skill, if you have it, for attachments.
8
8
 
9
9
  ### Unattended runs
10
10
  If the conversation is a cron run, a goal-mode work order, or otherwise says nobody will answer, don't ask questions — deliver the result directly; if genuinely blocked, state what's blocked in one line and stop.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: cron
3
- description: Manage scheduled cron jobs that run a halo agent on a schedule and optionally push the result to a chat channel (telegram / wechat / slack / feishu). Activate when the user asks to add / list / edit / pause / delete a recurring agent task.
3
+ description: Manage scheduled cron jobs that run a halo agent on a schedule and optionally push the result to a chat channel (telegram / wechat / slack / feishu / wecom). Activate when the user asks to add / list / edit / pause / delete a recurring agent task.
4
4
  command: /cron
5
5
  requiresAccess: full
6
6
  verbs:
@@ -19,7 +19,7 @@ natural-language activation, infer it from the request. All verbs run through
19
19
  this body — map them onto the helper script's subcommands below.
20
20
 
21
21
  Halo runs a global cron daemon that executes user-defined agent prompts on a schedule and
22
- optionally pushes the resulting text to a chat (telegram / wechat / slack / feishu). Use the
22
+ optionally pushes the resulting text to a chat (telegram / wechat / slack / feishu / wecom). Use the
23
23
  `manage-cron.py` helper script (sibling of this file) for every operation — it handles id
24
24
  generation, JSON encoding for `targets`, timestamps, and so on, so you don't end up
25
25
  handcrafting SQL.
@@ -97,11 +97,11 @@ shell_exec: python3 <skill-dir>/manage-cron.py channels
97
97
 
98
98
  Output is a JSON array `[{channelType, accountId, label, ready}, ...]`.
99
99
 
100
- #### Pinning the chatId — REQUIRED for telegram / slack / feishu
100
+ #### Pinning the chatId — REQUIRED for telegram / slack / feishu / wecom
101
101
 
102
102
  The cron dispatcher used to fall back to "whoever last messaged the bot"
103
103
  when no chatId was given, but in practice that always pushed to a stranger.
104
- **As of the current build, telegram / slack / feishu cron pushes require
104
+ **As of the current build, telegram / slack / feishu / wecom cron pushes require
105
105
  an explicit chatId.** WeChat is the exception — it has a QR-bound owner
106
106
  that's a stable single recipient.
107
107
 
@@ -117,6 +117,7 @@ Format per channel:
117
117
  | telegram | `telegram:<accountId>:<chatId>` | numeric (Telegram private-chat id) |
118
118
  | slack | `slack:<accountId>:<chatId>` | `D…` (DM), `C…` (channel top), `C…:<thread_ts>` (thread) |
119
119
  | feishu | `feishu:<accountId>:<chatId>` | `oc_…` chat_id |
120
+ | wecom | `wecom:<accountId>:<chatId>` | `<userid>` (bot DM) or `<chatid>` (group) |
120
121
 
121
122
  Comma-separated for multiple targets:
122
123
 
@@ -125,7 +126,7 @@ Comma-separated for multiple targets:
125
126
  ```
126
127
 
127
128
  **Pinning to the current chat (the common case).** When the user inside
128
- telegram/slack/feishu/wechat asks "remind me at X" / "send me a daily
129
+ telegram/slack/feishu/wecom/wechat asks "remind me at X" / "send me a daily
129
130
  digest", construct the target with `{{channel.chat_id}}`:
130
131
 
131
132
  ```
@@ -215,7 +216,7 @@ picks it up within ~10s. Example:
215
216
 
216
217
  ## Patterns that go sideways
217
218
 
218
- - **telegram / slack / feishu target without a chatId** — every fire errors with
219
+ - **telegram / slack / feishu / wecom target without a chatId** — every fire errors with
219
220
  `… cron target requires an explicit chatId …`. From inside a chat, use the
220
221
  `{{channel.chat_id}}` template; from the admin UI, ask the user for the chatId
221
222
  (or accept that the cron will run silently with no push target).
@@ -164,7 +164,7 @@ def cmd_list(args):
164
164
  # in-channel "delete my cron" / "list my crons" flow, where the
165
165
  # agent only knows the current chatId and needs to find which
166
166
  # cron_jobs reference it. chatId formats don't collide across
167
- # channels (telegram numeric, slack D…/C…, feishu oc_…, wechat o…)
167
+ # channels (telegram numeric, slack D…/C…, feishu oc_…, wecom userid/chatid, wechat o…)
168
168
  # so a single chatId match is unambiguous.
169
169
  if args.chat_id:
170
170
  jobs = [
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: send-file
3
3
  requiresAccess: workspace
4
- description: Send images, videos, or files as attachments to the current user. Works on all channels (Web, WeChat, Telegram, Slack, Feishu). Use when the user asks to send a file, or when an attachment (screenshot, PDF, chart, generated artifact) is more useful than inline text.
4
+ description: Send images, videos, or files as attachments to the current user. Works on all channels (Web, WeChat, Telegram, Slack, Feishu, WeCom). Use when the user asks to send a file, or when an attachment (screenshot, PDF, chart, generated artifact) is more useful than inline text.
5
5
  ---
6
6
  # Send File
7
7
 
@@ -0,0 +1,15 @@
1
+ # WeCom Channel — File Delivery
2
+
3
+ The bot uploads the file as a temporary media asset over the same long-connect socket, then replies with the matching message type. Type is inferred from extension, and WeCom is stricter than Feishu about which formats render inline:
4
+
5
+ - `.png/.jpg/.jpeg/.gif` → image (renders inline)
6
+ - `.mp4` → video (renders as a player)
7
+ - anything else → generic file (download card) — this includes `.webp/.bmp`, `.mov/.webm`, PDFs, audio, archives
8
+
9
+ There is no voice-bubble path: WeCom voice requires `amr`, which the agent never produces, so audio always goes as a file. Hard limit is 20 MB per file — larger files fail and the bot posts a short upload-failed note instead.
10
+
11
+ If an image must render inline, convert to png/jpg first:
12
+
13
+ ```bash
14
+ ffmpeg -i input.webp output.png -y
15
+ ```