@yadsh/dsh-qa-surface 0.1.0 → 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.
- package/CHANGELOG.md +83 -0
- package/README.md +162 -14
- package/SPEC-dsh-qa-surface.md +600 -96
- package/capability-policy.json +5 -0
- package/compatibility.json +7 -1
- package/cordis.patch.yml +11 -0
- package/docs/ARCHITECTURE.md +49 -7
- package/docs/COMPATIBILITY.md +5 -4
- package/docs/CONFIGURATION.md +96 -2
- package/lib/attestation.js +10 -0
- package/lib/attestation.js.map +1 -0
- package/lib/client/QaConfigController.js +111 -4
- package/lib/client/QaConfigController.js.map +1 -1
- package/lib/client/QaSessionController.js +501 -119
- package/lib/client/QaSessionController.js.map +1 -1
- package/lib/client/QaSurface.js +137 -20
- package/lib/client/QaSurface.js.map +1 -1
- package/lib/client/QaTranscriptAdapter.js +534 -45
- package/lib/client/QaTranscriptAdapter.js.map +1 -1
- package/lib/client/attestation.js +60 -0
- package/lib/client/attestation.js.map +1 -0
- package/lib/client/chat-index.js +86 -0
- package/lib/client/chat-index.js.map +1 -0
- package/lib/client/components/Markdown.js +75 -5
- package/lib/client/components/Markdown.js.map +1 -1
- package/lib/client/components/QaAgentsDrawer.js +40 -0
- package/lib/client/components/QaAgentsDrawer.js.map +1 -0
- package/lib/client/components/QaComposer.js +132 -15
- package/lib/client/components/QaComposer.js.map +1 -1
- package/lib/client/components/QaMessage.js +184 -10
- package/lib/client/components/QaMessage.js.map +1 -1
- package/lib/client/components/QaSidebar.js +124 -0
- package/lib/client/components/QaSidebar.js.map +1 -0
- package/lib/client/components/QaSourcesDrawer.js +46 -0
- package/lib/client/components/QaSourcesDrawer.js.map +1 -0
- package/lib/client/components/QaWorkGroup.js +135 -0
- package/lib/client/components/QaWorkGroup.js.map +1 -0
- package/lib/client/components/VariantSwitcher.js +29 -0
- package/lib/client/components/VariantSwitcher.js.map +1 -0
- package/lib/client/components/format.js +48 -0
- package/lib/client/components/format.js.map +1 -0
- package/lib/client/index.js +77 -34
- package/lib/client/index.js.map +1 -1
- package/lib/client/styles.js +308 -43
- package/lib/client/styles.js.map +1 -1
- package/lib/client/types.js +13 -0
- package/lib/client/types.js.map +1 -0
- package/lib/client/wait-for.js +49 -0
- package/lib/client/wait-for.js.map +1 -0
- package/lib/client.js +8228 -383
- package/lib/client.js.map +1 -1
- package/lib/config.js +61 -9
- package/lib/config.js.map +1 -1
- package/lib/index.js +166 -70
- package/lib/index.js.map +1 -1
- package/lib/lockdown-policy.js +20 -0
- package/lib/lockdown-policy.js.map +1 -0
- package/lib/resolve-config.js +122 -10
- package/lib/resolve-config.js.map +1 -1
- package/lib/secure-session.js +170 -0
- package/lib/secure-session.js.map +1 -0
- package/lib/typert.host.d.ts +3 -0
- package/lib/typert.host.js +191 -0
- package/lib/typert.remote-client.d.ts +24 -0
- package/lib/typert.remote-client.js +129 -0
- package/lib/types/attestation.d.ts +17 -0
- package/lib/types/client/QaConfigController.d.ts +34 -2
- package/lib/types/client/QaSessionController.d.ts +106 -19
- package/lib/types/client/QaSurface.d.ts +5 -4
- package/lib/types/client/QaTranscriptAdapter.d.ts +17 -2
- package/lib/types/client/attestation.d.ts +25 -0
- package/lib/types/client/chat-index.d.ts +28 -0
- package/lib/types/client/components/Markdown.d.ts +7 -3
- package/lib/types/client/components/QaAgentsDrawer.d.ts +25 -0
- package/lib/types/client/components/QaComposer.d.ts +12 -2
- package/lib/types/client/components/QaMessage.d.ts +14 -1
- package/lib/types/client/components/QaSidebar.d.ts +41 -0
- package/lib/types/client/components/QaSourcesDrawer.d.ts +8 -0
- package/lib/types/client/components/QaWorkGroup.d.ts +19 -0
- package/lib/types/client/components/VariantSwitcher.d.ts +19 -0
- package/lib/types/client/components/format.d.ts +9 -0
- package/lib/types/client/index.d.ts +1 -5
- package/lib/types/client/types.d.ts +29 -0
- package/lib/types/client/wait-for.d.ts +11 -0
- package/lib/types/index.d.ts +22 -6
- package/lib/types/lockdown-policy.d.ts +18 -0
- package/lib/types/secure-session.d.ts +22 -0
- package/lib/types/types.d.ts +148 -1
- package/package.json +76 -52
package/lib/config.js
CHANGED
|
@@ -10,25 +10,28 @@ const configSchema = z.object({
|
|
|
10
10
|
.default({ path: "/qa", matchChildren: true }),
|
|
11
11
|
branding: z
|
|
12
12
|
.object({
|
|
13
|
-
title: z.string().default("
|
|
13
|
+
title: z.string().default("Помощник"),
|
|
14
14
|
subtitle: z.string().default(""),
|
|
15
|
-
welcomeMessage: z.string().default("
|
|
16
|
-
placeholder: z.string().default("
|
|
15
|
+
welcomeMessage: z.string().default("Чем могу помочь?"),
|
|
16
|
+
placeholder: z.string().default("Задайте вопрос…"),
|
|
17
17
|
logoUrl: nullableString.default(null),
|
|
18
|
+
disclaimer: nullableString.default("Диалоги могут быть видны другим пользователям сервера и используются для улучшения качества ответов."),
|
|
18
19
|
})
|
|
19
20
|
.default({
|
|
20
|
-
title: "
|
|
21
|
+
title: "Помощник",
|
|
21
22
|
subtitle: "",
|
|
22
|
-
welcomeMessage: "
|
|
23
|
-
placeholder: "
|
|
23
|
+
welcomeMessage: "Чем могу помочь?",
|
|
24
|
+
placeholder: "Задайте вопрос…",
|
|
24
25
|
logoUrl: null,
|
|
26
|
+
disclaimer: "Диалоги могут быть видны другим пользователям сервера и используются для улучшения качества ответов.",
|
|
25
27
|
}),
|
|
26
28
|
session: z
|
|
27
29
|
.object({
|
|
28
30
|
policy: z
|
|
29
31
|
.union(["browser-persistent", "new-on-load", "fixed"])
|
|
30
32
|
.default("browser-persistent"),
|
|
31
|
-
storageKey: z.string().default("dsh-qa-surface"),
|
|
33
|
+
storageKey: z.string().default("dsh-qa-surface.session"),
|
|
34
|
+
cwd: nullableString.default(null),
|
|
32
35
|
workspaceId: nullableString.default(null),
|
|
33
36
|
fixedSessionId: nullableString.default(null),
|
|
34
37
|
agentPreset: nullableString.default(null),
|
|
@@ -38,7 +41,8 @@ const configSchema = z.object({
|
|
|
38
41
|
})
|
|
39
42
|
.default({
|
|
40
43
|
policy: "browser-persistent",
|
|
41
|
-
storageKey: "dsh-qa-surface",
|
|
44
|
+
storageKey: "dsh-qa-surface.session",
|
|
45
|
+
cwd: null,
|
|
42
46
|
workspaceId: null,
|
|
43
47
|
fixedSessionId: null,
|
|
44
48
|
agentPreset: null,
|
|
@@ -56,6 +60,7 @@ const configSchema = z.object({
|
|
|
56
60
|
showReasoning: z.boolean().default(false),
|
|
57
61
|
renderMarkdown: z.boolean().default(true),
|
|
58
62
|
maxContentWidth: z.number().step(1).min(480).max(1600).default(900),
|
|
63
|
+
showSessionList: z.boolean().default(false),
|
|
59
64
|
})
|
|
60
65
|
.default({
|
|
61
66
|
showHeader: true,
|
|
@@ -66,14 +71,61 @@ const configSchema = z.object({
|
|
|
66
71
|
showReasoning: false,
|
|
67
72
|
renderMarkdown: true,
|
|
68
73
|
maxContentWidth: 900,
|
|
74
|
+
showSessionList: false,
|
|
69
75
|
}),
|
|
70
|
-
suggestedQuestions: z
|
|
76
|
+
suggestedQuestions: z
|
|
77
|
+
.array(z.string())
|
|
78
|
+
.default([
|
|
79
|
+
"Что ты умеешь?",
|
|
80
|
+
"С чего начать?",
|
|
81
|
+
"Помоги разобраться с ошибкой",
|
|
82
|
+
]),
|
|
71
83
|
interaction: z
|
|
72
84
|
.object({
|
|
73
85
|
approvals: z.union(["blocked"]).default("blocked"),
|
|
74
86
|
questions: z.union(["unsupported"]).default("unsupported"),
|
|
75
87
|
})
|
|
76
88
|
.default({ approvals: "blocked", questions: "unsupported" }),
|
|
89
|
+
lockdown: z
|
|
90
|
+
.object({
|
|
91
|
+
enabled: z.boolean().default(true),
|
|
92
|
+
enforceFixedAgentPreset: z.boolean().default(true),
|
|
93
|
+
enforceFixedWorkspace: z.boolean().default(true),
|
|
94
|
+
enforceFixedModel: z.boolean().default(true),
|
|
95
|
+
sandboxMode: z.union(["read-only"]).default("read-only"),
|
|
96
|
+
approvalPolicy: z.union(["never"]).default("never"),
|
|
97
|
+
permissionPreset: z.string().default("qa-read-only"),
|
|
98
|
+
allowPermissionChanges: z.const(false).default(false),
|
|
99
|
+
allowSlashCommands: z.const(false).default(false),
|
|
100
|
+
allowSettingsMutation: z.const(false).default(false),
|
|
101
|
+
allowSessionReset: z.boolean().default(false),
|
|
102
|
+
allowSessionRename: z.const(false).default(false),
|
|
103
|
+
allowSessionDelete: z.const(false).default(false),
|
|
104
|
+
allowArbitrarySessionOpen: z.const(false).default(false),
|
|
105
|
+
toolPolicy: z
|
|
106
|
+
.object({
|
|
107
|
+
mode: z.union(["allow-list"]).default("allow-list"),
|
|
108
|
+
allow: z.array(z.string()).default([]),
|
|
109
|
+
})
|
|
110
|
+
.default({ mode: "allow-list", allow: [] }),
|
|
111
|
+
})
|
|
112
|
+
.default({
|
|
113
|
+
enabled: true,
|
|
114
|
+
enforceFixedAgentPreset: true,
|
|
115
|
+
enforceFixedWorkspace: true,
|
|
116
|
+
enforceFixedModel: true,
|
|
117
|
+
sandboxMode: "read-only",
|
|
118
|
+
approvalPolicy: "never",
|
|
119
|
+
permissionPreset: "qa-read-only",
|
|
120
|
+
allowPermissionChanges: false,
|
|
121
|
+
allowSlashCommands: false,
|
|
122
|
+
allowSettingsMutation: false,
|
|
123
|
+
allowSessionReset: false,
|
|
124
|
+
allowSessionRename: false,
|
|
125
|
+
allowSessionDelete: false,
|
|
126
|
+
allowArbitrarySessionOpen: false,
|
|
127
|
+
toolPolicy: { mode: "allow-list", allow: [] },
|
|
128
|
+
}),
|
|
77
129
|
embedding: z
|
|
78
130
|
.object({ frameAncestors: nullableString.default(null) })
|
|
79
131
|
.default({ frameAncestors: null }),
|
package/lib/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,0BAA0B,CAAC;AAGzC,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAE5D,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5B,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAClC,KAAK,EAAE,CAAC;SACL,MAAM,CAAC;QACN,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;QAC/B,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;KACzC,CAAC;SACD,OAAO,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;IAChD,QAAQ,EAAE,CAAC;SACR,MAAM,CAAC;QACN,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,0BAA0B,CAAC;AAGzC,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAE5D,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5B,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAClC,KAAK,EAAE,CAAC;SACL,MAAM,CAAC;QACN,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;QAC/B,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;KACzC,CAAC;SACD,OAAO,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;IAChD,QAAQ,EAAE,CAAC;SACR,MAAM,CAAC;QACN,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC;QACrC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;QAChC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,kBAAkB,CAAC;QACtD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,iBAAiB,CAAC;QAClD,OAAO,EAAE,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC;QACrC,UAAU,EAAE,cAAc,CAAC,OAAO,CAChC,sGAAsG,CACvG;KACF,CAAC;SACD,OAAO,CAAC;QACP,KAAK,EAAE,UAAU;QACjB,QAAQ,EAAE,EAAE;QACZ,cAAc,EAAE,kBAAkB;QAClC,WAAW,EAAE,iBAAiB;QAC9B,OAAO,EAAE,IAAI;QACb,UAAU,EACR,sGAAsG;KACzG,CAAC;IACJ,OAAO,EAAE,CAAC;SACP,MAAM,CAAC;QACN,MAAM,EAAE,CAAC;aACN,KAAK,CAAC,CAAC,oBAAoB,EAAE,aAAa,EAAE,OAAO,CAAU,CAAC;aAC9D,OAAO,CAAC,oBAAoB,CAAC;QAChC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,wBAAwB,CAAC;QACxD,GAAG,EAAE,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC;QACjC,WAAW,EAAE,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC;QACzC,cAAc,EAAE,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC;QAC5C,WAAW,EAAE,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC;QACzC,QAAQ,EAAE,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC;QACtC,KAAK,EAAE,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC;QACnC,eAAe,EAAE,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC;KAC9C,CAAC;SACD,OAAO,CAAC;QACP,MAAM,EAAE,oBAAoB;QAC5B,UAAU,EAAE,wBAAwB;QACpC,GAAG,EAAE,IAAI;QACT,WAAW,EAAE,IAAI;QACjB,cAAc,EAAE,IAAI;QACpB,WAAW,EAAE,IAAI;QACjB,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,IAAI;QACX,eAAe,EAAE,IAAI;KACtB,CAAC;IACJ,EAAE,EAAE,CAAC;SACF,MAAM,CAAC;QACN,UAAU,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;QACrC,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;QACpC,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;QACnC,cAAc,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;QAC1C,gBAAgB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;QAC5C,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;QACzC,cAAc,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;QACzC,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC;QACnE,eAAe,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;KAC5C,CAAC;SACD,OAAO,CAAC;QACP,UAAU,EAAE,IAAI;QAChB,SAAS,EAAE,IAAI;QACf,QAAQ,EAAE,IAAI;QACd,cAAc,EAAE,KAAK;QACrB,gBAAgB,EAAE,KAAK;QACvB,aAAa,EAAE,KAAK;QACpB,cAAc,EAAE,IAAI;QACpB,eAAe,EAAE,GAAG;QACpB,eAAe,EAAE,KAAK;KACvB,CAAC;IACJ,kBAAkB,EAAE,CAAC;SAClB,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;SACjB,OAAO,CAAC;QACP,gBAAgB;QAChB,gBAAgB;QAChB,8BAA8B;KAC/B,CAAC;IACJ,WAAW,EAAE,CAAC;SACX,MAAM,CAAC;QACN,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,SAAS,CAAU,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC;QAC3D,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,aAAa,CAAU,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC;KACpE,CAAC;SACD,OAAO,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC;IAC9D,QAAQ,EAAE,CAAC;SACR,MAAM,CAAC;QACN,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;QAClC,uBAAuB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;QAClD,qBAAqB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;QAChD,iBAAiB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;QAC5C,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,WAAW,CAAU,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;QACjE,cAAc,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAU,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;QAC5D,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,cAAc,CAAC;QACpD,sBAAsB,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;QACrD,kBAAkB,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;QACjD,qBAAqB,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;QACpD,iBAAiB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;QAC7C,kBAAkB,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;QACjD,kBAAkB,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;QACjD,yBAAyB,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;QACxD,UAAU,EAAE,CAAC;aACV,MAAM,CAAC;YACN,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,YAAY,CAAU,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC;YAC5D,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;SACvC,CAAC;aACD,OAAO,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;KAC9C,CAAC;SACD,OAAO,CAAC;QACP,OAAO,EAAE,IAAI;QACb,uBAAuB,EAAE,IAAI;QAC7B,qBAAqB,EAAE,IAAI;QAC3B,iBAAiB,EAAE,IAAI;QACvB,WAAW,EAAE,WAAW;QACxB,cAAc,EAAE,OAAO;QACvB,gBAAgB,EAAE,cAAc;QAChC,sBAAsB,EAAE,KAAK;QAC7B,kBAAkB,EAAE,KAAK;QACzB,qBAAqB,EAAE,KAAK;QAC5B,iBAAiB,EAAE,KAAK;QACxB,kBAAkB,EAAE,KAAK;QACzB,kBAAkB,EAAE,KAAK;QACzB,yBAAyB,EAAE,KAAK;QAChC,UAAU,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,EAAE,EAAE;KAC9C,CAAC;IACJ,SAAS,EAAE,CAAC;SACT,MAAM,CAAC,EAAE,cAAc,EAAE,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;SACxD,OAAO,CAAC,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC;CACrC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,YAAY,GAAG,YAA6C,CAAC;AAC1E,OAAO,EACL,yBAAyB,EACzB,kBAAkB,EAClB,aAAa,GACd,MAAM,qBAAqB,CAAC"}
|
package/lib/index.js
CHANGED
|
@@ -1,83 +1,179 @@
|
|
|
1
|
-
|
|
1
|
+
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
|
|
2
|
+
var useValue = arguments.length > 2;
|
|
3
|
+
for (var i = 0; i < initializers.length; i++) {
|
|
4
|
+
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
5
|
+
}
|
|
6
|
+
return useValue ? value : void 0;
|
|
7
|
+
};
|
|
8
|
+
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
9
|
+
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
|
10
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
11
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
12
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
13
|
+
var _, done = false;
|
|
14
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
15
|
+
var context = {};
|
|
16
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
17
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
18
|
+
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
|
|
19
|
+
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
|
|
20
|
+
if (kind === "accessor") {
|
|
21
|
+
if (result === void 0) continue;
|
|
22
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
23
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
|
24
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
|
25
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
|
26
|
+
}
|
|
27
|
+
else if (_ = accept(result)) {
|
|
28
|
+
if (kind === "field") initializers.unshift(_);
|
|
29
|
+
else descriptor[key] = _;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
33
|
+
done = true;
|
|
34
|
+
};
|
|
35
|
+
import { Remote, TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
|
|
2
36
|
import { installSettingsSection, settingsNamespace, } from "@deepseek-ai/dsh-settings";
|
|
3
37
|
import { createHostLoggerSink, getPluginLogger, } from "@yadsh/dsh-plugin-log";
|
|
4
38
|
import { ConfigSchema, resolveConfig } from "./config.js";
|
|
39
|
+
import { QaAttestationError } from "./attestation.js";
|
|
5
40
|
import { registerQaNavigationRoute } from "./host-route.js";
|
|
41
|
+
import { QaPolicyAdmission } from "./secure-session.js";
|
|
6
42
|
export const name = "qa-surface";
|
|
7
|
-
export const inject = [
|
|
43
|
+
export const inject = [
|
|
44
|
+
"agents",
|
|
45
|
+
"agentPresets",
|
|
46
|
+
"permissionPresets",
|
|
47
|
+
"tools",
|
|
48
|
+
"workspaceRegistry",
|
|
49
|
+
];
|
|
8
50
|
export const QA_SURFACE_SETTINGS_NAMESPACE = settingsNamespace("qa-surface");
|
|
9
51
|
export const Config = ConfigSchema;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
52
|
+
const CONFIGURATION_ERROR = "Assistant configuration is unavailable.";
|
|
53
|
+
/** Host companion: validates config, owns the admission boundary and the route. */
|
|
54
|
+
let QaSurface = (() => {
|
|
55
|
+
let _classSuper = TypertRemoteService;
|
|
56
|
+
let _instanceExtraInitializers = [];
|
|
57
|
+
let _describe_decorators;
|
|
58
|
+
let _secureSession_decorators;
|
|
59
|
+
return class QaSurface extends _classSuper {
|
|
60
|
+
static {
|
|
61
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
62
|
+
_describe_decorators = [Remote("describe")];
|
|
63
|
+
_secureSession_decorators = [Remote("secureSession")];
|
|
64
|
+
__esDecorate(this, null, _describe_decorators, { kind: "method", name: "describe", static: false, private: false, access: { has: obj => "describe" in obj, get: obj => obj.describe }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
65
|
+
__esDecorate(this, null, _secureSession_decorators, { kind: "method", name: "secureSession", static: false, private: false, access: { has: obj => "secureSession" in obj, get: obj => obj.secureSession }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
66
|
+
if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
67
|
+
}
|
|
68
|
+
static inject = inject;
|
|
69
|
+
static Config = ConfigSchema;
|
|
70
|
+
source = __runInitializers(this, _instanceExtraInitializers);
|
|
71
|
+
logger;
|
|
72
|
+
admission;
|
|
73
|
+
webServer;
|
|
74
|
+
disposeRoute;
|
|
75
|
+
routeKey;
|
|
76
|
+
constructor(ctx, entry = {}) {
|
|
77
|
+
super(ctx, "qaSurface", { namespace: "qaSurface" });
|
|
78
|
+
const resolvedEntry = resolveConfig(entry);
|
|
79
|
+
this.source = () => resolvedEntry;
|
|
80
|
+
this.logger = getPluginLogger({
|
|
81
|
+
pluginId: "dsh-qa-surface",
|
|
82
|
+
consoleSink: createHostLoggerSink(ctx.logger),
|
|
83
|
+
});
|
|
84
|
+
this.admission = new QaPolicyAdmission(ctx, () => this.getConfig(), this.logger);
|
|
85
|
+
ctx.effect(() => async () => this.logger.close(), "dsh-qa-surface.logger");
|
|
86
|
+
ctx.effect(() => () => this.admission.dispose(), "dsh-qa-surface.lockdown-policies");
|
|
87
|
+
installSettingsSection(ctx, QA_SURFACE_SETTINGS_NAMESPACE, ConfigSchema, entry, {
|
|
88
|
+
setSource: (source) => {
|
|
89
|
+
this.source = source;
|
|
90
|
+
},
|
|
91
|
+
onChange: () => {
|
|
92
|
+
const config = this.getConfig();
|
|
93
|
+
this.refreshRoute();
|
|
94
|
+
this.logger.info("config.updated", {
|
|
95
|
+
enabled: config.enabled,
|
|
96
|
+
route: config.route.path,
|
|
97
|
+
sessionPolicy: config.session.policy,
|
|
98
|
+
});
|
|
99
|
+
},
|
|
100
|
+
validate: (value) => {
|
|
101
|
+
resolveConfig(value);
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
ctx.inject(["webServer"], (webContext) => {
|
|
105
|
+
this.webServer = webContext.webServer;
|
|
34
106
|
this.refreshRoute();
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
107
|
+
webContext.effect(() => () => {
|
|
108
|
+
this.disposeRoute?.();
|
|
109
|
+
this.disposeRoute = undefined;
|
|
110
|
+
this.routeKey = undefined;
|
|
111
|
+
this.webServer = undefined;
|
|
112
|
+
}, "dsh-qa-surface.navigation-route");
|
|
113
|
+
});
|
|
114
|
+
this.logger.info("plugin.ready", {
|
|
115
|
+
enabled: resolvedEntry.enabled,
|
|
116
|
+
route: resolvedEntry.route.path,
|
|
117
|
+
sessionPolicy: resolvedEntry.session.policy,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
getConfig() {
|
|
121
|
+
return resolveConfig(this.source());
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Serve the effective QA configuration to the browser. The DSH gateway pins
|
|
125
|
+
* settings RPCs to loopback, so a browser served over the LAN always sees
|
|
126
|
+
* the settings namespace as unavailable; this method is the config channel
|
|
127
|
+
* such a browser falls back to. It is read-only projection — the admission
|
|
128
|
+
* boundary stays in {@link secureSession}.
|
|
129
|
+
*/
|
|
130
|
+
describe() {
|
|
131
|
+
return this.getConfig();
|
|
132
|
+
}
|
|
133
|
+
/** Pin and attest the effective policy. The browser supplies identity only. */
|
|
134
|
+
secureSession(sessionId) {
|
|
135
|
+
try {
|
|
136
|
+
return this.admission.secureSession(sessionId);
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
// The carrier empties error.details, so the coarse reason rides the
|
|
140
|
+
// wire message for the browser console; the specific mismatch facts
|
|
141
|
+
// stay in this log only.
|
|
142
|
+
const reason = error instanceof QaAttestationError
|
|
143
|
+
? error.reason
|
|
144
|
+
: "attestation-failed";
|
|
145
|
+
this.logger.error("lockdown.rejected", {
|
|
146
|
+
sessionId,
|
|
147
|
+
reason,
|
|
148
|
+
error: error instanceof Error ? error.message : String(error),
|
|
39
149
|
});
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
refreshRoute() {
|
|
65
|
-
const config = this.getConfig();
|
|
66
|
-
const key = config.enabled
|
|
67
|
-
? `${config.route.path}:${config.route.matchChildren}`
|
|
68
|
-
: undefined;
|
|
69
|
-
if (key === this.routeKey)
|
|
70
|
-
return;
|
|
71
|
-
this.disposeRoute?.();
|
|
72
|
-
this.disposeRoute = undefined;
|
|
73
|
-
this.routeKey = undefined;
|
|
74
|
-
if (key === undefined || this.webServer === undefined)
|
|
75
|
-
return;
|
|
76
|
-
this.disposeRoute = registerQaNavigationRoute(this.webServer, config);
|
|
77
|
-
this.routeKey = key;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
150
|
+
throw new Error(`${CONFIGURATION_ERROR} (reason: ${reason})`, {
|
|
151
|
+
cause: error,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
refreshRoute() {
|
|
156
|
+
const config = this.getConfig();
|
|
157
|
+
const key = config.enabled
|
|
158
|
+
? `${config.route.path}:${config.route.matchChildren}`
|
|
159
|
+
: undefined;
|
|
160
|
+
if (key === this.routeKey)
|
|
161
|
+
return;
|
|
162
|
+
this.disposeRoute?.();
|
|
163
|
+
this.disposeRoute = undefined;
|
|
164
|
+
this.routeKey = undefined;
|
|
165
|
+
if (key === undefined || this.webServer === undefined)
|
|
166
|
+
return;
|
|
167
|
+
this.disposeRoute = registerQaNavigationRoute(this.webServer, config);
|
|
168
|
+
this.routeKey = key;
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
})();
|
|
172
|
+
export { QaSurface };
|
|
80
173
|
export { ConfigSchema, DEFAULT_QA_SURFACE_CONFIG, normalizeRoutePath, resolveConfig, } from "./config.js";
|
|
174
|
+
export { QaAttestationError } from "./attestation.js";
|
|
81
175
|
export { registerQaNavigationRoute } from "./host-route.js";
|
|
176
|
+
export { qaToolDenial, qaToolPolicyPlan } from "./lockdown-policy.js";
|
|
177
|
+
export { QaPolicyAdmission } from "./secure-session.js";
|
|
82
178
|
export default QaSurface;
|
|
83
179
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const TOOL_DENIAL = "This tool is not available in the QA execution profile.";
|
|
2
|
+
/**
|
|
3
|
+
* Validate an allow-list against the complete agent-scoped view.
|
|
4
|
+
*
|
|
5
|
+
* Preset tools live on an ancestor scope, not necessarily in the global tool
|
|
6
|
+
* layer. The restriction must therefore retain the configured names verbatim;
|
|
7
|
+
* deriving it from the global view would hide every preset-owned tool after a
|
|
8
|
+
* successful first attestation and make the next attestation fail.
|
|
9
|
+
*/
|
|
10
|
+
export function qaToolPolicyPlan(allow, isMounted) {
|
|
11
|
+
return {
|
|
12
|
+
allow: [...allow],
|
|
13
|
+
unknown: allow.filter((toolName) => !isMounted(toolName)),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/** Monotonic execution decision shared by inherited, scoped and transport tools. */
|
|
17
|
+
export function qaToolDenial(allowed, toolName) {
|
|
18
|
+
return allowed.has(toolName) ? undefined : TOOL_DENIAL;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=lockdown-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lockdown-policy.js","sourceRoot":"","sources":["../src/lockdown-policy.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,GAAG,yDAAyD,CAAC;AAS9E;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAC9B,KAAwB,EACxB,SAAwC;IAExC,OAAO;QACL,KAAK,EAAE,CAAC,GAAG,KAAK,CAAC;QACjB,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;KAC1D,CAAC;AACJ,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,YAAY,CAC1B,OAA4B,EAC5B,QAAgB;IAEhB,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC;AACzD,CAAC"}
|
package/lib/resolve-config.js
CHANGED
|
@@ -2,15 +2,17 @@ export const DEFAULT_QA_SURFACE_CONFIG = Object.freeze({
|
|
|
2
2
|
enabled: true,
|
|
3
3
|
route: Object.freeze({ path: "/qa", matchChildren: true }),
|
|
4
4
|
branding: Object.freeze({
|
|
5
|
-
title: "
|
|
5
|
+
title: "Помощник",
|
|
6
6
|
subtitle: "",
|
|
7
|
-
welcomeMessage: "
|
|
8
|
-
placeholder: "
|
|
7
|
+
welcomeMessage: "Чем могу помочь?",
|
|
8
|
+
placeholder: "Задайте вопрос…",
|
|
9
9
|
logoUrl: null,
|
|
10
|
+
disclaimer: "Диалоги могут быть видны другим пользователям сервера и используются для улучшения качества ответов.",
|
|
10
11
|
}),
|
|
11
12
|
session: Object.freeze({
|
|
12
13
|
policy: "browser-persistent",
|
|
13
|
-
storageKey: "dsh-qa-surface",
|
|
14
|
+
storageKey: "dsh-qa-surface.session",
|
|
15
|
+
cwd: null,
|
|
14
16
|
workspaceId: null,
|
|
15
17
|
fixedSessionId: null,
|
|
16
18
|
agentPreset: null,
|
|
@@ -20,19 +22,44 @@ export const DEFAULT_QA_SURFACE_CONFIG = Object.freeze({
|
|
|
20
22
|
}),
|
|
21
23
|
ui: Object.freeze({
|
|
22
24
|
showHeader: true,
|
|
23
|
-
showReset:
|
|
25
|
+
showReset: false,
|
|
24
26
|
showStop: true,
|
|
25
27
|
showTimestamps: false,
|
|
26
28
|
showToolActivity: false,
|
|
27
29
|
showReasoning: false,
|
|
28
30
|
renderMarkdown: true,
|
|
29
31
|
maxContentWidth: 900,
|
|
32
|
+
showSessionList: false,
|
|
30
33
|
}),
|
|
31
|
-
suggestedQuestions: Object.freeze([
|
|
34
|
+
suggestedQuestions: Object.freeze([
|
|
35
|
+
"Что ты умеешь?",
|
|
36
|
+
"С чего начать?",
|
|
37
|
+
"Помоги разобраться с ошибкой",
|
|
38
|
+
]),
|
|
32
39
|
interaction: Object.freeze({
|
|
33
40
|
approvals: "blocked",
|
|
34
41
|
questions: "unsupported",
|
|
35
42
|
}),
|
|
43
|
+
lockdown: Object.freeze({
|
|
44
|
+
enabled: true,
|
|
45
|
+
enforceFixedAgentPreset: true,
|
|
46
|
+
enforceFixedWorkspace: true,
|
|
47
|
+
enforceFixedModel: true,
|
|
48
|
+
sandboxMode: "read-only",
|
|
49
|
+
approvalPolicy: "never",
|
|
50
|
+
permissionPreset: "qa-read-only",
|
|
51
|
+
allowPermissionChanges: false,
|
|
52
|
+
allowSlashCommands: false,
|
|
53
|
+
allowSettingsMutation: false,
|
|
54
|
+
allowSessionReset: false,
|
|
55
|
+
allowSessionRename: false,
|
|
56
|
+
allowSessionDelete: false,
|
|
57
|
+
allowArbitrarySessionOpen: false,
|
|
58
|
+
toolPolicy: Object.freeze({
|
|
59
|
+
mode: "allow-list",
|
|
60
|
+
allow: Object.freeze([]),
|
|
61
|
+
}),
|
|
62
|
+
}),
|
|
36
63
|
embedding: Object.freeze({ frameAncestors: null }),
|
|
37
64
|
});
|
|
38
65
|
function optionalText(value) {
|
|
@@ -65,6 +92,15 @@ function uniqueQuestions(values) {
|
|
|
65
92
|
}
|
|
66
93
|
return Object.freeze(questions);
|
|
67
94
|
}
|
|
95
|
+
function uniqueToolNames(values) {
|
|
96
|
+
const names = [
|
|
97
|
+
...new Set(values.map((value) => value.trim()).filter(Boolean)),
|
|
98
|
+
];
|
|
99
|
+
if (names.some((value) => value.length > 200)) {
|
|
100
|
+
throw new TypeError("dsh-qa-surface: lockdown.toolPolicy.allow names must be at most 200 characters");
|
|
101
|
+
}
|
|
102
|
+
return Object.freeze(names);
|
|
103
|
+
}
|
|
68
104
|
/** Materialize defaults and enforce route/session/model safety constraints. */
|
|
69
105
|
export function resolveConfig(input = {}) {
|
|
70
106
|
const routePath = normalizeRoutePath(input.route?.path ?? DEFAULT_QA_SURFACE_CONFIG.route.path);
|
|
@@ -73,6 +109,16 @@ export function resolveConfig(input = {}) {
|
|
|
73
109
|
if (policy === "fixed" && fixedSessionId === null) {
|
|
74
110
|
throw new TypeError("dsh-qa-surface: session.fixedSessionId is required for fixed policy");
|
|
75
111
|
}
|
|
112
|
+
// The cwd pin is the no-registry alternative to workspaceId; both pin the
|
|
113
|
+
// session to one directory, so together they are a configuration error.
|
|
114
|
+
const cwd = optionalText(input.session?.cwd);
|
|
115
|
+
if (cwd !== null && !/^([a-zA-Z]:[/\\]|\/)/u.test(cwd)) {
|
|
116
|
+
throw new TypeError("dsh-qa-surface: session.cwd must be an absolute directory path");
|
|
117
|
+
}
|
|
118
|
+
const workspaceId = optionalText(input.session?.workspaceId);
|
|
119
|
+
if (workspaceId !== null && cwd !== null) {
|
|
120
|
+
throw new TypeError("dsh-qa-surface: session.workspaceId and session.cwd are mutually exclusive");
|
|
121
|
+
}
|
|
76
122
|
const provider = optionalText(input.session?.provider);
|
|
77
123
|
const model = optionalText(input.session?.model);
|
|
78
124
|
if ((provider === null) !== (model === null)) {
|
|
@@ -89,8 +135,43 @@ export function resolveConfig(input = {}) {
|
|
|
89
135
|
maxContentWidth > 1600) {
|
|
90
136
|
throw new TypeError("dsh-qa-surface: ui.maxContentWidth must be an integer from 480 to 1600");
|
|
91
137
|
}
|
|
92
|
-
|
|
93
|
-
|
|
138
|
+
const lockdownEnabled = input.lockdown?.enabled ?? DEFAULT_QA_SURFACE_CONFIG.lockdown.enabled;
|
|
139
|
+
const rawLockdown = input.lockdown;
|
|
140
|
+
const forbiddenCapabilityFlags = [
|
|
141
|
+
["allowPermissionChanges", rawLockdown?.allowPermissionChanges],
|
|
142
|
+
["allowSlashCommands", rawLockdown?.allowSlashCommands],
|
|
143
|
+
["allowSettingsMutation", rawLockdown?.allowSettingsMutation],
|
|
144
|
+
["allowSessionRename", rawLockdown?.allowSessionRename],
|
|
145
|
+
["allowSessionDelete", rawLockdown?.allowSessionDelete],
|
|
146
|
+
["allowArbitrarySessionOpen", rawLockdown?.allowArbitrarySessionOpen],
|
|
147
|
+
];
|
|
148
|
+
const weakenedFlag = forbiddenCapabilityFlags.find(([, value]) => value === true);
|
|
149
|
+
if (weakenedFlag !== undefined) {
|
|
150
|
+
throw new TypeError(`dsh-qa-surface: lockdown.${weakenedFlag[0]} cannot be enabled`);
|
|
151
|
+
}
|
|
152
|
+
if (input.lockdown?.sandboxMode !== undefined &&
|
|
153
|
+
input.lockdown.sandboxMode !== "read-only") {
|
|
154
|
+
throw new TypeError("dsh-qa-surface: lockdown.sandboxMode must be read-only");
|
|
155
|
+
}
|
|
156
|
+
if (input.lockdown?.approvalPolicy !== undefined &&
|
|
157
|
+
input.lockdown.approvalPolicy !== "never") {
|
|
158
|
+
throw new TypeError("dsh-qa-surface: lockdown.approvalPolicy must be never");
|
|
159
|
+
}
|
|
160
|
+
if (input.lockdown?.toolPolicy?.mode !== undefined &&
|
|
161
|
+
input.lockdown.toolPolicy.mode !== "allow-list") {
|
|
162
|
+
throw new TypeError("dsh-qa-surface: lockdown.toolPolicy.mode must be allow-list");
|
|
163
|
+
}
|
|
164
|
+
const permissionPreset = input.lockdown?.permissionPreset?.trim() ??
|
|
165
|
+
DEFAULT_QA_SURFACE_CONFIG.lockdown.permissionPreset;
|
|
166
|
+
if (lockdownEnabled && permissionPreset === "") {
|
|
167
|
+
throw new TypeError("dsh-qa-surface: lockdown.permissionPreset is required when lockdown is enabled");
|
|
168
|
+
}
|
|
169
|
+
const allowSessionReset = input.lockdown?.allowSessionReset ??
|
|
170
|
+
DEFAULT_QA_SURFACE_CONFIG.lockdown.allowSessionReset;
|
|
171
|
+
if (lockdownEnabled &&
|
|
172
|
+
(input.ui?.showReset ?? DEFAULT_QA_SURFACE_CONFIG.ui.showReset) &&
|
|
173
|
+
!allowSessionReset) {
|
|
174
|
+
throw new TypeError("dsh-qa-surface: ui.showReset requires lockdown.allowSessionReset");
|
|
94
175
|
}
|
|
95
176
|
return Object.freeze({
|
|
96
177
|
enabled: input.enabled ?? DEFAULT_QA_SURFACE_CONFIG.enabled,
|
|
@@ -108,10 +189,16 @@ export function resolveConfig(input = {}) {
|
|
|
108
189
|
placeholder: input.branding?.placeholder?.trim() ||
|
|
109
190
|
DEFAULT_QA_SURFACE_CONFIG.branding.placeholder,
|
|
110
191
|
logoUrl: optionalText(input.branding?.logoUrl),
|
|
192
|
+
// Undefined falls back to the default notice; an explicit null or
|
|
193
|
+
// empty string hides the plate entirely.
|
|
194
|
+
disclaimer: input.branding?.disclaimer === undefined
|
|
195
|
+
? DEFAULT_QA_SURFACE_CONFIG.branding.disclaimer
|
|
196
|
+
: (optionalText(input.branding.disclaimer) ?? ""),
|
|
111
197
|
}),
|
|
112
198
|
session: Object.freeze({
|
|
113
199
|
policy,
|
|
114
200
|
storageKey,
|
|
201
|
+
cwd,
|
|
115
202
|
workspaceId: optionalText(input.session?.workspaceId),
|
|
116
203
|
fixedSessionId,
|
|
117
204
|
agentPreset: optionalText(input.session?.agentPreset),
|
|
@@ -126,15 +213,40 @@ export function resolveConfig(input = {}) {
|
|
|
126
213
|
showTimestamps: input.ui?.showTimestamps ?? DEFAULT_QA_SURFACE_CONFIG.ui.showTimestamps,
|
|
127
214
|
showToolActivity: input.ui?.showToolActivity ??
|
|
128
215
|
DEFAULT_QA_SURFACE_CONFIG.ui.showToolActivity,
|
|
129
|
-
showReasoning:
|
|
216
|
+
showReasoning: input.ui?.showReasoning ?? DEFAULT_QA_SURFACE_CONFIG.ui.showReasoning,
|
|
130
217
|
renderMarkdown: input.ui?.renderMarkdown ?? DEFAULT_QA_SURFACE_CONFIG.ui.renderMarkdown,
|
|
131
218
|
maxContentWidth,
|
|
219
|
+
showSessionList: input.ui?.showSessionList ??
|
|
220
|
+
DEFAULT_QA_SURFACE_CONFIG.ui.showSessionList,
|
|
132
221
|
}),
|
|
133
|
-
suggestedQuestions: uniqueQuestions(input.suggestedQuestions ??
|
|
222
|
+
suggestedQuestions: uniqueQuestions(input.suggestedQuestions ?? DEFAULT_QA_SURFACE_CONFIG.suggestedQuestions),
|
|
134
223
|
interaction: Object.freeze({
|
|
135
224
|
approvals: "blocked",
|
|
136
225
|
questions: "unsupported",
|
|
137
226
|
}),
|
|
227
|
+
lockdown: Object.freeze({
|
|
228
|
+
enabled: lockdownEnabled,
|
|
229
|
+
enforceFixedAgentPreset: input.lockdown?.enforceFixedAgentPreset ??
|
|
230
|
+
DEFAULT_QA_SURFACE_CONFIG.lockdown.enforceFixedAgentPreset,
|
|
231
|
+
enforceFixedWorkspace: input.lockdown?.enforceFixedWorkspace ??
|
|
232
|
+
DEFAULT_QA_SURFACE_CONFIG.lockdown.enforceFixedWorkspace,
|
|
233
|
+
enforceFixedModel: input.lockdown?.enforceFixedModel ??
|
|
234
|
+
DEFAULT_QA_SURFACE_CONFIG.lockdown.enforceFixedModel,
|
|
235
|
+
sandboxMode: "read-only",
|
|
236
|
+
approvalPolicy: "never",
|
|
237
|
+
permissionPreset,
|
|
238
|
+
allowPermissionChanges: false,
|
|
239
|
+
allowSlashCommands: false,
|
|
240
|
+
allowSettingsMutation: false,
|
|
241
|
+
allowSessionReset,
|
|
242
|
+
allowSessionRename: false,
|
|
243
|
+
allowSessionDelete: false,
|
|
244
|
+
allowArbitrarySessionOpen: false,
|
|
245
|
+
toolPolicy: Object.freeze({
|
|
246
|
+
mode: "allow-list",
|
|
247
|
+
allow: uniqueToolNames(input.lockdown?.toolPolicy?.allow ?? []),
|
|
248
|
+
}),
|
|
249
|
+
}),
|
|
138
250
|
embedding: Object.freeze({
|
|
139
251
|
frameAncestors: optionalText(input.embedding?.frameAncestors),
|
|
140
252
|
}),
|