dsh-better-display 0.3.0 → 0.3.2

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.
Files changed (45) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.en.md +3 -3
  3. package/README.md +3 -3
  4. package/compat/harness-rc2.json +56 -18
  5. package/docs/official-rendering-bridge.md +1 -1
  6. package/lib/client.js +4702 -4605
  7. package/lib/client.js.map +1 -1
  8. package/lib/dsh-better-display.js +4 -2
  9. package/lib/types/client/OfficialContent.d.ts.map +1 -1
  10. package/lib/types/client/OfficialContent.js +16 -5
  11. package/lib/types/client/OfficialContent.js.map +1 -1
  12. package/lib/types/client/Reader.d.ts.map +1 -1
  13. package/lib/types/client/Reader.js +6 -7
  14. package/lib/types/client/Reader.js.map +1 -1
  15. package/lib/types/client/ToolActivity.js +3 -3
  16. package/lib/types/client/ToolActivity.js.map +1 -1
  17. package/lib/types/client/native/ContextInjectionRow.d.ts +2 -2
  18. package/lib/types/client/native/ContextInjectionRow.d.ts.map +1 -1
  19. package/lib/types/client/native/ContextInjectionRow.js +2 -2
  20. package/lib/types/client/native/ContextInjectionRow.js.map +1 -1
  21. package/lib/types/client/native/ReferenceIcon.js +3 -3
  22. package/lib/types/client/native/ReferenceIcon.js.map +1 -1
  23. package/lib/types/client/native/tool-call-model.js +1 -1
  24. package/lib/types/client/native/tool-call-model.js.map +1 -1
  25. package/lib/types/client/official-slots.js +1 -1
  26. package/lib/types/client/official-slots.js.map +1 -1
  27. package/lib/types/client/primitive-labels.d.ts.map +1 -1
  28. package/lib/types/client/primitive-labels.js +3 -2
  29. package/lib/types/client/primitive-labels.js.map +1 -1
  30. package/lib/types/client/tool-activity.js +2 -2
  31. package/lib/types/client/tool-activity.js.map +1 -1
  32. package/package.json +16 -16
  33. package/scripts/verify-official-bridge.mjs +6 -4
  34. package/src/client/OfficialContent.tsx +19 -7
  35. package/src/client/Reader.module.css +12 -0
  36. package/src/client/Reader.tsx +8 -9
  37. package/src/client/ToolActivity.tsx +3 -3
  38. package/src/client/native/ContextInjectionRow.tsx +4 -4
  39. package/src/client/native/ReferenceIcon.tsx +3 -3
  40. package/src/client/native/tool-call-model.ts +1 -1
  41. package/src/client/official-slots.tsx +1 -1
  42. package/src/client/primitive-labels.ts +3 -2
  43. package/src/client/tool-activity.ts +2 -2
  44. package/tests/browser-auto-fold.tsx +1 -1
  45. package/tests/browser-official-bridge.tsx +17 -9
@@ -14,22 +14,23 @@ export const markdownLabels: MarkdownLabels = {
14
14
  };
15
15
 
16
16
  export const readBlockLabels: ReadBlockLabels = {
17
+ codeLabel: '代码', wrapLabel: '自动换行', unwrapLabel: '不换行',
17
18
  window: (shown, total) => `显示 ${shown} / ${total} 行`,
18
19
  copy: '复制', copied: '已复制', collapseAria: '收起文件内容',
19
20
  expandAria: hidden => `展开其余 ${hidden} 行`, collapse: '收起', expand: hidden => `展开其余 ${hidden} 行`,
20
21
  };
21
22
 
22
23
  export const terminalBlockLabels: TerminalBlockLabels = {
23
- signal: signal => `信号 ${signal}`, exitCode: code => `退出码 ${code}`,
24
+ signal: signal => `信号 ${signal}`, exitCode: code => `退出码 ${code}`, noExitCode: '无退出码',
24
25
  running: '执行中', failed: '失败', done: '已完成', copy: '复制', copied: '已复制',
25
26
  noOutput: '没有输出', collapseAria: '收起命令输出', collapse: '收起',
26
27
  expandAria: hidden => `展开其余 ${hidden} 行`, expand: hidden => `展开其余 ${hidden} 行`,
27
28
  };
28
29
 
29
30
  export const diffBlockLabels: DiffBlockLabels = {
31
+ codeLabel: '代码', wrapLabel: '自动换行', unwrapLabel: '不换行',
30
32
  copy: '复制', copied: '已复制', collapseAria: '收起差异', collapse: '收起',
31
33
  expandAria: hidden => `展开其余 ${hidden} 行`, expand: hidden => `展开其余 ${hidden} 行`,
32
- files: count => `${count} 个文件`,
33
34
  };
