@shivaedev/work-board 0.7.2 → 0.9.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 (277) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +110 -2
  3. package/assets/agent.js +37 -0
  4. package/assets/native.js +54 -25
  5. package/dist/board.d.ts +1 -0
  6. package/dist/board.d.ts.map +1 -1
  7. package/dist/board.js +15 -2
  8. package/dist/board.js.map +1 -1
  9. package/dist/browser/client.d.ts +19 -79
  10. package/dist/browser/client.d.ts.map +1 -1
  11. package/dist/browser/client.js +12 -1
  12. package/dist/browser/client.js.map +1 -1
  13. package/dist/browser/entry.d.ts +3 -0
  14. package/dist/browser/entry.d.ts.map +1 -0
  15. package/dist/browser/entry.js +7 -0
  16. package/dist/browser/entry.js.map +1 -0
  17. package/dist/browser/responses/Prompt.d.ts +10 -0
  18. package/dist/browser/responses/Prompt.d.ts.map +1 -0
  19. package/dist/browser/responses/Prompt.js +2 -0
  20. package/dist/browser/responses/Prompt.js.map +1 -0
  21. package/dist/browser/responses/answerBody.d.ts +4 -0
  22. package/dist/browser/responses/answerBody.d.ts.map +1 -0
  23. package/dist/browser/responses/answerBody.js +9 -0
  24. package/dist/browser/responses/answerBody.js.map +1 -0
  25. package/dist/browser/responses/draftSession.d.ts +8 -0
  26. package/dist/browser/responses/draftSession.d.ts.map +1 -0
  27. package/dist/browser/responses/draftSession.js +105 -0
  28. package/dist/browser/responses/draftSession.js.map +1 -0
  29. package/dist/browser/responses/drafts.d.ts +21 -0
  30. package/dist/browser/responses/drafts.d.ts.map +1 -0
  31. package/dist/browser/responses/drafts.js +68 -0
  32. package/dist/browser/responses/drafts.js.map +1 -0
  33. package/dist/browser/responses/preview.d.ts +4 -0
  34. package/dist/browser/responses/preview.d.ts.map +1 -0
  35. package/dist/browser/responses/preview.js +5 -0
  36. package/dist/browser/responses/preview.js.map +1 -0
  37. package/dist/browser/responses/questionnaireControls.d.ts +10 -0
  38. package/dist/browser/responses/questionnaireControls.d.ts.map +1 -0
  39. package/dist/browser/responses/questionnaireControls.js +68 -0
  40. package/dist/browser/responses/questionnaireControls.js.map +1 -0
  41. package/dist/browser/responses/schema.d.ts +168 -0
  42. package/dist/browser/responses/schema.d.ts.map +1 -0
  43. package/dist/browser/responses/schema.js +57 -0
  44. package/dist/browser/responses/schema.js.map +1 -0
  45. package/dist/browser/responses/setup.d.ts +2 -0
  46. package/dist/browser/responses/setup.d.ts.map +1 -0
  47. package/dist/browser/responses/setup.js +129 -0
  48. package/dist/browser/responses/setup.js.map +1 -0
  49. package/dist/browser/responses/submissionFields.d.ts +15 -0
  50. package/dist/browser/responses/submissionFields.d.ts.map +1 -0
  51. package/dist/browser/responses/submissionFields.js +14 -0
  52. package/dist/browser/responses/submissionFields.js.map +1 -0
  53. package/dist/browser/responses/submit.d.ts +4 -0
  54. package/dist/browser/responses/submit.d.ts.map +1 -0
  55. package/dist/browser/responses/submit.js +30 -0
  56. package/dist/browser/responses/submit.js.map +1 -0
  57. package/dist/browser/session.d.ts +1 -79
  58. package/dist/browser/session.d.ts.map +1 -1
  59. package/dist/cli.d.ts.map +1 -1
  60. package/dist/cli.js +24 -15
  61. package/dist/cli.js.map +1 -1
  62. package/dist/files/changes.d.ts +1 -0
  63. package/dist/files/changes.d.ts.map +1 -1
  64. package/dist/files/changes.js +1 -1
  65. package/dist/files/changes.js.map +1 -1
  66. package/dist/http/respond.d.ts.map +1 -1
  67. package/dist/http/respond.js +2 -0
  68. package/dist/http/respond.js.map +1 -1
  69. package/dist/metadata/backlinks.d.ts.map +1 -1
  70. package/dist/metadata/backlinks.js +5 -0
  71. package/dist/metadata/backlinks.js.map +1 -1
  72. package/dist/metadata/fields.d.ts +23 -1
  73. package/dist/metadata/fields.d.ts.map +1 -1
  74. package/dist/metadata/problems.d.ts.map +1 -1
  75. package/dist/metadata/problems.js +3 -0
  76. package/dist/metadata/problems.js.map +1 -1
  77. package/dist/metadata/schema.d.ts +23 -1
  78. package/dist/metadata/schema.d.ts.map +1 -1
  79. package/dist/metadata/schema.js +6 -2
  80. package/dist/metadata/schema.js.map +1 -1
  81. package/dist/page/attentionDetails.d.ts.map +1 -1
  82. package/dist/page/attentionDetails.js +2 -1
  83. package/dist/page/attentionDetails.js.map +1 -1
  84. package/dist/page/metadataDetails.d.ts.map +1 -1
  85. package/dist/page/metadataDetails.js +6 -0
  86. package/dist/page/metadataDetails.js.map +1 -1
  87. package/dist/page/navigationScript.js +1 -1
  88. package/dist/page/shell.d.ts +1 -1
  89. package/dist/page/shell.d.ts.map +1 -1
  90. package/dist/page/shell.js.map +1 -1
  91. package/dist/page/style.d.ts.map +1 -1
  92. package/dist/page/style.js +3 -1
  93. package/dist/page/style.js.map +1 -1
  94. package/dist/page/swap.d.ts +1 -1
  95. package/dist/page/swap.d.ts.map +1 -1
  96. package/dist/page/swap.js +3 -0
  97. package/dist/page/swap.js.map +1 -1
  98. package/dist/path/Identity.d.ts +3 -0
  99. package/dist/path/Identity.d.ts.map +1 -0
  100. package/dist/path/Identity.js +3 -0
  101. package/dist/path/Identity.js.map +1 -0
  102. package/dist/render/markdown.d.ts +1 -0
  103. package/dist/render/markdown.d.ts.map +1 -1
  104. package/dist/render/markdown.js +4 -2
  105. package/dist/render/markdown.js.map +1 -1
  106. package/dist/render/questionnaireDocuments.d.ts +3 -0
  107. package/dist/render/questionnaireDocuments.d.ts.map +1 -0
  108. package/dist/render/questionnaireDocuments.js +11 -0
  109. package/dist/render/questionnaireDocuments.js.map +1 -0
  110. package/dist/render/visualDocuments.d.ts.map +1 -1
  111. package/dist/render/visualDocuments.js +3 -0
  112. package/dist/render/visualDocuments.js.map +1 -1
  113. package/dist/responses/agent-cli.d.ts +2 -0
  114. package/dist/responses/agent-cli.d.ts.map +1 -0
  115. package/dist/responses/agent-cli.js +31 -0
  116. package/dist/responses/agent-cli.js.map +1 -0
  117. package/dist/responses/agent.d.ts +80 -0
  118. package/dist/responses/agent.d.ts.map +1 -0
  119. package/dist/responses/agent.js +49 -0
  120. package/dist/responses/agent.js.map +1 -0
  121. package/dist/responses/await.d.ts +39 -0
  122. package/dist/responses/await.d.ts.map +1 -0
  123. package/dist/responses/await.js +21 -0
  124. package/dist/responses/await.js.map +1 -0
  125. package/dist/responses/composerHtml.d.ts +27 -0
  126. package/dist/responses/composerHtml.d.ts.map +1 -0
  127. package/dist/responses/composerHtml.js +14 -0
  128. package/dist/responses/composerHtml.js.map +1 -0
  129. package/dist/responses/flags.d.ts +6 -0
  130. package/dist/responses/flags.d.ts.map +1 -0
  131. package/dist/responses/flags.js +23 -0
  132. package/dist/responses/flags.js.map +1 -0
  133. package/dist/responses/history.d.ts +20 -0
  134. package/dist/responses/history.d.ts.map +1 -0
  135. package/dist/responses/history.js +16 -0
  136. package/dist/responses/history.js.map +1 -0
  137. package/dist/responses/locate.d.ts +13 -0
  138. package/dist/responses/locate.d.ts.map +1 -0
  139. package/dist/responses/locate.js +55 -0
  140. package/dist/responses/locate.js.map +1 -0
  141. package/dist/responses/make.d.ts +3 -0
  142. package/dist/responses/make.d.ts.map +1 -0
  143. package/dist/responses/make.js +16 -0
  144. package/dist/responses/make.js.map +1 -0
  145. package/dist/responses/outcome.d.ts +71 -0
  146. package/dist/responses/outcome.d.ts.map +1 -0
  147. package/dist/responses/outcome.js +14 -0
  148. package/dist/responses/outcome.js.map +1 -0
  149. package/dist/responses/page.d.ts +6 -0
  150. package/dist/responses/page.d.ts.map +1 -0
  151. package/dist/responses/page.js +22 -0
  152. package/dist/responses/page.js.map +1 -0
  153. package/dist/responses/publish.d.ts +4 -0
  154. package/dist/responses/publish.d.ts.map +1 -0
  155. package/dist/responses/publish.js +56 -0
  156. package/dist/responses/publish.js.map +1 -0
  157. package/dist/responses/publishIn.d.ts +3 -0
  158. package/dist/responses/publishIn.d.ts.map +1 -0
  159. package/dist/responses/publishIn.js +69 -0
  160. package/dist/responses/publishIn.js.map +1 -0
  161. package/dist/responses/read.d.ts +36 -0
  162. package/dist/responses/read.d.ts.map +1 -0
  163. package/dist/responses/read.js +43 -0
  164. package/dist/responses/read.js.map +1 -0
  165. package/dist/responses/records.d.ts +12 -0
  166. package/dist/responses/records.d.ts.map +1 -0
  167. package/dist/responses/records.js +49 -0
  168. package/dist/responses/records.js.map +1 -0
  169. package/dist/responses/retry.d.ts +34 -0
  170. package/dist/responses/retry.d.ts.map +1 -0
  171. package/dist/responses/retry.js +14 -0
  172. package/dist/responses/retry.js.map +1 -0
  173. package/dist/responses/service.d.ts +142 -0
  174. package/dist/responses/service.d.ts.map +1 -0
  175. package/dist/responses/service.js +95 -0
  176. package/dist/responses/service.js.map +1 -0
  177. package/dist/responses/template.d.ts +7 -0
  178. package/dist/responses/template.d.ts.map +1 -0
  179. package/dist/responses/template.js +58 -0
  180. package/dist/responses/template.js.map +1 -0
  181. package/dist/responses/templateHtml.d.ts +7 -0
  182. package/dist/responses/templateHtml.d.ts.map +1 -0
  183. package/dist/responses/templateHtml.js +18 -0
  184. package/dist/responses/templateHtml.js.map +1 -0
  185. package/dist/responses/templateLinks.d.ts +3 -0
  186. package/dist/responses/templateLinks.d.ts.map +1 -0
  187. package/dist/responses/templateLinks.js +45 -0
  188. package/dist/responses/templateLinks.js.map +1 -0
  189. package/dist/responses/templateNodes.d.ts +17 -0
  190. package/dist/responses/templateNodes.d.ts.map +1 -0
  191. package/dist/responses/templateNodes.js +47 -0
  192. package/dist/responses/templateNodes.js.map +1 -0
  193. package/dist/responses/validateSupersedes.d.ts +5 -0
  194. package/dist/responses/validateSupersedes.d.ts.map +1 -0
  195. package/dist/responses/validateSupersedes.js +21 -0
  196. package/dist/responses/validateSupersedes.js.map +1 -0
  197. package/dist/responses/validatedInput.d.ts +3 -0
  198. package/dist/responses/validatedInput.d.ts.map +1 -0
  199. package/dist/responses/validatedInput.js +43 -0
  200. package/dist/responses/validatedInput.js.map +1 -0
  201. package/dist/responses/waitFor.d.ts +37 -0
  202. package/dist/responses/waitFor.d.ts.map +1 -0
  203. package/dist/responses/waitFor.js +47 -0
  204. package/dist/responses/waitFor.js.map +1 -0
  205. package/dist/rpc/contract.d.ts +125 -2
  206. package/dist/rpc/contract.d.ts.map +1 -1
  207. package/dist/rpc/contract.js +3 -2
  208. package/dist/rpc/contract.js.map +1 -1
  209. package/dist/rpc/responseContract.d.ts +260 -0
  210. package/dist/rpc/responseContract.d.ts.map +1 -0
  211. package/dist/rpc/responseContract.js +37 -0
  212. package/dist/rpc/responseContract.js.map +1 -0
  213. package/dist/rpc/server.d.ts +3 -1
  214. package/dist/rpc/server.d.ts.map +1 -1
  215. package/dist/rpc/server.js +6 -1
  216. package/dist/rpc/server.js.map +1 -1
  217. package/dist/serve-cli.d.ts +3 -0
  218. package/dist/serve-cli.d.ts.map +1 -0
  219. package/dist/serve-cli.js +20 -0
  220. package/dist/serve-cli.js.map +1 -0
  221. package/package.json +3 -3
  222. package/src/board.ts +16 -2
  223. package/src/browser/client.ts +30 -4
  224. package/src/browser/entry.ts +9 -0
  225. package/src/browser/responses/Prompt.ts +6 -0
  226. package/src/browser/responses/answerBody.ts +11 -0
  227. package/src/browser/responses/draftSession.ts +101 -0
  228. package/src/browser/responses/drafts.ts +82 -0
  229. package/src/browser/responses/preview.ts +7 -0
  230. package/src/browser/responses/questionnaireControls.ts +74 -0
  231. package/src/browser/responses/schema.ts +63 -0
  232. package/src/browser/responses/setup.ts +132 -0
  233. package/src/browser/responses/submissionFields.ts +15 -0
  234. package/src/browser/responses/submit.ts +33 -0
  235. package/src/cli.ts +14 -22
  236. package/src/files/changes.ts +2 -1
  237. package/src/http/respond.ts +2 -0
  238. package/src/metadata/backlinks.ts +5 -0
  239. package/src/metadata/problems.ts +3 -0
  240. package/src/metadata/schema.ts +6 -2
  241. package/src/page/attentionDetails.ts +2 -1
  242. package/src/page/metadataDetails.ts +6 -0
  243. package/src/page/navigationScript.ts +1 -1
  244. package/src/page/shell.ts +1 -1
  245. package/src/page/style.ts +3 -1
  246. package/src/page/swap.ts +3 -0
  247. package/src/path/Identity.ts +3 -0
  248. package/src/render/markdown.ts +5 -2
  249. package/src/render/questionnaireDocuments.ts +12 -0
  250. package/src/render/visualDocuments.ts +3 -0
  251. package/src/responses/agent-cli.ts +35 -0
  252. package/src/responses/agent.ts +59 -0
  253. package/src/responses/await.ts +21 -0
  254. package/src/responses/composerHtml.ts +28 -0
  255. package/src/responses/flags.ts +22 -0
  256. package/src/responses/history.ts +18 -0
  257. package/src/responses/locate.ts +60 -0
  258. package/src/responses/make.ts +17 -0
  259. package/src/responses/outcome.ts +15 -0
  260. package/src/responses/page.ts +30 -0
  261. package/src/responses/publish.ts +53 -0
  262. package/src/responses/publishIn.ts +64 -0
  263. package/src/responses/read.ts +45 -0
  264. package/src/responses/records.ts +55 -0
  265. package/src/responses/retry.ts +23 -0
  266. package/src/responses/service.ts +117 -0
  267. package/src/responses/template.ts +72 -0
  268. package/src/responses/templateHtml.ts +26 -0
  269. package/src/responses/templateLinks.ts +43 -0
  270. package/src/responses/templateNodes.ts +55 -0
  271. package/src/responses/validateSupersedes.ts +24 -0
  272. package/src/responses/validatedInput.ts +45 -0
  273. package/src/responses/waitFor.ts +58 -0
  274. package/src/rpc/contract.ts +3 -2
  275. package/src/rpc/responseContract.ts +46 -0
  276. package/src/rpc/server.ts +8 -1
  277. package/src/serve-cli.ts +37 -0
