@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.
- package/README.md +10 -1
- package/admin-out/404.html +1 -1
- package/admin-out/_next/static/chunks/1b86ba38-c29611e086b2ce25.js +1 -0
- package/admin-out/_next/static/chunks/{1d2d5650-f5c38b9df5ca7466.js → 1d2d5650-d8d130c85727fdbb.js} +1 -1
- package/admin-out/_next/static/chunks/220.1ed70c874686122f.js +1 -0
- package/admin-out/_next/static/chunks/23-092ac3901411582e.js +1 -0
- package/admin-out/_next/static/chunks/250.9094fea2325b09a3.js +1 -0
- package/admin-out/_next/static/chunks/{304eda7d.662c3a1a7cd50701.js → 304eda7d.f525962766560ba5.js} +1 -1
- package/admin-out/_next/static/chunks/{170.14d53d7f32df020c.js → 336.3171154ecc29c80a.js} +1 -1
- package/admin-out/_next/static/chunks/{188.0cc6998eb0ed3519.js → 362.5970ef15ec3d7b15.js} +1 -1
- package/admin-out/_next/static/chunks/449.a403f7ad18054e3f.js +1 -0
- package/admin-out/_next/static/chunks/{444.c191bedee971e484.js → 510.e6c6faeb60ef3c33.js} +2 -2
- package/admin-out/_next/static/chunks/522.9e25c63e3082cb1c.js +1 -0
- package/admin-out/_next/static/chunks/613.f314fc12e05a566c.js +1 -0
- package/admin-out/_next/static/chunks/690.6a83d18b488a3e2e.js +1 -0
- package/admin-out/_next/static/chunks/698-19872069fed27164.js +1 -0
- package/admin-out/_next/static/chunks/73.a4617a551a8e176c.js +1 -0
- package/admin-out/_next/static/chunks/{841.48a39cec2ef962f3.js → 767.16a0b33b6f5e7965.js} +1 -1
- package/admin-out/_next/static/chunks/839.e381287756453ffe.js +1 -0
- package/admin-out/_next/static/chunks/868.cc7fd84c9f2fd711.js +1 -0
- package/admin-out/_next/static/chunks/892.92b2ed455683b49a.js +1 -0
- package/admin-out/_next/static/chunks/989-056ee2aecccce015.js +1 -0
- package/admin-out/_next/static/chunks/app/_not-found/page-4271518f2746cf73.js +1 -0
- package/admin-out/_next/static/chunks/app/layout-5ec6c5f713a8562b.js +1 -0
- package/admin-out/_next/static/chunks/app/page-5ed9b114aa1a8c10.js +1 -0
- package/admin-out/_next/static/chunks/db534642.657a5bd93dc1e8c7.js +1 -0
- package/admin-out/_next/static/chunks/framework-c48c994d2190a38e.js +1 -0
- package/admin-out/_next/static/chunks/main-app-340a5b58ed229c4d.js +1 -0
- package/admin-out/_next/static/chunks/main-f1f665fbc24e1033.js +1 -0
- package/admin-out/_next/static/chunks/pages/_app-a3b7e86f97343e7a.js +1 -0
- package/admin-out/_next/static/chunks/pages/_error-751fca0c729a7e01.js +1 -0
- package/admin-out/_next/static/chunks/webpack-ca926228f8cba1ff.js +1 -0
- package/admin-out/_next/static/css/59402ac06b2b1a10.css +3 -0
- package/admin-out/_next/static/{Z6KkY5u-XmAPBuUfiAvaG → vbv7FN3A5To2JBO2ozlis}/_buildManifest.js +1 -1
- package/admin-out/index.html +1 -1
- package/admin-out/index.txt +14 -14
- package/bundled-docs/design/cron.md +5 -4
- package/bundled-docs/design/evolution.md +2 -0
- package/bundled-docs/design/express-self.md +11 -0
- package/bundled-docs/design/observability.md +4 -2
- package/bundled-docs/design/session.md +10 -4
- package/bundled-docs/design/storage.md +10 -6
- package/bundled-docs/design/wecom.md +217 -0
- package/bundled-docs/design/ws.md +8 -2
- package/bundled-docs/dev/api.md +19 -4
- package/bundled-docs/guide/channels/README.md +5 -2
- package/bundled-docs/guide/channels/feishu.md +10 -0
- package/bundled-docs/guide/channels/slack.md +10 -0
- package/bundled-docs/guide/channels/wechat.md +2 -0
- package/bundled-docs/guide/channels/wecom.md +136 -0
- package/dist/index.js +1698 -829
- package/package.json +6 -6
- package/templates/prompts/all/RUNTIME.md +1 -1
- package/templates/skills/cron/SKILL.md +7 -6
- package/templates/skills/cron/manage-cron.py +1 -1
- package/templates/skills/send-file/SKILL.md +1 -1
- package/templates/skills/send-file/wecom.md +15 -0
- package/admin-out/_next/static/chunks/132-29179dca2ef093ce.js +0 -1
- package/admin-out/_next/static/chunks/187.9e822f6f0d366d9a.js +0 -1
- package/admin-out/_next/static/chunks/311.3cfaf322ec2a9170.js +0 -1
- package/admin-out/_next/static/chunks/401.c5e64882d4305a08.js +0 -1
- package/admin-out/_next/static/chunks/496.7997fc6558c88c22.js +0 -1
- package/admin-out/_next/static/chunks/530.03c0a6ec971d3528.js +0 -1
- package/admin-out/_next/static/chunks/540.a663b46781b2c309.js +0 -1
- package/admin-out/_next/static/chunks/556.10e21b9f7b45d412.js +0 -1
- package/admin-out/_next/static/chunks/813-9056b8ef0984bee6.js +0 -1
- package/admin-out/_next/static/chunks/891.cfe754015339e975.js +0 -1
- package/admin-out/_next/static/chunks/915.c6ee9ab9bee0ce9b.js +0 -1
- package/admin-out/_next/static/chunks/957-48c734b74e5437a8.js +0 -1
- package/admin-out/_next/static/chunks/968.1676baa9449dbd9d.js +0 -1
- package/admin-out/_next/static/chunks/app/_not-found/page-2ea4ee5eada04f69.js +0 -1
- package/admin-out/_next/static/chunks/app/layout-1853d21b0644f5a1.js +0 -1
- package/admin-out/_next/static/chunks/app/page-2ab109c9a25f867e.js +0 -1
- package/admin-out/_next/static/chunks/db534642.a148101e95a7d317.js +0 -1
- package/admin-out/_next/static/chunks/e3080c2c-fbf81b7cad547976.js +0 -1
- package/admin-out/_next/static/chunks/framework-67e5f0af3ea64f2b.js +0 -1
- package/admin-out/_next/static/chunks/main-6b28974253a3bc7c.js +0 -1
- package/admin-out/_next/static/chunks/main-app-3367dd99b8642c55.js +0 -1
- package/admin-out/_next/static/chunks/pages/_app-51a53534a0a4a898.js +0 -1
- package/admin-out/_next/static/chunks/pages/_error-dfd19566fa6f79ad.js +0 -1
- package/admin-out/_next/static/chunks/webpack-bf41edfde9cdefec.js +0 -1
- package/admin-out/_next/static/css/f96c61f28fab6941.css +0 -3
- /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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
+
```
|