@zaclinley/dsh-mailharbor 0.8.0 → 0.9.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.
package/lib/index.js CHANGED
@@ -1730,6 +1730,11 @@ var SUMMARY_SYSTEM = `\u4F60\u662F\u90AE\u4EF6\u52A9\u7406\uFF0C\u670D\u52A1\u4E
1730
1730
  \u5EFA\u8BAE\u56DE\u590D\u8981\u70B9
1731
1731
  \uFF081-3 \u6761\u4E2D\u6587\u8981\u70B9\uFF09
1732
1732
 
1733
+ \u8EAB\u4EFD\u89C4\u5219\uFF08\u7528\u6237\u8EAB\u4EFD\u4F1A\u5199\u5728\u90AE\u4EF6\u4FE1\u606F\u91CC\uFF09\uFF1A
1734
+ - \u5982\u679C\u7528\u6237\u662F\u300C\u4EC5\u6284\u9001\u300D\u6216\u300C\u4E0D\u5728\u6536\u4EF6\u4EBA/\u6284\u9001\u5217\u8868\u300D\uFF1A\u9700\u8981\u4F60\u505A\u4EC0\u4E48\u53EA\u5199\u300C\u4F60\u53EA\u662F\u88AB\u6284\u9001\uFF0C\u901A\u5E38\u65E0\u9700\u64CD\u4F5C\u300D\u8FD9\u7C7B\u7ED3\u8BBA\uFF1B\u4E0D\u8981\u8F93\u51FA\u300C\u5EFA\u8BAE\u56DE\u590D\u8981\u70B9\u300D\u8FD9\u4E00\u6BB5
1735
+ - \u5982\u679C\u7528\u6237\u662F\u300C\u53D1\u4EF6\u4EBA\u300D\uFF1A\u9700\u8981\u4F60\u505A\u4EC0\u4E48\u5199\u300C\u8FD9\u662F\u4F60\u53D1\u51FA\u7684\u90AE\u4EF6\uFF0C\u65E0\u9700\u64CD\u4F5C\u300D\uFF1B\u4E0D\u8981\u8F93\u51FA\u300C\u5EFA\u8BAE\u56DE\u590D\u8981\u70B9\u300D\u8FD9\u4E00\u6BB5
1736
+ - \u53EA\u6709\u300C\u76F4\u63A5\u6536\u4EF6\u4EBA\u300D\u4E14\u90AE\u4EF6\u786E\u5B9E\u8981\u6C42\u884C\u52A8\u65F6\uFF0C\u624D\u7ED9\u300C\u5EFA\u8BAE\u56DE\u590D\u8981\u70B9\u300D
1737
+
1733
1738
  \u53EA\u4F9D\u636E\u90AE\u4EF6\u5185\u5BB9\uFF0C\u4E0D\u8981\u7F16\u9020\uFF0C\u4E0D\u8981\u8F93\u51FA\u601D\u8003\u8FC7\u7A0B\u3002`;
1734
1739
  var REPLY_SYSTEM = (language, style) => `\u4F60\u662F\u90AE\u4EF6\u5199\u4F5C\u52A9\u7406\u3002\u6839\u636E\u539F\u59CB\u90AE\u4EF6\u548C\u7528\u6237\u7684\u8981\u6C42\uFF0C\u5199\u4E00\u5C01\u53EF\u4EE5\u76F4\u63A5\u53D1\u9001\u7684\u56DE\u590D\u6B63\u6587\u3002
1735
1740
 
@@ -1837,12 +1842,30 @@ function bodyText(message) {
1837
1842
  if (message.text.trim() !== "") return message.text;
1838
1843
  return (message.html ?? "").replace(/<style[\s\S]*?<\/style>/gi, "").replace(/<script[\s\S]*?<\/script>/gi, "").replace(/<br\s*\/?>/gi, "\n").replace(/<\/(p|div|li|tr|h[1-6])>/gi, "\n").replace(/<[^>]+>/g, "").replace(/&nbsp;/g, " ").replace(/&amp;/g, "&").trim();
1839
1844
  }
1840
- function contextOf(message) {
1845
+ function roleOf(message, email) {
1846
+ const target = String(email ?? "").trim().toLowerCase();
1847
+ if (target === "") return "unknown";
1848
+ const has = (list) => list.some((item) => item.address.trim().toLowerCase() === target);
1849
+ if (has(message.to)) return "to";
1850
+ if (has(message.cc)) return "cc";
1851
+ if (message.from.address.trim().toLowerCase() === target) return "sender";
1852
+ return "other";
1853
+ }
1854
+ var ROLE_TEXT = {
1855
+ to: "\u76F4\u63A5\u6536\u4EF6\u4EBA",
1856
+ cc: "\u4EC5\u6284\u9001\uFF08\u4E0D\u5728\u6536\u4EF6\u4EBA\u91CC\uFF09",
1857
+ sender: "\u53D1\u4EF6\u4EBA\uFF08\u4F60\u53D1\u51FA\u7684\u90AE\u4EF6\uFF09",
1858
+ other: "\u4E0D\u5728\u6536\u4EF6\u4EBA/\u6284\u9001\u5217\u8868\uFF08\u53EF\u80FD\u662F\u90AE\u4EF6\u5217\u8868\u6216\u5BC6\u9001\uFF09",
1859
+ unknown: "\u672A\u77E5"
1860
+ };
1861
+ function contextOf(message, email) {
1862
+ const role = roleOf(message, email);
1841
1863
  const lines = [
1842
1864
  `\u4E3B\u9898: ${message.subject}`,
1843
1865
  `\u53D1\u4EF6\u4EBA: ${message.from.name !== "" ? `${message.from.name} <${message.from.address}>` : message.from.address}`,
1844
1866
  `\u6536\u4EF6\u4EBA: ${message.to.map((item) => item.name !== "" ? `${item.name} <${item.address}>` : item.address).join(", ")}`,
1845
1867
  ...message.cc.length === 0 ? [] : [`\u6284\u9001: ${message.cc.map((item) => item.address).join(", ")}`],
1868
+ ...role === "unknown" ? [] : [`\u4F60\u7684\u8EAB\u4EFD: ${ROLE_TEXT[role]}`],
1846
1869
  `\u65F6\u95F4: ${message.date}`,
1847
1870
  "",
1848
1871
  clip(bodyText(message))
@@ -1941,8 +1964,10 @@ var AiService = class {
1941
1964
  if (trimmed === "") throw new Error("\u6A21\u578B\u6CA1\u6709\u8FD4\u56DE\u5185\u5BB9");
1942
1965
  return trimmed;
1943
1966
  }
1944
- async summarize(message, signal) {
1945
- return this.complete(SUMMARY_SYSTEM, contextOf(message), signal);
1967
+ async summarize(message, email, signal) {
1968
+ const output = await this.complete(SUMMARY_SYSTEM, contextOf(message, email), signal);
1969
+ const role = roleOf(message, email);
1970
+ return role === "to" || role === "unknown" ? output : stripReplySuggestions(output);
1946
1971
  }
1947
1972
  async reply(account, message, options = {}, signal) {
1948
1973
  const style = this.style(account)?.profile ?? "";
@@ -1961,14 +1986,14 @@ var AiService = class {
1961
1986
  return this.complete(TRANSLATE_SYSTEM(target), clip(text2, 2e4), signal);
1962
1987
  }
1963
1988
  /** Free-form question about a mail, with up to three earlier AI outputs as context. */
1964
- async ask(message, question, history, signal) {
1989
+ async ask(message, question, history, email, signal) {
1965
1990
  const prompt = (question ?? "").trim();
1966
1991
  if (prompt === "") throw new Error("\u95EE\u9898\u4E0D\u80FD\u4E3A\u7A7A");
1967
1992
  const earlier = history.filter((item) => item.trim() !== "").slice(-3).map((item, index) => `\u3010\u5DF2\u6709\u8BB0\u5F55 ${String(index + 1)}\u3011
