@rikaidev/yomi 0.5.0 → 0.6.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/README.md +28 -0
- package/dist/ambient/ambient-event-graph.js +172 -0
- package/dist/ambient/ambient-observer.js +71 -0
- package/dist/ambient/event-graph-reducer.js +300 -0
- package/dist/ambient/ingestion-adapter.js +203 -0
- package/dist/ambient/journal/crypto.js +58 -0
- package/dist/ambient/journal/journal-store.js +284 -0
- package/dist/ambient/journal/types.js +7 -0
- package/dist/ambient/summaries/retriever.js +55 -0
- package/dist/ambient/summaries/summary-engine.js +128 -0
- package/dist/ambient/summaries/types.js +4 -0
- package/dist/attention/policy.js +22 -16
- package/dist/auth/credential-store.js +25 -12
- package/dist/cli/query.js +276 -69
- package/dist/cli/work-item.js +24 -0
- package/dist/line/client/auth-service/client.js +7 -8
- package/dist/line/client/buddy-service/client.js +73 -0
- package/dist/line/client/index.js +28 -1
- package/dist/line/client/obs-media-client.js +2 -1
- package/dist/line/client/square-service/client.js +298 -0
- package/dist/line/client/talk-service/command-client.js +9 -1
- package/dist/line/client/talk-service/message-id-query.js +27 -3
- package/dist/line/client/talk-service/requests.js +9 -0
- package/dist/line/core/auth-session-runtime.js +1 -1
- package/dist/line/core/chat-event.js +2 -0
- package/dist/line/core/chat-runtime-service.js +18 -3
- package/dist/line/core/config.js +1 -0
- package/dist/line/core/flex-message.js +323 -0
- package/dist/line/core/service.js +0 -1
- package/dist/mcp/handlers/contacts.js +12 -6
- package/dist/mcp/handlers/conversations.js +54 -0
- package/dist/mcp/handlers/send.js +8 -11
- package/dist/mcp/integrator.js +21 -7
- package/dist/mcp/media.js +101 -2
- package/dist/mcp/names.js +78 -6
- package/dist/search/default-embedder.js +12 -3
- package/dist/version.js +1 -1
- package/dist/work-item/adapter.js +1 -0
- package/dist/work-item/destination-contracts.js +1 -0
- package/dist/work-item/event-context.js +73 -0
- package/dist/work-item/gold-contract.js +101 -0
- package/dist/work-item/gold-coverage.js +96 -0
- package/dist/work-item/gold-derivation.js +67 -0
- package/dist/work-item/gold-split.js +143 -0
- package/dist/work-item/index.js +23 -0
- package/dist/work-item/line-adapter.js +111 -0
- package/dist/work-item/llama-cpp-work-event-adapter.js +239 -0
- package/dist/work-item/local-provider.js +38 -0
- package/dist/work-item/local-work-event-provider.js +56 -0
- package/dist/work-item/onnx-work-event-adapter.js +223 -0
- package/dist/work-item/provider.js +21 -0
- package/dist/work-item/registry.js +19 -0
- package/dist/work-item/service.js +85 -0
- package/dist/work-item/store.js +97 -0
- package/dist/work-item/types.js +79 -0
- package/dist/work-item/work-event-graph-engine.js +63 -0
- package/dist/work-item/work-event-inference.js +267 -0
- package/dist/work-item/work-event-matcher.js +105 -0
- package/dist/work-item/work-event-model-manifest.js +39 -0
- package/dist/work-item/work-event-store.js +125 -0
- package/dist/work-item/work-event.js +123 -0
- package/package.json +25 -4
- package/run.mjs +186 -9
package/run.mjs
CHANGED
|
@@ -46,6 +46,15 @@ const ext = built ? '.js' : '.ts';
|
|
|
46
46
|
/** Import a module by its path under src/, resolved to dist/ when built. */
|
|
47
47
|
const load = (path) => import(new URL(path + ext, base).href);
|
|
48
48
|
|
|
49
|
+
const writeStdout = (text) =>
|
|
50
|
+
new Promise((resolve, reject) => {
|
|
51
|
+
process.stdout.write(text, (error) => {
|
|
52
|
+
if (error) reject(error);
|
|
53
|
+
else resolve();
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
const writeJson = (value) => writeStdout(`${JSON.stringify(value)}\n`);
|
|
57
|
+
|
|
49
58
|
const args = process.argv.slice(2);
|
|
50
59
|
const cmd = args[0] ?? 'serve';
|
|
51
60
|
|
|
@@ -80,10 +89,91 @@ switch (cmd) {
|
|
|
80
89
|
const { cliListConversationsJson } = await load('cli/query');
|
|
81
90
|
const limit = args[1] && args[1] !== 'all' ? parseInt(args[1], 10) : undefined;
|
|
82
91
|
const attentionOnly = args.includes('--attention-only');
|
|
83
|
-
const firstPage = args.includes('--first-page');
|
|
84
92
|
const semantic = args.includes('--semantic');
|
|
85
|
-
const json = await cliListConversationsJson({ limit, attentionOnly,
|
|
86
|
-
|
|
93
|
+
const json = await cliListConversationsJson({ limit, attentionOnly, semantic });
|
|
94
|
+
await writeJson(json);
|
|
95
|
+
process.exit(0);
|
|
96
|
+
}
|
|
97
|
+
case 'desktop-inbox': {
|
|
98
|
+
// Keep one authenticated LINE runtime for the complete desktop startup
|
|
99
|
+
// pass. Its resume result is the session authority; do not infer logout
|
|
100
|
+
// from an empty list, a cache miss, or a second probe process.
|
|
101
|
+
const { LineProtocolService } = await load('line/core/service');
|
|
102
|
+
const { cliListConversationsJson } = await load('cli/query');
|
|
103
|
+
const service = new LineProtocolService();
|
|
104
|
+
const connected = await service.resumeSession();
|
|
105
|
+
if (!connected) {
|
|
106
|
+
await writeJson({
|
|
107
|
+
session: { connected: false, reason: service.loginReason ?? 'unavailable' },
|
|
108
|
+
chats: [],
|
|
109
|
+
});
|
|
110
|
+
process.exit(0);
|
|
111
|
+
}
|
|
112
|
+
const chats = await cliListConversationsJson({}, service);
|
|
113
|
+
await writeJson({ session: { connected: true, reason: null }, chats });
|
|
114
|
+
process.exit(0);
|
|
115
|
+
}
|
|
116
|
+
case 'desktop-startup-messages': {
|
|
117
|
+
// One shared runtime warms all requested rooms at launch. This is a
|
|
118
|
+
// startup batch, not a click-triggered series of independent sessions.
|
|
119
|
+
const { LineProtocolService } = await load('line/core/service');
|
|
120
|
+
const { cliGetChatMessagesJson } = await load('cli/query');
|
|
121
|
+
const chatIds = args.slice(1).filter(Boolean);
|
|
122
|
+
const service = new LineProtocolService();
|
|
123
|
+
const connected = await service.resumeSession();
|
|
124
|
+
if (!connected) {
|
|
125
|
+
await writeJson({
|
|
126
|
+
session: { connected: false, reason: service.loginReason ?? 'unavailable' },
|
|
127
|
+
messages: {},
|
|
128
|
+
});
|
|
129
|
+
process.exit(0);
|
|
130
|
+
}
|
|
131
|
+
const messages = {};
|
|
132
|
+
for (const chatId of chatIds) {
|
|
133
|
+
messages[chatId] = await cliGetChatMessagesJson(chatId, 40, service);
|
|
134
|
+
}
|
|
135
|
+
await writeJson({ session: { connected: true, reason: null }, messages });
|
|
136
|
+
process.exit(0);
|
|
137
|
+
}
|
|
138
|
+
case 'work-item': {
|
|
139
|
+
const operation = args[1] || 'create';
|
|
140
|
+
let input = '';
|
|
141
|
+
for await (const chunk of process.stdin) input += chunk;
|
|
142
|
+
let payload;
|
|
143
|
+
try {
|
|
144
|
+
payload = JSON.parse(input || '{}');
|
|
145
|
+
} catch {
|
|
146
|
+
console.error(JSON.stringify({ error: 'invalid JSON payload' }));
|
|
147
|
+
process.exit(1);
|
|
148
|
+
}
|
|
149
|
+
const { cliCreateWorkItemDraftJson, cliWorkItemOperationJson } = await load('cli/work-item');
|
|
150
|
+
try {
|
|
151
|
+
const result = operation === 'create'
|
|
152
|
+
? await cliCreateWorkItemDraftJson(
|
|
153
|
+
payload.messages || payload.message,
|
|
154
|
+
payload.options || {},
|
|
155
|
+
)
|
|
156
|
+
: await cliWorkItemOperationJson(operation, payload.draft);
|
|
157
|
+
await writeJson(result);
|
|
158
|
+
process.exit(0);
|
|
159
|
+
} catch (error) {
|
|
160
|
+
console.error(JSON.stringify({ error: error instanceof Error ? error.message : String(error) }));
|
|
161
|
+
process.exit(1);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
case 'ambient-observe': {
|
|
165
|
+
const { scanAmbientObservations } = await load('ambient/ambient-observer');
|
|
166
|
+
const since = args[1] ? Number(args[1]) : undefined;
|
|
167
|
+
const report = await scanAmbientObservations(Number.isFinite(since) ? since : undefined);
|
|
168
|
+
// Work-event promotion intentionally abstains until the factorized model
|
|
169
|
+
// contract passes its independent acceptance suite. Ambient candidates
|
|
170
|
+
// remain available as revisable evidence; no flat classifier is allowed
|
|
171
|
+
// to create authoritative work items.
|
|
172
|
+
await writeJson({ ...report, workItems: [] });
|
|
173
|
+
process.exit(0);
|
|
174
|
+
}
|
|
175
|
+
case 'work-items': {
|
|
176
|
+
await writeJson([]);
|
|
87
177
|
process.exit(0);
|
|
88
178
|
}
|
|
89
179
|
case 'messages':
|
|
@@ -96,7 +186,20 @@ switch (cmd) {
|
|
|
96
186
|
process.exit(1);
|
|
97
187
|
}
|
|
98
188
|
const json = await cliGetChatMessagesJson(chatId, count);
|
|
99
|
-
|
|
189
|
+
await writeJson(json);
|
|
190
|
+
process.exit(0);
|
|
191
|
+
}
|
|
192
|
+
case 'rich-menu': {
|
|
193
|
+
const chatId = args[1];
|
|
194
|
+
if (!chatId) {
|
|
195
|
+
console.error(JSON.stringify({ error: 'chatId required' }));
|
|
196
|
+
process.exit(1);
|
|
197
|
+
}
|
|
198
|
+
const { LineProtocolService } = await load('line/core/service');
|
|
199
|
+
const service = new LineProtocolService();
|
|
200
|
+
if (!(await service.resumeSession())) process.exit(1);
|
|
201
|
+
const menu = await service.client.getBuddyRichMenu(chatId);
|
|
202
|
+
await writeJson(menu);
|
|
100
203
|
process.exit(0);
|
|
101
204
|
}
|
|
102
205
|
case 'attention-classify': {
|
|
@@ -104,13 +207,13 @@ switch (cmd) {
|
|
|
104
207
|
let input = '';
|
|
105
208
|
for await (const chunk of process.stdin) input += chunk;
|
|
106
209
|
const items = JSON.parse(input || '[]');
|
|
107
|
-
|
|
210
|
+
await writeJson(await cliClassifyAttentionJson(items));
|
|
108
211
|
process.exit(0);
|
|
109
212
|
}
|
|
110
213
|
case 'list-stickers': {
|
|
111
214
|
const { cliListStickersJson } = await load('cli/query');
|
|
112
215
|
const language = args[1] || 'zh_TW';
|
|
113
|
-
|
|
216
|
+
await writeJson(await cliListStickersJson(language));
|
|
114
217
|
process.exit(0);
|
|
115
218
|
}
|
|
116
219
|
case 'sticker-previews': {
|
|
@@ -122,7 +225,7 @@ switch (cmd) {
|
|
|
122
225
|
console.error(JSON.stringify({ error: 'packageId required' }));
|
|
123
226
|
process.exit(1);
|
|
124
227
|
}
|
|
125
|
-
|
|
228
|
+
await writeJson(await cliStickerPreviewsJson(packageId, limit, language));
|
|
126
229
|
process.exit(0);
|
|
127
230
|
}
|
|
128
231
|
case 'send-sticker': {
|
|
@@ -165,6 +268,29 @@ switch (cmd) {
|
|
|
165
268
|
}));
|
|
166
269
|
process.exit(0);
|
|
167
270
|
}
|
|
271
|
+
case 'unsend-message':
|
|
272
|
+
case 'unsend': {
|
|
273
|
+
const messageId = args[1];
|
|
274
|
+
if (!messageId) {
|
|
275
|
+
console.error(JSON.stringify({ error: 'messageId required' }));
|
|
276
|
+
process.exit(1);
|
|
277
|
+
}
|
|
278
|
+
const { LineProtocolService } = await load('line/core/service');
|
|
279
|
+
const service = new LineProtocolService();
|
|
280
|
+
if (!(await service.resumeSession())) process.exit(1);
|
|
281
|
+
try {
|
|
282
|
+
const res = await service.unsendMessage(messageId);
|
|
283
|
+
console.log(JSON.stringify({
|
|
284
|
+
unsent: true,
|
|
285
|
+
messageId,
|
|
286
|
+
...res,
|
|
287
|
+
}));
|
|
288
|
+
process.exit(0);
|
|
289
|
+
} catch (err) {
|
|
290
|
+
console.error(JSON.stringify({ error: err.message || String(err) }));
|
|
291
|
+
process.exit(1);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
168
294
|
case 'send-image': {
|
|
169
295
|
const chatId = args[1];
|
|
170
296
|
const imagePath = args[2];
|
|
@@ -215,6 +341,32 @@ switch (cmd) {
|
|
|
215
341
|
}));
|
|
216
342
|
process.exit(0);
|
|
217
343
|
}
|
|
344
|
+
case 'send-audio': {
|
|
345
|
+
const chatId = args[1];
|
|
346
|
+
const filePath = args[2];
|
|
347
|
+
const fileName = args[3];
|
|
348
|
+
if (!chatId || !filePath) {
|
|
349
|
+
console.error(JSON.stringify({ error: 'chatId and filePath required' }));
|
|
350
|
+
process.exit(1);
|
|
351
|
+
}
|
|
352
|
+
const { LineProtocolService } = await load('line/core/service');
|
|
353
|
+
const { readFile } = await import('node:fs/promises');
|
|
354
|
+
const { basename } = await import('node:path');
|
|
355
|
+
const service = new LineProtocolService();
|
|
356
|
+
if (!(await service.resumeSession())) process.exit(1);
|
|
357
|
+
const bytes = await readFile(filePath);
|
|
358
|
+
if (bytes.length === 0) {
|
|
359
|
+
console.error(JSON.stringify({ error: 'audio is empty' }));
|
|
360
|
+
process.exit(1);
|
|
361
|
+
}
|
|
362
|
+
const sent = await service.sendAudio(chatId, bytes, fileName || basename(filePath));
|
|
363
|
+
console.log(JSON.stringify({
|
|
364
|
+
sent: true,
|
|
365
|
+
messageId: sent?.messageId ?? sent?.id ?? null,
|
|
366
|
+
oid: sent?.oid ?? null,
|
|
367
|
+
}));
|
|
368
|
+
process.exit(0);
|
|
369
|
+
}
|
|
218
370
|
case 'media-preview': {
|
|
219
371
|
const chatId = args[1];
|
|
220
372
|
const messageId = args[2];
|
|
@@ -227,11 +379,21 @@ switch (cmd) {
|
|
|
227
379
|
const service = new LineProtocolService();
|
|
228
380
|
if (!(await service.resumeSession())) process.exit(1);
|
|
229
381
|
const result = await fetchLineMessageMedia(service, chatId, messageId, args[3] !== 'original');
|
|
230
|
-
|
|
382
|
+
if (args.includes('--file-output')) {
|
|
383
|
+
const { mkdtemp, writeFile } = await import('node:fs/promises');
|
|
384
|
+
const { join } = await import('node:path');
|
|
385
|
+
const { tmpdir } = await import('node:os');
|
|
386
|
+
const directory = await mkdtemp(join(tmpdir(), 'yomi-media-'));
|
|
387
|
+
const filePath = join(directory, 'payload');
|
|
388
|
+
await writeFile(filePath, result.bytes, { mode: 0o600 });
|
|
389
|
+
await writeJson({ filePath, mimeType: result.mimeType, fileName: result.fileName ?? null });
|
|
390
|
+
process.exit(0);
|
|
391
|
+
}
|
|
392
|
+
await writeJson({
|
|
231
393
|
data: result.bytes.toString('base64'),
|
|
232
394
|
mimeType: result.mimeType,
|
|
233
395
|
fileName: result.fileName ?? null,
|
|
234
|
-
})
|
|
396
|
+
});
|
|
235
397
|
process.exit(0);
|
|
236
398
|
}
|
|
237
399
|
case 'mark-read': {
|
|
@@ -246,6 +408,20 @@ switch (cmd) {
|
|
|
246
408
|
console.log(JSON.stringify(res));
|
|
247
409
|
process.exit(0);
|
|
248
410
|
}
|
|
411
|
+
case 'set-chat-muted': {
|
|
412
|
+
const chatId = args[1];
|
|
413
|
+
const disabled = args[2] === 'true';
|
|
414
|
+
if (!chatId?.startsWith('u') || !['true', 'false'].includes(args[2])) {
|
|
415
|
+
console.error(JSON.stringify({ error: '1:1 chatId and true|false required' }));
|
|
416
|
+
process.exit(1);
|
|
417
|
+
}
|
|
418
|
+
const { LineProtocolService } = await load('line/core/service');
|
|
419
|
+
const service = new LineProtocolService();
|
|
420
|
+
if (!(await service.resumeSession())) process.exit(1);
|
|
421
|
+
await service.client.updateContactNotificationDisabled(chatId, disabled);
|
|
422
|
+
console.log(JSON.stringify({ success: true, chatId, isMuted: disabled }));
|
|
423
|
+
process.exit(0);
|
|
424
|
+
}
|
|
249
425
|
case 'summary':
|
|
250
426
|
case 'recent':
|
|
251
427
|
case 'query': {
|
|
@@ -266,6 +442,7 @@ Usage:
|
|
|
266
442
|
yomi Start the MCP stdio server (default)
|
|
267
443
|
yomi serve Same as above, explicit
|
|
268
444
|
yomi login [...] Run the passwordless login flow in a terminal
|
|
445
|
+
yomi unsend <id> Retract (unsend) a message sent within the last hour
|
|
269
446
|
yomi help Show this help
|
|
270
447
|
yomi version Print version
|
|
271
448
|
|