dsh-auto-sight 0.4.6 → 0.4.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,158 +1,158 @@
1
- import assert from 'node:assert/strict'
2
-
3
- let definition
4
- globalThis.window = { __ModuleLoader__: { load(value) { definition = value } } }
5
-
6
- let hookIndex = 0
7
- let hooks = []
8
- let callback
9
- let effectQueued = false
10
- let renderCurrent
11
- let registered
12
- let mutation
13
-
14
- function rerender() {
15
- if (renderCurrent) renderCurrent()
16
- }
17
- function setAt(index, next) {
18
- hooks[index] = typeof next === 'function' ? next(hooks[index]) : next
19
- rerender()
20
- }
21
-
22
- const React = {
23
- createElement(type, props, ...children) {
24
- return { type, props: { ...(props || {}), children: children.flat(Infinity) } }
25
- },
26
- useState(initial) {
27
- const index = hookIndex++
28
- if (!(index in hooks)) hooks[index] = typeof initial === 'function' ? initial() : initial
29
- return [hooks[index], (next) => setAt(index, next)]
30
- },
31
- useCallback(fn) {
32
- callback ??= fn
33
- return callback
34
- },
35
- useEffect(fn) {
36
- if (effectQueued) return
37
- effectQueued = true
38
- queueMicrotask(fn)
39
- },
40
- }
41
-
42
- const dict = {
43
- nav: 'Auto Vision', title: 'Auto Vision', intro: '', target: 'Vision model', auto: 'Auto',
44
- hint: '', refresh: 'Refresh', loading: 'Loading', saving: 'Saving', saved: 'Saved',
45
- loadFailed: 'Load failed', saveFailed: 'Save failed', noModels: 'None', provider: 'API',
46
- }
47
-
48
- const settingsView = {
49
- ns: 'auto-vision',
50
- revision: 3,
51
- value: { visionProvider: 'p', visionModel: 'vision' },
52
- }
53
- const providerViews = [
54
- { ns: 'llm-p', revision: 1, value: { providers: { p: { models: [
55
- { id: 'vision', name: 'Vision', input: ['text', 'image'] },
56
- { id: 'text', name: 'Text', input: ['text'] },
57
- { id: 'DeepSeek-V4-Flash-Vision-Exp', name: 'DeepSeek-V4-Flash-Vision-Exp' },
58
- ] } } } },
59
- { ns: 'llm-q', revision: 2, value: { providers: { q: { models: [
60
- { id: 'vision2', name: 'Vision 2', input: ['image'] },
61
- ] } } } },
62
- ]
63
- const ctx = {
64
- effect(fn) { fn() },
65
- locale: {
66
- register() { return () => {} },
67
- bind() { return (key) => dict[key] ?? key },
68
- },
69
- slots: {
70
- inject(name, fn) { fn() },
71
- register(reg, component) { registered = { reg, component } },
72
- },
73
- remote: {
74
- settings: {
75
- async describe() {
76
- return { ok: true, value: { writable: true, namespaces: [settingsView, ...providerViews] } }
77
- },
78
- async mutate(ns, ops, revision) {
79
- mutation = { ns, ops, revision }
80
- return { ok: true, value: { ns, revision: revision + 1, value: { visionProvider: 'q', visionModel: 'vision2' } } }
81
- },
82
- },
83
- llm: {
84
- async listConfigurableProviders() {
85
- return { ok: true, value: [
86
- { provider: 'p', displayName: 'Provider P', settingsNs: 'llm-p', settingsPath: ['providers', 'p'] },
87
- { provider: 'q', displayName: 'Provider Q', settingsNs: 'llm-q', settingsPath: ['providers', 'q'] },
88
- ] }
89
- },
90
- async listProviders() {
91
- return { ok: true, value: [{ id: 'p' }, { id: 'q' }] }
92
- },
93
- async discoverModels() {
94
- // Deliberately omit q's declared vision2: the official endpoint may
95
- // not echo every configured alias, and declared models must still show.
96
- return { ok: true, value: [
97
- { id: 'vision', name: 'Vision', inputModalities: ['text', 'image'] },
98
- { id: 'text', name: 'Text', inputModalities: ['text'] },
99
- { id: 'GLM-4.6V', name: 'GLM-4.6V', inputModalities: ['text', 'image'] },
100
- { id: 'GLM-5.3', name: 'GLM-5.3', inputModalities: ['text'] },
101
- ] }
102
- },
103
- },
104
- },
105
- }
106
-
107
- await import('../client.js')
108
- const factory = definition.factory
109
- const plugin = factory((id) => {
110
- if (id === 'react') return React
111
- throw new Error(`unexpected require: ${id}`)
112
- })
113
- plugin.apply(ctx)
114
- assert.equal(registered.reg.name, 'settings.section')
115
- assert.equal(registered.reg.id, 'auto-vision')
116
- assert.equal(typeof registered.reg.label(), 'string')
117
-
118
- function render() {
119
- hookIndex = 0
120
- return registered.component({})
121
- }
122
- renderCurrent = () => { render() }
123
- render()
124
- await new Promise((resolve) => setTimeout(resolve, 10))
125
- await new Promise((resolve) => setTimeout(resolve, 10))
126
-
127
- function findAll(node, type, out = []) {
128
- if (!node || typeof node !== 'object') return out
129
- if (node.type === type) out.push(node)
130
- for (const child of node.props?.children || []) findAll(child, type, out)
131
- return out
132
- }
133
- const tree = render()
134
- const select = findAll(tree, 'select')[0]
135
- assert.ok(select, 'select rendered')
136
- assert.equal(select.props.value, 'p|vision')
137
- const optionValues = findAll(tree, 'option').map((option) => option.props.value)
138
- assert.deepEqual(optionValues, [
139
- '', 'p|vision', 'q|vision2', 'p|DeepSeek-V4-Flash-Vision-Exp',
140
- ])
141
- const checkbox = findAll(tree, 'input').find((node) => node.props.type === 'checkbox')
142
- assert.ok(checkbox, 'candidate toggle rendered')
143
- checkbox.props.onChange({ target: { checked: true } })
144
- assert.ok(findAll(render(), 'option').some((option) => option.props.value === 'p|GLM-4.6V'))
145
-
146
- await select.props.onChange({ target: { value: 'q|vision2' } })
147
- assert.deepEqual(mutation, {
148
- ns: 'auto-vision',
149
- ops: [
150
- { op: 'set', path: ['visionProvider'], value: 'q' },
151
- { op: 'set', path: ['visionModel'], value: 'vision2' },
152
- ],
153
- revision: 3,
154
- })
155
- const after = render()
156
- assert.equal(findAll(after, 'select')[0].props.value, 'q|vision2')
157
- assert.ok(findAll(after, 'span').some((node) => node.props.children.flat().join('') === 'Saved'))
158
- console.log('client smoke ok')
1
+ import assert from 'node:assert/strict'
2
+
3
+ let definition
4
+ globalThis.window = { __ModuleLoader__: { load(value) { definition = value } } }
5
+
6
+ let hookIndex = 0
7
+ let hooks = []
8
+ let callback
9
+ let effectQueued = false
10
+ let renderCurrent
11
+ let registered
12
+ let mutation
13
+
14
+ function rerender() {
15
+ if (renderCurrent) renderCurrent()
16
+ }
17
+ function setAt(index, next) {
18
+ hooks[index] = typeof next === 'function' ? next(hooks[index]) : next
19
+ rerender()
20
+ }
21
+
22
+ const React = {
23
+ createElement(type, props, ...children) {
24
+ return { type, props: { ...(props || {}), children: children.flat(Infinity) } }
25
+ },
26
+ useState(initial) {
27
+ const index = hookIndex++
28
+ if (!(index in hooks)) hooks[index] = typeof initial === 'function' ? initial() : initial
29
+ return [hooks[index], (next) => setAt(index, next)]
30
+ },
31
+ useCallback(fn) {
32
+ callback ??= fn
33
+ return callback
34
+ },
35
+ useEffect(fn) {
36
+ if (effectQueued) return
37
+ effectQueued = true
38
+ queueMicrotask(fn)
39
+ },
40
+ }
41
+
42
+ const dict = {
43
+ nav: 'Auto Vision', title: 'Auto Vision', intro: '', target: 'Vision model', auto: 'Auto',
44
+ hint: '', refresh: 'Refresh', loading: 'Loading', saving: 'Saving', saved: 'Saved',
45
+ loadFailed: 'Load failed', saveFailed: 'Save failed', noModels: 'None', provider: 'API',
46
+ }
47
+
48
+ const settingsView = {
49
+ ns: 'auto-vision',
50
+ revision: 3,
51
+ value: { visionProvider: 'p', visionModel: 'vision' },
52
+ }
53
+ const providerViews = [
54
+ { ns: 'llm-p', revision: 1, value: { providers: { p: { models: [
55
+ { id: 'vision', name: 'Vision', input: ['text', 'image'] },
56
+ { id: 'text', name: 'Text', input: ['text'] },
57
+ { id: 'DeepSeek-V4-Flash-Vision-Exp', name: 'DeepSeek-V4-Flash-Vision-Exp' },
58
+ ] } } } },
59
+ { ns: 'llm-q', revision: 2, value: { providers: { q: { models: [
60
+ { id: 'vision2', name: 'Vision 2', input: ['image'] },
61
+ ] } } } },
62
+ ]
63
+ const ctx = {
64
+ effect(fn) { fn() },
65
+ locale: {
66
+ register() { return () => {} },
67
+ bind() { return (key) => dict[key] ?? key },
68
+ },
69
+ slots: {
70
+ inject(name, fn) { fn() },
71
+ register(reg, component) { registered = { reg, component } },
72
+ },
73
+ remote: {
74
+ settings: {
75
+ async describe() {
76
+ return { ok: true, value: { writable: true, namespaces: [settingsView, ...providerViews] } }
77
+ },
78
+ async mutate(ns, ops, revision) {
79
+ mutation = { ns, ops, revision }
80
+ return { ok: true, value: { ns, revision: revision + 1, value: { visionProvider: 'q', visionModel: 'vision2' } } }
81
+ },
82
+ },
83
+ llm: {
84
+ async listConfigurableProviders() {
85
+ return { ok: true, value: [
86
+ { provider: 'p', displayName: 'Provider P', settingsNs: 'llm-p', settingsPath: ['providers', 'p'] },
87
+ { provider: 'q', displayName: 'Provider Q', settingsNs: 'llm-q', settingsPath: ['providers', 'q'] },
88
+ ] }
89
+ },
90
+ async listProviders() {
91
+ return { ok: true, value: [{ id: 'p' }, { id: 'q' }] }
92
+ },
93
+ async discoverModels() {
94
+ // Deliberately omit q's declared vision2: the official endpoint may
95
+ // not echo every configured alias, and declared models must still show.
96
+ return { ok: true, value: [
97
+ { id: 'vision', name: 'Vision', inputModalities: ['text', 'image'] },
98
+ { id: 'text', name: 'Text', inputModalities: ['text'] },
99
+ { id: 'GLM-4.6V', name: 'GLM-4.6V', inputModalities: ['text', 'image'] },
100
+ { id: 'GLM-5.3', name: 'GLM-5.3', inputModalities: ['text'] },
101
+ ] }
102
+ },
103
+ },
104
+ },
105
+ }
106
+
107
+ await import('../client.js')
108
+ const factory = definition.factory
109
+ const plugin = factory((id) => {
110
+ if (id === 'react') return React
111
+ throw new Error(`unexpected require: ${id}`)
112
+ })
113
+ plugin.apply(ctx)
114
+ assert.equal(registered.reg.name, 'settings.section')
115
+ assert.equal(registered.reg.id, 'auto-vision')
116
+ assert.equal(typeof registered.reg.label(), 'string')
117
+
118
+ function render() {
119
+ hookIndex = 0
120
+ return registered.component({})
121
+ }
122
+ renderCurrent = () => { render() }
123
+ render()
124
+ await new Promise((resolve) => setTimeout(resolve, 10))
125
+ await new Promise((resolve) => setTimeout(resolve, 10))
126
+
127
+ function findAll(node, type, out = []) {
128
+ if (!node || typeof node !== 'object') return out
129
+ if (node.type === type) out.push(node)
130
+ for (const child of node.props?.children || []) findAll(child, type, out)
131
+ return out
132
+ }
133
+ const tree = render()
134
+ const select = findAll(tree, 'select')[0]
135
+ assert.ok(select, 'select rendered')
136
+ assert.equal(select.props.value, 'p|vision')
137
+ const optionValues = findAll(tree, 'option').map((option) => option.props.value)
138
+ assert.deepEqual(optionValues, [
139
+ '', 'p|vision', 'q|vision2', 'p|DeepSeek-V4-Flash-Vision-Exp',
140
+ ])
141
+ const checkbox = findAll(tree, 'input').find((node) => node.props.type === 'checkbox')
142
+ assert.ok(checkbox, 'candidate toggle rendered')
143
+ checkbox.props.onChange({ target: { checked: true } })
144
+ assert.ok(findAll(render(), 'option').some((option) => option.props.value === 'p|GLM-4.6V'))
145
+
146
+ await select.props.onChange({ target: { value: 'q|vision2' } })
147
+ assert.deepEqual(mutation, {
148
+ ns: 'auto-vision',
149
+ ops: [
150
+ { op: 'set', path: ['visionProvider'], value: 'q' },
151
+ { op: 'set', path: ['visionModel'], value: 'vision2' },
152
+ ],
153
+ revision: 3,
154
+ })
155
+ const after = render()
156
+ assert.equal(findAll(after, 'select')[0].props.value, 'q|vision2')
157
+ assert.ok(findAll(after, 'span').some((node) => node.props.children.flat().join('') === 'Saved'))
158
+ console.log('client smoke ok')