micro-models-agent 2.16.1 → 2.17.1
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/CHANGELOG.md +28 -0
- package/dist/assets/app.js +1 -314
- package/dist/assets/hljs.js +5 -1244
- package/dist/assets/index.html +11 -0
- package/dist/assets/js/api.js +1 -28
- package/dist/assets/js/core/menus.js +1 -0
- package/dist/assets/js/core/store/feed.js +1 -0
- package/dist/assets/js/core/store/index.js +1 -0
- package/dist/assets/js/core/store/session.js +1 -0
- package/dist/assets/js/core/store/settings.js +1 -0
- package/dist/assets/js/core/store/tabs.js +1 -0
- package/dist/assets/js/dialog.js +1 -105
- package/dist/assets/js/dom.js +1 -178
- package/dist/assets/js/feed/core.js +1 -0
- package/dist/assets/js/feed/history.js +1 -0
- package/dist/assets/js/feed/plan.js +1 -0
- package/dist/assets/js/feed/question.js +3 -0
- package/dist/assets/js/feed/sidebar.js +1 -0
- package/dist/assets/js/feed/stream.js +1 -0
- package/dist/assets/js/feed/turn.js +5 -0
- package/dist/assets/js/feed.js +1 -1250
- package/dist/assets/js/format.js +2 -122
- package/dist/assets/js/i18n.js +1 -46
- package/dist/assets/js/rail.js +1 -114
- package/dist/assets/js/session/cmdk.js +1 -0
- package/dist/assets/js/session/composer.js +1 -0
- package/dist/assets/js/session/sessions-menu.js +1 -0
- package/dist/assets/js/session/tabs.js +1 -0
- package/dist/assets/js/settings/controls.js +1 -0
- package/dist/assets/js/settings/editors.js +1 -0
- package/dist/assets/js/settings/form.js +1 -0
- package/dist/assets/js/settings/modal.js +1 -0
- package/dist/assets/js/settings/panels.js +1 -0
- package/dist/assets/js/settings/providers.js +1 -0
- package/dist/assets/js/settings/search.js +1 -0
- package/dist/assets/js/settings/subdialog.js +1 -0
- package/dist/assets/js/settings/write.js +1 -0
- package/dist/assets/js/settings.js +1 -1914
- package/dist/assets/js/sidebar/core.js +1 -0
- package/dist/assets/js/sidebar/lsp.js +2 -0
- package/dist/assets/js/sidebar/map.js +1 -0
- package/dist/assets/js/sidebar/state.js +1 -0
- package/dist/assets/js/sidebar/trace.js +5 -0
- package/dist/assets/js/sidebar.js +1 -705
- package/dist/assets/js/store.js +1 -82
- package/dist/assets/js/subdialog.js +1 -0
- package/dist/assets/md.js +1 -291
- package/dist/assets/setup.js +3 -816
- package/dist/assets/smd.js +29 -1665
- package/dist/assets/styles.css +1 -1598
- package/dist/certification/certifications.json +1 -494
- package/dist/i18n/en.json +1 -1851
- package/dist/i18n/ru.json +1 -1854
- package/dist/main.js +815 -55797
- package/dist/modules/browser/bridge-server.mjs +2 -252
- package/package.json +10 -5
- package/dist/assets/js/settings-controls.js +0 -452
- package/dist/assets/js/tabs.js +0 -867
- package/dist/cli/cache-line.js +0 -31
- package/dist/cli/command-suggest.js +0 -39
- package/dist/cli/commands.js +0 -781
- package/dist/cli/completer.js +0 -268
- package/dist/cli/index.js +0 -3
- package/dist/cli/json-payload.js +0 -32
- package/dist/cli/main.js +0 -346
- package/dist/cli/onboarding-commands.js +0 -126
- package/dist/cli/plugin-commands.js +0 -38
- package/dist/cli/relaunch.js +0 -40
- package/dist/cli/repl-commands-lsp.js +0 -75
- package/dist/cli/repl-commands-skills.js +0 -105
- package/dist/cli/repl-commands.js +0 -1218
- package/dist/cli/repl.js +0 -1238
- package/dist/cli/run-result.js +0 -38
- package/dist/cli/security-commands.js +0 -177
- package/dist/cli/setup-order.js +0 -6
- package/dist/cli/setup-prompt.js +0 -50
- package/dist/cli/setup.js +0 -161
- package/dist/cli/web-command.js +0 -98
- package/dist/config/budget.js +0 -48
- package/dist/config/config.js +0 -345
- package/dist/config/defaults.js +0 -197
- package/dist/config/domains.js +0 -135
- package/dist/config/env.js +0 -46
- package/dist/config/experts.js +0 -17
- package/dist/config/index.js +0 -5
- package/dist/config/paths.js +0 -56
- package/dist/config/redact.js +0 -44
- package/dist/config/registry-extra.js +0 -334
- package/dist/config/registry.js +0 -584
- package/dist/config/security.js +0 -212
- package/dist/config/timeouts.js +0 -74
- package/dist/config/types.js +0 -1
- package/dist/config/utils.js +0 -57
- package/dist/core/agent/artifact-progress.js +0 -59
- package/dist/core/agent/artifact-resolve.js +0 -79
- package/dist/core/agent/audit-gate.js +0 -53
- package/dist/core/agent/compaction.js +0 -89
- package/dist/core/agent/constants.js +0 -90
- package/dist/core/agent/context-log.js +0 -454
- package/dist/core/agent/context-renderer.js +0 -45
- package/dist/core/agent/critic-gate.js +0 -132
- package/dist/core/agent/hallucination-gate.js +0 -197
- package/dist/core/agent/loop-state.js +0 -68
- package/dist/core/agent/prefix-monitor.js +0 -101
- package/dist/core/agent/reasoning-resolver.js +0 -65
- package/dist/core/agent/token-tracker.js +0 -99
- package/dist/core/agent/tool-batch.js +0 -312
- package/dist/core/agent/tool-images.js +0 -18
- package/dist/core/agent/tool-output.js +0 -116
- package/dist/core/agent/tool-pairing.js +0 -60
- package/dist/core/agent-moe.js +0 -248
- package/dist/core/agent.js +0 -1299
- package/dist/core/bootstrap/agent-phase.js +0 -66
- package/dist/core/bootstrap/config-phase.js +0 -86
- package/dist/core/bootstrap/modules-phase.js +0 -269
- package/dist/core/bootstrap/provider-phase.js +0 -183
- package/dist/core/bootstrap/session-phase.js +0 -204
- package/dist/core/bootstrap/state.js +0 -94
- package/dist/core/bootstrap/workspace-phase.js +0 -115
- package/dist/core/bootstrap.js +0 -112
- package/dist/core/crash-handler.js +0 -62
- package/dist/core/environment.js +0 -224
- package/dist/core/host-plan.js +0 -43
- package/dist/core/host.js +0 -23
- package/dist/core/index.js +0 -3
- package/dist/core/prompt-builder.js +0 -95
- package/dist/core/prompt-overflow.js +0 -306
- package/dist/core/session-logger.js +0 -375
- package/dist/core/system-prompt.js +0 -117
- package/dist/core/types.js +0 -1
- package/dist/core/version.js +0 -28
- package/dist/core/web-host.js +0 -34
- package/dist/core/workspace.js +0 -80
- package/dist/i18n/index.js +0 -80
- package/dist/index.js +0 -30
- package/dist/llm/cache-usage.js +0 -76
- package/dist/llm/image-utils.js +0 -138
- package/dist/llm/index.js +0 -4
- package/dist/llm/llm-errors.js +0 -50
- package/dist/llm/model-loader.js +0 -86
- package/dist/llm/models-dev.js +0 -121
- package/dist/llm/openai-compat.js +0 -756
- package/dist/llm/orchestrator.js +0 -294
- package/dist/llm/provider-budget.js +0 -68
- package/dist/llm/provider-context.js +0 -233
- package/dist/llm/provider.js +0 -9
- package/dist/llm/response.js +0 -44
- package/dist/llm/stream-state.js +0 -26
- package/dist/llm/token-counter.js +0 -83
- package/dist/llm/types.js +0 -1
- package/dist/logger/app-logger.js +0 -212
- package/dist/logger/file-log.js +0 -160
- package/dist/logger/index.js +0 -2
- package/dist/migration/backup.js +0 -56
- package/dist/migration/detect.js +0 -61
- package/dist/migration/index.js +0 -3
- package/dist/modules/artifacts/store.js +0 -62
- package/dist/modules/browser/actions.js +0 -79
- package/dist/modules/browser/bridge-client.js +0 -203
- package/dist/modules/browser/bridge-path.js +0 -10
- package/dist/modules/browser/console-buffer.js +0 -37
- package/dist/modules/browser/cookie-store.js +0 -29
- package/dist/modules/browser/driver-types.js +0 -1
- package/dist/modules/browser/driver.js +0 -186
- package/dist/modules/browser/index.js +0 -9
- package/dist/modules/browser/module.js +0 -30
- package/dist/modules/browser/session.js +0 -322
- package/dist/modules/browser/snapshot.js +0 -154
- package/dist/modules/browser/types.js +0 -13
- package/dist/modules/certification/cli.js +0 -264
- package/dist/modules/certification/fact-checker.js +0 -90
- package/dist/modules/certification/loader.js +0 -127
- package/dist/modules/certification/manifest.js +0 -231
- package/dist/modules/certification/runner.js +0 -233
- package/dist/modules/certification/scenarios.js +0 -586
- package/dist/modules/certification/syntax-scenarios.js +0 -50
- package/dist/modules/certification/types.js +0 -1
- package/dist/modules/context/chunk-query.js +0 -122
- package/dist/modules/context/fact-extractor.js +0 -170
- package/dist/modules/context/history.js +0 -15
- package/dist/modules/context/index.js +0 -2
- package/dist/modules/context/manager.js +0 -482
- package/dist/modules/critic/client.js +0 -176
- package/dist/modules/critic/evidence.js +0 -81
- package/dist/modules/critic/provider.js +0 -45
- package/dist/modules/critic/tools.js +0 -78
- package/dist/modules/critic/types.js +0 -1
- package/dist/modules/execution/audit-runners.js +0 -206
- package/dist/modules/execution/auditor.js +0 -222
- package/dist/modules/execution/execution-plugin.js +0 -478
- package/dist/modules/execution/index.js +0 -8
- package/dist/modules/execution/input-from.js +0 -70
- package/dist/modules/execution/module.js +0 -891
- package/dist/modules/execution/moe-executor.js +0 -443
- package/dist/modules/execution/plan-actions.js +0 -642
- package/dist/modules/execution/plan-checks.js +0 -35
- package/dist/modules/execution/plan-coverage.js +0 -71
- package/dist/modules/execution/plan-persister.js +0 -46
- package/dist/modules/execution/plan-steps.js +0 -31
- package/dist/modules/execution/plan-store.js +0 -274
- package/dist/modules/execution/plan-tool.js +0 -249
- package/dist/modules/execution/plan-validator.js +0 -197
- package/dist/modules/execution/planner.js +0 -103
- package/dist/modules/execution/stuck-detector.js +0 -834
- package/dist/modules/execution/tracker.js +0 -92
- package/dist/modules/execution/transient-error.js +0 -30
- package/dist/modules/execution/types.js +0 -1
- package/dist/modules/execution/verifier.js +0 -343
- package/dist/modules/execution/windows-commands.js +0 -52
- package/dist/modules/hallucination/artifact-claim.js +0 -93
- package/dist/modules/hallucination/confidence.js +0 -81
- package/dist/modules/hallucination/consistency.js +0 -37
- package/dist/modules/hallucination/detector.js +0 -57
- package/dist/modules/hallucination/factual.js +0 -205
- package/dist/modules/hallucination/index.js +0 -6
- package/dist/modules/hallucination/js-identifiers.js +0 -261
- package/dist/modules/hallucination/llm-judge.js +0 -116
- package/dist/modules/hallucination/success-claim.js +0 -59
- package/dist/modules/index.js +0 -5
- package/dist/modules/indexer/cache.js +0 -88
- package/dist/modules/indexer/index.js +0 -4
- package/dist/modules/indexer/map-command.js +0 -33
- package/dist/modules/indexer/map-select.js +0 -87
- package/dist/modules/indexer/module.js +0 -293
- package/dist/modules/indexer/project-profile.js +0 -184
- package/dist/modules/indexer/symbols.js +0 -189
- package/dist/modules/indexer/walker.js +0 -285
- package/dist/modules/lsp/check-tool.js +0 -61
- package/dist/modules/lsp/client.js +0 -406
- package/dist/modules/lsp/command.js +0 -53
- package/dist/modules/lsp/config.js +0 -189
- package/dist/modules/lsp/index.js +0 -4
- package/dist/modules/lsp/module.js +0 -295
- package/dist/modules/lsp/probe.js +0 -86
- package/dist/modules/lsp/project-root.js +0 -69
- package/dist/modules/lsp/startup-check.js +0 -154
- package/dist/modules/lsp/types.js +0 -1
- package/dist/modules/mcp/client.js +0 -445
- package/dist/modules/mcp/index.js +0 -4
- package/dist/modules/mcp/module.js +0 -295
- package/dist/modules/mcp/registry.js +0 -20
- package/dist/modules/memory/index.js +0 -2
- package/dist/modules/memory/module.js +0 -101
- package/dist/modules/memory/search.js +0 -45
- package/dist/modules/memory/store.js +0 -107
- package/dist/modules/onboarding/init.js +0 -47
- package/dist/modules/onboarding/meet.js +0 -30
- package/dist/modules/onboarding/mode.js +0 -30
- package/dist/modules/onboarding/prompts.js +0 -43
- package/dist/modules/pipelines/engine.js +0 -70
- package/dist/modules/pipelines/index.js +0 -4
- package/dist/modules/pipelines/parser.js +0 -59
- package/dist/modules/pipelines/template.js +0 -18
- package/dist/modules/plugins/builtin/lint-on-write.js +0 -377
- package/dist/modules/plugins/builtin/notify.js +0 -11
- package/dist/modules/plugins/index.js +0 -2
- package/dist/modules/plugins/loader.js +0 -85
- package/dist/modules/plugins/manager.js +0 -244
- package/dist/modules/plugins/types.js +0 -1
- package/dist/modules/pricing/index.js +0 -70
- package/dist/modules/pricing/prices.js +0 -147
- package/dist/modules/processes/detect.js +0 -34
- package/dist/modules/processes/index.js +0 -4
- package/dist/modules/processes/kill-tree.js +0 -52
- package/dist/modules/processes/registry.js +0 -294
- package/dist/modules/processes/runner.js +0 -23
- package/dist/modules/providers/cache.js +0 -23
- package/dist/modules/providers/capabilities.js +0 -28
- package/dist/modules/providers/create.js +0 -21
- package/dist/modules/providers/factory.js +0 -28
- package/dist/modules/providers/fallback.js +0 -81
- package/dist/modules/providers/health.js +0 -47
- package/dist/modules/providers/index.js +0 -6
- package/dist/modules/providers/manager.js +0 -207
- package/dist/modules/providers/naming.js +0 -15
- package/dist/modules/providers/preflight.js +0 -71
- package/dist/modules/providers/presets.js +0 -232
- package/dist/modules/providers/registry.js +0 -27
- package/dist/modules/providers/types.js +0 -1
- package/dist/modules/reasoning/policy.js +0 -42
- package/dist/modules/reasoning/probe.js +0 -116
- package/dist/modules/registry.js +0 -48
- package/dist/modules/security/audit-log.js +0 -119
- package/dist/modules/security/audit-notifier.js +0 -267
- package/dist/modules/security/command-validator.js +0 -272
- package/dist/modules/security/content-scanner.js +0 -53
- package/dist/modules/security/data-sanitizer.js +0 -82
- package/dist/modules/security/encryption.js +0 -216
- package/dist/modules/security/index.js +0 -15
- package/dist/modules/security/network-validator.js +0 -236
- package/dist/modules/security/path-validator.js +0 -261
- package/dist/modules/security/protected-paths.js +0 -73
- package/dist/modules/security/rate-limiter.js +0 -98
- package/dist/modules/security/security-policies.js +0 -499
- package/dist/modules/security/session-encryption.js +0 -182
- package/dist/modules/security/session-isolation.js +0 -75
- package/dist/modules/session/auto-name.js +0 -63
- package/dist/modules/session/export.js +0 -98
- package/dist/modules/session/index.js +0 -4
- package/dist/modules/session/manager.js +0 -234
- package/dist/modules/session/module.js +0 -33
- package/dist/modules/session/store.js +0 -295
- package/dist/modules/session/types.js +0 -1
- package/dist/modules/setup/answers.js +0 -35
- package/dist/modules/setup/apply.js +0 -79
- package/dist/modules/setup/discovery.js +0 -72
- package/dist/modules/skills/index.js +0 -3
- package/dist/modules/skills/loader.js +0 -86
- package/dist/modules/skills/matcher.js +0 -27
- package/dist/modules/skills/module.js +0 -141
- package/dist/modules/types.js +0 -1
- package/dist/modules/updater/changelog-reader.js +0 -93
- package/dist/modules/updater/checker.js +0 -101
- package/dist/modules/updater/dev-detect.js +0 -18
- package/dist/modules/updater/index.js +0 -4
- package/dist/modules/updater/module.js +0 -129
- package/dist/modules/user-profile/compressor.js +0 -18
- package/dist/modules/user-profile/index.js +0 -2
- package/dist/modules/user-profile/profile.js +0 -77
- package/dist/modules/webui/answer-api.js +0 -29
- package/dist/modules/webui/assets.js +0 -50
- package/dist/modules/webui/body.js +0 -21
- package/dist/modules/webui/commands-settings.js +0 -209
- package/dist/modules/webui/commands-shared.js +0 -60
- package/dist/modules/webui/commands.js +0 -174
- package/dist/modules/webui/config-api.js +0 -134
- package/dist/modules/webui/file-api.js +0 -202
- package/dist/modules/webui/forward.js +0 -159
- package/dist/modules/webui/history-api.js +0 -112
- package/dist/modules/webui/host-state.js +0 -60
- package/dist/modules/webui/i18n-api.js +0 -9
- package/dist/modules/webui/limits.js +0 -6
- package/dist/modules/webui/log-forward.js +0 -20
- package/dist/modules/webui/memory-commands.js +0 -64
- package/dist/modules/webui/model-cache.js +0 -18
- package/dist/modules/webui/module.js +0 -148
- package/dist/modules/webui/persist.js +0 -24
- package/dist/modules/webui/prompt-io.js +0 -97
- package/dist/modules/webui/providers-api.js +0 -337
- package/dist/modules/webui/providers-view.js +0 -56
- package/dist/modules/webui/reasoning-view.js +0 -15
- package/dist/modules/webui/run-agent.js +0 -81
- package/dist/modules/webui/server.js +0 -284
- package/dist/modules/webui/sessions-api.js +0 -178
- package/dist/modules/webui/settings-api.js +0 -561
- package/dist/modules/webui/setup-api.js +0 -201
- package/dist/modules/webui/state.js +0 -74
- package/dist/modules/webui/util.js +0 -261
- package/dist/output/bus.js +0 -37
- package/dist/output/channel.js +0 -285
- package/dist/output/format.js +0 -15
- package/dist/output/index.js +0 -8
- package/dist/output/json-sink.js +0 -24
- package/dist/output/machine.js +0 -9
- package/dist/output/session-sink.js +0 -27
- package/dist/output/types.js +0 -1
- package/dist/tools/approve.js +0 -41
- package/dist/tools/attach-image.js +0 -102
- package/dist/tools/auto-fixer.js +0 -180
- package/dist/tools/auto-tags.js +0 -83
- package/dist/tools/bash.js +0 -649
- package/dist/tools/browser.js +0 -160
- package/dist/tools/chunk-query.js +0 -112
- package/dist/tools/create-dir.js +0 -60
- package/dist/tools/delete-file.js +0 -67
- package/dist/tools/download-file.js +0 -142
- package/dist/tools/edit-file.js +0 -136
- package/dist/tools/enable-tools.js +0 -59
- package/dist/tools/executor.js +0 -304
- package/dist/tools/file-info.js +0 -49
- package/dist/tools/filter-tools.js +0 -17
- package/dist/tools/glob-tool.js +0 -37
- package/dist/tools/grep-tool.js +0 -142
- package/dist/tools/hidden-tools-block.js +0 -37
- package/dist/tools/index.js +0 -88
- package/dist/tools/list-dir.js +0 -53
- package/dist/tools/load-skill.js +0 -51
- package/dist/tools/mcp-call.js +0 -80
- package/dist/tools/meet-done.js +0 -14
- package/dist/tools/move-file.js +0 -94
- package/dist/tools/path-utils.js +0 -108
- package/dist/tools/pipeline-run.js +0 -167
- package/dist/tools/preview.js +0 -2
- package/dist/tools/process-ids.js +0 -31
- package/dist/tools/process-kill.js +0 -33
- package/dist/tools/process-list.js +0 -38
- package/dist/tools/process-log.js +0 -49
- package/dist/tools/process-wait.js +0 -63
- package/dist/tools/prompt-io.js +0 -29
- package/dist/tools/question.js +0 -288
- package/dist/tools/read-file.js +0 -200
- package/dist/tools/recall.js +0 -124
- package/dist/tools/registry.js +0 -48
- package/dist/tools/remember.js +0 -72
- package/dist/tools/scope-check.js +0 -32
- package/dist/tools/scope-request.js +0 -96
- package/dist/tools/search-history.js +0 -88
- package/dist/tools/session-info.js +0 -46
- package/dist/tools/set-thinking.js +0 -75
- package/dist/tools/subagent.js +0 -257
- package/dist/tools/syntax-validator.js +0 -379
- package/dist/tools/types.js +0 -1
- package/dist/tools/user-input.js +0 -134
- package/dist/tools/web-browse.js +0 -93
- package/dist/tools/web-fetch.js +0 -108
- package/dist/tools/web-search.js +0 -107
- package/dist/tools/write-file.js +0 -128
- package/dist/ui/action-log.js +0 -13
- package/dist/ui/box.js +0 -78
- package/dist/ui/colors.js +0 -6
- package/dist/ui/diff.js +0 -189
- package/dist/ui/index.js +0 -7
- package/dist/ui/line-editor.js +0 -1083
- package/dist/ui/line-math.js +0 -98
- package/dist/ui/md-formatter.js +0 -322
- package/dist/ui/output.js +0 -19
- package/dist/ui/plan-view.js +0 -109
- package/dist/ui/renderer.js +0 -589
- package/dist/ui/spinner.js +0 -91
- package/dist/ui/table.js +0 -142
- package/dist/ui/theme.js +0 -143
- package/dist/utils/child-run.js +0 -20
- package/dist/utils/error.js +0 -4
- package/dist/utils/index.js +0 -6
- package/dist/utils/retry.js +0 -17
- package/dist/utils/sleep.js +0 -23
- package/dist/utils/truncate.js +0 -9
package/dist/assets/js/format.js
CHANGED
|
@@ -1,122 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { t } from "./i18n.js";
|
|
4
|
-
import { S } from "./store.js";
|
|
5
|
-
|
|
6
|
-
export const CATEGORIES = {
|
|
7
|
-
recon: [
|
|
8
|
-
"read_file", "list_dir", "glob", "grep", "file_info", "project_map",
|
|
9
|
-
"chunk_query", "web_search", "web_fetch", "history", "recall",
|
|
10
|
-
"process_list", "process_log",
|
|
11
|
-
],
|
|
12
|
-
mutate: [
|
|
13
|
-
"write_file", "edit_file", "create_dir", "delete_file", "move_file",
|
|
14
|
-
"attach_image",
|
|
15
|
-
],
|
|
16
|
-
execute: [
|
|
17
|
-
"bash", "process_kill", "pipeline_run", "browser", "download_file",
|
|
18
|
-
"subagent", "mcp_call",
|
|
19
|
-
],
|
|
20
|
-
meta: [
|
|
21
|
-
"plan", "plan_step", "todo", "verify", "lsp_check", "enable_tools", "set_thinking",
|
|
22
|
-
"load_skill", "remember",
|
|
23
|
-
],
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export const FILE_TOOLS = ["read_file", "write_file", "edit_file", "list_dir", "delete_file", "move_file", "file_info"];
|
|
27
|
-
// Tools whose `path` argument points at a readable file the viewer can open.
|
|
28
|
-
// `list_dir` is a directory, `delete_file`/`move_file` leave the file gone.
|
|
29
|
-
export const OPENABLE_TOOLS = ["read_file", "write_file", "edit_file", "file_info"];
|
|
30
|
-
export const IMAGE_TOOLS = ["attach_image", "browser"];
|
|
31
|
-
export const LINK_TOOLS = ["web_fetch", "download_file"];
|
|
32
|
-
|
|
33
|
-
export function categoryOf(name) {
|
|
34
|
-
for (const cat of Object.keys(CATEGORIES)) {
|
|
35
|
-
if (CATEGORIES[cat].indexOf(name) !== -1) return cat;
|
|
36
|
-
}
|
|
37
|
-
return "meta";
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Friendly, localized tool label from `tool.friendly.*`; humanize unknown names.
|
|
41
|
-
export function labelOf(name) {
|
|
42
|
-
const key = "tool.friendly." + name;
|
|
43
|
-
const s = t(key);
|
|
44
|
-
if (s !== key) return s;
|
|
45
|
-
const human = String(name).replace(/_/g, " ");
|
|
46
|
-
return human.charAt(0).toUpperCase() + human.slice(1);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function argText(args) {
|
|
50
|
-
if (!args || typeof args !== "object") return "";
|
|
51
|
-
const keys = ["path", "file", "dir", "command", "query", "url", "pattern", "name", "id", "text", "prompt"];
|
|
52
|
-
for (const key of keys) {
|
|
53
|
-
if (typeof args[key] === "string" && args[key]) return args[key];
|
|
54
|
-
}
|
|
55
|
-
const keys2 = Object.keys(args);
|
|
56
|
-
if (!keys2.length) return "";
|
|
57
|
-
const val = args[keys2[0]];
|
|
58
|
-
if (typeof val === "string") return val;
|
|
59
|
-
if (typeof val === "number" || typeof val === "boolean") return String(val);
|
|
60
|
-
try {
|
|
61
|
-
const json = JSON.stringify(args);
|
|
62
|
-
return json === "{}" ? "" : json.slice(0, 120);
|
|
63
|
-
} catch (err) {
|
|
64
|
-
return "";
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export function formatMs(ms) {
|
|
69
|
-
if (typeof ms !== "number" || !isFinite(ms)) return "";
|
|
70
|
-
return ms >= 1000 ? (ms / 1000).toFixed(1) + "s" : Math.round(ms) + "ms";
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Effective chat verbosity, mirroring `resolveVerbosity` in src/ui/theme.ts:
|
|
74
|
-
// explicit `ui.verbosity` wins; the legacy boolean maps to verbose/quiet. A
|
|
75
|
-
// fresh config defaults to `quiet`, so the web feed matches the terminal.
|
|
76
|
-
export function verbosity() {
|
|
77
|
-
const ui = (S.state.config && S.state.config.ui) || {};
|
|
78
|
-
if (ui.verbosity) return ui.verbosity;
|
|
79
|
-
return ui.verbose ? "verbose" : "quiet";
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// First non-empty line of a tool result — the calm one-line cause shown in
|
|
83
|
-
// quiet mode instead of the whole model-facing body.
|
|
84
|
-
export function firstOutputLine(text) {
|
|
85
|
-
if (typeof text !== "string" || !text) return "";
|
|
86
|
-
for (const raw of text.split("\n")) {
|
|
87
|
-
const line = raw.trim();
|
|
88
|
-
if (line) return line.length > 200 ? line.slice(0, 197) + "…" : line;
|
|
89
|
-
}
|
|
90
|
-
return "";
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Case-insensitive substring match for dropdown filters (model / session
|
|
94
|
-
// search). Empty query matches everything; non-strings stringify safely.
|
|
95
|
-
export function matchesQuery(haystack, q) {
|
|
96
|
-
const needle = String(q == null ? "" : q).trim().toLowerCase();
|
|
97
|
-
if (!needle) return true;
|
|
98
|
-
return String(haystack == null ? "" : haystack).toLowerCase().indexOf(needle) !== -1;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export function relTime(ts) {
|
|
102
|
-
if (!ts) return "";
|
|
103
|
-
const diff = Date.now() - new Date(ts).getTime();
|
|
104
|
-
if (!isFinite(diff) || diff < 0) return "";
|
|
105
|
-
const min = Math.floor(diff / 60000);
|
|
106
|
-
if (min < 1) return "now";
|
|
107
|
-
if (min < 60) return min + "m";
|
|
108
|
-
const hrs = Math.floor(min / 60);
|
|
109
|
-
if (hrs < 24) return hrs + "h";
|
|
110
|
-
const days = Math.floor(hrs / 24);
|
|
111
|
-
return days + "d";
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export function fmtTokens(n) {
|
|
115
|
-
return n >= 1000 ? (n / 1000).toFixed(1) + "K" : String(n);
|
|
116
|
-
}
|
|
117
|
-
// Compact context-window label for selectors and the model panel.
|
|
118
|
-
export function contextLabel() {
|
|
119
|
-
const n = (S.state.config && S.state.config.contextWindow) || 0;
|
|
120
|
-
return n ? Math.round(n / 1024) + "K" : "—";
|
|
121
|
-
}
|
|
122
|
-
|
|
1
|
+
import{t as c}from"./i18n.js";import{settings as f}from"./store.js";export const CATEGORIES={recon:["read_file","list_dir","glob","grep","file_info","project_map","chunk_query","web_search","web_fetch","history","recall","process_list","process_log"],mutate:["write_file","edit_file","create_dir","delete_file","move_file","attach_image"],execute:["bash","process_kill","pipeline_run","browser","download_file","subagent","mcp_call"],meta:["plan","plan_step","todo","verify","lsp_check","enable_tools","set_thinking","load_skill","remember"]},FILE_TOOLS=["read_file","write_file","edit_file","list_dir","delete_file","move_file","file_info"],OPENABLE_TOOLS=["read_file","write_file","edit_file","file_info"],IMAGE_TOOLS=["attach_image","browser"],LINK_TOOLS=["web_fetch","download_file"];export function categoryOf(e){for(const t of Object.keys(CATEGORIES))if(CATEGORIES[t].indexOf(e)!==-1)return t;return"meta"}export function labelOf(e){const t="tool.friendly."+e,r=c(t);if(r!==t)return r;const o=String(e).replace(/_/g," ");return o.charAt(0).toUpperCase()+o.slice(1)}export function argText(e){if(!e||typeof e!="object")return"";const t=e,r=["path","file","dir","command","query","url","pattern","name","id","text","prompt"];for(const i of r)if(typeof t[i]=="string"&&t[i])return t[i];const o=Object.keys(t);if(!o.length)return"";const n=t[o[0]];if(typeof n=="string")return n;if(typeof n=="number"||typeof n=="boolean")return String(n);try{const i=JSON.stringify(e);return i==="{}"?"":i.slice(0,120)}catch{return""}}export function formatMs(e){return typeof e!="number"||!isFinite(e)?"":e>=1e3?(e/1e3).toFixed(1)+"s":Math.round(e)+"ms"}export function verbosity(){const e=f.config&&f.config.ui||{};return e.verbosity?e.verbosity:e.verbose?"verbose":"quiet"}export function firstOutputLine(e){if(typeof e!="string"||!e)return"";for(const t of e.split(`
|
|
2
|
+
`)){const r=t.trim();if(r)return r.length>200?r.slice(0,197)+"…":r}return""}export function matchesQuery(e,t){const r=String(t??"").trim().toLowerCase();return r?String(e??"").toLowerCase().indexOf(r)!==-1:!0}export function relTime(e){if(!e)return"";const t=Date.now()-new Date(e).getTime();if(!isFinite(t)||t<0)return"";const r=Math.floor(t/6e4);if(r<1)return"now";if(r<60)return r+"m";const o=Math.floor(r/60);return o<24?o+"h":Math.floor(o/24)+"d"}export function fmtTokens(e){return e>=1e3?(e/1e3).toFixed(1)+"K":String(e)}export function contextLabel(){const e=f.config&&f.config.contextWindow||0;return e?Math.round(e/1024)+"K":"—"}
|
package/dist/assets/js/i18n.js
CHANGED
|
@@ -1,46 +1 @@
|
|
|
1
|
-
|
|
2
|
-
// (`GET /api/i18n`) so the chrome follows `config.locale` without a reload.
|
|
3
|
-
|
|
4
|
-
import { api } from "./api.js";
|
|
5
|
-
|
|
6
|
-
export const I18N = { locale: "en", dicts: {} };
|
|
7
|
-
|
|
8
|
-
export function t(key, params) {
|
|
9
|
-
const dict = I18N.dicts[I18N.locale] || I18N.dicts.en || {};
|
|
10
|
-
const en = I18N.dicts.en || {};
|
|
11
|
-
let template = dict[key];
|
|
12
|
-
if (template === undefined) template = en[key];
|
|
13
|
-
if (template === undefined) return key;
|
|
14
|
-
if (params) {
|
|
15
|
-
Object.keys(params).forEach((k) => {
|
|
16
|
-
template = template.split("{" + k + "}").join(String(params[k]));
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
return template;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// Plural form for a `{count}` template: uses `baseKey_one|_few|_many`
|
|
23
|
-
// (RU one/few/many; EN one/many) and falls back to `baseKey` if absent.
|
|
24
|
-
export function pluralCount(baseKey, n) {
|
|
25
|
-
let form;
|
|
26
|
-
if (I18N.locale === "ru") {
|
|
27
|
-
const m10 = n % 10;
|
|
28
|
-
const m100 = n % 100;
|
|
29
|
-
if (m10 === 1 && m100 !== 11) form = "one";
|
|
30
|
-
else if (m10 >= 2 && m10 <= 4 && (m100 < 10 || m100 >= 20)) form = "few";
|
|
31
|
-
else form = "many";
|
|
32
|
-
} else {
|
|
33
|
-
form = n === 1 ? "one" : "many";
|
|
34
|
-
}
|
|
35
|
-
const key = baseKey + "_" + form;
|
|
36
|
-
const s = t(key, { count: n });
|
|
37
|
-
return s === key ? t(baseKey, { count: n }) : s;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export async function loadI18n() {
|
|
41
|
-
const r = await api("/api/i18n");
|
|
42
|
-
if (r.ok && r.data) {
|
|
43
|
-
I18N.locale = r.data.locale || "en";
|
|
44
|
-
I18N.dicts = r.data.dicts || {};
|
|
45
|
-
}
|
|
46
|
-
}
|
|
1
|
+
import{api as a}from"./api.js";export const I18N={locale:"en",dicts:{}};export function t(n,e){const c=I18N.dicts[I18N.locale]||I18N.dicts.en||{},l=I18N.dicts.en||{};let o=c[n];return o===void 0&&(o=l[n]),o===void 0?n:(e&&Object.keys(e).forEach(i=>{o=o.split("{"+i+"}").join(String(e[i]))}),o)}export function pluralCount(n,e){let c;if(I18N.locale==="ru"){const i=e%10,s=e%100;i===1&&s!==11?c="one":i>=2&&i<=4&&(s<10||s>=20)?c="few":c="many"}else c=e===1?"one":"many";const l=n+"_"+c,o=t(l,{count:e});return o===l?t(n,{count:e}):o}export async function loadI18n(){const n=await a("/api/i18n");n.ok&&n.data&&(I18N.locale=n.data.locale||"en",I18N.dicts=n.data.dicts||{})}
|
package/dist/assets/js/rail.js
CHANGED
|
@@ -1,114 +1 @@
|
|
|
1
|
-
|
|
2
|
-
//
|
|
3
|
-
// The in-feed `.busy` line clears on the first `text` event; the rail lives
|
|
4
|
-
// until the turn ends and shows only what we actually know: phase, elapsed,
|
|
5
|
-
// plan progress when a plan exists (MoE), tool/event counters. Without a plan
|
|
6
|
-
// the rail is an indeterminate scanner — no invented percentages.
|
|
7
|
-
// Layouts: off | line (default) | meta | full — see docs/specs/2026-09-27-activity-rail-design.md.
|
|
8
|
-
|
|
9
|
-
import { t, pluralCount } from "./i18n.js";
|
|
10
|
-
import { labelOf } from "./format.js";
|
|
11
|
-
|
|
12
|
-
const LAYOUTS = ["off", "line", "meta", "full"];
|
|
13
|
-
|
|
14
|
-
let root = null, trackEl = null, fillEl = null;
|
|
15
|
-
let labEl = null, timeEl = null, stepsEl = null, escEl = null;
|
|
16
|
-
let toolsEl = null, eventsEl = null, lastEl = null;
|
|
17
|
-
let layout = "line";
|
|
18
|
-
let busy = false, startedAt = 0;
|
|
19
|
-
let tools = 0, events = 0, lastTool = "";
|
|
20
|
-
let sawText = false, pendingTool = false;
|
|
21
|
-
let plan = null;
|
|
22
|
-
let timer = null;
|
|
23
|
-
|
|
24
|
-
function render() {
|
|
25
|
-
if (!root) return;
|
|
26
|
-
root.hidden = layout === "off" || !busy;
|
|
27
|
-
if (root.hidden) return;
|
|
28
|
-
const phase = pendingTool ? "tool" : sawText ? "composing" : "thinking";
|
|
29
|
-
root.classList.toggle("phase-tool", phase === "tool");
|
|
30
|
-
root.classList.toggle("phase-compose", phase === "composing");
|
|
31
|
-
labEl.textContent = "✦ " + (phase === "tool" ? t("web.rail.working")
|
|
32
|
-
: phase === "composing" ? t("web.rail.composing") : t("web.action.thinking"));
|
|
33
|
-
timeEl.textContent = ((Date.now() - startedAt) / 1000).toFixed(1) + "s";
|
|
34
|
-
const steps = plan && Array.isArray(plan.steps) ? plan.steps : [];
|
|
35
|
-
if (steps.length > 0) {
|
|
36
|
-
const done = steps.filter((s) => s && s.status === "done").length;
|
|
37
|
-
trackEl.dataset.mode = "plan";
|
|
38
|
-
fillEl.style.setProperty("--prog", String((done / steps.length) * 100));
|
|
39
|
-
stepsEl.textContent = t("web.rail.step_of", { cur: Math.min(done + 1, steps.length), total: steps.length });
|
|
40
|
-
} else {
|
|
41
|
-
trackEl.dataset.mode = "scan";
|
|
42
|
-
stepsEl.textContent = t("web.rail.no_plan");
|
|
43
|
-
}
|
|
44
|
-
toolsEl.textContent = pluralCount("web.rail.tools", tools);
|
|
45
|
-
eventsEl.textContent = pluralCount("web.rail.events", events);
|
|
46
|
-
lastEl.textContent = lastTool ? t("web.rail.last") + " " + lastTool : t("web.rail.none");
|
|
47
|
-
escEl.textContent = t("web.input.esc");
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function flash() {
|
|
51
|
-
if (!trackEl || !busy) return;
|
|
52
|
-
trackEl.classList.remove("flash");
|
|
53
|
-
void trackEl.offsetWidth;
|
|
54
|
-
trackEl.classList.add("flash");
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export function initRail(cfgLayout) {
|
|
58
|
-
root = document.getElementById("railWrap");
|
|
59
|
-
if (!root) return;
|
|
60
|
-
trackEl = root.querySelector(".rl-track");
|
|
61
|
-
fillEl = root.querySelector(".rl-fill");
|
|
62
|
-
labEl = root.querySelector(".lab");
|
|
63
|
-
timeEl = root.querySelector(".time");
|
|
64
|
-
stepsEl = root.querySelector(".st");
|
|
65
|
-
escEl = root.querySelector(".right");
|
|
66
|
-
toolsEl = root.querySelector(".tools");
|
|
67
|
-
eventsEl = root.querySelector(".events");
|
|
68
|
-
lastEl = root.querySelector(".last");
|
|
69
|
-
setLayout(cfgLayout);
|
|
70
|
-
if (!timer) timer = setInterval(render, 250);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export function setLayout(next) {
|
|
74
|
-
layout = LAYOUTS.includes(next) ? next : "line";
|
|
75
|
-
if (!root) return;
|
|
76
|
-
root.classList.remove("l-line", "l-meta", "l-full");
|
|
77
|
-
root.classList.add("l-" + layout);
|
|
78
|
-
const inpMeta = document.querySelector(".inp-meta");
|
|
79
|
-
const inputArea = document.querySelector(".input-area");
|
|
80
|
-
if (layout === "meta" && inpMeta && root.parentElement !== inpMeta) {
|
|
81
|
-
inpMeta.prepend(root);
|
|
82
|
-
} else if (layout !== "meta" && inputArea && root.parentElement !== inputArea) {
|
|
83
|
-
const selectors = inputArea.querySelector(".selectors");
|
|
84
|
-
inputArea.insertBefore(root, selectors || inputArea.firstChild);
|
|
85
|
-
}
|
|
86
|
-
render();
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export function setBusy(on) {
|
|
90
|
-
const next = !!on;
|
|
91
|
-
if (next && !busy) {
|
|
92
|
-
startedAt = Date.now();
|
|
93
|
-
tools = 0; events = 0; lastTool = "";
|
|
94
|
-
sawText = false; pendingTool = false; plan = null;
|
|
95
|
-
}
|
|
96
|
-
busy = next;
|
|
97
|
-
render();
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export function setPlan(p) {
|
|
101
|
-
plan = p && Array.isArray(p.steps) && p.steps.length > 0 ? p : null;
|
|
102
|
-
render();
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
export function railEvent(kind, name) {
|
|
106
|
-
events += 1;
|
|
107
|
-
if (kind === "tool_start") { pendingTool = true; lastTool = labelOf(name); }
|
|
108
|
-
else if (kind === "tool_end") { pendingTool = false; tools += 1; lastTool = labelOf(name); }
|
|
109
|
-
else if (kind === "text") sawText = true;
|
|
110
|
-
flash();
|
|
111
|
-
render();
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export function applyRailI18n() { render(); }
|
|
1
|
+
import{t as o,pluralCount as L}from"./i18n.js";import{labelOf as A}from"./format.js";const _=["off","line","meta","full"];let t=null,r=null,y=null,f=null,h=null,g=null,p=null,x=null,E=null,S=null,b=null,i="line",d=!1,k=0,w=0,q=0,a="",C=!1,m=!1,u=null,T=null,v=0;function B(e){if(!(!f||e===v)){v=e,f.textContent="";for(let l=1;l<e;l++){const n=document.createElement("i");n.style.left=(l/e*100).toFixed(3)+"%",f.appendChild(n)}}}function s(){if(!t||!h||!g||!r||!y||!p||!E||!S||!b||!x||(t.hidden=i==="off"||!d,t.hidden))return;const e=m?"tool":C?"composing":"thinking";t.classList.toggle("phase-tool",e==="tool"),t.classList.toggle("phase-compose",e==="composing"),h.textContent="✦ "+(e==="tool"?o("web.rail.working"):e==="composing"?o("web.rail.composing"):o("web.action.thinking")),g.textContent=((Date.now()-k)/1e3).toFixed(1)+"s";const l=u&&Array.isArray(u.steps)?u.steps:[];if(l.length>0){const n=l.filter(c=>c&&c.status==="done").length;r.dataset.mode="plan",B(l.length),y.style.setProperty("--prog",String(n/l.length*100)),p.textContent=o("web.rail.step_of",{cur:Math.min(n+1,l.length),total:l.length})}else r.dataset.mode="scan",p.textContent=o("web.rail.no_plan");E.textContent=L("web.rail.tools",w),S.textContent=L("web.rail.events",q),b.textContent=a?o("web.rail.last")+" "+a:o("web.rail.none"),x.textContent=o("web.input.esc")}function F(){!r||!d||(r.classList.remove("flash"),r.offsetWidth,r.classList.add("flash"))}export function initRail(e){t=document.getElementById("railWrap"),t&&(r=t.querySelector(".rl-track"),y=t.querySelector(".rl-fill"),f=t.querySelector(".rl-notches"),v=0,h=t.querySelector(".lab"),g=t.querySelector(".time"),p=t.querySelector(".st"),x=t.querySelector(".right"),E=t.querySelector(".tools"),S=t.querySelector(".events"),b=t.querySelector(".last"),setLayout(e),T||(T=setInterval(s,250)))}export function setLayout(e){if(i=typeof e=="string"&&_.includes(e)?e:"line",!t)return;t.classList.remove("l-line","l-meta","l-full"),t.classList.add("l-"+i);const l=document.querySelector(".inp-meta"),n=document.querySelector(".input-area");if(i==="meta"&&l&&t.parentElement!==l)l.prepend(t);else if(i!=="meta"&&n&&t.parentElement!==n){const c=n.querySelector(".selectors");n.insertBefore(t,c||n.firstChild)}s()}export function setBusy(e){const l=!!e;l&&!d&&(k=Date.now(),w=0,q=0,a="",C=!1,m=!1,u=null),d=l,s()}export function setPlan(e){u=e&&Array.isArray(e.steps)&&e.steps.length>0?e:null,s()}export function railEvent(e,l){q+=1,e==="tool_start"?(m=!0,a=A(l)):e==="tool_end"?(m=!1,w+=1,a=A(l)):e==="text"&&(C=!0),F(),s()}export function applyRailI18n(){s()}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{el as c,inp as o}from"../dom.js";import{t as C}from"../i18n.js";import{api as v}from"../api.js";const e=c("div","cmdk");e.id="cmdk-list",e.hidden=!0,e.setAttribute("role","listbox");const m=document.querySelector(".input-area");m&&m.appendChild(e);let l=[],s=[],n=0,p=()=>{};export function initCmdk(t){t&&typeof t.autogrow=="function"&&(p=t.autogrow)}export async function loadCommands(){const t=await v("/api/commands");t.ok&&t.data&&Array.isArray(t.data.commands)&&(l=t.data.commands)}function h(){const t=o.value;return t.startsWith("/")&&!/\s/.test(t)?t:null}export function isCmdkOpen(){return!e.hidden}export function closeCmdk(){e.hidden||(e.hidden=!0,e.textContent="",s=[],n=0,o.setAttribute("aria-expanded","false"),o.removeAttribute("aria-activedescendant"))}function f(){Array.from(e.children).forEach((r,i)=>r.classList.toggle("on",i===n));const t=e.children[n];t&&o.setAttribute("aria-activedescendant",t.id)}export function updateCmdk(){const t=h();if(t===null||!l.length){closeCmdk();return}const r=t.slice(1).toLowerCase(),i=l.filter(d=>String(d.name).toLowerCase().startsWith(r)).slice(0,8);if(!i.length){closeCmdk();return}s=i,n=0,e.textContent="",i.forEach((d,u)=>{const a=c("div","cmdk-item"+(u===0?" on":""));a.id="cmdk-opt-"+u,a.setAttribute("role","option"),a.appendChild(c("span","cmd",d.usage)),d.desc&&a.appendChild(c("span","desc",d.desc)),a.addEventListener("mousedown",k=>{k.preventDefault(),acceptCmdk(u)}),e.appendChild(a)}),e.hidden=!1,e.setAttribute("aria-label",C("web.cmdk.label")),o.setAttribute("aria-expanded","true"),o.setAttribute("aria-controls",e.id),f()}export function acceptCmdk(t){const r=s[t];r&&(o.value="/"+r.name+" ",p(),closeCmdk(),o.focus())}export function cmdkKeydown(t){if(e.hidden)return!1;if(t.key==="ArrowDown")return t.preventDefault(),n=Math.min(n+1,s.length-1),f(),!0;if(t.key==="ArrowUp")return t.preventDefault(),n=Math.max(n-1,0),f(),!0;if(t.key==="Escape")return t.preventDefault(),closeCmdk(),!0;if(t.key==="Tab")return t.preventDefault(),acceptCmdk(n),!0;if(t.key==="Enter"&&!t.shiftKey){const r=h(),i=s[n];if(r&&i&&r.slice(1).toLowerCase()!==String(i.name).toLowerCase())return t.preventDefault(),acceptCmdk(n),!0}return!1}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{inp as o,imgPicker as g,attachStrip as E,attachErr as B,sendBtn as p,el as u,icon as _}from"../dom.js";import{api as I}from"../api.js";import{t as c}from"../i18n.js";import{tabs as i,session as f,settings as v,MAX_IMAGES as k,MAX_IMAGE_BYTES as z}from"../store.js";import{contextLabel as W}from"../format.js";import{clearEmpty as N,activeFeed as Y,liveFeed as j,appendTo as y,scrollToBottom as P,clearFeed as J,finishMd as Q,resetTurnText as V,finishThink as Z,showBusy as $}from"../feed.js";import{setBusy as ee}from"../rail.js";import"../core/menus.js";import{openSessionsMenu as te}from"./sessions-menu.js";import{closeCmdk as F,updateCmdk as ne,cmdkKeydown as se,initCmdk as ae}from"./cmdk.js";let r={activeTab:()=>null,setTabStatus:()=>{},newChatTab:async()=>{},markTabDead:()=>{},openTab:()=>{},closeTab:()=>{},statusTitle:()=>""};export function initComposer(e){r={...r,...e}}ae({autogrow:C});const ie=200;function C(){o&&(o.style.height="auto",o.style.height=Math.min(o.scrollHeight,ie)+"px")}function oe(e){B&&(B.textContent=e,B.hidden=!1,clearTimeout(i.attachErrTimer),i.attachErrTimer=setTimeout(()=>{B.hidden=!0},4e3))}export function renderAttachments(){if(!E)return;E.textContent="",E.hidden=i.attachments.length===0,i.attachments.forEach((t,n)=>{const s=u("div","thumb"),a=document.createElement("img");a.alt="",a.src=t,s.appendChild(a);const d=u("button","rm");d.type="button",d.title=c("web.attach.remove"),d.setAttribute("aria-label",c("web.attach.remove")),d.appendChild(_("x")),d.addEventListener("click",()=>{i.attachments.splice(n,1),renderAttachments()}),s.appendChild(d),E.appendChild(s)});const e=r.activeTab();e&&(e.attachments=i.attachments.slice())}function re(e){return new Promise((t,n)=>{const s=new FileReader;s.onload=()=>t(String(s.result)),s.onerror=()=>n(s.error||new Error("read failed")),s.readAsDataURL(e)})}async function S(e){let t="";for(const n of e){if(!n||typeof n.type!="string"||n.type.indexOf("image/")!==0){t=c("web.attach.only_images");continue}if(i.attachments.length>=k){t=c("web.attach.too_many",{max:k});break}if(n.size>z){t=c("web.attach.too_large");continue}try{const s=await re(n);if(s.indexOf("data:image/")!==0){t=c("web.attach.invalid");continue}if(i.attachments.length>=k){t=c("web.attach.too_many",{max:k});break}i.attachments.push(s)}catch{t=c("web.attach.read_failed")}}renderAttachments(),t&&oe(t)}function ce(e,t){const n=u("div","u",e);return(t||[]).forEach(s=>{const a=document.createElement("img");a.className="uimg",a.alt="",a.src=s,n.appendChild(a)}),n}export function saveComposer(){const e=r.activeTab();!e||!o||(e.draft=o.value,e.attachments=i.attachments.slice())}export function restoreComposer(e){!e||!o||(o.value=e.draft||"",i.attachments=(e.attachments||[]).slice(),renderAttachments(),C(),F())}const de=document.getElementById("sessBar"),x=document.getElementById("sessNameBtn"),le=document.getElementById("sessName"),L=document.getElementById("sessPrev"),A=document.getElementById("sessNext"),D=document.getElementById("sessClose"),O=document.getElementById("sessTools"),q=document.getElementById("sessDD"),T=document.querySelector(".bar-top"),w=document.getElementById("newChat"),M=document.createComment("top-tools");T&&w&&T.insertBefore(M,w);function X(e){if(i.tabs.length<2)return;const t=i.tabs.findIndex(a=>a.id===i.activeTabId),n=t===-1?0:(t+e+i.tabs.length)%i.tabs.length,s=i.tabs[n];s&&r.openTab(s.id,s.name,s.kind,!0)}export function renderSessBar(){if(!de)return;const e=i.tabs.find(s=>s.id===i.activeTabId),t=e?e.name||String(e.id):"—";le.textContent=t,x.title=t+(e&&e.status&&e.status!=="idle"?" · "+r.statusTitle(e.status):"");const n=i.tabs.length>0;L.disabled=i.tabs.length<2,A.disabled=i.tabs.length<2,D.disabled=!n,x.disabled=!n}function U(){!T||!O||!w||!q||(window.matchMedia("(max-width: 760px)").matches?O.append(w,q):(T.insertBefore(w,M),T.insertBefore(q,M)))}if(L&&L.addEventListener("click",()=>X(-1)),A&&A.addEventListener("click",()=>X(1)),D&&D.addEventListener("click",()=>{i.activeTabId&&r.closeTab(i.activeTabId)}),x&&x.addEventListener("click",e=>{e.stopPropagation(),te()}),typeof window.matchMedia=="function"){const e=window.matchMedia("(max-width: 760px)");typeof e.addEventListener=="function"&&e.addEventListener("change",U),U()}g&&g.addEventListener("change",()=>{S(Array.from(g.files||[])),g.value=""});const G=document.getElementById("attachBtn");G&&g&&G.addEventListener("click",()=>g.click()),o.addEventListener("paste",e=>{const t=e.clipboardData&&e.clipboardData.items;if(!t)return;const n=[];for(const s of t)if(s.kind==="file"&&s.type&&s.type.indexOf("image/")===0){const a=s.getAsFile();a&&n.push(a)}n.length&&(e.preventDefault(),S(n))});const h=document.querySelector(".input-area");h&&(["dragenter","dragover"].forEach(e=>{h.addEventListener(e,t=>{t.preventDefault(),h.classList.add("dragover")})}),h.addEventListener("dragleave",e=>{const t=e;t.relatedTarget&&h.contains(t.relatedTarget)||h.classList.remove("dragover")}),h.addEventListener("drop",e=>{e.preventDefault(),h.classList.remove("dragover");const t=e.dataTransfer;t&&t.files&&t.files.length&&S(Array.from(t.files))}));function H(){o.value="",C(),F()}o&&o.addEventListener("input",()=>{const e=r.activeTab();e&&(e.draft=o.value),C(),ne()});async function K(){const e=o.value.trim(),t=i.attachments.slice();if(!e&&!t.length)return;const n=r.activeTab(),s=n&&n.kind==="session"?n.id:null,a=j()||Y();if(n&&n.dead){N(a),r.markTabDead(n.id);return}if(N(a),Q(),V(),Z(),e.startsWith("/")){y(a,u("div","u",e)),P(),n&&(n.draft="",n.attachments=[]),i.attachments=[],renderAttachments(),H();const l=e.slice(1).split(/\s+/)[0].toLowerCase();if(l==="clear"){J(a);return}if(l==="new"){r.newChatTab();return}const b={line:e};s&&(b.sessionId=s),(await I("/api/command",{method:"POST",body:b})).ok||y(a,u("div","detail","↳ "+c("web.misc.command_unavailable")));return}if(a&&a.querySelector(".startbanner")===null&&a.querySelector(".u")===null){const l=u("div","startbanner");l.appendChild(document.createTextNode(c("web.start.label")+" ")),l.appendChild(u("b","",v.config&&v.config.model||f.host.model||"—"));const b=f.host.sessionId?" · "+c("web.start.session")+" "+String(f.host.sessionId):"";l.appendChild(document.createTextNode(" · "+(f.host.provider||v.config&&v.config.provider&&v.config.provider.active||"—")+" · "+W()+b)),a.insertBefore(l,a.firstChild)}y(a,ce(e,t)),P(),n&&(n.draft="",n.attachments=[]),i.attachments=[],renderAttachments(),H(),s&&r.setTabStatus(s,"working");const d={text:e};t.length&&(d.images=t),s&&(d.sessionId=s);const m=await I("/api/message",{method:"POST",body:d});if(m.ok)if(m.data&&m.data.queued){const l=m.data.queuedForSession||m.data.queued;y(a,u("div","detail","↳ "+c("web.input.queued",{n:l}))),s&&r.setTabStatus(s,"queued")}else window.setTimeout(()=>$(a),180);else{const l=m.data&&m.data.error||m.status,b=l==="queue_full"?c("web.input.queue_full"):l;y(a,u("div","warnline","⚠ "+b)),s&&r.setTabStatus(s,"failed")}}async function R(){const e=r.activeTab(),t=e&&e.kind==="session"?e.id:null,n=f.runningSessionIds||[];t&&!n.includes(t)||!t&&!f.busy||await I("/api/interrupt",{method:"POST",body:t?{sessionId:t}:{}})}o.addEventListener("keydown",e=>{e.isComposing||e.keyCode===229||se(e)||(e.key==="Enter"&&!e.shiftKey?(e.preventDefault(),K()):e.key==="Escape"&&(e.preventDefault(),R()))}),p&&p.addEventListener("click",()=>{const e=r.activeTab();e&&e.kind==="session"&&f.runningSessionIds.includes(e.id)?R():K()});export function reflectBusy(){const e=r.activeTab(),t=f.runningSessionIds||[],n=!!(e&&e.kind==="session"&&t.includes(e.id));o&&o.setAttribute("aria-busy",n?"true":"false");const s=document.querySelector(".input-area");if(s&&s.classList.toggle("busy",n),p){const d=n?c("web.input.stop"):c("web.input.send");p.textContent="",p.appendChild(_(n?"square":"arrow-up")),p.classList.toggle("busy",n),p.title=d,p.setAttribute("aria-label",d)}const a=document.getElementById("hintEsc");a&&(a.hidden=!n),ee(f.busy)}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{el as o,icon as L}from"../dom.js";import{api as B}from"../api.js";import{t as r}from"../i18n.js";import{session as l}from"../store.js";import{relTime as I,matchesQuery as A}from"../format.js";import{openConfirm as T}from"../dialog.js";import{setSessOpen as E,setSessionCloseHook as D}from"../core/menus.js";let u={openTab:()=>{},closeTab:()=>{},loadSessions:async()=>{},newChatTab:async()=>{}};export function initSessionsMenu(e){u={...u,...e}}let w=null,p="",b=!1;function k(){const e=document.getElementById("sessSearch");return e?(e.placeholder=r("web.sessions.search"),e.setAttribute("aria-label",r("web.sessions.search")),b||(b=!0,e.addEventListener("click",s=>s.stopPropagation()),e.addEventListener("input",()=>{p=e.value,renderSessionsDropdown();const s=document.getElementById("sessSearch");s&&document.activeElement!==s&&s.focus()}),e.addEventListener("keydown",s=>{if(s.stopPropagation(),s.key==="Escape")e.value?(s.preventDefault(),e.value="",p="",renderSessionsDropdown(),e.focus()):E(!1);else if(s.key==="ArrowDown"){s.preventDefault();const t=document.querySelector("#sessActiveList .si-row .dd-row-main, #sessRecentList .si-row .dd-row-main");t&&t.focus()}})),e):null}export function renderSessionsDropdown(){k();const e=document.getElementById("sessActiveList"),s=document.getElementById("sessRecentList"),t=document.getElementById("sessActiveHeader"),n=document.getElementById("sessRecentHeader");if(!e||!s)return;e.textContent="",s.textContent="";const i=p.trim(),a=l.activeSessionId,m=l.sessions.slice().sort((d,f)=>{const v=d.updatedAt?new Date(d.updatedAt).getTime():0;return(f.updatedAt?new Date(f.updatedAt).getTime():0)-v}).filter(d=>A((d.name||"")+" "+String(d.id||""),i));let c=!1,h=!1;m.forEach(d=>{const f=d.id===a,v=_(d,f);f&&!c?(e.appendChild(v),c=!0):(s.appendChild(v),h=!0)}),i?(t&&(t.hidden=!c),n&&(n.hidden=!h),!c&&!h&&(n&&(n.hidden=!0),s.appendChild(o("div","si dim",r("web.settings.no_matches"))))):(t&&(t.hidden=!1),n&&(n.hidden=!1),c||e.appendChild(o("div","si",r("web.sessions.none_active"))),h||s.appendChild(o("div","si",r("web.sessions.none")))),l.sessionsError&&s.appendChild(o("div","dd-err",l.sessionsError))}function _(e,s){const t=o("div","si si-row"+(s?" on":"")),n=e.name||String(e.id),i=o("button","dd-row-main");if(i.type="button",i.setAttribute("aria-label",n),i.appendChild(o("span","id",String(e.id))),i.appendChild(o("span","name",n)),i.appendChild(o("span","meta",I(e.updatedAt))),i.addEventListener("click",()=>{E(!1),u.openTab(e.id,n,"session",!0)}),t.appendChild(i),!s){const a=o("button","del-btn");a.type="button",a.appendChild(L("trash"));const m=r("web.sessions.delete");a.title=m,a.setAttribute("aria-label",m+": "+n),a.addEventListener("click",c=>{c.stopPropagation(),R(e.id,n)}),t.appendChild(a)}return t}function R(e,s){T({title:r("web.sessions.confirm_title"),body:r("web.sessions.confirm_body",{name:s}),onAccept:()=>{x(e)}})}function P(e){l.sessionsError=e,renderSessionsDropdown(),w&&clearTimeout(w),w=setTimeout(()=>{l.sessionsError=null,renderSessionsDropdown()},4500)}async function x(e){const s=await B("/api/sessions/"+encodeURIComponent(e),{method:"DELETE"});if(s.ok)l.sessionsError=null,u.closeTab(e);else{const t=s.data&&typeof s.data.error=="string"?s.data.error:"";P(t==="active_session"||t==="session_busy"?r("web.sessions.active_guard"):r("web.sessions.delete_failed"))}await u.loadSessions()}const y=document.getElementById("sessDD"),S=document.getElementById("sessBtn");D(()=>{if(!p)return;p="";const e=document.getElementById("sessSearch");e&&e.value&&(e.value="",renderSessionsDropdown())});function H(){setTimeout(()=>{const e=document.getElementById("sessSearch");e&&e.focus()},0)}export function openSessionsMenu(){if(document.querySelectorAll("[data-sel]").forEach(s=>s.classList.remove("open")),!y)return;const e=!y.classList.contains("open");E(e),e&&H()}S&&S.addEventListener("click",e=>{e.stopPropagation(),openSessionsMenu()});const g=document.getElementById("sessNew");g&&g.addEventListener("click",()=>{u.newChatTab(),E(!1)});const C=document.getElementById("sessRefresh");C&&C.addEventListener("click",()=>{u.loadSessions()});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{msgs as k,inp as S,tabstripEl as l,el as u,icon as E,link as A}from"../dom.js";import{api as m}from"../api.js";import{t as o}from"../i18n.js";import{tabs as a,session as b,hooks as x}from"../store.js";import{makeFeed as q,showEmptyFeed as D,activeFeed as F,appendTo as C,feedHasContent as B,loadHistory as O,syncUrl as h,scrollToBottom as w}from"../feed.js";import{setIndicator as M}from"../dialog.js";import{sidebarSessionChanged as P,setSessionLoading as v}from"../sidebar.js";import{setSessOpen as H}from"../core/menus.js";import{closeCmdk as W}from"./cmdk.js";import{saveComposer as L,restoreComposer as I,renderAttachments as Y,renderSessBar as _,initComposer as N}from"./composer.js";import{renderSessionsDropdown as p,initSessionsMenu as U}from"./sessions-menu.js";export{reflectBusy}from"./composer.js";export{loadCommands}from"./cmdk.js";export{renderSessionsDropdown}from"./sessions-menu.js";const V={working:"●",waiting:"◉",queued:"○",failed:"✗",dead:"✗"};function T(e){return e==="working"?o("web.tab.working"):e==="waiting"?o("web.tab.waiting"):e==="queued"?o("web.tab.queued"):e==="failed"?o("web.tab.failed"):e==="dead"?o("web.tab.gone"):""}export function activeTab(){return a.tabs.find(e=>e.id===a.activeTabId)||null}export function setTabStatus(e,t){if(!e)return;const i=a.tabs.find(n=>n.id===e);!i||i.status===t||i.dead||(i.status=t,c())}export function markTabDead(e){const t=a.tabs.find(s=>s.id===e);if(!t||t.dead)return;t.dead=!0,t.status="dead",t.historyLoaded=!0,t.historyFailed=!1,t.planCard=null,v(!1),t.feed.replaceChildren();const i=u("div","warnline","✗ "+o("web.session.gone"));C(t.feed,i);const n=A(o("web.topbar.close"),"",()=>closeTab(e));C(t.feed,n),t.feed===F()&&w(),c()}function c(){l.textContent="",a.tabs.forEach(e=>{const t=e.id===a.activeTabId,i=e.name||e.id,n=e.kind==="session"?String(e.id):i,s=u("div","stab"+(t?" on":""));if(s.setAttribute("role","tab"),s.setAttribute("tabindex",t?"0":"-1"),s.setAttribute("aria-selected",t?"true":"false"),s.setAttribute("aria-label",i),s.title=n,e.status&&e.status!=="idle"){const d=u("span","dot st-"+e.status,V[e.status]||"●");d.title=T(e.status),d.setAttribute("aria-label",T(e.status)),s.appendChild(d)}const r=u("span","name",i);r.title=n,s.appendChild(r);const f=u("button","stab-x");f.type="button",f.title=o("web.topbar.close"),f.setAttribute("aria-label",o("web.topbar.close")+": "+i),f.appendChild(E("x")),f.addEventListener("click",d=>{d.stopPropagation(),closeTab(e.id)}),s.appendChild(f);const g=()=>openTab(e.id,e.name,e.kind,!0);s.addEventListener("click",g),s.addEventListener("keydown",d=>{(d.key==="Enter"||d.key===" ")&&(d.preventDefault(),g())}),l.appendChild(s)}),j(),_()}function j(){const e=l.querySelector(".stab.on");if(!e)return;const t=Math.max(0,e.offsetLeft-4);(t<l.scrollLeft||t+e.offsetWidth>l.scrollLeft+l.clientWidth)&&(l.scrollLeft=t)}l.addEventListener("wheel",e=>{e.deltaY!==0&&(e.preventDefault(),l.scrollLeft+=e.deltaY)},{passive:!1});export function updateTabName(e,t){if(!e||!t)return;const i=a.tabs.find(s=>s.id===e);i&&i.name!==t&&(i.name=t,c());const n=b.sessions.find(s=>s.id===e);n&&n.name!==t&&(n.name=t,p())}export function openTab(e,t,i,n){L();let s=a.tabs.find(r=>r.id===e);if(s?t&&(s.name=t):(s={id:e,name:t||e,kind:i||"session",feed:q(),historyLoaded:!1,historyLoading:!1,historyFailed:!1,dead:!1,planCard:null,draft:"",attachments:[],status:"idle"},a.tabs.push(s)),a.activeTabId=e,a.liveTabId=e,(i||"session")==="session"&&(b.activeSessionId=e,P(e)),k.replaceChildren(s.feed),I(s),c(),p(),w(),s.kind==="session"&&!n&&(s.historyLoaded=!0),n&&s.kind==="session"){if(s.dead){h();return}(!B(s.feed)||s.historyFailed)&&(s.historyLoaded=!1),v(!0),m("/api/sessions/activate",{method:"POST",body:{id:e}}).then(r=>{if(r.status===404){markTabDead(e),loadSessions();return}loadSessions(),a.activeTabId===e&&x.refreshState?.()}),O(s).then(r=>{r&&r.gone&&markTabDead(s.id)})}h()}export function closeTab(e){const t=a.tabs.findIndex(n=>n.id===e);if(t===-1)return;const i=a.activeTabId===e;if(i&&L(),a.tabs=a.tabs.filter(n=>n.id!==e),i){const n=a.tabs[Math.min(t,a.tabs.length-1)];n?(a.activeTabId=n.id,a.liveTabId=n.id,k.replaceChildren(n.feed),I(n),w()):(a.activeTabId=null,a.liveTabId=null,S&&(S.value=""),a.attachments=[],Y(),D())}c(),p(),h()}async function y(){const e=await m("/api/sessions",{method:"POST",body:{}});if(e.ok&&e.data&&e.data.session&&e.data.session.id){const t=e.data.session;openTab(t.id,t.name||String(t.id),"session",!1),await loadSessions(),v(!0),a.activeTabId===t.id&&x.refreshState?.();return}a.newSeq++,openTab("new"+a.newSeq,o("web.empty.title"),"new",!1),M(o("web.sessions.create_failed"),!0)}document.getElementById("newChat")?.addEventListener("click",()=>{y()});export function reconcileTabStatuses(){const e=b.runningSessionIds||[],t=b.queued||{};let i=!1;a.tabs.forEach(n=>{if(n.kind!=="session"||n.status==="waiting"||n.status==="failed"||n.status==="dead")return;const s=e.includes(n.id)?"working":t[n.id]>0?"queued":"idle";n.status!==s&&(n.status=s,i=!0)}),i&&c()}export async function loadSessions(){const e=await m("/api/sessions");!e.ok||!e.data||(b.sessions=Array.isArray(e.data.sessions)?e.data.sessions:[],p())}document.addEventListener("click",()=>{document.querySelectorAll("[data-sel]").forEach(e=>e.classList.remove("open")),H(!1),W()}),N({activeTab,setTabStatus,newChatTab:y,markTabDead,openTab,closeTab,statusTitle:T}),U({openTab,closeTab,loadSessions,newChatTab:y});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{el as c,makeToggle as y}from"../dom.js";import{tagsEditor as u,checkboxEditor as g,tableEditor as b}from"./editors.js";export function validateJson(i){const e=String(i??"").trim();if(!e)return{ok:!1,error:"required"};try{return JSON.parse(e),{ok:!0}}catch(t){return{ok:!1,error:t instanceof Error?t.message:"invalid JSON"}}}function l(i,e){const t=c("input");return t.setAttribute("aria-label",i),t.value=e,t}export function controlFor(i,e,t){if(i.readOnly){const s=c("span","val dim",e==null?"—":String(e));return e!=null&&(s.title=String(e)),s}if(i.valueType==="bool")return y(!!e,s=>(t.post(s),!0));if(i.valueType==="enum"){const s=c("select");return s.setAttribute("aria-label",t.label),(i.enum||[]).forEach(n=>{const o=c("option","",t.enumLabel(n));o.value=n,n===e&&(o.selected=!0),s.appendChild(o)}),s.addEventListener("change",()=>t.post(s.value)),s}if(i.valueType==="int"){const s=l(t.label,e==null?"":String(e));return s.type="number",i.min!=null&&(s.min=String(i.min)),i.max!=null&&(s.max=String(i.max)),i.step!=null&&(s.step=String(i.step)),s.addEventListener("change",()=>t.post(s.value)),s}if(i.valueType==="share"){const s=l(t.label,e==null?"":Math.round(Number(e)*100)+"%");return s.addEventListener("change",()=>t.post(s.value)),s}const r=i.editor;if(r&&r.kind==="tags"&&(i.valueType==="list"||i.valueType==="json"))return u(e,t,r);if(r&&r.kind==="checkboxes")return g(e,t,r);if(r&&r.kind==="table")return b(e,t,r);if(i.valueType==="list"){const s=Array.isArray(e)?e.join(", "):e==null?"":String(e),n=l(t.label,s);return n.placeholder="a, b, c",n.addEventListener("change",()=>t.post(n.value)),n}if(i.valueType==="json"){const s=c("div","jsonctl"),n=c("textarea");n.setAttribute("aria-label",t.label),n.rows=3,n.value=e==null?"":JSON.stringify(e,null,2);const o=c("div","json-err");return o.hidden=!0,n.addEventListener("input",()=>{const d=validateJson(n.value);o.hidden=d.ok,o.textContent=d.ok?"":String(d.error||"invalid JSON")}),n.addEventListener("change",()=>{validateJson(n.value).ok?t.post(n.value.trim()):n.focus()}),s.appendChild(n),s.appendChild(o),s}const a=l(t.label,e==null?"":String(e));return a.addEventListener("change",()=>t.post(a.value)),a}export const PANEL_SECTIONS={general:[{id:"general.interface",titleKey:"web.settings.sec.general.interface",keys:["locale","ui.verbosity"]},{id:"general.agent",titleKey:"web.settings.sec.general.agent",descKey:"web.settings.sec.general.agent.desc",keys:["maxToolIterations","stuckThreshold","autoPlan"]},{id:"general.provider",titleKey:"web.settings.sec.general.provider",keys:["provider.fallback"]}],model:[{id:"model.tuning",titleKey:"web.settings.sec.model.tuning",descKey:"web.settings.sec.model.tuning.desc",keys:["provider.maxCompletionTokens","modelLoad.autoLoad","modelLoad.flashAttention","modelLoad.evalBatchSize","modelLoad.offloadKvCacheToGpu"]},{id:"model.capabilities",titleKey:"web.settings.sec.model.capabilities",descKey:"web.settings.sec.model.capabilities.desc",keys:["modelCapabilities"]}],context:[{id:"context.window",titleKey:"web.settings.sec.context.window",descKey:"web.settings.sec.context.window.desc",keys:["contextWindow","contextBudget.systemPrompt","contextBudget.responseReserve"]},{id:"context.compaction",titleKey:"web.settings.sec.context.compaction",descKey:"web.settings.sec.context.compaction.desc",keys:["contextBudget.compactionThreshold","contextBudget.compactionMinLoad"]},{id:"context.instructions",titleKey:"web.settings.sec.context.instructions",descKey:"web.settings.sec.context.instructions.desc",keys:["instructions.summarize"]},{id:"context.log",titleKey:"web.settings.sec.context.log",descKey:"web.settings.sec.context.log.desc",keys:["contextLog.enabled","contextLog.redact"]}],reasoning:[{id:"reasoning.display",titleKey:"web.settings.sec.reasoning.display",keys:["showReasoning"]},{id:"reasoning.effort",titleKey:"web.settings.sec.reasoning.effort",descKey:"web.settings.sec.reasoning.effort.desc",keys:["reasoning.mode","reasoning.min","reasoning.max","reasoning.baseline","reasoning.overrideCooldown"]}],agent:[{id:"agent.moe",titleKey:"web.settings.sec.agent.moe",descKey:"web.settings.sec.agent.moe.desc",keys:["moe.enabled","moe.maxReplanCycles","experts"]},{id:"agent.critic",titleKey:"web.settings.sec.agent.critic",descKey:"web.settings.sec.agent.critic.desc",keys:["critic.enabled","critic.model","critic.provider","critic.tools","critic.maxCalls","critic.maxRepairCycles","critic.timeoutMs"]},{id:"agent.tools",titleKey:"web.settings.sec.agent.tools",descKey:"web.settings.sec.agent.tools.desc",keys:["tools.enableOnDemand","tools.defaultTags","skills.budget"]},{id:"agent.subagent",titleKey:"web.settings.sec.agent.subagent",descKey:"web.settings.sec.agent.subagent.desc",keys:["subagent.resultMode","subagent.maxSummaryChars","subagent.maxParallelChunkQueries","subagent.stableSystemPrompt"]},{id:"agent.hallucination",titleKey:"web.settings.sec.agent.hallucination",descKey:"web.settings.sec.agent.hallucination.desc",keys:["hallucination.judge.enabled"]}],network:[{id:"network.web",titleKey:"web.settings.sec.network.web",descKey:"web.settings.sec.network.web.desc",keys:["webSearch.enabled"]},{id:"network.error",titleKey:"web.settings.sec.network.error",descKey:"web.settings.sec.network.error.desc",keys:["errorWebSearch.enabled","errorWebSearch.threshold","errorWebSearch.maxResults","errorWebSearch.maxQueryChars","errorWebSearch.maxSearchesPerSession","errorWebSearch.requestTimeoutMs"]}],browser:[{id:"browser.main",titleKey:"web.settings.sec.browser.main",keys:["browser.enabled","browser.headless"]},{id:"browser.limits",titleKey:"web.settings.sec.browser.limits",descKey:"web.settings.sec.browser.limits.desc",keys:["browser.maxElements","browser.maxContentChars","browser.maxConsoleEntries","browser.maxConsoleLineChars"]},{id:"browser.viewport",titleKey:"web.settings.sec.browser.viewport",keys:["browser.viewportWidth","browser.viewportHeight","browser.navigationTimeout"]}],sessions:[{id:"sessions.main",titleKey:"web.settings.sec.sessions.main",descKey:"web.settings.sec.sessions.main.desc",keys:["session.autoSave","session.autoName","session.maxSessions","session.isolateMemory"]},{id:"sessions.isolation",titleKey:"web.settings.sec.sessions.isolation",descKey:"web.settings.sec.sessions.isolation.desc",keys:["sessionIsolation.enabled","sessionIsolation.isolatePlugins","sessionIsolation.isolateTempFiles"]}],ui:[{id:"ui.chat",titleKey:"web.settings.sec.ui.chat",descKey:"web.settings.sec.ui.chat.desc",keys:["ui.fontSize","ui.activityRail","ui.spinner","ui.showContextStats","ui.showCompaction"]}],security:[{id:"security.switches",titleKey:"web.settings.sec.security.switches",descKey:"web.settings.sec.security.switches.desc",keys:["security.enabled","security.bash.enabled","security.bash.blockDangerousFlags","security.paths.enabled","security.contentScan.enabled","security.network.enabled","security.sessionEncryption.enabled"]},{id:"security.limits",titleKey:"web.settings.sec.security.limits",descKey:"web.settings.sec.security.limits.desc",keys:["security.maxRecursionDepth","security.maxFileOperations","security.rateLimits.maxRequestsPerMinute","security.rateLimits.maxParallelTasks","security.network.requestTimeout","security.network.maxResponseSize"]},{id:"security.bash",titleKey:"web.settings.sec.security.bash",descKey:"web.settings.sec.security.bash.desc",keys:["security.bash.blacklist","security.bash.whitelist","security.bash.dangerousFlags","security.bash.dangerousOperators"]},{id:"security.paths",titleKey:"web.settings.sec.security.paths",descKey:"web.settings.sec.security.paths.desc",keys:["security.paths.denied","security.paths.allowed"]},{id:"security.network",titleKey:"web.settings.sec.security.network",descKey:"web.settings.sec.security.network.desc",keys:["security.network.deniedDomains","security.network.allowedDomains"]},{id:"security.scan",titleKey:"web.settings.sec.security.scan",descKey:"web.settings.sec.security.scan.desc",keys:["security.contentScan.dangerousPatterns"]},{id:"security.audit",titleKey:"web.settings.sec.security.audit",descKey:"web.settings.sec.security.audit.desc",keys:["security.auditNotifier.enabled","security.auditNotifier.filePath","security.auditNotifier.webhookUrl","security.auditNotifier.webhookTimeout","security.auditNotifier.minSeverity","security.auditNotifier.maxRetries","security.auditNotifier.eventTypes"]},{id:"security.encryption",titleKey:"web.settings.sec.security.encryption",descKey:"web.settings.sec.security.encryption.desc",keys:["security.sessionEncryption.encryptHistory","security.sessionEncryption.encryptSessionLog","security.sessionEncryption.keyPath"]}],advanced:[{id:"advanced.diagnostics",titleKey:"web.settings.sec.advanced.diagnostics",descKey:"web.settings.sec.advanced.diagnostics.desc",keys:["logLevel","version"]},{id:"advanced.retry",titleKey:"web.settings.sec.advanced.retry",descKey:"web.settings.sec.advanced.retry.desc",keys:["retry.maxRetries","retry.baseDelay","retry.maxDelay","retry.maxStreamRetries","retry.noDataTimeoutMs"]},{id:"advanced.service",titleKey:"web.settings.sec.advanced.service",descKey:"web.settings.sec.advanced.service.desc",keys:["pricing.enabled","pricing.overrides","updater.enabled","updater.checkOnStart","updater.autoInstall","updater.intervalMs"]}],plugins:[{id:"plugins.lsp",titleKey:"web.settings.sec.plugins.lsp",descKey:"web.settings.sec.plugins.lsp.desc",keys:["lsp.enabled","lsp.offline"]}]};export function keyToPanel(){const i=new Map;for(const[e,t]of Object.entries(PANEL_SECTIONS))for(const r of t)for(const a of r.keys)i.set(a,e);return i}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{el as l}from"../dom.js";import{t as w}from"../i18n.js";export function tagsEditor(y,i,g){const s=Array.isArray(y)?y.map(String):[],u=l("div","tagsctl ctl-block"),d=l("div","tags-list"),h=()=>i.post(JSON.stringify(s)),r=()=>{d.textContent="",s.forEach((o,E)=>{const A=l("span","tag-chip"),v=l("span","tag-text",o);v.title=o,A.appendChild(v);const C=l("button","tag-rm linkbtn","✕");C.type="button",C.setAttribute("aria-label",`${i.label}: remove ${o}`),C.addEventListener("click",()=>{s.splice(E,1),h(),r()}),A.appendChild(C),d.appendChild(A)}),s.length||d.appendChild(l("span","tags-empty",i.emptyLabel||"—"))};r(),u.appendChild(d);const f=l("div","tags-add"),p=l("input");p.type="text",p.placeholder=g.placeholder||"…",p.setAttribute("aria-label",i.label);const k=()=>{const o=p.value.trim();if(!o||s.includes(o)){p.select();return}s.push(o),h(),r(),p.value="",p.focus()};p.addEventListener("keydown",o=>{o.key==="Enter"&&(o.preventDefault(),k())}),f.appendChild(p);const b=l("button","tags-plus linkbtn","+");return b.type="button",b.setAttribute("aria-label",`${i.label}: add`),b.addEventListener("click",k),f.appendChild(b),u.appendChild(f),u}export function checkboxEditor(y,i,g){const s=new Set(Array.isArray(y)?y.map(String):[]),u=l("div","checksctl ctl-block");return(g.options||[]).forEach(d=>{const h=l("label","check-line"),r=l("input");r.type="checkbox",r.checked=s.has(d),r.addEventListener("change",()=>{r.checked?s.add(d):s.delete(d),i.post(JSON.stringify([...s]))}),h.appendChild(r),h.appendChild(l("span","",i.enumLabel?i.enumLabel(d):d)),u.appendChild(h)}),u}export function tableEditor(y,i,g){const s=g.columns||[],u=s[0],d=s.slice(1),h=y&&typeof y=="object"&&!Array.isArray(y)?y:{},r=Object.entries(h).map(([e,t])=>({name:e,val:t&&typeof t=="object"?{...t}:{},error:""})),f=l("div","tablectl ctl-block"),p=l("div","table-head");s.forEach(e=>p.appendChild(l("span","table-th",i.fieldLabel(e.key)))),f.appendChild(p);const k=l("div","table-body"),b=l("div","json-err");b.hidden=!0;const o=e=>e.array===!0,E=e=>e===void 0||e===""||Array.isArray(e)&&e.length===0,A=()=>{const e={};for(const t of r){if(!t.name)return{ok:!1,reason:"empty name"};if(e[t.name]!==void 0)return{ok:!1,reason:`duplicate: ${t.name}`};const a={};for(const n of d){const c=t.val[n.key];if(!(n.optional&&E(c))){if(!n.optional&&E(c))return{ok:!1,reason:`${t.name}: ${i.fieldLabel(n.key)}`};if(n.type==="number"){const N=Number(c);if(!Number.isFinite(N)||N<0)return{ok:!1,reason:`${t.name}: ${i.fieldLabel(n.key)}`};a[n.key]=N}else n.type==="bool"?c===!0&&(a[n.key]=!0):a[n.key]=o(n)?c:String(c)}}e[t.name]=a}return{ok:!0,value:e}},v=()=>{const e=A();return e.ok?(b.hidden=!0,b.textContent="",i.post(JSON.stringify(e.value)),!0):(b.hidden=!1,b.textContent=w("web.settings.table_invalid",{field:e.reason||""}),!1)},C=(e,t,a)=>{if(t.type==="bool")a.checked?e.val[t.key]=!0:delete e.val[t.key];else if(t.type==="number"){const n=a.value.trim();n===""?delete e.val[t.key]:e.val[t.key]=Number(n)}else{const n=a.value.trim();n===""?delete e.val[t.key]:e.val[t.key]=o(t)?n.split(",").map(c=>c.trim()).filter(Boolean):n}},O=(e,t)=>{const a=l("input"),n=e.val[t.key];return t.type==="bool"?(a.type="checkbox",a.checked=n===!0):t.type==="number"?(a.type="number",a.value=n==null?"":String(n)):(a.type="text",a.value=Array.isArray(n)?n.join(", "):n==null?"":String(n)),a.setAttribute("aria-label",`${e.name}: ${i.fieldLabel(t.key)}`),a.addEventListener("change",()=>{C(e,t,a),v()}),a},$=()=>{k.textContent="",r.forEach(e=>{const t=l("div","table-row");t.dataset.key=e.name;const a=l("input");a.type="text",a.value=e.name,a.placeholder=i.fieldLabel(u.key),a.setAttribute("aria-label",i.fieldLabel(u.key)),a.addEventListener("change",()=>{e.name=a.value.trim(),v()&&(t.dataset.key=e.name)}),t.appendChild(a),d.forEach(c=>t.appendChild(O(e,c)));const n=l("button","table-rm linkbtn","✕");n.type="button",n.setAttribute("aria-label",`${i.label}: remove ${e.name}`),n.addEventListener("click",()=>{r.splice(r.indexOf(e),1),v()&&$()}),t.appendChild(n),k.appendChild(t)})};$(),f.appendChild(k),f.appendChild(b);const S=l("div","table-add"),m=l("input");m.type="text",m.placeholder=i.fieldLabel(u.key),m.setAttribute("aria-label",`${i.label}: new ${i.fieldLabel(u.key)}`);const j=()=>{const e=m.value.trim();if(!e||r.some(c=>c.name===e)){m.select();return}const t={};r.push({name:e,val:t,error:""}),m.value="",$();const a=k.lastElementChild,n=a&&a.querySelectorAll("input")[1];n&&n.focus()};m.addEventListener("keydown",e=>{e.key==="Enter"&&(e.preventDefault(),j())}),S.appendChild(m);const L=l("button","table-plus linkbtn","+");return L.type="button",L.setAttribute("aria-label",`${i.label}: add`),L.addEventListener("click",j),S.appendChild(L),f.appendChild(S),f}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{el as o}from"../dom.js";import{t as l}from"../i18n.js";export function pfield(n,t){const e=o("div","pform-field");return e.appendChild(o("label","",l(n))),t.setAttribute("aria-label",l(n)),e.appendChild(t),e}export function providerInput(n,t,e){const i=o("input");return i.type=t||"text",e&&(i.placeholder=e),n!=null&&(i.value=String(n)),i}export function providerSelect(n,t){const e=o("select"),i=o("option","","—");i.value="",e.appendChild(i);const d=new Set([""]);if(n.forEach(r=>{d.add(r);const p=o("option","",r);p.value=r,r===t&&(p.selected=!0),e.appendChild(p)}),t!=null&&t!==""&&!d.has(t)){const r=o("option","",t);r.value=t,r.selected=!0,e.appendChild(r)}return t==null&&(e.value=""),e}export function providerCheck(n){const t=o("input");return t.type="checkbox",t.checked=n===!0,t}export function mcpLiteralField(n,t){const e=o("div","pform-field"),i=o("label","",n);return e.appendChild(i),t.setAttribute("aria-label",n),e.appendChild(t),e}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{settings as i}from"../store.js";import{closeConfirm as m,confirmOverlay as u,trapTab as g}from"../dialog.js";import{renderPanel as y,renderUiPanel as b,renderMemoryPanel as k,renderSkillsPanel as A,renderPluginsPanel as E,renderSecurityPanel as L,loadMemory as v,loadSkills as S,loadPlugins as w,loadLsp as P}from"./panels.js";import{renderModelPanel as h}from"./providers.js";import{closeSubDialog as f,isSubDialogOpen as x}from"./subdialog.js";import{setWriteHooks as B}from"./write.js";export function renderSettings(){for(const e of["general","context","reasoning","agent","network","browser","sessions","advanced"])y(e);h(),b(),k(),A(),E(),L()}const s=document.getElementById("overlay"),c=document.getElementById("openSettings"),I=document.getElementById("closeSettings");let a=null;const n=Array.from(document.querySelectorAll("#setMenu .mi"));export function selectSettingsPanel(e){n.forEach(t=>{const l=t.dataset.p===e;t.classList.toggle("on",l),t.setAttribute("aria-selected",l?"true":"false"),t.tabIndex=l?0:-1}),document.querySelectorAll(".content-col .panel").forEach(t=>t.classList.remove("on"));const r=document.getElementById("p-"+e);r&&r.classList.add("on")}n.forEach(e=>{const r=e.dataset.p||"";e.setAttribute("role","tab"),e.setAttribute("id","tab-"+r),e.setAttribute("aria-controls","p-"+r),e.setAttribute("aria-selected",e.classList.contains("on")?"true":"false"),e.tabIndex=e.classList.contains("on")?0:-1,e.addEventListener("click",()=>selectSettingsPanel(r)),e.addEventListener("keydown",t=>{const l=n.indexOf(e);let o=null;t.key==="ArrowDown"||t.key==="ArrowRight"?o=n[(l+1)%n.length]:t.key==="ArrowUp"||t.key==="ArrowLeft"?o=n[(l-1+n.length)%n.length]:t.key==="Home"?o=n[0]:t.key==="End"&&(o=n[n.length-1]),o&&(t.preventDefault(),selectSettingsPanel(o.dataset.p||""),o.focus())})}),document.querySelectorAll(".content-col .panel").forEach(e=>{e.setAttribute("role","tabpanel"),e.setAttribute("aria-labelledby","tab-"+e.id.replace(/^p-/,""))});function p(){a=document.activeElement,s.classList.add("open"),c.setAttribute("aria-expanded","true"),v(),S(),w(),P();const e=document.querySelector("#setMenu .mi.on")||n[0];e&&setTimeout(()=>e.focus(),0)}function M(e){p(),selectSettingsPanel(e)}function d(){f(),i.providerForm=null,i.mcpForm=null,i.lspForm=null,s.classList.remove("open"),c.setAttribute("aria-expanded","false"),a&&a.focus&&a.focus(),a=null}c.addEventListener("click",p),I.addEventListener("click",d),s.addEventListener("click",e=>{e.target===s&&d()}),s.addEventListener("keydown",e=>g(s,e)),document.addEventListener("keydown",e=>{e.key==="Escape"&&(x()?f():u&&u.classList.contains("open")?m():s.classList.contains("open")&&d())}),B({renderSettings,openSettingsAt:M});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{el as i,icon as O,link as k,inlineTextNodes as q,makeToggle as J}from"../dom.js";import{api as w}from"../api.js";import{t as s}from"../i18n.js";import{settings as l,getPath as D,THEME_KEY as N}from"../store.js";import{setIndicator as C}from"../dialog.js";import{controlFor as U,PANEL_SECTIONS as E}from"./controls.js";import{postConfig as j}from"./write.js";import{openSubDialog as F,closeSubDialog as x}from"./subdialog.js";import{mcpLiteralField as v,providerInput as _,providerSelect as H,providerCheck as P}from"./form.js";export function configLabel(e){const n="config.key."+e.key,t=s(n);return t===n?e.key:t}export function enumLabel(e){const n="config.enum."+e,t=s(n);return t===n?e:t}export function defFor(e){return l.registry.find(n=>n.key===e)||null}export function row(e,n,t){const a=i("div","row"),o=i("div","row-label");if(o.appendChild(i("span","row-name",e)),t&&o.appendChild(i("span","row-desc",t)),a.appendChild(o),typeof n=="string"){const d=i("span","val",n);d.title=n,a.appendChild(d)}else n&&a.appendChild(n);return a}export function descFor(e){const n="config.desc."+e,t=s(n);return t===n?"":t}function B(e,n){const t=e.readOnly&&e.value!==void 0?e.value:l.config?D(l.config,n):void 0;return U(e,t,{label:configLabel(e),enumLabel,emptyLabel:s("config.enum.none"),fieldLabel:a=>{const o="config.field."+a,d=s(o);return d===o?a:d},post:a=>{j(n,a,!1)}})}function Y(e){const n=i("div","settings-section"),t=i("div","sec-head");if(t.appendChild(i("span","sec-title",s(e.titleKey))),n.appendChild(t),e.descKey){const o=s(e.descKey);o!==e.descKey&&n.appendChild(i("div","sec-desc",o))}const a=i("div","sec-body");return e.keys.forEach(o=>{const d=defFor(o);d&&a.appendChild(row(configLabel(d),B(d,o),descFor(d.key)))}),n.appendChild(a),n}export function renderSections(e,n){const t=document.querySelector('[data-panel="'+e+'"]');t&&n.forEach(a=>t.appendChild(Y(a)))}export function renderPanel(e){const n=document.querySelector('[data-panel="'+e+'"]');n&&(n.textContent="",renderSections(e,E[e]||[]))}export function settingsSection(e){const n=i("div","settings-section"),t=i("div","sec-head");t.appendChild(i("span","sec-title",s(e))),n.appendChild(t);const a=i("div","sec-body");return n.appendChild(a),{el:n,head:t,body:a}}export function chip(e,n,t){const a=i("button","chip"+(n?" "+n:""),e);return a.type="button",a.addEventListener("click",t),a}export function placeholderFor(e,n){const t=i("div","placeholder");return e===void 0?t.textContent=s("web.settings.loading"):t.textContent=n,t}export function groupHeader(e,n){const t=i("div","row");return t.appendChild(i("span","val accent",e)),n!=null&&t.appendChild(i("span","val dim",String(n))),t}export function currentTheme(){return localStorage.getItem(N)||"auto"}function I(){const e=document.querySelector('[data-panel="ui"]');if(!e)return;e.textContent="";const n=i("span","seg");["dark","light","auto"].forEach(r=>{const p=i("button",currentTheme()===r?"on":"",r);p.type="button",p.setAttribute("aria-pressed",currentTheme()===r?"true":"false"),p.addEventListener("click",()=>{n.querySelectorAll("button").forEach(u=>{u.classList.remove("on"),u.setAttribute("aria-pressed","false")}),p.classList.add("on"),p.setAttribute("aria-pressed","true"),applyTheme(r)}),n.appendChild(p)});const t=i("div","settings-section"),a=i("div","sec-head");a.appendChild(i("span","sec-title",s("web.settings.sec.ui.theme"))),t.appendChild(a);const o=s("web.settings.sec.ui.theme.desc");o!=="web.settings.sec.ui.theme.desc"&&t.appendChild(i("div","sec-desc",o));const d=i("div","sec-body");d.appendChild(row(s("web.settings.theme"),n)),t.appendChild(d),e.appendChild(t),renderSections("ui",E.ui||[])}export function applyTheme(e){localStorage.setItem(N,e);const n=e==="light"||e==="auto"&&window.matchMedia&&window.matchMedia("(prefers-color-scheme: light)").matches;document.body.classList.toggle("light",!!n),I()}window.matchMedia&&window.matchMedia("(prefers-color-scheme: light)").addEventListener("change",()=>{currentTheme()==="auto"&&applyTheme("auto")});function z(){const e=document.querySelector('[data-panel="security"]');if(!e)return;e.textContent="",renderSections("security",E.security||[]);const n=i("div","settings-section"),t=i("div","sec-head");t.appendChild(i("span","sec-title",s("web.settings.sec.security.access"))),n.appendChild(t);const a=i("div","sec-body");a.appendChild(row(s("web.settings.web_token"),i("span","val dim",l.webToken||s("web.settings.web_token_none")),s("config.desc.webToken")));const o=i("div","placeholder");o.appendChild(i("span","tag",s("web.settings.terminal_tag"))),o.appendChild(document.createTextNode(" "+s("web.settings.security_note"))),a.appendChild(o),n.appendChild(a),e.appendChild(n)}const G=["conventions","decisions","errors","facts"];function Q(){const e=i("div","pform"),n=i("div","pform-grid"),t=i("select");t.setAttribute("aria-label",s("web.settings.memory_category")),G.forEach(d=>t.appendChild(i("option","",d))),t.value="facts",n.appendChild(v(s("web.settings.memory_category"),t)),e.appendChild(n);const a=i("textarea");a.rows=5,a.placeholder=s("web.settings.new_memory"),a.value="",e.appendChild(v(s("web.settings.new_memory"),a));const o=i("div","pform-actions");o.appendChild(k(s("web.settings.save"),"",async()=>{const d=a.value.trim();if(!d){a.focus();return}const r=await w("/api/memory",{method:"POST",body:{category:t.value,text:d}});r.ok&&r.data&&r.data.ok?(x(),await loadMemory()):C(s("web.settings.add_failed"),!0)})),o.appendChild(k(s("web.settings.cancel"),"dim",()=>x())),e.appendChild(o),F(s("web.settings.memory_add_title"),e,()=>L())}function L(){const e=document.querySelector('[data-panel="memory"]');if(!e)return;if(e.textContent="",l.memory===void 0||l.memory===null){e.appendChild(placeholderFor(l.memory,s("web.settings.memory_unavailable")));return}const n=l.memory,t=i("button","sec-add");t.type="button",t.appendChild(O("plus")),t.appendChild(i("span","",s("web.settings.add"))),t.addEventListener("click",()=>Q());const a=i("div","sec-head");a.appendChild(i("span","sec-title",s("web.settings.sec.memory.add"))),a.appendChild(t);const o=i("div","settings-section");o.appendChild(a),e.appendChild(o);const d=i("input","searchbox");d.placeholder=s("web.settings.search_memory"),d.setAttribute("aria-label",s("web.settings.search_memory")),e.appendChild(d);const r=i("div","settings-list");e.appendChild(r);const p=(h,g)=>{const c=i("div","mem-cat");return c.appendChild(i("span","",h)),g!=null&&c.appendChild(i("span","n",String(g))),c},u=(h,g)=>{const c=i("div","mem-entry"),m=i("span","mem-text");return m.appendChild(q(String(h??""))),m.title=String(h??""),c.appendChild(m),g&&c.appendChild(k(s("web.settings.forget"),"mem-del",g)),c},b=()=>{r.textContent="";const h=d.value.trim().toLowerCase();let g=!1;(n.categories||[]).forEach(m=>{const f=(m.entries||[]).filter(y=>!h||String(y.text).toLowerCase().indexOf(h)!==-1);f.length&&(g=!0,r.appendChild(p(m.name,f.length)),f.forEach(y=>{r.appendChild(u(y.text,async()=>{(await w("/api/memory/"+encodeURIComponent(m.name)+"/"+y.n,{method:"DELETE"})).ok?await loadMemory():C(s("web.settings.forget_failed"),!0)}))}))});const c=Object.entries(n.preferences||{});if(c.length&&!h&&(g=!0,r.appendChild(p(s("web.settings.preferences"),c.length)),c.forEach(([m,f])=>{r.appendChild(u(m+" = "+f))})),!g){const m=i("div","placeholder");m.textContent=h?s("web.settings.no_matches"):s("web.settings.no_memory"),r.appendChild(m)}};d.addEventListener("input",b),b()}function M(){const e=document.querySelector('[data-panel="skills"]');if(!e)return;if(e.textContent="",l.skills===void 0||l.skills===null){e.appendChild(placeholderFor(l.skills,s("web.settings.skills_unavailable")));return}if(!l.skills.length){const t=i("div","placeholder");t.textContent=s("web.settings.no_skills"),e.appendChild(t);return}const n=i("div","settings-list");l.skills.forEach(t=>{const a=i("div","skill-item"),o=i("div","skill-head");o.appendChild(i("span",t.enabled?"g":"dim",t.enabled?"✓":"○"));const d=i("span","name",t.name);if(d.title=t.name,o.appendChild(d),o.appendChild(i("span","st",t.enabled?s("web.settings.enabled"):s("web.settings.available"))),a.appendChild(o),t.source){const r=i("div","skill-src",t.source);r.title=t.source,a.appendChild(r)}n.appendChild(a)}),e.appendChild(n)}function S(){const e=document.querySelector('[data-panel="plugins"]');if(!e)return;if(e.textContent="",l.pluginsData===void 0||l.pluginsData===null){e.appendChild(placeholderFor(l.pluginsData,s("web.settings.plugins_unavailable")));return}const n=l.pluginsData,t=i("div","settings-list");if(t.appendChild(groupHeader(s("web.settings.plugins_header"),(n.plugins||[]).length)),!(n.plugins||[]).length){const d=i("div","placeholder");d.textContent=s("web.settings.no_plugins"),t.appendChild(d)}(n.plugins||[]).forEach(d=>{const r=i("div","list-line");r.appendChild(i("span","g","✓"));const p=i("span","name",d.name);if(p.title=d.name,r.appendChild(p),d.version&&r.appendChild(i("span","src","v"+d.version)),d.source){const u=i("span","src",d.source);u.title=d.source,r.appendChild(u)}d.builtin&&r.appendChild(i("span","src",s("web.settings.builtin"))),r.appendChild(i("span","st",d.enabled===!1?s("web.settings.disabled"):s("web.settings.enabled"))),t.appendChild(r)});const a=i("div","settings-note");a.textContent=s("web.settings.plugins_note"),t.appendChild(a),t.appendChild(groupHeader(s("web.settings.mcp_servers"),(n.mcp||[]).length));const o=i("button","sec-add");if(o.type="button",o.appendChild(O("plus")),o.appendChild(i("span","",s("web.settings.mcp_add"))),o.addEventListener("click",()=>R("add",null)),t.appendChild(o),!(n.mcp||[]).length){const d=i("div","placeholder");d.textContent=s("web.settings.no_mcp"),t.appendChild(d)}if((n.mcp||[]).forEach(d=>{const r=i("div","list-line"),p=d.status!=="disabled",u=J(p,h=>{w("/api/mcp/"+encodeURIComponent(d.id||d.name),{method:"POST",body:{enabled:h}}).then(async g=>{g.ok&&g.data&&g.data.ok?(C(s("web.settings.mcp_saved"),!1),await loadPlugins()):C(s("web.settings.save_failed"),!0)})});u.title=p?s("web.settings.mcp_disable"):s("web.settings.mcp_enable"),u.setAttribute("aria-label",u.title),r.appendChild(u);const b=i("span","name",d.name);b.title=d.name,r.appendChild(b),r.appendChild(i("span","st",d.status||"—")),r.appendChild(chip(s("web.settings.edit"),"",()=>R("edit",d))),r.appendChild(chip(s("web.settings.delete"),"danger",async()=>{const h=await w("/api/mcp/"+encodeURIComponent(d.id||d.name),{method:"DELETE"});h.ok&&h.data&&h.data.ok?(C(s("web.settings.mcp_saved"),!1),await loadPlugins()):C(h.data&&h.data.error||s("web.settings.delete_failed"),!0)})),t.appendChild(r)}),l.mcpForm&&t.appendChild(K()),(n.mcp||[]).length){const d=i("div","settings-note");d.textContent=s("web.settings.mcp_note"),t.appendChild(d)}X(t),e.appendChild(t),renderSections("plugins",E.plugins||[])}function K(){const e=l.mcpForm&&l.mcpForm.mode||"add",n=l.mcpForm&&l.mcpForm.entry||{},t=i("div","pform"),a=i("div","pform-grid"),o=_(n.name||"","text","my-server"),d=H(["stdio","sse","http"],n.transport||"stdio"),r=_(n.command||"","text","npx"),p=_(n.url||"","text","https://…");a.appendChild(v("name",o)),a.appendChild(v("transport",d)),a.appendChild(v("command",r)),a.appendChild(v("url",p)),t.appendChild(a);const u=i("details","pform-adv");u.appendChild(i("summary","",s("web.settings.provider_advanced")));const b=_(n.args?JSON.stringify(n.args):"","text",'["--stdio"]'),h=_(n.timeout!=null?String(n.timeout):"","number","30000"),g=P(n.enabled!==!1);u.appendChild(v("args (JSON)",b)),u.appendChild(v("timeout (ms)",h));const c=Array.isArray(n.envKeys)?n.envKeys:[],m=Array.isArray(n.headerKeys)?n.headerKeys:[],f=i("textarea");f.placeholder=c.length?"stored: "+c.join(", ")+" — blank keeps":'{"TOKEN": "…"}';const y=i("textarea");y.placeholder=m.length?"stored: "+m.join(", ")+" — blank keeps":'{"Authorization": "…"}',u.appendChild(v("env (JSON)",f)),u.appendChild(v("headers (JSON)",y)),u.appendChild(v("enabled",g)),t.appendChild(u);const T={name:o,transport:d,command:r,url:p,args:b,timeout:h,env:f,headers:y,enabled:g},A=i("div","pform-actions");return A.appendChild(k(s("web.settings.save"),"",()=>{W(T,e,n)})),A.appendChild(k(s("web.settings.cancel"),"dim",()=>x())),t.appendChild(A),t}function R(e,n){l.mcpForm={mode:e,entry:n||null},F(s(e==="edit"?"web.settings.mcp_edit_title":"web.settings.mcp_add"),K(),()=>{l.mcpForm=null,S(),loadPlugins()})}function V(e){const n=e.trim();if(!n)return{present:!1,value:null};let t=null;try{t=JSON.parse(n)}catch{return{present:!0,value:null}}return!t||typeof t!="object"||Array.isArray(t)?{present:!0,value:null}:Object.values(t).every(a=>typeof a=="string")?{present:!0,value:t}:{present:!0,value:null}}async function W(e,n,t){const a=e.name.value.trim(),o=e.transport.value||"stdio",d=e.command.value.trim(),r=e.url.value.trim();if(!a||(o==="stdio"?!d:!r)){C(s("web.settings.mcp_required"),!0);return}const p={name:a,transport:o};d&&(p.command=d),r&&(p.url=r);const u=e.args.value.trim();if(u){let c=null;try{c=JSON.parse(u)}catch{c=null}if(!Array.isArray(c)||!c.every(m=>typeof m=="string")){C(s("web.settings.mcp_invalid"),!0);return}p.args=c}for(const c of["env","headers"]){const m=V(e[c].value);if(m.present&&!m.value){C(s("web.settings.mcp_invalid"),!0);return}m.present&&(p[c]=m.value)}const b=e.timeout.value.trim();if(b){const c=Number(b);if(!Number.isInteger(c)||c<1e3||c>3e5){C(s("web.settings.mcp_invalid"),!0);return}p.timeout=c}p.enabled=e.enabled.checked;const h=n==="edit"?"/api/mcp/"+encodeURIComponent(t.id||t.name):"/api/mcp",g=await w(h,{method:n==="edit"?"PUT":"POST",body:p});g.ok&&g.data&&g.data.ok?(C(s("web.settings.mcp_saved"),!1),x()):C(g.data&&g.data.error||s("web.settings.save_failed"),!0)}function X(e){const n=l.lsp;if(e.appendChild(groupHeader(s("web.settings.lsp_servers"),Array.isArray(n)?n.length:null)),n==null){e.appendChild(placeholderFor(n,s("web.settings.lsp_unavailable")));return}if(!n.length){const t=i("div","placeholder");t.textContent=s("web.settings.no_lsp"),e.appendChild(t)}if(n.forEach(t=>{const a=i("div","list-line");a.appendChild(i("span",t.enabled?"g":"dim",t.enabled?"✓":"○"));const o=i("span","name",t.lang);o.title=t.lang,a.appendChild(o);const d=[t.command,t.timeout!=null?t.timeout+" ms":null].filter(Boolean).join(" · ");d&&a.appendChild(i("span","src",d)),a.appendChild(i("span","st",t.enabled?s("web.settings.enabled"):s("web.settings.disabled"))),a.appendChild(chip(s("web.settings.edit"),"",()=>Z(t))),e.appendChild(a)}),n.length){const t=i("div","settings-note");t.textContent=s("web.settings.lsp_note"),e.appendChild(t)}}function Z(e){l.lspForm={lang:e.lang,entry:e},F(e.lang,$(),()=>{l.lspForm=null,S(),loadLsp()})}function $(){const e=l.lspForm&&l.lspForm.entry||{},n=l.lspForm&&l.lspForm.lang||e.lang||"",t=i("div","pform"),a=i("div","pform-grid"),o=_(e.command||"","text","npx"),d=_(e.timeout!=null?String(e.timeout):"","number","30000"),r=P(e.enabled!==!1);a.appendChild(v("command",o)),a.appendChild(v("timeout (ms)",d)),a.appendChild(v("enabled",r)),t.appendChild(a);const p=i("textarea");p.value=e.args?JSON.stringify(e.args):"",p.placeholder='["--stdio"]',t.appendChild(v("args (JSON)",p));const u=i("div","pform-actions");return u.appendChild(k(s("web.settings.save"),"",async()=>{const b={},h=o.value.trim();h&&(b.command=h);const g=d.value.trim();if(g){const f=Number(g);if(!Number.isInteger(f)||f<1e3||f>3e5){C(s("web.settings.provider_invalid"),!0);return}b.timeout=f}const c=p.value.trim();if(c){let f=null;try{f=JSON.parse(c)}catch{f=null}if(!Array.isArray(f)||!f.every(y=>typeof y=="string")){C(s("web.settings.provider_invalid"),!0);return}b.args=f}b.enabled=r.checked;const m=await w("/api/lsp/"+encodeURIComponent(n),{method:"PUT",body:b});m.ok&&m.data&&m.data.ok?(C(s("web.settings.mcp_saved"),!1),x()):C(m.data&&m.data.error||s("web.settings.save_failed"),!0)})),u.appendChild(k(s("web.settings.cancel"),"dim",()=>x())),t.appendChild(u),t}export async function loadLsp(){const e=await w("/api/lsp");l.lsp=e.ok&&e.data&&Array.isArray(e.data.servers)?e.data.servers:null,S()}export async function loadMemory(){const e=await w("/api/memory");l.memory=e.ok&&e.data?e.data:null,L()}export async function loadSkills(){const e=await w("/api/skills");l.skills=e.ok&&e.data&&Array.isArray(e.data.skills)?e.data.skills:null,M()}export async function loadPlugins(){const e=await w("/api/plugins");l.pluginsData=e.ok&&e.data?{plugins:e.data.plugins||[],mcp:e.data.mcp||[]}:null,S()}export{I as renderUiPanel,L as renderMemoryPanel,M as renderSkillsPanel,S as renderPluginsPanel,z as renderSecurityPanel};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{el as a,icon as I,link as P}from"../dom.js";import{api as S}from"../api.js";import{t as s}from"../i18n.js";import{settings as u}from"../store.js";import{contextLabel as K}from"../format.js";import{setIndicator as _}from"../dialog.js";import{PANEL_SECTIONS as q}from"./controls.js";import{postConfig as R,loadConfig as U}from"./write.js";import{settingsSection as D,chip as k,renderSections as B}from"./panels.js";import{pfield as f,providerInput as C,providerSelect as F,providerCheck as G}from"./form.js";import{openSubDialog as W,closeSubDialog as O}from"./subdialog.js";function j(){if(u.providers&&Array.isArray(u.providers.entries)&&u.providers.entries.length)return u.providers.entries;const e=u.config&&u.config.provider||{};return Array.isArray(e.entries)&&e.entries.length?e.entries.map(t=>({type:t.type,label:t.label||t.type,baseUrl:t.baseUrl,hasApiKey:!!t.apiKey,contextWindow:t.contextWindow,priority:t.priority})):[{type:e.type,label:e.active||e.type,baseUrl:e.baseUrl,hasApiKey:!!e.apiKey}]}function L(e){return e.label||e.type||"—"}function H(e){const t=[e.type];return e.contextWindow&&t.push(Math.round(e.contextWindow/1024)+"K"),(typeof e.rpm=="number"||typeof e.parallel=="number")&&t.push("rpm "+(e.rpm==null?"—":e.rpm)+" · x"+(e.parallel==null?"—":e.parallel)),t.join(" · ")}function V(e){const t=a("div","pform-base"),i=a("select");T.forEach(([p,h])=>{const m=a("option","",p+" — "+h);m.value=h,i.appendChild(m)});const d=a("option","",s("web.settings.provider_baseurl_custom"));d.value=A,i.appendChild(d);const o=C("","text","https://…"),r=new Set(T.map(([,p])=>p)),c=()=>{o.style.display=i.value===A?"":"none"},v={node:t,sel:i,custom:o,get value(){return i.value===A?o.value:i.value},set value(p){p&&r.has(p)?i.value=p:(i.value=A,o.value=p||""),c()},addEventListener(p,h){i.addEventListener(p,h),o.addEventListener(p,h)},setAttribute(p,h){i.setAttribute(p,h)}};return v.value=e?String(e):"",i.addEventListener("change",c),t.appendChild(i),t.appendChild(o),v}const Y=["sessionHeader","requestCachePrompt","requestPromptCacheKey","requestSessionId","requestCacheControl","requestStreamUsage"],z=["openai-compat","lmstudio","openrouter","openai","anthropic","opencode-zen","opencode-go"],T=[["LM Studio","http://localhost:1234/v1"],["Ollama","http://localhost:11434/v1"],["OpenRouter","https://openrouter.ai/api/v1"],["OpenAI","https://api.openai.com/v1"],["Anthropic","https://api.anthropic.com"]],A="__custom__";function X(e){const t=u.providerPresets||[];if(!t.length)return{presets:t,sel:null,node:null};const i=a("select","pform-preset"),d=a("option","",s("web.settings.provider_custom"));d.value="",i.appendChild(d),t.forEach(r=>{const c=a("option","",r.label||r.type);c.value=r.id,i.appendChild(c)});const o=t.find(r=>r.type===e.type&&r.baseUrl&&r.baseUrl===e.baseUrl)||t.find(r=>r.type===e.type&&!r.baseUrl)||t.find(r=>r.type===e.type);return o&&(i.value=o.id),{presets:t,sel:i,node:f("web.settings.provider_preset",i)}}function J(e,t,i,d){t&&(t.addEventListener("change",()=>{const o=e.find(r=>r.id===t.value);o&&(d.type.value=o.type,(i==="add"||!d.label.value.trim())&&(d.label.value=o.name),d.base.value=o.baseUrl||"")}),d.type.addEventListener("input",()=>{const o=e.find(r=>r.id===t.value);(!o||d.type.value.trim()!==o.type)&&(t.value="")}),d.type.addEventListener("change",()=>{const o=e.find(r=>r.id===t.value);(!o||d.type.value.trim()!==o.type)&&(t.value="")}))}function Q(e){const t=a("details","pform-adv");t.appendChild(a("summary","",s("web.settings.provider_advanced")));const i=a("div","pform-grid"),d=e.cache||{},o=e.retry||{},r={ctx:C(e.contextWindow,"number","32768"),prio:C(e.priority,"number","0"),rpm:C(e.rpm,"number","60"),par:C(e.parallel,"number","1"),maxTokens:C(e.maxCompletionTokens,"number","8192"),cacheMech:F(["auto","explicit","local","none"],d.mechanism),cacheReport:F(["openai","deepseek","anthropic","ollama","none"],d.report),retryMax:C(o.maxRetries,"number","3"),retryBase:C(o.baseDelay,"number","1000"),retryMaxD:C(o.maxDelay,"number","30000"),cacheFlags:[]};r.cacheFlags=Y.map(m=>{const y=G(d[m]),l=s("web.settings.provider_flag."+m);y.setAttribute("aria-label",l);const n=a("label","pform-check");return n.title=m,n.appendChild(y),n.appendChild(a("span","",l)),{key:m,box:y,node:n}}),i.appendChild(f("web.settings.provider_context",r.ctx)),i.appendChild(f("web.settings.provider_priority",r.prio)),i.appendChild(f("web.settings.provider_rpm",r.rpm)),i.appendChild(f("web.settings.provider_parallel",r.par)),i.appendChild(f("web.settings.provider_max_tokens",r.maxTokens)),i.appendChild(f("web.settings.provider_cache_mechanism",r.cacheMech)),i.appendChild(f("web.settings.provider_cache_report",r.cacheReport)),t.appendChild(i);const c=a("div","pform-checks");c.appendChild(a("span","pform-checks-title",s("web.settings.provider_retry")));const v=a("div","pform-grid");v.appendChild(f("web.settings.provider_retry_max",r.retryMax)),v.appendChild(f("web.settings.provider_retry_base",r.retryBase)),v.appendChild(f("web.settings.provider_retry_maxdelay",r.retryMaxD)),c.appendChild(v),t.appendChild(c);const p=a("div","pform-checks");p.appendChild(a("span","pform-checks-title",s("web.settings.provider_cache_flags")));const h=a("div","pform-checks-grid");return r.cacheFlags.forEach(({node:m})=>h.appendChild(m)),p.appendChild(h),t.appendChild(p),{node:t,...r}}async function Z(e,t,i){const d=e.type.value.trim(),o=e.base.value.trim();if(!d||!o){_(s("web.settings.provider_required"),!0);return}const r={type:d,baseUrl:o},c=e.label.value.trim();if(c&&(r.label=c),t==="edit"){const n=L(i);n&&n!=="—"&&(r.originalName=n)}const v=e.key.value.trim();v&&v!=="***"&&(r.apiKey=v);const p=[["contextWindow",e.ctx,1024],["priority",e.prio,0],["rpm",e.rpm,1],["parallel",e.par,1],["maxCompletionTokens",e.maxTokens,512,128e3],["maxRetries",e.retryMax,0,10],["baseDelay",e.retryBase,0,6e4],["maxDelay",e.retryMaxD,0,3e5]],h={};for(const n of p){const b=n[1].value.trim();if(!b)continue;const g=Number(b),w=n[3]===void 0?Number.MAX_SAFE_INTEGER:n[3];if(!Number.isInteger(g)||g<n[2]||g>w){_(s("web.settings.provider_invalid"),!0);return}n[0]==="maxRetries"||n[0]==="baseDelay"||n[0]==="maxDelay"?h[n[0]]=g:r[n[0]]=g}Object.keys(h).length&&(r.retry=h);const m={};e.cacheMech.value&&(m.mechanism=e.cacheMech.value),e.cacheReport.value&&(m.report=e.cacheReport.value);const y=i&&i.cache||{};e.cacheFlags.forEach(({key:n,box:b})=>{b.checked!==(y[n]===!0)&&(m[n]=b.checked)}),Object.keys(m).length&&(r.cache=m);const l=await S("/api/providers",{method:"POST",body:r});if(l.ok&&l.data&&l.data.ok){const n=l.data.persisted!==!1;_(n?s("web.settings.saved"):l.data.warning||"not persisted",!n),O(),await loadProviders(),await U()}else{const n=l.data&&l.data.error||"";_(n==="name-conflict"?s("web.settings.provider_name_conflict"):n||s("web.settings.save_failed"),!0)}}function $(){const e=u.providerForm&&u.providerForm.mode||"add",t=u.providerForm&&u.providerForm.entry||{},i=a("div","pform"),{presets:d,sel:o,node:r}=X(t);r&&i.appendChild(r);const c=a("div","pform-grid"),v=F(z,t.type),p=C(t.label,"text","my-provider"),h=V(t.baseUrl),m=C("","password",t.hasApiKey?s("web.settings.provider_key_keep"):"");c.appendChild(f("web.settings.provider_type",v)),c.appendChild(f("web.settings.provider_label_field",p)),c.appendChild(f("web.settings.provider_baseurl",h.node)),c.appendChild(f("web.settings.provider_apikey",m)),i.appendChild(c),J(d,o,e,{type:v,label:p,base:h});const{node:y,...l}=Q(t);i.appendChild(y);const n={type:v,label:p,base:h,key:m,...l},b=a("div","pform-actions");return b.appendChild(P(s("web.settings.save"),"",()=>{Z(n,e,t)})),b.appendChild(P(s("web.settings.cancel"),"dim",()=>ee())),i.appendChild(b),i}export function renderModelPanel(){const e=document.querySelector('[data-panel="model"]');if(!e)return;e.textContent="";const t=u.config||{},i=D("web.settings.section_models"),d=a("input","searchbox");d.placeholder=s("web.settings.search_models"),d.setAttribute("aria-label",s("web.settings.search_models")),i.body.appendChild(d);const o=a("div","model-list");i.body.appendChild(o);const r=()=>{o.textContent="";const y=d.value.trim().toLowerCase(),l=u.models.filter(n=>!y||String(n).toLowerCase().indexOf(y)!==-1);if(!l.length){o.appendChild(a("div","placeholder",u.models.length?s("web.settings.no_matches"):s("web.settings.no_models")));return}l.forEach(n=>{const b=n===t.model,g=a("div","model-item"+(b?" active":"")),w=a("span","m-name",String(n));w.title=String(n),g.appendChild(w),b?g.appendChild(a("span","m-meta",K()+" · "+s("web.settings.active_check"))):g.appendChild(k(s("web.settings.use"),"",()=>{R("model",n,!0)})),o.appendChild(g)})};d.addEventListener("input",r),r(),e.appendChild(i.el);const c=D("web.settings.section_providers"),v=a("button","sec-add");v.type="button",v.setAttribute("aria-haspopup","dialog"),v.appendChild(I("plus")),v.appendChild(a("span","",s("web.settings.add_provider"))),v.addEventListener("click",()=>N("add",null)),c.head.appendChild(v);const p=j().filter(y=>{const l=L(y);return l&&l!=="—"}),h=u.providers&&u.providers.active||t.provider?.active||t.provider?.type||"—",m=a("div","provider-list");p.forEach(y=>{const l=L(y),n=l===h,b=a("div","provider-item"+(n?" active":"")),g=a("div","p-head");g.appendChild(a("span","p-name",l)),n&&g.appendChild(a("span","badge on",s("web.settings.active"))),b.appendChild(g);const w=H(y);w&&b.appendChild(a("div","p-meta",w));const E=a("div","p-actions");n||E.appendChild(k(s("web.settings.provider_make_active"),"",()=>{R("provider.active",l,!0)})),E.appendChild(k(s("web.settings.edit"),"",()=>N("edit",y))),n||E.appendChild(k(s("web.settings.delete"),"danger",async()=>{const x=await S("/api/providers/"+encodeURIComponent(l),{method:"DELETE"});if(x.ok&&x.data&&x.data.ok)_(s("web.settings.saved")),await loadProviders(),await U();else{const M=x.data&&x.data.error||s("web.settings.delete_failed");_(M==="active-provider"?s("web.settings.provider_active_guard"):String(M),!0)}})),b.appendChild(E),m.appendChild(b)}),p.length||m.appendChild(a("div","placeholder",s("web.settings.providers_empty"))),c.body.appendChild(m),e.appendChild(c.el),B("model",q.model||[])}export async function loadProviders(){const e=await S("/api/providers");u.providers=e.ok&&e.data&&Array.isArray(e.data.entries)?e.data:void 0,u.providerPresets=e.ok&&e.data&&Array.isArray(e.data.presets)?e.data.presets:[],renderModelPanel()}function N(e,t){u.providerForm={mode:e,entry:t||null},W(s(e==="edit"?"web.settings.provider_edit_title":"web.settings.provider_add_title"),$(),()=>renderModelPanel())}function ee(){u.providerForm=null,O()}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{el as f,icon as C}from"../dom.js";import{t as k}from"../i18n.js";import{settings as b}from"../store.js";import{keyToPanel as I}from"./controls.js";import{configLabel as y,descFor as S,defFor as L}from"./panels.js";import{selectSettingsPanel as A}from"./modal.js";const h=document.getElementById("setMenu"),c=document.getElementById("setSearch"),d=document.getElementById("setSearchClear"),w=document.getElementById("setSearchIcon"),s=document.getElementById("setResults");w&&w.appendChild(C("search","set-search-svg"));function B(){const e=I();return(b.registry||[]).filter(t=>t&&typeof t.key=="string").map(t=>{const r=y(t),n=S(t.key);return{def:t,panel:e.get(t.key)||"",label:r,desc:n,haystack:`${r} ${t.key} ${n}`.toLowerCase()}}).filter(t=>t.panel)}let l=[],i=-1;function m(){c&&(c.value=""),s&&(s.hidden=!0,s.textContent=""),h&&(h.hidden=!1),d&&(d.hidden=!0),l=[],i=-1}function R(e,t){const r=document.getElementById("p-"+e);if(!r)return;const n=Array.from(r.querySelectorAll(".row")),p=L(t);if(!p)return;const o=y(p),a=n.find(u=>{const g=u.querySelector(".row-name");return g&&g.textContent===o});a&&(a.scrollIntoView({block:"center"}),a.classList.add("row-flash"),setTimeout(()=>a.classList.remove("row-flash"),1200))}function E(e){!e||!e.panel||(m(),A(e.panel),R(e.panel,e.def.key))}function x(e){if(!s)return;const t=e.trim().toLowerCase();if(!t){m();return}const r=B().filter(n=>n.haystack.includes(t));if(s.textContent="",!r.length){const n=f("div","set-results-empty",k("web.settings.search_empty"));s.appendChild(n)}l=r.slice(0,40),i=l.length?0:-1,l.forEach((n,p)=>{const o=f("div","set-result"+(p===i?" on":""));o.setAttribute("role","option"),o.tabIndex=-1,o.appendChild(f("span","sr-label",n.label));const a=k("web.settings."+n.panel);o.appendChild(f("span","sr-panel",a==="web.settings."+n.panel?n.panel:a));const u=f("span","sr-key",n.def.key);u.title=n.def.key,o.appendChild(u),o.addEventListener("click",()=>E(n)),s.appendChild(o)}),s.hidden=!1,h&&(h.hidden=!0),d&&(d.hidden=!1)}function v(e){if(!l.length||!s)return;i=(i+e+l.length)%l.length,Array.from(s.children).forEach((r,n)=>r.classList.toggle("on",n===i));const t=s.children[i];t&&t.scrollIntoView({block:"nearest"})}c&&(c.addEventListener("input",()=>x(c.value)),c.addEventListener("keydown",e=>{e.key==="ArrowDown"?(e.preventDefault(),v(1)):e.key==="ArrowUp"?(e.preventDefault(),v(-1)):e.key==="Enter"?(e.preventDefault(),E(l[i])):e.key==="Escape"&&c.value&&(e.stopPropagation(),m())})),d&&d.addEventListener("click",m);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export*from"../subdialog.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{el as l,icon as A,link as _,connStatus as L,staleBar as w}from"../dom.js";import{api as k}from"../api.js";import{t as r,loadI18n as W}from"../i18n.js";import{settings as p,session as q,setPath as D,getPath as N,hooks as R}from"../store.js";import{contextLabel as z,matchesQuery as F}from"../format.js";import{closeAllMenus as v,setSessOpen as K}from"../core/menus.js";import{setIndicator as B}from"../dialog.js";import{setLayout as G}from"../rail.js";function S(e,n,o){e&&(e.textContent=n+":",e.appendChild(l("b","",o)),e.appendChild(A("chevron-down")))}function x(e,n,o,t){const i=l("button","mi"+(o?" on":""));return i.type="button",i.setAttribute("aria-pressed",o?"true":"false"),i.appendChild(l("span","",e)),n&&i.appendChild(l("span","sub",n)),i.addEventListener("click",s=>{s.stopPropagation(),t(),v()}),i}function O(e,n,o){const t=l("button","mi row-mi");return t.type="button",n&&t.appendChild(A(n)),t.appendChild(l("span","",e)),t.addEventListener("click",i=>{i.stopPropagation(),v(),o()}),t}let C="";export function renderSelectors(){const e=p.config||{},n=e.provider||{};S(document.getElementById("selModelBtn"),r("web.selectors.model"),e.model||"—");const o=document.getElementById("selModelMenu");o.textContent="";const t=document.createElement("input");t.id="selModelSearch",t.className="searchbox",t.type="search",t.autocomplete="off",t.spellcheck=!1,t.placeholder=r("web.selectors.search_models"),t.setAttribute("aria-label",r("web.selectors.search_models")),t.value=C,t.addEventListener("click",a=>a.stopPropagation()),o.appendChild(t);const i=l("div","model-menu-list");o.appendChild(i);const s=()=>{i.textContent="";const a=p.models.filter(d=>F(d,C));if(!a.length){i.appendChild(l("div","mi dim",p.models.length?r("web.settings.no_matches"):r("web.selectors.no_models")));return}a.forEach(d=>{const c=x(String(d),"",d===e.model,()=>{C="",postConfig("model",d,!0)});c.addEventListener("keydown",g=>{g.key==="ArrowUp"&&c===i.querySelector(".mi:not(.dim)")&&(g.preventDefault(),g.stopPropagation(),t.focus())}),i.appendChild(c)})};t.addEventListener("input",()=>{C=t.value,s()}),t.addEventListener("keydown",a=>{if(a.stopPropagation(),a.key==="ArrowDown"){a.preventDefault();const d=i.querySelector(".mi:not(.dim)");d&&d.focus()}else if(a.key==="Enter"){a.preventDefault();const d=i.querySelector(".mi:not(.dim)");d&&d.click()}else a.key==="Escape"&&(t.value?(a.preventDefault(),t.value="",C="",s()):v())}),s(),o.appendChild(l("div","sep")),o.appendChild(O(r("web.selectors.refresh_list"),"refresh",()=>{loadModels().then(renderSelectors)})),S(document.getElementById("selProviderBtn"),r("web.selectors.provider"),n.active||n.type||"—");const u=document.getElementById("selProviderMenu");u.textContent="",(Array.isArray(n.entries)&&n.entries.length?n.entries:[{label:n.active||n.type,type:n.type}]).forEach(a=>{const d=a.label||a.type;d&&u.appendChild(x(d,a.type||"",d===(n.active||n.type),()=>{postConfig("provider.active",d,!0)}))}),S(document.getElementById("selContextBtn"),r("web.selectors.context"),z());const m=document.getElementById("selContextMenu");m.textContent="",[8192,16384,32768,65536,131072].forEach(a=>{m.appendChild(x(Math.round(a/1024)+"K",a===e.contextWindow?r("web.selectors.current"):"",a===e.contextWindow,()=>{postConfig("contextWindow",a,!1)}))}),m.appendChild(l("div","sep"));const y=l("button","mi row-mi");y.type="button",y.appendChild(A("settings")),y.appendChild(l("span","",r("web.selectors.custom"))),y.addEventListener("click",a=>{if(a.stopPropagation(),m.querySelector(".ctx-custom"))return;const d=l("div","ctx-custom"),c=l("input");c.type="number",c.min="1024",c.step="1024",c.value=String(e.contextWindow||32768),c.placeholder=r("web.selectors.context_prompt"),c.setAttribute("aria-label",r("web.selectors.context_prompt"));const g=()=>{const f=Number(c.value.trim());Number.isFinite(f)&&f>=1024?(v(),postConfig("contextWindow",f,!1)):c.focus()};c.addEventListener("click",f=>f.stopPropagation()),c.addEventListener("keydown",f=>{f.stopPropagation(),f.key==="Enter"?(f.preventDefault(),g()):f.key==="Escape"&&d.remove()});const T=_(r("web.settings.save"),"",g);d.appendChild(c),d.appendChild(T),m.appendChild(d),setTimeout(()=>c.focus(),0)}),m.appendChild(y),V(),P()}const H=["auto","default","none","low","medium","high","max"],U=["auto","default","none","low","high"];function V(){const e=document.querySelector('[data-sel="reasoning"]'),n=document.getElementById("selReasoningBtn"),o=document.getElementById("selReasoningMenu");if(!e||!n||!o)return;const t=q.reasoning;if(!t||t.strategy==="none"){e.hidden=!0;return}if(e.hidden=!1,t.supported===!1){S(n,r("web.selectors.reasoning"),r("web.selectors.reasoning_off")),o.textContent="",o.appendChild(l("div","mi dim",r("reasoning.probe_failed"))),o.appendChild(l("div","sep")),o.appendChild(O(r("web.settings.reasoning"),"settings",()=>h.openSettingsAt?.("reasoning")));return}const i=p.config&&N(p.config,"reasoning.mode")||t.mode||"auto";S(n,r("web.selectors.reasoning"),String(i)),o.textContent="",(t.strategy==="openai-effort"?H:U).forEach(u=>{o.appendChild(x(u,u===i?r("web.selectors.current"):"",u===i,()=>{postConfig("reasoning.mode",u,!1)}))})}document.querySelectorAll("[data-sel]").forEach(e=>{const n=e.querySelector("button");n&&(n.setAttribute("aria-haspopup","menu"),n.setAttribute("aria-expanded","false"),n.addEventListener("click",o=>{o.stopPropagation(),K(!1),document.querySelectorAll("[data-sel]").forEach(i=>{if(i!==e){i.classList.remove("open");const s=i.querySelector("button");s&&s.setAttribute("aria-expanded","false")}});const t=e.classList.toggle("open");if(n.setAttribute("aria-expanded",t?"true":"false"),t&&e.dataset&&e.dataset.sel==="model"){const i=document.getElementById("selModelSearch");i&&setTimeout(()=>i.focus(),0)}}))});const j=["provider.active","model","contextWindow","reasoning.mode"];let I=0,E=null,h={renderSettings:null,openSettingsAt:null};export function setWriteHooks(e){h={...h,...e}}function P(){const e=E!==null||!p.config,n=document.querySelector(".selectors");n&&(e?n.setAttribute("data-pending",E||"boot"):n.removeAttribute("data-pending")),["selProviderBtn","selModelBtn","selContextBtn","selReasoningBtn"].forEach(o=>{const t=document.getElementById(o);t&&(t.classList.toggle("pending",e),t.setAttribute("aria-busy",e?"true":"false"))})}export async function postConfig(e,n,o){const t=j.indexOf(e)!==-1;if(t&&E!==null)return B(r("web.selectors.switch_busy"),!0),!1;let i=0;t&&(i=++I,E=e,v(),P());try{const s=await k("/api/config",{method:"POST",body:{key:e,value:n}});if(!s.ok||!s.data||!s.data.ok){const M=s.data&&(s.data.error||s.data.reason)||s.status||r("web.settings.save_failed");return B(String(M),!0),!1}const u=s.data.persisted!==!1;return B(u?r("web.settings.saved"):s.data.warning||"not persisted",!u),p.config&&s.data.value!==void 0&&D(p.config,e,s.data.value),e==="ui.activityRail"&&G(String(s.data.value)),e==="ui.fontSize"&&applyFontSize(String(s.data.value)),e==="locale"&&(await W(),R.applyStaticI18n&&R.applyStaticI18n(),h.renderSettings?.()),e==="provider.active"||e==="model"?await Promise.all([loadConfig(),loadModels()]):t&&await loadConfig(),t&&i!==I||(renderSelectors(),o&&h.renderSettings?.()),!0}finally{t&&i===I&&(E=null,P())}}export async function loadConfig(){const e=await k("/api/config");!e.ok||!e.data||(p.config=e.data.config||{},p.registry=Array.isArray(e.data.registry)?e.data.registry:[],p.webToken=typeof e.data.webToken=="string"?e.data.webToken:null,applyFontSize(),renderSelectors(),h.renderSettings?.())}export async function loadModels(){const e=await k("/api/models");!e.ok||!e.data||(p.models=Array.isArray(e.data.models)?e.data.models:[],e.data.reasoning&&typeof e.data.reasoning=="object"&&(q.reasoning=e.data.reasoning),renderSelectors())}export function setConnStatus(e){L&&(L.hidden=!e,L.textContent=e?"⋯ "+r("web.conn.reconnecting"):"")}let b=null;export function setStaleBar(e,n){if(!w)return null;const o=e===void 0?!!b:!!e;return!n&&o===b||(b=o,w.hidden=!o,w.textContent="",!o)||(w.appendChild(l("span","","⚠ "+r("web.i18n.stale")+" ")),w.appendChild(_(r("web.i18n.reload"),"",()=>location.reload()))),b}export function applyFontSize(e){const n=e||p.config&&p.config.ui&&p.config.ui.fontSize||"comfortable",o=n==="compact"||n==="large"?n:"comfortable";o==="comfortable"?document.body.removeAttribute("data-font"):document.body.setAttribute("data-font",o)}
|