@yadsh/dsh-qa-surface 0.1.1 → 0.2.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.
Files changed (89) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/README.md +162 -14
  3. package/SPEC-dsh-qa-surface.md +600 -96
  4. package/capability-policy.json +5 -0
  5. package/compatibility.json +7 -1
  6. package/cordis.patch.yml +11 -0
  7. package/docs/ARCHITECTURE.md +49 -7
  8. package/docs/COMPATIBILITY.md +5 -4
  9. package/docs/CONFIGURATION.md +96 -2
  10. package/lib/attestation.js +10 -0
  11. package/lib/attestation.js.map +1 -0
  12. package/lib/client/QaConfigController.js +111 -4
  13. package/lib/client/QaConfigController.js.map +1 -1
  14. package/lib/client/QaSessionController.js +501 -119
  15. package/lib/client/QaSessionController.js.map +1 -1
  16. package/lib/client/QaSurface.js +137 -20
  17. package/lib/client/QaSurface.js.map +1 -1
  18. package/lib/client/QaTranscriptAdapter.js +534 -45
  19. package/lib/client/QaTranscriptAdapter.js.map +1 -1
  20. package/lib/client/attestation.js +60 -0
  21. package/lib/client/attestation.js.map +1 -0
  22. package/lib/client/chat-index.js +86 -0
  23. package/lib/client/chat-index.js.map +1 -0
  24. package/lib/client/components/Markdown.js +75 -5
  25. package/lib/client/components/Markdown.js.map +1 -1
  26. package/lib/client/components/QaAgentsDrawer.js +40 -0
  27. package/lib/client/components/QaAgentsDrawer.js.map +1 -0
  28. package/lib/client/components/QaComposer.js +132 -15
  29. package/lib/client/components/QaComposer.js.map +1 -1
  30. package/lib/client/components/QaMessage.js +184 -10
  31. package/lib/client/components/QaMessage.js.map +1 -1
  32. package/lib/client/components/QaSidebar.js +124 -0
  33. package/lib/client/components/QaSidebar.js.map +1 -0
  34. package/lib/client/components/QaSourcesDrawer.js +46 -0
  35. package/lib/client/components/QaSourcesDrawer.js.map +1 -0
  36. package/lib/client/components/QaWorkGroup.js +135 -0
  37. package/lib/client/components/QaWorkGroup.js.map +1 -0
  38. package/lib/client/components/VariantSwitcher.js +29 -0
  39. package/lib/client/components/VariantSwitcher.js.map +1 -0
  40. package/lib/client/components/format.js +48 -0
  41. package/lib/client/components/format.js.map +1 -0
  42. package/lib/client/index.js +77 -34
  43. package/lib/client/index.js.map +1 -1
  44. package/lib/client/styles.js +308 -43
  45. package/lib/client/styles.js.map +1 -1
  46. package/lib/client/types.js +13 -0
  47. package/lib/client/types.js.map +1 -0
  48. package/lib/client/wait-for.js +49 -0
  49. package/lib/client/wait-for.js.map +1 -0
  50. package/lib/client.js +8228 -383
  51. package/lib/client.js.map +1 -1
  52. package/lib/config.js +61 -9
  53. package/lib/config.js.map +1 -1
  54. package/lib/index.js +166 -70
  55. package/lib/index.js.map +1 -1
  56. package/lib/lockdown-policy.js +20 -0
  57. package/lib/lockdown-policy.js.map +1 -0
  58. package/lib/resolve-config.js +122 -10
  59. package/lib/resolve-config.js.map +1 -1
  60. package/lib/secure-session.js +170 -0
  61. package/lib/secure-session.js.map +1 -0
  62. package/lib/typert.host.d.ts +3 -0
  63. package/lib/typert.host.js +191 -0
  64. package/lib/typert.remote-client.d.ts +24 -0
  65. package/lib/typert.remote-client.js +129 -0
  66. package/lib/types/attestation.d.ts +17 -0
  67. package/lib/types/client/QaConfigController.d.ts +34 -2
  68. package/lib/types/client/QaSessionController.d.ts +106 -19
  69. package/lib/types/client/QaSurface.d.ts +5 -4
  70. package/lib/types/client/QaTranscriptAdapter.d.ts +17 -2
  71. package/lib/types/client/attestation.d.ts +25 -0
  72. package/lib/types/client/chat-index.d.ts +28 -0
  73. package/lib/types/client/components/Markdown.d.ts +7 -3
  74. package/lib/types/client/components/QaAgentsDrawer.d.ts +25 -0
  75. package/lib/types/client/components/QaComposer.d.ts +12 -2
  76. package/lib/types/client/components/QaMessage.d.ts +14 -1
  77. package/lib/types/client/components/QaSidebar.d.ts +41 -0
  78. package/lib/types/client/components/QaSourcesDrawer.d.ts +8 -0
  79. package/lib/types/client/components/QaWorkGroup.d.ts +19 -0
  80. package/lib/types/client/components/VariantSwitcher.d.ts +19 -0
  81. package/lib/types/client/components/format.d.ts +9 -0
  82. package/lib/types/client/index.d.ts +1 -5
  83. package/lib/types/client/types.d.ts +29 -0
  84. package/lib/types/client/wait-for.d.ts +11 -0
  85. package/lib/types/index.d.ts +22 -6
  86. package/lib/types/lockdown-policy.d.ts +18 -0
  87. package/lib/types/secure-session.d.ts +22 -0
  88. package/lib/types/types.d.ts +148 -1
  89. package/package.json +29 -3
