@morphllm/subagents 0.1.3 → 0.1.4
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/base-client-B7fgl_Wg.d.mts +30 -0
- package/dist/base-client-C6pbtqLX.d.ts +30 -0
- package/dist/core/index.d.mts +4 -30
- package/dist/core/index.d.ts +4 -30
- package/dist/docx/index.d.mts +193 -11
- package/dist/docx/index.d.ts +193 -11
- package/dist/docx/index.js +156 -402
- package/dist/docx/index.js.map +1 -1
- package/dist/docx/index.mjs +156 -402
- package/dist/docx/index.mjs.map +1 -1
- package/dist/index.d.mts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +164 -263
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +164 -263
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/docx/agent.ts +134 -274
- package/src/docx/client.ts +58 -1
- package/src/docx/types.ts +146 -2
package/dist/docx/index.js
CHANGED
|
@@ -69,7 +69,7 @@ var BaseClient = class {
|
|
|
69
69
|
};
|
|
70
70
|
|
|
71
71
|
// src/docx/client.ts
|
|
72
|
-
var DEFAULT_API_URL = "https://
|
|
72
|
+
var DEFAULT_API_URL = "https://subagents.morphllm.com/v1/morph-docx";
|
|
73
73
|
var DocxClient = class extends BaseClient {
|
|
74
74
|
constructor(options = {}) {
|
|
75
75
|
super(options);
|
|
@@ -115,333 +115,60 @@ var DocxClient = class extends BaseClient {
|
|
|
115
115
|
async deleteDocument(docId) {
|
|
116
116
|
return this.delete(`/documents/${docId}`);
|
|
117
117
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
this.
|
|
124
|
-
this.model = options.model || this.getDefaultModel();
|
|
125
|
-
this.instructions = options.instructions || this.getDefaultInstructions();
|
|
126
|
-
this.client = options.client;
|
|
118
|
+
// --- Creation Operations ---
|
|
119
|
+
/**
|
|
120
|
+
* Create a new empty DOCX document.
|
|
121
|
+
*/
|
|
122
|
+
async create(title) {
|
|
123
|
+
return this.post("/documents/create", { title });
|
|
127
124
|
}
|
|
128
|
-
/**
|
|
129
|
-
|
|
130
|
-
|
|
125
|
+
/**
|
|
126
|
+
* Execute build operations on a document (add content).
|
|
127
|
+
*/
|
|
128
|
+
async build(docId, operations) {
|
|
129
|
+
return this.post(`/documents/${docId}/build`, { operations });
|
|
131
130
|
}
|
|
132
131
|
/**
|
|
133
|
-
*
|
|
134
|
-
* Returns the final response and all tool calls made.
|
|
132
|
+
* Get document information.
|
|
135
133
|
*/
|
|
136
|
-
async
|
|
137
|
-
|
|
138
|
-
throw new Error("OpenAI client is required for agent.run(). Pass it in the constructor options.");
|
|
139
|
-
}
|
|
140
|
-
const messages = [
|
|
141
|
-
{ role: "system", content: this.instructions },
|
|
142
|
-
...conversationHistory,
|
|
143
|
-
{ role: "user", content: userMessage }
|
|
144
|
-
];
|
|
145
|
-
const toolCalls = [];
|
|
146
|
-
let response = "";
|
|
147
|
-
const tools = this.getTools();
|
|
148
|
-
while (true) {
|
|
149
|
-
const completion = await this.openai.chat.completions.create({
|
|
150
|
-
model: this.model,
|
|
151
|
-
messages,
|
|
152
|
-
tools,
|
|
153
|
-
tool_choice: "auto"
|
|
154
|
-
});
|
|
155
|
-
const assistantMessage = completion.choices[0].message;
|
|
156
|
-
if (assistantMessage.tool_calls && assistantMessage.tool_calls.length > 0) {
|
|
157
|
-
messages.push({
|
|
158
|
-
role: "assistant",
|
|
159
|
-
content: assistantMessage.content || ""
|
|
160
|
-
});
|
|
161
|
-
for (const tc of assistantMessage.tool_calls) {
|
|
162
|
-
const fn = tc.function;
|
|
163
|
-
const args = JSON.parse(fn.arguments);
|
|
164
|
-
const toolCall = {
|
|
165
|
-
id: tc.id,
|
|
166
|
-
name: fn.name,
|
|
167
|
-
arguments: args,
|
|
168
|
-
status: "running"
|
|
169
|
-
};
|
|
170
|
-
toolCalls.push(toolCall);
|
|
171
|
-
const result = await this.executeTool(fn.name, args);
|
|
172
|
-
if (result.startsWith("Error:")) {
|
|
173
|
-
toolCall.error = result;
|
|
174
|
-
toolCall.status = "error";
|
|
175
|
-
} else {
|
|
176
|
-
toolCall.result = result;
|
|
177
|
-
toolCall.status = "completed";
|
|
178
|
-
}
|
|
179
|
-
messages.push({
|
|
180
|
-
role: "tool",
|
|
181
|
-
content: result,
|
|
182
|
-
tool_call_id: tc.id
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
} else {
|
|
186
|
-
response = assistantMessage.content || "";
|
|
187
|
-
break;
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
return { response, toolCalls };
|
|
134
|
+
async getInfo(docId) {
|
|
135
|
+
return this.get(`/documents/${docId}/info`);
|
|
191
136
|
}
|
|
137
|
+
// --- Convenience Methods ---
|
|
192
138
|
/**
|
|
193
|
-
*
|
|
194
|
-
* Yields events for real-time UI updates.
|
|
139
|
+
* Add a heading to the document.
|
|
195
140
|
*/
|
|
196
|
-
async
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
const toolCallBuffers = /* @__PURE__ */ new Map();
|
|
217
|
-
for await (const chunk of stream) {
|
|
218
|
-
const delta = chunk.choices[0]?.delta;
|
|
219
|
-
if (delta?.content) {
|
|
220
|
-
contentBuffer += delta.content;
|
|
221
|
-
yield { type: "content_delta", delta: { text: delta.content } };
|
|
222
|
-
}
|
|
223
|
-
if (delta?.tool_calls) {
|
|
224
|
-
for (const tc of delta.tool_calls) {
|
|
225
|
-
const idx = tc.index;
|
|
226
|
-
if (!toolCallBuffers.has(idx)) {
|
|
227
|
-
toolCallBuffers.set(idx, { id: "", name: "", arguments: "" });
|
|
228
|
-
}
|
|
229
|
-
const buffer = toolCallBuffers.get(idx);
|
|
230
|
-
if (tc.id) buffer.id = tc.id;
|
|
231
|
-
if (tc.function?.name) buffer.name = tc.function.name;
|
|
232
|
-
if (tc.function?.arguments) buffer.arguments += tc.function.arguments;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
if (toolCallBuffers.size > 0) {
|
|
237
|
-
messages.push({
|
|
238
|
-
role: "assistant",
|
|
239
|
-
content: contentBuffer
|
|
240
|
-
});
|
|
241
|
-
for (const [_, buffer] of toolCallBuffers) {
|
|
242
|
-
const args = JSON.parse(buffer.arguments);
|
|
243
|
-
yield {
|
|
244
|
-
type: "tool_start",
|
|
245
|
-
tool: { id: buffer.id, name: buffer.name, arguments: args }
|
|
246
|
-
};
|
|
247
|
-
const result = await this.executeTool(buffer.name, args);
|
|
248
|
-
if (result.startsWith("Error:")) {
|
|
249
|
-
yield { type: "tool_end", tool: { id: buffer.id, error: result } };
|
|
250
|
-
} else {
|
|
251
|
-
yield { type: "tool_end", tool: { id: buffer.id, result } };
|
|
252
|
-
}
|
|
253
|
-
messages.push({
|
|
254
|
-
role: "tool",
|
|
255
|
-
content: result,
|
|
256
|
-
tool_call_id: buffer.id
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
} else {
|
|
260
|
-
yield { type: "message_end" };
|
|
261
|
-
break;
|
|
262
|
-
}
|
|
263
|
-
}
|
|
141
|
+
async addHeading(docId, text, level = 1) {
|
|
142
|
+
return this.build(docId, [{ type: "add_heading", text, level }]);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Add a paragraph to the document.
|
|
146
|
+
*/
|
|
147
|
+
async addParagraph(docId, text, options) {
|
|
148
|
+
return this.build(docId, [{ type: "add_paragraph", text, ...options }]);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Add a table to the document.
|
|
152
|
+
*/
|
|
153
|
+
async addTable(docId, headers, rows) {
|
|
154
|
+
return this.build(docId, [{ type: "add_table", headers, rows }]);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Add page numbers to the document.
|
|
158
|
+
*/
|
|
159
|
+
async addPageNumbers(docId, format = "Page {PAGE} of {NUMPAGES}") {
|
|
160
|
+
return this.build(docId, [{ type: "add_page_numbers", format_string: format }]);
|
|
264
161
|
}
|
|
265
162
|
};
|
|
266
163
|
|
|
267
164
|
// src/docx/agent.ts
|
|
268
|
-
var
|
|
269
|
-
|
|
270
|
-
When editing documents:
|
|
271
|
-
1. First read the document to understand its structure
|
|
272
|
-
2. Use track changes for all modifications
|
|
273
|
-
3. Add comments to flag issues or request clarification
|
|
274
|
-
4. Be precise with paragraph text matching - use unique text snippets
|
|
275
|
-
|
|
276
|
-
Available tools:
|
|
277
|
-
- read_document: Read the document content
|
|
278
|
-
- add_comment: Add a comment to a specific paragraph
|
|
279
|
-
- insert_text: Insert text within a paragraph (tracked change)
|
|
280
|
-
- propose_deletion: Mark text for deletion (tracked change)
|
|
281
|
-
- reply_comment: Reply to an existing comment
|
|
282
|
-
- resolve_comment: Mark a comment as resolved
|
|
283
|
-
- delete_comment: Delete a comment
|
|
284
|
-
- insert_paragraph: Insert a new paragraph
|
|
285
|
-
- validate_document: Validate DOCX structure`;
|
|
286
|
-
var TOOLS = [
|
|
287
|
-
{
|
|
288
|
-
type: "function",
|
|
289
|
-
function: {
|
|
290
|
-
name: "read_document",
|
|
291
|
-
description: "Read the document content as plain text",
|
|
292
|
-
parameters: {
|
|
293
|
-
type: "object",
|
|
294
|
-
properties: {
|
|
295
|
-
doc_id: { type: "string", description: "Document ID" }
|
|
296
|
-
},
|
|
297
|
-
required: ["doc_id"]
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
},
|
|
301
|
-
{
|
|
302
|
-
type: "function",
|
|
303
|
-
function: {
|
|
304
|
-
name: "add_comment",
|
|
305
|
-
description: "Add a comment to a specific paragraph in the document",
|
|
306
|
-
parameters: {
|
|
307
|
-
type: "object",
|
|
308
|
-
properties: {
|
|
309
|
-
doc_id: { type: "string", description: "Document ID" },
|
|
310
|
-
para_text: { type: "string", description: "Unique text from the target paragraph" },
|
|
311
|
-
comment: { type: "string", description: "Comment text to add" },
|
|
312
|
-
highlight: { type: "string", description: "Optional specific text to highlight" }
|
|
313
|
-
},
|
|
314
|
-
required: ["doc_id", "para_text", "comment"]
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
},
|
|
318
|
-
{
|
|
319
|
-
type: "function",
|
|
320
|
-
function: {
|
|
321
|
-
name: "insert_text",
|
|
322
|
-
description: "Insert text within a paragraph (creates a tracked change)",
|
|
323
|
-
parameters: {
|
|
324
|
-
type: "object",
|
|
325
|
-
properties: {
|
|
326
|
-
doc_id: { type: "string", description: "Document ID" },
|
|
327
|
-
para_text: { type: "string", description: "Unique text from the target paragraph" },
|
|
328
|
-
after: { type: "string", description: "Text after which to insert" },
|
|
329
|
-
new_text: { type: "string", description: "Text to insert" }
|
|
330
|
-
},
|
|
331
|
-
required: ["doc_id", "para_text", "after", "new_text"]
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
},
|
|
335
|
-
{
|
|
336
|
-
type: "function",
|
|
337
|
-
function: {
|
|
338
|
-
name: "propose_deletion",
|
|
339
|
-
description: "Mark text for deletion (creates a tracked change)",
|
|
340
|
-
parameters: {
|
|
341
|
-
type: "object",
|
|
342
|
-
properties: {
|
|
343
|
-
doc_id: { type: "string", description: "Document ID" },
|
|
344
|
-
para_text: { type: "string", description: "Unique text from the target paragraph" },
|
|
345
|
-
target: { type: "string", description: "Specific text to delete (optional, defaults to whole paragraph)" }
|
|
346
|
-
},
|
|
347
|
-
required: ["doc_id", "para_text"]
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
},
|
|
351
|
-
{
|
|
352
|
-
type: "function",
|
|
353
|
-
function: {
|
|
354
|
-
name: "reply_comment",
|
|
355
|
-
description: "Reply to an existing comment",
|
|
356
|
-
parameters: {
|
|
357
|
-
type: "object",
|
|
358
|
-
properties: {
|
|
359
|
-
doc_id: { type: "string", description: "Document ID" },
|
|
360
|
-
comment_id: { type: "string", description: "ID of the comment to reply to" },
|
|
361
|
-
reply: { type: "string", description: "Reply text" }
|
|
362
|
-
},
|
|
363
|
-
required: ["doc_id", "comment_id", "reply"]
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
},
|
|
367
|
-
{
|
|
368
|
-
type: "function",
|
|
369
|
-
function: {
|
|
370
|
-
name: "resolve_comment",
|
|
371
|
-
description: "Mark a comment as resolved",
|
|
372
|
-
parameters: {
|
|
373
|
-
type: "object",
|
|
374
|
-
properties: {
|
|
375
|
-
doc_id: { type: "string", description: "Document ID" },
|
|
376
|
-
comment_id: { type: "string", description: "ID of the comment to resolve" }
|
|
377
|
-
},
|
|
378
|
-
required: ["doc_id", "comment_id"]
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
},
|
|
382
|
-
{
|
|
383
|
-
type: "function",
|
|
384
|
-
function: {
|
|
385
|
-
name: "delete_comment",
|
|
386
|
-
description: "Delete a comment and its replies",
|
|
387
|
-
parameters: {
|
|
388
|
-
type: "object",
|
|
389
|
-
properties: {
|
|
390
|
-
doc_id: { type: "string", description: "Document ID" },
|
|
391
|
-
comment_id: { type: "string", description: "ID of the comment to delete" }
|
|
392
|
-
},
|
|
393
|
-
required: ["doc_id", "comment_id"]
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
},
|
|
397
|
-
{
|
|
398
|
-
type: "function",
|
|
399
|
-
function: {
|
|
400
|
-
name: "insert_paragraph",
|
|
401
|
-
description: "Insert a new paragraph after existing text",
|
|
402
|
-
parameters: {
|
|
403
|
-
type: "object",
|
|
404
|
-
properties: {
|
|
405
|
-
doc_id: { type: "string", description: "Document ID" },
|
|
406
|
-
after_text: { type: "string", description: "Text after which to insert the new paragraph" },
|
|
407
|
-
new_text: { type: "string", description: "Content of the new paragraph" }
|
|
408
|
-
},
|
|
409
|
-
required: ["doc_id", "after_text", "new_text"]
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
},
|
|
413
|
-
{
|
|
414
|
-
type: "function",
|
|
415
|
-
function: {
|
|
416
|
-
name: "validate_document",
|
|
417
|
-
description: "Validate the document structure",
|
|
418
|
-
parameters: {
|
|
419
|
-
type: "object",
|
|
420
|
-
properties: {
|
|
421
|
-
doc_id: { type: "string", description: "Document ID" }
|
|
422
|
-
},
|
|
423
|
-
required: ["doc_id"]
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
];
|
|
428
|
-
var DocxAgent = class extends BaseAgent {
|
|
165
|
+
var DEFAULT_BASE_URL = "https://subagents.morphllm.com/v1";
|
|
166
|
+
var DocxAgent = class {
|
|
429
167
|
constructor(options = {}) {
|
|
430
|
-
|
|
431
|
-
|
|
168
|
+
this.baseUrl = options.baseUrl || process.env.MORPH_API_URL || DEFAULT_BASE_URL;
|
|
169
|
+
this.apiKey = options.apiKey || process.env.MORPH_API_KEY || "";
|
|
432
170
|
this.documentId = options.documentId;
|
|
433
171
|
}
|
|
434
|
-
getDefaultModel() {
|
|
435
|
-
return "moonshot-v1-32k";
|
|
436
|
-
}
|
|
437
|
-
getDefaultInstructions() {
|
|
438
|
-
return this.documentId ? `${DEFAULT_INSTRUCTIONS}
|
|
439
|
-
|
|
440
|
-
Current document ID: ${this.documentId}` : DEFAULT_INSTRUCTIONS;
|
|
441
|
-
}
|
|
442
|
-
getTools() {
|
|
443
|
-
return TOOLS;
|
|
444
|
-
}
|
|
445
172
|
/** Set the current document ID */
|
|
446
173
|
setDocument(docId) {
|
|
447
174
|
this.documentId = docId;
|
|
@@ -450,100 +177,127 @@ Current document ID: ${this.documentId}` : DEFAULT_INSTRUCTIONS;
|
|
|
450
177
|
getDocumentId() {
|
|
451
178
|
return this.documentId;
|
|
452
179
|
}
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
180
|
+
/**
|
|
181
|
+
* Send a chat completion request (non-streaming).
|
|
182
|
+
* This runs the full agent loop on the server and returns the final response.
|
|
183
|
+
*/
|
|
184
|
+
async chat(messages) {
|
|
185
|
+
const contextMessages = this.documentId ? messages.map((m, i) => {
|
|
186
|
+
if (i === messages.length - 1 && m.role === "user") {
|
|
187
|
+
return {
|
|
188
|
+
...m,
|
|
189
|
+
content: `[Document ID: ${this.documentId}]
|
|
190
|
+
|
|
191
|
+
${m.content}`
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
return m;
|
|
195
|
+
}) : messages;
|
|
196
|
+
const response = await fetch(`${this.baseUrl}/chat/completions`, {
|
|
197
|
+
method: "POST",
|
|
198
|
+
headers: {
|
|
199
|
+
"Content-Type": "application/json",
|
|
200
|
+
...this.apiKey && { Authorization: `Bearer ${this.apiKey}` }
|
|
201
|
+
},
|
|
202
|
+
body: JSON.stringify({
|
|
203
|
+
model: "morph-docx",
|
|
204
|
+
messages: contextMessages,
|
|
205
|
+
stream: false
|
|
206
|
+
})
|
|
207
|
+
});
|
|
208
|
+
if (!response.ok) {
|
|
209
|
+
const error = await response.text();
|
|
210
|
+
throw new Error(`API error: ${error}`);
|
|
457
211
|
}
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
212
|
+
return response.json();
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Send a streaming chat completion request.
|
|
216
|
+
* Returns an async generator that yields chunks as they arrive.
|
|
217
|
+
*/
|
|
218
|
+
async *chatStream(messages) {
|
|
219
|
+
const contextMessages = this.documentId ? messages.map((m, i) => {
|
|
220
|
+
if (i === messages.length - 1 && m.role === "user") {
|
|
221
|
+
return {
|
|
222
|
+
...m,
|
|
223
|
+
content: `[Document ID: ${this.documentId}]
|
|
463
224
|
|
|
464
|
-
${
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
]);
|
|
506
|
-
return result.results[0];
|
|
507
|
-
}
|
|
508
|
-
case "resolve_comment": {
|
|
509
|
-
const result = await this.client.edit(docId, [
|
|
510
|
-
{
|
|
511
|
-
type: "resolve_comment",
|
|
512
|
-
comment_id: args.comment_id
|
|
513
|
-
}
|
|
514
|
-
]);
|
|
515
|
-
return result.results[0];
|
|
516
|
-
}
|
|
517
|
-
case "delete_comment": {
|
|
518
|
-
const result = await this.client.edit(docId, [
|
|
519
|
-
{
|
|
520
|
-
type: "delete_comment",
|
|
521
|
-
comment_id: args.comment_id
|
|
522
|
-
}
|
|
523
|
-
]);
|
|
524
|
-
return result.results[0];
|
|
525
|
-
}
|
|
526
|
-
case "insert_paragraph": {
|
|
527
|
-
const result = await this.client.edit(docId, [
|
|
528
|
-
{
|
|
529
|
-
type: "insert_paragraph",
|
|
530
|
-
after_text: args.after_text,
|
|
531
|
-
new_text: args.new_text
|
|
532
|
-
}
|
|
533
|
-
]);
|
|
534
|
-
return result.results[0];
|
|
535
|
-
}
|
|
536
|
-
case "validate_document": {
|
|
537
|
-
const result = await this.client.validate(docId);
|
|
538
|
-
return `${result.result}: ${result.output}`;
|
|
225
|
+
${m.content}`
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
return m;
|
|
229
|
+
}) : messages;
|
|
230
|
+
const response = await fetch(`${this.baseUrl}/chat/completions`, {
|
|
231
|
+
method: "POST",
|
|
232
|
+
headers: {
|
|
233
|
+
"Content-Type": "application/json",
|
|
234
|
+
...this.apiKey && { Authorization: `Bearer ${this.apiKey}` }
|
|
235
|
+
},
|
|
236
|
+
body: JSON.stringify({
|
|
237
|
+
model: "morph-docx",
|
|
238
|
+
messages: contextMessages,
|
|
239
|
+
stream: true
|
|
240
|
+
})
|
|
241
|
+
});
|
|
242
|
+
if (!response.ok) {
|
|
243
|
+
const error = await response.text();
|
|
244
|
+
throw new Error(`API error: ${error}`);
|
|
245
|
+
}
|
|
246
|
+
const reader = response.body?.getReader();
|
|
247
|
+
if (!reader) {
|
|
248
|
+
throw new Error("No response body");
|
|
249
|
+
}
|
|
250
|
+
const decoder = new TextDecoder();
|
|
251
|
+
let buffer = "";
|
|
252
|
+
while (true) {
|
|
253
|
+
const { done, value } = await reader.read();
|
|
254
|
+
if (done) break;
|
|
255
|
+
buffer += decoder.decode(value, { stream: true });
|
|
256
|
+
const lines = buffer.split("\n");
|
|
257
|
+
buffer = lines.pop() || "";
|
|
258
|
+
for (const line of lines) {
|
|
259
|
+
if (!line.startsWith("data: ")) continue;
|
|
260
|
+
const data = line.slice(6).trim();
|
|
261
|
+
if (data === "[DONE]") return;
|
|
262
|
+
try {
|
|
263
|
+
const chunk = JSON.parse(data);
|
|
264
|
+
yield chunk;
|
|
265
|
+
} catch {
|
|
539
266
|
}
|
|
540
|
-
default:
|
|
541
|
-
return `Error: Unknown tool '${name}'`;
|
|
542
267
|
}
|
|
543
|
-
} catch (error) {
|
|
544
|
-
return `Error: ${error instanceof Error ? error.message : String(error)}`;
|
|
545
268
|
}
|
|
546
269
|
}
|
|
270
|
+
/**
|
|
271
|
+
* Helper: Simple completion that returns just the content string.
|
|
272
|
+
*/
|
|
273
|
+
async complete(userMessage) {
|
|
274
|
+
const response = await this.chat([{ role: "user", content: userMessage }]);
|
|
275
|
+
return response.choices[0]?.message?.content || "";
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Create an OpenAI-compatible client configuration.
|
|
279
|
+
* Use this with the OpenAI SDK or OpenAI Agents SDK.
|
|
280
|
+
*
|
|
281
|
+
* @example
|
|
282
|
+
* ```typescript
|
|
283
|
+
* import OpenAI from 'openai';
|
|
284
|
+
* import { DocxAgent } from '@morphllm/subagents/docx';
|
|
285
|
+
*
|
|
286
|
+
* const agent = new DocxAgent();
|
|
287
|
+
* const openai = new OpenAI(agent.getOpenAIConfig());
|
|
288
|
+
*
|
|
289
|
+
* const response = await openai.chat.completions.create({
|
|
290
|
+
* model: 'morph-docx',
|
|
291
|
+
* messages: [{ role: 'user', content: 'Hello!' }],
|
|
292
|
+
* });
|
|
293
|
+
* ```
|
|
294
|
+
*/
|
|
295
|
+
getOpenAIConfig() {
|
|
296
|
+
return {
|
|
297
|
+
baseURL: this.baseUrl,
|
|
298
|
+
apiKey: this.apiKey || "not-required"
|
|
299
|
+
};
|
|
300
|
+
}
|
|
547
301
|
};
|
|
548
302
|
|
|
549
303
|
exports.DocxAgent = DocxAgent;
|