agent-office 0.5.0 → 0.6.1
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.
- package/LICENSE +1 -1
- package/README.md +259 -228
- package/dist/commands/cron-requests.d.ts +7 -0
- package/dist/commands/cron-requests.d.ts.map +1 -0
- package/dist/commands/cron-requests.js +31 -0
- package/dist/commands/cron-requests.js.map +1 -0
- package/dist/commands/crons.d.ts +10 -0
- package/dist/commands/crons.d.ts.map +1 -0
- package/dist/commands/crons.js +45 -0
- package/dist/commands/crons.js.map +1 -0
- package/dist/commands/hello.d.ts +5 -0
- package/dist/commands/hello.d.ts.map +1 -0
- package/dist/commands/hello.js +4 -0
- package/dist/commands/hello.js.map +1 -0
- package/dist/commands/messages.d.ts +5 -0
- package/dist/commands/messages.d.ts.map +1 -0
- package/dist/commands/messages.js +18 -0
- package/dist/commands/messages.js.map +1 -0
- package/dist/commands/sessions.d.ts +13 -0
- package/dist/commands/sessions.d.ts.map +1 -0
- package/dist/commands/sessions.js +58 -0
- package/dist/commands/sessions.js.map +1 -0
- package/dist/commands/task-columns.d.ts +2 -0
- package/dist/commands/task-columns.d.ts.map +1 -0
- package/dist/commands/task-columns.js +13 -0
- package/dist/commands/task-columns.js.map +1 -0
- package/dist/commands/tasks.d.ts +11 -0
- package/dist/commands/tasks.d.ts.map +1 -0
- package/dist/commands/tasks.js +75 -0
- package/dist/commands/tasks.js.map +1 -0
- package/dist/config.test.d.ts +2 -0
- package/dist/config.test.d.ts.map +1 -0
- package/dist/config.test.js +50 -0
- package/dist/config.test.js.map +1 -0
- package/dist/db/index.d.ts +6 -70
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +4 -11
- package/dist/db/index.js.map +1 -0
- package/dist/db/mock-storage.d.ts +79 -0
- package/dist/db/mock-storage.d.ts.map +1 -0
- package/dist/db/mock-storage.js +381 -0
- package/dist/db/mock-storage.js.map +1 -0
- package/dist/db/mock-storage.test.d.ts +2 -0
- package/dist/db/mock-storage.test.d.ts.map +1 -0
- package/dist/db/mock-storage.test.js +234 -0
- package/dist/db/mock-storage.test.js.map +1 -0
- package/dist/db/postgresql-storage.d.ts +10 -8
- package/dist/db/postgresql-storage.d.ts.map +1 -0
- package/dist/db/postgresql-storage.js +76 -42
- package/dist/db/postgresql-storage.js.map +1 -0
- package/dist/db/sqlite-storage.d.ts +9 -8
- package/dist/db/sqlite-storage.d.ts.map +1 -0
- package/dist/db/sqlite-storage.js +75 -41
- package/dist/db/sqlite-storage.js.map +1 -0
- package/dist/db/storage-base.d.ts +7 -8
- package/dist/db/storage-base.d.ts.map +1 -0
- package/dist/db/storage-base.js +3 -2
- package/dist/db/storage-base.js.map +1 -0
- package/dist/db/storage.d.ts +12 -12
- package/dist/db/storage.d.ts.map +1 -0
- package/dist/db/storage.js +1 -0
- package/dist/db/storage.js.map +1 -0
- package/dist/db/types.d.ts +67 -0
- package/dist/db/types.d.ts.map +1 -0
- package/dist/db/types.js +2 -0
- package/dist/db/types.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +397 -0
- package/dist/index.js.map +1 -0
- package/dist/index.test.d.ts +2 -0
- package/dist/index.test.d.ts.map +1 -0
- package/dist/index.test.js +49 -0
- package/dist/index.test.js.map +1 -0
- package/dist/lib/output.d.ts +2 -0
- package/dist/lib/output.d.ts.map +1 -0
- package/dist/lib/output.js +8 -0
- package/dist/lib/output.js.map +1 -0
- package/dist/services/cron-service.constraints.test.d.ts +2 -0
- package/dist/services/cron-service.constraints.test.d.ts.map +1 -0
- package/dist/services/cron-service.constraints.test.js +90 -0
- package/dist/services/cron-service.constraints.test.js.map +1 -0
- package/dist/services/cron-service.d.ts +45 -0
- package/dist/services/cron-service.d.ts.map +1 -0
- package/dist/services/cron-service.js +157 -0
- package/dist/services/cron-service.js.map +1 -0
- package/dist/services/cron-service.test.d.ts +2 -0
- package/dist/services/cron-service.test.d.ts.map +1 -0
- package/dist/services/cron-service.test.js +280 -0
- package/dist/services/cron-service.test.js.map +1 -0
- package/dist/services/index.d.ts +5 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +5 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/message-service.d.ts +16 -0
- package/dist/services/message-service.d.ts.map +1 -0
- package/dist/services/message-service.js +39 -0
- package/dist/services/message-service.js.map +1 -0
- package/dist/services/message-service.test.d.ts +2 -0
- package/dist/services/message-service.test.d.ts.map +1 -0
- package/dist/services/message-service.test.js +145 -0
- package/dist/services/message-service.test.js.map +1 -0
- package/dist/services/session-service.constraints.test.d.ts +2 -0
- package/dist/services/session-service.constraints.test.d.ts.map +1 -0
- package/dist/services/session-service.constraints.test.js +34 -0
- package/dist/services/session-service.constraints.test.js.map +1 -0
- package/dist/services/session-service.d.ts +27 -0
- package/dist/services/session-service.d.ts.map +1 -0
- package/dist/services/session-service.js +55 -0
- package/dist/services/session-service.js.map +1 -0
- package/dist/services/session-service.test.d.ts +2 -0
- package/dist/services/session-service.test.d.ts.map +1 -0
- package/dist/services/session-service.test.js +87 -0
- package/dist/services/session-service.test.js.map +1 -0
- package/dist/services/task-service.d.ts +25 -0
- package/dist/services/task-service.d.ts.map +1 -0
- package/dist/services/task-service.js +87 -0
- package/dist/services/task-service.js.map +1 -0
- package/dist/services/task-service.test.d.ts +2 -0
- package/dist/services/task-service.test.d.ts.map +1 -0
- package/dist/services/task-service.test.js +180 -0
- package/dist/services/task-service.test.js.map +1 -0
- package/package.json +41 -42
- package/dist/cli.d.ts +0 -2
- package/dist/cli.js +0 -317
- package/dist/commands/communicator.d.ts +0 -9
- package/dist/commands/communicator.js +0 -2232
- package/dist/commands/manage.d.ts +0 -5
- package/dist/commands/manage.js +0 -20
- package/dist/commands/notifier.d.ts +0 -11
- package/dist/commands/notifier.js +0 -100
- package/dist/commands/screensaver.d.ts +0 -8
- package/dist/commands/screensaver.js +0 -1280
- package/dist/commands/serve.d.ts +0 -13
- package/dist/commands/serve.js +0 -95
- package/dist/commands/task-board.d.ts +0 -29
- package/dist/commands/task-board.js +0 -251
- package/dist/commands/worker.d.ts +0 -16
- package/dist/commands/worker.js +0 -145
- package/dist/db/migrate.d.ts +0 -2
- package/dist/db/migrate.js +0 -3
- package/dist/lib/agentic-coding-server.d.ts +0 -66
- package/dist/lib/agentic-coding-server.js +0 -7
- package/dist/lib/notifier.d.ts +0 -18
- package/dist/lib/notifier.js +0 -15
- package/dist/lib/opencode-coding-server.d.ts +0 -11
- package/dist/lib/opencode-coding-server.js +0 -66
- package/dist/lib/pi-coding-server.d.ts +0 -20
- package/dist/lib/pi-coding-server.js +0 -162
- package/dist/manage/app.d.ts +0 -6
- package/dist/manage/app.js +0 -128
- package/dist/manage/components/AgentCode.d.ts +0 -8
- package/dist/manage/components/AgentCode.js +0 -73
- package/dist/manage/components/CreateSession.d.ts +0 -8
- package/dist/manage/components/CreateSession.js +0 -37
- package/dist/manage/components/CronList.d.ts +0 -9
- package/dist/manage/components/CronList.js +0 -321
- package/dist/manage/components/CronRequests.d.ts +0 -8
- package/dist/manage/components/CronRequests.js +0 -181
- package/dist/manage/components/DeleteSession.d.ts +0 -7
- package/dist/manage/components/DeleteSession.js +0 -55
- package/dist/manage/components/InjectText.d.ts +0 -8
- package/dist/manage/components/InjectText.js +0 -51
- package/dist/manage/components/ItemSelector.d.ts +0 -7
- package/dist/manage/components/ItemSelector.js +0 -20
- package/dist/manage/components/MenuSelect.d.ts +0 -13
- package/dist/manage/components/MenuSelect.js +0 -22
- package/dist/manage/components/MyMail.d.ts +0 -9
- package/dist/manage/components/MyMail.js +0 -143
- package/dist/manage/components/Profile.d.ts +0 -8
- package/dist/manage/components/Profile.js +0 -60
- package/dist/manage/components/ReadMail.d.ts +0 -8
- package/dist/manage/components/ReadMail.js +0 -110
- package/dist/manage/components/SendMessage.d.ts +0 -9
- package/dist/manage/components/SendMessage.js +0 -79
- package/dist/manage/components/SessionList.d.ts +0 -9
- package/dist/manage/components/SessionList.js +0 -608
- package/dist/manage/components/SessionSidebar.d.ts +0 -6
- package/dist/manage/components/SessionSidebar.js +0 -24
- package/dist/manage/components/TailMessages.d.ts +0 -8
- package/dist/manage/components/TailMessages.js +0 -126
- package/dist/manage/hooks/useApi.d.ts +0 -147
- package/dist/manage/hooks/useApi.js +0 -181
- package/dist/server/cron.d.ts +0 -25
- package/dist/server/cron.js +0 -107
- package/dist/server/index.d.ts +0 -4
- package/dist/server/index.js +0 -22
- package/dist/server/routes.d.ts +0 -13
- package/dist/server/routes.js +0 -1396
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-service.test.d.ts","sourceRoot":"","sources":["../../src/services/message-service.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
2
|
+
import { createMockStorage } from '../db/mock-storage.js';
|
|
3
|
+
import { MessageService } from './message-service.js';
|
|
4
|
+
describe('MessageService', () => {
|
|
5
|
+
let storage;
|
|
6
|
+
let service;
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
storage = createMockStorage();
|
|
9
|
+
service = new MessageService(storage);
|
|
10
|
+
});
|
|
11
|
+
describe('sendMessage', () => {
|
|
12
|
+
it('should send message to single recipient', async () => {
|
|
13
|
+
const messages = await service.sendMessage('sender1', ['recipient1'], 'Hello!');
|
|
14
|
+
expect(messages).toHaveLength(1);
|
|
15
|
+
expect(messages[0].from_name).toBe('sender1');
|
|
16
|
+
expect(messages[0].to_name).toBe('recipient1');
|
|
17
|
+
expect(messages[0].body).toBe('Hello!');
|
|
18
|
+
expect(messages[0].read).toBe(false);
|
|
19
|
+
});
|
|
20
|
+
it('should send message to multiple recipients', async () => {
|
|
21
|
+
const messages = await service.sendMessage('sender1', ['recipient1', 'recipient2', 'recipient3'], 'Hello all!');
|
|
22
|
+
expect(messages).toHaveLength(3);
|
|
23
|
+
expect(messages.map(m => m.to_name)).toEqual(['recipient1', 'recipient2', 'recipient3']);
|
|
24
|
+
});
|
|
25
|
+
it('should create messages with correct timestamps', async () => {
|
|
26
|
+
const before = new Date();
|
|
27
|
+
const messages = await service.sendMessage('sender1', ['recipient1'], 'Hello!');
|
|
28
|
+
const after = new Date();
|
|
29
|
+
expect(messages[0].created_at.getTime()).toBeGreaterThanOrEqual(before.getTime());
|
|
30
|
+
expect(messages[0].created_at.getTime()).toBeLessThanOrEqual(after.getTime());
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
describe('listMessagesForRecipient', () => {
|
|
34
|
+
it('should return messages for recipient', async () => {
|
|
35
|
+
await service.sendMessage('sender1', ['recipient1'], 'Message 1');
|
|
36
|
+
await service.sendMessage('sender2', ['recipient1'], 'Message 2');
|
|
37
|
+
await service.sendMessage('sender1', ['recipient2'], 'Message 3');
|
|
38
|
+
const messages = await service.listMessagesForRecipient('recipient1');
|
|
39
|
+
expect(messages).toHaveLength(2);
|
|
40
|
+
expect(messages.map(m => m.body).sort()).toEqual(['Message 1', 'Message 2']);
|
|
41
|
+
});
|
|
42
|
+
it('should filter by unread only', async () => {
|
|
43
|
+
await service.sendMessage('sender1', ['recipient1'], 'Unread message');
|
|
44
|
+
const readMessage = await service.sendMessage('sender1', ['recipient1'], 'Read message');
|
|
45
|
+
await storage.markMessageAsRead(readMessage[0].id);
|
|
46
|
+
const messages = await service.listMessagesForRecipient('recipient1', { unread: true });
|
|
47
|
+
expect(messages).toHaveLength(1);
|
|
48
|
+
expect(messages[0].body).toBe('Unread message');
|
|
49
|
+
});
|
|
50
|
+
it('should filter by olderThanHours', async () => {
|
|
51
|
+
// Create a message
|
|
52
|
+
await service.sendMessage('sender1', ['recipient1'], 'Old message');
|
|
53
|
+
// Filter should exclude recent messages (assuming test runs quickly)
|
|
54
|
+
const messages = await service.listMessagesForRecipient('recipient1', { olderThanHours: 0 });
|
|
55
|
+
expect(messages).toHaveLength(0);
|
|
56
|
+
});
|
|
57
|
+
it('should return messages sorted by created_at desc', async () => {
|
|
58
|
+
await service.sendMessage('sender1', ['recipient1'], 'First');
|
|
59
|
+
await new Promise(resolve => setTimeout(resolve, 10));
|
|
60
|
+
await service.sendMessage('sender1', ['recipient1'], 'Second');
|
|
61
|
+
const messages = await service.listMessagesForRecipient('recipient1');
|
|
62
|
+
expect(messages[0].body).toBe('Second');
|
|
63
|
+
expect(messages[1].body).toBe('First');
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
describe('listMessagesFromSender', () => {
|
|
67
|
+
it('should return messages from sender', async () => {
|
|
68
|
+
await service.sendMessage('sender1', ['recipient1'], 'Message 1');
|
|
69
|
+
await service.sendMessage('sender1', ['recipient2'], 'Message 2');
|
|
70
|
+
await service.sendMessage('sender2', ['recipient1'], 'Message 3');
|
|
71
|
+
const messages = await service.listMessagesFromSender('sender1');
|
|
72
|
+
expect(messages).toHaveLength(2);
|
|
73
|
+
expect(messages.map(m => m.body).sort()).toEqual(['Message 1', 'Message 2']);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
describe('markMessageAsRead', () => {
|
|
77
|
+
it('should mark message as read', async () => {
|
|
78
|
+
const [message] = await service.sendMessage('sender1', ['recipient1'], 'Hello!');
|
|
79
|
+
expect(message.read).toBe(false);
|
|
80
|
+
const updated = await service.markMessageAsRead(message.id);
|
|
81
|
+
expect(updated).not.toBeNull();
|
|
82
|
+
expect(updated?.read).toBe(true);
|
|
83
|
+
});
|
|
84
|
+
it('should return null for non-existent message', async () => {
|
|
85
|
+
const result = await service.markMessageAsRead(999);
|
|
86
|
+
expect(result).toBeNull();
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
describe('countUnreadBySender', () => {
|
|
90
|
+
it('should count unread messages by sender', async () => {
|
|
91
|
+
await service.sendMessage('sender1', ['recipient1'], 'Unread 1');
|
|
92
|
+
await service.sendMessage('sender1', ['recipient1'], 'Unread 2');
|
|
93
|
+
await service.sendMessage('sender2', ['recipient1'], 'Unread 3');
|
|
94
|
+
const readMessages = await service.sendMessage('sender1', ['recipient1'], 'Read');
|
|
95
|
+
await storage.markMessageAsRead(readMessages[0].id);
|
|
96
|
+
const counts = await service.countUnreadBySender('recipient1');
|
|
97
|
+
expect(counts.get('sender1')).toBe(2);
|
|
98
|
+
expect(counts.get('sender2')).toBe(1);
|
|
99
|
+
});
|
|
100
|
+
it('should return empty map when no unread messages', async () => {
|
|
101
|
+
const counts = await service.countUnreadBySender('recipient1');
|
|
102
|
+
expect(counts.size).toBe(0);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
describe('checkUnreadMail', () => {
|
|
106
|
+
it('should return true when unread messages exist', async () => {
|
|
107
|
+
await service.sendMessage('sender1', ['recipient1'], 'Hello!');
|
|
108
|
+
const hasUnread = await service.checkUnreadMail('recipient1');
|
|
109
|
+
expect(hasUnread).toBe(true);
|
|
110
|
+
});
|
|
111
|
+
it('should return false when no unread messages exist', async () => {
|
|
112
|
+
await service.sendMessage('sender1', ['recipient1'], 'Hello!');
|
|
113
|
+
const messages = await storage.listMessagesForRecipient('recipient1');
|
|
114
|
+
await storage.markMessageAsRead(messages[0].id);
|
|
115
|
+
const hasUnread = await service.checkUnreadMail('recipient1');
|
|
116
|
+
expect(hasUnread).toBe(false);
|
|
117
|
+
});
|
|
118
|
+
it('should return false when no messages exist', async () => {
|
|
119
|
+
const hasUnread = await service.checkUnreadMail('recipient1');
|
|
120
|
+
expect(hasUnread).toBe(false);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
describe('getUnreadMail', () => {
|
|
124
|
+
it('should return unread messages and mark them as read', async () => {
|
|
125
|
+
await service.sendMessage('sender1', ['recipient1'], 'Message 1');
|
|
126
|
+
await service.sendMessage('sender2', ['recipient1'], 'Message 2');
|
|
127
|
+
await storage.markMessageAsRead((await storage.listMessagesForRecipient('recipient1'))[0].id);
|
|
128
|
+
const unread = await service.getUnreadMail('recipient1');
|
|
129
|
+
expect(unread).toHaveLength(1);
|
|
130
|
+
expect(unread[0].body).toBe('Message 2');
|
|
131
|
+
expect(unread[0].read).toBe(false);
|
|
132
|
+
// Verify they were marked as read
|
|
133
|
+
const allMessages = await storage.listMessagesForRecipient('recipient1');
|
|
134
|
+
expect(allMessages.every(m => m.read)).toBe(true);
|
|
135
|
+
});
|
|
136
|
+
it('should return empty array when no unread messages', async () => {
|
|
137
|
+
await service.sendMessage('sender1', ['recipient1'], 'Hello!');
|
|
138
|
+
const messages = await storage.listMessagesForRecipient('recipient1');
|
|
139
|
+
await storage.markMessageAsRead(messages[0].id);
|
|
140
|
+
const unread = await service.getUnreadMail('recipient1');
|
|
141
|
+
expect(unread).toEqual([]);
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
//# sourceMappingURL=message-service.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-service.test.js","sourceRoot":"","sources":["../../src/services/message-service.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-service.constraints.test.d.ts","sourceRoot":"","sources":["../../src/services/session-service.constraints.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
2
|
+
import { createMockStorage } from '../db/mock-storage.js';
|
|
3
|
+
import { SessionService } from './session-service.js';
|
|
4
|
+
describe('SessionService - Constraint Handling', () => {
|
|
5
|
+
let storage;
|
|
6
|
+
let service;
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
storage = createMockStorage();
|
|
9
|
+
service = new SessionService(storage);
|
|
10
|
+
});
|
|
11
|
+
describe('UNIQUE constraint: sessions.name', () => {
|
|
12
|
+
it('should throw error when creating session with duplicate name', async () => {
|
|
13
|
+
await service.createSession('duplicate', 'id1', 'agent1');
|
|
14
|
+
await expect(service.createSession('duplicate', 'id2', 'agent2')).rejects.toThrow('Coworker duplicate already exists');
|
|
15
|
+
});
|
|
16
|
+
it('should allow creating sessions with different names', async () => {
|
|
17
|
+
await service.createSession('session1', 'id1', 'agent1');
|
|
18
|
+
await service.createSession('session2', 'id2', 'agent2');
|
|
19
|
+
const sessions = await storage.listSessions();
|
|
20
|
+
expect(sessions).toHaveLength(2);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
describe('UNIQUE constraint: sessions.session_id', () => {
|
|
24
|
+
it('should handle duplicate session_id appropriately', async () => {
|
|
25
|
+
// This constraint is handled at database level
|
|
26
|
+
// Our mock should simulate this behavior
|
|
27
|
+
await storage.createSession('session1', 'same-id', 'agent1');
|
|
28
|
+
// In real implementation, this would throw from DB
|
|
29
|
+
// For now, our mock allows it (which is a limitation)
|
|
30
|
+
// In production, this would violate UNIQUE constraint
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
//# sourceMappingURL=session-service.constraints.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-service.constraints.test.js","sourceRoot":"","sources":["../../src/services/session-service.constraints.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AACzD,OAAO,EAA0B,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AACjF,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAErD,QAAQ,CAAC,sCAAsC,EAAE,GAAG,EAAE;IACpD,IAAI,OAA+B,CAAA;IACnC,IAAI,OAAuB,CAAA;IAE3B,UAAU,CAAC,GAAG,EAAE;QACd,OAAO,GAAG,iBAAiB,EAAE,CAAA;QAC7B,OAAO,GAAG,IAAI,cAAc,CAAC,OAAO,CAAC,CAAA;IACvC,CAAC,CAAC,CAAA;IAEF,QAAQ,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAChD,EAAE,CAAC,8DAA8D,EAAE,KAAK,IAAI,EAAE;YAC5E,MAAM,OAAO,CAAC,aAAa,CAAC,WAAW,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAA;YAEzD,MAAM,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,WAAW,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAC/E,mCAAmC,CACpC,CAAA;QACH,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;YACnE,MAAM,OAAO,CAAC,aAAa,CAAC,UAAU,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAA;YACxD,MAAM,OAAO,CAAC,aAAa,CAAC,UAAU,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAA;YAExD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,YAAY,EAAE,CAAA;YAC7C,MAAM,CAAC,QAAQ,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;QAClC,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,QAAQ,CAAC,wCAAwC,EAAE,GAAG,EAAE;QACtD,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;YAChE,+CAA+C;YAC/C,yCAAyC;YACzC,MAAM,OAAO,CAAC,aAAa,CAAC,UAAU,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAA;YAE5D,mDAAmD;YACnD,sDAAsD;YACtD,sDAAsD;QACxD,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { AgentOfficeStorage, SessionRow } from '../db/index.js';
|
|
2
|
+
export interface CoworkerInfo {
|
|
3
|
+
name: string;
|
|
4
|
+
agent: string;
|
|
5
|
+
status: string | null;
|
|
6
|
+
description: string | null;
|
|
7
|
+
philosophy: string | null;
|
|
8
|
+
visual_description: string | null;
|
|
9
|
+
created_at: Date;
|
|
10
|
+
}
|
|
11
|
+
export declare class SessionService {
|
|
12
|
+
private storage;
|
|
13
|
+
constructor(storage: AgentOfficeStorage);
|
|
14
|
+
listCoworkers(): Promise<CoworkerInfo[]>;
|
|
15
|
+
getCoworkerInfo(name: string): Promise<CoworkerInfo>;
|
|
16
|
+
updateCoworker(name: string, updates: {
|
|
17
|
+
agent?: string;
|
|
18
|
+
status?: string | null;
|
|
19
|
+
description?: string | null;
|
|
20
|
+
philosophy?: string | null;
|
|
21
|
+
visual_description?: string | null;
|
|
22
|
+
}): Promise<SessionRow>;
|
|
23
|
+
createSession(name: string, sessionId: string, agent: string): Promise<SessionRow>;
|
|
24
|
+
getSessionByName(name: string): Promise<SessionRow | null>;
|
|
25
|
+
deleteSession(id: number): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=session-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-service.d.ts","sourceRoot":"","sources":["../../src/services/session-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAE/D,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAA;IACjC,UAAU,EAAE,IAAI,CAAA;CACjB;AAED,qBAAa,cAAc;IACb,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,kBAAkB;IAEzC,aAAa,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;IAaxC,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAgBpD,cAAc,CAClB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE;QACP,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QACtB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QAC3B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QAC1B,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KACnC,GACA,OAAO,CAAC,UAAU,CAAC;IAShB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAQlF,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAI1D,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAG/C"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export class SessionService {
|
|
2
|
+
storage;
|
|
3
|
+
constructor(storage) {
|
|
4
|
+
this.storage = storage;
|
|
5
|
+
}
|
|
6
|
+
async listCoworkers() {
|
|
7
|
+
const sessions = await this.storage.listSessions();
|
|
8
|
+
return sessions.map(session => ({
|
|
9
|
+
name: session.name,
|
|
10
|
+
agent: session.agent,
|
|
11
|
+
status: session.status,
|
|
12
|
+
description: session.description,
|
|
13
|
+
philosophy: session.philosophy,
|
|
14
|
+
visual_description: session.visual_description,
|
|
15
|
+
created_at: session.created_at,
|
|
16
|
+
}));
|
|
17
|
+
}
|
|
18
|
+
async getCoworkerInfo(name) {
|
|
19
|
+
const session = await this.storage.getSessionByName(name);
|
|
20
|
+
if (!session) {
|
|
21
|
+
throw new Error(`Coworker ${name} not found`);
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
name: session.name,
|
|
25
|
+
agent: session.agent,
|
|
26
|
+
status: session.status,
|
|
27
|
+
description: session.description,
|
|
28
|
+
philosophy: session.philosophy,
|
|
29
|
+
visual_description: session.visual_description,
|
|
30
|
+
created_at: session.created_at,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
async updateCoworker(name, updates) {
|
|
34
|
+
const session = await this.storage.getSessionByName(name);
|
|
35
|
+
if (!session) {
|
|
36
|
+
throw new Error(`Coworker ${name} not found`);
|
|
37
|
+
}
|
|
38
|
+
const updated = await this.storage.updateSession(name, updates);
|
|
39
|
+
return updated;
|
|
40
|
+
}
|
|
41
|
+
async createSession(name, sessionId, agent) {
|
|
42
|
+
const exists = await this.storage.sessionExists(name);
|
|
43
|
+
if (exists) {
|
|
44
|
+
throw new Error(`Coworker ${name} already exists`);
|
|
45
|
+
}
|
|
46
|
+
return this.storage.createSession(name, sessionId, agent);
|
|
47
|
+
}
|
|
48
|
+
async getSessionByName(name) {
|
|
49
|
+
return this.storage.getSessionByName(name);
|
|
50
|
+
}
|
|
51
|
+
async deleteSession(id) {
|
|
52
|
+
await this.storage.deleteSession(id);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=session-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-service.js","sourceRoot":"","sources":["../../src/services/session-service.ts"],"names":[],"mappings":"AAYA,MAAM,OAAO,cAAc;IACL;IAApB,YAAoB,OAA2B;QAA3B,YAAO,GAAP,OAAO,CAAoB;IAAG,CAAC;IAEnD,KAAK,CAAC,aAAa;QACjB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAA;QAClD,OAAO,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAC9B,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,kBAAkB,EAAE,OAAO,CAAC,kBAAkB;YAC9C,UAAU,EAAE,OAAO,CAAC,UAAU;SAC/B,CAAC,CAAC,CAAA;IACL,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,IAAY;QAChC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAA;QACzD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,YAAY,IAAI,YAAY,CAAC,CAAA;QAC/C,CAAC;QACD,OAAO;YACL,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,kBAAkB,EAAE,OAAO,CAAC,kBAAkB;YAC9C,UAAU,EAAE,OAAO,CAAC,UAAU;SAC/B,CAAA;IACH,CAAC;IAED,KAAK,CAAC,cAAc,CAClB,IAAY,EACZ,OAMC;QAED,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAA;QACzD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,YAAY,IAAI,YAAY,CAAC,CAAA;QAC/C,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QAC/D,OAAO,OAAQ,CAAA;IACjB,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,IAAY,EAAE,SAAiB,EAAE,KAAa;QAChE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,CAAA;QACrD,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,YAAY,IAAI,iBAAiB,CAAC,CAAA;QACpD,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,CAAA;IAC3D,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,IAAY;QACjC,OAAO,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAA;IAC5C,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,EAAU;QAC5B,MAAM,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC,CAAA;IACtC,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-service.test.d.ts","sourceRoot":"","sources":["../../src/services/session-service.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
2
|
+
import { createMockStorage } from '../db/mock-storage.js';
|
|
3
|
+
import { SessionService } from './session-service.js';
|
|
4
|
+
describe('SessionService', () => {
|
|
5
|
+
let storage;
|
|
6
|
+
let service;
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
storage = createMockStorage();
|
|
9
|
+
service = new SessionService(storage);
|
|
10
|
+
});
|
|
11
|
+
describe('listCoworkers', () => {
|
|
12
|
+
it('should return empty array when no sessions exist', async () => {
|
|
13
|
+
const coworkers = await service.listCoworkers();
|
|
14
|
+
expect(coworkers).toEqual([]);
|
|
15
|
+
});
|
|
16
|
+
it('should return all sessions as coworkers', async () => {
|
|
17
|
+
await storage.createSession('session1', 'id1', 'agent1');
|
|
18
|
+
await new Promise(resolve => setTimeout(resolve, 10)); // Ensure different timestamps
|
|
19
|
+
await storage.createSession('session2', 'id2', 'agent2');
|
|
20
|
+
const coworkers = await service.listCoworkers();
|
|
21
|
+
expect(coworkers).toHaveLength(2);
|
|
22
|
+
expect(coworkers[0].name).toBe('session2'); // Most recent first
|
|
23
|
+
expect(coworkers[1].name).toBe('session1');
|
|
24
|
+
});
|
|
25
|
+
it('should include agent and status info', async () => {
|
|
26
|
+
await storage.createSession('session1', 'id1', 'agent1');
|
|
27
|
+
await storage.updateSession('session1', { status: 'busy' });
|
|
28
|
+
const coworkers = await service.listCoworkers();
|
|
29
|
+
expect(coworkers[0].agent).toBe('agent1');
|
|
30
|
+
expect(coworkers[0].status).toBe('busy');
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
describe('updateCoworker', () => {
|
|
34
|
+
it('should set status for existing session', async () => {
|
|
35
|
+
await storage.createSession('session1', 'id1', 'agent1');
|
|
36
|
+
const updated = await service.updateCoworker('session1', { status: 'available' });
|
|
37
|
+
expect(updated.status).toBe('available');
|
|
38
|
+
const stored = await storage.getSessionByName('session1');
|
|
39
|
+
expect(stored?.status).toBe('available');
|
|
40
|
+
});
|
|
41
|
+
it('should clear status when null is passed', async () => {
|
|
42
|
+
await storage.createSession('session1', 'id1', 'agent1');
|
|
43
|
+
await storage.updateSession('session1', { status: 'busy' });
|
|
44
|
+
const updated = await service.updateCoworker('session1', { status: null });
|
|
45
|
+
expect(updated.status).toBeNull();
|
|
46
|
+
});
|
|
47
|
+
it('should throw error for non-existent session', async () => {
|
|
48
|
+
await expect(service.updateCoworker('nonexistent', { status: 'available' })).rejects.toThrow('Coworker nonexistent not found');
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
describe('createSession', () => {
|
|
52
|
+
it('should create a new session', async () => {
|
|
53
|
+
const session = await service.createSession('session1', 'id1', 'agent1');
|
|
54
|
+
expect(session.name).toBe('session1');
|
|
55
|
+
expect(session.session_id).toBe('id1');
|
|
56
|
+
expect(session.agent).toBe('agent1');
|
|
57
|
+
});
|
|
58
|
+
it('should throw error when session already exists', async () => {
|
|
59
|
+
await service.createSession('session1', 'id1', 'agent1');
|
|
60
|
+
await expect(service.createSession('session1', 'id2', 'agent2')).rejects.toThrow('Coworker session1 already exists');
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
describe('getSessionByName', () => {
|
|
64
|
+
it('should return session by name', async () => {
|
|
65
|
+
await storage.createSession('session1', 'id1', 'agent1');
|
|
66
|
+
const session = await service.getSessionByName('session1');
|
|
67
|
+
expect(session).not.toBeNull();
|
|
68
|
+
expect(session?.name).toBe('session1');
|
|
69
|
+
});
|
|
70
|
+
it('should return null for non-existent session', async () => {
|
|
71
|
+
const session = await service.getSessionByName('nonexistent');
|
|
72
|
+
expect(session).toBeNull();
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
describe('deleteSession', () => {
|
|
76
|
+
it('should delete existing session', async () => {
|
|
77
|
+
const session = await storage.createSession('session1', 'id1', 'agent1');
|
|
78
|
+
await service.deleteSession(session.id);
|
|
79
|
+
const stored = await storage.getSessionByName('session1');
|
|
80
|
+
expect(stored).toBeNull();
|
|
81
|
+
});
|
|
82
|
+
it('should not throw when deleting non-existent session', async () => {
|
|
83
|
+
await expect(service.deleteSession(999)).resolves.not.toThrow();
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
//# sourceMappingURL=session-service.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-service.test.js","sourceRoot":"","sources":["../../src/services/session-service.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { AgentOfficeStorage, TaskRow } from '../db/index.js';
|
|
2
|
+
export type ColumnName = 'idea' | 'approved idea' | 'working on' | 'blocked' | 'ready for review' | 'done';
|
|
3
|
+
export interface ColumnStats {
|
|
4
|
+
column: string;
|
|
5
|
+
count: number;
|
|
6
|
+
}
|
|
7
|
+
export declare class TaskService {
|
|
8
|
+
private storage;
|
|
9
|
+
constructor(storage: AgentOfficeStorage);
|
|
10
|
+
createTask(title: string, description: string, assignee: string | null, column: string, dependencies: number[]): Promise<TaskRow>;
|
|
11
|
+
listTasks(): Promise<TaskRow[]>;
|
|
12
|
+
getTaskById(id: number): Promise<TaskRow | null>;
|
|
13
|
+
updateTask(id: number, updates: Partial<Pick<TaskRow, 'title' | 'description' | 'assignee' | 'column' | 'dependencies'>>): Promise<TaskRow>;
|
|
14
|
+
deleteTask(id: number): Promise<void>;
|
|
15
|
+
searchTasks(query: string, filters?: {
|
|
16
|
+
assignee?: string;
|
|
17
|
+
column?: string;
|
|
18
|
+
}): Promise<TaskRow[]>;
|
|
19
|
+
assignTask(id: number, assignee: string): Promise<TaskRow>;
|
|
20
|
+
unassignTask(id: number): Promise<TaskRow>;
|
|
21
|
+
moveTask(id: number, newColumn: string): Promise<TaskRow>;
|
|
22
|
+
getColumnStats(): Promise<ColumnStats[]>;
|
|
23
|
+
getTasksByAssignee(assignee: string, column?: string): Promise<TaskRow[]>;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=task-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-service.d.ts","sourceRoot":"","sources":["../../src/services/task-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAE5D,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,eAAe,GAAG,YAAY,GAAG,SAAS,GAAG,kBAAkB,GAAG,MAAM,CAAA;AAE1G,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;CACd;AAED,qBAAa,WAAW;IACV,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,kBAAkB;IAEzC,UAAU,CACd,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EAAE,GACrB,OAAO,CAAC,OAAO,CAAC;IAUb,SAAS,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAI/B,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAIhD,UAAU,CACd,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,aAAa,GAAG,UAAU,GAAG,QAAQ,GAAG,cAAc,CAAC,CAAC,GAChG,OAAO,CAAC,OAAO,CAAC;IAqBb,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQrC,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAIhG,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI1D,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI1C,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAkBzD,cAAc,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAmBxC,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;CAGhF"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
export class TaskService {
|
|
2
|
+
storage;
|
|
3
|
+
constructor(storage) {
|
|
4
|
+
this.storage = storage;
|
|
5
|
+
}
|
|
6
|
+
async createTask(title, description, assignee, column, dependencies) {
|
|
7
|
+
// Validate column name
|
|
8
|
+
const validColumns = ['idea', 'approved idea', 'working on', 'blocked', 'ready for review', 'done'];
|
|
9
|
+
if (!validColumns.includes(column)) {
|
|
10
|
+
throw new Error(`Invalid column "${column}". Valid columns: ${validColumns.join(', ')}`);
|
|
11
|
+
}
|
|
12
|
+
return this.storage.createTask(title, description, assignee, column, dependencies);
|
|
13
|
+
}
|
|
14
|
+
async listTasks() {
|
|
15
|
+
return this.storage.listTasks();
|
|
16
|
+
}
|
|
17
|
+
async getTaskById(id) {
|
|
18
|
+
return this.storage.getTaskById(id);
|
|
19
|
+
}
|
|
20
|
+
async updateTask(id, updates) {
|
|
21
|
+
const task = await this.storage.getTaskById(id);
|
|
22
|
+
if (!task) {
|
|
23
|
+
throw new Error(`Task ${id} not found`);
|
|
24
|
+
}
|
|
25
|
+
// Validate column if provided
|
|
26
|
+
if (updates.column) {
|
|
27
|
+
const validColumns = ['idea', 'approved idea', 'working on', 'blocked', 'ready for review', 'done'];
|
|
28
|
+
if (!validColumns.includes(updates.column)) {
|
|
29
|
+
throw new Error(`Invalid column "${updates.column}". Valid columns: ${validColumns.join(', ')}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const updated = await this.storage.updateTask(id, updates);
|
|
33
|
+
if (!updated) {
|
|
34
|
+
throw new Error(`Failed to update task ${id}`);
|
|
35
|
+
}
|
|
36
|
+
return updated;
|
|
37
|
+
}
|
|
38
|
+
async deleteTask(id) {
|
|
39
|
+
const task = await this.storage.getTaskById(id);
|
|
40
|
+
if (!task) {
|
|
41
|
+
throw new Error(`Task ${id} not found`);
|
|
42
|
+
}
|
|
43
|
+
await this.storage.deleteTask(id);
|
|
44
|
+
}
|
|
45
|
+
async searchTasks(query, filters) {
|
|
46
|
+
return this.storage.searchTasks(query, filters);
|
|
47
|
+
}
|
|
48
|
+
async assignTask(id, assignee) {
|
|
49
|
+
return this.updateTask(id, { assignee });
|
|
50
|
+
}
|
|
51
|
+
async unassignTask(id) {
|
|
52
|
+
return this.updateTask(id, { assignee: null });
|
|
53
|
+
}
|
|
54
|
+
async moveTask(id, newColumn) {
|
|
55
|
+
const validColumns = ['idea', 'approved idea', 'working on', 'blocked', 'ready for review', 'done'];
|
|
56
|
+
if (!validColumns.includes(newColumn)) {
|
|
57
|
+
throw new Error(`Invalid column "${newColumn}". Valid columns: ${validColumns.join(', ')}`);
|
|
58
|
+
}
|
|
59
|
+
const task = await this.storage.getTaskById(id);
|
|
60
|
+
if (!task) {
|
|
61
|
+
throw new Error(`Task ${id} not found`);
|
|
62
|
+
}
|
|
63
|
+
if (task.column === newColumn) {
|
|
64
|
+
throw new Error(`Task ${id} is already in column "${newColumn}"`);
|
|
65
|
+
}
|
|
66
|
+
return this.updateTask(id, { column: newColumn });
|
|
67
|
+
}
|
|
68
|
+
async getColumnStats() {
|
|
69
|
+
const tasks = await this.storage.listTasks();
|
|
70
|
+
const validColumns = ['idea', 'approved idea', 'working on', 'blocked', 'ready for review', 'done'];
|
|
71
|
+
const stats = new Map();
|
|
72
|
+
// Initialize all columns with 0
|
|
73
|
+
for (const col of validColumns) {
|
|
74
|
+
stats.set(col, 0);
|
|
75
|
+
}
|
|
76
|
+
// Count tasks in each column
|
|
77
|
+
for (const task of tasks) {
|
|
78
|
+
const current = stats.get(task.column) ?? 0;
|
|
79
|
+
stats.set(task.column, current + 1);
|
|
80
|
+
}
|
|
81
|
+
return validColumns.map(col => ({ column: col, count: stats.get(col) ?? 0 }));
|
|
82
|
+
}
|
|
83
|
+
async getTasksByAssignee(assignee, column) {
|
|
84
|
+
return this.storage.searchTasks('', { assignee, column });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=task-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-service.js","sourceRoot":"","sources":["../../src/services/task-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-service.test.d.ts","sourceRoot":"","sources":["../../src/services/task-service.test.ts"],"names":[],"mappings":""}
|