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
package/server/agent/cli.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import readline from 'node:readline';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
4
5
|
import { stdin as input } from 'node:process';
|
|
5
6
|
import { existsSync } from 'node:fs';
|
|
6
7
|
import { spawn } from 'node:child_process';
|
|
@@ -15,11 +16,14 @@ import { eventBus, Events } from './eventBus.js';
|
|
|
15
16
|
import { AgentStates } from './agentState.js';
|
|
16
17
|
import { sanitizeQuery } from './sanitizer.js';
|
|
17
18
|
import { isAbortError, formatExecutionErrorCard } from './errors.js';
|
|
18
|
-
import { COMMAND_DEFINITIONS, SUB_COMMANDS, findCommandDefinition, getCommandDetails } from './commandRegistry.js';
|
|
19
|
+
import { COMMAND_DEFINITIONS, COMMAND_CATEGORIES, SUB_COMMANDS, findCommandDefinition, getCommandDetails } from './commandRegistry.js';
|
|
19
20
|
import { ModelManager } from './modelManager.js';
|
|
20
21
|
import { PACKAGE_VERSION } from './version.js';
|
|
21
|
-
import {
|
|
22
|
+
import { getProfile, listProfiles } from './profiles.js';
|
|
23
|
+
import { formatCitationsBlock } from './citations.js';
|
|
24
|
+
import { getTheme, getThemeName, setTheme, THEME_NAMES, setColorDisabled } from './theme.js';
|
|
22
25
|
import { createTerminalImageGallery, getWelcomeGalleryLines } from './terminalImage.js';
|
|
26
|
+
import { formatQuestionsForCLI } from './clarifyingQuestions.js';
|
|
23
27
|
import {
|
|
24
28
|
classifyToolResult,
|
|
25
29
|
formatDetailDuration,
|
|
@@ -33,7 +37,7 @@ import {
|
|
|
33
37
|
import {
|
|
34
38
|
C, getStringDisplayWidth, getFullWidth, wrapText, stripAnsi, fitStyledText, sanitizeTerminalText,
|
|
35
39
|
previousGraphemeBoundary, nextGraphemeBoundary, sliceLineForDisplay,
|
|
36
|
-
printSolidBannerRow, printSolidPanel, formatSolidPanelLines, formatTerminalMarkdown,
|
|
40
|
+
printSolidBannerRow, printSolidPanel, formatSolidPanelLines, formatTerminalMarkdown, formatMarkdownLines,
|
|
37
41
|
parseMarkdownTableRow, isMarkdownTableSeparator, expandMarkdownLinks,
|
|
38
42
|
formatRichCardLines, printRichCard, printRichStatusCard, formatStatusBadge, formatRichTable,
|
|
39
43
|
printWelcomeHero, getWelcomeHeroLines, randomFanName, setupOutputInterception,
|
|
@@ -53,9 +57,64 @@ const deferredCommands = [];
|
|
|
53
57
|
let globalTuiPrompt = null;
|
|
54
58
|
let lastQueryDetails = null;
|
|
55
59
|
const queryDetails = new Map();
|
|
60
|
+
let globalSpinnerInterval = null;
|
|
56
61
|
|
|
57
|
-
function
|
|
58
|
-
|
|
62
|
+
function startGlobalSpinner(label) {
|
|
63
|
+
if (globalTuiPrompt) {
|
|
64
|
+
if (label !== undefined && label !== null) {
|
|
65
|
+
globalTuiPrompt.agentState = label;
|
|
66
|
+
globalTuiPrompt.agentStateTime = Date.now();
|
|
67
|
+
}
|
|
68
|
+
globalTuiPrompt.render();
|
|
69
|
+
}
|
|
70
|
+
if (!globalSpinnerInterval) {
|
|
71
|
+
globalSpinnerInterval = setInterval(() => {
|
|
72
|
+
if (globalTuiPrompt && isProcessing) {
|
|
73
|
+
globalTuiPrompt.render();
|
|
74
|
+
}
|
|
75
|
+
}, 80);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function stopGlobalSpinner() {
|
|
80
|
+
if (globalSpinnerInterval) {
|
|
81
|
+
clearInterval(globalSpinnerInterval);
|
|
82
|
+
globalSpinnerInterval = null;
|
|
83
|
+
}
|
|
84
|
+
if (globalTuiPrompt) {
|
|
85
|
+
globalTuiPrompt.agentState = '';
|
|
86
|
+
globalTuiPrompt.render();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function recordQueryDiagnostics(details) {
|
|
91
|
+
if (!details) return null;
|
|
92
|
+
const num = details.number ?? nextQueryNumber++;
|
|
93
|
+
lastQueryDetails = {
|
|
94
|
+
number: num,
|
|
95
|
+
prompt: details.prompt || '',
|
|
96
|
+
answer: details.answer || '',
|
|
97
|
+
thinking: details.thinking || '',
|
|
98
|
+
tools: details.tools || [],
|
|
99
|
+
status: details.status || 'complete',
|
|
100
|
+
error: details.error || null,
|
|
101
|
+
provider: details.provider || 'unknown',
|
|
102
|
+
model: details.model || 'unknown',
|
|
103
|
+
language: details.language || null,
|
|
104
|
+
iterations: details.iterations || (details.tools?.length ? 1 : 0),
|
|
105
|
+
maxIterations: details.maxIterations || 3,
|
|
106
|
+
startedAt: details.startedAt || Date.now(),
|
|
107
|
+
completedAt: details.completedAt || Date.now(),
|
|
108
|
+
durationMs: details.durationMs || (details.completedAt && details.startedAt ? details.completedAt - details.startedAt : 0),
|
|
109
|
+
timestamp: Date.now(),
|
|
110
|
+
};
|
|
111
|
+
queryDetails.set(num, lastQueryDetails);
|
|
112
|
+
if (queryDetails.size > 50) queryDetails.delete(queryDetails.keys().next().value);
|
|
113
|
+
return lastQueryDetails;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function parseCliArgs(customArgs = null) {
|
|
117
|
+
const args = customArgs || process.argv.slice(2);
|
|
59
118
|
const options = {
|
|
60
119
|
query: null,
|
|
61
120
|
provider: null,
|
|
@@ -63,12 +122,20 @@ function parseCliArgs() {
|
|
|
63
122
|
model: null,
|
|
64
123
|
url: null,
|
|
65
124
|
mcp: null,
|
|
125
|
+
profile: null,
|
|
66
126
|
showTools: false,
|
|
67
127
|
showStats: false,
|
|
68
128
|
thinking: 'show',
|
|
69
129
|
verbose: false,
|
|
70
130
|
help: false,
|
|
71
|
-
version: false
|
|
131
|
+
version: false,
|
|
132
|
+
print: false,
|
|
133
|
+
output: 'text',
|
|
134
|
+
plain: false,
|
|
135
|
+
noColor: false,
|
|
136
|
+
webChat: false,
|
|
137
|
+
port: null,
|
|
138
|
+
noOpen: false,
|
|
72
139
|
};
|
|
73
140
|
|
|
74
141
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -85,8 +152,54 @@ function parseCliArgs() {
|
|
|
85
152
|
else if (arg === '--model' || arg === '-m') options.model = args[++i];
|
|
86
153
|
else if (arg === '--url' || arg === '-u') options.url = args[++i];
|
|
87
154
|
else if (arg === '--query' || arg === '-q') options.query = args[++i];
|
|
155
|
+
else if (arg === '--profile') options.profile = args[++i];
|
|
156
|
+
else if (arg === '--print' || arg === '-p') options.print = true;
|
|
157
|
+
else if (arg === '--output' || arg === '-o') options.output = (args[++i] || 'text').toLowerCase();
|
|
158
|
+
else if (arg === '--plain') { options.plain = true; options.noColor = true; }
|
|
159
|
+
else if (arg === '--no-color') options.noColor = true;
|
|
160
|
+
else if (arg === '--web-chat' || arg === '--web') options.webChat = true;
|
|
161
|
+
else if (arg.startsWith('--web-chat=')) {
|
|
162
|
+
options.webChat = true;
|
|
163
|
+
const maybePort = Number(arg.slice('--web-chat='.length));
|
|
164
|
+
if (Number.isFinite(maybePort) && maybePort > 0) options.port = Math.trunc(maybePort);
|
|
165
|
+
}
|
|
166
|
+
else if (arg === '--port') {
|
|
167
|
+
const maybePort = Number(args[++i]);
|
|
168
|
+
if (!Number.isFinite(maybePort) || maybePort < 1 || maybePort > 65535) {
|
|
169
|
+
console.error(`Invalid --port: ${args[i]}. Expected 1-65535.`);
|
|
170
|
+
process.exit(3);
|
|
171
|
+
}
|
|
172
|
+
options.port = Math.trunc(maybePort);
|
|
173
|
+
}
|
|
174
|
+
else if (arg.startsWith('--port=')) {
|
|
175
|
+
const maybePort = Number(arg.slice('--port='.length));
|
|
176
|
+
if (!Number.isFinite(maybePort) || maybePort < 1 || maybePort > 65535) {
|
|
177
|
+
console.error(`Invalid --port: ${arg}. Expected 1-65535.`);
|
|
178
|
+
process.exit(3);
|
|
179
|
+
}
|
|
180
|
+
options.port = Math.trunc(maybePort);
|
|
181
|
+
}
|
|
182
|
+
else if (arg === '--no-open') options.noOpen = true;
|
|
183
|
+
else if (arg === '--open') options.noOpen = false;
|
|
88
184
|
else if (!arg.startsWith('-') && !options.query) { options.query = args.slice(i).join(' '); break; }
|
|
185
|
+
else if (arg.startsWith('-')) {
|
|
186
|
+
console.error(`Unknown option: ${arg}`);
|
|
187
|
+
process.exit(3);
|
|
188
|
+
}
|
|
89
189
|
}
|
|
190
|
+
|
|
191
|
+
if (options.output !== 'text' && options.output !== 'json') {
|
|
192
|
+
console.error(`Invalid --output format: ${options.output}. Supported formats: text, json`);
|
|
193
|
+
process.exit(3);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (options.noColor || options.plain || (typeof process !== 'undefined' && process.env?.NO_COLOR)) {
|
|
197
|
+
setColorDisabled(true);
|
|
198
|
+
}
|
|
199
|
+
if (options.output === 'json') {
|
|
200
|
+
options.print = true;
|
|
201
|
+
}
|
|
202
|
+
|
|
90
203
|
return options;
|
|
91
204
|
}
|
|
92
205
|
|
|
@@ -236,7 +349,7 @@ function printQueryDetails(reference = '') {
|
|
|
236
349
|
printSolidPanel({
|
|
237
350
|
title: `Answer • ${queryLabel}`,
|
|
238
351
|
lines: details.answer
|
|
239
|
-
?
|
|
352
|
+
? formatMarkdownLines(details.answer, width - 4)
|
|
240
353
|
: [`${C.dim}${C.slate}No final answer was recorded.${C.reset}`],
|
|
241
354
|
});
|
|
242
355
|
return;
|
|
@@ -292,7 +405,7 @@ function printQueryDetails(reference = '') {
|
|
|
292
405
|
const copyable = getCopyableContent(details, request);
|
|
293
406
|
printSolidPanel({
|
|
294
407
|
title: copyable.title,
|
|
295
|
-
lines: copyable.text
|
|
408
|
+
lines: formatMarkdownLines(copyable.text, width - 4),
|
|
296
409
|
});
|
|
297
410
|
return;
|
|
298
411
|
}
|
|
@@ -338,19 +451,33 @@ function copyQueryDetails(reference = '', session = null) {
|
|
|
338
451
|
return false;
|
|
339
452
|
}
|
|
340
453
|
|
|
454
|
+
if (request.isSession) {
|
|
455
|
+
if (!session || !session.messages || session.messages.length === 0) {
|
|
456
|
+
console.log(`\n ${C.amber}[EMPTY] No conversation messages in the current session to copy.${C.reset}\n`);
|
|
457
|
+
return false;
|
|
458
|
+
}
|
|
459
|
+
} else {
|
|
460
|
+
const details = request.queryNumber == null
|
|
461
|
+
? lastQueryDetails
|
|
462
|
+
: queryDetails.get(request.queryNumber);
|
|
463
|
+
|
|
464
|
+
if (!details) {
|
|
465
|
+
const target = request.queryNumber == null ? 'the latest query' : `Q${request.queryNumber}`;
|
|
466
|
+
console.log(`\n ${C.amber}[NOT FOUND] No diagnostics recorded for ${target}. Ask a question or run a tool first.${C.reset}\n`);
|
|
467
|
+
return false;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
341
471
|
const details = request.queryNumber == null
|
|
342
472
|
? lastQueryDetails
|
|
343
473
|
: queryDetails.get(request.queryNumber);
|
|
344
474
|
|
|
345
|
-
if (!details && !request.isSession && !session) {
|
|
346
|
-
const target = request.queryNumber == null ? 'the latest query' : `Q${request.queryNumber}`;
|
|
347
|
-
console.log(`\n ${C.amber}[NOT FOUND] No diagnostics recorded for ${target}.${C.reset}\n`);
|
|
348
|
-
return false;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
475
|
const copyable = getCopyableContent(details, request, session);
|
|
352
|
-
if (!copyable || !copyable.text) {
|
|
353
|
-
|
|
476
|
+
if (!copyable || !copyable.text || !copyable.text.trim()) {
|
|
477
|
+
const target = request.isSession
|
|
478
|
+
? 'the active session'
|
|
479
|
+
: (request.queryNumber == null ? `the latest query (${request.view})` : `Q${request.queryNumber} (${request.view})`);
|
|
480
|
+
console.log(`\n ${C.amber}[EMPTY] Nothing recorded to copy for ${target}.${C.reset}\n`);
|
|
354
481
|
return false;
|
|
355
482
|
}
|
|
356
483
|
|
|
@@ -437,23 +564,55 @@ export function printHelp(specificCmd = null) {
|
|
|
437
564
|
const termWidth = getFullWidth();
|
|
438
565
|
const maxContentWidth = Math.max(40, termWidth - 8);
|
|
439
566
|
const helpLines = [];
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
567
|
+
const cmdMap = new Map(COMMAND_DEFINITIONS.map(c => [c.name, c]));
|
|
568
|
+
const categories = Array.isArray(COMMAND_CATEGORIES) && COMMAND_CATEGORIES.length > 0
|
|
569
|
+
? COMMAND_CATEGORIES
|
|
570
|
+
: [{ id: 'all', name: 'All Commands', icon: '✦', commands: COMMAND_DEFINITIONS.map(c => c.name) }];
|
|
571
|
+
|
|
572
|
+
for (const cat of categories) {
|
|
573
|
+
helpLines.push(`${C.bold}${C.sakura}${cat.icon || '✦'} ${cat.name}${C.reset}`);
|
|
574
|
+
for (const cmdName of cat.commands) {
|
|
575
|
+
const command = cmdMap.get(cmdName);
|
|
576
|
+
if (!command) continue;
|
|
577
|
+
const usageWidth = 30;
|
|
578
|
+
const descWidth = maxContentWidth - usageWidth - 4;
|
|
579
|
+
|
|
580
|
+
if (command.usage.length > 28 || command.desc.length > descWidth) {
|
|
581
|
+
const wrappedDesc = wrapText(command.desc, maxContentWidth - 8);
|
|
582
|
+
helpLines.push(` ${C.emerald}${command.usage}${C.reset}`);
|
|
583
|
+
for (const d of wrappedDesc) {
|
|
584
|
+
helpLines.push(` ${C.dim}↳${C.reset} ${C.white}${d}${C.reset}`);
|
|
585
|
+
}
|
|
586
|
+
} else {
|
|
587
|
+
helpLines.push(` ${C.emerald}${command.usage.padEnd(usageWidth)}${C.reset} ${C.white}${command.desc}${C.reset}`);
|
|
450
588
|
}
|
|
451
|
-
} else {
|
|
452
|
-
helpLines.push(`${C.emerald}${command.usage.padEnd(usageWidth)}${C.reset} ${C.white}${command.desc}${C.reset}`);
|
|
453
589
|
}
|
|
590
|
+
helpLines.push('');
|
|
454
591
|
}
|
|
455
592
|
|
|
456
|
-
helpLines.
|
|
593
|
+
if (helpLines[helpLines.length - 1] === '') helpLines.pop();
|
|
594
|
+
helpLines.push('', `${C.dim}Tip: Press Tab for auto-completion • Type /help <command> (e.g. /help session, /help provider, /help mcp) for detailed subcommand breakdowns.${C.reset}`);
|
|
595
|
+
|
|
596
|
+
helpLines.push('', `${C.bold}${C.sakura}✦ CLI Flags & Options${C.reset}`);
|
|
597
|
+
helpLines.push(` ${C.emerald}${"-q, --query <text>".padEnd(28)}${C.reset} ${C.white}Run a one-shot query${C.reset}`);
|
|
598
|
+
helpLines.push(` ${C.emerald}${"-p, --print".padEnd(28)}${C.reset} ${C.white}Headless non-interactive print mode (clean text output)${C.reset}`);
|
|
599
|
+
helpLines.push(` ${C.emerald}${"-o, --output <format>".padEnd(28)}${C.reset} ${C.white}Output format: text (default) or json${C.reset}`);
|
|
600
|
+
helpLines.push(` ${C.emerald}${"-P, --provider <name>".padEnd(28)}${C.reset} ${C.white}Select provider (lmstudio, openai, gemini, groq, etc.)${C.reset}`);
|
|
601
|
+
helpLines.push(` ${C.emerald}${"--profile <name>".padEnd(28)}${C.reset} ${C.white}Load configuration profile (default, fast, deep-reasoning, cloud, gemini)${C.reset}`);
|
|
602
|
+
helpLines.push(` ${C.emerald}${"-m, --model <id>".padEnd(28)}${C.reset} ${C.white}Model ID override${C.reset}`);
|
|
603
|
+
helpLines.push(` ${C.emerald}${"-k, --api-key <key>".padEnd(28)}${C.reset} ${C.white}Provider API key override${C.reset}`);
|
|
604
|
+
helpLines.push(` ${C.emerald}${"-u, --url <url>".padEnd(28)}${C.reset} ${C.white}Provider base URL override${C.reset}`);
|
|
605
|
+
helpLines.push(` ${C.emerald}${"--plain".padEnd(28)}${C.reset} ${C.white}Disable ANSI styles, colors, and alternate screen${C.reset}`);
|
|
606
|
+
helpLines.push(` ${C.emerald}${"--no-color".padEnd(28)}${C.reset} ${C.white}Disable ANSI colors (honors NO_COLOR env)${C.reset}`);
|
|
607
|
+
helpLines.push(` ${C.emerald}${"--thinking <mode>".padEnd(28)}${C.reset} ${C.white}Show or hide reasoning process (show | hide)${C.reset}`);
|
|
608
|
+
helpLines.push(` ${C.emerald}${"-t, --tools".padEnd(28)}${C.reset} ${C.white}List all registered tools${C.reset}`);
|
|
609
|
+
helpLines.push(` ${C.emerald}${"-s, --stats".padEnd(28)}${C.reset} ${C.white}Show system and catalog stats${C.reset}`);
|
|
610
|
+
helpLines.push(` ${C.emerald}${"--web-chat, --web".padEnd(28)}${C.reset} ${C.white}Start standalone web chatbot (default port 3300)${C.reset}`);
|
|
611
|
+
helpLines.push(` ${C.emerald}${"--port <n>".padEnd(28)}${C.reset} ${C.white}Web chatbot port 1-65535 (or --web-chat=<port>)${C.reset}`);
|
|
612
|
+
helpLines.push(` ${C.emerald}${"--no-open, --open".padEnd(28)}${C.reset} ${C.white}Skip or force auto-open browser for --web-chat${C.reset}`);
|
|
613
|
+
helpLines.push(` ${C.emerald}${"-v, --verbose".padEnd(28)}${C.reset} ${C.white}Verbose logging and thinking${C.reset}`);
|
|
614
|
+
helpLines.push(` ${C.emerald}${"-V, --version".padEnd(28)}${C.reset} ${C.white}Print version${C.reset}`);
|
|
615
|
+
helpLines.push(` ${C.emerald}${"-h, --help".padEnd(28)}${C.reset} ${C.white}Show this help message${C.reset}`);
|
|
457
616
|
|
|
458
617
|
printSolidPanel({
|
|
459
618
|
title: `${UI_ICONS.help} Kiku AI Agent — ${COMMAND_DEFINITIONS.length} Commands`,
|
|
@@ -694,6 +853,7 @@ class InteractiveTuiPrompt {
|
|
|
694
853
|
this._cleanupInput();
|
|
695
854
|
this.line = '';
|
|
696
855
|
this.cursor = 0;
|
|
856
|
+
this.ghostText = '';
|
|
697
857
|
this.popoverActive = false;
|
|
698
858
|
this.popoverItems = [];
|
|
699
859
|
if (this.recordInputHistory && result && result.trim()) this.history.push(result);
|
|
@@ -1002,8 +1162,15 @@ class InteractiveTuiPrompt {
|
|
|
1002
1162
|
if (isF3) { this.finish('/details thinking'); return; }
|
|
1003
1163
|
if (isF4) { this.finish('/details tools'); return; }
|
|
1004
1164
|
if (isF5) { this.finish('/copy'); return; }
|
|
1005
|
-
if (isF6) { this.finish('/
|
|
1006
|
-
if (isF7) {
|
|
1165
|
+
if (isF6) { this.finish('/timeline'); return; }
|
|
1166
|
+
if (isF7) {
|
|
1167
|
+
const current = getThemeName();
|
|
1168
|
+
const currentIndex = THEME_NAMES.indexOf(current);
|
|
1169
|
+
const nextIndex = (currentIndex + 1) % THEME_NAMES.length;
|
|
1170
|
+
setTheme(THEME_NAMES[nextIndex]);
|
|
1171
|
+
this.render();
|
|
1172
|
+
return;
|
|
1173
|
+
}
|
|
1007
1174
|
if (isF8) { this.finish('/stats'); return; }
|
|
1008
1175
|
if (isF9) { this.finish('/provider'); return; }
|
|
1009
1176
|
if (isF10) { this.finish('/mcp list'); return; }
|
|
@@ -1014,12 +1181,21 @@ class InteractiveTuiPrompt {
|
|
|
1014
1181
|
const isCtrlR = (key?.ctrl && key?.name === 'r') || str === '\x12';
|
|
1015
1182
|
const isCtrlS = (key?.ctrl && key?.name === 's') || str === '\x13';
|
|
1016
1183
|
const isCtrlG = (key?.ctrl && key?.name === 'g') || str === '\x07';
|
|
1184
|
+
const isCtrlK = (key?.ctrl && key?.name === 'k') || str === '\x0b';
|
|
1185
|
+
const isCtrlP = (key?.ctrl && key?.name === 'p') || str === '\x10';
|
|
1017
1186
|
|
|
1018
1187
|
if (isCtrlL) { this.render(); return; }
|
|
1019
1188
|
if (isCtrlT) { this.finish('/thinking toggle'); return; }
|
|
1020
1189
|
if (isCtrlR) { this.finish('/retry'); return; }
|
|
1021
1190
|
if (isCtrlS) { this.finish('/save'); return; }
|
|
1022
1191
|
if (isCtrlG) { this.finish('/gallery'); return; }
|
|
1192
|
+
if (isCtrlK || isCtrlP) {
|
|
1193
|
+
this.line = '/';
|
|
1194
|
+
this.cursor = 1;
|
|
1195
|
+
this.updateState();
|
|
1196
|
+
this.render();
|
|
1197
|
+
return;
|
|
1198
|
+
}
|
|
1023
1199
|
|
|
1024
1200
|
if (key?.name === 'tab' || str === '\t') {
|
|
1025
1201
|
if (this.popoverActive && this.popoverItems.length > 0) {
|
|
@@ -1443,29 +1619,11 @@ async function executeQueryWithUI(agent, prompt, isThinkingVisible = false, sign
|
|
|
1443
1619
|
};
|
|
1444
1620
|
|
|
1445
1621
|
const startSpinner = (label) => {
|
|
1446
|
-
|
|
1447
|
-
globalTuiPrompt.agentState = label;
|
|
1448
|
-
globalTuiPrompt.agentStateTime = Date.now();
|
|
1449
|
-
globalTuiPrompt.render();
|
|
1450
|
-
}
|
|
1451
|
-
if (!spinnerInterval) {
|
|
1452
|
-
spinnerInterval = setInterval(() => {
|
|
1453
|
-
if (globalTuiPrompt && isProcessing) {
|
|
1454
|
-
globalTuiPrompt.render();
|
|
1455
|
-
}
|
|
1456
|
-
}, 80);
|
|
1457
|
-
}
|
|
1622
|
+
startGlobalSpinner(label);
|
|
1458
1623
|
};
|
|
1459
1624
|
|
|
1460
1625
|
const stopSpinner = () => {
|
|
1461
|
-
|
|
1462
|
-
clearInterval(spinnerInterval);
|
|
1463
|
-
spinnerInterval = null;
|
|
1464
|
-
}
|
|
1465
|
-
if (globalTuiPrompt) {
|
|
1466
|
-
globalTuiPrompt.agentState = '';
|
|
1467
|
-
globalTuiPrompt.render();
|
|
1468
|
-
}
|
|
1626
|
+
stopGlobalSpinner();
|
|
1469
1627
|
};
|
|
1470
1628
|
|
|
1471
1629
|
let thinkingShown = false;
|
|
@@ -1479,12 +1637,13 @@ async function executeQueryWithUI(agent, prompt, isThinkingVisible = false, sign
|
|
|
1479
1637
|
let finalMeta = {};
|
|
1480
1638
|
|
|
1481
1639
|
const persistQueryDetails = (status, error = null) => {
|
|
1482
|
-
|
|
1640
|
+
recordQueryDiagnostics({
|
|
1483
1641
|
number: queryNumber,
|
|
1484
1642
|
prompt,
|
|
1485
1643
|
answer: finalAnswer,
|
|
1486
1644
|
thinking: accumulatedThinking,
|
|
1487
1645
|
tools: recordedTools,
|
|
1646
|
+
citations: agent?.lastCitations || [],
|
|
1488
1647
|
status,
|
|
1489
1648
|
error: error ? String(error.message || error) : null,
|
|
1490
1649
|
provider: agent.client?.providerName || agent.client?.provider || 'unknown',
|
|
@@ -1495,12 +1654,7 @@ async function executeQueryWithUI(agent, prompt, isThinkingVisible = false, sign
|
|
|
1495
1654
|
startedAt: queryStartedAt,
|
|
1496
1655
|
completedAt: Date.now(),
|
|
1497
1656
|
durationMs: finalMeta.durationMs ?? (Date.now() - queryStartedAt),
|
|
1498
|
-
|
|
1499
|
-
};
|
|
1500
|
-
if (queryNumber != null) {
|
|
1501
|
-
queryDetails.set(queryNumber, lastQueryDetails);
|
|
1502
|
-
if (queryDetails.size > 50) queryDetails.delete(queryDetails.keys().next().value);
|
|
1503
|
-
}
|
|
1657
|
+
});
|
|
1504
1658
|
};
|
|
1505
1659
|
|
|
1506
1660
|
startSpinner(`${C.slate}Thinking…${C.reset}`);
|
|
@@ -1508,6 +1662,19 @@ async function executeQueryWithUI(agent, prompt, isThinkingVisible = false, sign
|
|
|
1508
1662
|
try {
|
|
1509
1663
|
const returnedAnswer = await agent.ask(prompt, {
|
|
1510
1664
|
signal,
|
|
1665
|
+
onClarifyingQuestions: (questions) => {
|
|
1666
|
+
stopSpinner();
|
|
1667
|
+
console.log(formatQuestionsForCLI(questions, C));
|
|
1668
|
+
},
|
|
1669
|
+
onClarifyingAnswer: (queryId) => {
|
|
1670
|
+
return new Promise((resolve) => {
|
|
1671
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
1672
|
+
rl.question(`${C.gold}> ${C.reset}`, (answer) => {
|
|
1673
|
+
rl.close();
|
|
1674
|
+
resolve(answer.trim());
|
|
1675
|
+
});
|
|
1676
|
+
});
|
|
1677
|
+
},
|
|
1511
1678
|
onStepStart: iteration => { completedIterations = Math.max(completedIterations, Number(iteration) || 0); },
|
|
1512
1679
|
onReasoningStart: () => {
|
|
1513
1680
|
startSpinner(`${C.slate}Thinking…${C.reset}`);
|
|
@@ -1624,6 +1791,16 @@ async function executeQueryWithUI(agent, prompt, isThinkingVisible = false, sign
|
|
|
1624
1791
|
if (!finalAnswer && returnedAnswer) finalAnswer = String(returnedAnswer);
|
|
1625
1792
|
persistQueryDetails('complete');
|
|
1626
1793
|
if (responsePanelStarted) console.log('');
|
|
1794
|
+
if (agent?.lastCitations?.length > 0) {
|
|
1795
|
+
const citLines = agent.lastCitations.map(c => {
|
|
1796
|
+
const yearStr = c.year ? ` [${c.year}]` : '';
|
|
1797
|
+
const catStr = c.category ? ` • ${c.category}` : '';
|
|
1798
|
+
const srcStr = c.url ? ` • ${c.url}` : ` • ${c.source}`;
|
|
1799
|
+
return ` ${C.gold}[${c.id}]${C.reset} ${C.bold}${c.title}${C.reset}${C.dim}${yearStr}${catStr}${srcStr}${C.reset}`;
|
|
1800
|
+
});
|
|
1801
|
+
console.log(`${C.dim}📖 Sources & Citations (${agent.lastCitations.length}):${C.reset}`);
|
|
1802
|
+
console.log(citLines.join('\n') + '\n');
|
|
1803
|
+
}
|
|
1627
1804
|
} catch (err) {
|
|
1628
1805
|
stopSpinner();
|
|
1629
1806
|
persistQueryDetails(isAbortError(err) ? 'aborted' : 'error', err);
|
|
@@ -1641,44 +1818,267 @@ async function executeQueryWithUI(agent, prompt, isThinkingVisible = false, sign
|
|
|
1641
1818
|
}
|
|
1642
1819
|
}
|
|
1643
1820
|
|
|
1821
|
+
async function readStdin() {
|
|
1822
|
+
if (process.stdin.isTTY) return null;
|
|
1823
|
+
return new Promise((resolve) => {
|
|
1824
|
+
let data = '';
|
|
1825
|
+
let hasData = false;
|
|
1826
|
+
const timer = setTimeout(() => {
|
|
1827
|
+
if (!hasData) resolve(null);
|
|
1828
|
+
}, 120);
|
|
1829
|
+
timer.unref();
|
|
1830
|
+
|
|
1831
|
+
process.stdin.setEncoding('utf8');
|
|
1832
|
+
process.stdin.on('data', chunk => {
|
|
1833
|
+
hasData = true;
|
|
1834
|
+
data += chunk;
|
|
1835
|
+
});
|
|
1836
|
+
process.stdin.on('end', () => {
|
|
1837
|
+
clearTimeout(timer);
|
|
1838
|
+
resolve(data.trim() || null);
|
|
1839
|
+
});
|
|
1840
|
+
process.stdin.on('error', () => {
|
|
1841
|
+
clearTimeout(timer);
|
|
1842
|
+
resolve(null);
|
|
1843
|
+
});
|
|
1844
|
+
});
|
|
1845
|
+
}
|
|
1846
|
+
|
|
1847
|
+
async function executeHeadlessQuery(opts, query) {
|
|
1848
|
+
const startTime = Date.now();
|
|
1849
|
+
|
|
1850
|
+
if (opts.profile) {
|
|
1851
|
+
const p = getProfile(opts.profile);
|
|
1852
|
+
if (!p) {
|
|
1853
|
+
console.error(`Profile "${opts.profile}" not found. Run kiku-agent with /profile list or check available profiles.`);
|
|
1854
|
+
process.exit(3);
|
|
1855
|
+
}
|
|
1856
|
+
opts.provider = opts.provider || p.provider;
|
|
1857
|
+
opts.model = opts.model || p.model;
|
|
1858
|
+
if (p.thinking && !process.argv.includes('--thinking')) opts.thinking = p.thinking;
|
|
1859
|
+
}
|
|
1860
|
+
|
|
1861
|
+
const client = new LLMClient({
|
|
1862
|
+
provider: opts.provider || config.activeProvider,
|
|
1863
|
+
baseUrl: opts.url,
|
|
1864
|
+
apiKey: opts.apiKey,
|
|
1865
|
+
model: opts.model
|
|
1866
|
+
});
|
|
1867
|
+
|
|
1868
|
+
let agent = null;
|
|
1869
|
+
let answer = '';
|
|
1870
|
+
let thinking = '';
|
|
1871
|
+
const recordedTools = [];
|
|
1872
|
+
let executionError = null;
|
|
1873
|
+
|
|
1874
|
+
try {
|
|
1875
|
+
const modelManager = new ModelManager(client, { requestedModel: opts.model || client.model });
|
|
1876
|
+
const modelResolution = await modelManager.resolve({ requestedModel: opts.model || client.model });
|
|
1877
|
+
|
|
1878
|
+
if (!modelResolution.connected || !modelResolution.selectedModel) {
|
|
1879
|
+
throw new Error(modelResolution.error || `Cannot reach model server or no model found for ${client.providerName}`);
|
|
1880
|
+
}
|
|
1881
|
+
|
|
1882
|
+
agent = new KikuAgent({ client, thinkingMode: opts.thinking });
|
|
1883
|
+
await agent.ready();
|
|
1884
|
+
|
|
1885
|
+
answer = await agent.run(query, {
|
|
1886
|
+
onReasoningDelta: (chunk) => {
|
|
1887
|
+
thinking += chunk;
|
|
1888
|
+
},
|
|
1889
|
+
onToolStart: (name, args) => {
|
|
1890
|
+
recordedTools.push({ name, args, status: 'running' });
|
|
1891
|
+
},
|
|
1892
|
+
onToolResult: (name, result, duration) => {
|
|
1893
|
+
const t = recordedTools.find(tool => tool.name === name && tool.status === 'running');
|
|
1894
|
+
if (t) {
|
|
1895
|
+
t.status = 'done';
|
|
1896
|
+
t.result = result;
|
|
1897
|
+
t.duration = duration;
|
|
1898
|
+
} else {
|
|
1899
|
+
recordedTools.push({ name, result, duration, status: 'done' });
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1902
|
+
});
|
|
1903
|
+
} catch (err) {
|
|
1904
|
+
executionError = err;
|
|
1905
|
+
}
|
|
1906
|
+
|
|
1907
|
+
const durationMs = Date.now() - startTime;
|
|
1908
|
+
const isError = Boolean(executionError);
|
|
1909
|
+
|
|
1910
|
+
if (opts.output === 'json') {
|
|
1911
|
+
const payload = {
|
|
1912
|
+
version: PACKAGE_VERSION,
|
|
1913
|
+
sessionId: agent?.session?.id || null,
|
|
1914
|
+
query,
|
|
1915
|
+
status: isError ? 'error' : 'success',
|
|
1916
|
+
answer: isError ? '' : (answer || '').trim(),
|
|
1917
|
+
...(opts.thinking === 'show' ? { thinking: (thinking || '').trim() } : {}),
|
|
1918
|
+
tools: recordedTools.map(t => ({
|
|
1919
|
+
name: t.name,
|
|
1920
|
+
durationMs: t.duration || 0,
|
|
1921
|
+
status: t.status || 'done'
|
|
1922
|
+
})),
|
|
1923
|
+
citations: agent?.lastCitations || [],
|
|
1924
|
+
metrics: {
|
|
1925
|
+
durationMs,
|
|
1926
|
+
iterations: recordedTools.length ? 1 : 0,
|
|
1927
|
+
tokens: agent?.lastTelemetry?.tokens || agent?.session?.lastQueryTokens || {
|
|
1928
|
+
prompt: 0,
|
|
1929
|
+
completion: 0,
|
|
1930
|
+
reasoning: 0,
|
|
1931
|
+
total: 0
|
|
1932
|
+
},
|
|
1933
|
+
costUsd: agent?.lastTelemetry?.costUsd ?? agent?.session?.lastQueryCostUsd ?? 0
|
|
1934
|
+
}
|
|
1935
|
+
};
|
|
1936
|
+
if (isError) {
|
|
1937
|
+
payload.error = executionError.message;
|
|
1938
|
+
}
|
|
1939
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
1940
|
+
process.exit(isError ? 2 : 0);
|
|
1941
|
+
}
|
|
1942
|
+
|
|
1943
|
+
|
|
1944
|
+
if (isError) {
|
|
1945
|
+
console.error(`Error: ${executionError.message}`);
|
|
1946
|
+
process.exit(2);
|
|
1947
|
+
}
|
|
1948
|
+
|
|
1949
|
+
if (opts.thinking === 'show' && thinking.trim()) {
|
|
1950
|
+
console.log(`[Thinking]\n${thinking.trim()}\n`);
|
|
1951
|
+
}
|
|
1952
|
+
console.log((answer || '').trim());
|
|
1953
|
+
if (agent?.lastCitations?.length) {
|
|
1954
|
+
console.log('\n' + formatCitationsBlock(agent.lastCitations, { lang: 'auto' }));
|
|
1955
|
+
}
|
|
1956
|
+
process.exit(0);
|
|
1957
|
+
}
|
|
1958
|
+
|
|
1959
|
+
async function runWebChatStandalone(opts) {
|
|
1960
|
+
const { startWebChatServer, stopWebChatServer, openBrowser } = await import('../webChatServer.js');
|
|
1961
|
+
const port = opts.port || Number(process.env.PORT_WEB_CHAT) || 3300;
|
|
1962
|
+
|
|
1963
|
+
const client = new LLMClient({
|
|
1964
|
+
provider: opts.provider || config.activeProvider,
|
|
1965
|
+
baseUrl: opts.url,
|
|
1966
|
+
apiKey: opts.apiKey,
|
|
1967
|
+
model: opts.model,
|
|
1968
|
+
});
|
|
1969
|
+
const agent = new KikuAgent({ client, thinkingMode: opts.thinking });
|
|
1970
|
+
|
|
1971
|
+
const res = await startWebChatServer({ port, agent });
|
|
1972
|
+
if (!opts.noOpen) {
|
|
1973
|
+
try { openBrowser(res.url); } catch { /* browser is best-effort */ }
|
|
1974
|
+
}
|
|
1975
|
+
|
|
1976
|
+
if (!opts.plain && !opts.noColor) printWelcomeHero();
|
|
1977
|
+
printRichCard({
|
|
1978
|
+
title: res.alreadyRunning ? 'Web Chatbot Already Running' : 'Kiku Web Chatbot Ready',
|
|
1979
|
+
status: 'connected',
|
|
1980
|
+
lines: [
|
|
1981
|
+
`• URL: ${res.url}`,
|
|
1982
|
+
`• Port: ${res.port}${res.alreadyRunning ? ' (existing server reused)' : ''}`,
|
|
1983
|
+
`• Provider: ${client.providerName || client.provider} • Model: ${client.model}`,
|
|
1984
|
+
`• Browser: ${opts.noOpen ? 'skipped (--no-open)' : 'opened automatically'}`,
|
|
1985
|
+
'• Press Ctrl+C to stop the server.',
|
|
1986
|
+
'• Endpoints: / /api/chat /api/status /api/v1/timeline',
|
|
1987
|
+
],
|
|
1988
|
+
});
|
|
1989
|
+
|
|
1990
|
+
const shutdown = async () => {
|
|
1991
|
+
try { await stopWebChatServer(); } catch { /* best-effort */ }
|
|
1992
|
+
try { await agent.endSession?.(); } catch { /* best-effort */ }
|
|
1993
|
+
console.log(`\n ${C.sakura}Web chatbot stopped • 再见!${C.reset}\n`);
|
|
1994
|
+
process.exit(0);
|
|
1995
|
+
};
|
|
1996
|
+
process.once('SIGINT', shutdown);
|
|
1997
|
+
process.once('SIGTERM', shutdown);
|
|
1998
|
+
|
|
1999
|
+
// Keep the process alive until Ctrl+C.
|
|
2000
|
+
await new Promise(() => {});
|
|
2001
|
+
}
|
|
2002
|
+
|
|
1644
2003
|
async function main() {
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
if (opts.version) { console.log(PACKAGE_VERSION); process.exit(0); }
|
|
1648
|
-
if (opts.help) { printWelcomeHero(); printHelp(); process.exit(0); }
|
|
1649
|
-
if (opts.showTools) {
|
|
1650
|
-
printWelcomeHero();
|
|
1651
|
-
console.log(`\n ${C.bold}${C.sakura}Tools (${toolsSchema.length})${C.reset}\n`);
|
|
1652
|
-
for (const [i, t] of toolsSchema.entries()) {
|
|
1653
|
-
console.log(` ${C.gold}${String(i + 1).padStart(2)}${C.reset} ${C.cyberCyan}${t.function.name}${C.reset} — ${C.dim}${t.function.description.slice(0, 60)}${C.reset}`);
|
|
1654
|
-
}
|
|
1655
|
-
console.log('');
|
|
1656
|
-
process.exit(0);
|
|
1657
|
-
}
|
|
2004
|
+
const opts = parseCliArgs();
|
|
1658
2005
|
|
|
1659
|
-
|
|
2006
|
+
if (!opts.query && !process.stdin.isTTY) {
|
|
2007
|
+
const pipedInput = await readStdin();
|
|
2008
|
+
if (pipedInput) {
|
|
2009
|
+
opts.query = pipedInput;
|
|
2010
|
+
opts.print = true;
|
|
2011
|
+
}
|
|
2012
|
+
}
|
|
1660
2013
|
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
2014
|
+
if (opts.profile) {
|
|
2015
|
+
const p = getProfile(opts.profile);
|
|
2016
|
+
if (!p) {
|
|
2017
|
+
console.error(`Profile "${opts.profile}" not found. Run kiku-agent with /profile list to view available profiles.`);
|
|
2018
|
+
process.exit(3);
|
|
2019
|
+
}
|
|
2020
|
+
opts.provider = opts.provider || p.provider;
|
|
2021
|
+
opts.model = opts.model || p.model;
|
|
2022
|
+
if (p.thinking && !process.argv.includes('--thinking')) {
|
|
2023
|
+
opts.thinking = p.thinking;
|
|
2024
|
+
}
|
|
2025
|
+
}
|
|
2026
|
+
|
|
2027
|
+
if (opts.version) { console.log(PACKAGE_VERSION); process.exit(0); }
|
|
2028
|
+
if (opts.help) {
|
|
2029
|
+
if (!opts.plain && !opts.noColor) printWelcomeHero();
|
|
2030
|
+
printHelp();
|
|
2031
|
+
process.exit(0);
|
|
2032
|
+
}
|
|
2033
|
+
if (opts.showTools) {
|
|
2034
|
+
if (!opts.plain && !opts.noColor) printWelcomeHero();
|
|
2035
|
+
console.log(`\n ${C.bold}${C.sakura}Tools (${toolsSchema.length})${C.reset}\n`);
|
|
2036
|
+
for (const [i, t] of toolsSchema.entries()) {
|
|
2037
|
+
console.log(` ${C.gold}${String(i + 1).padStart(2)}${C.reset} ${C.cyberCyan}${t.function.name}${C.reset} — ${C.dim}${t.function.description.slice(0, 60)}${C.reset}`);
|
|
2038
|
+
}
|
|
2039
|
+
console.log('');
|
|
2040
|
+
process.exit(0);
|
|
2041
|
+
}
|
|
2042
|
+
|
|
2043
|
+
if (opts.showStats) {
|
|
2044
|
+
if (!opts.plain && !opts.noColor) printWelcomeHero();
|
|
2045
|
+
const r = await executeTool('get_system_stats', {});
|
|
2046
|
+
console.log(JSON.stringify(r, null, 2));
|
|
2047
|
+
process.exit(0);
|
|
2048
|
+
}
|
|
2049
|
+
|
|
2050
|
+
if (opts.webChat) {
|
|
2051
|
+
await runWebChatStandalone(opts);
|
|
2052
|
+
return;
|
|
2053
|
+
}
|
|
2054
|
+
|
|
2055
|
+
if (opts.query) {
|
|
2056
|
+
if (opts.print || opts.output === 'json') {
|
|
2057
|
+
await executeHeadlessQuery(opts, opts.query);
|
|
2058
|
+
return;
|
|
2059
|
+
}
|
|
2060
|
+
|
|
2061
|
+
printWelcomeHero();
|
|
2062
|
+
const client = new LLMClient({
|
|
2063
|
+
provider: opts.provider || config.activeProvider,
|
|
2064
|
+
baseUrl: opts.url,
|
|
2065
|
+
apiKey: opts.apiKey,
|
|
2066
|
+
model: opts.model
|
|
2067
|
+
});
|
|
2068
|
+
const modelManager = new ModelManager(client, { requestedModel: opts.model || client.model });
|
|
2069
|
+
const modelResolution = await modelManager.resolve({ requestedModel: opts.model || client.model });
|
|
2070
|
+
if (!modelResolution.connected || !modelResolution.selectedModel) {
|
|
2071
|
+
console.error(modelResolution.error || `No available chat model found for ${client.providerName}`);
|
|
2072
|
+
process.exit(2);
|
|
2073
|
+
}
|
|
2074
|
+
if (modelResolution.usedFallback) {
|
|
2075
|
+
console.log(` ${C.amber}Model ${modelResolution.requestedModel} is unavailable; using ${modelResolution.selectedModel}.${C.reset}\n`);
|
|
2076
|
+
}
|
|
2077
|
+
console.log(` ${C.bold}${C.gold}QUERY${C.reset} ${C.white}${opts.query}${C.reset}\n`);
|
|
2078
|
+
const agent = new KikuAgent({ client, thinkingMode: opts.thinking });
|
|
2079
|
+
await executeQueryWithUI(agent, opts.query, agent.session.thinkingMode === 'show', null, 1);
|
|
2080
|
+
process.exit(0);
|
|
2081
|
+
}
|
|
1682
2082
|
|
|
1683
2083
|
|
|
1684
2084
|
try { process.stdout.write('\x1b[?1000l\x1b[?1002l\x1b[?1003l\x1b[?1005l\x1b[?1006l\x1b[?1015l'); } catch { }
|
|
@@ -1969,9 +2369,11 @@ async function main() {
|
|
|
1969
2369
|
copyQueryDetails: (ref) => copyQueryDetails(ref, agent?.session),
|
|
1970
2370
|
printWelcome: printWelcomeHero,
|
|
1971
2371
|
printAd,
|
|
1972
|
-
showTerminalImage: (
|
|
1973
|
-
const
|
|
1974
|
-
|
|
2372
|
+
showTerminalImage: (options = 2) => {
|
|
2373
|
+
const opts = typeof options === 'number'
|
|
2374
|
+
? { count: options, force: true }
|
|
2375
|
+
: (typeof options === 'object' && options !== null ? { force: true, ...options } : { count: 2, force: true });
|
|
2376
|
+
const imageLines = terminalGallery.maybeRender(queryCount, opts);
|
|
1975
2377
|
if (imageLines.length > 0) tuiPrompt.addViewportLines(imageLines);
|
|
1976
2378
|
return imageLines.length > 0;
|
|
1977
2379
|
},
|
|
@@ -1984,12 +2386,13 @@ async function main() {
|
|
|
1984
2386
|
clearQueryQueue: () => { queryQueue.length = 0; },
|
|
1985
2387
|
getQueryQueueLength: () => queryQueue.length,
|
|
1986
2388
|
get isProcessing() { return isProcessing; },
|
|
2389
|
+
recordQueryDiagnostics: (details) => recordQueryDiagnostics(details),
|
|
1987
2390
|
setIsProcessing: (val, label = '') => {
|
|
1988
2391
|
isProcessing = Boolean(val);
|
|
1989
|
-
if (
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
2392
|
+
if (isProcessing) {
|
|
2393
|
+
startGlobalSpinner(label || 'Processing…');
|
|
2394
|
+
} else {
|
|
2395
|
+
stopGlobalSpinner();
|
|
1993
2396
|
}
|
|
1994
2397
|
},
|
|
1995
2398
|
setAgentState: (label, time = Date.now()) => {
|
|
@@ -1998,6 +2401,9 @@ async function main() {
|
|
|
1998
2401
|
globalTuiPrompt.agentStateTime = time;
|
|
1999
2402
|
globalTuiPrompt.render();
|
|
2000
2403
|
}
|
|
2404
|
+
if (label && isProcessing) {
|
|
2405
|
+
startGlobalSpinner();
|
|
2406
|
+
}
|
|
2001
2407
|
},
|
|
2002
2408
|
};
|
|
2003
2409
|
|
|
@@ -2114,20 +2520,27 @@ async function main() {
|
|
|
2114
2520
|
const extra = parts.slice(2).join(' ');
|
|
2115
2521
|
|
|
2116
2522
|
let result;
|
|
2523
|
+
activeAbortController = new AbortController();
|
|
2117
2524
|
try {
|
|
2118
2525
|
result = await routeCommand(trimmed, {
|
|
2119
2526
|
...cmdCtx,
|
|
2527
|
+
signal: activeAbortController.signal,
|
|
2120
2528
|
sub,
|
|
2121
2529
|
extra,
|
|
2122
2530
|
parts,
|
|
2123
2531
|
});
|
|
2124
2532
|
} catch (cmdErr) {
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2533
|
+
if (!isAbortError(cmdErr)) {
|
|
2534
|
+
printRichCard({
|
|
2535
|
+
title: 'Command Error',
|
|
2536
|
+
status: 'error',
|
|
2537
|
+
lines: [cmdErr.message || String(cmdErr)],
|
|
2538
|
+
});
|
|
2539
|
+
}
|
|
2130
2540
|
continue;
|
|
2541
|
+
} finally {
|
|
2542
|
+
activeAbortController = null;
|
|
2543
|
+
cmdCtx.setIsProcessing(false);
|
|
2131
2544
|
}
|
|
2132
2545
|
|
|
2133
2546
|
if (result === 'EXIT') {
|
|
@@ -2250,24 +2663,35 @@ async function main() {
|
|
|
2250
2663
|
});
|
|
2251
2664
|
}
|
|
2252
2665
|
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2666
|
+
const currentScriptPath = fileURLToPath(import.meta.url);
|
|
2667
|
+
const isDirectRun = process.argv[1] && (
|
|
2668
|
+
process.argv[1] === currentScriptPath ||
|
|
2669
|
+
process.argv[1].endsWith('server/agent/cli.js') ||
|
|
2670
|
+
process.argv[1].endsWith('server\\agent\\cli.js') ||
|
|
2671
|
+
process.argv[1].endsWith('bin/kiku-agent') ||
|
|
2672
|
+
process.argv[1].endsWith('bin\\kiku-agent')
|
|
2673
|
+
);
|
|
2674
|
+
|
|
2675
|
+
if (isDirectRun) {
|
|
2676
|
+
process.on('exit', () => {
|
|
2677
|
+
try { globalTuiPrompt?.dispose(); } catch { }
|
|
2678
|
+
exitAlternateScreen();
|
|
2679
|
+
});
|
|
2680
|
+
process.on('uncaughtException', (err) => {
|
|
2681
|
+
try { globalTuiPrompt?.dispose(); } catch { }
|
|
2682
|
+
exitAlternateScreen();
|
|
2683
|
+
console.error(`\n Uncaught: ${err.message}`);
|
|
2684
|
+
process.exit(1);
|
|
2685
|
+
});
|
|
2686
|
+
process.on('SIGINT', () => {
|
|
2687
|
+
try { globalTuiPrompt?.dispose(); } catch { }
|
|
2688
|
+
exitAlternateScreen();
|
|
2689
|
+
process.exit(130);
|
|
2690
|
+
});
|
|
2268
2691
|
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2692
|
+
main().catch(err => {
|
|
2693
|
+
exitAlternateScreen();
|
|
2694
|
+
console.error(`\n ${C.red}Fatal: ${err.message}${C.reset}\n`);
|
|
2695
|
+
process.exit(1);
|
|
2696
|
+
});
|
|
2697
|
+
}
|