Version 1.0.0 Release Notes
Package version: 1.0.0
CrestApps.Core 1.0.0 establishes the standalone framework repository for the reusable CrestApps libraries.
Highlights
- ships the shared abstractions, infrastructure, AI runtime, provider integrations, and protocol packages under the
CrestApps.Corename - assigns stable first-party anonymous visitor IDs to AI chat sessions, uses those visitor IDs for unique-visitor analytics, makes remote-address capture configurable with privacy-first hashed defaults plus optional plain-text or encrypted-at-rest storage, protects anonymous chat session starts with shared ASP.NET Core plus hub-level rate limiting, and documents how hosts can tune thresholds or replace the default endpoint policy with their own
Microsoft.AspNetCore.RateLimitingpolicy - lets AI Profiles and AI Profile-source templates override the site-wide anti-spam throttle limits through
PromptSecurityProfileSettings(max messages per window, message window, max anonymous sessions per window, and anonymous session window), with each unset value falling back to thePromptSecurityOptionssite default so profiles can raise or lower quotas per use case; both the message and anonymous session-start limiters honor the overrides, while high-level input and output security guards (injection detection, output filtering, security preamble, input delimiters, blocking threshold, and maximum prompt length) remain global-only concerns - defers AI Profile initial-prompt persistence until the first real user prompt arrives and stops the sample chat widgets from auto-creating empty sessions on initial page load
- includes a reference MVC host and an Aspire host for local composition and testing
- includes a dedicated
CrestApps.Core.Testsproject for framework validation - publishes a framework-focused documentation site at core.crestapps.com
- makes the generic AI deployment and connection catalog interfaces provider-backed database stores when YesSql or EntityCore is registered, while keeping
IAIDeploymentStoreandIAIProviderConnectionStoreas the merged runtime views across configuration and database sources - merges appsettings-backed and UI-managed AI provider connections and deployments through runtime catalogs, so MVC selectors and AI resolution stay current without rebuilding options or restarting the app
- keeps
IAIProviderConnectionStoreandIAIDeploymentStoreas the merged runtime views, makes the shared generic AI catalog interfaces provider-backed database stores once YesSql or EntityCore is registered, initializes configured YesSql collections up front soAI,AIDocs, andAIMemoryeach get their own document tables, adds genericAdd*DocumentCatalog<TModel, TIndex, T>()helpers for custom catalog registration, keeps deterministic name conflict handling so UI-managed records override conflicting appsettings entries, and standardizes settings so connections and deployments are configured separately - documents the default AI configuration sections (
CrestApps:AI:ConnectionsandCrestApps:AI:Deployments), tightens the quick-start path around Chat Interactions, and refreshes the docs navigation and landing page for faster onboarding - keeps the MVC sample focused on the recommended standalone AI configuration layout by default, using
CrestApps:AI:ConnectionsandCrestApps:AI:Deploymentsinstead of provider-grouped sample settings - adds Debug-level diagnostics in
ConfigurationAIDeploymentCatalogso hosts can trace which configuration sections were evaluated and how standalone deployments were parsed - treats
CrestApps:AI:Deploymentsas shared deployment metadata for all providers, not only providers with contained-connection support, so hosts can keep credentials inConnectionswhile still declaring deployment names and types in appsettings - evaluates every configured AI connection and deployment section when importing appsettings records, including provider-grouped connection sections and deployment entries that reference shared
ConnectionNamevalues - adds shared
JsonNodesupport extensions for common string, boolean, and raw-value extraction so AI configuration parsing and Elasticsearch document readers reuse one implementation instead of duplicating private helpers - replaces removed obsolete connection-level deployment-name helpers with non-obsolete legacy lookup extensions for
AIProviderConnectionEntry, keeping backward-compatible fallback resolution without depending on deleted APIs - renames
CrestApps.Core.AI.AISearchtoCrestApps.Core.AI.Azure.AISearch, groups the docs navigation around orchestrators, surfaces the Claude docs page, renames AI Providers to AI Clients, and updates the OpenAI docs to call out common OpenAI-compatible endpoints plus the dedicated Claude path - renames the old
AddCoreAIProfile<TClient>()provider-registration helper to the completion-client-basedAddCoreAICompletionClient<TClient>(..., configure)overload, and updatesAIOptionsmetadata fromProfileSources/AIProfileProviderEntrytoCompletionClients/AICompletionClientEntry - aligns the built-in Entity Framework Core stores with the same
IStoreCommitterunit-of-work pattern as YesSql and refreshes the storage/getting-started docs to explain MVC, Minimal API, SignalR, and background commit boundaries consistently - adds hierarchical document retrieval mode support so document RAG can rank on chunks and then inject full matched document text when hosts or profiles opt into that behavior
- moves data-source source-to-knowledge-base synchronization into shared framework services so
AIDataSourcemappings react automatically toISearchDocumentManagerupserts and deletes, and adds nightly background reconciliation to repair drift without host-specific observer code - replaces the data-source observer hook with shared
ISearchDocumentHandler-based notifications, adds Trace-level logging across queueing and background processing for async data-source synchronization, and documents the queue/handler override points plus providerAddAIDataSources()registrations - generalizes
AIDataSourcesources beyondSearchIndexProfileby adding first-class source-type handling, built-in external source connectors for Elasticsearch, Azure AI Search, and PostgreSQL, protected per-source credentials, and a publicIAIDataSourceChangeNotifiercontract so custom or external systems can push add/update/delete events into the knowledge-base sync pipeline - removes Azure OpenAI connection-level logging flags in favor of shared
CrestApps:AI:AzureClientsettings, keeps Azure completion resolution deployment-driven, and refreshes the AI client docs aroundClientName-based configuration - clarifies deployment-store registration by introducing
IAIDeploymentStorefor persisted deployments, moves Chat Interactions ahead of AI Profiles / AI Chat in the MVC sample onboarding flow, and adds dedicated AI Profile documentation that explains how profiles power reusable chat, agents, orchestration, retrieval, and session processing - registers a shared
DefaultAIProfileManagerin the framework so YesSql, EntityCore, and custom profile catalogs can reuse oneNamedCatalogManager<AIProfile>-based implementation instead of sample-host-specific manager classes - centralizes reusable MCP runtime registration in
AddCoreAIMcpServices(), moves the shared MCP metadata, capability-resolution, tool-registry, SSE settings-handler, and invoke-function services intoCrestApps.Core.AI.Mcp, and splits optional StdIO transport registration so hosts can enable it only where needed - standardizes A2A and MCP connection authentication on the shared
ClientAuthenticationTypeenum, removes the protocol-specific duplicate enums, and adds anAzureOpenAIClientMarkerso Azure OpenAI can participate in the same provider-marker conventions as the other AI clients without changing current runtime behavior - treats aborted and canceled request-stream failures in the Aspire AppHost as observed task exceptions so local development no longer floods the console with benign unobserved-task noise
- keeps the MVC and Blazor sample hosts writing runtime uploads and other mutable files into each project's own
App_Datafolder while switching their.NET 10watch exclusions to the documented**/App_Data/**glob so Visual Studio Aspire runs do not restart when chat document uploads create files underApp_Data/Documents - generates external
.mapsource map files for all JS and CSS assets in the gulp build pipeline, copies them intodist/during npm package preparation, and includes them in the@crestapps/ai-chat-uipackage exports - adds per-message text-to-speech play/pause controls on assistant messages in the AI Chat and Chat Interaction UIs, keeps the action toolbar pinned to the bottom-right of each response without reserving a separate action row, automatically stops other message players before starting a new one, and hides manual playback controls during Conversation mode
- adds declarative
data-*auto-initialization for the shared AI Chat, AI Chat widget, Chat Interaction, Chat Interaction settings, and document drop-zone scripts so MVC and Blazor hosts can render configuration directly in markup without separate bootstrap calls, now uses universalcoreai-prefixed chat/widget data attributes and script globals as a breaking rename, and shows a brief green success check on assistant-message copy buttons for clearer clipboard confirmation - renders sample-host
[doc:n]citations as superscript markers and shows the resolved document links below each cited assistant response in both the MVC and Blazor chat UIs - adds
AddReferenceDownloads()plusAddDownloadAIDocumentEndpoint()so attached-document citation links can be registered and downloaded explicitly in sample or custom hosts - moves the duplicated MVC and Blazor citation-reference collector into shared
CrestApps.Core.AI.Chatservices asCitationReferenceCollector, registers it fromAddCoreAIChatInteractions(), and lets hosts reuse the same citation-merging logic without copying sample code - detects when uploaded chat-interaction or chat-session documents are being used for whole-document tasks such as summarization, review, rewrite, translation, or complete extraction work, and injects the full document text instead of relying only on chunk-level RAG
- upgrades the MVC sample host to Font Awesome 7 and adds draggable, resizable AI Chat widget layout persistence with a reset-size control that hosts can disable through widget config
- makes the shared
@crestapps/ai-chat-uimessage-action icons compatible with both Font Awesome CSS/webfont hosts and SVG+JS hosts that loadfontawesome-free/js/all.js, so dynamically rendered playback and action buttons now appear correctly in Orchard-style integrations - makes the shared
@crestapps/ai-chat-uichat styles resolve colors through Bootstrap CSS variables with fallbacks, so admin and frontend chat widgets inherit Bootstrap 5 light/dark theme values when available - adds Chat History page listing previous sessions per AI Profile sorted by creation date, with resume, delete, delete-all, and new-chat actions
- adds Test page for Utility and Agent AI Profiles providing a single-prompt/single-response streamed UI
- renames the "Chat" button to "New Chat" on the AI Profile list and adds "Chat History" and "Test" buttons for applicable profile types
- splits document ingestion, document-processing services, document endpoints, and document RAG into the dedicated
CrestApps.Core.AI.Documentspackage, renames the format-specific helpers toCrestApps.Core.AI.Documents.OpenXmlandCrestApps.Core.AI.Documents.Pdf, removes the data-ingestion dependency fromCrestApps.Core.AI, persists uploaded files throughIDocumentFileStorewith GUID-based stored file names plus database-backed stored file metadata so hosts can redirect or clean up physical files reliably, and now registers a default filesystem-backedIDocumentFileStorefromAddCoreAIDocumentProcessing()withDocumentFileSystemFileStoreOptionsfor base-path overrides - simplifies template discovery by splitting generic
Templates/loading from prompt-onlyTemplates/Prompts/, keeps generic file discovery flat so provider-specific subfolders are not double-loaded, addsKind-based template selection throughITemplateService, suppresses duplicate template IDs with first-match wins behavior, and removes Orchard-specific embedded-resource path handling from the standalone framework templating providers - registers shared indexing services in the framework by default, including
ISearchIndexProfileManager,ISearchIndexProfileProvisioningService, and a null fallbackISearchIndexProfileStore, so hosts only need.AddIndexingServices(...).AddYesSqlStores()or.AddEntityCoreStores()when they want persisted index profile records - registers
IAIProfileStorein the shared AI services layer with a null fallback, and replaces it with provider-backed EntityCore or YesSql stores when AI services data stores are enabled so downstream services can always resolve the profile store - keeps the MVC and Blazor sample-host AI profile, template, and chat-edit screens usable when Claude is not configured by treating failed Claude options validation as "provider unavailable" instead of crashing the page, and removes the legacy memory-settings compatibility shim so profile/template memory state now flows only through
MemoryMetadata - keeps the MVC and Blazor sample-host index profile editors aligned with deployment-name-based indexing by posting embedding deployment names instead of catalog IDs and by accepting either selector during embedding profile validation
- fixes sample-host content-root resolution when MVC or Blazor are launched through the Aspire AppHost so
App_Data\appsettings.jsonand related local sample assets still load from the web-project directory instead of an Aspire output folder fallback - updates the shared A2A and MCP sample clients so one client app can target either the MVC or Blazor sample host through a built-in server selector, and wires the Aspire AppHost to advertise both endpoints to those samples
- moves AI chat extracted-data snapshot persistence into shared framework/store infrastructure by introducing
IAIChatSessionExtractedDataStore, registering a default recorder automatically when YesSql or EntityCore chat session stores are enabled, and rewiring the sample extracted-data reports to consume the shared store instead of host-specific recorder services - moves AI chat usage analytics and session analytics into shared framework abstractions/services, registers the default runtime analytics services from the framework, and lets YesSql or EntityCore provide the persisted
IAICompletionUsageStoreandIAIChatSessionEventStoreimplementations so the MVC and Blazor reports no longer depend on sample-only analytics services - moves AI chat inactivity closing into a shared
AIChatSessionCloseBackgroundServiceregistered fromAddCoreAIChatSessionProcessing(), so all hosts using the standard chat-session pipeline automatically evaluate inactive sessions and retry post-close work at startup and every 5 minutes instead of depending on sample-host-only background workers - persists per-attempt post-session task failure history in
PostSessionResults, records invalid structured task payloads explicitly, honors task-scoped post-session tool names during tool resolution, and makesProcessedAtUtcnullable so pending tasks no longer serialize a default0001-01-01timestamp - raises the shared AI chat post-close retry limit to 5 attempts, recalculates completion from the actual task results so stale terminal flags from older retry policies can recover, and splits the default inactivity-close worker into reusable
AIChatSessionCloseCycleServiceandAIChatSessionCloseRunnerservices so non-BackgroundServicehosts can reuse the same lifecycle logic throughRunOnceAsync,StartAsync, andStopAsync - makes the shared AI chat post-close retry cap configurable through
AIChatSessionProcessingOptions.MaxPostCloseAttemptsand the MVC admin site settings UI, and updates the shared processor to honor the liveIOptionsMonitor<>value instead of a hard-coded constant - treats valid post-session JSON with an empty
tasksarray as an explicit structured-result failure, persists that clearer error inPostSessionResults, and strengthens the shared post-session prompts so every configured task must still return a result even when no tool call is needed - stops serializing redundant top-level post-session error fields on
PostSessionResult, keeps attempt-specific failures inAttemptHistory, retries tool-enabled runs through structured recovery when the model returns invalid task entries such as blank names or blank values, and falls back to a no-tools structured retry when the tool path never actually invoked a tool - refreshes site-settings-backed options through the standard
IOptionsMonitor<>pipeline by documenting the minimalIOptionsChangeTokenSource<>pattern for custom hosts, and moves uploaded AI document vector indexing into a sharedDefaultAIDocumentIndexingServiceso MVC and Blazor no longer carry duplicate sample-only indexer implementations - writes and reads
ExtensibleEntity.Propertiesonly through the nestedPropertiesJSON object instead of flattening typed metadata onto the document root - introduces
AIDeploymentPurposeas the primary deployment terminology, keeps the legacy type surface for backward compatibility, addsVisionplusDefaultVisionDeploymentName, updates the MVC and Blazor deployment/settings UX to say purpose, and allows vision-capable chat interactions and chat sessions to upload supported image files as multimodal inputs - distinguishes uploaded vision images from searchable documents in the shared document-availability prompt so multimodal chat sessions analyze supported attached images directly instead of defaulting to document-tool or metadata-only responses
- caps the total uploaded vision-image bytes loaded into a single multimodal request through
ChatDocumentsOptions.MaxVisionInputBytesPerRequest, removes the extraMemoryStreamcopy when attaching those images, and documents how to resolve a vision-capable chat client for direct image-description requests - adds the standalone
CrestApps.Core.AI.Resiliencepackage with opt-in Microsoft.Extensions.AI builder resilience extensions for chat, embeddings, image generation, speech-to-text, and text-to-speech clients, includingUseDefaultResilience()for provider429 Too Many Requestsretries andUseResilience(...)for custom Polly/Microsoft resilience pipelines; the docs now include a dedicated AI Resilience page, the default retry schedule uses exponential backoff with jitter (about 1-2, 2-4, 4-8, 8-16, and 16-32 seconds across five retries), framework-owned completion clients and utility-deployment chat flows apply the default retry policy automatically, host-created clients remain opt-in, builder examples requireBuild(serviceProvider)instead ofBuild(null), and Azure OpenAI exposes shared SDK retry settings throughCrestApps:AI:AzureClientwith matching five-retry exponential defaults - adds
IAIClientFactoryoverloads that accept builder-configuration delegates for chat, embeddings, image generation, speech-to-text, and text-to-speech clients, so callers can apply middleware such asUseDefaultResilience()while the factory owns the finalBuild(serviceProvider)step - expands Elasticsearch AI data source authentication beyond Basic by adding Elastic Cloud ID support plus
ApiKey,Base64ApiKey, andKeyIdAndKeymodes with protected per-source secrets in the MVC and Blazor editors and the shared Elasticsearch client factory - adds
CrestApps.Core.PostgreSQLandCrestApps.Core.AI.PostgreSQLpackages providing a lightweight PostgreSQL + pgvector vector search backend as an alternative to Elasticsearch and Azure AI Search, registers the same keyed services (ISearchIndexManager,ISearchDocumentManager,IDataSourceContentManager,IDataSourceDocumentReader,IODataFilterTranslator) under the"PostgreSQL"provider name, supportsAddAIDocuments(),AddAIDataSources(), andAddAIMemory()builder extensions, and integrates into both MVC and Blazor sample hosts - fixes hosted document and data-source indexing flows so background workers create a scoped service provider before resolving scoped indexing services, preventing upload-triggered failures and similar nightly alignment lifetime issues
- aligns named catalog manager creation overloads so
INamedCatalogManager<T>also exposes unnamedNewAsync(...)creation, while source-aware managers keep source-required creation paths and no longer advertise name-only manager registrations for source-bound AI templates and deployments - standardizes Azure AI Search configuration on top-level
AuthenticationType,ApiKey,IdentityClientId, andIndexPrefixsettings underCrestApps:AzureAISearch, and refreshes the sample host / docs examples to list the full supported option set in one place - adds an explicit Elasticsearch data-source environment selector (
SelfManagedvsCloudHosted) so the MVC and Blazor editors show eitherUrlorCloudIdas appropriate and validation now requires the matching field for the chosen environment - makes
AIDataSourcesource-aware through the sharedSourceproperty, updates the AI data-source stores to exposeISourceCatalog<AIDataSource>, and removes the publicSourceTypemodel property in favor ofSourcewhile still reading legacy persistedSourceTypepayloads - replaces per-turn raw image byte injection with an analyze-once-at-upload strategy:
IImageAnalysisServicecalls a vision model to extract caption, OCR text, and detected entities when images are uploaded, stores the results asAIDocumentChunkrecords searchable viaread_documentandsearch_documents, addsinspect_imageas an on-demand tool for pixel-level inspection when the text analysis is insufficient, removesBuildVisionUserContentsAsyncfromDocumentOrchestrationHandlerso image bytes are never attached to every user message, and updates the document-availability prompt to guide the model toward text-based tools first - adds a defense-in-depth prompt security layer for AI Profile chat experiences with normalized regex-rule evaluation, weighted risk scoring, profile-level overrides, output filtering, audit logging, and documentation for remaining regex-based limitations
- adds AI tool dependency registration through the fluent
AIToolBuilder, automatically expands selected tool sets to include registered dependencies during profile/system tool resolution, ignores missing dependencies safely, and adds focused unit coverage for recursive, shared, and circular dependency graphs - replaces the always-on
read_tabular_datasystem tool with an always-available, system Tabular Data Agent that loads uploaded non-embeddable files (such as CSV and Excel) lazily into an in-memory SQLite database and exposeslist_tabular_data,query_tabular_data,execute_tabular_command, andexport_tabular_dataSQL tools, so the model analyzes, manipulates, and creates downloadable CSV versions of large tabular files through scoped SQL while only minimal results enter the prompt and the original uploaded file is always preserved; the agent's system prompt is sourced from the embeddedtabular-data-agentAI template and its SQL tools are hidden from the user-facing tool picker - tightens the MVC, Blazor, and shared chat-settings selection flows so only selectable tools and user-selectable agents can be chosen or persisted from the UI, keeping hidden/system tools and framework-managed system agents such as the Tabular Data Agent out of manual pickers while still exposing those system agents through the A2A host
- caches in-memory tabular databases per active chat scope instead of rebuilding them for every prompt: workspaces are keyed by chat interaction/session/profile document scope, reused while the user remains active, expired after a configurable sliding idle timeout (five minutes by default), cleaned by a hosted background service, and invalidated immediately when tabular documents or related chat interactions/sessions are removed; parsed tabular document artifacts are persisted through
ITabularDocumentArtifactStoreso another app instance can hydrate from shared document storage, andITabularWorkspaceInvalidationPublisherprovides the distributed backplane extension point for cross-instance cache clears; tabular files are identified throughExtractorExtension.IsTabularandChatDocumentsOptions.TabularFileExtensionsinstead of a hardcoded extension list - improves tabular upload handling by storing raw tabular content chunks without embeddings, preserving sparse XLSX cell positions, using compact survey header codes such as
Q3_C28as SQL column names while retaining the full source header, exposing typedobject[]query rows, and adding document-availability guidance that routes row counts, summaries, and calculations to the Tabular Data Agent - ensures generated tabular-export files are always downloadable:
AICompletionReference.IsGeneratedflags tool-produced deliverables, the export tool sets it when it creates the CSVAIDocument, and the chat UI always renders generated references as a download even when the primary model omits the[doc:n]marker after delegating to the Tabular Data Agent - adds tool-capable agents via
AgentMetadata.AllowToolInvocation, letting designated agents run their own tools through the orchestrator under anAIInvocationContext.AgentInvocationDepthrecursion-depth guard that prevents agent-to-agent recursion, plus code-defined profiles through the newIAIProfileProvider(withAgentMetadata.IsSystemfor system agents) that are merged with stored profiles and can provide always-available agents exposed via A2A and hidden from the user-facing agent selection list - adds a general file-generation chat capability: the always-available
generate_filecontent-generation tool turns model-generated content into a downloadableAIDocument(PDF, Word, Markdown, HTML, text, CSV, or spreadsheet) and surfaces it through the same[doc:N]download path used for charts and tabular exports, backed by a pluggableIGeneratedFileWriter/IGeneratedFileWriterResolverabstraction (AddGeneratedFileWriter<T>(extensions)) with core writers for.csvand plain-text formats plus OpenXml (.xlsx,.docx) and PDF (.pdf) writers in their respective modules - preserves the original tabular upload format on export so
export_tabular_datadownloads an.xlsxworkbook when the source was.xlsxand a.csvwhen the source was.csv, adds an optionalformatargument to request a different output format, and falls back to.csvwhen no writer is registered for the original extension - exports tabular files from the current in-memory data instead of the original upload:
export_tabular_datanow treatssqlas optional and, when omitted, dumps the entire current table (including everyexecute_tabular_commandmutation) using the original source column headers, and each successfulexecute_tabular_commandsnapshots the mutated table back throughITabularDocumentArtifactStoreso the edits survive workspace eviction, a process restart, or another app instance while the originally uploaded file stays untouched - persists generated tabular-export and
generate_filedownloads to the sharedIDocumentFileStoreunder a collision-free random storage name so they stay re-downloadable across in-memory workspace eviction and process restarts, keeps the[doc:n]reference saved with the assistant message so reopening a session re-renders the same download link, and removes a conversation's documents, stored files, tabular artifacts, and chunks automatically when its chat session or chat interaction is deleted through the newIConversationDocumentCleanupService(wired into the chat session managers and aChatInteractionDocumentCleanupHandler) - makes the PDF
generate_filewriter work out of the box on non-Windows hosts by falling back to a sans-serif font discovered in the standard system font directories when no customIFontResolveris registered, and sanitizes user-provided conversation identifiers before they are written to cleanup log entries - speeds up in-memory tabular edits by persisting
execute_tabular_commandsnapshots through a coalesced background operation onTabularWorkspaceinstead of blocking each command on a full-table snapshot, serialization, and write, so a burst of edits no longer slows the model's tool-call loop while the mutated state is still saved throughITabularDocumentArtifactStore - removes AI-generated downloadable files when a chat interaction's history is cleared: clearing history now collects the generated
[doc:n]references stored on the cleared messages and deletes those files (and their stored content, chunks, and tabular artifacts) through the newIConversationDocumentCleanupService.CleanupGeneratedDocumentsAsyncand a decoupledIChatInteractionHistoryHandler, so generated exports no longer linger in the document file store after the messages that produced them are gone while uploaded source documents are left intact - steers the model to deliver updated tabular files correctly: the Tabular Data Agent prompt now requires a single set-based
UPDATEfor bulk cell changes (instead of slow per-cell commands) and mandatesexport_tabular_datafor downloads, and thegenerate_filetool description warns that itscontentbecomes the entire file verbatim and must not be used to re-save uploaded spreadsheet/tabular data - makes
export_tabular_dataproduce a single downloadable file by removing the duplicate parsed-artifact write, and excludes generated documents (flagged withDefaultGeneratedDocumentService.GeneratedPropertyName) from the in-memory tabular workspace so an exported file is never re-ingested as a duplicate source table or blocks a later full-table export - strengthens the
export_tabular_datatool description and result message so the model always returns the[doc:N]download marker verbatim instead of writing the file name in brackets, matching thegenerate_filedownload experience - lets
execute_tabular_commandapply multiple SQL statements in a single call: the tool now accepts one or more semicolon-separated data/schema statements, validates each one independently against the tabular SQL guard (respecting string literals, quoted identifiers, and comments so semicolons inside them never split a statement), and runs the whole batch in one transaction that rolls back together on failure, so the model makes every requested change in one tool call instead of many slow per-cell round-trips that previously hit the tool iteration limit on large files - stores AI-generated downloads under a dedicated
generatedsubfolder inside each chat session/chat interaction document path, letsFileSystemFileStoreopen download streams with delete sharing soClearHistorycan remove generated files even after a user downloaded them, caches identicalexport_tabular_datacalls within the same prompt, and rejects status-onlygenerate_filecalls after an existing export so the model no longer creates an extra bogus file that only says the download is ready - adds a dedicated hidden
fill_empty_tabular_cellstool for the Tabular Data Agent so “replace every empty cell with X” requests run as one set-based update instead of the model composing hundreds of per-column statements, and broadensgenerate_filetabular misuse detection so conversational/question text like “Would you like me to generate…” cannot be written into.xlsxdownloads - keeps hidden tools private to their owning profiles and agents across the shared MCP server handlers, so agent-only helpers such as the Tabular Data Agent SQL tools are no longer listed or callable as direct MCP tools
- moves tabular workspace storage from in-memory SQLite to a file-based SQLite database stored alongside uploaded documents in a
datafolder, so workspace state persists across process restarts without artifact-store round-trips and reduces peak memory usage under high traffic; removes the singleton workspace cache, invalidation publisher interfaces, and cleanup background service in favor of creating a disposable workspace per tool call that opens and closes its own connection, with the document cleanup service and document event handler deleting the database file directly on session or document removal - adds parameterized AI tool instances so developers can author a tool blueprint once in code via the
IAIToolInstanceSourceinterface (registered under a unique name withAddAIToolInstanceSource<TSource>()) and let users create multiple configuredAIToolInstanceentries of it, each supplying its own settings (endpoint, authentication, headers, …), a unique name, and a natural-language description up front instead of relying on the AI model to provide them; the model still decides when to invoke each instance,ToolInstanceRegistryProvider(a pluggableIToolRegistryProvider) surfaces every referenced instance as a distinctly namedAIToolso multiple instances built from the same source appear as separate functions to every client (OpenAI, Azure OpenAI, …), projects can register their ownIToolRegistryProviderto add logic such as permission checks, ships a built-inhttp-api-requestsource that calls arbitrary HTTP APIs with data-protected credentials, persists instances through theAIToolInstancecatalog on both YesSql and EntityCore, and includes full management UI plus AI profile attachment in the MVC and Blazor sample hosts - refines the parameterized AI tool instances so profiles and chat interactions reference instances by their stable unique name (via the renamed, feature-agnostic
AIToolInstanceMetadataandAICompletionContext.ToolInstanceNames) resolved throughINamedCatalog<AIToolInstance>.FindByNameAsyncinstead of by generated id; the name is immutable after creation andAIToolInstance.GetFunctionName()appends a short deterministic hash when sanitizing would be lossy so distinct names can never collapse to the same function; decouples the default registry so the opt-out lives onAddToolInstances(..., useDefaultRegistry: false)and exposesAddDefaultAIToolInstanceRegistryProvider(), letting hosts opt out and register their ownIToolRegistryProviderwithout ever callingRemoveAll<IToolRegistryProvider>(); makesToolInstanceRegistryProviderpublic with aShouldIncludeInstanceAsynchook for simple permission-gated subclasses; and adds OAuth 2.0 support to the built-inhttp-api-requestsource that acquires, data-protects, caches, and refreshes access/refresh tokens on the instance itself so it authenticates once and reuses the token across requests and restarts - promotes the parameterized AI tool instances into a first-class opt-in feature registered on the AI suite builder with
AddToolInstances(toolInstances => toolInstances.AddSource<TSource>(...))(with anAddHttpApiRequestSource()convenience for the built-in source), instead of being wired into the core AI services automatically; persistence is registered on the tool-instances builder viaAddYesSqlStores()/AddEntityCoreStores()rather than on the AI suite; drops the redundant per-instanceDisplayTextin favor of the uniqueName, localizes the sourceDisplayName/Description/Category, simplifiesIAIToolInstanceSource.CreateTool(AIToolInstance instance)to take the instance directly, generalizes the completion-context handler to honor tool instances on any resource so both AI profiles and chat interactions can select them, renames the built-in HTTP source's basic/OAuth credentials toUsername/Passwordand adds the OAuth 2.0 resource-owner password grant, hardens model-provided paths so they cannot redirect a request off the configured host, and updates the MVC and Blazor sample hosts to let users attach instances to both AI profiles and chat interactions - namespaces every tool-instance function name with the
AIToolInstanceExtensions.FunctionNamePrefix(tool_instance_) prefix so a user-chosen instance name can never collide with a tool registered in code viaAddCoreAITool(which the model sees under its bare registered name); both kinds of tool now coexist safely in the single function namespace exposed to OpenAI, Azure OpenAI, and every other client - adds a source dropdown to the AI tool instance create form in the MVC and Blazor sample hosts that reveals only the selected source's fields (the source is fixed and shown read-only on edit), and relocates the "AI Tool Instances" admin menu item next to "AI Profiles" in both samples
- requires the key, title, and content field mappings when creating or editing an AI data source in the MVC and Blazor sample hosts, and makes every built-in source reader fall back to the document key instead of the serialized source document when no title is mapped, so chat citations never render a full JSON document as a reference title
- makes the Copilot CLI acquisition work behind corporate proxies and artifact mirrors, and downloads it only once per machine:
CrestApps.Core.AI.Copilotnow resolves the effective npm registry fromNPM_CONFIG_REGISTRYornpm config get registrybefore theGitHub.Copilot.SDKtargets download the CLI tarball (the SDK hardcodeshttps://registry.npmjs.org, and MSBuild'sDownloadFiletask cannot read npm configuration), and redirects the SDK's per-project, per-configuration cache to a shared cache under the NuGet global packages folder so a multi-project solution, a fresh worktree, or a CI agent no longer re-downloads the same large tarball for every project; both behaviors are opt-out throughCopilotResolveNpmRegistryandCopilotUseSharedCliCache, the cache location is configurable throughCopilotCliCacheDir(point it at a pre-seeded directory to build offline), and an explicitly setCopilotNpmRegistryUrl,CopilotCliBinaryPath, orCopilotSkipCliDownloadalways takes precedence