@alephantai/n8n-nodes-alephant-analytics-ai 0.1.2 → 0.1.3

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,5 +1,6 @@
1
- import type { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
1
+ import type { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription, ISupplyDataFunctions, SupplyData } from 'n8n-workflow';
2
2
  export declare class AlephantAnalyticsAi implements INodeType {
3
3
  description: INodeTypeDescription;
4
+ supplyData(this: ISupplyDataFunctions, itemIndex: number): Promise<SupplyData>;
4
5
  execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
5
6
  }
@@ -1,8 +1,40 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AlephantAnalyticsAi = void 0;
4
+ const tools_1 = require("@langchain/core/tools");
4
5
  const n8n_workflow_1 = require("n8n-workflow");
6
+ const zod_1 = require("zod");
5
7
  const usage_1 = require("../../shared/usage");
8
+ function toSafeToolName(nodeName) {
9
+ const normalized = (0, n8n_workflow_1.nodeNameToToolName)(nodeName)
10
+ .replace(/[^A-Za-z0-9_]/g, '_')
11
+ .replace(/^[^A-Za-z_]+/, '');
12
+ return normalized || 'Alephant_Analytics_AI';
13
+ }
14
+ const analyticsToolSchema = zod_1.z.object({
15
+ operation: zod_1.z
16
+ .enum([
17
+ 'scope',
18
+ 'budgetStatus',
19
+ 'usageSummary',
20
+ 'dailyCosts',
21
+ 'costByModel',
22
+ 'recentRequests',
23
+ 'requestLogDetail',
24
+ ])
25
+ .describe('Alephant analytics operation to run.'),
26
+ period: zod_1.z
27
+ .enum(['24h', '7d', '30d', '90d'])
28
+ .optional()
29
+ .describe('Time period for budget, usage, daily cost, and cost-by-model operations.'),
30
+ limit: zod_1.z.number().int().positive().optional().describe('Maximum recent requests to return.'),
31
+ offset: zod_1.z.number().int().min(0).optional().describe('Recent requests offset.'),
32
+ requestLogId: zod_1.z.string().optional().describe('Request log ID for requestLogDetail.'),
33
+ workspaceId: zod_1.z
34
+ .string()
35
+ .optional()
36
+ .describe('Workspace ID for request log detail lookups when credentials do not include one.'),
37
+ });
6
38
  class AlephantAnalyticsAi {
7
39
  constructor() {
8
40
  this.description = {
@@ -101,6 +133,36 @@ class AlephantAnalyticsAi {
101
133
  ],
102
134
  };
103
135
  }
136
+ async supplyData(itemIndex) {
137
+ const name = toSafeToolName(this.getNode().name);
138
+ try {
139
+ (0, n8n_workflow_1.tryToParseAlphanumericString)(name);
140
+ }
141
+ catch {
142
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'The name of this tool is not a valid alphanumeric string', {
143
+ itemIndex,
144
+ description: "Only alphanumeric characters and underscores are allowed in the tool's name, and the name cannot start with a number",
145
+ });
146
+ }
147
+ return {
148
+ response: new tools_1.DynamicStructuredTool({
149
+ name,
150
+ description: 'Query Alephant AI analytics for usage, cost, latency, model/provider performance, budget status, recent requests, and request log detail.',
151
+ schema: analyticsToolSchema,
152
+ func: async (input) => {
153
+ const data = await (0, usage_1.runUsageRequest)(this, {
154
+ operation: input.operation,
155
+ period: input.period ?? '7d',
156
+ limit: input.limit ?? 50,
157
+ offset: input.offset ?? 0,
158
+ requestLogId: input.requestLogId ?? '',
159
+ workspaceId: input.workspaceId ?? '',
160
+ }, itemIndex);
161
+ return JSON.stringify(data);
162
+ },
163
+ }),
164
+ };
165
+ }
104
166
  async execute() {
105
167
  return usage_1.executeUsageNode.call(this);
106
168
  }
@@ -1,3 +1,3 @@
1
1
  import { NodeApiError } from 'n8n-workflow';
2
- import type { IExecuteFunctions, IHttpRequestMethods } from 'n8n-workflow';
3
- export declare function toNodeApiError(ctx: IExecuteFunctions, error: unknown, method: IHttpRequestMethods, url: string, itemIndex?: number): NodeApiError;
2
+ import type { IExecuteFunctions, IHttpRequestMethods, ISupplyDataFunctions } from 'n8n-workflow';
3
+ export declare function toNodeApiError(ctx: IExecuteFunctions | ISupplyDataFunctions, error: unknown, method: IHttpRequestMethods, url: string, itemIndex?: number): NodeApiError;
@@ -1,4 +1,4 @@
1
- import type { IDataObject, IExecuteFunctions, IHttpRequestMethods } from 'n8n-workflow';
1
+ import type { IDataObject, IExecuteFunctions, IHttpRequestMethods, ISupplyDataFunctions } from 'n8n-workflow';
2
2
  export interface AlephantRequestOptions {
3
3
  method: IHttpRequestMethods;
4
4
  baseUrl: string;
@@ -10,4 +10,4 @@ export interface AlephantRequestOptions {
10
10
  body?: IDataObject;
11
11
  itemIndex?: number;
12
12
  }
13
- export declare function alephantRequest<T>(ctx: IExecuteFunctions, options: AlephantRequestOptions): Promise<T>;
13
+ export declare function alephantRequest<T>(ctx: IExecuteFunctions | ISupplyDataFunctions, options: AlephantRequestOptions): Promise<T>;
@@ -1,4 +1,4 @@
1
- import type { IDataObject, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
1
+ import type { IDataObject, IExecuteFunctions, INodeExecutionData, ISupplyDataFunctions } from 'n8n-workflow';
2
2
  export type UsageOperation = 'scope' | 'budgetStatus' | 'usageSummary' | 'dailyCosts' | 'costByModel' | 'recentRequests' | 'requestLogDetail';
3
3
  export interface UsageRequestParams {
4
4
  period?: string | null;
@@ -6,10 +6,17 @@ export interface UsageRequestParams {
6
6
  offset?: number | null;
7
7
  requestLogId?: string | null;
8
8
  }
9
+ export interface UsageToolInput extends UsageRequestParams {
10
+ operation: UsageOperation;
11
+ requestLogMaxAttempts?: number | null;
12
+ workspaceId?: string | null;
13
+ inputJson?: IDataObject;
14
+ }
9
15
  export interface UsageRequest {
10
16
  host?: 'saas' | 'analytics';
11
17
  path: string;
12
18
  qs?: IDataObject;
13
19
  }
14
20
  export declare function buildUsageRequest(operation: UsageOperation, params: UsageRequestParams): UsageRequest;
21
+ export declare function runUsageRequest(ctx: IExecuteFunctions | ISupplyDataFunctions, params: UsageToolInput, itemIndex?: number): Promise<IDataObject>;
15
22
  export declare function executeUsageNode(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.buildUsageRequest = buildUsageRequest;
4
+ exports.runUsageRequest = runUsageRequest;
4
5
  exports.executeUsageNode = executeUsageNode;
5
6
  const n8n_workflow_1 = require("n8n-workflow");
6
7
  const constants_1 = require("./constants");
@@ -111,56 +112,62 @@ function buildUsageRequest(operation, params) {
111
112
  };
112
113
  }
113
114
  }
115
+ async function runUsageRequest(ctx, params, itemIndex = 0) {
116
+ const credentials = (0, credentials_1.resolveVirtualKeyCredentials)((await ctx.getCredentials('alephantVirtualKeyApi')));
117
+ let request;
118
+ try {
119
+ request = buildUsageRequest(params.operation, params);
120
+ }
121
+ catch (error) {
122
+ throw new n8n_workflow_1.NodeOperationError(ctx.getNode(), error instanceof Error ? error.message : 'Invalid Alephant Usage input', { itemIndex });
123
+ }
124
+ let workspaceId = request.host === 'analytics'
125
+ ? normalizeOptionalString(params.workspaceId) ||
126
+ normalizeOptionalString(params.inputJson?.workspaceId) ||
127
+ normalizeOptionalString(params.inputJson?.workspace_id) ||
128
+ normalizeOptionalString(params.inputJson?.xWorkspaceId) ||
129
+ credentials.workspaceId
130
+ : undefined;
131
+ if (request.host === 'analytics' && workspaceId === '') {
132
+ const scope = await (0, http_1.alephantRequest)(ctx, {
133
+ method: 'GET',
134
+ baseUrl: credentials.saasBaseUrl,
135
+ path: constants_1.ENDPOINTS.cockpitScope,
136
+ token: credentials.virtualKey,
137
+ itemIndex,
138
+ });
139
+ workspaceId = extractWorkspaceIdFromScope(scope);
140
+ }
141
+ if (request.host === 'analytics' && workspaceId === '') {
142
+ throw new n8n_workflow_1.NodeOperationError(ctx.getNode(), 'Workspace ID is required for request log detail lookups and could not be resolved from Alephant Scope', { itemIndex });
143
+ }
144
+ const requestOptions = {
145
+ method: 'GET',
146
+ baseUrl: request.host === 'analytics' ? credentials.analyticsBaseUrl : credentials.saasBaseUrl,
147
+ path: request.path,
148
+ token: credentials.virtualKey,
149
+ workspaceId,
150
+ qs: request.qs,
151
+ itemIndex,
152
+ };
153
+ return request.host === 'analytics'
154
+ ? await requestWithLogPolling(ctx, requestOptions, normalizeAttemptCount(params.requestLogMaxAttempts))
155
+ : await (0, http_1.alephantRequest)(ctx, requestOptions);
156
+ }
114
157
  async function executeUsageNode() {
115
158
  const items = this.getInputData();
116
- const credentials = (0, credentials_1.resolveVirtualKeyCredentials)((await this.getCredentials('alephantVirtualKeyApi')));
117
159
  const returnData = [];
118
160
  for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
119
- const operation = this.getNodeParameter('operation', itemIndex);
120
- let request;
121
- try {
122
- request = buildUsageRequest(operation, {
123
- period: this.getNodeParameter('period', itemIndex, '7d'),
124
- limit: this.getNodeParameter('limit', itemIndex, 50),
125
- offset: this.getNodeParameter('offset', itemIndex, 0),
126
- requestLogId: this.getNodeParameter('requestLogId', itemIndex, ''),
127
- });
128
- }
129
- catch (error) {
130
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), error instanceof Error ? error.message : 'Invalid Alephant Usage input', { itemIndex });
131
- }
132
- let workspaceId = request.host === 'analytics'
133
- ? normalizeOptionalString(this.getNodeParameter('workspaceId', itemIndex, '')) ||
134
- normalizeOptionalString(items[itemIndex]?.json?.workspaceId) ||
135
- normalizeOptionalString(items[itemIndex]?.json?.workspace_id) ||
136
- normalizeOptionalString(items[itemIndex]?.json?.xWorkspaceId) ||
137
- credentials.workspaceId
138
- : undefined;
139
- if (request.host === 'analytics' && workspaceId === '') {
140
- const scope = await (0, http_1.alephantRequest)(this, {
141
- method: 'GET',
142
- baseUrl: credentials.saasBaseUrl,
143
- path: constants_1.ENDPOINTS.cockpitScope,
144
- token: credentials.virtualKey,
145
- itemIndex,
146
- });
147
- workspaceId = extractWorkspaceIdFromScope(scope);
148
- }
149
- if (request.host === 'analytics' && workspaceId === '') {
150
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Workspace ID is required for request log detail lookups and could not be resolved from Alephant Scope', { itemIndex });
151
- }
152
- const requestOptions = {
153
- method: 'GET',
154
- baseUrl: request.host === 'analytics' ? credentials.analyticsBaseUrl : credentials.saasBaseUrl,
155
- path: request.path,
156
- token: credentials.virtualKey,
157
- workspaceId,
158
- qs: request.qs,
159
- itemIndex,
160
- };
161
- const data = request.host === 'analytics'
162
- ? await requestWithLogPolling(this, requestOptions, normalizeAttemptCount(this.getNodeParameter('requestLogMaxAttempts', itemIndex, 6)))
163
- : await (0, http_1.alephantRequest)(this, requestOptions);
161
+ const data = await runUsageRequest(this, {
162
+ operation: this.getNodeParameter('operation', itemIndex),
163
+ period: this.getNodeParameter('period', itemIndex, '7d'),
164
+ limit: this.getNodeParameter('limit', itemIndex, 50),
165
+ offset: this.getNodeParameter('offset', itemIndex, 0),
166
+ requestLogId: this.getNodeParameter('requestLogId', itemIndex, ''),
167
+ workspaceId: this.getNodeParameter('workspaceId', itemIndex, ''),
168
+ requestLogMaxAttempts: this.getNodeParameter('requestLogMaxAttempts', itemIndex, 6),
169
+ inputJson: items[itemIndex]?.json,
170
+ }, itemIndex);
164
171
  returnData.push({
165
172
  json: data,
166
173
  pairedItem: { item: itemIndex },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alephantai/n8n-nodes-alephant-analytics-ai",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "n8n AI tool node for Alephant analytics",
5
5
  "license": "MIT",
6
6
  "homepage": "https://alephant.io",
@@ -50,6 +50,10 @@
50
50
  "peerDependencies": {
51
51
  "n8n-workflow": "*"
52
52
  },
53
+ "dependencies": {
54
+ "@langchain/core": "^1.1.46",
55
+ "zod": "^3.25.67"
56
+ },
53
57
  "devDependencies": {
54
58
  "n8n-workflow": "*",
55
59
  "typescript": "^5.6.3"