@qzhuli/qzhuli-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/dist/cmd.js CHANGED
@@ -12302,37 +12302,46 @@ var import_commander2 = require("commander");
12302
12302
  // src/commands/cache/clear.ts
12303
12303
  init_cjs_shims();
12304
12304
  async function cacheClearRun(factory, opts) {
12305
- if (opts.table) {
12306
- switch (opts.table) {
12307
- case "conversations":
12308
- factory.repos.conversation.clear();
12309
- break;
12310
- case "contacts":
12311
- factory.repos.contact.clear();
12312
- break;
12313
- case "users":
12314
- factory.repos.user.clear();
12315
- break;
12316
- case "relations":
12317
- factory.repos.relation.clear();
12318
- break;
12319
- case "messages":
12320
- factory.repos.message.clear();
12321
- break;
12322
- default:
12323
- return {
12324
- status: "error",
12325
- code: "INVALID_ARGUMENT" /* INVALID_ARGUMENT */,
12326
- message: t("commands.cache.unknownTable").replace("{table}", opts.table),
12327
- data: null
12328
- };
12305
+ try {
12306
+ if (opts.table) {
12307
+ switch (opts.table) {
12308
+ case "conversations":
12309
+ factory.repos.conversation.clear();
12310
+ break;
12311
+ case "contacts":
12312
+ factory.repos.contact.clear();
12313
+ break;
12314
+ case "users":
12315
+ factory.repos.user.clear();
12316
+ break;
12317
+ case "relations":
12318
+ factory.repos.relation.clear();
12319
+ break;
12320
+ case "messages":
12321
+ factory.repos.message.clear();
12322
+ break;
12323
+ default:
12324
+ return {
12325
+ status: "error",
12326
+ code: "INVALID_ARGUMENT" /* INVALID_ARGUMENT */,
12327
+ message: t("commands.cache.unknownTable").replace("{table}", opts.table),
12328
+ data: null
12329
+ };
12330
+ }
12331
+ } else {
12332
+ factory.repos.conversation.clear();
12333
+ factory.repos.contact.clear();
12334
+ factory.repos.user.clear();
12335
+ factory.repos.relation.clear();
12336
+ factory.repos.message.clear();
12329
12337
  }
12330
- } else {
12331
- factory.repos.conversation.clear();
12332
- factory.repos.contact.clear();
12333
- factory.repos.user.clear();
12334
- factory.repos.relation.clear();
12335
- factory.repos.message.clear();
12338
+ } catch (error) {
12339
+ return {
12340
+ status: "error",
12341
+ code: "INTERNAL_ERROR" /* INTERNAL_ERROR */,
12342
+ message: error instanceof Error ? error.message : "Failed to clear cache",
12343
+ data: null
12344
+ };
12336
12345
  }
12337
12346
  return {
12338
12347
  status: "success",
@@ -12345,25 +12354,34 @@ async function cacheClearRun(factory, opts) {
12345
12354
  // src/commands/cache/status.ts
12346
12355
  init_cjs_shims();
12347
12356
  async function cacheStatusRun(factory) {
12348
- const [convStatus, contactStatus] = await Promise.all([
12349
- factory.repos.conversation.getStatus(),
12350
- factory.repos.contact.getStatus()
12351
- ]);
12352
- return {
12353
- status: "success",
12354
- code: "CONFIG_RETRIEVED" /* CONFIG_RETRIEVED */,
12355
- message: "Cache status:",
12356
- data: {
12357
- conversations: {
12358
- count: convStatus.count,
12359
- lastSyncAt: convStatus.lastSyncAt ? new Date(convStatus.lastSyncAt).toISOString() : "never"
12360
- },
12361
- contacts: {
12362
- count: contactStatus.count,
12363
- lastSyncAt: contactStatus.lastSyncAt ? new Date(contactStatus.lastSyncAt).toISOString() : "never"
12357
+ try {
12358
+ const [convStatus, contactStatus] = await Promise.all([
12359
+ factory.repos.conversation.getStatus(),
12360
+ factory.repos.contact.getStatus()
12361
+ ]);
12362
+ return {
12363
+ status: "success",
12364
+ code: "CONFIG_RETRIEVED" /* CONFIG_RETRIEVED */,
12365
+ message: "Cache status:",
12366
+ data: {
12367
+ conversations: {
12368
+ count: convStatus.count,
12369
+ lastSyncAt: convStatus.lastSyncAt ? new Date(convStatus.lastSyncAt).toISOString() : "never"
12370
+ },
12371
+ contacts: {
12372
+ count: contactStatus.count,
12373
+ lastSyncAt: contactStatus.lastSyncAt ? new Date(contactStatus.lastSyncAt).toISOString() : "never"
12374
+ }
12364
12375
  }
12365
- }
12366
- };
12376
+ };
12377
+ } catch (error) {
12378
+ return {
12379
+ status: "error",
12380
+ code: "INTERNAL_ERROR" /* INTERNAL_ERROR */,
12381
+ message: error instanceof Error ? error.message : "Failed to read cache status",
12382
+ data: null
12383
+ };
12384
+ }
12367
12385
  }
12368
12386
 
12369
12387
  // src/commands/cache/sync.ts
@@ -12727,11 +12745,24 @@ async function searchByName(factory, name) {
12727
12745
  const profileResults = await Promise.all(
12728
12746
  conversations3.map((c) => factory.repos.conversation.getProfile(c.id))
12729
12747
  );
12730
- const matchedProfiles = profileResults.filter((r) => r.ok).map((r) => r.data).filter((p) => {
12748
+ const queryLower = name.toLowerCase();
12749
+ const scored = profileResults.filter((r) => r.ok).flatMap((r) => {
12750
+ const p = r.data;
12731
12751
  const convName = p.conversation.name ?? "";
12732
- return convName.includes(name);
12733
- });
12734
- if (matchedProfiles.length === 0) {
12752
+ const teamName = p.conversation.team_name ?? "";
12753
+ const fields = [convName, teamName].filter(Boolean);
12754
+ if (fields.length === 0) return [];
12755
+ let best = 0;
12756
+ for (const f of fields) {
12757
+ const lower = f.toLowerCase();
12758
+ if (lower === queryLower) best = Math.max(best, 3);
12759
+ else if (lower.startsWith(queryLower)) best = Math.max(best, 2);
12760
+ else if (lower.includes(queryLower)) best = Math.max(best, 1);
12761
+ }
12762
+ if (best === 0) return [];
12763
+ return [{ profile: p, score: best }];
12764
+ }).sort((a, b) => b.score - a.score);
12765
+ if (scored.length === 0) {
12735
12766
  return {
12736
12767
  status: "success",
12737
12768
  code: "NOT_FOUND" /* NOT_FOUND */,
@@ -12739,7 +12770,7 @@ async function searchByName(factory, name) {
12739
12770
  data: null
12740
12771
  };
12741
12772
  }
12742
- const items = matchedProfiles.map(profileToItem);
12773
+ const items = scored.map((s) => profileToItem(s.profile));
12743
12774
  const groupedByUid = /* @__PURE__ */ new Map();
12744
12775
  for (const item of items) {
12745
12776
  const primaryUser = item.users[0];
@@ -12757,7 +12788,19 @@ async function searchByName(factory, name) {
12757
12788
  });
12758
12789
  }
12759
12790
  }
12760
- const results = [...groupedByUid.values()];
12791
+ const results = [...groupedByUid.values()].sort((a, b) => {
12792
+ const maxScoreA = Math.max(
12793
+ ...a.conversations.map(
12794
+ (c) => scored.find((s) => s.profile.conversation.conversation_id === c.conversationId)?.score ?? 0
12795
+ )
12796
+ );
12797
+ const maxScoreB = Math.max(
12798
+ ...b.conversations.map(
12799
+ (c) => scored.find((s) => s.profile.conversation.conversation_id === c.conversationId)?.score ?? 0
12800
+ )
12801
+ );
12802
+ return maxScoreB - maxScoreA;
12803
+ });
12761
12804
  if (results.length === 0) {
12762
12805
  return {
12763
12806
  status: "success",
@@ -12846,6 +12889,14 @@ async function friendListRun(factory) {
12846
12889
 
12847
12890
  // src/commands/friend/profile.ts
12848
12891
  init_cjs_shims();
12892
+ function matchScore(text, queryLower) {
12893
+ if (!text) return 0;
12894
+ const lower = text.toLowerCase();
12895
+ if (lower === queryLower) return 3;
12896
+ if (lower.startsWith(queryLower)) return 2;
12897
+ if (lower.includes(queryLower)) return 1;
12898
+ return 0;
12899
+ }
12849
12900
  async function friendProfileRun(factory, opts) {
12850
12901
  const listResult = await factory.repos.contact.getLinksContacts();
12851
12902
  if (!listResult.ok) {
@@ -12886,17 +12937,17 @@ async function friendProfileRun(factory, opts) {
12886
12937
  friend_name: team.name
12887
12938
  }))
12888
12939
  ];
12889
- const query = opts.query.toLowerCase();
12890
- const matches = allEntries.filter((e) => {
12891
- if (opts.byUid) {
12892
- return e.uid?.toLowerCase() === query;
12893
- }
12894
- if (opts.byRemark) {
12895
- return e.friend_name?.toLowerCase() === query;
12896
- }
12897
- return e.nickname?.toLowerCase().includes(query);
12898
- });
12899
- if (matches.length === 0) {
12940
+ const queryLower = opts.query.toLowerCase();
12941
+ let scored;
12942
+ if (opts.byUid) {
12943
+ scored = allEntries.filter((e) => e.uid?.toLowerCase() === queryLower).map((e) => ({ ...e, score: 3 }));
12944
+ } else {
12945
+ scored = allEntries.map((e) => {
12946
+ const field = opts.byRemark ? e.friend_name : e.nickname;
12947
+ return { ...e, score: matchScore(field, queryLower) };
12948
+ }).filter((e) => e.score > 0).sort((a, b) => b.score - a.score);
12949
+ }
12950
+ if (scored.length === 0) {
12900
12951
  return {
12901
12952
  status: "error",
12902
12953
  code: "NOT_FOUND" /* NOT_FOUND */,
@@ -12904,12 +12955,13 @@ async function friendProfileRun(factory, opts) {
12904
12955
  data: null
12905
12956
  };
12906
12957
  }
12907
- if (matches.length > 1) {
12908
- const suggestions = matches.map((m) => ({
12958
+ if (scored.length > 1) {
12959
+ const suggestions = scored.map((m) => ({
12909
12960
  uid: m.uid,
12910
12961
  nickname: m.nickname ?? "",
12911
12962
  remark: m.friend_name ?? "",
12912
- type: m._type
12963
+ type: m._type,
12964
+ score: m.score
12913
12965
  }));
12914
12966
  return {
12915
12967
  status: "needs_resolution",
@@ -12918,12 +12970,12 @@ async function friendProfileRun(factory, opts) {
12918
12970
  data: suggestions
12919
12971
  };
12920
12972
  }
12921
- const match = matches[0];
12973
+ const match = scored[0];
12922
12974
  if (match._type !== "link") {
12923
12975
  return {
12924
12976
  status: "success",
12925
12977
  code: "USER_FOUND" /* USER_FOUND */,
12926
- message: t("messages.found").replace("{name}", match.nickname ?? match.friend_name),
12978
+ message: t("messages.found").replace("{name}", match.nickname ?? match.friend_name ?? ""),
12927
12979
  data: {
12928
12980
  uid: match.uid,
12929
12981
  nickname: match.nickname ?? match.friend_name,
@@ -14335,33 +14387,53 @@ var SqliteContactRepository = class {
14335
14387
  this.db = db;
14336
14388
  }
14337
14389
  async getLinksContacts() {
14338
- const rows = this.db.prepare(
14339
- "SELECT owner_uid, data, cached_at FROM contacts_cache ORDER BY cached_at DESC LIMIT 1"
14340
- ).all();
14341
- if (!rows || rows.length === 0) {
14342
- return fail("NOT_FOUND" /* NOT_FOUND */, "Contacts not found in cache");
14390
+ try {
14391
+ const rows = this.db.prepare(
14392
+ "SELECT owner_uid, data, cached_at FROM contacts_cache ORDER BY cached_at DESC LIMIT 1"
14393
+ ).all();
14394
+ if (!rows || rows.length === 0) {
14395
+ return fail("NOT_FOUND" /* NOT_FOUND */, "Contacts not found in cache");
14396
+ }
14397
+ return ok(JSON.parse(rows[0].data));
14398
+ } catch (error) {
14399
+ return fail(
14400
+ "INTERNAL_ERROR" /* INTERNAL_ERROR */,
14401
+ error instanceof Error ? error.message : "Failed to read contacts from cache"
14402
+ );
14343
14403
  }
14344
- return ok(JSON.parse(rows[0].data));
14345
14404
  }
14346
14405
  upsert(ownerUid, data) {
14347
- this.db.prepare("INSERT INTO contacts_cache (owner_uid, data, cached_at) VALUES (?, ?, ?)").run(ownerUid, JSON.stringify(data), Date.now());
14406
+ try {
14407
+ this.db.prepare("INSERT INTO contacts_cache (owner_uid, data, cached_at) VALUES (?, ?, ?)").run(ownerUid, JSON.stringify(data), Date.now());
14408
+ } catch {
14409
+ }
14348
14410
  }
14349
14411
  invalidate() {
14350
- this.db.exec("DELETE FROM contacts_cache");
14412
+ try {
14413
+ this.db.exec("DELETE FROM contacts_cache");
14414
+ } catch {
14415
+ }
14351
14416
  }
14352
14417
  async sync() {
14353
14418
  }
14354
14419
  clear() {
14355
- this.db.exec("DELETE FROM contacts_cache");
14356
- this.db.exec("DELETE FROM cache_metadata WHERE key = 'last_sync_contacts'");
14420
+ try {
14421
+ this.db.exec("DELETE FROM contacts_cache");
14422
+ this.db.exec("DELETE FROM cache_metadata WHERE key = 'last_sync_contacts'");
14423
+ } catch {
14424
+ }
14357
14425
  }
14358
14426
  async getStatus() {
14359
- const count = this.db.prepare("SELECT COUNT(*) as c FROM contacts_cache").get();
14360
- const meta = this.db.prepare("SELECT value FROM cache_metadata WHERE key = 'last_sync_contacts'").get();
14361
- return {
14362
- count: count.c,
14363
- lastSyncAt: meta ? parseInt(meta.value, 10) : null
14364
- };
14427
+ try {
14428
+ const count = this.db.prepare("SELECT COUNT(*) as c FROM contacts_cache").get();
14429
+ const meta = this.db.prepare("SELECT value FROM cache_metadata WHERE key = 'last_sync_contacts'").get();
14430
+ return {
14431
+ count: count.c,
14432
+ lastSyncAt: meta ? parseInt(meta.value, 10) : null
14433
+ };
14434
+ } catch {
14435
+ return { count: 0, lastSyncAt: null };
14436
+ }
14365
14437
  }
14366
14438
  };
14367
14439
  var CachedContactRepository = class {
@@ -14374,17 +14446,23 @@ var CachedContactRepository = class {
14374
14446
  remote;
14375
14447
  ttlMs;
14376
14448
  async getLinksContacts() {
14377
- const cached = await this.local.getLinksContacts();
14378
- if (cached.ok) {
14379
- const status = await this.local.getStatus();
14380
- if (status.lastSyncAt !== null && Date.now() - status.lastSyncAt < this.ttlMs) {
14381
- return cached;
14449
+ try {
14450
+ const cached = await this.local.getLinksContacts();
14451
+ if (cached.ok) {
14452
+ const status = await this.local.getStatus();
14453
+ if (status.lastSyncAt !== null && Date.now() - status.lastSyncAt < this.ttlMs) {
14454
+ return cached;
14455
+ }
14382
14456
  }
14457
+ } catch {
14383
14458
  }
14384
14459
  const remote = await this.remote.getLinksContacts();
14385
14460
  if (remote.ok) {
14386
- this.local.upsert("", remote.data);
14387
- this.local.db.prepare("INSERT OR REPLACE INTO cache_metadata (key, value) VALUES (?, ?)").run("last_sync_contacts", String(Date.now()));
14461
+ try {
14462
+ this.local.upsert("", remote.data);
14463
+ this.local.db.prepare("INSERT OR REPLACE INTO cache_metadata (key, value) VALUES (?, ?)").run("last_sync_contacts", String(Date.now()));
14464
+ } catch {
14465
+ }
14388
14466
  }
14389
14467
  return remote;
14390
14468
  }
@@ -14394,8 +14472,11 @@ var CachedContactRepository = class {
14394
14472
  async sync() {
14395
14473
  const result = await this.remote.getLinksContacts();
14396
14474
  if (result.ok) {
14397
- this.local.upsert("", result.data);
14398
- this.local.db.prepare("INSERT OR REPLACE INTO cache_metadata (key, value) VALUES (?, ?)").run("last_sync_contacts", String(Date.now()));
14475
+ try {
14476
+ this.local.upsert("", result.data);
14477
+ this.local.db.prepare("INSERT OR REPLACE INTO cache_metadata (key, value) VALUES (?, ?)").run("last_sync_contacts", String(Date.now()));
14478
+ } catch {
14479
+ }
14399
14480
  }
14400
14481
  }
14401
14482
  clear() {
@@ -14461,38 +14542,62 @@ var SqliteConversationRepository = class {
14461
14542
  return Promise.resolve(ok([]));
14462
14543
  }
14463
14544
  getProfile(conversationId) {
14464
- const row = this.db.prepare("SELECT data FROM conversation_profiles WHERE conversation_id = ?").get(conversationId);
14465
- if (!row) {
14545
+ try {
14546
+ const row = this.db.prepare("SELECT data FROM conversation_profiles WHERE conversation_id = ?").get(conversationId);
14547
+ if (!row) {
14548
+ return Promise.resolve(
14549
+ fail("NOT_FOUND" /* NOT_FOUND */, "Conversation profile not found in cache")
14550
+ );
14551
+ }
14552
+ return Promise.resolve(ok(JSON.parse(row.data)));
14553
+ } catch (error) {
14466
14554
  return Promise.resolve(
14467
- fail("NOT_FOUND" /* NOT_FOUND */, "Conversation profile not found in cache")
14555
+ fail(
14556
+ "INTERNAL_ERROR" /* INTERNAL_ERROR */,
14557
+ error instanceof Error ? error.message : "Failed to read conversation from cache"
14558
+ )
14468
14559
  );
14469
14560
  }
14470
- return Promise.resolve(ok(JSON.parse(row.data)));
14471
14561
  }
14472
14562
  searchByUid(uid) {
14473
- const rows = this.db.prepare(
14474
- "SELECT data FROM conversation_profiles WHERE user_ids LIKE ? OR user_ids LIKE ? OR user_ids LIKE ? OR user_ids = ?"
14475
- ).all(`%${uid},%`, `%,${uid},%`, `%,${uid}`, uid);
14476
- const results = rows.map((r) => JSON.parse(r.data));
14477
- return Promise.resolve(ok(results));
14563
+ try {
14564
+ const rows = this.db.prepare(
14565
+ "SELECT data FROM conversation_profiles WHERE user_ids LIKE ? OR user_ids LIKE ? OR user_ids LIKE ? OR user_ids = ?"
14566
+ ).all(`%${uid},%`, `%,${uid},%`, `%,${uid}`, uid);
14567
+ const results = rows.map((r) => JSON.parse(r.data));
14568
+ return Promise.resolve(ok(results));
14569
+ } catch (error) {
14570
+ return Promise.resolve(
14571
+ fail(
14572
+ "INTERNAL_ERROR" /* INTERNAL_ERROR */,
14573
+ error instanceof Error ? error.message : "Failed to search conversations in cache"
14574
+ )
14575
+ );
14576
+ }
14478
14577
  }
14479
14578
  upsertProfile(conversationId, profile) {
14480
- const user_ids = profile.users.map((u) => u.uid).join(",");
14481
- const cached_at = Date.now();
14482
- const data = JSON.stringify(profile);
14483
- this.db.prepare(
14484
- "INSERT INTO conversation_profiles (conversation_id, data, user_ids, cached_at) VALUES (?, ?, ?, ?) ON CONFLICT(conversation_id) DO UPDATE SET data=?, user_ids=?, cached_at=?"
14485
- ).run(conversationId, data, user_ids, cached_at, data, user_ids, cached_at);
14579
+ try {
14580
+ const user_ids = profile.users.map((u) => u.uid).join(",");
14581
+ const cached_at = Date.now();
14582
+ const data = JSON.stringify(profile);
14583
+ this.db.prepare(
14584
+ "INSERT INTO conversation_profiles (conversation_id, data, user_ids, cached_at) VALUES (?, ?, ?, ?) ON CONFLICT(conversation_id) DO UPDATE SET data=?, user_ids=?, cached_at=?"
14585
+ ).run(conversationId, data, user_ids, cached_at, data, user_ids, cached_at);
14586
+ } catch {
14587
+ }
14486
14588
  }
14487
14589
  // MARK: Conversation Index (for incremental sync)
14488
14590
  upsertIndex(conv) {
14489
- const members = JSON.stringify(conv.cids);
14490
- const nicks = conv.nicks ? JSON.stringify(conv.nicks) : null;
14491
- const im_version = conv.version;
14492
- const cached_at = Date.now();
14493
- this.db.prepare(
14494
- "INSERT INTO conversations_index (conversation_id, im_version, members, nicks, cached_at) VALUES (?, ?, ?, ?, ?) ON CONFLICT(conversation_id) DO UPDATE SET im_version=?, members=?, nicks=?, cached_at=?"
14495
- ).run(conv.id, im_version, members, nicks, cached_at, im_version, members, nicks, cached_at);
14591
+ try {
14592
+ const members = JSON.stringify(conv.cids);
14593
+ const nicks = conv.nicks ? JSON.stringify(conv.nicks) : null;
14594
+ const im_version = conv.version;
14595
+ const cached_at = Date.now();
14596
+ this.db.prepare(
14597
+ "INSERT INTO conversations_index (conversation_id, im_version, members, nicks, cached_at) VALUES (?, ?, ?, ?, ?) ON CONFLICT(conversation_id) DO UPDATE SET im_version=?, members=?, nicks=?, cached_at=?"
14598
+ ).run(conv.id, im_version, members, nicks, cached_at, im_version, members, nicks, cached_at);
14599
+ } catch {
14600
+ }
14496
14601
  }
14497
14602
  getIndexById(conversationId) {
14498
14603
  return this.db.prepare(
@@ -14500,34 +14605,51 @@ var SqliteConversationRepository = class {
14500
14605
  ).get(conversationId);
14501
14606
  }
14502
14607
  getAllIds() {
14503
- const rows = this.db.prepare("SELECT conversation_id FROM conversations_index").all();
14504
- return rows.map((r) => r.conversation_id);
14608
+ try {
14609
+ const rows = this.db.prepare("SELECT conversation_id FROM conversations_index").all();
14610
+ return rows.map((r) => r.conversation_id);
14611
+ } catch {
14612
+ return [];
14613
+ }
14505
14614
  }
14506
14615
  deleteStale(conversationIds) {
14507
- if (conversationIds.length === 0) return;
14508
- const placeholders = conversationIds.map(() => "?").join(",");
14509
- this.db.prepare(`DELETE FROM conversation_profiles WHERE conversation_id NOT IN (${placeholders})`).run(...conversationIds);
14510
- this.db.prepare(`DELETE FROM conversations_index WHERE conversation_id NOT IN (${placeholders})`).run(...conversationIds);
14616
+ try {
14617
+ if (conversationIds.length === 0) return;
14618
+ const placeholders = conversationIds.map(() => "?").join(",");
14619
+ this.db.prepare(`DELETE FROM conversation_profiles WHERE conversation_id NOT IN (${placeholders})`).run(...conversationIds);
14620
+ this.db.prepare(`DELETE FROM conversations_index WHERE conversation_id NOT IN (${placeholders})`).run(...conversationIds);
14621
+ } catch {
14622
+ }
14511
14623
  }
14512
14624
  invalidate(conversationId) {
14513
- this.db.prepare("DELETE FROM conversation_profiles WHERE conversation_id = ?").run(conversationId);
14514
- this.db.prepare("DELETE FROM conversations_index WHERE conversation_id = ?").run(conversationId);
14625
+ try {
14626
+ this.db.prepare("DELETE FROM conversation_profiles WHERE conversation_id = ?").run(conversationId);
14627
+ this.db.prepare("DELETE FROM conversations_index WHERE conversation_id = ?").run(conversationId);
14628
+ } catch {
14629
+ }
14515
14630
  }
14516
14631
  sync() {
14517
14632
  return Promise.resolve();
14518
14633
  }
14519
14634
  clear() {
14520
- this.db.exec("DELETE FROM conversation_profiles");
14521
- this.db.exec("DELETE FROM conversations_index");
14522
- this.db.exec("DELETE FROM cache_metadata WHERE key = 'last_sync_conversations'");
14635
+ try {
14636
+ this.db.exec("DELETE FROM conversation_profiles");
14637
+ this.db.exec("DELETE FROM conversations_index");
14638
+ this.db.exec("DELETE FROM cache_metadata WHERE key = 'last_sync_conversations'");
14639
+ } catch {
14640
+ }
14523
14641
  }
14524
14642
  getStatus() {
14525
- const count = this.db.prepare("SELECT COUNT(*) as c FROM conversation_profiles").get();
14526
- const meta = this.db.prepare("SELECT value FROM cache_metadata WHERE key = 'last_sync_conversations'").get();
14527
- return Promise.resolve({
14528
- count: count.c,
14529
- lastSyncAt: meta ? parseInt(meta.value, 10) : null
14530
- });
14643
+ try {
14644
+ const count = this.db.prepare("SELECT COUNT(*) as c FROM conversation_profiles").get();
14645
+ const meta = this.db.prepare("SELECT value FROM cache_metadata WHERE key = 'last_sync_conversations'").get();
14646
+ return Promise.resolve({
14647
+ count: count.c,
14648
+ lastSyncAt: meta ? parseInt(meta.value, 10) : null
14649
+ });
14650
+ } catch {
14651
+ return Promise.resolve({ count: 0, lastSyncAt: null });
14652
+ }
14531
14653
  }
14532
14654
  };
14533
14655
  var CachedConversationRepository = class {
@@ -14634,50 +14756,66 @@ var SqliteMessageRepository = class {
14634
14756
  this.db = db;
14635
14757
  }
14636
14758
  async pullMessages(conversationId, options3) {
14637
- const limit = options3?.limit ?? 50;
14638
- const fromId = options3?.fromMessageId;
14639
- let sql = "SELECT message_id, data FROM messages_cache WHERE conversation_id = ?";
14640
- const params = [conversationId];
14641
- if (fromId) {
14642
- if (options3?.direction === "newer") {
14643
- sql += " AND message_id > ?";
14644
- params.push(fromId);
14645
- } else {
14646
- sql += " AND message_id < ?";
14647
- params.push(fromId);
14759
+ try {
14760
+ const limit = options3?.limit ?? 50;
14761
+ const fromId = options3?.fromMessageId;
14762
+ let sql = "SELECT message_id, data FROM messages_cache WHERE conversation_id = ?";
14763
+ const params = [conversationId];
14764
+ if (fromId) {
14765
+ if (options3?.direction === "newer") {
14766
+ sql += " AND message_id > ?";
14767
+ params.push(fromId);
14768
+ } else {
14769
+ sql += " AND message_id < ?";
14770
+ params.push(fromId);
14771
+ }
14648
14772
  }
14773
+ sql += " ORDER BY message_id DESC LIMIT ?";
14774
+ params.push(limit);
14775
+ const rows = this.db.prepare(sql).all(...params);
14776
+ if (rows.length === 0) {
14777
+ return fail("NOT_FOUND" /* NOT_FOUND */, "Messages not found in cache");
14778
+ }
14779
+ return ok({
14780
+ messages: rows.map((r) => JSON.parse(r.data)),
14781
+ finished: rows.length < limit,
14782
+ lastId: rows[rows.length - 1]?.message_id ?? ""
14783
+ });
14784
+ } catch (error) {
14785
+ return fail(
14786
+ "INTERNAL_ERROR" /* INTERNAL_ERROR */,
14787
+ error instanceof Error ? error.message : "Failed to read messages from cache"
14788
+ );
14649
14789
  }
14650
- sql += " ORDER BY message_id DESC LIMIT ?";
14651
- params.push(limit);
14652
- const rows = this.db.prepare(sql).all(...params);
14653
- if (rows.length === 0) {
14654
- return fail("NOT_FOUND" /* NOT_FOUND */, "Messages not found in cache");
14655
- }
14656
- return ok({
14657
- messages: rows.map((r) => JSON.parse(r.data)),
14658
- finished: rows.length < limit,
14659
- lastId: rows[rows.length - 1]?.message_id ?? ""
14660
- });
14661
14790
  }
14662
14791
  upsert(conversationId, messageId, data) {
14663
- this.db.prepare(
14664
- "INSERT INTO messages_cache (conversation_id, message_id, data, cached_at) VALUES (?, ?, ?, ?) ON CONFLICT(conversation_id, message_id) DO UPDATE SET data=?, cached_at=?"
14665
- ).run(
14666
- conversationId,
14667
- messageId,
14668
- JSON.stringify(data),
14669
- Date.now(),
14670
- JSON.stringify(data),
14671
- Date.now()
14672
- );
14792
+ try {
14793
+ this.db.prepare(
14794
+ "INSERT INTO messages_cache (conversation_id, message_id, data, cached_at) VALUES (?, ?, ?, ?) ON CONFLICT(conversation_id, message_id) DO UPDATE SET data=?, cached_at=?"
14795
+ ).run(
14796
+ conversationId,
14797
+ messageId,
14798
+ JSON.stringify(data),
14799
+ Date.now(),
14800
+ JSON.stringify(data),
14801
+ Date.now()
14802
+ );
14803
+ } catch {
14804
+ }
14673
14805
  }
14674
14806
  invalidate(conversationId) {
14675
- this.db.prepare("DELETE FROM messages_cache WHERE conversation_id = ?").run(conversationId);
14807
+ try {
14808
+ this.db.prepare("DELETE FROM messages_cache WHERE conversation_id = ?").run(conversationId);
14809
+ } catch {
14810
+ }
14676
14811
  }
14677
14812
  async sync(_conversationId) {
14678
14813
  }
14679
14814
  clear() {
14680
- this.db.exec("DELETE FROM messages_cache");
14815
+ try {
14816
+ this.db.exec("DELETE FROM messages_cache");
14817
+ } catch {
14818
+ }
14681
14819
  }
14682
14820
  };
14683
14821
  var CachedMessageRepository = class {
@@ -14743,22 +14881,38 @@ var SqliteRelationRepository = class {
14743
14881
  this.db = db;
14744
14882
  }
14745
14883
  async getLinkNameType(friendUid) {
14746
- const row = this.db.prepare("SELECT name, type, cached_at FROM relations_cache WHERE friend_uid = ?").get(friendUid);
14747
- if (!row) return fail("NOT_FOUND" /* NOT_FOUND */, "Relation not found in cache");
14748
- return ok({ name: row.name, type: row.type });
14884
+ try {
14885
+ const row = this.db.prepare("SELECT name, type, cached_at FROM relations_cache WHERE friend_uid = ?").get(friendUid);
14886
+ if (!row) return fail("NOT_FOUND" /* NOT_FOUND */, "Relation not found in cache");
14887
+ return ok({ name: row.name, type: row.type });
14888
+ } catch (error) {
14889
+ return fail(
14890
+ "INTERNAL_ERROR" /* INTERNAL_ERROR */,
14891
+ error instanceof Error ? error.message : "Failed to read relation from cache"
14892
+ );
14893
+ }
14749
14894
  }
14750
14895
  upsert(friendUid, name, type) {
14751
- this.db.prepare(
14752
- "INSERT OR REPLACE INTO relations_cache (friend_uid, name, type, cached_at) VALUES (?, ?, ?, ?)"
14753
- ).run(friendUid, name, type, Date.now());
14896
+ try {
14897
+ this.db.prepare(
14898
+ "INSERT OR REPLACE INTO relations_cache (friend_uid, name, type, cached_at) VALUES (?, ?, ?, ?)"
14899
+ ).run(friendUid, name, type, Date.now());
14900
+ } catch {
14901
+ }
14754
14902
  }
14755
14903
  invalidate(friendUid) {
14756
- this.db.prepare("DELETE FROM relations_cache WHERE friend_uid = ?").run(friendUid);
14904
+ try {
14905
+ this.db.prepare("DELETE FROM relations_cache WHERE friend_uid = ?").run(friendUid);
14906
+ } catch {
14907
+ }
14757
14908
  }
14758
14909
  async sync() {
14759
14910
  }
14760
14911
  clear() {
14761
- this.db.exec("DELETE FROM relations_cache");
14912
+ try {
14913
+ this.db.exec("DELETE FROM relations_cache");
14914
+ } catch {
14915
+ }
14762
14916
  }
14763
14917
  };
14764
14918
  var CachedRelationRepository = class {
@@ -14771,13 +14925,19 @@ var CachedRelationRepository = class {
14771
14925
  remote;
14772
14926
  ttlMs;
14773
14927
  async getLinkNameType(friendUid) {
14774
- const row = this.local.db.prepare("SELECT name, type, cached_at FROM relations_cache WHERE friend_uid = ?").get(friendUid);
14775
- if (row && Date.now() - row.cached_at < this.ttlMs) {
14776
- return ok({ name: row.name, type: row.type });
14928
+ try {
14929
+ const row = this.local.db.prepare("SELECT name, type, cached_at FROM relations_cache WHERE friend_uid = ?").get(friendUid);
14930
+ if (row && Date.now() - row.cached_at < this.ttlMs) {
14931
+ return ok({ name: row.name, type: row.type });
14932
+ }
14933
+ } catch {
14777
14934
  }
14778
14935
  const remote = await this.remote.getLinkNameType(friendUid);
14779
14936
  if (remote.ok) {
14780
- this.local.upsert(friendUid, remote.data.name, remote.data.type);
14937
+ try {
14938
+ this.local.upsert(friendUid, remote.data.name, remote.data.type);
14939
+ } catch {
14940
+ }
14781
14941
  }
14782
14942
  return remote;
14783
14943
  }
@@ -14904,37 +15064,67 @@ var SqliteUserRepository = class {
14904
15064
  this.db = db;
14905
15065
  }
14906
15066
  async findUserById(id) {
14907
- const row = this.db.prepare("SELECT data FROM user_profiles WHERE uid = ?").get(id);
14908
- if (!row) return fail("NOT_FOUND" /* NOT_FOUND */, "User not found in cache");
14909
- return ok(JSON.parse(row.data));
15067
+ try {
15068
+ const row = this.db.prepare("SELECT data FROM user_profiles WHERE uid = ?").get(id);
15069
+ if (!row) return fail("NOT_FOUND" /* NOT_FOUND */, "User not found in cache");
15070
+ return ok(JSON.parse(row.data));
15071
+ } catch (error) {
15072
+ return fail(
15073
+ "INTERNAL_ERROR" /* INTERNAL_ERROR */,
15074
+ error instanceof Error ? error.message : "Failed to read user from cache"
15075
+ );
15076
+ }
14910
15077
  }
14911
15078
  async searchUserById(id) {
14912
- const row = this.db.prepare("SELECT data FROM user_profiles WHERE uid = ?").get(id);
14913
- if (!row) return fail("NOT_FOUND" /* NOT_FOUND */, "User not found in cache");
14914
- const data = JSON.parse(row.data);
14915
- return ok({
14916
- id: data.id,
14917
- uid: data.uid,
14918
- nickname: data.nickname,
14919
- avatar: data.avatar,
14920
- agent: data.agent
14921
- });
15079
+ try {
15080
+ const row = this.db.prepare("SELECT data FROM user_profiles WHERE uid = ?").get(id);
15081
+ if (!row) return fail("NOT_FOUND" /* NOT_FOUND */, "User not found in cache");
15082
+ const data = JSON.parse(row.data);
15083
+ return ok({
15084
+ id: data.id,
15085
+ uid: data.uid,
15086
+ nickname: data.nickname,
15087
+ avatar: data.avatar,
15088
+ agent: data.agent
15089
+ });
15090
+ } catch (error) {
15091
+ return fail(
15092
+ "INTERNAL_ERROR" /* INTERNAL_ERROR */,
15093
+ error instanceof Error ? error.message : "Failed to search user in cache"
15094
+ );
15095
+ }
14922
15096
  }
14923
15097
  async getUserAgentProfile(friendUid, _agentId) {
14924
- const row = this.db.prepare("SELECT data FROM user_profiles WHERE uid = ?").get(friendUid);
14925
- if (!row) return fail("NOT_FOUND" /* NOT_FOUND */, "User profile not found in cache");
14926
- return ok(JSON.parse(row.data));
15098
+ try {
15099
+ const row = this.db.prepare("SELECT data FROM user_profiles WHERE uid = ?").get(friendUid);
15100
+ if (!row) return fail("NOT_FOUND" /* NOT_FOUND */, "User profile not found in cache");
15101
+ return ok(JSON.parse(row.data));
15102
+ } catch (error) {
15103
+ return fail(
15104
+ "INTERNAL_ERROR" /* INTERNAL_ERROR */,
15105
+ error instanceof Error ? error.message : "Failed to read user profile from cache"
15106
+ );
15107
+ }
14927
15108
  }
14928
15109
  upsert(uid, data) {
14929
- this.db.prepare("INSERT OR REPLACE INTO user_profiles (uid, data, cached_at) VALUES (?, ?, ?)").run(uid, JSON.stringify(data), Date.now());
15110
+ try {
15111
+ this.db.prepare("INSERT OR REPLACE INTO user_profiles (uid, data, cached_at) VALUES (?, ?, ?)").run(uid, JSON.stringify(data), Date.now());
15112
+ } catch {
15113
+ }
14930
15114
  }
14931
15115
  invalidate(uid) {
14932
- this.db.prepare("DELETE FROM user_profiles WHERE uid = ?").run(uid);
15116
+ try {
15117
+ this.db.prepare("DELETE FROM user_profiles WHERE uid = ?").run(uid);
15118
+ } catch {
15119
+ }
14933
15120
  }
14934
15121
  async sync() {
14935
15122
  }
14936
15123
  clear() {
14937
- this.db.exec("DELETE FROM user_profiles");
15124
+ try {
15125
+ this.db.exec("DELETE FROM user_profiles");
15126
+ } catch {
15127
+ }
14938
15128
  }
14939
15129
  };
14940
15130
  var CachedUserRepository = class {
@@ -14981,13 +15171,19 @@ var CachedUserRepository = class {
14981
15171
  );
14982
15172
  }
14983
15173
  async fetchWithCache(uid, fetch2, store) {
14984
- const row = this.local.db.prepare("SELECT data, cached_at FROM user_profiles WHERE uid = ?").get(uid);
14985
- if (row && Date.now() - row.cached_at < this.ttlMs) {
14986
- return ok(JSON.parse(row.data));
15174
+ try {
15175
+ const row = this.local.db.prepare("SELECT data, cached_at FROM user_profiles WHERE uid = ?").get(uid);
15176
+ if (row && Date.now() - row.cached_at < this.ttlMs) {
15177
+ return ok(JSON.parse(row.data));
15178
+ }
15179
+ } catch (error) {
14987
15180
  }
14988
15181
  const remote = await fetch2();
14989
15182
  if (remote.ok) {
14990
- store(remote.data);
15183
+ try {
15184
+ store(remote.data);
15185
+ } catch {
15186
+ }
14991
15187
  }
14992
15188
  return remote;
14993
15189
  }
@@ -15109,7 +15305,7 @@ async function main() {
15109
15305
  ${t("cli.banner")}` : t("cli.banner");
15110
15306
  program.addHelpText("beforeAll", `${banner}
15111
15307
  `);
15112
- program.name("qz").version(`v${"0.5.3"}`, "-v, --version", t("options.version")).helpOption("-h, --help", t("options.help")).option("-q, --jq <expr>", t("options.jq")).option("--dry-run", t("options.dryRun"));
15308
+ program.name("qz").version(`v${"0.5.5"}`, "-v, --version", t("options.version")).helpOption("-h, --help", t("options.help")).option("-q, --jq <expr>", t("options.jq")).option("--dry-run", t("options.dryRun"));
15113
15309
  program.usage("<command> [subcommand] [options]");
15114
15310
  program.hook("preAction", () => {
15115
15311
  const opts = program.opts();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qzhuli/qzhuli-cli",
3
- "version": "0.5.3",
3
+ "version": "0.5.5",
4
4
  "description": "CLI tool for Q助理 (QZhuli)",
5
5
  "main": "dist/cmd.js",
6
6
  "bin": {
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: qzhuli-cli
3
3
  description: Use when operating the QZhuli CLI (`qz`), including login, auth status, config, friends, relations, users, conversations, messages, cache management, JSON filtering, dry-run, command help, and interpreting test-environment banners or config files.
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  ---
6
6
 
7
7
  # QZhuli CLI
@@ -127,6 +127,7 @@ qz --jq ".data" conversation list --limit 5
127
127
  | Get conversation profile | `qz conversation profile <conversation-id> [--type <n>]` |
128
128
  | Create conversation | `qz conversation create <uid> --agent-id <id>` |
129
129
  | Search conversations (ID) | `qz conversation search <conversation-id>` |
130
+ | Search conversations (CID) | `qz conversation search <cid> --cid` |
130
131
  | Search conversations (name) | `qz conversation search <name> --name` |
131
132
  | Search conversations (Q助号) | `qz conversation search <q-number> --qnumber` |
132
133
  | Search conversations (UID) | `qz conversation search <uid> --uid` |
@@ -165,6 +166,7 @@ Relation type values: `0=stranger`, `1=friend`, `2=family`, `3=colleague`.
165
166
 
166
167
  ```bash
167
168
  qz conversation search <conversation-id> # default: by conversation ID
169
+ qz conversation search <cid> --cid # by user CID
168
170
  qz conversation search <name> --name # by conversation name
169
171
  qz conversation search <q-number> --qnumber # by user Q助号
170
172
  qz conversation search <uid> --uid # by user UID