snow-flow 3.5.7 → 3.5.8

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.
@@ -10,6 +10,10 @@ export declare class ServiceNowClientWithTracking extends ServiceNowClient {
10
10
  * Override makeRequest to add tracking
11
11
  */
12
12
  makeRequest(config: any): Promise<any>;
13
+ /**
14
+ * Override searchRecordsWithFields to add tracking
15
+ */
16
+ searchRecordsWithFields(table: string, query: string, fields: string[], limit?: number): Promise<any>;
13
17
  /**
14
18
  * Override searchRecords to add tracking
15
19
  */
@@ -36,6 +36,27 @@ class ServiceNowClientWithTracking extends servicenow_client_js_1.ServiceNowClie
36
36
  throw error;
37
37
  }
38
38
  }
39
+ /**
40
+ * Override searchRecordsWithFields to add tracking
41
+ */
42
+ async searchRecordsWithFields(table, query, fields, limit = 10) {
43
+ this.mcpLogger.progress(`Searching ${table} with specific fields: ${fields.join(', ')}`);
44
+ try {
45
+ const result = await super.searchRecordsWithFields(table, query, fields, limit);
46
+ // Estimate tokens based on fields requested
47
+ const fieldCount = fields.length;
48
+ const estimatedTokens = Math.min(fieldCount * 100, 1000); // Rough estimate
49
+ this.mcpLogger.trackTokens(estimatedTokens, 0);
50
+ if (result?.data?.result?.length > 0) {
51
+ this.mcpLogger.info(`Found ${result.data.result.length} records with ${fieldCount} fields`);
52
+ }
53
+ return result;
54
+ }
55
+ catch (error) {
56
+ this.mcpLogger.error('Search with fields failed', error);
57
+ throw error;
58
+ }
59
+ }
39
60
  /**
40
61
  * Override searchRecords to add tracking
41
62
  */
@@ -156,6 +156,10 @@ export declare class ServiceNowClient {
156
156
  * Get multiple records from a table
157
157
  */
158
158
  getRecords(table: string, params?: any): Promise<ServiceNowAPIResponse<any[]>>;
159
+ /**
160
+ * Search records with specific fields
161
+ */
162
+ searchRecordsWithFields(table: string, query: string, fields: string[], limit?: number): Promise<ServiceNowAPIResponse<any>>;
159
163
  /**
160
164
  * Search records in a table using encoded query
161
165
  */
@@ -1039,6 +1039,33 @@ class ServiceNowClient {
1039
1039
  };
1040
1040
  }
1041
1041
  }
1042
+ /**
1043
+ * Search records with specific fields
1044
+ */
1045
+ async searchRecordsWithFields(table, query, fields, limit = 10) {
1046
+ try {
1047
+ await this.ensureAuthenticated();
1048
+ const url = `/api/now/table/${table}`;
1049
+ const params = {
1050
+ sysparm_query: query,
1051
+ sysparm_limit: limit.toString(),
1052
+ sysparm_fields: fields.join(',')
1053
+ };
1054
+ const response = await this.client.get(url, { params });
1055
+ return {
1056
+ success: true,
1057
+ data: response.data
1058
+ };
1059
+ }
1060
+ catch (error) {
1061
+ console.error('API Error:', error);
1062
+ return {
1063
+ success: false,
1064
+ error: error instanceof Error ? error.message : String(error),
1065
+ data: null
1066
+ };
1067
+ }
1068
+ }
1042
1069
  /**
1043
1070
  * Search records in a table using encoded query
1044
1071
  */