34
35
 
35
36
  export const searchBlockLabels: SearchBlockLabels = {
@@ -95,13 +95,13 @@ export function toolIdentity(entry: Pick<ToolActivityEntry, 'block' | 'draft'>)
95
95
  const block = entry.block;
96
96
  return {
97
97
  name: block ? 'kind' in block ? block.call?.name ?? entry.draft?.name ?? '工具调用' : block.name : entry.draft?.name ?? '工具调用',
98
- raw: block ? 'kind' in block ? block.call?.argsRaw ?? entry.draft?.argsRaw ?? '' : block.argsRaw : entry.draft?.argsRaw ?? '',
98
+ raw: block ? 'kind' in block ? block.call?.argsRaw ?? entry.draft?.argsRaw ?? '' : ('argsRaw' in block ? block.argsRaw : '') : entry.draft?.argsRaw ?? '',
99
99
  };
100
100
  }
101
101
 
102
102
  /** Name and raw arguments of any call block, whether it has landed or is pending. */
103
103
  function childIdentity(block: ToolCallBlock): { name?: string; raw: string } {
104
- if (!block || !('kind' in block)) return { name: block?.name, raw: block?.argsRaw ?? '' };
104
+ if (!block || !('kind' in block)) return { name: block?.name, raw: block && 'argsRaw' in block ? block.argsRaw : '' };
105
105
  return { name: block.call?.name, raw: block.call?.argsRaw ?? '' };
106
106
  }
107
107
 
