agent-tower 0.5.2-beta.0 → 0.5.2-beta.2
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/dist/mcp/http-client.d.ts +12 -3
- package/dist/mcp/http-client.d.ts.map +1 -1
- package/dist/mcp/http-client.js +6 -6
- package/dist/mcp/http-client.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +48 -5
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools/workspaces.d.ts.map +1 -1
- package/dist/mcp/tools/workspaces.js +4 -1
- package/dist/mcp/tools/workspaces.js.map +1 -1
- package/dist/mcp/types.d.ts +3 -0
- package/dist/mcp/types.d.ts.map +1 -1
- package/dist/mcp/types.js +2 -0
- package/dist/mcp/types.js.map +1 -1
- package/dist/routes/git.d.ts.map +1 -1
- package/dist/routes/git.js +6 -1
- package/dist/routes/git.js.map +1 -1
- package/dist/routes/system.d.ts.map +1 -1
- package/dist/routes/system.js +21 -5
- package/dist/routes/system.js.map +1 -1
- package/dist/routes/team-runs.d.ts.map +1 -1
- package/dist/routes/team-runs.js +92 -2
- package/dist/routes/team-runs.js.map +1 -1
- package/dist/routes/workspaces.d.ts.map +1 -1
- package/dist/routes/workspaces.js +11 -4
- package/dist/routes/workspaces.js.map +1 -1
- package/dist/services/__tests__/task.service.test.js +65 -1
- package/dist/services/__tests__/task.service.test.js.map +1 -1
- package/dist/services/__tests__/team-reconciler.service.test.js +171 -3
- package/dist/services/__tests__/team-reconciler.service.test.js.map +1 -1
- package/dist/services/__tests__/team-run.service.test.js +87 -0
- package/dist/services/__tests__/team-run.service.test.js.map +1 -1
- package/dist/services/__tests__/team-scheduler.service.test.js +131 -0
- package/dist/services/__tests__/team-scheduler.service.test.js.map +1 -1
- package/dist/services/__tests__/workspace.service.test.js +55 -0
- package/dist/services/__tests__/workspace.service.test.js.map +1 -1
- package/dist/services/commit-message.service.d.ts.map +1 -1
- package/dist/services/commit-message.service.js +3 -0
- package/dist/services/commit-message.service.js.map +1 -1
- package/dist/services/project.service.d.ts.map +1 -1
- package/dist/services/project.service.js +3 -2
- package/dist/services/project.service.js.map +1 -1
- package/dist/services/session-manager.d.ts +8 -0
- package/dist/services/session-manager.d.ts.map +1 -1
- package/dist/services/session-manager.js +20 -6
- package/dist/services/session-manager.js.map +1 -1
- package/dist/services/task-cleanup.service.d.ts +2 -0
- package/dist/services/task-cleanup.service.d.ts.map +1 -1
- package/dist/services/task-cleanup.service.js +8 -1
- package/dist/services/task-cleanup.service.js.map +1 -1
- package/dist/services/task.service.d.ts +4 -0
- package/dist/services/task.service.d.ts.map +1 -1
- package/dist/services/task.service.js +3 -0
- package/dist/services/task.service.js.map +1 -1
- package/dist/services/team-run.service.d.ts +16 -0
- package/dist/services/team-run.service.d.ts.map +1 -1
- package/dist/services/team-run.service.js +196 -4
- package/dist/services/team-run.service.js.map +1 -1
- package/dist/services/team-scheduler.service.d.ts +8 -4
- package/dist/services/team-scheduler.service.d.ts.map +1 -1
- package/dist/services/team-scheduler.service.js +26 -9
- package/dist/services/team-scheduler.service.js.map +1 -1
- package/dist/services/workspace-kind.d.ts +13 -0
- package/dist/services/workspace-kind.d.ts.map +1 -0
- package/dist/services/workspace-kind.js +16 -0
- package/dist/services/workspace-kind.js.map +1 -0
- package/dist/services/workspace.service.d.ts +18 -0
- package/dist/services/workspace.service.d.ts.map +1 -1
- package/dist/services/workspace.service.js +104 -12
- package/dist/services/workspace.service.js.map +1 -1
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -1
- package/dist/utils/process-launch.d.ts.map +1 -1
- package/dist/utils/process-launch.js +52 -9
- package/dist/utils/process-launch.js.map +1 -1
- package/dist/utils/process-launch.test.js +65 -1
- package/dist/utils/process-launch.test.js.map +1 -1
- package/dist/web/assets/{AgentDemoPage-CWcu7-P7.js → AgentDemoPage-Co63rtls.js} +1 -1
- package/dist/web/assets/{DemoPage-6hMli_sP.js → DemoPage-PD8AX5pI.js} +1 -1
- package/dist/web/assets/{GeneralSettingsPage-DUaFSgCY.js → GeneralSettingsPage-C5eiEeTZ.js} +1 -1
- package/dist/web/assets/{MemberAvatar-S-eJAdWH.js → MemberAvatar-BDXmryjB.js} +1 -1
- package/dist/web/assets/{NotificationSettingsPage-Cl5x8F4G.js → NotificationSettingsPage-BjjPan2M.js} +1 -1
- package/dist/web/assets/{ProfileSettingsPage-QFN9385l.js → ProfileSettingsPage-BRpeNq6u.js} +1 -1
- package/dist/web/assets/ProjectKanbanPage-DUUu2EYy.js +89 -0
- package/dist/web/assets/{ProjectSettingsPage-Do3Q1_r4.js → ProjectSettingsPage-avctMKfk.js} +1 -1
- package/dist/web/assets/{ProviderSettingsPage-DYOb33XQ.js → ProviderSettingsPage-BIUYN2e0.js} +14 -14
- package/dist/web/assets/{SettingsSection-D0Zzbbhp.js → SettingsSection-pLJ3msrT.js} +1 -1
- package/dist/web/assets/{TeamSettingsPage-Dq_DU1S8.js → TeamSettingsPage-BjKW9nT8.js} +1 -1
- package/dist/web/assets/{arrow-left-D0xGRsQG.js → arrow-left-lFz8nyZM.js} +1 -1
- package/dist/web/assets/{button-C-IDw2d8.js → button-BUA8P726.js} +1 -1
- package/dist/web/assets/check-BYuuXc71.js +1 -0
- package/dist/web/assets/{chevron-down-C735lPj9.js → chevron-down-B931AgE2.js} +1 -1
- package/dist/web/assets/{chevron-right-DfFiWY3R.js → chevron-right-F9i4wey6.js} +1 -1
- package/dist/web/assets/{chevron-up-DqGc0SsZ.js → chevron-up-BEHjZ-SB.js} +1 -1
- package/dist/web/assets/{circle-check-CSlvn06a.js → circle-check-C7xXtl8B.js} +1 -1
- package/dist/web/assets/{code-block-OCS4YCEC-BRT1Nrpy.js → code-block-OCS4YCEC-6FHTyCN2.js} +1 -1
- package/dist/web/assets/{confirm-dialog-BtsxywSG.js → confirm-dialog-B_wk_zqm.js} +1 -1
- package/dist/web/assets/{folder-picker-BuvfyaHB.js → folder-picker-BEHS3b2Q.js} +1 -1
- package/dist/web/assets/index-DEQhT5sD.css +1 -0
- package/dist/web/assets/{index-BAz6UxmL.js → index-RxbHMWXV.js} +7 -7
- package/dist/web/assets/{loader-circle-BLO3w-ze.js → loader-circle-stJcjnm-.js} +1 -1
- package/dist/web/assets/log-adapter-CtvxzS4j.js +1 -0
- package/dist/web/assets/{mermaid-NOHMQCX5-BLfGHrOE.js → mermaid-NOHMQCX5-fubZbKyF.js} +3 -3
- package/dist/web/assets/{message-square-CIyucdyo.js → message-square-C8lb-TDo.js} +1 -1
- package/dist/web/assets/modal-UGrjU63G.js +1 -0
- package/dist/web/assets/{pencil-CdJXJig-.js → pencil-uRBgB4qA.js} +1 -1
- package/dist/web/assets/{rotate-ccw-B42Jf1RW.js → rotate-ccw-CWaMrTz4.js} +1 -1
- package/dist/web/assets/{select-kVmZCXo9.js → select-BMlH2AuL.js} +1 -1
- package/dist/web/assets/upload-B-Mpvu9j.js +1 -0
- package/dist/web/assets/{use-profiles-Bvj_EW-7.js → use-profiles-D6cZwU1R.js} +1 -1
- package/dist/web/assets/{use-providers-CcFzAUyf.js → use-providers-DVP6emIi.js} +1 -1
- package/dist/web/index.html +2 -2
- package/node_modules/@agent-tower/shared/dist/socket/events.d.ts +1 -1
- package/node_modules/@agent-tower/shared/dist/socket/events.d.ts.map +1 -1
- package/node_modules/@agent-tower/shared/dist/types.d.ts +14 -1
- package/node_modules/@agent-tower/shared/dist/types.d.ts.map +1 -1
- package/node_modules/@agent-tower/shared/dist/types.js +6 -0
- package/node_modules/@agent-tower/shared/dist/types.js.map +1 -1
- package/node_modules/@prisma/client/.prisma/client/edge.js +8 -5
- package/node_modules/@prisma/client/.prisma/client/index-browser.js +3 -0
- package/node_modules/@prisma/client/.prisma/client/index.d.ts +161 -0
- package/node_modules/@prisma/client/.prisma/client/index.js +8 -5
- package/node_modules/@prisma/client/.prisma/client/package.json +1 -1
- package/node_modules/@prisma/client/.prisma/client/schema.prisma +8 -1
- package/node_modules/@prisma/client/.prisma/client/wasm.js +3 -0
- package/package.json +1 -1
- package/prisma/migrations/20260609000000_add_team_member_membership_status/migration.sql +3 -0
- package/prisma/migrations/20260609000000_add_workspace_kind_working_dir/migration.sql +7 -0
- package/prisma/schema.prisma +8 -1
- package/dist/web/assets/ProjectKanbanPage-Dye8K5K1.js +0 -89
- package/dist/web/assets/check-KjbNKANU.js +0 -1
- package/dist/web/assets/index-r8en4dlI.css +0 -1
- package/dist/web/assets/log-adapter-i7kNXXup.js +0 -1
- package/dist/web/assets/modal-D_VShm6D.js +0 -1
|
@@ -122,7 +122,7 @@ function createRouteSchedulerMock() {
|
|
|
122
122
|
}
|
|
123
123
|
return asAgentInvocations(invocations);
|
|
124
124
|
});
|
|
125
|
-
scheduler.approveWorkRequestAndStartNext = vi.fn(async (workRequestId) => {
|
|
125
|
+
scheduler.approveWorkRequestAndStartNext = vi.fn(async (workRequestId, _options) => {
|
|
126
126
|
const workRequest = await prisma.workRequest.update({
|
|
127
127
|
where: { id: workRequestId },
|
|
128
128
|
data: { status: 'QUEUED' },
|
|
@@ -130,7 +130,7 @@ function createRouteSchedulerMock() {
|
|
|
130
130
|
const startedInvocations = await scheduler.startNextSessions(workRequest.teamRunId);
|
|
131
131
|
return { workRequest: asWorkRequest(workRequest), startedInvocations };
|
|
132
132
|
});
|
|
133
|
-
scheduler.rejectWorkRequest = vi.fn(async (workRequestId) => prisma.workRequest.update({
|
|
133
|
+
scheduler.rejectWorkRequest = vi.fn(async (workRequestId, _options) => prisma.workRequest.update({
|
|
134
134
|
where: { id: workRequestId },
|
|
135
135
|
data: { status: 'REJECTED' },
|
|
136
136
|
}).then(asWorkRequest));
|
|
@@ -1463,6 +1463,15 @@ describe('TeamReconcilerService', () => {
|
|
|
1463
1463
|
});
|
|
1464
1464
|
expect(noMentionResult.isError).toBe(true);
|
|
1465
1465
|
expect(getMcpToolText(noMentionResult)).toContain('mentionMembers');
|
|
1466
|
+
const noStopResult = await callToolForCurrentMember(noRead, noReadInvocation.id, {
|
|
1467
|
+
name: 'stop_member_work',
|
|
1468
|
+
arguments: {
|
|
1469
|
+
member_id: noRead.members[1].id,
|
|
1470
|
+
cancel_queued: true,
|
|
1471
|
+
},
|
|
1472
|
+
});
|
|
1473
|
+
expect(noStopResult.isError).toBe(true);
|
|
1474
|
+
expect(getMcpToolText(noStopResult)).toContain('stopMemberWork');
|
|
1466
1475
|
await expect(prisma.roomMessage.count({
|
|
1467
1476
|
where: {
|
|
1468
1477
|
content: {
|
|
@@ -1512,6 +1521,24 @@ describe('TeamReconcilerService', () => {
|
|
|
1512
1521
|
status: 'QUEUED',
|
|
1513
1522
|
instruction: 'Other queued request',
|
|
1514
1523
|
});
|
|
1524
|
+
const ownPendingApproval = await createWorkRequest({
|
|
1525
|
+
teamRunId: teamRun.id,
|
|
1526
|
+
targetMemberId: members[0].id,
|
|
1527
|
+
status: 'PENDING_APPROVAL',
|
|
1528
|
+
instruction: 'Own pending approval',
|
|
1529
|
+
});
|
|
1530
|
+
const ownPendingRejection = await createWorkRequest({
|
|
1531
|
+
teamRunId: teamRun.id,
|
|
1532
|
+
targetMemberId: members[0].id,
|
|
1533
|
+
status: 'PENDING_APPROVAL',
|
|
1534
|
+
instruction: 'Own pending rejection',
|
|
1535
|
+
});
|
|
1536
|
+
const otherPendingApproval = await createWorkRequest({
|
|
1537
|
+
teamRunId: teamRun.id,
|
|
1538
|
+
targetMemberId: members[1].id,
|
|
1539
|
+
status: 'PENDING_APPROVAL',
|
|
1540
|
+
instruction: 'Other pending approval',
|
|
1541
|
+
});
|
|
1515
1542
|
const app = Fastify({ logger: false });
|
|
1516
1543
|
try {
|
|
1517
1544
|
setTeamRunEnv({
|
|
@@ -1569,6 +1596,33 @@ describe('TeamReconcilerService', () => {
|
|
|
1569
1596
|
});
|
|
1570
1597
|
expect(forbiddenCancel.isError).toBe(true);
|
|
1571
1598
|
expect(getMcpToolText(forbiddenCancel)).toContain('FORBIDDEN');
|
|
1599
|
+
await expect(prisma.workRequest.findUnique({ where: { id: otherRequest.id } })).resolves.toMatchObject({
|
|
1600
|
+
status: 'QUEUED',
|
|
1601
|
+
});
|
|
1602
|
+
const approveResult = await client.callTool({
|
|
1603
|
+
name: 'approve_work_request',
|
|
1604
|
+
arguments: { work_request_id: ownPendingApproval.id },
|
|
1605
|
+
});
|
|
1606
|
+
expect(approveResult.isError, getMcpToolText(approveResult)).not.toBe(true);
|
|
1607
|
+
expect(JSON.parse(getMcpToolText(approveResult)).workRequest).toMatchObject({
|
|
1608
|
+
id: ownPendingApproval.id,
|
|
1609
|
+
status: 'QUEUED',
|
|
1610
|
+
});
|
|
1611
|
+
const rejectResult = await client.callTool({
|
|
1612
|
+
name: 'reject_work_request',
|
|
1613
|
+
arguments: { work_request_id: ownPendingRejection.id },
|
|
1614
|
+
});
|
|
1615
|
+
expect(rejectResult.isError, getMcpToolText(rejectResult)).not.toBe(true);
|
|
1616
|
+
expect(JSON.parse(getMcpToolText(rejectResult))).toMatchObject({
|
|
1617
|
+
id: ownPendingRejection.id,
|
|
1618
|
+
status: 'REJECTED',
|
|
1619
|
+
});
|
|
1620
|
+
const forbiddenApprove = await client.callTool({
|
|
1621
|
+
name: 'approve_work_request',
|
|
1622
|
+
arguments: { work_request_id: otherPendingApproval.id },
|
|
1623
|
+
});
|
|
1624
|
+
expect(forbiddenApprove.isError).toBe(true);
|
|
1625
|
+
expect(getMcpToolText(forbiddenApprove)).toContain('FORBIDDEN');
|
|
1572
1626
|
}
|
|
1573
1627
|
finally {
|
|
1574
1628
|
await client.close();
|
|
@@ -1578,7 +1632,13 @@ describe('TeamReconcilerService', () => {
|
|
|
1578
1632
|
status: 'CANCELLED',
|
|
1579
1633
|
});
|
|
1580
1634
|
await expect(prisma.workRequest.findUnique({ where: { id: otherRequest.id } })).resolves.toMatchObject({
|
|
1581
|
-
status: '
|
|
1635
|
+
status: 'STARTED',
|
|
1636
|
+
});
|
|
1637
|
+
await expect(prisma.workRequest.findUnique({ where: { id: ownPendingRejection.id } })).resolves.toMatchObject({
|
|
1638
|
+
status: 'REJECTED',
|
|
1639
|
+
});
|
|
1640
|
+
await expect(prisma.workRequest.findUnique({ where: { id: otherPendingApproval.id } })).resolves.toMatchObject({
|
|
1641
|
+
status: 'PENDING_APPROVAL',
|
|
1582
1642
|
});
|
|
1583
1643
|
}
|
|
1584
1644
|
finally {
|
|
@@ -1712,6 +1772,114 @@ describe('TeamReconcilerService', () => {
|
|
|
1712
1772
|
await app.close();
|
|
1713
1773
|
}
|
|
1714
1774
|
});
|
|
1775
|
+
it('passes requester member scope for REST WorkRequest approval and rejection', async () => {
|
|
1776
|
+
const { teamRun, members } = await createFixture({ memberCount: 2, teamRunMode: 'CONFIRM' });
|
|
1777
|
+
const ownPending = await createWorkRequest({
|
|
1778
|
+
teamRunId: teamRun.id,
|
|
1779
|
+
targetMemberId: members[0].id,
|
|
1780
|
+
status: 'PENDING_APPROVAL',
|
|
1781
|
+
instruction: 'Own approval',
|
|
1782
|
+
});
|
|
1783
|
+
const otherPending = await createWorkRequest({
|
|
1784
|
+
teamRunId: teamRun.id,
|
|
1785
|
+
targetMemberId: members[1].id,
|
|
1786
|
+
status: 'PENDING_APPROVAL',
|
|
1787
|
+
instruction: 'Other rejection',
|
|
1788
|
+
});
|
|
1789
|
+
const routeScheduler = createRouteSchedulerMock();
|
|
1790
|
+
const app = Fastify({ logger: false });
|
|
1791
|
+
try {
|
|
1792
|
+
await app.register(teamRunRoutes, { prefix: '/api', scheduler: routeScheduler });
|
|
1793
|
+
const approve = await app.inject({
|
|
1794
|
+
method: 'POST',
|
|
1795
|
+
url: `/api/team-runs/work-requests/${ownPending.id}/approve`,
|
|
1796
|
+
payload: {
|
|
1797
|
+
teamRunId: teamRun.id,
|
|
1798
|
+
requesterMemberId: members[0].id,
|
|
1799
|
+
},
|
|
1800
|
+
});
|
|
1801
|
+
expect(approve.statusCode).toBe(200);
|
|
1802
|
+
expect(routeScheduler.approveWorkRequestAndStartNext).toHaveBeenCalledWith(ownPending.id, {
|
|
1803
|
+
teamRunId: teamRun.id,
|
|
1804
|
+
requesterMemberId: members[0].id,
|
|
1805
|
+
});
|
|
1806
|
+
const reject = await app.inject({
|
|
1807
|
+
method: 'POST',
|
|
1808
|
+
url: `/api/team-runs/work-requests/${otherPending.id}/reject`,
|
|
1809
|
+
payload: {
|
|
1810
|
+
teamRunId: teamRun.id,
|
|
1811
|
+
requesterMemberId: members[0].id,
|
|
1812
|
+
},
|
|
1813
|
+
});
|
|
1814
|
+
expect(reject.statusCode).toBe(200);
|
|
1815
|
+
expect(routeScheduler.rejectWorkRequest).toHaveBeenCalledWith(otherPending.id, {
|
|
1816
|
+
teamRunId: teamRun.id,
|
|
1817
|
+
requesterMemberId: members[0].id,
|
|
1818
|
+
});
|
|
1819
|
+
}
|
|
1820
|
+
finally {
|
|
1821
|
+
await app.close();
|
|
1822
|
+
}
|
|
1823
|
+
});
|
|
1824
|
+
it('does not soft-remove a member when active stop fails during removal', async () => {
|
|
1825
|
+
const { workspace, teamRun, members } = await createFixture({ memberCount: 2 });
|
|
1826
|
+
const activeRequest = await createWorkRequest({
|
|
1827
|
+
teamRunId: teamRun.id,
|
|
1828
|
+
targetMemberId: members[0].id,
|
|
1829
|
+
status: 'STARTED',
|
|
1830
|
+
instruction: 'Active work',
|
|
1831
|
+
});
|
|
1832
|
+
const queuedRequest = await createWorkRequest({
|
|
1833
|
+
teamRunId: teamRun.id,
|
|
1834
|
+
targetMemberId: members[0].id,
|
|
1835
|
+
status: 'QUEUED',
|
|
1836
|
+
instruction: 'Queued work',
|
|
1837
|
+
});
|
|
1838
|
+
await createRunningInvocation({
|
|
1839
|
+
teamRunId: teamRun.id,
|
|
1840
|
+
workRequestId: activeRequest.id,
|
|
1841
|
+
memberId: members[0].id,
|
|
1842
|
+
workspaceId: workspace.id,
|
|
1843
|
+
status: 'RUNNING',
|
|
1844
|
+
});
|
|
1845
|
+
const routeScheduler = createRouteSchedulerMock();
|
|
1846
|
+
routeScheduler.stopMemberWork = vi.fn(async () => {
|
|
1847
|
+
throw new Error('stop failed');
|
|
1848
|
+
});
|
|
1849
|
+
const app = Fastify({ logger: false });
|
|
1850
|
+
try {
|
|
1851
|
+
await app.register(teamRunRoutes, { prefix: '/api', scheduler: routeScheduler });
|
|
1852
|
+
const response = await app.inject({
|
|
1853
|
+
method: 'POST',
|
|
1854
|
+
url: `/api/team-runs/${teamRun.id}/members/${members[0].id}/remove`,
|
|
1855
|
+
payload: {
|
|
1856
|
+
stopActive: true,
|
|
1857
|
+
cancelQueued: true,
|
|
1858
|
+
},
|
|
1859
|
+
});
|
|
1860
|
+
expect(response.statusCode).toBe(500);
|
|
1861
|
+
expect(routeScheduler.stopMemberWork).toHaveBeenCalledWith(teamRun.id, members[0].id, {
|
|
1862
|
+
cancelQueued: true,
|
|
1863
|
+
});
|
|
1864
|
+
await expect(prisma.teamMember.findUnique({ where: { id: members[0].id } })).resolves.toMatchObject({
|
|
1865
|
+
membershipStatus: 'ACTIVE',
|
|
1866
|
+
status: 'IDLE',
|
|
1867
|
+
});
|
|
1868
|
+
await expect(prisma.workRequest.findUnique({ where: { id: queuedRequest.id } })).resolves.toMatchObject({
|
|
1869
|
+
status: 'QUEUED',
|
|
1870
|
+
});
|
|
1871
|
+
await expect(prisma.agentInvocation.count({
|
|
1872
|
+
where: {
|
|
1873
|
+
teamRunId: teamRun.id,
|
|
1874
|
+
memberId: members[0].id,
|
|
1875
|
+
status: 'RUNNING',
|
|
1876
|
+
},
|
|
1877
|
+
})).resolves.toBe(1);
|
|
1878
|
+
}
|
|
1879
|
+
finally {
|
|
1880
|
+
await app.close();
|
|
1881
|
+
}
|
|
1882
|
+
});
|
|
1715
1883
|
it('auto-starts USER_MESSAGES work when a user posts an unmentioned room message', async () => {
|
|
1716
1884
|
const { teamRun, members } = await createFixture({
|
|
1717
1885
|
memberCount: 2,
|