citekit 0.1.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 (45) hide show
  1. package/dist/address.d.ts +30 -0
  2. package/dist/address.d.ts.map +1 -0
  3. package/dist/address.js +129 -0
  4. package/dist/address.js.map +1 -0
  5. package/dist/client.d.ts +47 -0
  6. package/dist/client.d.ts.map +1 -0
  7. package/dist/client.js +121 -0
  8. package/dist/client.js.map +1 -0
  9. package/dist/index.d.ts +9 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +9 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/mapper/base.d.ts +5 -0
  14. package/dist/mapper/base.d.ts.map +1 -0
  15. package/dist/mapper/base.js +2 -0
  16. package/dist/mapper/base.js.map +1 -0
  17. package/dist/mapper/gemini.d.ts +13 -0
  18. package/dist/mapper/gemini.d.ts.map +1 -0
  19. package/dist/mapper/gemini.js +169 -0
  20. package/dist/mapper/gemini.js.map +1 -0
  21. package/dist/mcp-server.d.ts +11 -0
  22. package/dist/mcp-server.d.ts.map +1 -0
  23. package/dist/mcp-server.js +124 -0
  24. package/dist/mcp-server.js.map +1 -0
  25. package/dist/models.d.ts +51 -0
  26. package/dist/models.d.ts.map +1 -0
  27. package/dist/models.js +8 -0
  28. package/dist/models.js.map +1 -0
  29. package/dist/resolvers/base.d.ts +5 -0
  30. package/dist/resolvers/base.d.ts.map +1 -0
  31. package/dist/resolvers/base.js +2 -0
  32. package/dist/resolvers/base.js.map +1 -0
  33. package/dist/resolvers/document.d.ts +6 -0
  34. package/dist/resolvers/document.d.ts.map +1 -0
  35. package/dist/resolvers/document.js +32 -0
  36. package/dist/resolvers/document.js.map +1 -0
  37. package/dist/resolvers/image.d.ts +6 -0
  38. package/dist/resolvers/image.d.ts.map +1 -0
  39. package/dist/resolvers/image.js +36 -0
  40. package/dist/resolvers/image.js.map +1 -0
  41. package/dist/resolvers/video.d.ts +6 -0
  42. package/dist/resolvers/video.d.ts.map +1 -0
  43. package/dist/resolvers/video.js +33 -0
  44. package/dist/resolvers/video.js.map +1 -0
  45. package/package.json +47 -0
