dsh-thinkbar 0.1.0
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/LICENSE +22 -0
- package/README.md +112 -0
- package/README.zh.md +112 -0
- package/cordis.patch.yml +3 -0
- package/lib/client.cjs +679 -0
- package/lib/client.cjs.map +1 -0
- package/lib/index.js +11 -0
- package/lib/index.js.map +1 -0
- package/lib/types/client/ModelTriggerBridge.d.ts +6 -0
- package/lib/types/client/ModelTriggerBridge.d.ts.map +1 -0
- package/lib/types/client/ReasoningWaitIndicator.d.ts +8 -0
- package/lib/types/client/ReasoningWaitIndicator.d.ts.map +1 -0
- package/lib/types/client/fill-face.d.ts +8 -0
- package/lib/types/client/fill-face.d.ts.map +1 -0
- package/lib/types/client/index.d.ts +11 -0
- package/lib/types/client/index.d.ts.map +1 -0
- package/lib/types/client/model-trigger-adapter.d.ts +10 -0
- package/lib/types/client/model-trigger-adapter.d.ts.map +1 -0
- package/lib/types/client/reasoning-wait-projection.d.ts +30 -0
- package/lib/types/client/reasoning-wait-projection.d.ts.map +1 -0
- package/lib/types/client/service.d.ts +18 -0
- package/lib/types/client/service.d.ts.map +1 -0
- package/lib/types/client/thermometer.d.ts +48 -0
- package/lib/types/client/thermometer.d.ts.map +1 -0
- package/lib/types/client/use-model-trigger.d.ts +4 -0
- package/lib/types/client/use-model-trigger.d.ts.map +1 -0
- package/lib/types/index.d.ts +7 -0
- package/lib/types/index.d.ts.map +1 -0
- package/package.json +95 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.cjs","names":["Service","useState","useRef","css","useState","useRef","css","createPortal"],"sources":["../src/client/thermometer.ts","../src/client/service.ts","../src/client/ReasoningWaitIndicator.tsx","../src/client/model-trigger-adapter.ts","../src/client/use-model-trigger.ts","../src/client/ModelTriggerBridge.tsx","../src/client/reasoning-wait-projection.ts","../src/client/index.ts"],"sourcesContent":["import type { ReasoningWaitProjection } from './reasoning-wait-projection.ts'\r\n\r\nconst FULL_SCALE_MS = 20_000\r\nconst MIN_FILL = 0.08\r\nconst DRAIN_MS = 240\r\n\r\nconst IRON_STOPS = [\r\n { t: 0, hex: 'var(--dsw-alias-button-info-fill)' },\r\n { t: 1 / 3, hex: '#dc2626' },\r\n { t: 2 / 3, hex: '#e07020' },\r\n { t: 1, hex: '#ffcc00' },\r\n] as const\r\n\r\nexport type ReasoningWaitAppearance =\r\n | { readonly phase: 'idle' }\r\n | {\r\n readonly phase: 'thermometer'\r\n readonly t: number\r\n readonly height: number\r\n readonly color: string\r\n }\r\n\r\nexport interface StreamClockAnchor {\r\n readonly stamp: string\r\n readonly identity: string\r\n readonly eventElapsed: number\r\n readonly observedAt: number\r\n readonly renderedElapsed: number\r\n}\r\n\r\nexport type ReasoningWaitState =\r\n | { readonly phase: 'idle' }\r\n | {\r\n readonly phase: 'thermometer'\r\n readonly identity: string\r\n readonly t: number\r\n readonly height: number\r\n readonly color: string\r\n }\r\n | {\r\n readonly phase: 'drain'\r\n readonly identity: string\r\n readonly t: number\r\n readonly height: number\r\n readonly color: string\r\n readonly fromHeight: number\r\n readonly startedAt: number\r\n }\r\n\r\nexport interface ReasoningWaitInput {\r\n readonly projection: ReasoningWaitProjection | null | undefined\r\n readonly elapsed: number\r\n readonly frameNow: number\r\n readonly reducedMotion: boolean\r\n readonly identity: string\r\n}\r\n\r\nexport interface SessionClock {\r\n readonly elapsed: number\r\n readonly anchor: StreamClockAnchor | null\r\n}\r\n\r\nexport function reasoningWaitAppearance(\r\n projection: ReasoningWaitProjection | null | undefined,\r\n elapsed: number,\r\n): ReasoningWaitAppearance {\r\n if (projection?.active !== true) return { phase: 'idle' }\r\n const t = Math.min(1, Math.max(0, elapsed / FULL_SCALE_MS))\r\n return {\r\n phase: 'thermometer',\r\n t,\r\n height: MIN_FILL + (1 - MIN_FILL) * easeOutFill(t),\r\n color: ironScale(t),\r\n }\r\n}\r\n\r\nexport function extrapolateProjectionClock(\r\n projection: ReasoningWaitProjection | null | undefined,\r\n frameNow: number,\r\n anchor: StreamClockAnchor | null,\r\n identity: string,\r\n): SessionClock {\r\n if (projection?.active !== true) return { elapsed: 0, anchor: null }\r\n const eventElapsed = Math.max(0, projection.streamTime - projection.waitOrigin)\r\n const stamp = `${identity}:${projection.waitOrigin}:${projection.streamTime}`\r\n if (anchor?.stamp !== stamp) {\r\n const elapsed = Math.max(anchor?.identity === identity ? anchor.renderedElapsed : 0, eventElapsed)\r\n return {\r\n elapsed,\r\n anchor: { stamp, identity, eventElapsed, observedAt: frameNow, renderedElapsed: elapsed },\r\n }\r\n }\r\n const elapsed = Math.max(anchor.renderedElapsed, anchor.eventElapsed + frameNow - anchor.observedAt)\r\n return { elapsed, anchor: { ...anchor, renderedElapsed: elapsed } }\r\n}\r\n\r\nexport function advanceReasoningWait(\r\n previous: ReasoningWaitState,\r\n input: ReasoningWaitInput,\r\n): ReasoningWaitState {\r\n const snapshot = reasoningWaitAppearance(input.projection, input.elapsed)\r\n if (snapshot.phase === 'thermometer') {\r\n if (\r\n previous.phase === 'thermometer'\r\n && previous.identity === input.identity\r\n && previous.t === snapshot.t\r\n && previous.height === snapshot.height\r\n && previous.color === snapshot.color\r\n ) return previous\r\n return { ...snapshot, identity: input.identity }\r\n }\r\n if (input.reducedMotion) return previous.phase === 'idle' ? previous : { phase: 'idle' }\r\n const sameIdentity = previous.phase !== 'idle' && previous.identity === input.identity\r\n if (previous.phase === 'thermometer' && sameIdentity) {\r\n return {\r\n phase: 'drain',\r\n identity: input.identity,\r\n t: previous.t,\r\n height: previous.height,\r\n color: previous.color,\r\n fromHeight: previous.height,\r\n startedAt: input.frameNow,\r\n }\r\n }\r\n if (previous.phase === 'drain' && sameIdentity) {\r\n const elapsed = input.frameNow - previous.startedAt\r\n if (elapsed >= DRAIN_MS) return { phase: 'idle' }\r\n const height = previous.fromHeight * (1 - elapsed / DRAIN_MS)\r\n if (height === previous.height) return previous\r\n return { ...previous, height }\r\n }\r\n return previous.phase === 'idle' ? previous : { phase: 'idle' }\r\n}\r\n\r\nfunction nearestStop(t: number): string | undefined {\r\n for (const stop of IRON_STOPS) {\r\n if (Math.abs(t - stop.t) <= 1 / FULL_SCALE_MS) return stop.hex\r\n }\r\n return undefined\r\n}\r\n\r\nfunction ironScale(t: number): string {\r\n const snapped = nearestStop(t)\r\n if (snapped !== undefined) return snapped\r\n if (t < IRON_STOPS[1].t) {\r\n return mixOklch(IRON_STOPS[0].hex, IRON_STOPS[1].hex, t / (1 / 3))\r\n }\r\n if (t < IRON_STOPS[2].t) {\r\n return mixOklch(IRON_STOPS[1].hex, IRON_STOPS[2].hex, (t - 1 / 3) / (1 / 3))\r\n }\r\n return mixOklch(IRON_STOPS[2].hex, IRON_STOPS[3].hex, (t - 2 / 3) / (1 / 3))\r\n}\r\n\r\nfunction mixOklch(fromHex: string, toHex: string, amount: number): string {\r\n return `color-mix(in oklch, ${fromHex}, ${toHex} ${amount * 100}%)`\r\n}\r\n\r\nfunction easeOutFill(linearT: number): number {\r\n if (linearT <= 0) return 0\r\n if (linearT >= 1) return 1\r\n const xAt = (u: number): number => 3 * (1 - u) * u * u * 0.58 + u ** 3\r\n const yAt = (u: number): number => 3 * (1 - u) * u * u + u ** 3\r\n let low = 0\r\n let high = 1\r\n for (let i = 0; i < 24; i++) {\r\n const mid = (low + high) / 2\r\n if (xAt(mid) < linearT) low = mid\r\n else high = mid\r\n }\r\n return yAt((low + high) / 2)\r\n}\r\n","import { Service } from '@deepseek-ai/cordis'\r\nimport type { Context } from '@deepseek-ai/cordis'\r\nimport type { ReasoningWaitProjection } from './reasoning-wait-projection.ts'\r\nimport {\r\n advanceReasoningWait,\r\n extrapolateProjectionClock,\r\n type ReasoningWaitInput,\r\n type ReasoningWaitState,\r\n type SessionClock,\r\n type StreamClockAnchor,\r\n} from './thermometer.ts'\r\n\r\ndeclare module '@deepseek-ai/cordis' {\r\n interface Context {\r\n /** Stateless frame math used by the reasoning-wait decoration. */\r\n reasoningWait: ReasoningWaitService\r\n }\r\n}\r\n\r\n/** Stateless reasoning-wait frame service. */\r\nexport class ReasoningWaitService extends Service {\r\n static inject = []\r\n\r\n constructor(ctx: Context) {\r\n super(ctx, 'reasoningWait')\r\n }\r\n\r\n clock(\r\n projection: ReasoningWaitProjection | null | undefined,\r\n frameNow: number,\r\n anchor: StreamClockAnchor | null,\r\n identity: string,\r\n ): SessionClock {\r\n return extrapolateProjectionClock(projection, frameNow, anchor, identity)\r\n }\r\n\r\n advance(previous: ReasoningWaitState, input: ReasoningWaitInput): ReasoningWaitState {\r\n return advanceReasoningWait(previous, input)\r\n }\r\n}\r\n","import { useEffect, useLayoutEffect, useRef, useState, type CSSProperties } from 'react'\r\nimport type { ReasoningWaitProjection } from './reasoning-wait-projection.ts'\r\nimport type { ReasoningWaitFill } from './fill-face.ts'\r\nimport type { ReasoningWaitState, StreamClockAnchor } from './thermometer.ts'\r\nimport css from './ReasoningWaitIndicator.module.css'\r\n\r\nexport interface ReasoningWaitIndicatorProps extends ReasoningWaitFill {\r\n readonly identity: string\r\n readonly projection: ReasoningWaitProjection | null | undefined\r\n}\r\n\r\ninterface FillParticle {\r\n readonly x: number\r\n readonly y: number\r\n readonly size: number\r\n readonly opacity: number\r\n readonly dur: number\r\n readonly delay: number\r\n readonly dx: number\r\n readonly dy: number\r\n}\r\n\r\nconst FILL_PARTICLES: readonly FillParticle[] = [\r\n { x: 10, y: 15, size: 2, opacity: 1, dur: 2.6, delay: 0, dx: 3, dy: -2 },\r\n { x: 26, y: 8, size: 3, opacity: 0.95, dur: 3.4, delay: -0.8, dx: -2, dy: 3 },\r\n { x: 40, y: 19, size: 2, opacity: 1, dur: 2.2, delay: -1.4, dx: 3, dy: -3 },\r\n { x: 56, y: 12, size: 2, opacity: 0.9, dur: 4.1, delay: -0.4, dx: -3, dy: 2 },\r\n { x: 72, y: 21, size: 3, opacity: 1, dur: 3, delay: -2.1, dx: 2, dy: -2 },\r\n { x: 90, y: 7, size: 2, opacity: 0.95, dur: 2.8, delay: -1.1, dx: -2, dy: 3 },\r\n { x: 106, y: 16, size: 2, opacity: 1, dur: 3.6, delay: -0.6, dx: 3, dy: -2 },\r\n { x: 124, y: 10, size: 3, opacity: 0.9, dur: 4.4, delay: -2.8, dx: -3, dy: 2 },\r\n { x: 142, y: 19, size: 2, opacity: 1, dur: 2.4, delay: -1.7, dx: 2, dy: -3 },\r\n { x: 160, y: 13, size: 2, opacity: 0.95, dur: 3.2, delay: -0.9, dx: -2, dy: 3 },\r\n { x: 180, y: 8, size: 3, opacity: 0.95, dur: 3.8, delay: -2.4, dx: 3, dy: -2 },\r\n { x: 202, y: 18, size: 2, opacity: 1, dur: 2.7, delay: -1.2, dx: -3, dy: 2 },\r\n { x: 226, y: 12, size: 2, opacity: 0.9, dur: 4.3, delay: -0.3, dx: 2, dy: -3 },\r\n { x: 250, y: 17, size: 3, opacity: 1, dur: 3.1, delay: -1.9, dx: -2, dy: 2 },\r\n { x: 278, y: 9, size: 2, opacity: 0.95, dur: 2.9, delay: -0.7, dx: 3, dy: -2 },\r\n { x: 306, y: 14, size: 2, opacity: 0.9, dur: 3.7, delay: -2.6, dx: -2, dy: 3 },\r\n]\r\n\r\nfunction particleStyle(particle: FillParticle): CSSProperties {\r\n return {\r\n left: `${particle.x}px`,\r\n top: `${particle.y}px`,\r\n width: `${particle.size}px`,\r\n height: `${particle.size}px`,\r\n '--dsh-particle-opacity': String(particle.opacity),\r\n '--dsh-particle-dx': `${particle.dx}px`,\r\n '--dsh-particle-dy': `${particle.dy}px`,\r\n '--dsh-particle-dur': `${particle.dur}s`,\r\n '--dsh-particle-delay': `${particle.delay}s`,\r\n } as CSSProperties\r\n}\r\n\r\nexport function ReasoningWaitIndicator({ identity, projection, clock, advance }: ReasoningWaitIndicatorProps) {\r\n const [waitState, setWaitState] = useState<ReasoningWaitState>({ phase: 'idle' })\r\n const clockAnchorRef = useRef<StreamClockAnchor | null>(null)\r\n const reducedMotion = window.matchMedia?.('(prefers-reduced-motion: reduce)')?.matches ?? false\r\n const frameNow = useFrameNow(projection?.active === true || waitState.phase !== 'idle')\r\n const clockRead = clock(projection, frameNow, clockAnchorRef.current, identity)\r\n clockAnchorRef.current = clockRead.anchor\r\n const input = { projection, elapsed: clockRead.elapsed, frameNow, reducedMotion, identity }\r\n const view = advance(waitState, input)\r\n\r\n useLayoutEffect(() => {\r\n setWaitState(previous => advance(previous, input))\r\n }, [projection, clockRead.elapsed, frameNow, reducedMotion, identity, advance])\r\n\r\n if (view.phase === 'idle') return null\r\n return (\r\n <span className={css.root} data-reasoning-wait={view.phase} aria-hidden=\"true\">\r\n <span\r\n className={css.fill}\r\n data-reasoning-wait-fill=\"\"\r\n style={{ width: `${view.height * 100}%`, backgroundColor: view.color }}\r\n >\r\n {FILL_PARTICLES.map((particle, index) => (\r\n <span\r\n key={index}\r\n className={css.particle}\r\n data-reasoning-wait-particle=\"\"\r\n style={particleStyle(particle)}\r\n />\r\n ))}\r\n </span>\r\n </span>\r\n )\r\n}\r\n\r\nfunction useFrameNow(active: boolean): number {\r\n const [, setTick] = useState(0)\r\n useEffect(() => {\r\n if (!active) return\r\n let frame = 0\r\n const tick = (): void => {\r\n setTick(value => value + 1)\r\n frame = requestAnimationFrame(tick)\r\n }\r\n frame = requestAnimationFrame(tick)\r\n return () => cancelAnimationFrame(frame)\r\n }, [active])\r\n return performance.now()\r\n}\r\n","const COMPOSER_SELECTOR = '[data-composer-card]'\r\nconst MODEL_TRIGGER_SELECTOR = 'button[aria-haspopup=\"menu\"]'\r\nconst HOST_ATTRIBUTE = 'data-dsh-thinkbar-host'\r\nconst LAYER_ATTRIBUTE = 'data-dsh-thinkbar-layer'\r\n\r\nlet compatibilityWarningShown = false\r\n\r\nexport interface ModelTriggerMount {\r\n readonly layer: HTMLSpanElement\r\n dispose(): void\r\n}\r\n\r\n/** Resolve the only semantic menu trigger following the public Slot anchor. */\r\nexport function resolveModelTrigger(anchor: HTMLElement): HTMLButtonElement | null {\r\n const composer = anchor.closest<HTMLElement>(COMPOSER_SELECTOR)\r\n if (composer === null) return null\r\n const candidates = [...composer.querySelectorAll<HTMLButtonElement>(MODEL_TRIGGER_SELECTOR)]\r\n .filter(candidate => Boolean(\r\n anchor.compareDocumentPosition(candidate) & Node.DOCUMENT_POSITION_FOLLOWING,\r\n ))\r\n return candidates.length === 1 ? candidates[0] ?? null : null\r\n}\r\n\r\nfunction warnCompatibility(): void {\r\n if (compatibilityWarningShown) return\r\n compatibilityWarningShown = true\r\n console.warn(\r\n '[dsh-thinkbar] Could not uniquely identify the DeepSeek Harness model selector; the indicator is disabled.',\r\n )\r\n}\r\n\r\nfunction existingLayer(target: HTMLButtonElement): HTMLSpanElement | null {\r\n return [...target.children].find((child): child is HTMLSpanElement =>\r\n child instanceof HTMLSpanElement && child.hasAttribute(LAYER_ATTRIBUTE)) ?? null\r\n}\r\n\r\n/** Attach one plugin-owned Portal layer without moving or rewriting host children. */\r\nexport function mountModelTrigger(anchor: HTMLElement): ModelTriggerMount | null {\r\n const target = resolveModelTrigger(anchor)\r\n if (target === null) {\r\n warnCompatibility()\r\n return null\r\n }\r\n const layer = existingLayer(target) ?? document.createElement('span')\r\n layer.setAttribute(LAYER_ATTRIBUTE, '')\r\n if (!layer.isConnected) target.prepend(layer)\r\n target.setAttribute(HOST_ATTRIBUTE, '')\r\n let disposed = false\r\n return {\r\n layer,\r\n dispose: () => {\r\n if (disposed) return\r\n disposed = true\r\n layer.remove()\r\n if (existingLayer(target) === null) target.removeAttribute(HOST_ATTRIBUTE)\r\n },\r\n }\r\n}\r\n\r\nexport function resetCompatibilityWarningForTests(): void {\r\n compatibilityWarningShown = false\r\n}\r\n","import { useLayoutEffect, useState, type RefObject } from 'react'\r\nimport {\r\n mountModelTrigger,\r\n resolveModelTrigger,\r\n type ModelTriggerMount,\r\n} from './model-trigger-adapter.ts'\r\n\r\n/** Keep a Portal layer attached across ModelSelect and composer reconstruction. */\r\nexport function useModelTrigger(anchorRef: RefObject<HTMLElement | null>): HTMLElement | null {\r\n const [layer, setLayer] = useState<HTMLElement | null>(null)\r\n\r\n useLayoutEffect(() => {\r\n const anchor = anchorRef.current\r\n if (anchor === null) return\r\n const composer = anchor.closest<HTMLElement>('[data-composer-card]')\r\n if (composer === null) return\r\n let mount: ModelTriggerMount | null = null\r\n\r\n const refresh = (): void => {\r\n const target = resolveModelTrigger(anchor)\r\n if (mount?.layer.isConnected === true && mount.layer.parentElement === target) return\r\n mount?.dispose()\r\n mount = mountModelTrigger(anchor)\r\n setLayer(mount?.layer ?? null)\r\n }\r\n\r\n refresh()\r\n const observer = new MutationObserver(refresh)\r\n observer.observe(composer, { childList: true, subtree: true })\r\n return () => {\r\n observer.disconnect()\r\n mount?.dispose()\r\n }\r\n }, [anchorRef])\r\n\r\n return layer\r\n}\r\n","import type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\r\nimport { createPortal } from 'react-dom'\r\nimport { useRef } from 'react'\r\nimport type { ReasoningWaitFill } from './fill-face.ts'\r\nimport { ReasoningWaitIndicator } from './ReasoningWaitIndicator.tsx'\r\nimport { useModelTrigger } from './use-model-trigger.ts'\r\nimport css from './ReasoningWaitIndicator.module.css'\r\n\r\nexport type ModelTriggerBridgeProps = PropsRuntime<'conversation.input.right'> & ReasoningWaitFill\r\n\r\n/** Public-Slot lifecycle bridge that portals the indicator into the model trigger. */\r\nexport function ModelTriggerBridge({ useSession, sessionId, clock, advance }: ModelTriggerBridgeProps) {\r\n const anchorRef = useRef<HTMLSpanElement>(null)\r\n const layer = useModelTrigger(anchorRef)\r\n const projection = useSession(snapshot => snapshot.views.get('dsh-thinkbar'))\r\n const identity = projection === null || projection === undefined\r\n ? String(sessionId)\r\n : `${String(sessionId)}:${projection.turn}:${projection.step}`\r\n\r\n return (\r\n <span ref={anchorRef} className={css.anchor} data-dsh-thinkbar-anchor=\"\" aria-hidden=\"true\">\r\n {layer === null ? null : createPortal(\r\n <ReasoningWaitIndicator\r\n identity={identity}\r\n projection={projection}\r\n clock={clock}\r\n advance={advance}\r\n />,\r\n layer,\r\n )}\r\n </span>\r\n )\r\n}\r\n","import type {\r\n ConversationMatch,\r\n ConversationNodeDefinition,\r\n ConversationViewDefinition,\r\n ConversationViewNode,\r\n} from '@deepseek-ai/dsh-client-runtime/client'\r\nimport type {} from '@deepseek-ai/dsh-llm-retry/types'\r\n\r\nexport type ReasoningWaitTailKind = 'empty' | 'reasoning' | 'text' | 'tool' | 'other'\r\n\r\n/** Replayable reasoning-wait state derived only from public Session events. */\r\nexport interface ReasoningWaitProjection {\r\n readonly turn: number\r\n readonly step: number\r\n readonly waitOrigin: number\r\n readonly streamTime: number\r\n readonly active: boolean\r\n readonly tailKind: ReasoningWaitTailKind\r\n}\r\n\r\ndeclare module '@deepseek-ai/dsh-client-runtime/client' {\r\n interface ConversationViewSnapshotMap {\r\n 'dsh-thinkbar': ReasoningWaitProjection | null\r\n }\r\n}\r\n\r\ninterface ReasoningWaitState extends ReasoningWaitProjection {\r\n readonly retryPending: boolean\r\n}\r\n\r\ninterface ReasoningWaitNode extends ConversationViewNode {\r\n readonly target: 'dsh-thinkbar'\r\n readonly anchorSeq: number\r\n readonly data: ReasoningWaitProjection\r\n}\r\n\r\ninterface CompactChunkEvent {\r\n readonly type:\r\n | 'chunkrow/text-chunks'\r\n | 'chunkrow/reasoning-chunks'\r\n | 'chunkrow/tool-call-chunks'\r\n readonly seq: number\r\n readonly time: number\r\n readonly data: {\r\n readonly turn: number\r\n readonly step: number\r\n readonly dt: readonly number[]\r\n readonly texts?: readonly string[]\r\n readonly args?: readonly string[]\r\n }\r\n}\r\n\r\ntype ProjectionEvent = ConversationMatch['event'] | CompactChunkEvent\r\n\r\nfunction isCompactChunkEvent(event: ProjectionEvent): event is CompactChunkEvent {\r\n const type = String(event.type)\r\n return type === 'chunkrow/text-chunks'\r\n || type === 'chunkrow/reasoning-chunks'\r\n || type === 'chunkrow/tool-call-chunks'\r\n}\r\n\r\nfunction projectionOf(state: ReasoningWaitState): ReasoningWaitProjection {\r\n const { retryPending: _retryPending, ...projection } = state\r\n return projection\r\n}\r\n\r\nfunction eventIdentity(event: ProjectionEvent): string | null {\r\n if (isCompactChunkEvent(event)) return `${event.data.turn}:${event.data.step}`\r\n if (event.type === 'step/start'\r\n || event.type === 'step/end'\r\n || event.type === 'assistant/chunk'\r\n || event.type === 'assistant/message'\r\n || event.type === 'llm/retry'\r\n || event.type === 'llm/retry-started') {\r\n return `${event.data.turn}:${event.data.step}`\r\n }\r\n return null\r\n}\r\n\r\nfunction transition(\r\n state: ReasoningWaitState,\r\n time: number,\r\n tailKind: ReasoningWaitTailKind,\r\n active: boolean,\r\n originTime = time,\r\n): ReasoningWaitState {\r\n return {\r\n ...state,\r\n waitOrigin: state.retryPending && tailKind === 'reasoning' ? originTime : state.waitOrigin,\r\n streamTime: time,\r\n active,\r\n tailKind,\r\n retryPending: state.retryPending && tailKind === 'empty',\r\n }\r\n}\r\n\r\nfunction chunkTransition(state: ReasoningWaitState, match: ConversationMatch): ReasoningWaitState {\r\n if (match.event.type !== 'assistant/chunk') return state\r\n const { chunk } = match.event.data\r\n switch (chunk.type) {\r\n case 'block-start':\r\n if (chunk.blockType === 'reasoning') return transition(state, match.event.time, 'reasoning', true)\r\n if (chunk.blockType === 'text') return transition(state, match.event.time, 'text', false)\r\n if (chunk.blockType === 'tool-call') return transition(state, match.event.time, 'tool', false)\r\n return transition(state, match.event.time, 'other', false)\r\n case 'reasoning-delta':\r\n return transition(state, match.event.time, 'reasoning', true)\r\n case 'text-delta':\r\n return transition(state, match.event.time, 'text', false)\r\n case 'tool-call-delta':\r\n return transition(state, match.event.time, 'tool', false)\r\n case 'block-end':\r\n if (chunk.block.type === 'reasoning') return transition(state, match.event.time, 'reasoning', true)\r\n if (chunk.block.type === 'text') return transition(state, match.event.time, 'text', false)\r\n if (chunk.block.type === 'tool-call') return transition(state, match.event.time, 'tool', false)\r\n return transition(state, match.event.time, 'other', false)\r\n default:\r\n return state\r\n }\r\n}\r\n\r\nfunction compactEndTime(event: CompactChunkEvent): number {\r\n return event.data.dt.reduce((time, gap) => time + gap, event.time)\r\n}\r\n\r\nfunction compactFirstEvidenceTime(event: CompactChunkEvent): number | null {\r\n let time = event.time\r\n for (let index = 0; index < (event.data.texts?.length ?? 0); index++) {\r\n if (event.data.texts?.[index] !== '') return time\r\n time += event.data.dt[index] ?? 0\r\n }\r\n return null\r\n}\r\n\r\nfunction compactTransition(state: ReasoningWaitState, event: CompactChunkEvent): ReasoningWaitState {\r\n const streamTime = compactEndTime(event)\r\n if (event.type === 'chunkrow/reasoning-chunks') {\r\n const firstEvidenceTime = compactFirstEvidenceTime(event)\r\n return firstEvidenceTime === null\r\n ? state\r\n : transition(state, streamTime, 'reasoning', true, firstEvidenceTime)\r\n }\r\n if (event.type === 'chunkrow/text-chunks') return transition(state, streamTime, 'text', false)\r\n return transition(state, streamTime, 'tool', false)\r\n}\r\n\r\nfunction updateState(state: ReasoningWaitState, match: ConversationMatch): ReasoningWaitState {\r\n const event = match.event as ProjectionEvent\r\n if (isCompactChunkEvent(event)) return compactTransition(state, event)\r\n if (event.type === 'assistant/chunk') return chunkTransition(state, match)\r\n if (event.type === 'llm/retry' || event.type === 'llm/retry-started') {\r\n return { ...state, streamTime: event.time, active: false, tailKind: 'empty', retryPending: true }\r\n }\r\n if (event.type === 'assistant/message' || event.type === 'step/end') {\r\n return { ...state, streamTime: event.time, active: false, retryPending: false }\r\n }\r\n return state\r\n}\r\n\r\n/** Per-Step event state machine for the reasoning indicator. */\r\nexport const reasoningWaitDefinition: ConversationNodeDefinition<ReasoningWaitState> = {\r\n kind: 'dsh-thinkbar/reasoning-wait',\r\n target: 'dsh-thinkbar',\r\n match: (event) => {\r\n const id = eventIdentity(event as ProjectionEvent)\r\n if (id === null) return null\r\n return { id, role: event.type === 'step/start' ? 'start' : 'update' }\r\n },\r\n start: (_context, match) => {\r\n if (match.event.type !== 'step/start') throw new Error('reasoning-wait start requires step/start')\r\n return {\r\n turn: match.event.data.turn,\r\n step: match.event.data.step,\r\n waitOrigin: match.event.time,\r\n streamTime: match.event.time,\r\n active: false,\r\n tailKind: 'empty',\r\n retryPending: false,\r\n }\r\n },\r\n update: (context, match) => updateState(context.state, match),\r\n publication: match => match.event.type === 'assistant/chunk'\r\n || isCompactChunkEvent(match.event as ProjectionEvent)\r\n ? 'animation-frame'\r\n : 'immediate',\r\n buildViewNode: (context) => {\r\n if (context.state === undefined) return null\r\n return {\r\n key: context.key,\r\n kind: context.kind,\r\n id: context.id,\r\n target: 'dsh-thinkbar',\r\n anchorSeq: context.matches.at(-1)?.event.seq ?? context.start?.event.seq ?? 0,\r\n data: projectionOf(context.state),\r\n }\r\n },\r\n}\r\n\r\nfunction latestProjection(nodes: Iterable<ReasoningWaitNode>): ReasoningWaitProjection | null {\r\n let latest: ReasoningWaitNode | undefined\r\n for (const node of nodes) {\r\n if (latest === undefined || node.anchorSeq > latest.anchorSeq) latest = node\r\n }\r\n return latest?.data ?? null\r\n}\r\n\r\n/** Session-owned reducer selecting the latest Step projection. */\r\nexport const reasoningWaitView: ConversationViewDefinition<\r\n ReasoningWaitNode,\r\n ReasoningWaitProjection | null\r\n> = {\r\n target: 'dsh-thinkbar',\r\n create: () => {\r\n const nodes = new Map<string, ReasoningWaitNode>()\r\n return {\r\n empty: null,\r\n replace: (input) => {\r\n nodes.clear()\r\n for (const node of input.nodes) nodes.set(node.key, node)\r\n return latestProjection(nodes.values())\r\n },\r\n apply: (input) => {\r\n for (const node of input.upserts) nodes.set(node.key, node)\r\n return latestProjection(nodes.values())\r\n },\r\n }\r\n },\r\n}\r\n","/** Browser half: public event projection plus a DOM-adapted model-seat fill. */\r\nimport type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\r\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client'\r\nimport type {} from '@deepseek-ai/dsh-client-ui-model-selection/client'\r\nimport { ReasoningWaitService } from './service.ts'\r\nimport { ModelTriggerBridge } from './ModelTriggerBridge.tsx'\r\nimport type { ReasoningWaitFill } from './fill-face.ts'\r\nimport { reasoningWaitDefinition, reasoningWaitView } from './reasoning-wait-projection.ts'\r\n\r\nexport { ReasoningWaitService } from './service.ts'\r\nexport type { ReasoningWaitFill } from './fill-face.ts'\r\nexport type {\r\n ReasoningWaitProjection,\r\n ReasoningWaitTailKind,\r\n} from './reasoning-wait-projection.ts'\r\nexport type {\r\n ReasoningWaitInput,\r\n ReasoningWaitState,\r\n SessionClock,\r\n StreamClockAnchor,\r\n} from './thermometer.ts'\r\n\r\n/** Required public rc.2 registries. */\r\nexport const inject = ['slots', 'conversationEvents', 'conversationViews']\r\n\r\n/** Mount the projection, frame service, and public-Slot DOM bridge. */\r\nexport function apply(ctx: ClientContext): void {\r\n ctx.conversationEvents.register(reasoningWaitDefinition)\r\n ctx.conversationViews.register(reasoningWaitView)\r\n ctx.plugin(ReasoningWaitService)\r\n ctx.slots.inject('conversation.input.right', () => ctx.slots.register({\r\n name: 'conversation.input.right',\r\n id: 'dsh-thinkbar',\r\n order: 20,\r\n inject: (): ReasoningWaitFill => {\r\n const reasoningWait = (): ReasoningWaitService | undefined =>\r\n ctx.get('reasoningWait') as ReasoningWaitService | undefined\r\n return {\r\n clock: (projection, frameNow, anchor, identity) =>\r\n reasoningWait()?.clock(projection, frameNow, anchor, identity) ?? { elapsed: 0, anchor: null },\r\n advance: (previous, input) => reasoningWait()?.advance(previous, input) ?? { phase: 'idle' },\r\n }\r\n },\r\n }, ModelTriggerBridge))\r\n}\r\n"],"mappings":"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"}
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/index.ts
|
|
2
|
+
/**
|
|
3
|
+
* dsh-thinkbar node half. This UI-only plugin needs a host Loader row so the
|
|
4
|
+
* DSH client-module scanner can discover its browser bundle.
|
|
5
|
+
*/
|
|
6
|
+
/** Host plugin body: dsh-thinkbar has no host-side behavior. */
|
|
7
|
+
function apply() {}
|
|
8
|
+
//#endregion
|
|
9
|
+
export { apply };
|
|
10
|
+
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\r\n * dsh-thinkbar node half. This UI-only plugin needs a host Loader row so the\r\n * DSH client-module scanner can discover its browser bundle.\r\n */\r\n\r\n/** Host plugin body: dsh-thinkbar has no host-side behavior. */\r\nexport function apply(): void {}\r\n"],"mappings":";;;;;;AAMA,SAAgB,QAAc,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
2
|
+
import type { ReasoningWaitFill } from './fill-face.ts';
|
|
3
|
+
export type ModelTriggerBridgeProps = PropsRuntime<'conversation.input.right'> & ReasoningWaitFill;
|
|
4
|
+
/** Public-Slot lifecycle bridge that portals the indicator into the model trigger. */
|
|
5
|
+
export declare function ModelTriggerBridge({ useSession, sessionId, clock, advance }: ModelTriggerBridgeProps): import("react").JSX.Element;
|
|
6
|
+
//# sourceMappingURL=ModelTriggerBridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ModelTriggerBridge.d.ts","sourceRoot":"","sources":["../../../src/client/ModelTriggerBridge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AAGpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAKvD,MAAM,MAAM,uBAAuB,GAAG,YAAY,CAAC,0BAA0B,CAAC,GAAG,iBAAiB,CAAA;AAElG,sFAAsF;AACtF,wBAAgB,kBAAkB,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,uBAAuB,+BAqBpG"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ReasoningWaitProjection } from './reasoning-wait-projection.ts';
|
|
2
|
+
import type { ReasoningWaitFill } from './fill-face.ts';
|
|
3
|
+
export interface ReasoningWaitIndicatorProps extends ReasoningWaitFill {
|
|
4
|
+
readonly identity: string;
|
|
5
|
+
readonly projection: ReasoningWaitProjection | null | undefined;
|
|
6
|
+
}
|
|
7
|
+
export declare function ReasoningWaitIndicator({ identity, projection, clock, advance }: ReasoningWaitIndicatorProps): import("react").JSX.Element | null;
|
|
8
|
+
//# sourceMappingURL=ReasoningWaitIndicator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ReasoningWaitIndicator.d.ts","sourceRoot":"","sources":["../../../src/client/ReasoningWaitIndicator.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAA;AAC7E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAIvD,MAAM,WAAW,2BAA4B,SAAQ,iBAAiB;IACpE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,UAAU,EAAE,uBAAuB,GAAG,IAAI,GAAG,SAAS,CAAA;CAChE;AA8CD,wBAAgB,sBAAsB,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,2BAA2B,sCAiC3G"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ReasoningWaitProjection } from './reasoning-wait-projection.ts';
|
|
2
|
+
import type { ReasoningWaitInput, ReasoningWaitState, SessionClock, StreamClockAnchor } from './thermometer.ts';
|
|
3
|
+
/** Frame-math interface injected into the public Slot bridge. */
|
|
4
|
+
export interface ReasoningWaitFill {
|
|
5
|
+
clock(projection: ReasoningWaitProjection | null | undefined, frameNow: number, anchor: StreamClockAnchor | null, identity: string): SessionClock;
|
|
6
|
+
advance(previous: ReasoningWaitState, input: ReasoningWaitInput): ReasoningWaitState;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=fill-face.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fill-face.d.ts","sourceRoot":"","sources":["../../../src/client/fill-face.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAA;AAC7E,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAE/G,iEAAiE;AACjE,MAAM,WAAW,iBAAiB;IAChC,KAAK,CACH,UAAU,EAAE,uBAAuB,GAAG,IAAI,GAAG,SAAS,EACtD,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,iBAAiB,GAAG,IAAI,EAChC,QAAQ,EAAE,MAAM,GACf,YAAY,CAAA;IACf,OAAO,CAAC,QAAQ,EAAE,kBAAkB,EAAE,KAAK,EAAE,kBAAkB,GAAG,kBAAkB,CAAA;CACrF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Browser half: public event projection plus a DOM-adapted model-seat fill. */
|
|
2
|
+
import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client';
|
|
3
|
+
export { ReasoningWaitService } from './service.ts';
|
|
4
|
+
export type { ReasoningWaitFill } from './fill-face.ts';
|
|
5
|
+
export type { ReasoningWaitProjection, ReasoningWaitTailKind, } from './reasoning-wait-projection.ts';
|
|
6
|
+
export type { ReasoningWaitInput, ReasoningWaitState, SessionClock, StreamClockAnchor, } from './thermometer.ts';
|
|
7
|
+
/** Required public rc.2 registries. */
|
|
8
|
+
export declare const inject: string[];
|
|
9
|
+
/** Mount the projection, frame service, and public-Slot DOM bridge. */
|
|
10
|
+
export declare function apply(ctx: ClientContext): void;
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAA;AAQ3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACnD,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AACvD,YAAY,EACV,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,gCAAgC,CAAA;AACvC,YAAY,EACV,kBAAkB,EAClB,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,GAClB,MAAM,kBAAkB,CAAA;AAEzB,uCAAuC;AACvC,eAAO,MAAM,MAAM,UAAuD,CAAA;AAE1E,uEAAuE;AACvE,wBAAgB,KAAK,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAkB9C"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface ModelTriggerMount {
|
|
2
|
+
readonly layer: HTMLSpanElement;
|
|
3
|
+
dispose(): void;
|
|
4
|
+
}
|
|
5
|
+
/** Resolve the only semantic menu trigger following the public Slot anchor. */
|
|
6
|
+
export declare function resolveModelTrigger(anchor: HTMLElement): HTMLButtonElement | null;
|
|
7
|
+
/** Attach one plugin-owned Portal layer without moving or rewriting host children. */
|
|
8
|
+
export declare function mountModelTrigger(anchor: HTMLElement): ModelTriggerMount | null;
|
|
9
|
+
export declare function resetCompatibilityWarningForTests(): void;
|
|
10
|
+
//# sourceMappingURL=model-trigger-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-trigger-adapter.d.ts","sourceRoot":"","sources":["../../../src/client/model-trigger-adapter.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAA;IAC/B,OAAO,IAAI,IAAI,CAAA;CAChB;AAED,+EAA+E;AAC/E,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,WAAW,GAAG,iBAAiB,GAAG,IAAI,CAQjF;AAeD,sFAAsF;AACtF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,iBAAiB,GAAG,IAAI,CAoB/E;AAED,wBAAgB,iCAAiC,IAAI,IAAI,CAExD"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { ConversationNodeDefinition, ConversationViewDefinition, ConversationViewNode } from '@deepseek-ai/dsh-client-runtime/client';
|
|
2
|
+
export type ReasoningWaitTailKind = 'empty' | 'reasoning' | 'text' | 'tool' | 'other';
|
|
3
|
+
/** Replayable reasoning-wait state derived only from public Session events. */
|
|
4
|
+
export interface ReasoningWaitProjection {
|
|
5
|
+
readonly turn: number;
|
|
6
|
+
readonly step: number;
|
|
7
|
+
readonly waitOrigin: number;
|
|
8
|
+
readonly streamTime: number;
|
|
9
|
+
readonly active: boolean;
|
|
10
|
+
readonly tailKind: ReasoningWaitTailKind;
|
|
11
|
+
}
|
|
12
|
+
declare module '@deepseek-ai/dsh-client-runtime/client' {
|
|
13
|
+
interface ConversationViewSnapshotMap {
|
|
14
|
+
'dsh-thinkbar': ReasoningWaitProjection | null;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
interface ReasoningWaitState extends ReasoningWaitProjection {
|
|
18
|
+
readonly retryPending: boolean;
|
|
19
|
+
}
|
|
20
|
+
interface ReasoningWaitNode extends ConversationViewNode {
|
|
21
|
+
readonly target: 'dsh-thinkbar';
|
|
22
|
+
readonly anchorSeq: number;
|
|
23
|
+
readonly data: ReasoningWaitProjection;
|
|
24
|
+
}
|
|
25
|
+
/** Per-Step event state machine for the reasoning indicator. */
|
|
26
|
+
export declare const reasoningWaitDefinition: ConversationNodeDefinition<ReasoningWaitState>;
|
|
27
|
+
/** Session-owned reducer selecting the latest Step projection. */
|
|
28
|
+
export declare const reasoningWaitView: ConversationViewDefinition<ReasoningWaitNode, ReasoningWaitProjection | null>;
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=reasoning-wait-projection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reasoning-wait-projection.d.ts","sourceRoot":"","sources":["../../../src/client/reasoning-wait-projection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,0BAA0B,EAC1B,0BAA0B,EAC1B,oBAAoB,EACrB,MAAM,wCAAwC,CAAA;AAG/C,MAAM,MAAM,qBAAqB,GAAG,OAAO,GAAG,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;AAErF,+EAA+E;AAC/E,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;IACxB,QAAQ,CAAC,QAAQ,EAAE,qBAAqB,CAAA;CACzC;AAED,OAAO,QAAQ,wCAAwC,CAAC;IACtD,UAAU,2BAA2B;QACnC,cAAc,EAAE,uBAAuB,GAAG,IAAI,CAAA;KAC/C;CACF;AAED,UAAU,kBAAmB,SAAQ,uBAAuB;IAC1D,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAA;CAC/B;AAED,UAAU,iBAAkB,SAAQ,oBAAoB;IACtD,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAA;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,IAAI,EAAE,uBAAuB,CAAA;CACvC;AA6HD,gEAAgE;AAChE,eAAO,MAAM,uBAAuB,EAAE,0BAA0B,CAAC,kBAAkB,CAoClF,CAAA;AAUD,kEAAkE;AAClE,eAAO,MAAM,iBAAiB,EAAE,0BAA0B,CACxD,iBAAiB,EACjB,uBAAuB,GAAG,IAAI,CAkB/B,CAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Service } from '@deepseek-ai/cordis';
|
|
2
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
3
|
+
import type { ReasoningWaitProjection } from './reasoning-wait-projection.ts';
|
|
4
|
+
import { type ReasoningWaitInput, type ReasoningWaitState, type SessionClock, type StreamClockAnchor } from './thermometer.ts';
|
|
5
|
+
declare module '@deepseek-ai/cordis' {
|
|
6
|
+
interface Context {
|
|
7
|
+
/** Stateless frame math used by the reasoning-wait decoration. */
|
|
8
|
+
reasoningWait: ReasoningWaitService;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/** Stateless reasoning-wait frame service. */
|
|
12
|
+
export declare class ReasoningWaitService extends Service {
|
|
13
|
+
static inject: never[];
|
|
14
|
+
constructor(ctx: Context);
|
|
15
|
+
clock(projection: ReasoningWaitProjection | null | undefined, frameNow: number, anchor: StreamClockAnchor | null, identity: string): SessionClock;
|
|
16
|
+
advance(previous: ReasoningWaitState, input: ReasoningWaitInput): ReasoningWaitState;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/client/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAC7C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAA;AAC7E,OAAO,EAGL,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACvB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,OAAO;QACf,kEAAkE;QAClE,aAAa,EAAE,oBAAoB,CAAA;KACpC;CACF;AAED,8CAA8C;AAC9C,qBAAa,oBAAqB,SAAQ,OAAO;IAC/C,MAAM,CAAC,MAAM,UAAK;gBAEN,GAAG,EAAE,OAAO;IAIxB,KAAK,CACH,UAAU,EAAE,uBAAuB,GAAG,IAAI,GAAG,SAAS,EACtD,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,iBAAiB,GAAG,IAAI,EAChC,QAAQ,EAAE,MAAM,GACf,YAAY;IAIf,OAAO,CAAC,QAAQ,EAAE,kBAAkB,EAAE,KAAK,EAAE,kBAAkB,GAAG,kBAAkB;CAGrF"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { ReasoningWaitProjection } from './reasoning-wait-projection.ts';
|
|
2
|
+
export type ReasoningWaitAppearance = {
|
|
3
|
+
readonly phase: 'idle';
|
|
4
|
+
} | {
|
|
5
|
+
readonly phase: 'thermometer';
|
|
6
|
+
readonly t: number;
|
|
7
|
+
readonly height: number;
|
|
8
|
+
readonly color: string;
|
|
9
|
+
};
|
|
10
|
+
export interface StreamClockAnchor {
|
|
11
|
+
readonly stamp: string;
|
|
12
|
+
readonly identity: string;
|
|
13
|
+
readonly eventElapsed: number;
|
|
14
|
+
readonly observedAt: number;
|
|
15
|
+
readonly renderedElapsed: number;
|
|
16
|
+
}
|
|
17
|
+
export type ReasoningWaitState = {
|
|
18
|
+
readonly phase: 'idle';
|
|
19
|
+
} | {
|
|
20
|
+
readonly phase: 'thermometer';
|
|
21
|
+
readonly identity: string;
|
|
22
|
+
readonly t: number;
|
|
23
|
+
readonly height: number;
|
|
24
|
+
readonly color: string;
|
|
25
|
+
} | {
|
|
26
|
+
readonly phase: 'drain';
|
|
27
|
+
readonly identity: string;
|
|
28
|
+
readonly t: number;
|
|
29
|
+
readonly height: number;
|
|
30
|
+
readonly color: string;
|
|
31
|
+
readonly fromHeight: number;
|
|
32
|
+
readonly startedAt: number;
|
|
33
|
+
};
|
|
34
|
+
export interface ReasoningWaitInput {
|
|
35
|
+
readonly projection: ReasoningWaitProjection | null | undefined;
|
|
36
|
+
readonly elapsed: number;
|
|
37
|
+
readonly frameNow: number;
|
|
38
|
+
readonly reducedMotion: boolean;
|
|
39
|
+
readonly identity: string;
|
|
40
|
+
}
|
|
41
|
+
export interface SessionClock {
|
|
42
|
+
readonly elapsed: number;
|
|
43
|
+
readonly anchor: StreamClockAnchor | null;
|
|
44
|
+
}
|
|
45
|
+
export declare function reasoningWaitAppearance(projection: ReasoningWaitProjection | null | undefined, elapsed: number): ReasoningWaitAppearance;
|
|
46
|
+
export declare function extrapolateProjectionClock(projection: ReasoningWaitProjection | null | undefined, frameNow: number, anchor: StreamClockAnchor | null, identity: string): SessionClock;
|
|
47
|
+
export declare function advanceReasoningWait(previous: ReasoningWaitState, input: ReasoningWaitInput): ReasoningWaitState;
|
|
48
|
+
//# sourceMappingURL=thermometer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thermometer.d.ts","sourceRoot":"","sources":["../../../src/client/thermometer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAA;AAa7E,MAAM,MAAM,uBAAuB,GAC/B;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC1B;IACA,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAA;IAC7B,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB,CAAA;AAEH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;CACjC;AAED,MAAM,MAAM,kBAAkB,GAC1B;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC1B;IACA,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAA;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB,GACC;IACA,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAC3B,CAAA;AAEH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,UAAU,EAAE,uBAAuB,GAAG,IAAI,GAAG,SAAS,CAAA;IAC/D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAA;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAA;CAC1C;AAED,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,uBAAuB,GAAG,IAAI,GAAG,SAAS,EACtD,OAAO,EAAE,MAAM,GACd,uBAAuB,CASzB;AAED,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,uBAAuB,GAAG,IAAI,GAAG,SAAS,EACtD,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,iBAAiB,GAAG,IAAI,EAChC,QAAQ,EAAE,MAAM,GACf,YAAY,CAad;AAED,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,kBAAkB,EAC5B,KAAK,EAAE,kBAAkB,GACxB,kBAAkB,CAiCpB"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type RefObject } from 'react';
|
|
2
|
+
/** Keep a Portal layer attached across ModelSelect and composer reconstruction. */
|
|
3
|
+
export declare function useModelTrigger(anchorRef: RefObject<HTMLElement | null>): HTMLElement | null;
|
|
4
|
+
//# sourceMappingURL=use-model-trigger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-model-trigger.d.ts","sourceRoot":"","sources":["../../../src/client/use-model-trigger.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAOjE,mFAAmF;AACnF,wBAAgB,eAAe,CAAC,SAAS,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,WAAW,GAAG,IAAI,CA4B5F"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dsh-thinkbar node half. This UI-only plugin needs a host Loader row so the
|
|
3
|
+
* DSH client-module scanner can discover its browser bundle.
|
|
4
|
+
*/
|
|
5
|
+
/** Host plugin body: dsh-thinkbar has no host-side behavior. */
|
|
6
|
+
export declare function apply(): void;
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,gEAAgE;AAChE,wBAAgB,KAAK,IAAI,IAAI,CAAG"}
|
package/package.json
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dsh-thinkbar",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Reasoning-wait thinking indicator for the DeepSeek Harness web composer",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./lib/index.js",
|
|
7
|
+
"types": "./lib/types/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./lib/types/index.d.ts",
|
|
11
|
+
"default": "./lib/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./client": {
|
|
14
|
+
"types": "./lib/types/client/index.d.ts",
|
|
15
|
+
"default": "./lib/client.cjs"
|
|
16
|
+
},
|
|
17
|
+
"./package.json": "./package.json"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"lib",
|
|
21
|
+
"cordis.patch.yml"
|
|
22
|
+
],
|
|
23
|
+
"dsh": {
|
|
24
|
+
"bundle": {
|
|
25
|
+
"patch": "./cordis.patch.yml"
|
|
26
|
+
},
|
|
27
|
+
"client": {
|
|
28
|
+
"inject": [
|
|
29
|
+
"@deepseek-ai/dsh-client-runtime",
|
|
30
|
+
"@deepseek-ai/dsh-client-ui-conversation",
|
|
31
|
+
"@deepseek-ai/dsh-client-ui-model-selection"
|
|
32
|
+
],
|
|
33
|
+
"platform": "web"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"engines": {
|
|
37
|
+
"node": "^22.19.0 || >=24.0.0"
|
|
38
|
+
},
|
|
39
|
+
"license": "MIT",
|
|
40
|
+
"repository": {
|
|
41
|
+
"type": "git",
|
|
42
|
+
"url": "git+https://github.com/tower1229/dsh-thinkbar.git"
|
|
43
|
+
},
|
|
44
|
+
"homepage": "https://github.com/tower1229/dsh-thinkbar#readme",
|
|
45
|
+
"bugs": {
|
|
46
|
+
"url": "https://github.com/tower1229/dsh-thinkbar/issues"
|
|
47
|
+
},
|
|
48
|
+
"keywords": [
|
|
49
|
+
"deepseek",
|
|
50
|
+
"deepseek-harness",
|
|
51
|
+
"dsh",
|
|
52
|
+
"dsh-plugin",
|
|
53
|
+
"reasoning"
|
|
54
|
+
],
|
|
55
|
+
"publishConfig": {
|
|
56
|
+
"access": "public"
|
|
57
|
+
},
|
|
58
|
+
"peerDependencies": {
|
|
59
|
+
"@deepseek-ai/cordis": "4.0.1",
|
|
60
|
+
"@deepseek-ai/dsh-client-runtime": "0.1.1-rc.2",
|
|
61
|
+
"@deepseek-ai/dsh-client-ui-conversation": "0.1.1-rc.2",
|
|
62
|
+
"@deepseek-ai/dsh-client-ui-model-selection": "0.1.1-rc.2",
|
|
63
|
+
"react": "^18.2.0",
|
|
64
|
+
"react-dom": "^18.2.0"
|
|
65
|
+
},
|
|
66
|
+
"devDependencies": {
|
|
67
|
+
"@deepseek-ai/cordis": "4.0.1",
|
|
68
|
+
"@deepseek-ai/dsh-api-remotes": "0.1.1-rc.2",
|
|
69
|
+
"@deepseek-ai/dsh-client-runtime": "0.1.1-rc.2",
|
|
70
|
+
"@deepseek-ai/dsh-client-ui-conversation": "0.1.1-rc.2",
|
|
71
|
+
"@deepseek-ai/dsh-client-ui-model-selection": "0.1.1-rc.2",
|
|
72
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.1.1-rc.2",
|
|
73
|
+
"@deepseek-ai/dsh-llm-retry": "0.1.1-rc.2",
|
|
74
|
+
"@testing-library/react": "^16.3.2",
|
|
75
|
+
"@types/node": "^24.0.0",
|
|
76
|
+
"@types/react": "~18.3.1",
|
|
77
|
+
"@types/react-dom": "~18.3.1",
|
|
78
|
+
"jsdom": "29.1.1",
|
|
79
|
+
"lightningcss": "^1.32.0",
|
|
80
|
+
"publint": "^0.3.21",
|
|
81
|
+
"react": "^18.2.0",
|
|
82
|
+
"react-dom": "^18.2.0",
|
|
83
|
+
"tsdown": "^0.22.2",
|
|
84
|
+
"typescript": "^6.0.3",
|
|
85
|
+
"vitest": "^4.1.8"
|
|
86
|
+
},
|
|
87
|
+
"scripts": {
|
|
88
|
+
"clean": "node scripts/clean.mjs",
|
|
89
|
+
"typecheck": "tsc --noEmit",
|
|
90
|
+
"test": "vitest run",
|
|
91
|
+
"build": "pnpm run clean && tsc -p tsconfig.build.json && tsdown",
|
|
92
|
+
"pack:check": "pnpm run build && node scripts/verify-package.mjs",
|
|
93
|
+
"verify": "pnpm run typecheck && pnpm run test && pnpm run pack:check && publint --pack npm --strict"
|
|
94
|
+
}
|
|
95
|
+
}
|