@rejot-dev/thalo 0.0.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 (237) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +396 -0
  3. package/dist/ast/ast-types.d.ts +469 -0
  4. package/dist/ast/ast-types.d.ts.map +1 -0
  5. package/dist/ast/ast-types.js +11 -0
  6. package/dist/ast/ast-types.js.map +1 -0
  7. package/dist/ast/builder.js +158 -0
  8. package/dist/ast/builder.js.map +1 -0
  9. package/dist/ast/extract.js +748 -0
  10. package/dist/ast/extract.js.map +1 -0
  11. package/dist/ast/node-at-position.d.ts +147 -0
  12. package/dist/ast/node-at-position.d.ts.map +1 -0
  13. package/dist/ast/node-at-position.js +382 -0
  14. package/dist/ast/node-at-position.js.map +1 -0
  15. package/dist/ast/visitor.js +232 -0
  16. package/dist/ast/visitor.js.map +1 -0
  17. package/dist/checker/check.d.ts +53 -0
  18. package/dist/checker/check.d.ts.map +1 -0
  19. package/dist/checker/check.js +105 -0
  20. package/dist/checker/check.js.map +1 -0
  21. package/dist/checker/rules/actualize-missing-updated.js +34 -0
  22. package/dist/checker/rules/actualize-missing-updated.js.map +1 -0
  23. package/dist/checker/rules/actualize-unresolved-target.js +42 -0
  24. package/dist/checker/rules/actualize-unresolved-target.js.map +1 -0
  25. package/dist/checker/rules/alter-before-define.js +53 -0
  26. package/dist/checker/rules/alter-before-define.js.map +1 -0
  27. package/dist/checker/rules/alter-undefined-entity.js +32 -0
  28. package/dist/checker/rules/alter-undefined-entity.js.map +1 -0
  29. package/dist/checker/rules/create-requires-section.js +34 -0
  30. package/dist/checker/rules/create-requires-section.js.map +1 -0
  31. package/dist/checker/rules/define-entity-requires-section.js +31 -0
  32. package/dist/checker/rules/define-entity-requires-section.js.map +1 -0
  33. package/dist/checker/rules/duplicate-entity-definition.js +37 -0
  34. package/dist/checker/rules/duplicate-entity-definition.js.map +1 -0
  35. package/dist/checker/rules/duplicate-field-in-schema.js +38 -0
  36. package/dist/checker/rules/duplicate-field-in-schema.js.map +1 -0
  37. package/dist/checker/rules/duplicate-link-id.js +52 -0
  38. package/dist/checker/rules/duplicate-link-id.js.map +1 -0
  39. package/dist/checker/rules/duplicate-metadata-key.js +21 -0
  40. package/dist/checker/rules/duplicate-metadata-key.js.map +1 -0
  41. package/dist/checker/rules/duplicate-section-heading.js +41 -0
  42. package/dist/checker/rules/duplicate-section-heading.js.map +1 -0
  43. package/dist/checker/rules/duplicate-section-in-schema.js +38 -0
  44. package/dist/checker/rules/duplicate-section-in-schema.js.map +1 -0
  45. package/dist/checker/rules/duplicate-timestamp.js +104 -0
  46. package/dist/checker/rules/duplicate-timestamp.js.map +1 -0
  47. package/dist/checker/rules/empty-required-value.js +45 -0
  48. package/dist/checker/rules/empty-required-value.js.map +1 -0
  49. package/dist/checker/rules/empty-section.js +21 -0
  50. package/dist/checker/rules/empty-section.js.map +1 -0
  51. package/dist/checker/rules/invalid-date-range-value.js +56 -0
  52. package/dist/checker/rules/invalid-date-range-value.js.map +1 -0
  53. package/dist/checker/rules/invalid-default-value.js +86 -0
  54. package/dist/checker/rules/invalid-default-value.js.map +1 -0
  55. package/dist/checker/rules/invalid-field-type.js +45 -0
  56. package/dist/checker/rules/invalid-field-type.js.map +1 -0
  57. package/dist/checker/rules/missing-required-field.js +48 -0
  58. package/dist/checker/rules/missing-required-field.js.map +1 -0
  59. package/dist/checker/rules/missing-required-section.js +51 -0
  60. package/dist/checker/rules/missing-required-section.js.map +1 -0
  61. package/dist/checker/rules/missing-title.js +56 -0
  62. package/dist/checker/rules/missing-title.js.map +1 -0
  63. package/dist/checker/rules/remove-undefined-field.js +42 -0
  64. package/dist/checker/rules/remove-undefined-field.js.map +1 -0
  65. package/dist/checker/rules/remove-undefined-section.js +42 -0
  66. package/dist/checker/rules/remove-undefined-section.js.map +1 -0
  67. package/dist/checker/rules/rules.d.ts +71 -0
  68. package/dist/checker/rules/rules.d.ts.map +1 -0
  69. package/dist/checker/rules/rules.js +102 -0
  70. package/dist/checker/rules/rules.js.map +1 -0
  71. package/dist/checker/rules/synthesis-empty-query.js +35 -0
  72. package/dist/checker/rules/synthesis-empty-query.js.map +1 -0
  73. package/dist/checker/rules/synthesis-missing-prompt.js +42 -0
  74. package/dist/checker/rules/synthesis-missing-prompt.js.map +1 -0
  75. package/dist/checker/rules/synthesis-missing-sources.js +32 -0
  76. package/dist/checker/rules/synthesis-missing-sources.js.map +1 -0
  77. package/dist/checker/rules/synthesis-unknown-query-entity.js +39 -0
  78. package/dist/checker/rules/synthesis-unknown-query-entity.js.map +1 -0
  79. package/dist/checker/rules/timestamp-out-of-order.js +55 -0
  80. package/dist/checker/rules/timestamp-out-of-order.js.map +1 -0
  81. package/dist/checker/rules/unknown-entity.js +32 -0
  82. package/dist/checker/rules/unknown-entity.js.map +1 -0
  83. package/dist/checker/rules/unknown-field.js +40 -0
  84. package/dist/checker/rules/unknown-field.js.map +1 -0
  85. package/dist/checker/rules/unknown-section.js +47 -0
  86. package/dist/checker/rules/unknown-section.js.map +1 -0
  87. package/dist/checker/rules/unresolved-link.js +34 -0
  88. package/dist/checker/rules/unresolved-link.js.map +1 -0
  89. package/dist/checker/rules/update-without-create.js +65 -0
  90. package/dist/checker/rules/update-without-create.js.map +1 -0
  91. package/dist/checker/visitor.d.ts +69 -0
  92. package/dist/checker/visitor.d.ts.map +1 -0
  93. package/dist/checker/visitor.js +67 -0
  94. package/dist/checker/visitor.js.map +1 -0
  95. package/dist/checker/workspace-index.d.ts +50 -0
  96. package/dist/checker/workspace-index.d.ts.map +1 -0
  97. package/dist/checker/workspace-index.js +108 -0
  98. package/dist/checker/workspace-index.js.map +1 -0
  99. package/dist/commands/actualize.d.ts +113 -0
  100. package/dist/commands/actualize.d.ts.map +1 -0
  101. package/dist/commands/actualize.js +111 -0
  102. package/dist/commands/actualize.js.map +1 -0
  103. package/dist/commands/check.d.ts +65 -0
  104. package/dist/commands/check.d.ts.map +1 -0
  105. package/dist/commands/check.js +61 -0
  106. package/dist/commands/check.js.map +1 -0
  107. package/dist/commands/format.d.ts +90 -0
  108. package/dist/commands/format.d.ts.map +1 -0
  109. package/dist/commands/format.js +80 -0
  110. package/dist/commands/format.js.map +1 -0
  111. package/dist/commands/query.d.ts +152 -0
  112. package/dist/commands/query.d.ts.map +1 -0
  113. package/dist/commands/query.js +151 -0
  114. package/dist/commands/query.js.map +1 -0
  115. package/dist/constants.d.ts +31 -0
  116. package/dist/constants.d.ts.map +1 -0
  117. package/dist/constants.js +51 -0
  118. package/dist/constants.js.map +1 -0
  119. package/dist/files.d.ts +58 -0
  120. package/dist/files.d.ts.map +1 -0
  121. package/dist/files.js +103 -0
  122. package/dist/files.js.map +1 -0
  123. package/dist/formatters.d.ts +39 -0
  124. package/dist/formatters.d.ts.map +1 -0
  125. package/dist/formatters.js +200 -0
  126. package/dist/formatters.js.map +1 -0
  127. package/dist/fragment.d.ts +22 -0
  128. package/dist/fragment.d.ts.map +1 -0
  129. package/dist/git/git.js +240 -0
  130. package/dist/git/git.js.map +1 -0
  131. package/dist/merge/conflict-detector.d.ts +89 -0
  132. package/dist/merge/conflict-detector.d.ts.map +1 -0
  133. package/dist/merge/conflict-detector.js +352 -0
  134. package/dist/merge/conflict-detector.js.map +1 -0
  135. package/dist/merge/conflict-formatter.js +143 -0
  136. package/dist/merge/conflict-formatter.js.map +1 -0
  137. package/dist/merge/driver.d.ts +54 -0
  138. package/dist/merge/driver.d.ts.map +1 -0
  139. package/dist/merge/driver.js +112 -0
  140. package/dist/merge/driver.js.map +1 -0
  141. package/dist/merge/entry-matcher.d.ts +50 -0
  142. package/dist/merge/entry-matcher.d.ts.map +1 -0
  143. package/dist/merge/entry-matcher.js +141 -0
  144. package/dist/merge/entry-matcher.js.map +1 -0
  145. package/dist/merge/entry-merger.js +194 -0
  146. package/dist/merge/entry-merger.js.map +1 -0
  147. package/dist/merge/merge-result-builder.d.ts +62 -0
  148. package/dist/merge/merge-result-builder.d.ts.map +1 -0
  149. package/dist/merge/merge-result-builder.js +89 -0
  150. package/dist/merge/merge-result-builder.js.map +1 -0
  151. package/dist/mod.d.ts +31 -0
  152. package/dist/mod.js +23 -0
  153. package/dist/model/document.d.ts +134 -0
  154. package/dist/model/document.d.ts.map +1 -0
  155. package/dist/model/document.js +275 -0
  156. package/dist/model/document.js.map +1 -0
  157. package/dist/model/line-index.d.ts +85 -0
  158. package/dist/model/line-index.d.ts.map +1 -0
  159. package/dist/model/line-index.js +159 -0
  160. package/dist/model/line-index.js.map +1 -0
  161. package/dist/model/workspace.d.ts +296 -0
  162. package/dist/model/workspace.d.ts.map +1 -0
  163. package/dist/model/workspace.js +562 -0
  164. package/dist/model/workspace.js.map +1 -0
  165. package/dist/parser.js +27 -0
  166. package/dist/parser.js.map +1 -0
  167. package/dist/parser.native.d.ts +51 -0
  168. package/dist/parser.native.d.ts.map +1 -0
  169. package/dist/parser.native.js +62 -0
  170. package/dist/parser.native.js.map +1 -0
  171. package/dist/parser.shared.d.ts +99 -0
  172. package/dist/parser.shared.d.ts.map +1 -0
  173. package/dist/parser.shared.js +124 -0
  174. package/dist/parser.shared.js.map +1 -0
  175. package/dist/parser.web.d.ts +67 -0
  176. package/dist/parser.web.d.ts.map +1 -0
  177. package/dist/parser.web.js +49 -0
  178. package/dist/parser.web.js.map +1 -0
  179. package/dist/schema/registry.d.ts +108 -0
  180. package/dist/schema/registry.d.ts.map +1 -0
  181. package/dist/schema/registry.js +281 -0
  182. package/dist/schema/registry.js.map +1 -0
  183. package/dist/semantic/analyzer.d.ts +107 -0
  184. package/dist/semantic/analyzer.d.ts.map +1 -0
  185. package/dist/semantic/analyzer.js +261 -0
  186. package/dist/semantic/analyzer.js.map +1 -0
  187. package/dist/services/change-tracker/change-tracker.d.ts +111 -0
  188. package/dist/services/change-tracker/change-tracker.d.ts.map +1 -0
  189. package/dist/services/change-tracker/change-tracker.js +62 -0
  190. package/dist/services/change-tracker/change-tracker.js.map +1 -0
  191. package/dist/services/change-tracker/create-tracker.d.ts +42 -0
  192. package/dist/services/change-tracker/create-tracker.d.ts.map +1 -0
  193. package/dist/services/change-tracker/create-tracker.js +53 -0
  194. package/dist/services/change-tracker/create-tracker.js.map +1 -0
  195. package/dist/services/change-tracker/git-tracker.d.ts +59 -0
  196. package/dist/services/change-tracker/git-tracker.d.ts.map +1 -0
  197. package/dist/services/change-tracker/git-tracker.js +218 -0
  198. package/dist/services/change-tracker/git-tracker.js.map +1 -0
  199. package/dist/services/change-tracker/timestamp-tracker.d.ts +22 -0
  200. package/dist/services/change-tracker/timestamp-tracker.d.ts.map +1 -0
  201. package/dist/services/change-tracker/timestamp-tracker.js +74 -0
  202. package/dist/services/change-tracker/timestamp-tracker.js.map +1 -0
  203. package/dist/services/definition.d.ts +37 -0
  204. package/dist/services/definition.d.ts.map +1 -0
  205. package/dist/services/definition.js +43 -0
  206. package/dist/services/definition.js.map +1 -0
  207. package/dist/services/entity-navigation.d.ts +200 -0
  208. package/dist/services/entity-navigation.d.ts.map +1 -0
  209. package/dist/services/entity-navigation.js +211 -0
  210. package/dist/services/entity-navigation.js.map +1 -0
  211. package/dist/services/hover.d.ts +81 -0
  212. package/dist/services/hover.d.ts.map +1 -0
  213. package/dist/services/hover.js +669 -0
  214. package/dist/services/hover.js.map +1 -0
  215. package/dist/services/query.d.ts +116 -0
  216. package/dist/services/query.d.ts.map +1 -0
  217. package/dist/services/query.js +225 -0
  218. package/dist/services/query.js.map +1 -0
  219. package/dist/services/references.d.ts +52 -0
  220. package/dist/services/references.d.ts.map +1 -0
  221. package/dist/services/references.js +66 -0
  222. package/dist/services/references.js.map +1 -0
  223. package/dist/services/semantic-tokens.d.ts +54 -0
  224. package/dist/services/semantic-tokens.d.ts.map +1 -0
  225. package/dist/services/semantic-tokens.js +213 -0
  226. package/dist/services/semantic-tokens.js.map +1 -0
  227. package/dist/services/synthesis.d.ts +90 -0
  228. package/dist/services/synthesis.d.ts.map +1 -0
  229. package/dist/services/synthesis.js +113 -0
  230. package/dist/services/synthesis.js.map +1 -0
  231. package/dist/source-map.d.ts +42 -0
  232. package/dist/source-map.d.ts.map +1 -0
  233. package/dist/source-map.js +170 -0
  234. package/dist/source-map.js.map +1 -0
  235. package/package.json +128 -0
  236. package/tree-sitter-thalo.wasm +0 -0
  237. package/web-tree-sitter.wasm +0 -0
