dsh-daruma 0.1.7 → 0.1.8

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/README.md CHANGED
@@ -59,6 +59,36 @@ in-repo retries render. The notices are **live-only** — out-of-repo session
59
59
  events are not yet persisted by the harness, so rows do not survive a page
60
60
  reload or a resumed session.
61
61
 
62
+ ## Usage screenshots / 使用截图
63
+
64
+ These are captures from a live DSH Web session running the mock-a → mock-b
65
+ failover flow.
66
+
67
+ The images are linked by absolute URL on purpose: npm's web UI does not resolve
68
+ relative README image paths, so a `./assets/…` link renders broken on the
69
+ package page (it still works on GitHub). The copies shipped in the tarball
70
+ (`files`) are for readers of the package itself.
71
+
72
+ ### English
73
+
74
+ ![English failover notice in the conversation](https://raw.githubusercontent.com/SISCHOI/daruma/main/packages/dsh-daruma/assets/en-failover-row.jpg)
75
+
76
+ *Failover notice shown inline after mock-a returns `RATE_LIMIT`.*
77
+
78
+ ![English backup channel panel](https://raw.githubusercontent.com/SISCHOI/daruma/main/packages/dsh-daruma/assets/en-backup-panel.jpg)
79
+
80
+ *Backup channel picker with the current and candidate models.*
81
+
82
+ ### 中文
83
+
84
+ ![中文会话中的故障转移提示](https://raw.githubusercontent.com/SISCHOI/daruma/main/packages/dsh-daruma/assets/zh-failover-row.jpg)
85
+
86
+ *mock-a 返回 `RATE_LIMIT` 后,中文界面显示故障转移提示。*
87
+
88
+ ![中文备用渠道面板](https://raw.githubusercontent.com/SISCHOI/daruma/main/packages/dsh-daruma/assets/zh-backup-panel.jpg)
89
+
90
+ *备用渠道面板展示当前备用模型和候选模型。*
91
+
62
92
  ## Audit log
63
93
 
64
94
  Every failover / give-up / boot decision is appended to
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Client transport for the daruma panel.
3
+ *
4
+ * Primary path: the legacy generic channel (`/dsh-daruma`) — served by
5
+ * `rpc.handle` on hosts up to 0.1.2 and on 0.1.5 hosts patched by the
6
+ * community fix.
7
+ *
8
+ * Fallback path: the `/api` shared carrier (`/api/dsh-daruma` exact route,
9
+ * registered by the host-side fallback in `src/http-transport.ts`). The
10
+ * browser caller switches on the first HTTP 404/405 — the route-miss shape of
11
+ * the 0.1.5 `rpc.handle` regression — and sticks with the fallback for the
12
+ * rest of the page lifetime, so the panel needs at most one failed request
13
+ * per load. Auth failures (401/403) and handler errors surface as-is: they
14
+ * say nothing about which transport should be used.
15
+ *
16
+ * Wire shape: exact Fetch routes match by URL path segment, and the shared
17
+ * carrier validates that the envelope `method` equals that segment — so the
18
+ * real endpoint and payload ride inside the payload tunnel, exactly like the
19
+ * real-plane-verified dsh-im management RPC.
20
+ */
21
+ import type { Rpc } from './api.ts';
22
+ /** Structural connection surface (host provides the real one). */
23
+ interface ConnectionLike {
24
+ rpc: {
25
+ call(channel: string, endpoint: string, payload: unknown): Promise<unknown>;
26
+ };
27
+ }
28
+ /** Generic channel served by `connection.rpc.handle` where it works. */
29
+ export declare const LEGACY_CHANNEL = "/dsh-daruma";
30
+ /** Shared browser carrier the host itself mounts on every web-capable host. */
31
+ export declare const FALLBACK_CHANNEL = "/api";
32
+ /** Envelope method demanded by the exact `/api/dsh-daruma` route. */
33
+ export declare const FALLBACK_ENDPOINT = "dsh-daruma";
34
+ /**
35
+ * Whether a rejected legacy call means "the channel route does not exist on
36
+ * this host" (switch to the fallback) rather than anything else. The browser
37
+ * caller throws `transport failure for <channel>/<endpoint>: HTTP <status>`
38
+ * when the response is not ok.
39
+ */
40
+ export declare function isChannelRouteMiss(error: unknown): boolean;
41
+ /** Build the panel `Rpc`: legacy channel first, sticky `/api` fallback. */
42
+ export declare function createAdaptiveRpc(connection: ConnectionLike): Rpc;
43
+ export {};
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Client transport for the daruma panel.
3
+ *
4
+ * Primary path: the legacy generic channel (`/dsh-daruma`) — served by
5
+ * `rpc.handle` on hosts up to 0.1.2 and on 0.1.5 hosts patched by the
6
+ * community fix.
7
+ *
8
+ * Fallback path: the `/api` shared carrier (`/api/dsh-daruma` exact route,
9
+ * registered by the host-side fallback in `src/http-transport.ts`). The
10
+ * browser caller switches on the first HTTP 404/405 — the route-miss shape of
11
+ * the 0.1.5 `rpc.handle` regression — and sticks with the fallback for the
12
+ * rest of the page lifetime, so the panel needs at most one failed request
13
+ * per load. Auth failures (401/403) and handler errors surface as-is: they
14
+ * say nothing about which transport should be used.
15
+ *
16
+ * Wire shape: exact Fetch routes match by URL path segment, and the shared
17
+ * carrier validates that the envelope `method` equals that segment — so the
18
+ * real endpoint and payload ride inside the payload tunnel, exactly like the
19
+ * real-plane-verified dsh-im management RPC.
20
+ */
21
+ /** Generic channel served by `connection.rpc.handle` where it works. */
22
+ export const LEGACY_CHANNEL = '/dsh-daruma';
23
+ /** Shared browser carrier the host itself mounts on every web-capable host. */
24
+ export const FALLBACK_CHANNEL = '/api';
25
+ /** Envelope method demanded by the exact `/api/dsh-daruma` route. */
26
+ export const FALLBACK_ENDPOINT = 'dsh-daruma';
27
+ /**
28
+ * Whether a rejected legacy call means "the channel route does not exist on
29
+ * this host" (switch to the fallback) rather than anything else. The browser
30
+ * caller throws `transport failure for <channel>/<endpoint>: HTTP <status>`
31
+ * when the response is not ok.
32
+ */
33
+ export function isChannelRouteMiss(error) {
34
+ return error instanceof Error && /HTTP (404|405)\b/u.test(error.message);
35
+ }
36
+ function tunnelCall(connection, endpoint, payload) {
37
+ return connection.rpc.call(FALLBACK_CHANNEL, FALLBACK_ENDPOINT, {
38
+ method: endpoint,
39
+ payload: payload ?? {},
40
+ });
41
+ }
42
+ /** Build the panel `Rpc`: legacy channel first, sticky `/api` fallback. */
43
+ export function createAdaptiveRpc(connection) {
44
+ let useFallback = false;
45
+ return (endpoint, payload) => {
46
+ if (useFallback) {
47
+ return tunnelCall(connection, endpoint, payload);
48
+ }
49
+ return connection.rpc.call(LEGACY_CHANNEL, endpoint, payload ?? {}).catch((error) => {
50
+ if (!isChannelRouteMiss(error))
51
+ throw error;
52
+ useFallback = true;
53
+ return tunnelCall(connection, endpoint, payload);
54
+ });
55
+ };
56
+ }
57
+ //# sourceMappingURL=adaptive-rpc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adaptive-rpc.js","sourceRoot":"","sources":["../../src/client/adaptive-rpc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAWH,wEAAwE;AACxE,MAAM,CAAC,MAAM,cAAc,GAAG,aAAa,CAAA;AAC3C,+EAA+E;AAC/E,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAA;AACtC,qEAAqE;AACrE,MAAM,CAAC,MAAM,iBAAiB,GAAG,YAAY,CAAA;AAE7C;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,OAAO,KAAK,YAAY,KAAK,IAAI,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;AAC1E,CAAC;AAED,SAAS,UAAU,CACjB,UAA0B,EAC1B,QAAgB,EAChB,OAAgB;IAEhB,OAAO,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,EAAE,iBAAiB,EAAE;QAC9D,MAAM,EAAE,QAAQ;QAChB,OAAO,EAAE,OAAO,IAAI,EAAE;KACvB,CAAC,CAAA;AACJ,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,iBAAiB,CAAC,UAA0B;IAC1D,IAAI,WAAW,GAAG,KAAK,CAAA;IACvB,OAAO,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE;QAC3B,IAAI,WAAW,EAAE,CAAC;YAChB,OAAO,UAAU,CAAC,UAAU,EAAE,QAAQ,EAAE,OAAO,CAAuB,CAAA;QACxE,CAAC;QACD,OAAO,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,EAAE,QAAQ,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,KAAK,CACvE,CAAC,KAAc,EAAE,EAAE;YACjB,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC;gBAAE,MAAM,KAAK,CAAA;YAC3C,WAAW,GAAG,IAAI,CAAA;YAClB,OAAO,UAAU,CAAC,UAAU,EAAE,QAAQ,EAAE,OAAO,CAAuB,CAAA;QACxE,CAAC,CACoB,CAAA;IACzB,CAAC,CAAA;AACH,CAAC"}
@@ -7,6 +7,7 @@
7
7
  import { createElement as h } from 'react';
8
8
  import { en, zh } from "./locales.js";
9
9
  import { createApi } from "./api.js";
10
+ import { createAdaptiveRpc } from "./adaptive-rpc.js";
10
11
  import { StatusDock } from "./StatusDock.js";
11
12
  import { createFailoverNoticeDefinition, FAILOVER_NOTICE_KIND, } from "./failover-notice.js";
12
13
  import { FailoverNoticeRow } from "./FailoverNoticeRow.js";
@@ -68,7 +69,7 @@ export function apply(ctx) {
68
69
  console.warn('[dsh-daruma] web transport unavailable — client UI disabled');
69
70
  return;
70
71
  }
71
- const rpc = (endpoint, payload) => connection.rpc.call('/dsh-daruma', endpoint, payload ?? {});
72
+ const rpc = createAdaptiveRpc(connection);
72
73
  const api = createApi(rpc);
73
74
  ctx.slots.inject('conversation.input.right', () => ctx.slots.register({
74
75
  name: 'conversation.input.right',
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"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"}
package/lib/client.js CHANGED
@@ -96,6 +96,61 @@ window.__ModuleLoader__.load({
96
96
  };
97
97
  }
98
98
  //#endregion
99
+ //#region lib/client/adaptive-rpc.js
100
+ /**
101
+ * Client transport for the daruma panel.
102
+ *
103
+ * Primary path: the legacy generic channel (`/dsh-daruma`) — served by
104
+ * `rpc.handle` on hosts up to 0.1.2 and on 0.1.5 hosts patched by the
105
+ * community fix.
106
+ *
107
+ * Fallback path: the `/api` shared carrier (`/api/dsh-daruma` exact route,
108
+ * registered by the host-side fallback in `src/http-transport.ts`). The
109
+ * browser caller switches on the first HTTP 404/405 — the route-miss shape of
110
+ * the 0.1.5 `rpc.handle` regression — and sticks with the fallback for the
111
+ * rest of the page lifetime, so the panel needs at most one failed request
112
+ * per load. Auth failures (401/403) and handler errors surface as-is: they
113
+ * say nothing about which transport should be used.
114
+ *
115
+ * Wire shape: exact Fetch routes match by URL path segment, and the shared
116
+ * carrier validates that the envelope `method` equals that segment — so the
117
+ * real endpoint and payload ride inside the payload tunnel, exactly like the
118
+ * real-plane-verified dsh-im management RPC.
119
+ */
120
+ /** Generic channel served by `connection.rpc.handle` where it works. */
121
+ const LEGACY_CHANNEL = "/dsh-daruma";
122
+ /** Shared browser carrier the host itself mounts on every web-capable host. */
123
+ const FALLBACK_CHANNEL = "/api";
124
+ /** Envelope method demanded by the exact `/api/dsh-daruma` route. */
125
+ const FALLBACK_ENDPOINT = "dsh-daruma";
126
+ /**
127
+ * Whether a rejected legacy call means "the channel route does not exist on
128
+ * this host" (switch to the fallback) rather than anything else. The browser
129
+ * caller throws `transport failure for <channel>/<endpoint>: HTTP <status>`
130
+ * when the response is not ok.
131
+ */
132
+ function isChannelRouteMiss(error) {
133
+ return error instanceof Error && /HTTP (404|405)\b/u.test(error.message);
134
+ }
135
+ function tunnelCall(connection, endpoint, payload) {
136
+ return connection.rpc.call(FALLBACK_CHANNEL, FALLBACK_ENDPOINT, {
137
+ method: endpoint,
138
+ payload: payload ?? {}
139
+ });
140
+ }
141
+ /** Build the panel `Rpc`: legacy channel first, sticky `/api` fallback. */
142
+ function createAdaptiveRpc(connection) {
143
+ let useFallback = false;
144
+ return (endpoint, payload) => {
145
+ if (useFallback) return tunnelCall(connection, endpoint, payload);
146
+ return connection.rpc.call(LEGACY_CHANNEL, endpoint, payload ?? {}).catch((error) => {
147
+ if (!isChannelRouteMiss(error)) throw error;
148
+ useFallback = true;
149
+ return tunnelCall(connection, endpoint, payload);
150
+ });
151
+ };
152
+ }
153
+ //#endregion
99
154
  //#region lib/client/health.js
100
155
  /**
101
156
  * Time-aware channel-health classification for the status dock.
@@ -732,8 +787,7 @@ window.__ModuleLoader__.load({
732
787
  console.warn("[dsh-daruma] web transport unavailable — client UI disabled");
733
788
  return;
734
789
  }
735
- const rpc = (endpoint, payload) => connection.rpc.call("/dsh-daruma", endpoint, payload ?? {});
736
- const api = createApi(rpc);
790
+ const api = createApi(createAdaptiveRpc(connection));
737
791
  ctx.slots.inject("conversation.input.right", () => ctx.slots.register({
738
792
  name: "conversation.input.right",
739
793
  id: "daruma-status",
package/lib/client.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","names":["rowStyle","memo","_jsxs","_jsx","Pill","Button","useState","useMemo","useCallback","Modal","_Fragment","_jsx","IconCheckOutline16","IconWarningOutline16","useState","useCallback","_jsxs","_Fragment","Button","h","h"],"sources":["client/locales.js","client/api.js","client/health.js","client/BackupPanel.js","client/StatusDock.js","client/failover-notice.js","client/FailoverNoticeRow.js","client/index.js"],"sourcesContent":["/** zh/en dictionaries for the daruma client UI. */\nexport const zh = {\n status: '渠道状态',\n current: '当前',\n backup: '备用',\n backupNone: '未设置',\n backupManage: '备用渠道',\n backupManageHint: '从候选列表选择备用渠道',\n failoverCount: '已切换',\n lastFailover: '上次切换',\n healthy: '健康',\n cooldown: '冷却中',\n probe: '探测中',\n refresh: '刷新',\n close: '关闭',\n clearBackup: '清除备用',\n provider: '提供方',\n providerPlaceholder: 'provider,如 mt',\n loadCandidates: '加载候选',\n loading: '加载中…',\n candidates: '候选模型',\n setBackup: '设为备用',\n currentBackup: '当前备用',\n currentBackupMark: '备用',\n noCandidates: '未加载到候选模型',\n empty: '暂无渠道数据',\n failoverNoticeLine: '{from} 请求失败({reason})→ 本次尝试 {to}',\n failoverNoticeDetail: '第 {count}/{budget} 次失败切换 · turn {turn} step {step}',\n failoverGiveUpLine: '{from} 请求失败({reason})→ 已用尽恢复手段,停止重试',\n failoverGiveUpDetail: '失败切换 {count}/{budget} · turn {turn} step {step}',\n};\nexport const en = {\n status: 'Channel status',\n current: 'Current',\n backup: 'Backup',\n backupNone: 'none',\n backupManage: 'Backup channel',\n backupManageHint: 'Pick a backup channel from the candidate list',\n failoverCount: 'failovers',\n lastFailover: 'last failover',\n healthy: 'healthy',\n cooldown: 'cooling',\n probe: 'probing',\n refresh: 'Refresh',\n close: 'Close',\n clearBackup: 'Clear backup',\n provider: 'Provider',\n providerPlaceholder: 'provider, e.g. mt',\n loadCandidates: 'Load candidates',\n loading: 'Loading…',\n candidates: 'Candidate models',\n setBackup: 'Set as backup',\n currentBackup: 'Current backup',\n currentBackupMark: 'backup',\n noCandidates: 'No candidates loaded',\n empty: 'No channel data yet',\n failoverNoticeLine: '{from} failed ({reason}) → trying {to}',\n failoverNoticeDetail: 'failover {count}/{budget} · turn {turn} step {step}',\n failoverGiveUpLine: '{from} failed ({reason}) → recovery budget exhausted, giving up',\n failoverGiveUpDetail: 'failovers {count}/{budget} · turn {turn} step {step}',\n};\n//# sourceMappingURL=locales.js.map","/**\n * Client-side wire types and RPC wrapper for the `/dsh-daruma` channel.\n * Structural types only — no monorepo-internal imports.\n */\nexport function createApi(rpc) {\n const call = async (endpoint, payload) => {\n const result = (await rpc(endpoint, payload));\n if (!result.ok) {\n throw new Error(result.error?.message ?? `daruma rpc ${endpoint} failed`);\n }\n return result.value;\n };\n return {\n status: () => call('status'),\n listCandidates: (provider) => call('listCandidates', { provider }),\n setBackup: async (provider, model) => {\n await call('setBackup', { provider, model });\n },\n clearBackup: async () => {\n await call('clearBackup');\n },\n };\n}\n//# sourceMappingURL=api.js.map","/**\n * Time-aware channel-health classification for the status dock.\n *\n * The adapter now records successes (inferred from `agent/pre-step`), which\n * resets a channel to HEALTHY on its first successful request. But a channel\n * that never routes again (removed from the chain, one-shot backup) keeps its\n * last persisted state forever — including a stale COOLDOWN whose deadline\n * has long passed. The dock therefore still judges by time, not by the raw\n * state field: only a channel that is *still* cooling (cooldown not yet\n * expired) counts as an error.\n */\n/**\n * Overall dock state:\n * - `error` — at least one channel is still cooling (`cooldownUntilMs > now`).\n * - `warning` — a probe is in flight (kept for parity; the adapter no longer\n * enters PROBE, but persisted legacy states may surface it).\n * - `done` — everything routable: healthy, or cooled down long enough.\n * - `ongoing` — no snapshot yet.\n */\nexport function overallState(channels, nowMs) {\n if (channels === null)\n return 'ongoing';\n if (channels.some((c) => c.state === 'COOLDOWN' && c.cooldownUntilMs > nowMs))\n return 'error';\n if (channels.some((c) => c.state === 'PROBE'))\n return 'warning';\n return 'done';\n}\n//# sourceMappingURL=health.js.map","import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from \"react/jsx-runtime\";\n/**\n * BackupChannelPanel: list candidate models for a provider and pick one as\n * the failover backup. Rendered inside a primitives Modal.\n *\n * No probing happens here anymore — the panel is a plain picker. Channel\n * health still updates from real traffic via the recovery engine.\n */\nimport { memo, useCallback, useEffect, useMemo, useState } from 'react';\nimport { Button, Modal, Pill, } from '@deepseek-ai/dsh-client-ui-primitives';\nfunction deriveProvider(status) {\n if (status === null)\n return '';\n if (status.current !== null)\n return status.current.split('::')[0] ?? '';\n if (status.backup !== null)\n return status.backup.provider;\n return status.providers[0] ?? '';\n}\nconst sectionStyle = {\n display: 'flex',\n flexDirection: 'column',\n gap: '8px',\n padding: '12px 0',\n fontSize: '13px',\n};\nconst rowStyle = {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n};\nconst noteStyle = { color: 'var(--dsw-text-tertiary, #999)', fontSize: '12px' };\n/** Clamp a long provider/model name so the row never wraps. */\nconst backupPillStyle = {\n flex: '1 1 auto',\n minWidth: 0,\n overflow: 'hidden',\n};\nconst ellipsisStyle = {\n minWidth: 0,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n};\nconst listStyle = {\n maxHeight: 300,\n overflowY: 'auto',\n display: 'flex',\n flexDirection: 'column',\n gap: 4,\n contain: 'content',\n willChange: 'scroll-position',\n overscrollBehavior: 'contain',\n};\n/** Skip rendering rows outside the viewport while scrolling. */\nconst candidateRowStyle = {\n ...rowStyle,\n contentVisibility: 'auto',\n containIntrinsicSize: '28px',\n};\n/** One candidate row, memoized so selection changes only re-render it. */\nconst CandidateRow = memo(function CandidateRow(props) {\n const { candidate, isBackup, busy, t, onSetBackup } = props;\n return (_jsxs(\"div\", { style: candidateRowStyle, children: [_jsx(\"span\", { style: { width: 14, flexShrink: 0 } }), _jsx(\"span\", { style: { flex: 1, minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }, children: candidate.model }), isBackup && _jsx(Pill, { active: true, children: t('currentBackupMark') }), _jsx(Button, { size: \"sm\", variant: \"ghost\", disabled: isBackup || busy, onClick: () => onSetBackup(candidate.model), children: t('setBackup') })] }));\n});\nexport function BackupPanel(props) {\n const { api, t, status, onClose } = props;\n const [provider, setProvider] = useState(deriveProvider(status));\n const [candidates, setCandidates] = useState(null);\n const [loading, setLoading] = useState(false);\n const [busy, setBusy] = useState(null);\n const [error, setError] = useState(null);\n // Local overlay on the status-prop backup: applied optimistically after\n // set/clear so the row reflects the change without waiting for the parent\n // to re-fetch status. Cleared whenever a fresh status arrives.\n const [backupOverride, setBackupOverride] = useState(undefined);\n // The effective backup shown in the panel: local override → status prop.\n const backupShown = backupOverride !== undefined ? backupOverride : status?.backup ?? null;\n // O(1) lookup for the current backup model; re-built only when the effective backup changes.\n const backupModel = useMemo(() => (backupShown !== null && backupShown.provider === provider ? backupShown.model : null), [backupShown, provider]);\n const loadCandidates = async () => {\n if (provider === '')\n return;\n setLoading(true);\n setError(null);\n try {\n setCandidates(await api.listCandidates(provider));\n }\n catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause));\n }\n finally {\n setLoading(false);\n }\n };\n useEffect(() => {\n if (provider !== '')\n void loadCandidates();\n }, [provider]);\n // A fresh status from the parent supersedes the local override.\n useEffect(() => {\n setBackupOverride(undefined);\n }, [status]);\n const setBackup = async (model) => {\n setBusy(model);\n setError(null);\n try {\n await api.setBackup(provider, model);\n setBackupOverride({ provider, model });\n }\n catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause));\n }\n finally {\n setBusy(null);\n }\n };\n const clearBackup = async () => {\n setBusy('__clear__');\n setError(null);\n try {\n await api.clearBackup();\n setBackupOverride(null);\n }\n catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause));\n }\n finally {\n setBusy(null);\n }\n };\n // Stable callback so memoized CandidateRow props don't change every render.\n const handleSetBackup = useCallback((model) => void setBackup(model), [provider]);\n return (_jsx(Modal, { open: true, onClose: onClose, title: t('backupManage'), className: \"daruma-wide-dialog\", closeLabel: t('close'), description: t('backupManageHint'), footer: _jsx(Button, { variant: \"primary\", onClick: onClose, children: t('close') }), children: _jsxs(\"div\", { style: sectionStyle, children: [status !== null && status.failoverCount > 0 && (_jsxs(\"div\", { style: noteStyle, children: [t('failoverCount'), \": \", status.failoverCount, status.failoverHistory.length > 0 && (_jsxs(_Fragment, { children: [' · ', t('lastFailover'), \": \", status.failoverHistory.map((h) => `${h.from} → ${h.to}`).join(' · ')] }))] })), backupShown !== null && (_jsxs(\"div\", { style: rowStyle, children: [_jsxs(\"span\", { style: { flexShrink: 0 }, children: [t('currentBackup'), \":\"] }), _jsx(Pill, { active: true, style: backupPillStyle, title: `${backupShown.provider}/${backupShown.model}`, children: _jsxs(\"span\", { style: ellipsisStyle, children: [backupShown.provider, \"/\", backupShown.model] }) }), _jsx(Button, { size: \"sm\", variant: \"ghost\", style: { flexShrink: 0 }, disabled: busy !== null, onClick: () => void clearBackup(), children: t('clearBackup') })] })), _jsxs(\"div\", { style: rowStyle, children: [(status?.providers ?? []).length > 0 ? (_jsx(\"select\", { value: provider, disabled: loading, onChange: (event) => setProvider(event.currentTarget.value), style: { flex: 1, padding: '4px 8px', fontSize: 13 }, children: status?.providers.map((name) => (_jsx(\"option\", { value: name, children: name }, name))) })) : (_jsx(\"input\", { value: provider, placeholder: t('providerPlaceholder'), onChange: (event) => setProvider(event.currentTarget.value), style: { flex: 1, padding: '4px 8px', fontSize: 13 } })), _jsx(Button, { size: \"sm\", variant: \"outline\", onClick: () => void loadCandidates(), disabled: provider === '' || loading, children: loading ? t('loading') : t('loadCandidates') })] }), error !== null && _jsx(\"div\", { style: { color: 'var(--dsw-text-danger, #e5484d)' }, children: error }), candidates !== null && (_jsxs(_Fragment, { children: [_jsx(\"div\", { style: rowStyle, children: _jsxs(\"span\", { children: [t('candidates'), \" (\", candidates.length, \")\"] }) }), candidates.length === 0 && _jsx(\"div\", { style: noteStyle, children: t('noCandidates') }), _jsx(\"div\", { style: listStyle, children: candidates.map((candidate) => (_jsx(CandidateRow, { candidate: candidate, isBackup: candidate.model === backupModel, busy: busy !== null, t: t, onSetBackup: handleSetBackup }, candidate.model))) })] }))] }) }));\n}\n//# sourceMappingURL=BackupPanel.js.map","import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from \"react/jsx-runtime\";\n/**\n * DarumaStatus: a compact control at the right end of the composer tool row,\n * next to the model selector. Shows overall channel health and the backup\n * selection; clicking it opens the backup-channel panel.\n */\nimport { useCallback, useEffect, useState } from 'react';\nimport { Button, IconCheckOutline16, IconWarningOutline16 } from '@deepseek-ai/dsh-client-ui-primitives';\nimport { overallState } from \"./health.js\";\nimport { BackupPanel } from \"./BackupPanel.js\";\nconst controlStyle = {\n display: 'inline-flex',\n alignItems: 'center',\n gap: 6,\n maxWidth: 220,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n};\nconst iconColor = {\n done: 'var(--dsw-text-success, #30a46c)',\n warning: 'var(--dsw-text-warning, #f5a524)',\n error: 'var(--dsw-text-danger, #e5484d)',\n ongoing: 'var(--dsw-text-secondary, #888)',\n};\n/** Status glyph: a check when healthy, a warning otherwise. */\nfunction StatusIcon(props) {\n return (_jsx(\"span\", { style: { display: 'inline-flex', color: iconColor[props.state], flexShrink: 0 }, children: props.state === 'done'\n ? _jsx(IconCheckOutline16, { size: 14 })\n : _jsx(IconWarningOutline16, { size: 14 }) }));\n}\nexport function StatusDock(props) {\n const [status, setStatus] = useState(null);\n const [panelOpen, setPanelOpen] = useState(false);\n const load = useCallback(async () => {\n try {\n const value = await props.api.status();\n setStatus(value);\n }\n catch {\n // keep last good snapshot; the control stays quiet on RPC failure\n }\n }, [props.api]);\n useEffect(() => {\n void load();\n const timer = setInterval(() => void load(), 30_000);\n return () => clearInterval(timer);\n }, [load]);\n const t = props.t;\n const backupLabel = status?.backup !== null && status?.backup !== undefined\n ? `${status.backup.provider}/${status.backup.model}`\n : t('backupNone');\n return (_jsxs(_Fragment, { children: [_jsxs(Button, { size: \"sm\", variant: \"ghost\", title: t('backupManageHint'), onClick: () => setPanelOpen(true), style: controlStyle, children: [_jsx(StatusIcon, { state: overallState(status?.channels ?? null, Date.now()) }), _jsxs(\"span\", { style: { minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }, children: [t('backup'), \": \", backupLabel] })] }), panelOpen && (_jsx(BackupPanel, { api: props.api, t: t, status: status, onClose: () => {\n setPanelOpen(false);\n void load();\n } }))] }));\n}\n//# sourceMappingURL=StatusDock.js.map","/**\n * Pure failover-notice logic for the daruma web client.\n *\n * Bridges the server-appended `daruma/failover` session event into a visible\n * row inside the DSH conversation window. Host chat rendering is\n * definition-driven and out-of-repo event types are never rendered on their\n * own (the host fallback only claims append-surface events), so the client\n * registers its own conversation definition (kind {@link FAILOVER_NOTICE_KIND},\n * target `chat`) plus a keyed renderer for that kind.\n *\n * This module is framework- and DOM-free on purpose: the event contract and\n * the produced chat node are unit-testable without mounting a browser.\n */\n/** Session event type appended by the daruma server on every channel switch. */\nexport const FAILOVER_EVENT_TYPE = 'daruma/failover';\n/** Session event type appended when recovery gives up entirely. */\nexport const GIVE_UP_EVENT_TYPE = 'daruma/give-up';\n/** Chat node kind (conversation-definition kind + renderer key) used here. */\nexport const FAILOVER_NOTICE_KIND = 'daruma-failover';\n/** Display length caps mirroring the server-side event assembly. */\nconst CHANNEL_LIMIT = 80;\nconst REASON_LIMIT = 40;\nfunction isRecord(value) {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n/** Trim a payload string, clipping over-long values with an ellipsis. */\nfunction clip(value, limit) {\n if (typeof value !== 'string')\n return undefined;\n const text = value.trim();\n if (text.length === 0)\n return undefined;\n return text.length <= limit ? text : `${text.slice(0, limit)}…`;\n}\nfunction finiteNumber(value) {\n return typeof value === 'number' && Number.isFinite(value) ? value : 0;\n}\n/**\n * Defensively parse one `daruma/failover` (or `daruma/give-up`) payload into\n * display data. Returns `null` when the payload is not a usable record, so a\n * malformed event never renders (and is never claimed by this definition).\n * A `give-up` row needs only `from`; a `failover` row needs `from` and `to`.\n */\nexport function parseFailoverNotice(raw) {\n if (!isRecord(raw))\n return null;\n const kind = raw.kind === 'give-up' ? 'give-up' : 'failover';\n const from = clip(raw.from, CHANNEL_LIMIT);\n const to = clip(raw.to, CHANNEL_LIMIT);\n if (from === undefined)\n return null;\n if (kind === 'failover' && to === undefined)\n return null;\n const reason = clip(raw.reason, REASON_LIMIT) ?? 'FAILURE';\n const at = finiteNumber(raw.at);\n return {\n kind,\n from,\n to: to ?? '',\n reason,\n at: at === 0 ? Date.now() : at,\n turn: finiteNumber(raw.turn),\n step: finiteNumber(raw.step),\n count: finiteNumber(raw.failoverCount),\n budget: finiteNumber(raw.giveUpBudget),\n };\n}\n/** Replace `{key}` placeholders with matching values; unknown keys stay. */\nexport function fillTemplate(template, values) {\n return template.replace(/\\{(\\w+)\\}/g, (match, name) => name in values ? values[name] ?? '' : match);\n}\n/** Compose the row copy through the daruma locale dictionary. */\nexport function failoverNoticeCopy(data, t) {\n if (data.kind === 'give-up') {\n const line = fillTemplate(t('failoverGiveUpLine'), {\n from: data.from,\n reason: data.reason,\n });\n const detail = fillTemplate(t('failoverGiveUpDetail'), {\n count: String(data.count),\n budget: String(data.budget),\n turn: String(data.turn),\n step: String(data.step),\n });\n return { line, detail };\n }\n const line = fillTemplate(t('failoverNoticeLine'), {\n from: data.from,\n to: data.to,\n reason: data.reason,\n });\n const detail = fillTemplate(t('failoverNoticeDetail'), {\n count: String(data.count),\n budget: String(data.budget),\n turn: String(data.turn),\n step: String(data.step),\n });\n return { line, detail };\n}\n/**\n * The conversation Definition claiming `daruma/failover` and `daruma/give-up`\n * events for the chat target. One decision = one context (id = its event seq)\n * = one settled row, anchored at the event's own log position so it lands\n * inline in the flow.\n */\nexport function createFailoverNoticeDefinition() {\n const start = (_context, match) => {\n const parsed = parseFailoverNotice(match.event.data);\n if (parsed === null) {\n throw new Error(`daruma failover notice: unparseable ${FAILOVER_EVENT_TYPE} event at seq ${match.event.seq}`);\n }\n return parsed;\n };\n return {\n kind: FAILOVER_NOTICE_KIND,\n target: 'chat',\n match: (event) => {\n if (event.type !== FAILOVER_EVENT_TYPE && event.type !== GIVE_UP_EVENT_TYPE)\n return null;\n if (parseFailoverNotice(event.data) === null)\n return null;\n return { id: String(event.seq), role: 'start' };\n },\n start,\n // Every claimed event is a standalone start; keep update total for safety.\n update: (context, match) => start(context, match),\n buildViewNode: (context) => {\n const match = context.start;\n if (match === undefined)\n return null;\n const data = parseFailoverNotice(match.event.data);\n if (data === null)\n return null;\n return {\n key: context.key,\n kind: context.kind,\n id: context.id,\n target: 'chat',\n anchorSeq: match.event.seq,\n location: match.location ?? { kind: 'unresolved' },\n visibility: 'visible',\n data,\n };\n },\n };\n}\n//# sourceMappingURL=failover-notice.js.map","/**\n * FailoverNoticeRow — the daruma chat renderer for {@link FAILOVER_NOTICE_KIND}.\n *\n * A single quiet row inside the conversation flow telling the user that\n * daruma caught a failed model request and switched the channel for the\n * retry. Registered behind the host's keyed `conversation.chat.node` seat,\n * so it renders exactly like an in-repo chat row (no DOM injection).\n */\nimport { createElement as h } from 'react';\nimport { failoverNoticeCopy, parseFailoverNotice, } from \"./failover-notice.js\";\nconst rowStyle = {\n display: 'flex',\n alignItems: 'center',\n gap: '6px',\n minWidth: 0,\n padding: '2px 4px',\n fontSize: '12px',\n lineHeight: '18px',\n color: 'var(--dsw-alias-label-secondary)',\n};\nconst dotStyle = {\n width: '6px',\n height: '6px',\n borderRadius: '50%',\n flex: 'none',\n background: 'var(--dsw-static-deepseek-500)',\n};\n/** Give-up rows use the error tint instead of the brand dot. */\nconst giveUpDotStyle = {\n ...dotStyle,\n background: 'var(--dsw-alias-status-error, #e5484d)',\n};\nconst brandStyle = {\n flex: 'none',\n fontWeight: 600,\n color: 'var(--dsw-alias-label-primary)',\n};\nconst lineStyle = {\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n minWidth: 0,\n};\n/** Render one settled failover / give-up row, or nothing when unusable. */\nexport function FailoverNoticeRow({ node, t }) {\n const data = parseFailoverNotice(node.data);\n if (data === null)\n return null;\n const { line, detail } = failoverNoticeCopy(data, t);\n const title = line === detail ? detail : `${line} · ${detail}`;\n const isGiveUp = data.kind === 'give-up';\n return h('div', {\n 'data-daruma-notice': isGiveUp ? 'give-up' : 'failover',\n role: 'note',\n style: rowStyle,\n title,\n }, [\n h('span', { 'aria-hidden': true, style: isGiveUp ? giveUpDotStyle : dotStyle }),\n h('span', { style: brandStyle }, 'daruma'),\n h('span', { style: lineStyle }, line),\n ]);\n}\n//# sourceMappingURL=FailoverNoticeRow.js.map","/**\n * dsh-daruma client: registers a compact channel-status dock above the\n * composer (conversation.input.dock) with a \"backup channel\" panel that\n * lists candidate models and picks a backup. Built by tsdown into the\n * __ModuleLoader__ factory bundle at lib/client.js.\n */\nimport { createElement as h } from 'react';\nimport { en, zh } from \"./locales.js\";\nimport { createApi } from \"./api.js\";\nimport { StatusDock } from \"./StatusDock.js\";\nimport { createFailoverNoticeDefinition, FAILOVER_NOTICE_KIND, } from \"./failover-notice.js\";\nimport { FailoverNoticeRow } from \"./FailoverNoticeRow.js\";\nconst NS = 'daruma';\n/**\n * Register the live failover notice: one conversation Definition claiming\n * `daruma/failover` events for the chat target, plus the keyed renderer for\n * its node kind. Absent or failing registrations degrade to nothing visible\n * (warn only) — the panel keeps working either way.\n */\nfunction registerFailoverChatNotice(ctx) {\n const registry = ctx.get('conversationEvents');\n if (registry === undefined) {\n console.warn('[dsh-daruma] conversation event registry unavailable — failover chat rows disabled');\n }\n else {\n try {\n ctx.effect(() => registry.register(createFailoverNoticeDefinition()), 'dsh-daruma: failover notice definition');\n }\n catch (error) {\n console.warn('[dsh-daruma] failover notice definition registration failed', error);\n }\n }\n ctx.slots.inject('conversation.chat.node', () => {\n try {\n // The keyed seat instantiates entries with props (node, t, …); the\n // structural slot type is narrower than the host's real registry.\n return ctx.slots.register({\n name: 'conversation.chat.node',\n key: FAILOVER_NOTICE_KIND,\n locale: NS,\n }, FailoverNoticeRow);\n }\n catch (error) {\n console.warn('[dsh-daruma] failover notice renderer registration failed', error);\n return () => { };\n }\n });\n}\nexport const name = 'dsh-daruma';\nexport const inject = ['slots', 'locale'];\nexport function apply(ctx) {\n // Widen the backup-panel dialog: the primitives Modal card is fixed at\n // min(380px, 100%), which truncates long provider/model names. A global\n // class (not a CSS module) outranks the module-scoped `.dialog` rule.\n if (typeof document !== 'undefined') {\n const tagId = 'daruma-panel-style';\n if (document.querySelector(`style[data-daruma=\"${tagId}\"]`) === null) {\n const style = document.createElement('style');\n style.dataset.daruma = tagId;\n style.textContent = '.daruma-wide-dialog.daruma-wide-dialog { width: min(560px, 100%); }';\n document.head.appendChild(style);\n }\n }\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'dsh-daruma: dictionaries');\n const t = ctx.locale.bind(NS);\n const connection = ctx.get('connection');\n if (connection === undefined) {\n console.warn('[dsh-daruma] web transport unavailable — client UI disabled');\n return;\n }\n const rpc = (endpoint, payload) => connection.rpc.call('/dsh-daruma', endpoint, payload ?? {});\n const api = createApi(rpc);\n ctx.slots.inject('conversation.input.right', () => ctx.slots.register({\n name: 'conversation.input.right',\n id: 'daruma-status',\n order: 0,\n inject: () => ({ api, t }),\n }, () => h(StatusDock, { api, t })));\n registerFailoverChatNotice(ctx);\n}\n//# sourceMappingURL=index.js.map"],"mappings":"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"}
1
+ {"version":3,"file":"client.js","names":["rowStyle","memo","_jsxs","_jsx","Pill","Button","useState","useMemo","useCallback","Modal","_Fragment","_jsx","IconCheckOutline16","IconWarningOutline16","useState","useCallback","_jsxs","_Fragment","Button","h","h"],"sources":["client/locales.js","client/api.js","client/adaptive-rpc.js","client/health.js","client/BackupPanel.js","client/StatusDock.js","client/failover-notice.js","client/FailoverNoticeRow.js","client/index.js"],"sourcesContent":["/** zh/en dictionaries for the daruma client UI. */\nexport const zh = {\n status: '渠道状态',\n current: '当前',\n backup: '备用',\n backupNone: '未设置',\n backupManage: '备用渠道',\n backupManageHint: '从候选列表选择备用渠道',\n failoverCount: '已切换',\n lastFailover: '上次切换',\n healthy: '健康',\n cooldown: '冷却中',\n probe: '探测中',\n refresh: '刷新',\n close: '关闭',\n clearBackup: '清除备用',\n provider: '提供方',\n providerPlaceholder: 'provider,如 mt',\n loadCandidates: '加载候选',\n loading: '加载中…',\n candidates: '候选模型',\n setBackup: '设为备用',\n currentBackup: '当前备用',\n currentBackupMark: '备用',\n noCandidates: '未加载到候选模型',\n empty: '暂无渠道数据',\n failoverNoticeLine: '{from} 请求失败({reason})→ 本次尝试 {to}',\n failoverNoticeDetail: '第 {count}/{budget} 次失败切换 · turn {turn} step {step}',\n failoverGiveUpLine: '{from} 请求失败({reason})→ 已用尽恢复手段,停止重试',\n failoverGiveUpDetail: '失败切换 {count}/{budget} · turn {turn} step {step}',\n};\nexport const en = {\n status: 'Channel status',\n current: 'Current',\n backup: 'Backup',\n backupNone: 'none',\n backupManage: 'Backup channel',\n backupManageHint: 'Pick a backup channel from the candidate list',\n failoverCount: 'failovers',\n lastFailover: 'last failover',\n healthy: 'healthy',\n cooldown: 'cooling',\n probe: 'probing',\n refresh: 'Refresh',\n close: 'Close',\n clearBackup: 'Clear backup',\n provider: 'Provider',\n providerPlaceholder: 'provider, e.g. mt',\n loadCandidates: 'Load candidates',\n loading: 'Loading…',\n candidates: 'Candidate models',\n setBackup: 'Set as backup',\n currentBackup: 'Current backup',\n currentBackupMark: 'backup',\n noCandidates: 'No candidates loaded',\n empty: 'No channel data yet',\n failoverNoticeLine: '{from} failed ({reason}) → trying {to}',\n failoverNoticeDetail: 'failover {count}/{budget} · turn {turn} step {step}',\n failoverGiveUpLine: '{from} failed ({reason}) → recovery budget exhausted, giving up',\n failoverGiveUpDetail: 'failovers {count}/{budget} · turn {turn} step {step}',\n};\n//# sourceMappingURL=locales.js.map","/**\n * Client-side wire types and RPC wrapper for the `/dsh-daruma` channel.\n * Structural types only — no monorepo-internal imports.\n */\nexport function createApi(rpc) {\n const call = async (endpoint, payload) => {\n const result = (await rpc(endpoint, payload));\n if (!result.ok) {\n throw new Error(result.error?.message ?? `daruma rpc ${endpoint} failed`);\n }\n return result.value;\n };\n return {\n status: () => call('status'),\n listCandidates: (provider) => call('listCandidates', { provider }),\n setBackup: async (provider, model) => {\n await call('setBackup', { provider, model });\n },\n clearBackup: async () => {\n await call('clearBackup');\n },\n };\n}\n//# sourceMappingURL=api.js.map","/**\n * Client transport for the daruma panel.\n *\n * Primary path: the legacy generic channel (`/dsh-daruma`) — served by\n * `rpc.handle` on hosts up to 0.1.2 and on 0.1.5 hosts patched by the\n * community fix.\n *\n * Fallback path: the `/api` shared carrier (`/api/dsh-daruma` exact route,\n * registered by the host-side fallback in `src/http-transport.ts`). The\n * browser caller switches on the first HTTP 404/405 — the route-miss shape of\n * the 0.1.5 `rpc.handle` regression — and sticks with the fallback for the\n * rest of the page lifetime, so the panel needs at most one failed request\n * per load. Auth failures (401/403) and handler errors surface as-is: they\n * say nothing about which transport should be used.\n *\n * Wire shape: exact Fetch routes match by URL path segment, and the shared\n * carrier validates that the envelope `method` equals that segment — so the\n * real endpoint and payload ride inside the payload tunnel, exactly like the\n * real-plane-verified dsh-im management RPC.\n */\n/** Generic channel served by `connection.rpc.handle` where it works. */\nexport const LEGACY_CHANNEL = '/dsh-daruma';\n/** Shared browser carrier the host itself mounts on every web-capable host. */\nexport const FALLBACK_CHANNEL = '/api';\n/** Envelope method demanded by the exact `/api/dsh-daruma` route. */\nexport const FALLBACK_ENDPOINT = 'dsh-daruma';\n/**\n * Whether a rejected legacy call means \"the channel route does not exist on\n * this host\" (switch to the fallback) rather than anything else. The browser\n * caller throws `transport failure for <channel>/<endpoint>: HTTP <status>`\n * when the response is not ok.\n */\nexport function isChannelRouteMiss(error) {\n return error instanceof Error && /HTTP (404|405)\\b/u.test(error.message);\n}\nfunction tunnelCall(connection, endpoint, payload) {\n return connection.rpc.call(FALLBACK_CHANNEL, FALLBACK_ENDPOINT, {\n method: endpoint,\n payload: payload ?? {},\n });\n}\n/** Build the panel `Rpc`: legacy channel first, sticky `/api` fallback. */\nexport function createAdaptiveRpc(connection) {\n let useFallback = false;\n return (endpoint, payload) => {\n if (useFallback) {\n return tunnelCall(connection, endpoint, payload);\n }\n return connection.rpc.call(LEGACY_CHANNEL, endpoint, payload ?? {}).catch((error) => {\n if (!isChannelRouteMiss(error))\n throw error;\n useFallback = true;\n return tunnelCall(connection, endpoint, payload);\n });\n };\n}\n//# sourceMappingURL=adaptive-rpc.js.map","/**\n * Time-aware channel-health classification for the status dock.\n *\n * The adapter now records successes (inferred from `agent/pre-step`), which\n * resets a channel to HEALTHY on its first successful request. But a channel\n * that never routes again (removed from the chain, one-shot backup) keeps its\n * last persisted state forever — including a stale COOLDOWN whose deadline\n * has long passed. The dock therefore still judges by time, not by the raw\n * state field: only a channel that is *still* cooling (cooldown not yet\n * expired) counts as an error.\n */\n/**\n * Overall dock state:\n * - `error` — at least one channel is still cooling (`cooldownUntilMs > now`).\n * - `warning` — a probe is in flight (kept for parity; the adapter no longer\n * enters PROBE, but persisted legacy states may surface it).\n * - `done` — everything routable: healthy, or cooled down long enough.\n * - `ongoing` — no snapshot yet.\n */\nexport function overallState(channels, nowMs) {\n if (channels === null)\n return 'ongoing';\n if (channels.some((c) => c.state === 'COOLDOWN' && c.cooldownUntilMs > nowMs))\n return 'error';\n if (channels.some((c) => c.state === 'PROBE'))\n return 'warning';\n return 'done';\n}\n//# sourceMappingURL=health.js.map","import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from \"react/jsx-runtime\";\n/**\n * BackupChannelPanel: list candidate models for a provider and pick one as\n * the failover backup. Rendered inside a primitives Modal.\n *\n * No probing happens here anymore — the panel is a plain picker. Channel\n * health still updates from real traffic via the recovery engine.\n */\nimport { memo, useCallback, useEffect, useMemo, useState } from 'react';\nimport { Button, Modal, Pill, } from '@deepseek-ai/dsh-client-ui-primitives';\nfunction deriveProvider(status) {\n if (status === null)\n return '';\n if (status.current !== null)\n return status.current.split('::')[0] ?? '';\n if (status.backup !== null)\n return status.backup.provider;\n return status.providers[0] ?? '';\n}\nconst sectionStyle = {\n display: 'flex',\n flexDirection: 'column',\n gap: '8px',\n padding: '12px 0',\n fontSize: '13px',\n};\nconst rowStyle = {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n};\nconst noteStyle = { color: 'var(--dsw-text-tertiary, #999)', fontSize: '12px' };\n/** Clamp a long provider/model name so the row never wraps. */\nconst backupPillStyle = {\n flex: '1 1 auto',\n minWidth: 0,\n overflow: 'hidden',\n};\nconst ellipsisStyle = {\n minWidth: 0,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n};\nconst listStyle = {\n maxHeight: 300,\n overflowY: 'auto',\n display: 'flex',\n flexDirection: 'column',\n gap: 4,\n contain: 'content',\n willChange: 'scroll-position',\n overscrollBehavior: 'contain',\n};\n/** Skip rendering rows outside the viewport while scrolling. */\nconst candidateRowStyle = {\n ...rowStyle,\n contentVisibility: 'auto',\n containIntrinsicSize: '28px',\n};\n/** One candidate row, memoized so selection changes only re-render it. */\nconst CandidateRow = memo(function CandidateRow(props) {\n const { candidate, isBackup, busy, t, onSetBackup } = props;\n return (_jsxs(\"div\", { style: candidateRowStyle, children: [_jsx(\"span\", { style: { width: 14, flexShrink: 0 } }), _jsx(\"span\", { style: { flex: 1, minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }, children: candidate.model }), isBackup && _jsx(Pill, { active: true, children: t('currentBackupMark') }), _jsx(Button, { size: \"sm\", variant: \"ghost\", disabled: isBackup || busy, onClick: () => onSetBackup(candidate.model), children: t('setBackup') })] }));\n});\nexport function BackupPanel(props) {\n const { api, t, status, onClose } = props;\n const [provider, setProvider] = useState(deriveProvider(status));\n const [candidates, setCandidates] = useState(null);\n const [loading, setLoading] = useState(false);\n const [busy, setBusy] = useState(null);\n const [error, setError] = useState(null);\n // Local overlay on the status-prop backup: applied optimistically after\n // set/clear so the row reflects the change without waiting for the parent\n // to re-fetch status. Cleared whenever a fresh status arrives.\n const [backupOverride, setBackupOverride] = useState(undefined);\n // The effective backup shown in the panel: local override → status prop.\n const backupShown = backupOverride !== undefined ? backupOverride : status?.backup ?? null;\n // O(1) lookup for the current backup model; re-built only when the effective backup changes.\n const backupModel = useMemo(() => (backupShown !== null && backupShown.provider === provider ? backupShown.model : null), [backupShown, provider]);\n const loadCandidates = async () => {\n if (provider === '')\n return;\n setLoading(true);\n setError(null);\n try {\n setCandidates(await api.listCandidates(provider));\n }\n catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause));\n }\n finally {\n setLoading(false);\n }\n };\n useEffect(() => {\n if (provider !== '')\n void loadCandidates();\n }, [provider]);\n // A fresh status from the parent supersedes the local override.\n useEffect(() => {\n setBackupOverride(undefined);\n }, [status]);\n const setBackup = async (model) => {\n setBusy(model);\n setError(null);\n try {\n await api.setBackup(provider, model);\n setBackupOverride({ provider, model });\n }\n catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause));\n }\n finally {\n setBusy(null);\n }\n };\n const clearBackup = async () => {\n setBusy('__clear__');\n setError(null);\n try {\n await api.clearBackup();\n setBackupOverride(null);\n }\n catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause));\n }\n finally {\n setBusy(null);\n }\n };\n // Stable callback so memoized CandidateRow props don't change every render.\n const handleSetBackup = useCallback((model) => void setBackup(model), [provider]);\n return (_jsx(Modal, { open: true, onClose: onClose, title: t('backupManage'), className: \"daruma-wide-dialog\", closeLabel: t('close'), description: t('backupManageHint'), footer: _jsx(Button, { variant: \"primary\", onClick: onClose, children: t('close') }), children: _jsxs(\"div\", { style: sectionStyle, children: [status !== null && status.failoverCount > 0 && (_jsxs(\"div\", { style: noteStyle, children: [t('failoverCount'), \": \", status.failoverCount, status.failoverHistory.length > 0 && (_jsxs(_Fragment, { children: [' · ', t('lastFailover'), \": \", status.failoverHistory.map((h) => `${h.from} → ${h.to}`).join(' · ')] }))] })), backupShown !== null && (_jsxs(\"div\", { style: rowStyle, children: [_jsxs(\"span\", { style: { flexShrink: 0 }, children: [t('currentBackup'), \":\"] }), _jsx(Pill, { active: true, style: backupPillStyle, title: `${backupShown.provider}/${backupShown.model}`, children: _jsxs(\"span\", { style: ellipsisStyle, children: [backupShown.provider, \"/\", backupShown.model] }) }), _jsx(Button, { size: \"sm\", variant: \"ghost\", style: { flexShrink: 0 }, disabled: busy !== null, onClick: () => void clearBackup(), children: t('clearBackup') })] })), _jsxs(\"div\", { style: rowStyle, children: [(status?.providers ?? []).length > 0 ? (_jsx(\"select\", { value: provider, disabled: loading, onChange: (event) => setProvider(event.currentTarget.value), style: { flex: 1, padding: '4px 8px', fontSize: 13 }, children: status?.providers.map((name) => (_jsx(\"option\", { value: name, children: name }, name))) })) : (_jsx(\"input\", { value: provider, placeholder: t('providerPlaceholder'), onChange: (event) => setProvider(event.currentTarget.value), style: { flex: 1, padding: '4px 8px', fontSize: 13 } })), _jsx(Button, { size: \"sm\", variant: \"outline\", onClick: () => void loadCandidates(), disabled: provider === '' || loading, children: loading ? t('loading') : t('loadCandidates') })] }), error !== null && _jsx(\"div\", { style: { color: 'var(--dsw-text-danger, #e5484d)' }, children: error }), candidates !== null && (_jsxs(_Fragment, { children: [_jsx(\"div\", { style: rowStyle, children: _jsxs(\"span\", { children: [t('candidates'), \" (\", candidates.length, \")\"] }) }), candidates.length === 0 && _jsx(\"div\", { style: noteStyle, children: t('noCandidates') }), _jsx(\"div\", { style: listStyle, children: candidates.map((candidate) => (_jsx(CandidateRow, { candidate: candidate, isBackup: candidate.model === backupModel, busy: busy !== null, t: t, onSetBackup: handleSetBackup }, candidate.model))) })] }))] }) }));\n}\n//# sourceMappingURL=BackupPanel.js.map","import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from \"react/jsx-runtime\";\n/**\n * DarumaStatus: a compact control at the right end of the composer tool row,\n * next to the model selector. Shows overall channel health and the backup\n * selection; clicking it opens the backup-channel panel.\n */\nimport { useCallback, useEffect, useState } from 'react';\nimport { Button, IconCheckOutline16, IconWarningOutline16 } from '@deepseek-ai/dsh-client-ui-primitives';\nimport { overallState } from \"./health.js\";\nimport { BackupPanel } from \"./BackupPanel.js\";\nconst controlStyle = {\n display: 'inline-flex',\n alignItems: 'center',\n gap: 6,\n maxWidth: 220,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n};\nconst iconColor = {\n done: 'var(--dsw-text-success, #30a46c)',\n warning: 'var(--dsw-text-warning, #f5a524)',\n error: 'var(--dsw-text-danger, #e5484d)',\n ongoing: 'var(--dsw-text-secondary, #888)',\n};\n/** Status glyph: a check when healthy, a warning otherwise. */\nfunction StatusIcon(props) {\n return (_jsx(\"span\", { style: { display: 'inline-flex', color: iconColor[props.state], flexShrink: 0 }, children: props.state === 'done'\n ? _jsx(IconCheckOutline16, { size: 14 })\n : _jsx(IconWarningOutline16, { size: 14 }) }));\n}\nexport function StatusDock(props) {\n const [status, setStatus] = useState(null);\n const [panelOpen, setPanelOpen] = useState(false);\n const load = useCallback(async () => {\n try {\n const value = await props.api.status();\n setStatus(value);\n }\n catch {\n // keep last good snapshot; the control stays quiet on RPC failure\n }\n }, [props.api]);\n useEffect(() => {\n void load();\n const timer = setInterval(() => void load(), 30_000);\n return () => clearInterval(timer);\n }, [load]);\n const t = props.t;\n const backupLabel = status?.backup !== null && status?.backup !== undefined\n ? `${status.backup.provider}/${status.backup.model}`\n : t('backupNone');\n return (_jsxs(_Fragment, { children: [_jsxs(Button, { size: \"sm\", variant: \"ghost\", title: t('backupManageHint'), onClick: () => setPanelOpen(true), style: controlStyle, children: [_jsx(StatusIcon, { state: overallState(status?.channels ?? null, Date.now()) }), _jsxs(\"span\", { style: { minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }, children: [t('backup'), \": \", backupLabel] })] }), panelOpen && (_jsx(BackupPanel, { api: props.api, t: t, status: status, onClose: () => {\n setPanelOpen(false);\n void load();\n } }))] }));\n}\n//# sourceMappingURL=StatusDock.js.map","/**\n * Pure failover-notice logic for the daruma web client.\n *\n * Bridges the server-appended `daruma/failover` session event into a visible\n * row inside the DSH conversation window. Host chat rendering is\n * definition-driven and out-of-repo event types are never rendered on their\n * own (the host fallback only claims append-surface events), so the client\n * registers its own conversation definition (kind {@link FAILOVER_NOTICE_KIND},\n * target `chat`) plus a keyed renderer for that kind.\n *\n * This module is framework- and DOM-free on purpose: the event contract and\n * the produced chat node are unit-testable without mounting a browser.\n */\n/** Session event type appended by the daruma server on every channel switch. */\nexport const FAILOVER_EVENT_TYPE = 'daruma/failover';\n/** Session event type appended when recovery gives up entirely. */\nexport const GIVE_UP_EVENT_TYPE = 'daruma/give-up';\n/** Chat node kind (conversation-definition kind + renderer key) used here. */\nexport const FAILOVER_NOTICE_KIND = 'daruma-failover';\n/** Display length caps mirroring the server-side event assembly. */\nconst CHANNEL_LIMIT = 80;\nconst REASON_LIMIT = 40;\nfunction isRecord(value) {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n/** Trim a payload string, clipping over-long values with an ellipsis. */\nfunction clip(value, limit) {\n if (typeof value !== 'string')\n return undefined;\n const text = value.trim();\n if (text.length === 0)\n return undefined;\n return text.length <= limit ? text : `${text.slice(0, limit)}…`;\n}\nfunction finiteNumber(value) {\n return typeof value === 'number' && Number.isFinite(value) ? value : 0;\n}\n/**\n * Defensively parse one `daruma/failover` (or `daruma/give-up`) payload into\n * display data. Returns `null` when the payload is not a usable record, so a\n * malformed event never renders (and is never claimed by this definition).\n * A `give-up` row needs only `from`; a `failover` row needs `from` and `to`.\n */\nexport function parseFailoverNotice(raw) {\n if (!isRecord(raw))\n return null;\n const kind = raw.kind === 'give-up' ? 'give-up' : 'failover';\n const from = clip(raw.from, CHANNEL_LIMIT);\n const to = clip(raw.to, CHANNEL_LIMIT);\n if (from === undefined)\n return null;\n if (kind === 'failover' && to === undefined)\n return null;\n const reason = clip(raw.reason, REASON_LIMIT) ?? 'FAILURE';\n const at = finiteNumber(raw.at);\n return {\n kind,\n from,\n to: to ?? '',\n reason,\n at: at === 0 ? Date.now() : at,\n turn: finiteNumber(raw.turn),\n step: finiteNumber(raw.step),\n count: finiteNumber(raw.failoverCount),\n budget: finiteNumber(raw.giveUpBudget),\n };\n}\n/** Replace `{key}` placeholders with matching values; unknown keys stay. */\nexport function fillTemplate(template, values) {\n return template.replace(/\\{(\\w+)\\}/g, (match, name) => name in values ? values[name] ?? '' : match);\n}\n/** Compose the row copy through the daruma locale dictionary. */\nexport function failoverNoticeCopy(data, t) {\n if (data.kind === 'give-up') {\n const line = fillTemplate(t('failoverGiveUpLine'), {\n from: data.from,\n reason: data.reason,\n });\n const detail = fillTemplate(t('failoverGiveUpDetail'), {\n count: String(data.count),\n budget: String(data.budget),\n turn: String(data.turn),\n step: String(data.step),\n });\n return { line, detail };\n }\n const line = fillTemplate(t('failoverNoticeLine'), {\n from: data.from,\n to: data.to,\n reason: data.reason,\n });\n const detail = fillTemplate(t('failoverNoticeDetail'), {\n count: String(data.count),\n budget: String(data.budget),\n turn: String(data.turn),\n step: String(data.step),\n });\n return { line, detail };\n}\n/**\n * The conversation Definition claiming `daruma/failover` and `daruma/give-up`\n * events for the chat target. One decision = one context (id = its event seq)\n * = one settled row, anchored at the event's own log position so it lands\n * inline in the flow.\n */\nexport function createFailoverNoticeDefinition() {\n const start = (_context, match) => {\n const parsed = parseFailoverNotice(match.event.data);\n if (parsed === null) {\n throw new Error(`daruma failover notice: unparseable ${FAILOVER_EVENT_TYPE} event at seq ${match.event.seq}`);\n }\n return parsed;\n };\n return {\n kind: FAILOVER_NOTICE_KIND,\n target: 'chat',\n match: (event) => {\n if (event.type !== FAILOVER_EVENT_TYPE && event.type !== GIVE_UP_EVENT_TYPE)\n return null;\n if (parseFailoverNotice(event.data) === null)\n return null;\n return { id: String(event.seq), role: 'start' };\n },\n start,\n // Every claimed event is a standalone start; keep update total for safety.\n update: (context, match) => start(context, match),\n buildViewNode: (context) => {\n const match = context.start;\n if (match === undefined)\n return null;\n const data = parseFailoverNotice(match.event.data);\n if (data === null)\n return null;\n return {\n key: context.key,\n kind: context.kind,\n id: context.id,\n target: 'chat',\n anchorSeq: match.event.seq,\n location: match.location ?? { kind: 'unresolved' },\n visibility: 'visible',\n data,\n };\n },\n };\n}\n//# sourceMappingURL=failover-notice.js.map","/**\n * FailoverNoticeRow — the daruma chat renderer for {@link FAILOVER_NOTICE_KIND}.\n *\n * A single quiet row inside the conversation flow telling the user that\n * daruma caught a failed model request and switched the channel for the\n * retry. Registered behind the host's keyed `conversation.chat.node` seat,\n * so it renders exactly like an in-repo chat row (no DOM injection).\n */\nimport { createElement as h } from 'react';\nimport { failoverNoticeCopy, parseFailoverNotice, } from \"./failover-notice.js\";\nconst rowStyle = {\n display: 'flex',\n alignItems: 'center',\n gap: '6px',\n minWidth: 0,\n padding: '2px 4px',\n fontSize: '12px',\n lineHeight: '18px',\n color: 'var(--dsw-alias-label-secondary)',\n};\nconst dotStyle = {\n width: '6px',\n height: '6px',\n borderRadius: '50%',\n flex: 'none',\n background: 'var(--dsw-static-deepseek-500)',\n};\n/** Give-up rows use the error tint instead of the brand dot. */\nconst giveUpDotStyle = {\n ...dotStyle,\n background: 'var(--dsw-alias-status-error, #e5484d)',\n};\nconst brandStyle = {\n flex: 'none',\n fontWeight: 600,\n color: 'var(--dsw-alias-label-primary)',\n};\nconst lineStyle = {\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n minWidth: 0,\n};\n/** Render one settled failover / give-up row, or nothing when unusable. */\nexport function FailoverNoticeRow({ node, t }) {\n const data = parseFailoverNotice(node.data);\n if (data === null)\n return null;\n const { line, detail } = failoverNoticeCopy(data, t);\n const title = line === detail ? detail : `${line} · ${detail}`;\n const isGiveUp = data.kind === 'give-up';\n return h('div', {\n 'data-daruma-notice': isGiveUp ? 'give-up' : 'failover',\n role: 'note',\n style: rowStyle,\n title,\n }, [\n h('span', { 'aria-hidden': true, style: isGiveUp ? giveUpDotStyle : dotStyle }),\n h('span', { style: brandStyle }, 'daruma'),\n h('span', { style: lineStyle }, line),\n ]);\n}\n//# sourceMappingURL=FailoverNoticeRow.js.map","/**\n * dsh-daruma client: registers a compact channel-status dock above the\n * composer (conversation.input.dock) with a \"backup channel\" panel that\n * lists candidate models and picks a backup. Built by tsdown into the\n * __ModuleLoader__ factory bundle at lib/client.js.\n */\nimport { createElement as h } from 'react';\nimport { en, zh } from \"./locales.js\";\nimport { createApi } from \"./api.js\";\nimport { createAdaptiveRpc } from \"./adaptive-rpc.js\";\nimport { StatusDock } from \"./StatusDock.js\";\nimport { createFailoverNoticeDefinition, FAILOVER_NOTICE_KIND, } from \"./failover-notice.js\";\nimport { FailoverNoticeRow } from \"./FailoverNoticeRow.js\";\nconst NS = 'daruma';\n/**\n * Register the live failover notice: one conversation Definition claiming\n * `daruma/failover` events for the chat target, plus the keyed renderer for\n * its node kind. Absent or failing registrations degrade to nothing visible\n * (warn only) — the panel keeps working either way.\n */\nfunction registerFailoverChatNotice(ctx) {\n const registry = ctx.get('conversationEvents');\n if (registry === undefined) {\n console.warn('[dsh-daruma] conversation event registry unavailable — failover chat rows disabled');\n }\n else {\n try {\n ctx.effect(() => registry.register(createFailoverNoticeDefinition()), 'dsh-daruma: failover notice definition');\n }\n catch (error) {\n console.warn('[dsh-daruma] failover notice definition registration failed', error);\n }\n }\n ctx.slots.inject('conversation.chat.node', () => {\n try {\n // The keyed seat instantiates entries with props (node, t, …); the\n // structural slot type is narrower than the host's real registry.\n return ctx.slots.register({\n name: 'conversation.chat.node',\n key: FAILOVER_NOTICE_KIND,\n locale: NS,\n }, FailoverNoticeRow);\n }\n catch (error) {\n console.warn('[dsh-daruma] failover notice renderer registration failed', error);\n return () => { };\n }\n });\n}\nexport const name = 'dsh-daruma';\nexport const inject = ['slots', 'locale'];\nexport function apply(ctx) {\n // Widen the backup-panel dialog: the primitives Modal card is fixed at\n // min(380px, 100%), which truncates long provider/model names. A global\n // class (not a CSS module) outranks the module-scoped `.dialog` rule.\n if (typeof document !== 'undefined') {\n const tagId = 'daruma-panel-style';\n if (document.querySelector(`style[data-daruma=\"${tagId}\"]`) === null) {\n const style = document.createElement('style');\n style.dataset.daruma = tagId;\n style.textContent = '.daruma-wide-dialog.daruma-wide-dialog { width: min(560px, 100%); }';\n document.head.appendChild(style);\n }\n }\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'dsh-daruma: dictionaries');\n const t = ctx.locale.bind(NS);\n const connection = ctx.get('connection');\n if (connection === undefined) {\n console.warn('[dsh-daruma] web transport unavailable — client UI disabled');\n return;\n }\n const rpc = createAdaptiveRpc(connection);\n const api = createApi(rpc);\n ctx.slots.inject('conversation.input.right', () => ctx.slots.register({\n name: 'conversation.input.right',\n id: 'daruma-status',\n order: 0,\n inject: () => ({ api, t }),\n }, () => h(StatusDock, { api, t })));\n registerFailoverChatNotice(ctx);\n}\n//# sourceMappingURL=index.js.map"],"mappings":"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"}
package/lib/config.d.ts CHANGED
@@ -11,6 +11,7 @@ export interface PluginConfig {
11
11
  readonly failureBudget?: number;
12
12
  readonly cooldownMs?: number;
13
13
  readonly giveUpBudget?: number;
14
+ readonly tripOnRetryExhausted?: boolean;
14
15
  readonly stateFile?: string;
15
16
  readonly logFile?: string;
16
17
  }
package/lib/config.js CHANGED
@@ -55,6 +55,9 @@ export function resolveConfig(raw = {}) {
55
55
  const failureBudget = positiveInteger(raw.failureBudget, 3, 'failureBudget');
56
56
  const cooldownMs = positiveInteger(raw.cooldownMs, 30_000, 'cooldownMs');
57
57
  const giveUpBudget = positiveInteger(raw.giveUpBudget, 8, 'giveUpBudget');
58
+ if (raw.tripOnRetryExhausted !== undefined && typeof raw.tripOnRetryExhausted !== 'boolean') {
59
+ throw new Error('invalid tripOnRetryExhausted: expected a boolean');
60
+ }
58
61
  if (raw.stateFile !== undefined && (typeof raw.stateFile !== 'string' || raw.stateFile.trim() === '')) {
59
62
  throw new Error('invalid stateFile: expected a non-empty string');
60
63
  }
@@ -67,6 +70,9 @@ export function resolveConfig(raw = {}) {
67
70
  failureBudget,
68
71
  cooldownMs,
69
72
  giveUpBudget,
73
+ // Default on: see `RecoveryPolicyConfig.tripOnRetryExhausted`. Only an
74
+ // explicit `false` restores counting a spent retry budget as one failure.
75
+ tripOnRetryExhausted: raw.tripOnRetryExhausted ?? true,
70
76
  stateFile,
71
77
  logFile: raw.logFile || defaultLogFile(stateFile),
72
78
  };
package/lib/config.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -25,6 +25,12 @@ export type FailoverLogRecord = {
25
25
  readonly to: string;
26
26
  /** Stable failure code, e.g. `RATE_LIMIT`. */
27
27
  readonly reason: string;
28
+ /**
29
+ * Present when the switch was escalated by an already-exhausted same-channel
30
+ * retry budget rather than by the failure counter. Absent means the ordinary
31
+ * path, so older lines stay readable.
32
+ */
33
+ readonly retryExhausted?: boolean;
28
34
  /** HTTP status of the failed request, when available. */
29
35
  readonly status?: number;
30
36
  /** Turn / step of the failed request. */
@@ -1 +1 @@
1
- {"version":3,"file":"failover-log.js","sourceRoot":"","sources":["../src/failover-log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AACzE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAEnC,2EAA2E;AAC3E,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAA;AAmDxD,MAAM,OAAO,qBAAqB;IACH;IAA7B,YAA6B,IAAY;QAAZ,SAAI,GAAJ,IAAI,CAAQ;IAAG,CAAC;IAE7C,sEAAsE;IACtE,MAAM,CAAC,MAAyB;QAC9B,IAAI,CAAC;YACH,IAAI,CAAC,cAAc,EAAE,CAAA;YACrB,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;YAClD,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QAClE,CAAC;QAAC,MAAM,CAAC;YACP,iDAAiD;QACnD,CAAC;IACH,CAAC;IAEO,cAAc;QACpB,IAAI,CAAC;YACH,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,yBAAyB;gBAAE,OAAM;YAChE,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,CAAA;QACzC,CAAC;QAAC,MAAM,CAAC;YACP,mEAAmE;YACnE,gCAAgC;QAClC,CAAC;IACH,CAAC;CACF"}
1
+ {"version":3,"file":"failover-log.js","sourceRoot":"","sources":["../src/failover-log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AACzE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAEnC,2EAA2E;AAC3E,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAA;AAyDxD,MAAM,OAAO,qBAAqB;IACH;IAA7B,YAA6B,IAAY;QAAZ,SAAI,GAAJ,IAAI,CAAQ;IAAG,CAAC;IAE7C,sEAAsE;IACtE,MAAM,CAAC,MAAyB;QAC9B,IAAI,CAAC;YACH,IAAI,CAAC,cAAc,EAAE,CAAA;YACrB,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;YAClD,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QAClE,CAAC;QAAC,MAAM,CAAC;YACP,iDAAiD;QACnD,CAAC;IACH,CAAC;IAEO,cAAc;QACpB,IAAI,CAAC;YACH,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,yBAAyB;gBAAE,OAAM;YAChE,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,CAAA;QACzC,CAAC;QAAC,MAAM,CAAC;YACP,mEAAmE;YACnE,gCAAgC;QAClC,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * `/api/dsh-daruma` Fetch-route fallback for hosts whose generic channel
3
+ * RPC registry is broken (`0.1.5-alpha.1` … `0.1.5-rc.2` dropped `webServer`
4
+ * from the connection plugin's own inject list, so every
5
+ * `connection.rpc.handle()` caller throws `cannot get property "webServer"
6
+ * without inject`).
7
+ *
8
+ * The fallback registers an exact Fetch route through
9
+ * `connection.fetch.register`, whose registration path never touches the web
10
+ * server context: the host itself mounts the shared `/api` carrier inside its
11
+ * own `ctx.inject(['webServer'], …)` scope and applies the Host/Origin fence
12
+ * plus browser authentication before any `/api/*` handler runs. The handler
13
+ * below adds a loopback authority guard (defense in depth) and speaks the
14
+ * same `client-request` / `server-response` envelope as the built-in channel
15
+ * transport, so the browser caller keeps using `connection.rpc.call`.
16
+ *
17
+ * Wire shape verified against `@deepseek-ai/dsh-client-connection@0.1.5-*`
18
+ * (`rpcFetchHandler` / `endpointFromPath` / browser `parseConnectionResponse`)
19
+ * and against the real-plane-verified dsh-im management RPC.
20
+ */
21
+ import type { RpcResult } from './rpc.ts';
22
+ /** The exact Fetch route used by the fallback transport. */
23
+ export declare const HTTP_FALLBACK_CHANNEL = "/api/dsh-daruma";
24
+ /** Structural shape of the host connection's exact Fetch registry. */
25
+ export interface FetchRegisterConnection {
26
+ fetch: {
27
+ register(route: {
28
+ path: string;
29
+ methods: readonly string[];
30
+ requestBody: 'buffered';
31
+ fetch(request: unknown): Promise<unknown>;
32
+ }): unknown;
33
+ };
34
+ }
35
+ /** The dispatch contract shared with the legacy channel (`src/rpc.ts`). */
36
+ export type RpcDispatch = (endpoint: string, payload: unknown, signal: AbortSignal) => Promise<RpcResult>;
37
+ /** Errors thrown by the known host regression — the only fallback trigger. */
38
+ export declare function isBrokenRpcHandleError(error: unknown): boolean;
39
+ /** Structural request surface used by the loopback guard. */
40
+ interface GuardedRequest {
41
+ headers: {
42
+ get(name: string): string | null;
43
+ };
44
+ }
45
+ /**
46
+ * Loopback-only guard mirroring the host's own request fence semantics: the
47
+ * request must target a loopback authority, and an explicit `Origin` (browser
48
+ * cross-frame scenarios) must also be loopback. The host already applied its
49
+ * Host/Origin trust fence and browser authentication before this handler;
50
+ * this is defense in depth, not the primary gate.
51
+ */
52
+ export declare function isLoopbackRequest(request: GuardedRequest): boolean;
53
+ /** The connection surface pieces the fallback needs. */
54
+ export declare function hasFetchRegistry(connection: unknown): connection is FetchRegisterConnection;
55
+ /**
56
+ * Register the fallback route. Returns `true` when the route is mounted (the
57
+ * disposer is tied to a context effect), `false` when the host lacks the
58
+ * registry or refuses the registration — the caller decides how loudly to
59
+ * fail in that case.
60
+ */
61
+ export declare function mountHttpFallback(ctx: {
62
+ effect(callback: () => unknown, label?: string): void;
63
+ logger: {
64
+ info(message: string): void;
65
+ warn(message: string): void;
66
+ };
67
+ }, connection: unknown, dispatch: RpcDispatch): boolean;
68
+ export {};
@@ -0,0 +1,173 @@
1
+ /**
2
+ * `/api/dsh-daruma` Fetch-route fallback for hosts whose generic channel
3
+ * RPC registry is broken (`0.1.5-alpha.1` … `0.1.5-rc.2` dropped `webServer`
4
+ * from the connection plugin's own inject list, so every
5
+ * `connection.rpc.handle()` caller throws `cannot get property "webServer"
6
+ * without inject`).
7
+ *
8
+ * The fallback registers an exact Fetch route through
9
+ * `connection.fetch.register`, whose registration path never touches the web
10
+ * server context: the host itself mounts the shared `/api` carrier inside its
11
+ * own `ctx.inject(['webServer'], …)` scope and applies the Host/Origin fence
12
+ * plus browser authentication before any `/api/*` handler runs. The handler
13
+ * below adds a loopback authority guard (defense in depth) and speaks the
14
+ * same `client-request` / `server-response` envelope as the built-in channel
15
+ * transport, so the browser caller keeps using `connection.rpc.call`.
16
+ *
17
+ * Wire shape verified against `@deepseek-ai/dsh-client-connection@0.1.5-*`
18
+ * (`rpcFetchHandler` / `endpointFromPath` / browser `parseConnectionResponse`)
19
+ * and against the real-plane-verified dsh-im management RPC.
20
+ */
21
+ /** The exact Fetch route used by the fallback transport. */
22
+ export const HTTP_FALLBACK_CHANNEL = '/api/dsh-daruma';
23
+ /** Endpoint segment the host derives from the fallback route path. */
24
+ const FALLBACK_ENDPOINT = 'dsh-daruma';
25
+ /** Errors thrown by the known host regression — the only fallback trigger. */
26
+ export function isBrokenRpcHandleError(error) {
27
+ const message = error instanceof Error ? error.message : String(error);
28
+ return message.includes('webServer') && message.includes('without inject');
29
+ }
30
+ function isLoopbackAuthority(authority) {
31
+ if (authority === null || authority === undefined || authority === '')
32
+ return false;
33
+ let hostname;
34
+ try {
35
+ const url = new URL(`http://${authority}`);
36
+ if (url.username !== '' || url.password !== '' || url.pathname !== '/'
37
+ || url.search !== '' || url.hash !== '')
38
+ return false;
39
+ hostname = url.hostname.replace(/\.$/u, '');
40
+ }
41
+ catch {
42
+ return false;
43
+ }
44
+ if (hostname === 'localhost' || hostname === '[::1]')
45
+ return true;
46
+ const parts = hostname.split('.');
47
+ return parts.length === 4 && parts[0] === '127'
48
+ && parts.slice(1).every((part) => /^\d{1,3}$/u.test(part) && Number(part) <= 255);
49
+ }
50
+ /**
51
+ * Loopback-only guard mirroring the host's own request fence semantics: the
52
+ * request must target a loopback authority, and an explicit `Origin` (browser
53
+ * cross-frame scenarios) must also be loopback. The host already applied its
54
+ * Host/Origin trust fence and browser authentication before this handler;
55
+ * this is defense in depth, not the primary gate.
56
+ */
57
+ export function isLoopbackRequest(request) {
58
+ if (!isLoopbackAuthority(request.headers.get('host')))
59
+ return false;
60
+ const origin = request.headers.get('origin');
61
+ if (origin === null)
62
+ return true;
63
+ try {
64
+ const url = new URL(origin);
65
+ return (url.protocol === 'http:' || url.protocol === 'https:')
66
+ && isLoopbackAuthority(url.host);
67
+ }
68
+ catch {
69
+ return false;
70
+ }
71
+ }
72
+ /** The connection surface pieces the fallback needs. */
73
+ export function hasFetchRegistry(connection) {
74
+ const candidate = connection;
75
+ return candidate !== undefined
76
+ && typeof candidate.fetch?.register === 'function';
77
+ }
78
+ function isRecord(value) {
79
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
80
+ }
81
+ function parseClientRequest(raw) {
82
+ if (!isRecord(raw))
83
+ return undefined;
84
+ const message = raw;
85
+ if (message.type !== 'client-request')
86
+ return undefined;
87
+ if (typeof message.rpcId !== 'string')
88
+ return undefined;
89
+ if (message.method !== FALLBACK_ENDPOINT)
90
+ return undefined;
91
+ // Same shape the host transport forwards: { method, payload } call tuple.
92
+ if (!isRecord(message.payload) || typeof message.payload.method !== 'string'
93
+ || !Object.hasOwn(message.payload, 'payload'))
94
+ return undefined;
95
+ return message;
96
+ }
97
+ /**
98
+ * Register the fallback route. Returns `true` when the route is mounted (the
99
+ * disposer is tied to a context effect), `false` when the host lacks the
100
+ * registry or refuses the registration — the caller decides how loudly to
101
+ * fail in that case.
102
+ */
103
+ export function mountHttpFallback(ctx, connection, dispatch) {
104
+ if (!hasFetchRegistry(connection))
105
+ return false;
106
+ try {
107
+ const dispose = connection.fetch.register({
108
+ path: HTTP_FALLBACK_CHANNEL,
109
+ methods: ['POST'],
110
+ requestBody: 'buffered',
111
+ async fetch(request) {
112
+ return handleFallbackRequest(request, dispatch);
113
+ },
114
+ });
115
+ ctx.effect(() => dispose, 'dsh-daruma: /api/dsh-daruma fetch fallback route');
116
+ ctx.logger.info('dsh-daruma: generic channel RPC unavailable on this host; '
117
+ + `panel mounted through the ${HTTP_FALLBACK_CHANNEL} carrier`);
118
+ return true;
119
+ }
120
+ catch {
121
+ return false;
122
+ }
123
+ }
124
+ async function handleFallbackRequest(request, dispatch) {
125
+ const req = request;
126
+ if (!isLoopbackRequest(req))
127
+ return new Response('forbidden', { status: 403 });
128
+ const contentType = req.headers.get('content-type')?.split(';', 1)[0]?.trim().toLowerCase();
129
+ if (contentType !== 'application/json') {
130
+ return new Response('content type must be application/json', { status: 415 });
131
+ }
132
+ let raw;
133
+ try {
134
+ raw = await req.json();
135
+ }
136
+ catch {
137
+ return new Response('body is not JSON', { status: 400 });
138
+ }
139
+ const message = parseClientRequest(raw);
140
+ if (message === undefined) {
141
+ return envelopeResponse(typeof raw?.rpcId === 'string'
142
+ ? raw.rpcId
143
+ : 'invalid-request', {
144
+ ok: false,
145
+ error: { code: 'bad-request', message: 'invalid daruma request', details: {} },
146
+ });
147
+ }
148
+ const call = message.payload;
149
+ let result;
150
+ try {
151
+ result = await dispatch(call.method, call.payload, req.signal);
152
+ }
153
+ catch (error) {
154
+ result = {
155
+ ok: false,
156
+ error: {
157
+ code: 'internal',
158
+ message: error instanceof Error ? error.message : String(error),
159
+ },
160
+ };
161
+ }
162
+ // The browser response validator requires `details` on failures —
163
+ // normalize before hitting the wire so panel error paths render. A dispatch
164
+ // that already set one keeps its value.
165
+ const normalized = result.ok
166
+ ? result
167
+ : { ok: false, error: { ...result.error, details: result.error.details ?? {} } };
168
+ return envelopeResponse(message.rpcId, normalized);
169
+ }
170
+ function envelopeResponse(rpcId, result) {
171
+ return Response.json({ type: 'server-response', rpcId, result });
172
+ }
173
+ //# sourceMappingURL=http-transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-transport.js","sourceRoot":"","sources":["../src/http-transport.ts"],"names":[],"mappings":"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"}
package/lib/index.d.ts CHANGED
@@ -12,6 +12,10 @@
12
12
  * owns same-channel retry and delegates here (via `next()`) when it gives up,
13
13
  * so daruma only escalates after retry has exhausted its budget.
14
14
  *
15
+ * That position is also read as evidence: a failure retry already spent its
16
+ * budget on arrives as `retryExhausted` and opens the circuit on the first one,
17
+ * instead of waiting for `failureBudget` failing turns (see `isRetryExhausted`).
18
+ *
15
19
  * Additionally mounts the `/dsh-daruma` RPC channel (status, candidate
16
20
  * discovery, backup selection) for the web client UI, and appends a durable
17
21
  * `daruma/failover` session event on every channel switch.
package/lib/index.js CHANGED
@@ -12,11 +12,15 @@
12
12
  * owns same-channel retry and delegates here (via `next()`) when it gives up,
13
13
  * so daruma only escalates after retry has exhausted its budget.
14
14
  *
15
+ * That position is also read as evidence: a failure retry already spent its
16
+ * budget on arrives as `retryExhausted` and opens the circuit on the first one,
17
+ * instead of waiting for `failureBudget` failing turns (see `isRetryExhausted`).
18
+ *
15
19
  * Additionally mounts the `/dsh-daruma` RPC channel (status, candidate
16
20
  * discovery, backup selection) for the web client UI, and appends a durable
17
21
  * `daruma/failover` session event on every channel switch.
18
22
  */
19
- import { channelIdOf, channelIdOfConfig, toFailoverConfig, toFailureSignal } from "./mapping.js";
23
+ import { channelIdOf, channelIdOfConfig, isRetryExhausted, toFailoverConfig, toFailureSignal, } from "./mapping.js";
20
24
  import { resolveConfig } from "./config.js";
21
25
  import { RecoveryEngine } from "./engine.js";
22
26
  import { JsonFileChannelHealthStore } from "./store.js";
@@ -104,7 +108,10 @@ export function apply(ctx, rawConfig = {}) {
104
108
  ctx.on('agent/request-error', async (payload, next) => {
105
109
  failedSinceRequest.add(payload.agent.id);
106
110
  const channel = currentChannel.get(payload.agent.id) ?? channelIdOf(payload.provider, '');
107
- const signal = toFailureSignal(payload.failure, channel, Date.now());
111
+ // Reaching this listener already means the in-box retry declined the code;
112
+ // for a code its own policy calls retryable, that is a spent budget rather
113
+ // than a single attempt.
114
+ const signal = toFailureSignal(payload.failure, channel, Date.now(), isRetryExhausted(payload.failure.code, payload.retryPolicy));
108
115
  const plan = engine.onFailure(signal, backupChannel(), payload.agent.id);
109
116
  if (plan.verdict.kind === 'FAILOVER') {
110
117
  pending.set(payload.agent.id, plan.verdict.target);
@@ -129,6 +136,8 @@ export function apply(ctx, rawConfig = {}) {
129
136
  to: plan.verdict.target.id,
130
137
  reason: signal.code,
131
138
  status: payload.failure.status,
139
+ // Audit trail for *why now*: an escalated switch is not a counted one.
140
+ ...(signal.retryExhausted === true ? { retryExhausted: true } : {}),
132
141
  turn: payload.turn,
133
142
  step: payload.step,
134
143
  failoverCount: plan.failoverCount,
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/lib/mapping.d.ts CHANGED
@@ -5,14 +5,33 @@
5
5
  * taxonomy mirrors them. Anything unknown is downgraded to `UNKNOWN`
6
6
  * (treated as retryable).
7
7
  */
8
- import type { LlmCallConfig, LlmFailure, LlmResolvedModelInfo } from '@deepseek-ai/dsh-llm';
8
+ import type { LlmCallConfig, LlmFailure, LlmResolvedModelInfo, ResolvedRetryPolicy } from '@deepseek-ai/dsh-llm';
9
9
  import { type Channel, type ChannelId, type FailureCode, type FailureSignal } from 'daruma-core';
10
10
  export declare function toFailureCode(code: string): FailureCode;
11
11
  /** Stable channel identity from a provider+model pair. */
12
12
  export declare function channelIdOf(provider: string, model: string): ChannelId;
13
13
  /** Channel identity of a resolved request config. */
14
14
  export declare function channelIdOfConfig(config: LlmCallConfig): ChannelId;
15
- export declare function toFailureSignal(failure: LlmFailure, channel: ChannelId, occurredAtMs: number): FailureSignal;
15
+ export declare function toFailureSignal(failure: LlmFailure, channel: ChannelId, occurredAtMs: number, retryExhausted?: boolean): FailureSignal;
16
+ /**
17
+ * Whether the host's same-channel retry budget was already spent on the failure
18
+ * daruma is being asked to escalate.
19
+ *
20
+ * daruma sits downstream of the in-box `dsh-llm-retry` on the
21
+ * `agent/request-error` waterfall (`dsh-llm-retry/lib/index.js`): that plugin
22
+ * answers a retryable failure with a retry of the same channel and only calls
23
+ * through when its budget runs out. Being handed the failure at all therefore
24
+ * *is* the exhaustion signal — for a code its own policy lists as retryable.
25
+ *
26
+ * Two cases must not be read that way:
27
+ * - no policy at all: no adapter route owned the request, so nothing retried it;
28
+ * - `always` mode: that mode consults its downstream listeners *before* deciding
29
+ * to retry, so arrival carries no information about the budget there.
30
+ *
31
+ * @param code - the failure code, as DSH reports it (not yet mapped).
32
+ * @param policy - the failed route's resolved retry policy, per the host payload.
33
+ */
34
+ export declare function isRetryExhausted(code: string, policy: ResolvedRetryPolicy | undefined): boolean;
16
35
  /**
17
36
  * The one read daruma makes of the LLM runtime before it swaps channels: the
18
37
  * target's own model metadata. Structural, so a test can answer it without a
package/lib/mapping.js CHANGED
@@ -27,15 +27,41 @@ export function channelIdOf(provider, model) {
27
27
  export function channelIdOfConfig(config) {
28
28
  return channelIdOf(config.provider, config.model);
29
29
  }
30
- export function toFailureSignal(failure, channel, occurredAtMs) {
30
+ export function toFailureSignal(failure, channel, occurredAtMs, retryExhausted = false) {
31
31
  return {
32
32
  code: toFailureCode(failure.code),
33
33
  status: failure.status,
34
34
  channel,
35
35
  occurredAtMs,
36
36
  message: failure.message,
37
+ // Absent unless it happened, so a signal from a host without a retry owner
38
+ // keeps the shape it always had.
39
+ ...(retryExhausted ? { retryExhausted: true } : {}),
37
40
  };
38
41
  }
42
+ /**
43
+ * Whether the host's same-channel retry budget was already spent on the failure
44
+ * daruma is being asked to escalate.
45
+ *
46
+ * daruma sits downstream of the in-box `dsh-llm-retry` on the
47
+ * `agent/request-error` waterfall (`dsh-llm-retry/lib/index.js`): that plugin
48
+ * answers a retryable failure with a retry of the same channel and only calls
49
+ * through when its budget runs out. Being handed the failure at all therefore
50
+ * *is* the exhaustion signal — for a code its own policy lists as retryable.
51
+ *
52
+ * Two cases must not be read that way:
53
+ * - no policy at all: no adapter route owned the request, so nothing retried it;
54
+ * - `always` mode: that mode consults its downstream listeners *before* deciding
55
+ * to retry, so arrival carries no information about the budget there.
56
+ *
57
+ * @param code - the failure code, as DSH reports it (not yet mapped).
58
+ * @param policy - the failed route's resolved retry policy, per the host payload.
59
+ */
60
+ export function isRetryExhausted(code, policy) {
61
+ if (policy === undefined || policy.mode === 'always')
62
+ return false;
63
+ return policy.retryableCodes.includes(code);
64
+ }
39
65
  /**
40
66
  * Read the reasoning efforts `target` advertises.
41
67
  *
@@ -1 +1 @@
1
- {"version":3,"file":"mapping.js","sourceRoot":"","sources":["../src/mapping.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mapping.js","sourceRoot":"","sources":["../src/mapping.ts"],"names":[],"mappings":"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"}
package/lib/rpc.d.ts CHANGED
@@ -13,9 +13,19 @@ export type RpcResult = {
13
13
  value: unknown;
14
14
  } | {
15
15
  ok: false;
16
+ /**
17
+ * The host's response envelope validates failures against
18
+ * `dsh-client-connection`'s `rpcErrorSchema`, which requires a `details`
19
+ * record; the browser's `parseConnectionResponse` throws
20
+ * `connection: invalid server-response failure` without one — on **both**
21
+ * transports (`rpc.handle` and the `/api` fallback) since they share that
22
+ * parser. Optional in the type so a foreign dispatch cannot be forced to
23
+ * invent one, but every failure daruma owns sets it.
24
+ */
16
25
  error: {
17
26
  code: string;
18
27
  message: string;
28
+ details?: Record<string, unknown>;
19
29
  };
20
30
  };
21
31
  export interface RpcDeps {
package/lib/rpc.js CHANGED
@@ -2,6 +2,7 @@
2
2
  * `/dsh-daruma` RPC channel: status snapshot, candidate discovery, and
3
3
  * backup-channel management for the client UI.
4
4
  */
5
+ import { isBrokenRpcHandleError, mountHttpFallback } from "./http-transport.js";
5
6
  function messageOf(error) {
6
7
  return error instanceof Error ? error.message : String(error);
7
8
  }
@@ -117,7 +118,7 @@ export function mountRpc(ctx, deps) {
117
118
  const code = message.startsWith('bad-request:') ? 'bad-request' : 'internal';
118
119
  return {
119
120
  ok: false,
120
- error: { code, message: message.replace(/^bad-request: /u, '') },
121
+ error: { code, message: message.replace(/^bad-request: /u, ''), details: {} },
121
122
  };
122
123
  }
123
124
  };
@@ -126,10 +127,14 @@ export function mountRpc(ctx, deps) {
126
127
  ctx.effect(() => dispose, 'dsh-daruma: /dsh-daruma rpc channel');
127
128
  }
128
129
  catch (error) {
129
- // Known host regression: 0.1.5-rc.1/rc.2 dropped `webServer` from the
130
+ // Known host regression: 0.1.5-alpha.1rc.2 dropped `webServer` from the
130
131
  // connection plugin's own inject list while `rpc.handle()` still registers
131
132
  // its route through the service context, so the call throws for every
132
- // caller. Fail loudly instead of leaving the panel silently empty.
133
+ // caller. On exactly that failure, mount the panel through the shared
134
+ // `/api` Fetch carrier instead (see src/http-transport.ts). Anything else
135
+ // still fails loudly instead of leaving the panel silently empty.
136
+ if (isBrokenRpcHandleError(error) && mountHttpFallback(ctx, connection, dispatch))
137
+ return;
133
138
  ctx.logger.warn(`dsh-daruma: /dsh-daruma rpc channel could not be registered (${messageOf(error)}); `
134
139
  + 'the status dock and backup picker stay disabled on this host generation');
135
140
  }
package/lib/rpc.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"rpc.js","sourceRoot":"","sources":["../src/rpc.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"rpc.js","sourceRoot":"","sources":["../src/rpc.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-daruma",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "Daruma resilience plugin for DeepSeek Harness — detects model-request failures and fails over to another channel to keep long tasks alive.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -32,7 +32,8 @@
32
32
  },
33
33
  "files": [
34
34
  "lib",
35
- "cordis.patch.yml"
35
+ "cordis.patch.yml",
36
+ "assets"
36
37
  ],
37
38
  "sideEffects": false,
38
39
  "engines": {