@@ -152,34 +152,103 @@ class SmartFieldFetcher {
152
152
  * (Wrapper for backward compatibility)
153
153
  */
154
154
  async fetchWidget(sys_id) {
155
- return this.fetchArtifact('sp_widget', sys_id);
156
155
  console.log(`\nšŸ” Smart fetching widget: ${sys_id}`);
157
156
  const results = {
158
157
  _fetch_strategy: 'smart_chunked',
159
158
  _context_hint: 'Widget fields fetched separately but are interconnected: template references {{data.x}} from server script, calls methods from client script, and uses CSS classes',
160
159
  _field_groups: {}
161
160
  };
162
- // Fetch each field group
163
- for (const group of WIDGET_FIELD_GROUPS) {
164
- console.log(`šŸ“¦ Fetching ${group.groupName}: ${group.description}`);
165
- try {
166
- const response = await this.client.getRecord('sp_widget', sys_id);
167
- if (response) {
161
+ // Try to fetch all fields first, then fall back to individual fields if too large
162
+ console.log(`šŸ“¦ Attempting to fetch complete widget data...`);
163
+ try {
164
+ // Try to get all fields at once
165
+ const response = await this.client.searchRecords('sp_widget', `sys_id=${sys_id}`, 1);
166
+ if (response && response.result && response.result.length > 0) {
167
+ const widgetData = response.result[0];
168
+ console.log(`āœ… Successfully fetched complete widget`);
169
+ // Organize into field groups for better context
170
+ for (const group of WIDGET_FIELD_GROUPS) {
171
+ const groupData = {};
172
+ for (const fieldName of group.fields) {
173
+ if (widgetData[fieldName] !== undefined) {
174
+ groupData[fieldName] = widgetData[fieldName];
175
+ }
176
+ }
168
177
  results._field_groups[group.groupName] = {
169
- data: response,
178
+ data: groupData,
170
179
  description: group.description,
171
180
  fields: group.fields
172
181
  };
173
- // Add to flat structure for easy access
174
- Object.assign(results, response.result[0]);
175
182
  }
183
+ // Add complete widget data to flat structure
184
+ Object.assign(results, widgetData);
176
185
  }
177
- catch (error) {
178
- console.log(`āš ļø Failed to fetch ${group.groupName}: ${error.message}`);
179
- // If group fails due to size, fetch fields individually
180
- if (error.message?.includes('exceeds maximum allowed tokens')) {
181
- results._field_groups[group.groupName] = await this.fetchFieldsIndividually('sp_widget', sys_id, group.fields, group.description);
186
+ else {
187
+ throw new Error('Widget not found');
188
+ }
189
+ }
190
+ catch (error) {
191
+ console.log(`āš ļø Complete fetch failed: ${error.message}`);
192
+ console.log(`šŸ”„ Switching to field-by-field fetching...`);
193
+ // Fall back to fetching fields per group or individually
194
+ for (const group of WIDGET_FIELD_GROUPS) {
195
+ console.log(`šŸ“¦ Fetching ${group.groupName}: ${group.description}`);
196
+ try {
197
+ // Try to fetch all fields in this group at once
198
+ const groupResponse = await this.client.searchRecordsWithFields('sp_widget', `sys_id=${sys_id}`, group.fields, 1);
199
+ if (groupResponse && groupResponse.success && groupResponse.data && groupResponse.data.result && groupResponse.data.result.length > 0) {
200
+ const groupData = groupResponse.data.result[0];
201
+ console.log(` āœ… Successfully fetched ${group.groupName}`);
202
+ results._field_groups[group.groupName] = {
203
+ data: groupData,
204
+ description: group.description,
205
+ fields: group.fields
206
+ };
207
+ // Add to flat structure
208
+ Object.assign(results, groupData);
209
+ }
210
+ else {
211
+ throw new Error('No data returned for group');
212
+ }
182
213
  }
214
+ catch (groupError) {
215
+ console.log(` āš ļø Group ${group.groupName} failed, fetching fields individually...`);
216
+ // If group fails, fetch fields one by one
217
+ const groupData = {};
218
+ for (const fieldName of group.fields) {
219
+ console.log(` šŸ“„ Fetching field: ${fieldName}`);
220
+ try {
221
+ // Fetch just this single field
222
+ const fieldResponse = await this.client.searchRecordsWithFields('sp_widget', `sys_id=${sys_id}`, [fieldName], 1);
223
+ if (fieldResponse && fieldResponse.success && fieldResponse.data && fieldResponse.data.result && fieldResponse.data.result.length > 0) {
224
+ const fieldValue = fieldResponse.data.result[0][fieldName];
225
+ if (fieldValue !== undefined && fieldValue !== null) {
226
+ groupData[fieldName] = fieldValue;
227
+ results[fieldName] = fieldValue; // Also add to flat structure
228
+ console.log(` āœ… Got ${fieldName} (${typeof fieldValue === 'string' ? fieldValue.length : 0} chars)`);
229
+ }
230
+ else {
231
+ groupData[fieldName] = '';
232
+ console.log(` āš ļø ${fieldName} is empty`);
233
+ }
234
+ }
235
+ }
236
+ catch (fieldError) {
237
+ console.log(` āŒ Failed to fetch ${fieldName}: ${fieldError.message}`);
238
+ groupData[fieldName] = ''; // Empty string for failed fields
239
+ }
240
+ }
241
+ results._field_groups[group.groupName] = {
242
+ data: groupData,
243
+ description: group.description,
244
+ fields: group.fields,
245
+ _fetched_individually: true
246
+ };
247
+ }
248
+ }
249
+ // Make sure we have at least the sys_id
250
+ if (!results.sys_id) {
251
+ results.sys_id = sys_id;
183
252
  }
184
253
  }
185
254
  // Add coherence validation hints
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "snow-flow",
3
- "version": "3.5.7",
3
+ "version": "3.5.8",
4
4
  "description": "ServiceNow development framework with MCP server integration. Executes background scripts using ES5 JavaScript only (ServiceNow Rhino engine requirement). Provides 18 MCP servers including local development sync for editing ServiceNow artifacts with Claude Code native tools, widget deployment with coherence validation, table operations, script execution, machine learning, advanced features, and comprehensive platform management.",
5
5
  "main": "dist/index.js",
6
6
  "type": "commonjs",