@powerhousedao/reactor-mcp 6.0.0-dev.13 → 6.0.0-dev.130
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/src/cli.js +1 -1
- package/dist/src/cli.js.map +1 -1
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/logger.d.ts +1 -1
- package/dist/src/logger.d.ts.map +1 -1
- package/dist/src/logger.js +1 -1
- package/dist/src/logger.js.map +1 -1
- package/dist/src/mcp-routes.d.ts +19 -0
- package/dist/src/mcp-routes.d.ts.map +1 -0
- package/dist/src/mcp-routes.js +50 -0
- package/dist/src/mcp-routes.js.map +1 -0
- package/dist/src/server.d.ts +7 -3
- package/dist/src/server.d.ts.map +1 -1
- package/dist/src/server.js +8 -5
- package/dist/src/server.js.map +1 -1
- package/dist/src/stdio/index.d.ts.map +1 -1
- package/dist/src/stdio/index.js +22 -51
- package/dist/src/stdio/index.js.map +1 -1
- package/dist/src/stdio/loader.d.ts +1 -1
- package/dist/src/stdio/loader.d.ts.map +1 -1
- package/dist/src/stdio/loader.js +1 -1
- package/dist/src/stdio/loader.js.map +1 -1
- package/dist/src/tools/reactor.d.ts +83 -363
- package/dist/src/tools/reactor.d.ts.map +1 -1
- package/dist/src/tools/reactor.js +98 -101
- package/dist/src/tools/reactor.js.map +1 -1
- package/dist/src/tools/types.d.ts +1 -1
- package/dist/src/tools/types.d.ts.map +1 -1
- package/dist/src/tools/utils.d.ts +1 -1
- package/dist/src/tools/utils.d.ts.map +1 -1
- package/dist/src/tools/utils.js.map +1 -1
- package/dist/test/reactor.test.js +205 -248
- package/dist/test/reactor.test.js.map +1 -1
- package/dist/test/setup-mcp-server.test.d.ts +10 -0
- package/dist/test/setup-mcp-server.test.d.ts.map +1 -0
- package/dist/test/setup-mcp-server.test.js +172 -0
- package/dist/test/setup-mcp-server.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +19 -20
- package/dist/src/express.d.ts +0 -5
- package/dist/src/express.d.ts.map +0 -1
- package/dist/src/express.js +0 -59
- package/dist/src/express.js.map +0 -1
|
@@ -1,76 +1,92 @@
|
|
|
1
|
+
import { ReactorBuilder, ReactorClientBuilder } from "@powerhousedao/reactor";
|
|
1
2
|
import { createReactorMcpProvider } from "@powerhousedao/reactor-mcp";
|
|
2
|
-
import {
|
|
3
|
-
import { documentModelCreateDocument, documentModelDocumentModelModule,
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
import { driveDocumentModelModule } from "@powerhousedao/shared/document-drive";
|
|
4
|
+
import { documentModelCreateDocument, documentModelDocumentModelModule, } from "document-model";
|
|
5
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
6
|
+
function getTextContent(result, index = 0) {
|
|
7
|
+
const content = result.content[index];
|
|
8
|
+
return content.type === "text" ? content.text : "";
|
|
9
|
+
}
|
|
10
|
+
// Mock reactor client for unit tests
|
|
11
|
+
const createMockReactorClient = () => {
|
|
12
|
+
const mockClient = {
|
|
13
|
+
get: vi.fn(),
|
|
14
|
+
getDocumentModelModule: vi.fn(),
|
|
15
|
+
getDocumentModelModules: vi.fn().mockResolvedValue({
|
|
16
|
+
results: [],
|
|
17
|
+
options: { cursor: "", limit: 10 },
|
|
18
|
+
}),
|
|
19
|
+
createEmpty: vi.fn(),
|
|
20
|
+
getChildren: vi.fn().mockResolvedValue({
|
|
21
|
+
results: [],
|
|
22
|
+
options: { cursor: "", limit: 10 },
|
|
23
|
+
}),
|
|
24
|
+
deleteDocument: vi.fn(),
|
|
25
|
+
execute: vi.fn(),
|
|
26
|
+
createDocumentInDrive: vi.fn(),
|
|
27
|
+
find: vi.fn().mockResolvedValue({
|
|
28
|
+
results: [],
|
|
29
|
+
options: { cursor: "", limit: 10 },
|
|
30
|
+
}),
|
|
31
|
+
rename: vi.fn(),
|
|
11
32
|
};
|
|
12
|
-
return
|
|
33
|
+
return mockClient;
|
|
13
34
|
};
|
|
14
|
-
|
|
15
|
-
|
|
35
|
+
// Create a real reactor client for integration tests
|
|
36
|
+
async function createReactorClientModule() {
|
|
37
|
+
const reactorBuilder = new ReactorBuilder().withDocumentModels([
|
|
16
38
|
documentModelDocumentModelModule,
|
|
17
39
|
driveDocumentModelModule,
|
|
18
40
|
]);
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
41
|
+
const module = await new ReactorClientBuilder()
|
|
42
|
+
.withReactorBuilder(reactorBuilder)
|
|
43
|
+
.buildModule();
|
|
44
|
+
return module;
|
|
22
45
|
}
|
|
23
|
-
describe
|
|
24
|
-
let
|
|
25
|
-
let
|
|
46
|
+
describe("ReactorMcpProvider", () => {
|
|
47
|
+
let mockClient;
|
|
48
|
+
let reactorModule;
|
|
49
|
+
let client;
|
|
26
50
|
beforeEach(async () => {
|
|
27
|
-
|
|
28
|
-
|
|
51
|
+
reactorModule = await createReactorClientModule();
|
|
52
|
+
client = reactorModule.client;
|
|
53
|
+
mockClient = createMockReactorClient();
|
|
29
54
|
vi.clearAllMocks();
|
|
30
55
|
});
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
expect(mockReactor.initialize).toHaveBeenCalledOnce();
|
|
56
|
+
afterEach(() => {
|
|
57
|
+
reactorModule.reactor.kill();
|
|
34
58
|
});
|
|
35
|
-
describe("
|
|
59
|
+
describe("getDocument tool", () => {
|
|
36
60
|
it("should retrieve a document successfully", async () => {
|
|
61
|
+
// Create a document using the client
|
|
37
62
|
const document = documentModelCreateDocument();
|
|
38
|
-
|
|
39
|
-
const provider = await createReactorMcpProvider(
|
|
63
|
+
await client.create(document);
|
|
64
|
+
const provider = await createReactorMcpProvider({ client });
|
|
40
65
|
const result = await provider.tools.getDocument.callback({
|
|
41
66
|
id: document.header.id,
|
|
42
67
|
});
|
|
43
|
-
expect(
|
|
44
|
-
document: {
|
|
45
|
-
header: resultDocument.header,
|
|
46
|
-
state: resultDocument.state,
|
|
47
|
-
},
|
|
48
|
-
});
|
|
68
|
+
expect(result.isError).toBeUndefined();
|
|
49
69
|
expect(result.structuredContent).toMatchObject({
|
|
50
70
|
document: {
|
|
51
|
-
header:
|
|
52
|
-
|
|
71
|
+
header: expect.objectContaining({
|
|
72
|
+
id: document.header.id,
|
|
73
|
+
documentType: document.header.documentType,
|
|
74
|
+
}),
|
|
53
75
|
},
|
|
54
76
|
});
|
|
55
|
-
expect(result.isError).toBeUndefined();
|
|
56
77
|
});
|
|
57
78
|
it("should handle errors gracefully", async () => {
|
|
58
|
-
const provider = await createReactorMcpProvider(
|
|
79
|
+
const provider = await createReactorMcpProvider({ client });
|
|
59
80
|
const result = await provider.tools.getDocument.callback({
|
|
60
81
|
id: "non-existent-id",
|
|
61
82
|
});
|
|
62
83
|
expect(result.isError).toBe(true);
|
|
63
|
-
expect(result
|
|
64
|
-
{
|
|
65
|
-
type: "text",
|
|
66
|
-
text: "Error: Document with id non-existent-id not found",
|
|
67
|
-
},
|
|
68
|
-
]);
|
|
84
|
+
expect(getTextContent(result)).toContain("non-existent-id");
|
|
69
85
|
});
|
|
70
86
|
it("should handle non-Error exceptions", async () => {
|
|
71
87
|
const errorMessage = "String error message";
|
|
72
|
-
|
|
73
|
-
const provider = await createReactorMcpProvider(
|
|
88
|
+
vi.mocked(mockClient.get).mockRejectedValue(errorMessage);
|
|
89
|
+
const provider = await createReactorMcpProvider({ client: mockClient });
|
|
74
90
|
const result = await provider.tools.getDocument.callback({
|
|
75
91
|
id: "test-id",
|
|
76
92
|
});
|
|
@@ -82,40 +98,83 @@ describe.skip("ReactorMcpProvider", () => {
|
|
|
82
98
|
},
|
|
83
99
|
]);
|
|
84
100
|
});
|
|
85
|
-
it("should handle empty string ID", async () => {
|
|
86
|
-
mockReactor.getDocument = vi
|
|
87
|
-
.fn()
|
|
88
|
-
.mockRejectedValue(new DocumentNotFoundError(""));
|
|
89
|
-
const provider = await createReactorMcpProvider(reactor);
|
|
90
|
-
const result = await provider.tools.getDocument.callback({ id: "" });
|
|
91
|
-
expect(result.isError).toBe(true);
|
|
92
|
-
expect(result.content).toEqual([
|
|
93
|
-
{
|
|
94
|
-
type: "text",
|
|
95
|
-
text: "Error: Document with id not found",
|
|
96
|
-
},
|
|
97
|
-
]);
|
|
98
|
-
});
|
|
99
101
|
});
|
|
100
102
|
describe("createDocument tool", () => {
|
|
101
103
|
it("should create a document successfully", async () => {
|
|
102
|
-
const provider = await createReactorMcpProvider(
|
|
104
|
+
const provider = await createReactorMcpProvider({ client });
|
|
103
105
|
const result = await provider.tools.createDocument.callback({
|
|
104
106
|
documentType: "powerhouse/document-model",
|
|
105
|
-
documentId: "test-doc-id",
|
|
106
107
|
});
|
|
107
108
|
expect(result.isError).toBeUndefined();
|
|
108
|
-
expect(result.structuredContent).
|
|
109
|
-
documentId:
|
|
109
|
+
expect(result.structuredContent).toMatchObject({
|
|
110
|
+
documentId: expect.any(String),
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
it("should create a document in a drive when driveId is provided", async () => {
|
|
114
|
+
const drive = await client.createEmpty("powerhouse/document-drive");
|
|
115
|
+
const provider = await createReactorMcpProvider({ client });
|
|
116
|
+
const result = await provider.tools.createDocument.callback({
|
|
117
|
+
documentType: "powerhouse/document-model",
|
|
118
|
+
driveId: drive.header.id,
|
|
110
119
|
});
|
|
120
|
+
expect(result.isError).toBeUndefined();
|
|
121
|
+
expect(result.structuredContent).toMatchObject({
|
|
122
|
+
documentId: expect.any(String),
|
|
123
|
+
});
|
|
124
|
+
// Verify the document was created and can be retrieved
|
|
125
|
+
const documentId = result.structuredContent
|
|
126
|
+
.documentId;
|
|
127
|
+
const doc = await client.get(documentId);
|
|
128
|
+
expect(doc).toBeDefined();
|
|
129
|
+
expect(doc.header.documentType).toBe("powerhouse/document-model");
|
|
130
|
+
});
|
|
131
|
+
it("should create a document in a drive with parentFolder", async () => {
|
|
132
|
+
const drive = await client.createEmpty("powerhouse/document-drive");
|
|
133
|
+
// Add a folder to the drive using addActions tool (properly formats actions)
|
|
134
|
+
const folderId = "test-folder-id";
|
|
135
|
+
const provider = await createReactorMcpProvider({ client });
|
|
136
|
+
await provider.tools.addActions.callback({
|
|
137
|
+
documentId: drive.header.id,
|
|
138
|
+
actions: [
|
|
139
|
+
{
|
|
140
|
+
type: "ADD_FOLDER",
|
|
141
|
+
input: { id: folderId, name: "Test Folder" },
|
|
142
|
+
scope: "global",
|
|
143
|
+
},
|
|
144
|
+
],
|
|
145
|
+
});
|
|
146
|
+
const result = await provider.tools.createDocument.callback({
|
|
147
|
+
documentType: "powerhouse/document-model",
|
|
148
|
+
driveId: drive.header.id,
|
|
149
|
+
parentFolder: folderId,
|
|
150
|
+
});
|
|
151
|
+
expect(result.isError).toBeUndefined();
|
|
152
|
+
expect(result.structuredContent).toMatchObject({
|
|
153
|
+
documentId: expect.any(String),
|
|
154
|
+
});
|
|
155
|
+
// Verify the document exists
|
|
156
|
+
const documentId = result.structuredContent
|
|
157
|
+
.documentId;
|
|
158
|
+
const doc = await client.get(documentId);
|
|
159
|
+
expect(doc).toBeDefined();
|
|
160
|
+
expect(doc.header.documentType).toBe("powerhouse/document-model");
|
|
161
|
+
});
|
|
162
|
+
it("should return error for unknown document type with driveId", async () => {
|
|
163
|
+
const drive = await client.createEmpty("powerhouse/document-drive");
|
|
164
|
+
const provider = await createReactorMcpProvider({ client });
|
|
165
|
+
const result = await provider.tools.createDocument.callback({
|
|
166
|
+
documentType: "non-existent/type",
|
|
167
|
+
driveId: drive.header.id,
|
|
168
|
+
});
|
|
169
|
+
expect(result.isError).toBe(true);
|
|
170
|
+
expect(getTextContent(result)).toContain("non-existent/type");
|
|
111
171
|
});
|
|
112
172
|
});
|
|
113
173
|
describe("getDocuments tool", () => {
|
|
114
174
|
it("should get documents from a drive", async () => {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
});
|
|
118
|
-
const provider = await createReactorMcpProvider(reactor);
|
|
175
|
+
// Create a drive first
|
|
176
|
+
const drive = await client.createEmpty("powerhouse/document-drive");
|
|
177
|
+
const provider = await createReactorMcpProvider({ client });
|
|
119
178
|
const result = await provider.tools.getDocuments.callback({
|
|
120
179
|
parentId: drive.header.id,
|
|
121
180
|
});
|
|
@@ -123,31 +182,15 @@ describe.skip("ReactorMcpProvider", () => {
|
|
|
123
182
|
expect(result.structuredContent).toMatchObject({
|
|
124
183
|
documentIds: [],
|
|
125
184
|
});
|
|
126
|
-
const { document } = await reactor.queueDocument({
|
|
127
|
-
documentType: "powerhouse/document-model",
|
|
128
|
-
id: generateId(),
|
|
129
|
-
});
|
|
130
|
-
const addResult = await reactor.addAction(drive.header.id, driveDocumentModelModule.actions.addFile({
|
|
131
|
-
id: document?.header.id,
|
|
132
|
-
documentType: "powerhouse/document-model",
|
|
133
|
-
name: "test-doc",
|
|
134
|
-
}));
|
|
135
|
-
expect(addResult.error).toBeUndefined();
|
|
136
|
-
const result2 = await provider.tools.getDocuments.callback({
|
|
137
|
-
parentId: drive.header.id,
|
|
138
|
-
});
|
|
139
|
-
expect(result2.structuredContent).toMatchObject({
|
|
140
|
-
documentIds: [document?.header.id],
|
|
141
|
-
});
|
|
142
185
|
});
|
|
143
186
|
});
|
|
144
187
|
describe("deleteDocument tool", () => {
|
|
145
188
|
it("should delete a document successfully", async () => {
|
|
146
189
|
const document = documentModelCreateDocument();
|
|
147
|
-
await
|
|
148
|
-
const provider = await createReactorMcpProvider(
|
|
190
|
+
await client.create(document);
|
|
191
|
+
const provider = await createReactorMcpProvider({ client });
|
|
149
192
|
const result = await provider.tools.deleteDocument.callback({
|
|
150
|
-
documentId: document
|
|
193
|
+
documentId: document.header.id,
|
|
151
194
|
});
|
|
152
195
|
expect(result.isError).toBeUndefined();
|
|
153
196
|
expect(result.structuredContent).toMatchObject({
|
|
@@ -155,22 +198,21 @@ describe.skip("ReactorMcpProvider", () => {
|
|
|
155
198
|
});
|
|
156
199
|
});
|
|
157
200
|
it("should handle deletion of non-existent document", async () => {
|
|
158
|
-
const provider = await createReactorMcpProvider(
|
|
201
|
+
const provider = await createReactorMcpProvider({ client });
|
|
159
202
|
const result = await provider.tools.deleteDocument.callback({
|
|
160
203
|
documentId: "non-existent-id",
|
|
161
204
|
});
|
|
162
|
-
|
|
163
|
-
// The reactor implementation returns true even for non-existent documents
|
|
205
|
+
// The new reactor throws for non-existent documents
|
|
164
206
|
expect(result.structuredContent).toMatchObject({
|
|
165
|
-
success:
|
|
207
|
+
success: false,
|
|
166
208
|
});
|
|
167
209
|
});
|
|
168
210
|
});
|
|
169
211
|
describe("addActions tool", () => {
|
|
170
212
|
it("should add an action to a document", async () => {
|
|
171
213
|
const document = documentModelCreateDocument();
|
|
172
|
-
await
|
|
173
|
-
const provider = await createReactorMcpProvider(
|
|
214
|
+
await client.create(document);
|
|
215
|
+
const provider = await createReactorMcpProvider({ client });
|
|
174
216
|
const action = documentModelDocumentModelModule.actions.setModelName({
|
|
175
217
|
name: "test-doc",
|
|
176
218
|
});
|
|
@@ -178,7 +220,6 @@ describe.skip("ReactorMcpProvider", () => {
|
|
|
178
220
|
documentId: document.header.id,
|
|
179
221
|
actions: [action],
|
|
180
222
|
});
|
|
181
|
-
const expectedResult = documentModelReducer(document, action);
|
|
182
223
|
expect(result.isError).toBeUndefined();
|
|
183
224
|
expect(result.structuredContent).toStrictEqual({
|
|
184
225
|
success: true,
|
|
@@ -186,11 +227,11 @@ describe.skip("ReactorMcpProvider", () => {
|
|
|
186
227
|
});
|
|
187
228
|
it("should add multiple actions to a document", async () => {
|
|
188
229
|
const document = documentModelCreateDocument();
|
|
189
|
-
await
|
|
190
|
-
const provider = await createReactorMcpProvider(
|
|
230
|
+
await client.create(document);
|
|
231
|
+
const provider = await createReactorMcpProvider({ client });
|
|
191
232
|
const actions = [
|
|
192
233
|
documentModelDocumentModelModule.actions.setModelName({
|
|
193
|
-
name: "Test Name 1
|
|
234
|
+
name: "Test Name 1",
|
|
194
235
|
}),
|
|
195
236
|
documentModelDocumentModelModule.actions.setModelName({
|
|
196
237
|
name: "Test Name 2",
|
|
@@ -200,8 +241,6 @@ describe.skip("ReactorMcpProvider", () => {
|
|
|
200
241
|
documentId: document.header.id,
|
|
201
242
|
actions,
|
|
202
243
|
});
|
|
203
|
-
const intermediateResult = documentModelReducer(document, actions[0]);
|
|
204
|
-
const expectedResult = documentModelReducer(intermediateResult, actions[1]);
|
|
205
244
|
expect(result.isError).toBeUndefined();
|
|
206
245
|
expect(result.structuredContent).toStrictEqual({
|
|
207
246
|
success: true,
|
|
@@ -209,8 +248,8 @@ describe.skip("ReactorMcpProvider", () => {
|
|
|
209
248
|
});
|
|
210
249
|
it("should throw error on invalid action type", async () => {
|
|
211
250
|
const document = documentModelCreateDocument();
|
|
212
|
-
await
|
|
213
|
-
const provider = await createReactorMcpProvider(
|
|
251
|
+
await client.create(document);
|
|
252
|
+
const provider = await createReactorMcpProvider({ client });
|
|
214
253
|
const result = await provider.tools.addActions.callback({
|
|
215
254
|
documentId: document.header.id,
|
|
216
255
|
actions: [
|
|
@@ -222,14 +261,14 @@ describe.skip("ReactorMcpProvider", () => {
|
|
|
222
261
|
],
|
|
223
262
|
});
|
|
224
263
|
expect(result.isError).toBe(true);
|
|
225
|
-
expect(result
|
|
264
|
+
expect(getTextContent(result)).toContain(`Operation "INVALID_ACTION" is not defined in any module of the document model`);
|
|
226
265
|
});
|
|
227
266
|
it("should throw error on invalid action input", async () => {
|
|
228
267
|
const document = documentModelCreateDocument();
|
|
229
|
-
await
|
|
230
|
-
const provider = await createReactorMcpProvider(
|
|
268
|
+
await client.create(document);
|
|
269
|
+
const provider = await createReactorMcpProvider({ client });
|
|
231
270
|
const result = await provider.tools.addActions.callback({
|
|
232
|
-
documentId: document
|
|
271
|
+
documentId: document.header.id,
|
|
233
272
|
actions: [
|
|
234
273
|
{
|
|
235
274
|
type: "SET_MODEL_NAME",
|
|
@@ -241,21 +280,10 @@ describe.skip("ReactorMcpProvider", () => {
|
|
|
241
280
|
],
|
|
242
281
|
});
|
|
243
282
|
expect(result.isError).toBe(true);
|
|
244
|
-
expect(result.
|
|
245
|
-
.toContain(`Input validation error: Invalid action input: [
|
|
246
|
-
{
|
|
247
|
-
"code": "invalid_type",
|
|
248
|
-
"expected": "string",
|
|
249
|
-
"received": "undefined",
|
|
250
|
-
"path": [
|
|
251
|
-
"name"
|
|
252
|
-
],
|
|
253
|
-
"message": "Required"
|
|
254
|
-
}
|
|
255
|
-
]`);
|
|
283
|
+
expect(getTextContent(result)).toContain("Input validation error");
|
|
256
284
|
});
|
|
257
285
|
it("should throw error on action on non-existent document", async () => {
|
|
258
|
-
const provider = await createReactorMcpProvider(
|
|
286
|
+
const provider = await createReactorMcpProvider({ client });
|
|
259
287
|
const result = await provider.tools.addActions.callback({
|
|
260
288
|
documentId: "non-existent-id",
|
|
261
289
|
actions: [
|
|
@@ -268,92 +296,46 @@ describe.skip("ReactorMcpProvider", () => {
|
|
|
268
296
|
});
|
|
269
297
|
// Action on non-existent document returns an error
|
|
270
298
|
expect(result.isError).toBe(true);
|
|
271
|
-
expect(result
|
|
272
|
-
{
|
|
273
|
-
text: "Error: Document with id non-existent-id not found",
|
|
274
|
-
type: "text",
|
|
275
|
-
},
|
|
276
|
-
]);
|
|
277
|
-
expect(result.structuredContent).toBeUndefined();
|
|
299
|
+
expect(getTextContent(result)).toContain("non-existent-id");
|
|
278
300
|
});
|
|
279
301
|
});
|
|
280
|
-
// describe("addOperation tool", () => {
|
|
281
|
-
// it("should add an operation to a document", async () => {
|
|
282
|
-
// const document = documentModelCreateDocument();
|
|
283
|
-
// await reactor.addDocument(document);
|
|
284
|
-
// const provider = await createReactorMcpProvider(reactor);
|
|
285
|
-
// const result = await provider.tools.addOperation.callback({
|
|
286
|
-
// documentId: document.header.id,
|
|
287
|
-
// operation: {
|
|
288
|
-
// type: "SET_NAME",
|
|
289
|
-
// input: "Operation Name",
|
|
290
|
-
// scope: "global",
|
|
291
|
-
// index: 1,
|
|
292
|
-
// timestampUtcMs: new Date().toISOString(),
|
|
293
|
-
// hash: "test-hash",
|
|
294
|
-
// skip: 0,
|
|
295
|
-
// },
|
|
296
|
-
// });
|
|
297
|
-
// expect(result.isError).toBeUndefined();
|
|
298
|
-
// expect(result.structuredContent).toMatchObject({
|
|
299
|
-
// result: {
|
|
300
|
-
// status: "ERROR",
|
|
301
|
-
//
|
|
302
|
-
// error: expect.any(String),
|
|
303
|
-
// operations: [],
|
|
304
|
-
// signals: [],
|
|
305
|
-
// },
|
|
306
|
-
// });
|
|
307
|
-
// });
|
|
308
|
-
// });
|
|
309
302
|
describe("getDrives tool", () => {
|
|
310
303
|
it("should list all drives", async () => {
|
|
311
|
-
await
|
|
312
|
-
await
|
|
313
|
-
const provider = await createReactorMcpProvider(
|
|
304
|
+
await client.createEmpty("powerhouse/document-drive");
|
|
305
|
+
await client.createEmpty("powerhouse/document-drive");
|
|
306
|
+
const provider = await createReactorMcpProvider({ client });
|
|
314
307
|
const result = await provider.tools.getDrives.callback({});
|
|
315
308
|
expect(result.isError).toBeUndefined();
|
|
316
309
|
expect(result.structuredContent).toMatchObject({
|
|
317
|
-
driveIds: expect.
|
|
310
|
+
driveIds: expect.any(Array),
|
|
318
311
|
});
|
|
312
|
+
expect(result.structuredContent.driveIds.length).toBeGreaterThanOrEqual(2);
|
|
319
313
|
});
|
|
320
314
|
});
|
|
321
315
|
describe("addDrive tool", () => {
|
|
322
316
|
it("should add a new drive", async () => {
|
|
323
|
-
const provider = await createReactorMcpProvider(
|
|
317
|
+
const provider = await createReactorMcpProvider({ client });
|
|
324
318
|
const result = await provider.tools.addDrive.callback({
|
|
325
319
|
driveInput: {
|
|
326
320
|
global: {
|
|
327
321
|
name: "New Test Drive",
|
|
328
322
|
icon: "test-icon",
|
|
329
323
|
},
|
|
330
|
-
id: "test-drive-id",
|
|
331
|
-
slug: "test-drive-slug",
|
|
332
|
-
preferredEditor: "test-editor",
|
|
333
|
-
local: {
|
|
334
|
-
availableOffline: true,
|
|
335
|
-
sharingType: "private",
|
|
336
|
-
},
|
|
337
324
|
},
|
|
338
325
|
});
|
|
339
326
|
expect(result.isError).toBeUndefined();
|
|
340
|
-
expect(result.structuredContent).
|
|
341
|
-
driveId:
|
|
327
|
+
expect(result.structuredContent).toMatchObject({
|
|
328
|
+
driveId: expect.any(String),
|
|
342
329
|
});
|
|
343
|
-
const drive = await
|
|
330
|
+
const drive = await client.get(result.structuredContent.driveId);
|
|
344
331
|
expect(drive).toMatchObject({
|
|
345
332
|
header: expect.objectContaining({
|
|
346
333
|
documentType: "powerhouse/document-drive",
|
|
347
334
|
}),
|
|
348
|
-
state: expect.objectContaining({
|
|
349
|
-
global: expect.objectContaining({
|
|
350
|
-
name: expect.any(String),
|
|
351
|
-
}),
|
|
352
|
-
}),
|
|
353
335
|
});
|
|
354
336
|
});
|
|
355
337
|
it("should add a drive with minimal input", async () => {
|
|
356
|
-
const provider = await createReactorMcpProvider(
|
|
338
|
+
const provider = await createReactorMcpProvider({ client });
|
|
357
339
|
const result = await provider.tools.addDrive.callback({
|
|
358
340
|
driveInput: {
|
|
359
341
|
global: {
|
|
@@ -362,51 +344,23 @@ describe.skip("ReactorMcpProvider", () => {
|
|
|
362
344
|
},
|
|
363
345
|
});
|
|
364
346
|
expect(result.isError).toBeUndefined();
|
|
365
|
-
expect(result.structuredContent).
|
|
347
|
+
expect(result.structuredContent).toMatchObject({
|
|
366
348
|
driveId: expect.any(String),
|
|
367
349
|
});
|
|
368
|
-
const drive = await
|
|
350
|
+
const drive = await client.get(result.structuredContent.driveId);
|
|
369
351
|
expect(drive).toMatchObject({
|
|
370
352
|
header: expect.objectContaining({
|
|
371
353
|
documentType: "powerhouse/document-drive",
|
|
372
354
|
}),
|
|
373
|
-
state: expect.objectContaining({
|
|
374
|
-
global: expect.objectContaining({
|
|
375
|
-
name: expect.any(String),
|
|
376
|
-
}),
|
|
377
|
-
}),
|
|
378
355
|
});
|
|
379
356
|
});
|
|
380
357
|
});
|
|
381
358
|
describe("getDrive tool", () => {
|
|
382
359
|
it("should get a specific drive", async () => {
|
|
383
|
-
const drive = await
|
|
384
|
-
const provider = await createReactorMcpProvider(
|
|
360
|
+
const drive = await client.createEmpty("powerhouse/document-drive");
|
|
361
|
+
const provider = await createReactorMcpProvider({ client });
|
|
385
362
|
const result = await provider.tools.getDrive.callback({
|
|
386
|
-
driveId: drive
|
|
387
|
-
});
|
|
388
|
-
expect(result.isError).toBeUndefined();
|
|
389
|
-
expect(result.structuredContent).toMatchObject({
|
|
390
|
-
drive: expect.objectContaining({
|
|
391
|
-
header: expect.objectContaining({
|
|
392
|
-
documentType: "powerhouse/document-drive",
|
|
393
|
-
}),
|
|
394
|
-
state: expect.objectContaining({
|
|
395
|
-
global: expect.objectContaining({
|
|
396
|
-
name: expect.any(String),
|
|
397
|
-
}),
|
|
398
|
-
}),
|
|
399
|
-
}),
|
|
400
|
-
});
|
|
401
|
-
});
|
|
402
|
-
it("should get a drive with options", async () => {
|
|
403
|
-
const drive = await reactor.addDrive({ global: { name: "Test Drive" } });
|
|
404
|
-
const provider = await createReactorMcpProvider(reactor);
|
|
405
|
-
const result = await provider.tools.getDrive.callback({
|
|
406
|
-
driveId: drive?.header.id,
|
|
407
|
-
options: {
|
|
408
|
-
checkHashes: true,
|
|
409
|
-
},
|
|
363
|
+
driveId: drive.header.id,
|
|
410
364
|
});
|
|
411
365
|
expect(result.isError).toBeUndefined();
|
|
412
366
|
expect(result.structuredContent).toMatchObject({
|
|
@@ -414,19 +368,14 @@ describe.skip("ReactorMcpProvider", () => {
|
|
|
414
368
|
header: expect.objectContaining({
|
|
415
369
|
documentType: "powerhouse/document-drive",
|
|
416
370
|
}),
|
|
417
|
-
state: expect.objectContaining({
|
|
418
|
-
global: expect.objectContaining({
|
|
419
|
-
name: expect.any(String),
|
|
420
|
-
}),
|
|
421
|
-
}),
|
|
422
371
|
}),
|
|
423
372
|
});
|
|
424
373
|
});
|
|
425
374
|
});
|
|
426
375
|
describe("deleteDrive tool", () => {
|
|
427
376
|
it("should delete a drive successfully", async () => {
|
|
428
|
-
const drive = await
|
|
429
|
-
const provider = await createReactorMcpProvider(
|
|
377
|
+
const drive = await client.createEmpty("powerhouse/document-drive");
|
|
378
|
+
const provider = await createReactorMcpProvider({ client });
|
|
430
379
|
const result = await provider.tools.deleteDrive.callback({
|
|
431
380
|
driveId: drive.header.id,
|
|
432
381
|
});
|
|
@@ -436,29 +385,20 @@ describe.skip("ReactorMcpProvider", () => {
|
|
|
436
385
|
});
|
|
437
386
|
});
|
|
438
387
|
it("should handle deletion of non-existent drive", async () => {
|
|
439
|
-
const provider = await createReactorMcpProvider(
|
|
388
|
+
const provider = await createReactorMcpProvider({ client });
|
|
440
389
|
const result = await provider.tools.deleteDrive.callback({
|
|
441
390
|
driveId: "non-existent-drive-id",
|
|
442
391
|
});
|
|
443
|
-
|
|
444
|
-
// The reactor implementation returns true even for non-existent drives
|
|
392
|
+
// The new reactor throws for non-existent documents
|
|
445
393
|
expect(result.structuredContent).toMatchObject({
|
|
446
|
-
success:
|
|
394
|
+
success: false,
|
|
447
395
|
});
|
|
448
396
|
});
|
|
449
397
|
});
|
|
450
398
|
describe("addRemoteDrive tool", () => {
|
|
451
|
-
it("should
|
|
452
|
-
//
|
|
453
|
-
|
|
454
|
-
header: { id: "remote-drive-id" },
|
|
455
|
-
state: { global: { name: "Remote Drive" } },
|
|
456
|
-
});
|
|
457
|
-
mockReactor.getDrive = vi.fn().mockResolvedValue({
|
|
458
|
-
header: { id: "remote-drive-id" },
|
|
459
|
-
state: { global: { name: "Remote Drive" } },
|
|
460
|
-
});
|
|
461
|
-
const provider = await createReactorMcpProvider(mockReactor);
|
|
399
|
+
it("should return an error when syncManager is not configured", async () => {
|
|
400
|
+
// No syncManager provided
|
|
401
|
+
const provider = await createReactorMcpProvider({ client });
|
|
462
402
|
const result = await provider.tools.addRemoteDrive.callback({
|
|
463
403
|
url: "https://example.com/remote-drive",
|
|
464
404
|
options: {
|
|
@@ -473,28 +413,45 @@ describe.skip("ReactorMcpProvider", () => {
|
|
|
473
413
|
pullInterval: 30000,
|
|
474
414
|
},
|
|
475
415
|
});
|
|
416
|
+
expect(result.isError).toBe(true);
|
|
417
|
+
expect(getTextContent(result)).toContain("Remote drive management is not available");
|
|
418
|
+
expect(getTextContent(result)).toContain("SyncManager was not configured");
|
|
419
|
+
});
|
|
420
|
+
});
|
|
421
|
+
describe("getDocumentModels tool", () => {
|
|
422
|
+
it("should list available document models", async () => {
|
|
423
|
+
const provider = await createReactorMcpProvider({ client });
|
|
424
|
+
const result = await provider.tools.getDocumentModels.callback({});
|
|
476
425
|
expect(result.isError).toBeUndefined();
|
|
477
|
-
expect(result.structuredContent).
|
|
478
|
-
|
|
426
|
+
expect(result.structuredContent).toMatchObject({
|
|
427
|
+
documentModels: expect.any(Array),
|
|
479
428
|
});
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
})
|
|
429
|
+
// Should include at least the document model and drive document model
|
|
430
|
+
const models = result.structuredContent.documentModels;
|
|
431
|
+
expect(models.length).toBeGreaterThanOrEqual(2);
|
|
432
|
+
});
|
|
433
|
+
});
|
|
434
|
+
describe("getDocumentModelSchema tool", () => {
|
|
435
|
+
it("should get schema for a document model", async () => {
|
|
436
|
+
const provider = await createReactorMcpProvider({ client });
|
|
437
|
+
const result = await provider.tools.getDocumentModelSchema.callback({
|
|
438
|
+
type: "powerhouse/document-model",
|
|
439
|
+
});
|
|
440
|
+
expect(result.isError).toBeUndefined();
|
|
441
|
+
expect(result.structuredContent).toMatchObject({
|
|
442
|
+
schema: expect.objectContaining({
|
|
443
|
+
name: expect.any(String),
|
|
444
|
+
id: "powerhouse/document-model",
|
|
445
|
+
}),
|
|
446
|
+
});
|
|
447
|
+
});
|
|
448
|
+
it("should return error for non-existent document model", async () => {
|
|
449
|
+
const provider = await createReactorMcpProvider({ client });
|
|
450
|
+
const result = await provider.tools.getDocumentModelSchema.callback({
|
|
451
|
+
type: "non-existent/model",
|
|
452
|
+
});
|
|
453
|
+
expect(result.isError).toBe(true);
|
|
454
|
+
expect(getTextContent(result)).toContain("non-existent/model");
|
|
498
455
|
});
|
|
499
456
|
});
|
|
500
457
|
});
|