@yadsh/dsh-qa-surface 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/CHANGELOG.md +84 -1
  2. package/README.md +87 -12
  3. package/compatibility.json +11 -3
  4. package/docs/ARCHITECTURE.md +1 -1
  5. package/docs/COMPATIBILITY.md +1 -1
  6. package/docs/CONFIGURATION.md +88 -1
  7. package/docs/SOURCES-MIGRATION.md +28 -0
  8. package/docs/SOURCES-PROVENANCE-AUDIT.md +88 -0
  9. package/docs/SPEC-dsh-qa-surface-accounts.md +219 -0
  10. package/docs/SPEC-dsh-qa-surface-sources-provenance.md +1692 -0
  11. package/lib/accounts/index.js +2 -0
  12. package/lib/accounts/index.js.map +1 -0
  13. package/lib/accounts/store.js +478 -0
  14. package/lib/accounts/store.js.map +1 -0
  15. package/lib/attestation.js.map +1 -1
  16. package/lib/cli.js +143 -0
  17. package/lib/cli.js.map +1 -0
  18. package/lib/client/QaAccountsController.js +329 -0
  19. package/lib/client/QaAccountsController.js.map +1 -0
  20. package/lib/client/QaSessionController.js +203 -127
  21. package/lib/client/QaSessionController.js.map +1 -1
  22. package/lib/client/QaSurface.js +234 -72
  23. package/lib/client/QaSurface.js.map +1 -1
  24. package/lib/client/QaTranscriptAdapter.js +27 -241
  25. package/lib/client/QaTranscriptAdapter.js.map +1 -1
  26. package/lib/client/attestation.js +6 -0
  27. package/lib/client/attestation.js.map +1 -1
  28. package/lib/client/components/Markdown.js +54 -13
  29. package/lib/client/components/Markdown.js.map +1 -1
  30. package/lib/client/components/QaAuthGate.js +40 -0
  31. package/lib/client/components/QaAuthGate.js.map +1 -0
  32. package/lib/client/components/QaChangelog.js +112 -0
  33. package/lib/client/components/QaChangelog.js.map +1 -0
  34. package/lib/client/components/QaMessage.js +47 -17
  35. package/lib/client/components/QaMessage.js.map +1 -1
  36. package/lib/client/components/QaSidebar.js +63 -20
  37. package/lib/client/components/QaSidebar.js.map +1 -1
  38. package/lib/client/components/QaSourcesDrawer.js +113 -32
  39. package/lib/client/components/QaSourcesDrawer.js.map +1 -1
  40. package/lib/client/components/QaTurnRail.js +281 -0
  41. package/lib/client/components/QaTurnRail.js.map +1 -0
  42. package/lib/client/components/QaWelcomeNotice.js +125 -0
  43. package/lib/client/components/QaWelcomeNotice.js.map +1 -0
  44. package/lib/client/components/QaWidthHandle.js +142 -0
  45. package/lib/client/components/QaWidthHandle.js.map +1 -0
  46. package/lib/client/components/source-refs.js +78 -0
  47. package/lib/client/components/source-refs.js.map +1 -0
  48. package/lib/client/create-session.js +51 -0
  49. package/lib/client/create-session.js.map +1 -0
  50. package/lib/client/index.js +100 -12
  51. package/lib/client/index.js.map +1 -1
  52. package/lib/client/project-session-state.js +78 -0
  53. package/lib/client/project-session-state.js.map +1 -0
  54. package/lib/client/session-admission.js +38 -0
  55. package/lib/client/session-admission.js.map +1 -0
  56. package/lib/client/session-assets.js +52 -0
  57. package/lib/client/session-assets.js.map +1 -0
  58. package/lib/client/session-sources.js +61 -0
  59. package/lib/client/session-sources.js.map +1 -0
  60. package/lib/client/settlement.js +24 -0
  61. package/lib/client/settlement.js.map +1 -0
  62. package/lib/client/styles.js +151 -9
  63. package/lib/client/styles.js.map +1 -1
  64. package/lib/client/tool-presentation.js +102 -0
  65. package/lib/client/tool-presentation.js.map +1 -0
  66. package/lib/client/turn-sources.js +98 -0
  67. package/lib/client/turn-sources.js.map +1 -0
  68. package/lib/client/types.js +2 -0
  69. package/lib/client/types.js.map +1 -1
  70. package/lib/client/use-session-ui-state.js +68 -0
  71. package/lib/client/use-session-ui-state.js.map +1 -0
  72. package/lib/client/use-transcript-view.js +44 -0
  73. package/lib/client/use-transcript-view.js.map +1 -0
  74. package/lib/client.js +4649 -861
  75. package/lib/client.js.map +1 -1
  76. package/lib/config.js +218 -102
  77. package/lib/config.js.map +1 -1
  78. package/lib/entry-redirect.js +44 -0
  79. package/lib/entry-redirect.js.map +1 -0
  80. package/lib/host-route.js +25 -1
  81. package/lib/host-route.js.map +1 -1
  82. package/lib/index.js +209 -23
  83. package/lib/index.js.map +1 -1
  84. package/lib/launch-token.js +42 -0
  85. package/lib/launch-token.js.map +1 -0
  86. package/lib/provenance/collector.js +40 -0
  87. package/lib/provenance/collector.js.map +1 -0
  88. package/lib/provenance/connectors.js +147 -0
  89. package/lib/provenance/connectors.js.map +1 -0
  90. package/lib/provenance/dedupe.js +89 -0
  91. package/lib/provenance/dedupe.js.map +1 -0
  92. package/lib/provenance/extractors.js +340 -0
  93. package/lib/provenance/extractors.js.map +1 -0
  94. package/lib/provenance/file-preview.js +39 -0
  95. package/lib/provenance/file-preview.js.map +1 -0
  96. package/lib/provenance/host-store.js +387 -0
  97. package/lib/provenance/host-store.js.map +1 -0
  98. package/lib/provenance/index.js +9 -0
  99. package/lib/provenance/index.js.map +1 -0
  100. package/lib/provenance/normalize.js +128 -0
  101. package/lib/provenance/normalize.js.map +1 -0
  102. package/lib/provenance/reported.js +53 -0
  103. package/lib/provenance/reported.js.map +1 -0
  104. package/lib/provenance/types.js +2 -0
  105. package/lib/provenance/types.js.map +1 -0
  106. package/lib/resolve-config.js +161 -0
  107. package/lib/resolve-config.js.map +1 -1
  108. package/lib/secure-session.js +50 -8
  109. package/lib/secure-session.js.map +1 -1
  110. package/lib/typert.host.js +599 -6
  111. package/lib/typert.remote-client.d.ts +19 -3
  112. package/lib/typert.remote-client.js +471 -3
  113. package/lib/types/accounts/index.d.ts +2 -0
  114. package/lib/types/accounts/store.d.ts +121 -0
  115. package/lib/types/attestation.d.ts +1 -1
  116. package/lib/types/cli.d.ts +9 -0
  117. package/lib/types/client/QaAccountsController.d.ts +95 -0
  118. package/lib/types/client/QaConfigController.d.ts +1 -1
  119. package/lib/types/client/QaSessionController.d.ts +46 -7
  120. package/lib/types/client/QaSurface.d.ts +8 -3
  121. package/lib/types/client/QaTranscriptAdapter.d.ts +5 -10
  122. package/lib/types/client/components/Markdown.d.ts +11 -1
  123. package/lib/types/client/components/QaAgentsDrawer.d.ts +1 -1
  124. package/lib/types/client/components/QaAuthGate.d.ts +15 -0
  125. package/lib/types/client/components/QaChangelog.d.ts +21 -0
  126. package/lib/types/client/components/QaMessage.d.ts +10 -3
  127. package/lib/types/client/components/QaSidebar.d.ts +30 -2
  128. package/lib/types/client/components/QaSourcesDrawer.d.ts +15 -3
  129. package/lib/types/client/components/QaTurnRail.d.ts +59 -0
  130. package/lib/types/client/components/QaWelcomeNotice.d.ts +27 -0
  131. package/lib/types/client/components/QaWidthHandle.d.ts +36 -0
  132. package/lib/types/client/components/source-refs.d.ts +16 -0
  133. package/lib/types/client/create-session.d.ts +16 -0
  134. package/lib/types/client/index.d.ts +1 -0
  135. package/lib/types/client/project-session-state.d.ts +30 -0
  136. package/lib/types/client/session-admission.d.ts +23 -0
  137. package/lib/types/client/session-assets.d.ts +20 -0
  138. package/lib/types/client/session-sources.d.ts +28 -0
  139. package/lib/types/client/settlement.d.ts +6 -0
  140. package/lib/types/client/tool-presentation.d.ts +6 -0
  141. package/lib/types/client/turn-sources.d.ts +14 -0
  142. package/lib/types/client/types.d.ts +73 -9
  143. package/lib/types/client/use-session-ui-state.d.ts +35 -0
  144. package/lib/types/client/use-transcript-view.d.ts +20 -0
  145. package/lib/types/entry-redirect.d.ts +20 -0
  146. package/lib/types/host-route.d.ts +14 -1
  147. package/lib/types/index.d.ts +47 -3
  148. package/lib/types/launch-token.d.ts +21 -0
  149. package/lib/types/provenance/collector.d.ts +26 -0
  150. package/lib/types/provenance/connectors.d.ts +11 -0
  151. package/lib/types/provenance/dedupe.d.ts +6 -0
  152. package/lib/types/provenance/extractors.d.ts +14 -0
  153. package/lib/types/provenance/file-preview.d.ts +10 -0
  154. package/lib/types/provenance/host-store.d.ts +54 -0
  155. package/lib/types/provenance/index.d.ts +10 -0
  156. package/lib/types/provenance/normalize.d.ts +13 -0
  157. package/lib/types/provenance/reported.d.ts +5 -0
  158. package/lib/types/provenance/types.d.ts +78 -0
  159. package/lib/types/secure-session.d.ts +11 -2
  160. package/lib/types/types.d.ts +167 -11
  161. package/package.json +58 -41
