@yadsh/dsh-qa-surface 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +84 -1
- package/README.md +87 -12
- package/compatibility.json +11 -3
- package/docs/ARCHITECTURE.md +1 -1
- package/docs/COMPATIBILITY.md +1 -1
- package/docs/CONFIGURATION.md +88 -1
- package/docs/SOURCES-MIGRATION.md +28 -0
- package/docs/SOURCES-PROVENANCE-AUDIT.md +88 -0
- package/docs/SPEC-dsh-qa-surface-accounts.md +219 -0
- package/docs/SPEC-dsh-qa-surface-sources-provenance.md +1692 -0
- package/lib/accounts/index.js +2 -0
- package/lib/accounts/index.js.map +1 -0
- package/lib/accounts/store.js +478 -0
- package/lib/accounts/store.js.map +1 -0
- package/lib/attestation.js.map +1 -1
- package/lib/cli.js +143 -0
- package/lib/cli.js.map +1 -0
- package/lib/client/QaAccountsController.js +329 -0
- package/lib/client/QaAccountsController.js.map +1 -0
- package/lib/client/QaSessionController.js +203 -127
- package/lib/client/QaSessionController.js.map +1 -1
- package/lib/client/QaSurface.js +234 -72
- package/lib/client/QaSurface.js.map +1 -1
- package/lib/client/QaTranscriptAdapter.js +27 -241
- package/lib/client/QaTranscriptAdapter.js.map +1 -1
- package/lib/client/attestation.js +6 -0
- package/lib/client/attestation.js.map +1 -1
- package/lib/client/components/Markdown.js +54 -13
- package/lib/client/components/Markdown.js.map +1 -1
- package/lib/client/components/QaAuthGate.js +40 -0
- package/lib/client/components/QaAuthGate.js.map +1 -0
- package/lib/client/components/QaChangelog.js +112 -0
- package/lib/client/components/QaChangelog.js.map +1 -0
- package/lib/client/components/QaMessage.js +47 -17
- package/lib/client/components/QaMessage.js.map +1 -1
- package/lib/client/components/QaSidebar.js +63 -20
- package/lib/client/components/QaSidebar.js.map +1 -1
- package/lib/client/components/QaSourcesDrawer.js +113 -32
- package/lib/client/components/QaSourcesDrawer.js.map +1 -1
- package/lib/client/components/QaTurnRail.js +281 -0
- package/lib/client/components/QaTurnRail.js.map +1 -0
- package/lib/client/components/QaWelcomeNotice.js +125 -0
- package/lib/client/components/QaWelcomeNotice.js.map +1 -0
- package/lib/client/components/QaWidthHandle.js +142 -0
- package/lib/client/components/QaWidthHandle.js.map +1 -0
- package/lib/client/components/source-refs.js +78 -0
- package/lib/client/components/source-refs.js.map +1 -0
- package/lib/client/create-session.js +51 -0
- package/lib/client/create-session.js.map +1 -0
- package/lib/client/index.js +100 -12
- package/lib/client/index.js.map +1 -1
- package/lib/client/project-session-state.js +78 -0
- package/lib/client/project-session-state.js.map +1 -0
- package/lib/client/session-admission.js +38 -0
- package/lib/client/session-admission.js.map +1 -0
- package/lib/client/session-assets.js +52 -0
- package/lib/client/session-assets.js.map +1 -0
- package/lib/client/session-sources.js +61 -0
- package/lib/client/session-sources.js.map +1 -0
- package/lib/client/settlement.js +24 -0
- package/lib/client/settlement.js.map +1 -0
- package/lib/client/styles.js +151 -9
- package/lib/client/styles.js.map +1 -1
- package/lib/client/tool-presentation.js +102 -0
- package/lib/client/tool-presentation.js.map +1 -0
- package/lib/client/turn-sources.js +98 -0
- package/lib/client/turn-sources.js.map +1 -0
- package/lib/client/types.js +2 -0
- package/lib/client/types.js.map +1 -1
- package/lib/client/use-session-ui-state.js +68 -0
- package/lib/client/use-session-ui-state.js.map +1 -0
- package/lib/client/use-transcript-view.js +44 -0
- package/lib/client/use-transcript-view.js.map +1 -0
- package/lib/client.js +4649 -861
- package/lib/client.js.map +1 -1
- package/lib/config.js +218 -102
- package/lib/config.js.map +1 -1
- package/lib/entry-redirect.js +44 -0
- package/lib/entry-redirect.js.map +1 -0
- package/lib/host-route.js +25 -1
- package/lib/host-route.js.map +1 -1
- package/lib/index.js +209 -23
- package/lib/index.js.map +1 -1
- package/lib/launch-token.js +42 -0
- package/lib/launch-token.js.map +1 -0
- package/lib/provenance/collector.js +40 -0
- package/lib/provenance/collector.js.map +1 -0
- package/lib/provenance/connectors.js +147 -0
- package/lib/provenance/connectors.js.map +1 -0
- package/lib/provenance/dedupe.js +89 -0
- package/lib/provenance/dedupe.js.map +1 -0
- package/lib/provenance/extractors.js +340 -0
- package/lib/provenance/extractors.js.map +1 -0
- package/lib/provenance/file-preview.js +39 -0
- package/lib/provenance/file-preview.js.map +1 -0
- package/lib/provenance/host-store.js +387 -0
- package/lib/provenance/host-store.js.map +1 -0
- package/lib/provenance/index.js +9 -0
- package/lib/provenance/index.js.map +1 -0
- package/lib/provenance/normalize.js +128 -0
- package/lib/provenance/normalize.js.map +1 -0
- package/lib/provenance/reported.js +53 -0
- package/lib/provenance/reported.js.map +1 -0
- package/lib/provenance/types.js +2 -0
- package/lib/provenance/types.js.map +1 -0
- package/lib/resolve-config.js +161 -0
- package/lib/resolve-config.js.map +1 -1
- package/lib/secure-session.js +50 -8
- package/lib/secure-session.js.map +1 -1
- package/lib/typert.host.js +599 -6
- package/lib/typert.remote-client.d.ts +19 -3
- package/lib/typert.remote-client.js +471 -3
- package/lib/types/accounts/index.d.ts +2 -0
- package/lib/types/accounts/store.d.ts +121 -0
- package/lib/types/attestation.d.ts +1 -1
- package/lib/types/cli.d.ts +9 -0
- package/lib/types/client/QaAccountsController.d.ts +95 -0
- package/lib/types/client/QaConfigController.d.ts +1 -1
- package/lib/types/client/QaSessionController.d.ts +46 -7
- package/lib/types/client/QaSurface.d.ts +8 -3
- package/lib/types/client/QaTranscriptAdapter.d.ts +5 -10
- package/lib/types/client/components/Markdown.d.ts +11 -1
- package/lib/types/client/components/QaAgentsDrawer.d.ts +1 -1
- package/lib/types/client/components/QaAuthGate.d.ts +15 -0
- package/lib/types/client/components/QaChangelog.d.ts +21 -0
- package/lib/types/client/components/QaMessage.d.ts +10 -3
- package/lib/types/client/components/QaSidebar.d.ts +30 -2
- package/lib/types/client/components/QaSourcesDrawer.d.ts +15 -3
- package/lib/types/client/components/QaTurnRail.d.ts +59 -0
- package/lib/types/client/components/QaWelcomeNotice.d.ts +27 -0
- package/lib/types/client/components/QaWidthHandle.d.ts +36 -0
- package/lib/types/client/components/source-refs.d.ts +16 -0
- package/lib/types/client/create-session.d.ts +16 -0
- package/lib/types/client/index.d.ts +1 -0
- package/lib/types/client/project-session-state.d.ts +30 -0
- package/lib/types/client/session-admission.d.ts +23 -0
- package/lib/types/client/session-assets.d.ts +20 -0
- package/lib/types/client/session-sources.d.ts +28 -0
- package/lib/types/client/settlement.d.ts +6 -0
- package/lib/types/client/tool-presentation.d.ts +6 -0
- package/lib/types/client/turn-sources.d.ts +14 -0
- package/lib/types/client/types.d.ts +73 -9
- package/lib/types/client/use-session-ui-state.d.ts +35 -0
- package/lib/types/client/use-transcript-view.d.ts +20 -0
- package/lib/types/entry-redirect.d.ts +20 -0
- package/lib/types/host-route.d.ts +14 -1
- package/lib/types/index.d.ts +47 -3
- package/lib/types/launch-token.d.ts +21 -0
- package/lib/types/provenance/collector.d.ts +26 -0
- package/lib/types/provenance/connectors.d.ts +11 -0
- package/lib/types/provenance/dedupe.d.ts +6 -0
- package/lib/types/provenance/extractors.d.ts +14 -0
- package/lib/types/provenance/file-preview.d.ts +10 -0
- package/lib/types/provenance/host-store.d.ts +54 -0
- package/lib/types/provenance/index.d.ts +10 -0
- package/lib/types/provenance/normalize.d.ts +13 -0
- package/lib/types/provenance/reported.d.ts +5 -0
- package/lib/types/provenance/types.d.ts +78 -0
- package/lib/types/secure-session.d.ts +11 -2
- package/lib/types/types.d.ts +167 -11
- package/package.json +58 -41
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import type { QaAccountRole, QaAccountSession, QaAccountUserPublic, QaClaimResult, QaOwnershipEntry, QaWhoamiResult } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Coarse, wire-safe account failure codes. They ride the `(reason: <code>)`
|
|
4
|
+
* marker pattern the attestation path established; the browser maps them to
|
|
5
|
+
* audience-safe copy and the precise cause stays in the Host logs.
|
|
6
|
+
*/
|
|
7
|
+
export type QaAccountsErrorReason = "auth-required" | "admin-required" | "invalid-credentials" | "account-disabled" | "email-taken" | "invalid-email" | "invalid-display-name" | "invalid-role" | "weak-password" | "registration-disabled" | "rate-limited" | "session-owned-elsewhere";
|
|
8
|
+
export declare class QaAccountsError extends Error {
|
|
9
|
+
readonly reason: QaAccountsErrorReason;
|
|
10
|
+
constructor(reason: QaAccountsErrorReason, message: string);
|
|
11
|
+
}
|
|
12
|
+
interface StoredUser {
|
|
13
|
+
readonly id: string;
|
|
14
|
+
readonly email: string;
|
|
15
|
+
readonly displayName: string;
|
|
16
|
+
readonly role: QaAccountRole;
|
|
17
|
+
/** scrypt material: hex salt + hex hash. */
|
|
18
|
+
readonly passwordHash: {
|
|
19
|
+
readonly salt: string;
|
|
20
|
+
readonly hash: string;
|
|
21
|
+
};
|
|
22
|
+
readonly createdAt: string;
|
|
23
|
+
lastLoginAt: string | null;
|
|
24
|
+
/** Disabled accounts are refused at login and lose their live tokens. */
|
|
25
|
+
disabled?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Bumped to invalidate every token ever issued to the account: the value
|
|
28
|
+
* rides the token payload and must match at verification time.
|
|
29
|
+
*/
|
|
30
|
+
tokenVersion?: number;
|
|
31
|
+
}
|
|
32
|
+
export interface QaAccountsOptions {
|
|
33
|
+
readonly sessionTtlDays: number;
|
|
34
|
+
readonly allowRegistration: boolean;
|
|
35
|
+
/** Login/registration attempts accepted per rolling minute, store-wide. */
|
|
36
|
+
readonly maxAuthAttemptsPerMinute?: number;
|
|
37
|
+
}
|
|
38
|
+
/** The accounts file lives next to the DSH home the launcher exports. */
|
|
39
|
+
export declare function defaultAccountsFilePath(): string;
|
|
40
|
+
/**
|
|
41
|
+
* Host authority for QA accounts: the file-backed user list, the session
|
|
42
|
+
* ownership map and the HMAC account tokens. All mutations are synchronous
|
|
43
|
+
* and persisted atomically (temp file + rename); LAN scale keeps this trivial.
|
|
44
|
+
*/
|
|
45
|
+
export declare class QaAccounts {
|
|
46
|
+
readonly filePath: string;
|
|
47
|
+
private file;
|
|
48
|
+
private readonly authAttempts;
|
|
49
|
+
private readonly maxAuthAttemptsPerMinute;
|
|
50
|
+
private readonly sessionTtlDays;
|
|
51
|
+
private readonly allowRegistration;
|
|
52
|
+
/** mtime+size of the file as of the last load; the external-change probe. */
|
|
53
|
+
private lastLoadStamp;
|
|
54
|
+
constructor(filePath: string | undefined, options: QaAccountsOptions);
|
|
55
|
+
/**
|
|
56
|
+
* The qa-accounts CLI runs in its own process against the same file. Re-read
|
|
57
|
+
* it whenever it changed on disk, before every read or read-modify-write:
|
|
58
|
+
* without this a running Host would keep honoring tokens the CLI revoked
|
|
59
|
+
* and its next save would resurrect the CLI's change from a stale snapshot.
|
|
60
|
+
* One file, one writer at a time remains the deployment's discipline; LAN
|
|
61
|
+
* scale keeps the stat per operation trivial.
|
|
62
|
+
*/
|
|
63
|
+
private reloadIfChanged;
|
|
64
|
+
private load;
|
|
65
|
+
private persist;
|
|
66
|
+
private save;
|
|
67
|
+
private pruneAuthAttempts;
|
|
68
|
+
private assertAuthBudget;
|
|
69
|
+
private userByEmail;
|
|
70
|
+
register(email: string, password: string, displayName?: string): QaAccountSession;
|
|
71
|
+
login(email: string, password: string): QaAccountSession;
|
|
72
|
+
whoami(token: string): QaWhoamiResult;
|
|
73
|
+
/** Resolve a token to its user, or null for absent/invalid/expired ones. */
|
|
74
|
+
verifyToken(token: string): string | null;
|
|
75
|
+
private mintToken;
|
|
76
|
+
/** The account behind a token, or an auth-required refusal. */
|
|
77
|
+
requireUser(token: string): StoredUser;
|
|
78
|
+
/**
|
|
79
|
+
* Ownership gate for one session: claim unowned sessions for the requesting
|
|
80
|
+
* user (first come, first served — the pre-accounts migration path), refuse
|
|
81
|
+
* foreign sessions unless the caller administers the deployment.
|
|
82
|
+
*/
|
|
83
|
+
ensureSessionAccess(token: string, sessionId: string): QaAccountUserPublic;
|
|
84
|
+
/** Bulk-claim a browser's local chat index; foreign ids come back as conflicts. */
|
|
85
|
+
claimSessions(token: string, sessionIds: readonly string[]): QaClaimResult;
|
|
86
|
+
/** Session ids owned by the token's user, most recently claimed first. */
|
|
87
|
+
ownedSessionIds(token: string): readonly string[];
|
|
88
|
+
/**
|
|
89
|
+
* Every ownership entry with the owner's display name resolved at read
|
|
90
|
+
* time, oldest claim first. Admin-only: this is the cross-user view the
|
|
91
|
+
* admin sidebar groups chats by; ordinary accounts get a dedicated refusal.
|
|
92
|
+
*/
|
|
93
|
+
listOwnership(token: string): readonly QaOwnershipEntry[];
|
|
94
|
+
/** Every account, file order; for `qa-accounts list`. */
|
|
95
|
+
listUsers(): readonly {
|
|
96
|
+
readonly email: string;
|
|
97
|
+
readonly displayName: string;
|
|
98
|
+
readonly role: QaAccountRole;
|
|
99
|
+
readonly disabled: boolean;
|
|
100
|
+
readonly createdAt: string;
|
|
101
|
+
readonly lastLoginAt: string | null;
|
|
102
|
+
}[];
|
|
103
|
+
/** Create an account outside the self-registration gate. */
|
|
104
|
+
addUser(email: string, password: string, options?: {
|
|
105
|
+
displayName?: string;
|
|
106
|
+
role?: QaAccountRole;
|
|
107
|
+
}): QaAccountUserPublic;
|
|
108
|
+
private editUser;
|
|
109
|
+
/** Grant or revoke the admin role. */
|
|
110
|
+
setUserRole(email: string, role: QaAccountRole): QaAccountUserPublic;
|
|
111
|
+
/**
|
|
112
|
+
* Disable an account: future logins are refused and every live token is
|
|
113
|
+
* invalidated (the token version bumps). `enable` does not resurrect old
|
|
114
|
+
* tokens — the account signs in again.
|
|
115
|
+
*/
|
|
116
|
+
setUserDisabled(email: string, disabled: boolean): QaAccountUserPublic;
|
|
117
|
+
/** Invalidate every token of the account (password-leak response). */
|
|
118
|
+
revokeTokens(email: string): QaAccountUserPublic;
|
|
119
|
+
}
|
|
120
|
+
export {};
|
|
121
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* audience, precise enough for an operator reading the browser console to
|
|
9
9
|
* know which class of mismatch to look for in the Host logs.
|
|
10
10
|
*/
|
|
11
|
-
export type QaAttestationReason = "agent-unavailable" | "workspace-unavailable" | "composition-mismatch" | "permission-preset" | "adoption-refused" | "unknown-tools" | "attestation-failed";
|
|
11
|
+
export type QaAttestationReason = "agent-unavailable" | "workspace-unavailable" | "composition-mismatch" | "permission-preset" | "adoption-refused" | "unknown-tools" | "auth-required" | "session-owned-elsewhere" | "attestation-failed";
|
|
12
12
|
/** Host rejection whose wire message carries the coarse reason marker. */
|
|
13
13
|
export declare class QaAttestationError extends Error {
|
|
14
14
|
readonly reason: QaAttestationReason;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
export interface CliIo {
|
|
3
|
+
out(line: string): void;
|
|
4
|
+
err(line: string): void;
|
|
5
|
+
}
|
|
6
|
+
/** Execute one management command; returns the process exit code. */
|
|
7
|
+
export declare function run(argv: readonly string[], io: CliIo, readPassword?: () => string): number;
|
|
8
|
+
export declare function main(argv: readonly string[], io?: CliIo, readPassword?: () => string): number;
|
|
9
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { QaAccountUserPublic, QaOwnershipEntry, ResolvedQaSurfaceConfig } from "../types.js";
|
|
2
|
+
import type { QaAccountsApi, StorageLike } from "./types.js";
|
|
3
|
+
export type QaAccountsSnapshot = {
|
|
4
|
+
readonly stage: "checking";
|
|
5
|
+
} | {
|
|
6
|
+
readonly stage: "gate";
|
|
7
|
+
readonly mode: "login" | "register";
|
|
8
|
+
readonly busy: boolean;
|
|
9
|
+
readonly error: string | null;
|
|
10
|
+
} | {
|
|
11
|
+
readonly stage: "authed";
|
|
12
|
+
readonly user: QaAccountUserPublic;
|
|
13
|
+
/**
|
|
14
|
+
* Server-known chat ids; the sidebar list authority. Own chats always,
|
|
15
|
+
* plus every mapped chat for an admin (the cross-user grouping view).
|
|
16
|
+
*/
|
|
17
|
+
readonly ownedIds: readonly string[];
|
|
18
|
+
/**
|
|
19
|
+
* The full ownership map; admins only, empty for ordinary accounts and
|
|
20
|
+
* whenever the admin listing was refused or unavailable.
|
|
21
|
+
*/
|
|
22
|
+
readonly ownership: readonly QaOwnershipEntry[];
|
|
23
|
+
/** Bumped whenever ownedIds or ownership changes; re-projects lists. */
|
|
24
|
+
readonly ownedRevision: number;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Audience-safe copy for the coarse account refusal codes; anything unknown
|
|
28
|
+
* falls back to the generic line.
|
|
29
|
+
*/
|
|
30
|
+
export declare function accountsErrorMessage(code: string | null): string;
|
|
31
|
+
/** Extract the coarse account reason code from a Host wire failure. */
|
|
32
|
+
export declare function accountsReasonOf(failure: unknown): string | null;
|
|
33
|
+
export interface QaAccountsControllerOptions {
|
|
34
|
+
readonly remote: QaAccountsApi;
|
|
35
|
+
readonly storage: StorageLike | undefined;
|
|
36
|
+
/** Config snapshot getter; the token key follows the deployment identity. */
|
|
37
|
+
readonly config: () => ResolvedQaSurfaceConfig;
|
|
38
|
+
/**
|
|
39
|
+
* The legacy per-browser chat index at login time, for the one-shot
|
|
40
|
+
* ownership migration; conflicts are dropped through {@link forgetChat}.
|
|
41
|
+
*/
|
|
42
|
+
readonly legacyChatIds?: () => readonly string[];
|
|
43
|
+
readonly forgetChat?: (sessionId: string) => void;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Browser-side account lifecycle: token persistence, the checking → gate →
|
|
47
|
+
* authed state machine, and the ownership bookkeeping the sidebar list is
|
|
48
|
+
* built from. Anonymous/failed identity never blocks a deployment with
|
|
49
|
+
* accounts disabled — the caller simply does not mount this controller.
|
|
50
|
+
*/
|
|
51
|
+
export declare class QaAccountsController {
|
|
52
|
+
private readonly options;
|
|
53
|
+
private readonly listeners;
|
|
54
|
+
private snapshot;
|
|
55
|
+
private tokenValue;
|
|
56
|
+
private disposed;
|
|
57
|
+
constructor(options: QaAccountsControllerOptions);
|
|
58
|
+
getSnapshot: () => QaAccountsSnapshot;
|
|
59
|
+
subscribe: (listener: () => void) => (() => void);
|
|
60
|
+
dispose(): void;
|
|
61
|
+
/** The bearer token threaded into gated remotes; null while anonymous. */
|
|
62
|
+
/** The bearer token threaded into gated remotes; null while anonymous. */
|
|
63
|
+
token(): string | null;
|
|
64
|
+
/** Server-owned chat ids (empty until authed); falls back to nothing. */
|
|
65
|
+
ownedIds(): readonly string[];
|
|
66
|
+
/** Boot probe: restore the stored token and ask the Host who it is. */
|
|
67
|
+
start(): Promise<void>;
|
|
68
|
+
login(email: string, password: string): Promise<void>;
|
|
69
|
+
register(email: string, password: string): Promise<void>;
|
|
70
|
+
setMode(mode: "login" | "register"): void;
|
|
71
|
+
/** Drop the token and return to the gate (logout or expired identity). */
|
|
72
|
+
signOut(): void;
|
|
73
|
+
/** Claim one freshly created chat so the ownership map stays current. */
|
|
74
|
+
claimNewSession(sessionId: string): Promise<void>;
|
|
75
|
+
private authenticate;
|
|
76
|
+
/** Own the account, migrate the legacy index, then project authed. */
|
|
77
|
+
private enterSession;
|
|
78
|
+
/** Refresh the owned list after index changes; cheap enough to re-pull. */
|
|
79
|
+
refreshOwned(): Promise<void>;
|
|
80
|
+
/** The admin cross-user ownership view; failures degrade to an empty map. */
|
|
81
|
+
private fetchOwnership;
|
|
82
|
+
/** Session id → owner display name; empty unless an admin is signed in. */
|
|
83
|
+
ownerNames(): ReadonlyMap<string, string>;
|
|
84
|
+
/**
|
|
85
|
+
* The chat owner's display name for author labels: admins see it on
|
|
86
|
+
* foreign chats only; the owner themself and ordinary accounts see none.
|
|
87
|
+
*/
|
|
88
|
+
messageAuthorOf(sessionId: string): string | undefined;
|
|
89
|
+
private readStoredToken;
|
|
90
|
+
private saveStoredToken;
|
|
91
|
+
private clearStoredToken;
|
|
92
|
+
private tokenKey;
|
|
93
|
+
private publish;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=QaAccountsController.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SettingsScope } from "@deepseek-ai/dsh-client-
|
|
1
|
+
import type { SettingsScope } from "@deepseek-ai/dsh-client-ui-settings/client";
|
|
2
2
|
import type { QaSurfaceConfig, ResolvedQaSurfaceConfig } from "../types.js";
|
|
3
3
|
export interface QaConfigSnapshot {
|
|
4
4
|
readonly status: "loading" | "ready" | "unavailable" | "error";
|
|
@@ -1,13 +1,33 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ConnectionGenerationState } from "@deepseek-ai/dsh-client-connection/client";
|
|
2
2
|
import type { QaImageDraft, QaSessionState, ResolvedQaSurfaceConfig } from "../types.js";
|
|
3
|
-
import type { QaSecureSession, QaSessions, QaSessionsApi, StorageLike } from "./types.js";
|
|
3
|
+
import type { QaConversation, QaSecureSession, QaSessions, QaSessionsApi, QaSourceApi, StorageLike } from "./types.js";
|
|
4
|
+
export interface QaAccountsFacade {
|
|
5
|
+
/** The account bearer token, or null while anonymous. */
|
|
6
|
+
readonly token: () => string | null;
|
|
7
|
+
/** Server-owned chat ids; the list authority while accounts are on. */
|
|
8
|
+
readonly ownedIds: () => readonly string[];
|
|
9
|
+
/**
|
|
10
|
+
* The chat owner's display name for author labels; admins see it on
|
|
11
|
+
* foreign chats only, everyone else gets undefined.
|
|
12
|
+
*/
|
|
13
|
+
readonly messageAuthorOf: (sessionId: string) => string | undefined;
|
|
14
|
+
/** Called after a new chat binds, so ownership stays current. */
|
|
15
|
+
readonly onSessionCreated: (sessionId: string) => void;
|
|
16
|
+
/** Called when the Host refuses with auth-required (expired/rotated). */
|
|
17
|
+
readonly onAuthRequired: () => void;
|
|
18
|
+
}
|
|
4
19
|
export interface QaSessionControllerOptions {
|
|
5
20
|
readonly sessions: QaSessions;
|
|
6
21
|
readonly api: QaSessionsApi;
|
|
7
|
-
|
|
22
|
+
/** Conversation assembly feeding the transcript projection. */
|
|
23
|
+
readonly conversation: QaConversation;
|
|
24
|
+
readonly connection: ConnectionGenerationState;
|
|
8
25
|
readonly config: ResolvedQaSurfaceConfig;
|
|
9
26
|
readonly secureSession: QaSecureSession;
|
|
27
|
+
readonly sourceApi?: QaSourceApi;
|
|
10
28
|
readonly storage?: StorageLike;
|
|
29
|
+
/** Present while the deployment gates QA users with accounts. */
|
|
30
|
+
readonly accounts?: QaAccountsFacade;
|
|
11
31
|
readonly timeoutMs?: number;
|
|
12
32
|
/**
|
|
13
33
|
* Minimum spacing between projections of a running turn's stream frames.
|
|
@@ -26,15 +46,22 @@ export declare class QaSessionController {
|
|
|
26
46
|
private readonly listeners;
|
|
27
47
|
private readonly sessions;
|
|
28
48
|
private readonly api;
|
|
49
|
+
private readonly conversation;
|
|
29
50
|
private readonly connection;
|
|
30
51
|
private readonly config;
|
|
31
52
|
private readonly secureSessionRemote;
|
|
53
|
+
private readonly sourceApi;
|
|
32
54
|
private readonly chats;
|
|
55
|
+
private readonly accounts;
|
|
56
|
+
/** Per-chat attachment URL cache; blob URLs die with the chat binding. */
|
|
57
|
+
private readonly assets;
|
|
33
58
|
private readonly timeoutMs;
|
|
34
59
|
private readonly streamIntervalMs;
|
|
35
60
|
private state;
|
|
36
61
|
private session;
|
|
62
|
+
private conversationBinding;
|
|
37
63
|
private unsubscribeSession;
|
|
64
|
+
private unsubscribeChat;
|
|
38
65
|
private readonly unsubscribeConnection;
|
|
39
66
|
private ensuring;
|
|
40
67
|
private materializing;
|
|
@@ -50,6 +77,8 @@ export declare class QaSessionController {
|
|
|
50
77
|
private disposed;
|
|
51
78
|
private generation;
|
|
52
79
|
private chatsRevision;
|
|
80
|
+
/** Host-side provenance of the bound chat, merged into the projection. */
|
|
81
|
+
private readonly hostSources;
|
|
53
82
|
constructor(options: QaSessionControllerOptions);
|
|
54
83
|
getSnapshot: () => QaSessionState;
|
|
55
84
|
subscribe: (listener: () => void) => (() => void);
|
|
@@ -93,15 +122,19 @@ export declare class QaSessionController {
|
|
|
93
122
|
viewSubagent(id: string, title: string): Promise<void>;
|
|
94
123
|
/** Leave the subagent transcript and re-open the chat it was launched from. */
|
|
95
124
|
closeSubagent(): Promise<void>;
|
|
96
|
-
/** This browser's
|
|
125
|
+
/** This browser's chat ids: the owned list when accounts are on, else the
|
|
126
|
+
* local index. Both intersect the host session list at projection time. */
|
|
97
127
|
chatIds(): readonly string[];
|
|
98
128
|
/** The bound session id, or null while no chat is bound. */
|
|
99
129
|
activeSessionId(): string | null;
|
|
100
130
|
/**
|
|
101
131
|
* Resolve one durable image attachment of the bound session into a
|
|
102
|
-
* browser-usable URL.
|
|
132
|
+
* browser-usable URL. Resolutions are cached per chat in the asset
|
|
133
|
+
* repository (attachment ids repeat across chats) and revoked when the chat
|
|
134
|
+
* is unbound; failures surface as broken views and retry on demand.
|
|
103
135
|
*/
|
|
104
136
|
readImage(attachmentId: string): Promise<string>;
|
|
137
|
+
private readAttachmentUrl;
|
|
105
138
|
/**
|
|
106
139
|
* Remove one chat from this browser's index. Deleting the chat that is
|
|
107
140
|
* currently open also forgets the persisted id and starts a fresh attested
|
|
@@ -120,10 +153,10 @@ export declare class QaSessionController {
|
|
|
120
153
|
* re-opening re-materializes it. Step 2 — when that refused session is
|
|
121
154
|
* still blank (it never received the prompt, so there is nothing to lose) —
|
|
122
155
|
* starts a fresh attested session instead. A session with history is left
|
|
123
|
-
* alone: recreating it would silently drop the conversation.
|
|
156
|
+
* alone: recreating it would silently drop the conversation. Returns the
|
|
157
|
+
* attested session id, or null when nothing was attested.
|
|
124
158
|
*/
|
|
125
159
|
private recoverForSend;
|
|
126
|
-
private createSession;
|
|
127
160
|
private bind;
|
|
128
161
|
private unbind;
|
|
129
162
|
private waitForConnection;
|
|
@@ -140,6 +173,12 @@ export declare class QaSessionController {
|
|
|
140
173
|
private clearStreamFlush;
|
|
141
174
|
private publish;
|
|
142
175
|
private fail;
|
|
176
|
+
/**
|
|
177
|
+
* Attest the currently bound session. `ok` carries the session id the proof
|
|
178
|
+
* was issued for; `stale` means the binding changed while the request was
|
|
179
|
+
* in flight, so nothing was written — the newer binding manages its own
|
|
180
|
+
* attestation; `refused` is a genuine admission refusal of this binding.
|
|
181
|
+
*/
|
|
143
182
|
private attestPolicy;
|
|
144
183
|
private emit;
|
|
145
184
|
}
|
|
@@ -1,15 +1,20 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ConnectionGenerationState } from "@deepseek-ai/dsh-client-connection/client";
|
|
2
2
|
import type { InjectFace, PropsRuntime } from "@deepseek-ai/dsh-client-ui-slots";
|
|
3
3
|
import type { QaConfigController } from "./QaConfigController.js";
|
|
4
4
|
import type { QaRouteController } from "./QaRouteController.js";
|
|
5
|
-
import type {
|
|
5
|
+
import type { QaAccountsController } from "./QaAccountsController.js";
|
|
6
|
+
import type { QaConversation, QaSecureSession, QaSessions, QaSessionsApi, QaSourceApi } from "./types.js";
|
|
6
7
|
export interface QaSurfaceFace {
|
|
7
8
|
readonly route: QaRouteController;
|
|
8
9
|
readonly config: QaConfigController;
|
|
9
10
|
readonly sessions: QaSessions;
|
|
11
|
+
readonly conversation: QaConversation;
|
|
10
12
|
readonly api: QaSessionsApi;
|
|
11
|
-
readonly connection:
|
|
13
|
+
readonly connection: ConnectionGenerationState;
|
|
12
14
|
readonly secureSession: QaSecureSession;
|
|
15
|
+
readonly sourceApi: QaSourceApi;
|
|
16
|
+
/** Present when the deployment mounts the QA account gate. */
|
|
17
|
+
readonly accounts?: QaAccountsController;
|
|
13
18
|
}
|
|
14
19
|
type QaSurfaceProps = PropsRuntime<"shell.overlay"> & InjectFace<QaSurfaceFace>;
|
|
15
20
|
export declare function QaSurface(props: QaSurfaceProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { ConversationSnapshot } from "@deepseek-ai/dsh-client-
|
|
2
|
-
import type { QaMessage
|
|
1
|
+
import type { ConversationSnapshot } from "@deepseek-ai/dsh-client-ui-conversation/client";
|
|
2
|
+
import type { QaMessage } from "../types.js";
|
|
3
3
|
/**
|
|
4
4
|
* The hidden regeneration prompt. Regenerate sends this as an ordinary
|
|
5
5
|
* prompt — the session has no truncation seam, so a "variant" is a real
|
|
@@ -8,15 +8,10 @@ import type { QaMessage, QaSource } from "../types.js";
|
|
|
8
8
|
*/
|
|
9
9
|
export declare const QA_REGENERATE_MARKER = "\u041F\u0435\u0440\u0435\u0433\u0435\u043D\u0435\u0440\u0438\u0440\u0443\u0439 \u0441\u0432\u043E\u0439 \u043F\u0440\u0435\u0434\u044B\u0434\u0443\u0449\u0438\u0439 \u043E\u0442\u0432\u0435\u0442 \u2014 \u0434\u0430\u0439 \u043D\u043E\u0432\u044B\u0439 \u0432\u0430\u0440\u0438\u0430\u043D\u0442, \u043D\u0435 \u043F\u043E\u0432\u0442\u043E\u0440\u044F\u044F \u043F\u0440\u0435\u0434\u044B\u0434\u0443\u0449\u0438\u0439.";
|
|
10
10
|
/** Project end-user messages plus optional operator-approved work detail. */
|
|
11
|
-
export declare function projectTranscript(snapshot: ConversationSnapshot, options?: {
|
|
11
|
+
export declare function projectTranscript(snapshot: ConversationSnapshot | undefined, options?: {
|
|
12
|
+
/** Live turn lifecycle from the bound Session (drives running-row status). */
|
|
13
|
+
readonly running?: boolean;
|
|
12
14
|
readonly showToolActivity?: boolean;
|
|
13
15
|
readonly showReasoning?: boolean;
|
|
14
16
|
}): readonly QaMessage[];
|
|
15
|
-
/**
|
|
16
|
-
* Collect the sources this chat has actually touched, in first-use order:
|
|
17
|
-
* fetched pages, searches, and files read. This is the same tool activity the
|
|
18
|
-
* work groups render, projected as a flat citation-style list, so it carries
|
|
19
|
-
* no information beyond `ui.showToolActivity`.
|
|
20
|
-
*/
|
|
21
|
-
export declare function projectSources(snapshot: ConversationSnapshot): readonly QaSource[];
|
|
22
17
|
//# sourceMappingURL=QaTranscriptAdapter.d.ts.map
|
|
@@ -1,9 +1,19 @@
|
|
|
1
|
+
import type { QaSource } from "../../types.js";
|
|
2
|
+
import { type QaSourceRefs } from "./source-refs.js";
|
|
3
|
+
/** Inline source awareness handed down from the owning assistant message. */
|
|
4
|
+
export interface MarkdownSourceContext {
|
|
5
|
+
readonly refs?: QaSourceRefs;
|
|
6
|
+
/** Open a path-backed source in the sources drawer's detail view. */
|
|
7
|
+
readonly onSourceOpen?: (source: QaSource) => void;
|
|
8
|
+
}
|
|
1
9
|
/**
|
|
2
10
|
* Deliberately small, HTML-free Markdown renderer for assistant-visible text.
|
|
3
11
|
* Memoized on the text value: stream updates re-render only the message whose
|
|
4
12
|
* text actually changed, so committed history is never re-parsed.
|
|
5
13
|
*/
|
|
6
|
-
export declare const Markdown: import("react").MemoExoticComponent<({ text, }: {
|
|
14
|
+
export declare const Markdown: import("react").MemoExoticComponent<({ text, sourceRefs, onSourceOpen, }: {
|
|
7
15
|
readonly text: string;
|
|
16
|
+
readonly sourceRefs?: QaSourceRefs;
|
|
17
|
+
readonly onSourceOpen?: (source: QaSource) => void;
|
|
8
18
|
}) => import("react/jsx-runtime").JSX.Element>;
|
|
9
19
|
//# sourceMappingURL=Markdown.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SessionSummary } from "@deepseek-ai/dsh-
|
|
1
|
+
import type { SessionSummary } from "@deepseek-ai/dsh-api-session-controller/client";
|
|
2
2
|
/** One row of the agents panel: a subagent session of the open chat. */
|
|
3
3
|
export interface QaSubagentRow {
|
|
4
4
|
readonly id: string;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { QaAccountsController, QaAccountsSnapshot } from "../QaAccountsController.js";
|
|
2
|
+
export interface QaAuthGateProps {
|
|
3
|
+
readonly accounts: QaAccountsController;
|
|
4
|
+
readonly snapshot: QaAccountsSnapshot;
|
|
5
|
+
readonly title: string;
|
|
6
|
+
readonly logoUrl: string | null;
|
|
7
|
+
readonly allowRegistration: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* The full-frame login/registration card shown instead of the chat while the
|
|
11
|
+
* deployment has accounts enabled and the browser holds no valid identity.
|
|
12
|
+
* Errors are the Host's coarse codes rendered as audience-safe copy.
|
|
13
|
+
*/
|
|
14
|
+
export declare function QaAuthGate(props: QaAuthGateProps): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
//# sourceMappingURL=QaAuthGate.d.ts.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare const QA_VERSION: string;
|
|
2
|
+
export interface QaChangelogEntry {
|
|
3
|
+
readonly version: string;
|
|
4
|
+
readonly date: string;
|
|
5
|
+
readonly sections: readonly {
|
|
6
|
+
readonly title: string;
|
|
7
|
+
readonly items: readonly string[];
|
|
8
|
+
}[];
|
|
9
|
+
}
|
|
10
|
+
export declare const QA_CHANGELOG: readonly QaChangelogEntry[];
|
|
11
|
+
/** Props of the {@link QaChangelogModal} dialog. */
|
|
12
|
+
export interface QaChangelogModalProps {
|
|
13
|
+
readonly open: boolean;
|
|
14
|
+
readonly onClose: () => void;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The version/changelog dialog opened from the sidebar footer. Rendering is
|
|
18
|
+
* a no-op while closed; Escape and a backdrop click close it.
|
|
19
|
+
*/
|
|
20
|
+
export declare function QaChangelogModal(props: QaChangelogModalProps): import("react/jsx-runtime").JSX.Element | null;
|
|
21
|
+
//# sourceMappingURL=QaChangelog.d.ts.map
|
|
@@ -1,14 +1,21 @@
|
|
|
1
|
-
import type { QaMessage as QaMessageModel } from "../../types.js";
|
|
1
|
+
import type { QaMessage as QaMessageModel, QaSource, QaTurnSources } from "../../types.js";
|
|
2
2
|
export interface QaMessageProps {
|
|
3
3
|
readonly message: QaMessageModel;
|
|
4
4
|
readonly renderMarkdown: boolean;
|
|
5
5
|
readonly showTimestamp: boolean;
|
|
6
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* Storage prefix persisted message ratings live under. Callers scope it to
|
|
8
|
+
* the chat: message ids repeat across chats (`assistant:<seq>`).
|
|
9
|
+
*/
|
|
7
10
|
readonly stateKey?: string;
|
|
8
11
|
/** Ask for a fresh variant of this answer; omit to hide the control. */
|
|
9
12
|
readonly onRegenerate?: () => void;
|
|
10
13
|
/** Resolve one durable attachment into a viewable URL. */
|
|
11
14
|
readonly resolveImage?: (attachmentId: string) => Promise<string>;
|
|
15
|
+
/** Open the drawer at the exact canonical snapshot shown in this footer. */
|
|
16
|
+
readonly onOpenSources?: (sources: readonly QaSource[], complete: boolean, incompleteOrigins: QaTurnSources["incompleteOrigins"]) => void;
|
|
17
|
+
/** Open one path-backed source's detail (an inline footnote click). */
|
|
18
|
+
readonly onSourceDetail?: (source: QaSource) => void;
|
|
12
19
|
}
|
|
13
20
|
/**
|
|
14
21
|
* Whether two transcript messages render identically. The transcript
|
|
@@ -17,5 +24,5 @@ export interface QaMessageProps {
|
|
|
17
24
|
* comparison is by value, which keeps fresh copies cheap to recognize.
|
|
18
25
|
*/
|
|
19
26
|
export declare function sameMessage(a: QaMessageModel, b: QaMessageModel): boolean;
|
|
20
|
-
export declare const QaMessage: import("react").MemoExoticComponent<({ message, renderMarkdown, showTimestamp, stateKey, onRegenerate, resolveImage, }: QaMessageProps) => import("react/jsx-runtime").JSX.Element>;
|
|
27
|
+
export declare const QaMessage: import("react").MemoExoticComponent<({ message, renderMarkdown, showTimestamp, stateKey, onRegenerate, resolveImage, onOpenSources, onSourceDetail, }: QaMessageProps) => import("react/jsx-runtime").JSX.Element>;
|
|
21
28
|
//# sourceMappingURL=QaMessage.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SessionSummary } from "@deepseek-ai/dsh-
|
|
1
|
+
import type { SessionSummary } from "@deepseek-ai/dsh-api-session-controller/client";
|
|
2
2
|
/** One renderable row of the chat-history sidebar. */
|
|
3
3
|
export interface QaChatRow {
|
|
4
4
|
readonly id: string;
|
|
@@ -7,6 +7,8 @@ export interface QaChatRow {
|
|
|
7
7
|
readonly active: boolean;
|
|
8
8
|
readonly meta: string;
|
|
9
9
|
readonly updatedAt: number;
|
|
10
|
+
/** Chat owner's display name; present in the admin ownership view only. */
|
|
11
|
+
readonly ownerName?: string;
|
|
10
12
|
}
|
|
11
13
|
/**
|
|
12
14
|
* Project this browser's indexed chat ids onto the host session list, most
|
|
@@ -14,9 +16,29 @@ export interface QaChatRow {
|
|
|
14
16
|
* `updatedAt` (fresh messages) orders the list. Ids the host no longer lists
|
|
15
17
|
* are skipped (the controller prunes them on switch).
|
|
16
18
|
*/
|
|
17
|
-
export declare function buildChatRows(chatIds: readonly string[], byId: Readonly<Record<string, SessionSummary>>, activeId: string | null, now?: number): readonly QaChatRow[];
|
|
19
|
+
export declare function buildChatRows(chatIds: readonly string[], byId: Readonly<Record<string, SessionSummary>>, activeId: string | null, ownerNameOf?: (sessionId: string) => string | undefined, now?: number): readonly QaChatRow[];
|
|
20
|
+
/** One per-owner section of the admin sidebar grouping. */
|
|
21
|
+
export interface QaSidebarSection {
|
|
22
|
+
/**
|
|
23
|
+
* Section header; chats nobody claimed group under "Без владельца". An
|
|
24
|
+
* empty name renders no header (the flat, non-grouped mode).
|
|
25
|
+
*/
|
|
26
|
+
readonly name: string;
|
|
27
|
+
readonly rows: readonly QaChatRow[];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Group rows into per-owner sections for the admin view. Sections order by
|
|
31
|
+
* their freshest row so the busiest users float up; unclaimed chats go last.
|
|
32
|
+
* Row order inside a section is already the global updatedAt order.
|
|
33
|
+
*/
|
|
34
|
+
export declare function buildOwnerSections(rows: readonly QaChatRow[]): readonly QaSidebarSection[];
|
|
18
35
|
export interface QaSidebarProps {
|
|
19
36
|
readonly rows: readonly QaChatRow[];
|
|
37
|
+
/**
|
|
38
|
+
* Render per-owner sections instead of the flat list; the admin ownership
|
|
39
|
+
* view. Rows without an owner name fall into a trailing section.
|
|
40
|
+
*/
|
|
41
|
+
readonly groupByOwner?: boolean;
|
|
20
42
|
/** Deployment brand shown next to the logo (also while collapsed). */
|
|
21
43
|
readonly title: string;
|
|
22
44
|
/** Optional image logo; a built-in mark is drawn when null. */
|
|
@@ -29,6 +51,12 @@ export interface QaSidebarProps {
|
|
|
29
51
|
readonly onNewChat: () => void;
|
|
30
52
|
/** Removes a chat from this browser's index; omit to hide the control. */
|
|
31
53
|
readonly onDelete?: (sessionId: string) => void;
|
|
54
|
+
/** The signed-in account; omit when accounts are disabled. */
|
|
55
|
+
readonly account?: {
|
|
56
|
+
readonly email: string;
|
|
57
|
+
readonly role: string;
|
|
58
|
+
readonly onLogout: () => void;
|
|
59
|
+
};
|
|
32
60
|
}
|
|
33
61
|
/**
|
|
34
62
|
* Whether two sidebar row lists show the same thing. Rows are rebuilt on
|
|
@@ -1,8 +1,20 @@
|
|
|
1
|
-
import type { QaSource } from "../../types.js";
|
|
1
|
+
import type { QaSource, QaTurnSources, ResolvedQaSurfaceConfig } from "../../types.js";
|
|
2
|
+
import type { QaBoundSourceApi } from "../types.js";
|
|
3
|
+
export declare function SourceIcon({ kind }: {
|
|
4
|
+
readonly kind: QaSource["kind"];
|
|
5
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
2
6
|
export interface QaSourcesDrawerProps {
|
|
3
7
|
readonly sources: readonly QaSource[];
|
|
8
|
+
readonly complete: boolean;
|
|
9
|
+
readonly incompleteOrigins?: QaTurnSources["incompleteOrigins"];
|
|
10
|
+
readonly sessionId: string | null;
|
|
11
|
+
readonly sourceApi: QaBoundSourceApi;
|
|
12
|
+
readonly display: ResolvedQaSurfaceConfig["sources"]["display"];
|
|
13
|
+
readonly filePreview: ResolvedQaSurfaceConfig["sources"]["filePreview"];
|
|
14
|
+
/** Open straight onto this source's detail (an inline footnote click). */
|
|
15
|
+
readonly initialDetail?: QaSource | null;
|
|
4
16
|
readonly onClose: () => void;
|
|
5
17
|
}
|
|
6
|
-
/**
|
|
7
|
-
export declare function QaSourcesDrawer({ sources, onClose }: QaSourcesDrawerProps): import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
/** Canonical grouped source panel and safe local-file preview. */
|
|
19
|
+
export declare function QaSourcesDrawer({ sources, complete, incompleteOrigins, sessionId, sourceApi, display, filePreview, initialDetail, onClose, }: QaSourcesDrawerProps): import("react/jsx-runtime").JSX.Element;
|
|
8
20
|
//# sourceMappingURL=QaSourcesDrawer.d.ts.map
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { type RefObject } from "react";
|
|
2
|
+
import type { QaMessage } from "../../types.js";
|
|
3
|
+
/**
|
|
4
|
+
* One mark of the turn rail: the user prompt that opens the turn, a bounded
|
|
5
|
+
* answer preview for the hover tooltip, and the message id that anchors the
|
|
6
|
+
* jump (the prompt's message slot in the transcript).
|
|
7
|
+
*/
|
|
8
|
+
export interface QaTurnRailItem {
|
|
9
|
+
/** 1-based position in the visible transcript; also the React key. */
|
|
10
|
+
readonly turn: number;
|
|
11
|
+
/** The user message id that opens the turn (scroll anchor). */
|
|
12
|
+
readonly id: string;
|
|
13
|
+
readonly prompt: string;
|
|
14
|
+
readonly response: string;
|
|
15
|
+
}
|
|
16
|
+
/** Transcript attribute marking the message slot that opens a turn. */
|
|
17
|
+
export declare const QA_TURN_ANCHOR_ATTRIBUTE = "data-dsh-qa-turn-anchor";
|
|
18
|
+
/** Scroll distance from the floor at which the rail still calls it "at bottom". */
|
|
19
|
+
export declare const QA_TURN_FOLLOW_PX = 96;
|
|
20
|
+
/** The reading line: reading offset from the scrollport top while scrolling. */
|
|
21
|
+
export declare const QA_TURN_READING_PX = 96;
|
|
22
|
+
/**
|
|
23
|
+
* Rail ladder of the visible transcript: every user prompt opens a turn, the
|
|
24
|
+
* first non-empty answer after it fills the response preview. Hidden variant
|
|
25
|
+
* answers never reach this list because callers pass the already-filtered
|
|
26
|
+
* messages.
|
|
27
|
+
*/
|
|
28
|
+
export declare function buildTurnRailItems(messages: readonly QaMessage[]): readonly QaTurnRailItem[];
|
|
29
|
+
/** Deep equality guard so the memoized rail skips streaming commits. */
|
|
30
|
+
export declare function sameTurnRailItems(left: readonly QaTurnRailItem[], right: readonly QaTurnRailItem[]): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Turn owning the transcript's reading line, or the newest one while the
|
|
33
|
+
* reader follows the live tail. Anchors above the line are scanned in flow
|
|
34
|
+
* order; the last one at or above it owns the mark.
|
|
35
|
+
*/
|
|
36
|
+
export declare function computeActiveTurn(scroller: HTMLElement, items: readonly QaTurnRailItem[]): number | null;
|
|
37
|
+
export interface QaTurnRailProps {
|
|
38
|
+
readonly items: readonly QaTurnRailItem[];
|
|
39
|
+
readonly activeTurn: number | null;
|
|
40
|
+
/** Turn still generating; its mark pulses. */
|
|
41
|
+
readonly busyTurn: number | null;
|
|
42
|
+
/** The transcript scroller the rail floats over and measures its band from. */
|
|
43
|
+
readonly scrollerRef: RefObject<HTMLDivElement | null>;
|
|
44
|
+
readonly onNavigate: (item: QaTurnRailItem) => void;
|
|
45
|
+
}
|
|
46
|
+
declare function QaTurnRailView({ items, activeTurn, busyTurn, scrollerRef, onNavigate, }: QaTurnRailProps): import("react/jsx-runtime").JSX.Element | null;
|
|
47
|
+
/**
|
|
48
|
+
* Fixed-pitch rail of every turn of the visible transcript, floating over the
|
|
49
|
+
* transcript's right gutter: the active mark follows the reading line, a
|
|
50
|
+
* hover/focus preview shows the prompt and answer, and a click lands the
|
|
51
|
+
* transcript on that turn. Memoized like the harness rail — the transcript
|
|
52
|
+
* re-renders on every streaming delta, and the rail only changes when a turn
|
|
53
|
+
* is added or becomes active.
|
|
54
|
+
*/
|
|
55
|
+
export declare const QaTurnRail: import("react").MemoExoticComponent<typeof QaTurnRailView>;
|
|
56
|
+
/** Land the transcript on a turn's prompt row, harness-style. */
|
|
57
|
+
export declare function turnScrollTarget(scroller: HTMLElement, row: HTMLElement): number;
|
|
58
|
+
export {};
|
|
59
|
+
//# sourceMappingURL=QaTurnRail.d.ts.map
|