mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-14 10:34:06 +02:00
create agent (#6520)
Added the create agent. Use [these prompts](https://github.com/Stirling-Tools/Stirling-PDF-SaaS/blob/main/docgen/backend/default_templates/sample_prompts.md) to test or try your own :) Here’s the one I use ``` Hey, I need to generate an employee expense report for reimbursement. Company: Summit Consulting Partners Company address: 88 Riverside Plaza, Suite 1400, New York, NY 10069 Accounting department email: [email protected] Employee details: * Employee Name: Michael Tran * Employee ID: EMP-1047 * Department: Client Services * Report Date: January 20th, 2026 * Reporting Period: January 5th, 2026 – January 16th, 2026 * Manager Approver: Laura Simmons Trip purpose: Client onsite meetings with Atlantic Energy Solutions in Boston, MA. Expense items: * Flight (NYC to Boston roundtrip) — $325.40 — January 5th, 2026 — Airline ticket * Hotel (3 nights at Harborview Hotel) — $822.75 — January 5th-8th, 2026 * Taxi from airport to hotel — $48.00 — January 5th, 2026 * Client dinner (3 attendees) — $186.20 — January 6th, 2026 * Parking at JFK Airport — $72.00 — January 5th-8th, 2026 * Breakfast (per diem not used) — $18.50 — January 7th, 2026 * Uber to client office — $22.10 — January 7th, 2026 * Printing + presentation materials — $46.90 — January 8th, 2026 * Lunch with client — $39.75 — January 8th, 2026 * Office supplies (notebooks, pens) — $27.60 — January 10th, 2026 * Mileage reimbursement (client visit in NJ, 42 miles @ $0.67/mile) — $28.14 — January 14th, 2026 * Team lunch meeting (internal) — $64.30 — January 15th, 2026 Reimbursement method should be direct deposit. Add a notes section stating: "All receipts attached. Expenses are business-related and comply with company travel policy." ``` --------- Co-authored-by: Anthony Stirling <[email protected]>
This commit is contained in:
co-authored by
Anthony Stirling
parent
9b877d4f8d
commit
88adb7adad
@@ -14,6 +14,7 @@ export function useChat() {
|
||||
toggleOpen: () => {},
|
||||
setOpen: (_open: boolean) => {},
|
||||
sendMessage: async (_content: string) => {},
|
||||
cancelMessage: () => {},
|
||||
clearChat: () => {},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -370,6 +370,7 @@ interface ChatContextValue {
|
||||
toggleOpen: () => void;
|
||||
setOpen: (open: boolean) => void;
|
||||
sendMessage: (content: string) => Promise<void>;
|
||||
cancelMessage: () => void;
|
||||
/** Abort any in-flight request and reset the chat to an empty conversation. */
|
||||
clearChat: () => void;
|
||||
}
|
||||
@@ -432,32 +433,32 @@ export function ChatProvider({ children }: { children: ReactNode }) {
|
||||
|
||||
const files = await Promise.all(descriptors.map(downloadFile));
|
||||
|
||||
const operation: ToolOperation = {
|
||||
toolId: "ai-workflow",
|
||||
timestamp: Date.now(),
|
||||
};
|
||||
const isVersionMapping =
|
||||
sourceStubs.length > 0 && files.length === sourceStubs.length;
|
||||
const stubs = files.map((file, i) =>
|
||||
isVersionMapping
|
||||
? createChildStub(sourceStubs[i], operation, file)
|
||||
: createNewStirlingFileStub(file),
|
||||
);
|
||||
const stirlingFiles = files.map((file, i) =>
|
||||
createStirlingFile(file, stubs[i].id),
|
||||
);
|
||||
|
||||
if (sourceStubs.length > 0) {
|
||||
// Always consume the inputs so merge/split inputs are removed from the workbench.
|
||||
// For 1:1 operations (rotate, compress) the outputs carry the version chain; for
|
||||
// merge/split they're fresh roots.
|
||||
const operation: ToolOperation = {
|
||||
toolId: "ai-workflow",
|
||||
timestamp: Date.now(),
|
||||
};
|
||||
const isVersionMapping = files.length === sourceStubs.length;
|
||||
const stubs = files.map((file, i) =>
|
||||
isVersionMapping
|
||||
? createChildStub(sourceStubs[i], operation, file)
|
||||
: createNewStirlingFileStub(file),
|
||||
);
|
||||
const stirlingFiles = files.map((file, i) =>
|
||||
createStirlingFile(file, stubs[i].id),
|
||||
);
|
||||
await fileActions.consumeFiles(
|
||||
sourceStubs.map((s) => s.id),
|
||||
stirlingFiles,
|
||||
stubs,
|
||||
);
|
||||
} else {
|
||||
// No inputs were provided (unlikely for completed workflows, but handle it safely).
|
||||
// No inputs: pass raw files so addFiles assigns consistent IDs. Pre-assigning stub IDs
|
||||
// here would cause a fileId mismatch in filesRef, making getFiles() clone the file
|
||||
// on every render and breaking useFileWithUrl's memoisation (continuous PDF reloads).
|
||||
await fileActions.addFiles(files, { selectFiles: true });
|
||||
}
|
||||
},
|
||||
@@ -469,6 +470,10 @@ export function ChatProvider({ children }: { children: ReactNode }) {
|
||||
(open: boolean) => dispatch({ type: "SET_OPEN", open }),
|
||||
[],
|
||||
);
|
||||
const cancelMessage = useCallback(() => {
|
||||
abortRef.current?.abort();
|
||||
}, []);
|
||||
|
||||
const clearChat = useCallback(() => {
|
||||
abortRef.current?.abort();
|
||||
abortRef.current = null;
|
||||
@@ -509,7 +514,6 @@ export function ChatProvider({ children }: { children: ReactNode }) {
|
||||
formData.append(`conversationHistory[${i}].role`, message.role);
|
||||
formData.append(`conversationHistory[${i}].content`, message.content);
|
||||
});
|
||||
|
||||
const response = await fetch("/api/v1/ai/orchestrate/stream", {
|
||||
method: "POST",
|
||||
body: formData,
|
||||
@@ -652,6 +656,7 @@ export function ChatProvider({ children }: { children: ReactNode }) {
|
||||
toggleOpen,
|
||||
setOpen,
|
||||
sendMessage,
|
||||
cancelMessage,
|
||||
clearChat,
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -365,32 +365,32 @@ export function ChatProvider({ children }: { children: ReactNode }) {
|
||||
|
||||
const files = await Promise.all(descriptors.map(downloadFile));
|
||||
|
||||
const operation: ToolOperation = {
|
||||
toolId: "ai-workflow",
|
||||
timestamp: Date.now(),
|
||||
};
|
||||
const isVersionMapping =
|
||||
sourceStubs.length > 0 && files.length === sourceStubs.length;
|
||||
const stubs = files.map((file, i) =>
|
||||
isVersionMapping
|
||||
? createChildStub(sourceStubs[i], operation, file)
|
||||
: createNewStirlingFileStub(file),
|
||||
);
|
||||
const stirlingFiles = files.map((file, i) =>
|
||||
createStirlingFile(file, stubs[i].id),
|
||||
);
|
||||
|
||||
if (sourceStubs.length > 0) {
|
||||
// Always consume the inputs so merge/split inputs are removed from the workbench.
|
||||
// For 1:1 operations (rotate, compress) the outputs carry the version chain; for
|
||||
// merge/split they're fresh roots.
|
||||
const operation: ToolOperation = {
|
||||
toolId: "ai-workflow",
|
||||
timestamp: Date.now(),
|
||||
};
|
||||
const isVersionMapping = files.length === sourceStubs.length;
|
||||
const stubs = files.map((file, i) =>
|
||||
isVersionMapping
|
||||
? createChildStub(sourceStubs[i], operation, file)
|
||||
: createNewStirlingFileStub(file),
|
||||
);
|
||||
const stirlingFiles = files.map((file, i) =>
|
||||
createStirlingFile(file, stubs[i].id),
|
||||
);
|
||||
await fileActions.consumeFiles(
|
||||
sourceStubs.map((s) => s.id),
|
||||
stirlingFiles,
|
||||
stubs,
|
||||
);
|
||||
} else {
|
||||
// No inputs were provided (unlikely for completed workflows, but handle it safely).
|
||||
// No inputs: pass raw files so addFiles assigns consistent IDs. Pre-assigning stub IDs
|
||||
// here would cause a fileId mismatch in filesRef, making getFiles() clone the file
|
||||
// on every render and breaking useFileWithUrl's memoisation (continuous PDF reloads).
|
||||
await fileActions.addFiles(files, { selectFiles: true });
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user