mirror of
https://github.com/usebruno/bruno.git
synced 2026-07-08 14:35:03 +00:00
feat(ai-assist): add docs generation with folder and collection context (#8246)
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { callIpc } from 'utils/common/ipc';
|
||||
import { isItemAFolder, isItemARequest, sortItemsBySidebarOrder } from 'utils/collections';
|
||||
|
||||
/**
|
||||
* Renderer-side wrapper around the AI IPC channels.
|
||||
@@ -41,6 +42,66 @@ export const buildRequestContextFromItem = (item) => {
|
||||
};
|
||||
};
|
||||
|
||||
const summarizeDocsItems = (items = []) => {
|
||||
const folders = [];
|
||||
const requests = [];
|
||||
|
||||
for (const item of sortItemsBySidebarOrder(items)) {
|
||||
if (item.isTransient) continue;
|
||||
|
||||
if (isItemAFolder(item)) {
|
||||
const nestedItems = item.items || [];
|
||||
const nestedRequests = nestedItems.filter((i) => isItemARequest(i) && !i.isTransient);
|
||||
const nestedFolders = nestedItems.filter((i) => isItemAFolder(i) && !i.isTransient);
|
||||
folders.push({
|
||||
name: item.name,
|
||||
requestCount: nestedRequests.length,
|
||||
subfolderCount: nestedFolders.length
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isItemARequest(item)) {
|
||||
const req = item.draft?.request || item.request;
|
||||
requests.push({
|
||||
name: item.name,
|
||||
method: req?.method || 'GET',
|
||||
url: req?.url || '',
|
||||
type: item.type
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return { folders, requests };
|
||||
};
|
||||
|
||||
export const buildDocsContextFromCollection = (collection) => {
|
||||
if (!collection) return null;
|
||||
|
||||
const { folders, requests } = summarizeDocsItems(collection.items || []);
|
||||
|
||||
return {
|
||||
scope: 'collection',
|
||||
name: collection.name || '',
|
||||
folders,
|
||||
requests
|
||||
};
|
||||
};
|
||||
|
||||
export const buildDocsContextFromFolder = (collection, folder) => {
|
||||
if (!folder) return null;
|
||||
|
||||
const { folders, requests } = summarizeDocsItems(folder.items || []);
|
||||
|
||||
return {
|
||||
scope: 'folder',
|
||||
name: folder.name || '',
|
||||
collectionName: collection?.name || '',
|
||||
folders,
|
||||
requests
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Start a streaming generation. Subscribes to the corresponding `main:ai-stream-*`
|
||||
* channels filtered by streamId. Returns a handle with `.stop()` and a promise
|
||||
|
||||
118
packages/bruno-app/src/utils/ai/index.spec.js
Normal file
118
packages/bruno-app/src/utils/ai/index.spec.js
Normal file
@@ -0,0 +1,118 @@
|
||||
import {
|
||||
buildDocsContextFromCollection,
|
||||
buildDocsContextFromFolder,
|
||||
buildRequestContextFromItem
|
||||
} from './index';
|
||||
|
||||
describe('utils/ai', () => {
|
||||
const collection = {
|
||||
name: 'Pet Store API',
|
||||
items: [
|
||||
{
|
||||
uid: 'f1',
|
||||
type: 'folder',
|
||||
name: 'Users',
|
||||
items: [
|
||||
{
|
||||
uid: 'r1',
|
||||
type: 'http-request',
|
||||
name: 'List Users',
|
||||
request: { method: 'GET', url: '{{base}}/users' }
|
||||
},
|
||||
{
|
||||
uid: 'f2',
|
||||
type: 'folder',
|
||||
name: 'Admin',
|
||||
items: [
|
||||
{
|
||||
uid: 'r2',
|
||||
type: 'http-request',
|
||||
name: 'Delete User',
|
||||
request: { method: 'DELETE', url: '{{base}}/users/1' }
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
uid: 'r3',
|
||||
type: 'http-request',
|
||||
name: 'Health Check',
|
||||
request: { method: 'GET', url: '{{base}}/health' }
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
describe('buildDocsContextFromCollection', () => {
|
||||
it('summarizes top-level folders and requests', () => {
|
||||
expect(buildDocsContextFromCollection(collection)).toEqual({
|
||||
scope: 'collection',
|
||||
name: 'Pet Store API',
|
||||
folders: [
|
||||
{
|
||||
name: 'Users',
|
||||
requestCount: 1,
|
||||
subfolderCount: 1
|
||||
}
|
||||
],
|
||||
requests: [
|
||||
{
|
||||
name: 'Health Check',
|
||||
method: 'GET',
|
||||
url: '{{base}}/health',
|
||||
type: 'http-request'
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
it('returns null when collection is missing', () => {
|
||||
expect(buildDocsContextFromCollection(null)).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('buildDocsContextFromFolder', () => {
|
||||
it('summarizes direct child folders and requests for the folder scope', () => {
|
||||
const folder = collection.items[0];
|
||||
|
||||
expect(buildDocsContextFromFolder(collection, folder)).toEqual({
|
||||
scope: 'folder',
|
||||
name: 'Users',
|
||||
collectionName: 'Pet Store API',
|
||||
folders: [
|
||||
{
|
||||
name: 'Admin',
|
||||
requestCount: 1,
|
||||
subfolderCount: 0
|
||||
}
|
||||
],
|
||||
requests: [
|
||||
{
|
||||
name: 'List Users',
|
||||
method: 'GET',
|
||||
url: '{{base}}/users',
|
||||
type: 'http-request'
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
it('returns null when folder is missing', () => {
|
||||
expect(buildDocsContextFromFolder(collection, null)).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('buildRequestContextFromItem', () => {
|
||||
it('builds request details for request-level docs', () => {
|
||||
const item = collection.items[1];
|
||||
|
||||
expect(buildRequestContextFromItem(item)).toEqual({
|
||||
url: '{{base}}/health',
|
||||
method: 'GET',
|
||||
headers: [],
|
||||
params: [],
|
||||
body: null
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user