@agentscope-ai/chat 1.1.56 → 1.1.58

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/bin/cli.js CHANGED
@@ -3,6 +3,8 @@
3
3
  const { program } = require('commander');
4
4
  const { execSync } = require('child_process');
5
5
  const path = require('path');
6
+ const fs = require('fs');
7
+ const crypto = require('crypto');
6
8
 
7
9
  function execSyncSafe(command) {
8
10
  try {
@@ -11,11 +13,43 @@ function execSyncSafe(command) {
11
13
  }
12
14
  }
13
15
 
16
+ function getFileHash(filePath) {
17
+ try {
18
+ const data = fs.readFileSync(filePath);
19
+ return crypto.createHash('md5').update(data).digest('hex');
20
+ } catch (error) {
21
+ return null;
22
+ }
23
+ }
24
+
25
+ function getCacheFile() {
26
+ return path.join(__dirname, '.webui-cache.json');
27
+ }
28
+
29
+ function loadCache() {
30
+ try {
31
+ const cacheFile = getCacheFile();
32
+ if (fs.existsSync(cacheFile)) {
33
+ return JSON.parse(fs.readFileSync(cacheFile, 'utf-8'));
34
+ }
35
+ } catch (error) {
36
+ }
37
+ return null;
38
+ }
39
+
40
+ function saveCache(cache) {
41
+ try {
42
+ fs.writeFileSync(getCacheFile(), JSON.stringify(cache, null, 2));
43
+ } catch (error) {
44
+ }
45
+ }
46
+
14
47
  program
15
48
  .name('agentscope-runtime-webui')
16
49
  .description('Start the AgentScope Runtime WebUI service')
17
50
  .option('-u, --url <url>', 'The backend API address')
18
51
  .option('-t, --token <token>', 'The authentication token')
52
+ .option('-f, --force', 'Force re-extract WebUI even if it exists')
19
53
  .parse(process.argv);
20
54
 
21
55
  const options = program.opts();
@@ -24,15 +58,55 @@ async function startServer() {
24
58
  console.log('\nšŸš€ Starting AgentScope Runtime WebUI...\n');
25
59
 
26
60
  try {
27
- execSyncSafe(`npx rimraf ${__dirname}/starter_webui`);
28
- execSyncSafe(`npx rimraf ${__dirname}/__MACOSX`);
29
- execSyncSafe(
30
- `npx decompress-cli ${__dirname}/starter_webui.zip --out-dir ${__dirname}`,
31
- );
32
-
33
61
  const targetDir = path.join(__dirname, 'starter_webui');
62
+ const nodeModulesDir = path.join(targetDir, 'node_modules');
63
+ const zipFile = path.join(__dirname, 'starter_webui.zip');
64
+ const cache = loadCache();
65
+ const currentZipHash = getFileHash(zipFile);
66
+
67
+ let shouldDecompress = false;
68
+
69
+ // Force decompress if --force flag is set
70
+ if (options.force) {
71
+ console.log('āš ļø Force mode: removing existing WebUI...');
72
+ execSyncSafe(`npx rimraf ${targetDir}`);
73
+ execSyncSafe(`npx rimraf ${__dirname}/__MACOSX`);
74
+ shouldDecompress = true;
75
+ } else if (!fs.existsSync(targetDir)) {
76
+ // Decompress if target directory doesn't exist
77
+ console.log('šŸ“¦ Decompressing WebUI for the first time...');
78
+ shouldDecompress = true;
79
+ } else if (cache && cache.zipHash && currentZipHash && cache.zipHash !== currentZipHash) {
80
+ // Decompress if zip file has changed
81
+ console.log('šŸ”„ WebUI zip file has changed, re-extracting...');
82
+ execSyncSafe(`npx rimraf ${targetDir}`);
83
+ execSyncSafe(`npx rimraf ${__dirname}/__MACOSX`);
84
+ shouldDecompress = true;
85
+ } else {
86
+ console.log('āœ… WebUI is up to date, skipping decompression.');
87
+ }
88
+
89
+ if (shouldDecompress) {
90
+ execSyncSafe(
91
+ `npx decompress-cli ${zipFile} --out-dir ${__dirname}`,
92
+ );
93
+ // Save cache after successful decompression
94
+ saveCache({ zipHash: currentZipHash, timestamp: Date.now() });
95
+ }
96
+
97
+ // Only run npm install if node_modules doesn't exist
98
+ if (!fs.existsSync(nodeModulesDir)) {
99
+ console.log('šŸ“¦ Installing dependencies...');
100
+ execSync(`npm install`, {
101
+ cwd: targetDir,
102
+ stdio: 'inherit',
103
+ });
104
+ } else {
105
+ console.log('āœ… Dependencies already installed, skipping npm install.');
106
+ }
107
+
34
108
  execSync(
35
- `npm install && npm run dev`,
109
+ `npm run dev`,
36
110
  {
37
111
  cwd: targetDir,
38
112
  stdio: 'inherit',
@@ -43,16 +117,6 @@ async function startServer() {
43
117
  }
44
118
  },
45
119
  );
46
-
47
- process.on('SIGINT', () => {
48
- server.close();
49
- process.exit(0);
50
- });
51
-
52
- process.on('SIGTERM', () => {
53
- server.close();
54
- process.exit(0);
55
- });
56
120
  } catch (error) {
57
121
  console.error(error);
58
122
  process.exit(1);
@@ -3,5 +3,5 @@ import { ChatInput } from '@agentscope-ai/chat';
3
3
 
4
4
  export default function () {
5
5
  const [value, setValue] = useState('Hello, Alibaba Cloud Spark Chat!');
6
- return <ChatInput placeholder='Please type here...' value={value} onChange={setValue}></ChatInput>
6
+ return <ChatInput placeholder='Please type here...' value={value} onChange={setValue} maxLength={100}></ChatInput>
7
7
  }
@@ -430,8 +430,14 @@ const ForwardSender = React.forwardRef<SenderRef, SenderProps>((props, ref) => {
430
430
  isCompositionRef.current = true;
431
431
  };
432
432
 
433
- const onInternalCompositionEnd = () => {
433
+ const onInternalCompositionEnd = (e: React.CompositionEvent<HTMLTextAreaElement>) => {
434
434
  isCompositionRef.current = false;
435
+ if (props.maxLength) {
436
+ const currentValue = (e.target as HTMLTextAreaElement).value;
437
+ if (currentValue.length > props.maxLength) {
438
+ triggerValueChange(currentValue.slice(0, props.maxLength));
439
+ }
440
+ }
435
441
  };
436
442
 
437
443
  const onInternalPressEnter: TextareaProps['onPressEnter'] = (e) => {
@@ -533,7 +539,10 @@ const ForwardSender = React.forwardRef<SenderRef, SenderProps>((props, ref) => {
533
539
  autoSize={autoSize}
534
540
  value={innerValue.slice(0, props.maxLength || Number.MAX_SAFE_INTEGER)}
535
541
  onChange={(event) => {
536
- const nextValue = (event.target as HTMLTextAreaElement).value;
542
+ let nextValue = (event.target as HTMLTextAreaElement).value;
543
+ if (props.maxLength && !isCompositionRef.current && nextValue.length > props.maxLength) {
544
+ nextValue = nextValue.slice(0, props.maxLength);
545
+ }
537
546
  triggerValueChange(
538
547
  nextValue,
539
548
  event as React.ChangeEvent<HTMLTextAreaElement>,
@@ -639,7 +648,7 @@ const ForwardSender = React.forwardRef<SenderRef, SenderProps>((props, ref) => {
639
648
  >
640
649
  {
641
650
  props.maxLength ? <div className={`${actionListCls}-length`}>
642
- {innerValue.length}/{props.maxLength}
651
+ {Math.min(innerValue.length, props.maxLength)}/{props.maxLength}
643
652
  </div> : null
644
653
  }
645
654
  <ActionButtonContext.Provider
@@ -225,8 +225,14 @@ var ForwardSender = /*#__PURE__*/React.forwardRef(function (props, ref) {
225
225
  var onInternalCompositionStart = function onInternalCompositionStart() {
226
226
  isCompositionRef.current = true;
227
227
  };
228
- var onInternalCompositionEnd = function onInternalCompositionEnd() {
228
+ var onInternalCompositionEnd = function onInternalCompositionEnd(e) {
229
229
  isCompositionRef.current = false;
230
+ if (props.maxLength) {
231
+ var currentValue = e.target.value;
232
+ if (currentValue.length > props.maxLength) {
233
+ triggerValueChange(currentValue.slice(0, props.maxLength));
234
+ }
235
+ }
230
236
  };
231
237
  var onInternalPressEnter = function onInternalPressEnter(e) {
232
238
  var canSubmit = !isCompositionRef.current && !suggestionOpenRef.current;
@@ -326,6 +332,9 @@ var ForwardSender = /*#__PURE__*/React.forwardRef(function (props, ref) {
326
332
  value: innerValue.slice(0, props.maxLength || Number.MAX_SAFE_INTEGER),
327
333
  onChange: function onChange(event) {
328
334
  var nextValue = event.target.value;
335
+ if (props.maxLength && !isCompositionRef.current && nextValue.length > props.maxLength) {
336
+ nextValue = nextValue.slice(0, props.maxLength);
337
+ }
329
338
  triggerValueChange(nextValue, event);
330
339
  if (hasSuggestions) {
331
340
  var nextSlashCommandKeyword = getSlashCommandKeyword(nextValue);
@@ -413,7 +422,7 @@ var ForwardSender = /*#__PURE__*/React.forwardRef(function (props, ref) {
413
422
  style: styles.actions,
414
423
  children: [props.maxLength ? /*#__PURE__*/_jsxs("div", {
415
424
  className: "".concat(actionListCls, "-length"),
416
- children: [innerValue.length, "/", props.maxLength]
425
+ children: [Math.min(innerValue.length, props.maxLength), "/", props.maxLength]
417
426
  }) : null, /*#__PURE__*/_jsx(ActionButtonContext.Provider, {
418
427
  value: contextValue,
419
428
  children: actionNode
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentscope-ai/chat",
3
- "version": "1.1.56",
3
+ "version": "1.1.58",
4
4
  "description": "a free and open-source chat framework for building excellent LLM-powered chat experiences",
5
5
  "license": "Apache-2.0",
6
6
  "sideEffects": [