@yadsh/dsh-qa-surface 0.9.0 → 0.11.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 (250) hide show
  1. package/README.md +269 -2
  2. package/lib/access/service.js +49 -10
  3. package/lib/access/service.js.map +1 -1
  4. package/lib/account-remotes.js +41 -0
  5. package/lib/account-remotes.js.map +1 -1
  6. package/lib/accounts/database.js +140 -0
  7. package/lib/accounts/database.js.map +1 -1
  8. package/lib/accounts/errors.js.map +1 -1
  9. package/lib/accounts/service-token.js +103 -0
  10. package/lib/accounts/service-token.js.map +1 -0
  11. package/lib/accounts/store.js +291 -5
  12. package/lib/accounts/store.js.map +1 -1
  13. package/lib/admin/conversation-log.js +14 -8
  14. package/lib/admin/conversation-log.js.map +1 -1
  15. package/lib/admin/permissions.js +5 -0
  16. package/lib/admin/permissions.js.map +1 -1
  17. package/lib/admin/quality-store.js +4 -0
  18. package/lib/admin/quality-store.js.map +1 -1
  19. package/lib/admin/service.js +180 -7
  20. package/lib/admin/service.js.map +1 -1
  21. package/lib/admin/session-log.js +39 -8
  22. package/lib/admin/session-log.js.map +1 -1
  23. package/lib/attachment-rules.js +39 -6
  24. package/lib/attachment-rules.js.map +1 -1
  25. package/lib/cli.js +83 -1
  26. package/lib/cli.js.map +1 -1
  27. package/lib/client/QaAccountsController.js +213 -4
  28. package/lib/client/QaAccountsController.js.map +1 -1
  29. package/lib/client/QaSessionController.js +49 -21
  30. package/lib/client/QaSessionController.js.map +1 -1
  31. package/lib/client/QaSurface.js +51 -9
  32. package/lib/client/QaSurface.js.map +1 -1
  33. package/lib/client/QaSurfaceGuard.js +12 -5
  34. package/lib/client/QaSurfaceGuard.js.map +1 -1
  35. package/lib/client/admin/QaAdmin.js +14 -2
  36. package/lib/client/admin/QaAdmin.js.map +1 -1
  37. package/lib/client/admin/pages/SkillFiles.js +78 -0
  38. package/lib/client/admin/pages/SkillFiles.js.map +1 -0
  39. package/lib/client/admin/pages/Users.js +74 -3
  40. package/lib/client/admin/pages/Users.js.map +1 -1
  41. package/lib/client/admin/routes.js +8 -1
  42. package/lib/client/admin/routes.js.map +1 -1
  43. package/lib/client/admin/shared.js +5 -1
  44. package/lib/client/admin/shared.js.map +1 -1
  45. package/lib/client/admin/styles.js +2 -0
  46. package/lib/client/admin/styles.js.map +1 -1
  47. package/lib/client/attachments.js +41 -11
  48. package/lib/client/attachments.js.map +1 -1
  49. package/lib/client/base64.js +22 -1
  50. package/lib/client/base64.js.map +1 -1
  51. package/lib/client/components/QaAgentsDrawer.js +9 -6
  52. package/lib/client/components/QaAgentsDrawer.js.map +1 -1
  53. package/lib/client/components/QaApproval.js +1 -1
  54. package/lib/client/components/QaApproval.js.map +1 -1
  55. package/lib/client/components/QaAuthGate.js +19 -10
  56. package/lib/client/components/QaAuthGate.js.map +1 -1
  57. package/lib/client/components/QaChangelog.js +56 -0
  58. package/lib/client/components/QaChangelog.js.map +1 -1
  59. package/lib/client/components/QaFilesPanel.js +17 -11
  60. package/lib/client/components/QaFilesPanel.js.map +1 -1
  61. package/lib/client/components/QaHeader.js +3 -11
  62. package/lib/client/components/QaHeader.js.map +1 -1
  63. package/lib/client/components/QaModal.js.map +1 -1
  64. package/lib/client/components/QaQuestions.js +4 -4
  65. package/lib/client/components/QaQuestions.js.map +1 -1
  66. package/lib/client/components/QaSidebar.js +10 -2
  67. package/lib/client/components/QaSidebar.js.map +1 -1
  68. package/lib/client/components/QaWidthHandle.js +111 -5
  69. package/lib/client/components/QaWidthHandle.js.map +1 -1
  70. package/lib/client/components/QaWorkspaceBrowser.js +231 -0
  71. package/lib/client/components/QaWorkspaceBrowser.js.map +1 -0
  72. package/lib/client/index.js +122 -53
  73. package/lib/client/index.js.map +1 -1
  74. package/lib/client/kiosk.js +51 -0
  75. package/lib/client/kiosk.js.map +1 -0
  76. package/lib/client/lineage.js +64 -0
  77. package/lib/client/lineage.js.map +1 -1
  78. package/lib/client/markdown/blocks.js +122 -7
  79. package/lib/client/markdown/blocks.js.map +1 -1
  80. package/lib/client/markdown/inline.js +108 -12
  81. package/lib/client/markdown/inline.js.map +1 -1
  82. package/lib/client/markdown/katex-css.js +12 -0
  83. package/lib/client/markdown/katex-css.js.map +1 -0
  84. package/lib/client/markdown/math.js +84 -0
  85. package/lib/client/markdown/math.js.map +1 -0
  86. package/lib/client/markdown/render.js +74 -5
  87. package/lib/client/markdown/render.js.map +1 -1
  88. package/lib/client/settings/card.js +2 -2
  89. package/lib/client/settings/card.js.map +1 -1
  90. package/lib/client/settings/sections/attachments.js +6 -5
  91. package/lib/client/settings/sections/attachments.js.map +1 -1
  92. package/lib/client/settings/sections/notes.js +64 -0
  93. package/lib/client/settings/sections/notes.js.map +1 -0
  94. package/lib/client/settings/sections/sources.js +4 -1
  95. package/lib/client/settings/sections/sources.js.map +1 -1
  96. package/lib/client/settings/sections.js +1 -0
  97. package/lib/client/settings/sections.js.map +1 -1
  98. package/lib/client/settlement.js +1 -1
  99. package/lib/client/settlement.js.map +1 -1
  100. package/lib/client/source-preview.js +3 -0
  101. package/lib/client/source-preview.js.map +1 -1
  102. package/lib/client/styles.js +106 -18
  103. package/lib/client/styles.js.map +1 -1
  104. package/lib/client/types.js.map +1 -1
  105. package/lib/client/user-settings/IntegrationTokensPage.js +150 -0
  106. package/lib/client/user-settings/IntegrationTokensPage.js.map +1 -0
  107. package/lib/client/user-settings/PasswordSettingsPage.js +48 -0
  108. package/lib/client/user-settings/PasswordSettingsPage.js.map +1 -0
  109. package/lib/client/user-settings/SkillCatalog.js +2 -2
  110. package/lib/client/user-settings/SkillCatalog.js.map +1 -1
  111. package/lib/client/user-settings/UserSettingsDialog.js +17 -2
  112. package/lib/client/user-settings/UserSettingsDialog.js.map +1 -1
  113. package/lib/client/user-settings/copy.js +20 -0
  114. package/lib/client/user-settings/copy.js.map +1 -1
  115. package/lib/client.js +31007 -686
  116. package/lib/client.js.map +1 -1
  117. package/lib/config-resolvers/attachments.js +6 -5
  118. package/lib/config-resolvers/attachments.js.map +1 -1
  119. package/lib/config-resolvers/defaults.js +33 -2
  120. package/lib/config-resolvers/defaults.js.map +1 -1
  121. package/lib/config-resolvers/integration.js +94 -0
  122. package/lib/config-resolvers/integration.js.map +1 -0
  123. package/lib/config-resolvers/notes.js +26 -0
  124. package/lib/config-resolvers/notes.js.map +1 -0
  125. package/lib/config-resolvers/sources.js +4 -0
  126. package/lib/config-resolvers/sources.js.map +1 -1
  127. package/lib/config.js +107 -0
  128. package/lib/config.js.map +1 -1
  129. package/lib/index.js +348 -12
  130. package/lib/index.js.map +1 -1
  131. package/lib/integration/answer.js +100 -0
  132. package/lib/integration/answer.js.map +1 -0
  133. package/lib/integration/attachments.js +231 -0
  134. package/lib/integration/attachments.js.map +1 -0
  135. package/lib/integration/contract.js +53 -0
  136. package/lib/integration/contract.js.map +1 -0
  137. package/lib/integration/host-runner.js +243 -0
  138. package/lib/integration/host-runner.js.map +1 -0
  139. package/lib/integration/http.js +538 -0
  140. package/lib/integration/http.js.map +1 -0
  141. package/lib/integration/service.js +331 -0
  142. package/lib/integration/service.js.map +1 -0
  143. package/lib/integration/transcript-reader.js +202 -0
  144. package/lib/integration/transcript-reader.js.map +1 -0
  145. package/lib/integration/transcript.js +148 -0
  146. package/lib/integration/transcript.js.map +1 -0
  147. package/lib/personal-skills/index.js +2 -2
  148. package/lib/personal-skills/index.js.map +1 -1
  149. package/lib/personal-skills/paths.js +14 -8
  150. package/lib/personal-skills/paths.js.map +1 -1
  151. package/lib/personal-skills/provider.js +16 -4
  152. package/lib/personal-skills/provider.js.map +1 -1
  153. package/lib/personal-skills/service.js +240 -30
  154. package/lib/personal-skills/service.js.map +1 -1
  155. package/lib/prompt-notes.js +103 -6
  156. package/lib/prompt-notes.js.map +1 -1
  157. package/lib/provenance/document-preview.js +60 -0
  158. package/lib/provenance/document-preview.js.map +1 -0
  159. package/lib/provenance/file-preview.js +191 -19
  160. package/lib/provenance/file-preview.js.map +1 -1
  161. package/lib/qa-tools/catalog.js +18 -1
  162. package/lib/qa-tools/catalog.js.map +1 -1
  163. package/lib/qa-tools/docs-tools.js +563 -0
  164. package/lib/qa-tools/docs-tools.js.map +1 -0
  165. package/lib/qa-tools/file-delete-gate.js +60 -0
  166. package/lib/qa-tools/file-delete-gate.js.map +1 -0
  167. package/lib/qa-tools/file-delete.js +156 -0
  168. package/lib/qa-tools/file-delete.js.map +1 -0
  169. package/lib/resolve-config.js +6 -0
  170. package/lib/resolve-config.js.map +1 -1
  171. package/lib/secure-session.js +83 -3
  172. package/lib/secure-session.js.map +1 -1
  173. package/lib/shared/documents.js +22 -0
  174. package/lib/shared/documents.js.map +1 -0
  175. package/lib/shared/integration-tokens.js +23 -0
  176. package/lib/shared/integration-tokens.js.map +1 -0
  177. package/lib/typert.host.js +1320 -134
  178. package/lib/typert.remote-client.d.ts +33 -1
  179. package/lib/typert.remote-client.js +1102 -74
  180. package/lib/types/access/service.d.ts +33 -2
  181. package/lib/types/account-remotes.d.ts +30 -1
  182. package/lib/types/accounts/database.d.ts +53 -0
  183. package/lib/types/accounts/errors.d.ts +5 -1
  184. package/lib/types/accounts/service-token.d.ts +70 -0
  185. package/lib/types/accounts/store.d.ts +131 -1
  186. package/lib/types/admin/conversation-log.d.ts +12 -0
  187. package/lib/types/admin/service.d.ts +56 -1
  188. package/lib/types/admin/session-log.d.ts +21 -0
  189. package/lib/types/attachment-rules.d.ts +26 -3
  190. package/lib/types/client/QaAccountsController.d.ts +64 -5
  191. package/lib/types/client/QaSessionController.d.ts +24 -2
  192. package/lib/types/client/admin/pages/SkillFiles.d.ts +17 -0
  193. package/lib/types/client/admin/routes.d.ts +2 -0
  194. package/lib/types/client/admin/shared.d.ts +2 -0
  195. package/lib/types/client/attachments.d.ts +21 -4
  196. package/lib/types/client/base64.d.ts +13 -1
  197. package/lib/types/client/components/QaAgentsDrawer.d.ts +2 -1
  198. package/lib/types/client/components/QaFilesPanel.d.ts +16 -4
  199. package/lib/types/client/components/QaHeader.d.ts +9 -3
  200. package/lib/types/client/components/QaModal.d.ts +4 -3
  201. package/lib/types/client/components/QaWidthHandle.d.ts +48 -2
  202. package/lib/types/client/components/QaWorkspaceBrowser.d.ts +15 -0
  203. package/lib/types/client/index.d.ts +1 -1
  204. package/lib/types/client/kiosk.d.ts +34 -0
  205. package/lib/types/client/lineage.d.ts +42 -0
  206. package/lib/types/client/markdown/blocks.d.ts +14 -1
  207. package/lib/types/client/markdown/inline.d.ts +23 -7
  208. package/lib/types/client/markdown/katex-css.d.ts +11 -0
  209. package/lib/types/client/markdown/math.d.ts +23 -0
  210. package/lib/types/client/markdown/render.d.ts +2 -1
  211. package/lib/types/client/settings/sections/notes.d.ts +12 -0
  212. package/lib/types/client/settings/sections.d.ts +1 -0
  213. package/lib/types/client/settlement.d.ts +4 -1
  214. package/lib/types/client/styles.d.ts +15 -2
  215. package/lib/types/client/types.d.ts +120 -1
  216. package/lib/types/client/user-settings/IntegrationTokensPage.d.ts +21 -0
  217. package/lib/types/client/user-settings/PasswordSettingsPage.d.ts +19 -0
  218. package/lib/types/client/user-settings/UserSettingsDialog.d.ts +11 -2
  219. package/lib/types/client/user-settings/copy.d.ts +10 -1
  220. package/lib/types/config-resolvers/integration.d.ts +47 -0
  221. package/lib/types/config-resolvers/notes.d.ts +10 -0
  222. package/lib/types/config.d.ts +10 -0
  223. package/lib/types/index.d.ts +111 -1
  224. package/lib/types/integration/answer.d.ts +65 -0
  225. package/lib/types/integration/attachments.d.ts +85 -0
  226. package/lib/types/integration/contract.d.ts +196 -0
  227. package/lib/types/integration/host-runner.d.ts +44 -0
  228. package/lib/types/integration/http.d.ts +79 -0
  229. package/lib/types/integration/service.d.ts +120 -0
  230. package/lib/types/integration/transcript-reader.d.ts +100 -0
  231. package/lib/types/integration/transcript.d.ts +59 -0
  232. package/lib/types/personal-skills/index.d.ts +2 -2
  233. package/lib/types/personal-skills/paths.d.ts +15 -3
  234. package/lib/types/personal-skills/provider.d.ts +14 -2
  235. package/lib/types/personal-skills/service.d.ts +89 -14
  236. package/lib/types/prompt-notes.d.ts +37 -0
  237. package/lib/types/provenance/document-preview.d.ts +28 -0
  238. package/lib/types/provenance/file-preview.d.ts +69 -2
  239. package/lib/types/qa-tools/catalog.d.ts +1 -1
  240. package/lib/types/qa-tools/docs-tools.d.ts +160 -0
  241. package/lib/types/qa-tools/file-delete-gate.d.ts +42 -0
  242. package/lib/types/qa-tools/file-delete.d.ts +32 -0
  243. package/lib/types/secure-session.d.ts +52 -1
  244. package/lib/types/shared/documents.d.ts +20 -0
  245. package/lib/types/shared/integration-tokens.d.ts +24 -0
  246. package/lib/types/types.d.ts +263 -3
  247. package/lib/types/ui-mode.d.ts +18 -0
  248. package/lib/ui-mode.js +22 -0
  249. package/lib/ui-mode.js.map +1 -0
  250. package/package.json +12 -10
