Skip to content

Studio ai#3574

Merged
lvca merged 22 commits intomainfrom
studio-ai
Mar 3, 2026
Merged

Studio ai#3574
lvca merged 22 commits intomainfrom
studio-ai

Conversation

@lvca
Copy link
Member

@lvca lvca commented Mar 3, 2026

What does this PR do?

A brief description of the change being made with this pull request.

Motivation

What inspired you to submit this pull request?

Related issues

A list of issues either fixed, containing architectural discussions, otherwise relevant
for this Pull Request.

Additional Notes

Anything else we should know when reviewing?

Checklist

  • I have run the build using mvn clean package command
  • My unit tests cover both failure and success scenarios

lvca added 22 commits February 26, 2026 15:57
Add AI-powered database assistant with chat UI in Studio and backend
endpoints in the server module. Routes registered directly in HttpServer
(same pattern as MCP). Inactive until subscription token is set in
config/ai.json.

Backend (server module):
- AiConfiguration: loads config/ai.json (subscriptionToken, gatewayUrl)
- AiChatHandler: POST /api/v1/ai/chat - collects schema, forwards to gateway
- AiChatsHandler: GET/DELETE /api/v1/ai/chats - file-based chat persistence
- AiConfigHandler: GET /api/v1/ai/config - subscription status
- ChatStorage: per-user JSON file storage under chats/{username}/
- 19 tests (unit + integration)

Frontend (studio module):
- ai.html: chat tab with sidebar history, command blocks, inactive state
- studio-ai.js: chat logic, markdown rendering, command execution
- marked.js vendor dependency (MIT) for markdown in chat messages
@lvca lvca self-assigned this Mar 3, 2026
@lvca lvca added this to the 26.3.1 milestone Mar 3, 2026
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a significant new AI Assistant feature to ArcadeDB Studio, enhancing the user experience by providing intelligent, context-aware help for database management and optimization. It includes server-side APIs for AI integration, client-side UI components for interaction, and mechanisms for secure activation and chat history management. Users can now leverage AI for tasks like schema review, query optimization, and profiler analysis directly within the Studio.