@@ -43,7 +43,7 @@ const useReaderStore: ReaderProps['useStore'] = selector => selector(useSyncExte
43
43
  const props = {
44
44
  sessionId: 'auto-fold-fixture', useChat: selector => selector(chat),
45
45
  useSession: selector => selector(sessionSnapshot), useSessions: selector => selector(sessionsSnapshot),
46
- useSessionPendingInteraction: selector => selector(pending),
46
+ useSessionStatus: selector => selector(new Map([['auto-fold-fixture', { running: true, pendingInteraction: pending.get('auto-fold-fixture'), completionUnread: false }]])),
47
47
  useStore: useReaderStore, actions: session.actions, openPrefs: prefs,
48
48
  t: key => key, renderSlot: (_name, _owner, options) => options?.fallback ?? null,
49
49
  renderSlotChain: (_name, _owner, options) => options?.fallback ?? null,
@@ -10,8 +10,10 @@ import { readImageToolview } from '@fixture/read-image-row';
10
10
  import { en as conversationEn } from '@fixture/tool-locale';
11
11
  import { officialChildren, installOfficialSlots, OFFICIAL_SEATS } from '../src/client/official-slots.js';
12
12
  import { OfficialActions, OfficialTool } from '../src/client/OfficialContent.js';
13
- import { Deliverables } from '@fixture/deliverables';
13
+ import { DeliverablesTail } from '@fixture/deliverables';
14
14
  import { zh as deliverablesZh, en as deliverablesEn } from '@fixture/deliverables-locale';
15
+ import { FileRouteAction } from '@fixture/open-in-app-action';
16
+ import { zh as openInAppZh, en as openInAppEn } from '@fixture/open-in-app-locale';
15
17
  import { CopyAnswer } from '../src/client/Blocks.js';
16
18
  import { MotionMarkdown } from '../src/client/word-motion.js';
17
19
  import css from '../src/client/Reader.module.css';
@@ -32,7 +34,7 @@ const source = <T,>(initial: T) => {
32
34
  };
33
35
  const localeSource = source({ revision: 0 });
34
36
  let language = 'zh';
35
- const dictionaries: Record<string, any> = { deliverables: { zh: deliverablesZh, en: deliverablesEn }, conversation: { zh: conversationEn, en: conversationEn } };
37
+ const dictionaries: Record<string, any> = { deliverables: { zh: deliverablesZh, en: deliverablesEn }, 'open-in-app': { zh: openInAppZh, en: openInAppEn }, conversation: { zh: conversationEn, en: conversationEn } };
36
38
  const locale = {
37
39
  ...localeSource,
38
40
  register(ns: string, dictionary: any) { dictionaries[ns] = dictionary; return () => { delete dictionaries[ns]; }; },
@@ -60,7 +62,7 @@ ctx.provide('remote', {
60
62
  });
61
63
  const binding = { key: 'session-a', ctx: new Context(), hooks: {}, keyedHooks: {}, props: { sessionId: 'session-a' } };
62
64
  const current = source(binding);
63
- slots.installScope('session', { current, resolve: (id: string) => id === binding.key ? binding : undefined, renderArea: (_b: any, props: any) => props.children });
65
+ slots.installScope('session', { current, bindingSource: (target: any) => source(target === binding.key ? binding : undefined), renderArea: (_b: any, props: any) => props.children });
64
66
  const toolBlock = {
65
67
  kind: 'tool-result', callId: 'read-1', call: { name: 'read', args: { file_path: '/fixture/sample.ts', offset: 12 }, argsRaw: '{"file_path":"/fixture/sample.ts","offset":12}' },
66
68
  content: [{ type: 'text', text: '<path>/fixture/sample.ts</path>\n<type>file</type>\n<content>\n12: export const value = 1;\n</content>' }], isError: false, subCalls: [], time: 100, callTime: 10,
@@ -74,7 +76,7 @@ let stopMirror = () => {};
74
76
  slots.register({ name: 'root', children: {
75
77
  'conversation.chat.assistant-actions': { kind: 'list', scope: 'session' },
76
78
  'tool.call.toolview': { kind: 'keyed', scope: 'session' },
77
- 'conversation.chat.turnTail': { kind: 'chain', scope: 'session' },
79
+ 'conversation.chat.turnTail': { kind: 'list', scope: 'session' },
78
80
  'conversation.chat.node': { kind: 'keyed', scope: 'session', inject: { hooks: { turnData: (_s: any, value: any) => () => value } } },
79
81
  'conversation.message.images': { kind: 'single', scope: 'session' },
80
82
  'conversation.input.overlay': { kind: 'list', scope: 'session' },
@@ -90,12 +92,18 @@ slots.provideRoot({ hooks: { sessions: source({ byId: { 'session-a': { cwd: '/fi
90
92
  const artifact = { path: '/fixture/report.pdf', description: '演示报告', seq: 42, index: 0 };
91
93
  const presentedOpen = source({});
92
94
  const presentedHost = source({ available: true, fileManager: 'finder' });
93
- slots.register({ name: 'conversation.chat.turnTail', locale: 'deliverables',
94
- select: () => ({ produced: ['/fixture/sample.ts'], presented: [artifact] }),
95
- inject: () => ({ hooks: { presentedOpen, presentedHost }, reloadPresentedHost: async () => {},
95
+ const changesDiff = source({});
96
+ const changesSummary = source({});
97
+ const showCodeDiff = source(false);
98
+ slots.register({ name: 'conversation.chat.turnTail', id: '@deepseek-ai/dsh-client-ui-deliverables', locale: 'deliverables',
99
+ children: { 'deliverables.file.actions': { kind: 'list', scope: 'session' } },
100
+ inject: () => ({ hooks: { changesDiff, showCodeDiff, presentedOpen, presentedHost, changesSummary },
101
+ loadChangesDiff: async () => {}, reloadPresentedHost: async () => {}, loadChangesSummary: async () => {},
96
102
  openPresented: async (...args: any[]) => { observations.opens.push(['presented', ...args]); },
103
+ openChanged: async () => {}, openChangesReview: () => {},
97
104
  }),
98
- }, Deliverables);
105
+ }, DeliverablesTail);
106
+ slots.register({ name: 'deliverables.file.actions', id: 'open-in-app', locale: 'open-in-app' }, FileRouteAction);
99
107
  let liveDetail = source('initial');
100
108
  const storeHandle = { create: () => {
101
109
  observations.mounts++;
@@ -122,7 +130,7 @@ function ReaderFixture({ renderSlot, renderSlotChain }: any) {
122
130
  <CopyAnswer blocks={[{ kind: 'text', text }]} extraActions={<OfficialActions official={official} messageId={'message-1' as any} />} />
123
131
  </article>
124
132
  <div data-reader-tool><OfficialTool {...blockProps} official={official} renderSlotChain={renderSlotChain} block={toolBlock as any} toolName="read" fallback={<span>fallback</span>} /></div>
125
- {renderSlotChain(OFFICIAL_SEATS.tail, { openFile: blockProps.openFile, readerProducedPaths: ['/fixture/sample.ts'] })}
133
+ {renderSlot(OFFICIAL_SEATS.tail, { turn: { data: new Map([['deliverables', { changes: null, presented: [artifact] }]]) }, seq: 43, openFile: blockProps.openFile, readerProducedPaths: ['/fixture/sample.ts'] })}
126
134
  {renderSlot(OFFICIAL_SEATS.nodes, {}, { entryKey: 'future-widget', hookContext: 'turn-context' })}
127
135
  <button onClick={() => setText(text + '\n\n继续输出。')}>Append text</button>
128
136
  </div></main>;