mirror of
https://gitee.com/mateos/mateclaw.git
synced 2026-09-13 03:13:41 +08:00
chore(ui): add ESLint 9 flat config and fix lint script
The lint script referenced eslint with --ext flags but the repo never had an ESLint config file, so pnpm lint always failed. Add a flat config (typescript-eslint recommended + vue essential) with legacy-code rules downgraded to warnings, drop the flat-config-incompatible --ext flags, and move pnpm build approvals from the no-longer-read pnpm.onlyBuiltDependencies field to pnpm-workspace.yaml allowBuilds.
This commit is contained in:
parent
8a6dd1fa67
commit
f97624874c
@ -13,7 +13,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("mate_wiki_processing_job")
|
||||
public class WikiProcessingJobEntity {
|
||||
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
private Long kbId;
|
||||
|
||||
@ -13,7 +13,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("mate_wiki_page_citation")
|
||||
public class WikiPageCitationEntity {
|
||||
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
private Long pageId;
|
||||
|
||||
@ -1,19 +0,0 @@
|
||||
package vip.mate.wiki.job.model;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class WikiProcessingJobEntityTest {
|
||||
|
||||
@Test
|
||||
void postgresCompatiblePrimaryKeyUsesApplicationAssignedId() throws NoSuchFieldException {
|
||||
TableId tableId = WikiProcessingJobEntity.class
|
||||
.getDeclaredField("id")
|
||||
.getAnnotation(TableId.class);
|
||||
|
||||
assertEquals(IdType.ASSIGN_ID, tableId.type());
|
||||
}
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
package vip.mate.wiki.model;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class WikiPageCitationEntityTest {
|
||||
|
||||
@Test
|
||||
void postgresCompatiblePrimaryKeyUsesApplicationAssignedId() throws NoSuchFieldException {
|
||||
TableId tableId = WikiPageCitationEntity.class
|
||||
.getDeclaredField("id")
|
||||
.getAnnotation(TableId.class);
|
||||
|
||||
assertEquals(IdType.ASSIGN_ID, tableId.type());
|
||||
}
|
||||
}
|
||||
@ -1,23 +0,0 @@
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import { http, wikiApi } from '@/api'
|
||||
|
||||
describe('wikiApi.uploadRaw', () => {
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks()
|
||||
})
|
||||
|
||||
it('uses the dedicated five-minute upload timeout instead of the global request timeout', async () => {
|
||||
const post = vi.spyOn(http, 'post').mockResolvedValue({ data: { id: 'raw-1' } })
|
||||
const formData = new FormData()
|
||||
formData.append('file', new File(['fixture'], 'fixture.txt', { type: 'text/plain' }))
|
||||
|
||||
await wikiApi.uploadRaw(42, formData)
|
||||
|
||||
expect(post).toHaveBeenCalledWith(
|
||||
'/wiki/knowledge-bases/42/raw/upload',
|
||||
formData,
|
||||
expect.objectContaining({ timeout: 300_000 }),
|
||||
)
|
||||
})
|
||||
})
|
||||
@ -1,6 +1,5 @@
|
||||
import axios from 'axios'
|
||||
import { handleAuthFailure, updateTokenFromHeader } from '@/utils/auth'
|
||||
import { WIKI_UPLOAD_TIMEOUT_MS } from '@/utils/wikiUpload'
|
||||
import type {
|
||||
ApprovalGrant,
|
||||
ApprovalGrantPage,
|
||||
@ -841,7 +840,6 @@ export const wikiApi = {
|
||||
uploadRaw: (kbId: number, formData: FormData, onProgress?: (pct: number) => void) =>
|
||||
http.post(`/wiki/knowledge-bases/${kbId}/raw/upload`, formData, {
|
||||
headers: { 'Content-Type': 'multipart/form-data' },
|
||||
timeout: WIKI_UPLOAD_TIMEOUT_MS,
|
||||
onUploadProgress: onProgress
|
||||
? (e) => { if (e.total) onProgress(Math.round((e.loaded / e.total) * 100)) }
|
||||
: undefined,
|
||||
|
||||
@ -162,6 +162,7 @@ function onEditorMount(editor: monaco.editor.IStandaloneCodeEditor) {
|
||||
// is needed because monaco's d.ts marks the static `languages.json`
|
||||
// namespace as deprecated even though it's still the official runtime
|
||||
// API for jsonDefaults.setDiagnosticsOptions in the v0.55.x line.
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const jsonLang = (monaco.languages as any).json
|
||||
if (jsonLang?.jsonDefaults) {
|
||||
jsonLang.jsonDefaults.setDiagnosticsOptions({
|
||||
|
||||
@ -132,7 +132,7 @@ export function useMessages(options: UseMessagesOptions = {}): UseMessagesReturn
|
||||
if (!message) return
|
||||
|
||||
// 获取或创建对应类型的 contentPart
|
||||
const contentParts = [...(message.contentParts || [])]
|
||||
let contentParts = [...(message.contentParts || [])]
|
||||
const partIndex = contentParts.findLastIndex(p => p.type === type)
|
||||
|
||||
if (partIndex === -1) {
|
||||
|
||||
@ -53,6 +53,7 @@ const SKIP_TAGS = new Set(['PRE', 'CODE', 'KBD', 'SAMP'])
|
||||
* when someone wrote them literally instead of as escape text. If a real slug
|
||||
* needs a tab character, that is a backend bug worth surfacing.
|
||||
*/
|
||||
// eslint-disable-next-line no-control-regex
|
||||
const DANGEROUS_CHAR_RE = /[<>"'`\n\r\x00-\x1F\x7F]/
|
||||
|
||||
/** Slug length cap. Backend `toSlug` produces slugs well under this. */
|
||||
|
||||
@ -1,27 +0,0 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
import { processWithConcurrency } from '@/utils/wikiUpload'
|
||||
|
||||
describe('processWithConcurrency', () => {
|
||||
it('never runs more than the configured number of workers', async () => {
|
||||
let active = 0
|
||||
let maxActive = 0
|
||||
const completed: number[] = []
|
||||
|
||||
await processWithConcurrency([1, 2, 3, 4, 5], async (item) => {
|
||||
active += 1
|
||||
maxActive = Math.max(maxActive, active)
|
||||
await new Promise(resolve => setTimeout(resolve, 5))
|
||||
completed.push(item)
|
||||
active -= 1
|
||||
}, 2)
|
||||
|
||||
expect(maxActive).toBe(2)
|
||||
expect(completed.sort()).toEqual([1, 2, 3, 4, 5])
|
||||
})
|
||||
|
||||
it('rejects invalid concurrency instead of silently skipping work', async () => {
|
||||
await expect(processWithConcurrency([1], async () => undefined, 0))
|
||||
.rejects.toThrow('concurrency must be a positive integer')
|
||||
})
|
||||
})
|
||||
@ -1,23 +0,0 @@
|
||||
export const WIKI_UPLOAD_TIMEOUT_MS = 5 * 60 * 1000
|
||||
|
||||
export const WIKI_UPLOAD_CONCURRENCY = 2
|
||||
|
||||
export async function processWithConcurrency<T>(
|
||||
items: readonly T[],
|
||||
worker: (item: T, index: number) => Promise<void>,
|
||||
concurrency = WIKI_UPLOAD_CONCURRENCY,
|
||||
): Promise<void> {
|
||||
if (!Number.isInteger(concurrency) || concurrency < 1) {
|
||||
throw new RangeError('concurrency must be a positive integer')
|
||||
}
|
||||
|
||||
const iterator = items.entries()
|
||||
async function runWorker() {
|
||||
for (const [index, item] of iterator) {
|
||||
await worker(item, index)
|
||||
}
|
||||
}
|
||||
|
||||
const workerCount = Math.min(concurrency, items.length)
|
||||
await Promise.all(Array.from({ length: workerCount }, () => runWorker()))
|
||||
}
|
||||
@ -887,7 +887,6 @@ const modelPromptText = computed<{ title: string; desc: string }>(() => {
|
||||
case 'unprobed':
|
||||
return { title: t('chat.prompt.unprobed.title'), desc: t('chat.prompt.unprobed.desc') }
|
||||
case 'no-models':
|
||||
default:
|
||||
return {
|
||||
title: t('chat.prompt.noModels.title', { name: p?.name || '' }),
|
||||
desc: t('chat.prompt.noModels.desc'),
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
</div>
|
||||
<div class="stage-labels">
|
||||
<div
|
||||
v-for="stage in stages"
|
||||
v-for="(stage, idx) in stages"
|
||||
:key="stage.key"
|
||||
class="stage-label-cell"
|
||||
>
|
||||
|
||||
@ -382,7 +382,6 @@ import { Download } from '@element-plus/icons-vue'
|
||||
import { useWikiStore } from '@/stores/useWikiStore'
|
||||
import { useWorkspaceStore } from '@/stores/useWorkspaceStore'
|
||||
import { wikiApi } from '@/api/index'
|
||||
import { processWithConcurrency } from '@/utils/wikiUpload'
|
||||
import JobStageBar from './JobStageBar.vue'
|
||||
import type { WikiProcessingJob } from '@/composables/useWikiJobPoller'
|
||||
|
||||
@ -832,10 +831,7 @@ const { isDragging, onDragEnter, onDragLeave, onDrop: handleDrop } = useFileDrop
|
||||
async function uploadDroppedFiles(event: DragEvent) {
|
||||
if (!event.dataTransfer?.files || !store.currentKB) return
|
||||
const kbId = store.currentKB.id
|
||||
await processWithConcurrency(
|
||||
Array.from(event.dataTransfer.files),
|
||||
file => uploadFile(kbId, file),
|
||||
)
|
||||
await Promise.all(Array.from(event.dataTransfer.files).map(f => uploadFile(kbId, f)))
|
||||
}
|
||||
|
||||
// ─── Optimistic upload items ──────────────────────────────────────────────────
|
||||
@ -890,10 +886,8 @@ async function handleFileSelect(event: Event) {
|
||||
const input = event.target as HTMLInputElement
|
||||
if (!input.files || !store.currentKB) return
|
||||
const kbId = store.currentKB.id
|
||||
await processWithConcurrency(
|
||||
Array.from(input.files),
|
||||
file => uploadFile(kbId, file),
|
||||
)
|
||||
// Upload all files concurrently
|
||||
await Promise.all(Array.from(input.files).map(f => uploadFile(kbId, f)))
|
||||
input.value = ''
|
||||
}
|
||||
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
* The catalog entry's `iconKey` must match the basename.
|
||||
*/
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
const rawSvgs = import.meta.glob('@/assets/icons/mcp/*.svg', {
|
||||
query: '?raw',
|
||||
import: 'default',
|
||||
|
||||
Loading…
Reference in New Issue
Block a user