@@ -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"}
@@ -1,12 +1,20 @@
1
1
  import qaSurfaceRemote from "@yadsh/dsh-qa-surface/remote";
2
2
  import { QaConfigController } from "./QaConfigController.js";
3
- 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";
4
6
  import { QaSurface } from "./QaSurface.js";
7
+ import { QaWelcomeNoticeStep } from "./components/QaWelcomeNotice.js";
5
8
  import { QA_SURFACE_STYLES } from "./styles.js";
6
9
  const SETTINGS_NAMESPACE = "qa-surface";
10
+ const QA_WELCOME_SLOT_ID = "welcome-notice";
11
+ function qaWelcomeStorageKey(config) {
12
+ return `${config.session.storageKey}:v1:${config.route.path}:welcome-notice`;
13
+ }
7
14
  export const inject = [
8
15
  "slots",
9
16
  "sessions",
17
+ "uiConversation",
10
18
  "connection",
11
19
  "settingsScope",
12
20
  "remote",
@@ -15,14 +23,40 @@ export const inject = [
15
23
  export async function apply(ctx) {
16
24
  const remote = ctx.remote;
17
25
  const disposeRemote = await remote.$mount(qaSurfaceRemote);
18
- await ctx.inject(["remote.qaSurface"], (remoteContext) => {
19
- const policyRemote = remoteContext.remote
20
- .qaSurface;
21
- const secureSession = (sessionId) => policyRemote.secureSession(sessionId);
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);
22
30
  const qaApi = {
23
- selectModel: ctx.connection.api.sessions.selectModel,
24
- selectAgentPreset: ctx.connection.api.agentPresets.select,
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),
25
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
+ });
26
60
  const route = new QaRouteController();
27
61
  const config = new QaConfigController(ctx.settingsScope.bind({
28
62
  namespace: SETTINGS_NAMESPACE,
@@ -33,6 +67,8 @@ export async function apply(ctx) {
33
67
  if (!described.ok) {
34
68
  throw new Error(`qaSurface/describe failed: ${described.error.code}`);
35
69
  }
70
+ // The generated self-remote resolves through the previous build's
71
+ // declarations during an incremental source typecheck.
36
72
  return described.value;
37
73
  });
38
74
  const syncRoute = () => {
@@ -46,13 +82,59 @@ export async function apply(ctx) {
46
82
  // refuses. Loopback pages follow the settings mirror; this covers the
47
83
  // describe fallback (LAN browsers). Fires on every lost→restored
48
84
  // connection transition; while connected, ticks are ignored.
49
- let connectionUp = ctx.connection.hostDescription.getSnapshot() !== undefined;
50
- const unsubscribeConnection = ctx.connection.hostDescription.subscribe(() => {
51
- const connected = ctx.connection.hostDescription.getSnapshot() !== undefined;
52
- if (connected && !connectionUp)
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) {
53
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
+ }
54
94
  connectionUp = connected;
55
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
+ });
56
138
  ctx.effect(() => {
57
139
  const style = document.createElement("style");
58
140
  style.dataset.dshQaSurface = "styles";
@@ -73,16 +155,22 @@ export async function apply(ctx) {
73
155
  inject: () => ({
74
156
  route,
75
157
  config,
158
+ // The host dsh-session merge types ctx.sessions as SessionStore in
159
+ // this program; the client assembly provides the ISessions face.
76
160
  sessions: ctx.sessions,
161
+ conversation: ctx.uiConversation,
77
162
  api: qaApi,
78
- connection: ctx.connection.hostDescription,
163
+ connection: ctx.connection.generation,
79
164
  secureSession,
165
+ sourceApi,
166
+ accounts,
80
167
  }),
81
168
  }, QaSurface));
82
169
  });
83
170
  return disposeRemote;
84
171
  }
85
172
  export { QaConfigController } from "./QaConfigController.js";
173
+ export { QaAccountsController } from "./QaAccountsController.js";
86
174
  export { QaRouteController, matchesQaRoute } from "./QaRouteController.js";
87
175
  export { QaSessionController } from "./QaSessionController.js";
88
176
  export { projectTranscript } from "./QaTranscriptAdapter.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.tsx"],"names":[],"mappings":"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"}