Highlights

  • AI Assistant Integration: Introduced a new AI Assistant feature into ArcadeDB Studio, providing intelligent assistance for database tasks.
  • AI Activation and Configuration: Implemented a mechanism for activating the AI assistant using a subscription key and managing its configuration, including a gateway URL and hardware fingerprinting.
  • Interactive AI Chat: Developed a comprehensive AI chat interface within Studio, supporting conversation history, database context, and streaming responses for real-time tool call updates.
  • AI-Powered Profiler Analysis: Added functionality to send profiler data to the AI gateway for analysis, enabling AI to suggest optimizations and insights based on server performance.
  • New Server-Side AI Endpoints: Created several new REST API endpoints on the ArcadeDB server for AI activation, chat interactions, chat history management (CRUD), and profiler data analysis.
  • Client-Side UI Enhancements: Integrated the AI Assistant into the Studio UI with a dedicated tab, chat history sidebar, message rendering (including markdown and code blocks), and interactive command execution buttons.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • .gitignore
    • Added 'config/ai.json' to the ignore list to prevent committing AI configuration files.
  • ATTRIBUTIONS.md
    • Added 'marked' library (version 15.x, MIT License) to the Studio Frontend Libraries section.
  • server/src/main/java/com/arcadedb/server/ArcadeDBServer.java
    • Imported the new AiConfiguration class.
    • Added a private member aiConfiguration to manage AI settings.
    • Initialized and loaded the AiConfiguration during server startup.
    • Provided a public getter method getAiConfiguration() for accessing the AI configuration.
  • server/src/main/java/com/arcadedb/server/ai/AiActivateHandler.java
    • Added a new HTTP handler for activating AI subscriptions, which involves validating a subscription key against a gateway and generating a hardware ID.
  • server/src/main/java/com/arcadedb/server/ai/AiAnalyzeProfilerHandler.java
    • Added a new HTTP handler for sending profiler data to the AI gateway for analysis, including the collection of relevant database schemas.
  • server/src/main/java/com/arcadedb/server/ai/AiChatHandler.java
    • Added a new HTTP handler for managing AI chat interactions, including loading chat history, forwarding messages to the AI gateway, and handling streaming responses.
  • server/src/main/java/com/arcadedb/server/ai/AiChatsHandler.java
    • Added a new HTTP handler to manage CRUD operations (list, get, update, delete) for AI chat conversations.
  • server/src/main/java/com/arcadedb/server/ai/AiConfigHandler.java
    • Added a new HTTP handler to retrieve the current AI configuration status, indicating whether the AI assistant is configured.
  • server/src/main/java/com/arcadedb/server/ai/AiConfiguration.java
    • Added a new class to manage the AI assistant's configuration, including subscription token, gateway URL, and activation details, with methods for loading and saving to config/ai.json.
  • server/src/main/java/com/arcadedb/server/ai/AiTokenException.java
    • Added a new custom runtime exception for handling AI token-related errors, carrying HTTP status and JSON response.
  • server/src/main/java/com/arcadedb/server/ai/ChatStorage.java
    • Added a new class for file-based storage of AI chat conversations, including methods for listing, retrieving, saving, and deleting chats.
  • server/src/main/java/com/arcadedb/server/http/HttpServer.java
    • Imported new AI-related HTTP handlers and ChatStorage.
    • Registered new API routes under /api/v1/ai for configuration, activation, chat, profiler analysis, and chat history management.
  • server/src/test/java/com/arcadedb/server/ai/AiConfigurationTest.java
    • Added new unit tests for the AiConfiguration class, covering loading, saving, and status checks.
  • server/src/test/java/com/arcadedb/server/ai/AiServerTest.java
    • Added new integration tests for the AI server endpoints, verifying configuration status, chat listing, and authentication requirements.
  • server/src/test/java/com/arcadedb/server/ai/ChatStorageTest.java
    • Added new unit tests for the ChatStorage class, covering chat creation, retrieval, listing, deletion, and user isolation.
  • studio/package-lock.json
    • Updated package-lock.json to include the new marked dependency.
  • studio/package.json
    • Added marked (version ^15.0.0) as a new dependency for markdown rendering.
  • studio/pom.xml
    • Removed commented-out npm audit and prebuild execution blocks from the frontend build process.
  • studio/src/main/resources/static/ai.html
    • Added a new HTML file for the AI Assistant tab, including UI for activation, chat history, message display, and input.
  • studio/src/main/resources/static/css/studio.css
    • Adjusted the margin-top for .nav-label to 0.
    • Added new responsive CSS rules for the sidebar to support compact modes on smaller viewports.
  • studio/src/main/resources/static/index.html
    • Imported marked.min.js and studio-ai.js scripts.
    • Added a new navigation item for the 'AI' tab with a robot icon.
    • Included the ai.html content into the main Studio layout.
    • Added title attributes to navigation links for better accessibility and compact mode tooltips.
    • Added initAi() call when the AI tab is selected.
  • studio/src/main/resources/static/js/studio-ai.js
    • Added a new JavaScript file implementing the client-side logic for the AI Assistant, including activation, chat history management, message rendering (with markdown support), command execution, and streaming responses.
  • studio/src/main/resources/static/js/studio-profiler.js
    • Added a function profilerCheckAiAvailable() to determine if the AI button should be displayed based on AI configuration.
    • Integrated profilerAnalyzeWithAi() function to send profiler data for AI analysis and render the AI's response.
  • studio/src/main/resources/static/profiler.html
    • Added an 'Analyze with AI' button to the profiler tab, which appears if AI is configured.
    • Added a new panel (profilerAiPanel) to display AI analysis results for profiler data.
  • studio/webpack.config.js
    • Added a rule to copy marked.min.js from node_modules to the dist/js directory.
Activity
  • The pull request description is a generic template, indicating no specific human activity or detailed discussions were recorded in the PR body itself.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@lvca lvca merged commit 993588d into main Mar 3, 2026
13 of 53 checks passed
@mergify
Copy link
Contributor

mergify bot commented Mar 3, 2026

🧪 CI Insights

Here's what we observed from your CI run for 9f58abe.

🟢 All jobs passed!

But CI Insights is watching 👀

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a significant new AI assistant feature, including backend handlers for activation, chat, and profiler analysis, as well as a comprehensive frontend UI in Studio. The implementation is extensive and well-structured, with new services, storage mechanisms, and tests. The backend code demonstrates good practices, including security checks and robust error handling. The frontend provides a rich, interactive experience for the new AI capabilities. I've identified a potential stability issue in the hardware ID generation and an opportunity to improve maintainability by reducing code duplication in the JavaScript files.

Note: Security Review did not run due to the size of the PR.

