@hubblecommerce/overmind-core 0.1.2 → 0.1.4

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.
@@ -1,4 +1,4 @@
1
1
  import type { EmbeddingsProvider } from './embeddings.interface.js';
2
2
  export type { EmbeddingsProvider };
3
- export declare function createTransformersEmbeddings(modelName: string, pooling: 'mean', normalize: boolean): Promise<EmbeddingsProvider>;
3
+ export declare function createTransformersEmbeddings(): Promise<EmbeddingsProvider>;
4
4
  //# sourceMappingURL=transformers.provider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"transformers.provider.d.ts","sourceRoot":"","sources":["../../../src/embeddings/transformers.provider.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAEpE,YAAY,EAAE,kBAAkB,EAAE,CAAC;AAEnC,wBAAsB,4BAA4B,CAC9C,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,OAAO,GACnB,OAAO,CAAC,kBAAkB,CAAC,CAkB7B"}
1
+ {"version":3,"file":"transformers.provider.d.ts","sourceRoot":"","sources":["../../../src/embeddings/transformers.provider.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAGpE,YAAY,EAAE,kBAAkB,EAAE,CAAC;AAInC,wBAAsB,4BAA4B,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAuBhF"}
@@ -1,8 +1,13 @@
1
1
  import { pipeline } from '@xenova/transformers';
2
- export async function createTransformersEmbeddings(modelName, pooling, normalize) {
2
+ import { config } from '../config/app.config.js';
3
+ let instance = null;
4
+ export async function createTransformersEmbeddings() {
5
+ if (instance)
6
+ return instance;
3
7
  console.log('Loading local embedding model (first time may take a moment to download)...');
8
+ const { modelName, pooling, normalize } = config.embedding;
4
9
  const embedder = await pipeline('feature-extraction', modelName);
5
- return {
10
+ instance = {
6
11
  async embedDocuments(texts) {
7
12
  const embeddings = [];
8
13
  for (const text of texts) {
@@ -16,4 +21,5 @@ export async function createTransformersEmbeddings(modelName, pooling, normalize
16
21
  return Array.from(output.data);
17
22
  },
18
23
  };
24
+ return instance;
19
25
  }
@@ -19,6 +19,7 @@ export declare class ConfluenceClient {
19
19
  * Make HTTP request to Confluence API with retries
20
20
  */
21
21
  private request;
22
+ private paginate;
22
23
  /**
23
24
  * Get all spaces (with pagination)
24
25
  */
@@ -40,6 +41,12 @@ export declare class ConfluenceClient {
40
41
  * Get space by key
41
42
  */
42
43
  getSpaceByKey(spaceKey: string): Promise<ConfluenceSpace>;
44
+ /**
45
+ * Get all direct child pages of a given parent page
46
+ */
47
+ getChildPages(parentId: string): Promise<{
48
+ id: string;
49
+ }[]>;
43
50
  /**
44
51
  * Get recent pages across all spaces or specific spaces
45
52
  */
@@ -49,17 +56,10 @@ export declare class ConfluenceClient {
49
56
  * Returns only label names as strings
50
57
  */
51
58
  getPageLabels(pageId: string): Promise<string[]>;
52
- /**
53
- * Get numeric space ID from space key
54
- * Helper method to convert space key to numeric ID required by v2 API
55
- * @param spaceKey - The space key (e.g., "TEST")
56
- * @returns The numeric space ID
57
- */
58
- getSpaceIdByKey(spaceKey: string): Promise<string>;
59
59
  /**
60
60
  * Create a new page in Confluence using REST API v2 with ADF (Atlassian Document Format)
61
61
  * This is the modern format for the new Confluence editor
62
- * @param spaceId - The numeric space ID (not space key) - use getSpaceIdByKey() if you have a space key
62
+ * @param spaceId - The numeric space ID (not space key)
63
63
  * @param title - The page title
64
64
  * @param adfBody - The page content in ADF format (from @atlaskit/editor-markdown-transformer)
65
65
  * @param parentId - Optional parent page ID to create as child page
@@ -1 +1 @@
1
- {"version":3,"file":"confluence.client.d.ts","sourceRoot":"","sources":["../../../../src/integrations/confluence/confluence.client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACR,cAAc,EAEd,eAAe,EAKlB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,sBAAsB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAuBD,qBAAa,gBAAgB;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,eAAe,CAAa;gBAExB,MAAM,EAAE,sBAAsB;IAS1C;;OAEG;YACW,gBAAgB;IAa9B;;OAEG;YACW,OAAO;IAwDrB;;OAEG;IACG,SAAS,CAAC,KAAK,GAAE,MAAW,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAkB/D;;;OAGG;IACG,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAyBpF;;OAEG;IACG,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,GAAE,SAAS,GAAG,kBAA8B,GAAG,OAAO,CAAC,cAAc,CAAC;IAKlH;;OAEG;IACG,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAUrD;;OAEG;IACG,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAW/D;;OAEG;IACG,cAAc,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,EAAE,KAAK,GAAE,MAAW,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAYzF;;;OAGG;IACG,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IA0BtD;;;;;OAKG;IACG,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAKxD;;;;;;;;OAQG;IACG,iBAAiB,CAAC,MAAM,EAAE;QAC5B,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,OAAO,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACrB,GAAG,OAAO,CAAC,cAAc,CAAC;CAuC9B"}
1
+ {"version":3,"file":"confluence.client.d.ts","sourceRoot":"","sources":["../../../../src/integrations/confluence/confluence.client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACR,cAAc,EAEd,eAAe,EAKlB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,sBAAsB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAuBD,qBAAa,gBAAgB;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,eAAe,CAAa;gBAExB,MAAM,EAAE,sBAAsB;IAS1C;;OAEG;YACW,gBAAgB;IAa9B;;OAEG;YACW,OAAO;YAwDP,QAAQ;IActB;;OAEG;IACG,SAAS,CAAC,KAAK,GAAE,MAAW,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAI/D;;;OAGG;IACG,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAKpF;;OAEG;IACG,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,GAAE,SAAS,GAAG,kBAA8B,GAAG,OAAO,CAAC,cAAc,CAAC;IAKlH;;OAEG;IACG,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAUrD;;OAEG;IACG,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAW/D;;OAEG;IACG,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAoBhE;;OAEG;IACG,cAAc,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,EAAE,KAAK,GAAE,MAAW,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAYzF;;;OAGG;IACG,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IA0BtD;;;;;;;;OAQG;IACG,iBAAiB,CAAC,MAAM,EAAE;QAC5B,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,OAAO,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACrB,GAAG,OAAO,CAAC,cAAc,CAAC;CAuC9B"}
@@ -73,46 +73,29 @@ export class ConfluenceClient {
73
73
  }
74
74
  throw lastError || new Error('Request failed after max retries');
75
75
  }
76
+ async paginate(initialUrl) {
77
+ const items = [];
78
+ let nextUrl = initialUrl;
79
+ while (nextUrl) {
80
+ const response = await this.request(nextUrl);
81
+ items.push(...response.results);
82
+ nextUrl = response._links.next?.replace(this.baseUrl, '');
83
+ }
84
+ return items;
85
+ }
76
86
  /**
77
87
  * Get all spaces (with pagination)
78
88
  */
79
89
  async getSpaces(limit = 25) {
80
- const spaces = [];
81
- let nextUrl = `/wiki/api/v2/spaces?limit=${limit}`;
82
- while (nextUrl) {
83
- const response = await this.request(nextUrl);
84
- const results = response.results;
85
- spaces.push(...results);
86
- // Extract cursor from next link if exists
87
- const links = response._links;
88
- const nextLink = links.next;
89
- nextUrl = nextLink ? nextLink.replace(this.baseUrl, '') : undefined;
90
- }
91
- return spaces;
90
+ return this.paginate(`/wiki/api/v2/spaces?limit=${limit}`);
92
91
  }
93
92
  /**
94
93
  * Get all pages in a space (with pagination)
95
94
  * Note: Accepts space key and automatically resolves to space ID for API v2
96
95
  */
97
96
  async getSpacePages(spaceKey, limit = 25) {
98
- // First, resolve space key to space ID (required by API v2)
99
97
  const space = await this.getSpaceByKey(spaceKey);
100
- const spaceId = space.id;
101
- const pages = [];
102
- let nextUrl = `/wiki/api/v2/spaces/${spaceId}/pages?limit=${limit}&status=current`;
103
- while (nextUrl) {
104
- const response = await this.request(nextUrl);
105
- const results = response.results;
106
- pages.push(...results);
107
- // Extract cursor from next link if exists
108
- const links = response._links;
109
- nextUrl = links.next || undefined;
110
- if (nextUrl) {
111
- // Convert full URL to relative path
112
- nextUrl = nextUrl.replace(this.baseUrl, '');
113
- }
114
- }
115
- return pages;
98
+ return this.paginate(`/wiki/api/v2/spaces/${space.id}/pages?limit=${limit}&status=current`);
116
99
  }
117
100
  /**
118
101
  * Get a single page by ID with content
@@ -142,6 +125,24 @@ export class ConfluenceClient {
142
125
  }
143
126
  return response.results[0];
144
127
  }
128
+ /**
129
+ * Get all direct child pages of a given parent page
130
+ */
131
+ async getChildPages(parentId) {
132
+ const pages = [];
133
+ let start = 0;
134
+ const limit = 250;
135
+ while (true) {
136
+ const endpoint = `/wiki/rest/api/content/${parentId}/child/page?start=${start}&limit=${limit}&status=current`;
137
+ const response = await this.request(endpoint);
138
+ pages.push(...response.results);
139
+ if (response.results.length < limit) {
140
+ break;
141
+ }
142
+ start += limit;
143
+ }
144
+ return pages;
145
+ }
145
146
  /**
146
147
  * Get recent pages across all spaces or specific spaces
147
148
  */
@@ -179,20 +180,10 @@ export class ConfluenceClient {
179
180
  // Return only the label names (without prefix)
180
181
  return labels.map(label => label.name);
181
182
  }
182
- /**
183
- * Get numeric space ID from space key
184
- * Helper method to convert space key to numeric ID required by v2 API
185
- * @param spaceKey - The space key (e.g., "TEST")
186
- * @returns The numeric space ID
187
- */
188
- async getSpaceIdByKey(spaceKey) {
189
- const space = await this.getSpaceByKey(spaceKey);
190
- return space.id;
191
- }
192
183
  /**
193
184
  * Create a new page in Confluence using REST API v2 with ADF (Atlassian Document Format)
194
185
  * This is the modern format for the new Confluence editor
195
- * @param spaceId - The numeric space ID (not space key) - use getSpaceIdByKey() if you have a space key
186
+ * @param spaceId - The numeric space ID (not space key)
196
187
  * @param title - The page title
197
188
  * @param adfBody - The page content in ADF format (from @atlaskit/editor-markdown-transformer)
198
189
  * @param parentId - Optional parent page ID to create as child page
@@ -48,9 +48,10 @@ export interface JiraClientConfig {
48
48
  apiToken: string;
49
49
  }
50
50
  export declare class JiraClient {
51
- private baseUrl;
52
- private authHeader;
51
+ private readonly baseUrl;
52
+ private readonly authHeader;
53
53
  constructor(config: JiraClientConfig);
54
+ private request;
54
55
  /**
55
56
  * Parse Atlassian Document Format (ADF) to plain text
56
57
  */
@@ -1 +1 @@
1
- {"version":3,"file":"jira.client.d.ts","sourceRoot":"","sources":["../../../../src/integrations/jira/jira.client.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACnB;AAkBD,MAAM,WAAW,SAAS;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE;QACJ,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,MAAM,EAAE;YACJ,IAAI,EAAE,MAAM,CAAC;YACb,EAAE,EAAE,MAAM,CAAC;SACd,CAAC;QACF,SAAS,EAAE;YACP,IAAI,EAAE,MAAM,CAAC;YACb,EAAE,EAAE,MAAM,CAAC;SACd,CAAC;QACF,OAAO,EAAE;YACL,GAAG,EAAE,MAAM,CAAC;YACZ,EAAE,EAAE,MAAM,CAAC;YACX,IAAI,EAAE,MAAM,CAAC;SAChB,CAAC;QACF,QAAQ,CAAC,EAAE;YACP,SAAS,EAAE,MAAM,CAAC;YAClB,WAAW,EAAE,MAAM,CAAC;SACvB,GAAG,IAAI,CAAC;QACT,QAAQ,CAAC,EAAE;YACP,SAAS,EAAE,MAAM,CAAC;YAClB,WAAW,EAAE,MAAM,CAAC;SACvB,GAAG,IAAI,CAAC;QACT,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC/B,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,UAAU,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,EAAE,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KACnD,CAAC;IACF,QAAQ,EAAE,WAAW,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,UAAU;IACnB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,UAAU,CAAS;gBAEf,MAAM,EAAE,gBAAgB;IAKpC;;OAEG;IACH,OAAO,CAAC,cAAc;IAgCtB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAexB;;OAEG;IACG,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;CAuI3D"}
1
+ {"version":3,"file":"jira.client.d.ts","sourceRoot":"","sources":["../../../../src/integrations/jira/jira.client.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACnB;AAkBD,MAAM,WAAW,SAAS;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE;QACJ,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,MAAM,EAAE;YACJ,IAAI,EAAE,MAAM,CAAC;YACb,EAAE,EAAE,MAAM,CAAC;SACd,CAAC;QACF,SAAS,EAAE;YACP,IAAI,EAAE,MAAM,CAAC;YACb,EAAE,EAAE,MAAM,CAAC;SACd,CAAC;QACF,OAAO,EAAE;YACL,GAAG,EAAE,MAAM,CAAC;YACZ,EAAE,EAAE,MAAM,CAAC;YACX,IAAI,EAAE,MAAM,CAAC;SAChB,CAAC;QACF,QAAQ,CAAC,EAAE;YACP,SAAS,EAAE,MAAM,CAAC;YAClB,WAAW,EAAE,MAAM,CAAC;SACvB,GAAG,IAAI,CAAC;QACT,QAAQ,CAAC,EAAE;YACP,SAAS,EAAE,MAAM,CAAC;YAClB,WAAW,EAAE,MAAM,CAAC;SACvB,GAAG,IAAI,CAAC;QACT,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC/B,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,UAAU,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,EAAE,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KACnD,CAAC;IACF,QAAQ,EAAE,WAAW,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,UAAU;IACnB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAExB,MAAM,EAAE,gBAAgB;YAKtB,OAAO;IAgBrB;;OAEG;IACH,OAAO,CAAC,cAAc;IAgCtB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAexB;;OAEG;IACG,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;CA4B3D"}
@@ -5,6 +5,19 @@ export class JiraClient {
5
5
  this.baseUrl = config.baseUrl;
6
6
  this.authHeader = 'Basic ' + Buffer.from(`${config.email}:${config.apiToken}`).toString('base64');
7
7
  }
8
+ async request(endpoint) {
9
+ const response = await fetch(`${this.baseUrl}${endpoint}`, {
10
+ headers: {
11
+ 'Authorization': this.authHeader,
12
+ 'Accept': 'application/json',
13
+ 'Content-Type': 'application/json',
14
+ },
15
+ });
16
+ if (!response.ok) {
17
+ throw new Error(`Jira API error: ${response.status} ${response.statusText}`);
18
+ }
19
+ return response.json();
20
+ }
8
21
  /**
9
22
  * Parse Atlassian Document Format (ADF) to plain text
10
23
  */
@@ -55,92 +68,16 @@ export class JiraClient {
55
68
  */
56
69
  async getIssue(issueKeyOrId) {
57
70
  try {
58
- // Fetch issue details
59
- const issueResponse = await fetch(`${this.baseUrl}/rest/api/3/issue/${issueKeyOrId}`, {
60
- headers: {
61
- 'Authorization': this.authHeader,
62
- 'Content-Type': 'application/json',
63
- 'Accept': 'application/json',
64
- },
65
- });
66
- if (!issueResponse.ok) {
67
- throw new Error(`Failed to fetch issue: ${issueResponse.status} ${issueResponse.statusText}`);
68
- }
69
- const issue = await issueResponse.json();
70
- // Fetch comments
71
- const commentsResponse = await fetch(`${this.baseUrl}/rest/api/3/issue/${issueKeyOrId}/comment`, {
72
- headers: {
73
- 'Authorization': this.authHeader,
74
- 'Content-Type': 'application/json',
75
- 'Accept': 'application/json',
76
- },
77
- });
78
- if (!commentsResponse.ok) {
79
- throw new Error(`Failed to fetch comments: ${commentsResponse.status} ${commentsResponse.statusText}`);
80
- }
81
- const commentsData = await commentsResponse.json();
82
- // Parse and filter comments (only 'doc' type, latest version only)
83
- const commentsMap = new Map();
84
- commentsData.comments?.forEach(comment => {
85
- // Only include ADF doc type comments
86
- if (typeof comment.body === 'object' && comment.body !== null) {
87
- const adfDoc = comment.body;
88
- if (adfDoc.type !== 'doc') {
89
- return;
90
- }
91
- const version = adfDoc.version || 1;
92
- const existing = commentsMap.get(comment.id);
93
- // Only keep the latest version of each comment
94
- if (!existing || version > existing.version) {
95
- commentsMap.set(comment.id, {
96
- author: comment.author.displayName,
97
- body: this.parseCommentBody(comment.body),
98
- updated: comment.updated,
99
- version,
100
- });
101
- }
102
- }
103
- });
104
- // Convert map to array (without version field)
105
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
106
- const parsedComments = Array.from(commentsMap.values()).map(({ version, ...comment }) => comment);
107
- // Transform to our interface
108
- return {
109
- id: issue.id,
110
- key: issue.key,
111
- self: issue.self,
112
- fields: {
113
- summary: issue.fields.summary,
114
- description: issue.fields.description,
115
- status: {
116
- name: issue.fields.status.name,
117
- id: issue.fields.status.id,
118
- },
119
- issuetype: {
120
- name: issue.fields.issuetype.name,
121
- id: issue.fields.issuetype.id,
122
- },
123
- project: {
124
- key: issue.fields.project.key,
125
- id: issue.fields.project.id,
126
- name: issue.fields.project.name,
127
- },
128
- assignee: issue.fields.assignee ? {
129
- accountId: issue.fields.assignee.accountId,
130
- displayName: issue.fields.assignee.displayName,
131
- } : null,
132
- reporter: issue.fields.reporter ? {
133
- accountId: issue.fields.reporter.accountId,
134
- displayName: issue.fields.reporter.displayName,
135
- } : null,
136
- created: issue.fields.created,
137
- updated: issue.fields.updated,
138
- resolutiondate: issue.fields.resolutiondate,
139
- labels: issue.fields.labels || [],
140
- components: issue.fields.components || [],
141
- },
142
- comments: parsedComments,
143
- };
71
+ const issue = await this.request(`/rest/api/3/issue/${issueKeyOrId}`);
72
+ const commentsData = await this.request(`/rest/api/3/issue/${issueKeyOrId}/comment`);
73
+ const parsedComments = commentsData.comments
74
+ ?.filter(c => typeof c.body === 'object' && c.body !== null && c.body.type === 'doc')
75
+ .map(c => ({
76
+ author: c.author.displayName,
77
+ body: this.parseCommentBody(c.body),
78
+ updated: c.updated,
79
+ })) ?? [];
80
+ return { ...issue, comments: parsedComments };
144
81
  }
145
82
  catch (error) {
146
83
  console.error(`[JiraClient] Error fetching issue ${issueKeyOrId}:`, error);
@@ -1 +1 @@
1
- {"version":3,"file":"confluence-html-parser.d.ts","sourceRoot":"","sources":["../../../src/processors/confluence-html-parser.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAqBxD"}
1
+ {"version":3,"file":"confluence-html-parser.d.ts","sourceRoot":"","sources":["../../../src/processors/confluence-html-parser.ts"],"names":[],"mappings":"AAYA;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CASxD"}
@@ -1,19 +1,18 @@
1
1
  import TurndownService from 'turndown';
2
+ const turndownService = new TurndownService({
3
+ headingStyle: 'atx',
4
+ hr: '---',
5
+ bulletListMarker: '-',
6
+ codeBlockStyle: 'fenced',
7
+ emDelimiter: '*',
8
+ strongDelimiter: '**',
9
+ });
10
+ addConfluenceRules(turndownService);
2
11
  /**
3
12
  * Parse Confluence storage format HTML to clean Markdown
4
13
  * Uses Turndown with custom rules for Confluence-specific elements
5
14
  */
6
15
  export function parseConfluenceHtml(html) {
7
- const turndownService = new TurndownService({
8
- headingStyle: 'atx', // Use # for headings
9
- hr: '---',
10
- bulletListMarker: '-',
11
- codeBlockStyle: 'fenced',
12
- emDelimiter: '*',
13
- strongDelimiter: '**',
14
- });
15
- // Add custom rules for Confluence-specific elements
16
- addConfluenceRules(turndownService);
17
16
  // Convert HTML to Markdown
18
17
  const markdown = turndownService.turndown(html);
19
18
  // Clean up extra whitespace
@@ -1 +1 @@
1
- {"version":3,"file":"get-current-date.tool.d.ts","sourceRoot":"","sources":["../../../src/tools/get-current-date.tool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,wBAAgB,wBAAwB,uJAqBvC"}
1
+ {"version":3,"file":"get-current-date.tool.d.ts","sourceRoot":"","sources":["../../../src/tools/get-current-date.tool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,wBAAgB,wBAAwB,uJAevC"}
@@ -3,11 +3,7 @@ import { z } from 'zod';
3
3
  export function createGetCurrentDateTool() {
4
4
  const getCurrentDateSchema = z.object({});
5
5
  return tool(() => {
6
- const currentDate = new Date();
7
- const year = currentDate.getFullYear();
8
- const month = (currentDate.getMonth() + 1).toString().padStart(2, '0');
9
- const day = currentDate.getDate().toString().padStart(2, '0');
10
- const formattedDate = `${year}-${month}-${day}`;
6
+ const formattedDate = new Date().toISOString().slice(0, 10);
11
7
  console.log(`\nšŸ“… Returning current date: ${formattedDate}`);
12
8
  return formattedDate;
13
9
  }, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hubblecommerce/overmind-core",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "type": "module",
5
5
  "description": "Shared infrastructure package for the Overmind AI agent system",
6
6
  "main": "./dist/src/index.js",
@@ -75,7 +75,9 @@
75
75
  "check": "npm run lint && npm run typecheck",
76
76
  "prepare": "husky",
77
77
  "sync:confluence": "tsx scripts/bulk-sync-confluence.ts",
78
- "sync:confluence:reset": "rm -f .confluence-sync-state.json && tsx scripts/bulk-sync-confluence.ts"
78
+ "sync:confluence:reset": "rm -f .confluence-sync-state.json && tsx scripts/bulk-sync-confluence.ts",
79
+ "sync:confluence:prod": "tsx scripts/bulk-sync-confluence.ts --prod",
80
+ "sync:confluence:prod:reset": "rm -f .confluence-sync-state.prod.json && tsx scripts/bulk-sync-confluence.ts --prod"
79
81
  },
80
82
  "devDependencies": {
81
83
  "@eslint/js": "^9.36.0",