@yadsh/dsh-qa-surface 0.8.0 → 0.10.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 +142 -4
- package/compatibility.json +5 -0
- package/lib/access/capability-catalog.js +32 -3
- package/lib/access/capability-catalog.js.map +1 -1
- package/lib/access/service.js +45 -17
- package/lib/access/service.js.map +1 -1
- package/lib/accounts/errors.js.map +1 -1
- package/lib/accounts/store.js +14 -0
- package/lib/accounts/store.js.map +1 -1
- package/lib/admin/permissions.js +4 -0
- package/lib/admin/permissions.js.map +1 -1
- package/lib/admin/quality-store.js +71 -0
- package/lib/admin/quality-store.js.map +1 -1
- package/lib/admin/service.js +113 -8
- package/lib/admin/service.js.map +1 -1
- package/lib/admin/session-log.js +66 -5
- package/lib/admin/session-log.js.map +1 -1
- package/lib/client/QaSessionController.js +371 -37
- package/lib/client/QaSessionController.js.map +1 -1
- package/lib/client/QaSurface.js +48 -8
- package/lib/client/QaSurface.js.map +1 -1
- package/lib/client/QaSurfaceGuard.js +12 -5
- package/lib/client/QaSurfaceGuard.js.map +1 -1
- package/lib/client/QaTranscriptAdapter.js +36 -0
- package/lib/client/QaTranscriptAdapter.js.map +1 -1
- package/lib/client/admin/QaAdmin.js +14 -2
- package/lib/client/admin/QaAdmin.js.map +1 -1
- package/lib/client/admin/pages/Conversations.js +33 -7
- package/lib/client/admin/pages/Conversations.js.map +1 -1
- package/lib/client/admin/pages/Users.js +9 -2
- package/lib/client/admin/pages/Users.js.map +1 -1
- package/lib/client/admin/shared.js +14 -1
- package/lib/client/admin/shared.js.map +1 -1
- package/lib/client/admin/styles.js +2 -0
- package/lib/client/admin/styles.js.map +1 -1
- package/lib/client/audit/QaAuditDialog.js +74 -0
- package/lib/client/audit/QaAuditDialog.js.map +1 -0
- package/lib/client/audit/QaAuditRowBadge.js +17 -0
- package/lib/client/audit/QaAuditRowBadge.js.map +1 -0
- package/lib/client/audit/controller.js +39 -0
- package/lib/client/audit/controller.js.map +1 -0
- package/lib/client/audit/types.js +36 -0
- package/lib/client/audit/types.js.map +1 -0
- package/lib/client/audit/use-chat-audits.js +139 -0
- package/lib/client/audit/use-chat-audits.js.map +1 -0
- package/lib/client/base64.js +22 -1
- package/lib/client/base64.js.map +1 -1
- package/lib/client/components/QaAgentsDrawer.js +9 -6
- package/lib/client/components/QaAgentsDrawer.js.map +1 -1
- package/lib/client/components/QaApproval.js +1 -1
- package/lib/client/components/QaApproval.js.map +1 -1
- package/lib/client/components/QaChangelog.js +72 -0
- package/lib/client/components/QaChangelog.js.map +1 -1
- package/lib/client/components/QaComposer.js +63 -3
- package/lib/client/components/QaComposer.js.map +1 -1
- package/lib/client/components/QaFilesPanel.js +17 -11
- package/lib/client/components/QaFilesPanel.js.map +1 -1
- package/lib/client/components/QaHeader.js +3 -11
- package/lib/client/components/QaHeader.js.map +1 -1
- package/lib/client/components/QaMessage.js +16 -0
- package/lib/client/components/QaMessage.js.map +1 -1
- package/lib/client/components/QaModal.js.map +1 -1
- package/lib/client/components/QaQuestions.js +5 -5
- package/lib/client/components/QaQuestions.js.map +1 -1
- package/lib/client/components/QaSidebar.js +22 -3
- package/lib/client/components/QaSidebar.js.map +1 -1
- package/lib/client/components/QaWidthHandle.js +111 -5
- package/lib/client/components/QaWidthHandle.js.map +1 -1
- package/lib/client/components/QaWorkspaceBrowser.js +231 -0
- package/lib/client/components/QaWorkspaceBrowser.js.map +1 -0
- package/lib/client/index.js +127 -51
- package/lib/client/index.js.map +1 -1
- package/lib/client/kiosk.js +51 -0
- package/lib/client/kiosk.js.map +1 -0
- package/lib/client/markdown/blocks.js +122 -7
- package/lib/client/markdown/blocks.js.map +1 -1
- package/lib/client/markdown/inline.js +108 -12
- package/lib/client/markdown/inline.js.map +1 -1
- package/lib/client/markdown/katex-css.js +12 -0
- package/lib/client/markdown/katex-css.js.map +1 -0
- package/lib/client/markdown/math.js +84 -0
- package/lib/client/markdown/math.js.map +1 -0
- package/lib/client/markdown/render.js +74 -5
- package/lib/client/markdown/render.js.map +1 -1
- package/lib/client/project-session-state.js +15 -2
- package/lib/client/project-session-state.js.map +1 -1
- package/lib/client/prompt-content.js +26 -0
- package/lib/client/prompt-content.js.map +1 -1
- package/lib/client/settings/card.js +2 -2
- package/lib/client/settings/card.js.map +1 -1
- package/lib/client/settings/sections/lockdown.js +1 -6
- package/lib/client/settings/sections/lockdown.js.map +1 -1
- package/lib/client/settings/sections/notes.js +46 -0
- package/lib/client/settings/sections/notes.js.map +1 -0
- package/lib/client/settings/sections/slash.js +57 -0
- package/lib/client/settings/sections/slash.js.map +1 -0
- package/lib/client/settings/sections/sources.js +4 -1
- package/lib/client/settings/sections/sources.js.map +1 -1
- package/lib/client/settings/sections/status.js +9 -1
- package/lib/client/settings/sections/status.js.map +1 -1
- package/lib/client/settings/sections.js +2 -0
- package/lib/client/settings/sections.js.map +1 -1
- package/lib/client/settlement.js +1 -1
- package/lib/client/settlement.js.map +1 -1
- package/lib/client/slash/SlashPalette.js +48 -0
- package/lib/client/slash/SlashPalette.js.map +1 -0
- package/lib/client/slash/copy.js +54 -0
- package/lib/client/slash/copy.js.map +1 -0
- package/lib/client/slash/slash-router.js +49 -0
- package/lib/client/slash/slash-router.js.map +1 -0
- package/lib/client/slash/useSlashNavigation.js +95 -0
- package/lib/client/slash/useSlashNavigation.js.map +1 -0
- package/lib/client/source-preview.js +3 -0
- package/lib/client/source-preview.js.map +1 -1
- package/lib/client/styles.js +145 -16
- package/lib/client/styles.js.map +1 -1
- package/lib/client/types.js +11 -0
- package/lib/client/types.js.map +1 -1
- package/lib/client.js +33548 -1876
- package/lib/client.js.map +1 -1
- package/lib/config-resolvers/basics.js +11 -2
- package/lib/config-resolvers/basics.js.map +1 -1
- package/lib/config-resolvers/defaults.js +32 -0
- package/lib/config-resolvers/defaults.js.map +1 -1
- package/lib/config-resolvers/lockdown.js +8 -2
- package/lib/config-resolvers/lockdown.js.map +1 -1
- package/lib/config-resolvers/notes.js +24 -0
- package/lib/config-resolvers/notes.js.map +1 -0
- package/lib/config-resolvers/slash-commands.js +60 -0
- package/lib/config-resolvers/slash-commands.js.map +1 -0
- package/lib/config-resolvers/sources.js +4 -0
- package/lib/config-resolvers/sources.js.map +1 -1
- package/lib/config.js +96 -2
- package/lib/config.js.map +1 -1
- package/lib/index.js +309 -11
- package/lib/index.js.map +1 -1
- package/lib/personal-skills/service.js +16 -3
- package/lib/personal-skills/service.js.map +1 -1
- package/lib/prompt-notes.js +45 -6
- package/lib/prompt-notes.js.map +1 -1
- package/lib/provenance/document-preview.js +51 -0
- package/lib/provenance/document-preview.js.map +1 -0
- package/lib/provenance/file-preview.js +191 -19
- package/lib/provenance/file-preview.js.map +1 -1
- package/lib/provenance/host-store.js +18 -1
- package/lib/provenance/host-store.js.map +1 -1
- package/lib/qa-tools/catalog.js +7 -1
- package/lib/qa-tools/catalog.js.map +1 -1
- package/lib/qa-tools/file-delete-gate.js +60 -0
- package/lib/qa-tools/file-delete-gate.js.map +1 -0
- package/lib/qa-tools/file-delete.js +156 -0
- package/lib/qa-tools/file-delete.js.map +1 -0
- package/lib/questions.js +90 -43
- package/lib/questions.js.map +1 -1
- package/lib/resolve-config.js +7 -0
- package/lib/resolve-config.js.map +1 -1
- package/lib/secure-session.js +24 -0
- package/lib/secure-session.js.map +1 -1
- package/lib/shared/documents.js +22 -0
- package/lib/shared/documents.js.map +1 -0
- package/lib/slash/catalog.js +77 -0
- package/lib/slash/catalog.js.map +1 -0
- package/lib/slash/matcher.js +100 -0
- package/lib/slash/matcher.js.map +1 -0
- package/lib/slash/parser.js +79 -0
- package/lib/slash/parser.js.map +1 -0
- package/lib/slash/policy.js +72 -0
- package/lib/slash/policy.js.map +1 -0
- package/lib/slash/remotes.js +272 -0
- package/lib/slash/remotes.js.map +1 -0
- package/lib/typert.host.js +544 -56
- package/lib/typert.remote-client.d.ts +13 -1
- package/lib/typert.remote-client.js +435 -53
- package/lib/types/access/capability-catalog.d.ts +28 -1
- package/lib/types/access/service.d.ts +33 -4
- package/lib/types/accounts/errors.d.ts +7 -1
- package/lib/types/accounts/store.d.ts +12 -0
- package/lib/types/admin/quality-store.d.ts +18 -0
- package/lib/types/admin/service.d.ts +34 -2
- package/lib/types/admin/session-log.d.ts +65 -1
- package/lib/types/client/QaSessionController.d.ts +84 -2
- package/lib/types/client/QaSurface.d.ts +14 -1
- package/lib/types/client/admin/pages/Conversations.d.ts +4 -0
- package/lib/types/client/admin/shared.d.ts +2 -0
- package/lib/types/client/audit/QaAuditDialog.d.ts +21 -0
- package/lib/types/client/audit/QaAuditRowBadge.d.ts +18 -0
- package/lib/types/client/audit/controller.d.ts +27 -0
- package/lib/types/client/audit/types.d.ts +72 -0
- package/lib/types/client/audit/use-chat-audits.d.ts +20 -0
- package/lib/types/client/base64.d.ts +13 -1
- package/lib/types/client/components/QaAgentsDrawer.d.ts +2 -1
- package/lib/types/client/components/QaComposer.d.ts +12 -2
- package/lib/types/client/components/QaFilesPanel.d.ts +16 -4
- package/lib/types/client/components/QaHeader.d.ts +9 -3
- package/lib/types/client/components/QaModal.d.ts +4 -3
- package/lib/types/client/components/QaQuestions.d.ts +7 -0
- package/lib/types/client/components/QaSidebar.d.ts +8 -0
- package/lib/types/client/components/QaWidthHandle.d.ts +48 -2
- package/lib/types/client/components/QaWorkspaceBrowser.d.ts +15 -0
- package/lib/types/client/index.d.ts +1 -1
- package/lib/types/client/kiosk.d.ts +34 -0
- package/lib/types/client/markdown/blocks.d.ts +14 -1
- package/lib/types/client/markdown/inline.d.ts +23 -7
- package/lib/types/client/markdown/katex-css.d.ts +11 -0
- package/lib/types/client/markdown/math.d.ts +23 -0
- package/lib/types/client/markdown/render.d.ts +2 -1
- package/lib/types/client/project-session-state.d.ts +3 -1
- package/lib/types/client/prompt-content.d.ts +9 -1
- package/lib/types/client/settings/sections/notes.d.ts +10 -0
- package/lib/types/client/settings/sections/slash.d.ts +16 -0
- package/lib/types/client/settings/sections.d.ts +2 -0
- package/lib/types/client/settlement.d.ts +4 -1
- package/lib/types/client/slash/SlashPalette.d.ts +24 -0
- package/lib/types/client/slash/copy.d.ts +30 -0
- package/lib/types/client/slash/slash-router.d.ts +67 -0
- package/lib/types/client/slash/useSlashNavigation.d.ts +47 -0
- package/lib/types/client/styles.d.ts +22 -0
- package/lib/types/client/types.d.ts +65 -1
- package/lib/types/config-resolvers/notes.d.ts +10 -0
- package/lib/types/config-resolvers/slash-commands.d.ts +20 -0
- package/lib/types/index.d.ts +116 -1
- package/lib/types/personal-skills/service.d.ts +5 -0
- package/lib/types/prompt-notes.d.ts +9 -0
- package/lib/types/provenance/document-preview.d.ts +24 -0
- package/lib/types/provenance/file-preview.d.ts +69 -2
- package/lib/types/provenance/host-store.d.ts +13 -0
- package/lib/types/qa-tools/catalog.d.ts +1 -1
- package/lib/types/qa-tools/file-delete-gate.d.ts +42 -0
- package/lib/types/qa-tools/file-delete.d.ts +32 -0
- package/lib/types/questions.d.ts +8 -0
- package/lib/types/shared/documents.d.ts +20 -0
- package/lib/types/slash/catalog.d.ts +56 -0
- package/lib/types/slash/matcher.d.ts +51 -0
- package/lib/types/slash/parser.d.ts +46 -0
- package/lib/types/slash/policy.d.ts +40 -0
- package/lib/types/slash/remotes.d.ts +35 -0
- package/lib/types/types.d.ts +293 -6
- package/lib/types/ui-mode.d.ts +18 -0
- package/lib/ui-mode.js +22 -0
- package/lib/ui-mode.js.map +1 -0
- package/package.json +15 -9
- package/scripts/attach-workspace-sessions.mjs +472 -0
package/lib/index.js
CHANGED
|
@@ -41,23 +41,27 @@ import { ConfigSchema, resolveConfig } from "./config.js";
|
|
|
41
41
|
import { createQaAccountRemotes } from "./account-remotes.js";
|
|
42
42
|
import { QaAdminService } from "./admin/service.js";
|
|
43
43
|
import { QaQualityStore } from "./admin/quality-store.js";
|
|
44
|
-
import { createSessionLogReader } from "./admin/session-log.js";
|
|
44
|
+
import { createSessionEraser, createSessionLogReader, } from "./admin/session-log.js";
|
|
45
45
|
import { createQaPersonalSkillRemotes, QaPersonalSkillsHost, } from "./personal-skills/index.js";
|
|
46
46
|
import { QaApprovalGate } from "./approvals.js";
|
|
47
47
|
import { QaAttestationError, qaAttestationFailureMessage, } from "./attestation.js";
|
|
48
|
+
import { QaFileDeleteGate } from "./qa-tools/file-delete-gate.js";
|
|
48
49
|
import { QaQuestionGate } from "./questions.js";
|
|
49
50
|
import { QaSessionOwnership } from "./session-ownership.js";
|
|
50
51
|
import { entryRedirectRow } from "./entry-redirect.js";
|
|
52
|
+
import { qaKioskDeployment } from "./ui-mode.js";
|
|
51
53
|
import { registerQaNavigationRoute } from "./host-route.js";
|
|
52
54
|
import { makeLaunchTokenSource } from "./launch-token.js";
|
|
53
55
|
import { QaIntegrationPrincipalBindings } from "./integration-principals.js";
|
|
54
56
|
import { QaPolicyAdmission } from "./secure-session.js";
|
|
55
57
|
import { QaAccessService } from "./access/service.js";
|
|
58
|
+
import { createQaSlashRemotes } from "./slash/remotes.js";
|
|
56
59
|
import { QaPromptNotes } from "./prompt-notes.js";
|
|
57
60
|
import { QaTools } from "./qa-tools/index.js";
|
|
58
61
|
import { QaProvenanceHost } from "./provenance/host-store.js";
|
|
59
62
|
import { defaultLegacyProvenanceFilePath, defaultQaProvenanceDirectoryPath, FileQaProvenanceSnapshotStore, } from "./provenance/snapshot-store.js";
|
|
60
|
-
import {
|
|
63
|
+
import { previewConvertibleDocument } from "./provenance/document-preview.js";
|
|
64
|
+
import { listWorkspaceDirectory, readSourceFilePreview, readWorkspaceFile, QaSourcePreviewError, } from "./provenance/file-preview.js";
|
|
61
65
|
import { existingQaUserWorkspace, prepareQaUserWorkspace, } from "./user-workspace.js";
|
|
62
66
|
export const name = "qa-surface";
|
|
63
67
|
export const inject = [
|
|
@@ -113,6 +117,7 @@ let QaSurface = (() => {
|
|
|
113
117
|
let _adminUpdateUser_decorators;
|
|
114
118
|
let _adminConversations_decorators;
|
|
115
119
|
let _adminConversation_decorators;
|
|
120
|
+
let _adminDeleteConversation_decorators;
|
|
116
121
|
let _adminFeedback_decorators;
|
|
117
122
|
let _adminRateMessage_decorators;
|
|
118
123
|
let _adminReviewQueue_decorators;
|
|
@@ -128,6 +133,9 @@ let QaSurface = (() => {
|
|
|
128
133
|
let _answerQuestion_decorators;
|
|
129
134
|
let _cancelQuestion_decorators;
|
|
130
135
|
let _readSourceFile_decorators;
|
|
136
|
+
let _listWorkspaceFiles_decorators;
|
|
137
|
+
let _readWorkspaceFile_decorators;
|
|
138
|
+
let _previewWorkspaceDocument_decorators;
|
|
131
139
|
let _skillsList_decorators;
|
|
132
140
|
let _skillsGet_decorators;
|
|
133
141
|
let _skillsCreate_decorators;
|
|
@@ -135,6 +143,8 @@ let QaSurface = (() => {
|
|
|
135
143
|
let _skillsRemove_decorators;
|
|
136
144
|
let _skillsValidate_decorators;
|
|
137
145
|
let _skillsTools_decorators;
|
|
146
|
+
let _slashCatalog_decorators;
|
|
147
|
+
let _slashExecute_decorators;
|
|
138
148
|
return class QaSurface extends _classSuper {
|
|
139
149
|
static {
|
|
140
150
|
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
@@ -164,6 +174,7 @@ let QaSurface = (() => {
|
|
|
164
174
|
_adminUpdateUser_decorators = [Remote("adminUpdateUser")];
|
|
165
175
|
_adminConversations_decorators = [Remote("adminConversations")];
|
|
166
176
|
_adminConversation_decorators = [Remote("adminConversation")];
|
|
177
|
+
_adminDeleteConversation_decorators = [Remote("adminDeleteConversation")];
|
|
167
178
|
_adminFeedback_decorators = [Remote("adminFeedback")];
|
|
168
179
|
_adminRateMessage_decorators = [Remote("adminRateMessage")];
|
|
169
180
|
_adminReviewQueue_decorators = [Remote("adminReviewQueue")];
|
|
@@ -179,6 +190,9 @@ let QaSurface = (() => {
|
|
|
179
190
|
_answerQuestion_decorators = [Remote("answerQuestion")];
|
|
180
191
|
_cancelQuestion_decorators = [Remote("cancelQuestion")];
|
|
181
192
|
_readSourceFile_decorators = [Remote("readSourceFile")];
|
|
193
|
+
_listWorkspaceFiles_decorators = [Remote("listWorkspaceFiles")];
|
|
194
|
+
_readWorkspaceFile_decorators = [Remote("readWorkspaceFile")];
|
|
195
|
+
_previewWorkspaceDocument_decorators = [Remote("previewWorkspaceDocument")];
|
|
182
196
|
_skillsList_decorators = [Remote("skillsList")];
|
|
183
197
|
_skillsGet_decorators = [Remote("skillsGet")];
|
|
184
198
|
_skillsCreate_decorators = [Remote("skillsCreate")];
|
|
@@ -186,6 +200,8 @@ let QaSurface = (() => {
|
|
|
186
200
|
_skillsRemove_decorators = [Remote("skillsRemove")];
|
|
187
201
|
_skillsValidate_decorators = [Remote("skillsValidate")];
|
|
188
202
|
_skillsTools_decorators = [Remote("skillsTools")];
|
|
203
|
+
_slashCatalog_decorators = [Remote("slashCatalog")];
|
|
204
|
+
_slashExecute_decorators = [Remote("slashExecute")];
|
|
189
205
|
__esDecorate(this, null, _accountsRegister_decorators, { kind: "method", name: "accountsRegister", static: false, private: false, access: { has: obj => "accountsRegister" in obj, get: obj => obj.accountsRegister }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
190
206
|
__esDecorate(this, null, _accountsLogin_decorators, { kind: "method", name: "accountsLogin", static: false, private: false, access: { has: obj => "accountsLogin" in obj, get: obj => obj.accountsLogin }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
191
207
|
__esDecorate(this, null, _accountsWhoami_decorators, { kind: "method", name: "accountsWhoami", static: false, private: false, access: { has: obj => "accountsWhoami" in obj, get: obj => obj.accountsWhoami }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
@@ -212,6 +228,7 @@ let QaSurface = (() => {
|
|
|
212
228
|
__esDecorate(this, null, _adminUpdateUser_decorators, { kind: "method", name: "adminUpdateUser", static: false, private: false, access: { has: obj => "adminUpdateUser" in obj, get: obj => obj.adminUpdateUser }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
213
229
|
__esDecorate(this, null, _adminConversations_decorators, { kind: "method", name: "adminConversations", static: false, private: false, access: { has: obj => "adminConversations" in obj, get: obj => obj.adminConversations }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
214
230
|
__esDecorate(this, null, _adminConversation_decorators, { kind: "method", name: "adminConversation", static: false, private: false, access: { has: obj => "adminConversation" in obj, get: obj => obj.adminConversation }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
231
|
+
__esDecorate(this, null, _adminDeleteConversation_decorators, { kind: "method", name: "adminDeleteConversation", static: false, private: false, access: { has: obj => "adminDeleteConversation" in obj, get: obj => obj.adminDeleteConversation }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
215
232
|
__esDecorate(this, null, _adminFeedback_decorators, { kind: "method", name: "adminFeedback", static: false, private: false, access: { has: obj => "adminFeedback" in obj, get: obj => obj.adminFeedback }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
216
233
|
__esDecorate(this, null, _adminRateMessage_decorators, { kind: "method", name: "adminRateMessage", static: false, private: false, access: { has: obj => "adminRateMessage" in obj, get: obj => obj.adminRateMessage }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
217
234
|
__esDecorate(this, null, _adminReviewQueue_decorators, { kind: "method", name: "adminReviewQueue", static: false, private: false, access: { has: obj => "adminReviewQueue" in obj, get: obj => obj.adminReviewQueue }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
@@ -227,6 +244,9 @@ let QaSurface = (() => {
|
|
|
227
244
|
__esDecorate(this, null, _answerQuestion_decorators, { kind: "method", name: "answerQuestion", static: false, private: false, access: { has: obj => "answerQuestion" in obj, get: obj => obj.answerQuestion }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
228
245
|
__esDecorate(this, null, _cancelQuestion_decorators, { kind: "method", name: "cancelQuestion", static: false, private: false, access: { has: obj => "cancelQuestion" in obj, get: obj => obj.cancelQuestion }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
229
246
|
__esDecorate(this, null, _readSourceFile_decorators, { kind: "method", name: "readSourceFile", static: false, private: false, access: { has: obj => "readSourceFile" in obj, get: obj => obj.readSourceFile }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
247
|
+
__esDecorate(this, null, _listWorkspaceFiles_decorators, { kind: "method", name: "listWorkspaceFiles", static: false, private: false, access: { has: obj => "listWorkspaceFiles" in obj, get: obj => obj.listWorkspaceFiles }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
248
|
+
__esDecorate(this, null, _readWorkspaceFile_decorators, { kind: "method", name: "readWorkspaceFile", static: false, private: false, access: { has: obj => "readWorkspaceFile" in obj, get: obj => obj.readWorkspaceFile }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
249
|
+
__esDecorate(this, null, _previewWorkspaceDocument_decorators, { kind: "method", name: "previewWorkspaceDocument", static: false, private: false, access: { has: obj => "previewWorkspaceDocument" in obj, get: obj => obj.previewWorkspaceDocument }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
230
250
|
__esDecorate(this, null, _skillsList_decorators, { kind: "method", name: "skillsList", static: false, private: false, access: { has: obj => "skillsList" in obj, get: obj => obj.skillsList }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
231
251
|
__esDecorate(this, null, _skillsGet_decorators, { kind: "method", name: "skillsGet", static: false, private: false, access: { has: obj => "skillsGet" in obj, get: obj => obj.skillsGet }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
232
252
|
__esDecorate(this, null, _skillsCreate_decorators, { kind: "method", name: "skillsCreate", static: false, private: false, access: { has: obj => "skillsCreate" in obj, get: obj => obj.skillsCreate }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
@@ -234,6 +254,8 @@ let QaSurface = (() => {
|
|
|
234
254
|
__esDecorate(this, null, _skillsRemove_decorators, { kind: "method", name: "skillsRemove", static: false, private: false, access: { has: obj => "skillsRemove" in obj, get: obj => obj.skillsRemove }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
235
255
|
__esDecorate(this, null, _skillsValidate_decorators, { kind: "method", name: "skillsValidate", static: false, private: false, access: { has: obj => "skillsValidate" in obj, get: obj => obj.skillsValidate }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
236
256
|
__esDecorate(this, null, _skillsTools_decorators, { kind: "method", name: "skillsTools", static: false, private: false, access: { has: obj => "skillsTools" in obj, get: obj => obj.skillsTools }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
257
|
+
__esDecorate(this, null, _slashCatalog_decorators, { kind: "method", name: "slashCatalog", static: false, private: false, access: { has: obj => "slashCatalog" in obj, get: obj => obj.slashCatalog }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
258
|
+
__esDecorate(this, null, _slashExecute_decorators, { kind: "method", name: "slashExecute", static: false, private: false, access: { has: obj => "slashExecute" in obj, get: obj => obj.slashExecute }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
237
259
|
if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
238
260
|
}
|
|
239
261
|
static inject = inject;
|
|
@@ -242,6 +264,7 @@ let QaSurface = (() => {
|
|
|
242
264
|
logger;
|
|
243
265
|
admission;
|
|
244
266
|
approvals;
|
|
267
|
+
fileDeleteGate;
|
|
245
268
|
userQuestions;
|
|
246
269
|
provenance;
|
|
247
270
|
notes;
|
|
@@ -260,6 +283,12 @@ let QaSurface = (() => {
|
|
|
260
283
|
personalSkills;
|
|
261
284
|
/** Personal-skill remote bodies; the wire signatures stay on this class. */
|
|
262
285
|
skillRemotes;
|
|
286
|
+
/**
|
|
287
|
+
* Slash-catalog and command-admission bodies. Admission, not execution:
|
|
288
|
+
* the native skill and command runtimes stay the only things that know what
|
|
289
|
+
* a `/name` means.
|
|
290
|
+
*/
|
|
291
|
+
slashRemotes;
|
|
263
292
|
launchToken;
|
|
264
293
|
/** Root session principals attested for their owner, never for admin viewing. */
|
|
265
294
|
integrationPrincipals = new QaIntegrationPrincipalBindings();
|
|
@@ -292,7 +321,14 @@ let QaSurface = (() => {
|
|
|
292
321
|
config: () => this.getConfig(),
|
|
293
322
|
logger: this.logger,
|
|
294
323
|
dynamicToolNames: () => this.tools?.catalogToolNames() ?? [],
|
|
324
|
+
presetScope: () => this.qaPresetScope(),
|
|
295
325
|
sessionLog,
|
|
326
|
+
// The record the sweep reclaims is the authorization boundary, not the
|
|
327
|
+
// whole of what the deployment kept about a chat: the quality rows a
|
|
328
|
+
// conversation owns outlive it unless they are dropped here.
|
|
329
|
+
onVanishedSessions: (sessionIds) => {
|
|
330
|
+
this.dropVanishedChats(sessionIds);
|
|
331
|
+
},
|
|
296
332
|
});
|
|
297
333
|
this.personalSkills = new QaPersonalSkillsHost({
|
|
298
334
|
ctx,
|
|
@@ -305,6 +341,10 @@ let QaSurface = (() => {
|
|
|
305
341
|
roles: () => this.access.roles,
|
|
306
342
|
access: () => this.access,
|
|
307
343
|
sessionLog,
|
|
344
|
+
// Deletion is the console's alone: the sidebar's delete stays a
|
|
345
|
+
// per-browser row, and only an administrator removes the chat itself.
|
|
346
|
+
sessionFiles: createSessionEraser(),
|
|
347
|
+
dropSources: (sessionId) => this.provenance.dropSession(sessionId),
|
|
308
348
|
logger: this.logger,
|
|
309
349
|
});
|
|
310
350
|
this.skillRemotes = createQaPersonalSkillRemotes({
|
|
@@ -313,6 +353,12 @@ let QaSurface = (() => {
|
|
|
313
353
|
skills: this.personalSkills.service,
|
|
314
354
|
accounts: this.accountRemotes,
|
|
315
355
|
});
|
|
356
|
+
this.slashRemotes = createQaSlashRemotes({
|
|
357
|
+
ctx,
|
|
358
|
+
getConfig: () => this.getConfig(),
|
|
359
|
+
logger: this.logger,
|
|
360
|
+
sessionGrant: (token, sessionId, agent) => this.slashSessionGrant(token, sessionId, agent),
|
|
361
|
+
});
|
|
316
362
|
this.admission = new QaPolicyAdmission(ctx, () => this.getConfig(), this.logger,
|
|
317
363
|
// Identity half of admission; no-ops while accounts stay disabled.
|
|
318
364
|
{
|
|
@@ -340,8 +386,15 @@ let QaSurface = (() => {
|
|
|
340
386
|
const ownership = new QaSessionOwnership((sessionId) => this.admission.knowsSession(sessionId));
|
|
341
387
|
this.approvals = new QaApprovalGate(ctx, () => this.getConfig().interaction.approvals === "interactive", ownership, this.logger);
|
|
342
388
|
this.userQuestions = new QaQuestionGate(ctx, () => this.getConfig().interaction.questions === "interactive", ownership, this.logger);
|
|
389
|
+
// The destructive tool of the QA catalog composes the same approval flow
|
|
390
|
+
// around itself: registered without `prepend`, it sits inside the approval
|
|
391
|
+
// gate and answers `ask` for every file_delete call of an attested chat,
|
|
392
|
+
// so the interactive card parks it for the operator (or the blocked
|
|
393
|
+
// configuration refuses it — nothing is deleted without a person).
|
|
394
|
+
this.fileDeleteGate = new QaFileDeleteGate(ctx, ownership);
|
|
343
395
|
this.approvals.install();
|
|
344
396
|
this.userQuestions.install();
|
|
397
|
+
this.fileDeleteGate.install();
|
|
345
398
|
// The identity note and the provenance rule ride the conversation as
|
|
346
399
|
// durable context messages, delegated experts included: the QA preset's
|
|
347
400
|
// complete persona closes the system prompt to plugins, the conversation
|
|
@@ -361,11 +414,13 @@ let QaSurface = (() => {
|
|
|
361
414
|
ctx.effect(() => async () => this.logger.close(), "dsh-qa-surface.logger");
|
|
362
415
|
ctx.effect(() => () => this.admission.dispose(), "dsh-qa-surface.lockdown-policies");
|
|
363
416
|
ctx.effect(() => () => this.approvals.dispose(), "dsh-qa-surface.approvals");
|
|
417
|
+
ctx.effect(() => () => this.fileDeleteGate.dispose(), "dsh-qa-surface.file-delete-gate");
|
|
364
418
|
ctx.effect(() => () => this.userQuestions.dispose(), "dsh-qa-surface.user-questions");
|
|
365
419
|
ctx.effect(() => () => this.provenance.dispose(), "dsh-qa-surface.provenance");
|
|
366
420
|
ctx.effect(() => () => this.notes.dispose(), "dsh-qa-surface.prompt-notes");
|
|
367
421
|
ctx.effect(() => () => this.personalSkills.dispose(), "dsh-qa-surface.personal-skills");
|
|
368
422
|
this.warnDocumentsMoved();
|
|
423
|
+
this.warnLegacySlashDefaults();
|
|
369
424
|
// The QA tool catalog is attached per agent, never at boot: nothing here
|
|
370
425
|
// reaches the model until a managed agent loads the activation skill.
|
|
371
426
|
this.tools = new QaTools(ctx, {
|
|
@@ -377,12 +432,17 @@ let QaSurface = (() => {
|
|
|
377
432
|
});
|
|
378
433
|
ctx.effect(() => () => this.tools.dispose(), "dsh-qa-surface.qa-tools");
|
|
379
434
|
// The root index gains one head script: non-loopback hostnames continue
|
|
380
|
-
// into /qa, the loopback operator keeps the full harness UI.
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
435
|
+
// into /qa, the loopback operator keeps the full harness UI. Not in the
|
|
436
|
+
// kiosk composition: there the index itself is served under /qa, so the
|
|
437
|
+
// script would meet its own target on every load and reload the page in
|
|
438
|
+
// a loop, and the server policy already routes the site root into /qa.
|
|
439
|
+
if (!qaKioskDeployment()) {
|
|
440
|
+
ctx.on("webserver/index-inject", (table) => {
|
|
441
|
+
const row = entryRedirectRow(this.getConfig());
|
|
442
|
+
if (row !== undefined)
|
|
443
|
+
table.push(row);
|
|
444
|
+
});
|
|
445
|
+
}
|
|
386
446
|
ctx.inject(["settings"], (settingsCtx) => {
|
|
387
447
|
settingsCtx.settings.installSection(ctx, QA_SURFACE_SETTINGS_NAMESPACE, ConfigSchema, entry, {
|
|
388
448
|
setSource: (source) => {
|
|
@@ -392,6 +452,7 @@ let QaSurface = (() => {
|
|
|
392
452
|
const config = this.getConfig();
|
|
393
453
|
this.refreshRoute();
|
|
394
454
|
this.warnDocumentsMoved();
|
|
455
|
+
this.warnLegacySlashDefaults();
|
|
395
456
|
this.logger.info("config.updated", {
|
|
396
457
|
enabled: config.enabled,
|
|
397
458
|
route: config.route.path,
|
|
@@ -417,6 +478,11 @@ let QaSurface = (() => {
|
|
|
417
478
|
enabled: resolvedEntry.enabled,
|
|
418
479
|
route: resolvedEntry.route.path,
|
|
419
480
|
sessionPolicy: resolvedEntry.session.policy,
|
|
481
|
+
// What the two parked-interaction seams resolve to on this deployment:
|
|
482
|
+
// the attestation path warns per session when the question seam and the
|
|
483
|
+
// tool policy disagree, and this is the config they are read against.
|
|
484
|
+
approvals: resolvedEntry.interaction.approvals,
|
|
485
|
+
questions: resolvedEntry.interaction.questions,
|
|
420
486
|
});
|
|
421
487
|
}
|
|
422
488
|
/** The quality store, opening its file the first time anyone needs it. */
|
|
@@ -424,6 +490,44 @@ let QaSurface = (() => {
|
|
|
424
490
|
this.qualityStore ??= new QaQualityStore();
|
|
425
491
|
return this.qualityStore;
|
|
426
492
|
}
|
|
493
|
+
/**
|
|
494
|
+
* The standing scope of the preset QA chats run under, so an administrator's
|
|
495
|
+
* capability catalog is read the way a chat reads it. Everything a preset
|
|
496
|
+
* mounts — its skill catalog, its tool family — is registered in that scope,
|
|
497
|
+
* and a global-only read showed the operator an almost empty page. Resolving
|
|
498
|
+
* the preset composes it but starts no agent, no session and no turn;
|
|
499
|
+
* without a pinned preset there is nothing to borrow, and the read stays
|
|
500
|
+
* global.
|
|
501
|
+
*/
|
|
502
|
+
async qaPresetScope() {
|
|
503
|
+
const preset = this.getConfig().session.agentPreset;
|
|
504
|
+
if (preset === null || preset === undefined)
|
|
505
|
+
return undefined;
|
|
506
|
+
return await this.ctx.agentPresets.standingKeyFor(preset);
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* Drop what the quality layer kept about chats that no longer exist in the
|
|
510
|
+
* Harness. The ownership sweep calls this with the ids it reclaimed: the
|
|
511
|
+
* record it removes is one thing the deployment held about a chat, and
|
|
512
|
+
* ratings, reviews and queue entries are the rest. Failure is logged and
|
|
513
|
+
* swallowed — housekeeping runs inside a review read, and a store that
|
|
514
|
+
* cannot be opened must not fail the page that triggered it.
|
|
515
|
+
*/
|
|
516
|
+
dropVanishedChats(sessionIds) {
|
|
517
|
+
try {
|
|
518
|
+
const rows = this.quality().dropConversations(sessionIds);
|
|
519
|
+
this.logger.info("quality.vanished-conversations-dropped", {
|
|
520
|
+
conversations: sessionIds.length,
|
|
521
|
+
rows,
|
|
522
|
+
sessionIds: sessionIds.slice(0, 20),
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
catch (error) {
|
|
526
|
+
this.logger.error("quality.vanished-conversations-drop-failed", {
|
|
527
|
+
message: error instanceof Error ? error.message : String(error),
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
}
|
|
427
531
|
/** Resolve browser authentication to the caller only; never accepts an id. */
|
|
428
532
|
principalForToken(token) {
|
|
429
533
|
const accounts = this.accountRemotes.resolve(this.getConfig());
|
|
@@ -450,6 +554,36 @@ let QaSurface = (() => {
|
|
|
450
554
|
getConfig() {
|
|
451
555
|
return resolveConfig(this.source());
|
|
452
556
|
}
|
|
557
|
+
/**
|
|
558
|
+
* Ownership plus the role's user-skill grant for one slash read.
|
|
559
|
+
*
|
|
560
|
+
* Ownership comes first and for the same reason the rest of the plugin does
|
|
561
|
+
* it: a catalog names the skills a chat can reach, and a foreign browser has
|
|
562
|
+
* no business enumerating that. With accounts off there is no identity to
|
|
563
|
+
* check and the deployment's lockdown is the boundary, exactly as it is for
|
|
564
|
+
* every other remote.
|
|
565
|
+
*
|
|
566
|
+
* The grant mirrors `installQaSkillPolicy` to the letter — an empty
|
|
567
|
+
* `userSkills` list means the role keeps no separate user list, not that it
|
|
568
|
+
* grants nothing — so the palette can never offer a skill the typed gesture
|
|
569
|
+
* would refuse, nor hide one it would accept.
|
|
570
|
+
*/
|
|
571
|
+
async slashSessionGrant(token, sessionId, agent) {
|
|
572
|
+
const accounts = this.accountRemotes.resolve(this.getConfig());
|
|
573
|
+
if (accounts === undefined)
|
|
574
|
+
return undefined;
|
|
575
|
+
if (agent === undefined) {
|
|
576
|
+
// A cold chat has no capability snapshot to read, but it still has an
|
|
577
|
+
// owner, and that is what the catalog read must respect.
|
|
578
|
+
this.accountRemotes.run(() => this.access.session(token, sessionId));
|
|
579
|
+
return undefined;
|
|
580
|
+
}
|
|
581
|
+
const resolved = await this.access.policyForSession(token, sessionId, agent);
|
|
582
|
+
if (resolved === undefined)
|
|
583
|
+
return undefined;
|
|
584
|
+
const { policy } = resolved;
|
|
585
|
+
return policy.userSkills.length === 0 ? policy.skills : policy.userSkills;
|
|
586
|
+
}
|
|
453
587
|
/**
|
|
454
588
|
* Self-service signup; the first account ever created becomes admin. The
|
|
455
589
|
* display name derives from the email: the generated client enforces exact
|
|
@@ -658,6 +792,14 @@ let QaSurface = (() => {
|
|
|
658
792
|
adminConversation(token, conversationId) {
|
|
659
793
|
return this.accountRemotes.runAsync(() => this.admin.conversation(token, conversationId));
|
|
660
794
|
}
|
|
795
|
+
/**
|
|
796
|
+
* Remove one conversation from the deployment. Admin-only, audited, and the
|
|
797
|
+
* only path that deletes what a person wrote — the sidebar's own delete
|
|
798
|
+
* stays what it always was, a per-browser row.
|
|
799
|
+
*/
|
|
800
|
+
adminDeleteConversation(token, conversationId) {
|
|
801
|
+
return this.accountRemotes.runAsync(() => this.admin.deleteConversation(token, conversationId));
|
|
802
|
+
}
|
|
661
803
|
adminFeedback(token, query, cursor, limit) {
|
|
662
804
|
return this.accountRemotes.runAsync(() => this.admin.feedback(token, query, cursor ?? undefined, limit ?? undefined));
|
|
663
805
|
}
|
|
@@ -796,6 +938,105 @@ let QaSurface = (() => {
|
|
|
796
938
|
throw sourcePreviewRefusal(error instanceof QaSourcePreviewError ? error.reason : "unavailable");
|
|
797
939
|
}
|
|
798
940
|
}
|
|
941
|
+
/**
|
|
942
|
+
* List one directory of the chat's own workspace for the files panel.
|
|
943
|
+
*
|
|
944
|
+
* Browsing is deliberately narrower than the source preview: it stays inside
|
|
945
|
+
* the chat's own directory tree, so a visitor can look at what their
|
|
946
|
+
* conversation produced and at nothing else of the deployment.
|
|
947
|
+
* `readWorkspaceFile` opens one entry of such a listing.
|
|
948
|
+
*/
|
|
949
|
+
async listWorkspaceFiles(token, sessionId, path) {
|
|
950
|
+
await this.admission.secureSession(token, sessionId);
|
|
951
|
+
const { config, cwd } = await this.browseContext(sessionId);
|
|
952
|
+
try {
|
|
953
|
+
return await listWorkspaceDirectory({
|
|
954
|
+
dirPath: path ?? "",
|
|
955
|
+
cwd,
|
|
956
|
+
maxEntries: config.sources.filePreview.maxListingEntries,
|
|
957
|
+
});
|
|
958
|
+
}
|
|
959
|
+
catch (error) {
|
|
960
|
+
throw this.browseRefusal("workspace.list-refused", sessionId, error);
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
/**
|
|
964
|
+
* Read one file of the chat's workspace: text when it decodes as UTF-8, bytes
|
|
965
|
+
* when it does not, so a document the agent produced can be downloaded while
|
|
966
|
+
* a note previews inline. The readable roots are the ones the model itself
|
|
967
|
+
* may read; unlike the source preview this does not require the file to be
|
|
968
|
+
* recorded evidence, because the panel is browsing a tree rather than
|
|
969
|
+
* reopening a cited source.
|
|
970
|
+
*/
|
|
971
|
+
async readWorkspaceFile(token, sessionId, path) {
|
|
972
|
+
await this.admission.secureSession(token, sessionId);
|
|
973
|
+
const { config, cwd } = await this.browseContext(sessionId);
|
|
974
|
+
const attachmentRoot = this.admission.attachmentRoot();
|
|
975
|
+
try {
|
|
976
|
+
return await readWorkspaceFile({
|
|
977
|
+
filePath: path ?? "",
|
|
978
|
+
cwd,
|
|
979
|
+
sharedReadOnlyRoots: config.lockdown.sharedReadOnlyRoots,
|
|
980
|
+
...(attachmentRoot === undefined ? {} : { attachmentRoot }),
|
|
981
|
+
maxBytes: config.sources.filePreview.maxBytes,
|
|
982
|
+
maxMarkdownRenderBytes: config.sources.filePreview.maxMarkdownRenderBytes,
|
|
983
|
+
});
|
|
984
|
+
}
|
|
985
|
+
catch (error) {
|
|
986
|
+
throw this.browseRefusal("workspace.read-refused", sessionId, error);
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
/**
|
|
990
|
+
* Render one Word document of the chat's workspace as a PDF for the panel.
|
|
991
|
+
*
|
|
992
|
+
* The conversion is the document pipeline's own, reached through the service
|
|
993
|
+
* `@yadsh/dsh-documents` publishes for its Host siblings — the panel gets the
|
|
994
|
+
* same providers, limits and refusals the `document_*` tools see, and a
|
|
995
|
+
* deployment without that plugin refuses instead of showing a guess. The
|
|
996
|
+
* produced PDF is read back here and travels as base64, so the audience never
|
|
997
|
+
* reaches an unfenced byte route.
|
|
998
|
+
*/
|
|
999
|
+
async previewWorkspaceDocument(token, sessionId, path) {
|
|
1000
|
+
await this.admission.secureSession(token, sessionId);
|
|
1001
|
+
const { config, cwd } = await this.browseContext(sessionId);
|
|
1002
|
+
const attachmentRoot = this.admission.attachmentRoot();
|
|
1003
|
+
try {
|
|
1004
|
+
return await previewConvertibleDocument({
|
|
1005
|
+
filePath: path ?? "",
|
|
1006
|
+
cwd,
|
|
1007
|
+
sharedReadOnlyRoots: config.lockdown.sharedReadOnlyRoots,
|
|
1008
|
+
...(attachmentRoot === undefined ? {} : { attachmentRoot }),
|
|
1009
|
+
documents: () => this.ctx.get("documents"),
|
|
1010
|
+
sessionId,
|
|
1011
|
+
maxBytes: config.sources.filePreview.maxBytes,
|
|
1012
|
+
});
|
|
1013
|
+
}
|
|
1014
|
+
catch (error) {
|
|
1015
|
+
throw this.browseRefusal("workspace.preview-refused", sessionId, error);
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
/**
|
|
1019
|
+
* Shared admission facts of both browse methods: the preview switch is what
|
|
1020
|
+
* opens the panel's file reading at all, and the chat's cwd is the tree that
|
|
1021
|
+
* browsing is confined to.
|
|
1022
|
+
*/
|
|
1023
|
+
async browseContext(sessionId) {
|
|
1024
|
+
const config = this.getConfig();
|
|
1025
|
+
if (!config.sources.filePreview.enabled) {
|
|
1026
|
+
throw sourcePreviewRefusal("unavailable");
|
|
1027
|
+
}
|
|
1028
|
+
const agent = this.ctx.agents.get((await import("@deepseek-ai/dsh-session/types")).SessionId(sessionId));
|
|
1029
|
+
const cwd = agent?.session.header.cwd;
|
|
1030
|
+
if (cwd === undefined)
|
|
1031
|
+
throw sourcePreviewRefusal("unavailable");
|
|
1032
|
+
return { config, cwd };
|
|
1033
|
+
}
|
|
1034
|
+
/** One browse refusal, logged with its coarse reason and rethrown for the wire. */
|
|
1035
|
+
browseRefusal(event, sessionId, error) {
|
|
1036
|
+
const reason = error instanceof QaSourcePreviewError ? error.reason : "unavailable";
|
|
1037
|
+
this.logger.debug(event, { sessionId, reason });
|
|
1038
|
+
return sourcePreviewRefusal(reason);
|
|
1039
|
+
}
|
|
799
1040
|
/** Every personal skill of the token's account, sorted by name. */
|
|
800
1041
|
skillsList(token) {
|
|
801
1042
|
return this.skillRemotes.list(token);
|
|
@@ -833,11 +1074,46 @@ let QaSurface = (() => {
|
|
|
833
1074
|
skillsTools(token) {
|
|
834
1075
|
return this.skillRemotes.tools(token);
|
|
835
1076
|
}
|
|
1077
|
+
/**
|
|
1078
|
+
* The slash entries this browser may offer for one chat: the session's
|
|
1079
|
+
* user-invocable skills and its agent's effective commands, already cut down
|
|
1080
|
+
* by the deployment policy and by the chat's role. The browser filters and
|
|
1081
|
+
* ranks this list; it never widens it.
|
|
1082
|
+
*
|
|
1083
|
+
* Enabled is reported rather than assumed, so a page that loaded before the
|
|
1084
|
+
* operator flipped the master switch learns the truth instead of showing an
|
|
1085
|
+
* empty palette forever.
|
|
1086
|
+
*/
|
|
1087
|
+
slashCatalog(token, sessionId) {
|
|
1088
|
+
return this.slashRemotes.catalog(token, sessionId);
|
|
1089
|
+
}
|
|
1090
|
+
/**
|
|
1091
|
+
* Run one human command line. The line is the whole request — the browser
|
|
1092
|
+
* sends no name, no kind and no descriptor, so there is nothing for it to
|
|
1093
|
+
* forge; admission re-derives the name and re-checks the policy against the
|
|
1094
|
+
* deployment's own config.
|
|
1095
|
+
*
|
|
1096
|
+
* A command never becomes a model message: the native runtime answers it and
|
|
1097
|
+
* writes `command/run`/`command/done` into the session log, which is where
|
|
1098
|
+
* the transcript row is read from.
|
|
1099
|
+
*/
|
|
1100
|
+
slashExecute(token, sessionId, line, attachments) {
|
|
1101
|
+
return this.slashRemotes.execute(token, sessionId, line, attachments);
|
|
1102
|
+
}
|
|
836
1103
|
refreshRoute() {
|
|
837
1104
|
const config = this.getConfig();
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
1105
|
+
// Kiosk: the harness route policy owns the QA paths and serves the
|
|
1106
|
+
// application there directly. This plugin's navigation redirect route
|
|
1107
|
+
// must not register — a named route shadows the fallback seat, so it
|
|
1108
|
+
// would bounce every /qa navigation to /?marker while the policy bounces
|
|
1109
|
+
// / back to /qa: a redirect loop. The kiosk key keeps the transition
|
|
1110
|
+
// machinery honest (dispose on entering kiosk, no re-registration, one
|
|
1111
|
+
// log line per transition).
|
|
1112
|
+
const key = qaKioskDeployment()
|
|
1113
|
+
? "kiosk"
|
|
1114
|
+
: config.enabled
|
|
1115
|
+
? `${config.route.path}:${config.route.matchChildren}`
|
|
1116
|
+
: undefined;
|
|
841
1117
|
if (key === this.routeKey)
|
|
842
1118
|
return;
|
|
843
1119
|
this.disposeRoute?.();
|
|
@@ -845,11 +1121,33 @@ let QaSurface = (() => {
|
|
|
845
1121
|
this.routeKey = undefined;
|
|
846
1122
|
if (key === undefined || this.webServer === undefined)
|
|
847
1123
|
return;
|
|
1124
|
+
if (key === "kiosk") {
|
|
1125
|
+
this.logger.info("route.kiosk", {
|
|
1126
|
+
message: "DSH_UI_MODE=qa: the navigation redirect route is not registered; the harness route policy serves the QA surface directly",
|
|
1127
|
+
});
|
|
1128
|
+
this.routeKey = key;
|
|
1129
|
+
return;
|
|
1130
|
+
}
|
|
848
1131
|
this.disposeRoute = registerQaNavigationRoute(this.webServer, config, {
|
|
849
1132
|
launchToken: this.launchToken,
|
|
850
1133
|
});
|
|
851
1134
|
this.routeKey = key;
|
|
852
1135
|
}
|
|
1136
|
+
/**
|
|
1137
|
+
* A deployment that set `lockdown.allowSlashCommands: true` before this
|
|
1138
|
+
* section existed keeps the behaviour it asked for — skills at `all`,
|
|
1139
|
+
* commands denied — and is told so once per configuration change, because
|
|
1140
|
+
* "skills appeared after the upgrade" is otherwise indistinguishable from a
|
|
1141
|
+
* defect. Commands are never part of that fallback: an upgrade must not hand
|
|
1142
|
+
* the user a control-plane command nobody named.
|
|
1143
|
+
*/
|
|
1144
|
+
warnLegacySlashDefaults() {
|
|
1145
|
+
if (!this.getConfig().slashCommands.legacyDefaults)
|
|
1146
|
+
return;
|
|
1147
|
+
this.logger.warn("slash.legacy-defaults", {
|
|
1148
|
+
message: "lockdown.allowSlashCommands=true without a slashCommands section: every user-invocable skill is admitted and no human command is. Declare slashCommands.commands to enable commands explicitly.",
|
|
1149
|
+
});
|
|
1150
|
+
}
|
|
853
1151
|
/**
|
|
854
1152
|
* The document pipeline moved out of this plugin into `@yadsh/dsh-documents`.
|
|
855
1153
|
* A deployment whose profile still carries the old `documents` section would
|