Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
sdream-ai-fe
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
侯明涛
sdream-ai-fe
Commits
6992b396
Commit
6992b396
authored
Jun 02, 2026
by
Liu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix:提问自动进入子工作流
parent
e9c54c3a
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
1678 additions
and
249 deletions
+1678
-249
package-lock.json
+1221
-134
src/pages/Chat/Chat.tsx
+183
-87
src/pages/Chat/components/ChatItem/ChatAnswerParser.tsx
+10
-1
src/pages/Chat/components/ChatItem/ChatAnswerShower.tsx
+2
-1
src/pages/Chat/helper.ts
+262
-26
No files found.
package-lock.json
View file @
6992b396
...
...
@@ -16,6 +16,7 @@
"date-fns"
:
"^3.6.0"
,
"docx-preview"
:
"^0.3.6"
,
"github-markdown-css"
:
"^5.8.0"
,
"mermaid"
:
"^11.13.0"
,
"pdfjs-dist"
:
"^5.4.149"
,
"react"
:
"^18.3.1"
,
"react-dom"
:
"^18.3.1"
,
...
...
@@ -646,6 +647,18 @@
"node"
:
">=6.9.0"
}
},
"node_modules/@braintree/sanitize-url"
:
{
"version"
:
"7.1.2"
,
"resolved"
:
"https://registry.npmmirror.com/@braintree/sanitize-url/-/sanitize-url-7.1.2.tgz"
,
"integrity"
:
"sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA=="
,
"license"
:
"MIT"
},
"node_modules/@chevrotain/types"
:
{
"version"
:
"11.1.2"
,
"resolved"
:
"https://registry.npmmirror.com/@chevrotain/types/-/types-11.1.2.tgz"
,
"integrity"
:
"sha512-U+HFai5+zmJCkK86QsaJtoITlboZHBqrVketcO2ROv865xfCMSFpELQoz1GkX5GzME8pTa+3kbKrZHQtI0gdbw=="
,
"license"
:
"Apache-2.0"
},
"node_modules/@clack/core"
:
{
"version"
:
"0.3.5"
,
"resolved"
:
"https://registry.npmmirror.com/@clack/core/-/core-0.3.5.tgz"
,
...
...
@@ -675,7 +688,7 @@
},
"node_modules/@clack/prompts/node_modules/is-unicode-supported"
:
{
"version"
:
"1.3.0"
,
"
dev
"
:
true
,
"
extraneous
"
:
true
,
"inBundle"
:
true
,
"license"
:
"MIT"
,
"engines"
:
{
...
...
@@ -2698,6 +2711,51 @@
"deprecated"
:
"Use @eslint/object-schema instead"
,
"license"
:
"BSD-3-Clause"
},
"node_modules/@iconify/types"
:
{
"version"
:
"2.0.0"
,
"resolved"
:
"https://registry.npmmirror.com/@iconify/types/-/types-2.0.0.tgz"
,
"integrity"
:
"sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="
,
"license"
:
"MIT"
},
"node_modules/@iconify/utils"
:
{
"version"
:
"3.1.3"
,
"resolved"
:
"https://registry.npmmirror.com/@iconify/utils/-/utils-3.1.3.tgz"
,
"integrity"
:
"sha512-LPKOXPn/zV+zis1oOfGWogaXVpqUybF3ZS6SCZIsz8vg0ivVp9+fVqyYB7xq0aiST/VhUQYGO1qo6uoYSiEJqw=="
,
"license"
:
"MIT"
,
"dependencies"
:
{
"@antfu/install-pkg"
:
"^1.1.0"
,
"@iconify/types"
:
"^2.0.0"
,
"import-meta-resolve"
:
"^4.2.0"
}
},
"node_modules/@iconify/utils/node_modules/@antfu/install-pkg"
:
{
"version"
:
"1.1.0"
,
"resolved"
:
"https://registry.npmmirror.com/@antfu/install-pkg/-/install-pkg-1.1.0.tgz"
,
"integrity"
:
"sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ=="
,
"license"
:
"MIT"
,
"dependencies"
:
{
"package-manager-detector"
:
"^1.3.0"
,
"tinyexec"
:
"^1.0.1"
},
"funding"
:
{
"url"
:
"https://github.com/sponsors/antfu"
}
},
"node_modules/@iconify/utils/node_modules/package-manager-detector"
:
{
"version"
:
"1.6.0"
,
"resolved"
:
"https://registry.npmmirror.com/package-manager-detector/-/package-manager-detector-1.6.0.tgz"
,
"integrity"
:
"sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA=="
,
"license"
:
"MIT"
},
"node_modules/@iconify/utils/node_modules/tinyexec"
:
{
"version"
:
"1.1.2"
,
"resolved"
:
"https://registry.npmmirror.com/tinyexec/-/tinyexec-1.1.2.tgz"
,
"integrity"
:
"sha512-dAqSqE/RabpBKI8+h26GfLq6Vb3JVXs30XYQjdMjaj/c2tS8IYYMbIzP599KtRj7c57/wYApb3QjgRgXmrCukA=="
,
"license"
:
"MIT"
,
"engines"
:
{
"node"
:
">=18"
}
},
"node_modules/@internationalized/date"
:
{
"version"
:
"3.6.0"
,
"resolved"
:
"https://registry.npmmirror.com/@internationalized/date/-/date-3.6.0.tgz"
,
...
...
@@ -2877,6 +2935,15 @@
"@jridgewell/sourcemap-codec"
:
"^1.4.14"
}
},
"node_modules/@mermaid-js/parser"
:
{
"version"
:
"1.1.1"
,
"resolved"
:
"https://registry.npmmirror.com/@mermaid-js/parser/-/parser-1.1.1.tgz"
,
"integrity"
:
"sha512-VuHdsYMK1bT6X2JbcAaWAhugTRvRBRyuZgd+c22swUeI9g/ntaxF7CY7dYarhZovofCbUNO0G7JesfmNtjYOCw=="
,
"license"
:
"MIT"
,
"dependencies"
:
{
"@chevrotain/types"
:
"~11.1.1"
}
},
"node_modules/@module-federation/error-codes"
:
{
"version"
:
"0.17.1"
,
"resolved"
:
"https://registry.npmmirror.com/@module-federation/error-codes/-/error-codes-0.17.1.tgz"
,
...
...
@@ -6501,6 +6568,259 @@
"@types/node"
:
"*"
}
},
"node_modules/@types/d3"
:
{
"version"
:
"7.4.3"
,
"resolved"
:
"https://registry.npmmirror.com/@types/d3/-/d3-7.4.3.tgz"
,
"integrity"
:
"sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww=="
,
"license"
:
"MIT"
,
"dependencies"
:
{
"@types/d3-array"
:
"*"
,
"@types/d3-axis"
:
"*"
,
"@types/d3-brush"
:
"*"
,
"@types/d3-chord"
:
"*"
,
"@types/d3-color"
:
"*"
,
"@types/d3-contour"
:
"*"
,
"@types/d3-delaunay"
:
"*"
,
"@types/d3-dispatch"
:
"*"
,
"@types/d3-drag"
:
"*"
,
"@types/d3-dsv"
:
"*"
,
"@types/d3-ease"
:
"*"
,
"@types/d3-fetch"
:
"*"
,
"@types/d3-force"
:
"*"
,
"@types/d3-format"
:
"*"
,
"@types/d3-geo"
:
"*"
,
"@types/d3-hierarchy"
:
"*"
,
"@types/d3-interpolate"
:
"*"
,
"@types/d3-path"
:
"*"
,
"@types/d3-polygon"
:
"*"
,
"@types/d3-quadtree"
:
"*"
,
"@types/d3-random"
:
"*"
,
"@types/d3-scale"
:
"*"
,
"@types/d3-scale-chromatic"
:
"*"
,
"@types/d3-selection"
:
"*"
,
"@types/d3-shape"
:
"*"
,
"@types/d3-time"
:
"*"
,
"@types/d3-time-format"
:
"*"
,
"@types/d3-timer"
:
"*"
,
"@types/d3-transition"
:
"*"
,
"@types/d3-zoom"
:
"*"
}
},
"node_modules/@types/d3-array"
:
{
"version"
:
"3.2.2"
,
"resolved"
:
"https://registry.npmmirror.com/@types/d3-array/-/d3-array-3.2.2.tgz"
,
"integrity"
:
"sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw=="
,
"license"
:
"MIT"
},
"node_modules/@types/d3-axis"
:
{
"version"
:
"3.0.6"
,
"resolved"
:
"https://registry.npmmirror.com/@types/d3-axis/-/d3-axis-3.0.6.tgz"
,
"integrity"
:
"sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw=="
,
"license"
:
"MIT"
,
"dependencies"
:
{
"@types/d3-selection"
:
"*"
}
},
"node_modules/@types/d3-brush"
:
{
"version"
:
"3.0.6"
,
"resolved"
:
"https://registry.npmmirror.com/@types/d3-brush/-/d3-brush-3.0.6.tgz"
,
"integrity"
:
"sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A=="
,
"license"
:
"MIT"
,
"dependencies"
:
{
"@types/d3-selection"
:
"*"
}
},
"node_modules/@types/d3-chord"
:
{
"version"
:
"3.0.6"
,
"resolved"
:
"https://registry.npmmirror.com/@types/d3-chord/-/d3-chord-3.0.6.tgz"
,
"integrity"
:
"sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg=="
,
"license"
:
"MIT"
},
"node_modules/@types/d3-color"
:
{
"version"
:
"3.1.3"
,
"resolved"
:
"https://registry.npmmirror.com/@types/d3-color/-/d3-color-3.1.3.tgz"
,
"integrity"
:
"sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A=="
,
"license"
:
"MIT"
},
"node_modules/@types/d3-contour"
:
{
"version"
:
"3.0.6"
,
"resolved"
:
"https://registry.npmmirror.com/@types/d3-contour/-/d3-contour-3.0.6.tgz"
,
"integrity"
:
"sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg=="
,
"license"
:
"MIT"
,
"dependencies"
:
{
"@types/d3-array"
:
"*"
,
"@types/geojson"
:
"*"
}
},
"node_modules/@types/d3-delaunay"
:
{
"version"
:
"6.0.4"
,
"resolved"
:
"https://registry.npmmirror.com/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz"
,
"integrity"
:
"sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw=="
,
"license"
:
"MIT"
},
"node_modules/@types/d3-dispatch"
:
{
"version"
:
"3.0.7"
,
"resolved"
:
"https://registry.npmmirror.com/@types/d3-dispatch/-/d3-dispatch-3.0.7.tgz"
,
"integrity"
:
"sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA=="
,
"license"
:
"MIT"
},
"node_modules/@types/d3-drag"
:
{
"version"
:
"3.0.7"
,
"resolved"
:
"https://registry.npmmirror.com/@types/d3-drag/-/d3-drag-3.0.7.tgz"
,
"integrity"
:
"sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ=="
,
"license"
:
"MIT"
,
"dependencies"
:
{
"@types/d3-selection"
:
"*"
}
},
"node_modules/@types/d3-dsv"
:
{
"version"
:
"3.0.7"
,
"resolved"
:
"https://registry.npmmirror.com/@types/d3-dsv/-/d3-dsv-3.0.7.tgz"
,
"integrity"
:
"sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g=="
,
"license"
:
"MIT"
},
"node_modules/@types/d3-ease"
:
{
"version"
:
"3.0.2"
,
"resolved"
:
"https://registry.npmmirror.com/@types/d3-ease/-/d3-ease-3.0.2.tgz"
,
"integrity"
:
"sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA=="
,
"license"
:
"MIT"
},
"node_modules/@types/d3-fetch"
:
{
"version"
:
"3.0.7"
,
"resolved"
:
"https://registry.npmmirror.com/@types/d3-fetch/-/d3-fetch-3.0.7.tgz"
,
"integrity"
:
"sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA=="
,
"license"
:
"MIT"
,
"dependencies"
:
{
"@types/d3-dsv"
:
"*"
}
},
"node_modules/@types/d3-force"
:
{
"version"
:
"3.0.10"
,
"resolved"
:
"https://registry.npmmirror.com/@types/d3-force/-/d3-force-3.0.10.tgz"
,
"integrity"
:
"sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw=="
,
"license"
:
"MIT"
},
"node_modules/@types/d3-format"
:
{
"version"
:
"3.0.4"
,
"resolved"
:
"https://registry.npmmirror.com/@types/d3-format/-/d3-format-3.0.4.tgz"
,
"integrity"
:
"sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g=="
,
"license"
:
"MIT"
},
"node_modules/@types/d3-geo"
:
{
"version"
:
"3.1.0"
,
"resolved"
:
"https://registry.npmmirror.com/@types/d3-geo/-/d3-geo-3.1.0.tgz"
,
"integrity"
:
"sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ=="
,
"license"
:
"MIT"
,
"dependencies"
:
{
"@types/geojson"
:
"*"
}
},
"node_modules/@types/d3-hierarchy"
:
{
"version"
:
"3.1.7"
,
"resolved"
:
"https://registry.npmmirror.com/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz"
,
"integrity"
:
"sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg=="
,
"license"
:
"MIT"
},
"node_modules/@types/d3-interpolate"
:
{
"version"
:
"3.0.4"
,
"resolved"
:
"https://registry.npmmirror.com/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz"
,
"integrity"
:
"sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA=="
,
"license"
:
"MIT"
,
"dependencies"
:
{
"@types/d3-color"
:
"*"
}
},
"node_modules/@types/d3-path"
:
{
"version"
:
"3.1.1"
,
"resolved"
:
"https://registry.npmmirror.com/@types/d3-path/-/d3-path-3.1.1.tgz"
,
"integrity"
:
"sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg=="
,
"license"
:
"MIT"
},
"node_modules/@types/d3-polygon"
:
{
"version"
:
"3.0.2"
,
"resolved"
:
"https://registry.npmmirror.com/@types/d3-polygon/-/d3-polygon-3.0.2.tgz"
,
"integrity"
:
"sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA=="
,
"license"
:
"MIT"
},
"node_modules/@types/d3-quadtree"
:
{
"version"
:
"3.0.6"
,
"resolved"
:
"https://registry.npmmirror.com/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz"
,
"integrity"
:
"sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg=="
,
"license"
:
"MIT"
},
"node_modules/@types/d3-random"
:
{
"version"
:
"3.0.3"
,
"resolved"
:
"https://registry.npmmirror.com/@types/d3-random/-/d3-random-3.0.3.tgz"
,
"integrity"
:
"sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ=="
,
"license"
:
"MIT"
},
"node_modules/@types/d3-scale"
:
{
"version"
:
"4.0.9"
,
"resolved"
:
"https://registry.npmmirror.com/@types/d3-scale/-/d3-scale-4.0.9.tgz"
,
"integrity"
:
"sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw=="
,
"license"
:
"MIT"
,
"dependencies"
:
{
"@types/d3-time"
:
"*"
}
},
"node_modules/@types/d3-scale-chromatic"
:
{
"version"
:
"3.1.0"
,
"resolved"
:
"https://registry.npmmirror.com/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz"
,
"integrity"
:
"sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ=="
,
"license"
:
"MIT"
},
"node_modules/@types/d3-selection"
:
{
"version"
:
"3.0.11"
,
"resolved"
:
"https://registry.npmmirror.com/@types/d3-selection/-/d3-selection-3.0.11.tgz"
,
"integrity"
:
"sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w=="
,
"license"
:
"MIT"
},
"node_modules/@types/d3-shape"
:
{
"version"
:
"3.1.8"
,
"resolved"
:
"https://registry.npmmirror.com/@types/d3-shape/-/d3-shape-3.1.8.tgz"
,
"integrity"
:
"sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w=="
,
"license"
:
"MIT"
,
"dependencies"
:
{
"@types/d3-path"
:
"*"
}
},
"node_modules/@types/d3-time"
:
{
"version"
:
"3.0.4"
,
"resolved"
:
"https://registry.npmmirror.com/@types/d3-time/-/d3-time-3.0.4.tgz"
,
"integrity"
:
"sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g=="
,
"license"
:
"MIT"
},
"node_modules/@types/d3-time-format"
:
{
"version"
:
"4.0.3"
,
"resolved"
:
"https://registry.npmmirror.com/@types/d3-time-format/-/d3-time-format-4.0.3.tgz"
,
"integrity"
:
"sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg=="
,
"license"
:
"MIT"
},
"node_modules/@types/d3-timer"
:
{
"version"
:
"3.0.2"
,
"resolved"
:
"https://registry.npmmirror.com/@types/d3-timer/-/d3-timer-3.0.2.tgz"
,
"integrity"
:
"sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw=="
,
"license"
:
"MIT"
},
"node_modules/@types/d3-transition"
:
{
"version"
:
"3.0.9"
,
"resolved"
:
"https://registry.npmmirror.com/@types/d3-transition/-/d3-transition-3.0.9.tgz"
,
"integrity"
:
"sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg=="
,
"license"
:
"MIT"
,
"dependencies"
:
{
"@types/d3-selection"
:
"*"
}
},
"node_modules/@types/d3-zoom"
:
{
"version"
:
"3.0.8"
,
"resolved"
:
"https://registry.npmmirror.com/@types/d3-zoom/-/d3-zoom-3.0.8.tgz"
,
"integrity"
:
"sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw=="
,
"license"
:
"MIT"
,
"dependencies"
:
{
"@types/d3-interpolate"
:
"*"
,
"@types/d3-selection"
:
"*"
}
},
"node_modules/@types/debug"
:
{
"version"
:
"4.1.12"
,
"resolved"
:
"https://registry.npmmirror.com/@types/debug/-/debug-4.1.12.tgz"
,
...
...
@@ -6547,6 +6867,12 @@
"@types/estree"
:
"*"
}
},
"node_modules/@types/geojson"
:
{
"version"
:
"7946.0.16"
,
"resolved"
:
"https://registry.npmmirror.com/@types/geojson/-/geojson-7946.0.16.tgz"
,
"integrity"
:
"sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg=="
,
"license"
:
"MIT"
},
"node_modules/@types/hast"
:
{
"version"
:
"3.0.4"
,
"resolved"
:
"https://registry.npmmirror.com/@types/hast/-/hast-3.0.4.tgz"
,
...
...
@@ -6647,6 +6973,13 @@
"tapable"
:
"^2.2.0"
}
},
"node_modules/@types/trusted-types"
:
{
"version"
:
"2.0.7"
,
"resolved"
:
"https://registry.npmmirror.com/@types/trusted-types/-/trusted-types-2.0.7.tgz"
,
"integrity"
:
"sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="
,
"license"
:
"MIT"
,
"optional"
:
true
},
"node_modules/@types/unist"
:
{
"version"
:
"2.0.11"
,
"resolved"
:
"https://registry.npmmirror.com/@types/unist/-/unist-2.0.11.tgz"
,
...
...
@@ -7249,6 +7582,16 @@
"win32"
]
},
"node_modules/@upsetjs/venn.js"
:
{
"version"
:
"2.0.0"
,
"resolved"
:
"https://registry.npmmirror.com/@upsetjs/venn.js/-/venn.js-2.0.0.tgz"
,
"integrity"
:
"sha512-WbBhLrooyePuQ1VZxrJjtLvTc4NVfpOyKx0sKqioq9bX1C1m7Jgykkn8gLrtwumBioXIqam8DLxp88Adbue6Hw=="
,
"license"
:
"MIT"
,
"optionalDependencies"
:
{
"d3-selection"
:
"^3.0.0"
,
"d3-transition"
:
"^3.0.1"
}
},
"node_modules/@vitest/eslint-plugin"
:
{
"version"
:
"1.3.4"
,
"resolved"
:
"https://registry.npmmirror.com/@vitest/eslint-plugin/-/eslint-plugin-1.3.4.tgz"
,
...
...
@@ -8550,184 +8893,713 @@
"dev"
:
true
,
"license"
:
"MIT"
,
"dependencies"
:
{
"browserslist"
:
"^4.25.1"
},
"funding"
:
{
"type"
:
"opencollective"
,
"url"
:
"https://opencollective.com/core-js"
"browserslist"
:
"^4.25.1"
},
"funding"
:
{
"type"
:
"opencollective"
,
"url"
:
"https://opencollective.com/core-js"
}
},
"node_modules/core-util-is"
:
{
"version"
:
"1.0.3"
,
"resolved"
:
"https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz"
,
"integrity"
:
"sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
,
"license"
:
"MIT"
},
"node_modules/cors"
:
{
"version"
:
"2.8.5"
,
"resolved"
:
"https://registry.npmmirror.com/cors/-/cors-2.8.5.tgz"
,
"integrity"
:
"sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"dependencies"
:
{
"object-assign"
:
"^4"
,
"vary"
:
"^1"
},
"engines"
:
{
"node"
:
">= 0.10"
}
},
"node_modules/cose-base"
:
{
"version"
:
"1.0.3"
,
"resolved"
:
"https://registry.npmmirror.com/cose-base/-/cose-base-1.0.3.tgz"
,
"integrity"
:
"sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg=="
,
"license"
:
"MIT"
,
"dependencies"
:
{
"layout-base"
:
"^1.0.0"
}
},
"node_modules/cosmiconfig"
:
{
"version"
:
"8.3.6"
,
"resolved"
:
"https://registry.npmmirror.com/cosmiconfig/-/cosmiconfig-8.3.6.tgz"
,
"integrity"
:
"sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"dependencies"
:
{
"import-fresh"
:
"^3.3.0"
,
"js-yaml"
:
"^4.1.0"
,
"parse-json"
:
"^5.2.0"
,
"path-type"
:
"^4.0.0"
},
"engines"
:
{
"node"
:
">=14"
},
"funding"
:
{
"url"
:
"https://github.com/sponsors/d-fischer"
},
"peerDependencies"
:
{
"typescript"
:
">=4.9.5"
},
"peerDependenciesMeta"
:
{
"typescript"
:
{
"optional"
:
true
}
}
},
"node_modules/crc-32"
:
{
"version"
:
"1.2.2"
,
"resolved"
:
"https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz"
,
"integrity"
:
"sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ=="
,
"license"
:
"Apache-2.0"
,
"bin"
:
{
"crc32"
:
"bin/crc32.njs"
},
"engines"
:
{
"node"
:
">=0.8"
}
},
"node_modules/cross-spawn"
:
{
"version"
:
"7.0.6"
,
"resolved"
:
"https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.6.tgz"
,
"integrity"
:
"sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="
,
"license"
:
"MIT"
,
"dependencies"
:
{
"path-key"
:
"^3.1.0"
,
"shebang-command"
:
"^2.0.0"
,
"which"
:
"^2.0.1"
},
"engines"
:
{
"node"
:
">= 8"
}
},
"node_modules/css-select"
:
{
"version"
:
"5.2.2"
,
"resolved"
:
"https://registry.npmmirror.com/css-select/-/css-select-5.2.2.tgz"
,
"integrity"
:
"sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw=="
,
"dev"
:
true
,
"license"
:
"BSD-2-Clause"
,
"dependencies"
:
{
"boolbase"
:
"^1.0.0"
,
"css-what"
:
"^6.1.0"
,
"domhandler"
:
"^5.0.2"
,
"domutils"
:
"^3.0.1"
,
"nth-check"
:
"^2.0.1"
},
"funding"
:
{
"url"
:
"https://github.com/sponsors/fb55"
}
},
"node_modules/css-tree"
:
{
"version"
:
"2.3.1"
,
"resolved"
:
"https://registry.npmmirror.com/css-tree/-/css-tree-2.3.1.tgz"
,
"integrity"
:
"sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"dependencies"
:
{
"mdn-data"
:
"2.0.30"
,
"source-map-js"
:
"^1.0.1"
},
"engines"
:
{
"node"
:
"^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
}
},
"node_modules/css-what"
:
{
"version"
:
"6.2.2"
,
"resolved"
:
"https://registry.npmmirror.com/css-what/-/css-what-6.2.2.tgz"
,
"integrity"
:
"sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA=="
,
"dev"
:
true
,
"license"
:
"BSD-2-Clause"
,
"engines"
:
{
"node"
:
">= 6"
},
"funding"
:
{
"url"
:
"https://github.com/sponsors/fb55"
}
},
"node_modules/cssesc"
:
{
"version"
:
"3.0.0"
,
"resolved"
:
"https://registry.npmmirror.com/cssesc/-/cssesc-3.0.0.tgz"
,
"integrity"
:
"sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="
,
"license"
:
"MIT"
,
"bin"
:
{
"cssesc"
:
"bin/cssesc"
},
"engines"
:
{
"node"
:
">=4"
}
},
"node_modules/csso"
:
{
"version"
:
"5.0.5"
,
"resolved"
:
"https://registry.npmmirror.com/csso/-/csso-5.0.5.tgz"
,
"integrity"
:
"sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"dependencies"
:
{
"css-tree"
:
"~2.2.0"
},
"engines"
:
{
"node"
:
"^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
,
"npm"
:
">=7.0.0"
}
},
"node_modules/csso/node_modules/css-tree"
:
{
"version"
:
"2.2.1"
,
"resolved"
:
"https://registry.npmmirror.com/css-tree/-/css-tree-2.2.1.tgz"
,
"integrity"
:
"sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"dependencies"
:
{
"mdn-data"
:
"2.0.28"
,
"source-map-js"
:
"^1.0.1"
},
"engines"
:
{
"node"
:
"^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
,
"npm"
:
">=7.0.0"
}
},
"node_modules/csso/node_modules/mdn-data"
:
{
"version"
:
"2.0.28"
,
"resolved"
:
"https://registry.npmmirror.com/mdn-data/-/mdn-data-2.0.28.tgz"
,
"integrity"
:
"sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g=="
,
"dev"
:
true
,
"license"
:
"CC0-1.0"
},
"node_modules/csstype"
:
{
"version"
:
"3.1.3"
,
"resolved"
:
"https://registry.npmmirror.com/csstype/-/csstype-3.1.3.tgz"
,
"integrity"
:
"sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
,
"license"
:
"MIT"
},
"node_modules/cytoscape"
:
{
"version"
:
"3.33.4"
,
"resolved"
:
"https://registry.npmmirror.com/cytoscape/-/cytoscape-3.33.4.tgz"
,
"integrity"
:
"sha512-HIN5Pmd9MrX9BkV7tDwnOcEJCSFvCpc8X97h3f508J6I5FsqAY65wKOCvgH2CuP42CaahWaz4tuh32SOOIH7ww=="
,
"license"
:
"MIT"
,
"engines"
:
{
"node"
:
">=0.10"
}
},
"node_modules/cytoscape-cose-bilkent"
:
{
"version"
:
"4.1.0"
,
"resolved"
:
"https://registry.npmmirror.com/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz"
,
"integrity"
:
"sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ=="
,
"license"
:
"MIT"
,
"dependencies"
:
{
"cose-base"
:
"^1.0.0"
},
"peerDependencies"
:
{
"cytoscape"
:
"^3.2.0"
}
},
"node_modules/cytoscape-fcose"
:
{
"version"
:
"2.2.0"
,
"resolved"
:
"https://registry.npmmirror.com/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz"
,
"integrity"
:
"sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ=="
,
"license"
:
"MIT"
,
"dependencies"
:
{
"cose-base"
:
"^2.2.0"
},
"peerDependencies"
:
{
"cytoscape"
:
"^3.2.0"
}
},
"node_modules/cytoscape-fcose/node_modules/cose-base"
:
{
"version"
:
"2.2.0"
,
"resolved"
:
"https://registry.npmmirror.com/cose-base/-/cose-base-2.2.0.tgz"
,
"integrity"
:
"sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g=="
,
"license"
:
"MIT"
,
"dependencies"
:
{
"layout-base"
:
"^2.0.0"
}
},
"node_modules/cytoscape-fcose/node_modules/layout-base"
:
{
"version"
:
"2.0.1"
,
"resolved"
:
"https://registry.npmmirror.com/layout-base/-/layout-base-2.0.1.tgz"
,
"integrity"
:
"sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg=="
,
"license"
:
"MIT"
},
"node_modules/d3"
:
{
"version"
:
"7.9.0"
,
"resolved"
:
"https://registry.npmmirror.com/d3/-/d3-7.9.0.tgz"
,
"integrity"
:
"sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA=="
,
"license"
:
"ISC"
,
"dependencies"
:
{
"d3-array"
:
"3"
,
"d3-axis"
:
"3"
,
"d3-brush"
:
"3"
,
"d3-chord"
:
"3"
,
"d3-color"
:
"3"
,
"d3-contour"
:
"4"
,
"d3-delaunay"
:
"6"
,
"d3-dispatch"
:
"3"
,
"d3-drag"
:
"3"
,
"d3-dsv"
:
"3"
,
"d3-ease"
:
"3"
,
"d3-fetch"
:
"3"
,
"d3-force"
:
"3"
,
"d3-format"
:
"3"
,
"d3-geo"
:
"3"
,
"d3-hierarchy"
:
"3"
,
"d3-interpolate"
:
"3"
,
"d3-path"
:
"3"
,
"d3-polygon"
:
"3"
,
"d3-quadtree"
:
"3"
,
"d3-random"
:
"3"
,
"d3-scale"
:
"4"
,
"d3-scale-chromatic"
:
"3"
,
"d3-selection"
:
"3"
,
"d3-shape"
:
"3"
,
"d3-time"
:
"3"
,
"d3-time-format"
:
"4"
,
"d3-timer"
:
"3"
,
"d3-transition"
:
"3"
,
"d3-zoom"
:
"3"
},
"engines"
:
{
"node"
:
">=12"
}
},
"node_modules/d3-array"
:
{
"version"
:
"3.2.4"
,
"resolved"
:
"https://registry.npmmirror.com/d3-array/-/d3-array-3.2.4.tgz"
,
"integrity"
:
"sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg=="
,
"license"
:
"ISC"
,
"dependencies"
:
{
"internmap"
:
"1 - 2"
},
"engines"
:
{
"node"
:
">=12"
}
},
"node_modules/d3-axis"
:
{
"version"
:
"3.0.0"
,
"resolved"
:
"https://registry.npmmirror.com/d3-axis/-/d3-axis-3.0.0.tgz"
,
"integrity"
:
"sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw=="
,
"license"
:
"ISC"
,
"engines"
:
{
"node"
:
">=12"
}
},
"node_modules/d3-brush"
:
{
"version"
:
"3.0.0"
,
"resolved"
:
"https://registry.npmmirror.com/d3-brush/-/d3-brush-3.0.0.tgz"
,
"integrity"
:
"sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ=="
,
"license"
:
"ISC"
,
"dependencies"
:
{
"d3-dispatch"
:
"1 - 3"
,
"d3-drag"
:
"2 - 3"
,
"d3-interpolate"
:
"1 - 3"
,
"d3-selection"
:
"3"
,
"d3-transition"
:
"3"
},
"engines"
:
{
"node"
:
">=12"
}
},
"node_modules/d3-chord"
:
{
"version"
:
"3.0.1"
,
"resolved"
:
"https://registry.npmmirror.com/d3-chord/-/d3-chord-3.0.1.tgz"
,
"integrity"
:
"sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g=="
,
"license"
:
"ISC"
,
"dependencies"
:
{
"d3-path"
:
"1 - 3"
},
"engines"
:
{
"node"
:
">=12"
}
},
"node_modules/d3-color"
:
{
"version"
:
"3.1.0"
,
"resolved"
:
"https://registry.npmmirror.com/d3-color/-/d3-color-3.1.0.tgz"
,
"integrity"
:
"sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA=="
,
"license"
:
"ISC"
,
"engines"
:
{
"node"
:
">=12"
}
},
"node_modules/d3-contour"
:
{
"version"
:
"4.0.2"
,
"resolved"
:
"https://registry.npmmirror.com/d3-contour/-/d3-contour-4.0.2.tgz"
,
"integrity"
:
"sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA=="
,
"license"
:
"ISC"
,
"dependencies"
:
{
"d3-array"
:
"^3.2.0"
},
"engines"
:
{
"node"
:
">=12"
}
},
"node_modules/d3-delaunay"
:
{
"version"
:
"6.0.4"
,
"resolved"
:
"https://registry.npmmirror.com/d3-delaunay/-/d3-delaunay-6.0.4.tgz"
,
"integrity"
:
"sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A=="
,
"license"
:
"ISC"
,
"dependencies"
:
{
"delaunator"
:
"5"
},
"engines"
:
{
"node"
:
">=12"
}
},
"node_modules/d3-dispatch"
:
{
"version"
:
"3.0.1"
,
"resolved"
:
"https://registry.npmmirror.com/d3-dispatch/-/d3-dispatch-3.0.1.tgz"
,
"integrity"
:
"sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg=="
,
"license"
:
"ISC"
,
"engines"
:
{
"node"
:
">=12"
}
},
"node_modules/d3-drag"
:
{
"version"
:
"3.0.0"
,
"resolved"
:
"https://registry.npmmirror.com/d3-drag/-/d3-drag-3.0.0.tgz"
,
"integrity"
:
"sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg=="
,
"license"
:
"ISC"
,
"dependencies"
:
{
"d3-dispatch"
:
"1 - 3"
,
"d3-selection"
:
"3"
},
"engines"
:
{
"node"
:
">=12"
}
},
"node_modules/d3-dsv"
:
{
"version"
:
"3.0.1"
,
"resolved"
:
"https://registry.npmmirror.com/d3-dsv/-/d3-dsv-3.0.1.tgz"
,
"integrity"
:
"sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q=="
,
"license"
:
"ISC"
,
"dependencies"
:
{
"commander"
:
"7"
,
"iconv-lite"
:
"0.6"
,
"rw"
:
"1"
},
"bin"
:
{
"csv2json"
:
"bin/dsv2json.js"
,
"csv2tsv"
:
"bin/dsv2dsv.js"
,
"dsv2dsv"
:
"bin/dsv2dsv.js"
,
"dsv2json"
:
"bin/dsv2json.js"
,
"json2csv"
:
"bin/json2dsv.js"
,
"json2dsv"
:
"bin/json2dsv.js"
,
"json2tsv"
:
"bin/json2dsv.js"
,
"tsv2csv"
:
"bin/dsv2dsv.js"
,
"tsv2json"
:
"bin/dsv2json.js"
},
"engines"
:
{
"node"
:
">=12"
}
},
"node_modules/d3-dsv/node_modules/commander"
:
{
"version"
:
"7.2.0"
,
"resolved"
:
"https://registry.npmmirror.com/commander/-/commander-7.2.0.tgz"
,
"integrity"
:
"sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="
,
"license"
:
"MIT"
,
"engines"
:
{
"node"
:
">= 10"
}
},
"node_modules/d3-dsv/node_modules/iconv-lite"
:
{
"version"
:
"0.6.3"
,
"resolved"
:
"https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz"
,
"integrity"
:
"sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="
,
"license"
:
"MIT"
,
"dependencies"
:
{
"safer-buffer"
:
">= 2.1.2 < 3.0.0"
},
"engines"
:
{
"node"
:
">=0.10.0"
}
},
"node_modules/d3-ease"
:
{
"version"
:
"3.0.1"
,
"resolved"
:
"https://registry.npmmirror.com/d3-ease/-/d3-ease-3.0.1.tgz"
,
"integrity"
:
"sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w=="
,
"license"
:
"BSD-3-Clause"
,
"engines"
:
{
"node"
:
">=12"
}
},
"node_modules/d3-fetch"
:
{
"version"
:
"3.0.1"
,
"resolved"
:
"https://registry.npmmirror.com/d3-fetch/-/d3-fetch-3.0.1.tgz"
,
"integrity"
:
"sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw=="
,
"license"
:
"ISC"
,
"dependencies"
:
{
"d3-dsv"
:
"1 - 3"
},
"engines"
:
{
"node"
:
">=12"
}
},
"node_modules/d3-force"
:
{
"version"
:
"3.0.0"
,
"resolved"
:
"https://registry.npmmirror.com/d3-force/-/d3-force-3.0.0.tgz"
,
"integrity"
:
"sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg=="
,
"license"
:
"ISC"
,
"dependencies"
:
{
"d3-dispatch"
:
"1 - 3"
,
"d3-quadtree"
:
"1 - 3"
,
"d3-timer"
:
"1 - 3"
},
"engines"
:
{
"node"
:
">=12"
}
},
"node_modules/d3-format"
:
{
"version"
:
"3.1.2"
,
"resolved"
:
"https://registry.npmmirror.com/d3-format/-/d3-format-3.1.2.tgz"
,
"integrity"
:
"sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg=="
,
"license"
:
"ISC"
,
"engines"
:
{
"node"
:
">=12"
}
},
"node_modules/d3-geo"
:
{
"version"
:
"3.1.1"
,
"resolved"
:
"https://registry.npmmirror.com/d3-geo/-/d3-geo-3.1.1.tgz"
,
"integrity"
:
"sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q=="
,
"license"
:
"ISC"
,
"dependencies"
:
{
"d3-array"
:
"2.5.0 - 3"
},
"engines"
:
{
"node"
:
">=12"
}
},
"node_modules/d3-hierarchy"
:
{
"version"
:
"3.1.2"
,
"resolved"
:
"https://registry.npmmirror.com/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz"
,
"integrity"
:
"sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA=="
,
"license"
:
"ISC"
,
"engines"
:
{
"node"
:
">=12"
}
},
"node_modules/d3-interpolate"
:
{
"version"
:
"3.0.1"
,
"resolved"
:
"https://registry.npmmirror.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz"
,
"integrity"
:
"sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g=="
,
"license"
:
"ISC"
,
"dependencies"
:
{
"d3-color"
:
"1 - 3"
},
"engines"
:
{
"node"
:
">=12"
}
},
"node_modules/d3-path"
:
{
"version"
:
"3.1.0"
,
"resolved"
:
"https://registry.npmmirror.com/d3-path/-/d3-path-3.1.0.tgz"
,
"integrity"
:
"sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ=="
,
"license"
:
"ISC"
,
"engines"
:
{
"node"
:
">=12"
}
},
"node_modules/d3-polygon"
:
{
"version"
:
"3.0.1"
,
"resolved"
:
"https://registry.npmmirror.com/d3-polygon/-/d3-polygon-3.0.1.tgz"
,
"integrity"
:
"sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg=="
,
"license"
:
"ISC"
,
"engines"
:
{
"node"
:
">=12"
}
},
"node_modules/d3-quadtree"
:
{
"version"
:
"3.0.1"
,
"resolved"
:
"https://registry.npmmirror.com/d3-quadtree/-/d3-quadtree-3.0.1.tgz"
,
"integrity"
:
"sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw=="
,
"license"
:
"ISC"
,
"engines"
:
{
"node"
:
">=12"
}
},
"node_modules/d3-random"
:
{
"version"
:
"3.0.1"
,
"resolved"
:
"https://registry.npmmirror.com/d3-random/-/d3-random-3.0.1.tgz"
,
"integrity"
:
"sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ=="
,
"license"
:
"ISC"
,
"engines"
:
{
"node"
:
">=12"
}
},
"node_modules/d3-sankey"
:
{
"version"
:
"0.12.3"
,
"resolved"
:
"https://registry.npmmirror.com/d3-sankey/-/d3-sankey-0.12.3.tgz"
,
"integrity"
:
"sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ=="
,
"license"
:
"BSD-3-Clause"
,
"dependencies"
:
{
"d3-array"
:
"1 - 2"
,
"d3-shape"
:
"^1.2.0"
}
},
"node_modules/d3-sankey/node_modules/d3-array"
:
{
"version"
:
"2.12.1"
,
"resolved"
:
"https://registry.npmmirror.com/d3-array/-/d3-array-2.12.1.tgz"
,
"integrity"
:
"sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ=="
,
"license"
:
"BSD-3-Clause"
,
"dependencies"
:
{
"internmap"
:
"^1.0.0"
}
},
"node_modules/d3-sankey/node_modules/d3-path"
:
{
"version"
:
"1.0.9"
,
"resolved"
:
"https://registry.npmmirror.com/d3-path/-/d3-path-1.0.9.tgz"
,
"integrity"
:
"sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg=="
,
"license"
:
"BSD-3-Clause"
},
"node_modules/d3-sankey/node_modules/d3-shape"
:
{
"version"
:
"1.3.7"
,
"resolved"
:
"https://registry.npmmirror.com/d3-shape/-/d3-shape-1.3.7.tgz"
,
"integrity"
:
"sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw=="
,
"license"
:
"BSD-3-Clause"
,
"dependencies"
:
{
"d3-path"
:
"1"
}
},
"node_modules/
core-util-is
"
:
{
"version"
:
"1.0.
3
"
,
"resolved"
:
"https://registry.npm
js.org/core-util-is/-/core-util-is-1.0.3
.tgz"
,
"integrity"
:
"sha512-
ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ
=="
,
"license"
:
"
MIT
"
"node_modules/
d3-sankey/node_modules/internmap
"
:
{
"version"
:
"1.0.
1
"
,
"resolved"
:
"https://registry.npm
mirror.com/internmap/-/internmap-1.0.1
.tgz"
,
"integrity"
:
"sha512-
lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw
=="
,
"license"
:
"
ISC
"
},
"node_modules/cors"
:
{
"version"
:
"2.8.5"
,
"resolved"
:
"https://registry.npmmirror.com/cors/-/cors-2.8.5.tgz"
,
"integrity"
:
"sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"node_modules/d3-scale"
:
{
"version"
:
"4.0.2"
,
"resolved"
:
"https://registry.npmmirror.com/d3-scale/-/d3-scale-4.0.2.tgz"
,
"integrity"
:
"sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ=="
,
"license"
:
"ISC"
,
"dependencies"
:
{
"object-assign"
:
"^4"
,
"vary"
:
"^1"
"d3-array"
:
"2.10.0 - 3"
,
"d3-format"
:
"1 - 3"
,
"d3-interpolate"
:
"1.2.0 - 3"
,
"d3-time"
:
"2.1.1 - 3"
,
"d3-time-format"
:
"2 - 4"
},
"engines"
:
{
"node"
:
">=
0.10
"
"node"
:
">=
12
"
}
},
"node_modules/cosmiconfig"
:
{
"version"
:
"8.3.6"
,
"resolved"
:
"https://registry.npmmirror.com/cosmiconfig/-/cosmiconfig-8.3.6.tgz"
,
"integrity"
:
"sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"node_modules/d3-scale-chromatic"
:
{
"version"
:
"3.1.0"
,
"resolved"
:
"https://registry.npmmirror.com/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz"
,
"integrity"
:
"sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ=="
,
"license"
:
"ISC"
,
"dependencies"
:
{
"import-fresh"
:
"^3.3.0"
,
"js-yaml"
:
"^4.1.0"
,
"parse-json"
:
"^5.2.0"
,
"path-type"
:
"^4.0.0"
"d3-color"
:
"1 - 3"
,
"d3-interpolate"
:
"1 - 3"
},
"engines"
:
{
"node"
:
">=14"
},
"funding"
:
{
"url"
:
"https://github.com/sponsors/d-fischer"
},
"peerDependencies"
:
{
"typescript"
:
">=4.9.5"
},
"peerDependenciesMeta"
:
{
"typescript"
:
{
"optional"
:
true
}
"node"
:
">=12"
}
},
"node_modules/crc-32"
:
{
"version"
:
"1.2.2"
,
"resolved"
:
"https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz"
,
"integrity"
:
"sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ=="
,
"license"
:
"Apache-2.0"
,
"bin"
:
{
"crc32"
:
"bin/crc32.njs"
},
"node_modules/d3-selection"
:
{
"version"
:
"3.0.0"
,
"resolved"
:
"https://registry.npmmirror.com/d3-selection/-/d3-selection-3.0.0.tgz"
,
"integrity"
:
"sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ=="
,
"license"
:
"ISC"
,
"engines"
:
{
"node"
:
">=
0.8
"
"node"
:
">=
12
"
}
},
"node_modules/
cross-spawn
"
:
{
"version"
:
"
7.0.6
"
,
"resolved"
:
"https://registry.npmmirror.com/
cross-spawn/-/cross-spawn-7.0.6
.tgz"
,
"integrity"
:
"sha512-
uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3v
A=="
,
"license"
:
"
MIT
"
,
"node_modules/
d3-shape
"
:
{
"version"
:
"
3.2.0
"
,
"resolved"
:
"https://registry.npmmirror.com/
d3-shape/-/d3-shape-3.2.0
.tgz"
,
"integrity"
:
"sha512-
SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGT
A=="
,
"license"
:
"
ISC
"
,
"dependencies"
:
{
"path-key"
:
"^3.1.0"
,
"shebang-command"
:
"^2.0.0"
,
"which"
:
"^2.0.1"
"d3-path"
:
"^3.1.0"
},
"engines"
:
{
"node"
:
">=
8
"
"node"
:
">=
12
"
}
},
"node_modules/css-select"
:
{
"version"
:
"5.2.2"
,
"resolved"
:
"https://registry.npmmirror.com/css-select/-/css-select-5.2.2.tgz"
,
"integrity"
:
"sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw=="
,
"dev"
:
true
,
"license"
:
"BSD-2-Clause"
,
"node_modules/d3-time"
:
{
"version"
:
"3.1.0"
,
"resolved"
:
"https://registry.npmmirror.com/d3-time/-/d3-time-3.1.0.tgz"
,
"integrity"
:
"sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q=="
,
"license"
:
"ISC"
,
"dependencies"
:
{
"boolbase"
:
"^1.0.0"
,
"css-what"
:
"^6.1.0"
,
"domhandler"
:
"^5.0.2"
,
"domutils"
:
"^3.0.1"
,
"nth-check"
:
"^2.0.1"
"d3-array"
:
"2 - 3"
},
"
funding
"
:
{
"
url"
:
"https://github.com/sponsors/fb55
"
"
engines
"
:
{
"
node"
:
">=12
"
}
},
"node_modules/css-tree"
:
{
"version"
:
"2.3.1"
,
"resolved"
:
"https://registry.npmmirror.com/css-tree/-/css-tree-2.3.1.tgz"
,
"integrity"
:
"sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"node_modules/d3-time-format"
:
{
"version"
:
"4.1.0"
,
"resolved"
:
"https://registry.npmmirror.com/d3-time-format/-/d3-time-format-4.1.0.tgz"
,
"integrity"
:
"sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg=="
,
"license"
:
"ISC"
,
"dependencies"
:
{
"mdn-data"
:
"2.0.30"
,
"source-map-js"
:
"^1.0.1"
"d3-time"
:
"1 - 3"
},
"engines"
:
{
"node"
:
"
^10 || ^12.20.0 || ^14.13.0 || >=15.0.0
"
"node"
:
"
>=12
"
}
},
"node_modules/css-what"
:
{
"version"
:
"6.2.2"
,
"resolved"
:
"https://registry.npmmirror.com/css-what/-/css-what-6.2.2.tgz"
,
"integrity"
:
"sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA=="
,
"dev"
:
true
,
"license"
:
"BSD-2-Clause"
,
"node_modules/d3-timer"
:
{
"version"
:
"3.0.1"
,
"resolved"
:
"https://registry.npmmirror.com/d3-timer/-/d3-timer-3.0.1.tgz"
,
"integrity"
:
"sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA=="
,
"license"
:
"ISC"
,
"engines"
:
{
"node"
:
">= 6"
},
"funding"
:
{
"url"
:
"https://github.com/sponsors/fb55"
"node"
:
">=12"
}
},
"node_modules/cssesc"
:
{
"version"
:
"3.0.0"
,
"resolved"
:
"https://registry.npmmirror.com/cssesc/-/cssesc-3.0.0.tgz"
,
"integrity"
:
"sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="
,
"license"
:
"MIT"
,
"bin"
:
{
"cssesc"
:
"bin/cssesc"
"node_modules/d3-transition"
:
{
"version"
:
"3.0.1"
,
"resolved"
:
"https://registry.npmmirror.com/d3-transition/-/d3-transition-3.0.1.tgz"
,
"integrity"
:
"sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w=="
,
"license"
:
"ISC"
,
"dependencies"
:
{
"d3-color"
:
"1 - 3"
,
"d3-dispatch"
:
"1 - 3"
,
"d3-ease"
:
"1 - 3"
,
"d3-interpolate"
:
"1 - 3"
,
"d3-timer"
:
"1 - 3"
},
"engines"
:
{
"node"
:
">=4"
"node"
:
">=12"
},
"peerDependencies"
:
{
"d3-selection"
:
"2 - 3"
}
},
"node_modules/csso"
:
{
"version"
:
"5.0.5"
,
"resolved"
:
"https://registry.npmmirror.com/csso/-/csso-5.0.5.tgz"
,
"integrity"
:
"sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"node_modules/d3-zoom"
:
{
"version"
:
"3.0.0"
,
"resolved"
:
"https://registry.npmmirror.com/d3-zoom/-/d3-zoom-3.0.0.tgz"
,
"integrity"
:
"sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw=="
,
"license"
:
"ISC"
,
"dependencies"
:
{
"css-tree"
:
"~2.2.0"
"d3-dispatch"
:
"1 - 3"
,
"d3-drag"
:
"2 - 3"
,
"d3-interpolate"
:
"1 - 3"
,
"d3-selection"
:
"2 - 3"
,
"d3-transition"
:
"2 - 3"
},
"engines"
:
{
"node"
:
"^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
,
"npm"
:
">=7.0.0"
"node"
:
">=12"
}
},
"node_modules/csso/node_modules/css-tree"
:
{
"version"
:
"2.2.1"
,
"resolved"
:
"https://registry.npmmirror.com/css-tree/-/css-tree-2.2.1.tgz"
,
"integrity"
:
"sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA=="
,
"dev"
:
true
,
"node_modules/dagre-d3-es"
:
{
"version"
:
"7.0.14"
,
"resolved"
:
"https://registry.npmmirror.com/dagre-d3-es/-/dagre-d3-es-7.0.14.tgz"
,
"integrity"
:
"sha512-P4rFMVq9ESWqmOgK+dlXvOtLwYg0i7u0HBGJER0LZDJT2VHIPAMZ/riPxqJceWMStH5+E61QxFra9kIS3AqdMg=="
,
"license"
:
"MIT"
,
"dependencies"
:
{
"mdn-data"
:
"2.0.28"
,
"source-map-js"
:
"^1.0.1"
},
"engines"
:
{
"node"
:
"^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
,
"npm"
:
">=7.0.0"
"d3"
:
"^7.9.0"
,
"lodash-es"
:
"^4.17.21"
}
},
"node_modules/csso/node_modules/mdn-data"
:
{
"version"
:
"2.0.28"
,
"resolved"
:
"https://registry.npmmirror.com/mdn-data/-/mdn-data-2.0.28.tgz"
,
"integrity"
:
"sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g=="
,
"dev"
:
true
,
"license"
:
"CC0-1.0"
},
"node_modules/csstype"
:
{
"version"
:
"3.1.3"
,
"resolved"
:
"https://registry.npmmirror.com/csstype/-/csstype-3.1.3.tgz"
,
"integrity"
:
"sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
,
"license"
:
"MIT"
},
"node_modules/date-fns"
:
{
"version"
:
"3.6.0"
,
"resolved"
:
"https://registry.npmmirror.com/date-fns/-/date-fns-3.6.0.tgz"
,
...
...
@@ -8848,6 +9720,15 @@
"license"
:
"MIT"
,
"peer"
:
true
},
"node_modules/delaunator"
:
{
"version"
:
"5.1.0"
,
"resolved"
:
"https://registry.npmmirror.com/delaunator/-/delaunator-5.1.0.tgz"
,
"integrity"
:
"sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ=="
,
"license"
:
"ISC"
,
"dependencies"
:
{
"robust-predicates"
:
"^3.0.2"
}
},
"node_modules/delayed-stream"
:
{
"version"
:
"1.0.0"
,
"resolved"
:
"https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz"
,
...
...
@@ -8977,6 +9858,15 @@
"url"
:
"https://github.com/fb55/domhandler?sponsor=1"
}
},
"node_modules/dompurify"
:
{
"version"
:
"3.4.5"
,
"resolved"
:
"https://registry.npmmirror.com/dompurify/-/dompurify-3.4.5.tgz"
,
"integrity"
:
"sha512-OrwIBKsdNSVEeubdJ1HBv/wNENRM9ytAVCv7YXt//A3vPdVMNuACRqK9mXCGCBW2ln7BT/A4X0jXHo2Gu89miA=="
,
"license"
:
"(MPL-2.0 OR Apache-2.0)"
,
"optionalDependencies"
:
{
"@types/trusted-types"
:
"^2.0.7"
}
},
"node_modules/domutils"
:
{
"version"
:
"3.2.2"
,
"resolved"
:
"https://registry.npmmirror.com/domutils/-/domutils-3.2.2.tgz"
,
...
...
@@ -9246,6 +10136,16 @@
"node"
:
">= 0.4"
}
},
"node_modules/es-toolkit"
:
{
"version"
:
"1.46.1"
,
"resolved"
:
"https://registry.npmmirror.com/es-toolkit/-/es-toolkit-1.46.1.tgz"
,
"integrity"
:
"sha512-5eNtXOs3tbfxXOj04tjjseeWkRWaoCjdEI+96DgwzZoe6c9juL49pXlzAFTI72aWC9Y8p7168g6XIKjh7k6pyQ=="
,
"license"
:
"MIT"
,
"workspaces"
:
[
"docs"
,
"benchmarks"
]
},
"node_modules/escalade"
:
{
"version"
:
"3.2.0"
,
"resolved"
:
"https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz"
,
...
...
@@ -11013,6 +11913,12 @@
"url"
:
"https://github.com/sponsors/sindresorhus"
}
},
"node_modules/hachure-fill"
:
{
"version"
:
"0.5.2"
,
"resolved"
:
"https://registry.npmmirror.com/hachure-fill/-/hachure-fill-0.5.2.tgz"
,
"integrity"
:
"sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg=="
,
"license"
:
"MIT"
},
"node_modules/has-flag"
:
{
"version"
:
"4.0.0"
,
"resolved"
:
"https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz"
,
...
...
@@ -11380,6 +12286,16 @@
"url"
:
"https://github.com/sponsors/sindresorhus"
}
},
"node_modules/import-meta-resolve"
:
{
"version"
:
"4.2.0"
,
"resolved"
:
"https://registry.npmmirror.com/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz"
,
"integrity"
:
"sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg=="
,
"license"
:
"MIT"
,
"funding"
:
{
"type"
:
"github"
,
"url"
:
"https://github.com/sponsors/wooorm"
}
},
"node_modules/imurmurhash"
:
{
"version"
:
"0.1.4"
,
"resolved"
:
"https://registry.npmmirror.com/imurmurhash/-/imurmurhash-0.1.4.tgz"
,
...
...
@@ -11432,6 +12348,15 @@
"react-dom"
:
"^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc"
}
},
"node_modules/internmap"
:
{
"version"
:
"2.0.3"
,
"resolved"
:
"https://registry.npmmirror.com/internmap/-/internmap-2.0.3.tgz"
,
"integrity"
:
"sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg=="
,
"license"
:
"ISC"
,
"engines"
:
{
"node"
:
">=12"
}
},
"node_modules/intersection-observer"
:
{
"version"
:
"0.12.2"
,
"resolved"
:
"https://registry.npmmirror.com/intersection-observer/-/intersection-observer-0.12.2.tgz"
,
...
...
@@ -11913,6 +12838,31 @@
"setimmediate"
:
"^1.0.5"
}
},
"node_modules/katex"
:
{
"version"
:
"0.16.47"
,
"resolved"
:
"https://registry.npmmirror.com/katex/-/katex-0.16.47.tgz"
,
"integrity"
:
"sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg=="
,
"funding"
:
[
"https://opencollective.com/katex"
,
"https://github.com/sponsors/katex"
],
"license"
:
"MIT"
,
"dependencies"
:
{
"commander"
:
"^8.3.0"
},
"bin"
:
{
"katex"
:
"cli.js"
}
},
"node_modules/katex/node_modules/commander"
:
{
"version"
:
"8.3.0"
,
"resolved"
:
"https://registry.npmmirror.com/commander/-/commander-8.3.0.tgz"
,
"integrity"
:
"sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="
,
"license"
:
"MIT"
,
"engines"
:
{
"node"
:
">= 12"
}
},
"node_modules/keyv"
:
{
"version"
:
"4.5.4"
,
"resolved"
:
"https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz"
,
...
...
@@ -11922,6 +12872,17 @@
"json-buffer"
:
"3.0.1"
}
},
"node_modules/khroma"
:
{
"version"
:
"2.1.0"
,
"resolved"
:
"https://registry.npmmirror.com/khroma/-/khroma-2.1.0.tgz"
,
"integrity"
:
"sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw=="
},
"node_modules/layout-base"
:
{
"version"
:
"1.0.2"
,
"resolved"
:
"https://registry.npmmirror.com/layout-base/-/layout-base-1.0.2.tgz"
,
"integrity"
:
"sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg=="
,
"license"
:
"MIT"
},
"node_modules/levn"
:
{
"version"
:
"0.4.1"
,
"resolved"
:
"https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz"
,
...
...
@@ -12088,6 +13049,12 @@
"integrity"
:
"sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
,
"license"
:
"MIT"
},
"node_modules/lodash-es"
:
{
"version"
:
"4.18.1"
,
"resolved"
:
"https://registry.npmmirror.com/lodash-es/-/lodash-es-4.18.1.tgz"
,
"integrity"
:
"sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A=="
,
"license"
:
"MIT"
},
"node_modules/lodash.merge"
:
{
"version"
:
"4.6.2"
,
"resolved"
:
"https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz"
,
...
...
@@ -12269,6 +13236,18 @@
"url"
:
"https://github.com/sponsors/wooorm"
}
},
"node_modules/marked"
:
{
"version"
:
"16.4.2"
,
"resolved"
:
"https://registry.npmmirror.com/marked/-/marked-16.4.2.tgz"
,
"integrity"
:
"sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA=="
,
"license"
:
"MIT"
,
"bin"
:
{
"marked"
:
"bin/marked.js"
},
"engines"
:
{
"node"
:
">= 20"
}
},
"node_modules/math-intrinsics"
:
{
"version"
:
"1.1.0"
,
"resolved"
:
"https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz"
,
...
...
@@ -13555,6 +14534,41 @@
"node"
:
">= 8"
}
},
"node_modules/mermaid"
:
{
"version"
:
"11.15.0"
,
"resolved"
:
"https://registry.npmmirror.com/mermaid/-/mermaid-11.15.0.tgz"
,
"integrity"
:
"sha512-pTMbcf3rWdtLiYGpmoTjHEpeY8seiy6sR+9nD7LOs8KfUbHE4lOUAprTRqRAcWSQ6MQpdX+YEsxShtGsINtPtw=="
,
"license"
:
"MIT"
,
"dependencies"
:
{
"@braintree/sanitize-url"
:
"^7.1.1"
,
"@iconify/utils"
:
"^3.0.2"
,
"@mermaid-js/parser"
:
"^1.1.1"
,
"@types/d3"
:
"^7.4.3"
,
"@upsetjs/venn.js"
:
"^2.0.0"
,
"cytoscape"
:
"^3.33.1"
,
"cytoscape-cose-bilkent"
:
"^4.1.0"
,
"cytoscape-fcose"
:
"^2.2.0"
,
"d3"
:
"^7.9.0"
,
"d3-sankey"
:
"^0.12.3"
,
"dagre-d3-es"
:
"7.0.14"
,
"dayjs"
:
"^1.11.19"
,
"dompurify"
:
"^3.3.1"
,
"es-toolkit"
:
"^1.45.1"
,
"katex"
:
"^0.16.25"
,
"khroma"
:
"^2.1.0"
,
"marked"
:
"^16.3.0"
,
"roughjs"
:
"^4.6.6"
,
"stylis"
:
"^4.3.6"
,
"ts-dedent"
:
"^2.2.0"
,
"uuid"
:
"^11.1.0 || ^12 || ^13 || ^14.0.0"
}
},
"node_modules/mermaid/node_modules/dayjs"
:
{
"version"
:
"1.11.20"
,
"resolved"
:
"https://registry.npmmirror.com/dayjs/-/dayjs-1.11.20.tgz"
,
"integrity"
:
"sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ=="
,
"license"
:
"MIT"
},
"node_modules/micromark"
:
{
"version"
:
"2.11.4"
,
"resolved"
:
"https://registry.npmmirror.com/micromark/-/micromark-2.11.4.tgz"
,
...
...
@@ -14742,6 +15756,12 @@
"dev"
:
true
,
"license"
:
"MIT"
},
"node_modules/path-data-parser"
:
{
"version"
:
"0.1.0"
,
"resolved"
:
"https://registry.npmmirror.com/path-data-parser/-/path-data-parser-0.1.0.tgz"
,
"integrity"
:
"sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w=="
,
"license"
:
"MIT"
},
"node_modules/path-exists"
:
{
"version"
:
"4.0.0"
,
"resolved"
:
"https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz"
,
...
...
@@ -14905,6 +15925,22 @@
"node"
:
">=4"
}
},
"node_modules/points-on-curve"
:
{
"version"
:
"0.2.0"
,
"resolved"
:
"https://registry.npmmirror.com/points-on-curve/-/points-on-curve-0.2.0.tgz"
,
"integrity"
:
"sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A=="
,
"license"
:
"MIT"
},
"node_modules/points-on-path"
:
{
"version"
:
"0.2.1"
,
"resolved"
:
"https://registry.npmmirror.com/points-on-path/-/points-on-path-0.2.1.tgz"
,
"integrity"
:
"sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g=="
,
"license"
:
"MIT"
,
"dependencies"
:
{
"path-data-parser"
:
"0.1.0"
,
"points-on-curve"
:
"0.2.0"
}
},
"node_modules/popper.js"
:
{
"version"
:
"1.16.1"
,
"resolved"
:
"https://registry.npmmirror.com/popper.js/-/popper.js-1.16.1.tgz"
,
...
...
@@ -16148,6 +17184,24 @@
"url"
:
"https://github.com/sponsors/isaacs"
}
},
"node_modules/robust-predicates"
:
{
"version"
:
"3.0.3"
,
"resolved"
:
"https://registry.npmmirror.com/robust-predicates/-/robust-predicates-3.0.3.tgz"
,
"integrity"
:
"sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA=="
,
"license"
:
"Unlicense"
},
"node_modules/roughjs"
:
{
"version"
:
"4.6.6"
,
"resolved"
:
"https://registry.npmmirror.com/roughjs/-/roughjs-4.6.6.tgz"
,
"integrity"
:
"sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ=="
,
"license"
:
"MIT"
,
"dependencies"
:
{
"hachure-fill"
:
"^0.5.2"
,
"path-data-parser"
:
"^0.1.0"
,
"points-on-curve"
:
"^0.2.0"
,
"points-on-path"
:
"^0.2.1"
}
},
"node_modules/rslog"
:
{
"version"
:
"1.2.11"
,
"resolved"
:
"https://registry.npmmirror.com/rslog/-/rslog-1.2.11.tgz"
,
...
...
@@ -16178,6 +17232,12 @@
"queue-microtask"
:
"^1.2.2"
}
},
"node_modules/rw"
:
{
"version"
:
"1.3.3"
,
"resolved"
:
"https://registry.npmmirror.com/rw/-/rw-1.3.3.tgz"
,
"integrity"
:
"sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ=="
,
"license"
:
"BSD-3-Clause"
},
"node_modules/safe-buffer"
:
{
"version"
:
"5.2.1"
,
"resolved"
:
"https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz"
,
...
...
@@ -16203,7 +17263,6 @@
"version"
:
"2.1.2"
,
"resolved"
:
"https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz"
,
"integrity"
:
"sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
,
"dev"
:
true
,
"license"
:
"MIT"
},
"node_modules/scheduler"
:
{
...
...
@@ -17069,6 +18128,12 @@
"inline-style-parser"
:
"0.2.4"
}
},
"node_modules/stylis"
:
{
"version"
:
"4.4.0"
,
"resolved"
:
"https://registry.npmmirror.com/stylis/-/stylis-4.4.0.tgz"
,
"integrity"
:
"sha512-5Z9ZpRzfuH6l/UAvCPAPUo3665Nk2wLaZU3x+TLHKVzIz33+sbJqbtrYoC3KD4/uVOr2Zp+L0LySezP9OHV9yA=="
,
"license"
:
"MIT"
},
"node_modules/sucrase"
:
{
"version"
:
"3.35.0"
,
"resolved"
:
"https://registry.npmmirror.com/sucrase/-/sucrase-3.35.0.tgz"
,
...
...
@@ -17577,6 +18642,15 @@
"typescript"
:
">=4.0.0"
}
},
"node_modules/ts-dedent"
:
{
"version"
:
"2.2.0"
,
"resolved"
:
"https://registry.npmmirror.com/ts-dedent/-/ts-dedent-2.2.0.tgz"
,
"integrity"
:
"sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ=="
,
"license"
:
"MIT"
,
"engines"
:
{
"node"
:
">=6.10"
}
},
"node_modules/ts-interface-checker"
:
{
"version"
:
"0.1.13"
,
"resolved"
:
"https://registry.npmmirror.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz"
,
...
...
@@ -17980,6 +19054,19 @@
"node"
:
">= 0.4.0"
}
},
"node_modules/uuid"
:
{
"version"
:
"14.0.0"
,
"resolved"
:
"https://registry.npmmirror.com/uuid/-/uuid-14.0.0.tgz"
,
"integrity"
:
"sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg=="
,
"funding"
:
[
"https://github.com/sponsors/broofa"
,
"https://github.com/sponsors/ctavan"
],
"license"
:
"MIT"
,
"bin"
:
{
"uuid"
:
"dist-node/bin/uuid"
}
},
"node_modules/validate-npm-package-license"
:
{
"version"
:
"3.0.4"
,
"resolved"
:
"https://registry.npmmirror.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz"
,
...
...
src/pages/Chat/Chat.tsx
View file @
6992b396
...
...
@@ -4,7 +4,7 @@ import { Button } from '@heroui/react'
import
{
motion
}
from
'framer-motion'
import
{
useScroll
}
from
'ahooks'
import
styles
from
'./Chat.module.less'
import
{
type
Workflow
ParseOptions
,
getLastQaRecordWorkflowContext
,
hasQaWorkflowContext
,
hasWorkflowFormCards
,
isHiddenWorkflowRedirectControl
,
isHiddenWorkflowRedirectPayload
,
isWorkflowControlEnd
,
isWorkflowPacketEnd
,
markWorkflowFormSubmittedOnRecord
,
processApiResponse
,
resolveDisplayAnswerText
,
resolveWorkFlowSessionId
,
tryParseWorkflowControlJson
}
from
'./helper'
import
{
type
Workflow
ControlPayload
,
type
WorkflowParseOptions
,
enrichWorkflowControlWithPacketQuestion
,
getLastQaRecordWorkflowContext
,
hasQaWorkflowContext
,
hasWorkflowFormCards
,
isHiddenWorkflowRedirectControl
,
isHiddenWorkflowRedirectPayload
,
isWorkflowControlEnd
,
isWorkflowControlPayloadComplete
,
isWorkflowEnterSubPayload
,
isWorkflowPacketEnd
,
markWorkflowFormSubmittedOnRecord
,
normalizeStreamAnswerChunk
,
parseWorkflowControlForStream
,
processApiResponse
,
resolveDisplayAnswerText
,
resolveWorkFlowSessionId
}
from
'./helper'
import
type
{
WorkflowParamMap
}
from
'./lib/workflowCardForm'
import
{
ChatWelcome
}
from
'./components/ChatWelcome'
import
{
ChatItemUser
}
from
'./components/ChatItem/ChatItemUser'
...
...
@@ -28,10 +28,20 @@ type WorkflowStreamAnswer = Answer & {
workflowParseText
?:
string
workflowAnswerChunk
?:
string
workflowPacketEnd
?:
boolean
/** 任一分片解析到的工作流控制 JSON,流结束后用于自动续问 */
workflowDetectedControl
?:
WorkflowControlPayload
}
const
PENDING_WORKFLOW_SILENT_BOOTSTRAP_KEY
=
'pendingWorkflowSilentBootstrap'
function
findLastAiIndex
(
items
:
ChatRecord
[]):
number
{
for
(
let
i
=
items
.
length
-
1
;
i
>=
0
;
i
--
)
{
if
(
items
[
i
].
role
===
'ai'
)
return
i
}
return
-
1
}
function
makeLocalGroupId
(
prefix
:
string
)
{
try
{
// modern browsers
...
...
@@ -126,6 +136,8 @@ export const Chat: React.FC = () => {
...(
snapshot
.
workflowPacketEnd
?
{
packetEnd
:
true
}
:
{}),
}
},
[])
/** 当前流式请求对应的 AI 气泡 groupId,避免写入错误的历史 AI 记录 */
const
activeStreamingAiGroupIdRef
=
useRef
<
string
|
null
>
(
null
)
/** 工作流静默续跑(空问题开子/子流/表单提交):提交前已追加独立 AI 占位,流式勿再覆盖上一条 */
const
workflowSilentAppendAiRef
=
useRef
(
false
)
/** 本次 paramMap 表单提交对应的 AI 记录标识(recordId 或 groupId),流结束后标记 workflowFormSubmitted */
...
...
@@ -285,19 +297,21 @@ export const Chat: React.FC = () => {
lastAnswer
:
WorkflowStreamAnswer
,
)
=>
{
const
streamSnapshot
=
lastStreamedAiAnswerRef
.
current
const
parseText
=
streamSnapshot
?.
workflowParseText
??
lastAnswer
.
workflowParseText
??
lastAnswer
.
answer
??
''
const
parseOptions
=
buildWorkflowParseOptions
(
streamSnapshot
??
lastAnswer
)
const
parsedAnswer
=
tryParseWorkflowControlJson
(
parseText
,
parseOptions
)
const
packetQuestion
=
(
lastAnswer
as
WorkflowStreamAnswer
&
{
question
?:
string
}).
question
const
wfParseText
=
trimSpacesOnly
(
lastAnswer
.
workflowParseText
??
streamSnapshot
?.
workflowParseText
??
lastAnswer
.
answer
??
''
,
)
let
parsedAnswer
=
parseWorkflowControlForStream
(
wfParseText
,
parseOptions
,
packetQuestion
)
if
(
!
parsedAnswer
)
{
const
detected
=
lastAnswer
.
workflowDetectedControl
??
streamSnapshot
?.
workflowDetectedControl
const
enriched
=
enrichWorkflowControlWithPacketQuestion
(
detected
,
packetQuestion
,
wfParseText
)
if
(
enriched
&&
isWorkflowControlPayloadComplete
(
enriched
))
parsedAnswer
=
enriched
}
const
lastAnswerSessionId
=
resolveWorkFlowSessionId
(
lastAnswer
)
const
hasHiddenRedirect
=
isHiddenWorkflowRedirectPayload
(
parsedAnswer
)
const
hasEnterSubSignal
=
Boolean
(
parsedAnswer
?.
recordType
!=
null
&&
String
(
parsedAnswer
.
recordType
).
trim
()
&&
parsedAnswer
.
question
!=
null
,
)
const
hasEnterSubSignal
=
isWorkflowEnterSubPayload
(
parsedAnswer
)
const
wf
=
businessInsightWorkflowRef
.
current
const
shouldHandleWorkflowAnswer
=
Boolean
(
lastAnswerSessionId
)
...
...
@@ -395,7 +409,7 @@ export const Chat: React.FC = () => {
return
}
if
(
parsedAnswer
?.
recordType
!=
null
&&
parsedAnswer
.
question
!=
null
)
{
if
(
hasEnterSubSignal
&&
parsedAnswer
)
{
const
subRecordType
=
String
(
parsedAnswer
.
recordType
).
trim
()
const
controlQ
=
parsedAnswer
.
question
!=
null
?
String
(
parsedAnswer
.
question
).
trim
()
:
''
const
mainUserQ
=
lastMainUserQuestionRef
.
current
?.
trim
()
||
''
...
...
@@ -416,6 +430,7 @@ export const Chat: React.FC = () => {
pendingSubQuestionRef
.
current
=
pendingQ
||
null
pendingSubOpenRecordTypeRef
.
current
=
subRecordType
expectingSubWorkflowOpenRef
.
current
=
true
console
.
log
(
'[Chat WF] 自动开子工作流'
,
{
recordType
:
subRecordType
,
pendingQ
,
mainSessionId
})
queueMicrotask
(()
=>
{
void
handleSubmitQuestionRef
.
current
?.(
''
,
undefined
,
resolveWorkflowToolId
()
||
undefined
,
{
recordType
:
subRecordType
,
...
...
@@ -476,9 +491,68 @@ export const Chat: React.FC = () => {
/** 处理正常stream的数据 */
const
handleStreamMesageData
=
(
msg
:
any
,
question
:
string
)
=>
{
const
packetData
=
msg
.
content
?.
data
||
{}
const
answerChunk
=
normalizeStreamAnswerChunk
(
packetData
.
answer
)
const
prevRef
=
lastStreamedAiAnswerRef
.
current
const
previousRaw
=
prevRef
?.
workflowParseText
??
''
const
originalAnswer
=
previousRaw
+
answerChunk
let
filteredAnswer
=
originalAnswer
.
replace
(
/
\([^
)
]
*
\)
/g
,
(
match
,
offset
,
str
)
=>
{
return
str
[
offset
-
1
]
===
']'
?
match
:
''
})
filteredAnswer
=
filteredAnswer
.
replace
(
/
\[
参考文档
(?:
《
[^
》
]
*》
\s
*
)
+
\]
/g
,
''
)
filteredAnswer
=
trimSpacesOnly
(
filteredAnswer
)
const
packetEnd
=
isWorkflowPacketEnd
(
packetData
)
const
streamParseOptions
:
WorkflowParseOptions
|
undefined
=
(
answerChunk
||
packetEnd
)
?
{
...(
answerChunk
?
{
answerChunk
}
:
{}),
...(
packetEnd
?
{
packetEnd
:
true
}
:
{}),
}
:
undefined
const
{
endAnswerFlag
:
_syncOmitEnd
,
...
dataWithoutEndFlag
}
=
packetData
const
wfParseText
=
trimSpacesOnly
(
originalAnswer
)
const
packetControl
=
parseWorkflowControlForStream
(
wfParseText
,
streamParseOptions
,
dataWithoutEndFlag
.
question
,
)
filteredAnswer
=
resolveDisplayAnswerText
(
filteredAnswer
,
streamParseOptions
,
dataWithoutEndFlag
.
question
)
const
syncSessionId
=
resolveWorkFlowSessionId
(
{
...
prevRef
,
...
dataWithoutEndFlag
},
prevRef
?.
workFlowSessionId
,
)
// 同步写入 ref:流 fetch resolve 时 React 可能尚未执行 setAllItems,避免读不到控制 JSON
if
(
answerChunk
||
packetEnd
||
packetControl
)
{
lastStreamedAiAnswerRef
.
current
=
{
...(
prevRef
||
{}),
...
dataWithoutEndFlag
,
workFlowSessionId
:
syncSessionId
,
recordId
:
dataWithoutEndFlag
.
recordId
??
prevRef
?.
recordId
,
cardList
:
Array
.
isArray
(
dataWithoutEndFlag
.
cardList
)
&&
dataWithoutEndFlag
.
cardList
.
length
>
0
?
dataWithoutEndFlag
.
cardList
:
prevRef
?.
cardList
,
answer
:
filteredAnswer
,
workflowParseText
:
wfParseText
,
workflowAnswerChunk
:
answerChunk
,
workflowPacketEnd
:
packetEnd
||
prevRef
?.
workflowPacketEnd
,
...(
packetControl
?
{
workflowDetectedControl
:
packetControl
}
:
{}),
}
if
(
packetControl
)
{
console
.
log
(
'[Chat WF] 分片识别到控制 JSON'
,
{
recordType
:
packetControl
.
recordType
,
question
:
packetControl
.
question
,
packetQuestion
:
dataWithoutEndFlag
.
question
,
parseTextTail
:
trimSpacesOnly
(
originalAnswer
).
slice
(
-
120
),
complete
:
isWorkflowControlPayloadComplete
(
packetControl
),
displayAnswer
:
filteredAnswer
,
packetEnd
,
})
}
}
setAllItems
((
prevItems
)
=>
{
const
newItems
=
[...
prevItems
]
// 创建数组的浅拷贝
const
lastIndex
=
newItems
.
length
-
1
const
isEmptyQuestion
=
!
question
.
trim
()
// 提质增效自动欢迎语场景:空问题的流式回答应追加在历史记录之后,避免复用最后一条历史 AI 记录
const
shouldAlwaysAppendAi
=
isAutoSubmitQualityImprovementRef
.
current
&&
isEmptyQuestion
...
...
@@ -519,75 +593,62 @@ export const Chat: React.FC = () => {
}
}
let
lastAiIndex
=
findLastAiIndex
(
newItems
)
const
streamingGroupId
=
activeStreamingAiGroupIdRef
.
current
if
(
streamingGroupId
)
{
let
streamingIndex
=
newItems
.
findIndex
(
item
=>
item
.
role
===
'ai'
&&
item
.
groupId
===
streamingGroupId
,
)
if
(
streamingIndex
<
0
)
{
newItems
.
push
({
role
:
'ai'
,
groupId
:
streamingGroupId
,
answerList
:
[{
answer
:
''
,
isShow
:
false
}],
}
as
ChatRecord
)
streamingIndex
=
newItems
.
length
-
1
}
lastAiIndex
=
streamingIndex
}
// 如果是空问题且需要追加新的 AI 记录(历史末尾没有 AI,或提质增效自动欢迎语场景),则添加 AI 回答占位
if
(
isEmptyQuestion
&&
(
last
Index
<
0
||
newItems
[
lastIndex
].
role
!==
'ai'
||
shouldAlwaysAppendAi
))
{
if
(
isEmptyQuestion
&&
(
last
AiIndex
<
0
||
shouldAlwaysAppendAi
))
{
newItems
.
push
({
role
:
'ai'
,
groupId
:
makeLocalGroupId
(
'ai'
),
answerList
:
[{
answer
:
''
}],
}
as
ChatRecord
)
lastAiIndex
=
newItems
.
length
-
1
}
const
currentIndex
=
newItems
.
length
-
1
if
(
currentIndex
>=
0
&&
newItems
[
currentIndex
].
role
===
'ai'
)
{
if
(
lastAiIndex
>=
0
)
{
// 创建最后一项的新对象,合并现有数据和新的 answer
const
existingAnswer
=
newItems
[
currentIndex
].
answerList
?.[
0
]
||
{}
const
originalAnswer
=
(
existingAnswer
.
answer
||
''
)
+
(
msg
.
content
.
data
.
answer
??
'
\
n'
)
// 移除所有括号及其内容(但保留 Markdown 链接语法中的 ](...))
let
filteredAnswer
=
originalAnswer
.
replace
(
/
\([^
)
]
*
\)
/g
,
(
match
,
offset
,
str
)
=>
{
return
str
[
offset
-
1
]
===
']'
?
match
:
''
})
// 去除 [参考文档《任意内容》 《任意内容》...] 格式的内容
filteredAnswer
=
filteredAnswer
.
replace
(
/
\[
参考文档
(?:
《
[^
》
]
*》
\s
*
)
+
\]
/g
,
''
)
// 只移除空格和制表符,保留换行符(避免移除末尾的 \n\n)
filteredAnswer
=
trimSpacesOnly
(
filteredAnswer
)
const
packetData
=
msg
.
content
.
data
||
{}
const
answerChunk
=
typeof
packetData
.
answer
===
'string'
?
packetData
.
answer
:
''
const
packetEnd
=
isWorkflowPacketEnd
(
packetData
)
const
streamParseOptions
:
WorkflowParseOptions
|
undefined
=
(
answerChunk
||
packetEnd
)
?
{
...(
answerChunk
?
{
answerChunk
}
:
{}),
...(
packetEnd
?
{
packetEnd
:
true
}
:
{}),
}
:
undefined
filteredAnswer
=
resolveDisplayAnswerText
(
filteredAnswer
,
streamParseOptions
)
// 在流式响应过程中,忽略服务器返回的 endAnswerFlag,避免过早禁用输入框
const
{
endAnswerFlag
:
_omitEndAnswerFlag
,
...
dataWithoutEndFlag
}
=
packetData
const
existingAnswer
=
newItems
[
lastAiIndex
].
answerList
?.[
0
]
||
{}
const
mergedFromRef
=
lastStreamedAiAnswerRef
.
current
const
chunkToolId
=
dataWithoutEndFlag
.
toolId
!=
null
?
String
(
dataWithoutEndFlag
.
toolId
).
trim
()
:
''
const
chunkRecordType
=
dataWithoutEndFlag
.
recordType
!=
null
?
String
(
dataWithoutEndFlag
.
recordType
).
trim
()
:
''
if
(
chunkToolId
&&
chunkRecordType
)
setWorkflowLastToolPair
(
chunkToolId
,
chunkRecordType
)
const
resolvedSessionId
=
resolveWorkFlowSessionId
(
{
...
existingAnswer
,
...
dataWithoutEndFlag
},
existingAnswer
.
workFlowSessionId
,
)
// 保留之前保存的 workFlowSessionId 和 recordId,避免被覆盖
const
mergedAnswer
:
Answer
=
{
const
mergedAnswer
:
WorkflowStreamAnswer
=
{
...
existingAnswer
,
...
dataWithoutEndFlag
,
workFlowSessionId
:
resolvedSessionId
,
recordId
:
dataWithoutEndFlag
.
recordId
??
existingAnswer
.
recordId
,
cardList
:
Array
.
isArray
(
dataWithoutEndFlag
.
cardList
)
&&
dataWithoutEndFlag
.
cardList
.
length
>
0
?
dataWithoutEndFlag
.
cardList
:
existingAnswer
.
cardList
,
...(
mergedFromRef
||
dataWithoutEndFlag
),
workFlowSessionId
:
mergedFromRef
?.
workFlowSessionId
??
resolveWorkFlowSessionId
({
...
existingAnswer
,
...
dataWithoutEndFlag
},
existingAnswer
.
workFlowSessionId
),
recordId
:
mergedFromRef
?.
recordId
??
dataWithoutEndFlag
.
recordId
??
existingAnswer
.
recordId
,
cardList
:
mergedFromRef
?.
cardList
??
(
Array
.
isArray
(
dataWithoutEndFlag
.
cardList
)
&&
dataWithoutEndFlag
.
cardList
.
length
>
0
?
dataWithoutEndFlag
.
cardList
:
existingAnswer
.
cardList
),
isShow
:
false
,
answer
:
filteredAnswer
,
answer
:
mergedFromRef
?.
answer
??
filteredAnswer
,
workflowParseText
:
mergedFromRef
?.
workflowParseText
??
trimSpacesOnly
(
originalAnswer
),
workflowDetectedControl
:
packetControl
??
mergedFromRef
?.
workflowDetectedControl
,
}
newItems
[
current
Index
]
=
{
...
newItems
[
current
Index
],
newItems
[
lastAi
Index
]
=
{
...
newItems
[
lastAi
Index
],
question
:
isEmptyQuestion
?
undefined
:
question
,
answerList
:
[
mergedAnswer
],
}
lastStreamedAiAnswerRef
.
current
=
{
...
mergedAnswer
,
workflowParseText
:
trimSpacesOnly
(
originalAnswer
),
workflowAnswerChunk
:
answerChunk
,
workflowPacketEnd
:
packetEnd
||
lastStreamedAiAnswerRef
.
current
?.
workflowPacketEnd
,
}
}
return
newItems
})
...
...
@@ -729,17 +790,20 @@ export const Chat: React.FC = () => {
workflowSilentAppendAiRef
.
current
=
isWorkflowSilentSubmit
lastStreamedAiAnswerRef
.
current
=
null
activeStreamingAiGroupIdRef
.
current
=
null
const
isNew
=
allItems
.
length
<=
1
dispatch
(
setIsAsking
(
true
))
// 工作流静默续跑:单独追加 AI 占位,避免覆盖上一条(含 JSON 控制指令)的回答
if
(
isWorkflowSilentSubmit
)
{
const
silentAiGroupId
=
makeLocalGroupId
(
'ai'
)
activeStreamingAiGroupIdRef
.
current
=
silentAiGroupId
setAllItems
(
prevItems
=>
[
...
prevItems
,
{
role
:
'ai'
,
groupId
:
makeLocalGroupId
(
'ai'
)
,
groupId
:
silentAiGroupId
,
answerList
:
[{
answer
:
''
,
isShow
:
false
}],
}
as
ChatRecord
,
])
...
...
@@ -748,6 +812,8 @@ export const Chat: React.FC = () => {
// 如果 question 不为空,才添加用户问题和空的 AI 回答(静默提问不展示用户气泡)
if
(
!
isEmptyQuestion
)
{
const
questionText
=
question
.
trim
()
const
aiGroupId
=
makeLocalGroupId
(
'ai'
)
activeStreamingAiGroupIdRef
.
current
=
aiGroupId
setAllItems
(
prevItems
=>
[
...
prevItems
,
{
...
...
@@ -757,7 +823,7 @@ export const Chat: React.FC = () => {
}
as
ChatRecord
,
{
role
:
'ai'
,
groupId
:
makeLocalGroupId
(
'ai'
)
,
groupId
:
aiGroupId
,
question
:
questionText
,
answerList
:
[{
answer
:
''
,
isShow
:
false
}],
}
as
ChatRecord
,
...
...
@@ -902,7 +968,7 @@ export const Chat: React.FC = () => {
// 正常的stream数据
if
(
msg
?.
type
===
'DATA'
&&
msg
?.
content
?.
code
===
'00000000'
)
{
console
.
log
(
'========================流式输出===================='
,
msg
)
console
.
log
(
'========================流式输出
1111
===================='
,
msg
)
console
.
log
(
'========================流式输出字符串===================='
,
msg
.
content
?.
data
)
handleStreamMesageData
(
msg
,
question
)
}
...
...
@@ -933,29 +999,40 @@ export const Chat: React.FC = () => {
setAllItems
((
prevItems
)
=>
{
const
newItems
=
[...
prevItems
]
const
streamed
=
lastStreamedAiAnswerRef
.
current
for
(
let
i
=
newItems
.
length
-
1
;
i
>=
0
;
i
--
)
{
if
(
newItems
[
i
].
role
===
'ai'
&&
newItems
[
i
].
answerList
?.[
0
])
{
const
base
=
newItems
[
i
].
answerList
[
0
]
const
streamingGroupId
=
activeStreamingAiGroupIdRef
.
current
let
mergeAiIndex
=
-
1
if
(
streamingGroupId
)
{
mergeAiIndex
=
newItems
.
findIndex
(
item
=>
item
.
role
===
'ai'
&&
item
.
groupId
===
streamingGroupId
,
)
}
if
(
mergeAiIndex
<
0
)
mergeAiIndex
=
findLastAiIndex
(
newItems
)
if
(
mergeAiIndex
>=
0
&&
newItems
[
mergeAiIndex
].
role
===
'ai'
&&
newItems
[
mergeAiIndex
].
answerList
?.[
0
])
{
const
i
=
mergeAiIndex
const
base
=
newItems
[
i
].
answerList
!
[
0
]
const
mergedCardList
=
streamed
?.
cardList
??
base
.
cardList
const
hasCards
=
Array
.
isArray
(
mergedCardList
)
&&
mergedCardList
.
length
>
0
const
rawParseText
=
streamed
?.
workflowParseText
??
streamed
?.
answer
??
base
.
answer
??
''
const
streamParseOptions
=
buildWorkflowParseOptions
(
streamed
)
const
packetQuestion
=
(
streamed
as
WorkflowStreamAnswer
&
{
question
?:
string
})?.
question
const
isHiddenRedirect
=
isHiddenWorkflowRedirectControl
(
rawParseText
,
streamParseOptions
)
const
displayAnswer
=
resolveDisplayAnswerText
(
(
streamed
?.
answer
??
base
.
answer
)
===
''
?
''
:
(
streamed
?.
answer
??
base
.
answer
),
)
const
parsedCtrl
=
parseWorkflowControlForStream
(
rawParseText
,
streamParseOptions
,
packetQuestion
)
const
isEnterSub
=
isWorkflowEnterSubPayload
(
parsedCtrl
)
const
displayAnswer
=
resolveDisplayAnswerText
(
rawParseText
,
streamParseOptions
,
packetQuestion
)
const
merged
:
Answer
=
streamed
?
{
...
base
,
...
streamed
,
answer
:
isHiddenRedirect
?
''
:
(
displayAnswer
===
''
&&
!
hasCards
?
'暂无内容'
:
displayAnswer
),
:
(
displayAnswer
===
''
&&
!
hasCards
&&
!
isEnterSub
?
'暂无内容'
:
displayAnswer
),
workFlowSessionId
:
resolveWorkFlowSessionId
(
streamed
,
resolveWorkFlowSessionId
(
base
)),
recordId
:
streamed
.
recordId
??
base
.
recordId
,
recordType
:
streamed
.
recordType
??
base
.
recordType
,
cardList
:
mergedCardList
,
endAnswerFlag
:
true
,
workflowParseText
:
rawParseText
,
// 含工作流表单卡片时保持 Parser,便于流式过程中展示表单;其余 cardList 流结束后走 Shower
isShow
:
isHiddenRedirect
||
(
hasCards
&&
hasWorkflowFormCards
(
mergedCardList
))
?
false
...
...
@@ -971,6 +1048,7 @@ export const Chat: React.FC = () => {
workflowParseText
:
rawParseText
,
workflowAnswerChunk
:
streamed
?.
workflowAnswerChunk
,
workflowPacketEnd
:
streamed
?.
workflowPacketEnd
,
workflowDetectedControl
:
parsedCtrl
??
streamed
?.
workflowDetectedControl
,
}
if
(
isHiddenRedirect
&&
!
hasCards
)
{
newItems
.
splice
(
i
,
1
)
...
...
@@ -978,8 +1056,6 @@ export const Chat: React.FC = () => {
else
{
newItems
[
i
]
=
{
...
newItems
[
i
],
answerList
:
[
merged
]
}
}
break
}
}
if
(
!
workflowLastAnswer
&&
streamed
)
{
workflowLastAnswer
=
{
...
...
@@ -998,9 +1074,14 @@ export const Chat: React.FC = () => {
pendingWorkflowFormSourceKeyRef
.
current
=
null
dispatch
(
setIsAsking
(
false
))
workflowSilentAppendAiRef
.
current
=
false
const
wfParseText
=
streamSnapshotForWf
?.
workflowParseText
??
''
const
wfParseOpts
=
buildWorkflowParseOptions
(
streamSnapshotForWf
)
const
wfParsedCtrl
=
tryParseWorkflowControlJson
(
wfParseText
,
wfParseOpts
)
const
wfPacketQuestion
=
(
streamSnapshotForWf
as
WorkflowStreamAnswer
&
{
question
?:
string
})?.
question
const
wfRawParseText
=
trimSpacesOnly
(
streamSnapshotForWf
?.
workflowParseText
??
streamSnapshotForWf
?.
answer
??
''
,
)
const
wfParsedCtrl
=
parseWorkflowControlForStream
(
wfRawParseText
,
wfParseOpts
,
wfPacketQuestion
)
const
wfCtxRecordType
=
wfParsedCtrl
?.
recordType
!=
null
?
String
(
wfParsedCtrl
.
recordType
).
trim
()
:
(
streamSnapshotForWf
?.
recordType
!=
null
?
String
(
streamSnapshotForWf
.
recordType
).
trim
()
:
''
)
...
...
@@ -1012,15 +1093,34 @@ export const Chat: React.FC = () => {
busiType
:
streamSnapshotForWf
?.
busiType
!=
null
?
String
(
streamSnapshotForWf
.
busiType
).
trim
()
:
'01'
,
}
}
if
(
workflowLastAnswer
)
{
queueMicrotask
(()
=>
{
processBusinessInsightWorkflowAfterStream
(
workflowLastAnswer
!
)
lastStreamedAiAnswerRef
.
current
=
null
const
wfAnswerForFollowUp
:
WorkflowStreamAnswer
|
null
=
workflowLastAnswer
??
(
streamSnapshotForWf
?
{
...
streamSnapshotForWf
,
endAnswerFlag
:
true
,
workflowDetectedControl
:
wfParsedCtrl
??
streamSnapshotForWf
.
workflowDetectedControl
,
}
:
null
)
if
(
wfAnswerForFollowUp
)
{
console
.
log
(
'[Chat WF] 流结束准备续问'
,
{
parsed
:
wfParsedCtrl
,
complete
:
isWorkflowControlPayloadComplete
(
wfParsedCtrl
),
willEnterSub
:
isWorkflowEnterSubPayload
(
wfParsedCtrl
),
packetQuestion
:
wfPacketQuestion
,
wfRawParseText
:
wfRawParseText
.
slice
(
0
,
120
),
hasRef
:
Boolean
(
streamSnapshotForWf
),
displayAnswer
:
wfAnswerForFollowUp
.
answer
,
})
processBusinessInsightWorkflowAfterStream
(
wfAnswerForFollowUp
)
}
else
{
lastStreamedAiAnswerRef
.
current
=
null
console
.
warn
(
'[Chat WF] 流结束未续问:无 workflow 快照'
,
{
parsed
:
wfParsedCtrl
,
hasRef
:
Boolean
(
streamSnapshotForWf
),
})
}
lastStreamedAiAnswerRef
.
current
=
null
activeStreamingAiGroupIdRef
.
current
=
null
if
(
isNew
)
{
setTimeout
(()
=>
{
dispatch
(
fetchConversations
())
...
...
@@ -1058,6 +1158,7 @@ export const Chat: React.FC = () => {
workflowSilentAppendAiRef
.
current
=
false
pendingWorkflowFormSourceKeyRef
.
current
=
null
lastStreamedAiAnswerRef
.
current
=
null
activeStreamingAiGroupIdRef
.
current
=
null
})
}
...
...
@@ -1446,11 +1547,6 @@ export const Chat: React.FC = () => {
const
canSend
=
historyLoadedRef
.
current
.
conversationId
===
currentIdRef
.
current
||
allItems
.
length
<=
1
if
(
canSend
)
{
const
questionToSend
=
shouldSendQuestion
console
.
log
(
'[Chat] auto send triggered (shouldSendQuestion):'
,
{
conversationId
:
currentIdRef
.
current
,
question
:
questionToSend
,
currentToolId
,
})
lastSentQuestionRef
.
current
=
questionToSend
pendingQuestionRef
.
current
=
null
// 立即清除shouldSendQuestion,防止重复发送
...
...
src/pages/Chat/components/ChatItem/ChatAnswerParser.tsx
View file @
6992b396
...
...
@@ -43,7 +43,8 @@ function CheckIcon({ ...props }) {
}
export
const
ChatAnswerParser
:
React
.
FC
<
ChatAnswerParserProps
>
=
({
isLastAnswer
,
onTyping
,
onComplate
,
answer
,
isStopTyping
,
onSubmitQuestion
,
hideOperate
,
onWorkflowSubmit
,
isWorkflowSubmitting
,
isAsking
=
false
})
=>
{
const
displayAnswerText
=
resolveDisplayAnswerText
(
answer
.
answer
||
''
)
const
answerSourceText
=
(
answer
as
{
workflowParseText
?:
string
}).
workflowParseText
??
answer
.
answer
??
''
const
displayAnswerText
=
resolveDisplayAnswerText
(
answerSourceText
)
const
formatAnswer
=
formatMarkdown
(
displayAnswerText
)
const
hasCards
=
Array
.
isArray
(
answer
.
cardList
)
&&
answer
.
cardList
.
length
>
0
const
[
displayedText
,
setDisplayedText
]
=
useState
(
''
)
...
...
@@ -123,6 +124,14 @@ export const ChatAnswerParser: React.FC<ChatAnswerParserProps> = ({ isLastAnswer
}
useEffect
(()
=>
{
if
(
answer
.
endAnswerFlag
)
{
setDisplayedText
(
formatAnswer
)
setCurrentIndex
(
formatAnswer
.
length
)
setIsTyping
(
false
)
}
},
[
answer
.
endAnswerFlag
,
formatAnswer
])
useEffect
(()
=>
{
if
(
isStopTyping
)
{
return
}
...
...
src/pages/Chat/components/ChatItem/ChatAnswerShower.tsx
View file @
6992b396
...
...
@@ -20,7 +20,8 @@ interface ChatAnswerShowerProps {
export
const
ChatAnswerShower
:
React
.
FC
<
ChatAnswerShowerProps
>
=
({
answer
,
isLastAnswer
,
onSubmitQuestion
,
hideOperate
:
hideOperateProp
,
onWorkflowSubmit
,
isWorkflowSubmitting
,
isAsking
=
false
})
=>
{
const
hideOperateByCard
=
(
answer
.
cardList
||
[]).
some
(
attachment
=>
attachment
.
type
===
'box'
||
attachment
?.
type
?.
includes
(
'card-'
))
const
hideOperate
=
hideOperateByCard
||
hideOperateProp
const
displayAnswerText
=
resolveDisplayAnswerText
(
answer
.
answer
||
''
)
const
answerSourceText
=
(
answer
as
{
workflowParseText
?:
string
}).
workflowParseText
??
answer
.
answer
??
''
const
displayAnswerText
=
resolveDisplayAnswerText
(
answerSourceText
)
const
hasCards
=
Array
.
isArray
(
answer
.
cardList
)
&&
answer
.
cardList
.
length
>
0
// 历史首包静默记录隐藏卡片;流式/含工作流表单卡片需正常展示
const
shouldRenderCards
=
hasCards
&&
!
(
...
...
src/pages/Chat/helper.ts
View file @
6992b396
import
{
trimSpacesOnly
}
from
'./components/ChatItem/markdownFormatter'
import
{
isWorkflowFormAttachment
}
from
'./lib/workflowCardForm'
import
type
{
Answer
,
Attachment
,
ChatRecord
,
OriginalRecord
}
from
'@/types/chat'
...
...
@@ -150,21 +151,38 @@ function parseJsonLevel1(text: string): WorkflowControlPayload | null {
return
null
}
function
extractQuestionByRegex
(
text
:
string
):
string
|
undefined
{
const
quoted
=
text
.
match
(
/"question"
\s
*:
\s
*"
((?:\\
.|
[^
"
\\])
*
)
"/
)
if
(
quoted
?.[
1
])
{
const
value
=
unescapeJsonStringValue
(
quoted
[
1
]).
trim
()
if
(
value
)
return
value
}
// 兼容非法 JSON:question 未加引号,如 "question":客群洞察
const
unquoted
=
text
.
match
(
/"question"
\s
*:
\s
*
([^
,}
\]]
+
)
/
)
if
(
unquoted
?.[
1
])
{
const
value
=
unquoted
[
1
].
trim
().
replace
(
/^
[
"'
]
|
[
"'
]
$/g
,
''
)
if
(
value
)
return
value
}
return
undefined
}
/** L3:正则提取 recordType / question / end / showFlag */
function
extractByRegex
(
text
:
string
):
WorkflowControlPayload
|
null
{
const
recordTypeMatch
=
text
.
match
(
/"recordType"
\s
*:
\s
*"
((?:\\
.|
[^
"
\\])
*
)
"/
)
const
question
Match
=
text
.
match
(
/"question"
\s
*:
\s
*"
((?:\\
.|
[^
"
\\])
*
)
"/
)
const
question
FromRegex
=
extractQuestionByRegex
(
text
)
const
endMatch
=
text
.
match
(
/"end"
\s
*:
\s
*
(
true|false|"true"|"false"
)
/i
)
const
showFlagMatch
=
text
.
match
(
/"showFlag"
\s
*:
\s
*
(
false|true|"false"|"true"|0|1
)
/i
)
if
(
!
recordTypeMatch
&&
!
question
Match
&&
!
endMatch
)
if
(
!
recordTypeMatch
&&
!
question
FromRegex
&&
!
endMatch
)
return
null
const
payload
:
WorkflowControlPayload
=
{}
if
(
recordTypeMatch
?.[
1
])
payload
.
recordType
=
unescapeJsonStringValue
(
recordTypeMatch
[
1
]).
trim
()
if
(
question
Match
?.[
1
]
)
payload
.
question
=
unescapeJsonStringValue
(
questionMatch
[
1
])
if
(
question
FromRegex
)
payload
.
question
=
questionFromRegex
if
(
endMatch
?.[
1
])
payload
.
end
=
isWorkflowControlEnd
(
endMatch
[
1
].
replace
(
/"/g
,
''
))
if
(
showFlagMatch
?.[
1
])
{
...
...
@@ -174,6 +192,28 @@ function extractByRegex(text: string): WorkflowControlPayload | null {
return
payload
}
/** 合并多段解析结果,优先保留更完整的 recordType / question */
function
mergeWorkflowControlPayload
(
...
parts
:
Array
<
WorkflowControlPayload
|
null
|
undefined
>
):
WorkflowControlPayload
|
null
{
const
merged
:
WorkflowControlPayload
=
{}
for
(
const
part
of
parts
)
{
if
(
!
part
)
continue
if
(
part
.
recordType
!=
null
&&
String
(
part
.
recordType
).
trim
())
merged
.
recordType
=
String
(
part
.
recordType
).
trim
()
if
(
part
.
question
!=
null
&&
String
(
part
.
question
).
trim
())
merged
.
question
=
part
.
question
if
(
part
.
end
===
true
)
merged
.
end
=
true
if
(
part
.
showFlag
!==
undefined
&&
part
.
showFlag
!==
null
)
merged
.
showFlag
=
part
.
showFlag
}
if
(
!
merged
.
recordType
&&
merged
.
question
==
null
&&
merged
.
end
!==
true
&&
merged
.
showFlag
==
null
)
return
null
return
merged
}
function
mergePacketEnd
(
payload
:
WorkflowControlPayload
|
null
,
options
?:
WorkflowParseOptions
,
...
...
@@ -187,19 +227,22 @@ function mergePacketEnd(
function
parseWorkflowControlFromText
(
text
:
string
):
WorkflowControlPayload
|
null
{
const
candidates
=
collectParseCandidates
(
text
)
for
(
let
i
=
candidates
.
length
-
1
;
i
>=
0
;
i
--
)
{
const
candidate
=
candidates
[
i
]
const
level1
=
parseJsonLevel1
(
candidate
)
if
(
level1
)
return
level1
const
level2
=
parseJsonLevel1
(
normalizeEscaped
(
candidate
))
if
(
level2
)
return
level2
const
level3
=
extractByRegex
(
candidate
)
if
(
level3
)
return
level3
let
best
:
WorkflowControlPayload
|
null
=
null
for
(
const
candidate
of
candidates
)
{
const
merged
=
mergeWorkflowControlPayload
(
parseJsonLevel1
(
candidate
),
parseJsonLevel1
(
normalizeEscaped
(
candidate
)),
extractByRegex
(
candidate
),
)
if
(
!
merged
)
continue
if
(
isWorkflowEnterSubPayload
(
merged
)
||
isHiddenWorkflowRedirectPayload
(
merged
))
return
merged
best
=
mergeWorkflowControlPayload
(
best
,
merged
)
}
return
null
return
mergeWorkflowControlPayload
(
best
,
extractByRegex
(
text
))
}
/** 兼容 API 返回 workFlowSessionId / workflowSessionId 等字段名 */
...
...
@@ -254,29 +297,222 @@ export function tryParseWorkflowControlJson(text: string, options?: WorkflowPars
return
null
}
/** 是否包含工作流表单卡片(card-workflow + form_input,且含 text/select/file 字段) */
export
function
hasWorkflowFormCards
(
cardList
?:
Attachment
[]):
boolean
{
return
Array
.
isArray
(
cardList
)
&&
cardList
.
some
(
isWorkflowFormAttachment
)
/** 流式分片 answer 可能是 string / 双层 JSON 字符串 / 对象 */
export
function
normalizeStreamAnswerChunk
(
raw
:
unknown
):
string
{
if
(
raw
==
null
)
return
''
if
(
typeof
raw
===
'string'
)
return
raw
if
(
typeof
raw
===
'object'
)
{
try
{
return
JSON
.
stringify
(
raw
)
}
catch
{
return
''
}
}
return
String
(
raw
)
}
/** 是否为「进入子工作流」类控制 JSON(解析后含 recordType + question,且非 showFlag 隐藏路由) */
export
function
isEnterSubWorkflowControlAnswer
(
text
:
string
,
options
?:
WorkflowParseOptions
):
boolean
{
const
parsed
=
tryParseWorkflowControlJson
(
text
,
options
)
if
(
isHiddenWorkflowRedirectPayload
(
parsed
))
/** 是否为「进入子工作流」控制载荷(含 recordType + question,且非隐藏路由) */
export
function
isWorkflowEnterSubPayload
(
parsed
:
WorkflowControlPayload
|
null
|
undefined
):
boolean
{
if
(
!
parsed
||
isHiddenWorkflowRedirectPayload
(
parsed
))
return
false
return
Boolean
(
parsed
?
.
recordType
!=
null
parsed
.
recordType
!=
null
&&
String
(
parsed
.
recordType
).
trim
()
&&
parsed
.
question
!=
null
,
)
}
/**
* 从流式 AI 回答解析工作流控制 JSON:
* 优先 workflowParseText(原始累积文本),再 answer;解析失败时不用外层 recordType 误代替 answer 内 JSON。
*/
export
function
resolveWorkflowControlFromStreamAnswer
(
snapshot
:
{
workflowParseText
?:
string
answer
?:
string
},
options
?:
WorkflowParseOptions
,
):
WorkflowControlPayload
|
null
{
const
parseText
=
trimSpacesOnly
(
snapshot
.
workflowParseText
??
snapshot
.
answer
??
''
,
)
const
parsedFromText
=
parseText
?
tryParseWorkflowControlJson
(
parseText
,
options
)
:
null
if
(
parsedFromText
)
return
parsedFromText
if
(
options
?.
answerChunk
?.
trim
())
{
const
chunkText
=
trimSpacesOnly
(
normalizeStreamAnswerChunk
(
options
.
answerChunk
))
if
(
chunkText
)
return
tryParseWorkflowControlJson
(
chunkText
,
options
)
}
return
null
}
export
function
resolveWorkflowControlFromPacketAnswer
(
rawAnswer
:
unknown
,
options
?:
WorkflowParseOptions
,
):
WorkflowControlPayload
|
null
{
const
chunk
=
normalizeStreamAnswerChunk
(
rawAnswer
)
if
(
!
chunk
.
trim
())
return
null
return
tryParseWorkflowControlJson
(
chunk
,
options
)
}
/** 外层 data.question 或累积 answer 文本中的 question 字段,补全控制 JSON */
export
function
enrichWorkflowControlWithPacketQuestion
(
parsed
:
WorkflowControlPayload
|
null
|
undefined
,
packetQuestion
?:
unknown
,
parseText
?:
string
,
):
WorkflowControlPayload
|
null
{
if
(
!
parsed
)
return
null
const
fromParsed
=
parsed
.
question
!=
null
?
String
(
parsed
.
question
).
trim
()
:
''
if
(
fromParsed
)
return
parsed
const
fromPacket
=
packetQuestion
!=
null
?
String
(
packetQuestion
).
trim
()
:
''
if
(
fromPacket
)
return
{
...
parsed
,
question
:
fromPacket
}
const
text
=
parseText
?.
trim
()
??
''
if
(
text
)
{
const
fromText
=
extractQuestionByRegex
(
text
)
if
(
fromText
)
return
{
...
parsed
,
question
:
fromText
}
}
return
parsed
}
export
function
isWorkflowControlPayloadComplete
(
parsed
:
WorkflowControlPayload
|
null
|
undefined
):
boolean
{
if
(
!
parsed
)
return
false
if
(
isHiddenWorkflowRedirectPayload
(
parsed
))
return
true
return
isWorkflowEnterSubPayload
(
parsed
)
}
/**
* 流式 answer 是否为「进子工作流」控制 JSON:
* {"recordType":"A25","question":"客群洞察"}(可选 end / showFlag)
*/
export
function
isStreamEnterSubWorkflowControlText
(
text
:
string
,
options
?:
WorkflowParseOptions
,
packetQuestion
?:
unknown
,
):
boolean
{
return
isWorkflowEnterSubPayload
(
parseWorkflowControlForStream
(
text
,
options
,
packetQuestion
))
}
/**
* 从累积原始文本解析工作流控制 JSON(推荐唯一入口)
* 合并全文/分片 JSON.parse、正则字段、packet.question,且需满足 complete 才返回
*/
export
function
parseWorkflowControlForStream
(
parseText
:
string
,
options
?:
WorkflowParseOptions
,
packetQuestion
?:
unknown
,
):
WorkflowControlPayload
|
null
{
const
text
=
trimSpacesOnly
(
parseText
)
if
(
!
text
)
return
null
const
fromText
=
mergePacketEnd
(
parseWorkflowControlFromText
(
text
),
options
)
const
fromChunk
=
options
?.
answerChunk
?.
trim
()
?
mergePacketEnd
(
parseWorkflowControlFromText
(
options
.
answerChunk
),
options
)
:
null
const
merged
=
enrichWorkflowControlWithPacketQuestion
(
mergeWorkflowControlPayload
(
fromText
,
fromChunk
,
extractByRegex
(
text
)),
packetQuestion
,
text
,
)
if
(
merged
&&
isWorkflowControlPayloadComplete
(
merged
))
return
merged
return
null
}
/**
* 流式快照解析:只信 workflowParseText(原始累积),不用 answer / 历史缓存
*/
export
function
resolveWorkflowControlFromStreamSnapshot
(
snapshot
:
{
workflowParseText
?:
string
answer
?:
string
workflowAnswerChunk
?:
string
workflowDetectedControl
?:
WorkflowControlPayload
|
null
},
options
?:
WorkflowParseOptions
,
packetQuestion
?:
unknown
,
):
WorkflowControlPayload
|
null
{
const
parseText
=
trimSpacesOnly
(
snapshot
.
workflowParseText
??
''
)
if
(
parseText
)
{
const
parsed
=
parseWorkflowControlForStream
(
parseText
,
options
,
packetQuestion
)
if
(
parsed
)
return
parsed
}
const
chunkText
=
trimSpacesOnly
(
snapshot
.
workflowAnswerChunk
??
snapshot
.
answer
??
''
)
if
(
chunkText
&&
chunkText
!==
parseText
)
{
const
fromChunk
=
parseWorkflowControlForStream
(
chunkText
,
options
,
packetQuestion
)
if
(
fromChunk
)
return
fromChunk
}
return
null
}
/** 是否包含工作流表单卡片(card-workflow + form_input,且含 text/select/file 字段) */
export
function
hasWorkflowFormCards
(
cardList
?:
Attachment
[]):
boolean
{
return
Array
.
isArray
(
cardList
)
&&
cardList
.
some
(
isWorkflowFormAttachment
)
}
/** 是否为「进入子工作流」类控制 JSON(解析后含 recordType + question,且非 showFlag 隐藏路由) */
export
function
isEnterSubWorkflowControlAnswer
(
text
:
string
,
options
?:
WorkflowParseOptions
):
boolean
{
return
isWorkflowEnterSubPayload
(
resolveWorkflowControlFromStreamAnswer
(
{
workflowParseText
:
text
,
answer
:
text
},
options
,
))
}
/** 从混合正文中移除已识别的工作流控制 JSON,保留其余展示内容 */
export
function
stripWorkflowControlJsonFromText
(
text
:
string
,
options
?:
WorkflowParseOptions
):
string
{
const
trimmed
=
text
.
trim
()
if
(
!
trimmed
)
return
''
let
result
=
text
for
(
const
segment
of
splitTopLevelJsonObjects
(
trimmed
))
{
const
parsed
=
parseJsonLevel1
(
segment
)
||
parseJsonLevel1
(
normalizeEscaped
(
segment
))
||
extractByRegex
(
segment
)
const
merged
=
mergePacketEnd
(
parsed
,
options
)
if
(
!
merged
)
continue
if
(
isHiddenWorkflowRedirectPayload
(
merged
)
||
isWorkflowEnterSubPayload
(
merged
))
result
=
result
.
split
(
segment
).
join
(
''
)
}
return
trimSpacesOnly
(
result
)
}
/** 工作流控制 JSON 不在气泡中展示正文,仅保留卡片等内容 */
export
function
resolveDisplayAnswerText
(
text
:
string
,
options
?:
WorkflowParseOptions
):
string
{
export
function
resolveDisplayAnswerText
(
text
:
string
,
options
?:
WorkflowParseOptions
,
packetQuestion
?:
unknown
,
):
string
{
if
(
!
text
?.
trim
())
return
text
||
''
if
(
isHiddenWorkflowRedirectControl
(
text
,
options
)
||
isEnterSubWorkflowControlAnswer
(
text
,
options
))
const
parsed
=
parseWorkflowControlForStream
(
text
,
options
,
packetQuestion
)
if
(
isHiddenWorkflowRedirectPayload
(
parsed
))
return
''
if
(
isWorkflowEnterSubPayload
(
parsed
))
return
stripWorkflowControlJsonFromText
(
text
,
options
)
return
text
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment