@mu-cabin/muc-cli 0.5.3 → 0.5.5
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 +34 -40
- package/dist/muc.mjs +45 -39
- 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,13 +348,14 @@ 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
|
-
next refreshes.
|
|
356
|
+
next refreshes. Remembered-password daemon recovery is different: it uses
|
|
357
|
+
`createTokenPwd=false`, refreshing only accessToken and preserving the
|
|
358
|
+
phone's auto-login credential.
|
|
362
359
|
|
|
363
360
|
The fix is to give the daemon its **own account**, stored under
|
|
364
361
|
`~/.muc/assistant/` (next to its pid / socket / logs) and completely
|
|
@@ -367,7 +364,7 @@ separate from your personal `~/.muc/`:
|
|
|
367
364
|
```bash
|
|
368
365
|
muc assistant-init # tenant config → ~/.muc/assistant/config.json
|
|
369
366
|
# (tenant secrets/hosts default to whatever your
|
|
370
|
-
# personal `muc init` saved; defaultChatOs →
|
|
367
|
+
# personal `muc init` saved; defaultChatOs → iPad)
|
|
371
368
|
muc assistant-login --account <BOT_UID> # → ~/.muc/assistant/credentials.json
|
|
372
369
|
# (--platform defaults to mac)
|
|
373
370
|
muc assistantd-start # picks up the dedicated profile
|
|
@@ -376,10 +373,9 @@ muc whoami --assistant # confirm which account it's on
|
|
|
376
373
|
|
|
377
374
|
Once provisioned, `muc assistantd-start` reads the dedicated profile
|
|
378
375
|
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
|
|
376
|
+
daemon defaults to the **iPad slot**, so the account's desktop and phone
|
|
377
|
+
slots remain independent. A real iPad logged into that same assistant
|
|
378
|
+
account may be kicked. Remove the profile (`rm -rf ~/.muc/assistant/config.json
|
|
383
379
|
~/.muc/assistant/credentials.json`) only if you intend to use the explicit
|
|
384
380
|
shared-profile mode.
|
|
385
381
|
|
|
@@ -463,7 +459,7 @@ Hand-edit, or seeded by `assistant-new`:
|
|
|
463
459
|
|
|
464
460
|
```bash
|
|
465
461
|
# v1: foreground only; wrap in tmux/screen for persistence.
|
|
466
|
-
muc assistantd-start
|
|
462
|
+
muc assistantd-start # default iPad slot
|
|
467
463
|
muc assistant-new desk-bot --description "out-of-hours triage in IT 值班群"
|
|
468
464
|
$EDITOR ~/.muc/assistants/desk-bot/config.json # add scope.tids etc.
|
|
469
465
|
muc assistant-edit desk-bot # tune the persona
|
|
@@ -526,23 +522,22 @@ run anytime.
|
|
|
526
522
|
|
|
527
523
|
**Chat-channel commands** (`sync`, `search-team`, `team-members`, `send`, `send-file`,
|
|
528
524
|
`send-image`, `send-voice`, `withdraw`, `clear-session`, `pin`, `unpin`, `pinned`) open a TCP-8101
|
|
529
|
-
session and share a per-user **
|
|
525
|
+
session and share a per-user **three-slot** model with real devices:
|
|
530
526
|
|
|
531
527
|
| Slot | `--os` values |
|
|
532
528
|
|---|---|
|
|
533
529
|
| PC | `Windows`, `"OS X"`, `Mac` |
|
|
534
|
-
| Mobile | `iOS
|
|
530
|
+
| Mobile | `iOS`, `Android` |
|
|
531
|
+
| iPad | `iPad` (default; wire `os:"iOS", browser:"iPad"`) |
|
|
535
532
|
|
|
536
533
|
A second login in the same slot kicks the previous client off the realtime
|
|
537
534
|
channel — the IM panel goes offline, but tokens stay valid (reopen to
|
|
538
|
-
recover). The Mac desktop signs in as `"OS X"` (PC
|
|
539
|
-
|
|
535
|
+
recover). The Mac desktop signs in as `"OS X"` (PC); the iPhone signs in as
|
|
536
|
+
`iOS` (Mobile); the iPad app adds `browser:"iPad"` (iPad).
|
|
540
537
|
|
|
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).
|
|
538
|
+
The CLI defaults to `--os iPad`, so desktop and phone can remain online.
|
|
539
|
+
Only a real iPad on the same account may be kicked by the default. Explicit
|
|
540
|
+
PC or Mobile values intentionally target those older slots.
|
|
546
541
|
|
|
547
542
|
`tcp-ping` only does TCP connect + NEGOTIATE (no `auth/login`), so it can't
|
|
548
543
|
kick anything. Run it first to confirm the wire protocol is happy on your
|
|
@@ -636,13 +631,15 @@ files by hand.
|
|
|
636
631
|
## Changelog
|
|
637
632
|
|
|
638
633
|
#### Unreleased
|
|
634
|
+
- 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.
|
|
635
|
+
- 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
636
|
- 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
637
|
- 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
638
|
- Add raw event cursors (`<epoch_ms>-<sequence>`), 90-day personal daemon event retention, and `CURSOR_NOT_FOUND` handling for missing retained cursors.
|
|
642
639
|
|
|
643
640
|
#### `0.5.0`
|
|
644
641
|
`2026.05.11`
|
|
645
|
-
- Add `muc assistant-init` / `muc assistant-login` and `muc whoami --assistant`: the assistant daemon can
|
|
642
|
+
- 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
643
|
- 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
644
|
|
|
648
645
|
#### `0.4.1`
|
|
@@ -661,7 +658,7 @@ files by hand.
|
|
|
661
658
|
|
|
662
659
|
#### `0.3.1`
|
|
663
660
|
`2026.04.29`
|
|
664
|
-
- Add `defaultChatOs` to `~/.muc/config.json
|
|
661
|
+
- 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
662
|
|
|
666
663
|
#### `0.3.0`
|
|
667
664
|
`2026.04.29`
|
|
@@ -724,11 +721,9 @@ files by hand.
|
|
|
724
721
|
- `EPROTO` / TLS errors — corporate proxy or VPN intercepting traffic.
|
|
725
722
|
`muc-cli` does not pin certificates, so adding the proxy CA to your Node
|
|
726
723
|
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.
|
|
724
|
+
- A TCP command kicks a client off the IM panel — the CLI's `--os` value
|
|
725
|
+
collided with that client's slot. The default `--os iPad` only risks a
|
|
726
|
+
real iPad; explicit PC or Mobile values risk the matching client.
|
|
732
727
|
|
|
733
728
|
### 5.9 Gemini CLI headless timeout
|
|
734
729
|
|
|
@@ -779,9 +774,8 @@ works interactively.
|
|
|
779
774
|
leak through shell history and `/proc/<pid>/environ` to other processes
|
|
780
775
|
on the same machine. Use the interactive prompt or one-shot flags pulled
|
|
781
776
|
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.
|
|
777
|
+
- TCP login over 8101 registers a device session in one of three slots per
|
|
778
|
+
user (PC, Mobile, or iPad). A second login in the same slot kicks the first.
|
|
779
|
+
Default `--os iPad` only risks a real iPad on the same account.
|
|
786
780
|
- `tcp-ping` is the only chat-channel command that cannot kick anything —
|
|
787
781
|
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) {
|
|
@@ -22295,8 +22296,8 @@ async function doRefreshViaRememberedPwd() {
|
|
|
22295
22296
|
deviceName: cred.deviceName || getDeviceName(),
|
|
22296
22297
|
passwordType: 0,
|
|
22297
22298
|
// plaintext password (DES-encoded), not tokenPwd
|
|
22298
|
-
createTokenPwd:
|
|
22299
|
-
//
|
|
22299
|
+
createTokenPwd: false,
|
|
22300
|
+
// accessToken only; do not rotate phone auto-login
|
|
22300
22301
|
encrypt: true
|
|
22301
22302
|
};
|
|
22302
22303
|
form.sign = signRest(form, cfg.signSecretRest);
|
|
@@ -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,
|
|
@@ -24048,13 +24052,15 @@ async function tryRefreshViaEmpGet2(cred, cfg) {
|
|
|
24048
24052
|
}
|
|
24049
24053
|
}
|
|
24050
24054
|
async function refreshAccessTokenViaTokenPwd(cred, cfg) {
|
|
24055
|
+
const platform3 = DEFAULT_REST_PLATFORM;
|
|
24056
|
+
const appVersion = platform3 === PLATFORM_IOS ? APP_VERSION_IOS : APP_VERSION;
|
|
24051
24057
|
const form = {
|
|
24052
24058
|
account: cred.uid,
|
|
24053
24059
|
password: encryptPassword(cred.tokenPwd, pwdDesKeyOf(cfg)),
|
|
24054
24060
|
appName: APP_NAME,
|
|
24055
24061
|
appKey: cfg.appKey,
|
|
24056
|
-
appVersion
|
|
24057
|
-
platform:
|
|
24062
|
+
appVersion,
|
|
24063
|
+
platform: platform3,
|
|
24058
24064
|
osVersion: release3(),
|
|
24059
24065
|
deviceId: cred.deviceId,
|
|
24060
24066
|
deviceName: cred.deviceName,
|
|
@@ -25080,7 +25086,7 @@ function register10(program3) {
|
|
|
25080
25086
|
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
25087
|
output: Output10,
|
|
25082
25088
|
configure: (cmd) => {
|
|
25083
|
-
cmd.argument("<keyword>", "team name fragment").option("--enrich", "follow up with team/get_team per id").option("--os <os>", "chat-channel
|
|
25089
|
+
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
25090
|
},
|
|
25085
25091
|
run: async (cmd) => {
|
|
25086
25092
|
const [kw] = cmd.args;
|
|
@@ -25205,7 +25211,7 @@ function register11(program3) {
|
|
|
25205
25211
|
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
25212
|
output: Output11,
|
|
25207
25213
|
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
|
|
25214
|
+
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
25215
|
},
|
|
25210
25216
|
run: async (cmd) => {
|
|
25211
25217
|
const [id] = cmd.args;
|
|
@@ -25500,7 +25506,7 @@ function register15(program3) {
|
|
|
25500
25506
|
description: "After chat-login, run sync/syncDone, sync/syncSession, sync/syncWithdraws and return the raw responses.",
|
|
25501
25507
|
output: Output15,
|
|
25502
25508
|
configure: (cmd) => {
|
|
25503
|
-
cmd.option("--os <os>", "chat-channel
|
|
25509
|
+
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
25510
|
},
|
|
25505
25511
|
run: async (cmd) => {
|
|
25506
25512
|
const { os: optsOs, debug, daemon } = cmd.opts();
|
|
@@ -25825,7 +25831,7 @@ function register17(program3) {
|
|
|
25825
25831
|
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
25832
|
output: Output17,
|
|
25827
25833
|
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
|
|
25834
|
+
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
25835
|
"--at <uid[:name][,uid[:name]...]>",
|
|
25830
25836
|
'@-mention one or more uids in a group (use "uid:name" to control the rendered display name; group target only)'
|
|
25831
25837
|
).option("--debug", "forward wire-level debug events to stderr");
|
|
@@ -26689,7 +26695,7 @@ function register18(program3) {
|
|
|
26689
26695
|
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
26696
|
output: Output18,
|
|
26691
26697
|
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
|
|
26698
|
+
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
26699
|
},
|
|
26694
26700
|
run: async (cmd) => {
|
|
26695
26701
|
const filePath = path2.resolve(String(cmd.args[0] ?? ""));
|
|
@@ -26887,7 +26893,7 @@ function register19(program3) {
|
|
|
26887
26893
|
description: "Upload an image (TCP 6101) and broadcast as MESSAGE_CHAT_IMAGE (subType=8). VISIBLE \u2014 non-self targets require --yes-not-self.",
|
|
26888
26894
|
output: Output19,
|
|
26889
26895
|
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
|
|
26896
|
+
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
26897
|
},
|
|
26892
26898
|
run: async (cmd) => {
|
|
26893
26899
|
const filePath = path3.resolve(String(cmd.args[0] ?? ""));
|
|
@@ -27065,7 +27071,7 @@ function register20(program3) {
|
|
|
27065
27071
|
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
27072
|
output: Output20,
|
|
27067
27073
|
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
|
|
27074
|
+
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
27075
|
},
|
|
27070
27076
|
run: async (cmd) => {
|
|
27071
27077
|
const filePath = path4.resolve(String(cmd.args[0] ?? ""));
|
|
@@ -27326,7 +27332,7 @@ function register22(program3) {
|
|
|
27326
27332
|
description: "Withdraw a previously-sent message (P2P_MSG_CANCEL). VISIBLE TO THE RECIPIENT \u2014 non-self targets require --yes-not-self.",
|
|
27327
27333
|
output: Output22,
|
|
27328
27334
|
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
|
|
27335
|
+
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
27336
|
},
|
|
27331
27337
|
run: async (cmd) => {
|
|
27332
27338
|
const opts = cmd.opts();
|
|
@@ -27440,7 +27446,7 @@ function register23(program3) {
|
|
|
27440
27446
|
description: "Send user/delSession to drop the local session record on all of the user's devices.",
|
|
27441
27447
|
output: Output23,
|
|
27442
27448
|
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
|
|
27449
|
+
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
27450
|
},
|
|
27445
27451
|
run: async (cmd) => {
|
|
27446
27452
|
const opts = cmd.opts();
|
|
@@ -27642,7 +27648,7 @@ function registerPin(program3) {
|
|
|
27642
27648
|
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
27649
|
output: MutateOutput,
|
|
27644
27650
|
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
|
|
27651
|
+
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
27652
|
},
|
|
27647
27653
|
run: async (cmd) => mutateSticky(cmd, "pin")
|
|
27648
27654
|
});
|
|
@@ -27653,7 +27659,7 @@ function registerUnpin(program3) {
|
|
|
27653
27659
|
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
27660
|
output: MutateOutput,
|
|
27655
27661
|
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
|
|
27662
|
+
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
27663
|
},
|
|
27658
27664
|
run: async (cmd) => mutateSticky(cmd, "unpin")
|
|
27659
27665
|
});
|
|
@@ -27711,7 +27717,7 @@ function registerPinned(program3) {
|
|
|
27711
27717
|
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
27718
|
output: ListOutput,
|
|
27713
27719
|
configure: (cmd) => {
|
|
27714
|
-
cmd.option("--dry-run", "build the probe frame but do not connect").option("--os <os>", "chat-channel
|
|
27720
|
+
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
27721
|
},
|
|
27716
27722
|
run: async (cmd) => {
|
|
27717
27723
|
const opts = cmd.opts();
|
|
@@ -28036,10 +28042,10 @@ var Output27 = external_exports.object({
|
|
|
28036
28042
|
function register28(program3) {
|
|
28037
28043
|
define2(program3, {
|
|
28038
28044
|
name: "wait-react",
|
|
28039
|
-
description: "Block until someone adds a default emoji reaction (subType=300) to --mid. Consumes a TCP slot \u2014 defaults to
|
|
28045
|
+
description: "Block until someone adds a default emoji reaction (subType=300) to --mid. Consumes a TCP slot \u2014 defaults to the iPad slot.",
|
|
28040
28046
|
output: Output27,
|
|
28041
28047
|
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
|
|
28048
|
+
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
28049
|
},
|
|
28044
28050
|
run: async (cmd) => {
|
|
28045
28051
|
const opts = cmd.opts();
|
|
@@ -28252,7 +28258,7 @@ function register29(program3) {
|
|
|
28252
28258
|
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
28259
|
streamSchema: STREAM_SCHEMA,
|
|
28254
28260
|
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
|
|
28261
|
+
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
28262
|
},
|
|
28257
28263
|
run: async (cmd) => {
|
|
28258
28264
|
const opts = cmd.opts();
|
|
@@ -28642,7 +28648,7 @@ var ChatBroker = class {
|
|
|
28642
28648
|
);
|
|
28643
28649
|
}
|
|
28644
28650
|
this.cred = cred;
|
|
28645
|
-
this.os = this.opts.os ?? this.cfg.defaultChatOs ??
|
|
28651
|
+
this.os = this.opts.os ?? this.cfg.defaultChatOs ?? DEFAULT_CHAT_OS;
|
|
28646
28652
|
this.startedAt = Date.now();
|
|
28647
28653
|
ensureRuntimeDir(this.paths);
|
|
28648
28654
|
writePid(this.paths, process.pid);
|
|
@@ -29220,7 +29226,7 @@ function register30(program3) {
|
|
|
29220
29226
|
description: "Start the personal-account daemon in the foreground. Holds the chat socket for ordinary commands and writes raw daemon events.",
|
|
29221
29227
|
output: StartOutput,
|
|
29222
29228
|
configure: (cmd) => {
|
|
29223
|
-
cmd.option("--os <os>", "chat-channel
|
|
29229
|
+
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
29230
|
},
|
|
29225
29231
|
run: async (cmd) => {
|
|
29226
29232
|
const opts = cmd.opts();
|
|
@@ -33500,7 +33506,7 @@ return the JSON envelope and let the daemon send.
|
|
|
33500
33506
|
Every TCP verb above rides the assistant daemon's existing socket \u2014 no
|
|
33501
33507
|
slot taken, no device kicked. This exception applies only inside
|
|
33502
33508
|
assistant backend turns. Ordinary Codex/MUC skills use personal daemon
|
|
33503
|
-
routing (\`muc daemon-start\`) and must follow
|
|
33509
|
+
routing (\`muc daemon-start\`) and must follow the non-blocking iPad notice rules.
|
|
33504
33510
|
|
|
33505
33511
|
## Attachments and quotes
|
|
33506
33512
|
|
|
@@ -33957,7 +33963,7 @@ var AssistantDaemon = class {
|
|
|
33957
33963
|
if (!usingAssistantProfile) {
|
|
33958
33964
|
await assertNoPersonalDaemonConflict(this.cred.uid);
|
|
33959
33965
|
}
|
|
33960
|
-
this.os = this.opts.os ?? this.cfg.defaultChatOs ??
|
|
33966
|
+
this.os = this.opts.os ?? this.cfg.defaultChatOs ?? DEFAULT_CHAT_OS;
|
|
33961
33967
|
ensureRuntimeDir2();
|
|
33962
33968
|
writePid2(process.pid);
|
|
33963
33969
|
this.startedAt = Date.now();
|
|
@@ -36040,7 +36046,7 @@ function register32(program3) {
|
|
|
36040
36046
|
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
36047
|
output: StartOutput2,
|
|
36042
36048
|
configure: (cmd) => {
|
|
36043
|
-
cmd.option("--os <os>", "chat-channel
|
|
36049
|
+
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
36050
|
},
|
|
36045
36051
|
run: async (cmd) => {
|
|
36046
36052
|
const opts = cmd.opts();
|