chattercatcher 0.2.1 → 0.2.3

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/index.js CHANGED
@@ -178,6 +178,28 @@ function resolveEmbeddingApiKey(input) {
178
178
  return explicit || input.llmApiKey;
179
179
  }
180
180
 
181
+ // src/time/beijing.ts
182
+ var BEIJING_TIME_ZONE = "Asia/Shanghai";
183
+ var BEIJING_DATE_TIME_FORMATTER = new Intl.DateTimeFormat("zh-CN", {
184
+ timeZone: BEIJING_TIME_ZONE,
185
+ year: "numeric",
186
+ month: "2-digit",
187
+ day: "2-digit",
188
+ hour: "2-digit",
189
+ minute: "2-digit",
190
+ second: "2-digit",
191
+ hour12: false
192
+ });
193
+ function formatOffsetTimeZone(date) {
194
+ const parts = Object.fromEntries(
195
+ BEIJING_DATE_TIME_FORMATTER.formatToParts(date).map((part) => [part.type, part.value])
196
+ );
197
+ return `${parts.year}-${parts.month}-${parts.day}T${parts.hour}:${parts.minute}:${parts.second}+08:00`;
198
+ }
199
+ function formatBeijingTimeForPrompt(date) {
200
+ return `${formatOffsetTimeZone(date)}\uFF08\u5317\u4EAC\u65F6\u95F4\uFF0CUTC+8\uFF0CAsia/Shanghai\uFF09`;
201
+ }
202
+
181
203
  // src/cron/generator.ts
182
204
  var SYSTEM_PROMPT = "\u4F60\u6B63\u5728\u4E3A\u98DE\u4E66\u7FA4\u751F\u6210\u4E00\u6761\u5B9A\u65F6\u6D88\u606F\u3002\u53EF\u4EE5\u5148\u8C03\u7528\u641C\u7D22\u5DE5\u5177\u68C0\u7D22\u672C\u5730\u7FA4\u804A\u77E5\u8BC6\u5E93\u3002\u6700\u7EC8\u8F93\u51FA\u5FC5\u987B\u662F\u53EF\u4EE5\u76F4\u63A5\u53D1\u5230\u7FA4\u91CC\u7684\u7EAF\u6587\u672C\uFF0C\u4E0D\u8981\u8F93\u51FA\u5DE5\u5177\u8C03\u7528\u8BF4\u660E\u3002";
183
205
  function evidenceToText(evidence) {
@@ -199,7 +221,7 @@ ${input.memberPrompt}
199
221
  \u751F\u6210\u6D88\u606F\u65F6\u9047\u5230\u4E0A\u8FF0 ID \u65F6\u4F18\u5148\u4F7F\u7528\u5BF9\u5E94\u7FA4\u6635\u79F0\uFF1B\u6CA1\u6709\u6620\u5C04\u65F6\u4FDD\u7559\u539F ID\uFF0C\u4E0D\u8981\u7F16\u9020\u6635\u79F0\u3002` : SYSTEM_PROMPT;
200
222
  const messages = [
201
223
  { role: "system", content: systemPrompt },
202
- { role: "user", content: `\u5F53\u524D\u65F6\u95F4\uFF1A${input.now.toISOString()}
224
+ { role: "user", content: `\u5F53\u524D\u65F6\u95F4\uFF1A${formatBeijingTimeForPrompt(input.now)}
203
225
  \u4EFB\u52A1\u63D0\u793A\u8BCD\uFF1A${input.prompt}` }
204
226
  ];
205
227
  const toolsByName = new Map(input.tools.map((tool) => [tool.name, tool]));
@@ -219,7 +241,7 @@ ${input.memberPrompt}
219
241
  { role: "system", content: systemPrompt },
