@mrtdown/core 2.0.0-alpha.5 → 2.0.0-alpha.6

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/dist/index.d.ts +0 -7
  2. package/dist/index.js +0 -7
  3. package/dist/index.js.map +1 -1
  4. package/dist/schema/Landmark.js.map +1 -1
  5. package/dist/schema/Line.js.map +1 -1
  6. package/dist/schema/Operator.js.map +1 -1
  7. package/dist/schema/Service.js.map +1 -1
  8. package/dist/schema/Station.js.map +1 -1
  9. package/dist/schema/Town.js.map +1 -1
  10. package/dist/schema/common.js.map +1 -1
  11. package/dist/schema/issue/bundle.js.map +1 -1
  12. package/dist/schema/issue/cause.js.map +1 -1
  13. package/dist/schema/issue/claim.js.map +1 -1
  14. package/dist/schema/issue/entity.js.map +1 -1
  15. package/dist/schema/issue/evidence.js.map +1 -1
  16. package/dist/schema/issue/facilityEffect.js.map +1 -1
  17. package/dist/schema/issue/id.js.map +1 -1
  18. package/dist/schema/issue/impactEvent.js.map +1 -1
  19. package/dist/schema/issue/issue.js.map +1 -1
  20. package/dist/schema/issue/issueType.js.map +1 -1
  21. package/dist/schema/issue/period.js.map +1 -1
  22. package/dist/schema/issue/serviceEffect.js.map +1 -1
  23. package/dist/schema/issue/serviceScope.js.map +1 -1
  24. package/package.json +19 -44
  25. package/README.md +0 -107
  26. package/dist/cli/commands/create.d.ts +0 -30
  27. package/dist/cli/commands/create.js +0 -189
  28. package/dist/cli/commands/create.js.map +0 -1
  29. package/dist/cli/commands/list.d.ts +0 -6
  30. package/dist/cli/commands/list.js +0 -106
  31. package/dist/cli/commands/list.js.map +0 -1
  32. package/dist/cli/commands/show.d.ts +0 -6
  33. package/dist/cli/commands/show.js +0 -156
  34. package/dist/cli/commands/show.js.map +0 -1
  35. package/dist/cli/commands/validate.d.ts +0 -6
  36. package/dist/cli/commands/validate.js +0 -19
  37. package/dist/cli/commands/validate.js.map +0 -1
  38. package/dist/cli/index.d.ts +0 -2
  39. package/dist/cli/index.js +0 -162
  40. package/dist/cli/index.js.map +0 -1
  41. package/dist/constants.d.ts +0 -10
  42. package/dist/constants.js +0 -11
  43. package/dist/constants.js.map +0 -1
  44. package/dist/helpers/calculateDurationWithinServiceHours.d.ts +0 -2
  45. package/dist/helpers/calculateDurationWithinServiceHours.js +0 -13
  46. package/dist/helpers/calculateDurationWithinServiceHours.js.map +0 -1
  47. package/dist/helpers/calculateDurationWithinServiceHours.test.d.ts +0 -1
  48. package/dist/helpers/calculateDurationWithinServiceHours.test.js +0 -83
  49. package/dist/helpers/calculateDurationWithinServiceHours.test.js.map +0 -1
  50. package/dist/helpers/computeImpactFromEvidenceClaims.d.ts +0 -21
  51. package/dist/helpers/computeImpactFromEvidenceClaims.js +0 -293
  52. package/dist/helpers/computeImpactFromEvidenceClaims.js.map +0 -1
  53. package/dist/helpers/computeImpactFromEvidenceClaims.test.d.ts +0 -1
  54. package/dist/helpers/computeImpactFromEvidenceClaims.test.js +0 -544
  55. package/dist/helpers/computeImpactFromEvidenceClaims.test.js.map +0 -1
  56. package/dist/helpers/computeStartOfDaysWithinInterval.d.ts +0 -2
  57. package/dist/helpers/computeStartOfDaysWithinInterval.js +0 -15
  58. package/dist/helpers/computeStartOfDaysWithinInterval.js.map +0 -1
  59. package/dist/helpers/computeStartOfDaysWithinInterval.test.d.ts +0 -1
  60. package/dist/helpers/computeStartOfDaysWithinInterval.test.js +0 -126
  61. package/dist/helpers/computeStartOfDaysWithinInterval.test.js.map +0 -1
  62. package/dist/helpers/estimateOpenAICost.d.ts +0 -40
  63. package/dist/helpers/estimateOpenAICost.js +0 -55
  64. package/dist/helpers/estimateOpenAICost.js.map +0 -1
  65. package/dist/helpers/keyForAffectedEntity.d.ts +0 -7
  66. package/dist/helpers/keyForAffectedEntity.js +0 -14
  67. package/dist/helpers/keyForAffectedEntity.js.map +0 -1
  68. package/dist/helpers/normalizeRecurringPeriod.d.ts +0 -7
  69. package/dist/helpers/normalizeRecurringPeriod.js +0 -118
  70. package/dist/helpers/normalizeRecurringPeriod.js.map +0 -1
  71. package/dist/helpers/normalizeRecurringPeriod.test.d.ts +0 -1
  72. package/dist/helpers/normalizeRecurringPeriod.test.js +0 -93
  73. package/dist/helpers/normalizeRecurringPeriod.test.js.map +0 -1
  74. package/dist/helpers/resolvePeriods.d.ts +0 -224
  75. package/dist/helpers/resolvePeriods.js +0 -207
  76. package/dist/helpers/resolvePeriods.js.map +0 -1
  77. package/dist/helpers/resolvePeriods.test.d.ts +0 -1
  78. package/dist/helpers/resolvePeriods.test.js +0 -239
  79. package/dist/helpers/resolvePeriods.test.js.map +0 -1
  80. package/dist/helpers/splitIntervalByServiceHours.d.ts +0 -2
  81. package/dist/helpers/splitIntervalByServiceHours.js +0 -30
  82. package/dist/helpers/splitIntervalByServiceHours.js.map +0 -1
  83. package/dist/helpers/splitIntervalByServiceHours.test.d.ts +0 -1
  84. package/dist/helpers/splitIntervalByServiceHours.test.js +0 -152
  85. package/dist/helpers/splitIntervalByServiceHours.test.js.map +0 -1
  86. package/dist/helpers/sumIntervalDuration.d.ts +0 -2
  87. package/dist/helpers/sumIntervalDuration.js +0 -9
  88. package/dist/helpers/sumIntervalDuration.js.map +0 -1
  89. package/dist/llm/client.d.ts +0 -2
  90. package/dist/llm/client.js +0 -5
  91. package/dist/llm/client.js.map +0 -1
  92. package/dist/llm/common/MemoryStore.d.ts +0 -21
  93. package/dist/llm/common/MemoryStore.js +0 -100
  94. package/dist/llm/common/MemoryStore.js.map +0 -1
  95. package/dist/llm/common/MemoryStore.test.d.ts +0 -1
  96. package/dist/llm/common/MemoryStore.test.js +0 -225
  97. package/dist/llm/common/MemoryStore.test.js.map +0 -1
  98. package/dist/llm/common/formatCurrentState.d.ts +0 -10
  99. package/dist/llm/common/formatCurrentState.js +0 -342
  100. package/dist/llm/common/formatCurrentState.js.map +0 -1
  101. package/dist/llm/common/tool.d.ts +0 -32
  102. package/dist/llm/common/tool.js +0 -6
  103. package/dist/llm/common/tool.js.map +0 -1
  104. package/dist/llm/functions/extractClaimsFromNewEvidence/eval.test.d.ts +0 -1
  105. package/dist/llm/functions/extractClaimsFromNewEvidence/eval.test.js +0 -433
  106. package/dist/llm/functions/extractClaimsFromNewEvidence/eval.test.js.map +0 -1
  107. package/dist/llm/functions/extractClaimsFromNewEvidence/index.d.ts +0 -18
  108. package/dist/llm/functions/extractClaimsFromNewEvidence/index.js +0 -153
  109. package/dist/llm/functions/extractClaimsFromNewEvidence/index.js.map +0 -1
  110. package/dist/llm/functions/extractClaimsFromNewEvidence/prompt.d.ts +0 -1
  111. package/dist/llm/functions/extractClaimsFromNewEvidence/prompt.js +0 -168
  112. package/dist/llm/functions/extractClaimsFromNewEvidence/prompt.js.map +0 -1
  113. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindLinesTool.d.ts +0 -19
  114. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindLinesTool.js +0 -65
  115. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindLinesTool.js.map +0 -1
  116. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindServicesTool.d.ts +0 -21
  117. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindServicesTool.js +0 -115
  118. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindServicesTool.js.map +0 -1
  119. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindStationsTool.d.ts +0 -24
  120. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindStationsTool.js +0 -110
  121. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindStationsTool.js.map +0 -1
  122. package/dist/llm/functions/generateIssueTitleAndSlug/index.d.ts +0 -14
  123. package/dist/llm/functions/generateIssueTitleAndSlug/index.js +0 -38
  124. package/dist/llm/functions/generateIssueTitleAndSlug/index.js.map +0 -1
  125. package/dist/llm/functions/generateIssueTitleAndSlug/prompt.d.ts +0 -1
  126. package/dist/llm/functions/generateIssueTitleAndSlug/prompt.js +0 -23
  127. package/dist/llm/functions/generateIssueTitleAndSlug/prompt.js.map +0 -1
  128. package/dist/llm/functions/translate/index.d.ts +0 -1
  129. package/dist/llm/functions/translate/index.js +0 -59
  130. package/dist/llm/functions/translate/index.js.map +0 -1
  131. package/dist/llm/functions/triageNewEvidence/eval.test.d.ts +0 -1
  132. package/dist/llm/functions/triageNewEvidence/eval.test.js +0 -139
  133. package/dist/llm/functions/triageNewEvidence/eval.test.js.map +0 -1
  134. package/dist/llm/functions/triageNewEvidence/index.d.ts +0 -37
  135. package/dist/llm/functions/triageNewEvidence/index.js +0 -121
  136. package/dist/llm/functions/triageNewEvidence/index.js.map +0 -1
  137. package/dist/llm/functions/triageNewEvidence/prompt.d.ts +0 -1
  138. package/dist/llm/functions/triageNewEvidence/prompt.js +0 -60
  139. package/dist/llm/functions/triageNewEvidence/prompt.js.map +0 -1
  140. package/dist/llm/functions/triageNewEvidence/tools/FindIssuesTool.d.ts +0 -19
  141. package/dist/llm/functions/triageNewEvidence/tools/FindIssuesTool.js +0 -65
  142. package/dist/llm/functions/triageNewEvidence/tools/FindIssuesTool.js.map +0 -1
  143. package/dist/llm/functions/triageNewEvidence/tools/GetIssueTool.d.ts +0 -19
  144. package/dist/llm/functions/triageNewEvidence/tools/GetIssueTool.js +0 -37
  145. package/dist/llm/functions/triageNewEvidence/tools/GetIssueTool.js.map +0 -1
  146. package/dist/repo/MRTDownRepository.d.ts +0 -23
  147. package/dist/repo/MRTDownRepository.js +0 -28
  148. package/dist/repo/MRTDownRepository.js.map +0 -1
  149. package/dist/repo/common/FileStore.d.ts +0 -12
  150. package/dist/repo/common/FileStore.js +0 -27
  151. package/dist/repo/common/FileStore.js.map +0 -1
  152. package/dist/repo/common/StandardRepository.d.ts +0 -32
  153. package/dist/repo/common/StandardRepository.js +0 -58
  154. package/dist/repo/common/StandardRepository.js.map +0 -1
  155. package/dist/repo/common/store.d.ts +0 -29
  156. package/dist/repo/common/store.js +0 -2
  157. package/dist/repo/common/store.js.map +0 -1
  158. package/dist/repo/issue/IssueRepository.d.ts +0 -36
  159. package/dist/repo/issue/IssueRepository.js +0 -177
  160. package/dist/repo/issue/IssueRepository.js.map +0 -1
  161. package/dist/repo/issue/helpers/deriveCurrentState.d.ts +0 -51
  162. package/dist/repo/issue/helpers/deriveCurrentState.js +0 -113
  163. package/dist/repo/issue/helpers/deriveCurrentState.js.map +0 -1
  164. package/dist/repo/issue/helpers/deriveCurrentState.test.d.ts +0 -1
  165. package/dist/repo/issue/helpers/deriveCurrentState.test.js +0 -477
  166. package/dist/repo/issue/helpers/deriveCurrentState.test.js.map +0 -1
  167. package/dist/repo/landmark/LandmarkRepository.d.ts +0 -7
  168. package/dist/repo/landmark/LandmarkRepository.js +0 -12
  169. package/dist/repo/landmark/LandmarkRepository.js.map +0 -1
  170. package/dist/repo/line/LineRepository.d.ts +0 -13
  171. package/dist/repo/line/LineRepository.js +0 -32
  172. package/dist/repo/line/LineRepository.js.map +0 -1
  173. package/dist/repo/operator/OperatorRepository.d.ts +0 -7
  174. package/dist/repo/operator/OperatorRepository.js +0 -12
  175. package/dist/repo/operator/OperatorRepository.js.map +0 -1
  176. package/dist/repo/service/ServiceRepository.d.ts +0 -19
  177. package/dist/repo/service/ServiceRepository.js +0 -39
  178. package/dist/repo/service/ServiceRepository.js.map +0 -1
  179. package/dist/repo/station/StationRepository.d.ts +0 -13
  180. package/dist/repo/station/StationRepository.js +0 -30
  181. package/dist/repo/station/StationRepository.js.map +0 -1
  182. package/dist/repo/town/TownRepository.d.ts +0 -7
  183. package/dist/repo/town/TownRepository.js +0 -12
  184. package/dist/repo/town/TownRepository.js.map +0 -1
  185. package/dist/scripts/ingestViaWebhook.d.ts +0 -1
  186. package/dist/scripts/ingestViaWebhook.js +0 -9
  187. package/dist/scripts/ingestViaWebhook.js.map +0 -1
  188. package/dist/util/assert.d.ts +0 -1
  189. package/dist/util/assert.js +0 -6
  190. package/dist/util/assert.js.map +0 -1
  191. package/dist/util/ingestContent/helpers/getSlugDateTimeFromClaims.d.ts +0 -7
  192. package/dist/util/ingestContent/helpers/getSlugDateTimeFromClaims.js +0 -24
  193. package/dist/util/ingestContent/helpers/getSlugDateTimeFromClaims.js.map +0 -1
  194. package/dist/util/ingestContent/index.d.ts +0 -12
  195. package/dist/util/ingestContent/index.js +0 -171
  196. package/dist/util/ingestContent/index.js.map +0 -1
  197. package/dist/util/ingestContent/types.d.ts +0 -32
  198. package/dist/util/ingestContent/types.js +0 -2
  199. package/dist/util/ingestContent/types.js.map +0 -1
  200. package/dist/validators/buildContext.d.ts +0 -7
  201. package/dist/validators/buildContext.js +0 -164
  202. package/dist/validators/buildContext.js.map +0 -1
  203. package/dist/validators/index.d.ts +0 -17
  204. package/dist/validators/index.js +0 -58
  205. package/dist/validators/index.js.map +0 -1
  206. package/dist/validators/issue.d.ts +0 -13
  207. package/dist/validators/issue.js +0 -220
  208. package/dist/validators/issue.js.map +0 -1
  209. package/dist/validators/landmark.d.ts +0 -7
  210. package/dist/validators/landmark.js +0 -43
  211. package/dist/validators/landmark.js.map +0 -1
  212. package/dist/validators/line.d.ts +0 -8
  213. package/dist/validators/line.js +0 -87
  214. package/dist/validators/line.js.map +0 -1
  215. package/dist/validators/operator.d.ts +0 -7
  216. package/dist/validators/operator.js +0 -43
  217. package/dist/validators/operator.js.map +0 -1
  218. package/dist/validators/service.d.ts +0 -8
  219. package/dist/validators/service.js +0 -87
  220. package/dist/validators/service.js.map +0 -1
  221. package/dist/validators/station.d.ts +0 -8
  222. package/dist/validators/station.js +0 -93
  223. package/dist/validators/station.js.map +0 -1
  224. package/dist/validators/town.d.ts +0 -7
  225. package/dist/validators/town.js +0 -43
  226. package/dist/validators/town.js.map +0 -1
  227. package/dist/validators/types.d.ts +0 -19
  228. package/dist/validators/types.js +0 -2
  229. package/dist/validators/types.js.map +0 -1
  230. package/dist/validators/utils.d.ts +0 -2
  231. package/dist/validators/utils.js +0 -9
  232. package/dist/validators/utils.js.map +0 -1
  233. package/dist/write/MRTDownWriter.d.ts +0 -27
  234. package/dist/write/MRTDownWriter.js +0 -27
  235. package/dist/write/MRTDownWriter.js.map +0 -1
  236. package/dist/write/common/FileWriteStore.d.ts +0 -13
  237. package/dist/write/common/FileWriteStore.js +0 -31
  238. package/dist/write/common/FileWriteStore.js.map +0 -1
  239. package/dist/write/common/StandardWriter.d.ts +0 -14
  240. package/dist/write/common/StandardWriter.js +0 -17
  241. package/dist/write/common/StandardWriter.js.map +0 -1
  242. package/dist/write/common/store.d.ts +0 -32
  243. package/dist/write/common/store.js +0 -2
  244. package/dist/write/common/store.js.map +0 -1
  245. package/dist/write/id/IdGenerator.d.ts +0 -18
  246. package/dist/write/id/IdGenerator.js +0 -23
  247. package/dist/write/id/IdGenerator.js.map +0 -1
  248. package/dist/write/issue/IssueWriter.d.ts +0 -12
  249. package/dist/write/issue/IssueWriter.js +0 -33
  250. package/dist/write/issue/IssueWriter.js.map +0 -1
