@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.
Files changed (111) hide show
  1. package/README.md +166 -0
  2. package/convex/_generated/api.d.ts +45 -0
  3. package/convex/_generated/api.js +23 -0
  4. package/convex/_generated/dataModel.d.ts +58 -0
  5. package/convex/_generated/server.d.ts +143 -0
  6. package/convex/_generated/server.js +93 -0
  7. package/convex/cloud/CLAUDE.md +238 -0
  8. package/convex/cloud/_generated/api.ts +84 -0
  9. package/convex/cloud/_generated/component.ts +861 -0
  10. package/convex/cloud/_generated/dataModel.ts +60 -0
  11. package/convex/cloud/_generated/server.ts +156 -0
  12. package/convex/cloud/convex.config.ts +16 -0
  13. package/convex/cloud/index.ts +29 -0
  14. package/convex/cloud/intentSchema/generate.ts +447 -0
  15. package/convex/cloud/intentSchema/index.ts +16 -0
  16. package/convex/cloud/intentSchema/types.ts +418 -0
  17. package/convex/cloud/ksaPolicy.ts +554 -0
  18. package/convex/cloud/mail.ts +92 -0
  19. package/convex/cloud/schema.ts +322 -0
  20. package/convex/cloud/utils/kanbanContext.ts +229 -0
  21. package/convex/cloud/workflows/agentBoard.ts +451 -0
  22. package/convex/cloud/workflows/agentPrompt.ts +272 -0
  23. package/convex/cloud/workflows/agentThread.ts +374 -0
  24. package/convex/cloud/workflows/compileSandbox.ts +146 -0
  25. package/convex/cloud/workflows/crudBoard.ts +217 -0
  26. package/convex/cloud/workflows/crudKSAs.ts +262 -0
  27. package/convex/cloud/workflows/crudLorobeads.ts +371 -0
  28. package/convex/cloud/workflows/crudSkills.ts +205 -0
  29. package/convex/cloud/workflows/crudThreads.ts +708 -0
  30. package/convex/cloud/workflows/lifecycleSandbox.ts +1396 -0
  31. package/convex/cloud/workflows/sandboxConvex.ts +1046 -0
  32. package/convex/sandbox/README.md +90 -0
  33. package/convex/sandbox/_generated/api.d.ts +2934 -0
  34. package/convex/sandbox/_generated/api.js +23 -0
  35. package/convex/sandbox/_generated/dataModel.d.ts +60 -0
  36. package/convex/sandbox/_generated/server.d.ts +143 -0
  37. package/convex/sandbox/_generated/server.js +93 -0
  38. package/convex/sandbox/actions/bash.ts +130 -0
  39. package/convex/sandbox/actions/browser.ts +282 -0
  40. package/convex/sandbox/actions/file.ts +336 -0
  41. package/convex/sandbox/actions/lsp.ts +325 -0
  42. package/convex/sandbox/actions/pdf.ts +119 -0
  43. package/convex/sandbox/agent/codeExecLoop.ts +535 -0
  44. package/convex/sandbox/agent/decisions.ts +284 -0
  45. package/convex/sandbox/agent/index.ts +515 -0
  46. package/convex/sandbox/agent/subagents.ts +651 -0
  47. package/convex/sandbox/brandResearch/index.ts +417 -0
  48. package/convex/sandbox/context/index.ts +7 -0
  49. package/convex/sandbox/context/session.ts +402 -0
  50. package/convex/sandbox/convex.config.ts +17 -0
  51. package/convex/sandbox/index.ts +51 -0
  52. package/convex/sandbox/nodeActions/codeExec.ts +130 -0
  53. package/convex/sandbox/planning/beads.ts +187 -0
  54. package/convex/sandbox/planning/index.ts +8 -0
  55. package/convex/sandbox/planning/sync.ts +194 -0
  56. package/convex/sandbox/prompts/codeExec.ts +852 -0
  57. package/convex/sandbox/prompts/modes.ts +231 -0
  58. package/convex/sandbox/prompts/system.ts +142 -0
  59. package/convex/sandbox/schema.ts +510 -0
  60. package/convex/sandbox/state/artifacts.ts +99 -0
  61. package/convex/sandbox/state/checkpoints.ts +341 -0
  62. package/convex/sandbox/state/files.ts +383 -0
  63. package/convex/sandbox/state/index.ts +10 -0
  64. package/convex/sandbox/state/verification.actions.ts +268 -0
  65. package/convex/sandbox/state/verification.ts +101 -0
  66. package/convex/sandbox/tsconfig.json +25 -0
  67. package/convex/sandbox/utils/codeExecHelpers.ts +52 -0
  68. package/dist/cli/commands/build.d.ts +19 -0
  69. package/dist/cli/commands/build.d.ts.map +1 -0
  70. package/dist/cli/commands/build.js +223 -0
  71. package/dist/cli/commands/init.d.ts +16 -0
  72. package/dist/cli/commands/init.d.ts.map +1 -0
  73. package/dist/cli/commands/init.js +148 -0
  74. package/dist/cli/commands/publish.d.ts +12 -0
  75. package/dist/cli/commands/publish.d.ts.map +1 -0
  76. package/dist/cli/commands/publish.js +33 -0
  77. package/dist/cli/index.d.ts +14 -0
  78. package/dist/cli/index.d.ts.map +1 -0
  79. package/dist/cli/index.js +40 -0
  80. package/dist/sdk/builders.d.ts +104 -0
  81. package/dist/sdk/builders.d.ts.map +1 -0
  82. package/dist/sdk/builders.js +214 -0
  83. package/dist/sdk/index.d.ts +29 -0
  84. package/dist/sdk/index.d.ts.map +1 -0
  85. package/dist/sdk/index.js +38 -0
  86. package/dist/sdk/types.d.ts +107 -0
  87. package/dist/sdk/types.d.ts.map +1 -0
  88. package/dist/sdk/types.js +6 -0
  89. package/ksa/README.md +263 -0
  90. package/ksa/_generated/REFERENCE.md +2954 -0
  91. package/ksa/_generated/registry.ts +257 -0
  92. package/ksa/_shared/configReader.ts +302 -0
  93. package/ksa/_shared/configSchemas.ts +649 -0
  94. package/ksa/_shared/gateway.ts +175 -0
  95. package/ksa/_shared/ksaBehaviors.ts +411 -0
  96. package/ksa/_shared/ksaProxy.ts +248 -0
  97. package/ksa/_shared/localDb.ts +302 -0
  98. package/ksa/index.ts +134 -0
  99. package/package.json +93 -0
  100. package/runtime/browser/agent-browser.ts +330 -0
  101. package/runtime/entrypoint.ts +194 -0
  102. package/runtime/lsp/manager.ts +366 -0
  103. package/runtime/pdf/pdf-generator.ts +50 -0
  104. package/runtime/pdf/renderer.ts +357 -0
  105. package/runtime/pdf/schema.ts +97 -0
  106. package/runtime/services/file-watcher.ts +191 -0
  107. package/template/build.ts +307 -0
  108. package/template/e2b/Dockerfile +69 -0
  109. package/template/e2b/e2b.toml +13 -0
  110. package/template/e2b/prebuild.sh +68 -0
  111. package/template/e2b/start.sh +14 -0
