@mu-cabin/muc-cli 0.5.3 → 0.5.4
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 -12
- package/REFERENCE.md +31 -39
- package/dist/muc.mjs +39 -35
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -141,7 +141,7 @@ npx skills add <everything-cli 仓库地址>/packages/muc/skills -y -g
|
|
|
141
141
|
|
|
142
142
|
### Skill 的行为规则
|
|
143
143
|
|
|
144
|
-
-
|
|
144
|
+
- **首次直连 TCP 命令前**:Skill 只提醒“同账号 iPad 可能被踢”,不再等待槽位确认,随后直接执行。
|
|
145
145
|
- **不确定发给谁**:先用 `muc search` 缩小候选名单,通过 `AskUserQuestion` 让你选,不会猜。
|
|
146
146
|
- **非自身目标**:必须经过你显式确认,不会偷偷给真实联系人发消息。
|
|
147
147
|
- **token 过期**:自动用 `--token-pwd` 静默续登,续登失败才要求你手动 `muc login`。
|
|
@@ -232,25 +232,23 @@ muc withdraw --mid <mid> --to-self # 撤回自己发出的消
|
|
|
232
232
|
|
|
233
233
|
---
|
|
234
234
|
|
|
235
|
-
## 和桌面端 /
|
|
235
|
+
## 和桌面端 / 手机端 / iPad 共存
|
|
236
236
|
|
|
237
237
|
REST 命令(`search`、`history`、`whois`、`groups` 等)**永远可以共存**,与桌面端、手机端同时在线互不影响。
|
|
238
238
|
|
|
239
|
-
聊天通道命令(`send*`、`withdraw`、`sync`、`search-team`、`team-members
|
|
239
|
+
聊天通道命令(`send*`、`withdraw`、`sync`、`search-team`、`team-members`)进入 MUC 实时通道。每个账号有 **PC、Mobile、iPad 三个独立槽位**;同槽后登录会把前一个挤下线。CLI 继续沿用 `--os` 选槽位,其中 `iPad` 是逻辑值:线上报文实际发送 `os:"iOS"` 和 `browser:"iPad"`。
|
|
240
240
|
|
|
241
241
|
| 算作哪端 | 对应的 `--os` 取值 |
|
|
242
242
|
|---|---|
|
|
243
243
|
| PC 端 | `Windows` / `OS X` / `Mac`(Mac 桌面端登录时上报的是 `OS X`) |
|
|
244
|
-
| 移动端 | `iOS
|
|
244
|
+
| 移动端 | `iOS` / `Android` |
|
|
245
|
+
| iPad 端 | `iPad`(CLI 默认;线上报文为 `os:iOS + browser:iPad`) |
|
|
245
246
|
|
|
246
|
-
> ⚠️
|
|
247
|
-
> 只要跑了 `send` / `withdraw` 等聊天通道命令,**正在登录 MUC 的 iPhone 会被立刻挤下线**
|
|
248
|
-
> (`accessToken` 不失效,但要重新打开 App 才能继续收实时消息)。
|
|
247
|
+
> ⚠️ CLI 默认使用 **iPad 槽位**。PC 桌面端和手机端可以继续在线;如果同账号正登录 iPad,iPad 可能被挤下线,重新打开 App 即可恢复,`accessToken` 不失效。
|
|
249
248
|
>
|
|
250
249
|
> - 测试或跑通流程时,先用 `muc send --to-self ...` 发给自己。
|
|
251
|
-
> -
|
|
252
|
-
> -
|
|
253
|
-
> - **不要**显式传 `--os Windows / OS X / Mac`——那会把 Mac 桌面端 MUC 也顶下去。
|
|
250
|
+
> - `--os iOS/Android` 会改占 Mobile 槽位,可能踢手机;`--os Windows/OS X/Mac` 会改占 PC 槽位,可能踢桌面端。
|
|
251
|
+
> - Skill 对默认 iPad 风险只做非阻塞提醒,不再要求预先确认槽位;发送给真实联系人、撤回等业务确认仍保留。
|
|
254
252
|
|
|
255
253
|
`muc tcp-ping` 只做 TCP 连接和 NEGOTIATE,**不发登录帧**,不占任何在线名额,纯连通性测试,可以随时跑。
|
|
256
254
|
|
|
@@ -312,7 +310,7 @@ python3 analyze_api.py flows.ndjson --host muc.example.com
|
|
|
312
310
|
### 改动后测试流程
|
|
313
311
|
|
|
314
312
|
1. `pnpm run typecheck`(在 `packages/muc` 下)— 先过类型检查。
|
|
315
|
-
2. 按内部 `TEST_CASES.md`
|
|
313
|
+
2. 按内部 `TEST_CASES.md` 从头到尾跑一遍;实时命令默认走 iPad 槽位,实机验证前确认没有需要保持在线的同账号 iPad。
|
|
316
314
|
3. 任何一项失败:把 `--json` 原始信封贴给用户,停下来,不要"修一修再跑"。
|
|
317
315
|
|
|
318
316
|
### 协议层参考(内部文档)
|
|
@@ -324,6 +322,6 @@ python3 analyze_api.py flows.ndjson --host muc.example.com
|
|
|
324
322
|
### 红线
|
|
325
323
|
|
|
326
324
|
- **绝不入库** `accessToken`、`tokenPwd`、明文密码、`clientSecret`、`pfxPass`、`bsSecretKey`、`encrypt_key`,以及租户密钥(`APP_KEY` / `sign secrets`)。
|
|
327
|
-
- **CLI
|
|
325
|
+
- **CLI 默认占用同账号的 iPad 槽位**(`--os iPad` → `os:iOS + browser:iPad`),可能顶掉真实 iPad;显式传 Mobile/PC 类 `--os` 才会影响手机/桌面端。
|
|
328
326
|
- **CLI 发的消息所有参与方都可见。** 非自身目标必须带 `--yes-not-self`,先用 `--to-self` 测。
|
|
329
327
|
- **不要擅自改 Surge 配置文件**(`~/Library/Application Support/Surge/Profiles/*.conf`)。要加 MITM hostname 让用户在 Surge UI 里加。
|
package/REFERENCE.md
CHANGED
|
@@ -252,14 +252,10 @@ muc history --team 9009876543210000 --before 2026-04-20 --json | jq .
|
|
|
252
252
|
| `muc listen [--from-uid UID] [--team TEAM] [--peer UID] [--contains TEXT] [--regex …] [--at-me] [--max N]` | Long-lived TCP tap that emits one **NDJSON line per matching inbound message** (in `--json` mode each line is the standard envelope; in human mode it's a one-line summary). Supports repeatable filters (OR semantics within each kind, AND across kinds), `--at-me` to restrict to group messages where another user @-mentions you (implies excluding self), `--include-self` to include your own sends, `--include-reactions` to also surface type=3 sub=300/301 frames, `--max N` to exit after N matches. Stop with `^C`. |
|
|
253
253
|
|
|
254
254
|
`--os` resolves as **per-call `--os` → `defaultChatOs` in `~/.muc/config.json`
|
|
255
|
-
→ built-in `
|
|
256
|
-
|
|
257
|
-
`
|
|
258
|
-
|
|
259
|
-
chat-channel commands park on the PC slot instead of kicking your phone.
|
|
260
|
-
**`--os` / `defaultChatOs` does not provide coexistence — read the section
|
|
261
|
-
below before using any chat-channel command if you have a real device
|
|
262
|
-
logged in.**
|
|
255
|
+
→ built-in `iPad`**. Valid values: `Windows`, `OS X`, `Mac`, `iOS`, `Android`,
|
|
256
|
+
and `iPad`. The existing option name is retained for compatibility: logical
|
|
257
|
+
`iPad` serializes as `os:"iOS", browser:"iPad"` and selects the third slot.
|
|
258
|
+
Set an override with `muc init --default-os <os>` or `MUC_DEFAULT_OS`.
|
|
263
259
|
|
|
264
260
|
Sending to anyone other than yourself requires the explicit `--yes-not-self`
|
|
265
261
|
flag — a guard against accidentally messaging real humans during testing.
|
|
@@ -325,7 +321,7 @@ through `muc daemon-start`, not through a dedicated assistant account.
|
|
|
325
321
|
|
|
326
322
|
| Command | What it does |
|
|
327
323
|
|---|---|
|
|
328
|
-
| `muc assistantd-start [--os OS] [--on-kicked POLICY] [--debug]` | Start the assistant daemon in the foreground. Holds the
|
|
324
|
+
| `muc assistantd-start [--os OS] [--on-kicked POLICY] [--debug]` | Start the assistant daemon in the foreground. Holds the chosen slot (priority: `--os` → active profile `defaultChatOs` → built-in `iPad`). Personal and dedicated-assistant behavior share this default. `POLICY` defaults to `3m`. Without a dedicated profile it fails unless `muc init --allow-assistant-shared-profile` explicitly opted into shared-profile mode. |
|
|
329
325
|
| `muc assistantd-status` | Probe the daemon: running? slot? attached assistants? last paused-state message? |
|
|
330
326
|
| `muc assistantd-stop` | Send `SIGTERM` to the daemon (graceful shutdown). |
|
|
331
327
|
| `muc assistantd-resume` | Manual resume for `--on-kicked pause`, auth expiry, or exhausted network retries is reserved for v1.1. Today: `assistantd-stop` then `assistantd-start` again. |
|
|
@@ -352,10 +348,9 @@ Shared-profile assistant mode is an explicit advanced opt-in:
|
|
|
352
348
|
as the personal `~/.muc` account and is mutually exclusive with
|
|
353
349
|
`muc daemon-start` for that uid.
|
|
354
350
|
|
|
355
|
-
- **Chat slot.** A daemon and a real device on the **same** slot kick
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
offline.
|
|
351
|
+
- **Chat slot.** A daemon and a real device on the **same** slot kick each
|
|
352
|
+
other (`auth/kicked`, "same account login"). The built-in default is the
|
|
353
|
+
separate iPad slot, so desktop and phone coexist; a real iPad may conflict.
|
|
359
354
|
- **REST `tokenPwd`.** A fresh `muc login` rotates the account's refresh
|
|
360
355
|
token; other devices on that account get logged out when their token
|
|
361
356
|
next refreshes.
|
|
@@ -367,7 +362,7 @@ separate from your personal `~/.muc/`:
|
|
|
367
362
|
```bash
|
|
368
363
|
muc assistant-init # tenant config → ~/.muc/assistant/config.json
|
|
369
364
|
# (tenant secrets/hosts default to whatever your
|
|
370
|
-
# personal `muc init` saved; defaultChatOs →
|
|
365
|
+
# personal `muc init` saved; defaultChatOs → iPad)
|
|
371
366
|
muc assistant-login --account <BOT_UID> # → ~/.muc/assistant/credentials.json
|
|
372
367
|
# (--platform defaults to mac)
|
|
373
368
|
muc assistantd-start # picks up the dedicated profile
|
|
@@ -376,10 +371,9 @@ muc whoami --assistant # confirm which account it's on
|
|
|
376
371
|
|
|
377
372
|
Once provisioned, `muc assistantd-start` reads the dedicated profile
|
|
378
373
|
automatically (every REST call the daemon makes follows it too). The
|
|
379
|
-
daemon
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
run it). Remove the profile (`rm -rf ~/.muc/assistant/config.json
|
|
374
|
+
daemon defaults to the **iPad slot**, so the account's desktop and phone
|
|
375
|
+
slots remain independent. A real iPad logged into that same assistant
|
|
376
|
+
account may be kicked. Remove the profile (`rm -rf ~/.muc/assistant/config.json
|
|
383
377
|
~/.muc/assistant/credentials.json`) only if you intend to use the explicit
|
|
384
378
|
shared-profile mode.
|
|
385
379
|
|
|
@@ -463,7 +457,7 @@ Hand-edit, or seeded by `assistant-new`:
|
|
|
463
457
|
|
|
464
458
|
```bash
|
|
465
459
|
# v1: foreground only; wrap in tmux/screen for persistence.
|
|
466
|
-
muc assistantd-start
|
|
460
|
+
muc assistantd-start # default iPad slot
|
|
467
461
|
muc assistant-new desk-bot --description "out-of-hours triage in IT 值班群"
|
|
468
462
|
$EDITOR ~/.muc/assistants/desk-bot/config.json # add scope.tids etc.
|
|
469
463
|
muc assistant-edit desk-bot # tune the persona
|
|
@@ -526,23 +520,22 @@ run anytime.
|
|
|
526
520
|
|
|
527
521
|
**Chat-channel commands** (`sync`, `search-team`, `team-members`, `send`, `send-file`,
|
|
528
522
|
`send-image`, `send-voice`, `withdraw`, `clear-session`, `pin`, `unpin`, `pinned`) open a TCP-8101
|
|
529
|
-
session and share a per-user **
|
|
523
|
+
session and share a per-user **three-slot** model with real devices:
|
|
530
524
|
|
|
531
525
|
| Slot | `--os` values |
|
|
532
526
|
|---|---|
|
|
533
527
|
| PC | `Windows`, `"OS X"`, `Mac` |
|
|
534
|
-
| Mobile | `iOS
|
|
528
|
+
| Mobile | `iOS`, `Android` |
|
|
529
|
+
| iPad | `iPad` (default; wire `os:"iOS", browser:"iPad"`) |
|
|
535
530
|
|
|
536
531
|
A second login in the same slot kicks the previous client off the realtime
|
|
537
532
|
channel — the IM panel goes offline, but tokens stay valid (reopen to
|
|
538
|
-
recover). The Mac desktop signs in as `"OS X"` (PC
|
|
539
|
-
|
|
533
|
+
recover). The Mac desktop signs in as `"OS X"` (PC); the iPhone signs in as
|
|
534
|
+
`iOS` (Mobile); the iPad app adds `browser:"iPad"` (iPad).
|
|
540
535
|
|
|
541
|
-
The CLI defaults to `--os
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
`muc init --default-os windows` to flip the per-machine default to the PC
|
|
545
|
-
slot (which kicks the desktop instead of the phone).
|
|
536
|
+
The CLI defaults to `--os iPad`, so desktop and phone can remain online.
|
|
537
|
+
Only a real iPad on the same account may be kicked by the default. Explicit
|
|
538
|
+
PC or Mobile values intentionally target those older slots.
|
|
546
539
|
|
|
547
540
|
`tcp-ping` only does TCP connect + NEGOTIATE (no `auth/login`), so it can't
|
|
548
541
|
kick anything. Run it first to confirm the wire protocol is happy on your
|
|
@@ -636,13 +629,15 @@ files by hand.
|
|
|
636
629
|
## Changelog
|
|
637
630
|
|
|
638
631
|
#### Unreleased
|
|
632
|
+
- Add the third iPad chat slot. Logical `--os iPad` serializes as `os:"iOS", browser:"iPad"` and is now the built-in default for personal commands, the personal daemon, and assistantd. Existing explicit `defaultChatOs` values remain authoritative.
|
|
633
|
+
- Slot safety guidance is now non-blocking: skills remind that a real iPad may be kicked and continue without asking for slot confirmation. Recipient, content, and destructive-action confirmations are unchanged.
|
|
639
634
|
- Add the personal daemon command family: `muc daemon-start`, `daemon-status`, `daemon-stop`, and `daemon-events`. Ordinary chat-channel commands now route only through the personal daemon and report `daemon_kind:"personal"` when routed.
|
|
640
635
|
- Dedicated `assistantd` is no longer borrowed by ordinary commands. Without a dedicated assistant profile, `assistantd-start` now requires explicit `muc init --allow-assistant-shared-profile`; same-uid shared-profile assistantd conflicts with the personal daemon / direct ordinary TCP via `DAEMON_CONFLICT`.
|
|
641
636
|
- Add raw event cursors (`<epoch_ms>-<sequence>`), 90-day personal daemon event retention, and `CURSOR_NOT_FOUND` handling for missing retained cursors.
|
|
642
637
|
|
|
643
638
|
#### `0.5.0`
|
|
644
639
|
`2026.05.11`
|
|
645
|
-
- Add `muc assistant-init` / `muc assistant-login` and `muc whoami --assistant`: the assistant daemon can
|
|
640
|
+
- Add `muc assistant-init` / `muc assistant-login` and `muc whoami --assistant`: the assistant daemon can authenticate as a **dedicated account** under `~/.muc/assistant/`, fully separate from the personal profile. At this release it defaulted to the PC slot; the current Unreleased behavior supersedes that with the iPad default. `assistant-login` still defaults REST `--platform` to `mac`.
|
|
646
641
|
- Internals: `config.json` / `credentials.json` / `device-id` / `remember.salt` / `runtime/refresh-log.ndjson` paths now resolve through a process-wide *profile root* (default `~/.muc`) instead of being hardcoded. `configPath` / `credentialsPath` / `configDir` are now functions.
|
|
647
642
|
|
|
648
643
|
#### `0.4.1`
|
|
@@ -661,7 +656,7 @@ files by hand.
|
|
|
661
656
|
|
|
662
657
|
#### `0.3.1`
|
|
663
658
|
`2026.04.29`
|
|
664
|
-
- Add `defaultChatOs` to `~/.muc/config.json
|
|
659
|
+
- Add `defaultChatOs` to `~/.muc/config.json`. At this release the accepted values stopped at Android and the built-in fallback was `iOS`; current Unreleased behavior also accepts `ipad` and defaults to `iPad`.
|
|
665
660
|
|
|
666
661
|
#### `0.3.0`
|
|
667
662
|
`2026.04.29`
|
|
@@ -724,11 +719,9 @@ files by hand.
|
|
|
724
719
|
- `EPROTO` / TLS errors — corporate proxy or VPN intercepting traffic.
|
|
725
720
|
`muc-cli` does not pin certificates, so adding the proxy CA to your Node
|
|
726
721
|
trust store should suffice (`NODE_EXTRA_CA_CERTS=/path/to/ca.pem`).
|
|
727
|
-
- A TCP
|
|
728
|
-
collided with
|
|
729
|
-
|
|
730
|
-
desktop. If both desktop and phone are online, drop to REST-only
|
|
731
|
-
commands.
|
|
722
|
+
- A TCP command kicks a client off the IM panel — the CLI's `--os` value
|
|
723
|
+
collided with that client's slot. The default `--os iPad` only risks a
|
|
724
|
+
real iPad; explicit PC or Mobile values risk the matching client.
|
|
732
725
|
|
|
733
726
|
### 5.9 Gemini CLI headless timeout
|
|
734
727
|
|
|
@@ -779,9 +772,8 @@ works interactively.
|
|
|
779
772
|
leak through shell history and `/proc/<pid>/environ` to other processes
|
|
780
773
|
on the same machine. Use the interactive prompt or one-shot flags pulled
|
|
781
774
|
from a secret manager rather than persistent `MUC_*` exports.
|
|
782
|
-
- TCP login over 8101 registers a device session in one of
|
|
783
|
-
user (PC or
|
|
784
|
-
Default `--os
|
|
785
|
-
ever at risk.
|
|
775
|
+
- TCP login over 8101 registers a device session in one of three slots per
|
|
776
|
+
user (PC, Mobile, or iPad). A second login in the same slot kicks the first.
|
|
777
|
+
Default `--os iPad` only risks a real iPad on the same account.
|
|
786
778
|
- `tcp-ping` is the only chat-channel command that cannot kick anything —
|
|
787
779
|
use it as a network smoke-test before trying TCP sends.
|
package/dist/muc.mjs
CHANGED
|
@@ -21479,7 +21479,7 @@ function file() {
|
|
|
21479
21479
|
return join2(dir(), "config.json");
|
|
21480
21480
|
}
|
|
21481
21481
|
var CONFIG_SCHEMA_VERSION = 1;
|
|
21482
|
-
var CHAT_OS_VALUES = ["Windows", "OS X", "Mac", "iOS", "Android"];
|
|
21482
|
+
var CHAT_OS_VALUES = ["Windows", "OS X", "Mac", "iOS", "Android", "iPad"];
|
|
21483
21483
|
var MucConfigSchema = external_exports.object({
|
|
21484
21484
|
appKey: external_exports.string().regex(/^[0-9a-f]{8}$/, "appKey must be 8 lowercase hex chars"),
|
|
21485
21485
|
appId: external_exports.string().regex(/^[0-9a-f]{24}$/, "appId must be 24 lowercase hex chars"),
|
|
@@ -21499,9 +21499,9 @@ var MucConfigSchema = external_exports.object({
|
|
|
21499
21499
|
// any other → that literal string (e.g. "\n— bot")
|
|
21500
21500
|
// Per-call `--tail` / `--no-tail` flags on `muc send` override this.
|
|
21501
21501
|
messageTail: external_exports.string().max(200).optional(),
|
|
21502
|
-
// Default chat
|
|
21503
|
-
// PC
|
|
21504
|
-
//
|
|
21502
|
+
// Default logical chat slot for TCP commands when --os is not passed.
|
|
21503
|
+
// PC: Windows/OS X/Mac; Mobile: iOS/Android; iPad: iPad. The iPad value is
|
|
21504
|
+
// serialized on the wire as os=iOS + browser=iPad. Built-in fallback: iPad.
|
|
21505
21505
|
defaultChatOs: external_exports.enum(CHAT_OS_VALUES).optional(),
|
|
21506
21506
|
// Opt-in: when true, the assistant daemon writes a live status headline
|
|
21507
21507
|
// to your profile signature (`ext.sign`, visible to anyone who hovers
|
|
@@ -21652,7 +21652,7 @@ var PLATFORM_WIN = 4;
|
|
|
21652
21652
|
var PLATFORM_MAC = 5;
|
|
21653
21653
|
var SECURE_SYS_KEY = "mx_app_key";
|
|
21654
21654
|
var PWD_DES_IV = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);
|
|
21655
|
-
var DEFAULT_CHAT_OS = "
|
|
21655
|
+
var DEFAULT_CHAT_OS = "iPad";
|
|
21656
21656
|
var DEFAULT_REST_PLATFORM = PLATFORM_IOS;
|
|
21657
21657
|
function defaultMessageTail(userName) {
|
|
21658
21658
|
const name = userName.trim() || "unknown";
|
|
@@ -21855,7 +21855,8 @@ var CHAT_OS_MAP = {
|
|
|
21855
21855
|
mac: "Mac",
|
|
21856
21856
|
macos: "Mac",
|
|
21857
21857
|
ios: "iOS",
|
|
21858
|
-
android: "Android"
|
|
21858
|
+
android: "Android",
|
|
21859
|
+
ipad: "iPad"
|
|
21859
21860
|
};
|
|
21860
21861
|
function parseChatOs(raw) {
|
|
21861
21862
|
const k = raw.trim().toLowerCase();
|
|
@@ -21863,7 +21864,7 @@ function parseChatOs(raw) {
|
|
|
21863
21864
|
throw new CliError(
|
|
21864
21865
|
"USAGE",
|
|
21865
21866
|
`invalid --os: ${raw}`,
|
|
21866
|
-
"expected windows|osx|mac|ios|android"
|
|
21867
|
+
"expected windows|osx|mac|ios|android|ipad"
|
|
21867
21868
|
);
|
|
21868
21869
|
}
|
|
21869
21870
|
function resolveChatOs(optsOs, cfg) {
|
|
@@ -22494,7 +22495,7 @@ function register(program3, variant) {
|
|
|
22494
22495
|
const isAssistant = variant?.kind === "assistant";
|
|
22495
22496
|
define2(program3, {
|
|
22496
22497
|
name: isAssistant ? "assistant-login" : "login",
|
|
22497
|
-
description: isAssistant ? "Authenticate the assistant daemon's DEDICATED account and persist its tokens to ~/.muc/assistant/credentials.json (separate from your personal ~/.muc/credentials.json \u2014 the two never rotate each other's tokenPwd). Requires `muc assistant-init` first.
|
|
22498
|
+
description: isAssistant ? "Authenticate the assistant daemon's DEDICATED account and persist its tokens to ~/.muc/assistant/credentials.json (separate from your personal ~/.muc/credentials.json \u2014 the two never rotate each other's tokenPwd). Requires `muc assistant-init` first. REST login still defaults --platform to mac; the daemon chat connection separately defaults to the iPad slot via cfg.defaultChatOs. Run interactively: `muc assistant-login --account <UID>` prompts for the password with echo off." : "Authenticate against MUC and persist accessToken + tokenPwd. Run interactively in your own terminal: `muc login --account <UID>` prompts for the password with echo off. `--token-pwd` reuses the saved refresh token and needs no password (this is the only form an agent should run silently). Avoid `--password` / `--password-stdin` / `$MUC_PASSWORD` \u2014 they leak the password into shell history, process lists, and agent chat scrollback.",
|
|
22498
22499
|
output: Output,
|
|
22499
22500
|
configure: (cmd) => {
|
|
22500
22501
|
cmd.option("-a, --account <uid>", "MUC account uid (uppercase, e.g. WANGLULU8)").option("-p, --password <pwd>", "plaintext password (avoid; ends up in shell history)").option("--password-stdin", "read password from stdin (no trailing newline)").option("--token-pwd", "reuse the saved tokenPwd (skips password)").option("--platform <p>", "ios|android|win|mac or numeric code", (v) => parsePlatform(v)).option("--app-version <v>", "override appVersion sent in the login form").option("--remember", "persist an encrypted copy of the password for unattended re-login").option("--no-remember", "wipe any previously --remember'ed password");
|
|
@@ -22714,7 +22715,7 @@ var FingerprintShape = external_exports.object({
|
|
|
22714
22715
|
messageTail: external_exports.string(),
|
|
22715
22716
|
// summary: "default" / "none" / "custom (N chars)"
|
|
22716
22717
|
defaultChatOs: external_exports.string(),
|
|
22717
|
-
// summary: explicit value or "default (
|
|
22718
|
+
// summary: explicit value or "default (iPad)"
|
|
22718
22719
|
exposeStatusInSignature: external_exports.boolean(),
|
|
22719
22720
|
noRouteHint: external_exports.boolean(),
|
|
22720
22721
|
allowAssistantSharedProfile: external_exports.boolean(),
|
|
@@ -22911,10 +22912,10 @@ function register2(program3, variant) {
|
|
|
22911
22912
|
const isAssistant = variant?.kind === "assistant";
|
|
22912
22913
|
define2(program3, {
|
|
22913
22914
|
name: isAssistant ? "assistant-init" : "init",
|
|
22914
|
-
description: isAssistant ? "Bootstrap or update the assistant daemon's DEDICATED-account tenant config at ~/.muc/assistant/config.json (separate from your personal ~/.muc/config.json). Provisioning this makes `muc assistantd-start` authenticate as that account on its own chat slot (defaults defaultChatOs=
|
|
22915
|
+
description: isAssistant ? "Bootstrap or update the assistant daemon's DEDICATED-account tenant config at ~/.muc/assistant/config.json (separate from your personal ~/.muc/config.json). Provisioning this makes `muc assistantd-start` authenticate as that account on its own chat slot (defaults defaultChatOs=iPad, separate from PC and Mobile; a real iPad on the same account may be kicked). Tenant secrets default to whatever your personal `muc init` saved \u2014 pass --app-key/--app-id/--sign-secret-* to override. Then run `muc assistant-login`." : "Bootstrap or update ~/.muc/config.json (tenant config: APP_KEY, APP_ID, signing secrets, hosts/ports). Interactive prompts by default; non-interactive via flags or MUC_* env vars. WARNING: env vars are visible to other processes via /proc/<pid>/environ and shell history \u2014 prefer interactive or flag-based for production.",
|
|
22915
22916
|
output: Output2,
|
|
22916
22917
|
configure: (cmd) => {
|
|
22917
|
-
cmd.option("--check", "verify config presence and validity (exit 0 ok / 6 missing / 7 invalid); does not modify").option("--show", "print the saved config (secrets are always redacted in both human and JSON output; cat ~/.muc/config.json for raw values)").option("--reset", "delete ~/.muc/config.json (requires --yes)").option("--yes", "confirm a destructive action like --reset").option("--no-interactive", "fail rather than prompt for missing fields").option("--app-key <hex>", "tenant APP_KEY (8 lowercase hex)").option("--app-id <hex>", "tenant APP_ID (24 lowercase hex)").option("--sign-secret-rest <s>", "REST signing secret").option("--sign-secret-secure <s>", "secure-API signing secret").option("--pwd-des-key <s>", "password DES key (defaults to APP_KEY)").option("--rest-host <url>", "REST host URL").option("--sso-host <url>", "SSO host URL (optional)").option("--im-host <h>", "IM TCP host").option("--im-port <n>", "IM TCP port").option("--file-host <h>", "file-channel TCP host").option("--file-port <n>", "file-channel TCP port").option("--message-tail <text>", "custom signature appended to outbound `muc send` text (max 200 chars)").option("--no-message-tail", "explicitly disable the message tail (no signature appended)").option("--default-os <os>", "default chat-channel
|
|
22918
|
+
cmd.option("--check", "verify config presence and validity (exit 0 ok / 6 missing / 7 invalid); does not modify").option("--show", "print the saved config (secrets are always redacted in both human and JSON output; cat ~/.muc/config.json for raw values)").option("--reset", "delete ~/.muc/config.json (requires --yes)").option("--yes", "confirm a destructive action like --reset").option("--no-interactive", "fail rather than prompt for missing fields").option("--app-key <hex>", "tenant APP_KEY (8 lowercase hex)").option("--app-id <hex>", "tenant APP_ID (24 lowercase hex)").option("--sign-secret-rest <s>", "REST signing secret").option("--sign-secret-secure <s>", "secure-API signing secret").option("--pwd-des-key <s>", "password DES key (defaults to APP_KEY)").option("--rest-host <url>", "REST host URL").option("--sso-host <url>", "SSO host URL (optional)").option("--im-host <h>", "IM TCP host").option("--im-port <n>", "IM TCP port").option("--file-host <h>", "file-channel TCP host").option("--file-port <n>", "file-channel TCP port").option("--message-tail <text>", "custom signature appended to outbound `muc send` text (max 200 chars)").option("--no-message-tail", "explicitly disable the message tail (no signature appended)").option("--default-os <os>", "default chat-channel slot for TCP commands when --os is not passed (windows|osx|mac|ios|android|ipad); built-in fallback is iPad").option("--expose-status-in-signature", "opt in: assistant daemon writes a live status headline to your MUC profile signature (visible to anyone who hovers your name). Daemon reads this flag at start; restart `muc assistantd-start` after toggling for the change to take effect.").option("--no-expose-status-in-signature", "opt out (default) of profile-signature status updates; /status chat command stays available regardless. Daemon reads this flag at start; restart needed for the change to take effect.").option("--allow-assistant-shared-profile", "advanced opt-in: allow assistantd to use this personal profile when no dedicated assistant profile exists").option("--no-allow-assistant-shared-profile", "opt out (default): assistantd must use its dedicated ~/.muc/assistant profile");
|
|
22918
22919
|
},
|
|
22919
22920
|
run: async (cmd) => {
|
|
22920
22921
|
const opts = cmd.opts();
|
|
@@ -23056,7 +23057,7 @@ function register2(program3, variant) {
|
|
|
23056
23057
|
}
|
|
23057
23058
|
}
|
|
23058
23059
|
}
|
|
23059
|
-
const chatOsDefault =
|
|
23060
|
+
const chatOsDefault = DEFAULT_CHAT_OS.toLowerCase();
|
|
23060
23061
|
let defaultChatOs;
|
|
23061
23062
|
let dcoRaw;
|
|
23062
23063
|
const dcoFlag = opts.defaultOs;
|
|
@@ -23069,7 +23070,7 @@ function register2(program3, variant) {
|
|
|
23069
23070
|
defaultChatOs = existing.defaultChatOs;
|
|
23070
23071
|
} else if (interactive) {
|
|
23071
23072
|
const answer = await readLine(
|
|
23072
|
-
"Default chat
|
|
23073
|
+
"Default chat slot (windows|osx|mac|ios|android|ipad)",
|
|
23073
23074
|
chatOsDefault
|
|
23074
23075
|
);
|
|
23075
23076
|
if (answer.length > 0) dcoRaw = answer;
|
|
@@ -23078,7 +23079,7 @@ function register2(program3, variant) {
|
|
|
23078
23079
|
defaultChatOs = parseChatOs(dcoRaw);
|
|
23079
23080
|
}
|
|
23080
23081
|
if (defaultChatOs === void 0 && isAssistant) {
|
|
23081
|
-
defaultChatOs =
|
|
23082
|
+
defaultChatOs = DEFAULT_CHAT_OS;
|
|
23082
23083
|
}
|
|
23083
23084
|
const noRouteHint = existing?.noRouteHint;
|
|
23084
23085
|
const sharedConflict = detectFlagConflict(process.argv.slice(2), "allow-assistant-shared-profile");
|
|
@@ -23913,12 +23914,15 @@ var MucChatSocket = class extends EventEmitter {
|
|
|
23913
23914
|
|
|
23914
23915
|
// src/lib/chat.ts
|
|
23915
23916
|
init_profile();
|
|
23917
|
+
function chatLoginIdentity(chatOs) {
|
|
23918
|
+
return chatOs === "iPad" ? { os: "iOS", browser: "iPad" } : { os: chatOs };
|
|
23919
|
+
}
|
|
23916
23920
|
function buildLoginPayload(cred, chatOs, cfg) {
|
|
23917
23921
|
return {
|
|
23918
23922
|
login: {
|
|
23919
23923
|
account: cred.uid,
|
|
23920
23924
|
accessToken: cred.accessToken,
|
|
23921
|
-
|
|
23925
|
+
...chatLoginIdentity(chatOs),
|
|
23922
23926
|
osVersion: release3(),
|
|
23923
23927
|
sdkVersion: 21,
|
|
23924
23928
|
deviceId: cred.deviceId,
|
|
@@ -25080,7 +25084,7 @@ function register10(program3) {
|
|
|
25080
25084
|
description: 'Search groups the current user belongs to (TCP chat channel sid="team", cid="search_own_teams"). Pass --enrich for names + member counts. Will kick a session in the same online-slot.',
|
|
25081
25085
|
output: Output10,
|
|
25082
25086
|
configure: (cmd) => {
|
|
25083
|
-
cmd.argument("<keyword>", "team name fragment").option("--enrich", "follow up with team/get_team per id").option("--os <os>", "chat-channel
|
|
25087
|
+
cmd.argument("<keyword>", "team name fragment").option("--enrich", "follow up with team/get_team per id").option("--os <os>", "chat-channel slot (default: cfg.defaultChatOs ?? iPad)", parseChatOs).option("--no-daemon", "bypass any running personal daemon and use a direct connection on your own slot (also: MUC_NO_DAEMON=1)").option("--debug", "forward wire-level debug events to stderr");
|
|
25084
25088
|
},
|
|
25085
25089
|
run: async (cmd) => {
|
|
25086
25090
|
const [kw] = cmd.args;
|
|
@@ -25205,7 +25209,7 @@ function register11(program3) {
|
|
|
25205
25209
|
description: "List members of a joined group by TEAM_ID via TCP team/get_team_members. Pass --profiles to enrich department/title via organization search. Will kick a session in the same online-slot.",
|
|
25206
25210
|
output: Output11,
|
|
25207
25211
|
configure: (cmd) => {
|
|
25208
|
-
cmd.argument("<teamId>", "team/group id from search-team").option("--profiles", "enrich each member with org directory fields via REST organization/search").option("--os <os>", "chat-channel
|
|
25212
|
+
cmd.argument("<teamId>", "team/group id from search-team").option("--profiles", "enrich each member with org directory fields via REST organization/search").option("--os <os>", "chat-channel slot (default: cfg.defaultChatOs ?? iPad)", parseChatOs).option("--no-daemon", "bypass any running personal daemon and use a direct connection on your own slot (also: MUC_NO_DAEMON=1)").option("--debug", "forward wire-level debug events to stderr");
|
|
25209
25213
|
},
|
|
25210
25214
|
run: async (cmd) => {
|
|
25211
25215
|
const [id] = cmd.args;
|
|
@@ -25500,7 +25504,7 @@ function register15(program3) {
|
|
|
25500
25504
|
description: "After chat-login, run sync/syncDone, sync/syncSession, sync/syncWithdraws and return the raw responses.",
|
|
25501
25505
|
output: Output15,
|
|
25502
25506
|
configure: (cmd) => {
|
|
25503
|
-
cmd.option("--os <os>", "chat-channel
|
|
25507
|
+
cmd.option("--os <os>", "chat-channel slot (default: cfg.defaultChatOs ?? iPad)", parseChatOs).option("--no-daemon", "bypass any running personal daemon and use a direct connection on your own slot (also: MUC_NO_DAEMON=1)").option("--debug", "forward wire-level debug events to stderr");
|
|
25504
25508
|
},
|
|
25505
25509
|
run: async (cmd) => {
|
|
25506
25510
|
const { os: optsOs, debug, daemon } = cmd.opts();
|
|
@@ -25825,7 +25829,7 @@ function register17(program3) {
|
|
|
25825
25829
|
description: "Send a plain-text chat message via the TCP chat channel. VISIBLE TO THE RECIPIENT \u2014 non-self targets require --yes-not-self.",
|
|
25826
25830
|
output: Output17,
|
|
25827
25831
|
configure: (cmd) => {
|
|
25828
|
-
cmd.argument("<text...>", "message text (variadic; words rejoined with spaces)").option("--peer <uid>", "1:1 chat with a peer uid").option("--team <id>", "group chat with a team id").option("--to-self", "send to your own uid (default if no target given)").option("--yes-not-self", "required to confirm sending to anyone other than yourself").option("--dry-run", "build the frame but do not connect").option("--os <os>", "chat-channel
|
|
25832
|
+
cmd.argument("<text...>", "message text (variadic; words rejoined with spaces)").option("--peer <uid>", "1:1 chat with a peer uid").option("--team <id>", "group chat with a team id").option("--to-self", "send to your own uid (default if no target given)").option("--yes-not-self", "required to confirm sending to anyone other than yourself").option("--dry-run", "build the frame but do not connect").option("--os <os>", "chat-channel slot (default: cfg.defaultChatOs ?? iPad)", parseChatOs).option("--no-daemon", "bypass any running personal daemon and use a direct connection on your own slot (also: MUC_NO_DAEMON=1)").option("--tail <text>", "override message tail for this call only").option("--no-tail", "do not append a message tail for this call").option(
|
|
25829
25833
|
"--at <uid[:name][,uid[:name]...]>",
|
|
25830
25834
|
'@-mention one or more uids in a group (use "uid:name" to control the rendered display name; group target only)'
|
|
25831
25835
|
).option("--debug", "forward wire-level debug events to stderr");
|
|
@@ -26689,7 +26693,7 @@ function register18(program3) {
|
|
|
26689
26693
|
description: "Upload a local file (TCP 6101) and broadcast as MESSAGE_CHAT_FILE (subType=7). VISIBLE \u2014 non-self targets require --yes-not-self.",
|
|
26690
26694
|
output: Output18,
|
|
26691
26695
|
configure: (cmd) => {
|
|
26692
|
-
cmd.argument("<file>", "absolute or relative path to a local file").option("--peer <uid>", "1:1 chat with a peer uid").option("--team <id>", "group chat with a team id").option("--to-self", "send to your own uid (default if no target given)").option("--yes-not-self", "required to confirm sending to anyone other than yourself").option("--dry-run", "resolve target + sanity-check the local file but do not upload or send").option("--os <os>", "chat-channel
|
|
26696
|
+
cmd.argument("<file>", "absolute or relative path to a local file").option("--peer <uid>", "1:1 chat with a peer uid").option("--team <id>", "group chat with a team id").option("--to-self", "send to your own uid (default if no target given)").option("--yes-not-self", "required to confirm sending to anyone other than yourself").option("--dry-run", "resolve target + sanity-check the local file but do not upload or send").option("--os <os>", "chat-channel slot for talk/sendMsg (default: cfg.defaultChatOs ?? iPad)", parseChatOs).option("--no-daemon", "bypass any running personal daemon and use a direct connection on your own slot (also: MUC_NO_DAEMON=1)").option("--debug", "forward wire-level debug events to stderr");
|
|
26693
26697
|
},
|
|
26694
26698
|
run: async (cmd) => {
|
|
26695
26699
|
const filePath = path2.resolve(String(cmd.args[0] ?? ""));
|
|
@@ -26887,7 +26891,7 @@ function register19(program3) {
|
|
|
26887
26891
|
description: "Upload an image (TCP 6101) and broadcast as MESSAGE_CHAT_IMAGE (subType=8). VISIBLE \u2014 non-self targets require --yes-not-self.",
|
|
26888
26892
|
output: Output19,
|
|
26889
26893
|
configure: (cmd) => {
|
|
26890
|
-
cmd.argument("<file>", "PNG/JPEG/GIF/BMP image path").option("--peer <uid>", "1:1 chat with a peer uid").option("--team <id>", "group chat with a team id").option("--to-self", "send to your own uid (default)").option("--yes-not-self", "required for non-self targets").option("--width <px>", "override probed image width", parsePosInt("--width")).option("--height <px>", "override probed image height", parsePosInt("--height")).option("--dry-run", "sanity-check the local file (probe + stat) but do not upload or send").option("--os <os>", "chat-channel
|
|
26894
|
+
cmd.argument("<file>", "PNG/JPEG/GIF/BMP image path").option("--peer <uid>", "1:1 chat with a peer uid").option("--team <id>", "group chat with a team id").option("--to-self", "send to your own uid (default)").option("--yes-not-self", "required for non-self targets").option("--width <px>", "override probed image width", parsePosInt("--width")).option("--height <px>", "override probed image height", parsePosInt("--height")).option("--dry-run", "sanity-check the local file (probe + stat) but do not upload or send").option("--os <os>", "chat-channel slot (default: cfg.defaultChatOs ?? iPad)", parseChatOs).option("--no-daemon", "bypass any running personal daemon and use a direct connection on your own slot (also: MUC_NO_DAEMON=1)").option("--debug", "forward wire-level debug events to stderr");
|
|
26891
26895
|
},
|
|
26892
26896
|
run: async (cmd) => {
|
|
26893
26897
|
const filePath = path3.resolve(String(cmd.args[0] ?? ""));
|
|
@@ -27065,7 +27069,7 @@ function register20(program3) {
|
|
|
27065
27069
|
description: "Upload an audio clip (TCP 6101) and broadcast as MESSAGE_CHAT_AUDIO (subType=9). VISIBLE \u2014 non-self targets require --yes-not-self.",
|
|
27066
27070
|
output: Output20,
|
|
27067
27071
|
configure: (cmd) => {
|
|
27068
|
-
cmd.argument("<file>", "audio file path (typically .amr)").requiredOption("--duration <ms>", "clip duration in milliseconds", parsePosInt("--duration")).option("--peer <uid>", "1:1 chat with a peer uid").option("--team <id>", "group chat with a team id").option("--to-self", "send to your own uid (default)").option("--yes-not-self", "required for non-self targets").option("--dry-run", "sanity-check the local file but do not upload or send").option("--os <os>", "chat-channel
|
|
27072
|
+
cmd.argument("<file>", "audio file path (typically .amr)").requiredOption("--duration <ms>", "clip duration in milliseconds", parsePosInt("--duration")).option("--peer <uid>", "1:1 chat with a peer uid").option("--team <id>", "group chat with a team id").option("--to-self", "send to your own uid (default)").option("--yes-not-self", "required for non-self targets").option("--dry-run", "sanity-check the local file but do not upload or send").option("--os <os>", "chat-channel slot (default: cfg.defaultChatOs ?? iPad)", parseChatOs).option("--no-daemon", "bypass any running personal daemon and use a direct connection on your own slot (also: MUC_NO_DAEMON=1)").option("--debug", "forward wire-level debug events to stderr");
|
|
27069
27073
|
},
|
|
27070
27074
|
run: async (cmd) => {
|
|
27071
27075
|
const filePath = path4.resolve(String(cmd.args[0] ?? ""));
|
|
@@ -27326,7 +27330,7 @@ function register22(program3) {
|
|
|
27326
27330
|
description: "Withdraw a previously-sent message (P2P_MSG_CANCEL). VISIBLE TO THE RECIPIENT \u2014 non-self targets require --yes-not-self.",
|
|
27327
27331
|
output: Output22,
|
|
27328
27332
|
configure: (cmd) => {
|
|
27329
|
-
cmd.requiredOption("--mid <mid>", "message id to withdraw").option("--peer <uid>", "1:1 chat with a peer uid").option("--team <id>", "group chat with a team id").option("--to-self", "withdraw in your self-chat (default if no target)").option("--yes-not-self", "required to confirm withdrawing in a non-self conversation").option("--dry-run", "build the frame but do not connect").option("--os <os>", "chat-channel
|
|
27333
|
+
cmd.requiredOption("--mid <mid>", "message id to withdraw").option("--peer <uid>", "1:1 chat with a peer uid").option("--team <id>", "group chat with a team id").option("--to-self", "withdraw in your self-chat (default if no target)").option("--yes-not-self", "required to confirm withdrawing in a non-self conversation").option("--dry-run", "build the frame but do not connect").option("--os <os>", "chat-channel slot (default: cfg.defaultChatOs ?? iPad)", parseChatOs).option("--no-daemon", "bypass any running personal daemon and use a direct connection on your own slot (also: MUC_NO_DAEMON=1)").option("--debug", "forward wire-level debug events to stderr");
|
|
27330
27334
|
},
|
|
27331
27335
|
run: async (cmd) => {
|
|
27332
27336
|
const opts = cmd.opts();
|
|
@@ -27440,7 +27444,7 @@ function register23(program3) {
|
|
|
27440
27444
|
description: "Send user/delSession to drop the local session record on all of the user's devices.",
|
|
27441
27445
|
output: Output23,
|
|
27442
27446
|
configure: (cmd) => {
|
|
27443
|
-
cmd.option("--peer <uid>", "session with a peer uid").option("--team <id>", "session with a team id").option("--to-self", "self-chat session (default if no target)").option("--yes-not-self", "required to confirm clearing a non-self session").option("--dry-run", "build the frame but do not connect").option("--os <os>", "chat-channel
|
|
27447
|
+
cmd.option("--peer <uid>", "session with a peer uid").option("--team <id>", "session with a team id").option("--to-self", "self-chat session (default if no target)").option("--yes-not-self", "required to confirm clearing a non-self session").option("--dry-run", "build the frame but do not connect").option("--os <os>", "chat-channel slot (default: cfg.defaultChatOs ?? iPad)", parseChatOs).option("--no-daemon", "bypass any running personal daemon and use a direct connection on your own slot (also: MUC_NO_DAEMON=1)").option("--debug", "forward wire-level debug events to stderr");
|
|
27444
27448
|
},
|
|
27445
27449
|
run: async (cmd) => {
|
|
27446
27450
|
const opts = cmd.opts();
|
|
@@ -27642,7 +27646,7 @@ function registerPin(program3) {
|
|
|
27642
27646
|
description: "Pin a chat session to the top of the conversation list (TCP user/setCacheField sticky_on_top_id, op=1). Multi-device via user cache. Will kick a session in the same online-slot.",
|
|
27643
27647
|
output: MutateOutput,
|
|
27644
27648
|
configure: (cmd) => {
|
|
27645
|
-
cmd.option("--peer <uid>", "1:1 session with this uid").option("--team <id>", "group session (team id)").option("--to-self", "self-chat session (default if no target)").option("--sid <sId>", "raw session id (teamId or UID|UID); overrides --peer/--team/--to-self").option("--dry-run", "build the frame but do not connect").option("--os <os>", "chat-channel
|
|
27649
|
+
cmd.option("--peer <uid>", "1:1 session with this uid").option("--team <id>", "group session (team id)").option("--to-self", "self-chat session (default if no target)").option("--sid <sId>", "raw session id (teamId or UID|UID); overrides --peer/--team/--to-self").option("--dry-run", "build the frame but do not connect").option("--os <os>", "chat-channel slot (default: cfg.defaultChatOs ?? iPad)", parseChatOs).option("--no-daemon", "bypass any running personal daemon (also: MUC_NO_DAEMON=1)").option("--debug", "forward wire-level debug events to stderr");
|
|
27646
27650
|
},
|
|
27647
27651
|
run: async (cmd) => mutateSticky(cmd, "pin")
|
|
27648
27652
|
});
|
|
@@ -27653,7 +27657,7 @@ function registerUnpin(program3) {
|
|
|
27653
27657
|
description: "Remove a session from the pin list (TCP user/setCacheField sticky_on_top_id, op=2). Will kick a session in the same online-slot.",
|
|
27654
27658
|
output: MutateOutput,
|
|
27655
27659
|
configure: (cmd) => {
|
|
27656
|
-
cmd.option("--peer <uid>", "1:1 session with this uid").option("--team <id>", "group session (team id)").option("--to-self", "self-chat session (default if no target)").option("--sid <sId>", "raw session id (teamId or UID|UID); overrides --peer/--team/--to-self").option("--dry-run", "build the frame but do not connect").option("--os <os>", "chat-channel
|
|
27660
|
+
cmd.option("--peer <uid>", "1:1 session with this uid").option("--team <id>", "group session (team id)").option("--to-self", "self-chat session (default if no target)").option("--sid <sId>", "raw session id (teamId or UID|UID); overrides --peer/--team/--to-self").option("--dry-run", "build the frame but do not connect").option("--os <os>", "chat-channel slot (default: cfg.defaultChatOs ?? iPad)", parseChatOs).option("--no-daemon", "bypass any running personal daemon (also: MUC_NO_DAEMON=1)").option("--debug", "forward wire-level debug events to stderr");
|
|
27657
27661
|
},
|
|
27658
27662
|
run: async (cmd) => mutateSticky(cmd, "unpin")
|
|
27659
27663
|
});
|
|
@@ -27711,7 +27715,7 @@ function registerPinned(program3) {
|
|
|
27711
27715
|
description: "List pinned session sIds from user cache (TCP user/setCacheField no-op delete probe \u2192 sticky_on_top_id). Will kick a session in the same online-slot.",
|
|
27712
27716
|
output: ListOutput,
|
|
27713
27717
|
configure: (cmd) => {
|
|
27714
|
-
cmd.option("--dry-run", "build the probe frame but do not connect").option("--os <os>", "chat-channel
|
|
27718
|
+
cmd.option("--dry-run", "build the probe frame but do not connect").option("--os <os>", "chat-channel slot (default: cfg.defaultChatOs ?? iPad)", parseChatOs).option("--no-daemon", "bypass any running personal daemon (also: MUC_NO_DAEMON=1)").option("--debug", "forward wire-level debug events to stderr");
|
|
27715
27719
|
},
|
|
27716
27720
|
run: async (cmd) => {
|
|
27717
27721
|
const opts = cmd.opts();
|
|
@@ -28036,10 +28040,10 @@ var Output27 = external_exports.object({
|
|
|
28036
28040
|
function register28(program3) {
|
|
28037
28041
|
define2(program3, {
|
|
28038
28042
|
name: "wait-react",
|
|
28039
|
-
description: "Block until someone adds a default emoji reaction (subType=300) to --mid. Consumes a TCP slot \u2014 defaults to
|
|
28043
|
+
description: "Block until someone adds a default emoji reaction (subType=300) to --mid. Consumes a TCP slot \u2014 defaults to the iPad slot.",
|
|
28040
28044
|
output: Output27,
|
|
28041
28045
|
configure: (cmd) => {
|
|
28042
|
-
cmd.requiredOption("--mid <mid>", "message id to wait for a reaction on").option("--from-uid <uid>", "only consider reactions from this UID (case-insensitive match against fId of the type=3 notification)").option("--emoji <name>", "only consider this default reaction emoji name, e.g. [\u70B9\u8D5E] or \u70B9\u8D5E").option("--sticker-id <name>", "deprecated alias for --emoji").option("--timeout <seconds>", "give up after this many seconds (default 300)", parsePosInt("--timeout"), 300).option("--os <os>", "chat-channel
|
|
28046
|
+
cmd.requiredOption("--mid <mid>", "message id to wait for a reaction on").option("--from-uid <uid>", "only consider reactions from this UID (case-insensitive match against fId of the type=3 notification)").option("--emoji <name>", "only consider this default reaction emoji name, e.g. [\u70B9\u8D5E] or \u70B9\u8D5E").option("--sticker-id <name>", "deprecated alias for --emoji").option("--timeout <seconds>", "give up after this many seconds (default 300)", parsePosInt("--timeout"), 300).option("--os <os>", "chat-channel slot (default: cfg.defaultChatOs ?? iPad)", parseChatOs).option("--no-daemon", "bypass any running personal daemon and wait on a direct connection on your own slot (also: MUC_NO_DAEMON=1)").option("--debug", "forward wire-level debug events to stderr");
|
|
28043
28047
|
},
|
|
28044
28048
|
run: async (cmd) => {
|
|
28045
28049
|
const opts = cmd.opts();
|
|
@@ -28252,7 +28256,7 @@ function register29(program3) {
|
|
|
28252
28256
|
description: "Tail incoming chat messages, filtered by sender / team / peer / keyword / regex / @-mention. Emit one line per match \u2014 NDJSON envelope under `--json`, human summary otherwise. Consumes a TCP slot.",
|
|
28253
28257
|
streamSchema: STREAM_SCHEMA,
|
|
28254
28258
|
configure: (cmd) => {
|
|
28255
|
-
cmd.option("--from-uid <uid>", "only emit messages from this UID (repeat for OR; matched against fId, case-insensitive)", collect, []).option("--team <id>", "only emit messages in this team (repeat for OR)", collect, []).option("--peer <uid>", "only emit p2p messages with this peer UID (repeat for OR)", collect, []).option("--contains <text>", "only emit messages whose text contains this substring, case-insensitive (repeat for OR)", collect, []).option("--regex <pattern>", "only emit messages whose text matches this RE2-flavoured regex (repeat for OR)", collect, []).option("--type <n>", "only emit messages of this `type` field (default 1; repeat for OR)", collectInt("--type"), []).option("--subtype <n>", "only emit messages of this `subType` field (repeat for OR; default = any)", collectInt("--subtype"), []).option("--max <n>", "exit after emitting this many matching lines", parsePosInt("--max")).option("--at-me", "only emit group messages that @-mention you (mirrors the desktop SDK isAtMe: scene=team_g, fId\u2260self, atIds includes self uid). Implies excluding self.").option("--include-self", "do not filter out messages whose fId is your own UID").option("--include-reactions", "also emit type=3 sub=300/301 (reaction add/remove) frames").option("--include-offline", "also emit messages flushed via cid=offMsg on connect (default: only post-connect msg)").option("--os <os>", "chat-channel
|
|
28259
|
+
cmd.option("--from-uid <uid>", "only emit messages from this UID (repeat for OR; matched against fId, case-insensitive)", collect, []).option("--team <id>", "only emit messages in this team (repeat for OR)", collect, []).option("--peer <uid>", "only emit p2p messages with this peer UID (repeat for OR)", collect, []).option("--contains <text>", "only emit messages whose text contains this substring, case-insensitive (repeat for OR)", collect, []).option("--regex <pattern>", "only emit messages whose text matches this RE2-flavoured regex (repeat for OR)", collect, []).option("--type <n>", "only emit messages of this `type` field (default 1; repeat for OR)", collectInt("--type"), []).option("--subtype <n>", "only emit messages of this `subType` field (repeat for OR; default = any)", collectInt("--subtype"), []).option("--max <n>", "exit after emitting this many matching lines", parsePosInt("--max")).option("--at-me", "only emit group messages that @-mention you (mirrors the desktop SDK isAtMe: scene=team_g, fId\u2260self, atIds includes self uid). Implies excluding self.").option("--include-self", "do not filter out messages whose fId is your own UID").option("--include-reactions", "also emit type=3 sub=300/301 (reaction add/remove) frames").option("--include-offline", "also emit messages flushed via cid=offMsg on connect (default: only post-connect msg)").option("--os <os>", "chat-channel slot (default: cfg.defaultChatOs ?? iPad)", parseChatOs).option("--no-daemon", "bypass any running personal daemon and listen on a direct connection on your own slot (also: MUC_NO_DAEMON=1)").option("--debug", "forward wire-level debug events to stderr");
|
|
28256
28260
|
},
|
|
28257
28261
|
run: async (cmd) => {
|
|
28258
28262
|
const opts = cmd.opts();
|
|
@@ -28642,7 +28646,7 @@ var ChatBroker = class {
|
|
|
28642
28646
|
);
|
|
28643
28647
|
}
|
|
28644
28648
|
this.cred = cred;
|
|
28645
|
-
this.os = this.opts.os ?? this.cfg.defaultChatOs ??
|
|
28649
|
+
this.os = this.opts.os ?? this.cfg.defaultChatOs ?? DEFAULT_CHAT_OS;
|
|
28646
28650
|
this.startedAt = Date.now();
|
|
28647
28651
|
ensureRuntimeDir(this.paths);
|
|
28648
28652
|
writePid(this.paths, process.pid);
|
|
@@ -29220,7 +29224,7 @@ function register30(program3) {
|
|
|
29220
29224
|
description: "Start the personal-account daemon in the foreground. Holds the chat socket for ordinary commands and writes raw daemon events.",
|
|
29221
29225
|
output: StartOutput,
|
|
29222
29226
|
configure: (cmd) => {
|
|
29223
|
-
cmd.option("--os <os>", "chat-channel
|
|
29227
|
+
cmd.option("--os <os>", "chat-channel slot (default: cfg.defaultChatOs ?? iPad)", parseChatOs).option("--on-kicked <policy>", "when another device takes the slot: pause, immediate, or a delay such as 30s/5m/2h/1d (default: 3m)", parseKickedRecoveryPolicy).option("--debug", "forward wire-level debug events to stderr");
|
|
29224
29228
|
},
|
|
29225
29229
|
run: async (cmd) => {
|
|
29226
29230
|
const opts = cmd.opts();
|
|
@@ -33500,7 +33504,7 @@ return the JSON envelope and let the daemon send.
|
|
|
33500
33504
|
Every TCP verb above rides the assistant daemon's existing socket \u2014 no
|
|
33501
33505
|
slot taken, no device kicked. This exception applies only inside
|
|
33502
33506
|
assistant backend turns. Ordinary Codex/MUC skills use personal daemon
|
|
33503
|
-
routing (\`muc daemon-start\`) and must follow
|
|
33507
|
+
routing (\`muc daemon-start\`) and must follow the non-blocking iPad notice rules.
|
|
33504
33508
|
|
|
33505
33509
|
## Attachments and quotes
|
|
33506
33510
|
|
|
@@ -33957,7 +33961,7 @@ var AssistantDaemon = class {
|
|
|
33957
33961
|
if (!usingAssistantProfile) {
|
|
33958
33962
|
await assertNoPersonalDaemonConflict(this.cred.uid);
|
|
33959
33963
|
}
|
|
33960
|
-
this.os = this.opts.os ?? this.cfg.defaultChatOs ??
|
|
33964
|
+
this.os = this.opts.os ?? this.cfg.defaultChatOs ?? DEFAULT_CHAT_OS;
|
|
33961
33965
|
ensureRuntimeDir2();
|
|
33962
33966
|
writePid2(process.pid);
|
|
33963
33967
|
this.startedAt = Date.now();
|
|
@@ -36040,7 +36044,7 @@ function register32(program3) {
|
|
|
36040
36044
|
description: "Start the assistant daemon in the foreground. Holds the chat socket on the chosen --os slot. v1 has no launchd integration; rerun under tmux/screen if you want it persistent.",
|
|
36041
36045
|
output: StartOutput2,
|
|
36042
36046
|
configure: (cmd) => {
|
|
36043
|
-
cmd.option("--os <os>", "chat-channel
|
|
36047
|
+
cmd.option("--os <os>", "chat-channel slot (default: cfg.defaultChatOs ?? iPad)", parseChatOs).option("--on-kicked <policy>", "when another device takes the slot: pause, immediate, or a delay such as 30s/5m/2h/1d (default: 3m)", parseKickedRecoveryPolicy).option("--debug", "forward wire-level debug events to stderr");
|
|
36044
36048
|
},
|
|
36045
36049
|
run: async (cmd) => {
|
|
36046
36050
|
const opts = cmd.opts();
|