@mu-cabin/muc-cli 0.5.2 → 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 +12 -13
- package/REFERENCE.md +779 -0
- package/dist/muc.mjs +302 -47
- package/package.json +2 -1
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();
|
|
@@ -27506,6 +27510,254 @@ function register23(program3) {
|
|
|
27506
27510
|
});
|
|
27507
27511
|
}
|
|
27508
27512
|
|
|
27513
|
+
// src/lib/sticky.ts
|
|
27514
|
+
var STICKY_CACHE_KEY = "sticky_on_top_id";
|
|
27515
|
+
function stickyCacheFrom() {
|
|
27516
|
+
return process.platform === "win32" ? "WIN" : "MAC";
|
|
27517
|
+
}
|
|
27518
|
+
var STICKY_LIST_PROBE_SID = "__muc_cli_sticky_list_probe__";
|
|
27519
|
+
function buildStickyCacheFieldData(args) {
|
|
27520
|
+
return {
|
|
27521
|
+
from: args.from ?? stickyCacheFrom(),
|
|
27522
|
+
key: [STICKY_CACHE_KEY],
|
|
27523
|
+
subkey: null,
|
|
27524
|
+
value: [args.sId],
|
|
27525
|
+
op: args.op
|
|
27526
|
+
};
|
|
27527
|
+
}
|
|
27528
|
+
function extractStickyIds(frame) {
|
|
27529
|
+
if (!frame || typeof frame !== "object") return [];
|
|
27530
|
+
const f = frame;
|
|
27531
|
+
if (f.err) return [];
|
|
27532
|
+
const candidates = [f.respond, f.data, f];
|
|
27533
|
+
for (const c of candidates) {
|
|
27534
|
+
if (!c || typeof c !== "object" || Array.isArray(c)) continue;
|
|
27535
|
+
const ids = c.sticky_on_top_id;
|
|
27536
|
+
if (Array.isArray(ids)) {
|
|
27537
|
+
return ids.map((x) => String(x)).filter((s) => s && s !== STICKY_LIST_PROBE_SID);
|
|
27538
|
+
}
|
|
27539
|
+
}
|
|
27540
|
+
return [];
|
|
27541
|
+
}
|
|
27542
|
+
function classifySid(sId, selfUid) {
|
|
27543
|
+
if (!sId) return { kind: "unknown" };
|
|
27544
|
+
if (sId.includes("|")) {
|
|
27545
|
+
const parts = sId.split("|");
|
|
27546
|
+
if (parts.length === 2) {
|
|
27547
|
+
const self2 = selfUid.toUpperCase();
|
|
27548
|
+
const a = parts[0].toUpperCase();
|
|
27549
|
+
const b = parts[1].toUpperCase();
|
|
27550
|
+
if (a === self2 && b === self2) return { kind: "self" };
|
|
27551
|
+
const peer = a === self2 ? parts[1] : b === self2 ? parts[0] : parts[1];
|
|
27552
|
+
return { kind: "p2p", peer };
|
|
27553
|
+
}
|
|
27554
|
+
}
|
|
27555
|
+
if (/^\d{10,}$/.test(sId)) return { kind: "team", team_id: sId };
|
|
27556
|
+
return { kind: "unknown" };
|
|
27557
|
+
}
|
|
27558
|
+
function stickySessionRows(ids, selfUid) {
|
|
27559
|
+
return ids.map((sId) => ({ sId, ...classifySid(sId, selfUid) }));
|
|
27560
|
+
}
|
|
27561
|
+
|
|
27562
|
+
// src/commands/pin.ts
|
|
27563
|
+
var SessionRow = external_exports.object({
|
|
27564
|
+
sId: external_exports.string(),
|
|
27565
|
+
kind: external_exports.enum(["team", "p2p", "self", "unknown"]),
|
|
27566
|
+
peer: external_exports.string().optional(),
|
|
27567
|
+
team_id: external_exports.string().optional()
|
|
27568
|
+
});
|
|
27569
|
+
var MutateOutput = external_exports.object({
|
|
27570
|
+
action: external_exports.enum(["pin", "unpin"]),
|
|
27571
|
+
scene: external_exports.enum(["p2p", "team_g"]),
|
|
27572
|
+
toId: external_exports.string(),
|
|
27573
|
+
sId: external_exports.string(),
|
|
27574
|
+
dryRun: external_exports.boolean(),
|
|
27575
|
+
sticky_ids: external_exports.array(external_exports.string()),
|
|
27576
|
+
sessions: external_exports.array(SessionRow),
|
|
27577
|
+
frame: external_exports.unknown().optional(),
|
|
27578
|
+
raw: external_exports.unknown().optional(),
|
|
27579
|
+
route: external_exports.enum(["daemon", "direct"]).optional(),
|
|
27580
|
+
daemon_kind: external_exports.literal("personal").optional()
|
|
27581
|
+
});
|
|
27582
|
+
var ListOutput = external_exports.object({
|
|
27583
|
+
sticky_ids: external_exports.array(external_exports.string()),
|
|
27584
|
+
sessions: external_exports.array(SessionRow),
|
|
27585
|
+
count: external_exports.number(),
|
|
27586
|
+
dryRun: external_exports.boolean().optional(),
|
|
27587
|
+
frame: external_exports.unknown().optional(),
|
|
27588
|
+
raw: external_exports.unknown().optional(),
|
|
27589
|
+
route: external_exports.enum(["daemon", "direct"]).optional(),
|
|
27590
|
+
daemon_kind: external_exports.literal("personal").optional()
|
|
27591
|
+
});
|
|
27592
|
+
function resolveTarget(opts, selfUid, label) {
|
|
27593
|
+
requireSingleTarget(
|
|
27594
|
+
{ peer: opts.peer, team: opts.team, sid: opts.sid, toSelf: opts.toSelf },
|
|
27595
|
+
label
|
|
27596
|
+
);
|
|
27597
|
+
if (opts.sid) {
|
|
27598
|
+
const sId2 = opts.sid;
|
|
27599
|
+
if (sId2.includes("|")) {
|
|
27600
|
+
return { scene: "p2p", toId: selfUid, sId: sId2 };
|
|
27601
|
+
}
|
|
27602
|
+
return { scene: "team_g", toId: sId2, sId: sId2 };
|
|
27603
|
+
}
|
|
27604
|
+
let scene;
|
|
27605
|
+
let toId;
|
|
27606
|
+
if (opts.team) {
|
|
27607
|
+
scene = "team_g";
|
|
27608
|
+
toId = opts.team;
|
|
27609
|
+
} else if (opts.toSelf || !opts.peer && !opts.team) {
|
|
27610
|
+
scene = "p2p";
|
|
27611
|
+
toId = selfUid;
|
|
27612
|
+
} else {
|
|
27613
|
+
scene = "p2p";
|
|
27614
|
+
toId = opts.peer.toUpperCase();
|
|
27615
|
+
}
|
|
27616
|
+
const sId = buildSId(scene, selfUid, toId);
|
|
27617
|
+
return { scene, toId, sId };
|
|
27618
|
+
}
|
|
27619
|
+
async function tcpUserSetCacheField(args) {
|
|
27620
|
+
const { data, debug, daemon, cmd, credUid } = args;
|
|
27621
|
+
let os = args.os;
|
|
27622
|
+
const daemonDisabled = daemonRoutingDisabled({ daemon });
|
|
27623
|
+
if (daemonDisabled) await assertNoAssistantSlotConflict(credUid);
|
|
27624
|
+
const daemonRoute = daemonDisabled ? null : await probeDaemonRoute(credUid);
|
|
27625
|
+
if (daemonRoute) {
|
|
27626
|
+
os = assertNoSlotConflict({
|
|
27627
|
+
route: daemonRoute,
|
|
27628
|
+
userOs: args.optsOs ?? os,
|
|
27629
|
+
userExplicit: userExplicitOs(cmd)
|
|
27630
|
+
});
|
|
27631
|
+
const res = await tcpSendViaDaemon({ sid: "user", cid: "setCacheField", data });
|
|
27632
|
+
return { res, route: "daemon", daemon_kind: "personal", os };
|
|
27633
|
+
}
|
|
27634
|
+
const cred = requireAuth(loadCredentials());
|
|
27635
|
+
const session = await openChatSession(cred, { os, debug });
|
|
27636
|
+
try {
|
|
27637
|
+
const res = await session.socket.send("user", "setCacheField", data);
|
|
27638
|
+
return { res, route: "direct", os };
|
|
27639
|
+
} finally {
|
|
27640
|
+
session.socket.close();
|
|
27641
|
+
}
|
|
27642
|
+
}
|
|
27643
|
+
function registerPin(program3) {
|
|
27644
|
+
define2(program3, {
|
|
27645
|
+
name: "pin",
|
|
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.",
|
|
27647
|
+
output: MutateOutput,
|
|
27648
|
+
configure: (cmd) => {
|
|
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");
|
|
27650
|
+
},
|
|
27651
|
+
run: async (cmd) => mutateSticky(cmd, "pin")
|
|
27652
|
+
});
|
|
27653
|
+
}
|
|
27654
|
+
function registerUnpin(program3) {
|
|
27655
|
+
define2(program3, {
|
|
27656
|
+
name: "unpin",
|
|
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.",
|
|
27658
|
+
output: MutateOutput,
|
|
27659
|
+
configure: (cmd) => {
|
|
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");
|
|
27661
|
+
},
|
|
27662
|
+
run: async (cmd) => mutateSticky(cmd, "unpin")
|
|
27663
|
+
});
|
|
27664
|
+
}
|
|
27665
|
+
async function mutateSticky(cmd, action) {
|
|
27666
|
+
const opts = cmd.opts();
|
|
27667
|
+
const cfg = requireConfig();
|
|
27668
|
+
const cred = requireAuth(loadCredentials());
|
|
27669
|
+
const os = resolveChatOs(opts.os, cfg);
|
|
27670
|
+
const { scene, toId, sId } = resolveTarget(opts, cred.uid, action);
|
|
27671
|
+
const op = action === "pin" ? 1 : 2;
|
|
27672
|
+
const data = buildStickyCacheFieldData({ sId, op });
|
|
27673
|
+
const frame = { sid: "user", cid: "setCacheField", data };
|
|
27674
|
+
if (opts.dryRun) {
|
|
27675
|
+
return {
|
|
27676
|
+
action,
|
|
27677
|
+
scene,
|
|
27678
|
+
toId,
|
|
27679
|
+
sId,
|
|
27680
|
+
dryRun: true,
|
|
27681
|
+
sticky_ids: [],
|
|
27682
|
+
sessions: [],
|
|
27683
|
+
frame
|
|
27684
|
+
};
|
|
27685
|
+
}
|
|
27686
|
+
const { res, route: route2, daemon_kind } = await tcpUserSetCacheField({
|
|
27687
|
+
data,
|
|
27688
|
+
os,
|
|
27689
|
+
optsOs: opts.os,
|
|
27690
|
+
debug: opts.debug,
|
|
27691
|
+
daemon: opts.daemon,
|
|
27692
|
+
cmd,
|
|
27693
|
+
credUid: cred.uid
|
|
27694
|
+
});
|
|
27695
|
+
if (res?.err) {
|
|
27696
|
+
throw new CliError("REMOTE_ERROR", `${action} rejected: ${JSON.stringify(res).slice(0, 400)}`);
|
|
27697
|
+
}
|
|
27698
|
+
const sticky_ids = extractStickyIds(res);
|
|
27699
|
+
return {
|
|
27700
|
+
action,
|
|
27701
|
+
scene,
|
|
27702
|
+
toId,
|
|
27703
|
+
sId,
|
|
27704
|
+
dryRun: false,
|
|
27705
|
+
sticky_ids,
|
|
27706
|
+
sessions: stickySessionRows(sticky_ids, cred.uid),
|
|
27707
|
+
raw: res,
|
|
27708
|
+
route: route2,
|
|
27709
|
+
daemon_kind
|
|
27710
|
+
};
|
|
27711
|
+
}
|
|
27712
|
+
function registerPinned(program3) {
|
|
27713
|
+
define2(program3, {
|
|
27714
|
+
name: "pinned",
|
|
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.",
|
|
27716
|
+
output: ListOutput,
|
|
27717
|
+
configure: (cmd) => {
|
|
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");
|
|
27719
|
+
},
|
|
27720
|
+
run: async (cmd) => {
|
|
27721
|
+
const opts = cmd.opts();
|
|
27722
|
+
const cfg = requireConfig();
|
|
27723
|
+
const cred = requireAuth(loadCredentials());
|
|
27724
|
+
const os = resolveChatOs(opts.os, cfg);
|
|
27725
|
+
const data = buildStickyCacheFieldData({ sId: STICKY_LIST_PROBE_SID, op: 2 });
|
|
27726
|
+
const frame = { sid: "user", cid: "setCacheField", data };
|
|
27727
|
+
if (opts.dryRun) {
|
|
27728
|
+
return { sticky_ids: [], sessions: [], count: 0, dryRun: true, frame };
|
|
27729
|
+
}
|
|
27730
|
+
const { res, route: route2, daemon_kind } = await tcpUserSetCacheField({
|
|
27731
|
+
data,
|
|
27732
|
+
os,
|
|
27733
|
+
optsOs: opts.os,
|
|
27734
|
+
debug: opts.debug,
|
|
27735
|
+
daemon: opts.daemon,
|
|
27736
|
+
cmd,
|
|
27737
|
+
credUid: cred.uid
|
|
27738
|
+
});
|
|
27739
|
+
if (res?.err) {
|
|
27740
|
+
throw new CliError("REMOTE_ERROR", `pinned list rejected: ${JSON.stringify(res).slice(0, 400)}`);
|
|
27741
|
+
}
|
|
27742
|
+
const sticky_ids = extractStickyIds(res);
|
|
27743
|
+
return {
|
|
27744
|
+
sticky_ids,
|
|
27745
|
+
sessions: stickySessionRows(sticky_ids, cred.uid),
|
|
27746
|
+
count: sticky_ids.length,
|
|
27747
|
+
dryRun: false,
|
|
27748
|
+
raw: res,
|
|
27749
|
+
route: route2,
|
|
27750
|
+
daemon_kind
|
|
27751
|
+
};
|
|
27752
|
+
}
|
|
27753
|
+
});
|
|
27754
|
+
}
|
|
27755
|
+
function register24(program3) {
|
|
27756
|
+
registerPin(program3);
|
|
27757
|
+
registerUnpin(program3);
|
|
27758
|
+
registerPinned(program3);
|
|
27759
|
+
}
|
|
27760
|
+
|
|
27509
27761
|
// src/lib/reactions.ts
|
|
27510
27762
|
async function saveReply(cfg, args) {
|
|
27511
27763
|
const { ctx, stickerId, senderName, isFromMe, selfAppKey } = args;
|
|
@@ -27572,7 +27824,7 @@ var Output24 = external_exports.object({
|
|
|
27572
27824
|
emoticonId: external_exports.string().optional(),
|
|
27573
27825
|
raw: external_exports.unknown()
|
|
27574
27826
|
});
|
|
27575
|
-
function
|
|
27827
|
+
function register25(program3) {
|
|
27576
27828
|
define2(program3, {
|
|
27577
27829
|
name: "react",
|
|
27578
27830
|
description: "Add a default reaction emoji to a message (POST emoticon/reply/save). VISIBLE TO THE TARGET CHAT \u2014 non-self targets require --yes-not-self.",
|
|
@@ -27669,7 +27921,7 @@ var Output25 = external_exports.object({
|
|
|
27669
27921
|
reactions: external_exports.array(external_exports.unknown()),
|
|
27670
27922
|
raw: external_exports.unknown()
|
|
27671
27923
|
});
|
|
27672
|
-
function
|
|
27924
|
+
function register26(program3) {
|
|
27673
27925
|
define2(program3, {
|
|
27674
27926
|
name: "reactions",
|
|
27675
27927
|
description: "List default emoji reactions on a message (GET emoticon/reply/list?mid=\u2026).",
|
|
@@ -27712,7 +27964,7 @@ var Output26 = external_exports.object({
|
|
|
27712
27964
|
emoticonId: external_exports.string(),
|
|
27713
27965
|
raw: external_exports.unknown()
|
|
27714
27966
|
});
|
|
27715
|
-
function
|
|
27967
|
+
function register27(program3) {
|
|
27716
27968
|
define2(program3, {
|
|
27717
27969
|
name: "unreact",
|
|
27718
27970
|
description: "Revoke one of your default emoji reactions (POST emoticon/reply/revocation). VISIBLE TO THE TARGET CHAT \u2014 non-self targets require --yes-not-self.",
|
|
@@ -27785,13 +28037,13 @@ var Output27 = external_exports.object({
|
|
|
27785
28037
|
route: external_exports.enum(["daemon", "direct"]).optional(),
|
|
27786
28038
|
daemon_kind: external_exports.literal("personal").optional()
|
|
27787
28039
|
});
|
|
27788
|
-
function
|
|
28040
|
+
function register28(program3) {
|
|
27789
28041
|
define2(program3, {
|
|
27790
28042
|
name: "wait-react",
|
|
27791
|
-
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.",
|
|
27792
28044
|
output: Output27,
|
|
27793
28045
|
configure: (cmd) => {
|
|
27794
|
-
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");
|
|
27795
28047
|
},
|
|
27796
28048
|
run: async (cmd) => {
|
|
27797
28049
|
const opts = cmd.opts();
|
|
@@ -27998,13 +28250,13 @@ var STREAM_SCHEMA = {
|
|
|
27998
28250
|
}
|
|
27999
28251
|
]
|
|
28000
28252
|
};
|
|
28001
|
-
function
|
|
28253
|
+
function register29(program3) {
|
|
28002
28254
|
defineStream(program3, {
|
|
28003
28255
|
name: "listen",
|
|
28004
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.",
|
|
28005
28257
|
streamSchema: STREAM_SCHEMA,
|
|
28006
28258
|
configure: (cmd) => {
|
|
28007
|
-
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");
|
|
28008
28260
|
},
|
|
28009
28261
|
run: async (cmd) => {
|
|
28010
28262
|
const opts = cmd.opts();
|
|
@@ -28394,7 +28646,7 @@ var ChatBroker = class {
|
|
|
28394
28646
|
);
|
|
28395
28647
|
}
|
|
28396
28648
|
this.cred = cred;
|
|
28397
|
-
this.os = this.opts.os ?? this.cfg.defaultChatOs ??
|
|
28649
|
+
this.os = this.opts.os ?? this.cfg.defaultChatOs ?? DEFAULT_CHAT_OS;
|
|
28398
28650
|
this.startedAt = Date.now();
|
|
28399
28651
|
ensureRuntimeDir(this.paths);
|
|
28400
28652
|
writePid(this.paths, process.pid);
|
|
@@ -28773,13 +29025,14 @@ var ALLOWED_TCP_CALLS = /* @__PURE__ */ new Set([
|
|
|
28773
29025
|
"team/search_own_teams",
|
|
28774
29026
|
"team/get_team",
|
|
28775
29027
|
"team/get_team_members",
|
|
28776
|
-
"user/delSession"
|
|
29028
|
+
"user/delSession",
|
|
29029
|
+
"user/setCacheField"
|
|
28777
29030
|
]);
|
|
28778
29031
|
function isAllowedTcpCall(sid, cid) {
|
|
28779
29032
|
return ALLOWED_TCP_CALLS.has(`${sid}/${cid}`);
|
|
28780
29033
|
}
|
|
28781
29034
|
function shouldAuditTcpCall(sid, cid) {
|
|
28782
|
-
return sid === "talk" && cid === "sendMsg" || sid === "user" && cid === "delSession";
|
|
29035
|
+
return sid === "talk" && cid === "sendMsg" || sid === "user" && (cid === "delSession" || cid === "setCacheField");
|
|
28783
29036
|
}
|
|
28784
29037
|
function readState(paths2) {
|
|
28785
29038
|
if (!existsSync10(paths2.state)) return null;
|
|
@@ -28965,13 +29218,13 @@ var STREAM_SCHEMA2 = {
|
|
|
28965
29218
|
}
|
|
28966
29219
|
]
|
|
28967
29220
|
};
|
|
28968
|
-
function
|
|
29221
|
+
function register30(program3) {
|
|
28969
29222
|
define2(program3, {
|
|
28970
29223
|
name: "daemon-start",
|
|
28971
29224
|
description: "Start the personal-account daemon in the foreground. Holds the chat socket for ordinary commands and writes raw daemon events.",
|
|
28972
29225
|
output: StartOutput,
|
|
28973
29226
|
configure: (cmd) => {
|
|
28974
|
-
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");
|
|
28975
29228
|
},
|
|
28976
29229
|
run: async (cmd) => {
|
|
28977
29230
|
const opts = cmd.opts();
|
|
@@ -31040,7 +31293,7 @@ var KNOWN_CLAUDE_MODELS = /* @__PURE__ */ new Set([
|
|
|
31040
31293
|
"claude-haiku-4-5",
|
|
31041
31294
|
"claude-haiku-4-5-20251001"
|
|
31042
31295
|
]);
|
|
31043
|
-
var
|
|
31296
|
+
var ListOutput2 = external_exports.object({
|
|
31044
31297
|
count: external_exports.number(),
|
|
31045
31298
|
assistants: external_exports.array(external_exports.object({
|
|
31046
31299
|
name: external_exports.string(),
|
|
@@ -31086,7 +31339,7 @@ var LogOutput = external_exports.object({
|
|
|
31086
31339
|
since_ms: external_exports.number(),
|
|
31087
31340
|
rows: external_exports.array(LogRowSchema)
|
|
31088
31341
|
});
|
|
31089
|
-
function
|
|
31342
|
+
function register31(program3) {
|
|
31090
31343
|
define2(program3, {
|
|
31091
31344
|
name: "assistant-new",
|
|
31092
31345
|
description: "Create a new assistant scaffold under ~/.muc/assistants/<name>/. Edit the system-prompt.md afterwards.",
|
|
@@ -31187,7 +31440,7 @@ function register30(program3) {
|
|
|
31187
31440
|
define2(program3, {
|
|
31188
31441
|
name: "assistant-list",
|
|
31189
31442
|
description: "List registered assistants and which are currently attached to the daemon.",
|
|
31190
|
-
output:
|
|
31443
|
+
output: ListOutput2,
|
|
31191
31444
|
run: async () => {
|
|
31192
31445
|
const all = listAssistants();
|
|
31193
31446
|
const active = await fetchActiveSet();
|
|
@@ -33251,7 +33504,7 @@ return the JSON envelope and let the daemon send.
|
|
|
33251
33504
|
Every TCP verb above rides the assistant daemon's existing socket \u2014 no
|
|
33252
33505
|
slot taken, no device kicked. This exception applies only inside
|
|
33253
33506
|
assistant backend turns. Ordinary Codex/MUC skills use personal daemon
|
|
33254
|
-
routing (\`muc daemon-start\`) and must follow
|
|
33507
|
+
routing (\`muc daemon-start\`) and must follow the non-blocking iPad notice rules.
|
|
33255
33508
|
|
|
33256
33509
|
## Attachments and quotes
|
|
33257
33510
|
|
|
@@ -33708,7 +33961,7 @@ var AssistantDaemon = class {
|
|
|
33708
33961
|
if (!usingAssistantProfile) {
|
|
33709
33962
|
await assertNoPersonalDaemonConflict(this.cred.uid);
|
|
33710
33963
|
}
|
|
33711
|
-
this.os = this.opts.os ?? this.cfg.defaultChatOs ??
|
|
33964
|
+
this.os = this.opts.os ?? this.cfg.defaultChatOs ?? DEFAULT_CHAT_OS;
|
|
33712
33965
|
ensureRuntimeDir2();
|
|
33713
33966
|
writePid2(process.pid);
|
|
33714
33967
|
this.startedAt = Date.now();
|
|
@@ -35305,7 +35558,8 @@ var ALLOWED_TCP_CALLS2 = /* @__PURE__ */ new Set([
|
|
|
35305
35558
|
"team/search_own_teams",
|
|
35306
35559
|
"team/get_team",
|
|
35307
35560
|
"team/get_team_members",
|
|
35308
|
-
"user/delSession"
|
|
35561
|
+
"user/delSession",
|
|
35562
|
+
"user/setCacheField"
|
|
35309
35563
|
]);
|
|
35310
35564
|
function isAllowedTcpCall2(sid, cid) {
|
|
35311
35565
|
return ALLOWED_TCP_CALLS2.has(`${sid}/${cid}`);
|
|
@@ -35784,13 +36038,13 @@ var StatusOutput2 = external_exports.object({
|
|
|
35784
36038
|
});
|
|
35785
36039
|
var StopOutput2 = external_exports.object({ stopped: external_exports.boolean(), pid: external_exports.number().optional() });
|
|
35786
36040
|
var ResumeOutput = external_exports.object({ resumed: external_exports.boolean() });
|
|
35787
|
-
function
|
|
36041
|
+
function register32(program3) {
|
|
35788
36042
|
define2(program3, {
|
|
35789
36043
|
name: "assistantd-start",
|
|
35790
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.",
|
|
35791
36045
|
output: StartOutput2,
|
|
35792
36046
|
configure: (cmd) => {
|
|
35793
|
-
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");
|
|
35794
36048
|
},
|
|
35795
36049
|
run: async (cmd) => {
|
|
35796
36050
|
const opts = cmd.opts();
|
|
@@ -36865,7 +37119,7 @@ var StartOutput3 = external_exports.object({
|
|
|
36865
37119
|
// honest while leaving the long-running HTTP server in the background.
|
|
36866
37120
|
closed: external_exports.boolean()
|
|
36867
37121
|
});
|
|
36868
|
-
function
|
|
37122
|
+
function register33(program3) {
|
|
36869
37123
|
define2(program3, {
|
|
36870
37124
|
name: "assistant-ui",
|
|
36871
37125
|
description: "Start a local HTTP server (default 127.0.0.1:7821) that serves a read-only monitor for the running assistant daemon. Foreground; Ctrl-C to stop.",
|
|
@@ -37241,7 +37495,7 @@ var Output28 = external_exports.object({
|
|
|
37241
37495
|
output_schema: external_exports.unknown()
|
|
37242
37496
|
}))
|
|
37243
37497
|
});
|
|
37244
|
-
function
|
|
37498
|
+
function register34(program3) {
|
|
37245
37499
|
define2(program3, {
|
|
37246
37500
|
name: "manifest",
|
|
37247
37501
|
description: "Emit the full command graph + per-command output JSON Schema. Skill authors should consume this rather than parse --help.",
|
|
@@ -37305,6 +37559,7 @@ register30(program2);
|
|
|
37305
37559
|
register31(program2);
|
|
37306
37560
|
register32(program2);
|
|
37307
37561
|
register33(program2);
|
|
37562
|
+
register34(program2);
|
|
37308
37563
|
async function main() {
|
|
37309
37564
|
try {
|
|
37310
37565
|
await program2.parseAsync(argv);
|