@@ -0,0 +1,71 @@
1
+ import type { Reading } from "#browser/responses/schema.ts";
2
+ export declare function outcome(reading: Reading, after: string | undefined, now: number): {
3
+ readonly kind: "missing_cursor";
4
+ readonly response?: never;
5
+ readonly question?: never;
6
+ } | {
7
+ readonly kind: "response";
8
+ readonly question: {
9
+ readonly context: string;
10
+ readonly id: string;
11
+ readonly question: {
12
+ readonly deadline: number;
13
+ readonly item: string;
14
+ readonly reason: string;
15
+ readonly registeredAt: number;
16
+ readonly request: string;
17
+ readonly reviewedRevision: string;
18
+ readonly source: string;
19
+ };
20
+ };
21
+ readonly response: {
22
+ readonly body: string;
23
+ readonly id: string;
24
+ readonly response: {
25
+ readonly answers?: readonly {
26
+ readonly prompt: string;
27
+ readonly selected: readonly string[];
28
+ readonly text: string;
29
+ }[] | undefined;
30
+ readonly author: string;
31
+ readonly question: string;
32
+ readonly recordedAt: number;
33
+ readonly reviewedRevision: string;
34
+ readonly supersedes?: string | undefined;
35
+ readonly type: "answer" | "clarify" | "not_now";
36
+ };
37
+ };
38
+ } | {
39
+ readonly response?: never;
40
+ readonly kind: "unanswered";
41
+ readonly question: {
42
+ readonly context: string;
43
+ readonly id: string;
44
+ readonly question: {
45
+ readonly deadline: number;
46
+ readonly item: string;
47
+ readonly reason: string;
48
+ readonly registeredAt: number;
49
+ readonly request: string;
50
+ readonly reviewedRevision: string;
51
+ readonly source: string;
52
+ };
53
+ };
54
+ } | {
55
+ readonly response?: never;
56
+ readonly kind: "pending";
57
+ readonly question: {
58
+ readonly context: string;
59
+ readonly id: string;
60
+ readonly question: {
61
+ readonly deadline: number;
62
+ readonly item: string;
63
+ readonly reason: string;
64
+ readonly registeredAt: number;
65
+ readonly request: string;
66
+ readonly reviewedRevision: string;
67
+ readonly source: string;
68
+ };
69
+ };
70
+ };
71
+ //# sourceMappingURL=outcome.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outcome.d.ts","sourceRoot":"","sources":["../../src/responses/outcome.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAE5D,wBAAgB,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,GAAG,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAY/E"}
@@ -0,0 +1,14 @@
1
+ export function outcome(reading, after, now) {
2
+ const at = after === undefined ? -1 : reading.responses.findIndex((candidate) => candidate.id === after);
3
+ if (after !== undefined && at < 0) {
4
+ return { kind: "missing_cursor" };
5
+ }
6
+ const response = reading.responses[at + 1];
7
+ if (response) {
8
+ return { kind: "response", question: reading.question, response };
9
+ }
10
+ return now >= reading.question.question.deadline
11
+ ? { kind: "unanswered", question: reading.question }
12
+ : { kind: "pending", question: reading.question };
13
+ }
14
+ //# sourceMappingURL=outcome.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outcome.js","sourceRoot":"","sources":["../../src/responses/outcome.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,OAAO,CAAC,OAAgB,EAAE,KAAyB,EAAE,GAAW;IAC/E,MAAM,EAAE,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,KAAK,KAAK,CAAC,CAAC;IACzG,IAAI,KAAK,KAAK,SAAS,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;QACnC,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAW,CAAC;IAC5C,CAAC;IACD,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAC3C,IAAI,QAAQ,EAAE,CAAC;QACd,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,QAAQ,EAAW,CAAC;IAC5E,CAAC;IACD,OAAO,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ;QAC/C,CAAC,CAAE,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAY;QAC/D,CAAC,CAAE,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAY,CAAC;AAC/D,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { Effect } from "effect";
2
+ import type { HttpServerRequest } from "effect/unstable/http";
3
+ import type { Changes } from "#files/changes.ts";
4
+ import type { responseService } from "./service.ts";
5
+ export declare function responsePage(service: Effect.Success<ReturnType<typeof responseService>>, changes: Changes, home: string | undefined, enabled: boolean): (request: HttpServerRequest.HttpServerRequest) => Effect.Effect<import("effect/unstable/http/HttpServerResponse").HttpServerResponse, import("effect/PlatformError").PlatformError, import("effect/FileSystem").FileSystem | import("../render/highlighter.ts").Highlighter | import("effect/Path").Path>;
6
+ //# sourceMappingURL=page.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../src/responses/page.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAMjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,wBAAgB,YAAY,CAC3B,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC,EAC3D,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,OAAO,EAAE,OAAO,6SAehB"}
@@ -0,0 +1,22 @@
1
+ import { Effect } from "effect";
2
+ import { respond } from "#http/respond.ts";
3
+ import { escapeHtml } from "#page/escape.ts";
4
+ import { navHtml } from "#page/nav.ts";
5
+ import { shell } from "#page/shell.ts";
6
+ import { composerHtml } from "./composerHtml.js";
7
+ export function responsePage(service, changes, home, enabled) {
8
+ return Effect.fn("WorkBoard.responsePage")(function* (request) {
9
+ const params = new URL(request.url, "http://127.0.0.1").searchParams;
10
+ const files = yield* changes.files;
11
+ function layout(body, status = 200) {
12
+ return respond(shell("Respond", navHtml(files, "", home), body, changes.realRoot, false, undefined, "response"), "text/html", status);
13
+ }
14
+ return yield* Effect.gen(function* () {
15
+ const question = yield* service.locate(params.get("item") ?? "", params.get("request") ?? "");
16
+ yield* service.read(question.id).pipe(Effect.catch((error) => (error.code === "Missing" ? Effect.void : Effect.fail(error))));
17
+ const records = yield* service.history(question);
18
+ return layout(yield* composerHtml(question, records, enabled));
19
+ }).pipe(Effect.catch((error) => Effect.succeed(layout(`<h1>Response unavailable</h1><p>${escapeHtml(String(error))}</p>`, 409))));
20
+ });
21
+ }
22
+ //# sourceMappingURL=page.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page.js","sourceRoot":"","sources":["../../src/responses/page.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGhC,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGjD,MAAM,UAAU,YAAY,CAC3B,OAA2D,EAC3D,OAAgB,EAChB,IAAwB,EACxB,OAAgB;IAEhB,OAAO,MAAM,CAAC,EAAE,CAAC,wBAAwB,CAAC,CAAC,QAAQ,CAAC,EAAE,OAA4C;QACjG,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC,YAAY,CAAC;QACrE,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;QACnC,SAAS,MAAM,CAAC,IAAY,EAAE,MAAM,GAAG,GAAG;YACzC,OAAO,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,KAAK,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;QACvI,CAAC;QACD,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YACjC,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC;YAC9F,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9H,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YACjD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;QAChE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,mCAAmC,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACnI,CAAC,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { Effect } from "effect";
2
+ import { ResponseFailed } from "#browser/responses/schema.ts";
3
+ export declare function publish(root: string, realRoot: string, id: string, content: string): Effect.Effect<void, ResponseFailed, never>;
4
+ //# sourceMappingURL=publish.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../../src/responses/publish.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAW9D,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,8CAsClF"}
@@ -0,0 +1,56 @@
1
+ import { constants } from "node:fs";
2
+ import { mkdir, open, realpath } from "node:fs/promises";
3
+ import { Effect } from "effect";
4
+ import { ResponseFailed } from "#browser/responses/schema.ts";
5
+ import { publishIn } from "./publishIn.js";
6
+ function failure(cause) {
7
+ return cause instanceof ResponseFailed
8
+ ? cause
9
+ : new ResponseFailed({
10
+ code: "Unavailable",
11
+ message: "The response could not be recorded. Keep the draft and retry after checking local filesystem access.",
12
+ });
13
+ }
14
+ export function publish(root, realRoot, id, content) {
15
+ return Effect.tryPromise({
16
+ catch: failure,
17
+ try: async () => {
18
+ if (/^[a-zA-Z\d][a-zA-Z\d._-]*$/u.exec(id) === null) {
19
+ throw new ResponseFailed({ code: "Conflict", message: "Invalid response identity." });
20
+ }
21
+ if (process.platform !== "linux") {
22
+ throw new ResponseFailed({
23
+ code: "Unsupported",
24
+ message: "Safe response publication currently requires Linux directory descriptors. Reading remains available.",
25
+ });
26
+ }
27
+ const directory = await open(root, constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);
28
+ try {
29
+ const base = `/proc/self/fd/${directory.fd}`;
30
+ if ((await realpath(base)) !== realRoot || (await realpath(root)) !== realRoot) {
31
+ throw new ResponseFailed({ code: "Conflict", message: "The workspace root changed. Restart against the intended root." });
32
+ }
33
+ try {
34
+ await mkdir(`${base}/responses`);
35
+ }
36
+ catch (cause) {
37
+ if (!(cause instanceof Error && "code" in cause && cause.code === "EEXIST")) {
38
+ throw cause;
39
+ }
40
+ }
41
+ await directory.sync();
42
+ const target = await open(`${base}/responses`, constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);
43
+ try {
44
+ await publishIn(target, root, realRoot, id, content);
45
+ }
46
+ finally {
47
+ await target.close();
48
+ }
49
+ }
50
+ finally {
51
+ await directory.close();
52
+ }
53
+ },
54
+ });
55
+ }
56
+ //# sourceMappingURL=publish.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish.js","sourceRoot":"","sources":["../../src/responses/publish.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,SAAS,OAAO,CAAC,KAAc;IAC9B,OAAO,KAAK,YAAY,cAAc;QACrC,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,IAAI,cAAc,CAAC;YACnB,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,sGAAsG;SAC/G,CAAC,CAAC;AACN,CAAC;AACD,MAAM,UAAU,OAAO,CAAC,IAAY,EAAE,QAAgB,EAAE,EAAU,EAAE,OAAe;IAClF,OAAO,MAAM,CAAC,UAAU,CAAC;QACxB,KAAK,EAAE,OAAO;QACd,GAAG,EAAE,KAAK,IAAI,EAAE;YACf,IAAI,6BAA6B,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC;gBACrD,MAAM,IAAI,cAAc,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,4BAA4B,EAAE,CAAC,CAAC;YACvF,CAAC;YACD,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;gBAClC,MAAM,IAAI,cAAc,CAAC;oBACxB,IAAI,EAAE,aAAa;oBACnB,OAAO,EAAE,sGAAsG;iBAC/G,CAAC,CAAC;YACJ,CAAC;YACD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,QAAQ,GAAG,SAAS,CAAC,WAAW,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC;YACtG,IAAI,CAAC;gBACJ,MAAM,IAAI,GAAG,iBAAiB,SAAS,CAAC,EAAE,EAAE,CAAC;gBAC7C,IAAI,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,QAAQ,IAAI,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;oBAChF,MAAM,IAAI,cAAc,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,gEAAgE,EAAE,CAAC,CAAC;gBAC3H,CAAC;gBACD,IAAI,CAAC;oBACJ,MAAM,KAAK,CAAC,GAAG,IAAI,YAAY,CAAC,CAAC;gBAClC,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBAChB,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,EAAE,CAAC;wBAC7E,MAAM,KAAK,CAAC;oBACb,CAAC;gBACF,CAAC;gBACD,MAAM,SAAS,CAAC,IAAI,EAAE,CAAC;gBACvB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,IAAI,YAAY,EAAE,SAAS,CAAC,QAAQ,GAAG,SAAS,CAAC,WAAW,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC;gBAClH,IAAI,CAAC;oBACJ,MAAM,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;gBACtD,CAAC;wBAAS,CAAC;oBACV,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;gBACtB,CAAC;YACF,CAAC;oBAAS,CAAC;gBACV,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;YACzB,CAAC;QACF,CAAC;KACD,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { type FileHandle } from "node:fs/promises";
2
+ export declare function publishIn(target: FileHandle, root: string, realRoot: string, id: string, content: string): Promise<void>;
3
+ //# sourceMappingURL=publishIn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publishIn.d.ts","sourceRoot":"","sources":["../../src/responses/publishIn.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,UAAU,EAA0C,MAAM,kBAAkB,CAAC;AA4B3F,wBAAsB,SAAS,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,iBAiC9G"}
@@ -0,0 +1,69 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { constants } from "node:fs";
3
+ import { link, open, readFile, realpath, unlink } from "node:fs/promises";
4
+ import { ResponseFailed } from "#browser/responses/schema.ts";
5
+ function uncertain(cause) {
6
+ return new ResponseFailed({ cause, code: "Uncertain", message: "Publication may have completed. Re-read the response identity before retrying." });
7
+ }
8
+ function exists(cause) {
9
+ return cause instanceof Error && "code" in cause && cause.code === "EEXIST";
10
+ }
11
+ async function linkOrReconcile(temporary, name, content) {
12
+ try {
13
+ await link(temporary, name);
14
+ return true;
15
+ }
16
+ catch (cause) {
17
+ if (!exists(cause)) {
18
+ throw cause;
19
+ }
20
+ }
21
+ const existing = await open(name, constants.O_RDONLY | constants.O_NOFOLLOW);
22
+ try {
23
+ if ((await readFile(existing, "utf8")) !== content) {
24
+ throw new ResponseFailed({ code: "Conflict", message: "This identity already records different content; no file was replaced." });
25
+ }
26
+ }
27
+ finally {
28
+ await existing.close();
29
+ }
30
+ return false;
31
+ }
32
+ export async function publishIn(target, root, realRoot, id, content) {
33
+ const folder = `/proc/self/fd/${target.fd}`;
34
+ const expected = `${realRoot}/responses`;
35
+ async function validate() {
36
+ if ((await realpath(folder)) !== expected || (await realpath(root)) !== realRoot) {
37
+ throw new ResponseFailed({ code: "Conflict", message: "The write boundary changed." });
38
+ }
39
+ }
40
+ await validate();
41
+ const name = `${folder}/${id}.md`;
42
+ const temporary = `${folder}/.${randomUUID()}.tmp`;
43
+ let published = false;
44
+ try {
45
+ const file = await open(temporary, "wx", 0o600);
46
+ try {
47
+ await file.writeFile(content, "utf8");
48
+ await file.sync();
49
+ }
50
+ finally {
51
+ await file.close();
52
+ }
53
+ await validate();
54
+ await linkOrReconcile(temporary, name, content);
55
+ published = true;
56
+ await target.sync();
57
+ await validate();
58
+ }
59
+ catch (cause) {
60
+ if (published) {
61
+ throw uncertain(cause);
62
+ }
63
+ throw cause;
64
+ }
65
+ finally {
66
+ await unlink(temporary).catch(() => undefined);
67
+ }
68
+ }
69
+ //# sourceMappingURL=publishIn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publishIn.js","sourceRoot":"","sources":["../../src/responses/publishIn.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import { Effect } from "effect";
2
+ import { ResponseFailed } from "#browser/responses/schema.ts";
3
+ import type { Snapshot } from "#search/snapshot.ts";
4
+ export declare function readResponses(snapshot: Effect.Effect<Snapshot, ResponseFailed>): (id: string) => Effect.Effect<{
5
+ readonly question: {
6
+ readonly context: string;
7
+ readonly id: string;
8
+ readonly question: {
9
+ readonly deadline: number;
10
+ readonly item: string;
11
+ readonly reason: string;
12
+ readonly registeredAt: number;
13
+ readonly request: string;
14
+ readonly reviewedRevision: string;
15
+ readonly source: string;
16
+ };
17
+ };
18
+ readonly responses: readonly {
19
+ readonly body: string;
20
+ readonly id: string;
21
+ readonly response: {
22
+ readonly answers?: readonly {
23
+ readonly prompt: string;
24
+ readonly selected: readonly string[];
25
+ readonly text: string;
26
+ }[] | undefined;
27
+ readonly author: string;
28
+ readonly question: string;
29
+ readonly recordedAt: number;
30
+ readonly reviewedRevision: string;
31
+ readonly supersedes?: string | undefined;
32
+ readonly type: "answer" | "clarify" | "not_now";
33
+ };
34
+ }[];
35
+ }, ResponseFailed, never>;
36
+ //# sourceMappingURL=read.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../src/responses/read.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAE9D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAmBpD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,cAAc,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0BAsB9E"}
@@ -0,0 +1,43 @@
1
+ import { Effect } from "effect";
2
+ import { ResponseFailed } from "#browser/responses/schema.ts";
3
+ import { malformedResponse, questionFrom, responsesFor } from "./records.js";
4
+ function reject(code, message) {
5
+ return Effect.fail(new ResponseFailed({ code, message }));
6
+ }
7
+ const registeredQuestion = Effect.fn("WorkBoard.registeredQuestion")(function* (matches) {
8
+ if (!matches?.length) {
9
+ return yield* reject("Missing", "The registered question is missing.");
10
+ }
11
+ if (matches.length !== 1) {
12
+ return yield* reject("Conflict", "The registered question identity is ambiguous; response history is unknown.");
13
+ }
14
+ const question = matches[0] && questionFrom(matches[0]);
15
+ if (!question) {
16
+ return yield* reject("Conflict", "This identity is not a valid registered question; response history is unknown.");
17
+ }
18
+ return question;
19
+ });
20
+ export function readResponses(snapshot) {
21
+ return Effect.fn("WorkBoard.read")(function* (id) {
22
+ const data = yield* snapshot;
23
+ if (data.unavailable.length > 0) {
24
+ return yield* reject("Unavailable", "The workspace index is incomplete; no response can be selected safely.");
25
+ }
26
+ const question = yield* registeredQuestion(data.model.ids.get(id));
27
+ if (new TextEncoder().encode(question.context).length > 256 * 1024) {
28
+ return yield* reject("Unsupported", "The registered context exceeds the 256 KiB limit.");
29
+ }
30
+ if (data.documents.some(malformedResponse)) {
31
+ return yield* reject("Unavailable", "A response record is malformed; response history cannot be established safely.");
32
+ }
33
+ const result = responsesFor(data.documents, question);
34
+ if (result.responses.some((candidate) => candidate.body.length > 32_768)) {
35
+ return yield* reject("Unsupported", "A recorded response exceeds the supported text limit; read its source file directly.");
36
+ }
37
+ if (result.responses.some((candidate) => data.model.ids.get(candidate.id)?.length !== 1)) {
38
+ return yield* reject("Conflict", "A response identity is duplicated; no answer is selected.");
39
+ }
40
+ return result;
41
+ });
42
+ }
43
+ //# sourceMappingURL=read.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read.js","sourceRoot":"","sources":["../../src/responses/read.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { DraftInput, Question, Reading, RecordedResponse } from "#browser/responses/schema.ts";
2
+ import type { MetadataDocument } from "#metadata/model.ts";
3
+ export declare function revisionOf(source: string): string;
4
+ export declare function questionId(item: string, request: string, revision: string, source: string): string;
5
+ export declare function questionMarkdown(record: Question): string;
6
+ export declare function responseMarkdown(record: RecordedResponse): string;
7
+ export declare function questionFrom(document: MetadataDocument): Question | undefined;
8
+ export declare function responseFrom(document: MetadataDocument): RecordedResponse | undefined;
9
+ export declare function responsesFor(documents: readonly MetadataDocument[], question: Question): Reading;
10
+ export declare function matchesResponse(record: RecordedResponse, input: DraftInput): boolean;
11
+ export declare function malformedResponse(document: MetadataDocument): boolean;
12
+ //# sourceMappingURL=records.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"records.d.ts","sourceRoot":"","sources":["../../src/responses/records.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AACpG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,UAExC;AACD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,UAEzF;AACD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,CAEzD;AACD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAEjE;AACD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,gBAAgB,GAAG,QAAQ,GAAG,SAAS,CAS7E;AACD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,gBAAgB,GAAG,gBAAgB,GAAG,SAAS,CAGrF;AACD,wBAAgB,YAAY,CAAC,SAAS,EAAE,SAAS,gBAAgB,EAAE,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAOhG;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,gBAAgB,EAAE,KAAK,EAAE,UAAU,WAS1E;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,gBAAgB,WAG3D"}
@@ -0,0 +1,49 @@
1
+ import { createHash } from "node:crypto";
2
+ import { stringify } from "yaml";
3
+ export function revisionOf(source) {
4
+ return createHash("sha256").update(source).digest("hex");
5
+ }
6
+ export function questionId(item, request, revision, source) {
7
+ return `question.${revisionOf(JSON.stringify([item, request, revision, source]))}`;
8
+ }
9
+ export function questionMarkdown(record) {
10
+ return `---\n${stringify({ id: record.id, kind: "question", question: record.question })}---\n${record.context}`;
11
+ }
12
+ export function responseMarkdown(record) {
13
+ return `---\n${stringify({ id: record.id, kind: "response", response: record.response })}---\n${record.body}`;
14
+ }
15
+ export function questionFrom(document) {
16
+ const { id, kind, question } = document.parsed.fields;
17
+ return id
18
+ && kind === "question"
19
+ && question
20
+ && question.reviewedRevision === revisionOf(document.parsed.body)
21
+ && id === questionId(question.item, question.request, question.reviewedRevision, question.source)
22
+ ? { context: document.parsed.body, id, question }
23
+ : undefined;
24
+ }
25
+ export function responseFrom(document) {
26
+ const { id, kind, response } = document.parsed.fields;
27
+ return id && kind === "response" && response ? { body: document.parsed.body, id, response } : undefined;
28
+ }
29
+ export function responsesFor(documents, question) {
30
+ const responses = documents.flatMap((document) => {
31
+ const record = responseFrom(document);
32
+ return record?.response.question === question.id && record.response.reviewedRevision === question.question.reviewedRevision ? [record] : [];
33
+ });
34
+ responses.sort((a, b) => a.response.recordedAt - b.response.recordedAt || a.id.localeCompare(b.id));
35
+ return { question, responses };
36
+ }
37
+ export function matchesResponse(record, input) {
38
+ return (record.body === input.body
39
+ && JSON.stringify(record.response.answers) === JSON.stringify(input.answers)
40
+ && record.response.supersedes === input.supersedes
41
+ && record.response.author === input.author
42
+ && record.response.type === input.type
43
+ && record.response.question === input.question);
44
+ }
45
+ export function malformedResponse(document) {
46
+ const fields = document.parsed.fields;
47
+ return fields.kind === "response" && !(fields.id && fields.response);
48
+ }
49
+ //# sourceMappingURL=records.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"records.js","sourceRoot":"","sources":["../../src/responses/records.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AAIjC,MAAM,UAAU,UAAU,CAAC,MAAc;IACxC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC1D,CAAC;AACD,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,OAAe,EAAE,QAAgB,EAAE,MAAc;IACzF,OAAO,YAAY,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;AACpF,CAAC;AACD,MAAM,UAAU,gBAAgB,CAAC,MAAgB;IAChD,OAAO,QAAQ,SAAS,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,QAAQ,MAAM,CAAC,OAAO,EAAE,CAAC;AAClH,CAAC;AACD,MAAM,UAAU,gBAAgB,CAAC,MAAwB;IACxD,OAAO,QAAQ,SAAS,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;AAC/G,CAAC;AACD,MAAM,UAAU,YAAY,CAAC,QAA0B;IACtD,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;IACtD,OAAO,EAAE;WACL,IAAI,KAAK,UAAU;WACnB,QAAQ;WACR,QAAQ,CAAC,gBAAgB,KAAK,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC;WAC9D,EAAE,KAAK,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC;QACjG,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE;QACjD,CAAC,CAAC,SAAS,CAAC;AACd,CAAC;AACD,MAAM,UAAU,YAAY,CAAC,QAA0B;IACtD,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;IACtD,OAAO,EAAE,IAAI,IAAI,KAAK,UAAU,IAAI,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AACzG,CAAC;AACD,MAAM,UAAU,YAAY,CAAC,SAAsC,EAAE,QAAkB;IACtF,MAAM,SAAS,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE;QAChD,MAAM,MAAM,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;QACtC,OAAO,MAAM,EAAE,QAAQ,CAAC,QAAQ,KAAK,QAAQ,CAAC,EAAE,IAAI,MAAM,CAAC,QAAQ,CAAC,gBAAgB,KAAK,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7I,CAAC,CAAC,CAAC;IACH,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,GAAG,CAAC,CAAC,QAAQ,CAAC,UAAU,IAAI,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACpG,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,MAAwB,EAAE,KAAiB;IAC1E,OAAO,CACN,MAAM,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI;WACvB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC;WACzE,MAAM,CAAC,QAAQ,CAAC,UAAU,KAAK,KAAK,CAAC,UAAU;WAC/C,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM;WACvC,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI;WACnC,MAAM,CAAC,QAAQ,CAAC,QAAQ,KAAK,KAAK,CAAC,QAAQ,CAC9C,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,QAA0B;IAC3D,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;IACtC,OAAO,MAAM,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC;AACtE,CAAC"}
@@ -0,0 +1,34 @@
1
+ import { Effect } from "effect";
2
+ import { ResponseFailed } from "#browser/responses/schema.ts";
3
+ import type { Snapshot } from "#search/snapshot.ts";
4
+ import type { ResponseOptions } from "./service.ts";
5
+ export declare const retryResponse: (existing: {
6
+ readonly body: string;
7
+ readonly id: string;
8
+ readonly response: {
9
+ readonly answers?: readonly {
10
+ readonly prompt: string;
11
+ readonly selected: readonly string[];
12
+ readonly text: string;
13
+ }[] | undefined;
14
+ readonly author: string;
15
+ readonly question: string;
16
+ readonly recordedAt: number;
17
+ readonly reviewedRevision: string;
18
+ readonly supersedes?: string | undefined;
19
+ readonly type: "answer" | "clarify" | "not_now";
20
+ };
21
+ }, input: {
22
+ readonly answers?: readonly {
23
+ readonly prompt: string;
24
+ readonly selected: readonly string[];
25
+ readonly text: string;
26
+ }[] | undefined;
27
+ readonly author: string;
28
+ readonly body: string;
29
+ readonly id: string;
30
+ readonly question: string;
31
+ readonly supersedes?: string | undefined;
32
+ readonly type: "answer" | "clarify" | "not_now";
33
+ }, snapshot: Effect.Effect<Snapshot, ResponseFailed, never>, options: ResponseOptions) => Effect.Effect<undefined, ResponseFailed, never>;
34
+ //# sourceMappingURL=retry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/responses/retry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAA0C,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACtG,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;yIAexB,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { Effect } from "effect";
2
+ import { ResponseFailed } from "#browser/responses/schema.ts";
3
+ import { publish } from "./publish.js";
4
+ import { matchesResponse, responseMarkdown } from "./records.js";
5
+ export const retryResponse = Effect.fn("WorkBoard.retryResponse")(function* (existing, input, snapshot, options) {
6
+ if (!matchesResponse(existing, input)) {
7
+ return yield* Effect.fail(new ResponseFailed({ code: "Conflict", message: "The response identity already records different content." }));
8
+ }
9
+ if ((yield* snapshot).model.ids.get(input.id)?.[0]?.file !== `responses/${input.id}.md`) {
10
+ return yield* Effect.fail(new ResponseFailed({ code: "Conflict", message: "The saved response moved. Read its existing record instead of retrying a write." }));
11
+ }
12
+ yield* publish(options.root, options.changes.realRoot, existing.id, responseMarkdown(existing));
13
+ });
14
+ //# sourceMappingURL=retry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/responses/retry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAA0C,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAEtG,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGjE,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,EAAE,CAAC,yBAAyB,CAAC,CAAC,QAAQ,CAAC,EAC1E,QAA0B,EAC1B,KAAiB,EACjB,QAAiD,EACjD,OAAwB;IAExB,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC;QACvC,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,cAAc,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,0DAA0D,EAAE,CAAC,CAAC,CAAC;IAC1I,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,KAAK,aAAa,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC;QACzF,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CACxB,IAAI,cAAc,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,iFAAiF,EAAE,CAAC,CACpI,CAAC;IACH,CAAC;IACD,KAAK,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,EAAE,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC;AACjG,CAAC,CAAC,CAAC"}