Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions workspace-server/src/__tests__/services/GmailService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -830,4 +830,86 @@ describe('GmailService', () => {
expect(response.error).toBe('Failed to list labels');
});
});

describe('createLabel', () => {
it('should create a label with default visibility', async () => {
const mockLabel = {
id: 'Label_1',
name: 'Test Label',
type: 'user',
labelListVisibility: 'labelShow',
messageListVisibility: 'show',
};

mockGmailAPI.users.labels.create.mockResolvedValue({
data: mockLabel,
});

const result = await gmailService.createLabel({
name: 'Test Label',
});

expect(mockGmailAPI.users.labels.create).toHaveBeenCalledWith({
userId: 'me',
requestBody: {
name: 'Test Label',
labelListVisibility: 'labelShow',
messageListVisibility: 'show',
},
});

const response = JSON.parse(result.content[0].text);
expect(response).toEqual({
...mockLabel,
status: 'created',
});
});

it('should create a label with custom visibility settings', async () => {
const mockLabel = {
id: 'Label_2',
name: 'Hidden Label',
type: 'user',
labelListVisibility: 'labelHide',
messageListVisibility: 'hide',
};

mockGmailAPI.users.labels.create.mockResolvedValue({
data: mockLabel,
});

const result = await gmailService.createLabel({
name: 'Hidden Label',
labelListVisibility: 'labelHide',
messageListVisibility: 'hide',
});

expect(mockGmailAPI.users.labels.create).toHaveBeenCalledWith({
userId: 'me',
requestBody: {
name: 'Hidden Label',
labelListVisibility: 'labelHide',
messageListVisibility: 'hide',
},
});

const response = JSON.parse(result.content[0].text);
expect(response).toEqual({
...mockLabel,
status: 'created',
});
});

it('should handle create label errors', async () => {
const apiError = new Error('Label already exists');
mockGmailAPI.users.labels.create.mockRejectedValue(apiError);

const result = await gmailService.createLabel({
name: 'Duplicate Label',
});

const response = JSON.parse(result.content[0].text);
expect(response.error).toBe('Label already exists');
});
});
});
24 changes: 24 additions & 0 deletions workspace-server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1002,6 +1002,30 @@ There are a list of system labels that can be modified on a message:
gmailService.listLabels,
);

server.registerTool(
'gmail.createLabel',
{
description:
'Create a new Gmail label. Labels help organize emails into categories.',
inputSchema: {
name: z.string().min(1).describe('The display name of the label.'),
labelListVisibility: z
.enum(['labelShow', 'labelHide', 'labelShowIfUnread'])
.optional()
.describe(
'Visibility of the label in the label list. Defaults to "labelShow".',
),
messageListVisibility: z
.enum(['show', 'hide'])
.optional()
.describe(
'Visibility of messages with this label in the message list. Defaults to "show".',
),
},
},
gmailService.createLabel,
);

// Time tools
server.registerTool(
'time.getCurrentDate',
Expand Down
51 changes: 51 additions & 0 deletions workspace-server/src/services/GmailService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,57 @@ export class GmailService {
}
};

public createLabel = async ({
name,
labelListVisibility = 'labelShow',
messageListVisibility = 'show',
}: {
name: string;
labelListVisibility?: 'labelShow' | 'labelHide' | 'labelShowIfUnread';
messageListVisibility?: 'show' | 'hide';
}) => {
try {
logToFile(`Creating Gmail label: ${name}`);

const gmail = await this.getGmailClient();

const response = await gmail.users.labels.create({
userId: 'me',
requestBody: {
name,
labelListVisibility,
messageListVisibility,
},
});

const label = response.data;

logToFile(`Created label: ${label.name} with id: ${label.id}`);

return {
content: [
{
type: 'text' as const,
text: JSON.stringify(
{
id: label.id,
name: label.name,
type: label.type,
messageListVisibility: label.messageListVisibility,
labelListVisibility: label.labelListVisibility,
status: 'created',
},
null,
2,
),
},
],
};
} catch (error) {
return this.handleError(error, 'gmail.createLabel');
}
};

private extractAttachmentsAndBody(
payload: gmail_v1.Schema$MessagePart,
result: { body: string; attachments: GmailAttachment[] } = {
Expand Down
Loading