@@ -0,0 +1,65 @@
1
+ import { Workspace } from "../model/workspace.js";
2
+ import { CheckConfig } from "../checker/check.js";
3
+
4
+ //#region src/commands/check.d.ts
5
+
6
+ /**
7
+ * Severity levels for diagnostics
8
+ */
9
+ type DiagnosticSeverity = "error" | "warning" | "info";
10
+ /**
11
+ * A single diagnostic (error, warning, or info) from the checker.
12
+ */
13
+ interface DiagnosticInfo {
14
+ /** File path where the diagnostic occurred */
15
+ file: string;
16
+ /** 1-based line number */
17
+ line: number;
18
+ /** 1-based column number */
19
+ column: number;
20
+ /** End line (1-based) */
21
+ endLine: number;
22
+ /** End column (1-based) */
23
+ endColumn: number;
24
+ /** Severity level */
25
+ severity: DiagnosticSeverity;
26
+ /** Rule code (e.g., "unknown-entity", "missing-title") */
27
+ code: string;
28
+ /** Human-readable error message */
29
+ message: string;
30
+ }
31
+ /**
32
+ * Result of running the check command.
33
+ */
34
+ interface CheckResult {
35
+ /** Number of files that were checked */
36
+ filesChecked: number;
37
+ /** Diagnostics grouped by file path */
38
+ diagnosticsByFile: Map<string, DiagnosticInfo[]>;
39
+ /** Total number of errors */
40
+ errorCount: number;
41
+ /** Total number of warnings */
42
+ warningCount: number;
43
+ /** Total number of info messages */
44
+ infoCount: number;
45
+ }
46
+ /**
47
+ * Options for running the check command.
48
+ */
49
+ interface RunCheckOptions {
50
+ /** Checker configuration (rule overrides, etc.) */
51
+ config?: CheckConfig;
52
+ /** Minimum severity to include (default: "info") */
53
+ minSeverity?: DiagnosticSeverity;
54
+ }
55
+ /**
56
+ * Run the check command on a workspace.
57
+ *
58
+ * @param workspace - The workspace to check
59
+ * @param options - Check options
60
+ * @returns Structured check results
61
+ */
62
+ declare function runCheck(workspace: Workspace, options?: RunCheckOptions): CheckResult;
63
+ //#endregion
64
+ export { CheckResult, DiagnosticInfo, DiagnosticSeverity, RunCheckOptions, runCheck };
65
+ //# sourceMappingURL=check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.d.ts","names":[],"sources":["../../src/commands/check.ts"],"sourcesContent":[],"mappings":";;;;;AAoBA;AAsBA;AAgBA;AAoCgB,KA/EJ,kBAAA,GA+EY,OAAA,GAAA,SAAA,GAAA,MAAA;;;;AAAkE,UA1EzE,cAAA,CA0EyE;;;;;;;;;;;;YA9D9E;;;;;;;;;UAUK,WAAA;;;;qBAII,YAAY;;;;;;;;;;;UAYhB,eAAA;;WAEN;;gBAEK;;;;;;;;;iBAgCA,QAAA,YAAoB,qBAAoB,kBAAuB"}
@@ -0,0 +1,61 @@
1
+ import { check } from "../checker/check.js";
2
+
3
+ //#region src/commands/check.ts
4
+ const SEVERITY_ORDER = {
5
+ error: 0,
6
+ warning: 1,
7
+ info: 2
8
+ };
9
+ /**
10
+ * Convert a diagnostic to DiagnosticInfo.
11
+ */
12
+ function toDiagnosticInfo(diagnostic) {
13
+ return {
14
+ file: diagnostic.file,
15
+ line: diagnostic.location.startPosition.row + 1,
16
+ column: diagnostic.location.startPosition.column + 1,
17
+ endLine: diagnostic.location.endPosition.row + 1,
18
+ endColumn: diagnostic.location.endPosition.column + 1,
19
+ severity: diagnostic.severity,
20
+ code: diagnostic.code,
21
+ message: diagnostic.message
22
+ };
23
+ }
24
+ /**
25
+ * Run the check command on a workspace.
26
+ *
27
+ * @param workspace - The workspace to check
28
+ * @param options - Check options
29
+ * @returns Structured check results
30
+ */
31
+ function runCheck(workspace, options = {}) {
32
+ const { config = {}, minSeverity = "info" } = options;
33
+ const diagnostics = check(workspace, config);
34
+ const minSeverityOrder = SEVERITY_ORDER[minSeverity];
35
+ const filteredDiagnostics = diagnostics.filter((d) => SEVERITY_ORDER[d.severity] <= minSeverityOrder);
36
+ filteredDiagnostics.sort((a, b) => {
37
+ if (a.file !== b.file) return a.file.localeCompare(b.file);
38
+ if (a.location.startPosition.row !== b.location.startPosition.row) return a.location.startPosition.row - b.location.startPosition.row;
39
+ return a.location.startPosition.column - b.location.startPosition.column;
40
+ });
41
+ const diagnosticsByFile = /* @__PURE__ */ new Map();
42
+ for (const d of filteredDiagnostics) {
43
+ const existing = diagnosticsByFile.get(d.file) || [];
44
+ existing.push(toDiagnosticInfo(d));
45
+ diagnosticsByFile.set(d.file, existing);
46
+ }
47
+ const errorCount = filteredDiagnostics.filter((d) => d.severity === "error").length;
48
+ const warningCount = filteredDiagnostics.filter((d) => d.severity === "warning").length;
49
+ const infoCount = filteredDiagnostics.filter((d) => d.severity === "info").length;
50
+ return {
51
+ filesChecked: workspace.files().length,
52
+ diagnosticsByFile,
53
+ errorCount,
54
+ warningCount,
55
+ infoCount
56
+ };
57
+ }
58
+
59
+ //#endregion
60
+ export { runCheck };
61
+ //# sourceMappingURL=check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.js","names":["SEVERITY_ORDER: Record<DiagnosticSeverity, number>"],"sources":["../../src/commands/check.ts"],"sourcesContent":["/**\n * Check command - runs the checker on a workspace and returns structured results.\n */\n\nimport type { Workspace } from \"../model/workspace.js\";\nimport { check } from \"../checker/check.js\";\nimport type { CheckConfig, Diagnostic } from \"../checker/check.js\";\n\n// ===================\n// Types\n// ===================\n\n/**\n * Severity levels for diagnostics\n */\nexport type DiagnosticSeverity = \"error\" | \"warning\" | \"info\";\n\n/**\n * A single diagnostic (error, warning, or info) from the checker.\n */\nexport interface DiagnosticInfo {\n /** File path where the diagnostic occurred */\n file: string;\n /** 1-based line number */\n line: number;\n /** 1-based column number */\n column: number;\n /** End line (1-based) */\n endLine: number;\n /** End column (1-based) */\n endColumn: number;\n /** Severity level */\n severity: DiagnosticSeverity;\n /** Rule code (e.g., \"unknown-entity\", \"missing-title\") */\n code: string;\n /** Human-readable error message */\n message: string;\n}\n\n/**\n * Result of running the check command.\n */\nexport interface CheckResult {\n /** Number of files that were checked */\n filesChecked: number;\n /** Diagnostics grouped by file path */\n diagnosticsByFile: Map<string, DiagnosticInfo[]>;\n /** Total number of errors */\n errorCount: number;\n /** Total number of warnings */\n warningCount: number;\n /** Total number of info messages */\n infoCount: number;\n}\n\n/**\n * Options for running the check command.\n */\nexport interface RunCheckOptions {\n /** Checker configuration (rule overrides, etc.) */\n config?: CheckConfig;\n /** Minimum severity to include (default: \"info\") */\n minSeverity?: DiagnosticSeverity;\n}\n\nconst SEVERITY_ORDER: Record<DiagnosticSeverity, number> = {\n error: 0,\n warning: 1,\n info: 2,\n};\n\n/**\n * Convert a diagnostic to DiagnosticInfo.\n */\nfunction toDiagnosticInfo(diagnostic: Diagnostic): DiagnosticInfo {\n return {\n file: diagnostic.file,\n line: diagnostic.location.startPosition.row + 1,\n column: diagnostic.location.startPosition.column + 1,\n endLine: diagnostic.location.endPosition.row + 1,\n endColumn: diagnostic.location.endPosition.column + 1,\n severity: diagnostic.severity as DiagnosticSeverity,\n code: diagnostic.code,\n message: diagnostic.message,\n };\n}\n\n/**\n * Run the check command on a workspace.\n *\n * @param workspace - The workspace to check\n * @param options - Check options\n * @returns Structured check results\n */\nexport function runCheck(workspace: Workspace, options: RunCheckOptions = {}): CheckResult {\n const { config = {}, minSeverity = \"info\" } = options;\n\n // Run the checker\n const diagnostics = check(workspace, config);\n\n // Filter by minimum severity\n const minSeverityOrder = SEVERITY_ORDER[minSeverity];\n const filteredDiagnostics = diagnostics.filter(\n (d) => SEVERITY_ORDER[d.severity as DiagnosticSeverity] <= minSeverityOrder,\n );\n\n // Sort diagnostics by file, then position\n filteredDiagnostics.sort((a, b) => {\n if (a.file !== b.file) {\n return a.file.localeCompare(b.file);\n }\n if (a.location.startPosition.row !== b.location.startPosition.row) {\n return a.location.startPosition.row - b.location.startPosition.row;\n }\n return a.location.startPosition.column - b.location.startPosition.column;\n });\n\n // Group by file\n const diagnosticsByFile = new Map<string, DiagnosticInfo[]>();\n for (const d of filteredDiagnostics) {\n const existing = diagnosticsByFile.get(d.file) || [];\n existing.push(toDiagnosticInfo(d));\n diagnosticsByFile.set(d.file, existing);\n }\n\n // Count by severity\n const errorCount = filteredDiagnostics.filter((d) => d.severity === \"error\").length;\n const warningCount = filteredDiagnostics.filter((d) => d.severity === \"warning\").length;\n const infoCount = filteredDiagnostics.filter((d) => d.severity === \"info\").length;\n\n return {\n filesChecked: workspace.files().length,\n diagnosticsByFile,\n errorCount,\n warningCount,\n infoCount,\n };\n}\n"],"mappings":";;;AAiEA,MAAMA,iBAAqD;CACzD,OAAO;CACP,SAAS;CACT,MAAM;CACP;;;;AAKD,SAAS,iBAAiB,YAAwC;AAChE,QAAO;EACL,MAAM,WAAW;EACjB,MAAM,WAAW,SAAS,cAAc,MAAM;EAC9C,QAAQ,WAAW,SAAS,cAAc,SAAS;EACnD,SAAS,WAAW,SAAS,YAAY,MAAM;EAC/C,WAAW,WAAW,SAAS,YAAY,SAAS;EACpD,UAAU,WAAW;EACrB,MAAM,WAAW;EACjB,SAAS,WAAW;EACrB;;;;;;;;;AAUH,SAAgB,SAAS,WAAsB,UAA2B,EAAE,EAAe;CACzF,MAAM,EAAE,SAAS,EAAE,EAAE,cAAc,WAAW;CAG9C,MAAM,cAAc,MAAM,WAAW,OAAO;CAG5C,MAAM,mBAAmB,eAAe;CACxC,MAAM,sBAAsB,YAAY,QACrC,MAAM,eAAe,EAAE,aAAmC,iBAC5D;AAGD,qBAAoB,MAAM,GAAG,MAAM;AACjC,MAAI,EAAE,SAAS,EAAE,KACf,QAAO,EAAE,KAAK,cAAc,EAAE,KAAK;AAErC,MAAI,EAAE,SAAS,cAAc,QAAQ,EAAE,SAAS,cAAc,IAC5D,QAAO,EAAE,SAAS,cAAc,MAAM,EAAE,SAAS,cAAc;AAEjE,SAAO,EAAE,SAAS,cAAc,SAAS,EAAE,SAAS,cAAc;GAClE;CAGF,MAAM,oCAAoB,IAAI,KAA+B;AAC7D,MAAK,MAAM,KAAK,qBAAqB;EACnC,MAAM,WAAW,kBAAkB,IAAI,EAAE,KAAK,IAAI,EAAE;AACpD,WAAS,KAAK,iBAAiB,EAAE,CAAC;AAClC,oBAAkB,IAAI,EAAE,MAAM,SAAS;;CAIzC,MAAM,aAAa,oBAAoB,QAAQ,MAAM,EAAE,aAAa,QAAQ,CAAC;CAC7E,MAAM,eAAe,oBAAoB,QAAQ,MAAM,EAAE,aAAa,UAAU,CAAC;CACjF,MAAM,YAAY,oBAAoB,QAAQ,MAAM,EAAE,aAAa,OAAO,CAAC;AAE3E,QAAO;EACL,cAAc,UAAU,OAAO,CAAC;EAChC;EACA;EACA;EACA;EACD"}
@@ -0,0 +1,90 @@
1
+ import { Workspace } from "../model/workspace.js";
2
+
3
+ //#region src/commands/format.d.ts
4
+
5
+ /**
6
+ * A syntax error found during parsing.
7
+ */
8
+ interface SyntaxErrorInfo {
9
+ /** File path where the error occurred */
10
+ file: string;
11
+ /** 1-based line number */
12
+ line: number;
13
+ /** 1-based column number */
14
+ column: number;
15
+ /** Human-readable error message */
16
+ message: string;
17
+ /** Error code (e.g., "syntax-parse_error") */
18
+ code: string;
19
+ }
20
+ /**
21
+ * Result of formatting a single file.
22
+ */
23
+ interface FormatFileResult {
24
+ /** The file path */
25
+ file: string;
26
+ /** The formatted content (or original if unchanged/error) */
27
+ formatted: string;
28
+ /** Whether the content changed after formatting */
29
+ isChanged: boolean;
30
+ /** Whether the file has syntax errors (formatting skipped) */
31
+ hasSyntaxErrors: boolean;
32
+ /** Syntax errors found in the file (if any) */
33
+ syntaxErrors: SyntaxErrorInfo[];
34
+ }
35
+ /**
36
+ * Result of running the format command.
37
+ */
38
+ interface FormatResult {
39
+ /** Number of files that were processed */
40
+ filesProcessed: number;
41
+ /** Results for each file */
42
+ fileResults: FormatFileResult[];
43
+ /** Number of files that were changed/need changes */
44
+ changedCount: number;
45
+ /** Number of files with syntax errors */
46
+ syntaxErrorCount: number;
47
+ /** Total number of syntax errors across all files */
48
+ totalSyntaxErrors: number;
49
+ }
50
+ /**
51
+ * A formatter function that formats source code.
52
+ */
53
+ type Formatter = (source: string, filepath: string) => Promise<string>;
54
+ /**
55
+ * Input for formatting a single file.
56
+ */
57
+ interface FormatFileInput {
58
+ /** The file path */
59
+ file: string;
60
+ /** The file content */
61
+ content: string;
62
+ }
63
+ /**
64
+ * Options for running the format command.
65
+ */
66
+ interface RunFormatOptions {
67
+ /** Custom formatter function (e.g., prettier) */
68
+ formatter: Formatter;
69
+ }
70
+ /**
71
+ * Format a single file, checking for syntax errors first.
72
+ *
73
+ * @param workspace - The workspace to use for syntax checking
74
+ * @param input - The file input (path and content)
75
+ * @param formatter - The formatter function to apply
76
+ * @returns The format result for this file
77
+ */
78
+ declare function formatFile(workspace: Workspace, input: FormatFileInput, formatter: Formatter): Promise<FormatFileResult>;
79
+ /**
80
+ * Run the format command on multiple files.
81
+ *
82
+ * @param workspace - The workspace to use for syntax checking
83
+ * @param files - The files to format (path and content)
84
+ * @param options - Format options including the formatter function
85
+ * @returns Structured format results
86
+ */
87
+ declare function runFormat(workspace: Workspace, files: FormatFileInput[], options: RunFormatOptions): Promise<FormatResult>;
88
+ //#endregion
89
+ export { FormatFileInput, FormatFileResult, FormatResult, Formatter, RunFormatOptions, SyntaxErrorInfo, formatFile, runFormat };
90
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.d.ts","names":[],"sources":["../../src/commands/format.ts"],"sourcesContent":[],"mappings":";;;;AA6BA;AAgBA;AAgBA;AAKiB,UArDA,eAAA,CAqDe;EAUf;EAoDK,IAAA,EAAA,MAAA;EACT;EACJ,IAAA,EAAA,MAAA;EACI;EACF,MAAA,EAAA,MAAA;EAAR;EAAO,OAAA,EAAA,MAAA;EAoCY;EACT,IAAA,EAAA,MAAA;;;;;AAGH,UA/IO,gBAAA,CA+IP;;;;;;;;;;gBArIM;;;;;UAMC,YAAA;;;;eAIF;;;;;;;;;;;KAYH,SAAA,yCAAkD;;;;UAK7C,eAAA;;;;;;;;;UAUA,gBAAA;;aAEJ;;;;;;;;;;iBAkDS,UAAA,YACT,kBACJ,4BACI,YACV,QAAQ;;;;;;;;;iBAoCW,SAAA,YACT,kBACJ,4BACE,mBACR,QAAQ"}
@@ -0,0 +1,80 @@
1
+ //#region src/commands/format.ts
2
+ /**
3
+ * Check a file for syntax errors using the thalo parser.
4
+ * Returns syntax errors without running semantic analysis or rules.
5
+ */
6
+ function collectSyntaxErrors(workspace, file, content) {
7
+ const errors = [];
8
+ workspace.addDocument(content, { filename: file });
9
+ try {
10
+ const model = workspace.getModel(file);
11
+ if (!model) return errors;
12
+ for (const error of model.ast.syntaxErrors) errors.push({
13
+ file,
14
+ line: error.location.startPosition.row + 1,
15
+ column: error.location.startPosition.column + 1,
16
+ message: error.message,
17
+ code: `syntax-${error.code}`
18
+ });
19
+ return errors;
20
+ } finally {
21
+ workspace.removeDocument(file);
22
+ }
23
+ }
24
+ /**
25
+ * Format a single file, checking for syntax errors first.
26
+ *
27
+ * @param workspace - The workspace to use for syntax checking
28
+ * @param input - The file input (path and content)
29
+ * @param formatter - The formatter function to apply
30
+ * @returns The format result for this file
31
+ */
32
+ async function formatFile(workspace, input, formatter) {
33
+ const { file, content } = input;
34
+ const syntaxErrors = collectSyntaxErrors(workspace, file, content);
35
+ if (syntaxErrors.length > 0) return {
36
+ file,
37
+ formatted: content,
38
+ isChanged: false,
39
+ hasSyntaxErrors: true,
40
+ syntaxErrors
41
+ };
42
+ const formatted = await formatter(content, file);
43
+ return {
44
+ file,
45
+ formatted,
46
+ isChanged: content !== formatted,
47
+ hasSyntaxErrors: false,
48
+ syntaxErrors: []
49
+ };
50
+ }
51
+ /**
52
+ * Run the format command on multiple files.
53
+ *
54
+ * @param workspace - The workspace to use for syntax checking
55
+ * @param files - The files to format (path and content)
56
+ * @param options - Format options including the formatter function
57
+ * @returns Structured format results
58
+ */
59
+ async function runFormat(workspace, files, options) {
60
+ const { formatter } = options;
61
+ const fileResults = [];
62
+ for (const input of files) {
63
+ const result = await formatFile(workspace, input, formatter);
64
+ fileResults.push(result);
65
+ }
66
+ const changedCount = fileResults.filter((r) => r.isChanged).length;
67
+ const syntaxErrorCount = fileResults.filter((r) => r.hasSyntaxErrors).length;
68
+ const totalSyntaxErrors = fileResults.reduce((sum, r) => sum + r.syntaxErrors.length, 0);
69
+ return {
70
+ filesProcessed: files.length,
71
+ fileResults,
72
+ changedCount,
73
+ syntaxErrorCount,
74
+ totalSyntaxErrors
75
+ };
76
+ }
77
+
78
+ //#endregion
79
+ export { formatFile, runFormat };
80
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","names":["errors: SyntaxErrorInfo[]","fileResults: FormatFileResult[]"],"sources":["../../src/commands/format.ts"],"sourcesContent":["/**\n * Format command - checks syntax and formats files, returning structured results.\n */\n\nimport type { Workspace } from \"../model/workspace.js\";\n\n// ===================\n// Types\n// ===================\n\n/**\n * A syntax error found during parsing.\n */\nexport interface SyntaxErrorInfo {\n /** File path where the error occurred */\n file: string;\n /** 1-based line number */\n line: number;\n /** 1-based column number */\n column: number;\n /** Human-readable error message */\n message: string;\n /** Error code (e.g., \"syntax-parse_error\") */\n code: string;\n}\n\n/**\n * Result of formatting a single file.\n */\nexport interface FormatFileResult {\n /** The file path */\n file: string;\n /** The formatted content (or original if unchanged/error) */\n formatted: string;\n /** Whether the content changed after formatting */\n isChanged: boolean;\n /** Whether the file has syntax errors (formatting skipped) */\n hasSyntaxErrors: boolean;\n /** Syntax errors found in the file (if any) */\n syntaxErrors: SyntaxErrorInfo[];\n}\n\n/**\n * Result of running the format command.\n */\nexport interface FormatResult {\n /** Number of files that were processed */\n filesProcessed: number;\n /** Results for each file */\n fileResults: FormatFileResult[];\n /** Number of files that were changed/need changes */\n changedCount: number;\n /** Number of files with syntax errors */\n syntaxErrorCount: number;\n /** Total number of syntax errors across all files */\n totalSyntaxErrors: number;\n}\n\n/**\n * A formatter function that formats source code.\n */\nexport type Formatter = (source: string, filepath: string) => Promise<string>;\n\n/**\n * Input for formatting a single file.\n */\nexport interface FormatFileInput {\n /** The file path */\n file: string;\n /** The file content */\n content: string;\n}\n\n/**\n * Options for running the format command.\n */\nexport interface RunFormatOptions {\n /** Custom formatter function (e.g., prettier) */\n formatter: Formatter;\n}\n\n// ===================\n// Core Logic\n// ===================\n\n/**\n * Check a file for syntax errors using the thalo parser.\n * Returns syntax errors without running semantic analysis or rules.\n */\nfunction collectSyntaxErrors(\n workspace: Workspace,\n file: string,\n content: string,\n): SyntaxErrorInfo[] {\n const errors: SyntaxErrorInfo[] = [];\n\n workspace.addDocument(content, { filename: file });\n try {\n const model = workspace.getModel(file);\n if (!model) {\n return errors;\n }\n\n // Collect root-level syntax errors\n for (const error of model.ast.syntaxErrors) {\n errors.push({\n file,\n line: error.location.startPosition.row + 1,\n column: error.location.startPosition.column + 1,\n message: error.message,\n code: `syntax-${error.code}`,\n });\n }\n\n return errors;\n } finally {\n workspace.removeDocument(file);\n }\n}\n\n/**\n * Format a single file, checking for syntax errors first.\n *\n * @param workspace - The workspace to use for syntax checking\n * @param input - The file input (path and content)\n * @param formatter - The formatter function to apply\n * @returns The format result for this file\n */\nexport async function formatFile(\n workspace: Workspace,\n input: FormatFileInput,\n formatter: Formatter,\n): Promise<FormatFileResult> {\n const { file, content } = input;\n\n // Check for syntax errors first\n const syntaxErrors = collectSyntaxErrors(workspace, file, content);\n if (syntaxErrors.length > 0) {\n // Return unchanged content - don't format files with syntax errors\n return {\n file,\n formatted: content,\n isChanged: false,\n hasSyntaxErrors: true,\n syntaxErrors,\n };\n }\n\n // Format the file\n const formatted = await formatter(content, file);\n\n return {\n file,\n formatted,\n isChanged: content !== formatted,\n hasSyntaxErrors: false,\n syntaxErrors: [],\n };\n}\n\n/**\n * Run the format command on multiple files.\n *\n * @param workspace - The workspace to use for syntax checking\n * @param files - The files to format (path and content)\n * @param options - Format options including the formatter function\n * @returns Structured format results\n */\nexport async function runFormat(\n workspace: Workspace,\n files: FormatFileInput[],\n options: RunFormatOptions,\n): Promise<FormatResult> {\n const { formatter } = options;\n\n const fileResults: FormatFileResult[] = [];\n\n // Process files sequentially to avoid workspace conflicts\n // (workspace.addDocument/removeDocument is not concurrent-safe)\n for (const input of files) {\n const result = await formatFile(workspace, input, formatter);\n fileResults.push(result);\n }\n\n // Calculate summary statistics\n const changedCount = fileResults.filter((r) => r.isChanged).length;\n const syntaxErrorCount = fileResults.filter((r) => r.hasSyntaxErrors).length;\n const totalSyntaxErrors = fileResults.reduce((sum, r) => sum + r.syntaxErrors.length, 0);\n\n return {\n filesProcessed: files.length,\n fileResults,\n changedCount,\n syntaxErrorCount,\n totalSyntaxErrors,\n };\n}\n"],"mappings":";;;;;AAyFA,SAAS,oBACP,WACA,MACA,SACmB;CACnB,MAAMA,SAA4B,EAAE;AAEpC,WAAU,YAAY,SAAS,EAAE,UAAU,MAAM,CAAC;AAClD,KAAI;EACF,MAAM,QAAQ,UAAU,SAAS,KAAK;AACtC,MAAI,CAAC,MACH,QAAO;AAIT,OAAK,MAAM,SAAS,MAAM,IAAI,aAC5B,QAAO,KAAK;GACV;GACA,MAAM,MAAM,SAAS,cAAc,MAAM;GACzC,QAAQ,MAAM,SAAS,cAAc,SAAS;GAC9C,SAAS,MAAM;GACf,MAAM,UAAU,MAAM;GACvB,CAAC;AAGJ,SAAO;WACC;AACR,YAAU,eAAe,KAAK;;;;;;;;;;;AAYlC,eAAsB,WACpB,WACA,OACA,WAC2B;CAC3B,MAAM,EAAE,MAAM,YAAY;CAG1B,MAAM,eAAe,oBAAoB,WAAW,MAAM,QAAQ;AAClE,KAAI,aAAa,SAAS,EAExB,QAAO;EACL;EACA,WAAW;EACX,WAAW;EACX,iBAAiB;EACjB;EACD;CAIH,MAAM,YAAY,MAAM,UAAU,SAAS,KAAK;AAEhD,QAAO;EACL;EACA;EACA,WAAW,YAAY;EACvB,iBAAiB;EACjB,cAAc,EAAE;EACjB;;;;;;;;;;AAWH,eAAsB,UACpB,WACA,OACA,SACuB;CACvB,MAAM,EAAE,cAAc;CAEtB,MAAMC,cAAkC,EAAE;AAI1C,MAAK,MAAM,SAAS,OAAO;EACzB,MAAM,SAAS,MAAM,WAAW,WAAW,OAAO,UAAU;AAC5D,cAAY,KAAK,OAAO;;CAI1B,MAAM,eAAe,YAAY,QAAQ,MAAM,EAAE,UAAU,CAAC;CAC5D,MAAM,mBAAmB,YAAY,QAAQ,MAAM,EAAE,gBAAgB,CAAC;CACtE,MAAM,oBAAoB,YAAY,QAAQ,KAAK,MAAM,MAAM,EAAE,aAAa,QAAQ,EAAE;AAExF,QAAO;EACL,gBAAgB,MAAM;EACtB;EACA;EACA;EACA;EACD"}
@@ -0,0 +1,152 @@
1
+ import { Workspace } from "../model/workspace.js";
2
+ import { Query, QueryCondition, parseQueryString } from "../services/query.js";
3
+ import { ChangeTracker } from "../services/change-tracker/change-tracker.js";
4
+
5
+ //#region src/commands/query.d.ts
6
+
7
+ /**
8
+ * Information about a condition in a query.
9
+ */
10
+ interface QueryConditionInfo {
11
+ kind: QueryCondition["kind"];
12
+ /** For field conditions */
13
+ field?: string;
14
+ value?: string;
15
+ /** For tag conditions */
16
+ tag?: string;
17
+ /** For link conditions */
18
+ link?: string;
19
+ }
20
+ /**
21
+ * Information about an entry that matched a query.
22
+ */
23
+ interface QueryEntryInfo {
24
+ /** File path containing the entry */
25
+ file: string;
26
+ /** Formatted timestamp string */
27
+ timestamp: string;
28
+ /** Entity type (e.g., "lore", "opinion") */
29
+ entity: string;
30
+ /** Entry title */
31
+ title: string;
32
+ /** Link ID if present */
33
+ linkId: string | null;
34
+ /** Tags on the entry */
35
+ tags: string[];
36
+ /** 1-based start line */
37
+ startLine: number;
38
+ /** 1-based end line */
39
+ endLine: number;
40
+ /** Raw source text of the entry (optional, for "raw" format) */
41
+ rawText?: string;
42
+ }
43
+ /**
44
+ * Result of running the query command (single query).
45
+ */
46
+ interface QueryResult {
47
+ /** The parsed query */
48
+ query: Query;
49
+ /** Formatted query string for display */
50
+ queryString: string;
51
+ /** Matching entries */
52
+ entries: QueryEntryInfo[];
53
+ /** Total count (may be more than entries.length if limited) */
54
+ totalCount: number;
55
+ }
56
+ /**
57
+ * Result of running queries (multiple queries).
58
+ */
59
+ interface QueriesResult {
60
+ /** The parsed queries */
61
+ queries: Query[];
62
+ /** Formatted query string for display */
63
+ queryString: string;
64
+ /** Matching entries (deduplicated across all queries) */
65
+ entries: QueryEntryInfo[];
66
+ /** Total count (may be more than entries.length if limited) */
67
+ totalCount: number;
68
+ }
69
+ /**
70
+ * Error result when queries reference unknown entities.
71
+ */
72
+ interface QueryValidationError {
73
+ kind: "unknown-entities";
74
+ /** The unknown entity names */
75
+ entities: string[];
76
+ /** Human-readable error message */
77
+ message: string;
78
+ }
79
+ /**
80
+ * Options for running the query command.
81
+ */
82
+ interface RunQueryOptions {
83
+ /** Maximum number of results to return */
84
+ limit?: number;
85
+ /** Include raw source text in results */
86
+ includeRawText?: boolean;
87
+ /** Whether to validate that queried entities exist (default: true) */
88
+ validateEntities?: boolean;
89
+ /**
90
+ * Only return entries since this checkpoint.
91
+ * Format: "ts:2026-01-10T15:00Z" for timestamp-based filtering.
92
+ * Format: "git:abc123" for git-based filtering (requires tracker option).
93
+ */
94
+ since?: string;
95
+ /**
96
+ * Change tracker for git-based filtering.
97
+ * Required when using git checkpoints (git:...).
98
+ */
99
+ tracker?: ChangeTracker;
100
+ }
101
+ /**
102
+ * Error result when a checkpoint is invalid or missing required options.
103
+ */
104
+ interface CheckpointError {
105
+ kind: "invalid-checkpoint";
106
+ /** Human-readable error message */
107
+ message: string;
108
+ }
109
+ /**
110
+ * Run multiple queries on a workspace.
111
+ * Supports comma-separated query syntax like "lore, journal where #career".
112
+ *
113
+ * @param workspace - The workspace to query
114
+ * @param queryString - The query string to parse and execute (may contain multiple queries)
115
+ * @param options - Query options
116
+ * @returns Structured query results, validation error, checkpoint error, or null if query syntax is invalid
117
+ */
118
+ declare function runQueries(workspace: Workspace, queryString: string, options?: RunQueryOptions): Promise<QueriesResult | QueryValidationError | CheckpointError | null>;
119
+ /**
120
+ * Run the query command on a workspace.
121
+ * For backward compatibility, this only supports a single query.
122
+ * Use `runQueries` for multiple queries or comma-separated syntax.
123
+ *
124
+ * @param workspace - The workspace to query
125
+ * @param queryString - The query string to parse and execute
126
+ * @param options - Query options
127
+ * @returns Structured query results, validation error, checkpoint error, or null if query is invalid
128
+ */
129
+ declare function runQuery(workspace: Workspace, queryString: string, options?: RunQueryOptions): Promise<QueryResult | QueryValidationError | CheckpointError | null>;
130
+ /**
131
+ * Type guard to check if a query result is a validation error.
132
+ */
133
+ declare function isQueryValidationError(result: QueryResult | QueriesResult | QueryValidationError | CheckpointError | null): result is QueryValidationError;
134
+ /**
135
+ * Type guard to check if a query result is a checkpoint error.
136
+ */
137
+ declare function isCheckpointError(result: QueryResult | QueriesResult | QueryValidationError | CheckpointError | null): result is CheckpointError;
138
+ /**
139
+ * Type guard to check if a query result is any error type.
140
+ */
141
+ declare function isQueryError(result: QueryResult | QueriesResult | QueryValidationError | CheckpointError | null): result is QueryValidationError | CheckpointError;
142
+ /**
143
+ * Type guard to check if a query result is a successful result (not an error).
144
+ */
145
+ declare function isQuerySuccess(result: QueryResult | QueryValidationError | CheckpointError | null): result is QueryResult;
146
+ /**
147
+ * Type guard to check if a queries result is a successful result (not an error).
148
+ */
149
+ declare function isQueriesSuccess(result: QueriesResult | QueryValidationError | CheckpointError | null): result is QueriesResult;
150
+ //#endregion
151
+ export { CheckpointError, QueriesResult, QueryConditionInfo, QueryEntryInfo, QueryResult, QueryValidationError, RunQueryOptions, isCheckpointError, isQueriesSuccess, isQueryError, isQuerySuccess, isQueryValidationError, parseQueryString, runQueries, runQuery };
152
+ //# sourceMappingURL=query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.d.ts","names":[],"sources":["../../src/commands/query.ts"],"sourcesContent":[],"mappings":";;;;;;AAoFA;AAcA;AAcA;AAWiB,UA7EA,kBAAA,CA8FL;EAMK,IAAA,EAnGT,cAmGwB,CAAA,MAAA,CAAA;EA6CV;EACT,KAAA,CAAA,EAAA,MAAA;EAEF,KAAA,CAAA,EAAA,MAAA;EACA;EAAgB,GAAA,CAAA,EAAA,MAAA;EAAuB;EAA/C,IAAA,CAAA,EAAA,MAAA;;AA2FH;;;AAIW,UAtOM,cAAA,CAsON;EAAc;EAAuB,IAAA,EAAA,MAAA;EAA7C;EAAO,SAAA,EAAA,MAAA;EAyBM;EACN,MAAA,EAAA,MAAA;EAAc;EAAgB,KAAA,EAAA,MAAA;EAAuB;EAClD,MAAA,EAAA,MAAA,GAAA,IAAA;EAAoB;EAOjB,IAAA,EAAA,MAAA,EAAA;EACN;EAAc,SAAA,EAAA,MAAA;EAAgB;EAAuB,OAAA,EAAA,MAAA;EAClD;EAAe,OAAA,CAAA,EAAA,MAAA;AAO5B;;;;AAC+D,UA1P9C,WAAA,CA0P8C;EAClD;EAAuB,KAAA,EAzP3B,KAyP2B;EAAe;EAOnC,WAAA,EAAA,MAAc;EACpB;EAAc,OAAA,EA7Pb,cA6Pa,EAAA;EAAuB;EAClC,UAAA,EAAA,MAAA;;AAOb;;;AACiD,UA9PhC,aAAA,CA8PgC;EACpC;EAAa,OAAA,EA7Pf,KA6Pe,EAAA;;;;WAzPf;;;;;;;UAQM,oBAAA;;;;;;;;;;UAWA,eAAA;;;;;;;;;;;;;;;;;YAiBL;;;;;UAMK,eAAA;;;;;;;;;;;;;;iBA6CK,UAAA,YACT,0CAEF,kBACR,QAAQ,gBAAgB,uBAAuB;;;;;;;;;;;iBA2F5B,QAAA,YACT,0CAEF,kBACR,QAAQ,cAAc,uBAAuB;;;;iBAyBhC,sBAAA,SACN,cAAc,gBAAgB,uBAAuB,mCAClD;;;;iBAOG,iBAAA,SACN,cAAc,gBAAgB,uBAAuB,mCAClD;;;;iBAOG,YAAA,SACN,cAAc,gBAAgB,uBAAuB,mCAClD,uBAAuB;;;;iBAOpB,cAAA,SACN,cAAc,uBAAuB,mCAClC;;;;iBAOG,gBAAA,SACN,gBAAgB,uBAAuB,mCACpC"}
@@ -0,0 +1,151 @@
1
+ import { executeQueries, formatQuery, parseQueryString, validateQueryEntities } from "../services/query.js";
2
+ import { parseCheckpoint } from "../services/change-tracker/change-tracker.js";
3
+ import { formatTimestamp } from "../formatters.js";
4
+ import { findEntryFile, getEntrySourceText } from "../services/synthesis.js";
5
+
6
+ //#region src/commands/query.ts
7
+ /**
8
+ * Convert a timestamp to epoch milliseconds for correct comparison across timezones
9
+ */
10
+ function timestampToEpoch(ts) {
11
+ const isoStr = formatTimestamp(ts);
12
+ return Date.parse(isoStr);
13
+ }
14
+ /**
15
+ * Parse an ISO timestamp string to epoch milliseconds
16
+ */
17
+ function parseTimestampToEpoch(isoStr) {
18
+ return Date.parse(isoStr);
19
+ }
20
+ /**
21
+ * Convert an InstanceEntry to QueryEntryInfo.
22
+ */
23
+ function toQueryEntryInfo(entry, file, workspace, includeRawText) {
24
+ const info = {
25
+ file,
26
+ timestamp: formatTimestamp(entry.header.timestamp),
27
+ entity: entry.header.entity,
28
+ title: entry.header.title.value,
29
+ linkId: entry.header.link?.id ?? null,
30
+ tags: entry.header.tags.map((t) => t.name),
31
+ startLine: entry.location.startPosition.row + 1,
32
+ endLine: entry.location.endPosition.row + 1
33
+ };
34
+ if (includeRawText) {
35
+ const model = workspace.getModel(file);
36
+ if (model) info.rawText = getEntrySourceText(entry, model.source);
37
+ }
38
+ return info;
39
+ }
40
+ /**
41
+ * Run multiple queries on a workspace.
42
+ * Supports comma-separated query syntax like "lore, journal where #career".
43
+ *
44
+ * @param workspace - The workspace to query
45
+ * @param queryString - The query string to parse and execute (may contain multiple queries)
46
+ * @param options - Query options
47
+ * @returns Structured query results, validation error, checkpoint error, or null if query syntax is invalid
48
+ */
49
+ async function runQueries(workspace, queryString, options = {}) {
50
+ const { limit, includeRawText = false, validateEntities = true, since, tracker } = options;
51
+ let sinceMarker = null;
52
+ if (since) {
53
+ sinceMarker = parseCheckpoint(since);
54
+ if (!sinceMarker) return {
55
+ kind: "invalid-checkpoint",
56
+ message: `Invalid checkpoint format: '${since}'. Use 'ts:2026-01-10T15:00Z' for timestamps or 'git:abc123' for git commits.`
57
+ };
58
+ if (sinceMarker.type === "git" && !tracker) return {
59
+ kind: "invalid-checkpoint",
60
+ message: `Git checkpoints require a change tracker. Provide a tracker option or use timestamp checkpoints (ts:...).`
61
+ };
62
+ }
63
+ const queries = parseQueryString(queryString);
64
+ if (!queries) return null;
65
+ if (validateEntities) {
66
+ const unknownEntities = validateQueryEntities(workspace, queries);
67
+ if (unknownEntities.length > 0) return {
68
+ kind: "unknown-entities",
69
+ entities: unknownEntities,
70
+ message: `Unknown entity type${unknownEntities.length > 1 ? "s" : ""}: ${unknownEntities.map((e) => `'${e}'`).join(", ")}. Define ${unknownEntities.length > 1 ? "them" : "it"} using 'define-entity'.`
71
+ };
72
+ }
73
+ let results;
74
+ if (sinceMarker?.type === "git" && tracker) results = (await tracker.getChangedEntries(workspace, queries, sinceMarker)).entries;
75
+ else {
76
+ results = executeQueries(workspace, queries);
77
+ if (sinceMarker?.type === "ts") {
78
+ const sinceEpoch = parseTimestampToEpoch(sinceMarker.value);
79
+ results = results.filter((entry) => {
80
+ return timestampToEpoch(entry.header.timestamp) > sinceEpoch;
81
+ });
82
+ }
83
+ }
84
+ const entries = [];
85
+ const limitedResults = limit && limit > 0 ? results.slice(0, limit) : results;
86
+ for (const entry of limitedResults) {
87
+ const file = findEntryFile(workspace, entry);
88
+ if (file) entries.push(toQueryEntryInfo(entry, file, workspace, includeRawText));
89
+ }
90
+ return {
91
+ queries,
92
+ queryString: queries.map(formatQuery).join(", "),
93
+ entries,
94
+ totalCount: results.length
95
+ };
96
+ }
97
+ /**
98
+ * Run the query command on a workspace.
99
+ * For backward compatibility, this only supports a single query.
100
+ * Use `runQueries` for multiple queries or comma-separated syntax.
101
+ *
102
+ * @param workspace - The workspace to query
103
+ * @param queryString - The query string to parse and execute
104
+ * @param options - Query options
105
+ * @returns Structured query results, validation error, checkpoint error, or null if query is invalid
106
+ */
107
+ async function runQuery(workspace, queryString, options = {}) {
108
+ const result = await runQueries(workspace, queryString, options);
109
+ if (!result) return null;
110
+ if ("kind" in result) return result;
111
+ return {
112
+ query: result.queries[0],
113
+ queryString: result.queryString,
114
+ entries: result.entries,
115
+ totalCount: result.totalCount
116
+ };
117
+ }
118
+ /**
119
+ * Type guard to check if a query result is a validation error.
120
+ */
121
+ function isQueryValidationError(result) {
122
+ return result !== null && "kind" in result && result.kind === "unknown-entities";
123
+ }
124
+ /**
125
+ * Type guard to check if a query result is a checkpoint error.
126
+ */
127
+ function isCheckpointError(result) {
128
+ return result !== null && "kind" in result && result.kind === "invalid-checkpoint";
129
+ }
130
+ /**
131
+ * Type guard to check if a query result is any error type.
132
+ */
133
+ function isQueryError(result) {
134
+ return result !== null && "kind" in result;
135
+ }
136
+ /**
137
+ * Type guard to check if a query result is a successful result (not an error).
138
+ */
139
+ function isQuerySuccess(result) {
140
+ return result !== null && !("kind" in result);
141
+ }
142
+ /**
143
+ * Type guard to check if a queries result is a successful result (not an error).
144
+ */
145
+ function isQueriesSuccess(result) {
146
+ return result !== null && !("kind" in result);
147
+ }
148
+
149
+ //#endregion
150
+ export { isCheckpointError, isQueriesSuccess, isQueryError, isQuerySuccess, isQueryValidationError, parseQueryString, runQueries, runQuery };
151
+ //# sourceMappingURL=query.js.map