kiku-agent 1.0.11 → 1.2.0
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 +300 -495
- package/package.json +12 -11
- package/public/fonts/GoogleSans-Bold.ttf +0 -0
- package/public/fonts/GoogleSans-Bold.woff2 +0 -0
- package/public/fonts/GoogleSans-BoldItalic.ttf +0 -0
- package/public/fonts/GoogleSans-Italic.ttf +0 -0
- package/public/fonts/GoogleSans-Latin-400.woff2 +0 -0
- package/public/fonts/GoogleSans-Latin-500.woff2 +0 -0
- package/public/fonts/GoogleSans-Latin-600.woff2 +0 -0
- package/public/fonts/GoogleSans-Latin-700.woff2 +0 -0
- package/public/fonts/GoogleSans-Medium.ttf +0 -0
- package/public/fonts/GoogleSans-Medium.woff2 +0 -0
- package/public/fonts/GoogleSans-Regular.ttf +0 -0
- package/public/fonts/GoogleSans-Regular.woff2 +0 -0
- package/public/fonts/GoogleSans-Thai-400.woff2 +0 -0
- package/public/fonts/GoogleSans-Thai-500.woff2 +0 -0
- package/public/fonts/GoogleSans-Thai-600.woff2 +0 -0
- package/public/fonts/GoogleSans-Thai-700.woff2 +0 -0
- package/public/fonts/NotoSansThai-Bold.woff2 +0 -0
- package/public/fonts/NotoSansThai-Regular.woff2 +0 -0
- package/public/fonts/google-sans-official.css +900 -0
- package/public/images/0040jbadgy1id6am4yxqfj61s82dn1kx02.jpg +0 -0
- package/public/images/0040jbadgy1id6am708pbj62c0340qv602.jpg +0 -0
- package/public/images/0040jbadgy1id6amb81uqj62c0340x6q02.jpg +0 -0
- package/public/images/0040jbadgy1id6amcqte3j62c0340qv602.jpg +0 -0
- package/public/images/0040jbadgy1id6amdg3xcj62b232wqv502.jpg +0 -0
- package/public/images/0040jbadgy1id6amexv23j620v2pau0x02.jpg +0 -0
- package/public/images/0040jbadly8icq3if7twwj60qy0qy0uc02.jpg +0 -0
- package/public/images/008ET7Legy1ig9s89nri5j30i20n1gn4.jpg +0 -0
- package/public/images/008ET7Legy1ig9s8a2lmlj30i20ny409.jpg +0 -0
- package/public/images/008ET7Legy1ig9s8ay1hsj30i20nk3zv.jpg +0 -0
- package/public/images/008ET7Legy1ig9s8bab6sj30i20o7go1.jpg +0 -0
- package/public/images/008ET7Legy1ig9s8blqsxj30i20oiq4r.jpg +0 -0
- package/public/images/008ET7Legy1ig9s8cbxkzj30i20mxmzh.jpg +0 -0
- package/public/images/douyin-update/thumbs//346/212/226/351/237/2632026820-399915.jpg +0 -0
- package/public/images/douyin-update/thumbs//346/212/226/351/237/2632026820-424041.jpg +0 -0
- package/public/images/douyin-update/thumbs//346/212/226/351/237/2632026820-588166.jpg +0 -0
- package/public/images/douyin-update/thumbs//346/212/226/351/237/2632026820-672198.jpg +0 -0
- package/public/images/douyin-update/thumbs//346/212/226/351/237/2632026820-700522.jpg +0 -0
- package/public/images/douyin-update/thumbs//346/212/226/351/237/2632026820-839722.jpg +0 -0
- package/public/images/douyin-update/thumbs//346/212/226/351/237/2632026825-460586.jpg +0 -0
- package/public/images/douyin-update/thumbs//346/212/226/351/237/263202694-689407.jpg +0 -0
- package/public/images/douyin-update//346/212/226/351/237/2632026820-399915.mp4 +0 -0
- package/public/images/douyin-update//346/212/226/351/237/2632026820-424041.mp4 +0 -0
- package/public/images/douyin-update//346/212/226/351/237/2632026820-588166.mp4 +0 -0
- package/public/images/douyin-update//346/212/226/351/237/2632026820-672198.mp4 +0 -0
- package/public/images/douyin-update//346/212/226/351/237/2632026820-700522.mp4 +0 -0
- package/public/images/douyin-update//346/212/226/351/237/2632026820-839722.mp4 +0 -0
- package/public/images/douyin-update//346/212/226/351/237/2632026825-460586.mp4 +0 -0
- package/public/images/douyin-update//346/212/226/351/237/263202694-689407.mp4 +0 -0
- package/public/images/general/0040jbadgy1id6am4yxqfj61s82dn1kx02.jpg +0 -0
- package/public/images/general/0040jbadgy1id6am708pbj62c0340qv602.jpg +0 -0
- package/public/images/general/0040jbadgy1id6amb81uqj62c0340x6q02.jpg +0 -0
- package/public/images/general/0040jbadgy1id6amcqte3j62c0340qv602.jpg +0 -0
- package/public/images/general/0040jbadgy1id6amdg3xcj62b232wqv502.jpg +0 -0
- package/public/images/general/0040jbadgy1id6amexv23j620v2pau0x02.jpg +0 -0
- package/public/images/general/0040jbadly8icq3if7twwj60qy0qy0uc02.jpg +0 -0
- package/public/images/general/008ET7Legy1ig9s89nri5j30i20n1gn4.jpg +0 -0
- package/public/images/general/008ET7Legy1ig9s8a2lmlj30i20ny409.jpg +0 -0
- package/public/images/general/008ET7Legy1ig9s8ay1hsj30i20nk3zv.jpg +0 -0
- package/public/images/general/008ET7Legy1ig9s8bab6sj30i20o7go1.jpg +0 -0
- package/public/images/general/008ET7Legy1ig9s8blqsxj30i20oiq4r.jpg +0 -0
- package/public/images/general/008ET7Legy1ig9s8cbxkzj30i20mxmzh.jpg +0 -0
- package/public/images/general/jujingyi_portrait.jpg +0 -0
- package/public/images/jujingyi_portrait.jpg +0 -0
- package/public/images/series/a-millenniums-wait/poster.jpg +0 -0
- package/public/images/series/beauty-of-resilience/poster.jpg +0 -0
- package/public/images/series/detective-samoyeds/poster.jpg +0 -0
- package/public/images/series/everyday/poster.jpg +0 -0
- package/public/images/series/fu-rong-ancient-painting/poster.jpg +0 -0
- package/public/images/series/in-a-class-of-her-own/poster.jpg +0 -0
- package/public/images/series/in-blossom/poster.jpg +0 -0
- package/public/images/series/legend-of-yunxi/poster.jpg +0 -0
- package/public/images/series/lets-fight/poster-2.jpg +0 -0
- package/public/images/series/lets-fight/poster.jpg +0 -0
- package/public/images/series/love-emergency/poster.jpg +0 -0
- package/public/images/series/love-under-the-full-moon/poster.jpg +0 -0
- package/public/images/series/money-bastion/poster.jpg +0 -0
- package/public/images/series/mr-swimmer/poster.jpg +0 -0
- package/public/images/series/novoland-castle-in-the-sky/poster.jpg +0 -0
- package/public/images/series/please-give-me-a-pair-of-wings/poster.jpg +0 -0
- package/public/images/series/rebirth-for-you/poster.jpg +0 -0
- package/public/images/series/sword-and-fairy-4/poster.jpg +0 -0
- package/public/images/series/the-blooms-at-ruyi-pavilion/poster.jpg +0 -0
- package/public/images/series/the-eternal-fragrance/poster-2.jpg +0 -0
- package/public/images/series/the-eternal-fragrance/poster.jpg +0 -0
- package/public/images/series/the-fallen-flowers/poster.jpg +0 -0
- package/public/images/series/the-legend-of-white-snake/poster.jpg +0 -0
- package/public/images/series/veil-of-shadows/poster.jpg +0 -0
- package/public/images/series/wanhua-sin/poster-2.jpg +0 -0
- package/public/images/series/wanhua-sin/poster.jpg +0 -0
- package/public/images/weibo-update/41/345/210/206/351/222/237/345/211/215/0040jbadgy1igrkj10yogj62u03s0npe02.jpg +0 -0
- package/public/images/weibo-update/41/345/210/206/351/222/237/345/211/215/0040jbadgy1igrkj2pdvyj61li25jkjl02.jpg +0 -0
- package/public/images/weibo-update/41/345/210/206/351/222/237/345/211/215/0040jbadgy1igrkj71177j62672w9e8302.jpg +0 -0
- package/public/images/weibo-update/41/345/210/206/351/222/237/345/211/215/0040jbadgy1igrkj7twpfj62192197rw02.jpg +0 -0
- package/public/images/weibo-update/41/345/210/206/351/222/237/345/211/215/0040jbadgy1igrkj8jfu8j62c03401kx02.jpg +0 -0
- package/public/images/weibo-update/41/345/210/206/351/222/237/345/211/215/0040jbadgy1igrkj9dhdsj622k2l77wh02.jpg +0 -0
- package/public/images/weibo-update/41/345/210/206/351/222/237/345/211/215/0040jbadgy1igrkja31s4j62bw3407r802.jpg +0 -0
- package/public/images/weibo-update/41/345/210/206/351/222/237/345/211/215/0040jbadgy1igrkjcf331j61402ey1kx02.jpg +0 -0
- package/public/images/weibo-update/41/345/210/206/351/222/237/345/211/215/0040jbadgy1igrkjdx8gqj62602pihdt02.jpg +0 -0
- package/public/images/weibo-update/41/345/210/206/351/222/237/345/211/215/0040jbadgy1igrkjfvxnzj62432n57wh02.jpg +0 -0
- package/public/images/weibo-update/8-14-17-16/0040jbadgy1ig3ixniv2yj627y4fxb2b02.jpg +0 -0
- package/public/images/weibo-update/8-14-17-16/0040jbadgy1ig3ixsvbdaj625k2vfu1102.jpg +0 -0
- package/public/images/weibo-update/8-14-17-16/0040jbadgy1ig3ixxxdaoj62c03501l202.jpg +0 -0
- package/public/images/weibo-update/8-14-17-16/0040jbadgy1ig3ixzeef9j62c0340npd02.jpg +0 -0
- package/public/images/weibo-update/8-14-17-16/0040jbadgy1ig3iy0vs6tj626t4rbhdu02.jpg +0 -0
- package/public/images/weibo-update/8-14-17-16/0040jbadgy1ig3iy21wwuj62bt34hx6q02.jpg +0 -0
- package/public/images/weibo-update/8-8-17-39/0040jbadgy1ifwly4wr85j62z629y7wh02.jpg +0 -0
- package/public/images/weibo-update/8-8-17-39/0040jbadgy1ifwly67oilj623u2t5npd02.jpg +0 -0
- package/public/images/weibo-update/8-8-17-39/0040jbadgy1ifwly9qtw8j62c0340u0x02.jpg +0 -0
- package/public/images/weibo-update/8-8-17-39/0040jbadgy1ifwlyem4m4j63402c01kz02.jpg +0 -0
- package/public/images/weibo-update/8-8-17-39/0040jbadgy1ifwlygkoq4j627s2yeavd02.jpg +0 -0
- package/public/images/weibo-update/8-8-17-39/0040jbadgy1ifwlyjh0daj62bw340nm102.jpg +0 -0
- package/public/images/weibo-update/8-8-17-39/0040jbadgy1ifwlylejlhj62bw3401kx02.jpg +0 -0
- package/public/images/weibo-update/today/0040jbadgy1igaiaa8b7fj627j2y67wh02.jpg +0 -0
- package/public/images/weibo-update/today/0040jbadgy1igaiagw3ezj61s02ebu0x02.jpg +0 -0
- package/public/images/weibo-update/today/0040jbadgy1igaiaivng3j61rv2ebx6p02.jpg +0 -0
- package/public/images/weibo-update/today/0040jbadgy1igaiajuixvj62bw340qv502.jpg +0 -0
- package/public/images/weibo-update/today/0040jbadgy1igaiapyartj62bw340hdt02.jpg +0 -0
- package/public/images/weibo-update/today/0040jbadgy1igaibkwu4ij61vy2iq1kx02.jpg +0 -0
- package/public/images/weibo-update/today/0040jbadgy1igaic1fvkpj61u92eo1ky02.jpg +0 -0
- package/public/images/weibo-update/today/0040jbadgy1igaic3cruhj62822ywb2902.jpg +0 -0
- package/public/manifest.json +25 -0
- package/public/mcp-logo-128.png +0 -0
- package/public/mcp-logo-64.png +0 -0
- package/public/mcp-logo.svg +16 -0
- package/server/agent/agentCore.js +542 -74
- package/server/agent/appPaths.js +1 -0
- package/server/agent/audioPlayer.js +4 -2
- package/server/agent/citations.js +294 -0
- package/server/agent/clarificationAnalytics.js +477 -0
- package/server/agent/clarifyingQuestions.js +1089 -0
- package/server/agent/cli.js +549 -125
- package/server/agent/commandFeatures.js +1 -0
- package/server/agent/commandRegistry.js +946 -879
- package/server/agent/commands.js +546 -272
- package/server/agent/config.js +581 -412
- package/server/agent/contextCompactor.js +2 -2
- package/server/agent/debate.js +235 -0
- package/server/agent/eventBus.js +3 -0
- package/server/agent/feedbackLearning.js +217 -0
- package/server/agent/llmClient.js +512 -394
- package/server/agent/mcpClient.js +182 -32
- package/server/agent/memory.js +283 -224
- package/server/agent/modelManager.js +79 -39
- package/server/agent/profiles.js +178 -0
- package/server/agent/publicTools.js +22 -0
- package/server/agent/queryDetails.js +68 -8
- package/server/agent/quizData.js +398 -384
- package/server/agent/research.js +121 -79
- package/server/agent/sanitizer.js +104 -13
- package/server/agent/session.js +319 -11
- package/server/agent/subagent.js +8 -3
- package/server/agent/suggestionTui.js +294 -0
- package/server/agent/suggestions.js +69 -3
- package/server/agent/telemetry.js +119 -0
- package/server/agent/terminalImage.js +146 -27
- package/server/agent/theme.js +17 -0
- package/server/agent/toolRouter.js +16 -1
- package/server/agent/tools.js +424 -225
- package/server/agent/ui.js +486 -64
- package/server/agent/version.js +2 -4
- package/server/agent/webSearch.js +111 -11
- package/server/agent/youtubeAuth.js +24 -6
- package/server/apiRouter.js +4222 -0
- package/server/mcp/data/discography.js +25 -16
- package/server/mcp/data/gallery.js +308 -20
- package/server/mcp/data/profile.js +74 -44
- package/server/mcp/data/timeline.js +1 -1
- package/server/mcp/data/works.js +51 -17
- package/server/mcp/dataAdapter.js +5 -3
- package/server/mcp/handler.js +5 -11
- package/server/mcp/prompts.js +86 -0
- package/server/mcp/security.js +18 -15
- package/server/mcp/server.js +7 -2
- package/server/mcp/tools.js +66 -2
- package/server/web-chat/core/browserLauncher.js +18 -0
- package/server/web-chat/core/connection.js +194 -0
- package/server/web-chat/core/conversationContext.js +82 -0
- package/server/web-chat/core/directCatalogEngine.js +196 -0
- package/server/web-chat/core/dramaKnowledge.js +142 -0
- package/server/web-chat/core/errorHandler.js +51 -0
- package/server/web-chat/core/followUpEngine.js +182 -0
- package/server/web-chat/core/futureEventGuard.js +80 -0
- package/server/web-chat/core/memorySnapshot.js +12 -0
- package/server/web-chat/core/security.js +146 -0
- package/server/web-chat/core/toolInspector.js +52 -0
- package/server/web-chat/router.js +120 -0
- package/server/web-chat/routes/chatRoute.js +397 -0
- package/server/web-chat/routes/clarifyConfigRoute.js +98 -0
- package/server/web-chat/routes/clarifyRoute.js +83 -0
- package/server/web-chat/routes/compareRoute.js +79 -0
- package/server/web-chat/routes/exportRoute.js +59 -0
- package/server/web-chat/routes/feedbackRoute.js +57 -0
- package/server/web-chat/routes/newsRoute.js +33 -0
- package/server/web-chat/routes/quizRoute.js +11 -0
- package/server/web-chat/routes/staticRoute.js +103 -0
- package/server/web-chat/routes/statusRoute.js +52 -0
- package/server/web-chat/routes/suggestRoute.js +77 -0
- package/server/web-chat/routes/timelineRoute.js +34 -0
- package/server/web-chat/routes/verifyRoute.js +57 -0
- package/server/web-chat/server.js +116 -0
- package/server/web-chat/ui/htmlBuilder.js +91 -0
- package/server/web-chat/ui/previews/agentBubble.preview.html +134 -0
- package/server/web-chat/ui/scripts/agentBubbleSystem.js +320 -0
- package/server/web-chat/ui/scripts/client.js +8397 -0
- package/server/web-chat/ui/scripts/kikuDb.js +177 -0
- package/server/web-chat/ui/scripts/suggestionsData.js +118 -0
- package/server/web-chat/ui/scripts/webchatI18n.js +291 -0
- package/server/web-chat/ui/styles/main.css +8568 -0
- package/server/web-chat/ui/templates/body.html +796 -0
- package/server/webChatHtml.js +1 -0
- package/server/webChatServer.js +6 -0
- package/src/data/discographyData.js +892 -866
- package/src/data/galleryData.js +1805 -561
- package/src/data/profileData.js +79 -2
- package/src/data/socialUpdatesData.js +106 -47
- package/src/data/timelineData.js +1 -1
- package/src/data/worksData.js +25 -4
- package/tokens.css +97 -0
- package/server/agent/updateManager.js +0 -456
|
@@ -2,11 +2,15 @@ import { readFileSync, readdirSync } from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
4
|
import jpeg from 'jpeg-js';
|
|
5
|
+
import { galleryData } from '../../src/data/galleryData.js';
|
|
5
6
|
|
|
6
7
|
const moduleDirectory = path.dirname(fileURLToPath(import.meta.url));
|
|
7
|
-
export const DEFAULT_IMAGE_DIRECTORY = path.resolve(moduleDirectory, '../../
|
|
8
|
+
export const DEFAULT_IMAGE_DIRECTORY = path.resolve(moduleDirectory, '../../public/images');
|
|
9
|
+
export const FALLBACK_IMAGE_DIRECTORY = path.resolve(moduleDirectory, '../../src/assets/images');
|
|
8
10
|
|
|
9
11
|
const RESET = '\x1b[0m';
|
|
12
|
+
const BOLD = '\x1b[1m';
|
|
13
|
+
const DIM = '\x1b[2m';
|
|
10
14
|
const foreground = (r, g, b) => `\x1b[38;2;${r};${g};${b}m`;
|
|
11
15
|
const background = (r, g, b) => `\x1b[48;2;${r};${g};${b}m`;
|
|
12
16
|
const QUADRANT_GLYPHS = [
|
|
@@ -54,7 +58,7 @@ function sampleBilinear(image, x, y, targetWidth, targetHeight) {
|
|
|
54
58
|
return result;
|
|
55
59
|
}
|
|
56
60
|
|
|
57
|
-
function resizeAndEnhance(image, targetWidth, targetHeight) {
|
|
61
|
+
function resizeAndEnhance(image, targetWidth, targetHeight, { sharpness = 1.25, contrast = 1.05 } = {}) {
|
|
58
62
|
const pixels = new Float32Array(targetWidth * targetHeight * 3);
|
|
59
63
|
for (let y = 0; y < targetHeight; y++) {
|
|
60
64
|
for (let x = 0; x < targetWidth; x++) {
|
|
@@ -78,16 +82,22 @@ function resizeAndEnhance(image, targetWidth, targetHeight) {
|
|
|
78
82
|
const offset = (y * targetWidth + x) * 3;
|
|
79
83
|
const sharpened = [0, 1, 2].map(channel => {
|
|
80
84
|
const center = at(x, y, channel);
|
|
81
|
-
const
|
|
85
|
+
const crossAverage = (
|
|
82
86
|
at(x - 1, y, channel) + at(x + 1, y, channel)
|
|
83
87
|
+ at(x, y - 1, channel) + at(x, y + 1, channel)
|
|
84
88
|
) / 4;
|
|
85
|
-
|
|
89
|
+
const diagAverage = (
|
|
90
|
+
at(x - 1, y - 1, channel) + at(x + 1, y - 1, channel)
|
|
91
|
+
+ at(x - 1, y + 1, channel) + at(x + 1, y + 1, channel)
|
|
92
|
+
) / 4;
|
|
93
|
+
const neighborAverage = crossAverage * 0.7 + diagAverage * 0.3;
|
|
94
|
+
return center * (1 + 0.28 * sharpness) - neighborAverage * (0.28 * sharpness);
|
|
86
95
|
});
|
|
96
|
+
|
|
87
97
|
const luminance = sharpened[0] * 0.2126 + sharpened[1] * 0.7152 + sharpened[2] * 0.0722;
|
|
88
98
|
for (let channel = 0; channel < 3; channel++) {
|
|
89
|
-
const saturated = luminance + (sharpened[channel] - luminance) * 1.
|
|
90
|
-
enhanced[offset + channel] = clampChannel((saturated - 128) *
|
|
99
|
+
const saturated = luminance + (sharpened[channel] - luminance) * 1.08;
|
|
100
|
+
enhanced[offset + channel] = clampChannel((saturated - 128) * contrast + 128);
|
|
91
101
|
}
|
|
92
102
|
}
|
|
93
103
|
}
|
|
@@ -98,7 +108,8 @@ function colorDistance(left, right) {
|
|
|
98
108
|
const red = left[0] - right[0];
|
|
99
109
|
const green = left[1] - right[1];
|
|
100
110
|
const blue = left[2] - right[2];
|
|
101
|
-
|
|
111
|
+
// Human eye perceptual luminance weighting
|
|
112
|
+
return red * red * 0.299 + green * green * 0.587 + blue * blue * 0.114;
|
|
102
113
|
}
|
|
103
114
|
|
|
104
115
|
function averageColors(colors, fallback) {
|
|
@@ -127,7 +138,7 @@ function encodeQuadrants(colors) {
|
|
|
127
138
|
}
|
|
128
139
|
|
|
129
140
|
let assignments = [0, 0, 0, 0];
|
|
130
|
-
for (let iteration = 0; iteration <
|
|
141
|
+
for (let iteration = 0; iteration < 4; iteration++) {
|
|
131
142
|
assignments = colors.map(color => colorDistance(color, second) < colorDistance(color, first) ? 1 : 0);
|
|
132
143
|
first = averageColors(colors.filter((_, index) => assignments[index] === 0), first);
|
|
133
144
|
second = averageColors(colors.filter((_, index) => assignments[index] === 1), second);
|
|
@@ -147,6 +158,8 @@ export function renderJpegToAnsi(buffer, {
|
|
|
147
158
|
maxWidth = 60,
|
|
148
159
|
maxRows = 20,
|
|
149
160
|
indent = ' ',
|
|
161
|
+
sharpness = 1.25,
|
|
162
|
+
contrast = 1.05,
|
|
150
163
|
} = {}) {
|
|
151
164
|
const image = jpeg.decode(buffer, { useTArray: true, formatAsRGBA: true });
|
|
152
165
|
if (!image?.width || !image?.height) throw new Error('Unable to decode gallery image');
|
|
@@ -165,7 +178,7 @@ export function renderJpegToAnsi(buffer, {
|
|
|
165
178
|
}
|
|
166
179
|
|
|
167
180
|
const sampledWidth = targetWidth * 2;
|
|
168
|
-
const resized = resizeAndEnhance(image, sampledWidth, targetPixelHeight);
|
|
181
|
+
const resized = resizeAndEnhance(image, sampledWidth, targetPixelHeight, { sharpness, contrast });
|
|
169
182
|
const pixelAt = (x, y) => {
|
|
170
183
|
const offset = (y * sampledWidth + x) * 3;
|
|
171
184
|
return [resized[offset], resized[offset + 1], resized[offset + 2]];
|
|
@@ -196,15 +209,37 @@ export function renderJpegFile(filePath, options = {}) {
|
|
|
196
209
|
return renderJpegToAnsi(readFileSync(filePath), options);
|
|
197
210
|
}
|
|
198
211
|
|
|
199
|
-
export function discoverImages(directory) {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
212
|
+
export function discoverImages(directory = DEFAULT_IMAGE_DIRECTORY) {
|
|
213
|
+
function scanDir(dir) {
|
|
214
|
+
let list = [];
|
|
215
|
+
try {
|
|
216
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
217
|
+
for (const entry of entries) {
|
|
218
|
+
const fullPath = path.join(dir, entry.name);
|
|
219
|
+
if (entry.isDirectory()) {
|
|
220
|
+
list = list.concat(scanDir(fullPath));
|
|
221
|
+
} else if (entry.isFile() && /\.jpe?g$/i.test(entry.name)) {
|
|
222
|
+
list.push(fullPath);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
} catch {}
|
|
226
|
+
return list;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
let results = scanDir(directory);
|
|
230
|
+
if (results.length === 0 && directory !== FALLBACK_IMAGE_DIRECTORY) {
|
|
231
|
+
results = scanDir(FALLBACK_IMAGE_DIRECTORY);
|
|
207
232
|
}
|
|
233
|
+
return results.sort((a, b) => a.localeCompare(b));
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
export function findGalleryMetadata(filePath) {
|
|
237
|
+
if (!filePath || !Array.isArray(galleryData)) return null;
|
|
238
|
+
const basename = path.basename(filePath).toLowerCase();
|
|
239
|
+
return galleryData.find(item => {
|
|
240
|
+
if (!item.image) return false;
|
|
241
|
+
return item.image.toLowerCase().includes(basename);
|
|
242
|
+
}) || null;
|
|
208
243
|
}
|
|
209
244
|
|
|
210
245
|
export function renderTwoImagesSideBySide(filePath1, filePath2, {
|
|
@@ -214,7 +249,7 @@ export function renderTwoImagesSideBySide(filePath1, filePath2, {
|
|
|
214
249
|
} = {}) {
|
|
215
250
|
const availableWidth = Math.max(20, Math.floor(columns));
|
|
216
251
|
const sideBySide = availableWidth >= 76;
|
|
217
|
-
const singleMaxWidth = sideBySide ? Math.min(
|
|
252
|
+
const singleMaxWidth = sideBySide ? Math.min(36, Math.floor((availableWidth - 8) / 2)) : Math.min(50, availableWidth - 4);
|
|
218
253
|
|
|
219
254
|
const img1 = renderJpegFile(filePath1, {
|
|
220
255
|
columns: singleMaxWidth + 4,
|
|
@@ -253,6 +288,67 @@ export function renderTwoImagesSideBySide(filePath1, filePath2, {
|
|
|
253
288
|
return combined;
|
|
254
289
|
}
|
|
255
290
|
|
|
291
|
+
export function renderHdGalleryCard(filePath, {
|
|
292
|
+
index = 0,
|
|
293
|
+
total = 1,
|
|
294
|
+
columns = process.stdout.columns || 80,
|
|
295
|
+
rows = process.stdout.rows || 28,
|
|
296
|
+
maxWidth = 64,
|
|
297
|
+
maxRows = 22,
|
|
298
|
+
} = {}) {
|
|
299
|
+
const meta = findGalleryMetadata(filePath);
|
|
300
|
+
const titleCn = meta?.titleCn || path.basename(filePath);
|
|
301
|
+
const titleTh = meta?.titleTh || '';
|
|
302
|
+
const dateStr = meta?.date || meta?.era || '';
|
|
303
|
+
const styleVibe = meta?.styleVibe || '';
|
|
304
|
+
const quote = meta?.quote?.cn || '';
|
|
305
|
+
const quoteTh = meta?.quote?.th || '';
|
|
306
|
+
|
|
307
|
+
const imageLines = renderJpegFile(filePath, {
|
|
308
|
+
columns,
|
|
309
|
+
rows,
|
|
310
|
+
maxWidth,
|
|
311
|
+
maxRows,
|
|
312
|
+
indent: ' ',
|
|
313
|
+
sharpness: 1.4,
|
|
314
|
+
contrast: 1.08,
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
const lines = [];
|
|
318
|
+
lines.push('');
|
|
319
|
+
lines.push(` ${BOLD}\x1b[38;2;255;126;179m🌸 JU JINGYI • 鞠婧祎 HD GALLERY\x1b[0m \x1b[38;2;148;163;184m• Gallery ${index + 1}/${total}\x1b[0m`);
|
|
320
|
+
lines.push(` \x1b[38;2;251;191;36m◆ ${titleCn}\x1b[0m ${dateStr ? `\x1b[38;2;148;163;184m(${dateStr})\x1b[0m` : ''}`);
|
|
321
|
+
if (titleTh) {
|
|
322
|
+
lines.push(` \x1b[38;2;226;232;240m${DIM}${titleTh}${RESET}`);
|
|
323
|
+
}
|
|
324
|
+
lines.push('');
|
|
325
|
+
lines.push(...imageLines);
|
|
326
|
+
lines.push('');
|
|
327
|
+
|
|
328
|
+
if (styleVibe) {
|
|
329
|
+
lines.push(` \x1b[38;2;244;114;182m✨ Vibe:\x1b[0m \x1b[38;2;203;213;225m${styleVibe}\x1b[0m`);
|
|
330
|
+
}
|
|
331
|
+
if (quote) {
|
|
332
|
+
lines.push(` \x1b[38;2;251;191;36m💬 语录:\x1b[0m \x1b[38;2;248;250;252m“${quote}”\x1b[0m`);
|
|
333
|
+
if (quoteTh) {
|
|
334
|
+
lines.push(` ${DIM} “${quoteTh}”${RESET}`);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
if (meta?.colorPalette && Array.isArray(meta.colorPalette) && meta.colorPalette.length > 0) {
|
|
338
|
+
const swatches = meta.colorPalette.map(c => {
|
|
339
|
+
const hex = (c.hex || '').replace('#', '');
|
|
340
|
+
const r = parseInt(hex.slice(0, 2), 16) || 200;
|
|
341
|
+
const g = parseInt(hex.slice(2, 4), 16) || 200;
|
|
342
|
+
const b = parseInt(hex.slice(4, 6), 16) || 200;
|
|
343
|
+
return `${background(r, g, b)}${foreground(0, 0, 0)} ${c.name} ${RESET}`;
|
|
344
|
+
}).join(' ');
|
|
345
|
+
lines.push(` \x1b[38;2;148;163;184m🎨 Palette:\x1b[0m ${swatches}`);
|
|
346
|
+
}
|
|
347
|
+
lines.push('');
|
|
348
|
+
|
|
349
|
+
return lines;
|
|
350
|
+
}
|
|
351
|
+
|
|
256
352
|
export function getWelcomeGalleryLines(count = 2, {
|
|
257
353
|
directory = DEFAULT_IMAGE_DIRECTORY,
|
|
258
354
|
env = process.env,
|
|
@@ -305,24 +401,46 @@ export function createTerminalImageGallery({
|
|
|
305
401
|
return {
|
|
306
402
|
enabled,
|
|
307
403
|
imageCount: images.length,
|
|
308
|
-
|
|
404
|
+
getImagePaths: () => [...images],
|
|
405
|
+
maybeRender(completedQueries = 0, { force = false, count = 1, hd = false, index = null } = {}) {
|
|
309
406
|
const cadence = Math.max(1, Math.floor(frequency));
|
|
310
407
|
if (!enabled || (!force && (completedQueries <= 0 || completedQueries % cadence !== 0))) return [];
|
|
311
408
|
|
|
409
|
+
const targetIdx = index !== null && !isNaN(index) ? Math.abs(Number(index)) % images.length : imageIndex % images.length;
|
|
410
|
+
|
|
411
|
+
if (hd) {
|
|
412
|
+
const filePath = images[targetIdx];
|
|
413
|
+
try {
|
|
414
|
+
const hdCard = renderHdGalleryCard(filePath, {
|
|
415
|
+
index: targetIdx,
|
|
416
|
+
total: images.length,
|
|
417
|
+
columns: getColumns(),
|
|
418
|
+
rows: getRows(),
|
|
419
|
+
maxWidth: 62,
|
|
420
|
+
maxRows: 22,
|
|
421
|
+
});
|
|
422
|
+
imageIndex = (targetIdx + 1) % images.length;
|
|
423
|
+
return hdCard;
|
|
424
|
+
} catch {
|
|
425
|
+
return [];
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
312
429
|
if (count >= 2 && images.length >= 2) {
|
|
313
|
-
const idx1 =
|
|
314
|
-
const idx2 = (
|
|
430
|
+
const idx1 = targetIdx;
|
|
431
|
+
const idx2 = (targetIdx + 1) % images.length;
|
|
315
432
|
const path1 = images[idx1];
|
|
316
433
|
const path2 = images[idx2];
|
|
317
434
|
try {
|
|
318
435
|
const pairLines = renderTwoImagesSideBySide(path1, path2, {
|
|
319
436
|
columns: getColumns(),
|
|
320
437
|
rows: getRows(),
|
|
438
|
+
maxRows: 16,
|
|
321
439
|
});
|
|
322
|
-
imageIndex = (
|
|
440
|
+
imageIndex = (targetIdx + 2) % images.length;
|
|
323
441
|
return [
|
|
324
442
|
'',
|
|
325
|
-
` \x1b[1m\x1b[38;2;255;126;179m
|
|
443
|
+
` \x1b[1m\x1b[38;2;255;126;179m🌸 JU JINGYI • 鞠婧祎 GALLERY\x1b[0m \x1b[38;2;148;163;184m• Photos ${idx1 + 1} & ${idx2 + 1}/${images.length}\x1b[0m`,
|
|
326
444
|
...pairLines,
|
|
327
445
|
'',
|
|
328
446
|
];
|
|
@@ -331,17 +449,18 @@ export function createTerminalImageGallery({
|
|
|
331
449
|
}
|
|
332
450
|
}
|
|
333
451
|
|
|
334
|
-
const
|
|
335
|
-
const filePath = images[currentIndex];
|
|
452
|
+
const filePath = images[targetIdx];
|
|
336
453
|
try {
|
|
337
454
|
const imageLines = renderJpegFile(filePath, {
|
|
338
455
|
columns: getColumns(),
|
|
339
456
|
rows: getRows(),
|
|
457
|
+
maxWidth: 60,
|
|
458
|
+
maxRows: 20,
|
|
340
459
|
});
|
|
341
|
-
imageIndex
|
|
460
|
+
imageIndex = (targetIdx + 1) % images.length;
|
|
342
461
|
return [
|
|
343
462
|
'',
|
|
344
|
-
` \x1b[1m\x1b[38;2;255;126;179m
|
|
463
|
+
` \x1b[1m\x1b[38;2;255;126;179m🌸 KIKU MOMENT\x1b[0m \x1b[38;2;148;163;184m• Gallery ${targetIdx + 1}/${images.length}\x1b[0m`,
|
|
345
464
|
...imageLines,
|
|
346
465
|
'',
|
|
347
466
|
];
|
package/server/agent/theme.js
CHANGED
|
@@ -107,11 +107,28 @@ export function setTheme(name, { persist = true } = {}) {
|
|
|
107
107
|
return getTheme(normalized);
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
let explicitColorDisabled = null;
|
|
111
|
+
|
|
112
|
+
export function isColorDisabled() {
|
|
113
|
+
if (explicitColorDisabled !== null) return explicitColorDisabled;
|
|
114
|
+
if (typeof process !== 'undefined' && process.env) {
|
|
115
|
+
if (process.env.NO_COLOR !== undefined && process.env.NO_COLOR !== '') return true;
|
|
116
|
+
if (process.env.NODE_DISABLE_COLORS === '1') return true;
|
|
117
|
+
}
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function setColorDisabled(disabled) {
|
|
122
|
+
explicitColorDisabled = disabled === null ? null : Boolean(disabled);
|
|
123
|
+
}
|
|
124
|
+
|
|
110
125
|
export function ansiForeground(rgb) {
|
|
126
|
+
if (isColorDisabled()) return '';
|
|
111
127
|
return `\x1b[38;2;${rgb}m`;
|
|
112
128
|
}
|
|
113
129
|
|
|
114
130
|
export function ansiBackground(rgb) {
|
|
131
|
+
if (isColorDisabled()) return '';
|
|
115
132
|
return `\x1b[48;2;${rgb}m`;
|
|
116
133
|
}
|
|
117
134
|
|
|
@@ -58,6 +58,7 @@ const DEFAULT_UNIVERSAL_TOOLS = Object.freeze([
|
|
|
58
58
|
'get_profile_and_fandom',
|
|
59
59
|
'get_media_links',
|
|
60
60
|
'web_search',
|
|
61
|
+
'web_extract',
|
|
61
62
|
'run_subagent',
|
|
62
63
|
]);
|
|
63
64
|
|
|
@@ -167,6 +168,7 @@ export class DynamicToolRouter {
|
|
|
167
168
|
}
|
|
168
169
|
selectedNames.add('global_search');
|
|
169
170
|
selectedNames.add('web_search');
|
|
171
|
+
selectedNames.add('web_extract');
|
|
170
172
|
}
|
|
171
173
|
|
|
172
174
|
if (options.includeExtra && Array.isArray(options.includeExtra)) {
|
|
@@ -178,14 +180,27 @@ export class DynamicToolRouter {
|
|
|
178
180
|
const routed = [...pinnedTools];
|
|
179
181
|
const seenNames = new Set(pinnedTools.map(t => t.function?.name));
|
|
180
182
|
|
|
183
|
+
|
|
181
184
|
for (const tool of this.allTools) {
|
|
182
185
|
const name = tool.function?.name;
|
|
183
|
-
if (name && !
|
|
186
|
+
if (name && !name.startsWith('mcp_') && !seenNames.has(name) && selectedNames.has(name)) {
|
|
184
187
|
seenNames.add(name);
|
|
185
188
|
routed.push(tool);
|
|
186
189
|
}
|
|
187
190
|
}
|
|
188
191
|
|
|
192
|
+
|
|
193
|
+
const wantsMcpExplicitly = options.includeMcp === true || atMentions.some(m => m.toLowerCase().includes('mcp'));
|
|
194
|
+
if (wantsMcpExplicitly || routed.length < 3) {
|
|
195
|
+
for (const tool of this.allTools) {
|
|
196
|
+
const name = tool.function?.name;
|
|
197
|
+
if (name && name.startsWith('mcp_') && !seenNames.has(name) && (selectedNames.has(name) || wantsMcpExplicitly)) {
|
|
198
|
+
seenNames.add(name);
|
|
199
|
+
routed.push(tool);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
189
204
|
if (routed.length === 0) {
|
|
190
205
|
return this.allTools.slice(0, 8);
|
|
191
206
|
}
|