1968
1993
  ${clip(item, 4e3)}`).join("\n\n");
1969
1994
  const user = [
1970
1995
  "\u90AE\u4EF6\uFF1A",
1971
- contextOf(message),
1996
+ contextOf(message, email),
1972
1997
  ...earlier === "" ? [] : ["", "\u5DF2\u6709 AI \u8BB0\u5F55\uFF1A", earlier],
1973
1998
  "",
1974
1999
  `\u7528\u6237\u7684\u95EE\u9898\uFF1A${prompt}`
@@ -2103,6 +2128,12 @@ function parseTaskJson(text2) {
2103
2128
  }
2104
2129
  return result.slice(0, 30);
2105
2130
  }
2131
+ function stripReplySuggestions(text2) {
2132
+ const lines = text2.split(/\r?\n/);
2133
+ const index = lines.findIndex((line2) => /^#{0,4}\s*建议回复要点\s*[::]?\s*$/.test(line2.trim()));
2134
+ if (index < 0) return text2.trimEnd();
2135
+ return lines.slice(0, index).join("\n").trimEnd();
2136
+ }
2106
2137
  function summaryBlocks(text2) {
2107
2138
  const blocks = [];
2108
2139
  let current = { title: "", lines: [] };
@@ -2349,7 +2380,7 @@ ${conversation.trim()}
2349
2380
  }
2350
2381
 
2351
2382
  // src/host/version.ts
2352
- var VERSION = "0.8.0";
2383
+ var VERSION = "0.9.1";
2353
2384
 
2354
2385
  // src/host/api.ts
2355
2386
  init_smtp();
@@ -2708,7 +2739,7 @@ function buildRouter(runtime) {
2708
2739
  let html;
2709
2740
  let meta;
2710
2741
  if (kind === "summary") {
2711
- output = await ai.summarize(detail);
2742
+ output = await ai.summarize(detail, account.email);
2712
2743
  } else if (kind === "reply") {
2713
2744
  output = await ai.reply(account, detail, { instruction, language });
2714
2745
  html = textToHtml(output);
@@ -2727,7 +2758,7 @@ function buildRouter(runtime) {
2727
2758
  meta = { target };
2728
2759
  } else {
2729
2760
  const earlier = runtime.aiThreads(account).get(key)?.cards.filter((card2) => card2.kind === "answer").map((card2) => card2.output) ?? [];
2730
- output = await ai.ask(detail, instruction, earlier);
2761
+ output = await ai.ask(detail, instruction, earlier, account.email);
2731
2762
  }
2732
2763
  const card = {
2733
2764
  id: randomUUID3(),
@@ -2830,7 +2861,7 @@ function buildRouter(runtime) {
2830
2861
  mailboxOfPayload(payload)
2831
2862
  );
2832
2863
  try {
2833
- const summary = await runtime.ai().summarize(detail);
2864
+ const summary = await runtime.ai().summarize(detail, account.email);
2834
2865
  return { summary, blocks: summaryBlocks(summary) };
2835
2866
  } catch (error) {
2836
2867
  throw aiHttpError(error);