Comment on lines +122 to +133
final Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
final NetworkInterface ni = interfaces.nextElement();
if (ni.isLoopback() || ni.isVirtual())
continue;
final byte[] mac = ni.getHardwareAddress();
if (mac != null) {
for (final byte b : mac)
raw.append(String.format("%02x", b));
raw.append("|");
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The order of network interfaces returned by NetworkInterface.getNetworkInterfaces() is not guaranteed to be consistent across JVM restarts. This could lead to the hardwareId changing for the same machine, potentially causing issues with the AI subscription activation. To ensure a stable hardware ID, the collected MAC addresses should be sorted before being hashed.

Suggested change
final Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
final NetworkInterface ni = interfaces.nextElement();
if (ni.isLoopback() || ni.isVirtual())
continue;
final byte[] mac = ni.getHardwareAddress();
if (mac != null) {
for (final byte b : mac)
raw.append(String.format("%02x", b));
raw.append("|");
}
}
// Collect all non-loopback MAC addresses
final java.util.List<String> macs = new java.util.ArrayList<>();
final Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
final NetworkInterface ni = interfaces.nextElement();
if (ni.isLoopback() || ni.isVirtual())
continue;
final byte[] mac = ni.getHardwareAddress();
if (mac != null) {
final StringBuilder macBuilder = new StringBuilder();
for (final byte b : mac)
macBuilder.append(String.format("%02x", b));
macs.add(macBuilder.toString());
}
}
java.util.Collections.sort(macs);
for (final String mac : macs) {
raw.append(mac);
raw.append("|");
}

Comment on lines +435 to +501
function profilerAnalyzeWithAi() {
if (!profilerData) {
globalNotify("Profiler", "No profiler data to analyze", "warning");
return;
}

var btn = jQuery("#profilerAiBtn");
btn.prop("disabled", true).html('<i class="fa fa-spinner fa-spin me-1"></i>Analyzing...');

jQuery("#profilerAiPanel").show();
jQuery("#profilerAiContent").html(
'<div class="text-center py-3" style="color: var(--text-muted);">' +
'<i class="fa fa-spinner fa-spin me-1"></i> Analyzing profiler data...</div>'
);

jQuery.ajax({
type: "POST",
url: "api/v1/ai/analyze-profiler",
data: JSON.stringify({ profilerData: profilerData }),
contentType: "application/json",
headers: { Authorization: globalCredentials },
timeout: 120000
})
.done(function(data) {
btn.prop("disabled", false).html('<i class="fa fa-robot"></i> Analyze with AI');
profilerRenderAiResponse(data);
})
.fail(function(jqXHR) {
btn.prop("disabled", false).html('<i class="fa fa-robot"></i> Analyze with AI');
var errorMsg = "Failed to analyze profiler data.";
try {
var errData = JSON.parse(jqXHR.responseText);
if (errData.error) errorMsg = errData.error;
} catch (e) { /* ignore */ }
jQuery("#profilerAiContent").html(
'<div style="color: #dc3545;"><i class="fa fa-circle-exclamation me-1"></i>' + escapeHtml(errorMsg) + '</div>'
);
});
}