@@ -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"}
@@ -0,0 +1,24 @@
1
+ const SETTLED_HEAD = /^Background subagent ([0-9a-f][0-9a-f-]*) (finished|was stopped|ran out of room|declined the task|failed)/u;
2
+ const SETTLED_CLOSING = "Its closing message:";
3
+ const SETTLED_TITLES = Object.freeze({
4
+ finished: "завершён",
5
+ "was stopped": "остановлен",
6
+ "ran out of room": "упёрся в лимит длины",
7
+ "declined the task": "отклонил задачу",
8
+ failed: "завершился ошибкой",
9
+ });
10
+ /** Fold the host settlement wording into a title plus the closing message. */
11
+ export function parseSettlement(text) {
12
+ const head = SETTLED_HEAD.exec(text);
13
+ if (head === null)
14
+ return undefined;
15
+ const id = (head[1] ?? "").slice(0, 8);
16
+ const title = `Субагент ${id} ${SETTLED_TITLES[head[2] ?? "finished"] ?? "завершён"}`;
17
+ const closeAt = text.indexOf(SETTLED_CLOSING);
18
+ const body = closeAt === -1 ? "" : text.slice(closeAt + SETTLED_CLOSING.length).trim();
19
+ return {
20
+ title,
21
+ body: body.length <= 4_000 ? body : `${body.slice(0, 3_999)}…`,
22
+ };
23
+ }
24
+ //# sourceMappingURL=settlement.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settlement.js","sourceRoot":"","sources":["../../src/client/settlement.ts"],"names":[],"mappings":"AAAA,MAAM,YAAY,GAChB,4GAA4G,CAAC;AAC/G,MAAM,eAAe,GAAG,sBAAsB,CAAC;AAC/C,MAAM,cAAc,GAAqC,MAAM,CAAC,MAAM,CAAC;IACrE,QAAQ,EAAE,UAAU;IACpB,aAAa,EAAE,YAAY;IAC3B,iBAAiB,EAAE,sBAAsB;IACzC,mBAAmB,EAAE,iBAAiB;IACtC,MAAM,EAAE,oBAAoB;CAC7B,CAAC,CAAC;AAEH,8EAA8E;AAC9E,MAAM,UAAU,eAAe,CAC7B,IAAY;IAEZ,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrC,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IACpC,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,YAAY,EAAE,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,IAAI,UAAU,EAAE,CAAC;IACtF,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IAC9C,MAAM,IAAI,GACR,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5E,OAAO;QACL,KAAK;QACL,IAAI,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG;KAC/D,CAAC;AACJ,CAAC"}