@@ -0,0 +1,366 @@
1
+ /**
2
+ * LSP Manager - Language Server Lifecycle Management
3
+ *
4
+ * Start, stop, and communicate with language servers.
5
+ */
6
+
7
+ import { spawn, type ChildProcess } from "child_process";
8
+ import { EventEmitter } from "events";
9
+
10
+ export type Language = "typescript" | "python" | "rust";
11
+
12
+ export interface LspServer {
13
+ language: Language;
14
+ process: ChildProcess | null;
15
+ status: "stopped" | "starting" | "running" | "error";
16
+ error?: string;
17
+ pendingRequests: Map<number, { resolve: Function; reject: Function }>;
18
+ nextRequestId: number;
19
+ }
20
+
21
+ export interface LspRequest {
22
+ jsonrpc: "2.0";
23
+ id: number;
24
+ method: string;
25
+ params?: any;
26
+ }
27
+
28
+ export interface LspResponse {
29
+ jsonrpc: "2.0";
30
+ id: number;
31
+ result?: any;
32
+ error?: { code: number; message: string };
33
+ }
34
+
35
+ export interface LspNotification {
36
+ jsonrpc: "2.0";
37
+ method: string;
38
+ params?: any;
39
+ }
40
+
41
+ const LSP_COMMANDS: Record<Language, { cmd: string; args: string[] }> = {
42
+ typescript: {
43
+ cmd: "typescript-language-server",
44
+ args: ["--stdio"],
45
+ },
46
+ python: {
47
+ cmd: "pylsp",
48
+ args: [],
49
+ },
50
+ rust: {
51
+ cmd: "rust-analyzer",
52
+ args: [],
53
+ },
54
+ };
55
+
56
+ class LspManager extends EventEmitter {
57
+ private servers: Map<Language, LspServer> = new Map();
58
+ private messageBuffer: Map<Language, string> = new Map();
59
+
60
+ async start(language: Language): Promise<void> {
61
+ const existing = this.servers.get(language);
62
+ if (existing?.status === "running") {
63
+ return; // Already running
64
+ }
65
+
66
+ const config = LSP_COMMANDS[language];
67
+ if (!config) {
68
+ throw new Error(`Unknown language: ${language}`);
69
+ }
70
+
71
+ const server: LspServer = {
72
+ language,
73
+ process: null,
74
+ status: "starting",
75
+ pendingRequests: new Map(),
76
+ nextRequestId: 1,
77
+ };
78
+
79
+ this.servers.set(language, server);
80
+ this.messageBuffer.set(language, "");
81
+
82
+ try {
83
+ const proc = spawn(config.cmd, config.args, {
84
+ stdio: ["pipe", "pipe", "pipe"],
85
+ env: {
86
+ ...process.env,
87
+ HOME: "/home/user",
88
+ },
89
+ });
90
+
91
+ server.process = proc;
92
+
93
+ proc.stdout?.on("data", (data) => {
94
+ this.handleOutput(language, data.toString());
95
+ });
96
+
97
+ proc.stderr?.on("data", (data) => {
98
+ console.error(`[${language}-lsp]`, data.toString().trim());
99
+ });
100
+
101
+ proc.on("error", (err) => {
102
+ server.status = "error";
103
+ server.error = err.message;
104
+ this.emit("error", { language, error: err.message });
105
+ });
106
+
107
+ proc.on("exit", (code) => {
108
+ server.status = "stopped";
109
+ this.emit("exit", { language, code });
110
+ });
111
+
112
+ // Initialize the server
113
+ await this.initialize(language);
114
+
115
+ server.status = "running";
116
+ this.emit("ready", { language });
117
+ } catch (error: any) {
118
+ server.status = "error";
119
+ server.error = error.message;
120
+ throw error;
121
+ }
122
+ }
123
+
124
+ async stop(language: Language): Promise<void> {
125
+ const server = this.servers.get(language);
126
+ if (!server?.process) return;
127
+
128
+ // Send shutdown request
129
+ try {
130
+ await this.sendRequest(language, "shutdown", {});
131
+ this.sendNotification(language, "exit", {});
132
+ } catch {
133
+ // Force kill if graceful shutdown fails
134
+ server.process.kill("SIGTERM");
135
+ }
136
+
137
+ server.status = "stopped";
138
+ server.process = null;
139
+ }
140
+
141
+ async stopAll(): Promise<void> {
142
+ for (const language of this.servers.keys()) {
143
+ await this.stop(language);
144
+ }
145
+ }
146
+
147
+ getStatus(language: Language): LspServer["status"] {
148
+ return this.servers.get(language)?.status ?? "stopped";
149
+ }
150
+
151
+ private async initialize(language: Language): Promise<void> {
152
+ await this.sendRequest(language, "initialize", {
153
+ processId: process.pid,
154
+ rootUri: "file:///home/user/workspace",
155
+ capabilities: {
156
+ textDocument: {
157
+ synchronization: {
158
+ didOpen: true,
159
+ didChange: true,
160
+ didClose: true,
161
+ },
162
+ completion: {
163
+ completionItem: {
164
+ snippetSupport: true,
165
+ documentationFormat: ["markdown", "plaintext"],
166
+ },
167
+ },
168
+ hover: {
169
+ contentFormat: ["markdown", "plaintext"],
170
+ },
171
+ publishDiagnostics: {
172
+ relatedInformation: true,
173
+ },
174
+ },
175
+ workspace: {
176
+ workspaceFolders: true,
177
+ },
178
+ },
179
+ workspaceFolders: [
180
+ {
181
+ uri: "file:///home/user/workspace",
182
+ name: "workspace",
183
+ },
184
+ ],
185
+ });
186
+
187
+ this.sendNotification(language, "initialized", {});
188
+ }
189
+
190
+ async sendRequest(language: Language, method: string, params: any): Promise<any> {
191
+ const server = this.servers.get(language);
192
+ if (!server?.process || server.status !== "running") {
193
+ throw new Error(`LSP server for ${language} is not running`);
194
+ }
195
+
196
+ const id = server.nextRequestId++;
197
+ const request: LspRequest = {
198
+ jsonrpc: "2.0",
199
+ id,
200
+ method,
201
+ params,
202
+ };
203
+
204
+ return new Promise((resolve, reject) => {
205
+ server.pendingRequests.set(id, { resolve, reject });
206
+ this.send(language, request);
207
+
208
+ // Timeout after 30 seconds
209
+ setTimeout(() => {
210
+ if (server.pendingRequests.has(id)) {
211
+ server.pendingRequests.delete(id);
212
+ reject(new Error(`Request ${method} timed out`));
213
+ }
214
+ }, 30000);
215
+ });
216
+ }
217
+
218
+ sendNotification(language: Language, method: string, params: any): void {
219
+ const notification: LspNotification = {
220
+ jsonrpc: "2.0",
221
+ method,
222
+ params,
223
+ };
224
+ this.send(language, notification);
225
+ }
226
+
227
+ private send(language: Language, message: object): void {
228
+ const server = this.servers.get(language);
229
+ if (!server?.process?.stdin) return;
230
+
231
+ const content = JSON.stringify(message);
232
+ const header = `Content-Length: ${Buffer.byteLength(content)}\r\n\r\n`;
233
+ server.process.stdin.write(header + content);
234
+ }
235
+
236
+ private handleOutput(language: Language, data: string): void {
237
+ const buffer = (this.messageBuffer.get(language) || "") + data;
238
+ this.messageBuffer.set(language, buffer);
239
+
240
+ // Parse LSP messages
241
+ while (true) {
242
+ const headerEnd = buffer.indexOf("\r\n\r\n");
243
+ if (headerEnd === -1) break;
244
+
245
+ const header = buffer.slice(0, headerEnd);
246
+ const contentLengthMatch = header.match(/Content-Length: (\d+)/);
247
+ if (!contentLengthMatch) break;
248
+
249
+ const contentLength = parseInt(contentLengthMatch[1], 10);
250
+ const messageStart = headerEnd + 4;
251
+ const messageEnd = messageStart + contentLength;
252
+
253
+ if (buffer.length < messageEnd) break;
254
+
255
+ const content = buffer.slice(messageStart, messageEnd);
256
+ this.messageBuffer.set(language, buffer.slice(messageEnd));
257
+
258
+ try {
259
+ const message = JSON.parse(content);
260
+ this.handleMessage(language, message);
261
+ } catch (e) {
262
+ console.error(`[${language}-lsp] Failed to parse message:`, e);
263
+ }
264
+ }
265
+ }
266
+
267
+ private handleMessage(language: Language, message: LspResponse | LspNotification): void {
268
+ const server = this.servers.get(language);
269
+ if (!server) return;
270
+
271
+ if ("id" in message && message.id !== undefined) {
272
+ // Response to a request
273
+ const pending = server.pendingRequests.get(message.id);
274
+ if (pending) {
275
+ server.pendingRequests.delete(message.id);
276
+ if (message.error) {
277
+ pending.reject(new Error(message.error.message));
278
+ } else {
279
+ pending.resolve(message.result);
280
+ }
281
+ }
282
+ } else {
283
+ // Notification from server
284
+ this.emit("notification", { language, method: message.method, params: message.params });
285
+ }
286
+ }
287
+
288
+ // High-level API methods
289
+
290
+ async openDocument(language: Language, uri: string, text: string): Promise<void> {
291
+ const languageId = language === "typescript" ? "typescript" : language;
292
+ this.sendNotification(language, "textDocument/didOpen", {
293
+ textDocument: {
294
+ uri,
295
+ languageId,
296
+ version: 1,
297
+ text,
298
+ },
299
+ });
300
+ }
301
+
302
+ async closeDocument(language: Language, uri: string): Promise<void> {
303
+ this.sendNotification(language, "textDocument/didClose", {
304
+ textDocument: { uri },
305
+ });
306
+ }
307
+
308
+ async getCompletions(
309
+ language: Language,
310
+ uri: string,
311
+ line: number,
312
+ character: number
313
+ ): Promise<any> {
314
+ return await this.sendRequest(language, "textDocument/completion", {
315
+ textDocument: { uri },
316
+ position: { line, character },
317
+ });
318
+ }
319
+
320
+ async getHover(
321
+ language: Language,
322
+ uri: string,
323
+ line: number,
324
+ character: number
325
+ ): Promise<any> {
326
+ return await this.sendRequest(language, "textDocument/hover", {
327
+ textDocument: { uri },
328
+ position: { line, character },
329
+ });
330
+ }
331
+
332
+ async getDiagnostics(language: Language, uri: string): Promise<any[]> {
333
+ // Diagnostics are pushed via notifications, we need to trigger them
334
+ // by changing the document or waiting for them
335
+ // For now, return empty array - real implementation would track notifications
336
+ return [];
337
+ }
338
+
339
+ async getDefinition(
340
+ language: Language,
341
+ uri: string,
342
+ line: number,
343
+ character: number
344
+ ): Promise<any> {
345
+ return await this.sendRequest(language, "textDocument/definition", {
346
+ textDocument: { uri },
347
+ position: { line, character },
348
+ });
349
+ }
350
+
351
+ async getReferences(
352
+ language: Language,
353
+ uri: string,
354
+ line: number,
355
+ character: number
356
+ ): Promise<any> {
357
+ return await this.sendRequest(language, "textDocument/references", {
358
+ textDocument: { uri },
359
+ position: { line, character },
360
+ context: { includeDeclaration: true },
361
+ });
362
+ }
363
+ }
364
+
365
+ // Singleton instance
366
+ export const lspManager = new LspManager();
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * PDF Generator - Thin CLI that delegates to services/pdf/renderer
4
+ *
5
+ * Usage: bun run pdf-generator.ts <output-path> [title]
6
+ * Content is read from stdin
7
+ */
8
+
9
+ import * as fs from "fs";
10
+ import { markdownToDocNode, renderPdf } from "../services/pdf/renderer";
11
+
12
+ async function main() {
13
+ const args = process.argv.slice(2);
14
+ if (args.length < 1) {
15
+ console.error(JSON.stringify({ success: false, error: "Usage: bun run pdf-generator.ts <output-path> [title]" }));
16
+ process.exit(1);
17
+ }
18
+
19
+ const outputPath = args[0];
20
+ const title = args[1];
21
+
22
+ // Read content from stdin
23
+ let content = "";
24
+ for await (const chunk of Bun.stdin.stream()) {
25
+ content += new TextDecoder().decode(chunk);
26
+ }
27
+
28
+ if (!content.trim()) {
29
+ console.error(JSON.stringify({ success: false, error: "No content provided via stdin" }));
30
+ process.exit(1);
31
+ }
32
+
33
+ // Ensure output directory exists
34
+ const outputDir = outputPath.substring(0, outputPath.lastIndexOf("/"));
35
+ if (outputDir && !fs.existsSync(outputDir)) {
36
+ fs.mkdirSync(outputDir, { recursive: true });
37
+ }
38
+
39
+ // Convert markdown to document structure and render PDF
40
+ const docNode = markdownToDocNode(content, title);
41
+ await renderPdf(docNode, { outputPath });
42
+
43
+ const stats = fs.statSync(outputPath);
44
+ console.log(JSON.stringify({ success: true, path: outputPath, size: stats.size }));
45
+ }
46
+
47
+ main().catch((err) => {
48
+ console.error(JSON.stringify({ success: false, error: err.message }));
49
+ process.exit(1);
50
+ });