Skip to main content
Version: Latest

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.Core name
  • 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.RateLimiting policy
  • 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 the PromptSecurityOptions site 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.Tests project 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 IAIDeploymentStore and IAIProviderConnectionStore as 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 IAIProviderConnectionStore and IAIDeploymentStore as 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 so AI, AIDocs, and AIMemory each get their own document tables, adds generic Add*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:Connections and CrestApps: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:Connections and CrestApps:AI:Deployments instead of provider-grouped sample settings
  • adds Debug-level diagnostics in ConfigurationAIDeploymentCatalog so hosts can trace which configuration sections were evaluated and how standalone deployments were parsed
  • treats CrestApps:AI:Deployments as shared deployment metadata for all providers, not only providers with contained-connection support, so hosts can keep credentials in Connections while 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 ConnectionName values
  • adds shared JsonNode support 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.AISearch to CrestApps.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-based AddCoreAICompletionClient<TClient>(..., configure) overload, and updates AIOptions metadata from ProfileSources / AIProfileProviderEntry to CompletionClients / AICompletionClientEntry
  • aligns the built-in Entity Framework Core stores with the same IStoreCommitter unit-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 AIDataSource mappings react automatically to ISearchDocumentManager upserts 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 provider AddAIDataSources() registrations
  • generalizes AIDataSource sources beyond SearchIndexProfile by adding first-class source-type handling, built-in external source connectors for Elasticsearch, Azure AI Search, and PostgreSQL, protected per-source credentials, and a public IAIDataSourceChangeNotifier contract 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:AzureClient settings, keeps Azure completion resolution deployment-driven, and refreshes the AI client docs around ClientName-based configuration
  • clarifies deployment-store registration by introducing IAIDeploymentStore for 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 DefaultAIProfileManager in the framework so YesSql, EntityCore, and custom profile catalogs can reuse one NamedCatalogManager<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 into CrestApps.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 ClientAuthenticationType enum, removes the protocol-specific duplicate enums, and adds an AzureOpenAIClientMarker so 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_Data folder while switching their .NET 10 watch exclusions to the documented **/App_Data/** glob so Visual Studio Aspire runs do not restart when chat document uploads create files under App_Data/Documents
  • generates external .map source map files for all JS and CSS assets in the gulp build pipeline, copies them into dist/ during npm package preparation, and includes them in the @crestapps/ai-chat-ui package 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 universal coreai-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() plus AddDownloadAIDocumentEndpoint() 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.Chat services as CitationReferenceCollector, registers it from AddCoreAIChatInteractions(), 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-ui message-action icons compatible with both Font Awesome CSS/webfont hosts and SVG+JS hosts that load fontawesome-free/js/all.js, so dynamically rendered playback and action buttons now appear correctly in Orchard-style integrations
  • makes the shared @crestapps/ai-chat-ui chat 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.Documents package, renames the format-specific helpers to CrestApps.Core.AI.Documents.OpenXml and CrestApps.Core.AI.Documents.Pdf, removes the data-ingestion dependency from CrestApps.Core.AI, persists uploaded files through IDocumentFileStore with 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-backed IDocumentFileStore from AddCoreAIDocumentProcessing() with DocumentFileSystemFileStoreOptions for base-path overrides
  • simplifies template discovery by splitting generic Templates/ loading from prompt-only Templates/Prompts/, keeps generic file discovery flat so provider-specific subfolders are not double-loaded, adds Kind-based template selection through ITemplateService, 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 fallback ISearchIndexProfileStore, so hosts only need .AddIndexingServices(...).AddYesSqlStores() or .AddEntityCoreStores() when they want persisted index profile records
  • registers IAIProfileStore in 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.json and 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 IAICompletionUsageStore and IAIChatSessionEventStore implementations so the MVC and Blazor reports no longer depend on sample-only analytics services
  • moves AI chat inactivity closing into a shared AIChatSessionCloseBackgroundService registered from AddCoreAIChatSessionProcessing(), 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 makes ProcessedAtUtc nullable so pending tasks no longer serialize a default 0001-01-01 timestamp
  • 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 AIChatSessionCloseCycleService and AIChatSessionCloseRunner services so non-BackgroundService hosts can reuse the same lifecycle logic through RunOnceAsync, StartAsync, and StopAsync
  • makes the shared AI chat post-close retry cap configurable through AIChatSessionProcessingOptions.MaxPostCloseAttempts and the MVC admin site settings UI, and updates the shared processor to honor the live IOptionsMonitor<> value instead of a hard-coded constant
  • treats valid post-session JSON with an empty tasks array as an explicit structured-result failure, persists that clearer error in PostSessionResults, 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 in AttemptHistory, 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 minimal IOptionsChangeTokenSource<> pattern for custom hosts, and moves uploaded AI document vector indexing into a shared DefaultAIDocumentIndexingService so MVC and Blazor no longer carry duplicate sample-only indexer implementations
  • writes and reads ExtensibleEntity.Properties only through the nested Properties JSON object instead of flattening typed metadata onto the document root
  • introduces AIDeploymentPurpose as the primary deployment terminology, keeps the legacy type surface for backward compatibility, adds Vision plus DefaultVisionDeploymentName, 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 extra MemoryStream copy 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.Resilience package with opt-in Microsoft.Extensions.AI builder resilience extensions for chat, embeddings, image generation, speech-to-text, and text-to-speech clients, including UseDefaultResilience() for provider 429 Too Many Requests retries and UseResilience(...) 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 require Build(serviceProvider) instead of Build(null), and Azure OpenAI exposes shared SDK retry settings through CrestApps:AI:AzureClient with matching five-retry exponential defaults
  • adds IAIClientFactory overloads that accept builder-configuration delegates for chat, embeddings, image generation, speech-to-text, and text-to-speech clients, so callers can apply middleware such as UseDefaultResilience() while the factory owns the final Build(serviceProvider) step
  • expands Elasticsearch AI data source authentication beyond Basic by adding Elastic Cloud ID support plus ApiKey, Base64ApiKey, and KeyIdAndKey modes with protected per-source secrets in the MVC and Blazor editors and the shared Elasticsearch client factory
  • adds CrestApps.Core.PostgreSQL and CrestApps.Core.AI.PostgreSQL packages 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, supports AddAIDocuments(), AddAIDataSources(), and AddAIMemory() 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 unnamed NewAsync(...) 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, and IndexPrefix settings under CrestApps: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 (SelfManaged vs CloudHosted) so the MVC and Blazor editors show either Url or CloudId as appropriate and validation now requires the matching field for the chosen environment
  • makes AIDataSource source-aware through the shared Source property, updates the AI data-source stores to expose ISourceCatalog<AIDataSource>, and removes the public SourceType model property in favor of Source while still reading legacy persisted SourceType payloads
  • replaces per-turn raw image byte injection with an analyze-once-at-upload strategy: IImageAnalysisService calls a vision model to extract caption, OCR text, and detected entities when images are uploaded, stores the results as AIDocumentChunk records searchable via read_document and search_documents, adds inspect_image as an on-demand tool for pixel-level inspection when the text analysis is insufficient, removes BuildVisionUserContentsAsync from DocumentOrchestrationHandler so 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_data system 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 exposes list_tabular_data, query_tabular_data, execute_tabular_command, and export_tabular_data SQL 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 embedded tabular-data-agent AI 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 ITabularDocumentArtifactStore so another app instance can hydrate from shared document storage, and ITabularWorkspaceInvalidationPublisher provides the distributed backplane extension point for cross-instance cache clears; tabular files are identified through ExtractorExtension.IsTabular and ChatDocumentsOptions.TabularFileExtensions instead 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_C28 as SQL column names while retaining the full source header, exposing typed object[] 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.IsGenerated flags tool-produced deliverables, the export tool sets it when it creates the CSV AIDocument, 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 an AIInvocationContext.AgentInvocationDepth recursion-depth guard that prevents agent-to-agent recursion, plus code-defined profiles through the new IAIProfileProvider (with AgentMetadata.IsSystem for 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_file content-generation tool turns model-generated content into a downloadable AIDocument (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 pluggable IGeneratedFileWriter/IGeneratedFileWriterResolver abstraction (AddGeneratedFileWriter<T>(extensions)) with core writers for .csv and 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_data downloads an .xlsx workbook when the source was .xlsx and a .csv when the source was .csv, adds an optional format argument to request a different output format, and falls back to .csv when no writer is registered for the original extension
  • exports tabular files from the current in-memory data instead of the original upload: export_tabular_data now treats sql as optional and, when omitted, dumps the entire current table (including every execute_tabular_command mutation) using the original source column headers, and each successful execute_tabular_command snapshots the mutated table back through ITabularDocumentArtifactStore so 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_file downloads to the shared IDocumentFileStore under 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 new IConversationDocumentCleanupService (wired into the chat session managers and a ChatInteractionDocumentCleanupHandler)
  • makes the PDF generate_file writer 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 custom IFontResolver is 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_command snapshots through a coalesced background operation on TabularWorkspace instead 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 through ITabularDocumentArtifactStore
  • 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 new IConversationDocumentCleanupService.CleanupGeneratedDocumentsAsync and a decoupled IChatInteractionHistoryHandler, 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 UPDATE for bulk cell changes (instead of slow per-cell commands) and mandates export_tabular_data for downloads, and the generate_file tool description warns that its content becomes the entire file verbatim and must not be used to re-save uploaded spreadsheet/tabular data
  • makes export_tabular_data produce a single downloadable file by removing the duplicate parsed-artifact write, and excludes generated documents (flagged with DefaultGeneratedDocumentService.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_data tool description and result message so the model always returns the [doc:N] download marker verbatim instead of writing the file name in brackets, matching the generate_file download experience
  • lets execute_tabular_command apply 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 generated subfolder inside each chat session/chat interaction document path, lets FileSystemFileStore open download streams with delete sharing so ClearHistory can remove generated files even after a user downloaded them, caches identical export_tabular_data calls within the same prompt, and rejects status-only generate_file calls 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_cells tool 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 broadens generate_file tabular misuse detection so conversational/question text like “Would you like me to generate…” cannot be written into .xlsx downloads
  • 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 data folder, 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 IAIToolInstanceSource interface (registered under a unique name with AddAIToolInstanceSource<TSource>()) and let users create multiple configured AIToolInstance entries 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 pluggable IToolRegistryProvider) surfaces every referenced instance as a distinctly named AITool so multiple instances built from the same source appear as separate functions to every client (OpenAI, Azure OpenAI, …), projects can register their own IToolRegistryProvider to add logic such as permission checks, ships a built-in http-api-request source that calls arbitrary HTTP APIs with data-protected credentials, persists instances through the AIToolInstance catalog 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 AIToolInstanceMetadata and AICompletionContext.ToolInstanceNames) resolved through INamedCatalog<AIToolInstance>.FindByNameAsync instead of by generated id; the name is immutable after creation and AIToolInstance.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 on AddToolInstances(..., useDefaultRegistry: false) and exposes AddDefaultAIToolInstanceRegistryProvider(), letting hosts opt out and register their own IToolRegistryProvider without ever calling RemoveAll<IToolRegistryProvider>(); makes ToolInstanceRegistryProvider public with a ShouldIncludeInstanceAsync hook for simple permission-gated subclasses; and adds OAuth 2.0 support to the built-in http-api-request source 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 an AddHttpApiRequestSource() convenience for the built-in source), instead of being wired into the core AI services automatically; persistence is registered on the tool-instances builder via AddYesSqlStores()/AddEntityCoreStores() rather than on the AI suite; drops the redundant per-instance DisplayText in favor of the unique Name, localizes the source DisplayName/Description/Category, simplifies IAIToolInstanceSource.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 to Username/Password and 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 via AddCoreAITool (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.Copilot now resolves the effective npm registry from NPM_CONFIG_REGISTRY or npm config get registry before the GitHub.Copilot.SDK targets download the CLI tarball (the SDK hardcodes https://registry.npmjs.org, and MSBuild's DownloadFile task 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 through CopilotResolveNpmRegistry and CopilotUseSharedCliCache, the cache location is configurable through CopilotCliCacheDir (point it at a pre-seeded directory to build offline), and an explicitly set CopilotNpmRegistryUrl, CopilotCliBinaryPath, or CopilotSkipCliDownload always takes precedence
  • lets post-session processing invoke parameterized AI tool instances through the new AIProfilePostSessionSettings.ToolInstanceNames and PostSessionTask.ToolInstanceNames, merged and forwarded to the tool registry alongside the equivalent ToolNames so configuring only tool instances is enough to enable the tool-driven post-session path, and surfaces the per-task selection on the Capabilities tab of each post-session task in the AI profile create and edit screens of both the MVC and Blazor sample hosts
  • reports AI tools that were excluded from a completion because the current user is not authorized for them with a single Warning log entry per request instead of a Debug-only entry, so an answer that silently lost its tools is now traceable in the default logs, and corrects the documented IAIToolAccessEvaluator contract to match the implemented IsAuthorizedAsync(ClaimsPrincipal user, string toolName) signature
  • resolves the caller used for AI tool authorization through the new IUserAccessor abstraction instead of IHttpContextAccessor, because HttpContext is frequently unavailable inside SignalR hub invocations on long-lived transports, backplane-delivered messages, and hosted SignalR services; the built-in AI chat and chat interaction hubs now assign Context.User to that accessor for every invocation, and tool authorization is skipped only when there is genuinely no caller (background tasks, workflows, recipes) while unauthenticated callers are still evaluated so host-defined anonymous permissions continue to apply