@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
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admission policy for one half of the slash catalog.
|
|
3
|
+
*
|
|
4
|
+
* The policy is name-based because the persisted config is: an operator writes
|
|
5
|
+
* `generate-tkp`, never an internal id, and the same name means the same thing
|
|
6
|
+
* on every Host restart. Names that cannot be a native skill or command name
|
|
7
|
+
* are refused at config resolution rather than silently ignored at admission,
|
|
8
|
+
* so a typo surfaces while the deployment is being configured.
|
|
9
|
+
*/
|
|
10
|
+
import type { QaSlashPolicyMode } from "../types.js";
|
|
11
|
+
/** Every accepted policy mode, in the order the settings card lists them. */
|
|
12
|
+
export declare const QA_SLASH_MODES: readonly QaSlashPolicyMode[];
|
|
13
|
+
/** Longest name either registry accepts in practice; keeps host echoes bounded. */
|
|
14
|
+
export declare const QA_SLASH_NAME_MAX = 200;
|
|
15
|
+
export interface QaSlashPolicy {
|
|
16
|
+
readonly mode: QaSlashPolicyMode;
|
|
17
|
+
readonly allow: readonly string[];
|
|
18
|
+
}
|
|
19
|
+
export declare function isQaSlashPolicyMode(value: unknown): value is QaSlashPolicyMode;
|
|
20
|
+
/**
|
|
21
|
+
* Normalize one allow-list: trimmed, deduplicated, order-preserving. Refuses
|
|
22
|
+
* a name that neither registry could ever carry, and refuses `all` alongside a
|
|
23
|
+
* non-empty list, which would be two answers to one question.
|
|
24
|
+
*/
|
|
25
|
+
export declare function normalizeSlashAllow(values: readonly string[], label: string): readonly string[];
|
|
26
|
+
/** Whether the policy admits this native name. */
|
|
27
|
+
export declare function allowsSlashName(policy: QaSlashPolicy, name: string): boolean;
|
|
28
|
+
/** The admitted subset, in the order the native registry returned it. */
|
|
29
|
+
export declare function filterBySlashPolicy<T extends {
|
|
30
|
+
readonly name: string;
|
|
31
|
+
}>(entries: readonly T[], policy: QaSlashPolicy): readonly T[];
|
|
32
|
+
/**
|
|
33
|
+
* Intersect an already-admitted list with a second name set (the session's
|
|
34
|
+
* role grant). An empty set means "no second opinion" — the role system keeps
|
|
35
|
+
* its own switch, and a deployment that never enabled it grants nothing here.
|
|
36
|
+
*/
|
|
37
|
+
export declare function intersectSlashNames<T extends {
|
|
38
|
+
readonly name: string;
|
|
39
|
+
}>(entries: readonly T[], names: readonly string[] | undefined): readonly T[];
|
|
40
|
+
//# sourceMappingURL=policy.d.ts.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Context } from "@deepseek-ai/cordis";
|
|
2
|
+
import type { PluginLogger } from "@yadsh/dsh-plugin-log";
|
|
3
|
+
import type { QaSlashCatalog, QaSlashExecution, QaSlashSubmitAttachment, ResolvedQaSurfaceConfig } from "../types.js";
|
|
4
|
+
/**
|
|
5
|
+
* Host-side bodies of the slash remotes. The `@Remote`-decorated signatures
|
|
6
|
+
* stay on the `QaSurface` service class (typert code generation reads the class
|
|
7
|
+
* shape); this context owns everything behind them.
|
|
8
|
+
*
|
|
9
|
+
* The division of labour is the whole feature in one sentence: QA decides what
|
|
10
|
+
* the palette may show and whether a line may run, and the native registries
|
|
11
|
+
* decide what a skill and a command *mean*. Nothing here reads a SKILL.md,
|
|
12
|
+
* injects instructions or re-implements a registry.
|
|
13
|
+
*/
|
|
14
|
+
export interface QaSlashRemotes {
|
|
15
|
+
/** The catalog this browser may render, already policy-filtered. */
|
|
16
|
+
catalog(token: string, sessionId: string): Promise<QaSlashCatalog>;
|
|
17
|
+
/** Run one human command line through the native command runtime. */
|
|
18
|
+
execute(token: string, sessionId: string, line: string, attachments: readonly QaSlashSubmitAttachment[]): Promise<QaSlashExecution>;
|
|
19
|
+
}
|
|
20
|
+
export interface QaSlashRemotesOptions {
|
|
21
|
+
readonly ctx: Context;
|
|
22
|
+
readonly getConfig: () => ResolvedQaSurfaceConfig;
|
|
23
|
+
readonly logger: PluginLogger;
|
|
24
|
+
/**
|
|
25
|
+
* Ownership and role check for the current QA session. Runs only while the
|
|
26
|
+
* deployment gates QA users with accounts; it throws on refusal, which is
|
|
27
|
+
* what makes a foreign session unreadable instead of merely unowned.
|
|
28
|
+
*
|
|
29
|
+
* @returns the role's user-skill grant, or `undefined` when the access
|
|
30
|
+
* system has no opinion about this session's skills.
|
|
31
|
+
*/
|
|
32
|
+
readonly sessionGrant: (token: string, sessionId: string, agent: unknown) => Promise<readonly string[] | undefined>;
|
|
33
|
+
}
|
|
34
|
+
export declare function createQaSlashRemotes(options: QaSlashRemotesOptions): QaSlashRemotes;
|
|
35
|
+
//# sourceMappingURL=remotes.d.ts.map
|
package/lib/types/types.d.ts
CHANGED
|
@@ -20,6 +20,12 @@ export type QaApprovalInteraction = "blocked" | "interactive";
|
|
|
20
20
|
* refuses the ask outright; `interactive` answers it from the QA view.
|
|
21
21
|
*/
|
|
22
22
|
export type QaQuestionInteraction = "unsupported" | "interactive";
|
|
23
|
+
/**
|
|
24
|
+
* What a deployment may write for the question seam. `enabled` is accepted as
|
|
25
|
+
* the spelling of `interactive` a feature request asked for; the resolved
|
|
26
|
+
* config carries one name only.
|
|
27
|
+
*/
|
|
28
|
+
export type QaQuestionInteractionInput = QaQuestionInteraction | "enabled";
|
|
23
29
|
/** The operator's answer to one parked tool call. */
|
|
24
30
|
export type QaApprovalDecision = "allowed-once" | "rejected";
|
|
25
31
|
/** One answered question; `custom` is free text, and may accompany `selected`. */
|
|
@@ -36,7 +42,7 @@ export interface QaQuestionAnswerItem {
|
|
|
36
42
|
*/
|
|
37
43
|
export type QaAccountRole = "user" | "reviewer" | "admin";
|
|
38
44
|
/** Administrative permissions a role grants; see `admin/permissions.ts`. */
|
|
39
|
-
export type QaPermission = "users.read" | "users.manage" | "roles.read" | "roles.manage" | "conversations.read.all" | "conversations.read.own" | "reviews.read" | "reviews.write" | "analytics.read" | "audit.read" | "settings.manage";
|
|
45
|
+
export type QaPermission = "users.read" | "users.manage" | "roles.read" | "roles.manage" | "conversations.read.all" | "conversations.read.own" | "conversations.delete" | "reviews.read" | "reviews.write" | "analytics.read" | "audit.read" | "settings.manage";
|
|
40
46
|
/**
|
|
41
47
|
* Tools split by how they become available. `always` is visible from the first
|
|
42
48
|
* model step; `skillGrantable` is a ceiling — the tool only appears once an
|
|
@@ -45,6 +51,17 @@ export type QaPermission = "users.read" | "users.manage" | "roles.read" | "roles
|
|
|
45
51
|
export interface QaToolSelection {
|
|
46
52
|
readonly always: readonly string[];
|
|
47
53
|
readonly skillGrantable: readonly string[];
|
|
54
|
+
/**
|
|
55
|
+
* Names this layer takes away, whatever grants them.
|
|
56
|
+
*
|
|
57
|
+
* The deployment's pinned tools and the Common layer reach every role, so
|
|
58
|
+
* without this a system tool could only be withdrawn by editing the profile
|
|
59
|
+
* and restarting the Host. A denial beats every grant — system, Common, the
|
|
60
|
+
* role's own list and every skill — and it narrows the ceiling a delegated
|
|
61
|
+
* assistant is held to, so one checkbox takes a tool away from a role and
|
|
62
|
+
* from the experts that role may spawn.
|
|
63
|
+
*/
|
|
64
|
+
readonly deny?: readonly string[];
|
|
48
65
|
}
|
|
49
66
|
/** Tool/skill selection shared by the common layer and one QA subrole. */
|
|
50
67
|
export interface QaCapabilitySelection {
|
|
@@ -434,6 +451,16 @@ export interface QaSkillRemoval {
|
|
|
434
451
|
}
|
|
435
452
|
export interface QaSourcesConfig {
|
|
436
453
|
readonly enabled?: boolean;
|
|
454
|
+
/**
|
|
455
|
+
* How much durable provenance the deployment keeps. Every bound counts
|
|
456
|
+
* turns, shards or days, and zero keeps everything for that bound.
|
|
457
|
+
*/
|
|
458
|
+
readonly retention?: {
|
|
459
|
+
readonly maxTurnsPerSession?: number;
|
|
460
|
+
readonly maxSessions?: number;
|
|
461
|
+
readonly maxAgeDays?: number;
|
|
462
|
+
readonly sweepIntervalMinutes?: number;
|
|
463
|
+
};
|
|
437
464
|
readonly collect?: {
|
|
438
465
|
readonly parentAgent?: boolean;
|
|
439
466
|
readonly subagents?: boolean;
|
|
@@ -529,7 +556,7 @@ export interface QaSurfaceConfig {
|
|
|
529
556
|
readonly thinkingPhrases?: readonly string[];
|
|
530
557
|
readonly interaction?: {
|
|
531
558
|
readonly approvals?: QaApprovalInteraction;
|
|
532
|
-
readonly questions?:
|
|
559
|
+
readonly questions?: QaQuestionInteractionInput;
|
|
533
560
|
};
|
|
534
561
|
/**
|
|
535
562
|
* QA tool delivery. Dynamic activation keeps the QA tool schemas out of the
|
|
@@ -561,7 +588,14 @@ export interface QaSurfaceConfig {
|
|
|
561
588
|
readonly approvalPolicy?: QaApprovalPolicy;
|
|
562
589
|
readonly permissionPreset?: string;
|
|
563
590
|
readonly allowPermissionChanges?: false;
|
|
564
|
-
|
|
591
|
+
/**
|
|
592
|
+
* Master switch for the slash interface, and the only capability flag the
|
|
593
|
+
* resolver lets a deployment turn on. It opens the palette, which then
|
|
594
|
+
* offers exactly what `slashCommands` admits — human commands stay denied
|
|
595
|
+
* until the deployment names them. Nothing here widens the tool allow-list,
|
|
596
|
+
* the sandbox or the approval policy.
|
|
597
|
+
*/
|
|
598
|
+
readonly allowSlashCommands?: boolean;
|
|
565
599
|
readonly allowSettingsMutation?: false;
|
|
566
600
|
readonly allowSessionReset?: boolean;
|
|
567
601
|
readonly allowSessionRename?: false;
|
|
@@ -574,6 +608,12 @@ export interface QaSurfaceConfig {
|
|
|
574
608
|
/** Shared directories available to read-only filesystem tools. */
|
|
575
609
|
readonly sharedReadOnlyRoots?: readonly string[];
|
|
576
610
|
};
|
|
611
|
+
/**
|
|
612
|
+
* Slash interface policy. Admission only: the QA surface never implements a
|
|
613
|
+
* skill or command registry, it decides which native ones reach the palette.
|
|
614
|
+
* Inert while `lockdown.allowSlashCommands` is off.
|
|
615
|
+
*/
|
|
616
|
+
readonly slashCommands?: QaSlashCommandsConfig;
|
|
577
617
|
readonly embedding?: {
|
|
578
618
|
readonly frameAncestors?: string | null;
|
|
579
619
|
};
|
|
@@ -582,6 +622,21 @@ export interface QaSurfaceConfig {
|
|
|
582
622
|
readonly enabled?: boolean;
|
|
583
623
|
readonly allowRegistration?: boolean;
|
|
584
624
|
readonly sessionTtlDays?: number;
|
|
625
|
+
/**
|
|
626
|
+
* Login/registration attempts accepted per rolling minute, store-wide.
|
|
627
|
+
* The limit backs the password checks, so the default stays tight.
|
|
628
|
+
*/
|
|
629
|
+
readonly maxAuthAttemptsPerMinute?: number;
|
|
630
|
+
/**
|
|
631
|
+
* What happens to ownership records of chats the Harness no longer knows.
|
|
632
|
+
* A record is a chat's auth boundary, so only vanished chats are ever
|
|
633
|
+
* swept, and only after `ownershipGraceHours`.
|
|
634
|
+
*/
|
|
635
|
+
readonly retention?: {
|
|
636
|
+
readonly pruneVanishedSessions?: boolean;
|
|
637
|
+
readonly ownershipGraceHours?: number;
|
|
638
|
+
readonly sweepIntervalMinutes?: number;
|
|
639
|
+
};
|
|
585
640
|
/** Let admins see chats owned by other QA accounts. */
|
|
586
641
|
readonly showOtherUsersChats?: boolean;
|
|
587
642
|
/**
|
|
@@ -701,7 +756,7 @@ export interface ResolvedQaSurfaceConfig {
|
|
|
701
756
|
readonly approvalPolicy: QaApprovalPolicy;
|
|
702
757
|
readonly permissionPreset: string;
|
|
703
758
|
readonly allowPermissionChanges: false;
|
|
704
|
-
readonly allowSlashCommands:
|
|
759
|
+
readonly allowSlashCommands: boolean;
|
|
705
760
|
readonly allowSettingsMutation: false;
|
|
706
761
|
readonly allowSessionReset: boolean;
|
|
707
762
|
readonly allowSessionRename: false;
|
|
@@ -713,6 +768,7 @@ export interface ResolvedQaSurfaceConfig {
|
|
|
713
768
|
};
|
|
714
769
|
readonly sharedReadOnlyRoots: readonly string[];
|
|
715
770
|
};
|
|
771
|
+
readonly slashCommands: ResolvedQaSlashCommands;
|
|
716
772
|
readonly embedding: {
|
|
717
773
|
readonly frameAncestors: string | null;
|
|
718
774
|
};
|
|
@@ -720,8 +776,15 @@ export interface ResolvedQaSurfaceConfig {
|
|
|
720
776
|
readonly enabled: boolean;
|
|
721
777
|
readonly allowRegistration: boolean;
|
|
722
778
|
readonly sessionTtlDays: number;
|
|
779
|
+
/** Login/registration attempts accepted per rolling minute, store-wide. */
|
|
780
|
+
readonly maxAuthAttemptsPerMinute: number;
|
|
723
781
|
readonly showOtherUsersChats: boolean;
|
|
724
782
|
readonly perUserWorkspace: boolean;
|
|
783
|
+
readonly retention: {
|
|
784
|
+
readonly pruneVanishedSessions: boolean;
|
|
785
|
+
readonly ownershipGraceHours: number;
|
|
786
|
+
readonly sweepIntervalMinutes: number;
|
|
787
|
+
};
|
|
725
788
|
readonly profile: {
|
|
726
789
|
readonly enabled: boolean;
|
|
727
790
|
readonly inject: boolean;
|
|
@@ -757,6 +820,12 @@ export interface ResolvedQaSurfaceConfig {
|
|
|
757
820
|
};
|
|
758
821
|
readonly sources: {
|
|
759
822
|
readonly enabled: boolean;
|
|
823
|
+
readonly retention: {
|
|
824
|
+
readonly maxTurnsPerSession: number;
|
|
825
|
+
readonly maxSessions: number;
|
|
826
|
+
readonly maxAgeDays: number;
|
|
827
|
+
readonly sweepIntervalMinutes: number;
|
|
828
|
+
};
|
|
760
829
|
readonly collect: {
|
|
761
830
|
readonly parentAgent: boolean;
|
|
762
831
|
readonly subagents: boolean;
|
|
@@ -804,6 +873,163 @@ export interface ResolvedQaSurfaceConfig {
|
|
|
804
873
|
readonly extensions: readonly string[];
|
|
805
874
|
};
|
|
806
875
|
}
|
|
876
|
+
/** Which native registry one unified entry came from. */
|
|
877
|
+
export type QaSlashEntryKind = "skill" | "command";
|
|
878
|
+
/** How one half of the catalog admits native entries. */
|
|
879
|
+
export type QaSlashPolicyMode = "deny-all" | "allow-list" | "all";
|
|
880
|
+
export interface QaSlashPolicyConfig {
|
|
881
|
+
readonly mode?: QaSlashPolicyMode;
|
|
882
|
+
readonly allow?: readonly string[];
|
|
883
|
+
}
|
|
884
|
+
export interface QaSlashPaletteConfig {
|
|
885
|
+
readonly enabled?: boolean;
|
|
886
|
+
/** Run the two weakest matcher rungs (substring, subsequence). */
|
|
887
|
+
readonly fuzzySearch?: boolean;
|
|
888
|
+
readonly maxVisible?: number;
|
|
889
|
+
readonly showDescriptions?: boolean;
|
|
890
|
+
readonly showKindBadge?: boolean;
|
|
891
|
+
}
|
|
892
|
+
export interface QaSlashCommandsConfig {
|
|
893
|
+
readonly skills?: QaSlashPolicyConfig;
|
|
894
|
+
readonly commands?: QaSlashPolicyConfig;
|
|
895
|
+
readonly palette?: QaSlashPaletteConfig;
|
|
896
|
+
}
|
|
897
|
+
export interface ResolvedQaSlashCommands {
|
|
898
|
+
/** Mirror of `lockdown.allowSlashCommands`; the one master switch. */
|
|
899
|
+
readonly enabled: boolean;
|
|
900
|
+
readonly skills: {
|
|
901
|
+
readonly mode: QaSlashPolicyMode;
|
|
902
|
+
readonly allow: readonly string[];
|
|
903
|
+
};
|
|
904
|
+
readonly commands: {
|
|
905
|
+
readonly mode: QaSlashPolicyMode;
|
|
906
|
+
readonly allow: readonly string[];
|
|
907
|
+
};
|
|
908
|
+
readonly palette: {
|
|
909
|
+
readonly enabled: boolean;
|
|
910
|
+
readonly fuzzySearch: boolean;
|
|
911
|
+
readonly maxVisible: number;
|
|
912
|
+
readonly showDescriptions: boolean;
|
|
913
|
+
readonly showKindBadge: boolean;
|
|
914
|
+
};
|
|
915
|
+
/**
|
|
916
|
+
* True when the deployment turned the master switch on without declaring a
|
|
917
|
+
* `slashCommands` section: skills then admit every user-invocable skill the
|
|
918
|
+
* session already exposes, commands stay denied. The Host logs it once, so
|
|
919
|
+
* an upgrade cannot silently widen anything.
|
|
920
|
+
*/
|
|
921
|
+
readonly legacyDefaults: boolean;
|
|
922
|
+
}
|
|
923
|
+
/**
|
|
924
|
+
* One palette row. `id` is the routing identity: skill and command may share a
|
|
925
|
+
* name, so identity is `skill:<name>` or `command:<name>` and never the bare
|
|
926
|
+
* name the two halves would collide on.
|
|
927
|
+
*/
|
|
928
|
+
export interface QaSlashCatalogEntry {
|
|
929
|
+
readonly id: string;
|
|
930
|
+
readonly kind: QaSlashEntryKind;
|
|
931
|
+
readonly name: string;
|
|
932
|
+
readonly description: string;
|
|
933
|
+
/** Skill-only: the native `whenToUse`, rendered as secondary copy. */
|
|
934
|
+
readonly whenToUse?: string;
|
|
935
|
+
/** Skill-only: whether the model is also offered this skill. */
|
|
936
|
+
readonly modelInvocable?: boolean;
|
|
937
|
+
/** Command-only: the advertised argument shape. */
|
|
938
|
+
readonly inputHint?: string;
|
|
939
|
+
/** Command-only: whether the executor admits composer attachments. */
|
|
940
|
+
readonly acceptsAttachments?: boolean;
|
|
941
|
+
}
|
|
942
|
+
/**
|
|
943
|
+
* Whether the command half of the catalog could be read. `inactive` is the
|
|
944
|
+
* ordinary state of a cold chat: the native command registry resolves through
|
|
945
|
+
* a live Agent, and a chat with none answers with no commands rather than an
|
|
946
|
+
* error — the palette then offers skills alone.
|
|
947
|
+
*/
|
|
948
|
+
export type QaSlashCommandSurface = "ready" | "unavailable" | "inactive";
|
|
949
|
+
export interface QaSlashCatalog {
|
|
950
|
+
/** False while `lockdown.allowSlashCommands` is off. */
|
|
951
|
+
readonly enabled: boolean;
|
|
952
|
+
readonly entries: readonly QaSlashCatalogEntry[];
|
|
953
|
+
readonly commandSurface: QaSlashCommandSurface;
|
|
954
|
+
/**
|
|
955
|
+
* User-invocable skills of this chat that the deployment or the chat's role
|
|
956
|
+
* withheld from the palette. Naming them is what lets the browser warn about
|
|
957
|
+
* a `/name` typed inside an ordinary prompt — the native gesture path never
|
|
958
|
+
* consults this list, so it is a courtesy, not an authorization.
|
|
959
|
+
*/
|
|
960
|
+
readonly deniedSkills: readonly string[];
|
|
961
|
+
}
|
|
962
|
+
/**
|
|
963
|
+
* One composer attachment offered to a human command. The same two shapes the
|
|
964
|
+
* prompt path uses — an image rides inline, a file rides its staged receipt —
|
|
965
|
+
* because the native executor admits both through one attachment store.
|
|
966
|
+
*/
|
|
967
|
+
export type QaSlashSubmitAttachment = {
|
|
968
|
+
readonly type: "image";
|
|
969
|
+
readonly mediaType: QaImageMediaType;
|
|
970
|
+
readonly data: string;
|
|
971
|
+
readonly name?: string;
|
|
972
|
+
} | {
|
|
973
|
+
readonly type: "file";
|
|
974
|
+
readonly receiptId: string;
|
|
975
|
+
};
|
|
976
|
+
/** Why a command line was refused before, or instead of, running. */
|
|
977
|
+
export type QaSlashRefusal = "slash-disabled" | "unknown-command" | "not-allowed" | "attachments-unsupported" | "inactive-session";
|
|
978
|
+
export type QaSlashCommandOutcome = {
|
|
979
|
+
readonly kind: "success";
|
|
980
|
+
readonly text?: string;
|
|
981
|
+
/** Earlier authoritative event this result is presented from. */
|
|
982
|
+
readonly sourceEventSeq?: number;
|
|
983
|
+
} | {
|
|
984
|
+
readonly kind: "error";
|
|
985
|
+
readonly text: string;
|
|
986
|
+
};
|
|
987
|
+
/**
|
|
988
|
+
* The result of one admitted command. `refused` is an admission decision and
|
|
989
|
+
* costs nothing; `executed` means the native runtime ran the handler and the
|
|
990
|
+
* lifecycle is already in the session log, which is what the transcript row
|
|
991
|
+
* projects.
|
|
992
|
+
*/
|
|
993
|
+
export type QaSlashExecution = {
|
|
994
|
+
readonly kind: "executed";
|
|
995
|
+
readonly commandId: string;
|
|
996
|
+
readonly outcome: QaSlashCommandOutcome;
|
|
997
|
+
} | {
|
|
998
|
+
readonly kind: "refused";
|
|
999
|
+
readonly reason: QaSlashRefusal;
|
|
1000
|
+
/** Host-authored detail; the browser renders its own copy for `reason`. */
|
|
1001
|
+
readonly message: string;
|
|
1002
|
+
};
|
|
1003
|
+
/** One entry of the palette the browser is filtering. */
|
|
1004
|
+
export interface QaSlashView {
|
|
1005
|
+
readonly enabled: boolean;
|
|
1006
|
+
readonly state: "idle" | "loading" | "ready" | "error";
|
|
1007
|
+
readonly entries: readonly QaSlashCatalogEntry[];
|
|
1008
|
+
readonly commandSurface: QaSlashCommandSurface;
|
|
1009
|
+
readonly deniedSkills: readonly string[];
|
|
1010
|
+
/** Set when the catalog could not be read; ordinary prompts keep working. */
|
|
1011
|
+
readonly error: string | null;
|
|
1012
|
+
/**
|
|
1013
|
+
* Bumped when the surface must re-open a palette the user had dismissed —
|
|
1014
|
+
* an ambiguous `/name` is the case that needs it. The composer watches the
|
|
1015
|
+
* counter rather than the message, so a refusal can be re-stated.
|
|
1016
|
+
*/
|
|
1017
|
+
readonly reopen: number;
|
|
1018
|
+
}
|
|
1019
|
+
/**
|
|
1020
|
+
* One human command line projected into the transcript. Commands never enter
|
|
1021
|
+
* the model conversation, so this row is their only visible trace; it is a
|
|
1022
|
+
* control row, not an assistant bubble.
|
|
1023
|
+
*/
|
|
1024
|
+
export interface QaCommandActivity {
|
|
1025
|
+
readonly commandId: string;
|
|
1026
|
+
readonly name: string;
|
|
1027
|
+
/** Verbatim text after the name, with its separator whitespace removed. */
|
|
1028
|
+
readonly args?: string;
|
|
1029
|
+
readonly state: "running" | "success" | "error";
|
|
1030
|
+
readonly resultText?: string;
|
|
1031
|
+
readonly sourceEventSeq?: number;
|
|
1032
|
+
}
|
|
807
1033
|
export interface QaSourceFilePreview {
|
|
808
1034
|
readonly path: string;
|
|
809
1035
|
readonly content: string;
|
|
@@ -878,6 +1104,11 @@ export type QaMessage = QaUserMessage | {
|
|
|
878
1104
|
readonly text: string;
|
|
879
1105
|
readonly status: "info" | "error";
|
|
880
1106
|
readonly timestamp?: number;
|
|
1107
|
+
/**
|
|
1108
|
+
* Set on a human command row. Commands stay out of the model
|
|
1109
|
+
* conversation, so this projection is the only trace the user sees.
|
|
1110
|
+
*/
|
|
1111
|
+
readonly command?: QaCommandActivity;
|
|
881
1112
|
/** Collapsible settlement row (subagent finished/stopped/failed). */
|
|
882
1113
|
readonly notice?: {
|
|
883
1114
|
readonly title: string;
|
|
@@ -1039,6 +1270,8 @@ export interface QaSessionState {
|
|
|
1039
1270
|
readonly approvals: readonly QaPendingApproval[];
|
|
1040
1271
|
/** Question requests parked for the operator's answer, oldest first. */
|
|
1041
1272
|
readonly questions: readonly QaPendingQuestion[];
|
|
1273
|
+
/** Slash palette state, keyed to the chat this snapshot describes. */
|
|
1274
|
+
readonly slash: QaSlashView;
|
|
1042
1275
|
}
|
|
1043
1276
|
/** Minimal server-trusted identity exposed to principal-scoped plugins. */
|
|
1044
1277
|
export interface QaPrincipal {
|
|
@@ -1124,7 +1357,7 @@ export interface QaReviewQueueItem {
|
|
|
1124
1357
|
readonly feedbackId?: string;
|
|
1125
1358
|
}
|
|
1126
1359
|
/** Administrative actions recorded in the audit trail. */
|
|
1127
|
-
export type QaAdminAuditAction = "user.created" | "user.updated" | "user.enabled" | "user.disabled" | "authorization.changed" | "subrole.assignment.changed" | "subrole.created" | "subrole.updated" | "subrole.deleted" | "common_capabilities.updated" | "conversation.reviewed" | "review.updated" | "review.queued" | "admin.settings.updated";
|
|
1360
|
+
export type QaAdminAuditAction = "user.created" | "user.updated" | "user.enabled" | "user.disabled" | "authorization.changed" | "subrole.assignment.changed" | "subrole.created" | "subrole.updated" | "subrole.deleted" | "common_capabilities.updated" | "conversation.reviewed" | "conversation.deleted" | "review.updated" | "review.queued" | "admin.settings.updated";
|
|
1128
1361
|
export interface QaAdminAuditEvent {
|
|
1129
1362
|
readonly id: string;
|
|
1130
1363
|
readonly timestamp: string;
|
|
@@ -1217,6 +1450,17 @@ export interface QaConversationDetail {
|
|
|
1217
1450
|
readonly reviews: readonly QaConversationReview[];
|
|
1218
1451
|
readonly queueItems: readonly QaReviewQueueItem[];
|
|
1219
1452
|
}
|
|
1453
|
+
/** What one administrative deletion removed, for the console to report. */
|
|
1454
|
+
export interface QaConversationDeletion {
|
|
1455
|
+
readonly conversationId: string;
|
|
1456
|
+
/**
|
|
1457
|
+
* Every session whose stored log is gone, the chat first: a conversation's
|
|
1458
|
+
* subagent sessions are part of it and are removed with it.
|
|
1459
|
+
*/
|
|
1460
|
+
readonly sessions: readonly string[];
|
|
1461
|
+
/** Quality rows dropped with the conversation. */
|
|
1462
|
+
readonly qualityRows: number;
|
|
1463
|
+
}
|
|
1220
1464
|
/**
|
|
1221
1465
|
* Server-side filter for the conversation list. Every field is optional and
|
|
1222
1466
|
* accepts an explicit null: the wire carries whatever the browser has, and an
|
|
@@ -1360,7 +1604,12 @@ export interface QaAdminUserDetail {
|
|
|
1360
1604
|
readonly effective: readonly {
|
|
1361
1605
|
readonly subroleId: string;
|
|
1362
1606
|
readonly name: string;
|
|
1607
|
+
/** Visible from the first step: system-required, Common and the role. */
|
|
1363
1608
|
readonly tools: number;
|
|
1609
|
+
/** The role's ceiling for tools a loaded skill requires. */
|
|
1610
|
+
readonly grantableTools: number;
|
|
1611
|
+
/** Tools the profile withdraws, whatever else grants them. */
|
|
1612
|
+
readonly deniedTools: number;
|
|
1364
1613
|
readonly skills: number;
|
|
1365
1614
|
}[];
|
|
1366
1615
|
readonly activity: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yadsh/dsh-qa-surface",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "A focused end-user QA surface backed by native DeepSeek Harness sessions",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
"types": "./lib/types/index.d.ts",
|
|
17
17
|
"bin": {
|
|
18
18
|
"qa-accounts": "./lib/cli.js",
|
|
19
|
-
"qa-repair-sessions": "./scripts/repair-session-events.mjs"
|
|
19
|
+
"qa-repair-sessions": "./scripts/repair-session-events.mjs",
|
|
20
|
+
"qa-attach-sessions": "./scripts/attach-workspace-sessions.mjs"
|
|
20
21
|
},
|
|
21
22
|
"exports": {
|
|
22
23
|
".": {
|
|
@@ -76,6 +77,7 @@
|
|
|
76
77
|
"lib/**/*.js.map",
|
|
77
78
|
"lib/**/*.d.ts",
|
|
78
79
|
"scripts/repair-session-events.mjs",
|
|
80
|
+
"scripts/attach-workspace-sessions.mjs",
|
|
79
81
|
"cordis.patch.yml",
|
|
80
82
|
"compatibility.json",
|
|
81
83
|
"capability-policy.json",
|
|
@@ -131,7 +133,10 @@
|
|
|
131
133
|
"dependencies": {
|
|
132
134
|
"yaml": "^2.9.0",
|
|
133
135
|
"zod": "^4.4.3",
|
|
134
|
-
"@yadsh/dsh-
|
|
136
|
+
"@yadsh/dsh-audit-ui": "^0.1.0",
|
|
137
|
+
"@yadsh/dsh-audit-core": "^0.1.0",
|
|
138
|
+
"@yadsh/dsh-plugin-kit": "^0.3.0",
|
|
139
|
+
"@yadsh/dsh-plugin-log": "^0.4.0"
|
|
135
140
|
},
|
|
136
141
|
"devDependencies": {
|
|
137
142
|
"@deepseek-ai/cordis": "4.0.2",
|
|
@@ -175,8 +180,7 @@
|
|
|
175
180
|
"typescript": "^7.0.2",
|
|
176
181
|
"vitest": "^4.1.11",
|
|
177
182
|
"@yadsh/dsh-config": "^0.0.0",
|
|
178
|
-
"@yadsh/dsh-plugin-scripts": "^0.0.0"
|
|
179
|
-
"@yadsh/dsh-plugin-kit": "^0.1.0"
|
|
183
|
+
"@yadsh/dsh-plugin-scripts": "^0.0.0"
|
|
180
184
|
},
|
|
181
185
|
"publishConfig": {
|
|
182
186
|
"access": "public",
|