220
242
  {
221
243
  role: "user",
222
- content: `\u5F53\u524D\u65F6\u95F4\uFF1A${input.now.toISOString()}
244
+ content: `\u5F53\u524D\u65F6\u95F4\uFF1A${formatBeijingTimeForPrompt(input.now)}
223
245
  \u4EFB\u52A1\u63D0\u793A\u8BCD\uFF1A${input.prompt}
224
246
 
225
247
  \u8BC1\u636E\uFF1A
@@ -247,7 +269,7 @@ ${evidenceToText(evidence)}`
247
269
  { role: "system", content: SYSTEM_PROMPT },
248
270
  {
249
271
  role: "user",
250
- content: `\u5F53\u524D\u65F6\u95F4\uFF1A${input.now.toISOString()}
272
+ content: `\u5F53\u524D\u65F6\u95F4\uFF1A${formatBeijingTimeForPrompt(input.now)}
251
273
  \u4EFB\u52A1\u63D0\u793A\u8BCD\uFF1A${input.prompt}
252
274
 
253
275
  \u8BC1\u636E\uFF1A
@@ -3202,7 +3224,7 @@ async function summarizeEpisodeWindow(window, model, now) {
3202
3224
  },
3203
3225
  {
3204
3226
  role: "user",
3205
- content: `\u5F53\u524D\u65F6\u95F4\uFF1A${now.toISOString()}
3227
+ content: `\u5F53\u524D\u65F6\u95F4\uFF1A${formatBeijingTimeForPrompt(now)}
3206
3228
  \u7FA4\u804A\uFF1A${window.chatName}
3207
3229
  \u65F6\u95F4\uFF1A${window.startedAt} - ${window.endedAt}
3208
3230
 
@@ -4072,7 +4094,7 @@ async function runFeishuToolLoop(input) {
4072
4094
  const systemPrompt = systemPromptParts.join("\n\n");
4073
4095
  const messages = [
4074
4096
  { role: "system", content: systemPrompt },
4075
- { role: "user", content: `\u5F53\u524D\u65F6\u95F4\uFF1A${input.now.toISOString()}
4097
+ { role: "user", content: `\u5F53\u524D\u65F6\u95F4\uFF1A${formatBeijingTimeForPrompt(input.now)}
4076
4098
  \u95EE\u9898\uFF1A${input.question}` }
4077
4099
  ];
4078
4100
  const toolsByName = new Map(input.tools.map((tool) => [tool.name, tool]));
@@ -4318,8 +4340,8 @@ function findMarkdownLinkEnd(text, start) {
4318
4340
  }
4319
4341
  return -1;
4320
4342
  }
