@lih-x-x/kmr 1.0.3 → 1.0.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.
Files changed (2) hide show
  1. package/dist/index.js +101 -63
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -24,6 +24,11 @@ function createEventDispatcher(onMessage) {
24
24
  return;
25
25
  }
26
26
  const messageId = message.message_id;
27
+ const senderType = data.sender?.sender_type;
28
+ if (senderType === "app") {
29
+ console.log(`[recv] \u5FFD\u7565\u673A\u5668\u4EBA\u81EA\u8EAB\u6D88\u606F: ${messageId}`);
30
+ return;
31
+ }
27
32
  if (processedMessages.has(messageId)) {
28
33
  console.log(`[dedup] \u8DF3\u8FC7\u91CD\u590D\u6D88\u606F: ${messageId}`);
29
34
  return;
@@ -398,6 +403,36 @@ var RANK_RESULTS_PROMPT = `\u4F60\u662F\u4E00\u4E2A\u641C\u7D22\u6392\u5E8F\u52A
398
403
 
399
404
  \u7528\u6237\u67E5\u8BE2\uFF1A`;
400
405
 
406
+ // src/utils/claudeEnv.ts
407
+ import fs from "fs";
408
+ import path from "path";
409
+ import os from "os";
410
+ var cachedEnv = null;
411
+ function getClaudeEnv() {
412
+ if (cachedEnv) return cachedEnv;
413
+ const settingsPath = path.join(os.homedir(), ".claude", "settings.json");
414
+ let settingsEnv = {};
415
+ try {
416
+ const content = fs.readFileSync(settingsPath, "utf-8");
417
+ const settings = JSON.parse(content);
418
+ if (settings.env && typeof settings.env === "object") {
419
+ settingsEnv = settings.env;
420
+ }
421
+ } catch {
422
+ }
423
+ cachedEnv = { ...settingsEnv };
424
+ for (const key of Object.keys(settingsEnv)) {
425
+ if (process.env[key]) {
426
+ cachedEnv[key] = process.env[key];
427
+ }
428
+ }
429
+ return cachedEnv;
430
+ }
431
+ function getExecEnv() {
432
+ const claudeEnv = getClaudeEnv();
433
+ return { ...process.env, ...claudeEnv };
434
+ }
435
+
401
436
  // src/agent/claudeCode.ts
402
437
  var execFileAsync = promisify(execFile);
403
438
  var ClaudeCodeProvider = class {
@@ -448,7 +483,8 @@ ${prompt}
448
483
  try {
449
484
  const { stdout } = await execFileAsync("acpx", ["--allowed-tools", "", "claude", "exec", prompt], {
450
485
  timeout: this.timeout,
451
- maxBuffer: 1024 * 1024
486
+ maxBuffer: 1024 * 1024,
487
+ env: getExecEnv()
452
488
  });
453
489
  return this.extractJson(stdout);
454
490
  } catch (err) {
@@ -489,31 +525,31 @@ ${prompt}
489
525
  };
490
526
 
491
527
  // src/storage/jsonStore.ts
492
- import fs from "fs";
493
- import path from "path";
528
+ import fs2 from "fs";
529
+ import path2 from "path";
494
530
  var JsonStore = class {
495
531
  constructor(dataDir) {
496
532
  this.dataDir = dataDir;
497
- fs.mkdirSync(dataDir, { recursive: true });
533
+ fs2.mkdirSync(dataDir, { recursive: true });
498
534
  }
499
535
  dataDir;
500
536
  async save(record) {
501
537
  const date = record.summary.date || (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
502
538
  const fileName = `${date}_${record.id}.json`;
503
- const filePath = path.join(this.dataDir, fileName);
504
- fs.writeFileSync(filePath, JSON.stringify(record, null, 2), "utf-8");
539
+ const filePath = path2.join(this.dataDir, fileName);
540
+ fs2.writeFileSync(filePath, JSON.stringify(record, null, 2), "utf-8");
505
541
  return filePath;
506
542
  }
507
543
  async load(id) {
508
544
  const files = this.getFiles();
509
545
  const target = files.find((f) => f.includes(id));
510
546
  if (!target) return null;
511
- const raw = fs.readFileSync(target, "utf-8");
547
+ const raw = fs2.readFileSync(target, "utf-8");
512
548
  return JSON.parse(raw);
513
549
  }
514
550
  async list() {
515
551
  const files = this.getFiles();
516
- return files.map((f) => JSON.parse(fs.readFileSync(f, "utf-8")));
552
+ return files.map((f) => JSON.parse(fs2.readFileSync(f, "utf-8")));
517
553
  }
518
554
  async search(keywords) {
519
555
  const all = await this.list();
@@ -526,25 +562,25 @@ var JsonStore = class {
526
562
  const files = this.getFiles();
527
563
  const target = files.find((f) => f.includes(id));
528
564
  if (!target) return false;
529
- fs.unlinkSync(target);
565
+ fs2.unlinkSync(target);
530
566
  return true;
531
567
  }
532
568
  getFiles() {
533
- if (!fs.existsSync(this.dataDir)) return [];
534
- return fs.readdirSync(this.dataDir).filter((f) => f.endsWith(".json")).map((f) => path.join(this.dataDir, f));
569
+ if (!fs2.existsSync(this.dataDir)) return [];
570
+ return fs2.readdirSync(this.dataDir).filter((f) => f.endsWith(".json")).map((f) => path2.join(this.dataDir, f));
535
571
  }
536
572
  };
537
573
 
538
574
  // src/query/finder.ts
539
- import fs2 from "fs";
540
- import path2 from "path";
575
+ import fs3 from "fs";
576
+ import path3 from "path";
541
577
  async function grepMeetings(dataDir, keywords) {
542
- if (!fs2.existsSync(dataDir)) return [];
543
- const files = fs2.readdirSync(dataDir).filter((f) => f.endsWith(".json"));
578
+ if (!fs3.existsSync(dataDir)) return [];
579
+ const files = fs3.readdirSync(dataDir).filter((f) => f.endsWith(".json"));
544
580
  const matches = [];
545
581
  for (const file of files) {
546
- const filePath = path2.join(dataDir, file);
547
- const raw = fs2.readFileSync(filePath, "utf-8");
582
+ const filePath = path3.join(dataDir, file);
583
+ const raw = fs3.readFileSync(filePath, "utf-8");
548
584
  const hasMatch = keywords.some((kw) => raw.includes(kw));
549
585
  if (hasMatch) {
550
586
  matches.push(JSON.parse(raw));
@@ -572,11 +608,11 @@ var QueryHandler = class {
572
608
 
573
609
  // src/web/server.ts
574
610
  import http from "http";
575
- import fs3 from "fs";
576
- import path3 from "path";
611
+ import fs4 from "fs";
612
+ import path4 from "path";
577
613
  import { fileURLToPath } from "url";
578
- var __dirname = path3.dirname(fileURLToPath(import.meta.url));
579
- var PUBLIC_DIR = path3.join(__dirname, "public");
614
+ var __dirname = path4.dirname(fileURLToPath(import.meta.url));
615
+ var PUBLIC_DIR = path4.join(__dirname, "public");
580
616
  var MIME_TYPES = {
581
617
  ".html": "text/html; charset=utf-8",
582
618
  ".css": "text/css; charset=utf-8",
@@ -586,30 +622,30 @@ var MIME_TYPES = {
586
622
  ".svg": "image/svg+xml"
587
623
  };
588
624
  function serveStatic(res, urlPath) {
589
- const safePath = path3.normalize(urlPath).replace(/^(\.\.[/\\])+/, "");
590
- let filePath = path3.join(PUBLIC_DIR, safePath === "/" ? "index.html" : safePath);
591
- if (!fs3.existsSync(filePath) || fs3.statSync(filePath).isDirectory()) {
592
- filePath = path3.join(PUBLIC_DIR, "index.html");
625
+ const safePath = path4.normalize(urlPath).replace(/^(\.\.[/\\])+/, "");
626
+ let filePath = path4.join(PUBLIC_DIR, safePath === "/" ? "index.html" : safePath);
627
+ if (!fs4.existsSync(filePath) || fs4.statSync(filePath).isDirectory()) {
628
+ filePath = path4.join(PUBLIC_DIR, "index.html");
593
629
  }
594
- const ext = path3.extname(filePath);
630
+ const ext = path4.extname(filePath);
595
631
  const contentType = MIME_TYPES[ext] || "application/octet-stream";
596
- const content = fs3.readFileSync(filePath);
632
+ const content = fs4.readFileSync(filePath);
597
633
  res.writeHead(200, { "Content-Type": contentType });
598
634
  res.end(content);
599
635
  }
600
636
  function listSessions(kmrDir) {
601
- const sessionsDir = path3.join(kmrDir, "sessions");
602
- if (!fs3.existsSync(sessionsDir)) return [];
603
- return fs3.readdirSync(sessionsDir).filter((d) => {
604
- const full = path3.join(sessionsDir, d);
605
- return fs3.statSync(full).isDirectory();
637
+ const sessionsDir = path4.join(kmrDir, "sessions");
638
+ if (!fs4.existsSync(sessionsDir)) return [];
639
+ return fs4.readdirSync(sessionsDir).filter((d) => {
640
+ const full = path4.join(sessionsDir, d);
641
+ return fs4.statSync(full).isDirectory();
606
642
  }).map((userId) => {
607
- const summaryPath = path3.join(sessionsDir, userId, "summary.md");
643
+ const summaryPath = path4.join(sessionsDir, userId, "summary.md");
608
644
  let summaryPreview = "";
609
645
  let messageCount = 0;
610
646
  let lastActivity = "";
611
- if (fs3.existsSync(summaryPath)) {
612
- const content = fs3.readFileSync(summaryPath, "utf-8");
647
+ if (fs4.existsSync(summaryPath)) {
648
+ const content = fs4.readFileSync(summaryPath, "utf-8");
613
649
  const lines = content.split("\n").filter((l) => l.trim().length > 0);
614
650
  messageCount = lines.length;
615
651
  for (let i = lines.length - 1; i >= 0; i--) {
@@ -621,26 +657,26 @@ function listSessions(kmrDir) {
621
657
  const lastLine = lines[lines.length - 1] || "";
622
658
  const timeMatch = lastLine.match(/^\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\]/);
623
659
  if (timeMatch) lastActivity = timeMatch[1];
624
- const stat = fs3.statSync(summaryPath);
660
+ const stat = fs4.statSync(summaryPath);
625
661
  if (!lastActivity) lastActivity = stat.mtime.toISOString().replace("T", " ").slice(0, 19);
626
662
  } else {
627
- const userDir = path3.join(sessionsDir, userId);
628
- const stat = fs3.statSync(userDir);
663
+ const userDir = path4.join(sessionsDir, userId);
664
+ const stat = fs4.statSync(userDir);
629
665
  lastActivity = stat.mtime.toISOString().replace("T", " ").slice(0, 19);
630
666
  }
631
667
  return { userId, summaryPreview, messageCount, lastActivity };
632
668
  }).sort((a, b) => b.lastActivity.localeCompare(a.lastActivity));
633
669
  }
634
670
  function deleteSession(kmrDir, userId) {
635
- const sessionDir = path3.join(kmrDir, "sessions", userId);
636
- if (!fs3.existsSync(sessionDir)) return false;
637
- fs3.rmSync(sessionDir, { recursive: true, force: true });
671
+ const sessionDir = path4.join(kmrDir, "sessions", userId);
672
+ if (!fs4.existsSync(sessionDir)) return false;
673
+ fs4.rmSync(sessionDir, { recursive: true, force: true });
638
674
  return true;
639
675
  }
640
676
  function getSessionDetail(kmrDir, userId) {
641
- const summaryPath = path3.join(kmrDir, "sessions", userId, "summary.md");
642
- if (!fs3.existsSync(summaryPath)) return null;
643
- return fs3.readFileSync(summaryPath, "utf-8");
677
+ const summaryPath = path4.join(kmrDir, "sessions", userId, "summary.md");
678
+ if (!fs4.existsSync(summaryPath)) return null;
679
+ return fs4.readFileSync(summaryPath, "utf-8");
644
680
  }
645
681
  function startWebServer(store, kmrDir, port = 3e3) {
646
682
  return new Promise((resolve, reject) => {
@@ -710,8 +746,8 @@ async function handleApi(req, res, url, store, kmrDir) {
710
746
  return;
711
747
  }
712
748
  if (pathname === "/api/config" && method === "GET") {
713
- const configPath = path3.join(kmrDir, "config.json");
714
- const config = JSON.parse(fs3.readFileSync(configPath, "utf-8"));
749
+ const configPath = path4.join(kmrDir, "config.json");
750
+ const config = JSON.parse(fs4.readFileSync(configPath, "utf-8"));
715
751
  jsonResponse(res, 200, { ok: true, data: config });
716
752
  return;
717
753
  }
@@ -724,8 +760,8 @@ async function handleApi(req, res, url, store, kmrDir) {
724
760
  jsonResponse(res, 400, { ok: false, error: "\u65E0\u6548\u7684 JSON \u683C\u5F0F" });
725
761
  return;
726
762
  }
727
- const configPath = path3.join(kmrDir, "config.json");
728
- fs3.writeFileSync(configPath, JSON.stringify(parsed, null, 2), "utf-8");
763
+ const configPath = path4.join(kmrDir, "config.json");
764
+ fs4.writeFileSync(configPath, JSON.stringify(parsed, null, 2), "utf-8");
729
765
  jsonResponse(res, 200, { ok: true, data: parsed });
730
766
  return;
731
767
  }
@@ -779,8 +815,8 @@ function openBrowser(url) {
779
815
  // src/session/manager.ts
780
816
  import { execFile as execFile3 } from "child_process";
781
817
  import { promisify as promisify2 } from "util";
782
- import fs4 from "fs";
783
- import path4 from "path";
818
+ import fs5 from "fs";
819
+ import path5 from "path";
784
820
 
785
821
  // src/session/skill.ts
786
822
  var SESSION_SKILL = `\u4F60\u662F KMR\uFF08Key Meetings Record\uFF09\u7684\u667A\u80FD\u52A9\u624B\u3002
@@ -808,8 +844,8 @@ var execFileAsync2 = promisify2(execFile3);
808
844
  var SessionManager = class {
809
845
  constructor(kmrDir, timeout = 6e4) {
810
846
  this.timeout = timeout;
811
- this.sessionDir = path4.join(kmrDir, "sessions");
812
- fs4.mkdirSync(this.sessionDir, { recursive: true });
847
+ this.sessionDir = path5.join(kmrDir, "sessions");
848
+ fs5.mkdirSync(this.sessionDir, { recursive: true });
813
849
  }
814
850
  timeout;
815
851
  activeSessions = /* @__PURE__ */ new Map();
@@ -828,15 +864,16 @@ var SessionManager = class {
828
864
  return existing.name;
829
865
  }
830
866
  const sessionName = `kmr-${userId}`;
831
- const userDir = path4.join(this.sessionDir, userId);
832
- fs4.mkdirSync(userDir, { recursive: true });
833
- const skillPath = path4.join(userDir, "skill.md");
834
- fs4.writeFileSync(skillPath, SESSION_SKILL, "utf-8");
867
+ const userDir = path5.join(this.sessionDir, userId);
868
+ fs5.mkdirSync(userDir, { recursive: true });
869
+ const skillPath = path5.join(userDir, "skill.md");
870
+ fs5.writeFileSync(skillPath, SESSION_SKILL, "utf-8");
835
871
  console.log(`[session] \u521B\u5EFA\u65B0 session: ${sessionName}`);
836
872
  try {
837
873
  await execFileAsync2("acpx", ["claude", "sessions", "ensure", "--name", sessionName], {
838
874
  timeout: this.timeout,
839
- maxBuffer: 1024 * 1024
875
+ maxBuffer: 1024 * 1024,
876
+ env: getExecEnv()
840
877
  });
841
878
  } catch (err) {
842
879
  console.error(`[session] \u521B\u5EFA session \u5931\u8D25:`, err.message);
@@ -847,7 +884,7 @@ var SessionManager = class {
847
884
  await execFileAsync2(
848
885
  "acpx",
849
886
  ["--approve-all", "claude", "-s", sessionName, SESSION_SKILL],
850
- { timeout: this.timeout, maxBuffer: 1024 * 1024 }
887
+ { timeout: this.timeout, maxBuffer: 1024 * 1024, env: getExecEnv() }
851
888
  );
852
889
  } catch (err) {
853
890
  console.error(`[session] \u89D2\u8272\u8BBE\u5B9A\u5931\u8D25:`, err.message);
@@ -863,7 +900,7 @@ var SessionManager = class {
863
900
  const { stdout } = await execFileAsync2(
864
901
  "acpx",
865
902
  ["--approve-all", "claude", "-s", sessionName, text],
866
- { timeout: this.timeout, maxBuffer: 1024 * 1024 }
903
+ { timeout: this.timeout, maxBuffer: 1024 * 1024, env: getExecEnv() }
867
904
  );
868
905
  return this.extractReply(stdout);
869
906
  } catch (err) {
@@ -882,21 +919,22 @@ var SessionManager = class {
882
919
  return filtered || output.trim();
883
920
  }
884
921
  async appendSummary(userId, userText, aiReply) {
885
- const userDir = path4.join(this.sessionDir, userId);
886
- const summaryPath = path4.join(userDir, "summary.md");
922
+ const userDir = path5.join(this.sessionDir, userId);
923
+ const summaryPath = path5.join(userDir, "summary.md");
887
924
  const now = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
888
925
  const entry = `
889
926
  [${now}] \u7528\u6237: ${userText}
890
927
  [${now}] AI: ${aiReply}
891
928
  `;
892
- fs4.appendFileSync(summaryPath, entry, "utf-8");
929
+ fs5.appendFileSync(summaryPath, entry, "utf-8");
893
930
  }
894
931
  async closeSession(userId) {
895
932
  const info = this.activeSessions.get(userId);
896
933
  if (!info) return;
897
934
  try {
898
935
  await execFileAsync2("acpx", ["claude", "sessions", "close", info.name], {
899
- timeout: 1e4
936
+ timeout: 1e4,
937
+ env: getExecEnv()
900
938
  });
901
939
  console.log(`[session] \u5DF2\u5173\u95ED session: ${info.name}`);
902
940
  } catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lih-x-x/kmr",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "bin": {