mirror of
https://github.com/mudler/LocalAI.git
synced 2026-11-05 03:53:11 -05:00
Add the add-on runtime to LocalAI: manifests, the host operation broker, admin gating by account role, the add-on UI bundle builder and the SDK for add-on pages. Move the navigation to Chat, Models, Add-ons and Settings, with pinned add-ons in the sidebar and an Add-ons drawer. Ship the first-party add-ons (voice, face, fine-tuning, quantization) as packages for linux/amd64, linux/arm64 and darwin/arm64. Intel macOS (darwin/amd64) is enabled in the platform files. Squashed from the review branch. The tree is unchanged; the pre-squash history is kept on a local backup branch. Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
66 lines
3.1 KiB
JavaScript
66 lines
3.1 KiB
JavaScript
import test from 'node:test'
|
|
import assert from 'node:assert/strict'
|
|
import { planInsert, insertSteps, idSteps, chunk, toggle, setAll, allSelected, MAX_INSERT_ROWS, MAX_ROW_IDS } from '../src/lib/batch.js'
|
|
import { describeError } from '../src/lib/errors.js'
|
|
|
|
const columns = [
|
|
{ name: 'Item', type: 'text', required: true },
|
|
{ name: 'Qty', type: 'integer', required: false },
|
|
{ name: 'Note', type: 'text', required: false },
|
|
{ name: 'Paid', type: 'boolean', required: false },
|
|
]
|
|
const cell = (text, isNull = false) => ({ text, isNull })
|
|
|
|
test('batch: typed rows become wire rows and an untouched optional column is left to its default', () => {
|
|
const plan = planInsert([
|
|
{ Item: cell('pen'), Qty: cell('3'), Note: cell(''), Paid: cell('') },
|
|
{ Item: cell('ink'), Qty: cell('', true), Note: cell('', true), Paid: cell('true') },
|
|
], columns)
|
|
assert.deepEqual(plan.errors, {})
|
|
assert.deepEqual(plan.rows, [{ Item: 'pen', Qty: 3 }, { Item: 'ink', Qty: null, Note: null, Paid: true }])
|
|
})
|
|
|
|
test('batch: every cell error is named by row and column and nothing is sent', () => {
|
|
const plan = planInsert([{ Item: cell(''), Qty: cell('x') }, { Item: cell('ok'), Qty: cell('1.5') }], columns)
|
|
assert.deepEqual(plan.errors, { '0:Item': 'required', '0:Qty': 'integer', '1:Qty': 'integer' })
|
|
})
|
|
|
|
test('batch: steps stay inside the add-on bounds', () => {
|
|
const rows = Array.from({ length: 250 }, (_, i) => i)
|
|
assert.deepEqual(insertSteps(rows).map(s => s.length), [100, 100, 50])
|
|
const ids = Array.from({ length: 2500 }, (_, i) => i + 1)
|
|
assert.deepEqual(idSteps(ids).map(s => s.length), [1000, 1000, 500])
|
|
assert.equal(MAX_INSERT_ROWS, 100)
|
|
assert.equal(MAX_ROW_IDS, 1000)
|
|
assert.deepEqual(chunk([], 3), [])
|
|
})
|
|
|
|
test('batch: the selection toggles by row identifier and survives paging', () => {
|
|
let s = new Set()
|
|
s = toggle(s, 4)
|
|
s = toggle(s, 9)
|
|
s = toggle(s, 4)
|
|
assert.deepEqual([...s], [9])
|
|
s = setAll(s, [1, 2, 3], true)
|
|
assert.equal(allSelected(s, [1, 2, 3]), true)
|
|
assert.equal(allSelected(s, [1, 2, 3, 4]), false)
|
|
assert.equal(allSelected(s, []), false)
|
|
s = setAll(s, [1, 2, 3], false)
|
|
assert.deepEqual([...s], [9])
|
|
})
|
|
|
|
test('errors: each answer of the host gets its own words and recovery', () => {
|
|
assert.equal(describeError({ kind: 'stale' }).kind, 'stale')
|
|
assert.equal(describeError({ kind: 'denied', type: 'addon_error' }).kind, 'denied')
|
|
assert.equal(describeError({ kind: 'denied', type: 'quota_reached' }).kind, 'quota')
|
|
assert.equal(describeError({ kind: 'denied', type: 'outcome_blocked' }).kind, 'blocked')
|
|
assert.equal(describeError({ kind: 'unavailable' }).kind, 'unavailable')
|
|
const unknown = describeError({ kind: 'unknown_outcome', operationId: 'op-3' })
|
|
assert.deepEqual([unknown.kind, unknown.retry, unknown.operationId], ['unknown', true, 'op-3'])
|
|
assert.equal(describeError({ kind: 'sharing_disabled' }).kind, 'sharing')
|
|
assert.equal(describeError({ code: 'withdrawn' }).kind, 'withdrawn')
|
|
assert.equal(describeError({ name: 'AbortError' }).kind, 'withdrawn')
|
|
assert.equal(describeError(null).kind, 'error')
|
|
assert.equal(describeError({ kind: 'invalid' }).retry, false)
|
|
})
|