@yadsh/dsh-qa-surface 0.1.1 → 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 +151 -0
- package/README.md +239 -16
- package/SPEC-dsh-qa-surface.md +600 -96
- package/capability-policy.json +5 -0
- package/compatibility.json +18 -4
- package/cordis.patch.yml +11 -0
- package/docs/ARCHITECTURE.md +50 -8
- package/docs/COMPATIBILITY.md +5 -4
- package/docs/CONFIGURATION.md +184 -3
- 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 +10 -0
- package/lib/attestation.js.map +1 -0
- 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/QaConfigController.js +111 -4
- package/lib/client/QaConfigController.js.map +1 -1
- package/lib/client/QaSessionController.js +621 -163
- package/lib/client/QaSessionController.js.map +1 -1
- package/lib/client/QaSurface.js +303 -24
- package/lib/client/QaSurface.js.map +1 -1
- package/lib/client/QaTranscriptAdapter.js +324 -49
- package/lib/client/QaTranscriptAdapter.js.map +1 -1
- package/lib/client/attestation.js +66 -0
- package/lib/client/attestation.js.map +1 -0
- package/lib/client/chat-index.js +86 -0
- package/lib/client/chat-index.js.map +1 -0
- package/lib/client/components/Markdown.js +124 -13
- package/lib/client/components/Markdown.js.map +1 -1
- package/lib/client/components/QaAgentsDrawer.js +40 -0
- package/lib/client/components/QaAgentsDrawer.js.map +1 -0
- 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/QaComposer.js +132 -15
- package/lib/client/components/QaComposer.js.map +1 -1
- package/lib/client/components/QaMessage.js +214 -10
- package/lib/client/components/QaMessage.js.map +1 -1
- package/lib/client/components/QaSidebar.js +167 -0
- package/lib/client/components/QaSidebar.js.map +1 -0
- package/lib/client/components/QaSourcesDrawer.js +127 -0
- package/lib/client/components/QaSourcesDrawer.js.map +1 -0
- 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/QaWorkGroup.js +135 -0
- package/lib/client/components/QaWorkGroup.js.map +1 -0
- package/lib/client/components/VariantSwitcher.js +29 -0
- package/lib/client/components/VariantSwitcher.js.map +1 -0
- package/lib/client/components/format.js +48 -0
- package/lib/client/components/format.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 +166 -35
- 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 +450 -43
- 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 +15 -0
- package/lib/client/types.js.map +1 -0
- 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/wait-for.js +49 -0
- package/lib/client/wait-for.js.map +1 -0
- package/lib/client.js +12551 -918
- package/lib/client.js.map +1 -1
- package/lib/config.js +226 -58
- 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 +354 -72
- package/lib/index.js.map +1 -1
- package/lib/launch-token.js +42 -0
- package/lib/launch-token.js.map +1 -0
- package/lib/lockdown-policy.js +20 -0
- package/lib/lockdown-policy.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 +283 -10
- package/lib/resolve-config.js.map +1 -1
- package/lib/secure-session.js +212 -0
- package/lib/secure-session.js.map +1 -0
- package/lib/typert.host.d.ts +3 -0
- package/lib/typert.host.js +784 -0
- package/lib/typert.remote-client.d.ts +40 -0
- package/lib/typert.remote-client.js +597 -0
- package/lib/types/accounts/index.d.ts +2 -0
- package/lib/types/accounts/store.d.ts +121 -0
- package/lib/types/attestation.d.ts +17 -0
- package/lib/types/cli.d.ts +9 -0
- package/lib/types/client/QaAccountsController.d.ts +95 -0
- package/lib/types/client/QaConfigController.d.ts +35 -3
- package/lib/types/client/QaSessionController.d.ts +146 -20
- package/lib/types/client/QaSurface.d.ts +11 -5
- package/lib/types/client/QaTranscriptAdapter.d.ts +13 -3
- package/lib/types/client/attestation.d.ts +25 -0
- package/lib/types/client/chat-index.d.ts +28 -0
- package/lib/types/client/components/Markdown.d.ts +17 -3
- package/lib/types/client/components/QaAgentsDrawer.d.ts +25 -0
- 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/QaComposer.d.ts +12 -2
- package/lib/types/client/components/QaMessage.d.ts +22 -2
- package/lib/types/client/components/QaSidebar.d.ts +69 -0
- package/lib/types/client/components/QaSourcesDrawer.d.ts +20 -0
- 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/QaWorkGroup.d.ts +19 -0
- package/lib/types/client/components/VariantSwitcher.d.ts +19 -0
- package/lib/types/client/components/format.d.ts +9 -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 +2 -5
- 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 +93 -0
- 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/client/wait-for.d.ts +11 -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 +67 -7
- package/lib/types/launch-token.d.ts +21 -0
- package/lib/types/lockdown-policy.d.ts +18 -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 +31 -0
- package/lib/types/types.d.ts +304 -1
- package/package.json +70 -27
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/** http(s) URLs only, case-folded authority, hash and trailing slash gone. */
|
|
2
|
+
function normalizeUrl(value) {
|
|
3
|
+
try {
|
|
4
|
+
const url = new URL(value);
|
|
5
|
+
if (url.protocol !== "http:" && url.protocol !== "https:")
|
|
6
|
+
return undefined;
|
|
7
|
+
url.hash = "";
|
|
8
|
+
if (url.pathname.length > 1) {
|
|
9
|
+
url.pathname = url.pathname.replace(/\/+$/u, "");
|
|
10
|
+
}
|
|
11
|
+
return `${url.protocol}//${url.host.toLowerCase()}${url.pathname}${url.search}`;
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/** Separators normalized for comparison, not for display. */
|
|
18
|
+
function normalizePath(value) {
|
|
19
|
+
return value.trim().replace(/\\/gu, "/").replace(/\/+$/u, "").toLowerCase();
|
|
20
|
+
}
|
|
21
|
+
function basename(value) {
|
|
22
|
+
const slash = value.lastIndexOf("/");
|
|
23
|
+
return slash < 0 ? value : value.slice(slash + 1);
|
|
24
|
+
}
|
|
25
|
+
/** Display name for a file-backed source: the file name alone, case kept. */
|
|
26
|
+
export function sourceFileName(source) {
|
|
27
|
+
const normalized = (source.path ?? source.uri ?? source.title)
|
|
28
|
+
.trim()
|
|
29
|
+
.replace(/\\/gu, "/");
|
|
30
|
+
const slash = normalized.lastIndexOf("/");
|
|
31
|
+
const name = slash < 0 ? normalized : normalized.slice(slash + 1);
|
|
32
|
+
return name === "" ? source.title : name;
|
|
33
|
+
}
|
|
34
|
+
const NO_REFS = {
|
|
35
|
+
signature: "",
|
|
36
|
+
resolveUrl: () => undefined,
|
|
37
|
+
resolvePath: () => undefined,
|
|
38
|
+
};
|
|
39
|
+
export function buildSourceRefs(sources) {
|
|
40
|
+
if (sources.length === 0)
|
|
41
|
+
return NO_REFS;
|
|
42
|
+
const byUrl = new Map();
|
|
43
|
+
const paths = [];
|
|
44
|
+
for (const source of sources) {
|
|
45
|
+
if (source.uri !== undefined) {
|
|
46
|
+
const key = normalizeUrl(source.uri);
|
|
47
|
+
if (key !== undefined)
|
|
48
|
+
byUrl.set(key, source);
|
|
49
|
+
}
|
|
50
|
+
if (source.path !== undefined) {
|
|
51
|
+
paths.push({ normalized: normalizePath(source.path), source });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
signature: sources.map((source) => source.id).join("|"),
|
|
56
|
+
resolveUrl(url) {
|
|
57
|
+
const key = normalizeUrl(url);
|
|
58
|
+
return key === undefined ? undefined : byUrl.get(key);
|
|
59
|
+
},
|
|
60
|
+
resolvePath(token) {
|
|
61
|
+
const normalized = normalizePath(token);
|
|
62
|
+
if (normalized === "")
|
|
63
|
+
return undefined;
|
|
64
|
+
const exact = paths.find((path) => path.normalized === normalized);
|
|
65
|
+
if (exact !== undefined)
|
|
66
|
+
return exact.source;
|
|
67
|
+
if (!normalized.includes("/")) {
|
|
68
|
+
// A bare file name is ambiguous the moment two sources share it.
|
|
69
|
+
const named = paths.filter((path) => basename(path.normalized) === normalized);
|
|
70
|
+
return named.length === 1 ? named[0]?.source : undefined;
|
|
71
|
+
}
|
|
72
|
+
// A partial directory path must stay unambiguous the same way.
|
|
73
|
+
const suffix = paths.filter((path) => path.normalized.endsWith(`/${normalized}`));
|
|
74
|
+
return suffix.length === 1 ? suffix[0]?.source : undefined;
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=source-refs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source-refs.js","sourceRoot":"","sources":["../../../src/client/components/source-refs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/** The wire failure's code plus its message — preset composition reasons (a
|
|
2
|
+
* broken loader entry, a missing tool) ride the message and never anywhere
|
|
3
|
+
* else, so collapsing to the code costs the operator the whole diagnosis. */
|
|
4
|
+
function wireFailure(error) {
|
|
5
|
+
const code = typeof error === "object" && error !== null && "code" in error
|
|
6
|
+
? String(error.code ?? "")
|
|
7
|
+
: "";
|
|
8
|
+
const message = typeof error === "object" && error !== null && "message" in error
|
|
9
|
+
? String(error.message ?? "")
|
|
10
|
+
: "";
|
|
11
|
+
return message === "" ? code : `${code}: ${message}`;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Create one Host session and pin the configured preset and model onto the
|
|
15
|
+
* still-blank session. The creation wire takes no preset, so
|
|
16
|
+
* agentPresets/select recomposes the agent and durably logs
|
|
17
|
+
* `agent-preset/selected`, which the client projection replays. The session
|
|
18
|
+
* is addressed only here — no prompt can run before the caller attests the
|
|
19
|
+
* composed preset.
|
|
20
|
+
*/
|
|
21
|
+
export async function createQaSession(args) {
|
|
22
|
+
const { sessions, api, config } = args;
|
|
23
|
+
const created = await sessions.create({
|
|
24
|
+
...(config.session.workspaceId !== null
|
|
25
|
+
? { workspaceId: config.session.workspaceId }
|
|
26
|
+
: config.session.cwd !== null
|
|
27
|
+
? { cwd: config.session.cwd }
|
|
28
|
+
: {}),
|
|
29
|
+
});
|
|
30
|
+
const id = String(created);
|
|
31
|
+
if (config.session.agentPreset !== null) {
|
|
32
|
+
const selectedPreset = await api.selectAgentPreset(id, config.session.agentPreset);
|
|
33
|
+
if (!selectedPreset.ok) {
|
|
34
|
+
throw new Error(wireFailure(selectedPreset.error));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (config.session.provider !== null && config.session.model !== null) {
|
|
38
|
+
const selected = await api.selectModel({
|
|
39
|
+
sessionId: id,
|
|
40
|
+
provider: config.session.provider,
|
|
41
|
+
model: config.session.model,
|
|
42
|
+
...(config.session.reasoningEffort === null
|
|
43
|
+
? {}
|
|
44
|
+
: { reasoningEffort: config.session.reasoningEffort }),
|
|
45
|
+
});
|
|
46
|
+
if (!selected.ok)
|
|
47
|
+
throw new Error(wireFailure(selected.error));
|
|
48
|
+
}
|
|
49
|
+
return id;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=create-session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-session.js","sourceRoot":"","sources":["../../src/client/create-session.ts"],"names":[],"mappings":"AAKA;;6EAE6E;AAC7E,SAAS,WAAW,CAAC,KAAc;IACjC,MAAM,IAAI,GACR,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,IAAI,KAAK;QAC5D,CAAC,CAAC,MAAM,CAAE,KAA4B,CAAC,IAAI,IAAI,EAAE,CAAC;QAClD,CAAC,CAAC,EAAE,CAAC;IACT,MAAM,OAAO,GACX,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,SAAS,IAAI,KAAK;QAC/D,CAAC,CAAC,MAAM,CAAE,KAA+B,CAAC,OAAO,IAAI,EAAE,CAAC;QACxD,CAAC,CAAC,EAAE,CAAC;IACT,OAAO,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,OAAO,EAAE,CAAC;AACvD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAIrC;IACC,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACvC,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;QACpC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,KAAK,IAAI;YACrC,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,OAAO,CAAC,WAA0B,EAAE;YAC5D,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,KAAK,IAAI;gBAC3B,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE;gBAC7B,CAAC,CAAC,EAAE,CAAC;KACV,CAAC,CAAC;IACH,MAAM,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAC3B,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,KAAK,IAAI,EAAE,CAAC;QACxC,MAAM,cAAc,GAAG,MAAM,GAAG,CAAC,iBAAiB,CAChD,EAAe,EACf,MAAM,CAAC,OAAO,CAAC,WAAW,CAC3B,CAAC;QACF,IAAI,CAAC,cAAc,CAAC,EAAE,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,WAAW,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IACD,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,KAAK,IAAI,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;QACtE,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,WAAW,CAAC;YACrC,SAAS,EAAE,EAAe;YAC1B,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,QAAQ;YACjC,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,KAAK;YAC3B,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,eAAe,KAAK,IAAI;gBACzC,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC,EAAE,eAAe,EAAE,MAAM,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC;SACzD,CAAC,CAAC;QACH,IAAI,CAAC,QAAQ,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC"}
|
package/lib/client/index.js
CHANGED
|
@@ -1,45 +1,176 @@
|
|
|
1
|
+
import qaSurfaceRemote from "@yadsh/dsh-qa-surface/remote";
|
|
1
2
|
import { QaConfigController } from "./QaConfigController.js";
|
|
2
|
-
import { QaRouteController } from "./QaRouteController.js";
|
|
3
|
+
import { matchesQaRoute, QaRouteController } from "./QaRouteController.js";
|
|
4
|
+
import { QaAccountsController } from "./QaAccountsController.js";
|
|
5
|
+
import { QaChatIndex } from "./chat-index.js";
|
|
3
6
|
import { QaSurface } from "./QaSurface.js";
|
|
7
|
+
import { QaWelcomeNoticeStep } from "./components/QaWelcomeNotice.js";
|
|
4
8
|
import { QA_SURFACE_STYLES } from "./styles.js";
|
|
5
9
|
const SETTINGS_NAMESPACE = "qa-surface";
|
|
6
|
-
|
|
10
|
+
const QA_WELCOME_SLOT_ID = "welcome-notice";
|
|
11
|
+
function qaWelcomeStorageKey(config) {
|
|
12
|
+
return `${config.session.storageKey}:v1:${config.route.path}:welcome-notice`;
|
|
13
|
+
}
|
|
14
|
+
export const inject = [
|
|
15
|
+
"slots",
|
|
16
|
+
"sessions",
|
|
17
|
+
"uiConversation",
|
|
18
|
+
"connection",
|
|
19
|
+
"settingsScope",
|
|
20
|
+
"remote",
|
|
21
|
+
];
|
|
7
22
|
/** Register the route-aware, full-frame QA entry in the additive overlay slot. */
|
|
8
|
-
export function apply(ctx) {
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
23
|
+
export async function apply(ctx) {
|
|
24
|
+
const remote = ctx.remote;
|
|
25
|
+
const disposeRemote = await remote.$mount(qaSurfaceRemote);
|
|
26
|
+
await ctx.inject(["remote.qaSurface", "remote.session", "remote.agentPresets"], (remoteContext) => {
|
|
27
|
+
const injectedRemote = remoteContext.remote;
|
|
28
|
+
const policyRemote = injectedRemote.qaSurface;
|
|
29
|
+
const secureSession = (token, sessionId) => policyRemote.secureSession(token, sessionId);
|
|
30
|
+
const qaApi = {
|
|
31
|
+
selectModel: (request) => injectedRemote.session.selectModel(request),
|
|
32
|
+
selectAgentPreset: (agentId, agentPreset) => injectedRemote.agentPresets.select(agentId, agentPreset),
|
|
33
|
+
};
|
|
34
|
+
const sourceApi = {
|
|
35
|
+
sources: (token, sessionId) => policyRemote.sources(token, sessionId),
|
|
36
|
+
readSourceFile: (token, sessionId, sourcePath) => policyRemote.readSourceFile(token, sessionId, sourcePath),
|
|
37
|
+
};
|
|
38
|
+
// The account gate rides its own remote; a stale token simply answers
|
|
39
|
+
// "not authenticated" and the browser shows the login card.
|
|
40
|
+
const accounts = new QaAccountsController({
|
|
41
|
+
remote: policyRemote,
|
|
42
|
+
storage: window.localStorage,
|
|
43
|
+
config: () => config.getSnapshot().config,
|
|
44
|
+
legacyChatIds: () => {
|
|
45
|
+
// A standalone index view over the same prefix: reads the chat ids
|
|
46
|
+
// this browser accumulated before accounts existed.
|
|
47
|
+
const snapshot = config.getSnapshot().config;
|
|
48
|
+
const index = new QaChatIndex(window.localStorage, `${snapshot.session.storageKey}:v1:${snapshot.route.path}`);
|
|
49
|
+
const ids = [...index.chatIds()];
|
|
50
|
+
const active = index.activeId();
|
|
51
|
+
if (active !== null && !ids.includes(active))
|
|
52
|
+
ids.push(active);
|
|
53
|
+
return ids;
|
|
54
|
+
},
|
|
55
|
+
forgetChat: (sessionId) => {
|
|
56
|
+
const snapshot = config.getSnapshot().config;
|
|
57
|
+
new QaChatIndex(window.localStorage, `${snapshot.session.storageKey}:v1:${snapshot.route.path}`).forgetChat(sessionId);
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
const route = new QaRouteController();
|
|
61
|
+
const config = new QaConfigController(ctx.settingsScope.bind({
|
|
62
|
+
namespace: SETTINGS_NAMESPACE,
|
|
63
|
+
}), async () => {
|
|
64
|
+
// Settings RPCs are loopback-pinned by the gateway, so a browser the
|
|
65
|
+
// Host serves over the LAN reads the effective configuration here.
|
|
66
|
+
const described = await policyRemote.describe();
|
|
67
|
+
if (!described.ok) {
|
|
68
|
+
throw new Error(`qaSurface/describe failed: ${described.error.code}`);
|
|
69
|
+
}
|
|
70
|
+
// The generated self-remote resolves through the previous build's
|
|
71
|
+
// declarations during an incremental source typecheck.
|
|
72
|
+
return described.value;
|
|
73
|
+
});
|
|
74
|
+
const syncRoute = () => {
|
|
75
|
+
const snapshot = config.getSnapshot();
|
|
76
|
+
route.configure(snapshot.config, snapshot.status === "ready" || snapshot.status === "unavailable");
|
|
77
|
+
};
|
|
78
|
+
syncRoute();
|
|
79
|
+
const unsubscribeConfig = config.subscribe(syncRoute);
|
|
80
|
+
// After a Host restart an open page must re-read the deployment config,
|
|
81
|
+
// or the next attestation compares its proof against a stale copy and
|
|
82
|
+
// refuses. Loopback pages follow the settings mirror; this covers the
|
|
83
|
+
// describe fallback (LAN browsers). Fires on every lost→restored
|
|
84
|
+
// connection transition; while connected, ticks are ignored.
|
|
85
|
+
let connectionUp = ctx.connection.generation.getSnapshot() !== undefined;
|
|
86
|
+
const unsubscribeConnection = ctx.connection.generation.subscribe(() => {
|
|
87
|
+
const connected = ctx.connection.generation.getSnapshot() !== undefined;
|
|
88
|
+
if (connected && !connectionUp) {
|
|
89
|
+
config.refreshFallback();
|
|
90
|
+
// A boot-time whoami may have raced the lost connection; the
|
|
91
|
+
// controller no-ops unless it is still in the checking stage.
|
|
92
|
+
void accounts.start();
|
|
93
|
+
}
|
|
94
|
+
connectionUp = connected;
|
|
95
|
+
});
|
|
96
|
+
void accounts.start();
|
|
97
|
+
// The stock DSH welcome notice cannot persist its acknowledgement for
|
|
98
|
+
// non-loopback browsers. Shadow only its list-slot cell while the QA
|
|
99
|
+
// route is selected; leaving /qa immediately restores the host entry.
|
|
100
|
+
ctx.slots.inject("settings.onboarding", () => {
|
|
101
|
+
let removeEntry;
|
|
102
|
+
let mountedKey;
|
|
103
|
+
const reconcile = () => {
|
|
104
|
+
const configSnapshot = config.getSnapshot().config;
|
|
105
|
+
const routeSnapshot = route.getSnapshot();
|
|
106
|
+
const active = configSnapshot.enabled &&
|
|
107
|
+
matchesQaRoute(routeSnapshot.pathname, configSnapshot.route);
|
|
108
|
+
const nextKey = active
|
|
109
|
+
? qaWelcomeStorageKey(configSnapshot)
|
|
110
|
+
: undefined;
|
|
111
|
+
if (nextKey === mountedKey)
|
|
112
|
+
return;
|
|
113
|
+
removeEntry?.();
|
|
114
|
+
removeEntry = undefined;
|
|
115
|
+
mountedKey = nextKey;
|
|
116
|
+
if (nextKey === undefined)
|
|
117
|
+
return;
|
|
118
|
+
removeEntry = ctx.slots.register({
|
|
119
|
+
name: "settings.onboarding",
|
|
120
|
+
id: QA_WELCOME_SLOT_ID,
|
|
121
|
+
order: -100,
|
|
122
|
+
priority: -1_000,
|
|
123
|
+
inject: () => ({
|
|
124
|
+
storage: window.localStorage,
|
|
125
|
+
storageKey: nextKey,
|
|
126
|
+
}),
|
|
127
|
+
}, QaWelcomeNoticeStep);
|
|
128
|
+
};
|
|
129
|
+
reconcile();
|
|
130
|
+
const unsubscribeRoute = route.subscribe(reconcile);
|
|
131
|
+
const unsubscribeConfig = config.subscribe(reconcile);
|
|
132
|
+
return () => {
|
|
133
|
+
unsubscribeRoute();
|
|
134
|
+
unsubscribeConfig();
|
|
135
|
+
removeEntry?.();
|
|
136
|
+
};
|
|
137
|
+
});
|
|
138
|
+
ctx.effect(() => {
|
|
139
|
+
const style = document.createElement("style");
|
|
140
|
+
style.dataset.dshQaSurface = "styles";
|
|
141
|
+
style.textContent = QA_SURFACE_STYLES;
|
|
142
|
+
document.head.append(style);
|
|
143
|
+
return () => style.remove();
|
|
144
|
+
}, "dsh-qa-surface: styles");
|
|
145
|
+
ctx.effect(() => () => {
|
|
146
|
+
unsubscribeConfig();
|
|
147
|
+
unsubscribeConnection();
|
|
148
|
+
config.dispose();
|
|
149
|
+
route.dispose();
|
|
150
|
+
}, "dsh-qa-surface: controllers");
|
|
151
|
+
ctx.slots.inject("shell.overlay", () => ctx.slots.register({
|
|
152
|
+
name: "shell.overlay",
|
|
153
|
+
id: "dsh-qa-surface",
|
|
154
|
+
order: -10_000,
|
|
155
|
+
inject: () => ({
|
|
156
|
+
route,
|
|
157
|
+
config,
|
|
158
|
+
// The host dsh-session merge types ctx.sessions as SessionStore in
|
|
159
|
+
// this program; the client assembly provides the ISessions face.
|
|
160
|
+
sessions: ctx.sessions,
|
|
161
|
+
conversation: ctx.uiConversation,
|
|
162
|
+
api: qaApi,
|
|
163
|
+
connection: ctx.connection.generation,
|
|
164
|
+
secureSession,
|
|
165
|
+
sourceApi,
|
|
166
|
+
accounts,
|
|
167
|
+
}),
|
|
168
|
+
}, QaSurface));
|
|
169
|
+
});
|
|
170
|
+
return disposeRemote;
|
|
41
171
|
}
|
|
42
172
|
export { QaConfigController } from "./QaConfigController.js";
|
|
173
|
+
export { QaAccountsController } from "./QaAccountsController.js";
|
|
43
174
|
export { QaRouteController, matchesQaRoute } from "./QaRouteController.js";
|
|
44
175
|
export { QaSessionController } from "./QaSessionController.js";
|
|
45
176
|
export { projectTranscript } from "./QaTranscriptAdapter.js";
|
package/lib/client/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.tsx"],"names":[],"mappings":"AAIA,OAAO,eAAe,MAAM,8BAA8B,CAAC;AAQ3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAOtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAWhD,MAAM,kBAAkB,GAAG,YAAY,CAAC;AA2DxC,MAAM,kBAAkB,GAAG,gBAAgB,CAAC;AAE5C,SAAS,mBAAmB,CAAC,MAA+B;IAC1D,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,iBAAiB,CAAC;AAC/E,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,OAAO;IACP,UAAU;IACV,gBAAgB;IAChB,YAAY;IACZ,eAAe;IACf,QAAQ;CACT,CAAC;AAEF,kFAAkF;AAClF,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,GAAY;IACtC,MAAM,MAAM,GAAG,GAAG,CAAC,MAAwB,CAAC;IAC5C,MAAM,aAAa,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;IAC3D,MAAM,GAAG,CAAC,MAAM,CACd,CAAC,kBAAkB,EAAE,gBAAgB,EAAE,qBAAqB,CAAC,EAC7D,CAAC,aAAa,EAAE,EAAE;QAChB,MAAM,cAAc,GAAG,aAAa,CAAC,MAAwB,CAAC;QAC9D,MAAM,YAAY,GAAG,cAAc,CAAC,SAAS,CAAC;QAC9C,MAAM,aAAa,GAAoB,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,CAC1D,YAAY,CAAC,aAAa,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QAC/C,MAAM,KAAK,GAAkB;YAC3B,WAAW,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,cAAc,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC;YACrE,iBAAiB,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,CAC1C,cAAc,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,EAAE,WAAW,CAAC;SAC3D,CAAC;QACF,MAAM,SAAS,GAAgB;YAC7B,OAAO,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,CAC5B,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,SAAS,CAEpC;YACH,cAAc,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,EAAE,CAC/C,YAAY,CAAC,cAAc,CACzB,KAAK,EACL,SAAS,EACT,UAAU,CAC6C;SAC5D,CAAC;QACF,sEAAsE;QACtE,4DAA4D;QAC5D,MAAM,QAAQ,GAAG,IAAI,oBAAoB,CAAC;YACxC,MAAM,EAAE,YAAY;YACpB,OAAO,EAAE,MAAM,CAAC,YAAY;YAC5B,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,MAAM;YACzC,aAAa,EAAE,GAAG,EAAE;gBAClB,mEAAmE;gBACnE,oDAAoD;gBACpD,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC;gBAC7C,MAAM,KAAK,GAAG,IAAI,WAAW,CAC3B,MAAM,CAAC,YAAY,EACnB,GAAG,QAAQ,CAAC,OAAO,CAAC,UAAU,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAC3D,CAAC;gBACF,MAAM,GAAG,GAAG,CAAC,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;gBACjC,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;gBAChC,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC;oBAAE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBAC/D,OAAO,GAAG,CAAC;YACb,CAAC;YACD,UAAU,EAAE,CAAC,SAAS,EAAE,EAAE;gBACxB,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC;gBAC7C,IAAI,WAAW,CACb,MAAM,CAAC,YAAY,EACnB,GAAG,QAAQ,CAAC,OAAO,CAAC,UAAU,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAC3D,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;YAC1B,CAAC;SACF,CAAC,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,iBAAiB,EAAE,CAAC;QACtC,MAAM,MAAM,GAAG,IAAI,kBAAkB,CAClC,GAAG,CAAC,aAAqC,CAAC,IAAI,CAAkB;YAC/D,SAAS,EAAE,kBAAkB;SAC9B,CAAC,EACF,KAAK,IAAI,EAAE;YACT,qEAAqE;YACrE,mEAAmE;YACnE,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,QAAQ,EAAE,CAAC;YAChD,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC;gBAClB,MAAM,IAAI,KAAK,CACb,8BAA8B,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,CACrD,CAAC;YACJ,CAAC;YACD,kEAAkE;YAClE,uDAAuD;YACvD,OAAO,SAAS,CAAC,KAA2C,CAAC;QAC/D,CAAC,CACF,CAAC;QACF,MAAM,SAAS,GAAG,GAAG,EAAE;YACrB,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;YACtC,KAAK,CAAC,SAAS,CACb,QAAQ,CAAC,MAAM,EACf,QAAQ,CAAC,MAAM,KAAK,OAAO,IAAI,QAAQ,CAAC,MAAM,KAAK,aAAa,CACjE,CAAC;QACJ,CAAC,CAAC;QACF,SAAS,EAAE,CAAC;QACZ,MAAM,iBAAiB,GAAG,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QACtD,wEAAwE;QACxE,sEAAsE;QACtE,sEAAsE;QACtE,iEAAiE;QACjE,6DAA6D;QAC7D,IAAI,YAAY,GAAG,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,WAAW,EAAE,KAAK,SAAS,CAAC;QACzE,MAAM,qBAAqB,GAAG,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC,GAAG,EAAE;YACrE,MAAM,SAAS,GAAG,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,WAAW,EAAE,KAAK,SAAS,CAAC;YACxE,IAAI,SAAS,IAAI,CAAC,YAAY,EAAE,CAAC;gBAC/B,MAAM,CAAC,eAAe,EAAE,CAAC;gBACzB,6DAA6D;gBAC7D,8DAA8D;gBAC9D,KAAK,QAAQ,CAAC,KAAK,EAAE,CAAC;YACxB,CAAC;YACD,YAAY,GAAG,SAAS,CAAC;QAC3B,CAAC,CAAC,CAAC;QACH,KAAK,QAAQ,CAAC,KAAK,EAAE,CAAC;QAEtB,sEAAsE;QACtE,qEAAqE;QACrE,sEAAsE;QACtE,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,qBAAqB,EAAE,GAAG,EAAE;YAC3C,IAAI,WAAqC,CAAC;YAC1C,IAAI,UAA8B,CAAC;YACnC,MAAM,SAAS,GAAG,GAAG,EAAE;gBACrB,MAAM,cAAc,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC;gBACnD,MAAM,aAAa,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;gBAC1C,MAAM,MAAM,GACV,cAAc,CAAC,OAAO;oBACtB,cAAc,CAAC,aAAa,CAAC,QAAQ,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC;gBAC/D,MAAM,OAAO,GAAG,MAAM;oBACpB,CAAC,CAAC,mBAAmB,CAAC,cAAc,CAAC;oBACrC,CAAC,CAAC,SAAS,CAAC;gBACd,IAAI,OAAO,KAAK,UAAU;oBAAE,OAAO;gBACnC,WAAW,EAAE,EAAE,CAAC;gBAChB,WAAW,GAAG,SAAS,CAAC;gBACxB,UAAU,GAAG,OAAO,CAAC;gBACrB,IAAI,OAAO,KAAK,SAAS;oBAAE,OAAO;gBAClC,WAAW,GAAG,GAAG,CAAC,KAAK,CAAC,QAAQ,CAC9B;oBACE,IAAI,EAAE,qBAAqB;oBAC3B,EAAE,EAAE,kBAAkB;oBACtB,KAAK,EAAE,CAAC,GAAG;oBACX,QAAQ,EAAE,CAAC,KAAK;oBAChB,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;wBACb,OAAO,EAAE,MAAM,CAAC,YAAY;wBAC5B,UAAU,EAAE,OAAO;qBACpB,CAAC;iBACH,EACD,mBAAmB,CACpB,CAAC;YACJ,CAAC,CAAC;YACF,SAAS,EAAE,CAAC;YACZ,MAAM,gBAAgB,GAAG,KAAK,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;YACpD,MAAM,iBAAiB,GAAG,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;YACtD,OAAO,GAAG,EAAE;gBACV,gBAAgB,EAAE,CAAC;gBACnB,iBAAiB,EAAE,CAAC;gBACpB,WAAW,EAAE,EAAE,CAAC;YAClB,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE;YACd,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;YAC9C,KAAK,CAAC,OAAO,CAAC,YAAY,GAAG,QAAQ,CAAC;YACtC,KAAK,CAAC,WAAW,GAAG,iBAAiB,CAAC;YACtC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC5B,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QAC9B,CAAC,EAAE,wBAAwB,CAAC,CAAC;QAE7B,GAAG,CAAC,MAAM,CACR,GAAG,EAAE,CAAC,GAAG,EAAE;YACT,iBAAiB,EAAE,CAAC;YACpB,qBAAqB,EAAE,CAAC;YACxB,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,CAAC,EACD,6BAA6B,CAC9B,CAAC;QAEF,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,eAAe,EAAE,GAAG,EAAE,CACrC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAChB;YACE,IAAI,EAAE,eAAe;YACrB,EAAE,EAAE,gBAAgB;YACpB,KAAK,EAAE,CAAC,MAAM;YACd,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;gBACb,KAAK;gBACL,MAAM;gBACN,mEAAmE;gBACnE,iEAAiE;gBACjE,QAAQ,EAAE,GAAG,CAAC,QAAiC;gBAC/C,YAAY,EAAE,GAAG,CAAC,cAAc;gBAChC,GAAG,EAAE,KAAK;gBACV,UAAU,EAAE,GAAG,CAAC,UAAU,CAAC,UAAU;gBACrC,aAAa;gBACb,SAAS;gBACT,QAAQ;aACT,CAAC;SACH,EACD,SAAS,CACV,CACF,CAAC;IACJ,CAAC,CACF,CAAC;IACF,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { projectTranscript } from "./QaTranscriptAdapter.js";
|
|
2
|
+
/**
|
|
3
|
+
* Project one bound chat into the observable surface state: phase, transcript
|
|
4
|
+
* with per-turn sources, footer sources, and the composer's capabilities.
|
|
5
|
+
* Side effects (host-bundle refresh, notifications) live in the controller.
|
|
6
|
+
*/
|
|
7
|
+
export function projectBoundSessionState(input) {
|
|
8
|
+
const { config, sessionSnapshot: snapshot } = input;
|
|
9
|
+
// A pending approval interaction is invisible to this snapshot in 0.1.5;
|
|
10
|
+
// the QA lockdown pins approval=never and strips escalation-requiring
|
|
11
|
+
// tools, so no interaction the surface cannot answer should ever arise.
|
|
12
|
+
const error = input.operationError ??
|
|
13
|
+
(snapshot.removed || snapshot.openState === "error"
|
|
14
|
+
? "Этот чат больше недоступен."
|
|
15
|
+
: null);
|
|
16
|
+
const phase = !input.connected
|
|
17
|
+
? "reconnecting"
|
|
18
|
+
: snapshot.removed || snapshot.openState === "error"
|
|
19
|
+
? "error"
|
|
20
|
+
: snapshot.openState !== "open"
|
|
21
|
+
? "creating"
|
|
22
|
+
: snapshot.running || input.admissionPending
|
|
23
|
+
? "running"
|
|
24
|
+
: "ready";
|
|
25
|
+
const sourcesByTurn = new Map(input.sourceBundles.map((bundle) => [bundle.turn, bundle]));
|
|
26
|
+
const messages = projectTranscript(input.conversationSnapshot, {
|
|
27
|
+
running: snapshot.running,
|
|
28
|
+
showToolActivity: config.ui.showToolActivity,
|
|
29
|
+
showReasoning: config.ui.showReasoning,
|
|
30
|
+
}).map((message) => {
|
|
31
|
+
if (message.role === "user" && input.author !== undefined) {
|
|
32
|
+
return { ...message, author: input.author };
|
|
33
|
+
}
|
|
34
|
+
if (message.role !== "assistant" || message.turn === undefined)
|
|
35
|
+
return message;
|
|
36
|
+
const bundle = sourcesByTurn.get(message.turn);
|
|
37
|
+
const sources = bundle === undefined
|
|
38
|
+
? undefined
|
|
39
|
+
: [
|
|
40
|
+
...bundle.sources,
|
|
41
|
+
...(config.sources.display.showDiscovered
|
|
42
|
+
? (bundle.discovered ?? [])
|
|
43
|
+
: []),
|
|
44
|
+
];
|
|
45
|
+
return sources === undefined || sources.length === 0
|
|
46
|
+
? message
|
|
47
|
+
: {
|
|
48
|
+
...message,
|
|
49
|
+
sources,
|
|
50
|
+
sourcesComplete: bundle?.complete ?? true,
|
|
51
|
+
...(bundle?.incompleteOrigins === undefined
|
|
52
|
+
? {}
|
|
53
|
+
: { incompleteSourceOrigins: bundle.incompleteOrigins }),
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
|
+
const latest = input.sourceBundles.at(-1);
|
|
57
|
+
return {
|
|
58
|
+
phase,
|
|
59
|
+
sessionId: input.sessionId,
|
|
60
|
+
messages,
|
|
61
|
+
error,
|
|
62
|
+
canSend: input.connected && phase === "ready" && input.policyReady,
|
|
63
|
+
canStop: input.connected && snapshot.running && config.ui.showStop,
|
|
64
|
+
chatsRevision: input.chatsRevision,
|
|
65
|
+
sources: latest === undefined
|
|
66
|
+
? []
|
|
67
|
+
: [
|
|
68
|
+
...latest.sources,
|
|
69
|
+
...(config.sources.display.showDiscovered
|
|
70
|
+
? (latest.discovered ?? [])
|
|
71
|
+
: []),
|
|
72
|
+
],
|
|
73
|
+
sourcesComplete: latest?.complete ?? true,
|
|
74
|
+
incompleteSourceOrigins: latest?.incompleteOrigins,
|
|
75
|
+
viewingSubagent: input.viewingSubagent,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=project-session-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-session-state.js","sourceRoot":"","sources":["../../src/client/project-session-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { attestationHint, attestationReasonOf, proofMatchesConfig, } from "./attestation.js";
|
|
2
|
+
/**
|
|
3
|
+
* One send-time policy attestation against the Host admission gate. The
|
|
4
|
+
* QA-facing message stays generic by design; the coarse reason plus an
|
|
5
|
+
* operator hint go to the console once per refusal.
|
|
6
|
+
*/
|
|
7
|
+
export async function attestQaPolicy(args) {
|
|
8
|
+
try {
|
|
9
|
+
const result = await args.secureSession(args.token, args.sessionId);
|
|
10
|
+
if (!result.ok) {
|
|
11
|
+
const reason = attestationReasonOf(result.error);
|
|
12
|
+
if (reason === "auth-required") {
|
|
13
|
+
if (args.report) {
|
|
14
|
+
console.error("dsh-qa-surface: policy attestation failed (reason: auth-required). The account token is absent or expired.");
|
|
15
|
+
}
|
|
16
|
+
return { ok: false, authRequired: true, reason };
|
|
17
|
+
}
|
|
18
|
+
return reject(args, reason);
|
|
19
|
+
}
|
|
20
|
+
if (!proofMatchesConfig(result.value, args.lockdown, args.sessionId)) {
|
|
21
|
+
return reject(args, "proof-mismatch");
|
|
22
|
+
}
|
|
23
|
+
return { ok: true };
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
if (args.report) {
|
|
27
|
+
console.error("dsh-qa-surface: policy attestation request failed", error);
|
|
28
|
+
}
|
|
29
|
+
return { ok: false, authRequired: false, reason: null };
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function reject(args, reason) {
|
|
33
|
+
if (args.report) {
|
|
34
|
+
console.error(`dsh-qa-surface: policy attestation failed (reason: ${reason ?? "unknown"}). ${attestationHint(reason)}`);
|
|
35
|
+
}
|
|
36
|
+
return { ok: false, authRequired: false, reason };
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=session-admission.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-admission.js","sourceRoot":"","sources":["../../src/client/session-admission.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAa1B;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAMpC;IACC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QACpE,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,MAAM,MAAM,GAAG,mBAAmB,CAChC,MAAM,CAAC,KAAsC,CAC9C,CAAC;YACF,IAAI,MAAM,KAAK,eAAe,EAAE,CAAC;gBAC/B,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;oBAChB,OAAO,CAAC,KAAK,CACX,4GAA4G,CAC7G,CAAC;gBACJ,CAAC;gBACD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;YACnD,CAAC;YACD,OAAO,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC9B,CAAC;QACD,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YACrE,OAAO,MAAM,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACtB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,OAAO,CAAC,KAAK,CAAC,mDAAmD,EAAE,KAAK,CAAC,CAAC;QAC5E,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IAC1D,CAAC;AACH,CAAC;AAED,SAAS,MAAM,CACb,IAAkC,EAClC,MAAqB;IAErB,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,CACX,sDAAsD,MAAM,IAAI,SAAS,MAAM,eAAe,CAAC,MAAM,CAAC,EAAE,CACzG,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AACpD,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-chat cache of resolved attachment URLs. Attachment reads are
|
|
3
|
+
* session-scoped (the loader reads the bound session's durable store), and
|
|
4
|
+
* attachment ids are only unique within a chat, so both the cache and the
|
|
5
|
+
* blob lifetime are keyed by chat, not by the page.
|
|
6
|
+
*/
|
|
7
|
+
export class SessionAssetRepository {
|
|
8
|
+
bySession = new Map();
|
|
9
|
+
/** Resolve one attachment of one chat, deduplicating concurrent reads. */
|
|
10
|
+
resolve(sessionId, attachmentId, load) {
|
|
11
|
+
const byAttachment = this.bySession.get(sessionId) ?? new Map();
|
|
12
|
+
this.bySession.set(sessionId, byAttachment);
|
|
13
|
+
let pending = byAttachment.get(attachmentId);
|
|
14
|
+
if (pending === undefined) {
|
|
15
|
+
pending = load(attachmentId);
|
|
16
|
+
byAttachment.set(attachmentId, pending);
|
|
17
|
+
// A failed read must not poison the slot: the broken view retries by
|
|
18
|
+
// re-resolving on demand.
|
|
19
|
+
pending.catch(() => {
|
|
20
|
+
if (byAttachment.get(attachmentId) === pending)
|
|
21
|
+
byAttachment.delete(attachmentId);
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
return pending;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Revoke the chat's blob URLs and drop its cache. Data URLs need no
|
|
28
|
+
* revocation; a failed resolution never produced a URL at all.
|
|
29
|
+
*/
|
|
30
|
+
release(sessionId) {
|
|
31
|
+
const byAttachment = this.bySession.get(sessionId);
|
|
32
|
+
if (byAttachment === undefined)
|
|
33
|
+
return;
|
|
34
|
+
this.bySession.delete(sessionId);
|
|
35
|
+
for (const pending of byAttachment.values())
|
|
36
|
+
void pending.then(revokeIfBlob, () => undefined);
|
|
37
|
+
}
|
|
38
|
+
dispose() {
|
|
39
|
+
for (const sessionId of [...this.bySession.keys()])
|
|
40
|
+
this.release(sessionId);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function revokeIfBlob(url) {
|
|
44
|
+
revokeObjectUrlIfBlob(url);
|
|
45
|
+
}
|
|
46
|
+
/** Revoke one blob URL; data URLs (and other runtimes) need nothing. */
|
|
47
|
+
export function revokeObjectUrlIfBlob(url) {
|
|
48
|
+
if (url.startsWith("blob:") && typeof URL.revokeObjectURL === "function") {
|
|
49
|
+
URL.revokeObjectURL(url);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=session-assets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-assets.js","sourceRoot":"","sources":["../../src/client/session-assets.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,OAAO,sBAAsB;IAChB,SAAS,GAAG,IAAI,GAAG,EAAwC,CAAC;IAE7E,0EAA0E;IAC1E,OAAO,CACL,SAAiB,EACjB,YAAoB,EACpB,IAA+C;QAE/C,MAAM,YAAY,GAChB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI,GAAG,EAA2B,CAAC;QACtE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QAC5C,IAAI,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAC7C,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC;YAC7B,YAAY,CAAC,GAAG,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;YACxC,qEAAqE;YACrE,0BAA0B;YAC1B,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE;gBACjB,IAAI,YAAY,CAAC,GAAG,CAAC,YAAY,CAAC,KAAK,OAAO;oBAC5C,YAAY,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;YACtC,CAAC,CAAC,CAAC;QACL,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;;OAGG;IACH,OAAO,CAAC,SAAiB;QACvB,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACnD,IAAI,YAAY,KAAK,SAAS;YAAE,OAAO;QACvC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACjC,KAAK,MAAM,OAAO,IAAI,YAAY,CAAC,MAAM,EAAE;YACzC,KAAK,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IACrD,CAAC;IAED,OAAO;QACL,KAAK,MAAM,SAAS,IAAI,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;YAAE,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAC9E,CAAC;CACF;AAED,SAAS,YAAY,CAAC,GAAW;IAC/B,qBAAqB,CAAC,GAAG,CAAC,CAAC;AAC7B,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,qBAAqB,CAAC,GAAW;IAC/C,IAAI,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,CAAC,eAAe,KAAK,UAAU,EAAE,CAAC;QACzE,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host-side provenance of the bound chat. The client projects turn sources
|
|
3
|
+
* from durable conversation events; the Host bundle (which also carries
|
|
4
|
+
* subagent-inherited evidence) is fetched on the side and merged by turn,
|
|
5
|
+
* Host data winning over the projection.
|
|
6
|
+
*/
|
|
7
|
+
export class QaHostSourceBridge {
|
|
8
|
+
sourceApi;
|
|
9
|
+
token;
|
|
10
|
+
bundles = [];
|
|
11
|
+
signature = "";
|
|
12
|
+
refreshing = false;
|
|
13
|
+
/** Bumped on reset so a stale in-flight fetch never lands. */
|
|
14
|
+
generation = 0;
|
|
15
|
+
constructor(sourceApi, token) {
|
|
16
|
+
this.sourceApi = sourceApi;
|
|
17
|
+
this.token = token;
|
|
18
|
+
}
|
|
19
|
+
/** Leave the chat: drop its bundles; merging degrades to the projection. */
|
|
20
|
+
reset() {
|
|
21
|
+
this.generation += 1;
|
|
22
|
+
this.bundles = [];
|
|
23
|
+
this.signature = "";
|
|
24
|
+
this.refreshing = false;
|
|
25
|
+
}
|
|
26
|
+
merge(projected) {
|
|
27
|
+
const merged = new Map();
|
|
28
|
+
for (const bundle of projected)
|
|
29
|
+
merged.set(bundle.turn, bundle);
|
|
30
|
+
for (const bundle of this.bundles)
|
|
31
|
+
merged.set(bundle.turn, bundle);
|
|
32
|
+
return [...merged.values()].sort((left, right) => left.turn - right.turn);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Fetch the Host bundles of one chat; a changed payload republishes through
|
|
36
|
+
* the callback. Repeated calls coalesce while one is in flight, and a
|
|
37
|
+
* response that outlives the chat is dropped.
|
|
38
|
+
*/
|
|
39
|
+
async refresh(sessionId, onChanged) {
|
|
40
|
+
if (this.refreshing)
|
|
41
|
+
return;
|
|
42
|
+
const generation = this.generation;
|
|
43
|
+
this.refreshing = true;
|
|
44
|
+
try {
|
|
45
|
+
const result = await this.sourceApi.sources(this.token(), sessionId);
|
|
46
|
+
if (!result.ok || generation !== this.generation)
|
|
47
|
+
return;
|
|
48
|
+
const signature = JSON.stringify(result.value);
|
|
49
|
+
if (signature === this.signature)
|
|
50
|
+
return;
|
|
51
|
+
this.signature = signature;
|
|
52
|
+
this.bundles = result.value;
|
|
53
|
+
onChanged();
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
if (generation === this.generation)
|
|
57
|
+
this.refreshing = false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=session-sources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-sources.js","sourceRoot":"","sources":["../../src/client/session-sources.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,MAAM,OAAO,kBAAkB;IAQV,SAAS;IACT,KAAK;IARhB,OAAO,GAA6B,EAAE,CAAC;IACvC,SAAS,GAAG,EAAE,CAAC;IACf,UAAU,GAAG,KAAK,CAAC;IAC3B,8DAA8D;IACtD,UAAU,GAAG,CAAC,CAAC;IAEvB,YACmB,SAAsB,EACtB,KAAmB;yBADnB,SAAS;qBACT,KAAK;IACrB,CAAC;IAEJ,4EAA4E;IAC5E,KAAK;QACH,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC;QACrB,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAClB,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;QACpB,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,SAAmC;QACvC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAyB,CAAC;QAChD,KAAK,MAAM,MAAM,IAAI,SAAS;YAAE,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAChE,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO;YAAE,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACnE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5E,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,OAAO,CAAC,SAAiB,EAAE,SAAqB;QACpD,IAAI,IAAI,CAAC,UAAU;YAAE,OAAO;QAC5B,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;QACnC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC,CAAC;YACrE,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,UAAU,KAAK,IAAI,CAAC,UAAU;gBAAE,OAAO;YACzD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC/C,IAAI,SAAS,KAAK,IAAI,CAAC,SAAS;gBAAE,OAAO;YACzC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;YAC3B,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC;YAC5B,SAAS,EAAE,CAAC;QACd,CAAC;gBAAS,CAAC;YACT,IAAI,UAAU,KAAK,IAAI,CAAC,UAAU;gBAAE,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QAC9D,CAAC;IACH,CAAC;CACF"}
|