metame-cli 1.3.16 → 1.3.18

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.
@@ -38,7 +38,7 @@ function createBot(config) {
38
38
  * Send a plain text message
39
39
  */
40
40
  async sendMessage(chatId, text) {
41
- await client.im.message.create({
41
+ const res = await client.im.message.create({
42
42
  params: { receive_id_type: 'chat_id' },
43
43
  data: {
44
44
  receive_id: chatId,
@@ -46,20 +46,91 @@ function createBot(config) {
46
46
  content: JSON.stringify({ text }),
47
47
  },
48
48
  });
49
+ // Return Telegram-compatible shape so daemon can edit it later
50
+ const msgId = res?.data?.message_id;
51
+ return msgId ? { message_id: msgId } : null;
52
+ },
53
+
54
+ async editMessage(chatId, messageId, text) {
55
+ try {
56
+ await client.im.message.patch({
57
+ path: { message_id: messageId },
58
+ data: { content: JSON.stringify({ text }) },
59
+ });
60
+ } catch { /* non-fatal */ }
49
61
  },
50
62
 
51
63
  /**
52
- * Send markdown (Feishu doesn't support raw markdown sends as text)
64
+ * Send markdown as Feishu interactive card (lark_md renders bold, lists, code, links)
53
65
  */
54
66
  async sendMarkdown(chatId, markdown) {
55
- await client.im.message.create({
67
+ // Convert standard markdown → lark_md compatible format
68
+ let content = markdown
69
+ .replace(/^(#{1,3})\s+(.+)$/gm, '**$2**') // headers → bold
70
+ .replace(/^---+$/gm, '─────────────────────'); // hr → unicode line
71
+
72
+ // Split into chunks if too long (lark_md element limit ~4000 chars)
73
+ const MAX_CHUNK = 3800;
74
+ const chunks = [];
75
+ if (content.length <= MAX_CHUNK) {
76
+ chunks.push(content);
77
+ } else {
78
+ // Split on double newlines to avoid breaking mid-paragraph
79
+ const paragraphs = content.split(/\n\n/);
80
+ let buf = '';
81
+ for (const p of paragraphs) {
82
+ if (buf.length + p.length + 2 > MAX_CHUNK && buf) {
83
+ chunks.push(buf);
84
+ buf = p;
85
+ } else {
86
+ buf = buf ? buf + '\n\n' + p : p;
87
+ }
88
+ }
89
+ if (buf) chunks.push(buf);
90
+ }
91
+
92
+ const elements = chunks.map(c => ({
93
+ tag: 'div',
94
+ text: { tag: 'lark_md', content: c },
95
+ }));
96
+
97
+ const card = {
98
+ config: { wide_screen_mode: true },
99
+ elements,
100
+ };
101
+
102
+ const res = await client.im.message.create({
56
103
  params: { receive_id_type: 'chat_id' },
57
104
  data: {
58
105
  receive_id: chatId,
59
- msg_type: 'text',
60
- content: JSON.stringify({ text: markdown }),
106
+ msg_type: 'interactive',
107
+ content: JSON.stringify(card),
61
108
  },
62
109
  });
110
+ const msgId = res?.data?.message_id;
111
+ return msgId ? { message_id: msgId } : null;
112
+ },
113
+
114
+ /**
115
+ * Send a colored interactive card (for project-tagged notifications)
116
+ * @param {string} chatId
117
+ * @param {string} title - card header text
118
+ * @param {string} body - card body (lark markdown)
119
+ * @param {string} color - header color: blue|orange|green|red|grey|purple|turquoise
120
+ */
121
+ async sendCard(chatId, { title, body, color = 'blue' }) {
122
+ const elements = body ? [{ tag: 'div', text: { tag: 'lark_md', content: body } }] : [];
123
+ const card = {
124
+ config: { wide_screen_mode: true },
125
+ header: { title: { tag: 'plain_text', content: title }, template: color },
126
+ elements,
127
+ };
128
+ const res = await client.im.message.create({
129
+ params: { receive_id_type: 'chat_id' },
130
+ data: { receive_id: chatId, msg_type: 'interactive', content: JSON.stringify(card) },
131
+ });
132
+ const msgId = res?.data?.message_id;
133
+ return msgId ? { message_id: msgId } : null;
63
134
  },
64
135
 
65
136
  /**
@@ -13,7 +13,6 @@ const path = require('path');
13
13
  const os = require('os');
14
14
 
15
15
  const BUFFER_FILE = path.join(os.homedir(), '.metame', 'raw_signals.jsonl');
16
- const MAX_BUFFER_LINES = 50; // Safety cap to avoid unbounded growth
17
16
 
18
17
  // === CONFIDENCE PATTERNS ===
19
18
 
@@ -110,11 +109,6 @@ process.stdin.on('end', () => {
110
109
 
111
110
  existingLines.push(JSON.stringify(entry));
112
111
 
113
- // Keep only the most recent entries (drop oldest)
114
- if (existingLines.length > MAX_BUFFER_LINES) {
115
- existingLines = existingLines.slice(-MAX_BUFFER_LINES);
116
- }
117
-
118
112
  fs.writeFileSync(BUFFER_FILE, existingLines.join('\n') + '\n');
119
113
 
120
114
  } catch {