4321
- function parseInline(text) {
4322
- const elements = [];
4343
+ function stripInlineMarkdown(text) {
4344
+ let output = "";
4323
4345
  let index = 0;
4324
4346
  while (index < text.length) {
4325
4347
  const linkStart = text.indexOf("[", index);
@@ -4328,12 +4350,10 @@ function parseInline(text) {
4328
4350
  const candidates = [linkStart, boldStarStart, boldUnderscoreStart].filter((value) => value >= 0);
4329
4351
  const next = candidates.length ? Math.min(...candidates) : -1;
4330
4352
  if (next < 0) {
4331
- elements.push({ tag: "text", text: text.slice(index) });
4353
+ output += text.slice(index);
4332
4354
  break;
4333
4355
  }
4334
- if (next > index) {
4335
- elements.push({ tag: "text", text: text.slice(index, next) });
4336
- }
4356
+ output += text.slice(index, next);
4337
4357
  if (next === linkStart) {
4338
4358
  const labelEnd = text.indexOf("](", next);
4339
4359
  if (labelEnd > next) {
@@ -4341,27 +4361,29 @@ function parseInline(text) {
4341
4361
  const hrefEnd = findMarkdownLinkEnd(text, hrefStart);
4342
4362
  const href = hrefEnd >= 0 ? text.slice(hrefStart, hrefEnd) : "";
4343
4363
  if (hrefEnd >= 0 && /^https?:\/\/\S+$/.test(href)) {
4344
- elements.push({ tag: "a", text: text.slice(next + 1, labelEnd), href });
4364
+ output += `${text.slice(next + 1, labelEnd)} ${href}`;
4345
4365
  index = hrefEnd + 1;
4346
4366
  continue;
4347
4367
  }
4348
4368
  }
4349
- elements.push({ tag: "text", text: text[next] });
4369
+ output += text[next];
4350
4370
  index = next + 1;
4351
4371
  continue;
4352
4372
  }
4353
4373
  const marker = next === boldStarStart ? "**" : "__";
4354
4374
  const close = text.indexOf(marker, next + marker.length);
4355
4375
  if (close > next + marker.length) {
4356
- elements.push({ tag: "text", text: text.slice(next + marker.length, close), style: ["bold"] });
4376
+ output += text.slice(next + marker.length, close);
4357
4377
  index = close + marker.length;
4358
4378
  continue;
4359
4379
  }
4360
- elements.push({ tag: "text", text: marker });
4380
+ output += marker;
4361
4381
  index = next + marker.length;
4362
4382
  }
4363
- const compacted = elements.filter((element) => element.tag !== "text" || element.text.length > 0);
4364
- return compacted.length ? compacted : [{ tag: "text", text: " " }];
4383
+ return output;
4384
+ }
4385
+ function parseInline(text) {
4386
+ return [{ tag: "text", text: stripInlineMarkdown(text) || " " }];
4365
4387
  }
4366
4388
  function pushParagraph(content, lines) {
4367
4389
  if (lines.length === 0) return;
@@ -4402,7 +4424,7 @@ ${code.join("\n")}
4402
4424
  const heading = line.match(/^#{1,6}\s+(.+)$/);
4403
4425
  if (heading) {
4404
4426
  pushParagraph(content, paragraph);
4405
- content.push([{ tag: "text", text: heading[1], style: ["bold"] }]);
4427
+ content.push([{ tag: "text", text: stripInlineMarkdown(heading[1]) || " " }]);
4406
4428
  continue;
4407
4429
  }
4408
4430
  const unordered = line.match(/^[-*]\s+(.+)$/);
@@ -4430,17 +4452,13 @@ function buildFeishuPostContent(markdown, options) {
4430
4452
  const content = parseMarkdownBlocks(markdown);
4431
4453
  const mentions = options?.mentions ?? [];
4432
4454
  if (mentions.length) {
4433
- const mentionElements = mentions.map((mention) => ({
4434
- tag: "at",
4435
- user_id: mention.openId,
4436
- user_name: mention.name
4437
- }));
4438
4455
  const firstLine = content[0] ?? [];
4439
4456
  const firstText = firstLine[0];
4457
+ const prefix = mentions.map((mention) => `@${mention.name}`).join(" ");
4440
4458
  if (firstText?.tag === "text") {
4441
- content[0] = [...mentionElements, { ...firstText, text: ` ${firstText.text}` }, ...firstLine.slice(1)];
4459
+ content[0] = [{ tag: "text", text: `${prefix} ${firstText.text}` }, ...firstLine.slice(1)];
4442
4460
  } else {
4443
- content[0] = [...mentionElements, { tag: "text", text: " " }, ...firstLine];
4461
+ content[0] = [{ tag: "text", text: `${prefix} ` }, ...firstLine];
4444
4462
  }
4445
4463
  }
4446
4464
  return {
@@ -5406,7 +5424,7 @@ function buildEvidencePrompt(input, options = {}) {
5406
5424
  },
5407
5425
  {
5408
5426
  role: "user",
5409
- content: `\u5F53\u524D\u65F6\u95F4\uFF1A${now.toISOString()}
5427
+ content: `\u5F53\u524D\u65F6\u95F4\uFF1A${formatBeijingTimeForPrompt(now)}
5410
5428
  \u95EE\u9898\uFF1A${question}
5411
5429
 
5412
5430
  \u8BC1\u636E\u5904\u7406\u89C4\u5219\uFF1A