@profullstack/qryptchat 0.4.7 → 0.5.1

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.
@@ -727,6 +727,20 @@ class QcClient {
727
727
  return "unknown";
728
728
  }
729
729
  }
730
+ async profile() {
731
+ const { user } = await this.request(`/api/users/by-username/${encodeURIComponent(this.me?.username ?? "")}`);
732
+ return user;
733
+ }
734
+ async updateProfile(fields) {
735
+ const { user } = await this.request("/api/profile/update", { method: "POST", body: fields });
736
+ return user;
737
+ }
738
+ async openProfile() {
739
+ const res = await this.fetch(`${this.base}/u/${encodeURIComponent(this.me?.username ?? "")}/openprofile.md`);
740
+ if (!res.ok)
741
+ throw new QcError(`HTTP ${res.status}`, res.status);
742
+ return res.text();
743
+ }
730
744
  async conversations() {
731
745
  const { conversations = [] } = await this.request("/api/conversations/load", { method: "POST", body: {} });
732
746
  return conversations.map((c) => ({ ...c, title: conversationTitle(c, this.me) }));
@@ -751,6 +765,8 @@ class QcClient {
751
765
  conversationId: m.conversation_id,
752
766
  senderId: m.sender_id,
753
767
  sender: m.sender?.display_name || m.sender?.username || "unknown",
768
+ emoji: m.sender?.emoji || "",
769
+ pronouns: m.sender?.pronouns || "",
754
770
  username: m.sender?.username || "",
755
771
  mine: m.sender_id === this.me?.id,
756
772
  text: m.content,
@@ -1082,6 +1098,9 @@ Usage:
1082
1098
  qc login [--oob] sign in through your browser; --oob to paste a code (SSH)
1083
1099
  qc logout forget this terminal's session and keys
1084
1100
  qc whoami who this terminal is signed in as
1101
+ qc profile [--emoji \uD83D\uDD2D] [--pronouns she/her] [--website URL] [--bio TEXT]
1102
+ show or set your public profile (an empty value clears it);
1103
+ --openprofile prints it as OpenProfile.md
1085
1104
  qc chats list your chats
1086
1105
  qc read <chat> [-n 20] print the last messages of a chat
1087
1106
  qc send <chat> <text> send a message (text "-" reads stdin; --reply <message-id> to reply)
@@ -1094,7 +1113,8 @@ Keys and tokens are sealed (ChaCha20-Poly1305) in ${"$"}QC_HOME or ~/.config/qc;
1094
1113
  OS keychain, or comes from a passphrase (QC_PASSPHRASE for scripts and qc mcp).
1095
1114
  HD: emoji and icons are drawn as our OpenEmoji/OpenIcon images in Kitty, Ghostty, WezTerm and iTerm2.
1096
1115
  Over SSH or in tmux (set -g allow-passthrough on) say which: QC_HD=1 (Kitty/Ghostty) or
1097
- QC_HD=wezterm (WezTerm/iTerm2). QC_HD=0 turns it off.`;
1116
+ QC_HD=wezterm (WezTerm/iTerm2). QC_HD=0 turns it off. Mosh carries only text, so behind mosh
1117
+ emoji stay characters: for images use ssh or WezTerm's multiplexer (wezterm connect).`;
1098
1118
  function parseArgs2(argv) {
1099
1119
  const args = { _: [], flags: {} };
1100
1120
  for (let i = 0;i < argv.length; i++) {
@@ -1107,7 +1127,7 @@ function parseArgs2(argv) {
1107
1127
  const [k, v] = a.slice(2).split("=", 2);
1108
1128
  if (v !== undefined)
1109
1129
  args.flags[k] = v;
1110
- else if (["url", "n", "limit", "reply"].includes(k) && argv[i + 1] !== undefined)
1130
+ else if (["url", "n", "limit", "reply", "emoji", "pronouns", "website", "bio"].includes(k) && argv[i + 1] !== undefined && !argv[i + 1].startsWith("--"))
1111
1131
  args.flags[k] = argv[++i];
1112
1132
  else
1113
1133
  args.flags[k] = true;
@@ -1193,6 +1213,27 @@ async function main2(argv, { version = "0.0.0" } = {}) {
1193
1213
  throw new Error("Not signed in. Run qc login.");
1194
1214
  return flags.json ? json({ user: session.user, base: session.base }) : out(`@${session.user?.username} (${session.user?.display_name ?? ""}) on ${session.base}`);
1195
1215
  }
1216
+ case "profile": {
1217
+ const c = await client(flags);
1218
+ if (flags.openprofile)
1219
+ return out((await c.openProfile()).trimEnd());
1220
+ const fields = {};
1221
+ for (const k of ["emoji", "pronouns", "website", "bio"])
1222
+ if (flags[k] !== undefined)
1223
+ fields[k] = flags[k] === true ? "" : String(flags[k]);
1224
+ const p = Object.keys(fields).length ? await c.updateProfile(fields) : await c.profile();
1225
+ if (flags.json)
1226
+ return json({ username: p.username, emoji: p.emoji ?? null, pronouns: p.pronouns ?? null, website: p.website ?? null, bio: p.bio ?? null });
1227
+ out(`${p.emoji ? `${p.emoji} ` : ""}${p.displayName ?? p.display_name ?? p.username} @${p.username}${p.pronouns ? ` (${p.pronouns})` : ""}`);
1228
+ if (p.website)
1229
+ out(p.website);
1230
+ if (p.bio)
1231
+ out(p.bio);
1232
+ if (!Object.keys(fields).length)
1233
+ out(`
1234
+ Set: qc profile --emoji \uD83D\uDD2D --pronouns she/her --website https://you.example (an empty value clears)`);
1235
+ return;
1236
+ }
1196
1237
  case "chats":
1197
1238
  case "ls": {
1198
1239
  const chats = await (await client(flags)).conversations();
package/dist/commands.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  parseArgs2,
4
4
  findChat2,
5
5
  main2
6
- } from "./chunk-8rzydycp.js";
6
+ } from "./chunk-byfvkvkr.js";
7
7
  import"./chunk-vfahhydf.js";
8
8
  export {
9
9
  HELP2 as HELP,
package/dist/mcp.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import"./chunk-vfahhydf.js";
2
2
  import {
3
3
  findChat2
4
- } from "./chunk-8rzydycp.js";
4
+ } from "./chunk-byfvkvkr.js";
5
5
 
6
6
  // src/cli/mcp.js
7
7
  import { createInterface } from "node:readline";
package/dist/tui.js CHANGED
@@ -56,7 +56,8 @@ function transcriptLines(messages, width, theme) {
56
56
  if (!sameRun) {
57
57
  lines.push({
58
58
  spans: [
59
- { text: m.mine ? "you" : m.sender, fg: m.mine ? theme.primary : nameColor(theme, m.senderId || m.sender), bold: true },
59
+ { text: `${m.emoji ? `${m.emoji} ` : ""}${m.mine ? "you" : m.sender}`, fg: m.mine ? theme.primary : nameColor(theme, m.senderId || m.sender), bold: true },
60
+ ...m.pronouns && !m.mine ? [{ text: ` ${m.pronouns}`, fg: theme.muted }] : [],
60
61
  { text: ` ${timeOf(m.at)}`, fg: theme.muted }
61
62
  ]
62
63
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@profullstack/qryptchat",
3
- "version": "0.4.7",
3
+ "version": "0.5.1",
4
4
  "description": "qc: qrypt.chat in your terminal. A full-screen end-to-end encrypted chat client (ML-KEM-1024), plus a scriptable CLI and an MCP server.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -18,7 +18,7 @@
18
18
  "dependencies": {
19
19
  "@noble/ciphers": "^2.0.0",
20
20
  "@profullstack/encrypt": "^0.1.0",
21
- "@profullstack/hqtui": "^0.10.1",
21
+ "@profullstack/hqtui": "^0.10.2",
22
22
  "mlkem": "^2.5.0"
23
23
  },
24
24
  "keywords": [