@@ -0,0 +1,160 @@
1
+ import type { ToolDefinition } from "@deepseek-ai/dsh-tools";
2
+ /**
3
+ * `docs_search` and `docs_read` — the documentation surface of the QA catalog.
4
+ *
5
+ * A QA chat answers questions from the stand's documentation, and until now the
6
+ * model had no tool that said where that documentation is: the path in a
7
+ * reviewer's remark (`docs/platform/3.8/…`) was something the model had to
8
+ * guess its way to with a glob sweep, and a miss read as "the document does
9
+ * not exist" rather than "wrong tree". These two tools make the tree a
10
+ * first-class surface. Both are read-only, both are fenced to the
11
+ * documentation directory inside the calling chat's workspace
12
+ * (`<session cwd>/docs`, the directory the stand publishes its documentation
13
+ * into), and both name the documentation as what they search, so the tool
14
+ * description itself answers "where do I look for documentation?".
15
+ *
16
+ * The tree is read as a shallow layout convention, not a schema: hits carry
17
+ * the `version` and `module` parsed out of the path (`docs/<module>/<version>/…`)
18
+ * so the model can stay inside one edition of one module, and the same two
19
+ * names are accepted as filters. A path the convention does not describe is
20
+ * still searched and still read — it simply carries no identity.
21
+ *
22
+ * Nothing here is destructive and building it registers nothing: like the rest
23
+ * of the catalog these are side-effect-free definitions, and the workspace root
24
+ * is read from `exec.agent` at call time.
25
+ */
26
+ /** The documentation directory inside a chat workspace. */
27
+ export declare const QA_DOCS_DIRECTORY = "docs";
28
+ /** Search defaults and budgets, all fixed: a chat cannot raise them. */
29
+ export declare const QA_DOCS_SEARCH_DEFAULT_LIMIT = 8;
30
+ export declare const QA_DOCS_SEARCH_MAX_LIMIT = 40;
31
+ export declare const QA_DOCS_SEARCH_BYTE_BUDGET = 4000;
32
+ export declare const QA_DOCS_READ_DEFAULT_LINES = 120;
33
+ export declare const QA_DOCS_READ_MAX_LINES = 400;
34
+ /** Why a documentation tool refused a call. */
35
+ export type QaDocsRefusal = "workspace-unavailable" | "docs-unavailable" | "invalid-request" | "outside-docs" | "symlink-escape" | "not-found" | "not-a-file" | "not-text";
36
+ /**
37
+ * A typed refusal of one documentation call.
38
+ *
39
+ * The message is what the model reads. It names the reason in words and never
40
+ * echoes an absolute host path, so a refusal cannot leak the deployment's
41
+ * layout into the conversation.
42
+ */
43
+ export declare class QaDocsError extends Error {
44
+ readonly code: QaDocsRefusal;
45
+ constructor(code: QaDocsRefusal, message: string, options?: ErrorOptions);
46
+ }
47
+ /** The slice of the execution record these tool bodies read. */
48
+ interface QaDocsExecution {
49
+ readonly agent?: {
50
+ readonly session: {
51
+ readonly header: {
52
+ readonly cwd?: string;
53
+ };
54
+ };
55
+ };
56
+ }
57
+ /** The resolved documentation root of one call. */
58
+ export interface QaDocsRoot {
59
+ /** Canonical workspace root of the calling chat. */
60
+ readonly workspace: string;
61
+ /** Canonical `<workspace>/docs`. */
62
+ readonly docs: string;
63
+ }
64
+ /**
65
+ * Module/version identity parsed out of a documentation path.
66
+ *
67
+ * Both are optional and, when a path does not carry one, genuinely absent: the
68
+ * catalog's output schema is read with `exactOptionalPropertyTypes`, so an
69
+ * identity is spread into a report rather than written as `undefined`.
70
+ */
71
+ export interface QaDocsIdentity {
72
+ readonly version?: string;
73
+ readonly module?: string;
74
+ }
75
+ /** One documentation match. */
76
+ export interface QaDocsHit extends QaDocsIdentity {
77
+ /** Workspace-relative path, starting at `docs/`, with forward slashes. */
78
+ readonly path: string;
79
+ /** 1-based line number inside the file. */
80
+ readonly line: number;
81
+ /** The matched line, trimmed and bounded. */
82
+ readonly text: string;
83
+ }
84
+ /** The outcome of one documentation search. */
85
+ export interface QaDocsSearchResult extends QaDocsIdentity {
86
+ readonly query: string;
87
+ /** The directory documentation is read from, relative to the workspace. */
88
+ readonly root: string;
89
+ readonly hits: QaDocsHit[];
90
+ readonly truncated: boolean;
91
+ readonly filesScanned: number;
92
+ readonly skipped: number;
93
+ }
94
+ /** The outcome of one documentation read. */
95
+ export interface QaDocsReadResult extends QaDocsIdentity {
96
+ readonly path: string;
97
+ readonly from: number;
98
+ readonly to: number;
99
+ readonly totalLines: number;
100
+ readonly truncated: boolean;
101
+ readonly text: string;
102
+ }
103
+ /**
104
+ * Identity of one documentation path, read relative to the documentation root.
105
+ *
106
+ * The documented layout is `docs/<module>/<version>/…`: the version is the
107
+ * first directory segment that parses as one (`3.8`, `v2`, `2024.1`), and the
108
+ * module is the directory segment immediately before it. A path with no
109
+ * version segment keeps its first directory segment as the module; a file
110
+ * directly in `docs/` carries neither, and is still searched and read.
111
+ */
112
+ export declare function docsIdentityOf(pathFromDocsRoot: string): QaDocsIdentity;
113
+ /**
114
+ * The canonical documentation root of one call.
115
+ *
116
+ * The root is a real directory inside the canonical workspace: a `docs` entry
117
+ * that is a link or a file is refused rather than followed, because the fence
118
+ * is the point of the tool and a link is how a fence is left.
119
+ */
120
+ export declare function docsRootOf(exec: QaDocsExecution): Promise<QaDocsRoot>;
121
+ export interface QaDocsSearchRequest {
122
+ readonly query: string;
123
+ readonly version?: string | undefined;
124
+ readonly module?: string | undefined;
125
+ readonly path?: string | undefined;
126
+ readonly limit?: number | undefined;
127
+ }
128
+ /**
129
+ * Search the documentation tree of one chat workspace.
130
+ *
131
+ * Matching is a case-insensitive substring test, line by line: a hit is a
132
+ * line, not a file, so the caller can cite it. The result is bounded twice —
133
+ * by `limit` hits and by the byte budget of the rendered report — and reports
134
+ * which bound cut it short instead of silently dropping matches.
135
+ * @throws QaDocsError when the tree is missing, the scope path is wrong, or the query is empty.
136
+ */
137
+ export declare function searchDocumentation(root: QaDocsRoot, request: QaDocsSearchRequest): Promise<QaDocsSearchResult>;
138
+ export interface QaDocsReadRequest {
139
+ readonly path: string;
140
+ readonly from?: number | undefined;
141
+ readonly lines?: number | undefined;
142
+ }
143
+ /**
144
+ * Read one window of one documentation file of a chat workspace.
145
+ * @throws QaDocsError when the path is outside the tree, missing, a directory, or not text.
146
+ */
147
+ export declare function readDocumentation(root: QaDocsRoot, request: QaDocsReadRequest): Promise<QaDocsReadResult>;
148
+ /**
149
+ * `docs_search` — the catalog's documentation search.
150
+ *
151
+ * The description is part of the tool's job: it states that documentation is
152
+ * read here, from `docs/`, and that memory is not a documentation source. The
153
+ * version/module facets exist so a model that has been told "3.8" stops
154
+ * sweeping the whole tree.
155
+ */
156
+ export declare function createDocsSearchTool(): ToolDefinition;
157
+ /** `docs_read` — open one documentation file at a bounded window of lines. */
158
+ export declare function createDocsReadTool(): ToolDefinition;
159
+ export {};
160
+ //# sourceMappingURL=docs-tools.d.ts.map
@@ -0,0 +1,42 @@
1
+ import type { Context } from "@deepseek-ai/cordis";
2
+ import type { QaSessionOwnership } from "../session-ownership.js";
3
+ /** The one QA tool whose every call is parked for the operator. */
4
+ export declare const QA_FILE_DELETE_TOOL = "file_delete";
5
+ /** Why the gate answers `ask` before the chain can decide alone. */
6
+ export declare const QA_FILE_DELETE_ASK_REASON = "deleting a workspace file requires operator confirmation";
7
+ /**
8
+ * The inner half of `file_delete`'s safety: the decision that composes the
9
+ * approval flow around one destructive tool.
10
+ *
11
+ * Installed WITHOUT `prepend`, deliberately. The approval gate sits outside
12
+ * every other `tools/pre-execute` listener and resolves the decision the rest
13
+ * of the chain produced — an `ask` from an inner gate is what it parks for
14
+ * the operator. This listener is that inner gate: for a `file_delete` call
15
+ * from an attested QA session it answers `ask` on its own, without asking
16
+ * the chain, so the interactive approval card appears for every deletion,
17
+ * whatever the deployment's other policies would have said. The operator's
18
+ * answer becomes the decision, and on a deployment with
19
+ * `interaction.approvals: blocked` the approval gate keeps its fail-closed
20
+ * behavior and refuses the call — nothing is ever deleted without a person.
21
+ *
22
+ * Any other tool, and any caller this deployment did not attest, is handed
23
+ * back to the chain untouched.
24
+ */
25
+ export declare class QaFileDeleteGate {
26
+ private readonly ctx;
27
+ private readonly ownership;
28
+ private readonly disposers;
29
+ constructor(ctx: Context, ownership: QaSessionOwnership);
30
+ /** Sit inside the approval gate; registration order is the composition. */
31
+ install(): void;
32
+ /** Detach the listener. Wired as an effect, like every other gate. */
33
+ dispose(): void;
34
+ private handle;
35
+ /**
36
+ * Whether this deployment attested the chat the call belongs to, delegated
37
+ * children included. The same ownership service the approval gate reads,
38
+ * so one chat is parked under exactly one surface.
39
+ */
40
+ private attested;
41
+ }
42
+ //# sourceMappingURL=file-delete-gate.d.ts.map
@@ -0,0 +1,32 @@
1
+ import type { ToolDefinition } from "@deepseek-ai/dsh-tools";
2
+ /**
3
+ * `file_delete` — the QA catalog's one destructive capability.
4
+ *
5
+ * The QA surface serves untrusted-audience chats pinned to a read-only or
6
+ * workspace-write sandbox, and until now no chat could remove a file it had
7
+ * created. This tool deletes exactly one regular file strictly inside the
8
+ * calling agent's workspace root (the session cwd) and refuses everything
9
+ * else with a reason the model can act on: directories, missing paths, paths
10
+ * spelled outside the root, and paths that leave it through a symbolic link.
11
+ * Every call is additionally answered `ask` by the always-ask gate, so the
12
+ * interactive approval card parks it for the operator before this body ever
13
+ * runs — the fence here is the second of two boundaries, not the only one.
14
+ *
15
+ * The workspace root is read from `exec.agent` at call time, so building the
16
+ * tool (and the catalog that carries it) stays side-effect free.
17
+ */
18
+ /** Why `file_delete` refused a call. */
19
+ export type QaFileDeleteRefusal = "workspace-unavailable" | "outside-workspace" | "symlink-escape" | "not-found" | "not-a-file";
20
+ /**
21
+ * A typed refusal of one `file_delete` call.
22
+ *
23
+ * The message is what the model reads; it names the reason in words and
24
+ * deliberately never echoes the requested absolute host path, so a refusal
25
+ * cannot leak the deployment's layout into the conversation.
26
+ */
27
+ export declare class QaFileDeleteError extends Error {
28
+ readonly code: QaFileDeleteRefusal;
29
+ constructor(code: QaFileDeleteRefusal, message: string, options?: ErrorOptions);
30
+ }
31
+ export declare function createFileDeleteTool(): ToolDefinition;
32
+ //# sourceMappingURL=file-delete.d.ts.map
@@ -14,6 +14,13 @@ export interface QaAccountsGate {
14
14
  readonly id: string;
15
15
  } | undefined;
