kiku-agent 1.2.0 → 1.3.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 +459 -407
- package/package.json +27 -3
- package/server/agent/agentCore.js +635 -267
- package/server/agent/appPaths.js +2 -0
- package/server/agent/catalogEntityResolver.js +629 -0
- package/server/agent/citations.js +0 -21
- package/server/agent/clarificationAnalytics.js +1 -1
- package/server/agent/clarifyingQuestions.js +286 -216
- package/server/agent/cli.js +528 -73
- package/server/agent/commandFeatures.js +123 -24
- package/server/agent/commandRegistry.js +128 -62
- package/server/agent/commands.js +1410 -95
- package/server/agent/config.js +253 -163
- package/server/agent/contextCompactor.js +239 -25
- package/server/agent/dynamicCatalog.js +192 -0
- package/server/agent/envBootstrap.js +46 -0
- package/server/agent/envManager.js +317 -0
- package/server/agent/eventBus.js +3 -3
- package/server/agent/feedbackLearning.js +0 -8
- package/server/agent/gpuMetrics.js +188 -55
- package/server/agent/ingestionWorker.js +339 -0
- package/server/agent/lanDiscovery.js +369 -0
- package/server/agent/llmClient.js +111 -39
- package/server/agent/lmStudioWakeup.js +144 -0
- package/server/agent/mcpClient.js +2 -2
- package/server/agent/memory.js +635 -494
- package/server/agent/modelConfig.js +487 -0
- package/server/agent/newsIntelligence.js +219 -0
- package/server/agent/newsWatch.js +85 -0
- package/server/agent/prompts.js +146 -0
- package/server/agent/publicTools.js +7 -0
- package/server/agent/queryDetails.js +62 -1
- package/server/agent/research.js +314 -35
- package/server/agent/routingInterceptor.js +77 -0
- package/server/agent/rumoredProjects.js +15 -0
- package/server/agent/sanitizer.js +117 -17
- package/server/agent/subagent.js +52 -9
- package/server/agent/suggestionTui.js +33 -13
- package/server/agent/suggestions.js +29 -13
- package/server/agent/telemetry.js +0 -11
- package/server/agent/terminalImage.js +0 -1
- package/server/agent/textToolProtocol.js +190 -0
- package/server/agent/tokenTracker.js +220 -0
- package/server/agent/toolRouter.js +362 -216
- package/server/agent/tools.js +1155 -194
- package/server/agent/ui.js +144 -41
- package/server/agent/vramService.js +572 -0
- package/server/agent/webSearch.js +2279 -273
- package/server/agent/youtubeAuth.js +82 -73
- package/server/agent/youtubeTranscript.js +209 -0
- package/server/apiRouter.js +383 -179
- package/server/mcp/data/brands.js +5 -5
- package/server/mcp/data/discography.js +56 -45
- package/server/mcp/data/gallery.js +9 -0
- package/server/mcp/data/index.js +1 -0
- package/server/mcp/data/industryIndex.js +251 -0
- package/server/mcp/data/profile.js +5 -5
- package/server/mcp/data/timeline.js +2 -2
- package/server/mcp/data/works.js +2 -2
- package/server/mcp/handler.js +0 -2
- package/server/mcp/prompts.js +42 -2
- package/server/mcp/resources.js +5 -1
- package/server/mcp/security.js +25 -14
- package/server/mcp/server.js +92 -3
- package/server/mcp/tools.js +20 -11
- package/server/web-chat/core/connection.js +218 -194
- package/server/web-chat/core/conversationContext.js +1 -1
- package/server/web-chat/core/directCatalogEngine.js +190 -184
- package/server/web-chat/core/followUpEngine.js +88 -11
- package/server/web-chat/core/security.js +7 -4
- package/server/web-chat/router.js +54 -17
- package/server/web-chat/routes/bilibiliRoute.js +34 -0
- package/server/web-chat/routes/chatRoute.js +488 -397
- package/server/web-chat/routes/clarifyConfigRoute.js +1 -2
- package/server/web-chat/routes/exportRoute.js +2 -1
- package/server/web-chat/routes/lanDiscoveryRoute.js +90 -0
- package/server/web-chat/routes/newsRoute.js +36 -6
- package/server/web-chat/routes/providerRoute.js +87 -0
- package/server/web-chat/routes/staticRoute.js +61 -13
- package/server/web-chat/routes/statusRoute.js +23 -2
- package/server/web-chat/routes/vramRoute.js +22 -0
- package/server/web-chat/server.js +135 -106
- package/server/web-chat/ui/htmlBuilder.js +8 -8
- package/server/web-chat/ui/previews/modelSettings.preview.html +41 -0
- package/server/web-chat/ui/scripts/agentBubbleSystem.js +0 -5
- package/server/web-chat/ui/scripts/client.js +10526 -8397
- package/server/web-chat/ui/scripts/webchatI18n.js +190 -138
- package/server/web-chat/ui/styles/main.css +7471 -4246
- package/server/web-chat/ui/templates/body.html +305 -179
- package/src/data/brandsData.js +29 -6
- package/src/data/discographyData.js +918 -900
- package/src/data/galleryData.js +66 -0
- package/src/data/industryIndexData.js +292 -0
- package/src/data/musicVideoData.js +48 -5
- package/src/data/profileData.js +15 -1
- package/src/data/timelineData.js +4 -3
- package/src/data/worksData.js +536 -535
- package/src/lib/vram/estimator.js +464 -0
- package/src/lib/vram/modelRegistry.js +387 -0
- package/tokens.css +33 -2
|
@@ -1,116 +1,145 @@
|
|
|
1
|
-
import http from 'node:http';
|
|
2
|
-
import { handleWebChatRequest } from './router.js';
|
|
3
|
-
import { currentAgent, setCurrentAgent, webAgentCache } from './core/connection.js';
|
|
4
|
-
import { config } from '../agent/config.js';
|
|
5
|
-
|
|
1
|
+
import http from 'node:http';
|
|
2
|
+
import { handleWebChatRequest } from './router.js';
|
|
3
|
+
import { currentAgent, setCurrentAgent, webAgentCache } from './core/connection.js';
|
|
4
|
+
import { config } from '../agent/config.js';
|
|
5
|
+
|
|
6
6
|
let activeServer = null;
|
|
7
|
-
let activePort = Number(process.env.PORT_WEB_CHAT ||
|
|
8
|
-
let activeHost = process.env.KIKU_WEB_CHAT_HOST || '
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
7
|
+
let activePort = Number(process.env.PORT_WEB_CHAT || 3002);
|
|
8
|
+
let activeHost = process.env.KIKU_WEB_CHAT_HOST || 'localhost';
|
|
9
|
+
|
|
10
|
+
function formatServerUrl(host, port) {
|
|
11
|
+
const displayHost = (host === '127.0.0.1' || host === 'localhost' || host === '::1') ? 'localhost' : host;
|
|
12
|
+
return `http://${displayHost}:${port}`;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function getWebChatServerStatus() {
|
|
16
|
+
if (!activeServer) {
|
|
17
|
+
return {
|
|
18
|
+
running: false,
|
|
19
|
+
port: activePort,
|
|
20
|
+
url: formatServerUrl(activeHost, activePort),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
running: true,
|
|
25
|
+
port: activePort,
|
|
26
|
+
url: formatServerUrl(activeHost, activePort),
|
|
27
|
+
provider: currentAgent?.client?.provider || config.activeProvider || 'lmstudio',
|
|
28
|
+
model: currentAgent?.client?.model || 'google/gemma-4-e4b',
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function stopWebChatServer() {
|
|
33
|
+
return new Promise((resolve) => {
|
|
34
|
+
if (!activeServer) return resolve(false);
|
|
35
|
+
if (typeof activeServer.closeAllConnections === 'function') {
|
|
36
|
+
try { activeServer.closeAllConnections(); } catch {}
|
|
37
|
+
}
|
|
38
|
+
activeServer.close(async () => {
|
|
39
|
+
await Promise.allSettled(
|
|
40
|
+
Array.from(webAgentCache.values(), connection => connection.agent?.saveSession?.())
|
|
41
|
+
);
|
|
42
|
+
webAgentCache.clear();
|
|
43
|
+
activeServer = null;
|
|
44
|
+
resolve(true);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function getNextSafePort(port) {
|
|
50
|
+
if (port === 3000 || port === 3001) {
|
|
51
|
+
return 3002;
|
|
52
|
+
}
|
|
53
|
+
if (port >= 2940 && port < 3000) {
|
|
54
|
+
return 3002;
|
|
55
|
+
}
|
|
56
|
+
if (port >= 5380 && port <= 5590) {
|
|
57
|
+
return 5600;
|
|
58
|
+
}
|
|
59
|
+
return port + 1;
|
|
60
|
+
}
|
|
61
|
+
|
|
55
62
|
export async function startWebChatServer(options = {}) {
|
|
56
|
-
const requestedPort = Number(options.port || process.env.PORT_WEB_CHAT ||
|
|
57
|
-
const requestedHost = String(options.host || process.env.KIKU_WEB_CHAT_HOST || '
|
|
63
|
+
const requestedPort = Number(options.port || process.env.PORT_WEB_CHAT || 3002);
|
|
64
|
+
const requestedHost = String(options.host || process.env.KIKU_WEB_CHAT_HOST || 'localhost');
|
|
58
65
|
const isLoopback = requestedHost === '127.0.0.1' || requestedHost === '::1' || requestedHost === 'localhost';
|
|
59
66
|
if (!isLoopback && process.env.KIKU_ALLOW_REMOTE_WEB_CHAT !== 'true') {
|
|
60
67
|
throw new Error('Remote web-chat binding is disabled. Set KIKU_ALLOW_REMOTE_WEB_CHAT=true only behind an authenticated reverse proxy.');
|
|
61
68
|
}
|
|
62
|
-
if (options.agent) {
|
|
63
|
-
setCurrentAgent(options.agent);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (activeServer) {
|
|
67
|
-
if (options.port && activePort !== Number(options.port)) {
|
|
68
|
-
await stopWebChatServer();
|
|
69
|
-
} else {
|
|
70
|
-
return Promise.resolve({
|
|
71
|
-
server: activeServer,
|
|
72
|
-
port: activePort,
|
|
73
|
-
url:
|
|
74
|
-
alreadyRunning: true
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return new Promise((resolve, reject) => {
|
|
80
|
-
let currentPort = requestedPort;
|
|
81
|
-
let attempts = 0;
|
|
82
|
-
const maxAttempts = 15;
|
|
83
|
-
let server = null;
|
|
84
|
-
|
|
85
|
-
function tryBind() {
|
|
86
|
-
server = http.createServer(async (req, res) => {
|
|
87
|
-
await handleWebChatRequest(req, res, { port: activePort });
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
server.on('error', (err) => {
|
|
91
|
-
if ((err.code === 'EACCES' || err.code === 'EADDRINUSE') && attempts < maxAttempts) {
|
|
92
|
-
attempts++;
|
|
93
|
-
currentPort = getNextSafePort(currentPort);
|
|
94
|
-
try { server.close(); } catch {}
|
|
95
|
-
setTimeout(tryBind, 20);
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
reject(err);
|
|
99
|
-
});
|
|
100
|
-
|
|
69
|
+
if (options.agent) {
|
|
70
|
+
setCurrentAgent(options.agent);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (activeServer) {
|
|
74
|
+
if (options.port && activePort !== Number(options.port)) {
|
|
75
|
+
await stopWebChatServer();
|
|
76
|
+
} else {
|
|
77
|
+
return Promise.resolve({
|
|
78
|
+
server: activeServer,
|
|
79
|
+
port: activePort,
|
|
80
|
+
url: formatServerUrl(activeHost, activePort),
|
|
81
|
+
alreadyRunning: true
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return new Promise((resolve, reject) => {
|
|
87
|
+
let currentPort = requestedPort;
|
|
88
|
+
let attempts = 0;
|
|
89
|
+
const maxAttempts = 15;
|
|
90
|
+
let server = null;
|
|
91
|
+
|
|
92
|
+
function tryBind() {
|
|
93
|
+
server = http.createServer(async (req, res) => {
|
|
94
|
+
await handleWebChatRequest(req, res, { port: activePort });
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
server.on('error', (err) => {
|
|
98
|
+
if ((err.code === 'EACCES' || err.code === 'EADDRINUSE') && attempts < maxAttempts) {
|
|
99
|
+
attempts++;
|
|
100
|
+
currentPort = getNextSafePort(currentPort);
|
|
101
|
+
try { server.close(); } catch {}
|
|
102
|
+
setTimeout(tryBind, 20);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
reject(err);
|
|
106
|
+
});
|
|
107
|
+
|
|
101
108
|
server.listen(currentPort, requestedHost, () => {
|
|
102
109
|
activeServer = server;
|
|
103
110
|
activePort = currentPort;
|
|
104
111
|
activeHost = requestedHost;
|
|
105
|
-
resolve({
|
|
106
|
-
server,
|
|
107
|
-
port: activePort,
|
|
108
|
-
url:
|
|
109
|
-
alreadyRunning: false
|
|
110
|
-
});
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
tryBind();
|
|
115
|
-
});
|
|
116
|
-
}
|
|
112
|
+
resolve({
|
|
113
|
+
server,
|
|
114
|
+
port: activePort,
|
|
115
|
+
url: formatServerUrl(activeHost, activePort),
|
|
116
|
+
alreadyRunning: false
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
tryBind();
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
import { fileURLToPath } from 'node:url';
|
|
126
|
+
import path from 'node:path';
|
|
127
|
+
import { openBrowser } from './core/browserLauncher.js';
|
|
128
|
+
|
|
129
|
+
if (process.argv[1] && path.resolve(process.argv[1]) === path.resolve(fileURLToPath(import.meta.url))) {
|
|
130
|
+
const args = process.argv.slice(2);
|
|
131
|
+
const portIdx = args.indexOf('--port');
|
|
132
|
+
const port = portIdx !== -1 && args[portIdx + 1] ? Number(args[portIdx + 1]) : 3002;
|
|
133
|
+
const shouldOpen = args.includes('--open');
|
|
134
|
+
|
|
135
|
+
startWebChatServer({ port }).then((res) => {
|
|
136
|
+
console.log(`[Web Chat] Standalone server running at ${res.url}`);
|
|
137
|
+
if (shouldOpen) {
|
|
138
|
+
try { openBrowser(res.url); } catch {}
|
|
139
|
+
}
|
|
140
|
+
}).catch((err) => {
|
|
141
|
+
console.error('[Web Chat] Failed to start server:', err);
|
|
142
|
+
process.exit(1);
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
@@ -8,7 +8,7 @@ const __dirname = path.dirname(__filename);
|
|
|
8
8
|
|
|
9
9
|
const STYLES_PATH = path.join(__dirname, 'styles', 'main.css');
|
|
10
10
|
const TOKENS_PATH = path.resolve(__dirname, '../../../tokens.css');
|
|
11
|
-
const BODY_PATH = path.join(__dirname, 'templates', 'body.html');
|
|
11
|
+
const BODY_PATH = path.join(__dirname, 'templates', 'body.html');
|
|
12
12
|
const AGENT_BUBBLE_SCRIPT_PATH = path.join(__dirname, 'scripts', 'agentBubbleSystem.js');
|
|
13
13
|
const WEBCHAT_I18N_SCRIPT_PATH = path.join(__dirname, 'scripts', 'webchatI18n.js');
|
|
14
14
|
const SCRIPT_PATH = path.join(__dirname, 'scripts', 'client.js');
|
|
@@ -50,8 +50,8 @@ function loadAssets() {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
export function getWebChatHtml(_port = 3001) {
|
|
53
|
-
const { tokens, styles, body, agentBubbleScript, i18nScript, script } = loadAssets();
|
|
54
|
-
const categoriesJson = JSON.stringify(CATEGORIZED_SUGGESTIONS);
|
|
53
|
+
const { tokens, styles, body, agentBubbleScript, i18nScript, script } = loadAssets();
|
|
54
|
+
const categoriesJson = JSON.stringify(CATEGORIZED_SUGGESTIONS).replace(/</g, '\\u003c');
|
|
55
55
|
|
|
56
56
|
const resolvedScript = script.replace(/const ALL_CATEGORIES = [^;]+;/, `const ALL_CATEGORIES = ${categoriesJson};`);
|
|
57
57
|
|
|
@@ -62,7 +62,7 @@ export function getWebChatHtml(_port = 3001) {
|
|
|
62
62
|
' <meta charset="UTF-8">',
|
|
63
63
|
' <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">',
|
|
64
64
|
' <title>鞠婧祎 (Ju Jingyi) — Official AI Assistant</title>',
|
|
65
|
-
' <link rel="icon"
|
|
65
|
+
' <link rel="icon" href="/favicon.ico" />',
|
|
66
66
|
' <link rel="preconnect" href="https://fonts.googleapis.com">',
|
|
67
67
|
' <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>',
|
|
68
68
|
' <link href="https://fonts.googleapis.com/css2?family=Google+Sans:wght@400;500;600;700;800;900&family=JetBrains+Mono:wght@400;600&family=Noto+Sans+SC:wght@300;400;500;600;700;900&family=Ma+Shan+Zheng&display=swap" rel="stylesheet">',
|
|
@@ -71,9 +71,9 @@ export function getWebChatHtml(_port = 3001) {
|
|
|
71
71
|
tokens,
|
|
72
72
|
styles,
|
|
73
73
|
' </style>',
|
|
74
|
-
'</head>',
|
|
75
|
-
'<body>',
|
|
76
|
-
body,
|
|
74
|
+
'</head>',
|
|
75
|
+
'<body>',
|
|
76
|
+
body,
|
|
77
77
|
' <script>',
|
|
78
78
|
agentBubbleScript,
|
|
79
79
|
' </script>',
|
|
@@ -82,7 +82,7 @@ export function getWebChatHtml(_port = 3001) {
|
|
|
82
82
|
' </script>',
|
|
83
83
|
' <script>',
|
|
84
84
|
resolvedScript,
|
|
85
|
-
' </script>',
|
|
85
|
+
' </script>',
|
|
86
86
|
'</body>',
|
|
87
87
|
'</html>'
|
|
88
88
|
].join('\n');
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="th" data-theme="dark">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
|
6
|
+
<title>AI Model Workbench — interaction states</title>
|
|
7
|
+
<link rel="stylesheet" href="../../../../tokens.css">
|
|
8
|
+
<link rel="stylesheet" href="../styles/main.css">
|
|
9
|
+
<style>
|
|
10
|
+
html, body { overflow-x: clip; }
|
|
11
|
+
body { margin: 0; min-height: 100dvh; background: var(--color-settings-canvas); color: var(--color-settings-ink); font-family: var(--font-body); }
|
|
12
|
+
.preview-shell { width: min(48rem, calc(100% - 2rem)); margin-inline: auto; padding-block: var(--space-xl); }
|
|
13
|
+
.preview-shell h1 { margin: 0 0 var(--space-xs); font-family: var(--font-display); font-size: var(--text-xl); font-style: normal; }
|
|
14
|
+
.preview-shell > p { margin: 0 0 var(--space-lg); color: var(--color-settings-muted); }
|
|
15
|
+
.preview-grid { display: grid; gap: var(--space-xs); }
|
|
16
|
+
.preview-row { display: grid; grid-template-columns: 5rem minmax(0, 1fr); gap: var(--space-sm); align-items: center; }
|
|
17
|
+
.preview-label { color: var(--color-settings-muted); font-family: var(--font-mono); font-size: var(--text-xs); }
|
|
18
|
+
.preview-row .btn-sync-cli { width: 100%; }
|
|
19
|
+
.is-hover { border-color: var(--color-settings-accent); background: var(--color-settings-surface-raised); color: var(--color-settings-accent); transform: translateY(-1px); }
|
|
20
|
+
.is-focus { outline: 2px solid var(--color-settings-focus); outline-offset: 2px; }
|
|
21
|
+
.is-active { transform: translateY(1px); }
|
|
22
|
+
@media (max-width: 24rem) { .preview-row { grid-template-columns: minmax(0, 1fr); } }
|
|
23
|
+
</style>
|
|
24
|
+
</head>
|
|
25
|
+
<body>
|
|
26
|
+
<main class="preview-shell">
|
|
27
|
+
<h1>AI model workbench</h1>
|
|
28
|
+
<p>Production button treatment across all required interaction states.</p>
|
|
29
|
+
<section class="preview-grid" aria-label="Interaction states">
|
|
30
|
+
<div class="preview-row"><span class="preview-label">default</span><button class="btn-sync-cli">Use CLI defaults</button></div>
|
|
31
|
+
<div class="preview-row"><span class="preview-label">hover</span><button class="btn-sync-cli is-hover">Use CLI defaults</button></div>
|
|
32
|
+
<div class="preview-row"><span class="preview-label">focus</span><button class="btn-sync-cli is-focus">Use CLI defaults</button></div>
|
|
33
|
+
<div class="preview-row"><span class="preview-label">active</span><button class="btn-sync-cli is-active">Use CLI defaults</button></div>
|
|
34
|
+
<div class="preview-row"><span class="preview-label">disabled</span><button class="btn-sync-cli" disabled>Use CLI defaults</button></div>
|
|
35
|
+
<div class="preview-row"><span class="preview-label">loading</span><button class="btn-sync-cli" data-state="loading">Applying defaults</button></div>
|
|
36
|
+
<div class="preview-row"><span class="preview-label">error</span><button class="btn-sync-cli" data-state="error">Retry defaults</button></div>
|
|
37
|
+
<div class="preview-row"><span class="preview-label">success</span><button class="btn-sync-cli" data-state="success">Defaults applied</button></div>
|
|
38
|
+
</section>
|
|
39
|
+
</main>
|
|
40
|
+
</body>
|
|
41
|
+
</html>
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/* Hallmark · component: agent bubble · genre: atmospheric · theme: existing Kiku
|
|
2
|
-
* states: default · hover · focus · active · disabled · loading · error · success
|
|
3
|
-
* contrast: token-backed
|
|
4
|
-
*/
|
|
5
|
-
/* Hallmark · pre-emit critique: P5 H4 E4 S5 R4 V4 */
|
|
6
1
|
(function initializeAgentBubbleSystem(globalScope) {
|
|
7
2
|
const STATUS = Object.freeze({
|
|
8
3
|
IDLE: 'idle',
|