@lakitu/sdk 0.1.0
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/README.md +166 -0
- package/convex/_generated/api.d.ts +45 -0
- package/convex/_generated/api.js +23 -0
- package/convex/_generated/dataModel.d.ts +58 -0
- package/convex/_generated/server.d.ts +143 -0
- package/convex/_generated/server.js +93 -0
- package/convex/cloud/CLAUDE.md +238 -0
- package/convex/cloud/_generated/api.ts +84 -0
- package/convex/cloud/_generated/component.ts +861 -0
- package/convex/cloud/_generated/dataModel.ts +60 -0
- package/convex/cloud/_generated/server.ts +156 -0
- package/convex/cloud/convex.config.ts +16 -0
- package/convex/cloud/index.ts +29 -0
- package/convex/cloud/intentSchema/generate.ts +447 -0
- package/convex/cloud/intentSchema/index.ts +16 -0
- package/convex/cloud/intentSchema/types.ts +418 -0
- package/convex/cloud/ksaPolicy.ts +554 -0
- package/convex/cloud/mail.ts +92 -0
- package/convex/cloud/schema.ts +322 -0
- package/convex/cloud/utils/kanbanContext.ts +229 -0
- package/convex/cloud/workflows/agentBoard.ts +451 -0
- package/convex/cloud/workflows/agentPrompt.ts +272 -0
- package/convex/cloud/workflows/agentThread.ts +374 -0
- package/convex/cloud/workflows/compileSandbox.ts +146 -0
- package/convex/cloud/workflows/crudBoard.ts +217 -0
- package/convex/cloud/workflows/crudKSAs.ts +262 -0
- package/convex/cloud/workflows/crudLorobeads.ts +371 -0
- package/convex/cloud/workflows/crudSkills.ts +205 -0
- package/convex/cloud/workflows/crudThreads.ts +708 -0
- package/convex/cloud/workflows/lifecycleSandbox.ts +1396 -0
- package/convex/cloud/workflows/sandboxConvex.ts +1046 -0
- package/convex/sandbox/README.md +90 -0
- package/convex/sandbox/_generated/api.d.ts +2934 -0
- package/convex/sandbox/_generated/api.js +23 -0
- package/convex/sandbox/_generated/dataModel.d.ts +60 -0
- package/convex/sandbox/_generated/server.d.ts +143 -0
- package/convex/sandbox/_generated/server.js +93 -0
- package/convex/sandbox/actions/bash.ts +130 -0
- package/convex/sandbox/actions/browser.ts +282 -0
- package/convex/sandbox/actions/file.ts +336 -0
- package/convex/sandbox/actions/lsp.ts +325 -0
- package/convex/sandbox/actions/pdf.ts +119 -0
- package/convex/sandbox/agent/codeExecLoop.ts +535 -0
- package/convex/sandbox/agent/decisions.ts +284 -0
- package/convex/sandbox/agent/index.ts +515 -0
- package/convex/sandbox/agent/subagents.ts +651 -0
- package/convex/sandbox/brandResearch/index.ts +417 -0
- package/convex/sandbox/context/index.ts +7 -0
- package/convex/sandbox/context/session.ts +402 -0
- package/convex/sandbox/convex.config.ts +17 -0
- package/convex/sandbox/index.ts +51 -0
- package/convex/sandbox/nodeActions/codeExec.ts +130 -0
- package/convex/sandbox/planning/beads.ts +187 -0
- package/convex/sandbox/planning/index.ts +8 -0
- package/convex/sandbox/planning/sync.ts +194 -0
- package/convex/sandbox/prompts/codeExec.ts +852 -0
- package/convex/sandbox/prompts/modes.ts +231 -0
- package/convex/sandbox/prompts/system.ts +142 -0
- package/convex/sandbox/schema.ts +510 -0
- package/convex/sandbox/state/artifacts.ts +99 -0
- package/convex/sandbox/state/checkpoints.ts +341 -0
- package/convex/sandbox/state/files.ts +383 -0
- package/convex/sandbox/state/index.ts +10 -0
- package/convex/sandbox/state/verification.actions.ts +268 -0
- package/convex/sandbox/state/verification.ts +101 -0
- package/convex/sandbox/tsconfig.json +25 -0
- package/convex/sandbox/utils/codeExecHelpers.ts +52 -0
- package/dist/cli/commands/build.d.ts +19 -0
- package/dist/cli/commands/build.d.ts.map +1 -0
- package/dist/cli/commands/build.js +223 -0
- package/dist/cli/commands/init.d.ts +16 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +148 -0
- package/dist/cli/commands/publish.d.ts +12 -0
- package/dist/cli/commands/publish.d.ts.map +1 -0
- package/dist/cli/commands/publish.js +33 -0
- package/dist/cli/index.d.ts +14 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +40 -0
- package/dist/sdk/builders.d.ts +104 -0
- package/dist/sdk/builders.d.ts.map +1 -0
- package/dist/sdk/builders.js +214 -0
- package/dist/sdk/index.d.ts +29 -0
- package/dist/sdk/index.d.ts.map +1 -0
- package/dist/sdk/index.js +38 -0
- package/dist/sdk/types.d.ts +107 -0
- package/dist/sdk/types.d.ts.map +1 -0
- package/dist/sdk/types.js +6 -0
- package/ksa/README.md +263 -0
- package/ksa/_generated/REFERENCE.md +2954 -0
- package/ksa/_generated/registry.ts +257 -0
- package/ksa/_shared/configReader.ts +302 -0
- package/ksa/_shared/configSchemas.ts +649 -0
- package/ksa/_shared/gateway.ts +175 -0
- package/ksa/_shared/ksaBehaviors.ts +411 -0
- package/ksa/_shared/ksaProxy.ts +248 -0
- package/ksa/_shared/localDb.ts +302 -0
- package/ksa/index.ts +134 -0
- package/package.json +93 -0
- package/runtime/browser/agent-browser.ts +330 -0
- package/runtime/entrypoint.ts +194 -0
- package/runtime/lsp/manager.ts +366 -0
- package/runtime/pdf/pdf-generator.ts +50 -0
- package/runtime/pdf/renderer.ts +357 -0
- package/runtime/pdf/schema.ts +97 -0
- package/runtime/services/file-watcher.ts +191 -0
- package/template/build.ts +307 -0
- package/template/e2b/Dockerfile +69 -0
- package/template/e2b/e2b.toml +13 -0
- package/template/e2b/prebuild.sh +68 -0
- package/template/e2b/start.sh +14 -0
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
"use node";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* LSP Actions
|
|
5
|
+
*
|
|
6
|
+
* Internal actions for Language Server Protocol operations.
|
|
7
|
+
* Manages LSP server lifecycle and communication.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { internalAction } from "../_generated/server";
|
|
11
|
+
import { v } from "convex/values";
|
|
12
|
+
|
|
13
|
+
// LSP server state (managed by runtime/lsp/manager.ts)
|
|
14
|
+
// These actions communicate with the LSP manager
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Get diagnostics for a file
|
|
18
|
+
*/
|
|
19
|
+
export const getDiagnostics = internalAction({
|
|
20
|
+
args: {
|
|
21
|
+
path: v.string(),
|
|
22
|
+
language: v.optional(v.union(v.literal("typescript"), v.literal("python"), v.literal("rust"))),
|
|
23
|
+
},
|
|
24
|
+
handler: async (ctx, args) => {
|
|
25
|
+
const language = args.language || detectLanguage(args.path);
|
|
26
|
+
if (!language) {
|
|
27
|
+
return { success: false, error: "Could not determine language", diagnostics: [] };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
// Read file content
|
|
32
|
+
const fs = await import("fs/promises");
|
|
33
|
+
const content = await fs.readFile(args.path, "utf8");
|
|
34
|
+
|
|
35
|
+
// For TypeScript, we can use the TypeScript compiler API directly
|
|
36
|
+
// This is more reliable than waiting for LSP diagnostics
|
|
37
|
+
if (language === "typescript") {
|
|
38
|
+
const diagnostics = await getTypeScriptDiagnostics(args.path, content);
|
|
39
|
+
return { success: true, diagnostics };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// For other languages, return empty for now
|
|
43
|
+
// Full LSP integration would use the runtime/lsp/manager.ts
|
|
44
|
+
return { success: true, diagnostics: [], message: `LSP for ${language} not yet integrated` };
|
|
45
|
+
} catch (error: any) {
|
|
46
|
+
return { success: false, error: error.message, diagnostics: [] };
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Get completions at a position
|
|
53
|
+
*/
|
|
54
|
+
export const getCompletions = internalAction({
|
|
55
|
+
args: {
|
|
56
|
+
path: v.string(),
|
|
57
|
+
line: v.number(),
|
|
58
|
+
character: v.number(),
|
|
59
|
+
},
|
|
60
|
+
handler: async (ctx, args) => {
|
|
61
|
+
const language = detectLanguage(args.path);
|
|
62
|
+
if (!language) {
|
|
63
|
+
return { success: false, error: "Could not determine language", completions: [] };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
// For TypeScript, use TS language service
|
|
68
|
+
if (language === "typescript") {
|
|
69
|
+
const completions = await getTypeScriptCompletions(args.path, args.line, args.character);
|
|
70
|
+
return { success: true, completions };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return { success: true, completions: [], message: `LSP for ${language} not yet integrated` };
|
|
74
|
+
} catch (error: any) {
|
|
75
|
+
return { success: false, error: error.message, completions: [] };
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Get hover information at a position
|
|
82
|
+
*/
|
|
83
|
+
export const getHover = internalAction({
|
|
84
|
+
args: {
|
|
85
|
+
path: v.string(),
|
|
86
|
+
line: v.number(),
|
|
87
|
+
character: v.number(),
|
|
88
|
+
},
|
|
89
|
+
handler: async (ctx, args) => {
|
|
90
|
+
const language = detectLanguage(args.path);
|
|
91
|
+
if (!language) {
|
|
92
|
+
return { success: false, error: "Could not determine language" };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
try {
|
|
96
|
+
if (language === "typescript") {
|
|
97
|
+
const hover = await getTypeScriptHover(args.path, args.line, args.character);
|
|
98
|
+
return { success: true, hover };
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return { success: true, hover: null, message: `LSP for ${language} not yet integrated` };
|
|
102
|
+
} catch (error: any) {
|
|
103
|
+
return { success: false, error: error.message };
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Get definition locations
|
|
110
|
+
*/
|
|
111
|
+
export const getDefinition = internalAction({
|
|
112
|
+
args: {
|
|
113
|
+
path: v.string(),
|
|
114
|
+
line: v.number(),
|
|
115
|
+
character: v.number(),
|
|
116
|
+
},
|
|
117
|
+
handler: async (ctx, args) => {
|
|
118
|
+
const language = detectLanguage(args.path);
|
|
119
|
+
if (!language) {
|
|
120
|
+
return { success: false, error: "Could not determine language", definitions: [] };
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
try {
|
|
124
|
+
if (language === "typescript") {
|
|
125
|
+
const definitions = await getTypeScriptDefinition(args.path, args.line, args.character);
|
|
126
|
+
return { success: true, definitions };
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return { success: true, definitions: [], message: `LSP for ${language} not yet integrated` };
|
|
130
|
+
} catch (error: any) {
|
|
131
|
+
return { success: false, error: error.message, definitions: [] };
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Get references to a symbol
|
|
138
|
+
*/
|
|
139
|
+
export const getReferences = internalAction({
|
|
140
|
+
args: {
|
|
141
|
+
path: v.string(),
|
|
142
|
+
line: v.number(),
|
|
143
|
+
character: v.number(),
|
|
144
|
+
},
|
|
145
|
+
handler: async (ctx, args) => {
|
|
146
|
+
const language = detectLanguage(args.path);
|
|
147
|
+
if (!language) {
|
|
148
|
+
return { success: false, error: "Could not determine language", references: [] };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
try {
|
|
152
|
+
if (language === "typescript") {
|
|
153
|
+
const references = await getTypeScriptReferences(args.path, args.line, args.character);
|
|
154
|
+
return { success: true, references };
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return { success: true, references: [], message: `LSP for ${language} not yet integrated` };
|
|
158
|
+
} catch (error: any) {
|
|
159
|
+
return { success: false, error: error.message, references: [] };
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Get rename edits for a symbol
|
|
166
|
+
*/
|
|
167
|
+
export const getRenameEdits = internalAction({
|
|
168
|
+
args: {
|
|
169
|
+
path: v.string(),
|
|
170
|
+
line: v.number(),
|
|
171
|
+
character: v.number(),
|
|
172
|
+
newName: v.string(),
|
|
173
|
+
},
|
|
174
|
+
handler: async (ctx, args) => {
|
|
175
|
+
const language = detectLanguage(args.path);
|
|
176
|
+
if (!language) {
|
|
177
|
+
return { success: false, error: "Could not determine language", edits: [] };
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
try {
|
|
181
|
+
if (language === "typescript") {
|
|
182
|
+
const edits = await getTypeScriptRenameEdits(
|
|
183
|
+
args.path,
|
|
184
|
+
args.line,
|
|
185
|
+
args.character,
|
|
186
|
+
args.newName
|
|
187
|
+
);
|
|
188
|
+
return { success: true, edits };
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return { success: true, edits: [], message: `LSP for ${language} not yet integrated` };
|
|
192
|
+
} catch (error: any) {
|
|
193
|
+
return { success: false, error: error.message, edits: [] };
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
// ============================================
|
|
199
|
+
// Helper Functions
|
|
200
|
+
// ============================================
|
|
201
|
+
|
|
202
|
+
function detectLanguage(path: string): "typescript" | "python" | "rust" | null {
|
|
203
|
+
const ext = path.slice(path.lastIndexOf(".")).toLowerCase();
|
|
204
|
+
|
|
205
|
+
if ([".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"].includes(ext)) {
|
|
206
|
+
return "typescript";
|
|
207
|
+
}
|
|
208
|
+
if ([".py", ".pyi"].includes(ext)) {
|
|
209
|
+
return "python";
|
|
210
|
+
}
|
|
211
|
+
if (ext === ".rs") {
|
|
212
|
+
return "rust";
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// TypeScript-specific implementations using the TypeScript compiler API
|
|
219
|
+
|
|
220
|
+
async function getTypeScriptDiagnostics(
|
|
221
|
+
path: string,
|
|
222
|
+
content: string
|
|
223
|
+
): Promise<Array<{
|
|
224
|
+
line: number;
|
|
225
|
+
character: number;
|
|
226
|
+
severity: string;
|
|
227
|
+
message: string;
|
|
228
|
+
code?: number;
|
|
229
|
+
}>> {
|
|
230
|
+
try {
|
|
231
|
+
const ts = await import("typescript");
|
|
232
|
+
|
|
233
|
+
const compilerOptions: any = {
|
|
234
|
+
target: ts.ScriptTarget.ESNext,
|
|
235
|
+
module: ts.ModuleKind.ESNext,
|
|
236
|
+
strict: true,
|
|
237
|
+
esModuleInterop: true,
|
|
238
|
+
skipLibCheck: true,
|
|
239
|
+
noEmit: true,
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
const host = ts.createCompilerHost(compilerOptions);
|
|
243
|
+
const originalReadFile = host.readFile;
|
|
244
|
+
host.readFile = (fileName) => {
|
|
245
|
+
if (fileName === path) return content;
|
|
246
|
+
return originalReadFile(fileName);
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
const program = ts.createProgram([path], compilerOptions, host);
|
|
250
|
+
const sourceFile = program.getSourceFile(path);
|
|
251
|
+
if (!sourceFile) return [];
|
|
252
|
+
|
|
253
|
+
const diagnostics = [
|
|
254
|
+
...program.getSyntacticDiagnostics(sourceFile),
|
|
255
|
+
...program.getSemanticDiagnostics(sourceFile),
|
|
256
|
+
];
|
|
257
|
+
|
|
258
|
+
return diagnostics.map((d) => {
|
|
259
|
+
const start = d.start ?? 0;
|
|
260
|
+
const { line, character } = sourceFile.getLineAndCharacterOfPosition(start);
|
|
261
|
+
|
|
262
|
+
return {
|
|
263
|
+
line,
|
|
264
|
+
character,
|
|
265
|
+
severity:
|
|
266
|
+
d.category === ts.DiagnosticCategory.Error
|
|
267
|
+
? "error"
|
|
268
|
+
: d.category === ts.DiagnosticCategory.Warning
|
|
269
|
+
? "warning"
|
|
270
|
+
: "info",
|
|
271
|
+
message: ts.flattenDiagnosticMessageText(d.messageText, "\n"),
|
|
272
|
+
code: d.code,
|
|
273
|
+
};
|
|
274
|
+
});
|
|
275
|
+
} catch (error) {
|
|
276
|
+
console.error("[lsp] TypeScript diagnostics failed:", error);
|
|
277
|
+
return [];
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
async function getTypeScriptCompletions(
|
|
282
|
+
path: string,
|
|
283
|
+
line: number,
|
|
284
|
+
character: number
|
|
285
|
+
): Promise<Array<{ label: string; kind: string; detail?: string }>> {
|
|
286
|
+
// Simplified completion - full implementation would use TS language service
|
|
287
|
+
return [];
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
async function getTypeScriptHover(
|
|
291
|
+
path: string,
|
|
292
|
+
line: number,
|
|
293
|
+
character: number
|
|
294
|
+
): Promise<{ contents: string } | null> {
|
|
295
|
+
// Simplified hover - full implementation would use TS language service
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
async function getTypeScriptDefinition(
|
|
300
|
+
path: string,
|
|
301
|
+
line: number,
|
|
302
|
+
character: number
|
|
303
|
+
): Promise<Array<{ path: string; line: number; character: number }>> {
|
|
304
|
+
// Simplified definition - full implementation would use TS language service
|
|
305
|
+
return [];
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
async function getTypeScriptReferences(
|
|
309
|
+
path: string,
|
|
310
|
+
line: number,
|
|
311
|
+
character: number
|
|
312
|
+
): Promise<Array<{ path: string; line: number; character: number }>> {
|
|
313
|
+
// Simplified references - full implementation would use TS language service
|
|
314
|
+
return [];
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
async function getTypeScriptRenameEdits(
|
|
318
|
+
path: string,
|
|
319
|
+
line: number,
|
|
320
|
+
character: number,
|
|
321
|
+
newName: string
|
|
322
|
+
): Promise<Array<{ path: string; oldText: string; newText: string; line: number; character: number }>> {
|
|
323
|
+
// Simplified rename - full implementation would use TS language service
|
|
324
|
+
return [];
|
|
325
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use node";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* PDF Generation Action
|
|
5
|
+
*
|
|
6
|
+
* Calls the runtime PDF generator script which uses PDFKit.
|
|
7
|
+
* Running via external script ensures fonts are properly resolved.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { internalAction } from "../_generated/server";
|
|
11
|
+
import { v } from "convex/values";
|
|
12
|
+
import { execSync } from "child_process";
|
|
13
|
+
import * as fs from "fs";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Generate a PDF from markdown content using runtime script
|
|
17
|
+
*/
|
|
18
|
+
export const generatePdf = internalAction({
|
|
19
|
+
args: {
|
|
20
|
+
filename: v.string(),
|
|
21
|
+
content: v.string(),
|
|
22
|
+
title: v.optional(v.string()),
|
|
23
|
+
format: v.optional(v.union(v.literal("a4"), v.literal("letter"))),
|
|
24
|
+
outputDir: v.optional(v.string()),
|
|
25
|
+
},
|
|
26
|
+
handler: async (_ctx, args) => {
|
|
27
|
+
const outputDir = args.outputDir || "/home/user/artifacts";
|
|
28
|
+
const outputPath = `${outputDir}/${args.filename}.pdf`;
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
// Ensure output directory exists
|
|
32
|
+
if (!fs.existsSync(outputDir)) {
|
|
33
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Write content to temp file
|
|
37
|
+
const tempFile = `/tmp/pdf-content-${Date.now()}.md`;
|
|
38
|
+
fs.writeFileSync(tempFile, args.content);
|
|
39
|
+
|
|
40
|
+
// Build command - call the runtime PDF generator
|
|
41
|
+
const titleArg = args.title ? `"${args.title.replace(/"/g, '\\"')}"` : '""';
|
|
42
|
+
const cmd = `cat "${tempFile}" | bun run /home/user/lakitu/runtime/pdf-generator.ts "${outputPath}" ${titleArg}`;
|
|
43
|
+
|
|
44
|
+
console.log(`[pdf action] Running: ${cmd}`);
|
|
45
|
+
|
|
46
|
+
// Execute PDF generator
|
|
47
|
+
const result = execSync(cmd, {
|
|
48
|
+
encoding: "utf-8",
|
|
49
|
+
timeout: 60000,
|
|
50
|
+
cwd: "/home/user/lakitu",
|
|
51
|
+
env: {
|
|
52
|
+
...process.env,
|
|
53
|
+
HOME: "/home/user",
|
|
54
|
+
PATH: "/home/user/.bun/bin:/usr/local/bin:/usr/bin:/bin",
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// Clean up temp file
|
|
59
|
+
try {
|
|
60
|
+
fs.unlinkSync(tempFile);
|
|
61
|
+
} catch (e) {
|
|
62
|
+
console.warn("[pdf action] Failed to clean temp file:", e);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Parse result
|
|
66
|
+
const parsed = JSON.parse(result.trim());
|
|
67
|
+
|
|
68
|
+
if (!parsed.success) {
|
|
69
|
+
console.error("[pdf action] Generator failed:", parsed.error);
|
|
70
|
+
return {
|
|
71
|
+
success: false,
|
|
72
|
+
error: parsed.error || "PDF generation failed",
|
|
73
|
+
path: "",
|
|
74
|
+
filename: "",
|
|
75
|
+
size: 0,
|
|
76
|
+
pdfBase64: "",
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Read PDF and convert to base64
|
|
81
|
+
const pdfBuffer = fs.readFileSync(outputPath);
|
|
82
|
+
const pdfBase64 = pdfBuffer.toString("base64");
|
|
83
|
+
|
|
84
|
+
console.log(`[pdf action] Generated PDF: ${outputPath} (${pdfBuffer.length} bytes)`);
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
success: true,
|
|
88
|
+
path: outputPath,
|
|
89
|
+
filename: `${args.filename}.pdf`,
|
|
90
|
+
size: parsed.size || pdfBuffer.length,
|
|
91
|
+
pdfBase64,
|
|
92
|
+
};
|
|
93
|
+
} catch (error) {
|
|
94
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
95
|
+
console.error("[pdf action] Error:", errorMsg);
|
|
96
|
+
|
|
97
|
+
// Check for specific error types
|
|
98
|
+
if (errorMsg.includes("ENOENT") && errorMsg.includes("pdf-generator")) {
|
|
99
|
+
return {
|
|
100
|
+
success: false,
|
|
101
|
+
error: "PDF generator script not found. Ensure /home/user/lakitu/runtime/pdf-generator.ts exists.",
|
|
102
|
+
path: "",
|
|
103
|
+
filename: "",
|
|
104
|
+
size: 0,
|
|
105
|
+
pdfBase64: "",
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return {
|
|
110
|
+
success: false,
|
|
111
|
+
error: errorMsg,
|
|
112
|
+
path: "",
|
|
113
|
+
filename: "",
|
|
114
|
+
size: 0,
|
|
115
|
+
pdfBase64: "",
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
});
|