@lynn123411/dsh-subagent-judge-dispatch 0.1.1 → 0.1.3
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/DETAILS.md +1 -1
- package/lib/client.js.map +1 -1
- package/package.json +15 -14
package/DETAILS.md
CHANGED
|
@@ -58,7 +58,7 @@ cd ~/.dsh/profiles/web && pnpm add "link:<my-dsh 绝对路径>/plugins/dsh-subag
|
|
|
58
58
|
cd <my-dsh 绝对路径>/plugins/dsh-subagent-judge-dispatch && pnpm install && pnpm build
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
客户端半边改完刷新页面即生效,必要时强制刷新一次;宿主半边改完要触发一次 profile 重新组合——在插件页或 `plugin_manager` 里把本插件关一次再开一次,不必重启进程。
|
|
62
62
|
|
|
63
63
|
## 验证
|
|
64
64
|
|
package/lib/client.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/client/index.ts", "../src/client/settings/ui.tsx", "../src/client/settings/plugin-page.ts", "../src/server/judge-prompt.ts", "../src/server/credentials.ts", "../src/client/settings/store.ts", "../src/client/locales.ts"],
|
|
4
|
-
"sourcesContent": ["import type { Context as ClientContext } from '@deepseek-ai/cordis';\n// \u7C7B\u578B\u53EA\u8BFB\uFF1A\u8FD9\u4E9B\u5305\u7684\u6D4F\u89C8\u5668\u534A\u8FB9\u628A\u5EA7\u4F4D\u5951\u7EA6\u4E0E `ctx.configForms` \u5408\u5E76\u8FDB Context\u3002\nimport type {} from '@deepseek-ai/dsh-client-locale/client';\nimport type {} from '@deepseek-ai/dsh-client-ui-renderer/client';\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client';\nimport { injectCardStyles, setupSettingsUi } from './settings/ui.tsx';\nimport { apply as registerDictionaries, en, NS, zh } from './locales.ts';\n\n/**\n * \u6D4F\u89C8\u5668\u534A\u8FB9\uFF1A\u628A\u914D\u7F6E\u5361\u7247\u6302\u5230\u5BBF\u4E3B\u7684\u300C\u63D2\u4EF6\u300D\u9875\u4E0A\u3002\n *\n * `inject` \u662F cordis \u670D\u52A1\u540D\uFF08`remote.credentials` \u662F\u5224\u65AD\u5BC6\u94A5\u7684\u5199\u5165\u901A\u9053\uFF09\uFF1B\n * `package.json` \u7684 `dsh.client.inject` \u662F\u5305\u540D\u3002\n * \u4E24\u5C42\u90FD\u8981\u58F0\u660E\uFF0C\u6F0F\u4E00\u5C42\u6574\u6761 loader entry \u4F1A\u9759\u9ED8\u53D8\u6210 failed\uFF0C\u9875\u9762\u4E0A\u4EC0\u4E48\u4E5F\u770B\u4E0D\u89C1\n * \uFF08\u89C1 docs/rules/client-wiring.md\uFF09\u3002\n */\nexport const name = '@lynn123411/dsh-subagent-judge-dispatch';\nexport const inject = ['slots', 'configForms', 'remote', 'remote.session', 'remote.credentials', 'locale'];\n\n/**\n * \u63D2\u4EF6\u672C\u4F53\uFF1A\u6CE8\u518C\u5B57\u5178\uFF0C\u518D\u6302\u914D\u7F6E\u5361\u7247\u3002\n * @param ctx - \u5BA2\u6237\u7AEF\u6839\u4E0A\u4E0B\u6587\u3002\n */\nexport function apply(ctx: ClientContext): void {\n injectCardStyles();\n registerDictionaries(ctx);\n ctx.effect(\n () => {\n setupSettingsUi(ctx as never);\n return () => {};\n },\n 'dsh-subagent-judge-dispatch: plugins page config',\n );\n}\n\nexport { NS } from './locales.ts';\nexport { en, zh } from './locales.ts';\n\n/** \u5B57\u5178\u672C\u4F53\uFF0C\u968F bundle \u5BFC\u51FA\u4F9B\u81EA\u68C0\u6838\u5BF9\u952E\u96C6\u3002 */\nexport const __dictionaries = { en, zh };\nexport { JudgeDispatchPanel, injectCardStyles, setupSettingsUi } from './settings/ui.tsx';\nexport {\n ALLOWED_MODELS_NAMESPACE,\n buildModelOptions,\n createDispatchRemote,\n dispatchCardStore,\n readRow,\n SETTINGS_NAMESPACE,\n validateRows,\n} from './settings/store.ts';\n", "import { useEffect, useState } from 'react';\nimport * as React from 'react';\nimport type { PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';\nimport {\n Button,\n CodeBlock,\n Input,\n Menu,\n Modal,\n SegmentedTabs,\n Switch,\n Tag,\n} from '@deepseek-ai/dsh-client-ui-primitives';\nimport {\n BUNDLE_CONFIG_KEY,\n BUNDLE_CONFIG_SLOT,\n setupPluginPage,\n} from './plugin-page.ts';\nimport {\n ALLOWED_MODELS_NAMESPACE,\n createDispatchRemote,\n dispatchCardStore,\n JUDGE_API_KEY_REF,\n type CredentialsRemoteLike,\n routeKey,\n SETTINGS_NAMESPACE,\n splitRouteKey,\n type LogRow,\n type PageState,\n type Section,\n type TypeRowDraft,\n} from './store.ts';\nimport { NS } from '../locales.ts';\n\n/** The ready-made entries, each with the effort hint it ships. */\nconst PRESETS: readonly { key: string; effortHint: string }[] = [\n { key: 'mechanical', effortHint: 'preset.effortLow' },\n { key: 'research', effortHint: 'preset.effortLow' },\n { key: 'smallFeature', effortHint: 'preset.effortMedium' },\n { key: 'spec', effortHint: 'preset.effortHigh' },\n { key: 'review', effortHint: 'preset.effortMedium' },\n { key: 'debug', effortHint: 'preset.effortHigh' },\n { key: 'design', effortHint: 'preset.effortHigh' },\n { key: 'test', effortHint: 'preset.effortLow' },\n];\n\n/** Path shown in the key hint; the value itself never reaches the page. */\nconst CREDENTIALS_PATH = '~/.dsh/.credentials.yaml';\n\n/** One localized template with technical samples rendered inline. */\nfunction withSamples(text: string, samples: Record<string, string>): React.ReactNode {\n return text.split(/(\\{\\w+\\})/g).map((part, index) => {\n const name = /^\\{\\w+\\}$/.test(part) ? part.slice(1, -1) : '';\n const sample = name === '' ? undefined : samples[name];\n return sample === undefined ? part : <code key={index}>{sample}</code>;\n });\n}\n\n/**\n * The card's own styles.\n *\n * Only the shapes the Host's controls do not carry: the settings-card material\n * (R20, the settings stroke and fill), the section and field rows, and the\n * task-type table. Every colour resolves through a `--dsw-alias-*` token, and\n * every elevated surface uses the settings-card material rather than a border\n * plus a shadow.\n */\nconst CARD_CSS = `\n.dsh-judge-card { display: flex; flex-direction: column; gap: 16px; box-sizing: border-box; width: 100%; max-width: 760px; color: var(--dsw-alias-label-primary); }\n.dsh-judge-panel { display: flex; flex-direction: column; gap: 16px; }\n.dsh-judge-section {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 16px 18px;\n border: 0.5px solid var(--dsw-alias-settings-card-stroke);\n border-radius: var(--dsw-radius-xl);\n background: var(--dsw-alias-settings-card-fill);\n}\n.dsh-judge-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }\n.dsh-judge-title { font: var(--dsw-font-s-strong-14); }\n.dsh-judge-desc { max-width: 46em; color: var(--dsw-alias-label-tertiary); font: var(--dsw-font-xxs-12); }\n.dsh-judge-desc code { font-family: var(--ds-font-family-code); }\n.dsh-judge-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 24px; }\n.dsh-judge-row + .dsh-judge-row { padding-top: 12px; border-top: 0.5px solid var(--dsw-alias-border-l3); }\n.dsh-judge-row-info { flex: 1; min-width: 0; }\n.dsh-judge-row-title { font: var(--dsw-font-xs-strong-13); }\n.dsh-judge-row-hint { margin-top: 2px; color: var(--dsw-alias-label-tertiary); font: var(--dsw-font-xxs-12); }\n.dsh-judge-row-field { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; box-sizing: border-box; width: 360px; max-width: 100%; }\n/* \u5BBF\u4E3B\u7684 Input \u628A\u8F93\u5165\u6846\u5305\u5728\u4E00\u5C42 inline-flex \u7684 span \u91CC\uFF0C\u7C7B\u540D\u843D\u5728\u90A3\u5C42 span \u4E0A\uFF0C\n \u6240\u4EE5\u8981\u6491\u7684\u662F\u5B83\uFF0C\u53EA\u7ED9 input \u5199\u5BBD\u5EA6\u6CA1\u7528\u3002 */\n.dsh-judge-field { display: flex; box-sizing: border-box; width: 100%; min-width: 0; }\n.dsh-judge-field input { box-sizing: border-box; width: 100%; min-width: 0; }\n.dsh-judge-key-line { display: flex; align-items: center; gap: 8px; box-sizing: border-box; width: 100%; }\n.dsh-judge-off { display: block; color: var(--dsw-alias-state-warn-label); font: var(--dsw-font-xxxs-11); white-space: nowrap; }\n.dsh-judge-head-actions { display: flex; align-items: center; gap: 8px; }\n.dsh-judge-actions { display: flex; align-items: center; justify-content: flex-start; gap: 8px; padding-top: 12px; border-top: 0.5px solid var(--dsw-alias-border-l3); }\n.dsh-judge-hint { color: var(--dsw-alias-label-tertiary); font: var(--dsw-font-xxs-12); }\n.dsh-judge-note-ok { color: var(--dsw-alias-state-success-primary); font: var(--dsw-font-xxs-12); }\n.dsh-judge-note-bad { color: var(--dsw-alias-state-error-primary); font: var(--dsw-font-xxs-12); }\n.dsh-judge-field-wrap { display: flex; box-sizing: border-box; width: 100%; min-width: 0; }\n.dsh-judge-table { box-sizing: border-box; width: 100%; border-collapse: collapse; table-layout: fixed; }\n.dsh-judge-table th, .dsh-judge-table td { box-sizing: border-box; }\n.dsh-judge-table th {\n padding: 0 8px 6px 0;\n color: var(--dsw-alias-label-tertiary);\n font: var(--dsw-font-xxs-12);\n text-align: left;\n}\n.dsh-judge-table td { padding: 6px 8px 6px 0; vertical-align: middle; }\n.dsh-judge-table tbody tr + tr td { border-top: 0.5px solid var(--dsw-alias-border-l3); }\n.dsh-judge-table td:last-child, .dsh-judge-table th:last-child { padding-right: 0; }\n.dsh-judge-col-no { width: 52px; }\n.dsh-judge-col-model { width: 188px; }\n.dsh-judge-col-effort { width: 124px; }\n.dsh-judge-col-actions { width: 148px; }\n.dsh-judge-no { color: var(--dsw-alias-label-tertiary); font: var(--dsw-font-xxs-12); font-variant-numeric: tabular-nums; }\n.dsh-judge-row-off .dsh-judge-field { opacity: 0.6; }\n.dsh-judge-cell-actions { display: flex; gap: 6px; }\n.dsh-judge-presets { display: flex; flex-wrap: wrap; gap: 6px; }\n.dsh-judge-preset { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; padding: 6px 10px; border: 0.5px solid var(--dsw-alias-border-l3); border-radius: var(--dsw-radius-md); background: none; color: inherit; font: inherit; text-align: left; cursor: pointer; }\n.dsh-judge-preset:hover { background: var(--dsw-alias-interactive-bg-hover); }\n.dsh-judge-preset-title { font: var(--dsw-font-xs-13); }\n.dsh-judge-preset-hint { color: var(--dsw-alias-label-tertiary); font: var(--dsw-font-xxxs-11); }\n.dsh-judge-log { display: flex; flex-direction: column; gap: 4px; font: var(--dsw-font-xxs-12); }\n.dsh-judge-log-row { display: grid; grid-template-columns: 130px minmax(0, 1fr) 80px 92px 84px; gap: 8px; align-items: center; text-align: left; border: 0; background: none; padding: 6px 4px; border-radius: var(--dsw-radius-sm); cursor: pointer; color: inherit; }\n.dsh-judge-cell-clip { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.dsh-judge-log-row:hover { background: var(--dsw-alias-interactive-bg-hover); }\n.dsh-judge-log-head { font-weight: 600; color: var(--dsw-alias-label-tertiary); cursor: default; }\n.dsh-judge-log-head:hover { background: none; }\n.dsh-judge-detail { display: grid; grid-template-columns: 140px 1fr; gap: 6px 12px; font: var(--dsw-font-xs-13); }\n/* \u9884\u89C8\u91CC\u662F\u4E00\u6574\u6BB5 JSON\uFF0C\u9ED8\u8BA4\u7684\u5F39\u7A97\u5BBD\u5EA6\u4F1A\u628A\u5B83\u6298\u5F97\u5F88\u788E\u3002 */\n.dsh-judge-modal { width: min(760px, 100%); max-height: min(85vh, 100%); }\n`;\n\n/**\n * Append this card's stylesheet once, at apply() time.\n *\n * Injection happens here rather than on first render because the host's own\n * stylesheets are already-loaded `<link>` elements: a plugin sheet appended\n * later wins at equal specificity, and doing it once in apply() keeps that\n * order stable across remounts. The id makes the append idempotent.\n */\nexport function injectCardStyles(): void {\n if (typeof document === 'undefined') return;\n if (document.getElementById(STYLE_ID) !== null) return;\n const element = document.createElement('style');\n element.id = STYLE_ID;\n element.textContent = CARD_CSS;\n document.head.appendChild(element);\n}\n\n/** DOM id of this card's stylesheet, so a remount does not append a second one. */\nconst STYLE_ID = 'dsh-subagent-judge-dispatch-styles';\n\n/**\n * This plugin's configuration card inside the DSH **Plugins** page.\n *\n * Two tabs. The design tab holds two independently saved sections \u2014 the\n * judgement service, and the task-type table \u2014 because each is edited on its own\n * occasion and fails on its own terms; a single save for both would let an\n * unfinished description block an endpoint change. The log tab reads the Host's\n * runtime log. Nothing is written while the reader types.\n *\n * @param props - the renderer-bound seat of `plugins.bundle.config`.\n * @returns the card element.\n */\nexport function JudgeDispatchPanel(\n props: PropsRuntime<'plugins.bundle.config'> & PropsLocale<typeof NS>,\n): React.ReactElement {\n const { t } = props;\n\n const [state, setState] = useState<PageState>(() => dispatchCardStore.getState());\n const [tab, setTab] = useState<'design' | 'log'>('design');\n const [browsing, setBrowsing] = useState<number | null>(null);\n const [preview, setPreview] = useState<string | null>(null);\n const [previewOpen, setPreviewOpen] = useState(false);\n const [probing, setProbing] = useState(false);\n const [probeResult, setProbeResult] = useState<{ ok: boolean; latencyMs: number; reason?: string } | null>(null);\n const [detail, setDetail] = useState<LogRow | null>(null);\n /** Which row's dropdown is open, and which of the two. */\n const [openMenu, setOpenMenu] = useState<{ index: number; kind: 'model' | 'effort' } | null>(null);\n /** The reason a save was refused, shown as a popup. */\n const [refusal, setRefusal] = useState<string | null>(null);\n\n useEffect(() => {\n setState(dispatchCardStore.getState());\n return dispatchCardStore.subscribe(() => setState(dispatchCardStore.getState()));\n }, []);\n\n useEffect(() => {\n if (tab === 'log') void dispatchCardStore.refreshLog();\n }, [tab]);\n\n /** Localized reason text for one fallback. */\n const reasonText = (reason: string | undefined): string =>\n t(`reason.${reason ?? 'other'}` as never) || t('reason.unknown');\n\n const runProbe = async (): Promise<void> => {\n setProbing(true);\n setProbeResult(await dispatchCardStore.probe());\n setProbing(false);\n };\n\n /** \u7C7B\u578B\u6E05\u5355\u6709\u7F3A\u65F6\u6309\u6309\u94AE\u4E0D\u7ED9\u5199\uFF1A\u628A\u539F\u56E0\u5F39\u51FA\u6765\uFF0C\u800C\u4E0D\u662F\u8BA9\u6309\u94AE\u70B9\u4E0D\u52A8\u3002 */\n const saveRows = (): void => {\n if (state.rowsInvalid !== '') {\n setRefusal(state.rowsInvalid);\n return;\n }\n void dispatchCardStore.save('rows');\n };\n\n const openPreview = async (): Promise<void> => {\n const text = await dispatchCardStore.preview();\n setPreview(text ?? t('preview.failed'));\n setPreviewOpen(true);\n };\n\n /** One section's save row: the write, the discard, and what a save would do. */\n const saveRow = (section: Section, dirty: boolean, onSave: () => void): React.ReactElement => (\n <div className=\"dsh-judge-actions\">\n {/* \u7C7B\u578B\u6E05\u5355\u6709\u7F3A\u65F6\u6309\u94AE\u4ECD\u53EF\u70B9\uFF1A\u6309\u4E0B\u53BB\u7531 saveRows \u5F39\u7A97\u8BF4\u660E\u4E3A\u4EC0\u4E48\u5B58\u4E0D\u4E86\u3002\n \u505A\u6210 disabled \u7684\u8BDD\uFF0C\u8BFB\u8005\u53EA\u770B\u5230\u4E00\u4E2A\u70B9\u4E0D\u52A8\u7684\u6309\u94AE\uFF0C\u4E0D\u77E5\u9053\u8981\u6539\u54EA\u91CC\u3002 */}\n <Button\n variant=\"primary\"\n size=\"sm\"\n disabled={state.saving !== '' || !dirty || !state.writable}\n onClick={onSave}\n >\n {state.saving === section ? t('save.saving') : t('save.button')}\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={state.saving !== '' || !dirty}\n onClick={() => dispatchCardStore.revert(section)}\n >\n {t('save.discard')}\n </Button>\n {dirty && <span className=\"dsh-judge-hint\">{t('save.unsaved')}</span>}\n {/* \u5931\u8D25\u6309\u8282\u62A5\uFF1A\u5224\u65AD\u670D\u52A1\u90A3\u6B21\u4FDD\u5B58\u6CA1\u843D\u5730\u65F6\uFF0C\u4EFB\u52A1\u7C7B\u578B\u90A3\u4E00\u8282\u4E0D\u8BE5\u8DDF\u7740\u62A5\u9519\u3002 */}\n {state.saveFailed === section && state.saveError !== '' && (\n <span className=\"dsh-judge-note-bad\" role=\"alert\">\n {t('save.failed').replace('{error}', state.saveError)}\n </span>\n )}\n </div>\n );\n\n /** One task-type row as three cells plus its row number and its actions. */\n const row = (draft: TypeRowDraft, index: number): React.ReactElement => {\n const efforts = dispatchCardStore.effortsFor(draft);\n const usable = dispatchCardStore.rowUsable(draft);\n // \u53EA\u6709\u300C\u76EE\u5F55\u8BFB\u5230\u4E86\u3001\u4E14\u8FD9\u4E2A\u8DEF\u7531\u786E\u5B9E\u58F0\u660E\u4E86\u6863\u4F4D\u300D\u65F6\u624D\u7ED9\u4E0B\u62C9\uFF1B\u5426\u5219\u81EA\u7531\u586B\u5199\u3002\n const catalogOffersEffort = state.catalogRead && efforts.length > 0;\n return (\n <tr key={index} className={usable ? undefined : 'dsh-judge-row-off'}>\n <td className=\"dsh-judge-col-no\">\n <span className=\"dsh-judge-no\">{index + 1}</span>\n {usable ? null : <span className=\"dsh-judge-off\">{t('rows.incomplete')}</span>}\n </td>\n <td>\n <Input\n type=\"text\"\n className=\"dsh-judge-field\"\n value={draft.description}\n placeholder={t('rows.descriptionPlaceholder')}\n aria-label={`${t('rows.colDescription')} ${index + 1}`}\n onChange={(event: React.ChangeEvent<HTMLInputElement>) =>\n dispatchCardStore.cell(index, 'description', event.target.value)}\n />\n </td>\n <td>\n <Menu\n open={openMenu?.index === index && openMenu.kind === 'model'}\n anchor={<Input\n type=\"text\"\n className=\"dsh-judge-field\"\n readOnly\n value={draft.model === '' ? '' : `${draft.provider}/${draft.model}`}\n placeholder={t('rows.modelPlaceholder')}\n aria-label={`${t('rows.colModel')} ${index + 1}`}\n aria-haspopup=\"listbox\"\n aria-expanded={openMenu?.index === index && openMenu.kind === 'model'}\n onClick={() => setOpenMenu({ index, kind: 'model' })}\n onFocus={() => setOpenMenu({ index, kind: 'model' })}\n />}\n items={[\n { type: 'label', id: 'model', text: t('rows.colModel') },\n ...(state.models.length === 0\n ? []\n : state.models.map((option) => ({\n id: routeKey(option.provider, option.model),\n label: `${option.provider}/${option.label}`,\n }))),\n ]}\n selectedId={draft.model === '' ? undefined : routeKey(draft.provider, draft.model)}\n onSelect={(id) => {\n const { provider, model } = splitRouteKey(id);\n dispatchCardStore.cell(index, 'provider', provider);\n dispatchCardStore.cell(index, 'model', model);\n setOpenMenu(null);\n }}\n onClose={() => setOpenMenu(null)}\n className=\"dsh-judge-field-wrap\"\n portal\n />\n </td>\n {/* \u76EE\u5F55\u8BFB\u5F97\u5230\u65F6\uFF0C\u5F3A\u5EA6\u662F\u8FD9\u4EFD\u53EF\u9009\u6863\u4F4D\u91CC\u7684\u4E00\u4E2A\uFF1B\u8BFB\u4E0D\u5230\uFF08\u6216\u8FD9\u4E2A\u8DEF\u7531\u6CA1\u58F0\u660E\u6863\u4F4D\uFF09\n \u65F6\u9000\u56DE\u81EA\u7531\u586B\u5199\u2014\u2014\u628A\u683C\u5B50\u7981\u6389\u4F1A\u8BA9\u6574\u5F20\u8868\u6C38\u8FDC\u586B\u4E0D\u5168\uFF0C\u4E5F\u5C31\u6C38\u8FDC\u4E0D\u518D\u5224\u65AD\u4EFB\u4F55\u4E1C\u897F\u3002 */}\n <td>\n {catalogOffersEffort ? (\n <Menu\n open={openMenu?.index === index && openMenu.kind === 'effort'}\n anchor={<Input\n type=\"text\"\n className=\"dsh-judge-field\"\n readOnly\n value={draft.effort}\n placeholder={t('rows.effortPlaceholder')}\n aria-label={`${t('rows.colEffort')} ${index + 1}`}\n aria-haspopup=\"listbox\"\n aria-expanded={openMenu?.index === index && openMenu.kind === 'effort'}\n onClick={() => setOpenMenu({ index, kind: 'effort' })}\n onFocus={() => setOpenMenu({ index, kind: 'effort' })}\n />}\n items={[\n { type: 'label', id: 'effort', text: t('rows.colEffort') },\n ...efforts.map((effort) => ({ id: effort, label: effort })),\n ]}\n selectedId={draft.effort === '' ? undefined : draft.effort}\n onSelect={(id) => {\n dispatchCardStore.cell(index, 'effort', id);\n setOpenMenu(null);\n }}\n onClose={() => setOpenMenu(null)}\n className=\"dsh-judge-field-wrap\"\n portal\n />\n ) : (\n <Input\n type=\"text\"\n className=\"dsh-judge-field\"\n value={draft.effort}\n placeholder={t('rows.effortPlaceholder')}\n aria-label={`${t('rows.colEffort')} ${index + 1}`}\n onChange={(event: React.ChangeEvent<HTMLInputElement>) =>\n dispatchCardStore.cell(index, 'effort', event.target.value)}\n />\n )}\n </td>\n <td className=\"dsh-judge-col-actions\">\n <div className=\"dsh-judge-cell-actions\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n aria-label={`${t('rows.browse')} ${index + 1}`}\n onClick={() => setBrowsing(index)}\n >\n {t('rows.browse')}\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n aria-label={`${t('rows.remove')} ${index + 1}`}\n onClick={() => dispatchCardStore.removeRow(index)}\n >\n {t('rows.remove')}\n </Button>\n </div>\n </td>\n </tr>\n );\n };\n\n const design = (\n <div className=\"dsh-judge-panel\">\n <div className=\"dsh-judge-section\">\n <div className=\"dsh-judge-head\">\n <span className=\"dsh-judge-title\">{t('judge.title')}</span>\n {/* \u9884\u89C8\u4E0E\u8BD5\u901A\u90FD\u662F\u300C\u8FD9\u5957\u8BBE\u7F6E\u4F1A\u600E\u6837\u300D\u7684\u68C0\u67E5\uFF0C\u8DDF\u7740\u8BBE\u7F6E\u4E00\u8D77\u653E\uFF0C\u4E0D\u53E6\u5360\u4E00\u5757\u3002 */}\n <div className=\"dsh-judge-head-actions\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={probing || state.dirty}\n onClick={() => void runProbe()}\n >\n {probing ? t('judge.probing') : t('judge.probe')}\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={state.dirty}\n onClick={() => void openPreview()}\n >\n {t('preview.open')}\n </Button>\n </div>\n </div>\n <div className=\"dsh-judge-desc\">{t('judge.desc')}</div>\n\n {/* \u8FD9\u4E00\u8282\u91CC\u7684\u6BCF\u4E00\u683C\u90FD\u5F52\u4E0B\u9762\u90A3\u4E2A\u4FDD\u5B58\u6309\u94AE\u7BA1\uFF1A\u5F00\u5173\u3001\u7AEF\u70B9\u3001\u5224\u65AD\u6A21\u578B\u3001\u5BC6\u94A5\u4E00\u6B21\u5199\u5165\u3002\n \u5F00\u5173\u4E0D\u53E6\u5916\u7ED9\u4FDD\u5B58\u6309\u94AE\uFF0C\u4E5F\u4E0D\u5373\u65F6\u5199\u5165\u2014\u2014\u300C\u53EA\u6709\u6309\u4FDD\u5B58\u624D\u5199\u300D\u8FD9\u6761\u89C4\u5219\u5728\u4E00\u4E2A\u8282\u91CC\n \u53EA\u80FD\u6709\u4E00\u4E2A\u51FA\u53E3\uFF0C\u5426\u5219\u8BFB\u8005\u65E0\u6CD5\u9884\u5224\u54EA\u4E00\u4E0B\u4F1A\u843D\u76D8\u3002 */}\n <div className=\"dsh-judge-row\">\n <div className=\"dsh-judge-row-info\">\n <div className=\"dsh-judge-row-title\">{t('switch.rewrite.title')}</div>\n <div className=\"dsh-judge-row-hint\">{t('switch.rewrite.desc')}</div>\n </div>\n <Switch\n checked={state.enabled}\n onChange={(next: boolean) => dispatchCardStore.toggle('enabled', next)}\n label={t('switch.rewrite.title')}\n disabled={!state.writable || state.saving !== ''}\n />\n </div>\n\n <div className=\"dsh-judge-row\">\n <div className=\"dsh-judge-row-info\">\n <div className=\"dsh-judge-row-title\">{t('switch.log.title')}</div>\n <div className=\"dsh-judge-row-hint\">{t('switch.log.desc')}</div>\n </div>\n <Switch\n checked={state.logEnabled}\n onChange={(next: boolean) => dispatchCardStore.toggle('logEnabled', next)}\n label={t('switch.log.title')}\n disabled={!state.writable || state.saving !== ''}\n />\n </div>\n\n <div className=\"dsh-judge-row\">\n <div className=\"dsh-judge-row-info\">\n <div className=\"dsh-judge-row-title\">{t('judge.endpoint')}</div>\n <div className=\"dsh-judge-row-hint\">{t('judge.endpointDesc')}</div>\n </div>\n <div className=\"dsh-judge-row-field\">\n <Input\n type=\"text\"\n className=\"dsh-judge-field\"\n value={state.endpointUrl}\n placeholder=\"http://127.0.0.1:3425/v1/systemone\"\n aria-label={t('judge.endpoint')}\n onChange={(event: React.ChangeEvent<HTMLInputElement>) =>\n dispatchCardStore.field('endpointUrl', event.target.value)}\n />\n </div>\n </div>\n\n <div className=\"dsh-judge-row\">\n <div className=\"dsh-judge-row-info\">\n <div className=\"dsh-judge-row-title\">{t('judge.model')}</div>\n <div className=\"dsh-judge-row-hint\">{t('judge.modelDesc')}</div>\n </div>\n <div className=\"dsh-judge-row-field\">\n <Input\n type=\"text\"\n className=\"dsh-judge-field\"\n value={state.judgeModel}\n placeholder=\"future-jev/jev-latest\"\n aria-label={t('judge.model')}\n onChange={(event: React.ChangeEvent<HTMLInputElement>) =>\n dispatchCardStore.field('judgeModel', event.target.value)}\n />\n </div>\n </div>\n\n <div className=\"dsh-judge-row\">\n <div className=\"dsh-judge-row-info\">\n <div className=\"dsh-judge-row-title\">{t('judge.key')}</div>\n <div className=\"dsh-judge-row-hint\">\n {withSamples(t('judge.keyDesc'), { ref: JUDGE_API_KEY_REF, path: CREDENTIALS_PATH })}\n </div>\n </div>\n <div className=\"dsh-judge-row-field\">\n {/* \u5BC6\u94A5\u683C\u4E0E\u4E0A\u9762\u4E24\u683C\u540C\u5BBD\uFF1A\u72B6\u6001\u4E0E\u300C\u5220\u6389\u300D\u653E\u5728\u8F93\u5165\u6846\u4E0B\u9762\u90A3\u4E00\u884C\uFF0C\n \u8FD9\u6837\u4E09\u683C\u7684\u5DE6\u53F3\u8FB9\u7F18\u5BF9\u9F50\u3002 */}\n <Input\n type=\"password\"\n autoComplete=\"new-password\"\n className=\"dsh-judge-field\"\n value={state.key.text}\n placeholder={state.key.configured ? t('judge.keyPlaceholderSet') : t('judge.keyPlaceholder')}\n aria-label={t('judge.key')}\n disabled={state.key.unavailable}\n onChange={(event: React.ChangeEvent<HTMLInputElement>) =>\n dispatchCardStore.key(event.target.value)}\n />\n <div className=\"dsh-judge-key-line\">\n <Tag tone={state.key.configured ? 'success' : 'warning'}>\n {t(state.key.configured ? 'judge.keySet' : 'judge.keyUnset')}\n </Tag>\n {state.key.configured && (\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={state.key.saving || !state.key.writable}\n onClick={() => void dispatchCardStore.clearKey()}\n >\n {t('judge.keyClear')}\n </Button>\n )}\n {state.key.unavailable && <span className=\"dsh-judge-hint\">{t('judge.keyUnavailable')}</span>}\n {state.key.landed === 'saved' && <span className=\"dsh-judge-note-ok\">{t('judge.keySaved')}</span>}\n {state.key.landed === 'cleared' && <span className=\"dsh-judge-note-ok\">{t('judge.keyCleared')}</span>}\n {state.key.failed && (\n <span className=\"dsh-judge-note-bad\" role=\"alert\">\n {t('judge.keyFailed').replace('{error}', state.key.error || t('save.invalid'))}\n </span>\n )}\n </div>\n </div>\n </div>\n\n {probeResult !== null && (\n <div className={probeResult.ok ? 'dsh-judge-note-ok' : 'dsh-judge-note-bad'}>\n {probeResult.ok\n ? t('judge.probeOk').replace('{latency}', String(probeResult.latencyMs))\n : t('judge.probeFail').replace('{reason}', reasonText(probeResult.reason))}\n </div>\n )}\n {state.dirty && <div className=\"dsh-judge-hint\">{t('preview.blocked')}</div>}\n\n {saveRow('judge', state.judgeDirty, () => void dispatchCardStore.save('judge'))}\n </div>\n\n <div className=\"dsh-judge-section\">\n <div className=\"dsh-judge-title\">{t('rows.title')}</div>\n <div className=\"dsh-judge-desc\">{t('rows.desc')}</div>\n {state.models.length === 0 && <div className=\"dsh-judge-off\">{t('rows.allowedEmpty')}</div>}\n {state.rows.length === 0 && <div className=\"dsh-judge-desc\">{t('rows.empty')}</div>}\n {state.rows.length > 0 && (\n <table className=\"dsh-judge-table\">\n <thead>\n <tr>\n <th className=\"dsh-judge-col-no\">{t('rows.colId')}</th>\n <th>{t('rows.colType')}</th>\n <th className=\"dsh-judge-col-model\">{t('rows.colModel')}</th>\n <th className=\"dsh-judge-col-effort\">{t('rows.colEffort')}</th>\n <th className=\"dsh-judge-col-actions\" />\n </tr>\n </thead>\n <tbody>\n {state.rows.map((draft, index) => row(draft, index))}\n </tbody>\n </table>\n )}\n <div>\n <Button variant=\"outline\" size=\"sm\" onClick={() => dispatchCardStore.addRow()}>\n {t('rows.add')}\n </Button>\n </div>\n {state.rowsInvalid !== '' && state.rowsDirty && (\n <div className=\"dsh-judge-note-bad\" role=\"alert\">{state.rowsInvalid}</div>\n )}\n {saveRow('rows', state.rowsDirty, saveRows)}\n </div>\n\n <div className=\"dsh-judge-section\">\n <div className=\"dsh-judge-title\">{t('presets.title')}</div>\n <div className=\"dsh-judge-desc\">{t('presets.desc')}</div>\n <div className=\"dsh-judge-presets\">\n {PRESETS.map((preset) => (\n <button\n key={preset.key}\n type=\"button\"\n className=\"dsh-judge-preset\"\n onClick={() => dispatchCardStore.addPreset(t(`preset.${preset.key}.desc` as never))}\n >\n <span className=\"dsh-judge-preset-title\">{t(`preset.${preset.key}` as never)}</span>\n <span className=\"dsh-judge-preset-hint\">\n {t('presets.effortHint').replace('{effort}', t(preset.effortHint as never))}\n </span>\n </button>\n ))}\n </div>\n </div>\n </div>\n );\n\n const log = (\n <div className=\"dsh-judge-panel\">\n <div className=\"dsh-judge-section\">\n <div className=\"dsh-judge-head\">\n <span className=\"dsh-judge-title\">{t('log.title')}</span>\n <Button variant=\"outline\" size=\"sm\" onClick={() => void dispatchCardStore.refreshLog()}>\n {t('log.refresh')}\n </Button>\n </div>\n <div className=\"dsh-judge-desc\">{t('log.desc')}</div>\n {state.logFailed && <div className=\"dsh-judge-note-bad\">{t('log.loadFailed')}</div>}\n {state.logLoaded && state.log.length === 0 && (\n <div className=\"dsh-judge-desc\">{t('log.empty')}</div>\n )}\n {state.log.length > 0 && (\n <div className=\"dsh-judge-log\">\n <div className=\"dsh-judge-log-row dsh-judge-log-head\">\n <span>{t('log.colProvider')}</span>\n <span>{t('log.colModel')}</span>\n <span>{t('log.colEffort')}</span>\n <span>{t('log.colTime')}</span>\n <span>{t('log.colLatency')}</span>\n </div>\n {state.log.map((entry, index) => (\n <button\n key={index}\n type=\"button\"\n className=\"dsh-judge-log-row\"\n onClick={() => setDetail(entry)}\n >\n <span className=\"dsh-judge-cell-clip\" title={entry.provider}>{entry.provider || '\u2014'}</span>\n <span className=\"dsh-judge-cell-clip\" title={entry.model}>{entry.model || '\u2014'}</span>\n <span>{entry.effort || '\u2014'}</span>\n <span>{new Date(entry.at).toLocaleTimeString()}</span>\n <span>{t('ms').replace('{value}', String(entry.latencyMs))}</span>\n </button>\n ))}\n </div>\n )}\n </div>\n </div>\n );\n\n return (\n <div className=\"dsh-judge-card\">\n <SegmentedTabs\n items={[\n { value: 'design' as const, label: t('tab.design'), id: 'judge-tab-design', panelId: 'judge-panel-design' },\n { value: 'log' as const, label: t('tab.log'), id: 'judge-tab-log', panelId: 'judge-panel-log' },\n ]}\n value={tab}\n onChange={setTab}\n label={t('tab.design')}\n />\n {tab === 'design' ? design : log}\n\n <Modal\n open={refusal !== null}\n onClose={() => setRefusal(null)}\n title={t('save.refusedTitle')}\n closeLabel={t('rows.browseClose')}\n >\n <div className=\"dsh-judge-note-bad\" role=\"alert\">{refusal ?? ''}</div>\n </Modal>\n\n <Modal\n open={previewOpen}\n onClose={() => setPreviewOpen(false)}\n title={t('preview.title')}\n closeLabel={t('preview.close')}\n className=\"dsh-judge-modal\"\n >\n <div className=\"dsh-judge-desc\">{t('preview.desc')}</div>\n <CodeBlock code={preview ?? ''} copyLabel={t('preview.copy')} copiedLabel={t('preview.copied')} />\n </Modal>\n\n <Modal\n open={browsing !== null}\n onClose={() => setBrowsing(null)}\n title={t('rows.browseTitle').replace('{id}', String((browsing ?? 0) + 1))}\n closeLabel={t('rows.browseClose')}\n >\n <div className=\"dsh-judge-desc\" style={{ whiteSpace: 'pre-wrap' }}>\n {browsing === null ? '' : state.rows[browsing]?.description ?? ''}\n </div>\n </Modal>\n\n <Modal\n open={detail !== null}\n onClose={() => setDetail(null)}\n title={t('log.detailTitle')}\n closeLabel={t('log.detailClose')}\n >\n {detail !== null && (\n <div className=\"dsh-judge-detail\">\n <span>{t('log.detailSource')}</span>\n <span>\n {detail.source === 'judged'\n ? t('log.sourceJudged').replace('{id}', String(detail.typeId ?? ''))\n : t('log.sourceInherited').replace('{reason}', reasonText(detail.reason))}\n </span>\n <span>{t('log.detailProvider')}</span>\n <span>{detail.provider || '\u2014'}</span>\n <span>{t('log.detailModel')}</span>\n <span>{detail.model || '\u2014'}</span>\n <span>{t('log.detailEffort')}</span>\n <span>{detail.effort || '\u2014'}</span>\n <span>{t('log.detailReason')}</span>\n <span>{detail.reason === undefined ? '\u2014' : reasonText(detail.reason)}</span>\n <span>{t('log.detailLatency')}</span>\n <span>{t('ms').replace('{value}', String(detail.latencyMs))}</span>\n <span>{t('log.detailParent')}</span>\n <span>{detail.parentTitle || '\u2014'}</span>\n <span>{t('log.detailChild')}</span>\n <span style={{ whiteSpace: 'pre-wrap' }}>{detail.childLabel || '\u2014'}</span>\n </div>\n )}\n </Modal>\n </div>\n );\n}\n\n/** The client context surface this file uses. */\ninterface ClientContextLike {\n effect(factory: () => void | (() => void), label?: string): void;\n slots?: {\n inject(name: string, register: () => unknown): () => void;\n register(options: Record<string, unknown>, component: unknown): () => void;\n };\n configForms: {\n get(namespace: string): any;\n whileServed(namespaces: readonly string[], register: (served: ReadonlySet<string>) => () => void): () => void;\n };\n locale?: any;\n remote?: { session?: any; credentials?: CredentialsRemoteLike };\n}\n\n/**\n * Bind the card to this plugin's own configuration form, the Host's allowlist,\n * the credentials service, and this plugin's runtime routes, then contribute it\n * to the Plugins page.\n * @param ctx - the browser client context.\n */\nexport function setupSettingsUi(ctx: ClientContextLike): void {\n if (typeof window === 'undefined') return;\n const t = ctx.locale?.bind?.(NS) ?? ((key: string) => key);\n try {\n dispatchCardStore.attach({\n form: ctx.configForms.get(SETTINGS_NAMESPACE),\n // The Host owns which models a subagent may use; this card only reads it so\n // the plugin never keeps a second list that could drift from it.\n allowedForm: ctx.configForms.get(ALLOWED_MODELS_NAMESPACE),\n session: ctx.remote?.session ?? null,\n remote: createDispatchRemote(),\n // The judgement key is written here; its value never rides a response.\n credentials: ctx.remote?.credentials ?? null,\n t,\n });\n } catch (error) {\n console.warn('[dsh-subagent-judge-dispatch] \u914D\u7F6E\u8868\u5355\u7ED1\u5B9A\u5931\u8D25\uFF1A', error);\n }\n\n // The dictionaries are registered once by the client entry point; the card's\n // seat resolves `t` against them through its `locale: NS` registration above.\n\n // The card lives on the Plugins page, which declares `plugins.bundle.config`\n // only while its own entry is mounted; `whileServed` additionally ties the\n // contribution to the Host actually serving this plugin's own settings entry.\n ctx.effect(\n () => ctx.configForms.whileServed([SETTINGS_NAMESPACE], () =>\n setupPluginPage(ctx.slots, () =>\n (ctx.slots as NonNullable<ClientContextLike['slots']>).register(\n {\n name: BUNDLE_CONFIG_SLOT,\n key: BUNDLE_CONFIG_KEY,\n locale: NS,\n },\n JudgeDispatchPanel,\n ))),\n 'dsh-subagent-judge-dispatch: plugins page config',\n );\n}\n", "/**\n * This plugin's configuration card and where it lives: the DSH **Plugins** page,\n * registered into `plugins.bundle.config` under the bundle's package name.\n *\n * The key is the package name; the settings the card reads and writes live in a\n * DIFFERENT literal \u2014 the Loader row id, which is also this plugin's settings\n * namespace. Writing one where the other belongs makes the card silently never\n * appear, so both are spelled once, here and in `src/index.ts`.\n */\n\n// Type-only: brings the owner's `plugins.bundle.config` SlotMap contract into\n// this program. Erased from the bundle, so the browser half never depends on the\n// plugin manager at runtime.\nimport type {} from '@deepseek-ai/dsh-client-ui-plugin-manager/client';\n\n/** npm package name of this plugin's bundle \u2014 the whole `plugins.bundle.config` key. */\nexport const BUNDLE_NAME = '@lynn123411/dsh-subagent-judge-dispatch';\n\n/** The Plugins page slot a bundle's own configuration registers into. */\nexport const BUNDLE_CONFIG_SLOT = 'plugins.bundle.config';\n\n/** This plugin's own config key: the bundle's package name. */\nexport const BUNDLE_CONFIG_KEY = BUNDLE_NAME;\n\n/** Services this registration needs from the browser runtime. */\ninterface PluginPageSlots {\n inject(name: string, callback: () => unknown): () => void;\n}\n\n/**\n * Contribute this plugin's configuration card to the Plugins page.\n * @param slots - the client slot registry.\n * @param register - registers the card component; returns its disposer.\n * @returns A disposer releasing the contribution, or a no-op when the browser\n * runtime hands no slot registry at all.\n */\nexport function setupPluginPage(\n slots: PluginPageSlots | null | undefined,\n register: () => () => void,\n): () => void {\n if (!slots || typeof slots.inject !== 'function') return () => {};\n return slots.inject(BUNDLE_CONFIG_SLOT, register);\n}\n", "/**\n * The judgement request the plugin sends, and the answer it reads back.\n *\n * Two pure functions live here, so the whole \"what did the judge decide\"\n * question is answerable without a Host, a socket, or a timer:\n *\n * - {@link buildJudgeRequest} turns the type list plus the task text into the\n * exact body that goes out.\n * - {@link readJudgeAnswer} turns whatever came back into a decision, treating\n * every malformed, empty or off-list answer as \"no decision\" rather than\n * inventing one.\n *\n * The protocol is the System One one: POST a body of `{ model, state,\n * questions }`, where each question is a `choice` carrying an `instructions`\n * line and a `criteria` map of option id to the text that option means. The\n * answer names the chosen option id.\n */\n\nimport type { TypeRow } from './types.ts';\n\n/** The one question key the plugin asks. */\nexport const QUESTION_KEY = 'task_type';\n\n/**\n * The question's instructions line.\n *\n * It says what to weigh, not what the types are: the types themselves arrive as\n * the criteria map, so the reader's own descriptions are the whole criterion\n * list and nothing here can drift from them.\n */\nexport const QUESTION_INSTRUCTIONS =\n 'Which single task type below does the delegated job best match? '\n + 'Weigh what the job actually requires, not how it is phrased. '\n + 'Answer with the number of exactly one listed type.';\n\n/** The option id the connectivity check offers: the only one it offers. */\nexport const PROBE_OPTION_ID = '1';\n\n/** The task text the connectivity check sends. */\nexport const PROBE_TASK_TEXT = '\u8FDE\u63A5\u6D4B\u8BD5\uFF1A\u8FD9\u662F\u4E00\u6B21\u5224\u65AD\u670D\u52A1\u7684\u8FDE\u901A\u6027\u68C0\u67E5\u3002';\n\n/**\n * The connectivity check's instructions.\n *\n * It asks for the one option that exists, so an endpoint that understands the\n * protocol at all can answer it: answering it wrong is a failure of the\n * protocol, not of the reader's task list.\n */\nexport const PROBE_INSTRUCTIONS =\n 'Answer with the number of the one option listed below.';\n\n/** The single criterion the connectivity check offers. */\nexport const PROBE_CRITERION = '\u786E\u8BA4\u8FD9\u6B21\u8C03\u7528\u53EF\u4EE5\u5B8C\u6210\u3002';\n\n/** One option of the judge's question. */\nexport interface JudgeChoice {\n type: 'choice';\n instructions: string;\n criteria: Record<string, string>;\n}\n\n/** The exact body sent to the judge endpoint. */\nexport interface JudgeRequest {\n model: string;\n state: { message: string };\n questions: { [QUESTION_KEY]: JudgeChoice };\n}\n\n/**\n * Whether one row is complete enough to be offered to the judge.\n *\n * A row needs its provider, model and effort: a half-filled row could otherwise\n * be chosen and then have nothing to write, which would turn the reader's\n * unfinished edit into a delegation that silently lost its route. This is the\n * ONE place that rule lives \u2014 the page, the config gate and the rewrite all ask\n * this function rather than restating the three comparisons.\n *\n * The parameter is narrowed to the three fields the rule reads, so the page's\n * draft row (which carries no sequence number) and the server's numbered row\n * both satisfy it without either shape being converted into the other.\n *\n * @param row - one row, numbered or drafted.\n * @returns whether the judge may choose it.\n */\nexport function isSelectableRow(row: Pick<TypeRow, 'provider' | 'model' | 'effort'>): boolean {\n return row.provider.trim() !== '' && row.model.trim() !== '' && row.effort.trim() !== '';\n}\n\n/**\n * Which rows may be offered to the judge.\n * @param rows - every row on the page, in page order.\n * @returns the rows the judge may choose, in page order.\n */\nexport function selectableRows(rows: readonly TypeRow[]): TypeRow[] {\n return rows.filter(isSelectableRow);\n}\n\n/**\n * Build the exact body sent to the judge endpoint.\n *\n * @param rows - the selectable rows, in page order.\n * @param model - the judge model id.\n * @param taskText - the delegated job's text.\n * @returns the request body.\n */\nexport function buildJudgeRequest(\n rows: readonly TypeRow[],\n model: string,\n taskText: string,\n): JudgeRequest {\n const criteria: Record<string, string> = {};\n for (const row of rows) criteria[String(row.id)] = row.description;\n return {\n model,\n state: { message: taskText },\n questions: {\n [QUESTION_KEY]: {\n type: 'choice',\n instructions: QUESTION_INSTRUCTIONS,\n criteria,\n },\n },\n };\n}\n\n/**\n * Build the body the connectivity check sends.\n *\n * It carries its own single option rather than the reader's task types: the\n * question the button answers is \"does this endpoint and model work\", and that\n * question has an answer before any type list exists. Requiring a finished list\n * first would make the check unable to tell a reader with an empty list from a\n * reader whose endpoint is down.\n *\n * @param model - the judge model id.\n * @returns the request body.\n */\nexport function buildProbeRequest(model: string): JudgeRequest {\n return {\n model,\n state: { message: PROBE_TASK_TEXT },\n questions: {\n [QUESTION_KEY]: {\n type: 'choice',\n instructions: PROBE_INSTRUCTIONS,\n criteria: { [PROBE_OPTION_ID]: PROBE_CRITERION },\n },\n },\n };\n}\n\n/**\n * The text the configuration page's preview shows.\n *\n * It is the request body minus the task text, because no task text exists until\n * a delegation happens; the preview marks that spot instead of inventing one.\n *\n * @param rows - the selectable rows, in page order.\n * @param model - the judge model id.\n * @returns the pretty-printed preview text.\n */\nexport function buildPreview(rows: readonly TypeRow[], model: string): string {\n const body = buildJudgeRequest(rows, model, '\uFF08\u6D3E\u5DE5\u65F6\u624D\u586B\uFF09');\n return JSON.stringify(body, null, 2);\n}\n\n/** What reading the judge's answer produced. */\nexport type JudgeDecision =\n | { kind: 'row'; row: TypeRow }\n | { kind: 'empty' }\n | { kind: 'unmatched' };\n\n/**\n * Find the chosen option id inside whatever the endpoint answered.\n *\n * The protocol's own shape is `answers.<key>.choice`; the two fallbacks are the\n * ones the reference clients read, so an endpoint that answers the shorter way\n * still works. Anything else \u2014 a missing body, a non-string, an empty string \u2014\n * yields `undefined` and is treated as no answer.\n *\n * @param payload - the decoded response body.\n * @returns the chosen option id, or undefined when the body names none.\n */\nexport function readChoice(payload: unknown): string | undefined {\n if (typeof payload !== 'object' || payload === null) return undefined;\n const body = payload as Record<string, unknown>;\n const answers = body.answers;\n const fromAnswers =\n typeof answers === 'object' && answers !== null\n ? (answers as Record<string, unknown>)[QUESTION_KEY]\n : undefined;\n const candidate = fromAnswers ?? body[QUESTION_KEY];\n if (typeof candidate === 'object' && candidate !== null) {\n const choice = (candidate as Record<string, unknown>).choice;\n if (typeof choice === 'string' && choice.trim() !== '') return choice.trim();\n if (typeof choice === 'number' && Number.isFinite(choice)) return String(choice);\n return undefined;\n }\n if (typeof candidate === 'string' && candidate.trim() !== '') return candidate.trim();\n if (typeof candidate === 'number' && Number.isFinite(candidate)) return String(candidate);\n return undefined;\n}\n\n/**\n * Turn the judge's answer into a decision.\n *\n * The choice is the type row's number. Matching is by that number's numeric\n * value, so an endpoint that answers `\"3\"` and one that answers `3` agree; a\n * number no listed row carries is `unmatched`, and a body naming no choice at\n * all is `empty`. Both travel to the log as their own reason, because \"it\n * answered nothing\" and \"it answered something I do not have\" send the reader\n * to different fixes.\n *\n * @param payload - the decoded response body.\n * @param rows - the selectable rows, in page order.\n * @returns the decision.\n */\nexport function readJudgeAnswer(payload: unknown, rows: readonly TypeRow[]): JudgeDecision {\n const choice = readChoice(payload);\n if (choice === undefined) return { kind: 'empty' };\n const wanted = Number(choice);\n if (!Number.isFinite(wanted)) return { kind: 'unmatched' };\n const row = rows.find((candidate) => candidate.id === wanted);\n return row === undefined ? { kind: 'unmatched' } : { kind: 'row', row };\n}\n", "/**\n * Where the judgement key lives, and the Host service it is read through.\n *\n * The reference name is a constant of the plugin rather than a setting: the\n * page asks for the key itself and stores it write-only through the DSH\n * credentials service, so a reader never has to know what a \"credential\n * reference\" is, and no surface can point the plugin at somebody else's key.\n * This module imports nothing, so both halves can share the literal.\n *\n * The key value crosses in one direction only: it is written, and read back by\n * the Host half alone. The browser face reads a status-only view.\n */\n\n/** Credential reference the judgement key is stored under. */\nexport const JUDGE_API_KEY_REF = 'SUBAGENT_JUDGE_API_KEY';\n\n/** Minimal structural shape of the Host's `ctx.credentials` service. */\nexport interface CredentialsServiceLike {\n /** Resolve a reference to its stored or inherited value. */\n resolve(ref: string): Promise<{ value: string; source?: string } | undefined>;\n /** Status-only view of a reference; never returns the plaintext value. */\n describe(ref: string): Promise<{ configured: boolean; source?: string; writable: boolean }>;\n /** Store a non-empty value under a reference. */\n set(ref: string, value: string): Promise<void>;\n /** Remove a reference from the document. */\n unset(ref: string): Promise<void>;\n}\n\n/** Minimal structural shape of the browser's `ctx.remote.credentials` face. */\nexport interface CredentialsRemoteLike {\n describe(refs: string[]): Promise<\n { ok: true; value: Record<string, { configured: boolean; source?: string; writable: boolean }> }\n | { ok: false; error: { message: string } }\n >;\n set(ref: string, value: string): Promise<{ ok: true } | { ok: false; error: { message: string } }>;\n unset(ref: string): Promise<{ ok: true } | { ok: false; error: { message: string } }>;\n}\n", "/**\n * The configuration card's own state: what the Host serves, what the reader has\n * staged, and what a save would do.\n *\n * Three rules live here rather than in the component, because each is the kind\n * of thing a render pass must not be trusted with:\n *\n * - A row's sequence number is positional (`1..n`) and is never stored. Duplicate\n * numbers are therefore impossible by construction rather than by validation.\n * - The two sections save separately. The judgement service and the task-type\n * list are edited at different times and fail differently, so one save for both\n * would let a half-finished description block a change to the endpoint.\n * - A save that did not land is reported as such. The shared configuration form\n * answers `false` for a refusal, which is not a rejection: treating it as\n * success would show a saved page over a document the Host never accepted.\n *\n * The model and effort options come from the Host's own \"models subagents may\n * choose\" setting and the adapter catalogue, so the plugin never keeps a second\n * list that could drift from it. The judgement key is write-only over the DSH\n * credentials service, which is why no key value is ever part of this state.\n */\n\nimport { isSelectableRow } from '../../server/judge-prompt.ts';\nimport { JUDGE_API_KEY_REF, type CredentialsRemoteLike } from '../../server/credentials.ts';\n\nexport { JUDGE_API_KEY_REF };\nexport type { CredentialsRemoteLike };\n\n/** One type row as the page edits it; `id` is derived, never stored. */\nexport interface TypeRowDraft {\n description: string;\n provider: string;\n model: string;\n effort: string;\n}\n\n/** One selectable model and the efforts it declares. */\nexport interface ModelOption {\n provider: string;\n model: string;\n /** Display name from the adapter catalogue, when it advertises one. */\n label: string;\n /** Effort ids this exact route declares, in catalogue order. */\n efforts: string[];\n}\n\n/** One log row as the Host serves it. */\nexport interface LogRow {\n typeId: number | null;\n provider: string;\n model: string;\n effort: string;\n source: 'judged' | 'inherited';\n reason?: string;\n at: number;\n latencyMs: number;\n parentTitle: string;\n childLabel: string;\n}\n\n/** Which of the two sections a save writes. */\nexport type Section = 'judge' | 'rows';\n\n/** What the page shows about the judgement key; never its value. */\nexport interface KeyState {\n /** Staged key text; blank until the reader types one. */\n text: string;\n /** Whether the Host reports a stored key under the reference. */\n configured: boolean;\n /** Whether the credentials document accepts writes. */\n writable: boolean;\n /**\n * Whether this page has no credentials channel at all \u2014 a non-loopback page\n * is served without the namespace, and a field that cannot be written should\n * say so before the reader types into it.\n */\n unavailable: boolean;\n saving: boolean;\n failed: boolean;\n /** The credentials service's own message for a refused write, or ''. */\n error: string;\n /** What the last landed key write did, or '' when none has landed. */\n landed: '' | 'saved' | 'cleared';\n}\n\n/** The card's whole state. */\nexport interface PageState {\n available: boolean;\n writable: boolean;\n /** Whether the model-rewrite switch is on. */\n enabled: boolean;\n /** Whether the log switch is on. */\n logEnabled: boolean;\n endpointUrl: string;\n judgeModel: string;\n rows: TypeRowDraft[];\n /** Model options read from the Host's allowlist plus the adapter catalogue. */\n models: ModelOption[];\n /** Whether the adapter catalogue was read; false means the effort column is free text. */\n catalogRead: boolean;\n /** Persisted values, for computing dirtiness and reverting. */\n committed: {\n enabled: boolean;\n logEnabled: boolean;\n endpointUrl: string;\n judgeModel: string;\n rows: TypeRowDraft[];\n };\n /** Whether the judgement service section holds edits a save would write. */\n judgeDirty: boolean;\n /** Whether the task-type list holds edits a save would write. */\n rowsDirty: boolean;\n /** Whether either section holds edits, for the preview's own notice. */\n dirty: boolean;\n /** A reason the task-type drafts cannot be saved; '' when they can. */\n rowsInvalid: string;\n /** Which section a save is crossing the wire for, or '' when none is. */\n saving: Section | '';\n /** Which section's last save did not land, or '' when none failed. */\n saveFailed: Section | '';\n /** The Host's own message for the last refused write, or ''. */\n saveError: string;\n /** The judgement key's write-only state. */\n key: KeyState;\n /** Runtime log rows, newest first. */\n log: LogRow[];\n logLoaded: boolean;\n logFailed: boolean;\n}\n\n/** Defaults mirroring the Host schema, so an unserved page still renders. */\nexport const DEFAULT_ENDPOINT_URL = 'http://127.0.0.1:3425/v1/systemone';\nexport const DEFAULT_JUDGE_MODEL = 'future-jev/jev-latest';\n\n/** Profile entry id (== settings namespace). */\nexport const SETTINGS_NAMESPACE = 'dsh-subagent-judge-dispatch';\n\n/** The Host's own allowlist namespace, which the card reads for model options. */\nexport const ALLOWED_MODELS_NAMESPACE = 'subagent-model-selection-settings';\n\n/** One path-addressed edit, matching the wire shape the form's `mutate` accepts. */\nexport type SettingsPathOpLike =\n | { op: 'set'; path: string[]; value: unknown }\n | { op: 'unset'; path: string[] };\n\n/** Minimal structural shape of the DSH shared configuration form. */\nexport interface ConfigFormLike {\n getSnapshot(): {\n status: 'loading' | 'ready' | 'unavailable';\n value?: Record<string, unknown>;\n writable: boolean;\n revision?: number;\n };\n subscribe(listener: () => void): () => void;\n mutate(ops: readonly SettingsPathOpLike[], expectedRevision?: number): Promise<boolean>;\n}\n\n/** The `remote.session` face the model catalogue is read through. */\nexport interface SessionRemoteLike {\n modelCatalog(): Promise<\n | { ok: true; value: { groups: readonly { id: string; name: string; models: readonly { id: string; name: string; reasoning?: { efforts: readonly { id: string }[] } }[] }[] } }\n | { ok: false; error: { message: string } }\n >;\n}\n\n/**\n * The Host's three runtime reads.\n *\n * They are plain Fetch calls on this plugin's own routes rather than a Remote\n * namespace: the routes ride Connection's authenticated `/api` transport, which\n * is the same channel the page is already served over.\n */\nexport interface DispatchRemoteLike {\n log(): Promise<LogRow[]>;\n preview(): Promise<string | null>;\n probe(): Promise<{ ok: boolean; latencyMs: number; reason?: string }>;\n}\n\n/** The three route paths, shared with the Host half by literal. */\nexport const LOG_ROUTE_PATH = '/api/dsh-subagent-judge-dispatch/log';\nexport const PREVIEW_ROUTE_PATH = '/api/dsh-subagent-judge-dispatch/preview';\nexport const PROBE_ROUTE_PATH = '/api/dsh-subagent-judge-dispatch/probe';\n\n/** Decode a response body, treating an unreadable one as absent. */\nasync function readJson(response: Response): Promise<any> {\n try {\n return await response.json();\n } catch {\n return null;\n }\n}\n\n/** The real Host reads, over this plugin's own routes. */\nexport function createDispatchRemote(): DispatchRemoteLike {\n return {\n async log(): Promise<LogRow[]> {\n try {\n const response = await fetch(LOG_ROUTE_PATH);\n if (!response.ok) return [];\n const body = await readJson(response);\n return Array.isArray(body?.entries) ? (body.entries as LogRow[]) : [];\n } catch {\n return [];\n }\n },\n async preview(): Promise<string | null> {\n try {\n const response = await fetch(PREVIEW_ROUTE_PATH);\n if (!response.ok) return null;\n const body = await readJson(response);\n return typeof body?.preview === 'string' ? body.preview : null;\n } catch {\n return null;\n }\n },\n async probe(): Promise<{ ok: boolean; latencyMs: number; reason?: string }> {\n try {\n const response = await fetch(PROBE_ROUTE_PATH, { method: 'POST' });\n if (!response.ok) return { ok: false, latencyMs: 0, reason: 'unreachable' };\n const body = await readJson(response);\n if (body === null || typeof body !== 'object') return { ok: false, latencyMs: 0, reason: 'unreachable' };\n return {\n ok: body.ok === true,\n latencyMs: typeof body.latencyMs === 'number' ? body.latencyMs : 0,\n ...typeof body.reason === 'string' ? { reason: body.reason } : {},\n };\n } catch {\n return { ok: false, latencyMs: 0, reason: 'unreachable' };\n }\n },\n };\n}\n\n/**\n * Read one row from a stored document value, tolerating a partial record.\n * @param value - one entry of the stored `rows` array.\n * @returns the row's four text fields, each defaulted to ''.\n */\nexport function readRow(value: unknown): TypeRowDraft {\n const record = typeof value === 'object' && value !== null ? (value as Record<string, unknown>) : {};\n const text = (key: string): string => (typeof record[key] === 'string' ? (record[key] as string) : '');\n return {\n description: text('description'),\n provider: text('provider'),\n model: text('model'),\n effort: text('effort'),\n };\n}\n\n/**\n * Stable identity for one exact provider/model route.\n *\n * The separator is a NUL, which cannot appear in a provider or model id, so the\n * join and the split can never disagree. Both live here rather than at the call\n * sites: encoding and decoding are one concept and must not drift apart.\n *\n * @param provider - provider id.\n * @param model - model id.\n * @returns the composite key.\n */\nexport function routeKey(provider: string, model: string): string {\n return `${provider}\\0${model}`;\n}\n\n/**\n * Split a composite route key back into its two ids.\n * @param key - a value produced by {@link routeKey}.\n * @returns the provider and model, both '' when the key is malformed.\n */\nexport function splitRouteKey(key: string): { provider: string; model: string } {\n const at = key.indexOf('\\0');\n if (at < 0) return { provider: '', model: '' };\n return { provider: key.slice(0, at), model: key.slice(at + 1) };\n}\n\n/**\n * Pair the Host's allowlist with the adapter catalogue.\n *\n * The allowlist decides which routes may be offered; the catalogue supplies each\n * route's display name and the effort ids it declares. A route the allowlist\n * names but the catalogue no longer advertises is kept, so a stored row never\n * becomes uneditable merely because an adapter went away.\n *\n * @param allowed - the Host's `allowedModels` entries.\n * @param groups - catalogue provider groups.\n * @returns the options to render, in allowlist order.\n */\nexport function buildModelOptions(\n allowed: readonly { provider?: unknown; model?: unknown }[],\n groups: readonly { id: string; models: readonly { id: string; name: string; reasoning?: { efforts: readonly { id: string }[] } }[] }[],\n): ModelOption[] {\n const byRoute = new Map<string, { label: string; efforts: string[] }>();\n for (const group of groups) {\n for (const model of group.models) {\n byRoute.set(routeKey(group.id, model.id), {\n label: model.name,\n efforts: (model.reasoning?.efforts ?? []).map((effort) => effort.id),\n });\n }\n }\n const options: ModelOption[] = [];\n const seen = new Set<string>();\n for (const entry of allowed) {\n const provider = typeof entry.provider === 'string' ? entry.provider : '';\n const model = typeof entry.model === 'string' ? entry.model : '';\n if (provider === '' || model === '') continue;\n const key = routeKey(provider, model);\n if (seen.has(key)) continue;\n seen.add(key);\n const found = byRoute.get(key);\n options.push({\n provider,\n model,\n label: found?.label ?? model,\n efforts: found?.efforts ?? [],\n });\n }\n return options;\n}\n\n/**\n * The reason the task-type drafts cannot be saved, or '' when they can.\n *\n * A duplicate description is refused because the description is the criterion\n * the judge reads: two identical criteria would make the answer ambiguous and\n * the log unreadable. An empty description is refused for the same reason \u2014 a\n * row the judge cannot tell apart from any other.\n *\n * @param rows - the staged rows.\n * @param t - the page's translator, so the message is localized.\n * @returns the reason text, or ''.\n */\nexport function validateRows(rows: readonly TypeRowDraft[], t: (key: string) => string): string {\n const seen = new Set<string>();\n for (const row of rows) {\n const description = row.description.trim();\n if (description === '') return t('save.emptyDescription');\n if (seen.has(description)) return t('save.duplicateDescription');\n seen.add(description);\n }\n return '';\n}\n\n/** A key nothing is staged for and nothing is known about. */\nfunction emptyKey(): KeyState {\n return {\n text: '', configured: false, writable: false, unavailable: false,\n saving: false, failed: false, error: '', landed: '',\n };\n}\n\n/**\n * The read/write face of the Host document plus the runtime reads.\n *\n * Every control stages into this store and only a section's own save writes, so\n * a half-typed endpoint can never reach a delegation, and a half-written type\n * list can never be stored behind the reader's back.\n */\nexport class DispatchCardStore {\n private state: PageState = {\n available: false,\n writable: false,\n enabled: true,\n logEnabled: true,\n endpointUrl: DEFAULT_ENDPOINT_URL,\n judgeModel: DEFAULT_JUDGE_MODEL,\n rows: [],\n models: [],\n catalogRead: false,\n committed: {\n enabled: true,\n logEnabled: true,\n endpointUrl: DEFAULT_ENDPOINT_URL,\n judgeModel: DEFAULT_JUDGE_MODEL,\n rows: [],\n },\n judgeDirty: false,\n rowsDirty: false,\n dirty: false,\n rowsInvalid: '',\n saving: '',\n saveFailed: '',\n saveError: '',\n key: emptyKey(),\n log: [],\n logLoaded: false,\n logFailed: false,\n };\n\n private listeners = new Set<() => void>();\n private form: ConfigFormLike | null = null;\n private allowedForm: ConfigFormLike | null = null;\n private session: SessionRemoteLike | null = null;\n private remote: DispatchRemoteLike | null = null;\n private credentials: CredentialsRemoteLike | null = null;\n private offForm: (() => void) | null = null;\n private offAllowed: (() => void) | null = null;\n private translate: (key: string) => string = (key) => key;\n\n /** Bind the Host services; re-binding detaches the previous subscriptions. */\n attach(options: {\n form: ConfigFormLike | null;\n allowedForm: ConfigFormLike | null;\n session: SessionRemoteLike | null;\n remote: DispatchRemoteLike | null;\n credentials: CredentialsRemoteLike | null;\n t: (key: string) => string;\n }): void {\n this.offForm?.();\n this.offAllowed?.();\n this.form = options.form;\n this.allowedForm = options.allowedForm;\n this.session = options.session;\n this.remote = options.remote;\n this.credentials = options.credentials;\n this.translate = options.t;\n this.state = {\n ...this.state,\n key: { ...this.state.key, unavailable: options.credentials === null },\n };\n if (this.form !== null) {\n this.offForm = this.form.subscribe(() => this.deriveCommitted());\n this.deriveCommitted();\n }\n if (this.allowedForm !== null) {\n this.offAllowed = this.allowedForm.subscribe(() => void this.loadModels());\n void this.loadModels();\n }\n void this.refreshKeyStatus();\n }\n\n getState(): PageState {\n return this.state;\n }\n\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n /** Read the Host's allowlist and the adapter catalogue into the model options. */\n async loadModels(): Promise<void> {\n const allowedValue = this.allowedForm?.getSnapshot().value;\n const allowed = Array.isArray(allowedValue?.allowedModels)\n ? (allowedValue.allowedModels as { provider?: unknown; model?: unknown }[])\n : [];\n let groups: readonly { id: string; models: readonly { id: string; name: string; reasoning?: { efforts: readonly { id: string }[] } }[] }[] = [];\n let catalogRead = false;\n if (this.session !== null) {\n try {\n const response = await this.session.modelCatalog();\n if (response.ok) {\n groups = response.value.groups;\n catalogRead = true;\n }\n } catch {\n // Handled by the flag below.\n }\n }\n // Whether the effort column may offer a fixed list. When the catalogue could\n // not be read the column falls back to free text rather than going\n // unavailable: an empty list would otherwise disable the effort cell on\n // every row, and a table where no row can be completed is a table that\n // silently stops judging anything.\n this.state = { ...this.state, models: buildModelOptions(allowed, groups), catalogRead };\n this.notify();\n }\n\n /** Read the status-only view of the judgement key. */\n async refreshKeyStatus(): Promise<void> {\n if (this.credentials === null) return;\n try {\n const response = await this.credentials.describe([JUDGE_API_KEY_REF]);\n if (!response.ok) return;\n const info = response.value[JUDGE_API_KEY_REF];\n this.state = {\n ...this.state,\n key: {\n ...this.state.key,\n configured: info?.configured === true,\n writable: info?.writable === true,\n },\n };\n this.notify();\n } catch {\n // The key stays \"not configured\": the status is an enrichment, and a\n // failed read must not claim a key that may not be there.\n }\n }\n\n /**\n * Map the Host's resolved section into committed state and re-seed the drafts.\n *\n * Drafts are held FIELD BY FIELD, against the value this page last saw\n * committed. Holding a whole section instead would make a save write back a\n * field the reader never touched \u2014 reverting a change another page made to it \u2014\n * while holding nothing would discard input mid-typing every time the Host\n * publishes.\n */\n private deriveCommitted(): void {\n const snapshot = this.form?.getSnapshot();\n const value = snapshot?.value;\n if (value === undefined) return;\n const rows = Array.isArray(value.rows) ? (value.rows as unknown[]).map(readRow) : [];\n const committed = {\n enabled: typeof value.enabled === 'boolean' ? value.enabled : true,\n logEnabled: typeof value.logEnabled === 'boolean' ? value.logEnabled : true,\n endpointUrl: typeof value.endpointUrl === 'string' ? value.endpointUrl : DEFAULT_ENDPOINT_URL,\n judgeModel: typeof value.judgeModel === 'string' ? value.judgeModel : DEFAULT_JUDGE_MODEL,\n rows,\n };\n /** Whether the reader's staged value still differs from what this page last saw committed. */\n const staged = <T>(current: T, previously: T): boolean => current !== previously;\n const before = this.state.committed;\n this.state = {\n ...this.state,\n available: snapshot?.status === 'ready',\n writable: snapshot?.writable ?? false,\n committed,\n enabled: staged(this.state.enabled, before.enabled) ? this.state.enabled : committed.enabled,\n logEnabled: staged(this.state.logEnabled, before.logEnabled) ? this.state.logEnabled : committed.logEnabled,\n endpointUrl: staged(this.state.endpointUrl, before.endpointUrl) ? this.state.endpointUrl : committed.endpointUrl,\n judgeModel: staged(this.state.judgeModel, before.judgeModel) ? this.state.judgeModel : committed.judgeModel,\n rows: JSON.stringify(this.state.rows) !== JSON.stringify(before.rows) ? this.state.rows : committed.rows,\n };\n this.recompute();\n }\n\n /** Recompute per-section dirtiness and the row validation against committed values. */\n private recompute(): void {\n const committed = this.state.committed;\n const judgeDirty =\n this.state.enabled !== committed.enabled ||\n this.state.logEnabled !== committed.logEnabled ||\n this.state.endpointUrl !== committed.endpointUrl ||\n this.state.judgeModel !== committed.judgeModel ||\n this.state.key.text.trim() !== '';\n const rowsDirty = JSON.stringify(this.state.rows) !== JSON.stringify(committed.rows);\n this.state = {\n ...this.state,\n judgeDirty,\n rowsDirty,\n dirty: judgeDirty || rowsDirty,\n rowsInvalid: validateRows(this.state.rows, this.translate),\n };\n this.notify();\n }\n\n /** Stage one top-level field. */\n field(key: 'endpointUrl' | 'judgeModel', value: string): void {\n this.state = { ...this.state, [key]: value, saveFailed: '' };\n this.recompute();\n }\n\n /** Stage one switch. */\n toggle(key: 'enabled' | 'logEnabled', value: boolean): void {\n this.state = { ...this.state, [key]: value, saveFailed: '' };\n this.recompute();\n }\n\n /** Stage the judgement key. The value stays in this draft until a save. */\n key(text: string): void {\n this.state = { ...this.state, key: { ...this.state.key, text, failed: false, error: '', landed: '' } };\n this.recompute();\n }\n\n /** Stage one cell of one row. */\n cell(index: number, key: keyof TypeRowDraft, value: string): void {\n const rows = this.state.rows.map((row, at) => (at === index ? { ...row, [key]: value } : row));\n // Choosing a model drops an effort that model does not declare, so a save can\n // never carry an effort the selected route cannot run.\n this.state = {\n ...this.state,\n rows: key === 'model' ? this.reconcileEffort(rows, index) : rows,\n saveFailed: '',\n };\n this.recompute();\n }\n\n /** Drop an effort the freshly selected model does not declare. */\n private reconcileEffort(rows: TypeRowDraft[], index: number): TypeRowDraft[] {\n const row = rows[index];\n if (row === undefined) return rows;\n const option = this.state.models.find(\n (candidate) => candidate.provider === row.provider && candidate.model === row.model,\n );\n if (option === undefined || option.efforts.length === 0) return rows;\n if (row.effort !== '' && !option.efforts.includes(row.effort)) {\n return rows.map((candidate, at) => (at === index ? { ...candidate, effort: '' } : candidate));\n }\n return rows;\n }\n\n /** Append an empty row. */\n addRow(): void {\n this.state = { ...this.state, rows: [...this.state.rows, { description: '', provider: '', model: '', effort: '' }], saveFailed: '' };\n this.recompute();\n }\n\n /** Append a ready-made entry; the effort hint is not filled in. */\n addPreset(description: string): void {\n this.state = { ...this.state, rows: [...this.state.rows, { description, provider: '', model: '', effort: '' }], saveFailed: '' };\n this.recompute();\n }\n\n /** Delete one row; the remaining rows renumber themselves. */\n removeRow(index: number): void {\n this.state = { ...this.state, rows: this.state.rows.filter((_row, at) => at !== index), saveFailed: '' };\n this.recompute();\n }\n\n /** Discard one section's drafts back to the committed values. */\n revert(section: Section): void {\n const committed = this.state.committed;\n this.state = section === 'judge'\n ? {\n ...this.state,\n enabled: committed.enabled,\n logEnabled: committed.logEnabled,\n endpointUrl: committed.endpointUrl,\n judgeModel: committed.judgeModel,\n // \u53EA\u6E05\u6389\u300C\u8FD8\u6CA1\u4EA4\u51FA\u53BB\u7684\u90A3\u6BB5\u6587\u672C\u300D\u3002\u5BC6\u94A5\u5DF2\u7ECF\u5B58\u5728\u51ED\u636E\u6587\u4EF6\u91CC\uFF0C\u653E\u5F03\u8FD9\u4E00\u8282\u7684\n // \u8BBE\u7F6E\u8349\u7A3F\u4E0D\u8BE5\u8BA9\u9875\u9762\u6539\u53E3\u8BF4\u300C\u8FD8\u6CA1\u6709\u5BC6\u94A5\u300D\u2014\u2014\u90A3\u662F\u53E6\u4E00\u5904\u7684\u72B6\u6001\u3002\n key: { ...this.state.key, text: '', failed: false, error: '', landed: '' },\n saveFailed: '',\n }\n : { ...this.state, rows: committed.rows, saveFailed: '' };\n this.recompute();\n }\n\n /**\n * Write one section's staged edits as one revision-fenced batch.\n *\n * The judgement section also writes a typed key, so naming the endpoint and\n * giving it its credential is one gesture rather than two. The type rows are\n * written whole rather than diffed: the array is one value, and a positional\n * number is derived from it, so a partial write could momentarily renumber the\n * list under a reader mid-save.\n *\n * @param section - which section's drafts to write.\n */\n async save(section: Section): Promise<void> {\n if (this.state.saving !== '') return;\n const form = this.form;\n if (form === null || !this.state.writable) return;\n if (section === 'rows' && (this.state.rowsInvalid !== '' || !this.state.rowsDirty)) return;\n if (section === 'judge' && !this.state.judgeDirty) return;\n\n const ops: SettingsPathOpLike[] = [];\n if (section === 'judge') {\n if (this.state.endpointUrl !== this.state.committed.endpointUrl) {\n ops.push({ op: 'set', path: ['endpointUrl'], value: this.state.endpointUrl });\n }\n if (this.state.judgeModel !== this.state.committed.judgeModel) {\n ops.push({ op: 'set', path: ['judgeModel'], value: this.state.judgeModel });\n }\n if (this.state.enabled !== this.state.committed.enabled) {\n ops.push({ op: 'set', path: ['enabled'], value: this.state.enabled });\n }\n if (this.state.logEnabled !== this.state.committed.logEnabled) {\n ops.push({ op: 'set', path: ['logEnabled'], value: this.state.logEnabled });\n }\n } else if (JSON.stringify(this.state.rows) !== JSON.stringify(this.state.committed.rows)) {\n ops.push({ op: 'set', path: ['rows'], value: this.state.rows.map((row) => ({ ...row })) });\n }\n\n this.state = { ...this.state, saving: section, saveFailed: '', saveError: '' };\n this.notify();\n\n // The key goes first: a document write the Host refuses leaves the key in\n // place, while a key that landed with a refused endpoint is still a landed\n // key. Either way the reader is told which part did not take.\n const typedKey = section === 'judge' ? this.state.key.text.trim() : '';\n let failure = '';\n let keyLanded: '' | 'saved' | 'cleared' = '';\n if (typedKey !== '') {\n const result = await this.writeKey(typedKey);\n if (result.ok) keyLanded = 'saved';\n else failure = result.error;\n }\n if (failure === '' && ops.length > 0) {\n try {\n const landed = await form.mutate(ops, form.getSnapshot().revision);\n // `false` is a refusal, not a rejection: the Host answered and did not\n // accept, so reporting success here would show a saved page over a\n // document that still holds the old value.\n if (!landed) failure = this.translate('save.refused');\n } catch (error) {\n // The Host's own words, not a generic phrase: a rejected write is the one\n // place the reader needs to know WHAT the Host objected to.\n failure = error instanceof Error && error.message !== '' ? error.message : this.translate('save.invalid');\n }\n }\n this.state = {\n ...this.state,\n saving: '',\n saveFailed: failure === '' ? '' : section,\n saveError: failure,\n key: keyLanded === '' ? this.state.key : { ...this.state.key, text: '', landed: keyLanded },\n };\n if (failure === '') this.deriveCommitted();\n else this.notify();\n }\n\n /**\n * Write one judgement key through the credentials service.\n *\n * The service resolves with `{ ok: false }` rather than rejecting when it\n * refuses a write, so that result decides the outcome. The key value is handed\n * straight to the service and is never copied into the page state.\n *\n * @param value - the staged key text, already trimmed and known non-empty.\n * @returns whether the write landed, and the message when it did not.\n */\n private async writeKey(value: string): Promise<{ ok: boolean; error: string }> {\n const credentials = this.credentials;\n if (credentials === null) return { ok: false, error: this.translate('key.unavailable') };\n this.state = { ...this.state, key: { ...this.state.key, saving: true, failed: false, error: '' } };\n this.notify();\n try {\n const response = await credentials.set(JUDGE_API_KEY_REF, value);\n if (!response.ok) {\n const error = response.error.message || this.translate('key.saveFailed');\n this.state = { ...this.state, key: { ...this.state.key, saving: false, failed: true, error } };\n return { ok: false, error };\n }\n this.state = { ...this.state, key: { ...this.state.key, saving: false, failed: false, error: '', configured: true } };\n await this.refreshKeyStatus();\n return { ok: true, error: '' };\n } catch (error) {\n const message = error instanceof Error && error.message !== '' ? error.message : this.translate('key.saveFailed');\n this.state = { ...this.state, key: { ...this.state.key, saving: false, failed: true, error: message } };\n return { ok: false, error: message };\n }\n }\n\n /**\n * Remove the stored judgement key.\n *\n * A separate control rather than \"save an empty field\": the shared\n * configuration form's own rule is that a blank draft writes nothing, so an\n * emptied input cannot mean removal without contradicting it.\n *\n * @returns settlement after the credentials read-back.\n */\n async clearKey(): Promise<void> {\n const credentials = this.credentials;\n if (credentials === null) return;\n this.state = { ...this.state, key: { ...this.state.key, saving: true, failed: false, error: '' } };\n this.notify();\n try {\n const response = await credentials.unset(JUDGE_API_KEY_REF);\n if (!response.ok) {\n this.state = {\n ...this.state,\n key: {\n ...this.state.key,\n saving: false,\n failed: true,\n error: response.error.message || this.translate('key.clearFailed'),\n },\n };\n } else {\n this.state = {\n ...this.state,\n key: { ...this.state.key, saving: false, text: '', failed: false, error: '', landed: 'cleared', configured: false },\n };\n await this.refreshKeyStatus();\n }\n } catch (error) {\n this.state = {\n ...this.state,\n key: {\n ...this.state.key,\n saving: false,\n failed: true,\n error: error instanceof Error && error.message !== '' ? error.message : this.translate('key.clearFailed'),\n },\n };\n }\n this.notify();\n }\n\n /** Read the runtime log from the Host. */\n async refreshLog(): Promise<void> {\n if (this.remote === null) return;\n try {\n const entries = await this.remote.log();\n this.state = { ...this.state, log: entries, logLoaded: true, logFailed: false };\n } catch {\n this.state = { ...this.state, logLoaded: true, logFailed: true };\n }\n this.notify();\n }\n\n /** Read the exact prompt a judgement would send. */\n async preview(): Promise<string | null> {\n if (this.remote === null) return null;\n try {\n return await this.remote.preview();\n } catch {\n return null;\n }\n }\n\n /** Test the judge endpoint against the committed settings. */\n async probe(): Promise<{ ok: boolean; latencyMs: number; reason?: string }> {\n if (this.remote === null) return { ok: false, latencyMs: 0, reason: 'unreachable' };\n try {\n return await this.remote.probe();\n } catch {\n return { ok: false, latencyMs: 0, reason: 'unreachable' };\n }\n }\n\n /** The effort ids available for one row's currently selected model. */\n effortsFor(row: TypeRowDraft): string[] {\n return this.state.models.find(\n (candidate) => candidate.provider === row.provider && candidate.model === row.model,\n )?.efforts ?? [];\n }\n\n /** Whether one row will be offered to the judge (the server's own rule). */\n rowUsable(row: TypeRowDraft): boolean {\n return isSelectableRow(row);\n }\n\n private notify(): void {\n for (const listener of [...this.listeners]) {\n try {\n listener();\n } catch {}\n }\n }\n}\n\nexport const dispatchCardStore = new DispatchCardStore();\n", "// \u7C7B\u578B\u53EA\u8BFB\uFF1A\u5EA7\u4F4D\u5951\u7EA6\u4E0E\u5B83\u7684 LocaleNamespaceMap \u5408\u5E76\u6765\u81EA\u8FD9\u4E2A\u5305\u3002\nimport type {} from '@deepseek-ai/dsh-client-ui-slots';\n\n/** \u8FD9\u4E2A\u63D2\u4EF6\u7684\u5B57\u5178\u547D\u540D\u7A7A\u95F4\uFF1A\u5EA7\u4F4D\u6CE8\u518C\u4E0E\u5361\u7247\u6587\u6848\u90FD\u7528\u5B83\u3002 */\nexport const NS = 'subagentjudgedispatch';\n/** \u82F1\u6587\u6587\u6848\u3002 */\nexport const en = {\n 'tab.design': 'Design',\n 'tab.log': 'Log',\n 'switch.rewrite.title': 'Rewrite subagent model and effort',\n 'switch.rewrite.desc':\n 'Every subagent is judged once when it is delegated. While this is off, nothing is judged and nothing is logged.',\n 'switch.log.title': 'Record the log',\n 'switch.log.desc': 'Keep the most recent judgements in this running instance. Cleared on restart.',\n 'judge.title': 'Judgement service',\n 'judge.desc':\n 'The task type is decided by this endpoint. It receives the type list and the task text, and answers with one type number.',\n 'judge.endpoint': 'Endpoint address',\n 'judge.endpointDesc': 'The full address, including the protocol path. One System One example is prefilled.',\n 'judge.model': 'Judgement model',\n 'judge.modelDesc': 'The model id this endpoint interprets.',\n 'judge.key': 'Key',\n 'judge.keyDesc': 'Stored write-only as {ref} in {path}. It is never read back into this page.',\n 'judge.keyPlaceholder': 'Paste the key',\n 'judge.keyPlaceholderSet': 'A key is stored; type a new one to replace it',\n 'judge.keySet': 'Key stored',\n 'judge.keyUnset': 'No key',\n 'judge.keyClear': 'Remove the key',\n 'judge.keySaved': 'The key is stored.',\n 'judge.keyCleared': 'The key was removed.',\n 'judge.keyFailed': 'The key was not stored: {error}',\n 'key.unavailable': 'The credentials service is unavailable on this page.',\n 'judge.keyUnavailable': 'This page has no credentials channel, so a key cannot be stored from here.',\n 'key.saveFailed': 'The key was not accepted.',\n 'key.clearFailed': 'The key was not removed.',\n 'judge.probe': 'Test the connection',\n 'judge.probing': 'Testing\u2026',\n 'judge.probeOk': 'Connected in {latency} ms',\n 'judge.probeFail': 'Not usable: {reason}',\n 'reason.unconfigured': 'the endpoint address or model is not filled in',\n 'reason.unreachable': 'the endpoint could not be reached',\n 'reason.timeout': 'it did not answer within 5 seconds',\n 'reason.unmatched': 'the answer named no listed type',\n 'reason.incomplete': 'the selected type is not filled in',\n 'reason.other': 'other',\n 'reason.unknown': 'unknown reason',\n 'rows.title': 'Task types',\n 'rows.desc':\n 'One row per task type: the number it answers with, the description it reads, the model it runs on, and the effort. Numbers are assigned for you, always 1, 2, 3\u2026',\n 'rows.empty': 'No task type yet. Add one below, or pick a ready-made entry.',\n 'rows.colId': 'No.',\n 'rows.colType': 'Task type',\n 'rows.colDescription': 'Description',\n 'rows.colModel': 'Model',\n 'rows.colEffort': 'Effort',\n 'rows.add': 'Add a row',\n 'rows.remove': 'Remove',\n 'rows.browse': 'View',\n 'rows.browseTitle': 'Task type {id}',\n 'rows.browseClose': 'Close',\n 'rows.modelPlaceholder': 'Not chosen',\n 'rows.effortPlaceholder': 'Not chosen',\n 'rows.incomplete': 'Not used',\n 'rows.descriptionPlaceholder': 'What kind of job is this? Write as much as you like.',\n 'rows.allowedEmpty':\n 'The host setting \"models subagents may choose\" is empty, so there is nothing to pick. Fill it in on the Subagent settings page first.',\n 'presets.title': 'Ready-made entries',\n 'presets.desc': 'Click one to add it to the list. The effort shown is only a hint and is not filled in for you.',\n 'presets.effortHint': 'Suggested effort: {effort}',\n 'preset.mechanical': 'Mechanical edit',\n 'preset.mechanical.desc': 'Renaming, moving, formatting, or repeated small changes that need no judgement.',\n 'preset.research': 'Gathering material',\n 'preset.research.desc': 'Reading documents or code to collect facts and report them back.',\n 'preset.smallFeature': 'Small feature',\n 'preset.smallFeature.desc': 'Implementing one clearly specified piece of behaviour.',\n 'preset.spec': 'Writing a specification',\n 'preset.spec.desc': 'Turning a request into a precise written specification.',\n 'preset.review': 'Reviewing code',\n 'preset.review.desc': 'Reading a change and reporting what is wrong or missing in it.',\n 'preset.debug': 'Debugging a hard problem',\n 'preset.debug.desc': 'Finding the cause of a failure that is not obvious from the symptom.',\n 'preset.design': 'Technical plan',\n 'preset.design.desc': 'Deciding how to build something and what the trade-offs are.',\n 'preset.test': 'Running tests',\n 'preset.test.desc': 'Running an existing check and reporting what it produced.',\n 'preset.effortLow': 'low',\n 'preset.effortMedium': 'medium',\n 'preset.effortHigh': 'high',\n 'preview.title': 'View the full prompt',\n 'preview.desc': 'Exactly what would be sent to the judgement service. The task text is filled in at delegation time.',\n 'preview.open': 'View the full prompt',\n 'preview.copy': 'Copy',\n 'preview.copied': 'Copied',\n 'preview.close': 'Close',\n 'preview.blocked': 'Save your changes first.',\n 'preview.failed': 'The preview could not be read.',\n 'save.button': 'Save',\n 'save.saving': 'Saving\u2026',\n 'save.unsaved': 'There are unsaved changes.',\n 'save.discard': 'Discard',\n 'save.refusedTitle': 'This cannot be saved yet',\n 'save.failed': 'The save did not land: {error}',\n 'save.duplicateDescription': 'Two rows have the same description. Give them different descriptions before saving.',\n 'save.emptyDescription': 'Every row needs a description before it can be saved.',\n 'save.invalid': 'This cannot be saved yet.',\n 'save.refused': 'The host did not accept this write.',\n 'log.title': 'Recent judgements',\n 'log.desc': 'The most recent 20 judgements in this running instance, newest first.',\n 'log.empty': 'No judgement has run yet.',\n 'log.colProvider': 'Provider',\n 'log.colModel': 'Model',\n 'log.colEffort': 'Effort',\n 'log.colTime': 'Time',\n 'log.colLatency': 'Took',\n 'log.sourceJudged': 'Judged as type {id}',\n 'log.sourceInherited': 'Other: {reason}',\n 'log.refresh': 'Refresh',\n 'log.detailTitle': 'Judgement detail',\n 'log.detailClose': 'Close',\n 'log.detailSource': 'Where it came from',\n 'log.detailProvider': 'Provider',\n 'log.detailModel': 'Model',\n 'log.detailEffort': 'Effort',\n 'log.detailReason': 'Reason',\n 'log.detailLatency': 'Took',\n 'log.detailParent': 'Conversation',\n 'log.detailChild': 'Subagent description',\n 'log.loadFailed': 'The log could not be read.',\n 'ms': '{value} ms',\n};\n\n/** \u4E2D\u6587\u6587\u6848\u3002\u952E\u96C6\u4E0E\u82F1\u6587\u9010\u4E00\u5BF9\u9F50\uFF08smoke-client \u4F1A\u67E5\u8FD9\u4E00\u6761\uFF09\u3002 */\nexport const zh: Record<keyof typeof en, string> = {\n 'tab.design': '\u8BBE\u8BA1',\n 'tab.log': '\u65E5\u5FD7',\n 'switch.rewrite.title': '\u6539\u5199\u5B50\u4EE3\u7406\u7684\u6A21\u578B\u4E0E\u5F3A\u5EA6',\n 'switch.rewrite.desc': '\u6BCF\u4E2A\u5B50\u4EE3\u7406\u5728\u6D3E\u5DE5\u90A3\u4E00\u523B\u5224\u65AD\u4E00\u6B21\u3002\u8FD9\u4E2A\u5F00\u5173\u5173\u7740\u65F6\u4E0D\u5224\u65AD\uFF0C\u4E5F\u4E0D\u8BB0\u65E5\u5FD7\u3002',\n 'switch.log.title': '\u8BB0\u5F55\u65E5\u5FD7',\n 'switch.log.desc': '\u5728\u672C\u6B21\u8FD0\u884C\u671F\u95F4\u4FDD\u7559\u6700\u8FD1\u7684\u5224\u65AD\u8BB0\u5F55\u3002\u91CD\u542F\u5C31\u6E05\u7A7A\u3002',\n 'judge.title': '\u5224\u65AD\u670D\u52A1',\n 'judge.desc': '\u4EFB\u52A1\u7C7B\u578B\u7531\u8FD9\u4E2A\u5730\u5740\u51B3\u5B9A\uFF1A\u5B83\u6536\u5230\u7C7B\u578B\u6E05\u5355\u548C\u4EFB\u52A1\u6587\u5B57\uFF0C\u56DE\u7B54\u4E00\u4E2A\u7C7B\u578B\u7F16\u53F7\u3002',\n 'judge.endpoint': '\u7AEF\u70B9\u5730\u5740',\n 'judge.endpointDesc': '\u5B8C\u6574\u5730\u5740\uFF0C\u8981\u5E26\u534F\u8BAE\u8DEF\u5F84\u3002\u5DF2\u7ECF\u9884\u586B\u4E00\u4E2A System One \u7684\u4F8B\u5B50\u3002',\n 'judge.model': '\u5224\u65AD\u6A21\u578B',\n 'judge.modelDesc': '\u8FD9\u4E2A\u5730\u5740\u6240\u4F7F\u7528\u7684\u6A21\u578B\u540D\u3002',\n 'judge.key': '\u5BC6\u94A5',\n 'judge.keyDesc': '\u4EE5 {ref} \u7684\u540D\u5B57\u5B58\u8FDB {path}\uFF0C\u53EA\u5199\u4E0D\u8BFB\uFF0C\u4E0D\u4F1A\u56DE\u586B\u5230\u8FD9\u4E00\u9875\u3002',\n 'judge.keyPlaceholder': '\u628A\u5BC6\u94A5\u8D34\u8FDB\u6765',\n 'judge.keyPlaceholderSet': '\u5DF2\u7ECF\u5B58\u4E86\u5BC6\u94A5\uFF0C\u8981\u6362\u5C31\u586B\u4E00\u4E2A\u65B0\u7684',\n 'judge.keySet': '\u5DF2\u5B58\u5BC6\u94A5',\n 'judge.keyUnset': '\u8FD8\u6CA1\u6709\u5BC6\u94A5',\n 'judge.keyClear': '\u5220\u6389\u5BC6\u94A5',\n 'judge.keySaved': '\u5BC6\u94A5\u5DF2\u5B58\u3002',\n 'judge.keyCleared': '\u5BC6\u94A5\u5DF2\u5220\u6389\u3002',\n 'judge.keyFailed': '\u5BC6\u94A5\u6CA1\u5B58\u4E0A\uFF1A{error}',\n 'key.unavailable': '\u8FD9\u4E2A\u9875\u9762\u4E0A\u7528\u4E0D\u4E86\u51ED\u636E\u670D\u52A1\u3002',\n 'judge.keyUnavailable': '\u8FD9\u4E2A\u9875\u9762\u4E0A\u6CA1\u6709\u51ED\u636E\u901A\u9053\uFF0C\u5728\u8FD9\u91CC\u5B58\u4E0D\u4E86\u5BC6\u94A5\u3002',\n 'key.saveFailed': '\u5BC6\u94A5\u6CA1\u88AB\u63A5\u53D7\u3002',\n 'key.clearFailed': '\u5BC6\u94A5\u6CA1\u5220\u6389\u3002',\n 'judge.probe': '\u8BD5\u4E00\u4E0B\u901A\u4E0D\u901A',\n 'judge.probing': '\u6B63\u5728\u8BD5\u2026',\n 'judge.probeOk': '\u8FDE\u4E0A\u4E86\uFF0C\u7528\u4E86 {latency} \u6BEB\u79D2',\n 'judge.probeFail': '\u7528\u4E0D\u4E86\uFF1A{reason}',\n 'reason.unconfigured': '\u7AEF\u70B9\u5730\u5740\u6216\u5224\u65AD\u6A21\u578B\u8FD8\u6CA1\u586B',\n 'reason.unreachable': '\u8FDE\u4E0D\u4E0A\u8FD9\u4E2A\u5730\u5740',\n 'reason.timeout': '\u7B49\u4E86 5 \u79D2\u6CA1\u56DE',\n 'reason.unmatched': '\u7B54\u590D\u5BF9\u4E0D\u4E0A\u6E05\u5355',\n 'reason.incomplete': '\u9009\u4E2D\u7684\u7C7B\u578B\u6CA1\u586B\u5168',\n 'reason.other': '\u5176\u4ED6',\n 'reason.unknown': '\u539F\u56E0\u4E0D\u660E',\n 'rows.title': '\u4EFB\u52A1\u7C7B\u578B',\n 'rows.desc':\n '\u4E00\u884C\u4E00\u4E2A\u4EFB\u52A1\u7C7B\u578B\uFF1A\u5B83\u56DE\u7B54\u7684\u7F16\u53F7\u3001\u5B83\u8BFB\u7684\u63CF\u8FF0\u3001\u8BE5\u7528\u7684\u6A21\u578B\u4E0E\u5F3A\u5EA6\u3002\u7F16\u53F7\u7531\u63D2\u4EF6\u81EA\u52A8\u6392\uFF0C\u6C38\u8FDC\u4ECE 1 \u5F80\u540E\u8FDE\u7740\u3002',\n 'rows.empty': '\u8FD8\u6CA1\u6709\u4EFB\u52A1\u7C7B\u578B\u3002\u5728\u4E0B\u9762\u52A0\u4E00\u884C\uFF0C\u6216\u8005\u70B9\u4E00\u4E2A\u9884\u5236\u8BCD\u6761\u3002',\n 'rows.colId': '\u7F16\u53F7',\n 'rows.colType': '\u4EFB\u52A1\u7C7B\u578B',\n 'rows.colDescription': '\u63CF\u8FF0',\n 'rows.colModel': '\u6A21\u578B',\n 'rows.colEffort': '\u5F3A\u5EA6',\n 'rows.add': '\u52A0\u4E00\u884C',\n 'rows.remove': '\u5220\u6389',\n 'rows.browse': '\u67E5\u770B',\n 'rows.browseTitle': '\u4EFB\u52A1\u7C7B\u578B {id}',\n 'rows.browseClose': '\u5173\u95ED',\n 'rows.modelPlaceholder': '\u8FD8\u6CA1\u9009',\n 'rows.effortPlaceholder': '\u8FD8\u6CA1\u9009',\n 'rows.incomplete': '\u4E0D\u751F\u6548',\n 'rows.descriptionPlaceholder': '\u8FD9\u662F\u54EA\u79CD\u6D3B\uFF1F\u5199\u591A\u5C11\u90FD\u884C\u3002',\n 'rows.allowedEmpty': '\u5BBF\u4E3B\u90A3\u4EFD\u300C\u5B50\u4EE3\u7406\u53EF\u9009\u7528\u54EA\u4E9B\u6A21\u578B\u300D\u8FD8\u662F\u7A7A\u7684\uFF0C\u6CA1\u6709\u53EF\u4EE5\u9009\u7684\u4E1C\u897F\u3002\u5148\u5230\u5B50\u4EE3\u7406\u8BBE\u7F6E\u9875\u628A\u5B83\u586B\u4E0A\u3002',\n 'presets.title': '\u9884\u5236\u8BCD\u6761',\n 'presets.desc': '\u70B9\u4E00\u4E0B\u5C31\u52A0\u8FDB\u6E05\u5355\u3002\u65C1\u8FB9\u7684\u5F3A\u5EA6\u53EA\u662F\u63D0\u793A\uFF0C\u4E0D\u4F1A\u66FF\u4F60\u586B\u8FDB\u90A3\u4E24\u680F\u3002',\n 'presets.effortHint': '\u5EFA\u8BAE\u5F3A\u5EA6\uFF1A{effort}',\n 'preset.mechanical': '\u673A\u68B0\u4FEE\u6539',\n 'preset.mechanical.desc': '\u6539\u540D\u3001\u79FB\u52A8\u3001\u6392\u7248\uFF0C\u6216\u8005\u4E00\u6279\u4E0D\u9700\u8981\u5224\u65AD\u7684\u91CD\u590D\u5C0F\u6539\u3002',\n 'preset.research': '\u8D44\u6599\u6536\u96C6',\n 'preset.research.desc': '\u8BFB\u6587\u6863\u6216\u8BFB\u4EE3\u7801\uFF0C\u628A\u4E8B\u5B9E\u6536\u96C6\u8D77\u6765\u56DE\u62A5\u3002',\n 'preset.smallFeature': '\u5B9E\u73B0\u5C0F\u529F\u80FD',\n 'preset.smallFeature.desc': '\u5B9E\u73B0\u4E00\u6BB5\u5DF2\u7ECF\u8BB2\u6E05\u695A\u7684\u884C\u4E3A\u3002',\n 'preset.spec': '\u5199\u89C4\u683C',\n 'preset.spec.desc': '\u628A\u4E00\u53E5\u8981\u6C42\u5199\u6210\u4E00\u4EFD\u8BF4\u6E05\u695A\u7684\u89C4\u683C\u3002',\n 'preset.review': '\u8BC4\u5BA1\u4EE3\u7801',\n 'preset.review.desc': '\u8BFB\u4E00\u5904\u6539\u52A8\uFF0C\u6307\u51FA\u54EA\u91CC\u4E0D\u5BF9\u3001\u54EA\u91CC\u7F3A\u4E86\u3002',\n 'preset.debug': '\u8C03\u8BD5\u7591\u96BE',\n 'preset.debug.desc': '\u627E\u51FA\u4E00\u4E2A\u4ECE\u73B0\u8C61\u770B\u4E0D\u51FA\u6765\u7684\u5931\u8D25\u7684\u8D77\u56E0\u3002',\n 'preset.design': '\u505A\u6280\u672F\u65B9\u6848',\n 'preset.design.desc': '\u51B3\u5B9A\u8FD9\u4EF6\u4E8B\u600E\u4E48\u505A\uFF0C\u4EE5\u53CA\u5404\u6761\u8DEF\u7684\u53D6\u820D\u3002',\n 'preset.test': '\u8DD1\u6D4B\u8BD5',\n 'preset.test.desc': '\u8DD1\u4E00\u6B21\u73B0\u6210\u7684\u68C0\u67E5\uFF0C\u628A\u7ED3\u679C\u62A5\u56DE\u6765\u3002',\n 'preset.effortLow': '\u4F4E',\n 'preset.effortMedium': '\u4E2D',\n 'preset.effortHigh': '\u9AD8',\n 'preview.title': '\u67E5\u770B\u5B8C\u6574\u9884\u89C8',\n 'preview.desc': '\u771F\u6B63\u4F1A\u53D1\u7ED9\u5224\u65AD\u670D\u52A1\u7684\u90A3\u6BB5\u5185\u5BB9\u3002\u4EFB\u52A1\u6587\u5B57\u5728\u6D3E\u5DE5\u90A3\u4E00\u523B\u624D\u586B\u8FDB\u53BB\u3002',\n 'preview.open': '\u67E5\u770B\u5B8C\u6574\u9884\u89C8',\n 'preview.copy': '\u590D\u5236',\n 'preview.copied': '\u5DF2\u590D\u5236',\n 'preview.close': '\u5173\u95ED',\n 'preview.blocked': '\u5148\u628A\u6539\u52A8\u4FDD\u5B58\u4E0B\u6765\u3002',\n 'preview.failed': '\u9884\u89C8\u8BFB\u4E0D\u51FA\u6765\u3002',\n 'save.button': '\u4FDD\u5B58',\n 'save.saving': '\u6B63\u5728\u4FDD\u5B58\u2026',\n 'save.unsaved': '\u6709\u8FD8\u6CA1\u4FDD\u5B58\u7684\u6539\u52A8\u3002',\n 'save.discard': '\u653E\u5F03\u6539\u52A8',\n 'save.refusedTitle': '\u73B0\u5728\u8FD8\u5B58\u4E0D\u4E86',\n 'save.failed': '\u6CA1\u4FDD\u5B58\u4E0A\uFF1A{error}',\n 'save.duplicateDescription': '\u6709\u4E24\u6761\u7684\u63CF\u8FF0\u4E00\u6A21\u4E00\u6837\u3002\u6539\u6210\u4E0D\u4E00\u6837\u7684\u518D\u4FDD\u5B58\u3002',\n 'save.emptyDescription': '\u6BCF\u4E00\u884C\u90FD\u8981\u6709\u63CF\u8FF0\u624D\u80FD\u4FDD\u5B58\u3002',\n 'save.invalid': '\u73B0\u5728\u8FD8\u5B58\u4E0D\u4E86\u3002',\n 'save.refused': '\u5BBF\u4E3B\u6CA1\u6709\u63A5\u53D7\u8FD9\u6B21\u5199\u5165\u3002',\n 'log.title': '\u6700\u8FD1\u7684\u5224\u65AD',\n 'log.desc': '\u672C\u6B21\u8FD0\u884C\u671F\u95F4\u6700\u8FD1\u7684 20 \u6761\u5224\u65AD\uFF0C\u65B0\u7684\u5728\u6700\u524D\u9762\u3002',\n 'log.empty': '\u8FD8\u6CA1\u6709\u5224\u65AD\u8FC7\u3002',\n 'log.colProvider': '\u4F9B\u5E94\u5546',\n 'log.colModel': '\u6A21\u578B',\n 'log.colEffort': '\u5F3A\u5EA6',\n 'log.colTime': '\u65F6\u95F4',\n 'log.colLatency': '\u8017\u65F6',\n 'log.sourceJudged': '\u5224\u6210\u7C7B\u578B {id}',\n 'log.sourceInherited': '\u5176\u4ED6\uFF1A{reason}',\n 'log.refresh': '\u5237\u65B0',\n 'log.detailTitle': '\u5224\u65AD\u8BE6\u60C5',\n 'log.detailClose': '\u5173\u95ED',\n 'log.detailSource': '\u7ED3\u679C\u6765\u6E90',\n 'log.detailProvider': '\u4F9B\u5E94\u5546',\n 'log.detailModel': '\u6A21\u578B',\n 'log.detailEffort': '\u5F3A\u5EA6',\n 'log.detailReason': '\u539F\u56E0',\n 'log.detailLatency': '\u8017\u65F6',\n 'log.detailParent': '\u4F1A\u8BDD',\n 'log.detailChild': '\u5B50\u4EE3\u7406\u63CF\u8FF0',\n 'log.loadFailed': '\u65E5\u5FD7\u8BFB\u4E0D\u51FA\u6765\u3002',\n 'ms': '{value} \u6BEB\u79D2',\n};\n\n/**\n * \u628A\u5B57\u5178\u4EA4\u7ED9\u5BBF\u4E3B\u3002\u547D\u540D\u7A7A\u95F4\u4E0E\u952E\u96C6\u5728\u8FD9\u91CC\u58F0\u660E\u7684\u7C7B\u578B\u540C\u65F6\u662F\u5EA7\u4F4D `t` \u7684\u5951\u7EA6\u3002\n * @param ctx - \u5BA2\u6237\u7AEF\u4E0A\u4E0B\u6587\uFF08`locale` \u7531 inject \u58F0\u660E\uFF09\u3002\n */\nexport function apply(ctx: {\n effect(factory: () => () => void, label?: string): unknown;\n locale: { register(ns: string, dictionaries: unknown): () => void };\n}): void {\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'dsh-subagent-judge-dispatch: dictionaries');\n}\n\n/** \u672C\u547D\u540D\u7A7A\u95F4\u5168\u90E8\u952E\u7684\u7C7B\u578B\uFF0C\u5EA7\u4F4D\u4E0A\u7684 `t` \u6309\u5B83\u505A\u952E\u68C0\u67E5\u3002 */\nexport type JudgeDispatchLocaleKey = keyof typeof en;\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n /** \u672C\u63D2\u4EF6\u914D\u7F6E\u5361\u7247\u7684\u6587\u6848\u3002 */\n subagentjudgedispatch: JudgeDispatchLocaleKey;\n }\n}\n"],
|
|
4
|
+
"sourcesContent": ["import type { Context as ClientContext } from '@deepseek-ai/cordis';\n// \u7C7B\u578B\u53EA\u8BFB\uFF1A\u8FD9\u4E9B\u5305\u7684\u6D4F\u89C8\u5668\u534A\u8FB9\u628A\u5EA7\u4F4D\u5951\u7EA6\u4E0E `ctx.configForms` \u5408\u5E76\u8FDB Context\u3002\nimport type {} from '@deepseek-ai/dsh-client-locale/client';\nimport type {} from '@deepseek-ai/dsh-client-ui-renderer/client';\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client';\nimport { injectCardStyles, setupSettingsUi } from './settings/ui.tsx';\nimport { apply as registerDictionaries, en, zh } from './locales.ts';\n\n/**\n * \u6D4F\u89C8\u5668\u534A\u8FB9\uFF1A\u628A\u914D\u7F6E\u5361\u7247\u6302\u5230\u5BBF\u4E3B\u7684\u300C\u63D2\u4EF6\u300D\u9875\u4E0A\u3002\n *\n * `inject` \u662F cordis \u670D\u52A1\u540D\uFF08`remote.credentials` \u662F\u5224\u65AD\u5BC6\u94A5\u7684\u5199\u5165\u901A\u9053\uFF09\uFF1B\n * `package.json` \u7684 `dsh.client.inject` \u662F\u5305\u540D\u3002\n * \u4E24\u5C42\u90FD\u8981\u58F0\u660E\uFF0C\u6F0F\u4E00\u5C42\u6574\u6761 loader entry \u4F1A\u9759\u9ED8\u53D8\u6210 failed\uFF0C\u9875\u9762\u4E0A\u4EC0\u4E48\u4E5F\u770B\u4E0D\u89C1\n * \uFF08\u89C1 docs/rules/client-wiring.md\uFF09\u3002\n */\nexport const name = '@lynn123411/dsh-subagent-judge-dispatch';\nexport const inject = ['slots', 'configForms', 'remote', 'remote.session', 'remote.credentials', 'locale'];\n\n/**\n * \u63D2\u4EF6\u672C\u4F53\uFF1A\u6CE8\u518C\u5B57\u5178\uFF0C\u518D\u6302\u914D\u7F6E\u5361\u7247\u3002\n * @param ctx - \u5BA2\u6237\u7AEF\u6839\u4E0A\u4E0B\u6587\u3002\n */\nexport function apply(ctx: ClientContext): void {\n injectCardStyles();\n registerDictionaries(ctx);\n ctx.effect(\n () => {\n setupSettingsUi(ctx as never);\n return () => {};\n },\n 'dsh-subagent-judge-dispatch: plugins page config',\n );\n}\n\nexport { NS } from './locales.ts';\nexport { en, zh } from './locales.ts';\n\n/** \u5B57\u5178\u672C\u4F53\uFF0C\u968F bundle \u5BFC\u51FA\u4F9B\u81EA\u68C0\u6838\u5BF9\u952E\u96C6\u3002 */\nexport const __dictionaries = { en, zh };\nexport { JudgeDispatchPanel, injectCardStyles, setupSettingsUi } from './settings/ui.tsx';\nexport {\n ALLOWED_MODELS_NAMESPACE,\n buildModelOptions,\n createDispatchRemote,\n dispatchCardStore,\n readRow,\n SETTINGS_NAMESPACE,\n validateRows,\n} from './settings/store.ts';\n", "import { useEffect, useState } from 'react';\nimport * as React from 'react';\nimport type { PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';\nimport {\n Button,\n CodeBlock,\n Input,\n Menu,\n Modal,\n SegmentedTabs,\n Switch,\n Tag,\n} from '@deepseek-ai/dsh-client-ui-primitives';\nimport {\n BUNDLE_CONFIG_KEY,\n BUNDLE_CONFIG_SLOT,\n setupPluginPage,\n} from './plugin-page.ts';\nimport {\n ALLOWED_MODELS_NAMESPACE,\n createDispatchRemote,\n dispatchCardStore,\n JUDGE_API_KEY_REF,\n type CredentialsRemoteLike,\n routeKey,\n SETTINGS_NAMESPACE,\n splitRouteKey,\n type LogRow,\n type PageState,\n type Section,\n type TypeRowDraft,\n} from './store.ts';\nimport { NS } from '../locales.ts';\n\n/** The ready-made entries, each with the effort hint it ships. */\nconst PRESETS: readonly { key: string; effortHint: string }[] = [\n { key: 'mechanical', effortHint: 'preset.effortLow' },\n { key: 'research', effortHint: 'preset.effortLow' },\n { key: 'smallFeature', effortHint: 'preset.effortMedium' },\n { key: 'spec', effortHint: 'preset.effortHigh' },\n { key: 'review', effortHint: 'preset.effortMedium' },\n { key: 'debug', effortHint: 'preset.effortHigh' },\n { key: 'design', effortHint: 'preset.effortHigh' },\n { key: 'test', effortHint: 'preset.effortLow' },\n];\n\n/** Path shown in the key hint; the value itself never reaches the page. */\nconst CREDENTIALS_PATH = '~/.dsh/.credentials.yaml';\n\n/** One localized template with technical samples rendered inline. */\nfunction withSamples(text: string, samples: Record<string, string>): React.ReactNode {\n return text.split(/(\\{\\w+\\})/g).map((part, index) => {\n const name = /^\\{\\w+\\}$/.test(part) ? part.slice(1, -1) : '';\n const sample = name === '' ? undefined : samples[name];\n return sample === undefined ? part : <code key={index}>{sample}</code>;\n });\n}\n\n/**\n * The card's own styles.\n *\n * Only the shapes the Host's controls do not carry: the settings-card material\n * (R20, the settings stroke and fill), the section and field rows, and the\n * task-type table. Every colour resolves through a `--dsw-alias-*` token, and\n * every elevated surface uses the settings-card material rather than a border\n * plus a shadow.\n */\nconst CARD_CSS = `\n.dsh-judge-card { display: flex; flex-direction: column; gap: 16px; box-sizing: border-box; width: 100%; max-width: 760px; color: var(--dsw-alias-label-primary); }\n.dsh-judge-panel { display: flex; flex-direction: column; gap: 16px; }\n.dsh-judge-section {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 16px 18px;\n border: 0.5px solid var(--dsw-alias-settings-card-stroke);\n border-radius: var(--dsw-radius-xl);\n background: var(--dsw-alias-settings-card-fill);\n}\n.dsh-judge-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }\n.dsh-judge-title { font: var(--dsw-font-s-strong-14); }\n.dsh-judge-desc { max-width: 46em; color: var(--dsw-alias-label-tertiary); font: var(--dsw-font-xxs-12); }\n.dsh-judge-desc code { font-family: var(--ds-font-family-code); }\n.dsh-judge-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 24px; }\n.dsh-judge-row + .dsh-judge-row { padding-top: 12px; border-top: 0.5px solid var(--dsw-alias-border-l3); }\n.dsh-judge-row-info { flex: 1; min-width: 0; }\n.dsh-judge-row-title { font: var(--dsw-font-xs-strong-13); }\n.dsh-judge-row-hint { margin-top: 2px; color: var(--dsw-alias-label-tertiary); font: var(--dsw-font-xxs-12); }\n.dsh-judge-row-field { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; box-sizing: border-box; width: 360px; max-width: 100%; }\n/* \u5BBF\u4E3B\u7684 Input \u628A\u8F93\u5165\u6846\u5305\u5728\u4E00\u5C42 inline-flex \u7684 span \u91CC\uFF0C\u7C7B\u540D\u843D\u5728\u90A3\u5C42 span \u4E0A\uFF0C\n \u6240\u4EE5\u8981\u6491\u7684\u662F\u5B83\uFF0C\u53EA\u7ED9 input \u5199\u5BBD\u5EA6\u6CA1\u7528\u3002 */\n.dsh-judge-field { display: flex; box-sizing: border-box; width: 100%; min-width: 0; }\n.dsh-judge-field input { box-sizing: border-box; width: 100%; min-width: 0; }\n.dsh-judge-key-line { display: flex; align-items: center; gap: 8px; box-sizing: border-box; width: 100%; }\n.dsh-judge-off { display: block; color: var(--dsw-alias-state-warn-label); font: var(--dsw-font-xxxs-11); white-space: nowrap; }\n.dsh-judge-head-actions { display: flex; align-items: center; gap: 8px; }\n.dsh-judge-actions { display: flex; align-items: center; justify-content: flex-start; gap: 8px; padding-top: 12px; border-top: 0.5px solid var(--dsw-alias-border-l3); }\n.dsh-judge-hint { color: var(--dsw-alias-label-tertiary); font: var(--dsw-font-xxs-12); }\n.dsh-judge-note-ok { color: var(--dsw-alias-state-success-primary); font: var(--dsw-font-xxs-12); }\n.dsh-judge-note-bad { color: var(--dsw-alias-state-error-primary); font: var(--dsw-font-xxs-12); }\n.dsh-judge-field-wrap { display: flex; box-sizing: border-box; width: 100%; min-width: 0; }\n.dsh-judge-table { box-sizing: border-box; width: 100%; border-collapse: collapse; table-layout: fixed; }\n.dsh-judge-table th, .dsh-judge-table td { box-sizing: border-box; }\n.dsh-judge-table th {\n padding: 0 8px 6px 0;\n color: var(--dsw-alias-label-tertiary);\n font: var(--dsw-font-xxs-12);\n text-align: left;\n}\n.dsh-judge-table td { padding: 6px 8px 6px 0; vertical-align: middle; }\n.dsh-judge-table tbody tr + tr td { border-top: 0.5px solid var(--dsw-alias-border-l3); }\n.dsh-judge-table td:last-child, .dsh-judge-table th:last-child { padding-right: 0; }\n.dsh-judge-col-no { width: 52px; }\n.dsh-judge-col-model { width: 188px; }\n.dsh-judge-col-effort { width: 124px; }\n.dsh-judge-col-actions { width: 148px; }\n.dsh-judge-no { color: var(--dsw-alias-label-tertiary); font: var(--dsw-font-xxs-12); font-variant-numeric: tabular-nums; }\n.dsh-judge-row-off .dsh-judge-field { opacity: 0.6; }\n.dsh-judge-cell-actions { display: flex; gap: 6px; }\n.dsh-judge-presets { display: flex; flex-wrap: wrap; gap: 6px; }\n.dsh-judge-preset { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; padding: 6px 10px; border: 0.5px solid var(--dsw-alias-border-l3); border-radius: var(--dsw-radius-md); background: none; color: inherit; font: inherit; text-align: left; cursor: pointer; }\n.dsh-judge-preset:hover { background: var(--dsw-alias-interactive-bg-hover); }\n.dsh-judge-preset-title { font: var(--dsw-font-xs-13); }\n.dsh-judge-preset-hint { color: var(--dsw-alias-label-tertiary); font: var(--dsw-font-xxxs-11); }\n.dsh-judge-log { display: flex; flex-direction: column; gap: 4px; font: var(--dsw-font-xxs-12); }\n.dsh-judge-log-row { display: grid; grid-template-columns: 130px minmax(0, 1fr) 80px 92px 84px; gap: 8px; align-items: center; text-align: left; border: 0; background: none; padding: 6px 4px; border-radius: var(--dsw-radius-sm); cursor: pointer; color: inherit; }\n.dsh-judge-cell-clip { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.dsh-judge-log-row:hover { background: var(--dsw-alias-interactive-bg-hover); }\n.dsh-judge-log-head { font-weight: 600; color: var(--dsw-alias-label-tertiary); cursor: default; }\n.dsh-judge-log-head:hover { background: none; }\n.dsh-judge-detail { display: grid; grid-template-columns: 140px 1fr; gap: 6px 12px; font: var(--dsw-font-xs-13); }\n/* \u9884\u89C8\u91CC\u662F\u4E00\u6574\u6BB5 JSON\uFF0C\u9ED8\u8BA4\u7684\u5F39\u7A97\u5BBD\u5EA6\u4F1A\u628A\u5B83\u6298\u5F97\u5F88\u788E\u3002 */\n.dsh-judge-modal { width: min(760px, 100%); max-height: min(85vh, 100%); }\n`;\n\n/**\n * Append this card's stylesheet once, at apply() time.\n *\n * Injection happens here rather than on first render because the host's own\n * stylesheets are already-loaded `<link>` elements: a plugin sheet appended\n * later wins at equal specificity, and doing it once in apply() keeps that\n * order stable across remounts. The id makes the append idempotent.\n */\nexport function injectCardStyles(): void {\n if (typeof document === 'undefined') return;\n if (document.getElementById(STYLE_ID) !== null) return;\n const element = document.createElement('style');\n element.id = STYLE_ID;\n element.textContent = CARD_CSS;\n document.head.appendChild(element);\n}\n\n/** DOM id of this card's stylesheet, so a remount does not append a second one. */\nconst STYLE_ID = 'dsh-subagent-judge-dispatch-styles';\n\n/**\n * This plugin's configuration card inside the DSH **Plugins** page.\n *\n * Two tabs. The design tab holds two independently saved sections \u2014 the\n * judgement service, and the task-type table \u2014 because each is edited on its own\n * occasion and fails on its own terms; a single save for both would let an\n * unfinished description block an endpoint change. The log tab reads the Host's\n * runtime log. Nothing is written while the reader types.\n *\n * @param props - the renderer-bound seat of `plugins.bundle.config`.\n * @returns the card element.\n */\nexport function JudgeDispatchPanel(\n props: PropsRuntime<'plugins.bundle.config'> & PropsLocale<typeof NS>,\n): React.ReactElement {\n const { t } = props;\n\n const [state, setState] = useState<PageState>(() => dispatchCardStore.getState());\n const [tab, setTab] = useState<'design' | 'log'>('design');\n const [browsing, setBrowsing] = useState<number | null>(null);\n const [preview, setPreview] = useState<string | null>(null);\n const [previewOpen, setPreviewOpen] = useState(false);\n const [probing, setProbing] = useState(false);\n const [probeResult, setProbeResult] = useState<{ ok: boolean; latencyMs: number; reason?: string } | null>(null);\n const [detail, setDetail] = useState<LogRow | null>(null);\n /** Which row's dropdown is open, and which of the two. */\n const [openMenu, setOpenMenu] = useState<{ index: number; kind: 'model' | 'effort' } | null>(null);\n /** The reason a save was refused, shown as a popup. */\n const [refusal, setRefusal] = useState<string | null>(null);\n\n useEffect(() => {\n setState(dispatchCardStore.getState());\n return dispatchCardStore.subscribe(() => setState(dispatchCardStore.getState()));\n }, []);\n\n useEffect(() => {\n if (tab === 'log') void dispatchCardStore.refreshLog();\n }, [tab]);\n\n /** Localized reason text for one fallback. */\n const reasonText = (reason: string | undefined): string =>\n t(`reason.${reason ?? 'other'}` as never) || t('reason.unknown');\n\n const runProbe = async (): Promise<void> => {\n setProbing(true);\n setProbeResult(await dispatchCardStore.probe());\n setProbing(false);\n };\n\n /** \u7C7B\u578B\u6E05\u5355\u6709\u7F3A\u65F6\u6309\u6309\u94AE\u4E0D\u7ED9\u5199\uFF1A\u628A\u539F\u56E0\u5F39\u51FA\u6765\uFF0C\u800C\u4E0D\u662F\u8BA9\u6309\u94AE\u70B9\u4E0D\u52A8\u3002 */\n const saveRows = (): void => {\n if (state.rowsInvalid !== '') {\n setRefusal(state.rowsInvalid);\n return;\n }\n void dispatchCardStore.save('rows');\n };\n\n const openPreview = async (): Promise<void> => {\n const text = await dispatchCardStore.preview();\n setPreview(text ?? t('preview.failed'));\n setPreviewOpen(true);\n };\n\n /** One section's save row: the write, the discard, and what a save would do. */\n const saveRow = (section: Section, dirty: boolean, onSave: () => void): React.ReactElement => (\n <div className=\"dsh-judge-actions\">\n {/* \u7C7B\u578B\u6E05\u5355\u6709\u7F3A\u65F6\u6309\u94AE\u4ECD\u53EF\u70B9\uFF1A\u6309\u4E0B\u53BB\u7531 saveRows \u5F39\u7A97\u8BF4\u660E\u4E3A\u4EC0\u4E48\u5B58\u4E0D\u4E86\u3002\n \u505A\u6210 disabled \u7684\u8BDD\uFF0C\u8BFB\u8005\u53EA\u770B\u5230\u4E00\u4E2A\u70B9\u4E0D\u52A8\u7684\u6309\u94AE\uFF0C\u4E0D\u77E5\u9053\u8981\u6539\u54EA\u91CC\u3002 */}\n <Button\n variant=\"primary\"\n size=\"sm\"\n disabled={state.saving !== '' || !dirty || !state.writable}\n onClick={onSave}\n >\n {state.saving === section ? t('save.saving') : t('save.button')}\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={state.saving !== '' || !dirty}\n onClick={() => dispatchCardStore.revert(section)}\n >\n {t('save.discard')}\n </Button>\n {dirty && <span className=\"dsh-judge-hint\">{t('save.unsaved')}</span>}\n {/* \u5931\u8D25\u6309\u8282\u62A5\uFF1A\u5224\u65AD\u670D\u52A1\u90A3\u6B21\u4FDD\u5B58\u6CA1\u843D\u5730\u65F6\uFF0C\u4EFB\u52A1\u7C7B\u578B\u90A3\u4E00\u8282\u4E0D\u8BE5\u8DDF\u7740\u62A5\u9519\u3002 */}\n {state.saveFailed === section && state.saveError !== '' && (\n <span className=\"dsh-judge-note-bad\" role=\"alert\">\n {t('save.failed').replace('{error}', state.saveError)}\n </span>\n )}\n </div>\n );\n\n /** One task-type row as three cells plus its row number and its actions. */\n const row = (draft: TypeRowDraft, index: number): React.ReactElement => {\n const efforts = dispatchCardStore.effortsFor(draft);\n const usable = dispatchCardStore.rowUsable(draft);\n // \u53EA\u6709\u300C\u76EE\u5F55\u8BFB\u5230\u4E86\u3001\u4E14\u8FD9\u4E2A\u8DEF\u7531\u786E\u5B9E\u58F0\u660E\u4E86\u6863\u4F4D\u300D\u65F6\u624D\u7ED9\u4E0B\u62C9\uFF1B\u5426\u5219\u81EA\u7531\u586B\u5199\u3002\n const catalogOffersEffort = state.catalogRead && efforts.length > 0;\n return (\n <tr key={index} className={usable ? undefined : 'dsh-judge-row-off'}>\n <td className=\"dsh-judge-col-no\">\n <span className=\"dsh-judge-no\">{index + 1}</span>\n {usable ? null : <span className=\"dsh-judge-off\">{t('rows.incomplete')}</span>}\n </td>\n <td>\n <Input\n type=\"text\"\n className=\"dsh-judge-field\"\n value={draft.description}\n placeholder={t('rows.descriptionPlaceholder')}\n aria-label={`${t('rows.colDescription')} ${index + 1}`}\n onChange={(event: React.ChangeEvent<HTMLInputElement>) =>\n dispatchCardStore.cell(index, 'description', event.target.value)}\n />\n </td>\n <td>\n <Menu\n open={openMenu?.index === index && openMenu.kind === 'model'}\n anchor={<Input\n type=\"text\"\n className=\"dsh-judge-field\"\n readOnly\n value={draft.model === '' ? '' : `${draft.provider}/${draft.model}`}\n placeholder={t('rows.modelPlaceholder')}\n aria-label={`${t('rows.colModel')} ${index + 1}`}\n aria-haspopup=\"listbox\"\n aria-expanded={openMenu?.index === index && openMenu.kind === 'model'}\n onClick={() => setOpenMenu({ index, kind: 'model' })}\n onFocus={() => setOpenMenu({ index, kind: 'model' })}\n />}\n items={[\n { type: 'label', id: 'model', text: t('rows.colModel') },\n ...(state.models.length === 0\n ? []\n : state.models.map((option) => ({\n id: routeKey(option.provider, option.model),\n label: `${option.provider}/${option.label}`,\n }))),\n ]}\n selectedId={draft.model === '' ? undefined : routeKey(draft.provider, draft.model)}\n onSelect={(id) => {\n const { provider, model } = splitRouteKey(id);\n dispatchCardStore.cell(index, 'provider', provider);\n dispatchCardStore.cell(index, 'model', model);\n setOpenMenu(null);\n }}\n onClose={() => setOpenMenu(null)}\n className=\"dsh-judge-field-wrap\"\n portal\n />\n </td>\n {/* \u76EE\u5F55\u8BFB\u5F97\u5230\u65F6\uFF0C\u5F3A\u5EA6\u662F\u8FD9\u4EFD\u53EF\u9009\u6863\u4F4D\u91CC\u7684\u4E00\u4E2A\uFF1B\u8BFB\u4E0D\u5230\uFF08\u6216\u8FD9\u4E2A\u8DEF\u7531\u6CA1\u58F0\u660E\u6863\u4F4D\uFF09\n \u65F6\u9000\u56DE\u81EA\u7531\u586B\u5199\u2014\u2014\u628A\u683C\u5B50\u7981\u6389\u4F1A\u8BA9\u6574\u5F20\u8868\u6C38\u8FDC\u586B\u4E0D\u5168\uFF0C\u4E5F\u5C31\u6C38\u8FDC\u4E0D\u518D\u5224\u65AD\u4EFB\u4F55\u4E1C\u897F\u3002 */}\n <td>\n {catalogOffersEffort ? (\n <Menu\n open={openMenu?.index === index && openMenu.kind === 'effort'}\n anchor={<Input\n type=\"text\"\n className=\"dsh-judge-field\"\n readOnly\n value={draft.effort}\n placeholder={t('rows.effortPlaceholder')}\n aria-label={`${t('rows.colEffort')} ${index + 1}`}\n aria-haspopup=\"listbox\"\n aria-expanded={openMenu?.index === index && openMenu.kind === 'effort'}\n onClick={() => setOpenMenu({ index, kind: 'effort' })}\n onFocus={() => setOpenMenu({ index, kind: 'effort' })}\n />}\n items={[\n { type: 'label', id: 'effort', text: t('rows.colEffort') },\n ...efforts.map((effort) => ({ id: effort, label: effort })),\n ]}\n selectedId={draft.effort === '' ? undefined : draft.effort}\n onSelect={(id) => {\n dispatchCardStore.cell(index, 'effort', id);\n setOpenMenu(null);\n }}\n onClose={() => setOpenMenu(null)}\n className=\"dsh-judge-field-wrap\"\n portal\n />\n ) : (\n <Input\n type=\"text\"\n className=\"dsh-judge-field\"\n value={draft.effort}\n placeholder={t('rows.effortPlaceholder')}\n aria-label={`${t('rows.colEffort')} ${index + 1}`}\n onChange={(event: React.ChangeEvent<HTMLInputElement>) =>\n dispatchCardStore.cell(index, 'effort', event.target.value)}\n />\n )}\n </td>\n <td className=\"dsh-judge-col-actions\">\n <div className=\"dsh-judge-cell-actions\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n aria-label={`${t('rows.browse')} ${index + 1}`}\n onClick={() => setBrowsing(index)}\n >\n {t('rows.browse')}\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n aria-label={`${t('rows.remove')} ${index + 1}`}\n onClick={() => dispatchCardStore.removeRow(index)}\n >\n {t('rows.remove')}\n </Button>\n </div>\n </td>\n </tr>\n );\n };\n\n const design = (\n <div className=\"dsh-judge-panel\">\n <div className=\"dsh-judge-section\">\n <div className=\"dsh-judge-head\">\n <span className=\"dsh-judge-title\">{t('judge.title')}</span>\n {/* \u9884\u89C8\u4E0E\u8BD5\u901A\u90FD\u662F\u300C\u8FD9\u5957\u8BBE\u7F6E\u4F1A\u600E\u6837\u300D\u7684\u68C0\u67E5\uFF0C\u8DDF\u7740\u8BBE\u7F6E\u4E00\u8D77\u653E\uFF0C\u4E0D\u53E6\u5360\u4E00\u5757\u3002 */}\n <div className=\"dsh-judge-head-actions\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={probing || state.dirty}\n onClick={() => void runProbe()}\n >\n {probing ? t('judge.probing') : t('judge.probe')}\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={state.dirty}\n onClick={() => void openPreview()}\n >\n {t('preview.open')}\n </Button>\n </div>\n </div>\n <div className=\"dsh-judge-desc\">{t('judge.desc')}</div>\n\n {/* \u8FD9\u4E00\u8282\u91CC\u7684\u6BCF\u4E00\u683C\u90FD\u5F52\u4E0B\u9762\u90A3\u4E2A\u4FDD\u5B58\u6309\u94AE\u7BA1\uFF1A\u5F00\u5173\u3001\u7AEF\u70B9\u3001\u5224\u65AD\u6A21\u578B\u3001\u5BC6\u94A5\u4E00\u6B21\u5199\u5165\u3002\n \u5F00\u5173\u4E0D\u53E6\u5916\u7ED9\u4FDD\u5B58\u6309\u94AE\uFF0C\u4E5F\u4E0D\u5373\u65F6\u5199\u5165\u2014\u2014\u300C\u53EA\u6709\u6309\u4FDD\u5B58\u624D\u5199\u300D\u8FD9\u6761\u89C4\u5219\u5728\u4E00\u4E2A\u8282\u91CC\n \u53EA\u80FD\u6709\u4E00\u4E2A\u51FA\u53E3\uFF0C\u5426\u5219\u8BFB\u8005\u65E0\u6CD5\u9884\u5224\u54EA\u4E00\u4E0B\u4F1A\u843D\u76D8\u3002 */}\n <div className=\"dsh-judge-row\">\n <div className=\"dsh-judge-row-info\">\n <div className=\"dsh-judge-row-title\">{t('switch.rewrite.title')}</div>\n <div className=\"dsh-judge-row-hint\">{t('switch.rewrite.desc')}</div>\n </div>\n <Switch\n checked={state.enabled}\n onChange={(next: boolean) => dispatchCardStore.toggle('enabled', next)}\n label={t('switch.rewrite.title')}\n disabled={!state.writable || state.saving !== ''}\n />\n </div>\n\n <div className=\"dsh-judge-row\">\n <div className=\"dsh-judge-row-info\">\n <div className=\"dsh-judge-row-title\">{t('switch.log.title')}</div>\n <div className=\"dsh-judge-row-hint\">{t('switch.log.desc')}</div>\n </div>\n <Switch\n checked={state.logEnabled}\n onChange={(next: boolean) => dispatchCardStore.toggle('logEnabled', next)}\n label={t('switch.log.title')}\n disabled={!state.writable || state.saving !== ''}\n />\n </div>\n\n <div className=\"dsh-judge-row\">\n <div className=\"dsh-judge-row-info\">\n <div className=\"dsh-judge-row-title\">{t('judge.endpoint')}</div>\n <div className=\"dsh-judge-row-hint\">{t('judge.endpointDesc')}</div>\n </div>\n <div className=\"dsh-judge-row-field\">\n <Input\n type=\"text\"\n className=\"dsh-judge-field\"\n value={state.endpointUrl}\n placeholder=\"http://127.0.0.1:3425/v1/systemone\"\n aria-label={t('judge.endpoint')}\n onChange={(event: React.ChangeEvent<HTMLInputElement>) =>\n dispatchCardStore.field('endpointUrl', event.target.value)}\n />\n </div>\n </div>\n\n <div className=\"dsh-judge-row\">\n <div className=\"dsh-judge-row-info\">\n <div className=\"dsh-judge-row-title\">{t('judge.model')}</div>\n <div className=\"dsh-judge-row-hint\">{t('judge.modelDesc')}</div>\n </div>\n <div className=\"dsh-judge-row-field\">\n <Input\n type=\"text\"\n className=\"dsh-judge-field\"\n value={state.judgeModel}\n placeholder=\"future-jev/jev-latest\"\n aria-label={t('judge.model')}\n onChange={(event: React.ChangeEvent<HTMLInputElement>) =>\n dispatchCardStore.field('judgeModel', event.target.value)}\n />\n </div>\n </div>\n\n <div className=\"dsh-judge-row\">\n <div className=\"dsh-judge-row-info\">\n <div className=\"dsh-judge-row-title\">{t('judge.key')}</div>\n <div className=\"dsh-judge-row-hint\">\n {withSamples(t('judge.keyDesc'), { ref: JUDGE_API_KEY_REF, path: CREDENTIALS_PATH })}\n </div>\n </div>\n <div className=\"dsh-judge-row-field\">\n {/* \u5BC6\u94A5\u683C\u4E0E\u4E0A\u9762\u4E24\u683C\u540C\u5BBD\uFF1A\u72B6\u6001\u4E0E\u300C\u5220\u6389\u300D\u653E\u5728\u8F93\u5165\u6846\u4E0B\u9762\u90A3\u4E00\u884C\uFF0C\n \u8FD9\u6837\u4E09\u683C\u7684\u5DE6\u53F3\u8FB9\u7F18\u5BF9\u9F50\u3002 */}\n <Input\n type=\"password\"\n autoComplete=\"new-password\"\n className=\"dsh-judge-field\"\n value={state.key.text}\n placeholder={state.key.configured ? t('judge.keyPlaceholderSet') : t('judge.keyPlaceholder')}\n aria-label={t('judge.key')}\n disabled={state.key.unavailable}\n onChange={(event: React.ChangeEvent<HTMLInputElement>) =>\n dispatchCardStore.key(event.target.value)}\n />\n <div className=\"dsh-judge-key-line\">\n <Tag tone={state.key.configured ? 'success' : 'warning'}>\n {t(state.key.configured ? 'judge.keySet' : 'judge.keyUnset')}\n </Tag>\n {state.key.configured && (\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={state.key.saving || !state.key.writable}\n onClick={() => void dispatchCardStore.clearKey()}\n >\n {t('judge.keyClear')}\n </Button>\n )}\n {state.key.unavailable && <span className=\"dsh-judge-hint\">{t('judge.keyUnavailable')}</span>}\n {state.key.landed === 'saved' && <span className=\"dsh-judge-note-ok\">{t('judge.keySaved')}</span>}\n {state.key.landed === 'cleared' && <span className=\"dsh-judge-note-ok\">{t('judge.keyCleared')}</span>}\n {state.key.failed && (\n <span className=\"dsh-judge-note-bad\" role=\"alert\">\n {t('judge.keyFailed').replace('{error}', state.key.error || t('save.invalid'))}\n </span>\n )}\n </div>\n </div>\n </div>\n\n {probeResult !== null && (\n <div className={probeResult.ok ? 'dsh-judge-note-ok' : 'dsh-judge-note-bad'}>\n {probeResult.ok\n ? t('judge.probeOk').replace('{latency}', String(probeResult.latencyMs))\n : t('judge.probeFail').replace('{reason}', reasonText(probeResult.reason))}\n </div>\n )}\n {state.dirty && <div className=\"dsh-judge-hint\">{t('preview.blocked')}</div>}\n\n {saveRow('judge', state.judgeDirty, () => void dispatchCardStore.save('judge'))}\n </div>\n\n <div className=\"dsh-judge-section\">\n <div className=\"dsh-judge-title\">{t('rows.title')}</div>\n <div className=\"dsh-judge-desc\">{t('rows.desc')}</div>\n {state.models.length === 0 && <div className=\"dsh-judge-off\">{t('rows.allowedEmpty')}</div>}\n {state.rows.length === 0 && <div className=\"dsh-judge-desc\">{t('rows.empty')}</div>}\n {state.rows.length > 0 && (\n <table className=\"dsh-judge-table\">\n <thead>\n <tr>\n <th className=\"dsh-judge-col-no\">{t('rows.colId')}</th>\n <th>{t('rows.colType')}</th>\n <th className=\"dsh-judge-col-model\">{t('rows.colModel')}</th>\n <th className=\"dsh-judge-col-effort\">{t('rows.colEffort')}</th>\n <th className=\"dsh-judge-col-actions\" />\n </tr>\n </thead>\n <tbody>\n {state.rows.map((draft, index) => row(draft, index))}\n </tbody>\n </table>\n )}\n <div>\n <Button variant=\"outline\" size=\"sm\" onClick={() => dispatchCardStore.addRow()}>\n {t('rows.add')}\n </Button>\n </div>\n {state.rowsInvalid !== '' && state.rowsDirty && (\n <div className=\"dsh-judge-note-bad\" role=\"alert\">{state.rowsInvalid}</div>\n )}\n {saveRow('rows', state.rowsDirty, saveRows)}\n </div>\n\n <div className=\"dsh-judge-section\">\n <div className=\"dsh-judge-title\">{t('presets.title')}</div>\n <div className=\"dsh-judge-desc\">{t('presets.desc')}</div>\n <div className=\"dsh-judge-presets\">\n {PRESETS.map((preset) => (\n <button\n key={preset.key}\n type=\"button\"\n className=\"dsh-judge-preset\"\n onClick={() => dispatchCardStore.addPreset(t(`preset.${preset.key}.desc` as never))}\n >\n <span className=\"dsh-judge-preset-title\">{t(`preset.${preset.key}` as never)}</span>\n <span className=\"dsh-judge-preset-hint\">\n {t('presets.effortHint').replace('{effort}', t(preset.effortHint as never))}\n </span>\n </button>\n ))}\n </div>\n </div>\n </div>\n );\n\n const log = (\n <div className=\"dsh-judge-panel\">\n <div className=\"dsh-judge-section\">\n <div className=\"dsh-judge-head\">\n <span className=\"dsh-judge-title\">{t('log.title')}</span>\n <Button variant=\"outline\" size=\"sm\" onClick={() => void dispatchCardStore.refreshLog()}>\n {t('log.refresh')}\n </Button>\n </div>\n <div className=\"dsh-judge-desc\">{t('log.desc')}</div>\n {state.logFailed && <div className=\"dsh-judge-note-bad\">{t('log.loadFailed')}</div>}\n {state.logLoaded && state.log.length === 0 && (\n <div className=\"dsh-judge-desc\">{t('log.empty')}</div>\n )}\n {state.log.length > 0 && (\n <div className=\"dsh-judge-log\">\n <div className=\"dsh-judge-log-row dsh-judge-log-head\">\n <span>{t('log.colProvider')}</span>\n <span>{t('log.colModel')}</span>\n <span>{t('log.colEffort')}</span>\n <span>{t('log.colTime')}</span>\n <span>{t('log.colLatency')}</span>\n </div>\n {state.log.map((entry, index) => (\n <button\n key={index}\n type=\"button\"\n className=\"dsh-judge-log-row\"\n onClick={() => setDetail(entry)}\n >\n <span className=\"dsh-judge-cell-clip\" title={entry.provider}>{entry.provider || '\u2014'}</span>\n <span className=\"dsh-judge-cell-clip\" title={entry.model}>{entry.model || '\u2014'}</span>\n <span>{entry.effort || '\u2014'}</span>\n <span>{new Date(entry.at).toLocaleTimeString()}</span>\n <span>{t('ms').replace('{value}', String(entry.latencyMs))}</span>\n </button>\n ))}\n </div>\n )}\n </div>\n </div>\n );\n\n return (\n <div className=\"dsh-judge-card\">\n <SegmentedTabs\n items={[\n { value: 'design' as const, label: t('tab.design'), id: 'judge-tab-design', panelId: 'judge-panel-design' },\n { value: 'log' as const, label: t('tab.log'), id: 'judge-tab-log', panelId: 'judge-panel-log' },\n ]}\n value={tab}\n onChange={setTab}\n label={t('tab.design')}\n />\n {tab === 'design' ? design : log}\n\n <Modal\n open={refusal !== null}\n onClose={() => setRefusal(null)}\n title={t('save.refusedTitle')}\n closeLabel={t('rows.browseClose')}\n >\n <div className=\"dsh-judge-note-bad\" role=\"alert\">{refusal ?? ''}</div>\n </Modal>\n\n <Modal\n open={previewOpen}\n onClose={() => setPreviewOpen(false)}\n title={t('preview.title')}\n closeLabel={t('preview.close')}\n className=\"dsh-judge-modal\"\n >\n <div className=\"dsh-judge-desc\">{t('preview.desc')}</div>\n <CodeBlock code={preview ?? ''} copyLabel={t('preview.copy')} copiedLabel={t('preview.copied')} />\n </Modal>\n\n <Modal\n open={browsing !== null}\n onClose={() => setBrowsing(null)}\n title={t('rows.browseTitle').replace('{id}', String((browsing ?? 0) + 1))}\n closeLabel={t('rows.browseClose')}\n >\n <div className=\"dsh-judge-desc\" style={{ whiteSpace: 'pre-wrap' }}>\n {browsing === null ? '' : state.rows[browsing]?.description ?? ''}\n </div>\n </Modal>\n\n <Modal\n open={detail !== null}\n onClose={() => setDetail(null)}\n title={t('log.detailTitle')}\n closeLabel={t('log.detailClose')}\n >\n {detail !== null && (\n <div className=\"dsh-judge-detail\">\n <span>{t('log.detailSource')}</span>\n <span>\n {detail.source === 'judged'\n ? t('log.sourceJudged').replace('{id}', String(detail.typeId ?? ''))\n : t('log.sourceInherited').replace('{reason}', reasonText(detail.reason))}\n </span>\n <span>{t('log.detailProvider')}</span>\n <span>{detail.provider || '\u2014'}</span>\n <span>{t('log.detailModel')}</span>\n <span>{detail.model || '\u2014'}</span>\n <span>{t('log.detailEffort')}</span>\n <span>{detail.effort || '\u2014'}</span>\n <span>{t('log.detailReason')}</span>\n <span>{detail.reason === undefined ? '\u2014' : reasonText(detail.reason)}</span>\n <span>{t('log.detailLatency')}</span>\n <span>{t('ms').replace('{value}', String(detail.latencyMs))}</span>\n <span>{t('log.detailParent')}</span>\n <span>{detail.parentTitle || '\u2014'}</span>\n <span>{t('log.detailChild')}</span>\n <span style={{ whiteSpace: 'pre-wrap' }}>{detail.childLabel || '\u2014'}</span>\n </div>\n )}\n </Modal>\n </div>\n );\n}\n\n/** The client context surface this file uses. */\ninterface ClientContextLike {\n effect(factory: () => void | (() => void), label?: string): void;\n slots?: {\n inject(name: string, register: () => unknown): () => void;\n register(options: Record<string, unknown>, component: unknown): () => void;\n };\n configForms: {\n get(namespace: string): any;\n whileServed(namespaces: readonly string[], register: (served: ReadonlySet<string>) => () => void): () => void;\n };\n locale?: any;\n remote?: { session?: any; credentials?: CredentialsRemoteLike };\n}\n\n/**\n * Bind the card to this plugin's own configuration form, the Host's allowlist,\n * the credentials service, and this plugin's runtime routes, then contribute it\n * to the Plugins page.\n * @param ctx - the browser client context.\n */\nexport function setupSettingsUi(ctx: ClientContextLike): void {\n if (typeof window === 'undefined') return;\n const t = ctx.locale?.bind?.(NS) ?? ((key: string) => key);\n try {\n dispatchCardStore.attach({\n form: ctx.configForms.get(SETTINGS_NAMESPACE),\n // The Host owns which models a subagent may use; this card only reads it so\n // the plugin never keeps a second list that could drift from it.\n allowedForm: ctx.configForms.get(ALLOWED_MODELS_NAMESPACE),\n session: ctx.remote?.session ?? null,\n remote: createDispatchRemote(),\n // The judgement key is written here; its value never rides a response.\n credentials: ctx.remote?.credentials ?? null,\n t,\n });\n } catch (error) {\n console.warn('[dsh-subagent-judge-dispatch] \u914D\u7F6E\u8868\u5355\u7ED1\u5B9A\u5931\u8D25\uFF1A', error);\n }\n\n // The dictionaries are registered once by the client entry point; the card's\n // seat resolves `t` against them through its `locale: NS` registration above.\n\n // The card lives on the Plugins page, which declares `plugins.bundle.config`\n // only while its own entry is mounted; `whileServed` additionally ties the\n // contribution to the Host actually serving this plugin's own settings entry.\n ctx.effect(\n () => ctx.configForms.whileServed([SETTINGS_NAMESPACE], () =>\n setupPluginPage(ctx.slots, () =>\n (ctx.slots as NonNullable<ClientContextLike['slots']>).register(\n {\n name: BUNDLE_CONFIG_SLOT,\n key: BUNDLE_CONFIG_KEY,\n locale: NS,\n },\n JudgeDispatchPanel,\n ))),\n 'dsh-subagent-judge-dispatch: plugins page config',\n );\n}\n", "/**\n * This plugin's configuration card and where it lives: the DSH **Plugins** page,\n * registered into `plugins.bundle.config` under the bundle's package name.\n *\n * The key is the package name; the settings the card reads and writes live in a\n * DIFFERENT literal \u2014 the Loader row id, which is also this plugin's settings\n * namespace. Writing one where the other belongs makes the card silently never\n * appear, so both are spelled once, here and in `src/index.ts`.\n */\n\n// Type-only: brings the owner's `plugins.bundle.config` SlotMap contract into\n// this program. Erased from the bundle, so the browser half never depends on the\n// plugin manager at runtime.\nimport type {} from '@deepseek-ai/dsh-client-ui-plugin-manager/client';\n\n/** npm package name of this plugin's bundle \u2014 the whole `plugins.bundle.config` key. */\nexport const BUNDLE_NAME = '@lynn123411/dsh-subagent-judge-dispatch';\n\n/** The Plugins page slot a bundle's own configuration registers into. */\nexport const BUNDLE_CONFIG_SLOT = 'plugins.bundle.config';\n\n/** This plugin's own config key: the bundle's package name. */\nexport const BUNDLE_CONFIG_KEY = BUNDLE_NAME;\n\n/** Services this registration needs from the browser runtime. */\ninterface PluginPageSlots {\n inject(name: string, callback: () => unknown): () => void;\n}\n\n/**\n * Contribute this plugin's configuration card to the Plugins page.\n * @param slots - the client slot registry.\n * @param register - registers the card component; returns its disposer.\n * @returns A disposer releasing the contribution, or a no-op when the browser\n * runtime hands no slot registry at all.\n */\nexport function setupPluginPage(\n slots: PluginPageSlots | null | undefined,\n register: () => () => void,\n): () => void {\n if (!slots || typeof slots.inject !== 'function') return () => {};\n return slots.inject(BUNDLE_CONFIG_SLOT, register);\n}\n", "/**\n * The judgement request the plugin sends, and the answer it reads back.\n *\n * Two pure functions live here, so the whole \"what did the judge decide\"\n * question is answerable without a Host, a socket, or a timer:\n *\n * - {@link buildJudgeRequest} turns the type list plus the task text into the\n * exact body that goes out.\n * - {@link readJudgeAnswer} turns whatever came back into a decision, treating\n * every malformed, empty or off-list answer as \"no decision\" rather than\n * inventing one.\n *\n * The protocol is the System One one: POST a body of `{ model, state,\n * questions }`, where each question is a `choice` carrying an `instructions`\n * line and a `criteria` map of option id to the text that option means. The\n * answer names the chosen option id.\n */\n\nimport type { TypeRow } from './types.ts';\n\n/** The one question key the plugin asks. */\nexport const QUESTION_KEY = 'task_type';\n\n/**\n * The question's instructions line.\n *\n * It says what to weigh, not what the types are: the types themselves arrive as\n * the criteria map, so the reader's own descriptions are the whole criterion\n * list and nothing here can drift from them.\n */\nexport const QUESTION_INSTRUCTIONS =\n 'Which single task type below does the delegated job best match? '\n + 'Weigh what the job actually requires, not how it is phrased. '\n + 'Answer with the number of exactly one listed type.';\n\n/** The option id the connectivity check offers: the only one it offers. */\nexport const PROBE_OPTION_ID = '1';\n\n/** The task text the connectivity check sends. */\nexport const PROBE_TASK_TEXT = '\u8FDE\u63A5\u6D4B\u8BD5\uFF1A\u8FD9\u662F\u4E00\u6B21\u5224\u65AD\u670D\u52A1\u7684\u8FDE\u901A\u6027\u68C0\u67E5\u3002';\n\n/**\n * The connectivity check's instructions.\n *\n * It asks for the one option that exists, so an endpoint that understands the\n * protocol at all can answer it: answering it wrong is a failure of the\n * protocol, not of the reader's task list.\n */\nexport const PROBE_INSTRUCTIONS =\n 'Answer with the number of the one option listed below.';\n\n/** The single criterion the connectivity check offers. */\nexport const PROBE_CRITERION = '\u786E\u8BA4\u8FD9\u6B21\u8C03\u7528\u53EF\u4EE5\u5B8C\u6210\u3002';\n\n/** One option of the judge's question. */\nexport interface JudgeChoice {\n type: 'choice';\n instructions: string;\n criteria: Record<string, string>;\n}\n\n/** The exact body sent to the judge endpoint. */\nexport interface JudgeRequest {\n model: string;\n state: { message: string };\n questions: { [QUESTION_KEY]: JudgeChoice };\n}\n\n/**\n * Whether one row is complete enough to be offered to the judge.\n *\n * A row needs its provider, model and effort: a half-filled row could otherwise\n * be chosen and then have nothing to write, which would turn the reader's\n * unfinished edit into a delegation that silently lost its route. This is the\n * ONE place that rule lives \u2014 the page, the config gate and the rewrite all ask\n * this function rather than restating the three comparisons.\n *\n * The parameter is narrowed to the three fields the rule reads, so the page's\n * draft row (which carries no sequence number) and the server's numbered row\n * both satisfy it without either shape being converted into the other.\n *\n * @param row - one row, numbered or drafted.\n * @returns whether the judge may choose it.\n */\nexport function isSelectableRow(row: Pick<TypeRow, 'provider' | 'model' | 'effort'>): boolean {\n return row.provider.trim() !== '' && row.model.trim() !== '' && row.effort.trim() !== '';\n}\n\n/**\n * Which rows may be offered to the judge.\n * @param rows - every row on the page, in page order.\n * @returns the rows the judge may choose, in page order.\n */\nexport function selectableRows(rows: readonly TypeRow[]): TypeRow[] {\n return rows.filter(isSelectableRow);\n}\n\n/**\n * Build the exact body sent to the judge endpoint.\n *\n * @param rows - the selectable rows, in page order.\n * @param model - the judge model id.\n * @param taskText - the delegated job's text.\n * @returns the request body.\n */\nexport function buildJudgeRequest(\n rows: readonly TypeRow[],\n model: string,\n taskText: string,\n): JudgeRequest {\n const criteria: Record<string, string> = {};\n for (const row of rows) criteria[String(row.id)] = row.description;\n return {\n model,\n state: { message: taskText },\n questions: {\n [QUESTION_KEY]: {\n type: 'choice',\n instructions: QUESTION_INSTRUCTIONS,\n criteria,\n },\n },\n };\n}\n\n/**\n * Build the body the connectivity check sends.\n *\n * It carries its own single option rather than the reader's task types: the\n * question the button answers is \"does this endpoint and model work\", and that\n * question has an answer before any type list exists. Requiring a finished list\n * first would make the check unable to tell a reader with an empty list from a\n * reader whose endpoint is down.\n *\n * @param model - the judge model id.\n * @returns the request body.\n */\nexport function buildProbeRequest(model: string): JudgeRequest {\n return {\n model,\n state: { message: PROBE_TASK_TEXT },\n questions: {\n [QUESTION_KEY]: {\n type: 'choice',\n instructions: PROBE_INSTRUCTIONS,\n criteria: { [PROBE_OPTION_ID]: PROBE_CRITERION },\n },\n },\n };\n}\n\n/**\n * The text the configuration page's preview shows.\n *\n * It is the request body minus the task text, because no task text exists until\n * a delegation happens; the preview marks that spot instead of inventing one.\n *\n * @param rows - the selectable rows, in page order.\n * @param model - the judge model id.\n * @returns the pretty-printed preview text.\n */\nexport function buildPreview(rows: readonly TypeRow[], model: string): string {\n const body = buildJudgeRequest(rows, model, '\uFF08\u6D3E\u5DE5\u65F6\u624D\u586B\uFF09');\n return JSON.stringify(body, null, 2);\n}\n\n/** What reading the judge's answer produced. */\nexport type JudgeDecision =\n | { kind: 'row'; row: TypeRow }\n | { kind: 'empty' }\n | { kind: 'unmatched' };\n\n/**\n * Find the chosen option id inside whatever the endpoint answered.\n *\n * The protocol's own shape is `answers.<key>.choice`; the two fallbacks are the\n * ones the reference clients read, so an endpoint that answers the shorter way\n * still works. Anything else \u2014 a missing body, a non-string, an empty string \u2014\n * yields `undefined` and is treated as no answer.\n *\n * @param payload - the decoded response body.\n * @returns the chosen option id, or undefined when the body names none.\n */\nexport function readChoice(payload: unknown): string | undefined {\n if (typeof payload !== 'object' || payload === null) return undefined;\n const body = payload as Record<string, unknown>;\n const answers = body.answers;\n const fromAnswers =\n typeof answers === 'object' && answers !== null\n ? (answers as Record<string, unknown>)[QUESTION_KEY]\n : undefined;\n const candidate = fromAnswers ?? body[QUESTION_KEY];\n if (typeof candidate === 'object' && candidate !== null) {\n const choice = (candidate as Record<string, unknown>).choice;\n if (typeof choice === 'string' && choice.trim() !== '') return choice.trim();\n if (typeof choice === 'number' && Number.isFinite(choice)) return String(choice);\n return undefined;\n }\n if (typeof candidate === 'string' && candidate.trim() !== '') return candidate.trim();\n if (typeof candidate === 'number' && Number.isFinite(candidate)) return String(candidate);\n return undefined;\n}\n\n/**\n * Turn the judge's answer into a decision.\n *\n * The choice is the type row's number. Matching is by that number's numeric\n * value, so an endpoint that answers `\"3\"` and one that answers `3` agree; a\n * number no listed row carries is `unmatched`, and a body naming no choice at\n * all is `empty`. Both travel to the log as their own reason, because \"it\n * answered nothing\" and \"it answered something I do not have\" send the reader\n * to different fixes.\n *\n * @param payload - the decoded response body.\n * @param rows - the selectable rows, in page order.\n * @returns the decision.\n */\nexport function readJudgeAnswer(payload: unknown, rows: readonly TypeRow[]): JudgeDecision {\n const choice = readChoice(payload);\n if (choice === undefined) return { kind: 'empty' };\n const wanted = Number(choice);\n if (!Number.isFinite(wanted)) return { kind: 'unmatched' };\n const row = rows.find((candidate) => candidate.id === wanted);\n return row === undefined ? { kind: 'unmatched' } : { kind: 'row', row };\n}\n", "/**\n * Where the judgement key lives, and the Host service it is read through.\n *\n * The reference name is a constant of the plugin rather than a setting: the\n * page asks for the key itself and stores it write-only through the DSH\n * credentials service, so a reader never has to know what a \"credential\n * reference\" is, and no surface can point the plugin at somebody else's key.\n * This module imports nothing, so both halves can share the literal.\n *\n * The key value crosses in one direction only: it is written, and read back by\n * the Host half alone. The browser face reads a status-only view.\n */\n\n/** Credential reference the judgement key is stored under. */\nexport const JUDGE_API_KEY_REF = 'SUBAGENT_JUDGE_API_KEY';\n\n/** Minimal structural shape of the Host's `ctx.credentials` service. */\nexport interface CredentialsServiceLike {\n /** Resolve a reference to its stored or inherited value. */\n resolve(ref: string): Promise<{ value: string; source?: string } | undefined>;\n /** Status-only view of a reference; never returns the plaintext value. */\n describe(ref: string): Promise<{ configured: boolean; source?: string; writable: boolean }>;\n /** Store a non-empty value under a reference. */\n set(ref: string, value: string): Promise<void>;\n /** Remove a reference from the document. */\n unset(ref: string): Promise<void>;\n}\n\n/** Minimal structural shape of the browser's `ctx.remote.credentials` face. */\nexport interface CredentialsRemoteLike {\n describe(refs: string[]): Promise<\n { ok: true; value: Record<string, { configured: boolean; source?: string; writable: boolean }> }\n | { ok: false; error: { message: string } }\n >;\n set(ref: string, value: string): Promise<{ ok: true } | { ok: false; error: { message: string } }>;\n unset(ref: string): Promise<{ ok: true } | { ok: false; error: { message: string } }>;\n}\n", "/**\n * The configuration card's own state: what the Host serves, what the reader has\n * staged, and what a save would do.\n *\n * Three rules live here rather than in the component, because each is the kind\n * of thing a render pass must not be trusted with:\n *\n * - A row's sequence number is positional (`1..n`) and is never stored. Duplicate\n * numbers are therefore impossible by construction rather than by validation.\n * - The two sections save separately. The judgement service and the task-type\n * list are edited at different times and fail differently, so one save for both\n * would let a half-finished description block a change to the endpoint.\n * - A save that did not land is reported as such. The shared configuration form\n * answers `false` for a refusal, which is not a rejection: treating it as\n * success would show a saved page over a document the Host never accepted.\n *\n * The model and effort options come from the Host's own \"models subagents may\n * choose\" setting and the adapter catalogue, so the plugin never keeps a second\n * list that could drift from it. The judgement key is write-only over the DSH\n * credentials service, which is why no key value is ever part of this state.\n */\n\nimport { isSelectableRow } from '../../server/judge-prompt.ts';\nimport { JUDGE_API_KEY_REF, type CredentialsRemoteLike } from '../../server/credentials.ts';\n\nexport { JUDGE_API_KEY_REF };\nexport type { CredentialsRemoteLike };\n\n/** One type row as the page edits it; `id` is derived, never stored. */\nexport interface TypeRowDraft {\n description: string;\n provider: string;\n model: string;\n effort: string;\n}\n\n/** One selectable model and the efforts it declares. */\nexport interface ModelOption {\n provider: string;\n model: string;\n /** Display name from the adapter catalogue, when it advertises one. */\n label: string;\n /** Effort ids this exact route declares, in catalogue order. */\n efforts: string[];\n}\n\n/** One log row as the Host serves it. */\nexport interface LogRow {\n typeId: number | null;\n provider: string;\n model: string;\n effort: string;\n source: 'judged' | 'inherited';\n reason?: string;\n at: number;\n latencyMs: number;\n parentTitle: string;\n childLabel: string;\n}\n\n/** Which of the two sections a save writes. */\nexport type Section = 'judge' | 'rows';\n\n/** What the page shows about the judgement key; never its value. */\nexport interface KeyState {\n /** Staged key text; blank until the reader types one. */\n text: string;\n /** Whether the Host reports a stored key under the reference. */\n configured: boolean;\n /** Whether the credentials document accepts writes. */\n writable: boolean;\n /**\n * Whether this page has no credentials channel at all \u2014 a non-loopback page\n * is served without the namespace, and a field that cannot be written should\n * say so before the reader types into it.\n */\n unavailable: boolean;\n saving: boolean;\n failed: boolean;\n /** The credentials service's own message for a refused write, or ''. */\n error: string;\n /** What the last landed key write did, or '' when none has landed. */\n landed: '' | 'saved' | 'cleared';\n}\n\n/** The card's whole state. */\nexport interface PageState {\n available: boolean;\n writable: boolean;\n /** Whether the model-rewrite switch is on. */\n enabled: boolean;\n /** Whether the log switch is on. */\n logEnabled: boolean;\n endpointUrl: string;\n judgeModel: string;\n rows: TypeRowDraft[];\n /** Model options read from the Host's allowlist plus the adapter catalogue. */\n models: ModelOption[];\n /** Whether the adapter catalogue was read; false means the effort column is free text. */\n catalogRead: boolean;\n /** Persisted values, for computing dirtiness and reverting. */\n committed: {\n enabled: boolean;\n logEnabled: boolean;\n endpointUrl: string;\n judgeModel: string;\n rows: TypeRowDraft[];\n };\n /** Whether the judgement service section holds edits a save would write. */\n judgeDirty: boolean;\n /** Whether the task-type list holds edits a save would write. */\n rowsDirty: boolean;\n /** Whether either section holds edits, for the preview's own notice. */\n dirty: boolean;\n /** A reason the task-type drafts cannot be saved; '' when they can. */\n rowsInvalid: string;\n /** Which section a save is crossing the wire for, or '' when none is. */\n saving: Section | '';\n /** Which section's last save did not land, or '' when none failed. */\n saveFailed: Section | '';\n /** The Host's own message for the last refused write, or ''. */\n saveError: string;\n /** The judgement key's write-only state. */\n key: KeyState;\n /** Runtime log rows, newest first. */\n log: LogRow[];\n logLoaded: boolean;\n logFailed: boolean;\n}\n\n/** Defaults mirroring the Host schema, so an unserved page still renders. */\nexport const DEFAULT_ENDPOINT_URL = 'http://127.0.0.1:3425/v1/systemone';\nexport const DEFAULT_JUDGE_MODEL = 'future-jev/jev-latest';\n\n/** Profile entry id (== settings namespace). */\nexport const SETTINGS_NAMESPACE = 'dsh-subagent-judge-dispatch';\n\n/** The Host's own allowlist namespace, which the card reads for model options. */\nexport const ALLOWED_MODELS_NAMESPACE = 'subagent-model-selection-settings';\n\n/** One path-addressed edit, matching the wire shape the form's `mutate` accepts. */\nexport type SettingsPathOpLike =\n | { op: 'set'; path: string[]; value: unknown }\n | { op: 'unset'; path: string[] };\n\n/** Minimal structural shape of the DSH shared configuration form. */\nexport interface ConfigFormLike {\n getSnapshot(): {\n status: 'loading' | 'ready' | 'unavailable';\n value?: Record<string, unknown>;\n writable: boolean;\n revision?: number;\n };\n subscribe(listener: () => void): () => void;\n mutate(ops: readonly SettingsPathOpLike[], expectedRevision?: number): Promise<boolean>;\n}\n\n/** The `remote.session` face the model catalogue is read through. */\nexport interface SessionRemoteLike {\n modelCatalog(): Promise<\n | { ok: true; value: { groups: readonly { id: string; name: string; models: readonly { id: string; name: string; reasoning?: { efforts: readonly { id: string }[] } }[] }[] } }\n | { ok: false; error: { message: string } }\n >;\n}\n\n/**\n * The Host's three runtime reads.\n *\n * They are plain Fetch calls on this plugin's own routes rather than a Remote\n * namespace: the routes ride Connection's authenticated `/api` transport, which\n * is the same channel the page is already served over.\n */\nexport interface DispatchRemoteLike {\n log(): Promise<LogRow[]>;\n preview(): Promise<string | null>;\n probe(): Promise<{ ok: boolean; latencyMs: number; reason?: string }>;\n}\n\n/** The three route paths, shared with the Host half by literal. */\nexport const LOG_ROUTE_PATH = '/api/dsh-subagent-judge-dispatch/log';\nexport const PREVIEW_ROUTE_PATH = '/api/dsh-subagent-judge-dispatch/preview';\nexport const PROBE_ROUTE_PATH = '/api/dsh-subagent-judge-dispatch/probe';\n\n/** Decode a response body, treating an unreadable one as absent. */\nasync function readJson(response: Response): Promise<any> {\n try {\n return await response.json();\n } catch {\n return null;\n }\n}\n\n/** The real Host reads, over this plugin's own routes. */\nexport function createDispatchRemote(): DispatchRemoteLike {\n return {\n async log(): Promise<LogRow[]> {\n try {\n const response = await fetch(LOG_ROUTE_PATH);\n if (!response.ok) return [];\n const body = await readJson(response);\n return Array.isArray(body?.entries) ? (body.entries as LogRow[]) : [];\n } catch {\n return [];\n }\n },\n async preview(): Promise<string | null> {\n try {\n const response = await fetch(PREVIEW_ROUTE_PATH);\n if (!response.ok) return null;\n const body = await readJson(response);\n return typeof body?.preview === 'string' ? body.preview : null;\n } catch {\n return null;\n }\n },\n async probe(): Promise<{ ok: boolean; latencyMs: number; reason?: string }> {\n try {\n const response = await fetch(PROBE_ROUTE_PATH, { method: 'POST' });\n if (!response.ok) return { ok: false, latencyMs: 0, reason: 'unreachable' };\n const body = await readJson(response);\n if (body === null || typeof body !== 'object') return { ok: false, latencyMs: 0, reason: 'unreachable' };\n return {\n ok: body.ok === true,\n latencyMs: typeof body.latencyMs === 'number' ? body.latencyMs : 0,\n ...typeof body.reason === 'string' ? { reason: body.reason } : {},\n };\n } catch {\n return { ok: false, latencyMs: 0, reason: 'unreachable' };\n }\n },\n };\n}\n\n/**\n * Read one row from a stored document value, tolerating a partial record.\n * @param value - one entry of the stored `rows` array.\n * @returns the row's four text fields, each defaulted to ''.\n */\nexport function readRow(value: unknown): TypeRowDraft {\n const record = typeof value === 'object' && value !== null ? (value as Record<string, unknown>) : {};\n const text = (key: string): string => (typeof record[key] === 'string' ? (record[key] as string) : '');\n return {\n description: text('description'),\n provider: text('provider'),\n model: text('model'),\n effort: text('effort'),\n };\n}\n\n/**\n * Stable identity for one exact provider/model route.\n *\n * The separator is a NUL, which cannot appear in a provider or model id, so the\n * join and the split can never disagree. Both live here rather than at the call\n * sites: encoding and decoding are one concept and must not drift apart.\n *\n * @param provider - provider id.\n * @param model - model id.\n * @returns the composite key.\n */\nexport function routeKey(provider: string, model: string): string {\n return `${provider}\\0${model}`;\n}\n\n/**\n * Split a composite route key back into its two ids.\n * @param key - a value produced by {@link routeKey}.\n * @returns the provider and model, both '' when the key is malformed.\n */\nexport function splitRouteKey(key: string): { provider: string; model: string } {\n const at = key.indexOf('\\0');\n if (at < 0) return { provider: '', model: '' };\n return { provider: key.slice(0, at), model: key.slice(at + 1) };\n}\n\n/**\n * Pair the Host's allowlist with the adapter catalogue.\n *\n * The allowlist decides which routes may be offered; the catalogue supplies each\n * route's display name and the effort ids it declares. A route the allowlist\n * names but the catalogue no longer advertises is kept, so a stored row never\n * becomes uneditable merely because an adapter went away.\n *\n * @param allowed - the Host's `allowedModels` entries.\n * @param groups - catalogue provider groups.\n * @returns the options to render, in allowlist order.\n */\nexport function buildModelOptions(\n allowed: readonly { provider?: unknown; model?: unknown }[],\n groups: readonly { id: string; models: readonly { id: string; name: string; reasoning?: { efforts: readonly { id: string }[] } }[] }[],\n): ModelOption[] {\n const byRoute = new Map<string, { label: string; efforts: string[] }>();\n for (const group of groups) {\n for (const model of group.models) {\n byRoute.set(routeKey(group.id, model.id), {\n label: model.name,\n efforts: (model.reasoning?.efforts ?? []).map((effort) => effort.id),\n });\n }\n }\n const options: ModelOption[] = [];\n const seen = new Set<string>();\n for (const entry of allowed) {\n const provider = typeof entry.provider === 'string' ? entry.provider : '';\n const model = typeof entry.model === 'string' ? entry.model : '';\n if (provider === '' || model === '') continue;\n const key = routeKey(provider, model);\n if (seen.has(key)) continue;\n seen.add(key);\n const found = byRoute.get(key);\n options.push({\n provider,\n model,\n label: found?.label ?? model,\n efforts: found?.efforts ?? [],\n });\n }\n return options;\n}\n\n/**\n * The reason the task-type drafts cannot be saved, or '' when they can.\n *\n * A duplicate description is refused because the description is the criterion\n * the judge reads: two identical criteria would make the answer ambiguous and\n * the log unreadable. An empty description is refused for the same reason \u2014 a\n * row the judge cannot tell apart from any other.\n *\n * @param rows - the staged rows.\n * @param t - the page's translator, so the message is localized.\n * @returns the reason text, or ''.\n */\nexport function validateRows(rows: readonly TypeRowDraft[], t: (key: string) => string): string {\n const seen = new Set<string>();\n for (const row of rows) {\n const description = row.description.trim();\n if (description === '') return t('save.emptyDescription');\n if (seen.has(description)) return t('save.duplicateDescription');\n seen.add(description);\n }\n return '';\n}\n\n/** A key nothing is staged for and nothing is known about. */\nfunction emptyKey(): KeyState {\n return {\n text: '', configured: false, writable: false, unavailable: false,\n saving: false, failed: false, error: '', landed: '',\n };\n}\n\n/**\n * The read/write face of the Host document plus the runtime reads.\n *\n * Every control stages into this store and only a section's own save writes, so\n * a half-typed endpoint can never reach a delegation, and a half-written type\n * list can never be stored behind the reader's back.\n */\nexport class DispatchCardStore {\n private state: PageState = {\n available: false,\n writable: false,\n enabled: true,\n logEnabled: true,\n endpointUrl: DEFAULT_ENDPOINT_URL,\n judgeModel: DEFAULT_JUDGE_MODEL,\n rows: [],\n models: [],\n catalogRead: false,\n committed: {\n enabled: true,\n logEnabled: true,\n endpointUrl: DEFAULT_ENDPOINT_URL,\n judgeModel: DEFAULT_JUDGE_MODEL,\n rows: [],\n },\n judgeDirty: false,\n rowsDirty: false,\n dirty: false,\n rowsInvalid: '',\n saving: '',\n saveFailed: '',\n saveError: '',\n key: emptyKey(),\n log: [],\n logLoaded: false,\n logFailed: false,\n };\n\n private listeners = new Set<() => void>();\n private form: ConfigFormLike | null = null;\n private allowedForm: ConfigFormLike | null = null;\n private session: SessionRemoteLike | null = null;\n private remote: DispatchRemoteLike | null = null;\n private credentials: CredentialsRemoteLike | null = null;\n private offForm: (() => void) | null = null;\n private offAllowed: (() => void) | null = null;\n private translate: (key: string) => string = (key) => key;\n\n /** Bind the Host services; re-binding detaches the previous subscriptions. */\n attach(options: {\n form: ConfigFormLike | null;\n allowedForm: ConfigFormLike | null;\n session: SessionRemoteLike | null;\n remote: DispatchRemoteLike | null;\n credentials: CredentialsRemoteLike | null;\n t: (key: string) => string;\n }): void {\n this.offForm?.();\n this.offAllowed?.();\n this.form = options.form;\n this.allowedForm = options.allowedForm;\n this.session = options.session;\n this.remote = options.remote;\n this.credentials = options.credentials;\n this.translate = options.t;\n this.state = {\n ...this.state,\n key: { ...this.state.key, unavailable: options.credentials === null },\n };\n if (this.form !== null) {\n this.offForm = this.form.subscribe(() => this.deriveCommitted());\n this.deriveCommitted();\n }\n if (this.allowedForm !== null) {\n this.offAllowed = this.allowedForm.subscribe(() => void this.loadModels());\n void this.loadModels();\n }\n void this.refreshKeyStatus();\n }\n\n getState(): PageState {\n return this.state;\n }\n\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n /** Read the Host's allowlist and the adapter catalogue into the model options. */\n async loadModels(): Promise<void> {\n const allowedValue = this.allowedForm?.getSnapshot().value;\n const allowed = Array.isArray(allowedValue?.allowedModels)\n ? (allowedValue.allowedModels as { provider?: unknown; model?: unknown }[])\n : [];\n let groups: readonly { id: string; models: readonly { id: string; name: string; reasoning?: { efforts: readonly { id: string }[] } }[] }[] = [];\n let catalogRead = false;\n if (this.session !== null) {\n try {\n const response = await this.session.modelCatalog();\n if (response.ok) {\n groups = response.value.groups;\n catalogRead = true;\n }\n } catch {\n // Handled by the flag below.\n }\n }\n // Whether the effort column may offer a fixed list. When the catalogue could\n // not be read the column falls back to free text rather than going\n // unavailable: an empty list would otherwise disable the effort cell on\n // every row, and a table where no row can be completed is a table that\n // silently stops judging anything.\n this.state = { ...this.state, models: buildModelOptions(allowed, groups), catalogRead };\n this.notify();\n }\n\n /** Read the status-only view of the judgement key. */\n async refreshKeyStatus(): Promise<void> {\n if (this.credentials === null) return;\n try {\n const response = await this.credentials.describe([JUDGE_API_KEY_REF]);\n if (!response.ok) return;\n const info = response.value[JUDGE_API_KEY_REF];\n this.state = {\n ...this.state,\n key: {\n ...this.state.key,\n configured: info?.configured === true,\n writable: info?.writable === true,\n },\n };\n this.notify();\n } catch {\n // The key stays \"not configured\": the status is an enrichment, and a\n // failed read must not claim a key that may not be there.\n }\n }\n\n /**\n * Map the Host's resolved section into committed state and re-seed the drafts.\n *\n * Drafts are held FIELD BY FIELD, against the value this page last saw\n * committed. Holding a whole section instead would make a save write back a\n * field the reader never touched \u2014 reverting a change another page made to it \u2014\n * while holding nothing would discard input mid-typing every time the Host\n * publishes.\n */\n private deriveCommitted(): void {\n const snapshot = this.form?.getSnapshot();\n const value = snapshot?.value;\n if (value === undefined) return;\n const rows = Array.isArray(value.rows) ? (value.rows as unknown[]).map(readRow) : [];\n const committed = {\n enabled: typeof value.enabled === 'boolean' ? value.enabled : true,\n logEnabled: typeof value.logEnabled === 'boolean' ? value.logEnabled : true,\n endpointUrl: typeof value.endpointUrl === 'string' ? value.endpointUrl : DEFAULT_ENDPOINT_URL,\n judgeModel: typeof value.judgeModel === 'string' ? value.judgeModel : DEFAULT_JUDGE_MODEL,\n rows,\n };\n /** Whether the reader's staged value still differs from what this page last saw committed. */\n const staged = <T>(current: T, previously: T): boolean => current !== previously;\n const before = this.state.committed;\n this.state = {\n ...this.state,\n available: snapshot?.status === 'ready',\n writable: snapshot?.writable ?? false,\n committed,\n enabled: staged(this.state.enabled, before.enabled) ? this.state.enabled : committed.enabled,\n logEnabled: staged(this.state.logEnabled, before.logEnabled) ? this.state.logEnabled : committed.logEnabled,\n endpointUrl: staged(this.state.endpointUrl, before.endpointUrl) ? this.state.endpointUrl : committed.endpointUrl,\n judgeModel: staged(this.state.judgeModel, before.judgeModel) ? this.state.judgeModel : committed.judgeModel,\n rows: JSON.stringify(this.state.rows) !== JSON.stringify(before.rows) ? this.state.rows : committed.rows,\n };\n this.recompute();\n }\n\n /** Recompute per-section dirtiness and the row validation against committed values. */\n private recompute(): void {\n const committed = this.state.committed;\n const judgeDirty =\n this.state.enabled !== committed.enabled ||\n this.state.logEnabled !== committed.logEnabled ||\n this.state.endpointUrl !== committed.endpointUrl ||\n this.state.judgeModel !== committed.judgeModel ||\n this.state.key.text.trim() !== '';\n const rowsDirty = JSON.stringify(this.state.rows) !== JSON.stringify(committed.rows);\n this.state = {\n ...this.state,\n judgeDirty,\n rowsDirty,\n dirty: judgeDirty || rowsDirty,\n rowsInvalid: validateRows(this.state.rows, this.translate),\n };\n this.notify();\n }\n\n /** Stage one top-level field. */\n field(key: 'endpointUrl' | 'judgeModel', value: string): void {\n this.state = { ...this.state, [key]: value, saveFailed: '' };\n this.recompute();\n }\n\n /** Stage one switch. */\n toggle(key: 'enabled' | 'logEnabled', value: boolean): void {\n this.state = { ...this.state, [key]: value, saveFailed: '' };\n this.recompute();\n }\n\n /** Stage the judgement key. The value stays in this draft until a save. */\n key(text: string): void {\n this.state = { ...this.state, key: { ...this.state.key, text, failed: false, error: '', landed: '' } };\n this.recompute();\n }\n\n /** Stage one cell of one row. */\n cell(index: number, key: keyof TypeRowDraft, value: string): void {\n const rows = this.state.rows.map((row, at) => (at === index ? { ...row, [key]: value } : row));\n // Choosing a model drops an effort that model does not declare, so a save can\n // never carry an effort the selected route cannot run.\n this.state = {\n ...this.state,\n rows: key === 'model' ? this.reconcileEffort(rows, index) : rows,\n saveFailed: '',\n };\n this.recompute();\n }\n\n /** Drop an effort the freshly selected model does not declare. */\n private reconcileEffort(rows: TypeRowDraft[], index: number): TypeRowDraft[] {\n const row = rows[index];\n if (row === undefined) return rows;\n const option = this.state.models.find(\n (candidate) => candidate.provider === row.provider && candidate.model === row.model,\n );\n if (option === undefined || option.efforts.length === 0) return rows;\n if (row.effort !== '' && !option.efforts.includes(row.effort)) {\n return rows.map((candidate, at) => (at === index ? { ...candidate, effort: '' } : candidate));\n }\n return rows;\n }\n\n /** Append an empty row. */\n addRow(): void {\n this.state = { ...this.state, rows: [...this.state.rows, { description: '', provider: '', model: '', effort: '' }], saveFailed: '' };\n this.recompute();\n }\n\n /** Append a ready-made entry; the effort hint is not filled in. */\n addPreset(description: string): void {\n this.state = { ...this.state, rows: [...this.state.rows, { description, provider: '', model: '', effort: '' }], saveFailed: '' };\n this.recompute();\n }\n\n /** Delete one row; the remaining rows renumber themselves. */\n removeRow(index: number): void {\n this.state = { ...this.state, rows: this.state.rows.filter((_row, at) => at !== index), saveFailed: '' };\n this.recompute();\n }\n\n /** Discard one section's drafts back to the committed values. */\n revert(section: Section): void {\n const committed = this.state.committed;\n this.state = section === 'judge'\n ? {\n ...this.state,\n enabled: committed.enabled,\n logEnabled: committed.logEnabled,\n endpointUrl: committed.endpointUrl,\n judgeModel: committed.judgeModel,\n // \u53EA\u6E05\u6389\u300C\u8FD8\u6CA1\u4EA4\u51FA\u53BB\u7684\u90A3\u6BB5\u6587\u672C\u300D\u3002\u5BC6\u94A5\u5DF2\u7ECF\u5B58\u5728\u51ED\u636E\u6587\u4EF6\u91CC\uFF0C\u653E\u5F03\u8FD9\u4E00\u8282\u7684\n // \u8BBE\u7F6E\u8349\u7A3F\u4E0D\u8BE5\u8BA9\u9875\u9762\u6539\u53E3\u8BF4\u300C\u8FD8\u6CA1\u6709\u5BC6\u94A5\u300D\u2014\u2014\u90A3\u662F\u53E6\u4E00\u5904\u7684\u72B6\u6001\u3002\n key: { ...this.state.key, text: '', failed: false, error: '', landed: '' },\n saveFailed: '',\n }\n : { ...this.state, rows: committed.rows, saveFailed: '' };\n this.recompute();\n }\n\n /**\n * Write one section's staged edits as one revision-fenced batch.\n *\n * The judgement section also writes a typed key, so naming the endpoint and\n * giving it its credential is one gesture rather than two. The type rows are\n * written whole rather than diffed: the array is one value, and a positional\n * number is derived from it, so a partial write could momentarily renumber the\n * list under a reader mid-save.\n *\n * @param section - which section's drafts to write.\n */\n async save(section: Section): Promise<void> {\n if (this.state.saving !== '') return;\n const form = this.form;\n if (form === null || !this.state.writable) return;\n if (section === 'rows' && (this.state.rowsInvalid !== '' || !this.state.rowsDirty)) return;\n if (section === 'judge' && !this.state.judgeDirty) return;\n\n const ops: SettingsPathOpLike[] = [];\n if (section === 'judge') {\n if (this.state.endpointUrl !== this.state.committed.endpointUrl) {\n ops.push({ op: 'set', path: ['endpointUrl'], value: this.state.endpointUrl });\n }\n if (this.state.judgeModel !== this.state.committed.judgeModel) {\n ops.push({ op: 'set', path: ['judgeModel'], value: this.state.judgeModel });\n }\n if (this.state.enabled !== this.state.committed.enabled) {\n ops.push({ op: 'set', path: ['enabled'], value: this.state.enabled });\n }\n if (this.state.logEnabled !== this.state.committed.logEnabled) {\n ops.push({ op: 'set', path: ['logEnabled'], value: this.state.logEnabled });\n }\n } else if (JSON.stringify(this.state.rows) !== JSON.stringify(this.state.committed.rows)) {\n ops.push({ op: 'set', path: ['rows'], value: this.state.rows.map((row) => ({ ...row })) });\n }\n\n this.state = { ...this.state, saving: section, saveFailed: '', saveError: '' };\n this.notify();\n\n // The key goes first: a document write the Host refuses leaves the key in\n // place, while a key that landed with a refused endpoint is still a landed\n // key. Either way the reader is told which part did not take.\n const typedKey = section === 'judge' ? this.state.key.text.trim() : '';\n let failure = '';\n let keyLanded: '' | 'saved' | 'cleared' = '';\n if (typedKey !== '') {\n const result = await this.writeKey(typedKey);\n if (result.ok) keyLanded = 'saved';\n else failure = result.error;\n }\n if (failure === '' && ops.length > 0) {\n try {\n const landed = await form.mutate(ops, form.getSnapshot().revision);\n // `false` is a refusal, not a rejection: the Host answered and did not\n // accept, so reporting success here would show a saved page over a\n // document that still holds the old value.\n if (!landed) failure = this.translate('save.refused');\n } catch (error) {\n // The Host's own words, not a generic phrase: a rejected write is the one\n // place the reader needs to know WHAT the Host objected to.\n failure = error instanceof Error && error.message !== '' ? error.message : this.translate('save.invalid');\n }\n }\n this.state = {\n ...this.state,\n saving: '',\n saveFailed: failure === '' ? '' : section,\n saveError: failure,\n key: keyLanded === '' ? this.state.key : { ...this.state.key, text: '', landed: keyLanded },\n };\n if (failure === '') this.deriveCommitted();\n else this.notify();\n }\n\n /**\n * Write one judgement key through the credentials service.\n *\n * The service resolves with `{ ok: false }` rather than rejecting when it\n * refuses a write, so that result decides the outcome. The key value is handed\n * straight to the service and is never copied into the page state.\n *\n * @param value - the staged key text, already trimmed and known non-empty.\n * @returns whether the write landed, and the message when it did not.\n */\n private async writeKey(value: string): Promise<{ ok: boolean; error: string }> {\n const credentials = this.credentials;\n if (credentials === null) return { ok: false, error: this.translate('key.unavailable') };\n this.state = { ...this.state, key: { ...this.state.key, saving: true, failed: false, error: '' } };\n this.notify();\n try {\n const response = await credentials.set(JUDGE_API_KEY_REF, value);\n if (!response.ok) {\n const error = response.error.message || this.translate('key.saveFailed');\n this.state = { ...this.state, key: { ...this.state.key, saving: false, failed: true, error } };\n return { ok: false, error };\n }\n this.state = { ...this.state, key: { ...this.state.key, saving: false, failed: false, error: '', configured: true } };\n await this.refreshKeyStatus();\n return { ok: true, error: '' };\n } catch (error) {\n const message = error instanceof Error && error.message !== '' ? error.message : this.translate('key.saveFailed');\n this.state = { ...this.state, key: { ...this.state.key, saving: false, failed: true, error: message } };\n return { ok: false, error: message };\n }\n }\n\n /**\n * Remove the stored judgement key.\n *\n * A separate control rather than \"save an empty field\": the shared\n * configuration form's own rule is that a blank draft writes nothing, so an\n * emptied input cannot mean removal without contradicting it.\n *\n * @returns settlement after the credentials read-back.\n */\n async clearKey(): Promise<void> {\n const credentials = this.credentials;\n if (credentials === null) return;\n this.state = { ...this.state, key: { ...this.state.key, saving: true, failed: false, error: '' } };\n this.notify();\n try {\n const response = await credentials.unset(JUDGE_API_KEY_REF);\n if (!response.ok) {\n this.state = {\n ...this.state,\n key: {\n ...this.state.key,\n saving: false,\n failed: true,\n error: response.error.message || this.translate('key.clearFailed'),\n },\n };\n } else {\n this.state = {\n ...this.state,\n key: { ...this.state.key, saving: false, text: '', failed: false, error: '', landed: 'cleared', configured: false },\n };\n await this.refreshKeyStatus();\n }\n } catch (error) {\n this.state = {\n ...this.state,\n key: {\n ...this.state.key,\n saving: false,\n failed: true,\n error: error instanceof Error && error.message !== '' ? error.message : this.translate('key.clearFailed'),\n },\n };\n }\n this.notify();\n }\n\n /** Read the runtime log from the Host. */\n async refreshLog(): Promise<void> {\n if (this.remote === null) return;\n try {\n const entries = await this.remote.log();\n this.state = { ...this.state, log: entries, logLoaded: true, logFailed: false };\n } catch {\n this.state = { ...this.state, logLoaded: true, logFailed: true };\n }\n this.notify();\n }\n\n /** Read the exact prompt a judgement would send. */\n async preview(): Promise<string | null> {\n if (this.remote === null) return null;\n try {\n return await this.remote.preview();\n } catch {\n return null;\n }\n }\n\n /** Test the judge endpoint against the committed settings. */\n async probe(): Promise<{ ok: boolean; latencyMs: number; reason?: string }> {\n if (this.remote === null) return { ok: false, latencyMs: 0, reason: 'unreachable' };\n try {\n return await this.remote.probe();\n } catch {\n return { ok: false, latencyMs: 0, reason: 'unreachable' };\n }\n }\n\n /** The effort ids available for one row's currently selected model. */\n effortsFor(row: TypeRowDraft): string[] {\n return this.state.models.find(\n (candidate) => candidate.provider === row.provider && candidate.model === row.model,\n )?.efforts ?? [];\n }\n\n /** Whether one row will be offered to the judge (the server's own rule). */\n rowUsable(row: TypeRowDraft): boolean {\n return isSelectableRow(row);\n }\n\n private notify(): void {\n for (const listener of [...this.listeners]) {\n try {\n listener();\n } catch {}\n }\n }\n}\n\nexport const dispatchCardStore = new DispatchCardStore();\n", "// \u7C7B\u578B\u53EA\u8BFB\uFF1A\u5EA7\u4F4D\u5951\u7EA6\u4E0E\u5B83\u7684 LocaleNamespaceMap \u5408\u5E76\u6765\u81EA\u8FD9\u4E2A\u5305\u3002\nimport type {} from '@deepseek-ai/dsh-client-ui-slots';\n\n/** \u8FD9\u4E2A\u63D2\u4EF6\u7684\u5B57\u5178\u547D\u540D\u7A7A\u95F4\uFF1A\u5EA7\u4F4D\u6CE8\u518C\u4E0E\u5361\u7247\u6587\u6848\u90FD\u7528\u5B83\u3002 */\nexport const NS = 'subagentjudgedispatch';\n/** \u82F1\u6587\u6587\u6848\u3002 */\nexport const en = {\n 'tab.design': 'Design',\n 'tab.log': 'Log',\n 'switch.rewrite.title': 'Rewrite subagent model and effort',\n 'switch.rewrite.desc':\n 'Every subagent is judged once when it is delegated. While this is off, nothing is judged and nothing is logged.',\n 'switch.log.title': 'Record the log',\n 'switch.log.desc': 'Keep the most recent judgements in this running instance. Cleared on restart.',\n 'judge.title': 'Judgement service',\n 'judge.desc':\n 'The task type is decided by this endpoint. It receives the type list and the task text, and answers with one type number.',\n 'judge.endpoint': 'Endpoint address',\n 'judge.endpointDesc': 'The full address, including the protocol path. One System One example is prefilled.',\n 'judge.model': 'Judgement model',\n 'judge.modelDesc': 'The model id this endpoint interprets.',\n 'judge.key': 'Key',\n 'judge.keyDesc': 'Stored write-only as {ref} in {path}. It is never read back into this page.',\n 'judge.keyPlaceholder': 'Paste the key',\n 'judge.keyPlaceholderSet': 'A key is stored; type a new one to replace it',\n 'judge.keySet': 'Key stored',\n 'judge.keyUnset': 'No key',\n 'judge.keyClear': 'Remove the key',\n 'judge.keySaved': 'The key is stored.',\n 'judge.keyCleared': 'The key was removed.',\n 'judge.keyFailed': 'The key was not stored: {error}',\n 'key.unavailable': 'The credentials service is unavailable on this page.',\n 'judge.keyUnavailable': 'This page has no credentials channel, so a key cannot be stored from here.',\n 'key.saveFailed': 'The key was not accepted.',\n 'key.clearFailed': 'The key was not removed.',\n 'judge.probe': 'Test the connection',\n 'judge.probing': 'Testing\u2026',\n 'judge.probeOk': 'Connected in {latency} ms',\n 'judge.probeFail': 'Not usable: {reason}',\n 'reason.unconfigured': 'the endpoint address or model is not filled in',\n 'reason.unreachable': 'the endpoint could not be reached',\n 'reason.timeout': 'it did not answer within 5 seconds',\n 'reason.unmatched': 'the answer named no listed type',\n 'reason.incomplete': 'the selected type is not filled in',\n 'reason.other': 'other',\n 'reason.unknown': 'unknown reason',\n 'rows.title': 'Task types',\n 'rows.desc':\n 'One row per task type: the number it answers with, the description it reads, the model it runs on, and the effort. Numbers are assigned for you, always 1, 2, 3\u2026',\n 'rows.empty': 'No task type yet. Add one below, or pick a ready-made entry.',\n 'rows.colId': 'No.',\n 'rows.colType': 'Task type',\n 'rows.colDescription': 'Description',\n 'rows.colModel': 'Model',\n 'rows.colEffort': 'Effort',\n 'rows.add': 'Add a row',\n 'rows.remove': 'Remove',\n 'rows.browse': 'View',\n 'rows.browseTitle': 'Task type {id}',\n 'rows.browseClose': 'Close',\n 'rows.modelPlaceholder': 'Not chosen',\n 'rows.effortPlaceholder': 'Not chosen',\n 'rows.incomplete': 'Not used',\n 'rows.descriptionPlaceholder': 'What kind of job is this? Write as much as you like.',\n 'rows.allowedEmpty':\n 'The host setting \"models subagents may choose\" is empty, so there is nothing to pick. Fill it in on the Subagent settings page first.',\n 'presets.title': 'Ready-made entries',\n 'presets.desc': 'Click one to add it to the list. The effort shown is only a hint and is not filled in for you.',\n 'presets.effortHint': 'Suggested effort: {effort}',\n 'preset.mechanical': 'Mechanical edit',\n 'preset.mechanical.desc': 'Renaming, moving, formatting, or repeated small changes that need no judgement.',\n 'preset.research': 'Gathering material',\n 'preset.research.desc': 'Reading documents or code to collect facts and report them back.',\n 'preset.smallFeature': 'Small feature',\n 'preset.smallFeature.desc': 'Implementing one clearly specified piece of behaviour.',\n 'preset.spec': 'Writing a specification',\n 'preset.spec.desc': 'Turning a request into a precise written specification.',\n 'preset.review': 'Reviewing code',\n 'preset.review.desc': 'Reading a change and reporting what is wrong or missing in it.',\n 'preset.debug': 'Debugging a hard problem',\n 'preset.debug.desc': 'Finding the cause of a failure that is not obvious from the symptom.',\n 'preset.design': 'Technical plan',\n 'preset.design.desc': 'Deciding how to build something and what the trade-offs are.',\n 'preset.test': 'Running tests',\n 'preset.test.desc': 'Running an existing check and reporting what it produced.',\n 'preset.effortLow': 'low',\n 'preset.effortMedium': 'medium',\n 'preset.effortHigh': 'high',\n 'preview.title': 'View the full prompt',\n 'preview.desc': 'Exactly what would be sent to the judgement service. The task text is filled in at delegation time.',\n 'preview.open': 'View the full prompt',\n 'preview.copy': 'Copy',\n 'preview.copied': 'Copied',\n 'preview.close': 'Close',\n 'preview.blocked': 'Save your changes first.',\n 'preview.failed': 'The preview could not be read.',\n 'save.button': 'Save',\n 'save.saving': 'Saving\u2026',\n 'save.unsaved': 'There are unsaved changes.',\n 'save.discard': 'Discard',\n 'save.refusedTitle': 'This cannot be saved yet',\n 'save.failed': 'The save did not land: {error}',\n 'save.duplicateDescription': 'Two rows have the same description. Give them different descriptions before saving.',\n 'save.emptyDescription': 'Every row needs a description before it can be saved.',\n 'save.invalid': 'This cannot be saved yet.',\n 'save.refused': 'The host did not accept this write.',\n 'log.title': 'Recent judgements',\n 'log.desc': 'The most recent 20 judgements in this running instance, newest first.',\n 'log.empty': 'No judgement has run yet.',\n 'log.colProvider': 'Provider',\n 'log.colModel': 'Model',\n 'log.colEffort': 'Effort',\n 'log.colTime': 'Time',\n 'log.colLatency': 'Took',\n 'log.sourceJudged': 'Judged as type {id}',\n 'log.sourceInherited': 'Other: {reason}',\n 'log.refresh': 'Refresh',\n 'log.detailTitle': 'Judgement detail',\n 'log.detailClose': 'Close',\n 'log.detailSource': 'Where it came from',\n 'log.detailProvider': 'Provider',\n 'log.detailModel': 'Model',\n 'log.detailEffort': 'Effort',\n 'log.detailReason': 'Reason',\n 'log.detailLatency': 'Took',\n 'log.detailParent': 'Conversation',\n 'log.detailChild': 'Subagent description',\n 'log.loadFailed': 'The log could not be read.',\n 'ms': '{value} ms',\n};\n\n/** \u4E2D\u6587\u6587\u6848\u3002\u952E\u96C6\u4E0E\u82F1\u6587\u9010\u4E00\u5BF9\u9F50\uFF08smoke-client \u4F1A\u67E5\u8FD9\u4E00\u6761\uFF09\u3002 */\nexport const zh: Record<keyof typeof en, string> = {\n 'tab.design': '\u8BBE\u8BA1',\n 'tab.log': '\u65E5\u5FD7',\n 'switch.rewrite.title': '\u6539\u5199\u5B50\u4EE3\u7406\u7684\u6A21\u578B\u4E0E\u5F3A\u5EA6',\n 'switch.rewrite.desc': '\u6BCF\u4E2A\u5B50\u4EE3\u7406\u5728\u6D3E\u5DE5\u90A3\u4E00\u523B\u5224\u65AD\u4E00\u6B21\u3002\u8FD9\u4E2A\u5F00\u5173\u5173\u7740\u65F6\u4E0D\u5224\u65AD\uFF0C\u4E5F\u4E0D\u8BB0\u65E5\u5FD7\u3002',\n 'switch.log.title': '\u8BB0\u5F55\u65E5\u5FD7',\n 'switch.log.desc': '\u5728\u672C\u6B21\u8FD0\u884C\u671F\u95F4\u4FDD\u7559\u6700\u8FD1\u7684\u5224\u65AD\u8BB0\u5F55\u3002\u91CD\u542F\u5C31\u6E05\u7A7A\u3002',\n 'judge.title': '\u5224\u65AD\u670D\u52A1',\n 'judge.desc': '\u4EFB\u52A1\u7C7B\u578B\u7531\u8FD9\u4E2A\u5730\u5740\u51B3\u5B9A\uFF1A\u5B83\u6536\u5230\u7C7B\u578B\u6E05\u5355\u548C\u4EFB\u52A1\u6587\u5B57\uFF0C\u56DE\u7B54\u4E00\u4E2A\u7C7B\u578B\u7F16\u53F7\u3002',\n 'judge.endpoint': '\u7AEF\u70B9\u5730\u5740',\n 'judge.endpointDesc': '\u5B8C\u6574\u5730\u5740\uFF0C\u8981\u5E26\u534F\u8BAE\u8DEF\u5F84\u3002\u5DF2\u7ECF\u9884\u586B\u4E00\u4E2A System One \u7684\u4F8B\u5B50\u3002',\n 'judge.model': '\u5224\u65AD\u6A21\u578B',\n 'judge.modelDesc': '\u8FD9\u4E2A\u5730\u5740\u6240\u4F7F\u7528\u7684\u6A21\u578B\u540D\u3002',\n 'judge.key': '\u5BC6\u94A5',\n 'judge.keyDesc': '\u4EE5 {ref} \u7684\u540D\u5B57\u5B58\u8FDB {path}\uFF0C\u53EA\u5199\u4E0D\u8BFB\uFF0C\u4E0D\u4F1A\u56DE\u586B\u5230\u8FD9\u4E00\u9875\u3002',\n 'judge.keyPlaceholder': '\u628A\u5BC6\u94A5\u8D34\u8FDB\u6765',\n 'judge.keyPlaceholderSet': '\u5DF2\u7ECF\u5B58\u4E86\u5BC6\u94A5\uFF0C\u8981\u6362\u5C31\u586B\u4E00\u4E2A\u65B0\u7684',\n 'judge.keySet': '\u5DF2\u5B58\u5BC6\u94A5',\n 'judge.keyUnset': '\u8FD8\u6CA1\u6709\u5BC6\u94A5',\n 'judge.keyClear': '\u5220\u6389\u5BC6\u94A5',\n 'judge.keySaved': '\u5BC6\u94A5\u5DF2\u5B58\u3002',\n 'judge.keyCleared': '\u5BC6\u94A5\u5DF2\u5220\u6389\u3002',\n 'judge.keyFailed': '\u5BC6\u94A5\u6CA1\u5B58\u4E0A\uFF1A{error}',\n 'key.unavailable': '\u8FD9\u4E2A\u9875\u9762\u4E0A\u7528\u4E0D\u4E86\u51ED\u636E\u670D\u52A1\u3002',\n 'judge.keyUnavailable': '\u8FD9\u4E2A\u9875\u9762\u4E0A\u6CA1\u6709\u51ED\u636E\u901A\u9053\uFF0C\u5728\u8FD9\u91CC\u5B58\u4E0D\u4E86\u5BC6\u94A5\u3002',\n 'key.saveFailed': '\u5BC6\u94A5\u6CA1\u88AB\u63A5\u53D7\u3002',\n 'key.clearFailed': '\u5BC6\u94A5\u6CA1\u5220\u6389\u3002',\n 'judge.probe': '\u8BD5\u4E00\u4E0B\u901A\u4E0D\u901A',\n 'judge.probing': '\u6B63\u5728\u8BD5\u2026',\n 'judge.probeOk': '\u8FDE\u4E0A\u4E86\uFF0C\u7528\u4E86 {latency} \u6BEB\u79D2',\n 'judge.probeFail': '\u7528\u4E0D\u4E86\uFF1A{reason}',\n 'reason.unconfigured': '\u7AEF\u70B9\u5730\u5740\u6216\u5224\u65AD\u6A21\u578B\u8FD8\u6CA1\u586B',\n 'reason.unreachable': '\u8FDE\u4E0D\u4E0A\u8FD9\u4E2A\u5730\u5740',\n 'reason.timeout': '\u7B49\u4E86 5 \u79D2\u6CA1\u56DE',\n 'reason.unmatched': '\u7B54\u590D\u5BF9\u4E0D\u4E0A\u6E05\u5355',\n 'reason.incomplete': '\u9009\u4E2D\u7684\u7C7B\u578B\u6CA1\u586B\u5168',\n 'reason.other': '\u5176\u4ED6',\n 'reason.unknown': '\u539F\u56E0\u4E0D\u660E',\n 'rows.title': '\u4EFB\u52A1\u7C7B\u578B',\n 'rows.desc':\n '\u4E00\u884C\u4E00\u4E2A\u4EFB\u52A1\u7C7B\u578B\uFF1A\u5B83\u56DE\u7B54\u7684\u7F16\u53F7\u3001\u5B83\u8BFB\u7684\u63CF\u8FF0\u3001\u8BE5\u7528\u7684\u6A21\u578B\u4E0E\u5F3A\u5EA6\u3002\u7F16\u53F7\u7531\u63D2\u4EF6\u81EA\u52A8\u6392\uFF0C\u6C38\u8FDC\u4ECE 1 \u5F80\u540E\u8FDE\u7740\u3002',\n 'rows.empty': '\u8FD8\u6CA1\u6709\u4EFB\u52A1\u7C7B\u578B\u3002\u5728\u4E0B\u9762\u52A0\u4E00\u884C\uFF0C\u6216\u8005\u70B9\u4E00\u4E2A\u9884\u5236\u8BCD\u6761\u3002',\n 'rows.colId': '\u7F16\u53F7',\n 'rows.colType': '\u4EFB\u52A1\u7C7B\u578B',\n 'rows.colDescription': '\u63CF\u8FF0',\n 'rows.colModel': '\u6A21\u578B',\n 'rows.colEffort': '\u5F3A\u5EA6',\n 'rows.add': '\u52A0\u4E00\u884C',\n 'rows.remove': '\u5220\u6389',\n 'rows.browse': '\u67E5\u770B',\n 'rows.browseTitle': '\u4EFB\u52A1\u7C7B\u578B {id}',\n 'rows.browseClose': '\u5173\u95ED',\n 'rows.modelPlaceholder': '\u8FD8\u6CA1\u9009',\n 'rows.effortPlaceholder': '\u8FD8\u6CA1\u9009',\n 'rows.incomplete': '\u4E0D\u751F\u6548',\n 'rows.descriptionPlaceholder': '\u8FD9\u662F\u54EA\u79CD\u6D3B\uFF1F\u5199\u591A\u5C11\u90FD\u884C\u3002',\n 'rows.allowedEmpty': '\u5BBF\u4E3B\u90A3\u4EFD\u300C\u5B50\u4EE3\u7406\u53EF\u9009\u7528\u54EA\u4E9B\u6A21\u578B\u300D\u8FD8\u662F\u7A7A\u7684\uFF0C\u6CA1\u6709\u53EF\u4EE5\u9009\u7684\u4E1C\u897F\u3002\u5148\u5230\u5B50\u4EE3\u7406\u8BBE\u7F6E\u9875\u628A\u5B83\u586B\u4E0A\u3002',\n 'presets.title': '\u9884\u5236\u8BCD\u6761',\n 'presets.desc': '\u70B9\u4E00\u4E0B\u5C31\u52A0\u8FDB\u6E05\u5355\u3002\u65C1\u8FB9\u7684\u5F3A\u5EA6\u53EA\u662F\u63D0\u793A\uFF0C\u4E0D\u4F1A\u66FF\u4F60\u586B\u8FDB\u90A3\u4E24\u680F\u3002',\n 'presets.effortHint': '\u5EFA\u8BAE\u5F3A\u5EA6\uFF1A{effort}',\n 'preset.mechanical': '\u673A\u68B0\u4FEE\u6539',\n 'preset.mechanical.desc': '\u6539\u540D\u3001\u79FB\u52A8\u3001\u6392\u7248\uFF0C\u6216\u8005\u4E00\u6279\u4E0D\u9700\u8981\u5224\u65AD\u7684\u91CD\u590D\u5C0F\u6539\u3002',\n 'preset.research': '\u8D44\u6599\u6536\u96C6',\n 'preset.research.desc': '\u8BFB\u6587\u6863\u6216\u8BFB\u4EE3\u7801\uFF0C\u628A\u4E8B\u5B9E\u6536\u96C6\u8D77\u6765\u56DE\u62A5\u3002',\n 'preset.smallFeature': '\u5B9E\u73B0\u5C0F\u529F\u80FD',\n 'preset.smallFeature.desc': '\u5B9E\u73B0\u4E00\u6BB5\u5DF2\u7ECF\u8BB2\u6E05\u695A\u7684\u884C\u4E3A\u3002',\n 'preset.spec': '\u5199\u89C4\u683C',\n 'preset.spec.desc': '\u628A\u4E00\u53E5\u8981\u6C42\u5199\u6210\u4E00\u4EFD\u8BF4\u6E05\u695A\u7684\u89C4\u683C\u3002',\n 'preset.review': '\u8BC4\u5BA1\u4EE3\u7801',\n 'preset.review.desc': '\u8BFB\u4E00\u5904\u6539\u52A8\uFF0C\u6307\u51FA\u54EA\u91CC\u4E0D\u5BF9\u3001\u54EA\u91CC\u7F3A\u4E86\u3002',\n 'preset.debug': '\u8C03\u8BD5\u7591\u96BE',\n 'preset.debug.desc': '\u627E\u51FA\u4E00\u4E2A\u4ECE\u73B0\u8C61\u770B\u4E0D\u51FA\u6765\u7684\u5931\u8D25\u7684\u8D77\u56E0\u3002',\n 'preset.design': '\u505A\u6280\u672F\u65B9\u6848',\n 'preset.design.desc': '\u51B3\u5B9A\u8FD9\u4EF6\u4E8B\u600E\u4E48\u505A\uFF0C\u4EE5\u53CA\u5404\u6761\u8DEF\u7684\u53D6\u820D\u3002',\n 'preset.test': '\u8DD1\u6D4B\u8BD5',\n 'preset.test.desc': '\u8DD1\u4E00\u6B21\u73B0\u6210\u7684\u68C0\u67E5\uFF0C\u628A\u7ED3\u679C\u62A5\u56DE\u6765\u3002',\n 'preset.effortLow': '\u4F4E',\n 'preset.effortMedium': '\u4E2D',\n 'preset.effortHigh': '\u9AD8',\n 'preview.title': '\u67E5\u770B\u5B8C\u6574\u9884\u89C8',\n 'preview.desc': '\u771F\u6B63\u4F1A\u53D1\u7ED9\u5224\u65AD\u670D\u52A1\u7684\u90A3\u6BB5\u5185\u5BB9\u3002\u4EFB\u52A1\u6587\u5B57\u5728\u6D3E\u5DE5\u90A3\u4E00\u523B\u624D\u586B\u8FDB\u53BB\u3002',\n 'preview.open': '\u67E5\u770B\u5B8C\u6574\u9884\u89C8',\n 'preview.copy': '\u590D\u5236',\n 'preview.copied': '\u5DF2\u590D\u5236',\n 'preview.close': '\u5173\u95ED',\n 'preview.blocked': '\u5148\u628A\u6539\u52A8\u4FDD\u5B58\u4E0B\u6765\u3002',\n 'preview.failed': '\u9884\u89C8\u8BFB\u4E0D\u51FA\u6765\u3002',\n 'save.button': '\u4FDD\u5B58',\n 'save.saving': '\u6B63\u5728\u4FDD\u5B58\u2026',\n 'save.unsaved': '\u6709\u8FD8\u6CA1\u4FDD\u5B58\u7684\u6539\u52A8\u3002',\n 'save.discard': '\u653E\u5F03\u6539\u52A8',\n 'save.refusedTitle': '\u73B0\u5728\u8FD8\u5B58\u4E0D\u4E86',\n 'save.failed': '\u6CA1\u4FDD\u5B58\u4E0A\uFF1A{error}',\n 'save.duplicateDescription': '\u6709\u4E24\u6761\u7684\u63CF\u8FF0\u4E00\u6A21\u4E00\u6837\u3002\u6539\u6210\u4E0D\u4E00\u6837\u7684\u518D\u4FDD\u5B58\u3002',\n 'save.emptyDescription': '\u6BCF\u4E00\u884C\u90FD\u8981\u6709\u63CF\u8FF0\u624D\u80FD\u4FDD\u5B58\u3002',\n 'save.invalid': '\u73B0\u5728\u8FD8\u5B58\u4E0D\u4E86\u3002',\n 'save.refused': '\u5BBF\u4E3B\u6CA1\u6709\u63A5\u53D7\u8FD9\u6B21\u5199\u5165\u3002',\n 'log.title': '\u6700\u8FD1\u7684\u5224\u65AD',\n 'log.desc': '\u672C\u6B21\u8FD0\u884C\u671F\u95F4\u6700\u8FD1\u7684 20 \u6761\u5224\u65AD\uFF0C\u65B0\u7684\u5728\u6700\u524D\u9762\u3002',\n 'log.empty': '\u8FD8\u6CA1\u6709\u5224\u65AD\u8FC7\u3002',\n 'log.colProvider': '\u4F9B\u5E94\u5546',\n 'log.colModel': '\u6A21\u578B',\n 'log.colEffort': '\u5F3A\u5EA6',\n 'log.colTime': '\u65F6\u95F4',\n 'log.colLatency': '\u8017\u65F6',\n 'log.sourceJudged': '\u5224\u6210\u7C7B\u578B {id}',\n 'log.sourceInherited': '\u5176\u4ED6\uFF1A{reason}',\n 'log.refresh': '\u5237\u65B0',\n 'log.detailTitle': '\u5224\u65AD\u8BE6\u60C5',\n 'log.detailClose': '\u5173\u95ED',\n 'log.detailSource': '\u7ED3\u679C\u6765\u6E90',\n 'log.detailProvider': '\u4F9B\u5E94\u5546',\n 'log.detailModel': '\u6A21\u578B',\n 'log.detailEffort': '\u5F3A\u5EA6',\n 'log.detailReason': '\u539F\u56E0',\n 'log.detailLatency': '\u8017\u65F6',\n 'log.detailParent': '\u4F1A\u8BDD',\n 'log.detailChild': '\u5B50\u4EE3\u7406\u63CF\u8FF0',\n 'log.loadFailed': '\u65E5\u5FD7\u8BFB\u4E0D\u51FA\u6765\u3002',\n 'ms': '{value} \u6BEB\u79D2',\n};\n\n/**\n * \u628A\u5B57\u5178\u4EA4\u7ED9\u5BBF\u4E3B\u3002\u547D\u540D\u7A7A\u95F4\u4E0E\u952E\u96C6\u5728\u8FD9\u91CC\u58F0\u660E\u7684\u7C7B\u578B\u540C\u65F6\u662F\u5EA7\u4F4D `t` \u7684\u5951\u7EA6\u3002\n * @param ctx - \u5BA2\u6237\u7AEF\u4E0A\u4E0B\u6587\uFF08`locale` \u7531 inject \u58F0\u660E\uFF09\u3002\n */\nexport function apply(ctx: {\n effect(factory: () => () => void, label?: string): unknown;\n locale: { register(ns: string, dictionaries: unknown): () => void };\n}): void {\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'dsh-subagent-judge-dispatch: dictionaries');\n}\n\n/** \u672C\u547D\u540D\u7A7A\u95F4\u5168\u90E8\u952E\u7684\u7C7B\u578B\uFF0C\u5EA7\u4F4D\u4E0A\u7684 `t` \u6309\u5B83\u505A\u952E\u68C0\u67E5\u3002 */\nexport type JudgeDispatchLocaleKey = keyof typeof en;\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n /** \u672C\u63D2\u4EF6\u914D\u7F6E\u5361\u7247\u7684\u6587\u6848\u3002 */\n subagentjudgedispatch: JudgeDispatchLocaleKey;\n }\n}\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": ["apply", "name", "apply"]
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lynn123411/dsh-subagent-judge-dispatch",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "用一个判断模型从你写的任务类型清单里挑一个编号,据此改写子代理使用的模型与思考强度。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -56,20 +56,20 @@
|
|
|
56
56
|
}
|
|
57
57
|
},
|
|
58
58
|
"peerDependencies": {
|
|
59
|
-
"@deepseek-ai/cordis": "^4.0.5
|
|
60
|
-
"@deepseek-ai/dsh-client-connection": ">=0.2.1-
|
|
59
|
+
"@deepseek-ai/cordis": "^4.0.5",
|
|
60
|
+
"@deepseek-ai/dsh-client-connection": ">=0.2.1-rc.2"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
|
-
"@deepseek-ai/cordis": "^4.0.5
|
|
64
|
-
"@deepseek-ai/schemastery": "^3.18.5
|
|
65
|
-
"@deepseek-ai/dsh-agent": ">=0.2.1-
|
|
66
|
-
"@deepseek-ai/dsh-client-connection": ">=0.2.1-
|
|
67
|
-
"@deepseek-ai/dsh-client-locale": ">=0.2.1-
|
|
68
|
-
"@deepseek-ai/dsh-client-ui-plugin-manager": ">=0.2.1-
|
|
69
|
-
"@deepseek-ai/dsh-client-ui-primitives": ">=0.2.1-
|
|
70
|
-
"@deepseek-ai/dsh-client-ui-renderer": ">=0.2.1-
|
|
71
|
-
"@deepseek-ai/dsh-client-ui-settings": ">=0.2.1-
|
|
72
|
-
"@deepseek-ai/dsh-client-ui-slots": ">=0.2.1-
|
|
63
|
+
"@deepseek-ai/cordis": "^4.0.5",
|
|
64
|
+
"@deepseek-ai/schemastery": "^3.18.5",
|
|
65
|
+
"@deepseek-ai/dsh-agent": ">=0.2.1-rc.2",
|
|
66
|
+
"@deepseek-ai/dsh-client-connection": ">=0.2.1-rc.2",
|
|
67
|
+
"@deepseek-ai/dsh-client-locale": ">=0.2.1-rc.2",
|
|
68
|
+
"@deepseek-ai/dsh-client-ui-plugin-manager": ">=0.2.1-rc.2",
|
|
69
|
+
"@deepseek-ai/dsh-client-ui-primitives": ">=0.2.1-rc.2",
|
|
70
|
+
"@deepseek-ai/dsh-client-ui-renderer": ">=0.2.1-rc.2",
|
|
71
|
+
"@deepseek-ai/dsh-client-ui-settings": ">=0.2.1-rc.2",
|
|
72
|
+
"@deepseek-ai/dsh-client-ui-slots": ">=0.2.1-rc.2",
|
|
73
73
|
"@types/node": "^22.20.0",
|
|
74
74
|
"@types/react": "^19.2.18",
|
|
75
75
|
"@types/react-dom": "^19.3.0",
|
|
@@ -79,9 +79,10 @@
|
|
|
79
79
|
"typescript": "^6.0.0"
|
|
80
80
|
},
|
|
81
81
|
"engines": {
|
|
82
|
-
"dsh": ">=0.2.1-
|
|
82
|
+
"dsh": ">=0.2.1-rc.2",
|
|
83
83
|
"node": "^22.19 || >=24"
|
|
84
84
|
},
|
|
85
|
+
"packageManager": "pnpm@11.7.0",
|
|
85
86
|
"publishConfig": {
|
|
86
87
|
"access": "public"
|
|
87
88
|
},
|