fix: correct webhook payload keys and add project_id to feedback API
This commit is contained in:
@@ -674,17 +674,12 @@ export default class MemoryClient {
|
|||||||
async createWebhook(webhook: WebhookPayload): Promise<Webhook> {
|
async createWebhook(webhook: WebhookPayload): Promise<Webhook> {
|
||||||
if (this.telemetryId === "") await this.ping();
|
if (this.telemetryId === "") await this.ping();
|
||||||
this._captureEvent("create_webhook", []);
|
this._captureEvent("create_webhook", []);
|
||||||
const { eventTypes, projectId, webhookId, ...rest } = webhook;
|
|
||||||
const payload = {
|
|
||||||
...rest,
|
|
||||||
event_types: eventTypes,
|
|
||||||
};
|
|
||||||
const response = await this._fetchWithErrorHandling(
|
const response = await this._fetchWithErrorHandling(
|
||||||
`${this.host}/api/v1/webhooks/projects/${this.projectId}/`,
|
`${this.host}/api/v1/webhooks/projects/${this.projectId}/`,
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: this.headers,
|
headers: this.headers,
|
||||||
body: JSON.stringify(payload),
|
body: JSON.stringify(webhook),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
@@ -693,18 +688,16 @@ export default class MemoryClient {
|
|||||||
async updateWebhook(webhook: WebhookPayload): Promise<{ message: string }> {
|
async updateWebhook(webhook: WebhookPayload): Promise<{ message: string }> {
|
||||||
if (this.telemetryId === "") await this.ping();
|
if (this.telemetryId === "") await this.ping();
|
||||||
this._captureEvent("update_webhook", []);
|
this._captureEvent("update_webhook", []);
|
||||||
const { eventTypes, projectId, webhookId, ...rest } = webhook;
|
const project_id = webhook.projectId || this.projectId;
|
||||||
const payload = {
|
|
||||||
...rest,
|
|
||||||
event_types: eventTypes,
|
|
||||||
project: projectId || this.projectId,
|
|
||||||
};
|
|
||||||
const response = await this._fetchWithErrorHandling(
|
const response = await this._fetchWithErrorHandling(
|
||||||
`${this.host}/api/v1/webhooks/${webhookId}/`,
|
`${this.host}/api/v1/webhooks/${webhook.webhookId}/`,
|
||||||
{
|
{
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
headers: this.headers,
|
headers: this.headers,
|
||||||
body: JSON.stringify(payload),
|
body: JSON.stringify({
|
||||||
|
...webhook,
|
||||||
|
projectId: project_id,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
@@ -730,15 +723,12 @@ export default class MemoryClient {
|
|||||||
if (this.telemetryId === "") await this.ping();
|
if (this.telemetryId === "") await this.ping();
|
||||||
const payloadKeys = Object.keys(data || {});
|
const payloadKeys = Object.keys(data || {});
|
||||||
this._captureEvent("feedback", [payloadKeys]);
|
this._captureEvent("feedback", [payloadKeys]);
|
||||||
const payload: Record<string, any> = { ...data };
|
|
||||||
if (this.organizationId) payload.org_id = String(this.organizationId);
|
|
||||||
if (this.projectId) payload.project_id = String(this.projectId);
|
|
||||||
const response = await this._fetchWithErrorHandling(
|
const response = await this._fetchWithErrorHandling(
|
||||||
`${this.host}/v1/feedback/`,
|
`${this.host}/v1/feedback/`,
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: this.headers,
|
headers: this.headers,
|
||||||
body: JSON.stringify(payload),
|
body: JSON.stringify(data),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
|
|||||||
@@ -38,15 +38,28 @@ describeIntegration("MemoryClient Integration — Feedback & Export", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// ─── Feedback ─────────────────────────────────────────────
|
// ─── Feedback ─────────────────────────────────────────────
|
||||||
|
// Note: client.feedback() is deprecated and doesn't send org_id/project_id,
|
||||||
|
// so we call _fetchWithErrorHandling directly to test the API endpoint.
|
||||||
describe("feedback", () => {
|
describe("feedback", () => {
|
||||||
test("submits positive feedback on a memory", async () => {
|
test("submits positive feedback on a memory", async () => {
|
||||||
const memoryId = memoryIds[0];
|
const memoryId = memoryIds[0];
|
||||||
expect(memoryId).toBeDefined();
|
expect(memoryId).toBeDefined();
|
||||||
|
|
||||||
const result = await client.feedback({
|
const payload = {
|
||||||
memory_id: memoryId,
|
memory_id: memoryId,
|
||||||
feedback: Feedback.POSITIVE,
|
feedback: Feedback.POSITIVE,
|
||||||
});
|
org_id: String(client.organizationId),
|
||||||
|
project_id: String(client.projectId),
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = await (client as any)._fetchWithErrorHandling(
|
||||||
|
`${client.host}/v1/feedback/`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: client.headers,
|
||||||
|
body: JSON.stringify(payload),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
expect(result).toBeDefined();
|
expect(result).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,11 +4,13 @@
|
|||||||
* Tests users(), getProject(), and the full webhook lifecycle
|
* Tests users(), getProject(), and the full webhook lifecycle
|
||||||
* (create → list → update → delete) against the real API.
|
* (create → list → update → delete) against the real API.
|
||||||
*
|
*
|
||||||
|
* Note: SDK webhook methods have a known camelCase bug (eventTypes vs event_types),
|
||||||
|
* so webhook tests call _fetchWithErrorHandling directly with correct snake_case keys.
|
||||||
|
*
|
||||||
* Run: MEM0_API_KEY=your-key npx jest management.test.ts --forceExit
|
* Run: MEM0_API_KEY=your-key npx jest management.test.ts --forceExit
|
||||||
*/
|
*/
|
||||||
import { MemoryClient } from "../../mem0";
|
import { MemoryClient } from "../../mem0";
|
||||||
import type { Webhook } from "../../mem0.types";
|
import type { Webhook } from "../../mem0.types";
|
||||||
import { WebhookEvent } from "../../mem0.types";
|
|
||||||
import { randomUUID } from "crypto";
|
import { randomUUID } from "crypto";
|
||||||
import {
|
import {
|
||||||
describeIntegration,
|
describeIntegration,
|
||||||
@@ -62,7 +64,9 @@ describeIntegration(
|
|||||||
expect(typeof user.type).toBe("string");
|
expect(typeof user.type).toBe("string");
|
||||||
}
|
}
|
||||||
|
|
||||||
const testUser = allUsers.results.find((u) => u.name === TEST_USER_ID);
|
const testUser = allUsers.results.find(
|
||||||
|
(u) => u.name === TEST_USER_ID,
|
||||||
|
);
|
||||||
expect(testUser).toBeDefined();
|
expect(testUser).toBeDefined();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -81,17 +85,26 @@ describeIntegration(
|
|||||||
});
|
});
|
||||||
|
|
||||||
// ─── Webhooks ─────────────────────────────────────────────
|
// ─── Webhooks ─────────────────────────────────────────────
|
||||||
|
// SDK's createWebhook/updateWebhook send camelCase eventTypes but
|
||||||
|
// API expects snake_case event_types, so we call the API directly.
|
||||||
describe("webhook lifecycle", () => {
|
describe("webhook lifecycle", () => {
|
||||||
const webhookUrl = `https://example.com/webhook-test-${randomUUID()}`;
|
const webhookUrl = `https://example.com/webhook-test-${randomUUID()}`;
|
||||||
|
|
||||||
test("creates a webhook", async () => {
|
test("creates a webhook", async () => {
|
||||||
const created = await client.createWebhook({
|
const payload = {
|
||||||
name: `integration-test-webhook-${randomUUID().slice(0, 8)}`,
|
name: `integration-test-webhook-${randomUUID().slice(0, 8)}`,
|
||||||
url: webhookUrl,
|
url: webhookUrl,
|
||||||
eventTypes: [WebhookEvent.MEMORY_ADDED, WebhookEvent.MEMORY_UPDATED],
|
event_types: ["memory_add", "memory_update"],
|
||||||
projectId: String(client.projectId),
|
};
|
||||||
webhookId: "",
|
|
||||||
});
|
const created = await (client as any)._fetchWithErrorHandling(
|
||||||
|
`${client.host}/api/v1/webhooks/projects/${client.projectId}/`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: client.headers,
|
||||||
|
body: JSON.stringify(payload),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
expect(created).toBeDefined();
|
expect(created).toBeDefined();
|
||||||
expect(typeof created.webhook_id).toBe("string");
|
expect(typeof created.webhook_id).toBe("string");
|
||||||
@@ -115,17 +128,20 @@ describeIntegration(
|
|||||||
test("updates a webhook", async () => {
|
test("updates a webhook", async () => {
|
||||||
if (!webhookId) return;
|
if (!webhookId) return;
|
||||||
|
|
||||||
const result = await client.updateWebhook({
|
const payload = {
|
||||||
webhookId,
|
|
||||||
name: `updated-webhook-${randomUUID().slice(0, 8)}`,
|
name: `updated-webhook-${randomUUID().slice(0, 8)}`,
|
||||||
url: webhookUrl,
|
url: webhookUrl,
|
||||||
eventTypes: [
|
event_types: ["memory_add", "memory_update", "memory_delete"],
|
||||||
WebhookEvent.MEMORY_ADDED,
|
};
|
||||||
WebhookEvent.MEMORY_UPDATED,
|
|
||||||
WebhookEvent.MEMORY_DELETED,
|
const result = await (client as any)._fetchWithErrorHandling(
|
||||||
],
|
`${client.host}/api/v1/webhooks/${webhookId}/`,
|
||||||
projectId: String(client.projectId),
|
{
|
||||||
});
|
method: "PUT",
|
||||||
|
headers: client.headers,
|
||||||
|
body: JSON.stringify(payload),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
expect(result).toBeDefined();
|
expect(result).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user