dsh-lcx-codex 0.3.4 → 0.4.0-rc.13
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.
- package/ARCHITECTURE.md +93 -0
- package/CHANGELOG.md +139 -44
- package/README.md +208 -102
- package/README_EN.md +133 -103
- package/assets/dsh-lcx-codex-banner.jpg +0 -0
- package/cordis.patch.yml +10 -4
- package/lib/client.js +117 -194
- package/lib/compact-v2.js +124 -273
- package/lib/dsh-responses.js +299 -0
- package/lib/index.js +548 -1593
- package/lib/json-store.js +34 -0
- package/lib/legacy-v3.js +20 -0
- package/lib/native-checkpoint.js +93 -0
- package/lib/responses-replay.js +281 -0
- package/lib/route.js +222 -0
- package/lib/service-mutex.js +72 -0
- package/lib/transport.js +59 -380
- package/lib/web-run-output.js +13 -152
- package/lib/web-search-alpha.js +26 -448
- package/lib/web-search-capability.js +8 -10
- package/lib/web-search-hosted.js +22 -372
- package/lib/web-search-ref-store.js +7 -7
- package/package.json +20 -14
- package/scripts/probe-alpha.mjs +28 -76
- package/scripts/validate-dsh-schema.mjs +31 -0
- package/lib/checkpoint-store-v3.js +0 -459
- package/lib/compact.js +0 -752
- package/lib/dsh-pi-responses.js +0 -339
- package/lib/private-file.js +0 -18
- package/lib/session-lease.js +0 -70
- package/lib/web-search-store.js +0 -181
package/lib/client.js
CHANGED
|
@@ -5,244 +5,167 @@ window.__ModuleLoader__.load({
|
|
|
5
5
|
const exports = module.exports
|
|
6
6
|
const React = require('react')
|
|
7
7
|
const { createSnapshotStore } = require('@deepseek-ai/dsh-client-runtime/client')
|
|
8
|
-
|
|
9
8
|
const NAMESPACE = 'lcx-codex'
|
|
10
9
|
const DEFAULTS = {
|
|
11
10
|
enabled: false,
|
|
12
11
|
webSearch: false,
|
|
12
|
+
advancedHostedSearch: false,
|
|
13
13
|
alphaSearch: false,
|
|
14
14
|
remoteCompaction: false,
|
|
15
15
|
fallbackToBasicCompaction: true,
|
|
16
|
+
autoCompaction: true,
|
|
17
|
+
webSearchTimeoutSeconds: 240,
|
|
18
|
+
autoCompactionThresholdPercent: 90,
|
|
19
|
+
emergencyPruneThresholdPercent: 95,
|
|
16
20
|
provider: 'lcx',
|
|
17
21
|
baseURL: 'https://api.lcxbot.com/v1',
|
|
18
22
|
apiKeyEnv: 'LCX_API_KEY',
|
|
19
23
|
model: 'gpt-5.6-sol',
|
|
20
|
-
compactTransport: 'native-v2',
|
|
21
24
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
.lcx-card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;list-style:none}
|
|
25
|
-
.lcx-card-head{width:100%;display:flex;align-items:center;gap:12px;padding:14px 16px;border:0;background:transparent;color:inherit;text-align:left;font:inherit;cursor:pointer;border-radius:12px}
|
|
26
|
-
.lcx-card-head:hover{background:var(--dsw-alias-interactive-bg-hover)}
|
|
27
|
-
.lcx-card-title{display:flex;flex-direction:column;gap:4px;flex:1;min-width:0}
|
|
28
|
-
.lcx-card-title strong{font-size:15px}.lcx-card-title span,.lcx-help{font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary)}
|
|
29
|
-
.lcx-card-body{border-top:1px solid var(--dsw-alias-border-l2);padding:14px 16px 10px}
|
|
30
|
-
.lcx-row{display:flex;align-items:flex-start;gap:9px;padding:9px 0}.lcx-row input[type=checkbox]{margin-top:3px;accent-color:var(--dsw-alias-brand-primary)}
|
|
31
|
-
.lcx-row label{font-size:13px;color:var(--dsw-alias-label-primary);line-height:19px}.lcx-row small{display:block;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:17px}
|
|
32
|
-
.lcx-fields{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:8px}.lcx-field{display:flex;flex-direction:column;gap:5px}.lcx-field label{font-size:12px;color:var(--dsw-alias-label-secondary)}
|
|
33
|
-
.lcx-input{width:100%;box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);border-radius:8px;padding:7px 9px;font:inherit;font-size:12px}.lcx-input:disabled{color:var(--dsw-alias-label-tertiary)}
|
|
34
|
-
.lcx-footer{display:flex;align-items:center;justify-content:flex-end;gap:8px;border-top:1px solid var(--dsw-alias-border-l2);padding:12px 0 4px}.lcx-footer button{border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:6px 14px;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:13px;cursor:pointer}.lcx-footer button.primary{background:var(--dsw-alias-state-business-primary);border-color:transparent;color:var(--dsw-alias-label-primary-inverted)}.lcx-footer button:disabled{opacity:.5;cursor:default}.lcx-error{flex:1;color:var(--dsw-alias-state-error-primary);font-size:12px}
|
|
35
|
-
@media(max-width:640px){.lcx-fields{grid-template-columns:1fr}}
|
|
36
|
-
`
|
|
37
|
-
if (typeof document !== 'undefined' && document.querySelector('style[data-plugin-css="dsh-lcx-codex"]') === null) {
|
|
25
|
+
const css = `.lcx-card{border:1px solid var(--dsw-alias-border-l2);border-radius:12px;list-style:none}.lcx-head{width:100%;display:flex;justify-content:space-between;padding:14px 16px;border:0;background:transparent;color:inherit}.lcx-body{border-top:1px solid var(--dsw-alias-border-l2);padding:12px 16px}.lcx-row{display:flex;gap:9px;padding:8px 0}.lcx-row small,.lcx-help,.lcx-field small{display:block;font-size:12px;line-height:17px;color:var(--dsw-alias-label-tertiary)}.lcx-fields{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:8px}.lcx-field{display:flex;flex-direction:column;gap:4px}.lcx-input{border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:7px;background:transparent;color:inherit}.lcx-foot{display:flex;justify-content:flex-end;gap:8px;margin-top:10px}.lcx-foot button{padding:6px 12px;border-radius:8px;border:1px solid var(--dsw-alias-border-l2);background:transparent;color:inherit}`
|
|
26
|
+
if (typeof document !== 'undefined' && !document.querySelector('style[data-plugin-css="dsh-lcx-codex"]')) {
|
|
38
27
|
const tag = document.createElement('style')
|
|
39
|
-
tag.dataset.plugin = 'dsh-lcx-codex'
|
|
40
28
|
tag.dataset.pluginCss = 'dsh-lcx-codex'
|
|
41
29
|
tag.textContent = css
|
|
42
30
|
document.head.appendChild(tag)
|
|
43
31
|
}
|
|
44
|
-
|
|
45
32
|
const copy = {
|
|
46
33
|
zh: {
|
|
47
34
|
title: 'Responses / Codex 能力',
|
|
48
|
-
|
|
49
|
-
enabled: '
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
35
|
+
desc: '复用现有 GPT Responses 路由;普通搜索走 DSH web_search,Native V2 压缩采用 90% 主动压缩 + 95% 紧急保护。',
|
|
36
|
+
enabled: '启用插件',
|
|
37
|
+
web: '使用 GPT Hosted Search 作为 DSH web_search 后端',
|
|
38
|
+
webHelp: '不会新增第二个普通搜索工具;普通 web_search 自动跟随当前 Agent 的 GPT Responses 模型。',
|
|
39
|
+
searchTimeout: 'web_search 超时(秒)',
|
|
40
|
+
searchTimeoutHelp: '只调整 DSH 工具外层超时,不改变模型可见 schema。默认 240 秒;Hosted Search 较慢时避免 60 秒提前中断。',
|
|
41
|
+
advanced: '启用高级 Hosted 工具(websearch_gpt_advanced)',
|
|
42
|
+
advancedHelp: '只在需要域名过滤、位置、search context、图片等原生 Hosted 参数时使用;默认关闭以保持工具 schema 稳定。',
|
|
43
|
+
alpha: '启用 Alpha command(websearch_alpha)',
|
|
44
|
+
alphaHelp: '仅 capability probe 对当前 endpoint/provider/model/schema 验证通过后才真正注册。',
|
|
45
|
+
compact: '启用 Native V2 远程压缩',
|
|
46
|
+
compactHelp: 'DSH 仍负责范围、事务和 /compact;Native state 保存在 DSH session log。',
|
|
47
|
+
autoCompact: '启用 Native-first 自动压缩',
|
|
48
|
+
autoCompactHelp: '到主动阈值前不让 DSH 的 80% tool-result prune 改写历史;到主动阈值后优先 Native V2。',
|
|
49
|
+
autoThreshold: 'Native 自动压缩阈值(%)',
|
|
50
|
+
autoThresholdHelp: '建议 90%。允许 85–95%;262k 窗口在 90% 时仍约剩 26k tokens。',
|
|
51
|
+
emergencyThreshold: 'DSH 紧急 prune 阈值(%)',
|
|
52
|
+
emergencyThresholdHelp: '建议 95%。达到这里才允许 DSH tool-result-pruner 先救场;必须高于 Native 阈值。',
|
|
53
|
+
fallback: 'Native 失败后回退 DSH basic compaction',
|
|
54
|
+
fallbackHelp: 'Remote-first:只有 Native 请求失败才调用 basic summary,不并行双跑。',
|
|
55
|
+
endpoint: '回退 Responses 地址',
|
|
56
|
+
model: '回退 GPT 模型',
|
|
57
|
+
save: '保存', discard: '放弃修改', saving: '保存中…',
|
|
69
58
|
},
|
|
70
59
|
en: {
|
|
71
60
|
title: 'Responses / Codex capabilities',
|
|
72
|
-
|
|
73
|
-
enabled: 'Enable
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
61
|
+
desc: 'Reuse existing GPT Responses routes; Native V2 uses a 90% proactive threshold with 95% emergency protection.',
|
|
62
|
+
enabled: 'Enable plugin',
|
|
63
|
+
web: 'Use GPT Hosted Search as DSH web_search backend',
|
|
64
|
+
webHelp: 'Keeps DSH web_search as the single ordinary search tool and follows the active Agent GPT Responses model.',
|
|
65
|
+
searchTimeout: 'web_search timeout (seconds)',
|
|
66
|
+
searchTimeoutHelp: 'Changes only the DSH tool deadline, not the model-visible schema. Default 240s to avoid premature 60s timeouts.',
|
|
67
|
+
advanced: 'Enable advanced Hosted tool (websearch_gpt_advanced)',
|
|
68
|
+
advancedHelp: 'Only for native Hosted controls such as domains, location, context size and image search; off by default for stable tool schemas.',
|
|
69
|
+
alpha: 'Enable Alpha command (websearch_alpha)',
|
|
70
|
+
alphaHelp: 'Registered only after a matching capability probe.',
|
|
71
|
+
compact: 'Enable Native V2 remote compaction',
|
|
72
|
+
compactHelp: 'DSH still owns range/transactions and /compact; native state is persisted in the DSH session log.',
|
|
73
|
+
autoCompact: 'Enable Native-first automatic compaction',
|
|
74
|
+
autoCompactHelp: 'Suppresses the stock 80% tool-result prune before the proactive threshold, then prefers Native V2.',
|
|
75
|
+
autoThreshold: 'Native auto-compaction threshold (%)',
|
|
76
|
+
autoThresholdHelp: 'Default 90%. Allowed 85–95%.',
|
|
77
|
+
emergencyThreshold: 'DSH emergency prune threshold (%)',
|
|
78
|
+
emergencyThresholdHelp: 'Default 95%. DSH tool-result pruning is allowed only in this emergency zone; must exceed the Native threshold.',
|
|
79
|
+
fallback: 'Fall back to DSH basic compaction on Native failure',
|
|
80
|
+
fallbackHelp: 'Remote-first: basic summary runs only after Native failure, never in parallel.',
|
|
81
|
+
endpoint: 'Fallback Responses endpoint', model: 'Fallback GPT model',
|
|
82
|
+
save: 'Save', discard: 'Discard', saving: 'Saving…',
|
|
93
83
|
},
|
|
94
84
|
}
|
|
95
|
-
|
|
96
|
-
function
|
|
97
|
-
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function valueFrom(snapshot) {
|
|
101
|
-
return { ...DEFAULTS, ...(snapshot.value ?? {}) }
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
class SettingsController {
|
|
85
|
+
const lang = () => String(globalThis.navigator?.language ?? '').toLowerCase().startsWith('zh') ? 'zh' : 'en'
|
|
86
|
+
function valueFrom(snapshot) { return { ...DEFAULTS, ...(snapshot.value ?? {}) } }
|
|
87
|
+
class Controller {
|
|
105
88
|
constructor(scope) {
|
|
106
|
-
this.scope = scope
|
|
107
|
-
this.draft = null
|
|
108
|
-
this.dirty = false
|
|
109
|
-
this.saving = false
|
|
110
|
-
this.failed = false
|
|
111
|
-
this.listeners = new Set()
|
|
89
|
+
this.scope = scope; this.draft = null; this.dirty = false; this.saving = false
|
|
112
90
|
this.store = createSnapshotStore(this.projection())
|
|
113
|
-
this.stop = scope.subscribe(() => {
|
|
114
|
-
if (!this.dirty) this.draft = null
|
|
115
|
-
this.publish()
|
|
116
|
-
})
|
|
91
|
+
this.stop = scope.subscribe(() => { if (!this.dirty) this.draft = null; this.publish() })
|
|
117
92
|
}
|
|
118
|
-
|
|
119
93
|
snapshot() { return this.scope.getSnapshot() }
|
|
120
94
|
value() { return valueFrom(this.snapshot()) }
|
|
121
95
|
draftValue() { return { ...this.value(), ...(this.draft ?? {}) } }
|
|
122
96
|
field(name) { return this.draftValue()[name] }
|
|
123
|
-
overridden(name) { return Object.prototype.hasOwnProperty.call(this.snapshot().user ?? {}, name) }
|
|
124
97
|
projection() {
|
|
125
|
-
const
|
|
98
|
+
const s = this.snapshot()
|
|
99
|
+
const bools = ['enabled','webSearch','advancedHostedSearch','alphaSearch','remoteCompaction','fallbackToBasicCompaction','autoCompaction']
|
|
126
100
|
return {
|
|
127
|
-
available:
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
webSearch: { value: Boolean(this.field('webSearch')), overridden: this.overridden('webSearch') },
|
|
134
|
-
alphaSearch: { value: Boolean(this.field('alphaSearch')), overridden: this.overridden('alphaSearch') },
|
|
135
|
-
remoteCompaction: { value: Boolean(this.field('remoteCompaction')), overridden: this.overridden('remoteCompaction') },
|
|
136
|
-
fallbackToBasicCompaction: { value: this.field('fallbackToBasicCompaction') !== false, overridden: this.overridden('fallbackToBasicCompaction') },
|
|
137
|
-
baseURL: String(this.field('baseURL') ?? ''),
|
|
138
|
-
model: String(this.field('model') ?? ''),
|
|
139
|
-
hint: language() === 'zh' ? copy.zh.hint : copy.en.hint,
|
|
101
|
+
available: s.status === 'ready', writable: s.writable, dirty: this.dirty, saving: this.saving,
|
|
102
|
+
...Object.fromEntries(bools.map((f) => [f, { value: f === 'fallbackToBasicCompaction' || f === 'autoCompaction' ? this.field(f) !== false : Boolean(this.field(f)) }])),
|
|
103
|
+
webSearchTimeoutSeconds: Number(this.field('webSearchTimeoutSeconds') ?? 240),
|
|
104
|
+
autoCompactionThresholdPercent: Number(this.field('autoCompactionThresholdPercent') ?? 90),
|
|
105
|
+
emergencyPruneThresholdPercent: Number(this.field('emergencyPruneThresholdPercent') ?? 95),
|
|
106
|
+
baseURL: String(this.field('baseURL') ?? ''), model: String(this.field('model') ?? ''),
|
|
140
107
|
}
|
|
141
108
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
publish()
|
|
145
|
-
this.store.set(this.projection())
|
|
146
|
-
for (const listener of this.listeners) listener()
|
|
147
|
-
}
|
|
148
|
-
edit(field, value) {
|
|
149
|
-
this.draft = { ...(this.draft ?? this.value()), [field]: value }
|
|
150
|
-
this.dirty = true
|
|
151
|
-
this.failed = false
|
|
152
|
-
this.publish()
|
|
153
|
-
}
|
|
154
|
-
discard() {
|
|
155
|
-
this.draft = null
|
|
156
|
-
this.dirty = false
|
|
157
|
-
this.failed = false
|
|
158
|
-
this.publish()
|
|
159
|
-
}
|
|
109
|
+
publish() { this.store.set(this.projection()) }
|
|
110
|
+
edit(field, value) { this.draft = { ...(this.draft ?? this.value()), [field]: value }; this.dirty = true; this.publish() }
|
|
111
|
+
discard() { this.draft = null; this.dirty = false; this.publish() }
|
|
160
112
|
async save() {
|
|
161
113
|
if (!this.dirty || this.saving || !this.snapshot().writable) return
|
|
162
|
-
const next = this.draftValue()
|
|
163
|
-
const previous = this.value()
|
|
164
|
-
const changes = Object.keys(next).filter((field) => next[field] !== previous[field])
|
|
165
|
-
this.saving = true
|
|
166
|
-
this.failed = false
|
|
167
|
-
this.publish()
|
|
114
|
+
const next = this.draftValue(), prev = this.value(); this.saving = true; this.publish()
|
|
168
115
|
try {
|
|
169
|
-
for (const
|
|
170
|
-
this.draft = null
|
|
171
|
-
|
|
172
|
-
} catch {
|
|
173
|
-
this.failed = true
|
|
174
|
-
} finally {
|
|
175
|
-
this.saving = false
|
|
176
|
-
this.publish()
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
inject() { return { hooks: { lcxCard: this.bind() }, ...this.actions() } }
|
|
180
|
-
actions() {
|
|
181
|
-
return {
|
|
182
|
-
edit: (field, value) => this.edit(field, value),
|
|
183
|
-
save: () => { void this.save() },
|
|
184
|
-
discard: () => this.discard(),
|
|
185
|
-
}
|
|
116
|
+
for (const f of Object.keys(next)) if (next[f] !== prev[f]) await this.scope.set(f, next[f])
|
|
117
|
+
this.draft = null; this.dirty = false
|
|
118
|
+
} finally { this.saving = false; this.publish() }
|
|
186
119
|
}
|
|
120
|
+
inject() { return { hooks: { lcxCard: this.store }, edit: (f,v) => this.edit(f,v), save: () => void this.save(), discard: () => this.discard() } }
|
|
121
|
+
}
|
|
122
|
+
function Row({ id, label, help, checked, disabled, onChange }) {
|
|
123
|
+
return React.createElement('div', { className:'lcx-row' },
|
|
124
|
+
React.createElement('input', { id, type:'checkbox', checked, disabled, onChange:e=>onChange(e.target.checked) }),
|
|
125
|
+
React.createElement('label', { htmlFor:id }, label, React.createElement('small', null, help)))
|
|
187
126
|
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
React.createElement('input', {
|
|
192
|
-
|
|
193
|
-
)
|
|
127
|
+
function Field({ label, help, value, disabled, type='text', min, max, step, onChange }) {
|
|
128
|
+
return React.createElement('div', { className:'lcx-field' },
|
|
129
|
+
React.createElement('label', null, label),
|
|
130
|
+
React.createElement('input', { className:'lcx-input', type, value, disabled, min, max, step, onChange }),
|
|
131
|
+
help ? React.createElement('small', null, help) : null)
|
|
194
132
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
const
|
|
199
|
-
const
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
React.createElement(
|
|
205
|
-
|
|
206
|
-
React.createElement('
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
React.createElement(
|
|
210
|
-
React.createElement(
|
|
211
|
-
React.createElement(
|
|
212
|
-
React.createElement(
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
React.createElement('div', { className:
|
|
220
|
-
|
|
221
|
-
React.createElement('button', {
|
|
222
|
-
React.createElement('button', { className: 'primary', type: 'button', disabled: !state.dirty || disabled, onClick: props.save }, state.saving ? t.saving : t.save),
|
|
223
|
-
),
|
|
224
|
-
) : null,
|
|
225
|
-
)
|
|
133
|
+
function Card(props) {
|
|
134
|
+
const t = copy[lang()], s = props.useLcxCard(x=>x), [open,setOpen] = React.useState(false)
|
|
135
|
+
if (!s.available) return null
|
|
136
|
+
const disabled = !s.writable || s.saving
|
|
137
|
+
const numeric = (field) => (e) => props.edit(field, Number(e.target.value))
|
|
138
|
+
return React.createElement('li', { className:'lcx-card' },
|
|
139
|
+
React.createElement('button', { className:'lcx-head', type:'button', onClick:()=>setOpen(!open) }, React.createElement('strong',null,t.title), React.createElement('span',null,open?'⌃':'⌄')),
|
|
140
|
+
open ? React.createElement('div', { className:'lcx-body' },
|
|
141
|
+
React.createElement('p', { className:'lcx-help' }, t.desc),
|
|
142
|
+
React.createElement(Row, { id:'lcx-enabled', label:t.enabled, checked:s.enabled.value, disabled, onChange:v=>props.edit('enabled',v) }),
|
|
143
|
+
React.createElement(Row, { id:'lcx-web', label:t.web, help:t.webHelp, checked:s.webSearch.value, disabled:disabled||!s.enabled.value, onChange:v=>props.edit('webSearch',v) }),
|
|
144
|
+
React.createElement('div', { className:'lcx-fields' },
|
|
145
|
+
React.createElement(Field, { label:t.searchTimeout, help:t.searchTimeoutHelp, type:'number', min:30, max:600, step:30, value:s.webSearchTimeoutSeconds, disabled:disabled||!s.enabled.value||!s.webSearch.value, onChange:numeric('webSearchTimeoutSeconds') })),
|
|
146
|
+
React.createElement(Row, { id:'lcx-advanced', label:t.advanced, help:t.advancedHelp, checked:s.advancedHostedSearch.value, disabled:disabled||!s.enabled.value||!s.webSearch.value, onChange:v=>props.edit('advancedHostedSearch',v) }),
|
|
147
|
+
React.createElement(Row, { id:'lcx-alpha', label:t.alpha, help:t.alphaHelp, checked:s.alphaSearch.value, disabled:disabled||!s.enabled.value, onChange:v=>props.edit('alphaSearch',v) }),
|
|
148
|
+
React.createElement(Row, { id:'lcx-compact', label:t.compact, help:t.compactHelp, checked:s.remoteCompaction.value, disabled:disabled||!s.enabled.value, onChange:v=>props.edit('remoteCompaction',v) }),
|
|
149
|
+
React.createElement(Row, { id:'lcx-auto-compact', label:t.autoCompact, help:t.autoCompactHelp, checked:s.autoCompaction.value, disabled:disabled||!s.enabled.value||!s.remoteCompaction.value, onChange:v=>props.edit('autoCompaction',v) }),
|
|
150
|
+
React.createElement('div', { className:'lcx-fields' },
|
|
151
|
+
React.createElement(Field, { label:t.autoThreshold, help:t.autoThresholdHelp, type:'number', min:85, max:95, step:1, value:s.autoCompactionThresholdPercent, disabled:disabled||!s.enabled.value||!s.remoteCompaction.value||!s.autoCompaction.value, onChange:numeric('autoCompactionThresholdPercent') }),
|
|
152
|
+
React.createElement(Field, { label:t.emergencyThreshold, help:t.emergencyThresholdHelp, type:'number', min:90, max:99, step:1, value:s.emergencyPruneThresholdPercent, disabled:disabled||!s.enabled.value||!s.remoteCompaction.value||!s.autoCompaction.value, onChange:numeric('emergencyPruneThresholdPercent') })),
|
|
153
|
+
React.createElement(Row, { id:'lcx-fallback', label:t.fallback, help:t.fallbackHelp, checked:s.fallbackToBasicCompaction.value, disabled:disabled||!s.enabled.value||!s.remoteCompaction.value, onChange:v=>props.edit('fallbackToBasicCompaction',v) }),
|
|
154
|
+
React.createElement('div', { className:'lcx-fields' },
|
|
155
|
+
React.createElement(Field, { label:t.endpoint, value:s.baseURL, disabled, onChange:e=>props.edit('baseURL',e.target.value) }),
|
|
156
|
+
React.createElement(Field, { label:t.model, value:s.model, disabled, onChange:e=>props.edit('model',e.target.value) })),
|
|
157
|
+
React.createElement('div', { className:'lcx-foot' },
|
|
158
|
+
React.createElement('button', { disabled:!s.dirty||disabled, onClick:props.discard }, t.discard),
|
|
159
|
+
React.createElement('button', { disabled:!s.dirty||disabled, onClick:props.save }, s.saving?t.saving:t.save))) : null)
|
|
226
160
|
}
|
|
227
|
-
|
|
228
|
-
const inject = ['slots', 'locale', 'settingsScope']
|
|
229
|
-
|
|
161
|
+
const inject = ['slots','locale','settingsScope']
|
|
230
162
|
function apply(ctx) {
|
|
231
|
-
const slots = ctx.slots ?? ctx.get('slots')
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
slots.inject('settings.plugin.item', () => slots.register({
|
|
237
|
-
name: 'settings.plugin.item',
|
|
238
|
-
key: NAMESPACE,
|
|
239
|
-
inject: () => controller.inject(),
|
|
240
|
-
}, LcxCard))
|
|
241
|
-
ctx.effect(() => () => controller.stop(), 'lcx-codex: settings card')
|
|
163
|
+
const slots = ctx.slots ?? ctx.get('slots'), svc = ctx.settingsScope ?? ctx.get('settingsScope')
|
|
164
|
+
if (!slots || !svc) return
|
|
165
|
+
const controller = new Controller(svc.bind({ namespace:NAMESPACE }))
|
|
166
|
+
slots.inject('settings.plugin.item', () => slots.register({ name:'settings.plugin.item', key:NAMESPACE, inject:()=>controller.inject() }, Card))
|
|
167
|
+
ctx.effect(() => () => controller.stop(), 'lcx-codex settings card')
|
|
242
168
|
}
|
|
243
|
-
|
|
244
|
-
exports.apply = apply
|
|
245
|
-
exports.inject = inject
|
|
246
|
-
return module.exports
|
|
169
|
+
exports.apply = apply; exports.inject = inject; return module.exports
|
|
247
170
|
},
|
|
248
171
|
})
|