function profilerRenderAiResponse(data) {
profilerAiCommandCounter = 0;
var contentHtml = '';

// Render markdown content
if (data.response) {
if (typeof marked !== "undefined") {
try { contentHtml = marked.parse(data.response); }
catch (e) { contentHtml = '<pre>' + escapeHtml(data.response) + '</pre>'; }
} else
contentHtml = '<pre style="white-space: pre-wrap;">' + escapeHtml(data.response) + '</pre>';
}

var html = '<div class="ai-message-content" style="color: var(--text-primary); line-height: 1.6; font-size: 0.9rem;">' + contentHtml + '</div>';

// Render command blocks
if (data.commands && data.commands.length > 0) {
if (data.commands.length > 1)
html += '<div class="mt-2 mb-2"><button class="btn btn-sm" style="background: var(--color-brand); color: white; border: none;" onclick="profilerAiExecuteAll(this)">' +
'<i class="fa fa-forward me-1"></i>Execute All</button></div>';

for (var j = 0; j < data.commands.length; j++)
html += profilerRenderAiCommandBlock(data.commands[j]);
}

jQuery("#profilerAiContent").html(html);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

There is significant code duplication between studio-profiler.js and studio-ai.js for rendering and handling AI-suggested command blocks. For example, profilerRenderAiCommandBlock and aiRenderCommandBlock are very similar, as are the helper functions for command execution (profilerAiExecuteCommand, profilerAiExecuteAll, etc.). To improve maintainability and reduce redundancy, this shared functionality should be refactored into a common utility file (e.g., studio-ai-common.js). This would ensure that any future changes to command block rendering or execution only need to be made in one place.

@claude
Copy link

claude bot commented Mar 3, 2026

PR Review: Studio AI Assistant

This PR adds an AI assistant feature to ArcadeDB Studio, enabling schema analysis, query optimization, and profiler analysis via an external AI gateway. The implementation is well-structured overall, but there are several issues worth addressing before merging.


🔴 Security Issues

1. XSS via Unescaped Markdown (High)

studio-ai.js and studio-profiler.js use marked.js to render AI responses without HTML sanitization:

// studio-profiler.js
contentHtml = marked.parse(data.response);

// studio-ai.js
return marked.parse(text, { renderer: renderer });

In marked v15, HTML embedded in markdown is passed through by default. If the AI gateway (or a compromised gateway) returns a response containing <script> tags or other HTML, it will execute in the user's browser. You should either:

  • Use marked.parse(text, { renderer: renderer, sanitize: false }) with a DOMPurify pass after, or
  • Configure the renderer to escape all raw HTML

2. External Gateway Receives Live Session Tokens (High)

In AiChatHandler.java auto mode, a fresh session token is created and sent to the external AI gateway:

final HttpAuthSession authSession = httpServer.getAuthSessionManager().createSession(user);
gatewayRequest.put("arcadedb", new JSONObject()
    .put("url", serverUrl)
    .put("sessionId", authSession.token));

This allows the external gateway to call any endpoint on the user's ArcadeDB server using the delegated session. The UI labels this as "read-only" but there is no server-side enforcement preventing the gateway from issuing write operations with this session. Consider:

  • Creating a read-only, scoped session token rather than a full session
  • Listing allowed endpoints server-side and rejecting write operations during the callback
  • Or documenting that the gateway is fully trusted and the user should understand this

3. X-Forwarded-For Header is Untrusted (Low)

// AiActivateHandler.java
final String forwarded = exchange.getRequestHeaders().getFirst("X-Forwarded-For");
if (forwarded != null && !forwarded.isEmpty())
    return forwarded.split(",")[0].trim();

The client IP used for activation logging can be spoofed. Not critical (it's only stored for auditing), but worth noting.


🟠 Performance Issues

4. Hardware ID Computed on Every Request (Medium)

AiActivateHandler.getHardwareId() enumerates all network interfaces and performs SHA-256 hashing on every chat and profiler analysis request:

// AiChatHandler.java and AiAnalyzeProfilerHandler.java
gatewayRequest.put("hardwareId", AiActivateHandler.getHardwareId());

This should be computed once at startup and cached in AiConfiguration (it's already stored there after activation). Just use config.getHardwareId() for subsequent requests.

5. HttpClient Not Shared (Low)

Each handler instance creates its own HttpClient. These should be shared (e.g., a single static or injected client) for connection pool reuse.


🟡 Correctness & Reliability Issues

6. Chat/Config Files Written Non-Atomically (Medium)

Both AiConfiguration.save() and ChatStorage.saveChat() write directly to the target file:

try (final OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8)) {
    writer.write(chat.toString(2));
}

A crash mid-write will corrupt the file. The standard fix is to write to a temp file first, then Files.move(..., ATOMIC_MOVE) over the target.

7. No Limit on Chat Storage (Low)

ChatStorage has no limits on:

  • Number of chats per user
  • Number of messages per chat
  • Total disk usage

A malicious or careless user could exhaust disk space. Consider adding a max-chats-per-user limit and a max-messages-per-chat cap.

8. SSE Streaming — Resource Cleanup in Error Path (Low)

In AiChatHandler.handleStreamingRequest(), if an exception is thrown after exchange.startBlocking() but before any data is written, the exception propagates up to execute(), which then returns an ExecutionResponse. At this point the exchange is in blocking mode and the framework may attempt to write a second response body, causing undefined behavior or a silent error. Exceptions thrown after streaming starts should be handled within handleStreamingRequest rather than propagating.


🔵 Minor / Code Quality

9. Sanitize Username Collisions

ChatStorage.sanitizeFilename() maps "user@domain.com" and "user_domain_com" to the same path. While unlikely with ArcadeDB's simple username rules, a comment or assertion would help clarify the assumption.

10. isConfigured() is Redundant Null Check

public boolean isConfigured() {
    return subscriptionToken != null && !subscriptionToken.isEmpty();
}

subscriptionToken is initialized to "" and only set via activate() (never to null), so != null is always true. The volatile declaration is appropriate here.

11. Missing Test Coverage

  • No test for AiActivateHandler (gateway interaction could be mocked)
  • No test for AiAnalyzeProfilerHandler
  • No test for the SSE streaming path in AiChatHandler

12. Commented-Out Code in pom.xml Removed Silently

The removed XML comments previously documented the npm audit and prebuild steps. If these were intentionally disabled, a note in the PR or a code comment explaining why would help future maintainers.


✅ What's Done Well

  • The toJSON() / toFullJSON() split correctly keeps the subscription token out of browser responses
  • sanitizeFilename() properly prevents path traversal attacks
  • Per-user chat directory isolation is correctly implemented
  • AiChatsHandler includes appropriate 404 and method-not-allowed responses
  • Good test coverage for AiConfiguration and ChatStorage with both positive and negative cases
  • The Terms of Use modal before activation is a thoughtful UX choice for privacy compliance
  • mustExecuteOnWorkerThread() is correctly overridden in all blocking handlers

Summary

The biggest concerns are the XSS risk from unescaped markdown and the full-session token delegation to the external AI gateway. Both should be addressed before this merges. The performance issue with hardware ID recomputation is an easy fix. The non-atomic file writes are a reliability concern worth addressing, especially for the activation token which is critical for the feature to work.

@codacy-production
Copy link

Coverage summary from Codacy

See diff coverage on Codacy

Coverage variation Diff coverage
-10.00% 27.64%
Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (5edbb10) 103092 77201 74.89%
Head commit (9f58abe) 134191 (+31099) 87077 (+9876) 64.89% (-10.00%)

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#3574) 550 152 27.64%

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

See your quality gate settings    Change summary preferences

@codecov
Copy link

codecov bot commented Mar 3, 2026

Codecov Report

❌ Patch coverage is 26.18182% with 406 lines in your changes missing coverage. Please review.
✅ Project coverage is 65.80%. Comparing base (5edbb10) to head (9f58abe).
⚠️ Report is 7 commits behind head on main.

Files with missing lines Patch % Lines
...ain/java/com/arcadedb/server/ai/AiChatHandler.java 4.68% 182 Missing and 1 partial ⚠️
...m/arcadedb/server/ai/AiAnalyzeProfilerHandler.java 5.15% 92 Missing ⚠️
...java/com/arcadedb/server/ai/AiActivateHandler.java 6.15% 61 Missing ⚠️
...in/java/com/arcadedb/server/ai/AiChatsHandler.java 40.81% 25 Missing and 4 partials ⚠️
...n/java/com/arcadedb/server/ai/AiConfiguration.java 55.35% 24 Missing and 1 partial ⚠️
.../main/java/com/arcadedb/server/ai/ChatStorage.java 84.84% 8 Missing and 2 partials ⚠️
.../java/com/arcadedb/server/ai/AiTokenException.java 0.00% 6 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3574      +/-   ##
==========================================
- Coverage   65.91%   65.80%   -0.11%     
==========================================
  Files        1506     1514       +8     
  Lines      103092   103642     +550     
  Branches    21381    21448      +67     
==========================================
+ Hits        67956    68206     +250     
- Misses      25920    26174     +254     
- Partials     9216     9262      +46     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@lvca lvca deleted the studio-ai branch March 4, 2026 21:17
robfrank pushed a commit that referenced this pull request Mar 5, 2026
* feat: add ArcadeDBi AI assistant to Studio

Add AI-powered database assistant with chat UI in Studio and backend
endpoints in the server module. Routes registered directly in HttpServer
(same pattern as MCP). Inactive until subscription token is set in
config/ai.json.

Backend (server module):
- AiConfiguration: loads config/ai.json (subscriptionToken, gatewayUrl)
- AiChatHandler: POST /api/v1/ai/chat - collects schema, forwards to gateway
- AiChatsHandler: GET/DELETE /api/v1/ai/chats - file-based chat persistence
- AiConfigHandler: GET /api/v1/ai/config - subscription status
- ChatStorage: per-user JSON file storage under chats/{username}/
- 19 tests (unit + integration)

Frontend (studio module):
- ai.html: chat tab with sidebar history, command blocks, inactive state
- studio-ai.js: chat logic, markdown rendering, command execution
- marked.js vendor dependency (MIT) for markdown in chat messages

* Update ai.html

* feat: parallel query

Fixed issue #1339

* fx: fixed parallel query: avoided when can deadlock

Fixed issue #1339

* Added test file

* Improvements

* studio: Add ai profiler

* Implemented Profiler AI Analyze

* Misc improvements

* fix: map Cypher to OpenCypher when the old cypher module (on gremlin) is not available

* fix: display button at the bottom of the code block now

* removed ai.json cfg file

* Improved activation with disclaimer

* Fixed studio AI panel

* studio: 2 modes of execution in ai panel

* Improved agentic system

* studio: added Drop Type button

* feat: studio -> double confirmation on database deletion

(cherry picked from commit 993588d)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant