dsh-side-chat-plus 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +317 -0
  3. package/README.zh.md +261 -0
  4. package/cordis.patch.yml +8 -0
  5. package/dsh.plugin.json +16 -0
  6. package/lib/client-registry.js +2949 -0
  7. package/lib/client-registry.js.map +1 -0
  8. package/lib/client.js +2949 -0
  9. package/lib/client.js.map +1 -0
  10. package/lib/index.js +840 -0
  11. package/lib/types/client/api.d.ts +218 -0
  12. package/lib/types/client/attachments/AttachmentRail.d.ts +39 -0
  13. package/lib/types/client/attachments/DropOverlay.d.ts +18 -0
  14. package/lib/types/client/attachments/ImageLightbox.d.ts +20 -0
  15. package/lib/types/client/attachments/MessageImage.d.ts +38 -0
  16. package/lib/types/client/attachments/index.d.ts +18 -0
  17. package/lib/types/client/index.d.ts +6 -0
  18. package/lib/types/client/locales.d.ts +178 -0
  19. package/lib/types/context-types.d.ts +390 -0
  20. package/lib/types/index.d.ts +7 -0
  21. package/lib/types/settings-shared.d.ts +24 -0
  22. package/lib/types/trust-fence.d.ts +20 -0
  23. package/lib/types/wire.d.ts +25 -0
  24. package/package.json +114 -0
  25. package/src/client/api.ts +112 -0
  26. package/src/client/attachments/AttachmentRail.module.css +89 -0
  27. package/src/client/attachments/AttachmentRail.tsx +173 -0
  28. package/src/client/attachments/DropOverlay.module.css +38 -0
  29. package/src/client/attachments/DropOverlay.tsx +62 -0
  30. package/src/client/attachments/ImageLightbox.module.css +44 -0
  31. package/src/client/attachments/ImageLightbox.tsx +58 -0
  32. package/src/client/attachments/MessageImage.module.css +61 -0
  33. package/src/client/attachments/MessageImage.tsx +120 -0
  34. package/src/client/attachments/index.ts +19 -0
  35. package/src/client/client.module.css +1032 -0
  36. package/src/client/index.tsx +1966 -0
  37. package/src/client/layout.css +16 -0
  38. package/src/client/locales.ts +181 -0
  39. package/src/context-types.ts +384 -0
  40. package/src/css-modules.d.ts +10 -0
  41. package/src/index.ts +840 -0
  42. package/src/settings-shared.ts +33 -0
  43. package/src/trust-fence.ts +70 -0
  44. package/src/wire.ts +81 -0
@@ -0,0 +1,218 @@
1
+ /**
2
+ * Client API client for the /sidechat JSON routes (same fetch pattern the
3
+ * better-sidebar built-ins use). All requests are same-origin POSTs; the host
4
+ * fence (loopback/trusted authority) passes them naturally.
5
+ */
6
+ /** One API failure envelope. */
7
+ export interface SidechatApiError {
8
+ code: string;
9
+ message: string;
10
+ }
11
+ /** The unwrapped success value of one API method. */
12
+ export type SidechatResult<T> = {
13
+ ok: true;
14
+ value: T;
15
+ } | {
16
+ ok: false;
17
+ error: SidechatApiError;
18
+ };
19
+ /** Side-chat list row. */
20
+ export interface SidechatListItem {
21
+ childId: string;
22
+ running: boolean;
23
+ runningSince?: number;
24
+ }
25
+ /** Browser-submitted prompt content part (text or base64 image). */
26
+ export type PromptContentPart = {
27
+ type: 'text';
28
+ text: string;
29
+ } | {
30
+ type: 'image';
31
+ mediaType: string;
32
+ data: string;
33
+ name?: string;
34
+ };
35
+ /** One durable image reference returned by the host transcript. */
36
+ export interface SidechatImageRef {
37
+ attachmentId: string;
38
+ mediaType: string;
39
+ bytes: number;
40
+ width: number;
41
+ height: number;
42
+ name?: string;
43
+ }
44
+ /** One transcript message block. */
45
+ export type SidechatMessageBlock = {
46
+ type: 'text';
47
+ text: string;
48
+ } | {
49
+ type: 'image';
50
+ ref: SidechatImageRef;
51
+ } | {
52
+ type: 'reasoning';
53
+ text: string;
54
+ };
55
+ /** One transcript message. */
56
+ export interface SidechatMessage {
57
+ role: 'user' | 'assistant';
58
+ blocks: SidechatMessageBlock[];
59
+ }
60
+ /** Model / effort directory (provider groups → models → reasoning efforts). */
61
+ export interface SidechatDirectory {
62
+ groups: Array<{
63
+ id: string;
64
+ name: string;
65
+ models: Array<{
66
+ id: string;
67
+ name: string;
68
+ description?: string;
69
+ reasoning?: {
70
+ efforts: Array<{
71
+ id: string;
72
+ name: string;
73
+ }>;
74
+ defaultEffort?: string;
75
+ };
76
+ }>;
77
+ }>;
78
+ }
79
+ /** Permission options. */
80
+ export interface SidechatPermissions {
81
+ options: Array<{
82
+ value: string;
83
+ name: string;
84
+ description?: string;
85
+ }>;
86
+ current: string;
87
+ }
88
+ export declare const api: {
89
+ start: (args: {
90
+ parentSessionId: string;
91
+ content: PromptContentPart[];
92
+ lookupEnabled: boolean;
93
+ provider?: string;
94
+ model?: string;
95
+ reasoningEffort?: string;
96
+ preset?: string;
97
+ }) => Promise<SidechatResult<{
98
+ childId: string;
99
+ provider: string;
100
+ model: string;
101
+ reasoningEffort?: string;
102
+ }>>;
103
+ followup: (args: {
104
+ childId: string;
105
+ content: PromptContentPart[];
106
+ lookupEnabled: boolean;
107
+ }) => Promise<SidechatResult<{
108
+ accepted: true;
109
+ }>>;
110
+ list: (args: {
111
+ parentSessionId: string;
112
+ }) => Promise<SidechatResult<{
113
+ items: SidechatListItem[];
114
+ }>>;
115
+ history: (args: {
116
+ childId: string;
117
+ }) => Promise<SidechatResult<{
118
+ messages: SidechatMessage[];
119
+ }>>;
120
+ stop: (args: {
121
+ childId: string;
122
+ }) => Promise<SidechatResult<{
123
+ accepted: true;
124
+ }>>;
125
+ selectModel: (args: {
126
+ childId: string;
127
+ provider: string;
128
+ model: string;
129
+ reasoningEffort?: string;
130
+ }) => Promise<SidechatResult<{
131
+ accepted: true;
132
+ }>>;
133
+ selectPermission: (args: {
134
+ childId: string;
135
+ presetName: string;
136
+ }) => Promise<SidechatResult<{
137
+ accepted: true;
138
+ }>>;
139
+ summarize: (args: {
140
+ parentSessionId: string;
141
+ text: string;
142
+ provider?: string;
143
+ model?: string;
144
+ reasoningEffort?: string;
145
+ locale?: string;
146
+ }) => Promise<SidechatResult<{
147
+ summary: string;
148
+ }>>;
149
+ inject: (args: {
150
+ parentSessionId: string;
151
+ text: string;
152
+ summary?: string;
153
+ }) => Promise<SidechatResult<{
154
+ accepted: true;
155
+ }>>;
156
+ directory: () => Promise<SidechatResult<SidechatDirectory>>;
157
+ permissions: () => Promise<SidechatResult<SidechatPermissions>>;
158
+ limits: () => Promise<SidechatResult<{
159
+ mediaTypes: string[];
160
+ maxImageBytes: number;
161
+ maxImagesPerMessage: number;
162
+ maxMessageImageBytes: number;
163
+ maxImagePixels: number;
164
+ }>>;
165
+ attachment: (args: {
166
+ childId: string;
167
+ attachmentId: string;
168
+ }) => Promise<SidechatResult<{
169
+ mediaType: string;
170
+ data: string;
171
+ }>>;
172
+ inherit: (args: {
173
+ parentSessionId: string;
174
+ }) => Promise<SidechatResult<{
175
+ provider: string;
176
+ model: string;
177
+ reasoningEffort?: string;
178
+ }>>;
179
+ commands: (args: {
180
+ childId: string;
181
+ }) => Promise<SidechatResult<{
182
+ commands: Array<{
183
+ name: string;
184
+ description: string;
185
+ }>;
186
+ }>>;
187
+ command: (args: {
188
+ childId: string;
189
+ line: string;
190
+ }) => Promise<SidechatResult<{
191
+ executed: boolean;
192
+ }>>;
193
+ state: (args: {
194
+ childId: string;
195
+ }) => Promise<SidechatResult<{
196
+ plan: {
197
+ active: boolean;
198
+ pending: boolean;
199
+ };
200
+ goal: {
201
+ id: string;
202
+ objective: string;
203
+ } | null;
204
+ }>>;
205
+ settingsGet: () => Promise<SidechatResult<{
206
+ value?: unknown;
207
+ revision?: number;
208
+ }>>;
209
+ settingsUpdate: (patch: Record<string, unknown>, expectedRevision?: number) => Promise<SidechatResult<{
210
+ value?: unknown;
211
+ revision?: number;
212
+ }>>;
213
+ dispose: (args: {
214
+ childId: string;
215
+ }) => Promise<SidechatResult<{
216
+ accepted: true;
217
+ }>>;
218
+ };
@@ -0,0 +1,39 @@
1
+ /** One rail thumbnail; strings arrive resolved (zero-cordis atom). */
2
+ export interface AttachmentRailItem {
3
+ /** Stable identity for the React key. */
4
+ id: string;
5
+ /** Object or data URL rendered as the thumbnail. */
6
+ previewUrl: string;
7
+ /** Image alt text (display name with the owner's fallback applied). */
8
+ alt: string;
9
+ /** Accessible label of the item's remove control. */
10
+ removeLabel: string;
11
+ }
12
+ /** Rail-level strings the owner resolves from its own locale namespace. */
13
+ export interface AttachmentRailLabels {
14
+ /** Accessible name of the rail group. */
15
+ group: string;
16
+ /** Thumbnail tooltip inviting the original-image preview. */
17
+ open: string;
18
+ /** Accessible label of the left paging arrow. */
19
+ scrollLeft: string;
20
+ /** Accessible label of the right paging arrow. */
21
+ scrollRight: string;
22
+ }
23
+ /**
24
+ * Horizontal thumbnail rail over the caller's draft attachments.
25
+ *
26
+ * The rail scrolls with its scrollbar hidden; overflow is announced by edge
27
+ * arrows recomputed from scroll geometry on scroll, item-count changes, and
28
+ * rail size changes (a ResizeObserver on the rail element, so sidebar or panel
29
+ * resizes count, not only window resizes). A vertical wheel pans the rail
30
+ * horizontally and is consumed exclusively, a newly added item is revealed at
31
+ * the rail's end, and each thumbnail opens on a single click while its remove
32
+ * control sits inside the card. The owner decides mounting.
33
+ */
34
+ export declare function AttachmentRail<T extends AttachmentRailItem>({ items, labels, onOpen, onRemove }: {
35
+ items: readonly T[];
36
+ labels: AttachmentRailLabels;
37
+ onOpen: (item: T) => void;
38
+ onRemove: (item: T) => void;
39
+ }): import("react").JSX.Element;
@@ -0,0 +1,18 @@
1
+ /** Drop-overlay strings the owner resolves from its own locale namespace. */
2
+ export interface DropOverlayLabels {
3
+ /** Headline inviting the drop, or naming why it is unavailable. */
4
+ title: string;
5
+ /** Limits line under the title; shown only while drops are accepted. */
6
+ desc?: string | undefined;
7
+ }
8
+ /**
9
+ * Full-viewport invitation shown while a file drag is over the page.
10
+ * Decoration only: `pointer-events: none` keeps drag targeting on the page
11
+ * below, so the owner's document-level listeners keep an accurate enter/leave
12
+ * count and own accept/reject. Rendered through a body portal for the same
13
+ * transformed-ancestor reason as the lightbox.
14
+ */
15
+ export declare function DropOverlay({ disabled, labels }: {
16
+ disabled: boolean;
17
+ labels: DropOverlayLabels;
18
+ }): import("react").ReactPortal;
@@ -0,0 +1,20 @@
1
+ /** Preview strings the owner resolves from its own locale namespace. */
2
+ export interface ImageLightboxLabels {
3
+ /** Accessible name of the preview dialog. */
4
+ dialog: string;
5
+ /** Accessible label of the close control. */
6
+ close: string;
7
+ }
8
+ /**
9
+ * Document-level original-image preview opened by clicking a thumbnail.
10
+ * Closes on Escape, backdrop press, or the close control, and restores focus
11
+ * to the opener on unmount. Rendered through a body portal: an opener inside
12
+ * a transformed or filtered ancestor would otherwise trap the fixed backdrop
13
+ * in that ancestor's box instead of covering the viewport.
14
+ */
15
+ export declare function ImageLightbox({ src, alt, labels, onClose }: {
16
+ src: string;
17
+ alt: string;
18
+ labels: ImageLightboxLabels;
19
+ onClose: () => void;
20
+ }): import("react").ReactPortal;
@@ -0,0 +1,38 @@
1
+ import type { SidechatImageRef } from '../api.ts';
2
+ import type { ImageLightboxLabels } from './ImageLightbox.tsx';
3
+ /** Loads one durable image's bytes into a displayable URL. */
4
+ export type ImageLoader = (ref: SidechatImageRef) => Promise<string>;
5
+ /** Message-image strings the owner resolves from its own locale namespace. */
6
+ export interface MessageImageLabels {
7
+ /** Fallback display name for an unnamed image. */
8
+ image: string;
9
+ /** Thumbnail tooltip inviting the original-image preview. */
10
+ open: string;
11
+ /** Accessible thumbnail label; receives the image's display name. */
12
+ openNamed: (label: string) => string;
13
+ /** Loading placeholder shown until bytes resolve. */
14
+ loading: string;
15
+ /** Retry-control label shown when the load fails. */
16
+ loadFailed: string;
17
+ /** Lightbox strings forwarded to the opened preview. */
18
+ lightbox: ImageLightboxLabels;
19
+ }
20
+ /**
21
+ * Compact history renderer with retryable loading and click-to-open original
22
+ * preview. A lone image renders at its `singleFit` size; an image among
23
+ * several renders as a fixed 64px square tile.
24
+ */
25
+ export declare function MessageImage({ image, load, variant, labels }: {
26
+ image: SidechatImageRef;
27
+ load: ImageLoader;
28
+ variant: 'single' | 'tile';
29
+ labels: MessageImageLabels;
30
+ }): import("react").JSX.Element;
31
+ /** Wrapping image group: a lone image renders large, several render as 64px
32
+ * square tiles. */
33
+ export declare function ImageGallery({ images, load, align, labels }: {
34
+ images: readonly SidechatImageRef[];
35
+ load: ImageLoader;
36
+ align: 'start' | 'end';
37
+ labels: MessageImageLabels;
38
+ }): import("react").JSX.Element | null;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Image presentation owned by this plugin.
3
+ *
4
+ * The DSH attachment UI package registers these through conversation slots and
5
+ * exports no React components (`packages/client/AGENTS.md`: a feature plugin
6
+ * MUST NOT runtime-import another feature plugin's values — UI crosses
7
+ * packages through slots). A standalone side panel sits outside the
8
+ * conversation slot tree and cannot reach those slots, so it carries its own
9
+ * presentation, built only on `ui-primitives` (a sanctioned static owner).
10
+ */
11
+ export { AttachmentRail } from './AttachmentRail.tsx';
12
+ export type { AttachmentRailItem, AttachmentRailLabels } from './AttachmentRail.tsx';
13
+ export { DropOverlay } from './DropOverlay.tsx';
14
+ export type { DropOverlayLabels } from './DropOverlay.tsx';
15
+ export { ImageGallery, MessageImage } from './MessageImage.tsx';
16
+ export type { ImageLoader, MessageImageLabels } from './MessageImage.tsx';
17
+ export { ImageLightbox } from './ImageLightbox.tsx';
18
+ export type { ImageLightboxLabels } from './ImageLightbox.tsx';
@@ -0,0 +1,6 @@
1
+ import type { Context } from '../context-types.ts';
2
+ import './layout.css';
3
+ /** Services required before mounting. */
4
+ export declare const inject: string[];
5
+ /** Client plugin body. */
6
+ export declare function apply(ctx: Context): void;
@@ -0,0 +1,178 @@
1
+ /**
2
+ * Client locale dictionaries for dsh-side-chat (zh + en), registered under the
3
+ * `sidechat` namespace.
4
+ */
5
+ export declare const LOCALE_NS = "sidechat";
6
+ export declare const zh: {
7
+ 'ask.new': string;
8
+ 'ask.continue': string;
9
+ 'panel.title': string;
10
+ 'panel.empty': string;
11
+ 'panel.close': string;
12
+ 'panel.input.placeholder': string;
13
+ 'panel.send': string;
14
+ 'panel.stop': string;
15
+ 'panel.lookup': string;
16
+ 'panel.model': string;
17
+ 'panel.provider': string;
18
+ 'panel.effort': string;
19
+ 'panel.permission': string;
20
+ 'panel.noModel': string;
21
+ 'panel.effortDefault': string;
22
+ 'panel.expand': string;
23
+ 'panel.collapse': string;
24
+ 'panel.dispose': string;
25
+ 'panel.delete': string;
26
+ 'panel.deleteAll': string;
27
+ 'panel.error': string;
28
+ 'panel.running': string;
29
+ 'panel.copy': string;
30
+ 'panel.copied': string;
31
+ 'panel.footnotes': string;
32
+ 'panel.think': string;
33
+ 'panel.commands': string;
34
+ 'command.model': string;
35
+ 'command.permission': string;
36
+ 'plan.chipTitle': string;
37
+ 'plan.chipAria': string;
38
+ 'goal.label': string;
39
+ 'image.railGroup': string;
40
+ 'image.railOpen': string;
41
+ 'image.railScrollLeft': string;
42
+ 'image.railScrollRight': string;
43
+ 'image.remove': string;
44
+ 'image.label': string;
45
+ 'image.open': string;
46
+ 'image.loading': string;
47
+ 'image.loadFailed': string;
48
+ 'image.lightboxDialog': string;
49
+ 'image.close': string;
50
+ 'image.dropTitle': string;
51
+ 'image.dropDesc': string;
52
+ 'image.unsupported': string;
53
+ 'image.tooMany': string;
54
+ 'image.fileTooLarge': string;
55
+ settingsNav: string;
56
+ 'settings.lookupTitle': string;
57
+ 'settings.lookupDesc': string;
58
+ 'settings.sendImmediatelyTitle': string;
59
+ 'settings.sendImmediatelyDesc': string;
60
+ 'settings.defaultPromptTitle': string;
61
+ 'settings.defaultPromptDesc': string;
62
+ 'settings.defaultPromptPlaceholder': string;
63
+ 'settings.bringModeTitle': string;
64
+ 'settings.bringModeDesc': string;
65
+ 'settings.bringModeDraftTitle': string;
66
+ 'settings.bringModeDraftDesc': string;
67
+ 'settings.bringModeContextTitle': string;
68
+ 'settings.bringModeContextDesc': string;
69
+ 'insert.direct': string;
70
+ 'insert.summarize': string;
71
+ 'insert.summarizing': string;
72
+ 'insert.failed': string;
73
+ 'insert.summarizeFailed': string;
74
+ 'insert.contextSummary': string;
75
+ 'insert.summarizeContextSummary': string;
76
+ 'question.options': string;
77
+ 'question.option': string;
78
+ 'question.bringAll': string;
79
+ 'question.bringAllNew': string;
80
+ 'question.bringOne': string;
81
+ 'question.bringOneNew': string;
82
+ 'question.bringing': string;
83
+ 'question.failed': string;
84
+ 'question.delete': string;
85
+ 'question.deleteAll': string;
86
+ 'question.collapse': string;
87
+ 'question.expand': string;
88
+ 'question.allPrompt': string;
89
+ 'question.onePrompt': string;
90
+ 'question.openHint': string;
91
+ };
92
+ export declare const en: {
93
+ 'ask.new': string;
94
+ 'ask.continue': string;
95
+ 'panel.title': string;
96
+ 'panel.empty': string;
97
+ 'panel.close': string;
98
+ 'panel.input.placeholder': string;
99
+ 'panel.send': string;
100
+ 'panel.stop': string;
101
+ 'panel.lookup': string;
102
+ 'panel.model': string;
103
+ 'panel.provider': string;
104
+ 'panel.effort': string;
105
+ 'panel.permission': string;
106
+ 'panel.noModel': string;
107
+ 'panel.effortDefault': string;
108
+ 'panel.expand': string;
109
+ 'panel.collapse': string;
110
+ 'panel.dispose': string;
111
+ 'panel.delete': string;
112
+ 'panel.deleteAll': string;
113
+ 'panel.error': string;
114
+ 'panel.running': string;
115
+ 'panel.copy': string;
116
+ 'panel.copied': string;
117
+ 'panel.footnotes': string;
118
+ 'panel.think': string;
119
+ 'panel.commands': string;
120
+ 'command.model': string;
121
+ 'command.permission': string;
122
+ 'plan.chipTitle': string;
123
+ 'plan.chipAria': string;
124
+ 'goal.label': string;
125
+ 'image.railGroup': string;
126
+ 'image.railOpen': string;
127
+ 'image.railScrollLeft': string;
128
+ 'image.railScrollRight': string;
129
+ 'image.remove': string;
130
+ 'image.label': string;
131
+ 'image.open': string;
132
+ 'image.loading': string;
133
+ 'image.loadFailed': string;
134
+ 'image.lightboxDialog': string;
135
+ 'image.close': string;
136
+ 'image.dropTitle': string;
137
+ 'image.dropDesc': string;
138
+ 'image.unsupported': string;
139
+ 'image.tooMany': string;
140
+ 'image.fileTooLarge': string;
141
+ settingsNav: string;
142
+ 'settings.lookupTitle': string;
143
+ 'settings.lookupDesc': string;
144
+ 'settings.sendImmediatelyTitle': string;
145
+ 'settings.sendImmediatelyDesc': string;
146
+ 'settings.defaultPromptTitle': string;
147
+ 'settings.defaultPromptDesc': string;
148
+ 'settings.defaultPromptPlaceholder': string;
149
+ 'settings.bringModeTitle': string;
150
+ 'settings.bringModeDesc': string;
151
+ 'settings.bringModeDraftTitle': string;
152
+ 'settings.bringModeDraftDesc': string;
153
+ 'settings.bringModeContextTitle': string;
154
+ 'settings.bringModeContextDesc': string;
155
+ 'insert.direct': string;
156
+ 'insert.summarize': string;
157
+ 'insert.summarizing': string;
158
+ 'insert.failed': string;
159
+ 'insert.summarizeFailed': string;
160
+ 'insert.contextSummary': string;
161
+ 'insert.summarizeContextSummary': string;
162
+ 'question.options': string;
163
+ 'question.option': string;
164
+ 'question.bringAll': string;
165
+ 'question.bringAllNew': string;
166
+ 'question.bringOne': string;
167
+ 'question.bringOneNew': string;
168
+ 'question.bringing': string;
169
+ 'question.failed': string;
170
+ 'question.delete': string;
171
+ 'question.deleteAll': string;
172
+ 'question.collapse': string;
173
+ 'question.expand': string;
174
+ 'question.allPrompt': string;
175
+ 'question.onePrompt': string;
176
+ 'question.openHint': string;
177
+ };
178
+ export type SidechatLocaleKey = keyof typeof zh;