@@ -1,19 +0,0 @@
1
- import { type Service } from '../../schema/Service.js';
2
- import { StandardRepository } from '../common/StandardRepository.js';
3
- import type { IStore } from '../common/store.js';
4
- export declare class ServiceRepository extends StandardRepository<Service> {
5
- constructor(store: IStore);
6
- protected parseItem(json: unknown): Service;
7
- /**
8
- * Search services by name.
9
- * @param names
10
- * @returns
11
- */
12
- searchByName(names: string[]): Service[];
13
- /**
14
- * Search services by line ID.
15
- * @param lineId
16
- * @returns
17
- */
18
- searchByLineId(lineId: string): Service[];
19
- }
@@ -1,39 +0,0 @@
1
- import Fuse from 'fuse.js';
2
- import { DIR_SERVICE } from '../../constants.js';
3
- import { ServiceSchema } from '../../schema/Service.js';
4
- import { StandardRepository } from '../common/StandardRepository.js';
5
- export class ServiceRepository extends StandardRepository {
6
- constructor(store) {
7
- super(store, DIR_SERVICE);
8
- }
9
- parseItem(json) {
10
- return ServiceSchema.parse(json);
11
- }
12
- /**
13
- * Search services by name.
14
- * @param names
15
- * @returns
16
- */
17
- searchByName(names) {
18
- this.loadAll();
19
- const fuse = new Fuse(Array.from(this.byId.values()), {
20
- keys: ['id', 'name.en-SG'],
21
- includeScore: true,
22
- threshold: 0.3,
23
- });
24
- const results = fuse.search({
25
- $or: names.flatMap((name) => [{ id: name }, { 'name.en-SG': name }]),
26
- });
27
- return results.map((r) => r.item);
28
- }
29
- /**
30
- * Search services by line ID.
31
- * @param lineId
32
- * @returns
33
- */
34
- searchByLineId(lineId) {
35
- this.loadAll();
36
- return Array.from(this.byId.values()).filter((s) => s.lineId === lineId);
37
- }
38
- }
39
- //# sourceMappingURL=ServiceRepository.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ServiceRepository.js","sourceRoot":"/","sources":["repo/service/ServiceRepository.ts"],"names":[],"mappings":"AAAA,OAAO,IAAyB,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAgB,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAGrE,MAAM,OAAO,iBAAkB,SAAQ,kBAA2B;IAChE,YAAY,KAAa;QACvB,KAAK,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IAC5B,CAAC;IAES,SAAS,CAAC,IAAa;QAC/B,OAAO,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IAED;;;;OAIG;IACH,YAAY,CAAC,KAAe;QAC1B,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE;YACpD,IAAI,EAAE,CAAC,IAAI,EAAE,YAAY,CAAC;YAC1B,YAAY,EAAE,IAAI;YAClB,SAAS,EAAE,GAAG;SACf,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC;YAC1B,GAAG,EAAE,KAAK,CAAC,OAAO,CAChB,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAiB,CACjE;SACF,CAAC,CAAC;QACH,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAED;;;;OAIG;IACH,cAAc,CAAC,MAAc;QAC3B,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;IAC3E,CAAC;CACF","sourcesContent":["import Fuse, { type Expression } from 'fuse.js';\nimport { DIR_SERVICE } from '../../constants.js';\nimport { type Service, ServiceSchema } from '../../schema/Service.js';\nimport { StandardRepository } from '../common/StandardRepository.js';\nimport type { IStore } from '../common/store.js';\n\nexport class ServiceRepository extends StandardRepository<Service> {\n constructor(store: IStore) {\n super(store, DIR_SERVICE);\n }\n\n protected parseItem(json: unknown): Service {\n return ServiceSchema.parse(json);\n }\n\n /**\n * Search services by name.\n * @param names\n * @returns\n */\n searchByName(names: string[]): Service[] {\n this.loadAll();\n const fuse = new Fuse(Array.from(this.byId.values()), {\n keys: ['id', 'name.en-SG'],\n includeScore: true,\n threshold: 0.3,\n });\n const results = fuse.search({\n $or: names.flatMap(\n (name) => [{ id: name }, { 'name.en-SG': name }] as Expression[],\n ),\n });\n return results.map((r) => r.item);\n }\n\n /**\n * Search services by line ID.\n * @param lineId\n * @returns\n */\n searchByLineId(lineId: string): Service[] {\n this.loadAll();\n return Array.from(this.byId.values()).filter((s) => s.lineId === lineId);\n }\n}\n"]}
@@ -1,13 +0,0 @@
1
- import { type Station } from '../../schema/Station.js';
2
- import { StandardRepository } from '../common/StandardRepository.js';
3
- import type { IStore } from '../common/store.js';
4
- export declare class StationRepository extends StandardRepository<Station> {
5
- constructor(store: IStore);
6
- protected parseItem(json: unknown): Station;
7
- /**
8
- * Search stations by name.
9
- * @param names
10
- * @returns
11
- */
12
- searchByName(names: string[]): Station[];
13
- }
@@ -1,30 +0,0 @@
1
- import Fuse from 'fuse.js';
2
- import { DIR_STATION } from '../../constants.js';
3
- import { StationSchema } from '../../schema/Station.js';
4
- import { StandardRepository } from '../common/StandardRepository.js';
5
- export class StationRepository extends StandardRepository {
6
- constructor(store) {
7
- super(store, DIR_STATION);
8
- }
9
- parseItem(json) {
10
- return StationSchema.parse(json);
11
- }
12
- /**
13
- * Search stations by name.
14
- * @param names
15
- * @returns
16
- */
17
- searchByName(names) {
18
- this.loadAll();
19
- const fuse = new Fuse(Array.from(this.byId.values()), {
20
- keys: ['id', 'name.en-SG'],
21
- includeScore: true,
22
- threshold: 0.2,
23
- });
24
- const results = fuse.search({
25
- $or: names.flatMap((name) => [{ id: name }, { 'name.en-SG': name }]),
26
- });
27
- return results.map((r) => r.item);
28
- }
29
- }
30
- //# sourceMappingURL=StationRepository.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"StationRepository.js","sourceRoot":"/","sources":["repo/station/StationRepository.ts"],"names":[],"mappings":"AAAA,OAAO,IAAyB,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAgB,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAGrE,MAAM,OAAO,iBAAkB,SAAQ,kBAA2B;IAChE,YAAY,KAAa;QACvB,KAAK,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IAC5B,CAAC;IAES,SAAS,CAAC,IAAa;QAC/B,OAAO,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IAED;;;;OAIG;IACH,YAAY,CAAC,KAAe;QAC1B,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE;YACpD,IAAI,EAAE,CAAC,IAAI,EAAE,YAAY,CAAC;YAC1B,YAAY,EAAE,IAAI;YAClB,SAAS,EAAE,GAAG;SACf,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC;YAC1B,GAAG,EAAE,KAAK,CAAC,OAAO,CAChB,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAiB,CACjE;SACF,CAAC,CAAC;QACH,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;CACF","sourcesContent":["import Fuse, { type Expression } from 'fuse.js';\nimport { DIR_STATION } from '../../constants.js';\nimport { type Station, StationSchema } from '../../schema/Station.js';\nimport { StandardRepository } from '../common/StandardRepository.js';\nimport type { IStore } from '../common/store.js';\n\nexport class StationRepository extends StandardRepository<Station> {\n constructor(store: IStore) {\n super(store, DIR_STATION);\n }\n\n protected parseItem(json: unknown): Station {\n return StationSchema.parse(json);\n }\n\n /**\n * Search stations by name.\n * @param names\n * @returns\n */\n searchByName(names: string[]): Station[] {\n this.loadAll();\n const fuse = new Fuse(Array.from(this.byId.values()), {\n keys: ['id', 'name.en-SG'],\n includeScore: true,\n threshold: 0.2,\n });\n const results = fuse.search({\n $or: names.flatMap(\n (name) => [{ id: name }, { 'name.en-SG': name }] as Expression[],\n ),\n });\n return results.map((r) => r.item);\n }\n}\n"]}
@@ -1,7 +0,0 @@
1
- import { type Town } from '../../schema/Town.js';
2
- import { StandardRepository } from '../common/StandardRepository.js';
3
- import type { IStore } from '../common/store.js';
4
- export declare class TownRepository extends StandardRepository<Town> {
5
- constructor(store: IStore);
6
- protected parseItem(json: unknown): Town;
7
- }
@@ -1,12 +0,0 @@
1
- import { DIR_TOWN } from '../../constants.js';
2
- import { TownSchema } from '../../schema/Town.js';
3
- import { StandardRepository } from '../common/StandardRepository.js';
4
- export class TownRepository extends StandardRepository {
5
- constructor(store) {
6
- super(store, DIR_TOWN);
7
- }
8
- parseItem(json) {
9
- return TownSchema.parse(json);
10
- }
11
- }
12
- //# sourceMappingURL=TownRepository.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"TownRepository.js","sourceRoot":"/","sources":["repo/town/TownRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAa,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAGrE,MAAM,OAAO,cAAe,SAAQ,kBAAwB;IAC1D,YAAY,KAAa;QACvB,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACzB,CAAC;IAES,SAAS,CAAC,IAAa;QAC/B,OAAO,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;CACF","sourcesContent":["import { DIR_TOWN } from '../../constants.js';\nimport { type Town, TownSchema } from '../../schema/Town.js';\nimport { StandardRepository } from '../common/StandardRepository.js';\nimport type { IStore } from '../common/store.js';\n\nexport class TownRepository extends StandardRepository<Town> {\n constructor(store: IStore) {\n super(store, DIR_TOWN);\n }\n\n protected parseItem(json: unknown): Town {\n return TownSchema.parse(json);\n }\n}\n"]}
@@ -1 +0,0 @@
1
- export {};
@@ -1,9 +0,0 @@
1
- import { assert } from '../util/assert.js';
2
- import { ingestContent } from '../util/ingestContent/index.js';
3
- const { MESSAGE } = process.env;
4
- assert(MESSAGE != null, 'Expected MESSAGE env var');
5
- const message = JSON.parse(MESSAGE);
6
- for (const content of message.content) {
7
- await ingestContent(content);
8
- }
9
- //# sourceMappingURL=ingestViaWebhook.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ingestViaWebhook.js","sourceRoot":"/","sources":["scripts/ingestViaWebhook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAG/D,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;AAChC,MAAM,CAAC,OAAO,IAAI,IAAI,EAAE,0BAA0B,CAAC,CAAC;AAEpD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAEjC,CAAC;AACF,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IACtC,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC;AAC/B,CAAC","sourcesContent":["import { assert } from '../util/assert.js';\nimport { ingestContent } from '../util/ingestContent/index.js';\nimport type { IngestContent } from '../util/ingestContent/types.js';\n\nconst { MESSAGE } = process.env;\nassert(MESSAGE != null, 'Expected MESSAGE env var');\n\nconst message = JSON.parse(MESSAGE) as {\n content: IngestContent[];\n};\nfor (const content of message.content) {\n await ingestContent(content);\n}\n"]}
@@ -1 +0,0 @@
1
- export declare function assert(condition: boolean, message?: string): asserts condition;
@@ -1,6 +0,0 @@
1
- export function assert(condition, message = 'Assertion failed') {
2
- if (!condition) {
3
- throw new Error(message);
4
- }
5
- }
6
- //# sourceMappingURL=assert.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"assert.js","sourceRoot":"/","sources":["util/assert.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,MAAM,CACpB,SAAkB,EAClB,OAAO,GAAG,kBAAkB;IAE5B,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;AACH,CAAC","sourcesContent":["export function assert(\n condition: boolean,\n message = 'Assertion failed',\n): asserts condition {\n if (!condition) {\n throw new Error(message);\n }\n}\n"]}
@@ -1,7 +0,0 @@
1
- import type { Claim } from '../../../schema/issue/claim.js';
2
- /**
3
- * Get the slug date time from the claims.
4
- * @param claims - The claims.
5
- * @returns The slug date time or null if no time hints are found.
6
- */
7
- export declare function getSlugDateTimeFromClaims(claims: Claim[]): string | null;
@@ -1,24 +0,0 @@
1
- import { assert } from '../../assert.js';
2
- /**
3
- * Get the slug date time from the claims.
4
- * @param claims - The claims.
5
- * @returns The slug date time or null if no time hints are found.
6
- */
7
- export function getSlugDateTimeFromClaims(claims) {
8
- const timeHints = claims
9
- .filter((claim) => claim.timeHints != null)
10
- .map((claim) => claim.timeHints);
11
- if (timeHints.length > 0) {
12
- assert(timeHints[0] != null, 'Expected time hints');
13
- switch (timeHints[0].kind) {
14
- case 'fixed': {
15
- return timeHints[0].startAt;
16
- }
17
- case 'recurring': {
18
- return timeHints[0].startAt;
19
- }
20
- }
21
- }
22
- return null;
23
- }
24
- //# sourceMappingURL=getSlugDateTimeFromClaims.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"getSlugDateTimeFromClaims.js","sourceRoot":"/","sources":["util/ingestContent/helpers/getSlugDateTimeFromClaims.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEzC;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CAAC,MAAe;IACvD,MAAM,SAAS,GAAG,MAAM;SACrB,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,IAAI,IAAI,CAAC;SAC1C,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAEnC,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,qBAAqB,CAAC,CAAC;QACpD,QAAQ,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAC1B,KAAK,OAAO,CAAC,CAAC,CAAC;gBACb,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YAC9B,CAAC;YACD,KAAK,WAAW,CAAC,CAAC,CAAC;gBACjB,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YAC9B,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["import type { Claim } from '../../../schema/issue/claim.js';\nimport { assert } from '../../assert.js';\n\n/**\n * Get the slug date time from the claims.\n * @param claims - The claims.\n * @returns The slug date time or null if no time hints are found.\n */\nexport function getSlugDateTimeFromClaims(claims: Claim[]): string | null {\n const timeHints = claims\n .filter((claim) => claim.timeHints != null)\n .map((claim) => claim.timeHints);\n\n if (timeHints.length > 0) {\n assert(timeHints[0] != null, 'Expected time hints');\n switch (timeHints[0].kind) {\n case 'fixed': {\n return timeHints[0].startAt;\n }\n case 'recurring': {\n return timeHints[0].startAt;\n }\n }\n }\n\n return null;\n}\n"]}
@@ -1,12 +0,0 @@
1
- import type { IngestContent } from './types.js';
2
- /**
3
- * Ingests content from social media, news, or other sources into the MRTDown issue system.
4
- *
5
- * Triages the content to determine if it belongs to an existing issue or a new one, extracts
6
- * claims, computes impact (affected lines, stations, periods), and persists evidence and impact
7
- * events. Irrelevant content is ignored.
8
- *
9
- * @param content - The content to ingest (Reddit post, news article, or Twitter/Mastodon post).
10
- * @returns `null` when content is irrelevant or after successful ingestion.
11
- */
12
- export declare function ingestContent(content: IngestContent): Promise<null>;
@@ -1,171 +0,0 @@
1
- import { resolve } from 'node:path';
2
- import { DateTime } from 'luxon';
3
- import { ulid } from 'ulid';
4
- import { computeImpactFromEvidenceClaims } from '../../helpers/computeImpactFromEvidenceClaims.js';
5
- import { extractClaimsFromNewEvidence } from '../../llm/functions/extractClaimsFromNewEvidence/index.js';
6
- import { generateIssueTitleAndSlug } from '../../llm/functions/generateIssueTitleAndSlug/index.js';
7
- import { translate } from '../../llm/functions/translate/index.js';
8
- import { triageNewEvidence } from '../../llm/functions/triageNewEvidence/index.js';
9
- import { FileStore } from '../../repo/common/FileStore.js';
10
- import { MRTDownRepository } from '../../repo/MRTDownRepository.js';
11
- import { FileWriteStore } from '../../write/common/FileWriteStore.js';
12
- import { MRTDownWriter } from '../../write/MRTDownWriter.js';
13
- import { assert } from '../assert.js';
14
- import { getSlugDateTimeFromClaims } from './helpers/getSlugDateTimeFromClaims.js';
15
- const DATA_DIR = resolve(import.meta.dirname, '../../../data');
16
- const store = new FileStore(DATA_DIR);
17
- const writeStore = new FileWriteStore(DATA_DIR);
18
- const repo = new MRTDownRepository({ store });
19
- const writer = new MRTDownWriter({ store: writeStore });
20
- /**
21
- * Ingests content from social media, news, or other sources into the MRTDown issue system.
22
- *
23
- * Triages the content to determine if it belongs to an existing issue or a new one, extracts
24
- * claims, computes impact (affected lines, stations, periods), and persists evidence and impact
25
- * events. Irrelevant content is ignored.
26
- *
27
- * @param content - The content to ingest (Reddit post, news article, or Twitter/Mastodon post).
28
- * @returns `null` when content is irrelevant or after successful ingestion.
29
- */
30
- export async function ingestContent(content) {
31
- // --- Normalise input ---
32
- // HACK: Force `createdAt` to be Asia/Singapore timezone
33
- const createdAt = DateTime.fromISO(content.createdAt)
34
- .setZone('Asia/Singapore')
35
- .toISO();
36
- assert(createdAt != null, 'Expected valid createdAt');
37
- content.createdAt = createdAt;
38
- console.log('[ingestContent]', content);
39
- // --- Triage: existing issue, new issue, or irrelevant ---
40
- const triageResult = await triageNewEvidence({
41
- newEvidence: {
42
- ts: content.createdAt,
43
- text: getText(content),
44
- },
45
- repo,
46
- });
47
- console.log('[ingestContent.triageNewEvidence]', triageResult);
48
- if (triageResult.result.kind === 'irrelevant-content') {
49
- console.log('[ingestContent] Nothing to do.');
50
- return null;
51
- }
52
- // --- Extract structured claims (lines, stations, periods, effects) ---
53
- const { claims } = await extractClaimsFromNewEvidence({
54
- newEvidence: {
55
- ts: content.createdAt,
56
- text: getText(content),
57
- },
58
- repo,
59
- });
60
- console.log('[ingestContent.extractClaimsFromNewEvidence]', claims);
61
- // --- Resolve issue bundle: fetch existing or create new ---
62
- let issueBundle;
63
- switch (triageResult.result.kind) {
64
- case 'part-of-existing-issue': {
65
- // Load full bundle (issue + evidence + impact) for impact computation
66
- const { issueId } = triageResult.result;
67
- const existingBundle = repo.issues.get(issueId);
68
- assert(existingBundle != null, `Expected issue for id=${issueId}`);
69
- issueBundle = existingBundle;
70
- break;
71
- }
72
- case 'part-of-new-issue': {
73
- // Create issue: derive date from claims, generate title/slug, translate, persist
74
- const slugDateTime = DateTime.fromISO(getSlugDateTimeFromClaims(claims) ?? content.createdAt);
75
- assert(slugDateTime.isValid, `Invalid date: ${content.createdAt}`);
76
- const { title, slug } = await generateIssueTitleAndSlug({
77
- text: getText(content),
78
- });
79
- console.log('[ingestContent.generateSlug]', slug);
80
- const translatedTitles = await translate(title);
81
- const issueId = `${slugDateTime.toFormat('yyyy-MM-dd')}-${slug}`;
82
- const issue = {
83
- id: issueId,
84
- type: triageResult.result.issueType,
85
- title: translatedTitles,
86
- titleMeta: {
87
- source: '@openai/gpt-5-nano',
88
- },
89
- };
90
- writer.issues.create(issue);
91
- issueBundle = {
92
- issue,
93
- evidence: [],
94
- impactEvents: [],
95
- path: DATA_DIR,
96
- };
97
- break;
98
- }
99
- }
100
- // --- Build evidence record ---
101
- const contentDateTime = DateTime.fromISO(content.createdAt);
102
- assert(contentDateTime.isValid, `Invalid date: ${content.createdAt}`);
103
- const evidence = {
104
- id: `ev_${ulid(contentDateTime.toMillis())}`,
105
- ts: contentDateTime.toISO({ includeOffset: true }),
106
- type: getEvidenceType(content),
107
- text: getText(content),
108
- sourceUrl: content.url,
109
- render: {
110
- text: await translate(getText(content)),
111
- source: '@openai/gpt-5-nano',
112
- },
113
- };
114
- // --- Compute impact events from claims (effects, scopes, periods) ---
115
- const { newImpactEvents } = computeImpactFromEvidenceClaims({
116
- issueBundle: {
117
- ...issueBundle,
118
- evidence: [...issueBundle.evidence, evidence],
119
- },
120
- evidenceId: evidence.id,
121
- evidenceTs: evidence.ts,
122
- claims,
123
- });
124
- // --- Persist to disk ---
125
- writer.issues.appendEvidence(issueBundle.issue.id, evidence);
126
- for (const impact of newImpactEvents) {
127
- writer.issues.appendImpact(issueBundle.issue.id, impact);
128
- }
129
- return null;
130
- }
131
- /**
132
- * Extracts the primary text content from an IngestContent item based on its source type.
133
- *
134
- * @param content - The content to extract text from.
135
- * @returns The text body (selftext for Reddit, summary for news, text for social).
136
- */
137
- function getText(content) {
138
- switch (content.source) {
139
- case 'reddit': {
140
- return content.selftext;
141
- }
142
- case 'news-website': {
143
- return content.summary;
144
- }
145
- case 'twitter':
146
- case 'mastodon': {
147
- return content.text;
148
- }
149
- }
150
- }
151
- /**
152
- * Maps IngestContent source type to the corresponding Evidence type for provenance tracking.
153
- *
154
- * @param content - The content to classify.
155
- * @returns The evidence type: official-statement (Reddit), media.report (news), or public.report (social).
156
- */
157
- function getEvidenceType(content) {
158
- switch (content.source) {
159
- case 'reddit': {
160
- return 'official-statement';
161
- }
162
- case 'news-website': {
163
- return 'media.report';
164
- }
165
- case 'twitter':
166
- case 'mastodon': {
167
- return 'public.report';
168
- }
169
- }
170
- }
171
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"/","sources":["util/ingestContent/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { resolve } from 'node:path';\nimport { DateTime } from 'luxon';\nimport { ulid } from 'ulid';\nimport { computeImpactFromEvidenceClaims } from '../../helpers/computeImpactFromEvidenceClaims.js';\nimport { extractClaimsFromNewEvidence } from '../../llm/functions/extractClaimsFromNewEvidence/index.js';\nimport { generateIssueTitleAndSlug } from '../../llm/functions/generateIssueTitleAndSlug/index.js';\nimport { translate } from '../../llm/functions/translate/index.js';\nimport { triageNewEvidence } from '../../llm/functions/triageNewEvidence/index.js';\nimport { FileStore } from '../../repo/common/FileStore.js';\nimport { MRTDownRepository } from '../../repo/MRTDownRepository.js';\nimport type { IssueBundle } from '../../schema/issue/bundle.js';\nimport type { Evidence } from '../../schema/issue/evidence.js';\nimport type { Issue } from '../../schema/issue/issue.js';\nimport { FileWriteStore } from '../../write/common/FileWriteStore.js';\nimport { MRTDownWriter } from '../../write/MRTDownWriter.js';\nimport { assert } from '../assert.js';\nimport { getSlugDateTimeFromClaims } from './helpers/getSlugDateTimeFromClaims.js';\nimport type { IngestContent } from './types.js';\n\nconst DATA_DIR = resolve(import.meta.dirname, '../../../data');\n\nconst store = new FileStore(DATA_DIR);\nconst writeStore = new FileWriteStore(DATA_DIR);\nconst repo = new MRTDownRepository({ store });\nconst writer = new MRTDownWriter({ store: writeStore });\n\n/**\n * Ingests content from social media, news, or other sources into the MRTDown issue system.\n *\n * Triages the content to determine if it belongs to an existing issue or a new one, extracts\n * claims, computes impact (affected lines, stations, periods), and persists evidence and impact\n * events. Irrelevant content is ignored.\n *\n * @param content - The content to ingest (Reddit post, news article, or Twitter/Mastodon post).\n * @returns `null` when content is irrelevant or after successful ingestion.\n */\nexport async function ingestContent(content: IngestContent) {\n // --- Normalise input ---\n // HACK: Force `createdAt` to be Asia/Singapore timezone\n const createdAt = DateTime.fromISO(content.createdAt)\n .setZone('Asia/Singapore')\n .toISO();\n assert(createdAt != null, 'Expected valid createdAt');\n\n content.createdAt = createdAt;\n console.log('[ingestContent]', content);\n\n // --- Triage: existing issue, new issue, or irrelevant ---\n const triageResult = await triageNewEvidence({\n newEvidence: {\n ts: content.createdAt,\n text: getText(content),\n },\n repo,\n });\n console.log('[ingestContent.triageNewEvidence]', triageResult);\n\n if (triageResult.result.kind === 'irrelevant-content') {\n console.log('[ingestContent] Nothing to do.');\n return null;\n }\n\n // --- Extract structured claims (lines, stations, periods, effects) ---\n const { claims } = await extractClaimsFromNewEvidence({\n newEvidence: {\n ts: content.createdAt,\n text: getText(content),\n },\n repo,\n });\n console.log('[ingestContent.extractClaimsFromNewEvidence]', claims);\n\n // --- Resolve issue bundle: fetch existing or create new ---\n let issueBundle: IssueBundle;\n\n switch (triageResult.result.kind) {\n case 'part-of-existing-issue': {\n // Load full bundle (issue + evidence + impact) for impact computation\n const { issueId } = triageResult.result;\n const existingBundle = repo.issues.get(issueId);\n assert(existingBundle != null, `Expected issue for id=${issueId}`);\n issueBundle = existingBundle;\n break;\n }\n case 'part-of-new-issue': {\n // Create issue: derive date from claims, generate title/slug, translate, persist\n const slugDateTime = DateTime.fromISO(\n getSlugDateTimeFromClaims(claims) ?? content.createdAt,\n );\n assert(slugDateTime.isValid, `Invalid date: ${content.createdAt}`);\n\n const { title, slug } = await generateIssueTitleAndSlug({\n text: getText(content),\n });\n console.log('[ingestContent.generateSlug]', slug);\n\n const translatedTitles = await translate(title);\n\n const issueId = `${slugDateTime.toFormat('yyyy-MM-dd')}-${slug}`;\n\n const issue: Issue = {\n id: issueId,\n type: triageResult.result.issueType,\n title: translatedTitles,\n titleMeta: {\n source: '@openai/gpt-5-nano',\n },\n };\n writer.issues.create(issue);\n\n issueBundle = {\n issue,\n evidence: [],\n impactEvents: [],\n path: DATA_DIR,\n };\n break;\n }\n }\n\n // --- Build evidence record ---\n const contentDateTime = DateTime.fromISO(content.createdAt);\n assert(contentDateTime.isValid, `Invalid date: ${content.createdAt}`);\n\n const evidence: Evidence = {\n id: `ev_${ulid(contentDateTime.toMillis())}`,\n ts: contentDateTime.toISO({ includeOffset: true }),\n type: getEvidenceType(content),\n text: getText(content),\n sourceUrl: content.url,\n render: {\n text: await translate(getText(content)),\n source: '@openai/gpt-5-nano',\n },\n };\n\n // --- Compute impact events from claims (effects, scopes, periods) ---\n const { newImpactEvents } = computeImpactFromEvidenceClaims({\n issueBundle: {\n ...issueBundle,\n evidence: [...issueBundle.evidence, evidence],\n },\n evidenceId: evidence.id,\n evidenceTs: evidence.ts,\n claims,\n });\n\n // --- Persist to disk ---\n writer.issues.appendEvidence(issueBundle.issue.id, evidence);\n for (const impact of newImpactEvents) {\n writer.issues.appendImpact(issueBundle.issue.id, impact);\n }\n\n return null;\n}\n\n/**\n * Extracts the primary text content from an IngestContent item based on its source type.\n *\n * @param content - The content to extract text from.\n * @returns The text body (selftext for Reddit, summary for news, text for social).\n */\nfunction getText(content: IngestContent) {\n switch (content.source) {\n case 'reddit': {\n return content.selftext;\n }\n case 'news-website': {\n return content.summary;\n }\n case 'twitter':\n case 'mastodon': {\n return content.text;\n }\n }\n}\n\n/**\n * Maps IngestContent source type to the corresponding Evidence type for provenance tracking.\n *\n * @param content - The content to classify.\n * @returns The evidence type: official-statement (Reddit), media.report (news), or public.report (social).\n */\nfunction getEvidenceType(content: IngestContent) {\n switch (content.source) {\n case 'reddit': {\n return 'official-statement';\n }\n case 'news-website': {\n return 'media.report';\n }\n case 'twitter':\n case 'mastodon': {\n return 'public.report';\n }\n }\n}\n"]}
@@ -1,32 +0,0 @@
1
- import type { z } from 'zod';
2
- export type IngestContentTwitter = {
3
- source: 'twitter' | 'mastodon';
4
- accountName: string;
5
- text: string;
6
- url: string;
7
- createdAt: string;
8
- };
9
- export type IngestContentReddit = {
10
- source: 'reddit';
11
- subreddit: string;
12
- title: string;
13
- selftext: string;
14
- url: string;
15
- createdAt: string;
16
- thumbnailUrl: string | null;
17
- };
18
- export type IngestContentNewsArticle = {
19
- source: 'news-website';
20
- title: string;
21
- summary: string;
22
- url: string;
23
- createdAt: string;
24
- };
25
- export type IngestContent = IngestContentTwitter | IngestContentReddit | IngestContentNewsArticle;
26
- export type Tool<TParams = any> = {
27
- name: string;
28
- description: string;
29
- paramSchema: z.ZodType<TParams>;
30
- runner: (param: TParams) => Promise<string>;
31
- };
32
- export type ToolRegistry = Record<string, Tool>;
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=types.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.js","sourceRoot":"/","sources":["util/ingestContent/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { z } from 'zod';\n\nexport type IngestContentTwitter = {\n source: 'twitter' | 'mastodon';\n accountName: string;\n text: string;\n url: string;\n createdAt: string;\n};\n\nexport type IngestContentReddit = {\n source: 'reddit';\n subreddit: string;\n title: string;\n selftext: string;\n url: string;\n createdAt: string;\n thumbnailUrl: string | null;\n};\n\nexport type IngestContentNewsArticle = {\n source: 'news-website';\n title: string;\n summary: string;\n url: string;\n createdAt: string;\n};\n\nexport type IngestContent =\n | IngestContentTwitter\n | IngestContentReddit\n | IngestContentNewsArticle;\n\nexport type Tool<TParams = any> = {\n name: string;\n description: string;\n paramSchema: z.ZodType<TParams>;\n runner: (param: TParams) => Promise<string>;\n};\n\nexport type ToolRegistry = Record<string, Tool>;\n"]}
@@ -1,7 +0,0 @@
1
- import type { IStore } from '../repo/common/store.js';
2
- import type { ValidationContext } from './types.js';
3
- /**
4
- * Loads all entity IDs from the store into a ValidationContext.
5
- * Use this to build context once, then pass it to validators for relationship checks.
6
- */
7
- export declare function buildContext(store: IStore): ValidationContext;
@@ -1,164 +0,0 @@
1
- import { join } from 'node:path';
2
- import { NdJson } from 'json-nd';
3
- import z from 'zod';
4
- import { LandmarkSchema } from '../schema/Landmark.js';
5
- import { LineSchema } from '../schema/Line.js';
6
- import { OperatorSchema } from '../schema/Operator.js';
7
- import { ServiceSchema } from '../schema/Service.js';
8
- import { StationSchema } from '../schema/Station.js';
9
- import { TownSchema } from '../schema/Town.js';
10
- import { DIR_ISSUE, DIR_LANDMARK, DIR_LINE, DIR_OPERATOR, DIR_SERVICE, DIR_STATION, DIR_TOWN, } from '../constants.js';
11
- import { loadJson } from './utils.js';
12
- /**
13
- * Loads all entity IDs from the store into a ValidationContext.
14
- * Use this to build context once, then pass it to validators for relationship checks.
15
- */
16
- export function buildContext(store) {
17
- const ctx = {
18
- townIds: new Set(),
19
- landmarkIds: new Set(),
20
- operatorIds: new Set(),
21
- lineIds: new Set(),
22
- serviceIds: new Set(),
23
- stationIds: new Set(),
24
- evidenceIdsByIssue: new Map(),
25
- };
26
- try {
27
- for (const file of store.listDir(DIR_TOWN)) {
28
- if (!file.endsWith('.json'))
29
- continue;
30
- const path = join(DIR_TOWN, file);
31
- const raw = loadJson(store, path);
32
- const parsed = TownSchema.safeParse(raw);
33
- if (parsed.success)
34
- ctx.townIds.add(parsed.data.id);
35
- else
36
- console.warn(`[buildContext] Skipping invalid town: ${path}`, parsed.error?.message ?? parsed.error);
37
- }
38
- }
39
- catch (err) {
40
- console.warn('[buildContext] Failed to load towns:', err instanceof Error ? err.message : err);
41
- }
42
- try {
43
- for (const file of store.listDir(DIR_LANDMARK)) {
44
- if (!file.endsWith('.json'))
45
- continue;
46
- const path = join(DIR_LANDMARK, file);
47
- const raw = loadJson(store, path);
48
- const parsed = LandmarkSchema.safeParse(raw);
49
- if (parsed.success)
50
- ctx.landmarkIds.add(parsed.data.id);
51
- else
52
- console.warn(`[buildContext] Skipping invalid landmark: ${path}`, parsed.error?.message ?? parsed.error);
53
- }
54
- }
55
- catch (err) {
56
- console.warn('[buildContext] Failed to load landmarks:', err instanceof Error ? err.message : err);
57
- }
58
- try {
59
- for (const file of store.listDir(DIR_OPERATOR)) {
60
- if (!file.endsWith('.json'))
61
- continue;
62
- const path = join(DIR_OPERATOR, file);
63
- const raw = loadJson(store, path);
64
- const parsed = OperatorSchema.safeParse(raw);
65
- if (parsed.success)
66
- ctx.operatorIds.add(parsed.data.id);
67
- else
68
- console.warn(`[buildContext] Skipping invalid operator: ${path}`, parsed.error?.message ?? parsed.error);
69
- }
70
- }
71
- catch (err) {
72
- console.warn('[buildContext] Failed to load operators:', err instanceof Error ? err.message : err);
73
- }
74
- try {
75
- for (const file of store.listDir(DIR_LINE)) {
76
- if (!file.endsWith('.json'))
77
- continue;
78
- const path = join(DIR_LINE, file);
79
- const raw = loadJson(store, path);
80
- const parsed = LineSchema.safeParse(raw);
81
- if (parsed.success)
82
- ctx.lineIds.add(parsed.data.id);
83
- else
84
- console.warn(`[buildContext] Skipping invalid line: ${path}`, parsed.error?.message ?? parsed.error);
85
- }
86
- }
87
- catch (err) {
88
- console.warn('[buildContext] Failed to load lines:', err instanceof Error ? err.message : err);
89
- }
90
- try {
91
- for (const file of store.listDir(DIR_STATION)) {
92
- if (!file.endsWith('.json'))
93
- continue;
94
- const path = join(DIR_STATION, file);
95
- const raw = loadJson(store, path);
96
- const parsed = StationSchema.safeParse(raw);
97
- if (parsed.success)
98
- ctx.stationIds.add(parsed.data.id);
99
- else
100
- console.warn(`[buildContext] Skipping invalid station: ${path}`, parsed.error?.message ?? parsed.error);
101
- }
102
- }
103
- catch (err) {
104
- console.warn('[buildContext] Failed to load stations:', err instanceof Error ? err.message : err);
105
- }
106
- try {
107
- for (const file of store.listDir(DIR_SERVICE)) {
108
- if (!file.endsWith('.json'))
109
- continue;
110
- const path = join(DIR_SERVICE, file);
111
- const raw = loadJson(store, path);
112
- const parsed = ServiceSchema.safeParse(raw);
113
- if (parsed.success)
114
- ctx.serviceIds.add(parsed.data.id);
115
- else
116
- console.warn(`[buildContext] Skipping invalid service: ${path}`, parsed.error?.message ?? parsed.error);
117
- }
118
- }
119
- catch (err) {
120
- console.warn('[buildContext] Failed to load services:', err instanceof Error ? err.message : err);
121
- }
122
- try {
123
- const years = store.listDir(DIR_ISSUE);
124
- for (const year of years) {
125
- if (!/^\d{4}$/.test(year))
126
- continue;
127
- const monthsPath = join(DIR_ISSUE, year);
128
- const months = store.listDir(monthsPath);
129
- for (const month of months) {
130
- if (!/^\d{2}$/.test(month))
131
- continue;
132
- const issuesPath = join(monthsPath, month);
133
- const issues = store.listDir(issuesPath);
134
- for (const issueId of issues) {
135
- const relBase = join(DIR_ISSUE, year, month, issueId);
136
- const evidencePath = join(relBase, 'evidence.ndjson');
137
- const evidenceIds = new Set();
138
- try {
139
- const content = store.readText(evidencePath).trim();
140
- if (content) {
141
- const parsed = NdJson.parse(content);
142
- for (const row of parsed) {
143
- const idParsed = z.object({ id: z.string() }).safeParse(row);
144
- if (idParsed.success)
145
- evidenceIds.add(idParsed.data.id);
146
- else
147
- console.warn(`[buildContext] Skipping invalid evidence row in ${evidencePath}:`, idParsed.error?.message ?? idParsed.error);
148
- }
149
- }
150
- }
151
- catch (err) {
152
- console.warn(`[buildContext] Failed to read evidence: ${evidencePath}`, err instanceof Error ? err.message : err);
153
- }
154
- ctx.evidenceIdsByIssue.set(relBase, evidenceIds);
155
- }
156
- }
157
- }
158
- }
159
- catch (err) {
160
- console.warn('[buildContext] Failed to load issues/evidence:', err instanceof Error ? err.message : err);
161
- }
162
- return ctx;
163
- }
164
- //# sourceMappingURL=buildContext.js.map