16
16
  userWorkspace(userId: string, registeredWorkspacePath: string): string;
17
+ /**
18
+ * The account an ownership record names, for callers that authenticated by
19
+ * another credential (the integration API's service token). Absent records
20
+ * and a changed owner both resolve to undefined. Only read by that path: the
21
+ * token-shaped entry above remains the browser's only door.
22
+ */
23
+ ownerIdOf(sessionId: string): string | undefined;
17
24
  }
18
25
  /**
19
26
  * Host-side QA policy admission boundary — the only browser-callable operation
@@ -48,6 +55,11 @@ export declare class QaPolicyAdmission {
48
55
  */
49
56
  private readonly attested;
50
57
  private readonly workspaceAccess;
58
+ /**
59
+ * Removers of the document input roots granted per session, so a grant lives
60
+ * exactly as long as the workspace access that justified it.
61
+ */
62
+ private readonly documentInputRoots;
51
63
  /**
52
64
  * Every name reachable anywhere in one QA conversation, keyed by session id.
53
65
  *
@@ -67,7 +79,9 @@ export declare class QaPolicyAdmission {
67
79
  */
68
80
  dynamicToolNames?: (agent: Agent) => readonly string[],
69
81
  /** Resolve and freeze the session's subrole policy after its agent exists. */