@@ -1,4 +1,7 @@
1
1
  export type QaSessionPolicy = "browser-persistent" | "new-on-load" | "fixed";
2
+ export type QaSandboxMode = "read-only";
3
+ export type QaApprovalPolicy = "never";
4
+ export type QaToolPolicyMode = "allow-list";
2
5
  export interface QaSurfaceConfig {
3
6
  readonly enabled?: boolean;
4
7
  readonly route?: {
@@ -11,10 +14,14 @@ export interface QaSurfaceConfig {
11
14
  readonly welcomeMessage?: string;
12
15
  readonly placeholder?: string;
13
16
  readonly logoUrl?: string | null;
17
+ /** Data-usage notice under the composer; empty string hides the plate. */
18
+ readonly disclaimer?: string | null;
14
19
  };
15
20
  readonly session?: {
16
21
  readonly policy?: QaSessionPolicy;
17
22
  readonly storageKey?: string;
23
+ /** Absolute directory pinned as the session cwd (alternative to workspaceId). */
24
+ readonly cwd?: string | null;
18
25
  readonly workspaceId?: string | null;
19
26
  readonly fixedSessionId?: string | null;
20
27
  readonly agentPreset?: string | null;
@@ -31,12 +38,33 @@ export interface QaSurfaceConfig {
31
38
  readonly showReasoning?: boolean;
32
39
  readonly renderMarkdown?: boolean;
33
40
  readonly maxContentWidth?: number;
41
+ readonly showSessionList?: boolean;
34
42
  };
35
43
  readonly suggestedQuestions?: readonly string[];
36
44
  readonly interaction?: {
37
45
  readonly approvals?: "blocked";
38
46
  readonly questions?: "unsupported";
39
47
  };
48
+ readonly lockdown?: {
49
+ readonly enabled?: boolean;
50
+ readonly enforceFixedAgentPreset?: boolean;
51
+ readonly enforceFixedWorkspace?: boolean;
52
+ readonly enforceFixedModel?: boolean;
53
+ readonly sandboxMode?: QaSandboxMode;
54
+ readonly approvalPolicy?: QaApprovalPolicy;
55
+ readonly permissionPreset?: string;
56
+ readonly allowPermissionChanges?: false;
57
+ readonly allowSlashCommands?: false;
58
+ readonly allowSettingsMutation?: false;
59
+ readonly allowSessionReset?: boolean;
60
+ readonly allowSessionRename?: false;
61
+ readonly allowSessionDelete?: false;
62
+ readonly allowArbitrarySessionOpen?: false;
63
+ readonly toolPolicy?: {
64
+ readonly mode?: QaToolPolicyMode;
65
+ readonly allow?: readonly string[];
66
+ };
67
+ };
40
68
  readonly embedding?: {
41
69
  readonly frameAncestors?: string | null;
42
70
  };
@@ -53,10 +81,12 @@ export interface ResolvedQaSurfaceConfig {
53
81
  readonly welcomeMessage: string;
54
82
  readonly placeholder: string;
55
83
  readonly logoUrl: string | null;
84
+ readonly disclaimer: string;
56
85
  };
57
86
  readonly session: {
58
87
  readonly policy: QaSessionPolicy;
59
88
  readonly storageKey: string;
89
+ readonly cwd: string | null;
60
90
  readonly workspaceId: string | null;
61
91
  readonly fixedSessionId: string | null;
62
92
  readonly agentPreset: string | null;
@@ -70,39 +100,150 @@ export interface ResolvedQaSurfaceConfig {
70
100
  readonly showStop: boolean;
71
101
  readonly showTimestamps: boolean;
72
102
  readonly showToolActivity: boolean;
73
- readonly showReasoning: false;
103
+ readonly showReasoning: boolean;
74
104
  readonly renderMarkdown: boolean;
75
105
  readonly maxContentWidth: number;
106
+ readonly showSessionList: boolean;
76
107
  };
77
108
  readonly suggestedQuestions: readonly string[];
78
109
  readonly interaction: {
79
110
  readonly approvals: "blocked";
80
111
  readonly questions: "unsupported";
81
112
  };
113
+ readonly lockdown: {
114
+ readonly enabled: boolean;
115
+ readonly enforceFixedAgentPreset: boolean;
116
+ readonly enforceFixedWorkspace: boolean;
117
+ readonly enforceFixedModel: boolean;
118
+ readonly sandboxMode: QaSandboxMode;
119
+ readonly approvalPolicy: QaApprovalPolicy;
120
+ readonly permissionPreset: string;
121
+ readonly allowPermissionChanges: false;
122
+ readonly allowSlashCommands: false;
123
+ readonly allowSettingsMutation: false;
124
+ readonly allowSessionReset: boolean;
125
+ readonly allowSessionRename: false;
126
+ readonly allowSessionDelete: false;
127
+ readonly allowArbitrarySessionOpen: false;
128
+ readonly toolPolicy: {
129
+ readonly mode: QaToolPolicyMode;
130
+ readonly allow: readonly string[];
131
+ };
132
+ };
82
133
  readonly embedding: {
83
134
  readonly frameAncestors: string | null;
84
135
  };
85
136
  }
137
+ /** Host-attested facts required before the QA composer may become writable. */
138
+ export interface QaLockdownProof {
139
+ readonly sessionId: string;
140
+ readonly enabled: boolean;
141
+ readonly agentPresetMatches: boolean;
142
+ readonly workspaceMatches: boolean;
143
+ readonly modelMatches: boolean;
144
+ readonly sandboxIsReadOnly: boolean;
145
+ readonly approvalIsNever: boolean;
146
+ readonly permissionPreset: string;
147
+ readonly toolPolicyLoaded: boolean;
148
+ readonly toolAllowList: readonly string[];
149
+ }
86
150
  export type QaMessage = {
87
151
  readonly id: string;
88
152
  readonly role: "user";
89
153
  readonly text: string;
90
154
  readonly status: "committed";
91
155
  readonly timestamp?: number;
156
+ readonly images?: readonly QaImageView[];
92
157
  } | {
93
158
  readonly id: string;
94
159
  readonly role: "assistant";
95
160
  readonly text: string;
96
161
  readonly status: "streaming" | "committed" | "failed";
97
162
  readonly timestamp?: number;
163
+ /** Host turn this answer belongs to; groups regenerations into variants. */
164
+ readonly turn?: number;
165
+ /** Host-recorded response timing, present on finalized messages only. */
166
+ readonly stats?: {
167
+ /** step start → final message. */
168
+ readonly durationMs: number;
169
+ /** step start → first token; null when no token delta was recorded. */
170
+ readonly ttftMs: number | null;
171
+ /** Estimated from visible text (≈4 chars/token) over the generation window. */
172
+ readonly tokensPerSecond: number | null;
173
+ };
98
174
  } | {
99
175
  readonly id: string;
100
176
  readonly role: "system";
101
177
  readonly text: string;
102
178
  readonly status: "info" | "error";
103
179
  readonly timestamp?: number;
180
+ /** Collapsible settlement row (subagent finished/stopped/failed). */
181
+ readonly notice?: {
182
+ readonly title: string;
183
+ readonly body: string;
184
+ };
185
+ } | {
186
+ readonly id: string;
187
+ readonly role: "work";
188
+ readonly turn: number;
189
+ readonly status: "running" | "complete";
190
+ readonly startedAt?: number;
191
+ readonly endedAt?: number;
192
+ readonly items: readonly QaWorkItem[];
193
+ };
194
+ export type QaWorkItem = {
195
+ readonly id: string;
196
+ readonly kind: "reasoning" | "progress";
197
+ readonly text: string;
198
+ readonly status: "running" | "complete";
199
+ } | {
200
+ readonly id: string;
201
+ readonly kind: "tool";
202
+ readonly name: string;
203
+ readonly label: string;
204
+ readonly summary: string;
205
+ readonly input: string | null;
206
+ readonly output: string | null;
207
+ readonly status: "running" | "ok" | "error" | "stopped";
208
+ /** Durable child id, present on subagent launch calls that started one. */
209
+ readonly subagentId?: string;
210
+ readonly startedAt?: number;
211
+ readonly endedAt?: number;
104
212
  };
105
213
  export type QaSessionPhase = "idle" | "creating" | "ready" | "running" | "reconnecting" | "blocked" | "error";
214
+ /** One tool-derived source shown in the sources drawer. */
215
+ export interface QaSource {
216
+ readonly id: string;
217
+ readonly kind: "web" | "search" | "file";
218
+ /** URL, filesystem path or search query as the model supplied it. */
219
+ readonly target: string;
220
+ readonly title: string;
221
+ readonly snippet: string;
222
+ /** The tool's full text output, capped for the detail pane. */
223
+ readonly output: string;
224
+ }
225
+ /** Raster formats the attachment path accepts (mirrors the host contract). */
226
+ export type QaImageMediaType = "image/png" | "image/jpeg" | "image/webp" | "image/gif";
227
+ /** One image pending in the composer, browser-owned until the prompt lands. */
228
+ export interface QaImageDraft {
229
+ readonly id: string;
230
+ readonly mediaType: QaImageMediaType;
231
+ readonly name: string;
232
+ /** Canonical base64 of the image bytes, without the data: URL prefix. */
233
+ readonly data: string;
234
+ /** Local object URL for the preview thumbnail. */
235
+ readonly previewUrl: string;
236
+ }
237
+ /** A durable image attached to a sent message. */
238
+ export interface QaImageView {
239
+ readonly attachmentId: string;
240
+ readonly mediaType: QaImageMediaType;
241
+ }
242
+ /** A subagent transcript opened read-only from the agents panel. */
243
+ export interface QaSubagentView {
244
+ readonly id: string;
245
+ readonly title: string;
246
+ }
106
247
  export interface QaSessionState {
107
248
  readonly phase: QaSessionPhase;
108
249
  readonly sessionId: string | null;
@@ -110,5 +251,11 @@ export interface QaSessionState {
110
251
  readonly error: string | null;
111
252
  readonly canSend: boolean;
112
253
  readonly canStop: boolean;
254
+ /** Bumped whenever this browser's chat index changes (add/forget). */
255
+ readonly chatsRevision: number;
256
+ /** Tool-derived sources of the current chat (web targets and files read). */
257
+ readonly sources: readonly QaSource[];
258
+ /** Set while the bound session is a subagent watched from the panel. */
259
+ readonly viewingSubagent: QaSubagentView | null;
113
260
  }
114
261
  //# sourceMappingURL=types.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yadsh/dsh-qa-surface",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "A focused end-user QA surface backed by native DeepSeek Harness sessions",
5
5
  "repository": {
6
6
  "type": "git",
@@ -23,6 +23,14 @@
23
23
  "types": "./lib/types/client/index.d.ts",
24
24
  "default": "./lib/client.js"
25
25
  },
26
+ "./remote": {
27
+ "types": "./lib/typert.remote-client.d.ts",
28
+ "default": "./lib/typert.remote-client.js"
29
+ },
30
+ "./typert": {
31
+ "types": "./lib/typert.host.d.ts",
32
+ "default": "./lib/typert.host.js"
33
+ },
26
34
  "./types": {
27
35
  "types": "./lib/types/types.d.ts",
28
36
  "default": "./lib/types.js"
@@ -51,9 +59,10 @@
51
59
  "files": [
52
60
  "lib/**/*.js",
53
61
  "lib/**/*.js.map",
54
- "lib/types/**/*.d.ts",
62
+ "lib/**/*.d.ts",
55
63
  "cordis.patch.yml",
56
64
  "compatibility.json",
65
+ "capability-policy.json",
57
66
  "README.md",
58
67
  "CHANGELOG.md",
59
68
  "docs/*.md",
@@ -77,6 +86,8 @@
77
86
  "@deepseek-ai/cordis": "^4.0.1",
78
87
  "@deepseek-ai/schemastery": "^3.18.1",
79
88
  "@deepseek-ai/dsh-api-gateway": ">=0.1.1-rc.2 <0.2.0",
89
+ "@deepseek-ai/dsh-agent": ">=0.1.1-rc.2 <0.2.0",
90
+ "@deepseek-ai/dsh-agent-presets": ">=0.1.1-rc.2 <0.2.0",
80
91
  "@deepseek-ai/dsh-client-connection": ">=0.1.1-rc.2 <0.2.0",
81
92
  "@deepseek-ai/dsh-client-runtime": ">=0.1.1-rc.2 <0.2.0",
82
93
  "@deepseek-ai/dsh-client-ui-layout": ">=0.1.1-rc.2 <0.2.0",
@@ -84,16 +95,24 @@
84
95
  "@deepseek-ai/dsh-client-ui-slots": ">=0.1.1-rc.2 <0.2.0",
85
96
  "@deepseek-ai/dsh-client-ui-theme": ">=0.1.1-rc.2 <0.2.0",
86
97
  "@deepseek-ai/dsh-host-webserver": ">=0.1.1-rc.2 <0.2.0",
98
+ "@deepseek-ai/dsh-permission-presets": ">=0.1.1-rc.2 <0.2.0",
99
+ "@deepseek-ai/dsh-session": ">=0.1.1-rc.2 <0.2.0",
87
100
  "@deepseek-ai/dsh-settings": ">=0.1.1-rc.2 <0.2.0",
101
+ "@deepseek-ai/dsh-tools": ">=0.1.1-rc.2 <0.2.0",
102
+ "@deepseek-ai/dsh-typert-protocol": ">=0.1.1-rc.2 <0.2.0",
103
+ "@deepseek-ai/dsh-workspace": ">=0.1.1-rc.2 <0.2.0",
88
104
  "react": "^18.2.0"
89
105
  },
90
106
  "dependencies": {
107
+ "zod": "^4.4.3",
91
108
  "@yadsh/dsh-plugin-log": "^0.2.1"
92
109
  },
93
110
  "devDependencies": {
94
111
  "@deepseek-ai/cordis": "4.0.1",
95
112
  "@deepseek-ai/schemastery": "3.18.1",
96
113
  "@deepseek-ai/dsh-api-gateway": "0.1.1-rc.2",
114
+ "@deepseek-ai/dsh-agent": "0.1.1-rc.2",
115
+ "@deepseek-ai/dsh-agent-presets": "0.1.1-rc.2",
97
116
  "@deepseek-ai/dsh-client-connection": "0.1.1-rc.2",
98
117
  "@deepseek-ai/dsh-client-runtime": "0.1.1-rc.2",
99
118
  "@deepseek-ai/dsh-client-ui-layout": "0.1.1-rc.2",
@@ -101,7 +120,13 @@
101
120
  "@deepseek-ai/dsh-client-ui-slots": "0.1.1-rc.2",
102
121
  "@deepseek-ai/dsh-client-ui-theme": "0.1.1-rc.2",
103
122
  "@deepseek-ai/dsh-host-webserver": "0.1.1-rc.2",
123
+ "@deepseek-ai/dsh-permission-presets": "0.1.1-rc.2",
124
+ "@deepseek-ai/dsh-session": "0.1.1-rc.2",
104
125
  "@deepseek-ai/dsh-settings": "0.1.1-rc.2",
126
+ "@deepseek-ai/dsh-tools": "0.1.1-rc.2",
127
+ "@deepseek-ai/dsh-typert-generator": "0.1.1-rc.2",
128
+ "@deepseek-ai/dsh-typert-protocol": "0.1.1-rc.2",
129
+ "@deepseek-ai/dsh-workspace": "0.1.1-rc.2",
105
130
  "@testing-library/react": "^16.3.0",
106
131
  "@types/node": "^26.4.0",
107
132
  "@types/react": "18.3.28",
@@ -113,6 +138,7 @@
113
138
  "tsdown": "^0.22.14",
114
139
  "typescript": "^7.0.2",
115
140
  "vitest": "^4.1.11",
141
+ "@yadsh/dsh-plugin-scripts": "^0.0.0",
116
142
  "@yadsh/dsh-config": "^0.0.0"
117
143
  },
118
144
  "publishConfig": {
@@ -121,7 +147,7 @@
121
147
  },
122
148
  "scripts": {
123
149
  "clean": "node -e \"require('node:fs').rmSync('lib', { recursive: true, force: true })\"",
124
- "build": "pnpm run clean && tsdown && tsc -p tsconfig.build.json",
150
+ "build": "pnpm run clean && node scripts/generate-typert.mjs && tsc -p tsconfig.build.json && tsdown",
125
151
  "lint": "eslint src tests scripts tsdown.config.ts",
126
152
  "format": "prettier --check . --end-of-line auto",
127
153
  "format:write": "prettier --write . --end-of-line auto",