@yadsh/dsh-qa-surface 0.7.4 → 0.9.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 +169 -12
- 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/model.js +24 -4
- package/lib/access/model.js.map +1 -1
- package/lib/access/role-repository.js +199 -91
- package/lib/access/role-repository.js.map +1 -1
- package/lib/access/service.js +223 -7
- package/lib/access/service.js.map +1 -1
- package/lib/account-remotes.js +2 -4
- package/lib/account-remotes.js.map +1 -1
- package/lib/accounts/database.js +447 -0
- package/lib/accounts/database.js.map +1 -0
- package/lib/accounts/errors.js.map +1 -1
- package/lib/accounts/file.js +27 -90
- package/lib/accounts/file.js.map +1 -1
- package/lib/accounts/store.js +224 -59
- 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 +270 -54
- package/lib/admin/quality-store.js.map +1 -1
- package/lib/admin/service.js +145 -7
- 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/cli.js +2 -1
- package/lib/cli.js.map +1 -1
- package/lib/client/QaSessionController.js +379 -39
- package/lib/client/QaSessionController.js.map +1 -1
- package/lib/client/QaSurface.js +94 -34
- package/lib/client/QaSurface.js.map +1 -1
- package/lib/client/QaTranscriptAdapter.js +40 -0
- package/lib/client/QaTranscriptAdapter.js.map +1 -1
- package/lib/client/admin/QaAdmin.js +26 -8
- package/lib/client/admin/QaAdmin.js.map +1 -1
- package/lib/client/admin/{format.js → copy.js} +1 -1
- package/lib/client/admin/copy.js.map +1 -0
- package/lib/client/admin/pages/Conversations.js +34 -8
- package/lib/client/admin/pages/Conversations.js.map +1 -1
- package/lib/client/admin/pages/Overview.js +1 -1
- package/lib/client/admin/pages/Overview.js.map +1 -1
- package/lib/client/admin/pages/Quality.js +1 -1
- package/lib/client/admin/pages/Quality.js.map +1 -1
- package/lib/client/admin/pages/Review.js +1 -1
- package/lib/client/admin/pages/Review.js.map +1 -1
- package/lib/client/admin/pages/Users.js +6 -2
- package/lib/client/admin/pages/Users.js.map +1 -1
- package/lib/client/admin/shared.js +10 -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/components/Markdown.js +14 -206
- package/lib/client/components/Markdown.js.map +1 -1
- package/lib/client/components/QaChangelog.js +91 -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/QaHeader.js +1 -3
- package/lib/client/components/QaHeader.js.map +1 -1
- package/lib/client/components/QaMessage.js +25 -4
- package/lib/client/components/QaMessage.js.map +1 -1
- package/lib/client/components/QaQuestions.js +1 -1
- package/lib/client/components/QaQuestions.js.map +1 -1
- package/lib/client/components/QaSidebar.js +17 -3
- package/lib/client/components/QaSidebar.js.map +1 -1
- package/lib/client/components/QaSourcesPanel.js +3 -18
- package/lib/client/components/QaSourcesPanel.js.map +1 -1
- package/lib/client/components/QaWorkGroup.js +4 -8
- package/lib/client/components/QaWorkGroup.js.map +1 -1
- package/lib/client/components/source-icon.js +26 -0
- package/lib/client/components/source-icon.js.map +1 -0
- package/lib/client/components/thinking-phrases.js +2 -11
- package/lib/client/components/thinking-phrases.js.map +1 -1
- package/lib/client/components/use-now.js +21 -0
- package/lib/client/components/use-now.js.map +1 -0
- package/lib/client/index.js +33 -5
- package/lib/client/index.js.map +1 -1
- package/lib/client/lineage.js +18 -0
- package/lib/client/lineage.js.map +1 -0
- package/lib/client/markdown/CodeBlock.js +28 -0
- package/lib/client/markdown/CodeBlock.js.map +1 -0
- package/lib/client/markdown/blocks.js +342 -0
- package/lib/client/markdown/blocks.js.map +1 -0
- package/lib/client/markdown/highlight.js +1089 -0
- package/lib/client/markdown/highlight.js.map +1 -0
- package/lib/client/markdown/inline.js +377 -0
- package/lib/client/markdown/inline.js.map +1 -0
- package/lib/client/markdown/render.js +147 -0
- package/lib/client/markdown/render.js.map +1 -0
- package/lib/client/markdown/source-chip.js +55 -0
- package/lib/client/markdown/source-chip.js.map +1 -0
- package/lib/client/markdown/use-transient-flag.js +27 -0
- package/lib/client/markdown/use-transient-flag.js.map +1 -0
- 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/role/RoleSelector.js +11 -2
- package/lib/client/role/RoleSelector.js.map +1 -1
- package/lib/client/role/preview.js +123 -0
- package/lib/client/role/preview.js.map +1 -0
- 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/slash.js +57 -0
- package/lib/client/settings/sections/slash.js.map +1 -0
- 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 +1 -0
- package/lib/client/settings/sections.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/styles.js +124 -20
- 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 +7615 -1567
- package/lib/client.js.map +1 -1
- package/lib/config-resolvers/accounts.js +15 -0
- package/lib/config-resolvers/accounts.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 +30 -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/slash-commands.js +60 -0
- package/lib/config-resolvers/slash-commands.js.map +1 -0
- package/lib/config-resolvers/sources.js +16 -0
- package/lib/config-resolvers/sources.js.map +1 -1
- package/lib/config.js +118 -2
- package/lib/config.js.map +1 -1
- package/lib/index.js +183 -11
- package/lib/index.js.map +1 -1
- package/lib/lockdown-policy.js +19 -0
- package/lib/lockdown-policy.js.map +1 -1
- package/lib/personal-skills/service.js +16 -3
- package/lib/personal-skills/service.js.map +1 -1
- package/lib/provenance/host-store.js +25 -4
- package/lib/provenance/host-store.js.map +1 -1
- package/lib/provenance/retention.js +25 -0
- package/lib/provenance/retention.js.map +1 -0
- package/lib/provenance/snapshot-store.js +290 -35
- package/lib/provenance/snapshot-store.js.map +1 -1
- package/lib/questions.js +98 -38
- package/lib/questions.js.map +1 -1
- package/lib/resolve-config.js +5 -0
- package/lib/resolve-config.js.map +1 -1
- package/lib/secure-session.js +139 -21
- package/lib/secure-session.js.map +1 -1
- 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 +348 -56
- package/lib/typert.remote-client.d.ts +7 -1
- package/lib/typert.remote-client.js +274 -51
- package/lib/types/access/capability-catalog.d.ts +28 -1
- package/lib/types/access/role-repository.d.ts +38 -7
- package/lib/types/access/service.d.ts +106 -3
- package/lib/types/account-remotes.d.ts +8 -4
- package/lib/types/accounts/database.d.ts +84 -0
- package/lib/types/accounts/errors.d.ts +7 -1
- package/lib/types/accounts/file.d.ts +17 -39
- package/lib/types/accounts/store.d.ts +110 -19
- package/lib/types/admin/quality-store.d.ts +38 -2
- 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/{format.d.ts → copy.d.ts} +1 -1
- package/lib/types/client/admin/pages/Conversations.d.ts +4 -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/components/Markdown.d.ts +7 -8
- package/lib/types/client/components/QaComposer.d.ts +12 -2
- package/lib/types/client/components/QaQuestions.d.ts +7 -0
- package/lib/types/client/components/QaSidebar.d.ts +11 -1
- package/lib/types/client/components/QaSourcesPanel.d.ts +1 -3
- package/lib/types/client/components/source-icon.d.ts +12 -0
- package/lib/types/client/components/use-now.d.ts +8 -0
- package/lib/types/client/lineage.d.ts +15 -0
- package/lib/types/client/markdown/CodeBlock.d.ts +14 -0
- package/lib/types/client/markdown/blocks.d.ts +74 -0
- package/lib/types/client/markdown/highlight.d.ts +29 -0
- package/lib/types/client/markdown/inline.d.ts +40 -0
- package/lib/types/client/markdown/render.d.ts +13 -0
- package/lib/types/client/markdown/source-chip.d.ts +32 -0
- package/lib/types/client/markdown/use-transient-flag.d.ts +12 -0
- 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/role/RoleSelector.d.ts +11 -1
- package/lib/types/client/role/preview.d.ts +109 -0
- package/lib/types/client/settings/sections/slash.d.ts +16 -0
- package/lib/types/client/settings/sections.d.ts +1 -0
- 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 +9 -0
- package/lib/types/client/types.d.ts +16 -1
- package/lib/types/config-resolvers/slash-commands.d.ts +20 -0
- package/lib/types/index.d.ts +83 -2
- package/lib/types/lockdown-policy.d.ts +16 -0
- package/lib/types/personal-skills/service.d.ts +5 -0
- package/lib/types/provenance/host-store.d.ts +20 -3
- package/lib/types/provenance/retention.d.ts +46 -0
- package/lib/types/provenance/snapshot-store.d.ts +63 -7
- package/lib/types/questions.d.ts +13 -0
- package/lib/types/secure-session.d.ts +27 -1
- 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 +254 -5
- package/package.json +9 -5
- package/scripts/attach-workspace-sessions.mjs +472 -0
- package/lib/client/admin/format.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ClientRemote } from "@deepseek-ai/dsh-api-gateway/client";
|
|
2
2
|
import type { ISessions, SessionFace } from "@deepseek-ai/dsh-api-session-controller/client";
|
|
3
3
|
import type { UiConversation } from "@deepseek-ai/dsh-client-ui-conversation/client";
|
|
4
|
-
import type { QaAccountProfileInput, QaAccountSession, QaAccountStartersInput, QaAccountStarter, QaAccountUserPublic, QaAccessAdminSnapshot, QaApprovalDecision, QaClaimResult, QaLockdownProof, QaOwnershipEntry, QaPendingApproval, QaPendingQuestion, QaQuestionAnswerItem, QaSessionState, QaSkillDocument, QaSkillDraftInput, QaSkillRemoval, QaSkillSummary, QaSkillToolDescriptor, QaSkillValidation, QaSourceFilePreview, QaTurnSources, QaWhoamiResult, QaCapabilitySelection, QaCurrentAccess, QaSessionAccess, QaSkillActivationRecord, QaSkillAssignmentOverride, QaSubrole, QaUserAccess, QaAdminAuditEvent, QaAdminOverview, QaAdminPage, QaAdminUserDetail, QaAdminUserRow, QaAdminUserUpdate, QaAuditQuery, QaConversationDetail, QaConversationQuery, QaConversationReview, QaConversationReviewInput, QaConversationSummary, QaFeedbackQuery, QaFeedbackRow, QaMessageFeedback, QaMessageFeedbackInput, QaQualityMetrics, QaReviewQueueItem, QaReviewQueueRow, QaUserQuery } from "../types.js";
|
|
4
|
+
import type { QaAccountProfileInput, QaAccountSession, QaAccountStartersInput, QaAccountStarter, QaAccountUserPublic, QaAccessAdminSnapshot, QaApprovalDecision, QaClaimResult, QaLockdownProof, QaOwnershipEntry, QaPendingApproval, QaPendingQuestion, QaQuestionAnswerItem, QaSessionState, QaSkillDocument, QaSkillDraftInput, QaSkillRemoval, QaSkillSummary, QaSkillToolDescriptor, QaSkillValidation, QaSourceFilePreview, QaTurnSources, QaWhoamiResult, QaCapabilitySelection, QaCurrentAccess, QaSessionAccess, QaSkillActivationRecord, QaSkillAssignmentOverride, QaSubrole, QaUserAccess, QaAdminAuditEvent, QaAdminOverview, QaAdminPage, QaAdminUserDetail, QaAdminUserRow, QaAdminUserUpdate, QaAuditQuery, QaConversationDetail, QaConversationDeletion, QaConversationQuery, QaConversationReview, QaConversationReviewInput, QaConversationSummary, QaFeedbackQuery, QaFeedbackRow, QaMessageFeedback, QaMessageFeedbackInput, QaQualityMetrics, QaReviewQueueItem, QaReviewQueueRow, QaSlashCatalog, QaSlashExecution, QaSlashSubmitAttachment, QaUserQuery } from "../types.js";
|
|
5
5
|
/** Wire content one prompt carries: text plus base64 image uploads. */
|
|
6
6
|
export type QaPromptContent = Parameters<SessionFace["prompt"]>[0];
|
|
7
7
|
/** DSH session runtime surface the QA controller is allowed to touch. */
|
|
@@ -58,6 +58,11 @@ export interface QaAdminApi {
|
|
|
58
58
|
updateUser(token: string, userId: string, update: QaAdminUserUpdate): Promise<RemoteResult<QaAdminUserDetail>>;
|
|
59
59
|
conversations(token: string, query: QaConversationQuery, cursor: string | null, limit: number | null): Promise<RemoteResult<QaAdminPage<QaConversationSummary>>>;
|
|
60
60
|
conversation(token: string, conversationId: string): Promise<RemoteResult<QaConversationDetail>>;
|
|
61
|
+
/**
|
|
62
|
+
* Remove the conversation from the deployment, stored logs included. Only an
|
|
63
|
+
* administrator may call it; the sidebar's own delete is unrelated.
|
|
64
|
+
*/
|
|
65
|
+
deleteConversation(token: string, conversationId: string): Promise<RemoteResult<QaConversationDeletion>>;
|
|
61
66
|
feedback(token: string, query: QaFeedbackQuery, cursor: string | null, limit: number | null): Promise<RemoteResult<QaAdminPage<QaFeedbackRow>>>;
|
|
62
67
|
/** The signed-in user's own verdict on one of their assistant messages. */
|
|
63
68
|
rateMessage(token: string, conversationId: string, messageId: string, input: QaMessageFeedbackInput): Promise<RemoteResult<QaMessageFeedback>>;
|
|
@@ -107,6 +112,16 @@ export interface QaSourceApi {
|
|
|
107
112
|
readonly error: unknown;
|
|
108
113
|
}>;
|
|
109
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* The slash half of the Host namespace. The catalog comes back already cut
|
|
117
|
+
* down by the deployment policy and the chat's role; `execute` takes the raw
|
|
118
|
+
* line, because admission re-derives the name from it rather than trusting
|
|
119
|
+
* anything the browser says about which entry it means.
|
|
120
|
+
*/
|
|
121
|
+
export interface QaSlashApi {
|
|
122
|
+
catalog(token: string, sessionId: string): Promise<RemoteResult<QaSlashCatalog>>;
|
|
123
|
+
execute(token: string, sessionId: string, line: string, attachments: readonly QaSlashSubmitAttachment[]): Promise<RemoteResult<QaSlashExecution>>;
|
|
124
|
+
}
|
|
110
125
|
/** A source API with the account token already bound at the call site. */
|
|
111
126
|
export type QaBoundSourceApi = {
|
|
112
127
|
sources(sessionId: string): Promise<{
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { QaSurfaceConfig, ResolvedQaSlashCommands } from "../types.js";
|
|
2
|
+
/** Palette ceilings; a palette longer than the viewport is unusable on mobile. */
|
|
3
|
+
export declare const QA_SLASH_MAX_VISIBLE_MIN = 1;
|
|
4
|
+
export declare const QA_SLASH_MAX_VISIBLE_MAX = 100;
|
|
5
|
+
/**
|
|
6
|
+
* Resolve the slash interface policy.
|
|
7
|
+
*
|
|
8
|
+
* The master switch lives in lockdown, so it arrives as a neighbor rather than
|
|
9
|
+
* being re-read here — one owner per decision. Two consequences are deliberate:
|
|
10
|
+
*
|
|
11
|
+
* - An upgrade from a deployment that had already set
|
|
12
|
+
* `lockdown.allowSlashCommands: true` but knows nothing about this section
|
|
13
|
+
* keeps working: skills fall back to `all` (every user-invocable skill the
|
|
14
|
+
* session already exposed) and commands stay denied. The flag is reported as
|
|
15
|
+
* `legacyDefaults` so the Host can say so once, out loud.
|
|
16
|
+
* - A deployment that declares the section and leaves the switch off changes
|
|
17
|
+
* nothing at all: the resolved policy is inert until the switch is on.
|
|
18
|
+
*/
|
|
19
|
+
export declare function resolveSlashCommands(input: QaSurfaceConfig, allowSlashCommands: boolean): ResolvedQaSlashCommands;
|
|
20
|
+
//# sourceMappingURL=slash-commands.d.ts.map
|
package/lib/types/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
|
|
2
2
|
import type { Context } from "@deepseek-ai/cordis";
|
|
3
3
|
import type { QaTurnSources } from "./provenance/types.js";
|
|
4
|
-
import type { QaAccountProfileInput, QaAccountSession, QaAccountStartersInput, QaAccountUserPublic, QaApprovalDecision, QaClaimResult, QaLockdownProof, QaOwnershipEntry, QaPendingApproval, QaPendingQuestion, QaQuestionAnswerItem, QaSurfaceConfig, ResolvedQaSurfaceConfig, QaSkillDocument, QaSkillDraftInput, QaSkillRemoval, QaSkillSummary, QaSkillToolDescriptor, QaSkillValidation, QaSourceFilePreview, QaWhoamiResult, QaPrincipal, QaAccessAdminSnapshot, QaAdminAuditEvent, QaAdminOverview, QaAdminPage, QaAdminUserDetail, QaAdminUserRow, QaAdminUserUpdate, QaAuditQuery, QaCapabilitySelection, QaConversationDetail, QaConversationQuery, QaConversationReview, QaConversationReviewInput, QaConversationSummary, QaCurrentAccess, QaFeedbackQuery, QaFeedbackRow, QaMessageFeedback, QaMessageFeedbackInput, QaQualityMetrics, QaReviewQueueItem, QaReviewQueueRow, QaSessionAccess, QaSkillActivationRecord, QaSkillAssignmentOverride, QaSubrole, QaUserAccess, QaUserQuery } from "./types.js";
|
|
4
|
+
import type { QaAccountProfileInput, QaAccountSession, QaAccountStartersInput, QaAccountUserPublic, QaApprovalDecision, QaClaimResult, QaLockdownProof, QaOwnershipEntry, QaPendingApproval, QaPendingQuestion, QaQuestionAnswerItem, QaSurfaceConfig, ResolvedQaSurfaceConfig, QaSkillDocument, QaSkillDraftInput, QaSkillRemoval, QaSkillSummary, QaSkillToolDescriptor, QaSkillValidation, QaSourceFilePreview, QaWhoamiResult, QaPrincipal, QaAccessAdminSnapshot, QaAdminAuditEvent, QaAdminOverview, QaAdminPage, QaAdminUserDetail, QaAdminUserRow, QaAdminUserUpdate, QaAuditQuery, QaCapabilitySelection, QaConversationDetail, QaConversationDeletion, QaConversationQuery, QaConversationReview, QaConversationReviewInput, QaConversationSummary, QaCurrentAccess, QaFeedbackQuery, QaFeedbackRow, QaMessageFeedback, QaMessageFeedbackInput, QaQualityMetrics, QaReviewQueueItem, QaReviewQueueRow, QaSessionAccess, QaSlashCatalog, QaSlashExecution, QaSlashSubmitAttachment, QaSkillActivationRecord, QaSkillAssignmentOverride, QaSubrole, QaUserAccess, QaUserQuery } from "./types.js";
|
|
5
5
|
export declare const name = "qa-surface";
|
|
6
6
|
export declare const inject: string[];
|
|
7
7
|
import { QA_SURFACE_SETTINGS_NAMESPACE } from "./shared/settings.js";
|
|
@@ -38,6 +38,12 @@ export declare class QaSurface extends TypertRemoteService {
|
|
|
38
38
|
private readonly personalSkills;
|
|
39
39
|
/** Personal-skill remote bodies; the wire signatures stay on this class. */
|
|
40
40
|
private readonly skillRemotes;
|
|
41
|
+
/**
|
|
42
|
+
* Slash-catalog and command-admission bodies. Admission, not execution:
|
|
43
|
+
* the native skill and command runtimes stay the only things that know what
|
|
44
|
+
* a `/name` means.
|
|
45
|
+
*/
|
|
46
|
+
private readonly slashRemotes;
|
|
41
47
|
private readonly launchToken;
|
|
42
48
|
/** Root session principals attested for their owner, never for admin viewing. */
|
|
43
49
|
private readonly integrationPrincipals;
|
|
@@ -52,6 +58,25 @@ export declare class QaSurface extends TypertRemoteService {
|
|
|
52
58
|
constructor(ctx: Context, entry?: QaSurfaceConfig);
|
|
53
59
|
/** The quality store, opening its file the first time anyone needs it. */
|
|
54
60
|
private quality;
|
|
61
|
+
/**
|
|
62
|
+
* The standing scope of the preset QA chats run under, so an administrator's
|
|
63
|
+
* capability catalog is read the way a chat reads it. Everything a preset
|
|
64
|
+
* mounts — its skill catalog, its tool family — is registered in that scope,
|
|
65
|
+
* and a global-only read showed the operator an almost empty page. Resolving
|
|
66
|
+
* the preset composes it but starts no agent, no session and no turn;
|
|
67
|
+
* without a pinned preset there is nothing to borrow, and the read stays
|
|
68
|
+
* global.
|
|
69
|
+
*/
|
|
70
|
+
private qaPresetScope;
|
|
71
|
+
/**
|
|
72
|
+
* Drop what the quality layer kept about chats that no longer exist in the
|
|
73
|
+
* Harness. The ownership sweep calls this with the ids it reclaimed: the
|
|
74
|
+
* record it removes is one thing the deployment held about a chat, and
|
|
75
|
+
* ratings, reviews and queue entries are the rest. Failure is logged and
|
|
76
|
+
* swallowed — housekeeping runs inside a review read, and a store that
|
|
77
|
+
* cannot be opened must not fail the page that triggered it.
|
|
78
|
+
*/
|
|
79
|
+
private dropVanishedChats;
|
|
55
80
|
/** Resolve browser authentication to the caller only; never accepts an id. */
|
|
56
81
|
principalForToken(token: string): QaPrincipal | undefined;
|
|
57
82
|
/** Resolve only a directly QA-owned root session; delegated children fail closed. */
|
|
@@ -59,6 +84,21 @@ export declare class QaSurface extends TypertRemoteService {
|
|
|
59
84
|
/** Admit tools that independently enforce the same QA principal boundary. */
|
|
60
85
|
registerPrincipalScopedTools(names: readonly string[]): () => void;
|
|
61
86
|
getConfig(): ResolvedQaSurfaceConfig;
|
|
87
|
+
/**
|
|
88
|
+
* Ownership plus the role's user-skill grant for one slash read.
|
|
89
|
+
*
|
|
90
|
+
* Ownership comes first and for the same reason the rest of the plugin does
|
|
91
|
+
* it: a catalog names the skills a chat can reach, and a foreign browser has
|
|
92
|
+
* no business enumerating that. With accounts off there is no identity to
|
|
93
|
+
* check and the deployment's lockdown is the boundary, exactly as it is for
|
|
94
|
+
* every other remote.
|
|
95
|
+
*
|
|
96
|
+
* The grant mirrors `installQaSkillPolicy` to the letter — an empty
|
|
97
|
+
* `userSkills` list means the role keeps no separate user list, not that it
|
|
98
|
+
* grants nothing — so the palette can never offer a skill the typed gesture
|
|
99
|
+
* would refuse, nor hide one it would accept.
|
|
100
|
+
*/
|
|
101
|
+
private slashSessionGrant;
|
|
62
102
|
/**
|
|
63
103
|
* Self-service signup; the first account ever created becomes admin. The
|
|
64
104
|
* display name derives from the email: the generated client enforces exact
|
|
@@ -68,7 +108,11 @@ export declare class QaSurface extends TypertRemoteService {
|
|
|
68
108
|
accountsLogin(email: string, password: string): QaAccountSession;
|
|
69
109
|
/** Identity probe; safe to call with an empty or expired token. */
|
|
70
110
|
accountsWhoami(token: string): QaWhoamiResult;
|
|
71
|
-
/**
|
|
111
|
+
/**
|
|
112
|
+
* Migrate a browser's local chat index into server-side ownership. The
|
|
113
|
+
* access service owns the filter: a delegated session in that index is not a
|
|
114
|
+
* chat and is never claimed.
|
|
115
|
+
*/
|
|
72
116
|
accountsClaimSessions(token: string, sessionIds: readonly string[]): QaClaimResult;
|
|
73
117
|
/** The token user's owned session ids; the sidebar list authority. */
|
|
74
118
|
accountsOwnedSessions(token: string): {
|
|
@@ -135,6 +179,12 @@ export declare class QaSurface extends TypertRemoteService {
|
|
|
135
179
|
adminConversations(token: string, query: QaConversationQuery, cursor: string | null, limit: number | null): Promise<QaAdminPage<QaConversationSummary>>;
|
|
136
180
|
/** One conversation with its messages, tool calls and review state. */
|
|
137
181
|
adminConversation(token: string, conversationId: string): Promise<QaConversationDetail>;
|
|
182
|
+
/**
|
|
183
|
+
* Remove one conversation from the deployment. Admin-only, audited, and the
|
|
184
|
+
* only path that deletes what a person wrote — the sidebar's own delete
|
|
185
|
+
* stays what it always was, a per-browser row.
|
|
186
|
+
*/
|
|
187
|
+
adminDeleteConversation(token: string, conversationId: string): Promise<QaConversationDeletion>;
|
|
138
188
|
adminFeedback(token: string, query: QaFeedbackQuery, cursor: string | null, limit: number | null): Promise<QaAdminPage<QaFeedbackRow>>;
|
|
139
189
|
/**
|
|
140
190
|
* Rate one of the caller's own assistant messages. The token names the only
|
|
@@ -212,7 +262,38 @@ export declare class QaSurface extends TypertRemoteService {
|
|
|
212
262
|
skillsTools(token: string): {
|
|
213
263
|
readonly tools: readonly QaSkillToolDescriptor[];
|
|
214
264
|
};
|
|
265
|
+
/**
|
|
266
|
+
* The slash entries this browser may offer for one chat: the session's
|
|
267
|
+
* user-invocable skills and its agent's effective commands, already cut down
|
|
268
|
+
* by the deployment policy and by the chat's role. The browser filters and
|
|
269
|
+
* ranks this list; it never widens it.
|
|
270
|
+
*
|
|
271
|
+
* Enabled is reported rather than assumed, so a page that loaded before the
|
|
272
|
+
* operator flipped the master switch learns the truth instead of showing an
|
|
273
|
+
* empty palette forever.
|
|
274
|
+
*/
|
|
275
|
+
slashCatalog(token: string, sessionId: string): Promise<QaSlashCatalog>;
|
|
276
|
+
/**
|
|
277
|
+
* Run one human command line. The line is the whole request — the browser
|
|
278
|
+
* sends no name, no kind and no descriptor, so there is nothing for it to
|
|
279
|
+
* forge; admission re-derives the name and re-checks the policy against the
|
|
280
|
+
* deployment's own config.
|
|
281
|
+
*
|
|
282
|
+
* A command never becomes a model message: the native runtime answers it and
|
|
283
|
+
* writes `command/run`/`command/done` into the session log, which is where
|
|
284
|
+
* the transcript row is read from.
|
|
285
|
+
*/
|
|
286
|
+
slashExecute(token: string, sessionId: string, line: string, attachments: readonly QaSlashSubmitAttachment[]): Promise<QaSlashExecution>;
|
|
215
287
|
private refreshRoute;
|
|
288
|
+
/**
|
|
289
|
+
* A deployment that set `lockdown.allowSlashCommands: true` before this
|
|
290
|
+
* section existed keeps the behaviour it asked for — skills at `all`,
|
|
291
|
+
* commands denied — and is told so once per configuration change, because
|
|
292
|
+
* "skills appeared after the upgrade" is otherwise indistinguishable from a
|
|
293
|
+
* defect. Commands are never part of that fallback: an upgrade must not hand
|
|
294
|
+
* the user a control-plane command nobody named.
|
|
295
|
+
*/
|
|
296
|
+
private warnLegacySlashDefaults;
|
|
216
297
|
/**
|
|
217
298
|
* The document pipeline moved out of this plugin into `@yadsh/dsh-documents`.
|
|
218
299
|
* A deployment whose profile still carries the old `documents` section would
|
|
@@ -25,4 +25,20 @@ export declare function qaToolPolicyPlan(allow: readonly string[], isMounted: (t
|
|
|
25
25
|
* stays as unchecked as any allow-listed one, and no less.
|
|
26
26
|
*/
|
|
27
27
|
export declare function qaToolDenial(allowed: ReadonlySet<string>, toolName: string, dynamicNames?: readonly string[]): string | undefined;
|
|
28
|
+
/**
|
|
29
|
+
* The conversation-wide ceiling, applied to every agent of an attested chat.
|
|
30
|
+
*
|
|
31
|
+
* A scoped restriction and a scoped guard cover the scope that owns them and
|
|
32
|
+
* that scope's descendants. A delegated child is composed from the parent's
|
|
33
|
+
* PRESET, so the parent agent's own layers never enter the child's chain: the
|
|
34
|
+
* child is bounded by its preset `toolFilter` alone, and an expert can
|
|
35
|
+
* therefore hold — and call — a tool the subrole never granted the chat. This
|
|
36
|
+
* check is the ceiling the whole conversation shares: the subrole's reach,
|
|
37
|
+
* visible tools plus the grantable ones, so a skill may still hand a tool to a
|
|
38
|
+
* delegated assistant, but nothing may exceed what the role could ever grant.
|
|
39
|
+
* @param ceiling - names reachable anywhere in this conversation.
|
|
40
|
+
* @param toolName - the tool the model is trying to call.
|
|
41
|
+
* @returns the denial reason, or `undefined` when the call is within reach.
|
|
42
|
+
*/
|
|
43
|
+
export declare function qaCeilingDenial(ceiling: ReadonlySet<string>, toolName: string): string | undefined;
|
|
28
44
|
//# sourceMappingURL=lockdown-policy.d.ts.map
|
|
@@ -92,6 +92,11 @@ export declare class QaPersonalSkills {
|
|
|
92
92
|
* The skills one session cwd exposes to DSH. A file the parser rejects, or
|
|
93
93
|
* one whose name disagrees with its directory, is reported in the editor and
|
|
94
94
|
* never handed to the model as a half-valid skill.
|
|
95
|
+
*
|
|
96
|
+
* This is the model-facing discovery path, so it degrades to empty instead
|
|
97
|
+
* of throwing: a provider that throws marks the whole catalog snapshot
|
|
98
|
+
* incomplete, and the harness then withholds the available-skills section
|
|
99
|
+
* from every session — not just this account's skills.
|
|
95
100
|
*/
|
|
96
101
|
discover(cwd: string): readonly QaStoredSkill[];
|
|
97
102
|
/** Re-read one skill of a session cwd, re-checking the same boundary. */
|
|
@@ -35,11 +35,28 @@ export declare class QaProvenanceHost {
|
|
|
35
35
|
constructor(ctx: Context, config: () => ResolvedQaSurfaceConfig, store?: QaProvenanceSnapshotStore, onPersistenceError?: (error: unknown) => void);
|
|
36
36
|
dispose(): void;
|
|
37
37
|
/**
|
|
38
|
-
* Drop
|
|
39
|
-
* their sessions by weeks; without this the collector, snapshot,
|
|
40
|
-
* lineage maps grow with every chat and turn forever.
|
|
38
|
+
* Drop the in-memory per-session records of one chat. Long-lived servers
|
|
39
|
+
* outlive their sessions by weeks; without this the collector, snapshot,
|
|
40
|
+
* call and lineage maps grow with every chat and turn forever. The durable
|
|
41
|
+
* snapshot file is intentionally kept: `session/disposed` also fires for
|
|
42
|
+
* runtime teardown of a chat that still exists and will be reopened, and
|
|
43
|
+
* its stored turns are what let the transcript show sources after a Host
|
|
44
|
+
* restart. Growth of the file is bounded by the snapshot store's caps.
|
|
41
45
|
*/
|
|
42
46
|
private forget;
|
|
47
|
+
private forgetById;
|
|
48
|
+
/**
|
|
49
|
+
* Drop everything kept about one chat, in memory and in storage alike.
|
|
50
|
+
*
|
|
51
|
+
* Unlike {@link forget}, which runs on every teardown of a chat that still
|
|
52
|
+
* exists and deliberately keeps its stored turns, this is for a chat that is
|
|
53
|
+
* gone: nothing will reopen it, so the durable shard goes with it. The
|
|
54
|
+
* administrative deletion calls this in the same act that removes the
|
|
55
|
+
* session's logs.
|
|
56
|
+
*
|
|
57
|
+
* @param sessionId - the chat whose collected sources are dropped.
|
|
58
|
+
*/
|
|
59
|
+
dropSession(sessionId: string): void;
|
|
43
60
|
private forgetAll;
|
|
44
61
|
bundles(sessionId: string): readonly QaTurnSources[];
|
|
45
62
|
sourceAllowed(sessionId: string, path: string): boolean;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retention contract for durable provenance.
|
|
3
|
+
*
|
|
4
|
+
* This module is deliberately free of Node imports: the resolved default
|
|
5
|
+
* config reaches the browser bundle through `resolve-config`, and a single
|
|
6
|
+
* `node:fs` import here would break that bundle at runtime.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* What a sharded provenance store keeps. Every bound counts turns, shards or
|
|
10
|
+
* days; zero means "keep everything" for that bound.
|
|
11
|
+
*/
|
|
12
|
+
export interface QaProvenanceRetention {
|
|
13
|
+
/** Newest turns kept per chat. */
|
|
14
|
+
readonly maxTurnsPerSession: number;
|
|
15
|
+
/** Chats kept, most recently written first. */
|
|
16
|
+
readonly maxSessions: number;
|
|
17
|
+
/** Chats untouched for longer than this are dropped. */
|
|
18
|
+
readonly maxAgeDays: number;
|
|
19
|
+
/** How often a write may trigger the directory sweep. */
|
|
20
|
+
readonly sweepIntervalMinutes: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Defaults sized for a QA deployment: one chat is worth a few hundred turns, a
|
|
24
|
+
* fortnight of chats is worth keeping, and an untouched month is finished.
|
|
25
|
+
*/
|
|
26
|
+
export declare const DEFAULT_QA_PROVENANCE_RETENTION: QaProvenanceRetention;
|
|
27
|
+
/** Bounds the configuration validator enforces, mirrored for the CLI. */
|
|
28
|
+
export declare const QA_PROVENANCE_RETENTION_LIMITS: Readonly<{
|
|
29
|
+
maxTurnsPerSession: {
|
|
30
|
+
min: number;
|
|
31
|
+
max: number;
|
|
32
|
+
};
|
|
33
|
+
maxSessions: {
|
|
34
|
+
min: number;
|
|
35
|
+
max: number;
|
|
36
|
+
};
|
|
37
|
+
maxAgeDays: {
|
|
38
|
+
min: number;
|
|
39
|
+
max: number;
|
|
40
|
+
};
|
|
41
|
+
sweepIntervalMinutes: {
|
|
42
|
+
min: number;
|
|
43
|
+
max: number;
|
|
44
|
+
};
|
|
45
|
+
}>;
|
|
46
|
+
//# sourceMappingURL=retention.d.ts.map
|
|
@@ -1,23 +1,79 @@
|
|
|
1
|
+
import { type QaProvenanceRetention } from "./retention.js";
|
|
1
2
|
import type { QaTurnSources } from "./types.js";
|
|
2
3
|
export interface QaProvenanceSnapshotStore {
|
|
3
4
|
list(sessionId: string): readonly QaTurnSources[];
|
|
4
5
|
put(bundle: QaTurnSources): void;
|
|
6
|
+
/**
|
|
7
|
+
* Drop one session's snapshots. The host store wires this to the session's
|
|
8
|
+
* disposal, which is what keeps the durable file from growing with every
|
|
9
|
+
* chat a long-lived server ever served.
|
|
10
|
+
*/
|
|
11
|
+
drop(sessionId: string): void;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Retention bounds and their defaults live in a Node-free module: the resolved
|
|
15
|
+
* default config reaches the browser bundle, and this file does not.
|
|
16
|
+
*/
|
|
17
|
+
export { DEFAULT_QA_PROVENANCE_RETENTION, QA_PROVENANCE_RETENTION_LIMITS, } from "./retention.js";
|
|
18
|
+
export type { QaProvenanceRetention } from "./retention.js";
|
|
19
|
+
/** What one directory sweep did, for the maintenance command and the tests. */
|
|
20
|
+
export interface QaProvenanceSweepResult {
|
|
21
|
+
readonly scanned: number;
|
|
22
|
+
readonly droppedByAge: number;
|
|
23
|
+
readonly droppedByCount: number;
|
|
5
24
|
}
|
|
6
25
|
/** Process-local store used by tests and explicit ephemeral deployments. */
|
|
7
26
|
export declare class MemoryQaProvenanceSnapshotStore implements QaProvenanceSnapshotStore {
|
|
8
27
|
private readonly sessions;
|
|
9
28
|
list(sessionId: string): readonly QaTurnSources[];
|
|
10
29
|
put(bundle: QaTurnSources): void;
|
|
30
|
+
drop(sessionId: string): void;
|
|
11
31
|
}
|
|
12
|
-
/** Default durable provenance
|
|
13
|
-
export declare function
|
|
14
|
-
/**
|
|
32
|
+
/** Default durable provenance directory, deliberately outside Harness journals. */
|
|
33
|
+
export declare function defaultQaProvenanceDirectoryPath(): string;
|
|
34
|
+
/** The pre-sharding monolith, migrated on first use and then left alone. */
|
|
35
|
+
export declare function defaultLegacyProvenanceFilePath(): string;
|
|
36
|
+
/**
|
|
37
|
+
* Durable provenance, one file per chat.
|
|
38
|
+
*
|
|
39
|
+
* The read API is per-session and nothing enumerates every chat, so a shard is
|
|
40
|
+
* exactly the unit a writer touches: a turn rewrites one chat's history rather
|
|
41
|
+
* than every chat's. Empty turns collapse to their numbers and each shard is
|
|
42
|
+
* bounded by `QaProvenanceRetention`, so neither a long chat nor a long-lived
|
|
43
|
+
* deployment can make a single write grow without limit.
|
|
44
|
+
*
|
|
45
|
+
* The store is the only writer of its directory, and no cache sits in front of
|
|
46
|
+
* it: every read goes to disk.
|
|
47
|
+
*/
|
|
15
48
|
export declare class FileQaProvenanceSnapshotStore implements QaProvenanceSnapshotStore {
|
|
16
|
-
private readonly
|
|
17
|
-
|
|
49
|
+
private readonly directoryPath;
|
|
50
|
+
private readonly retention;
|
|
51
|
+
private readonly legacyFilePath;
|
|
52
|
+
private migrated;
|
|
53
|
+
private lastSweepAt;
|
|
54
|
+
constructor(directoryPath?: string, retention?: () => QaProvenanceRetention, legacyFilePath?: string);
|
|
18
55
|
list(sessionId: string): readonly QaTurnSources[];
|
|
19
56
|
put(bundle: QaTurnSources): void;
|
|
20
|
-
|
|
21
|
-
|
|
57
|
+
drop(sessionId: string): void;
|
|
58
|
+
/**
|
|
59
|
+
* Drop shards the retention policy no longer covers: untouched for
|
|
60
|
+
* `maxAgeDays`, then everything past the `maxSessions` most recent ones.
|
|
61
|
+
*
|
|
62
|
+
* `keep` names the chat whose shard must survive the sweep — a caller that
|
|
63
|
+
* swept right after writing it would otherwise be able to delete the very
|
|
64
|
+
* bundle it just stored.
|
|
65
|
+
*/
|
|
66
|
+
sweep(keep?: string): QaProvenanceSweepResult;
|
|
67
|
+
/**
|
|
68
|
+
* Split the pre-sharding monolith into shards exactly once, then rename it
|
|
69
|
+
* out of the way. A shard that already exists wins the merge, so a retried
|
|
70
|
+
* migration cannot lose turns that arrived after the first attempt.
|
|
71
|
+
*/
|
|
72
|
+
private migrateLegacyOnce;
|
|
73
|
+
private shardPath;
|
|
74
|
+
private readShard;
|
|
75
|
+
private writeShard;
|
|
76
|
+
private removeShard;
|
|
77
|
+
private maybeSweep;
|
|
22
78
|
}
|
|
23
79
|
//# sourceMappingURL=snapshot-store.d.ts.map
|
package/lib/types/questions.d.ts
CHANGED
|
@@ -33,6 +33,12 @@ export interface QaQuestionAnswer {
|
|
|
33
33
|
}
|
|
34
34
|
/** What the model reads when the deployment does not answer questions. */
|
|
35
35
|
export declare const QA_QUESTIONS_UNSUPPORTED = "questions are not answered in this assistant view; ask the user in plain text instead";
|
|
36
|
+
/**
|
|
37
|
+
* The harness tool that produces these requests. A deployment that parks
|
|
38
|
+
* questions still has to let the attested session call it: this plugin never
|
|
39
|
+
* adds the name to a tool policy on its own.
|
|
40
|
+
*/
|
|
41
|
+
export declare const QA_ASK_QUESTION_TOOL = "ask_user_question";
|
|
36
42
|
/**
|
|
37
43
|
* User questions in the QA view.
|
|
38
44
|
*
|
|
@@ -68,6 +74,11 @@ export declare class QaQuestionGate {
|
|
|
68
74
|
* parked request is authoritative: a label the question never offered is
|
|
69
75
|
* dropped, and a free-text answer replaces the choice in a single-select
|
|
70
76
|
* rather than accompanying it, so the model only ever reads a real answer.
|
|
77
|
+
*
|
|
78
|
+
* The payload arrives over the wire from the browser, so its shape is
|
|
79
|
+
* untrusted: a non-array, a non-object entry, or a non-array/non-string
|
|
80
|
+
* selection is folded into the refusal/skip semantics instead of crashing
|
|
81
|
+
* the gate with a TypeError.
|
|
71
82
|
*/
|
|
72
83
|
answer(sessionId: string, requestId: string, answers: readonly QaQuestionAnswerItem[]): boolean;
|
|
73
84
|
/** Close a request without answering it. */
|
|
@@ -79,5 +90,7 @@ export declare class QaQuestionGate {
|
|
|
79
90
|
private park;
|
|
80
91
|
/** Fail the questions one session's agent owns; a disposed agent cannot ask. */
|
|
81
92
|
private settleOwner;
|
|
93
|
+
/** Fail the questions one agent parked; an idle agent cannot receive them. */
|
|
94
|
+
private settleAgent;
|
|
82
95
|
}
|
|
83
96
|
//# sourceMappingURL=questions.d.ts.map
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Agent } from "@deepseek-ai/dsh-agent";
|
|
2
2
|
import type { Context } from "@deepseek-ai/cordis";
|
|
3
3
|
import type { PluginLogger } from "@yadsh/dsh-plugin-log";
|
|
4
|
+
import { type QaSessionFacts } from "./accounts/store.js";
|
|
4
5
|
import type { QaResolvedSessionPolicy } from "./access/service.js";
|
|
5
6
|
import type { QaLockdownProof, ResolvedQaSurfaceConfig } from "./types.js";
|
|
6
7
|
/**
|
|
@@ -9,7 +10,7 @@ import type { QaLockdownProof, ResolvedQaSurfaceConfig } from "./types.js";
|
|
|
9
10
|
* pair or throw the coarse `QaAttestationError`; see {@link QaAccounts}.
|
|
10
11
|
*/
|
|
11
12
|
export interface QaAccountsGate {
|
|
12
|
-
enforceSessionAccess(token: string, sessionId: string): {
|
|
13
|
+
enforceSessionAccess(token: string, sessionId: string, facts?: QaSessionFacts): {
|
|
13
14
|
readonly id: string;
|
|
14
15
|
} | undefined;
|
|
15
16
|
userWorkspace(userId: string, registeredWorkspacePath: string): string;
|
|
@@ -47,7 +48,17 @@ export declare class QaPolicyAdmission {
|
|
|
47
48
|
*/
|
|
48
49
|
private readonly attested;
|
|
49
50
|
private readonly workspaceAccess;
|
|
51
|
+
/**
|
|
52
|
+
* Every name reachable anywhere in one QA conversation, keyed by session id.
|
|
53
|
+
*
|
|
54
|
+
* The chat's agent and the agents delegated from it share one entry —
|
|
55
|
+
* children inherit it when their session is created — because the ceiling is
|
|
56
|
+
* a property of the conversation, not of one scope. See
|
|
57
|
+
* {@link qaCeilingDenial} for why a scoped restriction cannot express it.
|
|
58
|
+
*/
|
|
59
|
+
private readonly ceilings;
|
|
50
60
|
private readonly disposeWorkspaceGuard;
|
|
61
|
+
private readonly disposeCeilingGuard;
|
|
51
62
|
constructor(ctx: Context, config: () => ResolvedQaSurfaceConfig, logger: PluginLogger, accounts?: QaAccountsGate | undefined,
|
|
52
63
|
/**
|
|
53
64
|
* Names the QA tool catalog attached to one agent after its activation
|
|
@@ -100,6 +111,21 @@ export declare class QaPolicyAdmission {
|
|
|
100
111
|
* mismatch"), and the adoption and permission checks stay the gate.
|
|
101
112
|
*/
|
|
102
113
|
private liveAgent;
|
|
114
|
+
/**
|
|
115
|
+
* The Host-registered facts of one session, for the accounts gate's bounded
|
|
116
|
+
* auto-claim. A session this process has not materialized (a chat of an
|
|
117
|
+
* earlier Host run, reached before its agent exists) yields no facts and
|
|
118
|
+
* keeps the historical unbounded claim.
|
|
119
|
+
*/
|
|
120
|
+
private sessionFacts;
|
|
121
|
+
/**
|
|
122
|
+
* Account identity and ownership are checked before any policy work: an
|
|
123
|
+
* invalid token must not learn whether a session exists or how the
|
|
124
|
+
* deployment composes. Independent of lockdown — a deployment may gate
|
|
125
|
+
* users without pinning the policy, and the gate itself no-ops while
|
|
126
|
+
* accounts are disabled.
|
|
127
|
+
*/
|
|
128
|
+
private accessOwner;
|
|
103
129
|
secureSession(token: string, sessionId: string): Promise<QaLockdownProof>;
|
|
104
130
|
/**
|
|
105
131
|
* Mask one agent down to the policy's tool names, for the account-free path
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The unified presentation model behind the palette.
|
|
3
|
+
*
|
|
4
|
+
* Two native catalogs arrive here — the session's user-invocable skills and
|
|
5
|
+
* the session agent's effective commands — and leave as one list of entries
|
|
6
|
+
* whose identity is `skill:<name>` / `command:<name>`. The prefix is the whole
|
|
7
|
+
* point: both registries may publish a `plan`, and a palette that keyed rows
|
|
8
|
+
* by bare name would let one of them silently replace the other.
|
|
9
|
+
*
|
|
10
|
+
* Pure on purpose. Nothing here reads a session, a service or a file: the host
|
|
11
|
+
* remote gathers the native inputs, this module decides what the palette sees,
|
|
12
|
+
* and the tests drive it with plain arrays.
|
|
13
|
+
*/
|
|
14
|
+
import type { QaSlashCatalogEntry, QaSlashCommandSurface } from "../types.js";
|
|
15
|
+
import { type QaSlashPolicy } from "./policy.js";
|
|
16
|
+
export declare const QA_SLASH_SKILL_PREFIX = "skill:";
|
|
17
|
+
export declare const QA_SLASH_COMMAND_PREFIX = "command:";
|
|
18
|
+
/** One user-invocable skill, as the skills registry published it. */
|
|
19
|
+
export interface QaSlashNativeSkill {
|
|
20
|
+
readonly name: string;
|
|
21
|
+
readonly description: string;
|
|
22
|
+
readonly whenToUse?: string;
|
|
23
|
+
/** Whether the model is also offered this skill. */
|
|
24
|
+
readonly modelInvocable?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/** One effective command descriptor, as the command registry published it. */
|
|
27
|
+
export interface QaSlashNativeCommand {
|
|
28
|
+
readonly name: string;
|
|
29
|
+
readonly description: string;
|
|
30
|
+
readonly inputHint?: string;
|
|
31
|
+
readonly acceptsAttachments?: boolean;
|
|
32
|
+
}
|
|
33
|
+
export interface BuildSlashCatalogOptions {
|
|
34
|
+
readonly skills: readonly QaSlashNativeSkill[];
|
|
35
|
+
readonly commands: readonly QaSlashNativeCommand[];
|
|
36
|
+
readonly skillPolicy: QaSlashPolicy;
|
|
37
|
+
readonly commandPolicy: QaSlashPolicy;
|
|
38
|
+
/**
|
|
39
|
+
* The session role's own user-skill grant, when the access system is on.
|
|
40
|
+
* `undefined` means the role system has no opinion, which is its state on a
|
|
41
|
+
* deployment that never enabled roles — not "grant nothing".
|
|
42
|
+
*/
|
|
43
|
+
readonly grantedSkills?: readonly string[] | undefined;
|
|
44
|
+
readonly commandSurface: QaSlashCommandSurface;
|
|
45
|
+
/** Native entries arrive alphabetically; this makes the order explicit. */
|
|
46
|
+
readonly localeCompare?: (left: string, right: string) => number;
|
|
47
|
+
}
|
|
48
|
+
/** The routing identity of one native name; never the bare name. */
|
|
49
|
+
export declare function slashEntryId(kind: QaSlashCatalogEntry["kind"], name: string): string;
|
|
50
|
+
/**
|
|
51
|
+
* Build the palette the browser is allowed to show. Skills lead, commands
|
|
52
|
+
* follow: the two kinds stay contiguous so the palette can group them without
|
|
53
|
+
* re-sorting, and a name collision keeps both rows.
|
|
54
|
+
*/
|
|
55
|
+
export declare function buildSlashCatalog(options: BuildSlashCatalogOptions): readonly QaSlashCatalogEntry[];
|
|
56
|
+
//# sourceMappingURL=catalog.d.ts.map
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One matcher for both halves of the slash catalog.
|
|
3
|
+
*
|
|
4
|
+
* Upstream matches skills with `startsWith` and commands fuzzily, so the same
|
|
5
|
+
* query behaves differently depending on which registry answers it. QA always
|
|
6
|
+
* ranks with the ladder below, in this order:
|
|
7
|
+
*
|
|
8
|
+
* exact → prefix → name-token boundary → substring → ordered subsequence
|
|
9
|
+
*
|
|
10
|
+
* so `/tkp` finds `generate-tkp` through the token boundary and `/contract`
|
|
11
|
+
* finds both `contract-analysis` (prefix) and `review-contract` (token).
|
|
12
|
+
*
|
|
13
|
+
* Dependency-free on purpose: inlined into the browser bundle.
|
|
14
|
+
*/
|
|
15
|
+
/** How a name matched; lower is a stronger claim on the top of the list. */
|
|
16
|
+
export declare const SLASH_MATCH_EXACT = 0;
|
|
17
|
+
export declare const SLASH_MATCH_PREFIX = 1;
|
|
18
|
+
export declare const SLASH_MATCH_TOKEN = 2;
|
|
19
|
+
export declare const SLASH_MATCH_SUBSTRING = 3;
|
|
20
|
+
export declare const SLASH_MATCH_SUBSEQUENCE = 4;
|
|
21
|
+
export interface QaSlashMatch {
|
|
22
|
+
readonly rank: number;
|
|
23
|
+
/** Where the match starts; earlier wins inside one rank. */
|
|
24
|
+
readonly index: number;
|
|
25
|
+
}
|
|
26
|
+
export interface QaSlashMatchOptions {
|
|
27
|
+
/**
|
|
28
|
+
* Whether the two weakest rungs run. Turning them off keeps the matcher
|
|
29
|
+
* predictable for deployments that read the palette as an index.
|
|
30
|
+
*/
|
|
31
|
+
readonly fuzzy?: boolean;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Rank one name against a palette query. An empty query matches everything at
|
|
35
|
+
* the prefix rung, which keeps the unfiltered catalog in catalog order.
|
|
36
|
+
*/
|
|
37
|
+
export declare function matchSlashName(name: string, query: string, options?: QaSlashMatchOptions): QaSlashMatch | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* Order two ranked names; the caller has already ruled out `undefined`. Ties
|
|
40
|
+
* fall back to the name, so equal-rank rows keep catalog order and the list
|
|
41
|
+
* never reshuffles between two renders of the same query.
|
|
42
|
+
*/
|
|
43
|
+
export declare function compareSlashMatches(leftName: string, left: QaSlashMatch, rightName: string, right: QaSlashMatch): number;
|
|
44
|
+
/**
|
|
45
|
+
* The matching entries in rank order. Identity of the input entries is
|
|
46
|
+
* preserved, so a caller can render them without a lookup.
|
|
47
|
+
*/
|
|
48
|
+
export declare function rankSlashEntries<T extends {
|
|
49
|
+
readonly name: string;
|
|
50
|
+
}>(entries: readonly T[], query: string, options?: QaSlashMatchOptions): readonly T[];
|
|
51
|
+
//# sourceMappingURL=matcher.d.ts.map
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composer input classification for the slash interface.
|
|
3
|
+
*
|
|
4
|
+
* The grammars are mirrors, not inventions: a command line is what the native
|
|
5
|
+
* command runtime parses (`/name` at byte zero, name then end-of-input or
|
|
6
|
+
* whitespace, everything after kept verbatim as `rawInput`), and a skill
|
|
7
|
+
* gesture is what `dsh-tool-skill` recognises (any whitespace-bounded `/name`
|
|
8
|
+
* token with the public skill-name grammar). A line that matches neither is
|
|
9
|
+
* ordinary prose and must keep behaving exactly as it did before this feature.
|
|
10
|
+
*
|
|
11
|
+
* Deliberately dependency-free: this module is inlined into the browser
|
|
12
|
+
* bundle, where the Host's config surface must not follow it.
|
|
13
|
+
*/
|
|
14
|
+
export interface QaSlashLine {
|
|
15
|
+
readonly name: string;
|
|
16
|
+
/** Exact text after the name, including the separator whitespace. */
|
|
17
|
+
readonly args: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Parse a command-shaped line. `undefined` means the line is not one — either
|
|
21
|
+
* it is not slash-led at all, or the token after the slash is not a command
|
|
22
|
+
* name (`/usr/bin/env` stays a path, not a call).
|
|
23
|
+
*/
|
|
24
|
+
export declare function parseSlashLine(input: string): QaSlashLine | undefined;
|
|
25
|
+
/** The palette filter of a draft, or `undefined` when the palette is closed. */
|
|
26
|
+
export declare function slashPaletteQuery(input: string): string | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* Every whitespace-bounded `/name` gesture in the text, first-seen order and
|
|
29
|
+
* deduplicated. The Host owns invocation; this list exists only so the QA
|
|
30
|
+
* surface can warn about a gesture its own policy withholds before the turn
|
|
31
|
+
* is submitted.
|
|
32
|
+
*/
|
|
33
|
+
export declare function skillGestures(input: string): readonly string[];
|
|
34
|
+
/** The invocation a submitted draft carries, once its route is decided. */
|
|
35
|
+
export interface QaSlashInvocation {
|
|
36
|
+
readonly name: string;
|
|
37
|
+
/** Text after the name with its separator whitespace removed. */
|
|
38
|
+
readonly args: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The invocation a draft names, independent of the catalog. Used for the
|
|
42
|
+
* routing decision and for the "unknown command" refusal, both of which must
|
|
43
|
+
* work while the catalog itself is unavailable.
|
|
44
|
+
*/
|
|
45
|
+
export declare function slashInvocation(input: string): QaSlashInvocation | undefined;
|
|
46
|
+
//# sourceMappingURL=parser.d.ts.map
|