Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,7 @@ By default, provider connections are loaded from `CrestApps:AI:Connections` and
"Name": "gpt-4.1",
"ClientName": "OpenAI",
"ModelName": "gpt-4.1",
"Type": "Chat",
"IsDefault": true
"Type": "Chat"
}
]
}
Expand Down
36 changes: 36 additions & 0 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ var fs = require("graceful-fs"),
postcss = require('gulp-postcss'),
rtl = require('postcss-rtl'),
babel = require('gulp-babel');
const { Transform } = require("stream");
const { finished } = require("stream/promises");

// For compat with older versions of Node.js.
Expand Down Expand Up @@ -176,6 +177,37 @@ function waitForTaskCompletion(task) {
return typeof task.then === "function" ? task : finished(task);
}

function normalizeSourceMapContents() {
return new Transform({
objectMode: true,
transform(file, encoding, callback) {
if (!file || file.isNull() || path.extname(file.path).toLowerCase() !== ".map") {
callback(null, file);
return;
}

try {
var sourceMap = JSON.parse(file.contents.toString("utf8"));

if (Array.isArray(sourceMap.sourcesContent)) {
sourceMap.sourcesContent = sourceMap.sourcesContent.map(function (content) {
return typeof content === "string"
? content.replace(/\r\n/g, "\n")
: content;
});

file.contents = Buffer.from(JSON.stringify(sourceMap), "utf8");
}

callback(null, file);
}
catch (error) {
callback(error);
}
}
});
}

function createAssetGroupTask(assetGroup, doRebuild) {
var outputExt = path.extname(assetGroup.output).toLowerCase();
var doConcat = path.basename(assetGroup.outputFileName, outputExt) !== "@";
Expand Down Expand Up @@ -269,6 +301,7 @@ function buildCssPipeline(assetGroup, doConcat, doRebuild) {
.pipe(gulpif(doConcat, concat(assetGroup.outputFileName)))
.pipe(gulpif(generateRTL, postcss([rtl()])))
.pipe(gulpif(generateSourceMaps, sourcemaps.write('.')))
.pipe(normalizeSourceMapContents())
.pipe(eol('\n'))
.pipe(gulp.dest(assetGroup.outputDir));
// Uncomment to copy assets to wwwroot
Expand Down Expand Up @@ -324,6 +357,8 @@ function buildJsPipeline(assetGroup, doConcat, doRebuild) {

var devStream = createJsStream(generateSourceMaps)
.pipe(gulpif(generateSourceMaps, sourcemaps.write('.')))
.pipe(normalizeSourceMapContents())
.pipe(eol('\n'))
.pipe(gulp.dest(assetGroup.outputDir));
// Uncomment to copy assets to wwwroot
//.pipe(gulp.dest(assetGroup.webroot));
Expand All @@ -334,6 +369,7 @@ function buildJsPipeline(assetGroup, doConcat, doRebuild) {
suffix: ".min"
}))
.pipe(gulpif(generateSourceMaps, sourcemaps.write('.')))
.pipe(normalizeSourceMapContents())
.pipe(eol('\n'))
.pipe(gulp.dest(assetGroup.outputDir));
// Uncomment to copy assets to wwwroot
Expand Down
3 changes: 1 addition & 2 deletions src/CrestApps.Core.Docs/docs/core/getting-started-aspnet.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,7 @@ At minimum, provide a connection and a deployment through configuration or your
"Name": "gpt-4.1",
"ClientName": "OpenAI",
"Type": "Chat",
"ModelName": "gpt-4.1",
"IsDefault": true
"ModelName": "gpt-4.1"
}
]
}
Expand Down
3 changes: 1 addition & 2 deletions src/CrestApps.Core.Docs/docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,7 @@ By default:
"Name": "gpt-4.1",
"ClientName": "OpenAI",
"ModelName": "gpt-4.1",
"Type": "Chat",
"IsDefault": true
"Type": "Chat"
}
]
}
Expand Down
65 changes: 59 additions & 6 deletions src/Resources/CrestApps.AI.Resources/Assets/css/chat-widget.css
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@
overflow: hidden;
}

.ai-chat-widget-container.ai-chat-widget-resizable {
resize: both;
min-width: 320px;
min-height: 420px;
max-width: min(90vw, 960px);
max-height: min(90vh, 960px);
}

.ai-chat-widget-container.open {
display: flex;
}
Expand All @@ -58,6 +66,31 @@
color: white;
}

.ai-chat-widget-header.ai-chat-widget-drag-handle {
cursor: move;
user-select: none;
touch-action: none;
}

.ai-chat-widget-header-actions {
display: flex;
align-items: center;
gap: 0.15rem;
}

.ai-chat-widget-toggle.ai-chat-widget-draggable {
touch-action: none;
}

.ai-chat-widget-container.ai-chat-widget-dragging,
.ai-chat-widget-toggle.ai-chat-widget-dragging {
transition: none;
}

.ai-chat-widget-toggle.ai-chat-widget-dragging:hover {
transform: none;
}

.ai-chat-widget-header .title {
font-weight: 600;
font-size: 0.95rem;
Expand Down Expand Up @@ -140,7 +173,7 @@

.ai-chat-widget-messages .ai-chat-message-body {
position: relative;
padding: 0 0 0.25rem 0;
padding: 0;
overflow-wrap: break-word;
word-break: break-word;
min-width: 0;
Expand All @@ -153,17 +186,22 @@
/* ── Message action buttons (copy, thumbs up/down) ── */
.ai-chat-widget-messages .message-buttons-container {
position: absolute;
right: 0;
top: 0;
right: 0.1rem;
bottom: 0;
display: inline-flex;
align-items: center;
gap: 0.35rem;
width: auto;
max-width: max-content;
opacity: 0;
pointer-events: none;
transition: opacity 0.15s ease-in-out;
background: #fff;
padding: 0.15rem 0.35rem;
border-radius: 4px;
background: rgba(255, 255, 255, 0.96);
padding: 0.2rem 0.35rem;
border-radius: 999px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
margin-bottom: 1rem;
transform: translateY(50%);
z-index: 1;
}

Expand All @@ -174,10 +212,25 @@
}

.ai-chat-widget-messages .message-buttons-container > .button-message-toolbox {
display: inline-flex;
align-items: center;
justify-content: center;
flex: 0 0 auto;
width: 1.75rem;
height: 1.75rem;
margin: 0 !important;
padding: 0 !important;
border-radius: 50%;
color: var(--bs-secondary-color, #6c757d) !important;
text-decoration: none;
}

.ai-chat-widget-messages .message-buttons-container .ai-chat-message-assistant-feedback {
display: inline-flex;
align-items: center;
gap: 0.35rem;
}

.ai-chat-widget-messages .message-buttons-container > .button-message-toolbox:hover,
.ai-chat-widget-messages .message-buttons-container > .button-message-toolbox:focus {
color: var(--bs-body-color, #212529) !important;
Expand Down
Loading
Loading