@yadsh/dsh-qa-surface 0.17.0 → 0.18.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 +15 -3
- package/compatibility.json +1 -1
- package/lib/account-remotes.js +4 -0
- package/lib/account-remotes.js.map +1 -1
- package/lib/accounts/database.js +86 -1
- package/lib/accounts/database.js.map +1 -1
- package/lib/accounts/file.js.map +1 -1
- package/lib/accounts/store.js +111 -5
- package/lib/accounts/store.js.map +1 -1
- package/lib/accounts/token.js +8 -2
- package/lib/accounts/token.js.map +1 -1
- package/lib/admin/metrics.js +15 -2
- package/lib/admin/metrics.js.map +1 -1
- package/lib/admin/read-budget.js +28 -0
- package/lib/admin/read-budget.js.map +1 -0
- package/lib/admin/service.js +135 -40
- package/lib/admin/service.js.map +1 -1
- package/lib/admin/session-log.js +63 -4
- package/lib/admin/session-log.js.map +1 -1
- package/lib/chat-sharing/native-fence.js +20 -0
- package/lib/chat-sharing/native-fence.js.map +1 -1
- package/lib/chat-sharing/transport.js +8 -2
- package/lib/chat-sharing/transport.js.map +1 -1
- package/lib/chat-sharing/uploads.js +79 -6
- package/lib/chat-sharing/uploads.js.map +1 -1
- package/lib/cli.js +13 -0
- package/lib/cli.js.map +1 -1
- package/lib/client/QaAccountsController.js +61 -0
- package/lib/client/QaAccountsController.js.map +1 -1
- package/lib/client/QaRouteController.js +3 -1
- package/lib/client/QaRouteController.js.map +1 -1
- package/lib/client/QaSessionController.js +90 -26
- package/lib/client/QaSessionController.js.map +1 -1
- package/lib/client/QaSurface.js +40 -11
- package/lib/client/QaSurface.js.map +1 -1
- package/lib/client/account-sessions.js +74 -8
- package/lib/client/account-sessions.js.map +1 -1
- package/lib/client/admin/CapabilityPicker.js +50 -0
- package/lib/client/admin/CapabilityPicker.js.map +1 -0
- package/lib/client/admin/CoverageNotice.js +9 -0
- package/lib/client/admin/CoverageNotice.js.map +1 -0
- package/lib/client/admin/QaAdmin.js +3 -150
- package/lib/client/admin/QaAdmin.js.map +1 -1
- package/lib/client/admin/RoleEditor.js +46 -0
- package/lib/client/admin/RoleEditor.js.map +1 -0
- package/lib/client/admin/capability-selection.js +63 -0
- package/lib/client/admin/capability-selection.js.map +1 -0
- package/lib/client/admin/pages/Conversations.js +35 -17
- package/lib/client/admin/pages/Conversations.js.map +1 -1
- package/lib/client/admin/pages/Overview.js +3 -2
- package/lib/client/admin/pages/Overview.js.map +1 -1
- package/lib/client/admin/pages/Quality.js +77 -20
- package/lib/client/admin/pages/Quality.js.map +1 -1
- package/lib/client/admin/pages/SkillFiles.js +14 -3
- package/lib/client/admin/pages/SkillFiles.js.map +1 -1
- package/lib/client/admin/shared.js +68 -3
- package/lib/client/admin/shared.js.map +1 -1
- package/lib/client/components/QaAuthGate.js +31 -28
- package/lib/client/components/QaAuthGate.js.map +1 -1
- package/lib/client/components/QaChangelog.js +44 -0
- package/lib/client/components/QaChangelog.js.map +1 -1
- package/lib/client/components/QaComposer.js +27 -4
- package/lib/client/components/QaComposer.js.map +1 -1
- package/lib/client/components/QaFormItem.js +63 -0
- package/lib/client/components/QaFormItem.js.map +1 -0
- package/lib/client/components/QaInputForm.js +281 -0
- package/lib/client/components/QaInputForm.js.map +1 -0
- package/lib/client/components/QaModal.js +17 -4
- package/lib/client/components/QaModal.js.map +1 -1
- package/lib/client/forms-styles.js +14 -0
- package/lib/client/forms-styles.js.map +1 -0
- package/lib/client/forms.js +40 -0
- package/lib/client/forms.js.map +1 -0
- package/lib/client/index.js +15 -1
- package/lib/client/index.js.map +1 -1
- package/lib/client/oidc-browser.js +39 -0
- package/lib/client/oidc-browser.js.map +1 -0
- package/lib/client/panels/PanelHost.js +23 -1
- package/lib/client/panels/PanelHost.js.map +1 -1
- package/lib/client/settings/sections/interface.js +2 -1
- package/lib/client/settings/sections/interface.js.map +1 -1
- package/lib/client/settings/sections/status.js +3 -1
- package/lib/client/settings/sections/status.js.map +1 -1
- package/lib/client/styles.js +3 -3
- package/lib/client/types.js.map +1 -1
- package/lib/client.js +465 -72918
- package/lib/client.js.map +1 -1
- package/lib/config-resolvers/accounts.js +5 -4
- package/lib/config-resolvers/accounts.js.map +1 -1
- package/lib/config-resolvers/defaults.js +16 -0
- package/lib/config-resolvers/defaults.js.map +1 -1
- package/lib/config-resolvers/oidc.js +53 -0
- package/lib/config-resolvers/oidc.js.map +1 -0
- package/lib/config.js +71 -0
- package/lib/config.js.map +1 -1
- package/lib/forms/attachments.js +214 -0
- package/lib/forms/attachments.js.map +1 -0
- package/lib/forms/errors.js +37 -0
- package/lib/forms/errors.js.map +1 -0
- package/lib/forms/fingerprint.js +21 -0
- package/lib/forms/fingerprint.js.map +1 -0
- package/lib/forms/gate.js +125 -0
- package/lib/forms/gate.js.map +1 -0
- package/lib/forms/schema.js +182 -0
- package/lib/forms/schema.js.map +1 -0
- package/lib/forms/service.js +220 -0
- package/lib/forms/service.js.map +1 -0
- package/lib/forms/store.js +194 -0
- package/lib/forms/store.js.map +1 -0
- package/lib/forms/types.js +2 -0
- package/lib/forms/types.js.map +1 -0
- package/lib/forms/validation.js +113 -0
- package/lib/forms/validation.js.map +1 -0
- package/lib/index.js +227 -3
- package/lib/index.js.map +1 -1
- package/lib/oidc/http.js +30 -0
- package/lib/oidc/http.js.map +1 -0
- package/lib/oidc/service.js +250 -0
- package/lib/oidc/service.js.map +1 -0
- package/lib/qa-tools/activation-manager.js +24 -2
- package/lib/qa-tools/activation-manager.js.map +1 -1
- package/lib/qa-tools/catalog.js +11 -1
- package/lib/qa-tools/catalog.js.map +1 -1
- package/lib/qa-tools/index.js +27 -0
- package/lib/qa-tools/index.js.map +1 -1
- package/lib/qa-tools/request-user-form.js +121 -0
- package/lib/qa-tools/request-user-form.js.map +1 -0
- package/lib/resolve-config.js +2 -0
- package/lib/resolve-config.js.map +1 -1
- package/lib/secure-session.js +14 -8
- package/lib/secure-session.js.map +1 -1
- package/lib/typert.host.js +4587 -1101
- package/lib/typert.remote-client.d.ts +133 -3
- package/lib/typert.remote-client.js +4463 -1103
- package/lib/types/accounts/database.d.ts +8 -0
- package/lib/types/accounts/file.d.ts +2 -0
- package/lib/types/accounts/store.d.ts +17 -0
- package/lib/types/accounts/token.d.ts +3 -1
- package/lib/types/admin/metrics.d.ts +5 -1
- package/lib/types/admin/read-budget.d.ts +8 -0
- package/lib/types/admin/service.d.ts +17 -0
- package/lib/types/admin/session-log.d.ts +30 -1
- package/lib/types/chat-sharing/uploads.d.ts +2 -1
- package/lib/types/client/QaAccountsController.d.ts +4 -0
- package/lib/types/client/QaRouteController.d.ts +1 -0
- package/lib/types/client/QaSessionController.d.ts +12 -3
- package/lib/types/client/QaSurface.d.ts +2 -0
- package/lib/types/client/admin/CapabilityPicker.d.ts +14 -0
- package/lib/types/client/admin/CoverageNotice.d.ts +6 -0
- package/lib/types/client/admin/RoleEditor.d.ts +15 -0
- package/lib/types/client/admin/capability-selection.d.ts +27 -0
- package/lib/types/client/admin/shared.d.ts +39 -1
- package/lib/types/client/components/QaAuthGate.d.ts +2 -0
- package/lib/types/client/components/QaFormItem.d.ts +20 -0
- package/lib/types/client/components/QaInputForm.d.ts +18 -0
- package/lib/types/client/forms-styles.d.ts +2 -0
- package/lib/types/client/forms.d.ts +23 -0
- package/lib/types/client/oidc-browser.d.ts +12 -0
- package/lib/types/client/types.d.ts +7 -1
- package/lib/types/config-resolvers/oidc.d.ts +3 -0
- package/lib/types/forms/attachments.d.ts +48 -0
- package/lib/types/forms/errors.d.ts +11 -0
- package/lib/types/forms/fingerprint.d.ts +9 -0
- package/lib/types/forms/gate.d.ts +33 -0
- package/lib/types/forms/schema.d.ts +72 -0
- package/lib/types/forms/service.d.ts +15 -0
- package/lib/types/forms/store.d.ts +25 -0
- package/lib/types/forms/types.d.ts +215 -0
- package/lib/types/forms/validation.d.ts +20 -0
- package/lib/types/index.d.ts +28 -0
- package/lib/types/oidc/http.d.ts +5 -0
- package/lib/types/oidc/service.d.ts +30 -0
- package/lib/types/oidc.js +2 -0
- package/lib/types/oidc.js.map +1 -0
- package/lib/types/qa-tools/activation-manager.d.ts +5 -0
- package/lib/types/qa-tools/catalog.d.ts +4 -1
- package/lib/types/qa-tools/index.d.ts +5 -1
- package/lib/types/qa-tools/request-user-form.d.ts +5 -0
- package/lib/types/secure-session.d.ts +1 -0
- package/lib/types/types/accounts.d.ts +2 -0
- package/lib/types/types/admin.d.ts +6 -0
- package/lib/types/types/config.d.ts +6 -0
- package/lib/types/types/oidc.d.ts +36 -0
- package/lib/types/types.d.ts +2 -0
- package/package.json +57 -55
|
@@ -74,6 +74,14 @@ export declare class QaAccountsDatabase {
|
|
|
74
74
|
insertUser(user: StoredUser): void;
|
|
75
75
|
/** Replace one account's row in place. */
|
|
76
76
|
updateUser(user: StoredUser): void;
|
|
77
|
+
oidcUserId(issuer: string, subject: string): string | undefined;
|
|
78
|
+
isOidcUser(userId: string): boolean;
|
|
79
|
+
/** Account creation and identity attachment must commit together. */
|
|
80
|
+
attachOidcIdentity(issuer: string, subject: string, user: StoredUser, create: boolean): void;
|
|
81
|
+
/** Re-read and update authentication facts under the same write transaction. */
|
|
82
|
+
authenticateOidc(userId: string, email: string, displayName: string, role: StoredUser["role"], sid: string, expiresAt: number): StoredUser | undefined;
|
|
83
|
+
oidcSessionActive(id: string, userId: string): boolean;
|
|
84
|
+
revokeOidcSession(id: string): void;
|
|
77
85
|
/**
|
|
78
86
|
* Record one forgotten-password request. A repeat from the same account
|
|
79
87
|
* moves the row up the queue and counts up, so the console shows "asked
|
|
@@ -25,6 +25,8 @@ export interface StoredNotifications {
|
|
|
25
25
|
desktop?: boolean;
|
|
26
26
|
}
|
|
27
27
|
export interface StoredUser {
|
|
28
|
+
/** Derived from the identity table when the database is loaded. */
|
|
29
|
+
readonly authMethod?: "oidc";
|
|
28
30
|
readonly id: string;
|
|
29
31
|
readonly email: string;
|
|
30
32
|
readonly displayName: string;
|
|
@@ -6,6 +6,8 @@ export type { QaAccountsErrorReason } from "./errors.js";
|
|
|
6
6
|
export { defaultAccountsFilePath } from "./file.js";
|
|
7
7
|
export type { QaIssuedServiceToken, QaServiceTokenSummary } from "../types.js";
|
|
8
8
|
export interface QaAccountsOptions {
|
|
9
|
+
readonly oidcEnabled?: boolean;
|
|
10
|
+
readonly localLogin?: boolean;
|
|
9
11
|
readonly sessionTtlDays: number;
|
|
10
12
|
readonly allowRegistration: boolean;
|
|
11
13
|
/** Login/registration attempts accepted per rolling minute, store-wide. */
|
|
@@ -85,6 +87,8 @@ export declare class QaAccounts {
|
|
|
85
87
|
private readonly maxAuthAttemptsPerMinute;
|
|
86
88
|
private readonly sessionTtlDays;
|
|
87
89
|
private readonly allowRegistration;
|
|
90
|
+
private readonly oidcEnabled;
|
|
91
|
+
private readonly localLogin;
|
|
88
92
|
/** Character cap on a stored profile's agent guidance. */
|
|
89
93
|
private readonly instructionsMaxLength;
|
|
90
94
|
/** Whether a deployment declares which identity handles an account may hold. */
|
|
@@ -126,6 +130,19 @@ export declare class QaAccounts {
|
|
|
126
130
|
/** Resolve a token to its user, or null for absent/invalid/expired ones. */
|
|
127
131
|
verifyToken(token: string): string | null;
|
|
128
132
|
private mintToken;
|
|
133
|
+
/** Only the server OIDC verifier calls this with authenticated claims. */
|
|
134
|
+
loginOidc(identity: {
|
|
135
|
+
issuer: string;
|
|
136
|
+
subject: string;
|
|
137
|
+
email: string;
|
|
138
|
+
displayName: string;
|
|
139
|
+
role: QaAccountRole;
|
|
140
|
+
expiresAt: number;
|
|
141
|
+
autoProvision: boolean;
|
|
142
|
+
}): QaAccountSession;
|
|
143
|
+
/** Operator-confirmed attachment preserves ownership and revokes old credentials. */
|
|
144
|
+
linkOidcIdentity(email: string, issuer: string, subject: string): QaAccountUserPublic;
|
|
145
|
+
logoutOidc(token: string): boolean;
|
|
129
146
|
/**
|
|
130
147
|
* The account behind a token, or an auth-required refusal.
|
|
131
148
|
*
|
|
@@ -5,6 +5,8 @@ interface TokenUser {
|
|
|
5
5
|
}
|
|
6
6
|
/** The claims carried by a v1 account token payload. */
|
|
7
7
|
export interface TokenPayload {
|
|
8
|
+
/** OIDC-backed QA session; checked against the account database on every use. */
|
|
9
|
+
readonly sid?: string;
|
|
8
10
|
readonly uid: string;
|
|
9
11
|
/** Expiry, epoch milliseconds. */
|
|
10
12
|
readonly exp: number;
|
|
@@ -26,6 +28,6 @@ export declare function mintToken(secret: string, payload: TokenPayload): string
|
|
|
26
28
|
* timingSafeEqual) so a signature guess cannot be accelerated by measuring
|
|
27
29
|
* HMAC rejection time.
|
|
28
30
|
*/
|
|
29
|
-
export declare function verifyToken(secret: string, token: string, users: readonly TokenUser[]): string | null;
|
|
31
|
+
export declare function verifyToken(secret: string, token: string, users: readonly TokenUser[], sessionActive?: (id: string, userId: string) => boolean): string | null;
|
|
30
32
|
export {};
|
|
31
33
|
//# sourceMappingURL=token.d.ts.map
|
|
@@ -13,6 +13,8 @@ export interface QaConversationFact {
|
|
|
13
13
|
readonly userId: string;
|
|
14
14
|
readonly subroleId: string;
|
|
15
15
|
readonly assistantMessages: number;
|
|
16
|
+
readonly readable?: boolean;
|
|
17
|
+
readonly assistantMessageIds?: readonly string[];
|
|
16
18
|
/** Epoch ms of the conversation's creation, for the activity window. */
|
|
17
19
|
readonly createdAt: number;
|
|
18
20
|
}
|
|
@@ -22,8 +24,10 @@ export interface QaAggregationInput {
|
|
|
22
24
|
readonly reviews: readonly QaConversationReview[];
|
|
23
25
|
/** Days of feedback history the trend shows; older buckets are dropped. */
|
|
24
26
|
readonly trendDays?: number;
|
|
27
|
+
/** False when the request could not read every conversation in its population. */
|
|
28
|
+
readonly complete?: boolean;
|
|
25
29
|
}
|
|
26
|
-
export declare function aggregateQuality({ conversations, feedback, reviews, trendDays, }: QaAggregationInput): QaQualityMetrics;
|
|
30
|
+
export declare function aggregateQuality({ conversations, feedback, reviews, trendDays, complete, }: QaAggregationInput): QaQualityMetrics;
|
|
27
31
|
/** One rating's contribution to a conversation row, without re-reading logs. */
|
|
28
32
|
export declare function countRatings(feedback: readonly QaMessageFeedback[]): Readonly<Record<QaFeedbackRating, number>>;
|
|
29
33
|
//# sourceMappingURL=metrics.d.ts.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** One deadline shared by every storage phase of an administrative request. */
|
|
2
|
+
export interface QaReadBudget {
|
|
3
|
+
remaining(): number;
|
|
4
|
+
read<T>(work: () => Promise<T>, fallback: T): Promise<T>;
|
|
5
|
+
}
|
|
6
|
+
export declare const QA_ADMIN_REQUEST_BUDGET_MS = 15000;
|
|
7
|
+
export declare function readBudget(now: () => number, ms?: number): QaReadBudget;
|
|
8
|
+
//# sourceMappingURL=read-budget.d.ts.map
|
|
@@ -24,6 +24,18 @@ export declare const QA_ADMIN_PAGE_MAX = 100;
|
|
|
24
24
|
* says so; moving these counters onto a real index is the next iteration.
|
|
25
25
|
*/
|
|
26
26
|
export declare const QA_ADMIN_SCAN_LIMIT = 200;
|
|
27
|
+
/**
|
|
28
|
+
* How long one page may spend reading conversation logs before it answers with
|
|
29
|
+
* what it already has. The newest logs are read until this budget is spent; the
|
|
30
|
+
* rest of the rows are marked unread instead of the page waiting for a store
|
|
31
|
+
* that may never answer. Without this,
|
|
32
|
+
* one conversation whose log cannot be read — a blank chat its process holds
|
|
33
|
+
* open is the usual case on a stand — parked the page for as long as the
|
|
34
|
+
* deployment runs.
|
|
35
|
+
*/
|
|
36
|
+
export declare const QA_ADMIN_PAGE_BUDGET_MS = 10000;
|
|
37
|
+
/** The same budget for the aggregate window the overview and metrics read. */
|
|
38
|
+
export declare const QA_ADMIN_SCAN_BUDGET_MS = 10000;
|
|
27
39
|
interface QaServiceClock {
|
|
28
40
|
now(): number;
|
|
29
41
|
}
|
|
@@ -101,6 +113,7 @@ export declare class QaAdminService {
|
|
|
101
113
|
* reads the log — and what the aggregate pages show instead is the newest
|
|
102
114
|
* projection of every finished conversation, which is the cheaper lie.
|
|
103
115
|
*/
|
|
116
|
+
private now;
|
|
104
117
|
private transcript;
|
|
105
118
|
/** Insert or re-touch one projection, keeping the cache inside its budget. */
|
|
106
119
|
private retain;
|
|
@@ -121,6 +134,10 @@ export declare class QaAdminService {
|
|
|
121
134
|
* up between two reads once every caller has left, so a reviewer who abandons a
|
|
122
135
|
* page that has not answered does not keep the deployment reading logs for an
|
|
123
136
|
* answer nobody will see.
|
|
137
|
+
*
|
|
138
|
+
* `within` is the pass's read budget. A log the budget no longer covers is not
|
|
139
|
+
* opened: the conversation keeps its row and is marked unread. Metrics then
|
|
140
|
+
* disclose the incomplete population instead of treating it as zero answers.
|
|
124
141
|
*/
|
|
125
142
|
private walk;
|
|
126
143
|
overview(token: string, signal?: AbortSignal): Promise<QaAdminOverview>;
|
|
@@ -36,7 +36,27 @@ export type QaSessionReadResult = {
|
|
|
36
36
|
} | {
|
|
37
37
|
readonly ok: false;
|
|
38
38
|
readonly reason: QaTranscriptUnavailableReason;
|
|
39
|
+
/**
|
|
40
|
+
* True when the answer is "storage did not answer in time" rather than a
|
|
41
|
+
* verdict about the log. A caller that scans many logs skips such a
|
|
42
|
+
* conversation and keeps the rest of its rows; the wire reason stays one
|
|
43
|
+
* of the shared three, so no page learns a new word.
|
|
44
|
+
*/
|
|
45
|
+
readonly timedOut?: boolean;
|
|
39
46
|
};
|
|
47
|
+
/**
|
|
48
|
+
* How long one stored log may take before the console stops waiting for it.
|
|
49
|
+
*
|
|
50
|
+
* The durable backend answers a read by listing every session the deployment
|
|
51
|
+
* keeps and replaying the log; a log whose owning process is mid-flush — a
|
|
52
|
+
* blank chat created and left open is the usual case on a stand — can hold that
|
|
53
|
+
* answer indefinitely. The console is a reading surface, so a conversation it
|
|
54
|
+
* cannot read in this budget is reported and skipped rather than allowed to
|
|
55
|
+
* park the whole page.
|
|
56
|
+
*/
|
|
57
|
+
export declare const QA_SESSION_READ_TIMEOUT_MS = 5000;
|
|
58
|
+
/** The same budget for the one listing every administrative page needs. */
|
|
59
|
+
export declare const QA_SESSION_LIST_TIMEOUT_MS = 8000;
|
|
40
60
|
/**
|
|
41
61
|
* One listing of the deployment's sessions together with what the answer
|
|
42
62
|
* covers. The distinction is load-bearing: on a deployment that serves no
|
|
@@ -111,8 +131,17 @@ export interface QaStoredSessionEraser {
|
|
|
111
131
|
* Build the reader for one plugin instance. The services are looked up per
|
|
112
132
|
* call rather than captured: a cordis provider is only visible once its fiber
|
|
113
133
|
* is active, and a reference taken at construction time would stay dead.
|
|
134
|
+
*
|
|
135
|
+
* Every call that reaches storage is bounded. The bounded answer is a shape the
|
|
136
|
+
* callers already understand — a listing that answers only for the live store,
|
|
137
|
+
* a log that is "storage-unavailable" — so a store that never replies costs a
|
|
138
|
+
* page its detail instead of its whole payload. The budgets are options only so
|
|
139
|
+
* a test can watch the transition without waiting five seconds for it.
|
|
114
140
|
*/
|
|
115
|
-
export declare function createSessionLogReader(ctx: Context
|
|
141
|
+
export declare function createSessionLogReader(ctx: Context, options?: {
|
|
142
|
+
readonly readTimeoutMs?: number;
|
|
143
|
+
readonly listTimeoutMs?: number;
|
|
144
|
+
}): QaSessionLogReader;
|
|
116
145
|
/** A reader over an explicit set of logs; the tests' seam, and the empty default. */
|
|
117
146
|
export declare function staticSessionLogReader(input: {
|
|
118
147
|
readonly sessions?: readonly QaStoredSessionHeader[];
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Context } from "@deepseek-ai/cordis";
|
|
2
2
|
import type { QaChatSharingStore } from "./store.js";
|
|
3
|
+
import type { QaFormAttachmentAdapter } from "../forms/attachments.js";
|
|
3
4
|
/** Authenticate before transferring the body, and fence every uploaded chunk. */
|
|
4
|
-
export declare function installQaChatUploads(ctx: Context, store: () => QaChatSharingStore, admit: (token: string, id: string) => Promise<unknown
|
|
5
|
+
export declare function installQaChatUploads(ctx: Context, store: () => QaChatSharingStore, admit: (token: string, id: string) => Promise<unknown>, forms?: QaFormAttachmentAdapter): () => Promise<void>;
|
|
5
6
|
//# sourceMappingURL=uploads.d.ts.map
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { QaAccountNotificationsInput, QaAccountProfileInput, QaAccountStartersInput, QaAccountUserPublic, QaIssuedServiceToken, QaOwnershipEntry, QaServiceTokenCreateInput, QaServiceTokenSummary, ResolvedQaSurfaceConfig } from "../types.js";
|
|
2
|
+
import type { QaOidcBrowser } from "./oidc-browser.js";
|
|
2
3
|
import type { QaAccountsApi, QaIntegrationTokenResult, StorageLike } from "./types.js";
|
|
3
4
|
/**
|
|
4
5
|
* What the sign-in card says after a forgotten-password request. It names the
|
|
@@ -49,6 +50,7 @@ export declare function accountsErrorMessage(code: string | null): string;
|
|
|
49
50
|
/** Extract the coarse account reason code from a Host wire failure. */
|
|
50
51
|
export declare function accountsReasonOf(failure: unknown): string | null;
|
|
51
52
|
export interface QaAccountsControllerOptions {
|
|
53
|
+
readonly oidcBrowser?: QaOidcBrowser;
|
|
52
54
|
readonly remote: QaAccountsApi;
|
|
53
55
|
readonly storage: StorageLike | undefined;
|
|
54
56
|
/** Config snapshot getter; the token key follows the deployment identity. */
|
|
@@ -79,6 +81,7 @@ export interface QaAccountsControllerOptions {
|
|
|
79
81
|
*/
|
|
80
82
|
export declare class QaAccountsController {
|
|
81
83
|
private readonly options;
|
|
84
|
+
private logoutGeneration;
|
|
82
85
|
private readonly listeners;
|
|
83
86
|
private snapshot;
|
|
84
87
|
private tokenValue;
|
|
@@ -101,6 +104,7 @@ export declare class QaAccountsController {
|
|
|
101
104
|
/** Boot probe: restore the stored token and ask the Host who it is. */
|
|
102
105
|
start(): Promise<void>;
|
|
103
106
|
login(email: string, password: string): Promise<void>;
|
|
107
|
+
loginOidc(): Promise<void>;
|
|
104
108
|
register(email: string, password: string): Promise<void>;
|
|
105
109
|
setMode(mode: "login" | "register" | "reset"): void;
|
|
106
110
|
/**
|
|
@@ -120,7 +120,10 @@ export declare class QaSessionController {
|
|
|
120
120
|
private readonly unsubscribeConnection;
|
|
121
121
|
private ensuring;
|
|
122
122
|
private materializing;
|
|
123
|
+
/** A successful create survives a failed adoption; retry must not create again. */
|
|
124
|
+
private draftSessionId;
|
|
123
125
|
private operationError;
|
|
126
|
+
private operationDiagnostic;
|
|
124
127
|
private admissionPending;
|
|
125
128
|
private pendingSubmission;
|
|
126
129
|
private pendingSequence;
|
|
@@ -161,9 +164,9 @@ export declare class QaSessionController {
|
|
|
161
164
|
* both a failed adoption and {@link unbind} take it back. The converse does
|
|
162
165
|
* not hold: a held session may name nothing, which is the transcript of an
|
|
163
166
|
* attestation this chat could not pass and whose caller still reads it. So a
|
|
164
|
-
* chat whose first send fell short keeps its identity while naming no session
|
|
165
|
-
*
|
|
166
|
-
* was typed into
|
|
167
|
+
* chat whose first send fell short keeps its identity while naming no session;
|
|
168
|
+
* a retry adopts the successful create it already holds and preserves the
|
|
169
|
+
* composer the question was typed into.
|
|
167
170
|
*/
|
|
168
171
|
private namedSession;
|
|
169
172
|
/**
|
|
@@ -212,6 +215,12 @@ export declare class QaSessionController {
|
|
|
212
215
|
getSnapshot: () => QaSessionState;
|
|
213
216
|
subscribe: (listener: () => void) => (() => void);
|
|
214
217
|
ensureSession(): Promise<void>;
|
|
218
|
+
/** Retry opening a failed draft without abandoning its successful create. */
|
|
219
|
+
retrySession(): Promise<void>;
|
|
220
|
+
failureDiagnostic(): {
|
|
221
|
+
readonly reason: string;
|
|
222
|
+
readonly id: string;
|
|
223
|
+
} | null;
|
|
215
224
|
/**
|
|
216
225
|
* Select a different capability profile for the next agent. The current
|
|
217
226
|
* agent is never mutated: even a blank materialized chat is abandoned in
|
|
@@ -4,6 +4,7 @@ import type { QaConfigController } from "./QaConfigController.js";
|
|
|
4
4
|
import type { QaRouteController } from "./QaRouteController.js";
|
|
5
5
|
import type { QaAccountsController } from "./QaAccountsController.js";
|
|
6
6
|
import type { QaApprovalApi, QaAccessApi, QaAdminApi, QaConversation, QaCreateSession, QaForkSession, QaFileUpload, QaQueueStatusRemote, QaSecureSession, QaSessions, QaSessionsApi, QaQuestionApi, QaSkillApi, QaSlashApi, QaSourceApi } from "./types.js";
|
|
7
|
+
import type { QaFormApi } from "./forms.js";
|
|
7
8
|
import type { QaSurfacePanelRegistry } from "./panels/registry.js";
|
|
8
9
|
import type { QaUserSettingsSections } from "./settings-extensions/index.js";
|
|
9
10
|
import type { QaAuditController } from "./audit/controller.js";
|
|
@@ -40,6 +41,7 @@ export interface QaSurfaceFace {
|
|
|
40
41
|
readonly approvalApi?: QaApprovalApi;
|
|
41
42
|
/** Question half of the plugin's namespace, when the Host answers it. */
|
|
42
43
|
readonly questionApi?: QaQuestionApi;
|
|
44
|
+
readonly formApi?: QaFormApi;
|
|
43
45
|
/**
|
|
44
46
|
* Slash half of the plugin's namespace. Absent on a Host build that predates
|
|
45
47
|
* it: the composer then never opens a palette and ordinary prompts are
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { QaCapabilityDescriptor, QaSkillAccess } from "../../types.js";
|
|
2
|
+
import type { CapabilityType } from "./capability-selection.js";
|
|
3
|
+
export declare function CapabilityPicker(props: {
|
|
4
|
+
readonly type: CapabilityType;
|
|
5
|
+
/** The zone this picker is mounted in, so its rows stay addressable. */
|
|
6
|
+
readonly testId?: string;
|
|
7
|
+
readonly catalog: readonly QaCapabilityDescriptor[];
|
|
8
|
+
readonly selected: readonly string[];
|
|
9
|
+
readonly inherited?: readonly string[];
|
|
10
|
+
readonly system?: readonly string[];
|
|
11
|
+
readonly skillDetails?: readonly QaSkillAccess[];
|
|
12
|
+
readonly onChange?: (next: readonly string[]) => void;
|
|
13
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
//# sourceMappingURL=CapabilityPicker.d.ts.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { QaQualityMetrics } from "../../types.js";
|
|
2
|
+
/** A missing journal cannot be presented as a conversation with no answers. */
|
|
3
|
+
export declare function CoverageNotice({ metrics, }: {
|
|
4
|
+
readonly metrics: QaQualityMetrics;
|
|
5
|
+
}): import("react/jsx-runtime").JSX.Element | null;
|
|
6
|
+
//# sourceMappingURL=CoverageNotice.d.ts.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { QaCapabilityDescriptor, QaCapabilitySelection, QaSkillAccess, QaSubrole } from "../../types.js";
|
|
2
|
+
import type { QaAccessApi } from "../types.js";
|
|
3
|
+
export declare function RoleEditor(props: {
|
|
4
|
+
readonly role: QaSubrole | null;
|
|
5
|
+
readonly api: QaAccessApi;
|
|
6
|
+
readonly token: string;
|
|
7
|
+
readonly catalog: readonly QaCapabilityDescriptor[];
|
|
8
|
+
readonly common: QaCapabilitySelection;
|
|
9
|
+
readonly system: QaCapabilitySelection;
|
|
10
|
+
readonly skills: readonly QaSkillAccess[];
|
|
11
|
+
readonly subroles: readonly QaSubrole[];
|
|
12
|
+
readonly onCancel: () => void;
|
|
13
|
+
readonly onSave: (role: QaSubrole) => Promise<void>;
|
|
14
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
//# sourceMappingURL=RoleEditor.d.ts.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { QaCapabilitySelection, QaSkillAccess, QaSubrole } from "../../types.js";
|
|
2
|
+
export type CapabilityType = "tool" | "skill";
|
|
3
|
+
/**
|
|
4
|
+
* The three tool classes: visible immediately, reachable through a loaded
|
|
5
|
+
* skill, or withdrawn from the profile whatever grants them.
|
|
6
|
+
*/
|
|
7
|
+
export type ToolBucket = "always" | "skillGrantable" | "deny";
|
|
8
|
+
export declare const TOOL_BUCKET_LABELS: Record<ToolBucket, string>;
|
|
9
|
+
export declare function unique(values: readonly string[]): string[];
|
|
10
|
+
export declare function bucketOf(selection: QaCapabilitySelection, bucket: ToolBucket): readonly string[];
|
|
11
|
+
export declare function emptySelection(): QaCapabilitySelection;
|
|
12
|
+
export declare function emptyRole(): QaSubrole;
|
|
13
|
+
/** Tools and skills one role would receive, and where each one comes from. */
|
|
14
|
+
export declare function roleEffective(props: {
|
|
15
|
+
readonly system: QaCapabilitySelection;
|
|
16
|
+
readonly common: QaCapabilitySelection;
|
|
17
|
+
readonly role: QaCapabilitySelection;
|
|
18
|
+
readonly skills: readonly QaSkillAccess[];
|
|
19
|
+
}, roleId: string): {
|
|
20
|
+
alwaysTools: string[];
|
|
21
|
+
grantable: string[];
|
|
22
|
+
denied: string[];
|
|
23
|
+
via: Map<string, string[]>;
|
|
24
|
+
managed: string[];
|
|
25
|
+
declared: string[];
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=capability-selection.d.ts.map
|
|
@@ -19,6 +19,37 @@ export declare function useRequestSlot(): {
|
|
|
19
19
|
readonly start: () => AbortController;
|
|
20
20
|
readonly cancel: () => void;
|
|
21
21
|
};
|
|
22
|
+
/**
|
|
23
|
+
* How long a page waits for one Host answer before it stops waiting.
|
|
24
|
+
*
|
|
25
|
+
* The aggregate pages read conversation logs on the Host, and a log the store
|
|
26
|
+
* cannot answer for used to leave the request pending forever: the page then sat
|
|
27
|
+
* on «Загружаю…» with nothing to click. The Host bounds its own reads well
|
|
28
|
+
* inside this budget, so hitting it means the answer is lost, not that the
|
|
29
|
+
* deployment is merely slow.
|
|
30
|
+
*/
|
|
31
|
+
export declare const ADMIN_REQUEST_TIMEOUT_MS = 20000;
|
|
32
|
+
/** The copy a page shows once its deadline has passed. */
|
|
33
|
+
export declare function adminTimeoutMessage(timeoutMs?: number): string;
|
|
34
|
+
/** What one Host call did inside its deadline. */
|
|
35
|
+
export type BoundedOutcome<T> = {
|
|
36
|
+
readonly status: "ok";
|
|
37
|
+
readonly value: T;
|
|
38
|
+
} | {
|
|
39
|
+
readonly status: "timeout";
|
|
40
|
+
} | {
|
|
41
|
+
readonly status: "aborted";
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Run one Host call under a deadline.
|
|
45
|
+
*
|
|
46
|
+
* A promise that never settles is the shape of the hang this exists for, so the
|
|
47
|
+
* deadline is a race rather than an abort alone: aborting the request is what
|
|
48
|
+
* asks the Host to stop working, and the timer is what lets the page go on
|
|
49
|
+
* without an answer. The abandoned call keeps running on its own; its eventual
|
|
50
|
+
* rejection is observed here so it never surfaces as an unhandled one.
|
|
51
|
+
*/
|
|
52
|
+
export declare function callWithDeadline<T>(call: (signal: AbortSignal) => Promise<T>, outer: AbortSignal, timeoutMs?: number): Promise<BoundedOutcome<T>>;
|
|
22
53
|
/**
|
|
23
54
|
* Load one administrative resource, keeping the previous value visible while
|
|
24
55
|
* it refreshes. Reviewers page through lists while new conversations arrive;
|
|
@@ -26,8 +57,15 @@ export declare function useRequestSlot(): {
|
|
|
26
57
|
*
|
|
27
58
|
* `load` receives the cancellation of the call it is making: pass it on to the
|
|
28
59
|
* Remote, and a page the reviewer left stops being read on the server.
|
|
60
|
+
*
|
|
61
|
+
* The call is bounded by {@link ADMIN_REQUEST_TIMEOUT_MS}: a Host that does not
|
|
62
|
+
* answer leaves a stated error and a retry instead of an endless «Загружаю…».
|
|
63
|
+
* Whatever this page already held stays on screen — a partial answer is what a
|
|
64
|
+
* reviewer can still work with.
|
|
29
65
|
*/
|
|
30
|
-
export declare function useAdminResource<T>(load: (signal: AbortSignal) => Promise<RemoteResult<T>>, deps: readonly unknown[]
|
|
66
|
+
export declare function useAdminResource<T>(load: (signal: AbortSignal) => Promise<RemoteResult<T>>, deps: readonly unknown[], options?: {
|
|
67
|
+
readonly timeoutMs?: number;
|
|
68
|
+
}): {
|
|
31
69
|
readonly data: T | undefined;
|
|
32
70
|
readonly error: string | undefined;
|
|
33
71
|
readonly loading: boolean;
|
|
@@ -5,6 +5,8 @@ export interface QaAuthGateProps {
|
|
|
5
5
|
readonly title: string;
|
|
6
6
|
readonly logoUrl: string | null;
|
|
7
7
|
readonly allowRegistration: boolean;
|
|
8
|
+
readonly localLogin?: boolean;
|
|
9
|
+
readonly oidcLabel?: string | null;
|
|
8
10
|
}
|
|
9
11
|
/**
|
|
10
12
|
* The full-frame login/registration card shown instead of the chat while the
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { QaFormAnswer, QaFormItem as Item, QaFormAttachment, QaFormUpload } from "../../forms/types.js";
|
|
2
|
+
interface Props {
|
|
3
|
+
item: Item;
|
|
4
|
+
answer: QaFormAnswer | null;
|
|
5
|
+
files: QaFormAttachment[];
|
|
6
|
+
uploads: QaFormUpload[];
|
|
7
|
+
disabled: boolean;
|
|
8
|
+
onAnswer(answer: QaFormAnswer | null): void;
|
|
9
|
+
onUpload(file: File, target?: {
|
|
10
|
+
attachment_id: string;
|
|
11
|
+
version: number;
|
|
12
|
+
}): void;
|
|
13
|
+
onRemove(file: QaFormAttachment): void;
|
|
14
|
+
onCancel(upload: QaFormUpload): void;
|
|
15
|
+
onOpen(file: QaFormAttachment): void;
|
|
16
|
+
}
|
|
17
|
+
/** Input requirements are separate from file requirements, including in the labels. */
|
|
18
|
+
export declare function QaFormItem(props: Props): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=QaFormItem.d.ts.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { QaFormView } from "../../forms/types.js";
|
|
2
|
+
import { type QaFormApi } from "../forms.js";
|
|
3
|
+
interface Props {
|
|
4
|
+
policy?: Readonly<import("../../forms/types.js").QaFormPolicy>;
|
|
5
|
+
api: QaFormApi;
|
|
6
|
+
session: string;
|
|
7
|
+
token: string;
|
|
8
|
+
form: QaFormView;
|
|
9
|
+
canStop: boolean;
|
|
10
|
+
onStop(): Promise<void>;
|
|
11
|
+
onResume(id: string): void;
|
|
12
|
+
onTakeover(active: boolean): void;
|
|
13
|
+
}
|
|
14
|
+
export declare function QaInputForm(props: Props): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
/** Session/identity-keyed parent discards account-local state and aborts transfers on switch. */
|
|
16
|
+
export declare function QaInputForms(props: Omit<Props, "form">): import("react/jsx-runtime").JSX.Element | null;
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=QaInputForm.d.ts.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const QA_FORM_STYLES = "\n.dsh-qa-form{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:12px;padding:16px;max-height:75vh;overflow:hidden;overflow-wrap:anywhere;color:var(--dsw-alias-label-primary);display:flex;flex-direction:column}\n.dsh-qa-form__content{overflow:auto;min-height:0;padding:0 2px}.dsh-qa-form>header,.dsh-qa-form>footer,.dsh-qa-form>nav,.dsh-qa-form>p{flex-shrink:0}.dsh-qa-form>footer{border-top:1px solid var(--dsw-alias-border-l2);padding-top:12px;margin-top:8px}\n.dsh-qa-form>header{max-height:96px;overflow:auto}\n.dsh-qa-form header,.dsh-qa-form footer,.dsh-qa-form nav{display:flex;gap:8px;align-items:center;flex-wrap:wrap}\n.dsh-qa-form header{justify-content:space-between}.dsh-qa-form nav{margin:12px 0}.dsh-qa-form h3{margin:12px 0}\n.dsh-qa-form button{font:inherit;color:inherit;background:var(--dsw-alias-bg-layer-3);border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:8px 12px;cursor:pointer}\n.dsh-qa-form button:disabled{opacity:.55;cursor:default}.dsh-qa-form button:focus-visible,.dsh-qa-form input:focus-visible,.dsh-qa-form textarea:focus-visible{outline:var(--dsw-focus-ring-width,2px) solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:2px}\n.dsh-qa-form__item{min-width:0;border:0;border-bottom:1px solid var(--dsw-alias-border-l2);padding:12px 0;margin:0 0 12px}.dsh-qa-form legend{font-weight:600}.dsh-qa-form small{font-weight:400;display:block;color:var(--dsw-alias-label-tertiary)}\n.dsh-qa-form__hint{font-size:13px;color:var(--dsw-alias-label-secondary)}.dsh-qa-form label{display:block}.dsh-qa-form input[type=text],.dsh-qa-form textarea{display:block;box-sizing:border-box;width:100%;font:inherit;color:inherit;background:var(--dsw-alias-bg-layer-3);border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:10px;margin:6px 0}\n.dsh-qa-form__choices>label{display:flex;gap:8px;align-items:baseline;margin:8px 0}.dsh-qa-form__files{border:1px dashed var(--dsw-alias-border-l2);border-radius:8px;padding:12px;margin-top:12px}.dsh-qa-form input[type=file]{max-width:100%;display:block;margin:8px 0}.dsh-qa-form__files ul{padding-left:18px}.dsh-qa-form__files li{margin:10px 0}.dsh-qa-form__files button{margin:4px}.dsh-qa-form__review>div{border-bottom:1px solid var(--dsw-alias-border-l2);margin-bottom:12px}.dsh-qa-form [role=alert]{color:var(--dsw-alias-label-primary);border:1px solid var(--dsw-alias-border-l2);padding:10px;border-radius:8px}\n@media(max-width:600px){.dsh-qa-form{padding:12px;max-height:80vh}.dsh-qa-form footer button{flex:1 1 auto}.dsh-qa-form nav button{font-size:12px}}\n";
|
|
2
|
+
//# sourceMappingURL=forms-styles.d.ts.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { QaFormCommand, QaFormResult, QaFormView } from "../forms/types.js";
|
|
2
|
+
import type { RemoteResult } from "./types.js";
|
|
3
|
+
import type { QaUploadCarrier } from "./account-upload.js";
|
|
4
|
+
/** Typert adds an outer transport result; domain refusals remain stable codes. */
|
|
5
|
+
export interface QaFormApi {
|
|
6
|
+
list(token: string, session: string): Promise<RemoteResult<QaFormResult<QaFormView[]>>>;
|
|
7
|
+
get(token: string, session: string, id: string): Promise<RemoteResult<QaFormResult<QaFormView>>>;
|
|
8
|
+
mutate(token: string, session: string, command: QaFormCommand): Promise<RemoteResult<QaFormResult<QaFormView>>>;
|
|
9
|
+
upload(token: string, session: string, id: string, file: File, signal: AbortSignal): Promise<void>;
|
|
10
|
+
file(token: string, session: string, formId: string, resourceId: string): Promise<RemoteResult<QaFormResult<{
|
|
11
|
+
name: string;
|
|
12
|
+
media_type: string;
|
|
13
|
+
data: string;
|
|
14
|
+
}>>>;
|
|
15
|
+
}
|
|
16
|
+
export declare class QaFormClientError extends Error {
|
|
17
|
+
readonly code: string;
|
|
18
|
+
constructor(code: string, message: string);
|
|
19
|
+
}
|
|
20
|
+
export declare function unwrapForm<T>(result: RemoteResult<QaFormResult<T>>): T;
|
|
21
|
+
/** Same protected carrier and route as ordinary QA uploads; no fabricated percentage. */
|
|
22
|
+
export declare function uploadQaFormFile(carrier: QaUploadCarrier | undefined, token: string, session: string, uploadId: string, file: File, signal: AbortSignal): Promise<void>;
|
|
23
|
+
//# sourceMappingURL=forms.d.ts.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { QaOidcStart, ResolvedQaSurfaceConfig } from "../types.js";
|
|
2
|
+
export interface QaOidcBrowser {
|
|
3
|
+
begin(start: QaOidcStart): void;
|
|
4
|
+
takeHandoff(): {
|
|
5
|
+
handoff: string;
|
|
6
|
+
completionKey: string;
|
|
7
|
+
} | null;
|
|
8
|
+
logout(url: string): void;
|
|
9
|
+
}
|
|
10
|
+
/** Completion proof is isolated to the initiating tab and never goes in a URL. */
|
|
11
|
+
export declare function createQaOidcBrowser(browser: Pick<Window, "location" | "history" | "sessionStorage">, config: () => ResolvedQaSurfaceConfig): QaOidcBrowser;
|
|
12
|
+
//# sourceMappingURL=oidc-browser.d.ts.map
|
|
@@ -5,7 +5,10 @@ import type { QaAccountNotificationsInput, QaAccountProfileInput, QaAccountSessi
|
|
|
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. */
|
|
8
|
-
export type QaSessions = ISessions
|
|
8
|
+
export type QaSessions = ISessions & {
|
|
9
|
+
/** Register an exact id admitted by authenticated QA create/read before retain. */
|
|
10
|
+
rememberAdmitted?(sessionId: string): void;
|
|
11
|
+
};
|
|
9
12
|
/** Narrow client API slice used to pin the preset and model of a fresh chat. */
|
|
10
13
|
export type QaSessionsApi = {
|
|
11
14
|
selectModel: ClientRemote["session"]["selectModel"];
|
|
@@ -351,6 +354,9 @@ export interface QaAccountsApi {
|
|
|
351
354
|
accountsSetServiceTokenClarifications?(token: string, tokenId: string, allowed: boolean): Promise<RemoteResult<{
|
|
352
355
|
readonly updated: boolean;
|
|
353
356
|
}>>;
|
|
357
|
+
accountsOidcStart?(): Promise<RemoteResult<import("../types.js").QaOidcStart>>;
|
|
358
|
+
accountsOidcComplete?(handoff: string, completionKey: string): Promise<RemoteResult<QaAccountSession>>;
|
|
359
|
+
accountsOidcLogout?(token: string): Promise<RemoteResult<string | null>>;
|
|
354
360
|
chatVisible?(token: string): Promise<RemoteResult<readonly import("../chat-sharing/types.js").QaChatAccess[]>>;
|
|
355
361
|
accountsWhoami(token: string): Promise<RemoteResult<QaWhoamiResult>>;
|
|
356
362
|
accountsLogin(email: string, password: string): Promise<RemoteResult<QaAccountSession>>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { QaFormService } from "./service.js";
|
|
3
|
+
import type { QaFormRecord, QaFormSubmission } from "./types.js";
|
|
4
|
+
declare const fileRef: z.ZodObject<{
|
|
5
|
+
attachmentId: z.ZodString;
|
|
6
|
+
name: z.ZodString;
|
|
7
|
+
bytes: z.ZodNumber;
|
|
8
|
+
}, z.core.$strip>;
|
|
9
|
+
type FileRef = z.infer<typeof fileRef>;
|
|
10
|
+
/** Structural port to the installed Host; receipt data is runtime-validated. */
|
|
11
|
+
export interface QaFormHostAttachments {
|
|
12
|
+
readonly root: string;
|
|
13
|
+
readFileStream(file: FileRef, signal?: AbortSignal): AsyncIterable<Uint8Array>;
|
|
14
|
+
saveFile(input: {
|
|
15
|
+
data: Uint8Array;
|
|
16
|
+
name: string;
|
|
17
|
+
}): Promise<unknown>;
|
|
18
|
+
fileHostPath(file: FileRef): string | undefined;
|
|
19
|
+
validateImage?(input: {
|
|
20
|
+
data: Uint8Array;
|
|
21
|
+
mediaType: "image/png" | "image/jpeg";
|
|
22
|
+
name: string;
|
|
23
|
+
}): Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
export declare function validateFormFile(name: string, data: Buffer): string;
|
|
26
|
+
/** Durable bytes belong to the form store; Host objects are verified reader projections. */
|
|
27
|
+
export declare class QaFormAttachmentAdapter {
|
|
28
|
+
private readonly service;
|
|
29
|
+
private readonly host;
|
|
30
|
+
constructor(service: () => QaFormService, host: () => QaFormHostAttachments | undefined);
|
|
31
|
+
available(): boolean;
|
|
32
|
+
check(session: string, formId: string, uploadId: string): void;
|
|
33
|
+
claim(session: string, uploadId: string): {
|
|
34
|
+
record: QaFormRecord;
|
|
35
|
+
upload: QaFormRecord["uploads"][number];
|
|
36
|
+
};
|
|
37
|
+
complete(session: string, formId: string, uploadId: string, raw: unknown, signal: AbortSignal, authorize: () => void): Promise<QaFormRecord>;
|
|
38
|
+
fail(session: string, formId: string, uploadId: string): void;
|
|
39
|
+
/** Exact saved bytes are re-projected through the Host on each successful resume. */
|
|
40
|
+
readable(submission: QaFormSubmission): Promise<QaFormSubmission & {
|
|
41
|
+
resources: {
|
|
42
|
+
resource_id: string;
|
|
43
|
+
read_path: string;
|
|
44
|
+
}[];
|
|
45
|
+
}>;
|
|
46
|
+
}
|
|
47
|
+
export {};
|
|
48
|
+
//# sourceMappingURL=attachments.d.ts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { QaFormFieldError, QaFormResult } from "./types.js";
|
|
2
|
+
export declare class QaFormError extends Error {
|
|
3
|
+
readonly code: string;
|
|
4
|
+
readonly revision?: number | undefined;
|
|
5
|
+
readonly fields?: QaFormFieldError[] | undefined;
|
|
6
|
+
constructor(code: string, message: string, revision?: number | undefined, fields?: QaFormFieldError[] | undefined);
|
|
7
|
+
}
|
|
8
|
+
/** Deliberately redact unexpected storage/Host exceptions at the wire boundary. */
|
|
9
|
+
export declare function formFailure(error: unknown): QaFormResult<never>;
|
|
10
|
+
export declare function formAssert(condition: unknown, code: string, message: string): asserts condition;
|
|
11
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stable object-key ordering for schema and idempotency fingerprints.
|
|
3
|
+
*
|
|
4
|
+
* Lives apart from the sqlite store so every store implementation hashes the
|
|
5
|
+
* same way without importing the sqlite bridge: the client test graph mounts a
|
|
6
|
+
* store too, and a browser environment must not see `@yadsh/dsh-plugin-kit/sqlite`.
|
|
7
|
+
*/
|
|
8
|
+
export declare function fingerprint(value: unknown): string;
|
|
9
|
+
//# sourceMappingURL=fingerprint.d.ts.map
|