70
- capabilityPolicy?: ((token: string, sessionId: string, agent: Agent) => Promise<QaResolvedSessionPolicy | undefined>) | undefined,
82
+ capabilityPolicy?: ((owner: {
83
+ readonly id: string;
84
+ } | undefined, sessionId: string, agent: Agent) => Promise<QaResolvedSessionPolicy | undefined>) | undefined,
71
85
  /** Scope-local catalog entries may be known before they are activated. */
72
86
  knownDynamicToolNames?: () => readonly string[]);
73
87
  /**
@@ -92,6 +106,20 @@ export declare class QaPolicyAdmission {
92
106
  * Source preview asks for the same root, so one upload is readable by both.
93
107
  */
94
108
  attachmentRoot(): string | undefined;
109
+ /**
110
+ * Carry the fence's attachment exemption into the document pipeline.
111
+ *
112
+ * The guard above lets a single-file read reach the mounted store: an upload
113
+ * is content-addressed, immutable, outside every workspace, and the prompt
114
+ * hands the model exactly that path. The document pipeline keeps its own
115
+ * read scope and knew nothing about the store, so `document_*` refused the
116
+ * very file the model was allowed to read — the panel's own Word preview hit
117
+ * the same wall. The grant is the missing hand-over, made where the access it
118
+ * mirrors is made: per admitted session, and revoked with it.
119
+ */
120
+ private grantDocumentInputRoots;
121
+ /** Drop one session's document grant, if the pipeline still holds it. */
122
+ private revokeDocumentInputRoots;
95
123
  /**
96
124
  * The live agent for one session, resuming a Session the Host has not
97
125
  * materialized in this process.
@@ -127,6 +155,29 @@ export declare class QaPolicyAdmission {
127
155
  */
