@yadsh/dsh-qa-surface 0.3.0 → 0.4.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/README.md +153 -12
- package/lib/account-remotes.js +100 -0
- package/lib/account-remotes.js.map +1 -0
- package/lib/accounts/credentials.js +27 -0
- package/lib/accounts/credentials.js.map +1 -0
- package/lib/accounts/errors.js +9 -0
- package/lib/accounts/errors.js.map +1 -0
- package/lib/accounts/file.js +101 -0
- package/lib/accounts/file.js.map +1 -0
- package/lib/accounts/store.js +144 -161
- package/lib/accounts/store.js.map +1 -1
- package/lib/accounts/token.js +61 -0
- package/lib/accounts/token.js.map +1 -0
- package/lib/attachment-rules.js +111 -0
- package/lib/attachment-rules.js.map +1 -0
- package/lib/cli.js +122 -9
- package/lib/cli.js.map +1 -1
- package/lib/client/QaAccountsController.js +32 -2
- package/lib/client/QaAccountsController.js.map +1 -1
- package/lib/client/QaSessionController.js +47 -65
- package/lib/client/QaSessionController.js.map +1 -1
- package/lib/client/QaSurface.js +121 -107
- package/lib/client/QaSurface.js.map +1 -1
- package/lib/client/QaTranscriptAdapter.js +71 -6
- package/lib/client/QaTranscriptAdapter.js.map +1 -1
- package/lib/client/attachments.js +150 -0
- package/lib/client/attachments.js.map +1 -0
- package/lib/client/attestation.js +1 -1
- package/lib/client/attestation.js.map +1 -1
- package/lib/client/base64.js +16 -0
- package/lib/client/base64.js.map +1 -0
- package/lib/client/chat-files.js +48 -0
- package/lib/client/chat-files.js.map +1 -0
- package/lib/client/components/Markdown.js +1 -1
- package/lib/client/components/Markdown.js.map +1 -1
- package/lib/client/components/QaChangelog.js +38 -19
- package/lib/client/components/QaChangelog.js.map +1 -1
- package/lib/client/components/QaComposer.js +56 -74
- package/lib/client/components/QaComposer.js.map +1 -1
- package/lib/client/components/QaFileAttachment.js +19 -0
- package/lib/client/components/QaFileAttachment.js.map +1 -0
- package/lib/client/components/QaFilesPanel.js +45 -0
- package/lib/client/components/QaFilesPanel.js.map +1 -0
- package/lib/client/components/QaHeader.js +34 -0
- package/lib/client/components/QaHeader.js.map +1 -0
- package/lib/client/components/QaMessage.js +17 -4
- package/lib/client/components/QaMessage.js.map +1 -1
- package/lib/client/components/QaModal.js +31 -0
- package/lib/client/components/QaModal.js.map +1 -0
- package/lib/client/components/QaProfile.js +64 -0
- package/lib/client/components/QaProfile.js.map +1 -0
- package/lib/client/components/QaRightRail.js +15 -0
- package/lib/client/components/QaRightRail.js.map +1 -0
- package/lib/client/components/QaSidebar.js +6 -1
- package/lib/client/components/QaSidebar.js.map +1 -1
- package/lib/client/components/{QaSourcesDrawer.js → QaSourcesPanel.js} +3 -3
- package/lib/client/components/QaSourcesPanel.js.map +1 -0
- package/lib/client/components/QaTurnRail.js +15 -0
- package/lib/client/components/QaTurnRail.js.map +1 -1
- package/lib/client/components/QaWidthHandle.js +25 -20
- package/lib/client/components/QaWidthHandle.js.map +1 -1
- package/lib/client/components/QaWorkGroup.js +19 -20
- package/lib/client/components/QaWorkGroup.js.map +1 -1
- package/lib/client/components/surface-utils.js +28 -0
- package/lib/client/components/surface-utils.js.map +1 -0
- package/lib/client/components/thinking-phrases.js +24 -0
- package/lib/client/components/thinking-phrases.js.map +1 -0
- package/lib/client/create-session.js +7 -32
- package/lib/client/create-session.js.map +1 -1
- package/lib/client/failure-copy.js +63 -0
- package/lib/client/failure-copy.js.map +1 -0
- package/lib/client/index.js +38 -7
- package/lib/client/index.js.map +1 -1
- package/lib/client/prompt-content.js +54 -0
- package/lib/client/prompt-content.js.map +1 -0
- package/lib/client/settings/card.js +143 -0
- package/lib/client/settings/card.js.map +1 -0
- package/lib/client/settings/fields.js +145 -0
- package/lib/client/settings/fields.js.map +1 -0
- package/lib/client/settings/format.js +255 -0
- package/lib/client/settings/format.js.map +1 -0
- package/lib/client/settings/sections/access.js +25 -0
- package/lib/client/settings/sections/access.js.map +1 -0
- package/lib/client/settings/sections/accounts.js +47 -0
- package/lib/client/settings/sections/accounts.js.map +1 -0
- package/lib/client/settings/sections/attachments.js +46 -0
- package/lib/client/settings/sections/attachments.js.map +1 -0
- package/lib/client/settings/sections/branding.js +28 -0
- package/lib/client/settings/sections/branding.js.map +1 -0
- package/lib/client/settings/sections/common.js +20 -0
- package/lib/client/settings/sections/common.js.map +1 -0
- package/lib/client/settings/sections/embedding.js +19 -0
- package/lib/client/settings/sections/embedding.js.map +1 -0
- package/lib/client/settings/sections/interface.js +60 -0
- package/lib/client/settings/sections/interface.js.map +1 -0
- package/lib/client/settings/sections/lockdown.js +82 -0
- package/lib/client/settings/sections/lockdown.js.map +1 -0
- package/lib/client/settings/sections/session.js +53 -0
- package/lib/client/settings/sections/session.js.map +1 -0
- package/lib/client/settings/sections/sources.js +72 -0
- package/lib/client/settings/sections/sources.js.map +1 -0
- package/lib/client/settings/sections/status.js +37 -0
- package/lib/client/settings/sections/status.js.map +1 -0
- package/lib/client/settings/sections.js +23 -0
- package/lib/client/settings/sections.js.map +1 -0
- package/lib/client/settings/styles.js +57 -0
- package/lib/client/settings/styles.js.map +1 -0
- package/lib/client/stream-publisher.js +47 -0
- package/lib/client/stream-publisher.js.map +1 -0
- package/lib/client/styles.js +85 -19
- package/lib/client/styles.js.map +1 -1
- package/lib/client/types.js.map +1 -1
- package/lib/client/use-right-rail.js +96 -0
- package/lib/client/use-right-rail.js.map +1 -0
- package/lib/client/use-session-ui-state.js +26 -19
- package/lib/client/use-session-ui-state.js.map +1 -1
- package/lib/client.js +4788 -869
- package/lib/client.js.map +1 -1
- package/lib/config-resolvers/accounts.js +60 -0
- package/lib/config-resolvers/accounts.js.map +1 -0
- package/lib/config-resolvers/attachments.js +28 -0
- package/lib/config-resolvers/attachments.js.map +1 -0
- package/lib/config-resolvers/basics.js +59 -0
- package/lib/config-resolvers/basics.js.map +1 -0
- package/lib/config-resolvers/defaults.js +132 -0
- package/lib/config-resolvers/defaults.js.map +1 -0
- package/lib/config-resolvers/lockdown.js +79 -0
- package/lib/config-resolvers/lockdown.js.map +1 -0
- package/lib/config-resolvers/session.js +42 -0
- package/lib/config-resolvers/session.js.map +1 -0
- package/lib/config-resolvers/shared.js +42 -0
- package/lib/config-resolvers/shared.js.map +1 -0
- package/lib/config-resolvers/sources.js +81 -0
- package/lib/config-resolvers/sources.js.map +1 -0
- package/lib/config-resolvers/ui.js +20 -0
- package/lib/config-resolvers/ui.js.map +1 -0
- package/lib/config.js +65 -4
- package/lib/config.js.map +1 -1
- package/lib/entry-redirect.js +2 -1
- package/lib/entry-redirect.js.map +1 -1
- package/lib/index.js +123 -74
- package/lib/index.js.map +1 -1
- package/lib/profile.js +214 -0
- package/lib/profile.js.map +1 -0
- package/lib/prompt-notes.js +231 -0
- package/lib/prompt-notes.js.map +1 -0
- package/lib/resolve-config.js +35 -410
- package/lib/resolve-config.js.map +1 -1
- package/lib/secure-session.js +82 -16
- package/lib/secure-session.js.map +1 -1
- package/lib/shared/session-key.js +18 -0
- package/lib/shared/session-key.js.map +1 -0
- package/lib/shared/settings.js +10 -0
- package/lib/shared/settings.js.map +1 -0
- package/lib/thinking-phrases.js +68 -0
- package/lib/thinking-phrases.js.map +1 -0
- package/lib/typert.host.js +162 -17
- package/lib/typert.remote-client.d.ts +5 -1
- package/lib/typert.remote-client.js +132 -13
- package/lib/types/account-remotes.d.ts +42 -0
- package/lib/types/accounts/credentials.d.ts +14 -0
- package/lib/types/accounts/errors.d.ts +11 -0
- package/lib/types/accounts/file.d.ts +82 -0
- package/lib/types/accounts/store.d.ts +66 -43
- package/lib/types/accounts/token.d.ts +31 -0
- package/lib/types/attachment-rules.d.ts +44 -0
- package/lib/types/cli.d.ts +2 -2
- package/lib/types/client/QaAccountsController.d.ts +8 -1
- package/lib/types/client/QaSessionController.d.ts +16 -16
- package/lib/types/client/QaSurface.d.ts +7 -1
- package/lib/types/client/attachments.d.ts +54 -0
- package/lib/types/client/base64.d.ts +10 -0
- package/lib/types/client/chat-files.d.ts +30 -0
- package/lib/types/client/components/QaChangelog.d.ts +1 -1
- package/lib/types/client/components/QaComposer.d.ts +8 -4
- package/lib/types/client/components/QaFileAttachment.d.ts +14 -0
- package/lib/types/client/components/QaFilesPanel.d.ts +15 -0
- package/lib/types/client/components/QaHeader.d.ts +41 -0
- package/lib/types/client/components/QaMessage.d.ts +3 -1
- package/lib/types/client/components/QaModal.d.ts +26 -0
- package/lib/types/client/components/QaProfile.d.ts +25 -0
- package/lib/types/client/components/QaRightRail.d.ts +23 -0
- package/lib/types/client/components/QaSidebar.d.ts +14 -0
- package/lib/types/client/components/{QaSourcesDrawer.d.ts → QaSourcesPanel.d.ts} +7 -4
- package/lib/types/client/components/QaTurnRail.d.ts +6 -0
- package/lib/types/client/components/QaWidthHandle.d.ts +14 -7
- package/lib/types/client/components/QaWorkGroup.d.ts +5 -3
- package/lib/types/client/components/surface-utils.d.ts +11 -0
- package/lib/types/client/components/thinking-phrases.d.ts +9 -0
- package/lib/types/client/create-session.d.ts +6 -9
- package/lib/types/client/failure-copy.d.ts +19 -0
- package/lib/types/client/prompt-content.d.ts +30 -0
- package/lib/types/client/settings/card.d.ts +23 -0
- package/lib/types/client/settings/fields.d.ts +139 -0
- package/lib/types/client/settings/format.d.ts +108 -0
- package/lib/types/client/settings/sections/access.d.ts +9 -0
- package/lib/types/client/settings/sections/accounts.d.ts +9 -0
- package/lib/types/client/settings/sections/attachments.d.ts +15 -0
- package/lib/types/client/settings/sections/branding.d.ts +8 -0
- package/lib/types/client/settings/sections/common.d.ts +28 -0
- package/lib/types/client/settings/sections/embedding.d.ts +8 -0
- package/lib/types/client/settings/sections/interface.d.ts +9 -0
- package/lib/types/client/settings/sections/lockdown.d.ts +9 -0
- package/lib/types/client/settings/sections/session.d.ts +9 -0
- package/lib/types/client/settings/sections/sources.d.ts +9 -0
- package/lib/types/client/settings/sections/status.d.ts +22 -0
- package/lib/types/client/settings/sections.d.ts +25 -0
- package/lib/types/client/settings/styles.d.ts +8 -0
- package/lib/types/client/stream-publisher.d.ts +28 -0
- package/lib/types/client/types.d.ts +29 -1
- package/lib/types/client/use-right-rail.d.ts +56 -0
- package/lib/types/client/use-session-ui-state.d.ts +13 -7
- package/lib/types/config-resolvers/accounts.d.ts +15 -0
- package/lib/types/config-resolvers/attachments.d.ts +6 -0
- package/lib/types/config-resolvers/basics.d.ts +8 -0
- package/lib/types/config-resolvers/defaults.d.ts +4 -0
- package/lib/types/config-resolvers/lockdown.d.ts +10 -0
- package/lib/types/config-resolvers/session.d.ts +6 -0
- package/lib/types/config-resolvers/shared.d.ts +16 -0
- package/lib/types/config-resolvers/sources.d.ts +6 -0
- package/lib/types/config-resolvers/ui.d.ts +6 -0
- package/lib/types/index.d.ts +20 -13
- package/lib/types/profile.d.ts +76 -0
- package/lib/types/prompt-notes.d.ts +110 -0
- package/lib/types/resolve-config.d.ts +8 -3
- package/lib/types/secure-session.d.ts +26 -1
- package/lib/types/shared/session-key.d.ts +23 -0
- package/lib/types/shared/settings.d.ts +10 -0
- package/lib/types/thinking-phrases.d.ts +17 -0
- package/lib/types/types.d.ts +123 -5
- package/lib/types/user-workspace.d.ts +38 -0
- package/lib/user-workspace.js +231 -0
- package/lib/user-workspace.js.map +1 -0
- package/package.json +14 -7
- package/CHANGELOG.md +0 -176
- package/SPEC-dsh-qa-surface.md +0 -2425
- package/docs/ARCHITECTURE.md +0 -66
- package/docs/COMPATIBILITY.md +0 -14
- package/docs/CONFIGURATION.md +0 -199
- package/docs/EMBEDDING.md +0 -13
- package/docs/SOURCES-MIGRATION.md +0 -28
- package/docs/SOURCES-PROVENANCE-AUDIT.md +0 -88
- package/docs/SPEC-dsh-qa-surface-accounts.md +0 -219
- package/docs/SPEC-dsh-qa-surface-sources-provenance.md +0 -1692
- package/lib/client/components/QaSourcesDrawer.js.map +0 -1
package/lib/types/types.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { QaTurnSources } from "./provenance/types.js";
|
|
2
2
|
export type QaSessionPolicy = "browser-persistent" | "new-on-load" | "fixed";
|
|
3
|
-
export type QaSandboxMode = "read-only";
|
|
3
|
+
export type QaSandboxMode = "read-only" | "workspace-write";
|
|
4
4
|
export type QaApprovalPolicy = "never";
|
|
5
5
|
export type QaToolPolicyMode = "allow-list";
|
|
6
6
|
export type QaAccountRole = "user" | "admin";
|
|
@@ -13,6 +13,36 @@ export interface QaAccountUserPublic {
|
|
|
13
13
|
readonly createdAt: string;
|
|
14
14
|
readonly lastLoginAt: string | null;
|
|
15
15
|
readonly disabled: boolean;
|
|
16
|
+
/** Self-declared identity the QA prompt renders; empty until edited. */
|
|
17
|
+
readonly profile: QaAccountProfile;
|
|
18
|
+
}
|
|
19
|
+
/** One external system the deployment collects a handle for. */
|
|
20
|
+
export interface QaAccountIdentityField {
|
|
21
|
+
/** Stable lowercase key: the profile's storage key and the prompt's label. */
|
|
22
|
+
readonly key: string;
|
|
23
|
+
/** Operator copy shown in the profile form. */
|
|
24
|
+
readonly label: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* What one account says about itself. Every value is the owner's own wording,
|
|
28
|
+
* which is why the prompt renders it as self-declared rather than as a
|
|
29
|
+
* verified directory attribute.
|
|
30
|
+
*/
|
|
31
|
+
export interface QaAccountProfile {
|
|
32
|
+
/** Full name as the user writes it; empty when unset. */
|
|
33
|
+
readonly fullName: string;
|
|
34
|
+
/** External-system handles, keyed by the declared field key. */
|
|
35
|
+
readonly identities: Readonly<Record<string, string>>;
|
|
36
|
+
/** Free-form guidance about how the user wants answers; empty when unset. */
|
|
37
|
+
readonly instructions: string;
|
|
38
|
+
/** ISO timestamp of the last edit; null while the profile is untouched. */
|
|
39
|
+
readonly updatedAt: string | null;
|
|
40
|
+
}
|
|
41
|
+
/** Full-replace profile write: an absent value clears the stored one. */
|
|
42
|
+
export interface QaAccountProfileInput {
|
|
43
|
+
readonly fullName: string;
|
|
44
|
+
readonly identities: Readonly<Record<string, string>>;
|
|
45
|
+
readonly instructions: string;
|
|
16
46
|
}
|
|
17
47
|
/** One successful login/registration: the bearer token plus the user. */
|
|
18
48
|
export interface QaAccountSession {
|
|
@@ -117,10 +147,16 @@ export interface QaSurfaceConfig {
|
|
|
117
147
|
readonly showToolActivity?: boolean;
|
|
118
148
|
readonly showReasoning?: boolean;
|
|
119
149
|
readonly renderMarkdown?: boolean;
|
|
120
|
-
|
|
150
|
+
/** Floor for the visitor-resizable transcript/composer width; the page caps it. */
|
|
151
|
+
readonly minContentWidth?: number;
|
|
121
152
|
readonly showSessionList?: boolean;
|
|
122
153
|
};
|
|
123
154
|
readonly suggestedQuestions?: readonly string[];
|
|
155
|
+
/**
|
|
156
|
+
* Phrases the running indicator cycles through. An empty list restores the
|
|
157
|
+
* built-in phrases: the indicator always carries a label.
|
|
158
|
+
*/
|
|
159
|
+
readonly thinkingPhrases?: readonly string[];
|
|
124
160
|
readonly interaction?: {
|
|
125
161
|
readonly approvals?: "blocked";
|
|
126
162
|
readonly questions?: "unsupported";
|
|
@@ -155,6 +191,24 @@ export interface QaSurfaceConfig {
|
|
|
155
191
|
readonly sessionTtlDays?: number;
|
|
156
192
|
/** Let admins see chats owned by other QA accounts. */
|
|
157
193
|
readonly showOtherUsersChats?: boolean;
|
|
194
|
+
/**
|
|
195
|
+
* Give every account a private cwd below the configured workspaceId.
|
|
196
|
+
* The child directory is not registered as a separate DSH workspace.
|
|
197
|
+
*/
|
|
198
|
+
readonly perUserWorkspace?: boolean;
|
|
199
|
+
/** Self-declared profile: storage, the owner's form, and prompt injection. */
|
|
200
|
+
readonly profile?: {
|
|
201
|
+
readonly enabled?: boolean;
|
|
202
|
+
/** Render the profile into the QA agent's system prompt. */
|
|
203
|
+
readonly inject?: boolean;
|
|
204
|
+
/** External systems to collect a handle for; empty declares none. */
|
|
205
|
+
readonly identities?: readonly {
|
|
206
|
+
readonly key?: string;
|
|
207
|
+
readonly label?: string;
|
|
208
|
+
}[];
|
|
209
|
+
/** Character cap on the user's free-form agent guidance. */
|
|
210
|
+
readonly instructionsMaxLength?: number;
|
|
211
|
+
};
|
|
158
212
|
};
|
|
159
213
|
readonly entry?: {
|
|
160
214
|
/** Inject the root → /qa redirect for non-loopback hostnames. */
|
|
@@ -163,6 +217,26 @@ export interface QaSurfaceConfig {
|
|
|
163
217
|
readonly cookieBootstrap?: boolean;
|
|
164
218
|
};
|
|
165
219
|
readonly sources?: QaSourcesConfig;
|
|
220
|
+
readonly attachments?: QaAttachmentsConfig;
|
|
221
|
+
}
|
|
222
|
+
/** What a QA visitor may attach to one message. */
|
|
223
|
+
export interface QaAttachmentsConfig {
|
|
224
|
+
/** Offer text files (md, txt, log, …) next to images; off = images only. */
|
|
225
|
+
readonly textFiles?: boolean;
|
|
226
|
+
/**
|
|
227
|
+
* Line count above which pasted plain text becomes an attached file instead
|
|
228
|
+
* of landing in the input field. Zero never converts.
|
|
229
|
+
*/
|
|
230
|
+
readonly pastedTextLines?: number;
|
|
231
|
+
/** Byte ceiling for one attached file; the composer refuses anything larger. */
|
|
232
|
+
readonly maxFileBytes?: number;
|
|
233
|
+
/**
|
|
234
|
+
* Pending attachments (images plus text files) allowed on one message. The
|
|
235
|
+
* Host keeps its own authority over assembled image batches.
|
|
236
|
+
*/
|
|
237
|
+
readonly maxPending?: number;
|
|
238
|
+
/** Accepted text-file extensions, lowercase and without the dot. */
|
|
239
|
+
readonly extensions?: readonly string[];
|
|
166
240
|
}
|
|
167
241
|
export interface ResolvedQaSurfaceConfig {
|
|
168
242
|
readonly enabled: boolean;
|
|
@@ -197,10 +271,11 @@ export interface ResolvedQaSurfaceConfig {
|
|
|
197
271
|
readonly showToolActivity: boolean;
|
|
198
272
|
readonly showReasoning: boolean;
|
|
199
273
|
readonly renderMarkdown: boolean;
|
|
200
|
-
readonly
|
|
274
|
+
readonly minContentWidth: number;
|
|
201
275
|
readonly showSessionList: boolean;
|
|
202
276
|
};
|
|
203
277
|
readonly suggestedQuestions: readonly string[];
|
|
278
|
+
readonly thinkingPhrases: readonly string[];
|
|
204
279
|
readonly interaction: {
|
|
205
280
|
readonly approvals: "blocked";
|
|
206
281
|
readonly questions: "unsupported";
|
|
@@ -233,6 +308,13 @@ export interface ResolvedQaSurfaceConfig {
|
|
|
233
308
|
readonly allowRegistration: boolean;
|
|
234
309
|
readonly sessionTtlDays: number;
|
|
235
310
|
readonly showOtherUsersChats: boolean;
|
|
311
|
+
readonly perUserWorkspace: boolean;
|
|
312
|
+
readonly profile: {
|
|
313
|
+
readonly enabled: boolean;
|
|
314
|
+
readonly inject: boolean;
|
|
315
|
+
readonly identities: readonly QaAccountIdentityField[];
|
|
316
|
+
readonly instructionsMaxLength: number;
|
|
317
|
+
};
|
|
236
318
|
};
|
|
237
319
|
readonly entry: {
|
|
238
320
|
readonly redirectNonLoopback: boolean;
|
|
@@ -278,6 +360,13 @@ export interface ResolvedQaSurfaceConfig {
|
|
|
278
360
|
readonly parseAssistantSourcesBlock: boolean;
|
|
279
361
|
};
|
|
280
362
|
};
|
|
363
|
+
readonly attachments: {
|
|
364
|
+
readonly textFiles: boolean;
|
|
365
|
+
readonly pastedTextLines: number;
|
|
366
|
+
readonly maxFileBytes: number;
|
|
367
|
+
readonly maxPending: number;
|
|
368
|
+
readonly extensions: readonly string[];
|
|
369
|
+
};
|
|
281
370
|
}
|
|
282
371
|
export interface QaSourceFilePreview {
|
|
283
372
|
readonly path: string;
|
|
@@ -294,7 +383,7 @@ export interface QaLockdownProof {
|
|
|
294
383
|
readonly agentPresetMatches: boolean;
|
|
295
384
|
readonly workspaceMatches: boolean;
|
|
296
385
|
readonly modelMatches: boolean;
|
|
297
|
-
readonly
|
|
386
|
+
readonly sandboxModeMatches: boolean;
|
|
298
387
|
readonly approvalIsNever: boolean;
|
|
299
388
|
readonly permissionPreset: string;
|
|
300
389
|
readonly toolPolicyLoaded: boolean;
|
|
@@ -307,6 +396,8 @@ export type QaMessage = {
|
|
|
307
396
|
readonly status: "committed";
|
|
308
397
|
readonly timestamp?: number;
|
|
309
398
|
readonly images?: readonly QaImageView[];
|
|
399
|
+
/** Durable files the user attached to this message, in prompt order. */
|
|
400
|
+
readonly files?: readonly QaFileView[];
|
|
310
401
|
/**
|
|
311
402
|
* Chat owner's display name, set only for an admin reading a foreign
|
|
312
403
|
* chat; the owner themself sees their messages unlabeled.
|
|
@@ -348,7 +439,8 @@ export type QaMessage = {
|
|
|
348
439
|
readonly id: string;
|
|
349
440
|
readonly role: "work";
|
|
350
441
|
readonly turn: number;
|
|
351
|
-
|
|
442
|
+
/** "error" marks a turn the host ended with a provider failure. */
|
|
443
|
+
readonly status: "running" | "complete" | "error";
|
|
352
444
|
readonly startedAt?: number;
|
|
353
445
|
readonly endedAt?: number;
|
|
354
446
|
readonly items: readonly QaWorkItem[];
|
|
@@ -380,6 +472,7 @@ export type QaSource = import("./provenance/types.js").QaSourceReference;
|
|
|
380
472
|
export type QaImageMediaType = "image/png" | "image/jpeg" | "image/webp" | "image/gif";
|
|
381
473
|
/** One image pending in the composer, browser-owned until the prompt lands. */
|
|
382
474
|
export interface QaImageDraft {
|
|
475
|
+
readonly kind: "image";
|
|
383
476
|
readonly id: string;
|
|
384
477
|
readonly mediaType: QaImageMediaType;
|
|
385
478
|
readonly name: string;
|
|
@@ -388,11 +481,36 @@ export interface QaImageDraft {
|
|
|
388
481
|
/** Local object URL for the preview thumbnail. */
|
|
389
482
|
readonly previewUrl: string;
|
|
390
483
|
}
|
|
484
|
+
/**
|
|
485
|
+
* One file pending in the composer. The bytes stay in the browser until the
|
|
486
|
+
* prompt is sent: an image can ride the prompt inline, but a file must be
|
|
487
|
+
* staged through the Host upload route first and then cited by its receipt.
|
|
488
|
+
*/
|
|
489
|
+
export interface QaFileDraft {
|
|
490
|
+
readonly kind: "file";
|
|
491
|
+
readonly id: string;
|
|
492
|
+
readonly name: string;
|
|
493
|
+
readonly bytes: number;
|
|
494
|
+
/** Verbatim payload; a pasted blob is a File built from the pasted text. */
|
|
495
|
+
readonly blob: Blob;
|
|
496
|
+
}
|
|
497
|
+
/** Anything the composer may hold before the prompt is sent. */
|
|
498
|
+
export type QaAttachmentDraft = QaImageDraft | QaFileDraft;
|
|
391
499
|
/** A durable image attached to a sent message. */
|
|
392
500
|
export interface QaImageView {
|
|
393
501
|
readonly attachmentId: string;
|
|
394
502
|
readonly mediaType: QaImageMediaType;
|
|
395
503
|
}
|
|
504
|
+
/**
|
|
505
|
+
* A durable file attached to a sent message. The browser never reads these
|
|
506
|
+
* bytes back (the attachment route serves images); the row shows the handle
|
|
507
|
+
* the model resolves, and the Host keeps the verbatim copy.
|
|
508
|
+
*/
|
|
509
|
+
export interface QaFileView {
|
|
510
|
+
readonly attachmentId: string;
|
|
511
|
+
readonly name: string;
|
|
512
|
+
readonly bytes: number;
|
|
513
|
+
}
|
|
396
514
|
/** A subagent transcript opened read-only from the agents panel. */
|
|
397
515
|
export interface QaSubagentView {
|
|
398
516
|
readonly id: string;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/** Stable, non-workspace child used to keep account directories out of sight. */
|
|
2
|
+
export declare const QA_USER_WORKSPACES_DIRECTORY = ".qa-users";
|
|
3
|
+
/** Conservative fixed budgets; there is deliberately no browser override. */
|
|
4
|
+
export declare const QA_USER_WORKSPACE_MAX_BYTES: number;
|
|
5
|
+
export declare const QA_USER_WORKSPACE_MAX_WRITE_BYTES: number;
|
|
6
|
+
export interface QaToolExecutionLike {
|
|
7
|
+
readonly name: string;
|
|
8
|
+
readonly arguments: unknown;
|
|
9
|
+
}
|
|
10
|
+
export declare function pathIsInside(target: string, root: string): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Resolve the deepest existing ancestor, preserving the missing suffix. This
|
|
13
|
+
* catches symlink escapes for reads and for files which a write is about to
|
|
14
|
+
* create.
|
|
15
|
+
*/
|
|
16
|
+
export declare function canonicalCandidate(input: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Materialize `<registered workspace>/.qa-users/<account UUID>` without
|
|
19
|
+
* registering the child as a DSH Workspace. Both directory levels reject
|
|
20
|
+
* symlinks, and their real paths must stay below the configured workspace.
|
|
21
|
+
*/
|
|
22
|
+
export declare function prepareQaUserWorkspace(workspaceRoot: string, userId: string): string;
|
|
23
|
+
/** Resolve an already provisioned account directory for admission checks. */
|
|
24
|
+
export declare function existingQaUserWorkspace(workspaceRoot: string, userId: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* Monotonic guard used in addition to DSH's workspace-write sandbox. It
|
|
27
|
+
* fences model-controlled file paths for both reads and writes, rejects tools
|
|
28
|
+
* whose implementation can walk above cwd, and enforces bounded scratch use.
|
|
29
|
+
*
|
|
30
|
+
* `attachmentRoot` is the one deliberate read exemption: an uploaded file is
|
|
31
|
+
* an immutable content-addressed copy the deployment stores outside every
|
|
32
|
+
* workspace, and the model reaches it exactly as the harness intends (the
|
|
33
|
+
* prompt carries the stored path). Reads of a single such file are allowed;
|
|
34
|
+
* directory-wide tools stay confined because the store is shared by every
|
|
35
|
+
* account, and writes are never exempted.
|
|
36
|
+
*/
|
|
37
|
+
export declare function qaUserWorkspaceDenial(execution: QaToolExecutionLike, root: string, attachmentRoot?: string): string | undefined;
|
|
38
|
+
//# sourceMappingURL=user-workspace.d.ts.map
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { chmodSync, lstatSync, mkdirSync, readdirSync, realpathSync, statSync, } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
/** Stable, non-workspace child used to keep account directories out of sight. */
|
|
4
|
+
export const QA_USER_WORKSPACES_DIRECTORY = ".qa-users";
|
|
5
|
+
/** Conservative fixed budgets; there is deliberately no browser override. */
|
|
6
|
+
export const QA_USER_WORKSPACE_MAX_BYTES = 256 * 1024 * 1024;
|
|
7
|
+
export const QA_USER_WORKSPACE_MAX_WRITE_BYTES = 10 * 1024 * 1024;
|
|
8
|
+
const USER_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu;
|
|
9
|
+
const PATH_DENIAL = "QA workspace boundary: path is outside this user's directory.";
|
|
10
|
+
const QUOTA_DENIAL = "QA workspace boundary: storage quota exceeded.";
|
|
11
|
+
function samePath(left, right) {
|
|
12
|
+
return process.platform === "win32"
|
|
13
|
+
? left.toLowerCase() === right.toLowerCase()
|
|
14
|
+
: left === right;
|
|
15
|
+
}
|
|
16
|
+
export function pathIsInside(target, root) {
|
|
17
|
+
const relative = path.relative(root, target);
|
|
18
|
+
return (relative === "" ||
|
|
19
|
+
(!relative.startsWith(`..${path.sep}`) &&
|
|
20
|
+
relative !== ".." &&
|
|
21
|
+
!path.isAbsolute(relative)));
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Resolve the deepest existing ancestor, preserving the missing suffix. This
|
|
25
|
+
* catches symlink escapes for reads and for files which a write is about to
|
|
26
|
+
* create.
|
|
27
|
+
*/
|
|
28
|
+
export function canonicalCandidate(input) {
|
|
29
|
+
const resolved = path.resolve(input);
|
|
30
|
+
const suffix = [];
|
|
31
|
+
let cursor = resolved;
|
|
32
|
+
for (;;) {
|
|
33
|
+
try {
|
|
34
|
+
return path.resolve(realpathSync.native(cursor), ...suffix);
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
if (error.code !== "ENOENT")
|
|
38
|
+
throw error;
|
|
39
|
+
const parent = path.dirname(cursor);
|
|
40
|
+
if (parent === cursor)
|
|
41
|
+
throw error;
|
|
42
|
+
suffix.unshift(path.basename(cursor));
|
|
43
|
+
cursor = parent;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function assertPlainDirectory(input) {
|
|
48
|
+
const stat = lstatSync(input);
|
|
49
|
+
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
50
|
+
throw new Error(`QA user workspace must be a real directory: ${input}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Materialize `<registered workspace>/.qa-users/<account UUID>` without
|
|
55
|
+
* registering the child as a DSH Workspace. Both directory levels reject
|
|
56
|
+
* symlinks, and their real paths must stay below the configured workspace.
|
|
57
|
+
*/
|
|
58
|
+
export function prepareQaUserWorkspace(workspaceRoot, userId) {
|
|
59
|
+
if (!USER_ID_PATTERN.test(userId)) {
|
|
60
|
+
throw new Error("QA account id is not safe for a workspace directory");
|
|
61
|
+
}
|
|
62
|
+
const canonicalWorkspace = realpathSync.native(workspaceRoot);
|
|
63
|
+
const usersRoot = path.join(canonicalWorkspace, QA_USER_WORKSPACES_DIRECTORY);
|
|
64
|
+
mkdirSync(usersRoot, { recursive: true, mode: 0o700 });
|
|
65
|
+
assertPlainDirectory(usersRoot);
|
|
66
|
+
if (process.platform !== "win32")
|
|
67
|
+
chmodSync(usersRoot, 0o700);
|
|
68
|
+
const canonicalUsersRoot = realpathSync.native(usersRoot);
|
|
69
|
+
if (!pathIsInside(canonicalUsersRoot, canonicalWorkspace)) {
|
|
70
|
+
throw new Error("QA user-workspace root escapes the configured workspace");
|
|
71
|
+
}
|
|
72
|
+
const userRoot = path.join(canonicalUsersRoot, userId);
|
|
73
|
+
mkdirSync(userRoot, { recursive: true, mode: 0o700 });
|
|
74
|
+
assertPlainDirectory(userRoot);
|
|
75
|
+
if (process.platform !== "win32")
|
|
76
|
+
chmodSync(userRoot, 0o700);
|
|
77
|
+
const canonicalUserRoot = realpathSync.native(userRoot);
|
|
78
|
+
if (!pathIsInside(canonicalUserRoot, canonicalUsersRoot) ||
|
|
79
|
+
!samePath(path.dirname(canonicalUserRoot), canonicalUsersRoot)) {
|
|
80
|
+
throw new Error("QA user workspace escapes its account directory");
|
|
81
|
+
}
|
|
82
|
+
return canonicalUserRoot;
|
|
83
|
+
}
|
|
84
|
+
/** Resolve an already provisioned account directory for admission checks. */
|
|
85
|
+
export function existingQaUserWorkspace(workspaceRoot, userId) {
|
|
86
|
+
if (!USER_ID_PATTERN.test(userId)) {
|
|
87
|
+
throw new Error("QA account id is not safe for a workspace directory");
|
|
88
|
+
}
|
|
89
|
+
const canonicalWorkspace = realpathSync.native(workspaceRoot);
|
|
90
|
+
const usersRoot = path.join(canonicalWorkspace, QA_USER_WORKSPACES_DIRECTORY);
|
|
91
|
+
const userRoot = path.join(usersRoot, userId);
|
|
92
|
+
assertPlainDirectory(usersRoot);
|
|
93
|
+
assertPlainDirectory(userRoot);
|
|
94
|
+
const canonicalUsersRoot = realpathSync.native(usersRoot);
|
|
95
|
+
const canonicalUserRoot = realpathSync.native(userRoot);
|
|
96
|
+
if (!pathIsInside(canonicalUsersRoot, canonicalWorkspace) ||
|
|
97
|
+
!pathIsInside(canonicalUserRoot, canonicalUsersRoot) ||
|
|
98
|
+
!samePath(path.dirname(canonicalUserRoot), canonicalUsersRoot)) {
|
|
99
|
+
throw new Error("QA user workspace escapes the configured workspace");
|
|
100
|
+
}
|
|
101
|
+
return canonicalUserRoot;
|
|
102
|
+
}
|
|
103
|
+
function record(value) {
|
|
104
|
+
return value !== null && typeof value === "object" && !Array.isArray(value)
|
|
105
|
+
? value
|
|
106
|
+
: undefined;
|
|
107
|
+
}
|
|
108
|
+
function requestedPaths(execution) {
|
|
109
|
+
const args = record(execution.arguments);
|
|
110
|
+
if (args === undefined)
|
|
111
|
+
return [];
|
|
112
|
+
switch (execution.name) {
|
|
113
|
+
case "read":
|
|
114
|
+
case "read_image":
|
|
115
|
+
case "write":
|
|
116
|
+
case "edit": {
|
|
117
|
+
return typeof args.file_path === "string" ? [args.file_path] : [];
|
|
118
|
+
}
|
|
119
|
+
case "glob":
|
|
120
|
+
case "grep": {
|
|
121
|
+
return [typeof args.path === "string" ? args.path : "."];
|
|
122
|
+
}
|
|
123
|
+
case "str_replace_editor": {
|
|
124
|
+
return typeof args.path === "string" ? [args.path] : [];
|
|
125
|
+
}
|
|
126
|
+
default:
|
|
127
|
+
return [];
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Whether the named path is only read. Directory-wide tools stay confined even
|
|
132
|
+
* for reads: the attachment store is shared by every account, and only the
|
|
133
|
+
* exact file an upload produced is meant to be reachable.
|
|
134
|
+
*/
|
|
135
|
+
function isReadOnlyPathTool(execution) {
|
|
136
|
+
if (execution.name === "read" || execution.name === "read_image")
|
|
137
|
+
return true;
|
|
138
|
+
return (execution.name === "str_replace_editor" &&
|
|
139
|
+
record(execution.arguments)?.command === "view");
|
|
140
|
+
}
|
|
141
|
+
function directoryBytes(root, stopAfter) {
|
|
142
|
+
let total = 0;
|
|
143
|
+
const pending = [root];
|
|
144
|
+
while (pending.length > 0 && total <= stopAfter) {
|
|
145
|
+
const current = pending.pop();
|
|
146
|
+
for (const entry of readdirSync(current, { withFileTypes: true })) {
|
|
147
|
+
const candidate = path.join(current, entry.name);
|
|
148
|
+
if (entry.isSymbolicLink())
|
|
149
|
+
continue;
|
|
150
|
+
if (entry.isDirectory())
|
|
151
|
+
pending.push(candidate);
|
|
152
|
+
else if (entry.isFile())
|
|
153
|
+
total += statSync(candidate).size;
|
|
154
|
+
if (total > stopAfter)
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return total;
|
|
159
|
+
}
|
|
160
|
+
function requestedWriteBytes(execution) {
|
|
161
|
+
const args = record(execution.arguments);
|
|
162
|
+
if (args === undefined)
|
|
163
|
+
return 0;
|
|
164
|
+
const values = [args.content, args.new_string, args.new_str];
|
|
165
|
+
return values.reduce((total, value) => total + (typeof value === "string" ? Buffer.byteLength(value) : 0), 0);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Monotonic guard used in addition to DSH's workspace-write sandbox. It
|
|
169
|
+
* fences model-controlled file paths for both reads and writes, rejects tools
|
|
170
|
+
* whose implementation can walk above cwd, and enforces bounded scratch use.
|
|
171
|
+
*
|
|
172
|
+
* `attachmentRoot` is the one deliberate read exemption: an uploaded file is
|
|
173
|
+
* an immutable content-addressed copy the deployment stores outside every
|
|
174
|
+
* workspace, and the model reaches it exactly as the harness intends (the
|
|
175
|
+
* prompt carries the stored path). Reads of a single such file are allowed;
|
|
176
|
+
* directory-wide tools stay confined because the store is shared by every
|
|
177
|
+
* account, and writes are never exempted.
|
|
178
|
+
*/
|
|
179
|
+
export function qaUserWorkspaceDenial(execution, root, attachmentRoot) {
|
|
180
|
+
const args = record(execution.arguments);
|
|
181
|
+
if (args?.sandbox_permissions !== undefined ||
|
|
182
|
+
(execution.name === "edit" &&
|
|
183
|
+
(args?.replace_all === true || args?.replaceAll === true))) {
|
|
184
|
+
return PATH_DENIAL;
|
|
185
|
+
}
|
|
186
|
+
if (execution.name === "bash" ||
|
|
187
|
+
execution.name === "shell" ||
|
|
188
|
+
execution.name.startsWith("terminal_") ||
|
|
189
|
+
execution.name.startsWith("job_") ||
|
|
190
|
+
execution.name === "run_code" ||
|
|
191
|
+
execution.name === "lsp" ||
|
|
192
|
+
execution.name === "apply_patch" ||
|
|
193
|
+
execution.name.startsWith("dsh_git_")) {
|
|
194
|
+
return PATH_DENIAL;
|
|
195
|
+
}
|
|
196
|
+
const readsOnly = isReadOnlyPathTool(execution);
|
|
197
|
+
try {
|
|
198
|
+
for (const requested of requestedPaths(execution)) {
|
|
199
|
+
const absolute = path.isAbsolute(requested)
|
|
200
|
+
? requested
|
|
201
|
+
: path.resolve(root, requested);
|
|
202
|
+
const canonical = canonicalCandidate(absolute);
|
|
203
|
+
if (pathIsInside(canonical, root))
|
|
204
|
+
continue;
|
|
205
|
+
// Resolved only for a path the fence would otherwise refuse, so the
|
|
206
|
+
// common case pays no extra filesystem walk.
|
|
207
|
+
if (readsOnly &&
|
|
208
|
+
attachmentRoot !== undefined &&
|
|
209
|
+
pathIsInside(canonical, canonicalCandidate(attachmentRoot))) {
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
return PATH_DENIAL;
|
|
213
|
+
}
|
|
214
|
+
if (execution.name === "write" ||
|
|
215
|
+
execution.name === "edit" ||
|
|
216
|
+
(execution.name === "str_replace_editor" &&
|
|
217
|
+
record(execution.arguments)?.command !== "view")) {
|
|
218
|
+
const requested = requestedWriteBytes(execution);
|
|
219
|
+
if (requested > QA_USER_WORKSPACE_MAX_WRITE_BYTES ||
|
|
220
|
+
directoryBytes(root, QA_USER_WORKSPACE_MAX_BYTES) + requested >
|
|
221
|
+
QA_USER_WORKSPACE_MAX_BYTES) {
|
|
222
|
+
return QUOTA_DENIAL;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return undefined;
|
|
226
|
+
}
|
|
227
|
+
catch {
|
|
228
|
+
return PATH_DENIAL;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
//# sourceMappingURL=user-workspace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-workspace.js","sourceRoot":"","sources":["../src/user-workspace.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yadsh/dsh-qa-surface",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "A focused end-user QA surface backed by native DeepSeek Harness sessions",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -53,8 +53,10 @@
|
|
|
53
53
|
"@deepseek-ai/dsh-api-session-controller",
|
|
54
54
|
"@deepseek-ai/dsh-agent-presets",
|
|
55
55
|
"@deepseek-ai/dsh-client-connection",
|
|
56
|
+
"@deepseek-ai/dsh-client-file-upload",
|
|
56
57
|
"@deepseek-ai/dsh-client-ui-layout",
|
|
57
58
|
"@deepseek-ai/dsh-client-ui-settings",
|
|
59
|
+
"@deepseek-ai/dsh-client-ui-settings-plugins",
|
|
58
60
|
"@deepseek-ai/dsh-client-ui-theme"
|
|
59
61
|
],
|
|
60
62
|
"platform": "web"
|
|
@@ -68,9 +70,6 @@
|
|
|
68
70
|
"compatibility.json",
|
|
69
71
|
"capability-policy.json",
|
|
70
72
|
"README.md",
|
|
71
|
-
"CHANGELOG.md",
|
|
72
|
-
"docs/*.md",
|
|
73
|
-
"SPEC-dsh-qa-surface.md",
|
|
74
73
|
"LICENSE"
|
|
75
74
|
],
|
|
76
75
|
"keywords": [
|
|
@@ -78,9 +77,12 @@
|
|
|
78
77
|
"deepseek-harness",
|
|
79
78
|
"dsh",
|
|
80
79
|
"dsh-plugin",
|
|
80
|
+
"cordis",
|
|
81
81
|
"qa",
|
|
82
82
|
"chat",
|
|
83
|
-
"web-ui"
|
|
83
|
+
"web-ui",
|
|
84
|
+
"testing",
|
|
85
|
+
"quality-assurance"
|
|
84
86
|
],
|
|
85
87
|
"license": "MIT",
|
|
86
88
|
"engines": {
|
|
@@ -100,9 +102,11 @@
|
|
|
100
102
|
"@deepseek-ai/dsh-client-ui-layout": ">=0.1.5-rc.2 <0.2.0",
|
|
101
103
|
"@deepseek-ai/dsh-client-ui-renderer": ">=0.1.5-rc.2 <0.2.0",
|
|
102
104
|
"@deepseek-ai/dsh-client-ui-settings": ">=0.1.5-rc.2 <0.2.0",
|
|
105
|
+
"@deepseek-ai/dsh-client-ui-settings-plugins": ">=0.1.5-rc.2 <0.2.0",
|
|
103
106
|
"@deepseek-ai/dsh-client-ui-slots": ">=0.1.5-rc.2 <0.2.0",
|
|
104
107
|
"@deepseek-ai/dsh-client-ui-theme": ">=0.1.5-rc.2 <0.2.0",
|
|
105
108
|
"@deepseek-ai/dsh-host-webserver": ">=0.1.5-rc.2 <0.2.0",
|
|
109
|
+
"@deepseek-ai/dsh-llm": ">=0.1.5-rc.2 <0.2.0",
|
|
106
110
|
"@deepseek-ai/dsh-permission-presets": ">=0.1.5-rc.2 <0.2.0",
|
|
107
111
|
"@deepseek-ai/dsh-session": ">=0.1.5-rc.2 <0.2.0",
|
|
108
112
|
"@deepseek-ai/dsh-settings": ">=0.1.5-rc.2 <0.2.0",
|
|
@@ -115,7 +119,7 @@
|
|
|
115
119
|
},
|
|
116
120
|
"dependencies": {
|
|
117
121
|
"zod": "^4.4.3",
|
|
118
|
-
"@yadsh/dsh-plugin-log": "^0.
|
|
122
|
+
"@yadsh/dsh-plugin-log": "^0.3.0"
|
|
119
123
|
},
|
|
120
124
|
"devDependencies": {
|
|
121
125
|
"@deepseek-ai/cordis": "4.0.2",
|
|
@@ -131,9 +135,11 @@
|
|
|
131
135
|
"@deepseek-ai/dsh-client-ui-layout": "0.1.5-rc.2",
|
|
132
136
|
"@deepseek-ai/dsh-client-ui-renderer": "0.1.5-rc.2",
|
|
133
137
|
"@deepseek-ai/dsh-client-ui-settings": "0.1.5-rc.2",
|
|
138
|
+
"@deepseek-ai/dsh-client-ui-settings-plugins": "0.1.5-rc.2",
|
|
134
139
|
"@deepseek-ai/dsh-client-ui-slots": "0.1.5-rc.2",
|
|
135
140
|
"@deepseek-ai/dsh-client-ui-theme": "0.1.5-rc.2",
|
|
136
141
|
"@deepseek-ai/dsh-host-webserver": "0.1.5-rc.2",
|
|
142
|
+
"@deepseek-ai/dsh-llm": "0.1.5-rc.2",
|
|
137
143
|
"@deepseek-ai/dsh-permission-presets": "0.1.5-rc.2",
|
|
138
144
|
"@deepseek-ai/dsh-session": "0.1.5-rc.2",
|
|
139
145
|
"@deepseek-ai/dsh-settings": "0.1.5-rc.2",
|
|
@@ -155,8 +161,9 @@
|
|
|
155
161
|
"tsdown": "^0.22.14",
|
|
156
162
|
"typescript": "^7.0.2",
|
|
157
163
|
"vitest": "^4.1.11",
|
|
164
|
+
"@yadsh/dsh-config": "^0.0.0",
|
|
158
165
|
"@yadsh/dsh-plugin-scripts": "^0.0.0",
|
|
159
|
-
"@yadsh/dsh-
|
|
166
|
+
"@yadsh/dsh-plugin-kit": "^0.1.0"
|
|
160
167
|
},
|
|
161
168
|
"publishConfig": {
|
|
162
169
|
"access": "public",
|