@@ -0,0 +1,30 @@
1
+ /**
2
+ * CiteKit Address Parser — parse and build URI-style addresses.
3
+ *
4
+ * Formats:
5
+ * doc://resource_id#pages=3-5
6
+ * video://resource_id#t=192-230
7
+ * audio://resource_id#t=60-120
8
+ * image://resource_id#bbox=0.2,0.3,0.8,0.7
9
+ */
10
+ import type { Location } from "./models.js";
11
+ /**
12
+ * Parse a CiteKit address into a resource ID and location.
13
+ *
14
+ * @example
15
+ * parseAddress("doc://calculus_book#pages=12-13")
16
+ * // → { resourceId: "calculus_book", location: { modality: "document", pages: [12, 13] } }
17
+ */
18
+ export declare function parseAddress(address: string): {
19
+ resourceId: string;
20
+ location: Location;
21
+ };
22
+ /**
23
+ * Build a CiteKit address from a resource ID and location.
24
+ *
25
+ * @example
26
+ * buildAddress("book", { modality: "document", pages: [3, 4, 5] })
27
+ * // → "doc://book#pages=3-5"
28
+ */
29
+ export declare function buildAddress(resourceId: string, location: Location): string;
30
+ //# sourceMappingURL=address.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"address.d.ts","sourceRoot":"","sources":["../src/address.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAgB5C;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG;IAC3C,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,QAAQ,CAAC;CACtB,CAqDA;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,MAAM,CA8B3E"}
@@ -0,0 +1,129 @@
1
+ /**
2
+ * CiteKit Address Parser — parse and build URI-style addresses.
3
+ *
4
+ * Formats:
5
+ * doc://resource_id#pages=3-5
6
+ * video://resource_id#t=192-230
7
+ * audio://resource_id#t=60-120
8
+ * image://resource_id#bbox=0.2,0.3,0.8,0.7
9
+ */
10
+ const SCHEME_TO_MODALITY = {
11
+ doc: "document",
12
+ video: "video",
13
+ audio: "audio",
14
+ image: "image",
15
+ };
16
+ const MODALITY_TO_SCHEME = {
17
+ document: "doc",
18
+ video: "video",
19
+ audio: "audio",
20
+ image: "image",
21
+ };
22
+ /**
23
+ * Parse a CiteKit address into a resource ID and location.
24
+ *
25
+ * @example
26
+ * parseAddress("doc://calculus_book#pages=12-13")
27
+ * // → { resourceId: "calculus_book", location: { modality: "document", pages: [12, 13] } }
28
+ */
29
+ export function parseAddress(address) {
30
+ const match = address.match(/^(\w+):\/\/([^#]+)(?:#(.+))?$/);
31
+ if (!match) {
32
+ throw new Error(`Invalid CiteKit address: ${address}`);
33
+ }
34
+ const [, scheme, resourceId, fragment] = match;
35
+ const modality = SCHEME_TO_MODALITY[scheme];
36
+ if (!modality) {
37
+ throw new Error(`Unknown scheme '${scheme}'. Expected: ${Object.keys(SCHEME_TO_MODALITY).join(", ")}`);
38
+ }
39
+ const location = { modality };
40
+ if (fragment) {
41
+ const params = Object.fromEntries(fragment.split("&").map((part) => {
42
+ const [key, value] = part.split("=", 2);
43
+ return [key, value];
44
+ }));
45
+ if (params.pages) {
46
+ if (params.pages.includes("-")) {
47
+ const [start, end] = params.pages.split("-").map(Number);
48
+ location.pages = Array.from({ length: end - start + 1 }, (_, i) => start + i);
49
+ }
50
+ else {
51
+ location.pages = params.pages.split(",").map(Number);
52
+ }
53
+ }
54
+ if (params.t) {
55
+ const [start, end] = params.t.split("-").map(parseTime);
56
+ location.start = start;
57
+ location.end = end;
58
+ }
59
+ if (params.bbox) {
60
+ const parts = params.bbox.split(",").map(Number);
61
+ if (parts.length !== 4) {
62
+ throw new Error(`bbox must have 4 values, got ${parts.length}`);
63
+ }
64
+ location.bbox = parts;
65
+ }
66
+ }
67
+ return { resourceId, location };
68
+ }
69
+ /**
70
+ * Build a CiteKit address from a resource ID and location.
71
+ *
72
+ * @example
73
+ * buildAddress("book", { modality: "document", pages: [3, 4, 5] })
74
+ * // → "doc://book#pages=3-5"
75
+ */
76
+ export function buildAddress(resourceId, location) {
77
+ const scheme = MODALITY_TO_SCHEME[location.modality];
78
+ if (!scheme) {
79
+ throw new Error(`Unknown modality: ${location.modality}`);
80
+ }
81
+ const fragments = [];
82
+ if (location.pages && location.pages.length > 0) {
83
+ const sorted = [...location.pages].sort((a, b) => a - b);
84
+ const isConsecutive = sorted.length === sorted[sorted.length - 1] - sorted[0] + 1;
85
+ if (isConsecutive) {
86
+ fragments.push(`pages=${sorted[0]}-${sorted[sorted.length - 1]}`);
87
+ }
88
+ else {
89
+ fragments.push(`pages=${sorted.join(",")}`);
90
+ }
91
+ }
92
+ if (location.start !== undefined && location.end !== undefined) {
93
+ fragments.push(`t=${formatTime(location.start)}-${formatTime(location.end)}`);
94
+ }
95
+ if (location.bbox) {
96
+ fragments.push(`bbox=${location.bbox.join(",")}`);
97
+ }
98
+ const fragment = fragments.join("&");
99
+ return fragment ? `${scheme}://${resourceId}#${fragment}` : `${scheme}://${resourceId}`;
100
+ }
101
+ // ── Helpers ────────────────────────────────────────────────────────────────
102
+ function parseTime(timeStr) {
103
+ const trimmed = timeStr.trim();
104
+ if (trimmed.includes(":")) {
105
+ const parts = trimmed.split(":").map(Number);
106
+ if (parts.length === 3)
107
+ return parts[0] * 3600 + parts[1] * 60 + parts[2];
108
+ if (parts.length === 2)
109
+ return parts[0] * 60 + parts[1];
110
+ }
111
+ return Number(trimmed);
112
+ }
113
+ function formatTime(seconds) {
114
+ if (Number.isInteger(seconds)) {
115
+ if (seconds >= 3600) {
116
+ const h = Math.floor(seconds / 3600);
117
+ const m = Math.floor((seconds % 3600) / 60);
118
+ const s = seconds % 60;
119
+ return `${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
120
+ }
121
+ if (seconds >= 60) {
122
+ const m = Math.floor(seconds / 60);
123
+ const s = seconds % 60;
124
+ return `${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
125
+ }
126
+ }
127
+ return String(seconds);
128
+ }
129
+ //# sourceMappingURL=address.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"address.js","sourceRoot":"","sources":["../src/address.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,MAAM,kBAAkB,GAAyC;IAC7D,GAAG,EAAE,UAAU;IACf,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;CACjB,CAAC;AAEF,MAAM,kBAAkB,GAA2B;IAC/C,QAAQ,EAAE,KAAK;IACf,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;CACjB,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,OAAe;IAIxC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;IAC7D,IAAI,CAAC,KAAK,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CAAC,4BAA4B,OAAO,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,MAAM,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,GAAG,KAAK,CAAC;IAE/C,MAAM,QAAQ,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC5C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACX,mBAAmB,MAAM,gBAAgB,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACxF,CAAC;IACN,CAAC;IAED,MAAM,QAAQ,GAAa,EAAE,QAAQ,EAAE,CAAC;IAExC,IAAI,QAAQ,EAAE,CAAC;QACX,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAC7B,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YAC7B,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YACxC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACxB,CAAC,CAAC,CACL,CAAC;QAEF,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACf,IAAI,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC7B,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBACzD,QAAQ,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CACvB,EAAE,MAAM,EAAE,GAAG,GAAG,KAAK,GAAG,CAAC,EAAE,EAC3B,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,GAAG,CAAC,CACtB,CAAC;YACN,CAAC;iBAAM,CAAC;gBACJ,QAAQ,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACzD,CAAC;QACL,CAAC;QAED,IAAI,MAAM,CAAC,CAAC,EAAE,CAAC;YACX,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YACxD,QAAQ,CAAC,KAAK,GAAG,KAAK,CAAC;YACvB,QAAQ,CAAC,GAAG,GAAG,GAAG,CAAC;QACvB,CAAC;QAED,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;YACd,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACjD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACrB,MAAM,IAAI,KAAK,CAAC,gCAAgC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;YACpE,CAAC;YACD,QAAQ,CAAC,IAAI,GAAG,KAAyC,CAAC;QAC9D,CAAC;IACL,CAAC;IAED,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC;AACpC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,UAAkB,EAAE,QAAkB;IAC/D,MAAM,MAAM,GAAG,kBAAkB,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrD,IAAI,CAAC,MAAM,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,qBAAqB,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,SAAS,GAAa,EAAE,CAAC;IAE/B,IAAI,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9C,MAAM,MAAM,GAAG,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACzD,MAAM,aAAa,GACf,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAEhE,IAAI,aAAa,EAAE,CAAC;YAChB,SAAS,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;QACtE,CAAC;aAAM,CAAC;YACJ,SAAS,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChD,CAAC;IACL,CAAC;IAED,IAAI,QAAQ,CAAC,KAAK,KAAK,SAAS,IAAI,QAAQ,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;QAC7D,SAAS,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClF,CAAC;IAED,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;QAChB,SAAS,CAAC,IAAI,CAAC,QAAQ,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACtD,CAAC;IAED,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACrC,OAAO,QAAQ,CAAC,CAAC,CAAC,GAAG,MAAM,MAAM,UAAU,IAAI,QAAQ,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM,MAAM,UAAU,EAAE,CAAC;AAC5F,CAAC;AAED,8EAA8E;AAE9E,SAAS,SAAS,CAAC,OAAe;IAC9B,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAC/B,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC7C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAC1E,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC;AAC3B,CAAC;AAED,SAAS,UAAU,CAAC,OAAe;IAC/B,IAAI,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;YAClB,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;YACrC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;YAC5C,MAAM,CAAC,GAAG,OAAO,GAAG,EAAE,CAAC;YACvB,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;QACvG,CAAC;QACD,IAAI,OAAO,IAAI,EAAE,EAAE,CAAC;YAChB,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;YACnC,MAAM,CAAC,GAAG,OAAO,GAAG,EAAE,CAAC;YACvB,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;QACzE,CAAC;IACL,CAAC;IACD,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * CiteKit JavaScript Client.
3
+ *
4
+ * Reads/writes resource map JSON files locally and calls the Python
5
+ * resolver backend for resolution (since resolvers are Python-based).
6
+ */
7
+ import type { ResourceMap, ResolvedEvidence } from "./models.js";
8
+ export interface CiteKitClientOptions {
9
+ /** Directory where resource maps are stored. Default: ".resource_maps" */
10
+ storageDir?: string;
11
+ /** Directory for resolved output files. Default: ".citekit_output" */
12
+ outputDir?: string;
13
+ /** Gemini API Key (can also be set via env GEMINI_API_KEY) */
14
+ apiKey?: string;
15
+ /** Gemini Model (default: "gemini-2.0-flash") */
16
+ model?: string;
17
+ }
18
+ export declare class CiteKitClient {
19
+ private storageDir;
20
+ private outputDir;
21
+ private mapper;
22
+ private resolvers;
23
+ constructor(options?: CiteKitClientOptions);
24
+ /**
25
+ * Load a previously generated map from local storage.
26
+ */
27
+ getMap(resourceId: string): ResourceMap;
28
+ /**
29
+ * List all available resource map IDs.
30
+ */
31
+ listMaps(): string[];
32
+ /**
33
+ * Get the map as a plain object (for JSON serialization / MCP responses).
34
+ */
35
+ getStructure(resourceId: string): ResourceMap;
36
+ /**
37
+ * Ingest a resource using the configured mapper.
38
+ */
39
+ ingest(resourcePath: string, resourceType: string, options?: {
40
+ resourceId?: string;
41
+ }): Promise<ResourceMap>;
42
+ /**
43
+ * Resolve a node to evidence using the appropriate resolver.
44
+ */
45
+ resolve(resourceId: string, nodeId: string): Promise<ResolvedEvidence>;
46
+ }
47
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAQ,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAcvE,MAAM,WAAW,oBAAoB;IACjC,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,aAAa;IACtB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,SAAS,CAA2B;gBAEhC,OAAO,GAAE,oBAAyB;IA4C9C;;OAEG;IACH,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,WAAW;IAUvC;;OAEG;IACH,QAAQ,IAAI,MAAM,EAAE;IAOpB;;OAEG;IACH,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,WAAW;IAM7C;;OAEG;IACG,MAAM,CACR,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GAClC,OAAO,CAAC,WAAW,CAAC;IAgBvB;;OAEG;IACG,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;CA6B/E"}
package/dist/client.js ADDED
@@ -0,0 +1,121 @@
1
+ /**
2
+ * CiteKit JavaScript Client.
3
+ *
4
+ * Reads/writes resource map JSON files locally and calls the Python
5
+ * resolver backend for resolution (since resolvers are Python-based).
6
+ */
7
+ import { readFileSync, writeFileSync, readdirSync, existsSync, mkdirSync } from "node:fs";
8
+ import { join } from "node:path";
9
+ // ── Imported Mappers & Resolvers ────────────────────────────────────────
10
+ import { GeminiMapper } from "./mapper/gemini.js";
11
+ import { DocumentResolver } from "./resolvers/document.js";
12
+ import { VideoResolver } from "./resolvers/video.js";
13
+ import { ImageResolver } from "./resolvers/image.js";
14
+ export class CiteKitClient {
15
+ storageDir;
16
+ outputDir;
17
+ mapper;
18
+ resolvers;
19
+ constructor(options = {}) {
20
+ this.storageDir = options.storageDir ?? ".resource_maps";
21
+ this.outputDir = options.outputDir ?? ".citekit_output";
22
+ const apiKey = options.apiKey ?? process.env.GEMINI_API_KEY;
23
+ if (!apiKey) {
24
+ // We allow client init without key, but ingest will fail if we don't have it eventually.
25
+ // For now, let's just warn or let the mapper throw.
26
+ // Actually, the mapper constructor needs it.
27
+ // If unavailable, we can delay mapper init? Or throw?
28
+ // Let's assume user must provide it if they want to ingest.
29
+ // But if they only want resolve(), they might not need it?
30
+ // Resolution logic doesn't need Gemini.
31
+ // So we should lazily init mapper or allow null.
32
+ }
33
+ // Initialize mapper
34
+ // Note: For this MVP port, we assume GeminiMapper is the default.
35
+ if (apiKey) {
36
+ this.mapper = new GeminiMapper(apiKey, options.model);
37
+ }
38
+ else {
39
+ // Mock mapper that throws
40
+ this.mapper = {
41
+ generateMap: async () => { throw new Error("GEMINI_API_KEY required for ingestion."); }
42
+ };
43
+ }
44
+ // Initialize resolvers
45
+ this.resolvers = {
46
+ "document": new DocumentResolver(),
47
+ "video": new VideoResolver(),
48
+ "image": new ImageResolver(),
49
+ // Audio uses VideoResolver logic mostly, but we can reuse or just alias?
50
+ // "audio" -> Generic A/V resolver?
51
+ // "audio": new VideoResolver(), // ffmpeg handles both
52
+ };
53
+ // Ensure directories exist
54
+ if (!existsSync(this.storageDir))
55
+ mkdirSync(this.storageDir, { recursive: true });
56
+ if (!existsSync(this.outputDir))
57
+ mkdirSync(this.outputDir, { recursive: true });
58
+ }
59
+ // ── Map access ──────────────────────────────────────────────────────────
60
+ /**
61
+ * Load a previously generated map from local storage.
62
+ */
63
+ getMap(resourceId) {
64
+ const mapPath = join(this.storageDir, `${resourceId}.json`);
65
+ if (!existsSync(mapPath)) {
66
+ throw new Error(`No map found for resource '${resourceId}'. Expected at: ${mapPath}`);
67
+ }
68
+ return JSON.parse(readFileSync(mapPath, "utf-8"));
69
+ }
70
+ /**
71
+ * List all available resource map IDs.
72
+ */
73
+ listMaps() {
74
+ if (!existsSync(this.storageDir))
75
+ return [];
76
+ return readdirSync(this.storageDir)
77
+ .filter((f) => f.endsWith(".json"))
78
+ .map((f) => f.replace(/\.json$/, ""));
79
+ }
80
+ /**
81
+ * Get the map as a plain object (for JSON serialization / MCP responses).
82
+ */
83
+ getStructure(resourceId) {
84
+ return this.getMap(resourceId);
85
+ }
86
+ // ── Ingestion ───────────────────────────────────────────────────────────
87
+ /**
88
+ * Ingest a resource using the configured mapper.
89
+ */
90
+ async ingest(resourcePath, resourceType, options) {
91
+ const map = await this.mapper.generateMap(resourcePath, resourceType, options?.resourceId);
92
+ // Save map
93
+ const mapPath = join(this.storageDir, `${map.resource_id}.json`);
94
+ writeFileSync(mapPath, JSON.stringify(map, null, 2));
95
+ return map;
96
+ }
97
+ // ── Resolution ──────────────────────────────────────────────────────────
98
+ /**
99
+ * Resolve a node to evidence using the appropriate resolver.
100
+ */
101
+ async resolve(resourceId, nodeId) {
102
+ const map = this.getMap(resourceId);
103
+ const node = map.nodes.find((n) => n.id === nodeId);
104
+ if (!node) {
105
+ throw new Error(`Node '${nodeId}' not found in map '${resourceId}'`);
106
+ }
107
+ const type = map.type; // document, video, etc.
108
+ const resolver = this.resolvers[type];
109
+ if (!resolver) {
110
+ // Check if we can fallback?
111
+ // For now, if no resolver, failure.
112
+ // Maybe handle "audio" with video resolver?
113
+ if (type === "audio" && this.resolvers["video"]) {
114
+ return this.resolvers["video"].resolve(resourceId, nodeId, map.source_path, node.location, this.outputDir);
115
+ }
116
+ throw new Error(`No resolver implementation for resource type '${type}'`);
117
+ }
118
+ return resolver.resolve(resourceId, nodeId, map.source_path, node.location, this.outputDir);
119
+ }
120
+ }
121
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export * from "./client.js";
2
+ export * from "./models.js";
3
+ export * from "./mapper/base.js";
4
+ export * from "./mapper/gemini.js";
5
+ export * from "./resolvers/base.js";
6
+ export * from "./resolvers/document.js";
7
+ export * from "./resolvers/video.js";
8
+ export * from "./resolvers/image.js";
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ export * from "./client.js";
2
+ export * from "./models.js";
3
+ export * from "./mapper/base.js";
4
+ export * from "./mapper/gemini.js";
5
+ export * from "./resolvers/base.js";
6
+ export * from "./resolvers/document.js";
7
+ export * from "./resolvers/video.js";
8
+ export * from "./resolvers/image.js";
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { ResourceMap } from "../models.js";
2
+ export interface MapperProvider {
3
+ generateMap(resourcePath: string, resourceType: string, resourceId?: string): Promise<ResourceMap>;
4
+ }
5
+ //# sourceMappingURL=base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/mapper/base.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,WAAW,cAAc;IAC3B,WAAW,CACP,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,WAAW,CAAC,CAAC;CAC3B"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/mapper/base.ts"],"names":[],"mappings":""}
@@ -0,0 +1,13 @@
1
+ import { MapperProvider } from "./base.js";
2
+ import type { ResourceMap } from "../models.js";
3
+ export declare class GeminiMapper implements MapperProvider {
4
+ private genAI;
5
+ private model;
6
+ constructor(apiKey: string, modelName?: string);
7
+ generateMap(resourcePath: string, resourceType: string, resourceId?: string): Promise<ResourceMap>;
8
+ private mapDocument;
9
+ private mapVideo;
10
+ private callGemini;
11
+ private parseNodesResponse;
12
+ }
13
+ //# sourceMappingURL=gemini.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../src/mapper/gemini.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAkB,MAAM,cAAc,CAAC;AAkDhE,qBAAa,YAAa,YAAW,cAAc;IAC/C,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,KAAK,CAAM;gBAEP,MAAM,EAAE,MAAM,EAAE,SAAS,GAAE,MAA2B;IAK5D,WAAW,CACb,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,WAAW,CAAC;YA2BT,WAAW;YA2BX,QAAQ;YAkBR,UAAU;IAOxB,OAAO,CAAC,kBAAkB;CA+C7B"}
@@ -0,0 +1,169 @@
1
+ import { GoogleGenerativeAI } from "@google/generative-ai";
2
+ import { readFileSync, existsSync } from "node:fs";
3
+ import { basename, extname } from "node:path";
4
+ import { createRequire } from "node:module";
5
+ // pdf-parse is a CJS module, best imported via require in ESM
6
+ const require = createRequire(import.meta.url);
7
+ const pdf = require("pdf-parse");
8
+ // ── Prompt Templates ────────────────────────────────────────────────────────
9
+ const DOCUMENT_PROMPT = `\
10
+ You are a structure analyzer. Given the text content of a document, produce a JSON map \
11
+ that identifies the key concepts, sections, definitions, examples, and diagrams.
12
+
13
+ Each node must have:
14
+ - "id": a dot-separated identifier (e.g. "chapter1.derivatives.definition")
15
+ - "title": a short human-readable title
16
+ - "type": one of "section", "definition", "example", "explanation", "diagram", "theorem", "exercise", "summary"
17
+ - "location": { "modality": "document", "pages": [list of 1-indexed page numbers] }
18
+ - "summary": a 1-2 sentence summary of what this section covers
19
+
20
+ Rules:
21
+ - Be thorough — capture ALL distinct concepts, not just top-level sections.
22
+ - Page numbers are 1-indexed.
23
+ - Keep summaries concise but informative.
24
+ - IDs should be hierarchical and descriptive.
25
+
26
+ Return ONLY a JSON array of nodes. No markdown, no explanation.
27
+
28
+ Document title: {title}
29
+
30
+ --- DOCUMENT TEXT (page-delimited) ---
31
+ {text}
32
+ `;
33
+ const VIDEO_PROMPT = `\
34
+ You are a video structure analyzer. Given metadata about a video, identify key segments.
35
+
36
+ Video duration: {duration} seconds
37
+ Filename: {filename}
38
+
39
+ Each node must have:
40
+ - "id": a descriptive dot-separated identifier
41
+ - "title": a short human-readable title
42
+ - "type": one of "introduction", "explanation", "example", "demonstration", "summary", "transition"
43
+ - "location": { "modality": "video", "start": <seconds>, "end": <seconds> }
44
+ - "summary": brief description of what this segment covers
45
+
46
+ Rules:
47
+ - Segments should be meaningful chunks, not arbitrary splits.
48
+ - start/end are in seconds.
49
+ - Cover the entire video duration.
50
+
51
+ Return ONLY a JSON array of nodes. No markdown, no explanation.
52
+ `;
53
+ export class GeminiMapper {
54
+ genAI;
55
+ model;
56
+ constructor(apiKey, modelName = "gemini-2.0-flash") {
57
+ this.genAI = new GoogleGenerativeAI(apiKey);
58
+ this.model = this.genAI.getGenerativeModel({ model: modelName });
59
+ }
60
+ async generateMap(resourcePath, resourceType, resourceId) {
61
+ if (!existsSync(resourcePath)) {
62
+ throw new Error(`Resource not found: ${resourcePath}`);
63
+ }
64
+ const id = resourceId || basename(resourcePath, extname(resourcePath));
65
+ let nodes = [];
66
+ if (resourceType === "document") {
67
+ nodes = await this.mapDocument(resourcePath);
68
+ }
69
+ else if (resourceType === "video") {
70
+ nodes = await this.mapVideo(resourcePath);
71
+ }
72
+ else {
73
+ // Fallback or TODO for image/audio
74
+ throw new Error(`Resource type '${resourceType}' not fully implemented in JS port yet.`);
75
+ }
76
+ return {
77
+ resource_id: id,
78
+ type: resourceType,
79
+ title: id.replace(/[_-]/g, " ").replace(/\b\w/g, c => c.toUpperCase()),
80
+ source_path: resourcePath,
81
+ nodes: nodes,
82
+ created_at: new Date().toISOString()
83
+ };
84
+ }
85
+ async mapDocument(path) {
86
+ const dataBuffer = readFileSync(path);
87
+ // Use pdf-parse to extract text. Note: pdf-parse merges pages by default.
88
+ // To get basic page info we might need a custom render callback, but
89
+ // for MVP we'll just extract all text and let Gemini infer or use a simple split.
90
+ // Actually, pdf-parse provides page count but text is merged.
91
+ // We can use a pager render callback to insert delimiters.
92
+ const options = {
93
+ pagerender: (pageData) => {
94
+ return `--- PAGE ${pageData.pageIndex + 1} ---\n` +
95
+ pageData.getTextContent().items.map((i) => i.str).join(" ");
96
+ }
97
+ };
98
+ // TypeScript workaround for pdf-parse types if needed, but import * as pdf works usually.
99
+ // @ts-ignore
100
+ const data = await pdf(dataBuffer, options);
101
+ const prompt = DOCUMENT_PROMPT
102
+ .replace("{title}", basename(path))
103
+ .replace("{text}", data.text);
104
+ return this.callGemini(prompt);
105
+ }
106
+ async mapVideo(path) {
107
+ // We need duration. We can use fluent-ffmpeg to probe.
108
+ const { ffprobe } = await import("fluent-ffmpeg");
109
+ const duration = await new Promise((resolve, reject) => {
110
+ ffprobe(path, (err, metadata) => {
111
+ if (err)
112
+ return reject(err);
113
+ resolve(metadata.format.duration || 0);
114
+ });
115
+ });
116
+ const prompt = VIDEO_PROMPT
117
+ .replace("{duration}", duration.toString())
118
+ .replace("{filename}", basename(path));
119
+ return this.callGemini(prompt);
120
+ }
121
+ async callGemini(prompt) {
122
+ const result = await this.model.generateContent(prompt);
123
+ const response = await result.response;
124
+ const text = response.text();
125
+ return this.parseNodesResponse(text);
126
+ }
127
+ parseNodesResponse(text) {
128
+ let cleaned = text.trim();
129
+ // Regex to extract JSON array [ ... ]
130
+ const match = cleaned.match(/\[.*\]/s);
131
+ if (match) {
132
+ cleaned = match[0];
133
+ }
134
+ // Remove markdown fences
135
+ if (cleaned.startsWith("```")) {
136
+ cleaned = cleaned.replace(/^```[a-z]*\n/, "").replace(/\n```$/, "");
137
+ }
138
+ // Fix trailing commas: remove comma before ] or }
139
+ cleaned = cleaned.replace(/,\s*([\]}])/g, "$1");
140
+ // Fix object comma separation: } { -> }, {
141
+ cleaned = cleaned.replace(/}\s*{/g, "}, {");
142
+ // Attempt verify/repair brackets
143
+ const openBrackets = (cleaned.match(/\[/g) || []).length - (cleaned.match(/\]/g) || []).length;
144
+ const openBraces = (cleaned.match(/{/g) || []).length - (cleaned.match(/}/g) || []).length;
145
+ if (openBraces > 0) {
146
+ cleaned = cleaned.replace(/,+$/, "");
147
+ cleaned += "}".repeat(openBraces);
148
+ }
149
+ if (openBrackets > 0) {
150
+ cleaned = cleaned.replace(/,+$/, "");
151
+ cleaned += "]".repeat(openBrackets);
152
+ }
153
+ try {
154
+ const rawNodes = JSON.parse(cleaned);
155
+ return rawNodes.map((raw) => ({
156
+ id: raw.id,
157
+ title: raw.title,
158
+ type: raw.type || "section",
159
+ location: raw.location,
160
+ summary: raw.summary
161
+ }));
162
+ }
163
+ catch (e) {
164
+ console.error("DEBUG: Failed JSON parse. Raw:", cleaned);
165
+ throw new Error(`Failed to parse Gemini JSON: ${e}`);
166
+ }
167
+ }
168
+ }
169
+ //# sourceMappingURL=gemini.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/mapper/gemini.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * CiteKit MCP Server (JavaScript/TypeScript).
3
+ *
4
+ * Exposes listResources, getStructure, and resolve tools via MCP.
5
+ * Reads maps from local JSON and delegates resolution to the Python SDK.
6
+ *
7
+ * Run with:
8
+ * npx tsx src/mcp-server.ts
9
+ */
10
+ export {};
11
+ //# sourceMappingURL=mcp-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
@@ -0,0 +1,124 @@
1
+ /**
2
+ * CiteKit MCP Server (JavaScript/TypeScript).
3
+ *
4
+ * Exposes listResources, getStructure, and resolve tools via MCP.
5
+ * Reads maps from local JSON and delegates resolution to the Python SDK.
6
+ *
7
+ * Run with:
8
+ * npx tsx src/mcp-server.ts
9
+ */
10
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
11
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
12
+ import { ListToolsRequestSchema, CallToolRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
13
+ import { CiteKitClient } from "./client.js";
14
+ function createServer(storageDir, outputDir) {
15
+ const server = new Server({ name: "citekit", version: "0.1.0" }, { capabilities: { tools: {} } });
16
+ const client = new CiteKitClient({ storageDir, outputDir });
17
+ // ── List tools ──────────────────────────────────────────────────────────
18
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
19
+ tools: [
20
+ {
21
+ name: "listResources",
22
+ description: "List all available resource map IDs that have been ingested.",
23
+ inputSchema: { type: "object", properties: {} },
24
+ },
25
+ {
26
+ name: "getStructure",
27
+ description: "Get the structured map of a resource. Returns nodes with concept/section info and physical locations.",
28
+ inputSchema: {
29
+ type: "object",
30
+ properties: {
31
+ resource_id: {
32
+ type: "string",
33
+ description: "The resource ID to get the structure for.",
34
+ },
35
+ },
36
+ required: ["resource_id"],
37
+ },
38
+ },
39
+ {
40
+ name: "resolve",
41
+ description: "Resolve a node into extracted evidence (mini-PDF, clip, or crop).",
42
+ inputSchema: {
43
+ type: "object",
44
+ properties: {
45
+ resource_id: {
46
+ type: "string",
47
+ description: "The resource ID.",
48
+ },
49
+ node_id: {
50
+ type: "string",
51
+ description: "The node ID to resolve.",
52
+ },
53
+ },
54
+ required: ["resource_id", "node_id"],
55
+ },
56
+ },
57
+ ],
58
+ }));
59
+ // ── Call tools ──────────────────────────────────────────────────────────
60
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
61
+ const { name, arguments: args } = request.params;
62
+ try {
63
+ if (name === "listResources") {
64
+ const resources = client.listMaps();
65
+ return {
66
+ content: [
67
+ {
68
+ type: "text",
69
+ text: JSON.stringify({ resources }, null, 2),
70
+ },
71
+ ],
72
+ };
73
+ }
74
+ if (name === "getStructure") {
75
+ const resourceId = args.resource_id;
76
+ const structure = client.getStructure(resourceId);
77
+ return {
78
+ content: [
79
+ {
80
+ type: "text",
81
+ text: JSON.stringify(structure, null, 2),
82
+ },
83
+ ],
84
+ };
85
+ }
86
+ if (name === "resolve") {
87
+ const { resource_id, node_id } = args;
88
+ const evidence = client.resolve(resource_id, node_id);
89
+ return {
90
+ content: [
91
+ {
92
+ type: "text",
93
+ text: JSON.stringify(evidence, null, 2),
94
+ },
95
+ ],
96
+ };
97
+ }
98
+ return {
99
+ content: [{ type: "text", text: `Unknown tool: ${name}` }],
100
+ isError: true,
101
+ };
102
+ }
103
+ catch (error) {
104
+ return {
105
+ content: [
106
+ {
107
+ type: "text",
108
+ text: `Error: ${error instanceof Error ? error.message : String(error)}`,
109
+ },
110
+ ],
111
+ isError: true,
112
+ };
113
+ }
114
+ });
115
+ return server;
116
+ }
117
+ // ── Main ────────────────────────────────────────────────────────────────────
118
+ async function main() {
119
+ const server = createServer();
120
+ const transport = new StdioServerTransport();
121
+ await server.connect(transport);
122
+ }
123
+ main().catch(console.error);
124
+ //# sourceMappingURL=mcp-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACH,sBAAsB,EACtB,qBAAqB,GACxB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,SAAS,YAAY,CAAC,UAAmB,EAAE,SAAkB;IACzD,MAAM,MAAM,GAAG,IAAI,MAAM,CACrB,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,EACrC,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,CAClC,CAAC;IAEF,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC,CAAC;IAE5D,2EAA2E;IAE3E,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;QAC1D,KAAK,EAAE;YACH;gBACI,IAAI,EAAE,eAAe;gBACrB,WAAW,EACP,8DAA8D;gBAClE,WAAW,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE,UAAU,EAAE,EAAE,EAAE;aAC3D;YACD;gBACI,IAAI,EAAE,cAAc;gBACpB,WAAW,EACP,uGAAuG;gBAC3G,WAAW,EAAE;oBACT,IAAI,EAAE,QAAiB;oBACvB,UAAU,EAAE;wBACR,WAAW,EAAE;4BACT,IAAI,EAAE,QAAQ;4BACd,WAAW,EAAE,2CAA2C;yBAC3D;qBACJ;oBACD,QAAQ,EAAE,CAAC,aAAa,CAAC;iBAC5B;aACJ;YACD;gBACI,IAAI,EAAE,SAAS;gBACf,WAAW,EACP,mEAAmE;gBACvE,WAAW,EAAE;oBACT,IAAI,EAAE,QAAiB;oBACvB,UAAU,EAAE;wBACR,WAAW,EAAE;4BACT,IAAI,EAAE,QAAQ;4BACd,WAAW,EAAE,kBAAkB;yBAClC;wBACD,OAAO,EAAE;4BACL,IAAI,EAAE,QAAQ;4BACd,WAAW,EAAE,yBAAyB;yBACzC;qBACJ;oBACD,QAAQ,EAAE,CAAC,aAAa,EAAE,SAAS,CAAC;iBACvC;aACJ;SACJ;KACJ,CAAC,CAAC,CAAC;IAEJ,2EAA2E;IAE3E,MAAM,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QAC9D,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;QAEjD,IAAI,CAAC;YACD,IAAI,IAAI,KAAK,eAAe,EAAE,CAAC;gBAC3B,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;gBACpC,OAAO;oBACH,OAAO,EAAE;wBACL;4BACI,IAAI,EAAE,MAAe;4BACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;yBAC/C;qBACJ;iBACJ,CAAC;YACN,CAAC;YAED,IAAI,IAAI,KAAK,cAAc,EAAE,CAAC;gBAC1B,MAAM,UAAU,GAAI,IAA+B,CAAC,WAAW,CAAC;gBAChE,MAAM,SAAS,GAAG,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;gBAClD,OAAO;oBACH,OAAO,EAAE;wBACL;4BACI,IAAI,EAAE,MAAe;4BACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;yBAC3C;qBACJ;iBACJ,CAAC;YACN,CAAC;YAED,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACrB,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,IAA8B,CAAC;gBAChE,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;gBACtD,OAAO;oBACH,OAAO,EAAE;wBACL;4BACI,IAAI,EAAE,MAAe;4BACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;yBAC1C;qBACJ;iBACJ,CAAC;YACN,CAAC;YAED,OAAO;gBACH,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,iBAAiB,IAAI,EAAE,EAAE,CAAC;gBACnE,OAAO,EAAE,IAAI;aAChB,CAAC;QACN,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO;gBACH,OAAO,EAAE;oBACL;wBACI,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;qBAC3E;iBACJ;gBACD,OAAO,EAAE,IAAI;aAChB,CAAC;QACN,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,+EAA+E;AAE/E,KAAK,UAAU,IAAI;IACf,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AACpC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * CiteKit — TypeScript interfaces and types.
3
+ *
4
+ * These mirror the Python SDK's Pydantic models exactly,
5
+ * so maps generated by either SDK are cross-compatible.
6
+ */
7
+ /** Physical location within a resource. */
8
+ export interface Location {
9
+ modality: "document" | "video" | "audio" | "image";
10
+ /** Document: 1-indexed page numbers. */
11
+ pages?: number[];
12
+ /** Video/Audio: start time in seconds. */
13
+ start?: number;
14
+ /** Video/Audio: end time in seconds. */
15
+ end?: number;
16
+ /** Image: normalized bounding box [x1, y1, x2, y2] (0.0–1.0). */
17
+ bbox?: [number, number, number, number];
18
+ }
19
+ /** A concept or section within a resource. */
20
+ export interface Node {
21
+ /** Dot-separated identifier, e.g. "derivatives.definition". */
22
+ id: string;
23
+ /** Human-readable title. */
24
+ title?: string;
25
+ /** Node type: definition, example, explanation, diagram, etc. */
26
+ type: string;
27
+ /** Where this node lives in the resource. */
28
+ location: Location;
29
+ /** 1-2 sentence summary. */
30
+ summary?: string;
31
+ }
32
+ /** Structured map of a resource — the first output of ingestion. */
33
+ export interface ResourceMap {
34
+ resource_id: string;
35
+ type: "document" | "video" | "audio" | "image";
36
+ title: string;
37
+ source_path: string;
38
+ nodes: Node[];
39
+ created_at: string;
40
+ }
41
+ /** Result of resolving a node. */
42
+ export interface ResolvedEvidence {
43
+ /** Path to the extracted file (mini-PDF, clip, crop, etc.) */
44
+ output_path: string;
45
+ modality: string;
46
+ /** URI-style address, e.g. doc://book#pages=12-13 */
47
+ address: string;
48
+ node: Node;
49
+ resource_id: string;
50
+ }
51
+ //# sourceMappingURL=models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,2CAA2C;AAC3C,MAAM,WAAW,QAAQ;IACrB,QAAQ,EAAE,UAAU,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;IAEnD,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IAEjB,0CAA0C;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,wCAAwC;IACxC,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb,iEAAiE;IACjE,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;CAC3C;AAED,8CAA8C;AAC9C,MAAM,WAAW,IAAI;IACjB,+DAA+D;IAC/D,EAAE,EAAE,MAAM,CAAC;IAEX,4BAA4B;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,iEAAiE;IACjE,IAAI,EAAE,MAAM,CAAC;IAEb,6CAA6C;IAC7C,QAAQ,EAAE,QAAQ,CAAC;IAEnB,4BAA4B;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,oEAAoE;AACpE,MAAM,WAAW,WAAW;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,UAAU,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,kCAAkC;AAClC,MAAM,WAAW,gBAAgB;IAC7B,8DAA8D;IAC9D,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,IAAI,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;CACvB"}
package/dist/models.js ADDED
@@ -0,0 +1,8 @@
1
+ /**
2
+ * CiteKit — TypeScript interfaces and types.
3
+ *
4
+ * These mirror the Python SDK's Pydantic models exactly,
5
+ * so maps generated by either SDK are cross-compatible.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,5 @@
1
+ import type { ResolvedEvidence } from "../models.js";
2
+ export interface Resolver {
3
+ resolve(resourceId: string, nodeId: string, sourcePath: string, location: any, outputDir: string): Promise<ResolvedEvidence>;
4
+ }
5
+ //# sourceMappingURL=base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/resolvers/base.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD,MAAM,WAAW,QAAQ;IACrB,OAAO,CACH,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,GAAG,EACb,SAAS,EAAE,MAAM,GAClB,OAAO,CAAC,gBAAgB,CAAC,CAAC;CAChC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/resolvers/base.ts"],"names":[],"mappings":""}
@@ -0,0 +1,6 @@
1
+ import { Resolver } from "./base.js";
2
+ import type { ResolvedEvidence } from "../models.js";
3
+ export declare class DocumentResolver implements Resolver {
4
+ resolve(resourceId: string, nodeId: string, sourcePath: string, location: any, outputDir: string): Promise<ResolvedEvidence>;
5
+ }
6
+ //# sourceMappingURL=document.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../../src/resolvers/document.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD,qBAAa,gBAAiB,YAAW,QAAQ;IACvC,OAAO,CACT,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,GAAG,EACb,SAAS,EAAE,MAAM,GAClB,OAAO,CAAC,gBAAgB,CAAC;CAiC/B"}
@@ -0,0 +1,32 @@
1
+ import { PDFDocument } from "pdf-lib";
2
+ import { readFileSync, writeFileSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ export class DocumentResolver {
5
+ async resolve(resourceId, nodeId, sourcePath, location, outputDir) {
6
+ if (!location.pages || location.pages.length === 0) {
7
+ throw new Error(`Node ${nodeId} has no pages specified.`);
8
+ }
9
+ const pdfBytes = readFileSync(sourcePath);
10
+ const srcDoc = await PDFDocument.load(pdfBytes);
11
+ const newDoc = await PDFDocument.create();
12
+ // Pages are 1-indexed in our map, but 0-indexed in pdf-lib
13
+ const pagesToCopy = location.pages.map((p) => p - 1);
14
+ // Copy pages
15
+ const copiedPages = await newDoc.copyPages(srcDoc, pagesToCopy);
16
+ copiedPages.forEach((page) => newDoc.addPage(page));
17
+ const outputBytes = await newDoc.save();
18
+ // Generate filename similar to Python SDK: {resource}_{pages}_{p1}_{p2}.pdf
19
+ const pageStr = location.pages.join("_");
20
+ const filename = `${resourceId}_pages_${pageStr}.pdf`;
21
+ const outputPath = join(outputDir, filename);
22
+ writeFileSync(outputPath, outputBytes);
23
+ return {
24
+ output_path: outputPath,
25
+ modality: "document",
26
+ address: `doc://${resourceId}#pages=${location.pages[0]}-${location.pages[location.pages.length - 1]}`,
27
+ node: { id: nodeId, location: location }, // Only minimal node needed? Or fetch full?
28
+ resource_id: resourceId
29
+ };
30
+ }
31
+ }
32
+ //# sourceMappingURL=document.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document.js","sourceRoot":"","sources":["../../src/resolvers/document.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAIjC,MAAM,OAAO,gBAAgB;IACzB,KAAK,CAAC,OAAO,CACT,UAAkB,EAClB,MAAc,EACd,UAAkB,EAClB,QAAa,EACb,SAAiB;QAEjB,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjD,MAAM,IAAI,KAAK,CAAC,QAAQ,MAAM,0BAA0B,CAAC,CAAC;QAC9D,CAAC;QAED,MAAM,QAAQ,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC;QAC1C,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAChD,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,MAAM,EAAE,CAAC;QAE1C,2DAA2D;QAC3D,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAE7D,aAAa;QACb,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAChE,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAEpD,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QAExC,4EAA4E;QAC5E,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACzC,MAAM,QAAQ,GAAG,GAAG,UAAU,UAAU,OAAO,MAAM,CAAC;QACtD,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAE7C,aAAa,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;QAEvC,OAAO;YACH,WAAW,EAAE,UAAU;YACvB,QAAQ,EAAE,UAAU;YACpB,OAAO,EAAE,SAAS,UAAU,UAAU,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE;YACtG,IAAI,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAS,EAAE,2CAA2C;YAC5F,WAAW,EAAE,UAAU;SAC1B,CAAC;IACN,CAAC;CACJ"}
@@ -0,0 +1,6 @@
1
+ import { Resolver } from "./base.js";
2
+ import type { ResolvedEvidence } from "../models.js";
3
+ export declare class ImageResolver implements Resolver {
4
+ resolve(resourceId: string, nodeId: string, sourcePath: string, location: any, outputDir: string): Promise<ResolvedEvidence>;
5
+ }
6
+ //# sourceMappingURL=image.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../src/resolvers/image.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD,qBAAa,aAAc,YAAW,QAAQ;IACpC,OAAO,CACT,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,GAAG,EACb,SAAS,EAAE,MAAM,GAClB,OAAO,CAAC,gBAAgB,CAAC;CAuC/B"}
@@ -0,0 +1,36 @@
1
+ import sharp from "sharp";
2
+ import { join } from "node:path";
3
+ export class ImageResolver {
4
+ async resolve(resourceId, nodeId, sourcePath, location, outputDir) {
5
+ if (!location.bbox || location.bbox.length !== 4) {
6
+ throw new Error(`Node ${nodeId} missing valid bbox.`);
7
+ }
8
+ const [x1, y1, x2, y2] = location.bbox;
9
+ // Load original to get dimensions
10
+ const image = sharp(sourcePath);
11
+ const metadata = await image.metadata();
12
+ if (!metadata.width || !metadata.height) {
13
+ throw new Error("Could not read image dimensions.");
14
+ }
15
+ const width = metadata.width;
16
+ const height = metadata.height;
17
+ // Convert normalized bbox (0-1) to pixel coordinates
18
+ const left = Math.floor(x1 * width);
19
+ const top = Math.floor(y1 * height);
20
+ const cropWidth = Math.floor((x2 - x1) * width);
21
+ const cropHeight = Math.floor((y2 - y1) * height);
22
+ const filename = `${resourceId}_crop_${left}_${top}.png`;
23
+ const outputPath = join(outputDir, filename);
24
+ await image
25
+ .extract({ left, top, width: cropWidth, height: cropHeight })
26
+ .toFile(outputPath);
27
+ return {
28
+ output_path: outputPath,
29
+ modality: "image",
30
+ address: `image://${resourceId}#rect=${x1},${y1},${x2},${y2}`,
31
+ node: { id: nodeId, location: location },
32
+ resource_id: resourceId
33
+ };
34
+ }
35
+ }
36
+ //# sourceMappingURL=image.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image.js","sourceRoot":"","sources":["../../src/resolvers/image.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAIjC,MAAM,OAAO,aAAa;IACtB,KAAK,CAAC,OAAO,CACT,UAAkB,EAClB,MAAc,EACd,UAAkB,EAClB,QAAa,EACb,SAAiB;QAEjB,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/C,MAAM,IAAI,KAAK,CAAC,QAAQ,MAAM,sBAAsB,CAAC,CAAC;QAC1D,CAAC;QAED,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC;QAEvC,kCAAkC;QAClC,MAAM,KAAK,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC;QAChC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE,CAAC;QAExC,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YACtC,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;QACxD,CAAC;QAED,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;QAC7B,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;QAE/B,qDAAqD;QACrD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,KAAK,CAAC,CAAC;QACpC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC;QACpC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC;QAChD,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC;QAElD,MAAM,QAAQ,GAAG,GAAG,UAAU,SAAS,IAAI,IAAI,GAAG,MAAM,CAAC;QACzD,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAE7C,MAAM,KAAK;aACN,OAAO,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;aAC5D,MAAM,CAAC,UAAU,CAAC,CAAC;QAExB,OAAO;YACH,WAAW,EAAE,UAAU;YACvB,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,WAAW,UAAU,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;YAC7D,IAAI,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAS;YAC/C,WAAW,EAAE,UAAU;SAC1B,CAAC;IACN,CAAC;CACJ"}
@@ -0,0 +1,6 @@
1
+ import { Resolver } from "./base.js";
2
+ import type { ResolvedEvidence } from "../models.js";
3
+ export declare class VideoResolver implements Resolver {
4
+ resolve(resourceId: string, nodeId: string, sourcePath: string, location: any, outputDir: string): Promise<ResolvedEvidence>;
5
+ }
6
+ //# sourceMappingURL=video.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video.d.ts","sourceRoot":"","sources":["../../src/resolvers/video.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD,qBAAa,aAAc,YAAW,QAAQ;IACpC,OAAO,CACT,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,GAAG,EACb,SAAS,EAAE,MAAM,GAClB,OAAO,CAAC,gBAAgB,CAAC;CA+B/B"}
@@ -0,0 +1,33 @@
1
+ import ffmpeg from "fluent-ffmpeg";
2
+ import { join } from "node:path";
3
+ export class VideoResolver {
4
+ async resolve(resourceId, nodeId, sourcePath, location, outputDir) {
5
+ if (location.start === undefined || location.end === undefined) {
6
+ throw new Error(`Node ${nodeId} missing start/end times.`);
7
+ }
8
+ const start = location.start;
9
+ const duration = location.end - location.start;
10
+ const filename = `${resourceId}_clip_${start}_${location.end}.mp4`;
11
+ const outputPath = join(outputDir, filename);
12
+ return new Promise((resolve, reject) => {
13
+ ffmpeg(sourcePath)
14
+ .setStartTime(start)
15
+ .setDuration(duration)
16
+ .output(outputPath)
17
+ .on("end", () => {
18
+ resolve({
19
+ output_path: outputPath,
20
+ modality: "video",
21
+ address: `video://${resourceId}#t=${start},${location.end}`,
22
+ node: { id: nodeId, location: location },
23
+ resource_id: resourceId
24
+ });
25
+ })
26
+ .on("error", (err) => {
27
+ reject(new Error(`ffmpeg failed: ${err.message}`));
28
+ })
29
+ .run();
30
+ });
31
+ }
32
+ }
33
+ //# sourceMappingURL=video.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video.js","sourceRoot":"","sources":["../../src/resolvers/video.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,eAAe,CAAC;AACnC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAIjC,MAAM,OAAO,aAAa;IACtB,KAAK,CAAC,OAAO,CACT,UAAkB,EAClB,MAAc,EACd,UAAkB,EAClB,QAAa,EACb,SAAiB;QAEjB,IAAI,QAAQ,CAAC,KAAK,KAAK,SAAS,IAAI,QAAQ,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;YAC7D,MAAM,IAAI,KAAK,CAAC,QAAQ,MAAM,2BAA2B,CAAC,CAAC;QAC/D,CAAC;QAED,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;QAC7B,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC;QAE/C,MAAM,QAAQ,GAAG,GAAG,UAAU,SAAS,KAAK,IAAI,QAAQ,CAAC,GAAG,MAAM,CAAC;QACnE,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAE7C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACnC,MAAM,CAAC,UAAU,CAAC;iBACb,YAAY,CAAC,KAAK,CAAC;iBACnB,WAAW,CAAC,QAAQ,CAAC;iBACrB,MAAM,CAAC,UAAU,CAAC;iBAClB,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;gBACZ,OAAO,CAAC;oBACJ,WAAW,EAAE,UAAU;oBACvB,QAAQ,EAAE,OAAO;oBACjB,OAAO,EAAE,WAAW,UAAU,MAAM,KAAK,IAAI,QAAQ,CAAC,GAAG,EAAE;oBAC3D,IAAI,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAS;oBAC/C,WAAW,EAAE,UAAU;iBAC1B,CAAC,CAAC;YACP,CAAC,CAAC;iBACD,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;gBACjB,MAAM,CAAC,IAAI,KAAK,CAAC,kBAAkB,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YACvD,CAAC,CAAC;iBACD,GAAG,EAAE,CAAC;QACf,CAAC,CAAC,CAAC;IACP,CAAC;CACJ"}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "citekit",
3
+ "version": "0.1.0",
4
+ "description": "A local SDK that lets AI agents open specific parts of files instead of sending entire documents.",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "scripts": {
9
+ "build": "tsc",
10
+ "dev": "tsc --watch"
11
+ },
12
+ "dependencies": {
13
+ "@google/generative-ai": "^0.24.1",
14
+ "@modelcontextprotocol/sdk": "^1.0.0",
15
+ "fluent-ffmpeg": "^2.1.3",
16
+ "pdf-lib": "^1.17.1",
17
+ "pdf-parse": "^2.4.5",
18
+ "sharp": "^0.34.5",
19
+ "zod": "^4.3.6"
20
+ },
21
+ "devDependencies": {
22
+ "@types/fluent-ffmpeg": "^2.1.28",
23
+ "@types/node": "^20.0.0",
24
+ "@types/pdf-parse": "^1.1.5",
25
+ "typescript": "^5.4.0"
26
+ },
27
+ "license": "MIT",
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "https://github.com/citekit/citekit.git",
31
+ "directory": "javascript"
32
+ },
33
+ "keywords": [
34
+ "ai",
35
+ "sdk",
36
+ "llm",
37
+ "mcp",
38
+ "document",
39
+ "video"
40
+ ],
41
+ "author": "",
42
+ "files": [
43
+ "dist",
44
+ "README.md",
45
+ "LICENSE"
46
+ ]
47
+ }