128
156
  private accessOwner;
129
157
  secureSession(token: string, sessionId: string): Promise<QaLockdownProof>;
158
+ /**
159
+ * The same admission for a caller whose account was already authenticated by
160
+ * another credential — the integration API, which has a service token and no
161
+ * browser session.
162
+ *
163
+ * Everything after identity is shared with {@link secureSession}: the
164
+ * policy pins, the tool allow-list, the QA tool attachment and the
165
+ * attestation record are one code path, because a second copy of admission
166
+ * would be a second place for a QA chat to be admitted without them.
167
+ *
168
+ * @param userId - the account the credential resolved to.
169
+ * @param sessionId - the session to attest.
170
+ * @returns the sanitized proof, as the browser path receives it.
171
+ */
172
+ secureSessionForUser(userId: string, sessionId: string): Promise<QaLockdownProof>;
173
+ /**
174
+ * The account behind one session, taken from the ownership record rather
175
+ * than from a token. The record is the same authority the token path reads:
176
+ * a chat belongs to exactly one account, and a service token may only ever
177
+ * reach the chats of its own.
178
+ */
179
+ private ownerById;
180
+ private secureSessionAs;
130
181
  /**
131
182
  * Mask one agent down to the policy's tool names, for the account-free path
132
183
  * (a capability policy installs its own mask through its grants).
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Formats the files panel previews by conversion instead of by bytes.
3
+ *
4
+ * Shared by the Host half (which owns the conversion) and the browser card
5
+ * (which decides whether opening a file should ask for one), so the two cannot
6
+ * drift on what "we can render this" means. Dependency-free on purpose: the
7
+ * card bundle inlines it.
8
+ */
9
+ /** OOXML word-processing documents, as the deployment detects them. */
10
+ export declare const QA_WORD_MEDIA_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
11
+ /** The media type of the PDF a converted document arrives as. */
12
+ export declare const QA_PDF_MEDIA_TYPE = "application/pdf";
13
+ /**
14
+ * Whether the panel asks the Host for a converted PDF rather than rendering the
15
+ * bytes it already holds. Word documents are the whole set: the document
16
+ * pipeline reads them and renders PDF, while its other inputs are already
17
+ * previewable (Markdown as text, PDF through the browser's own viewer).
18
+ */
19
+ export declare function isConvertibleDocument(mediaType: string): boolean;
20
+ //# sourceMappingURL=documents.d.ts.map
@@ -0,0 +1,24 @@
1
+ import type { QaServiceTokenScope } from "../types.js";
2
+ /**
3
+ * The integration-token vocabulary and its bounds, on the browser side too.
4
+ *
5
+ * Minting lives in `accounts/service-token.ts`, which is Host-only (it hashes a
6
+ * secret before storing it); the profile page has to name the same scopes and
7
+ * enforce the same limits without importing that. Dependency-free like every
8
+ * `src/shared` module, so both bundles inline it and there is exactly one copy
9
+ * of the numbers the two halves have to agree on.
10
+ */
11
+ /**
12
+ * What an integration token may do. Scopes are checked per request rather than
13
+ * per deployment: the same bridge token that asks questions carries no
14
+ * permission to read back a conversation catalog it was not given.
15
+ */
16
+ export declare const QA_SERVICE_TOKEN_SCOPES: readonly QaServiceTokenScope[];
17
+ /** A token that carries no scope is useless; `ask` is what the API is for. */
18
+ export declare const QA_SERVICE_TOKEN_DEFAULT_SCOPES: readonly QaServiceTokenScope[];
19
+ /** Bounds the caller's label; it is a note to the operator, not a document. */
20
+ export declare const QA_SERVICE_TOKEN_LABEL_MAX = 80;
21
+ /** Bounds on a token's life; zero or a negative TTL would mint a dead token. */
22
+ export declare const QA_SERVICE_TOKEN_TTL_DAYS_MIN = 1;
23
+ export declare const QA_SERVICE_TOKEN_TTL_DAYS_MAX = 3650;
24
+ //# sourceMappingURL=integration-tokens.d.ts.map