@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,248 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KSA Proxy - Framework-Level Instrumentation
|
|
3
|
+
*
|
|
4
|
+
* This is the core of the local DB integration framework.
|
|
5
|
+
* Wraps KSA modules with a Proxy that automatically applies behaviors
|
|
6
|
+
* like caching, file tracking, and call logging.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import * as fileRaw from "./file";
|
|
11
|
+
* import { createKSAProxy } from "./_shared/ksaProxy";
|
|
12
|
+
*
|
|
13
|
+
* export const file = createKSAProxy("file", fileRaw);
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* The proxy is transparent to agents - they import and use KSAs normally,
|
|
17
|
+
* and the framework automatically applies behaviors based on config.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { getBehavior, type HookContext, type BeforeHookResult } from "./ksaBehaviors";
|
|
21
|
+
import { getFrameworkConfigForKSA } from "./configReader";
|
|
22
|
+
import type { FrameworkConfig } from "./configSchemas";
|
|
23
|
+
|
|
24
|
+
// ============================================================================
|
|
25
|
+
// Types
|
|
26
|
+
// ============================================================================
|
|
27
|
+
|
|
28
|
+
/** Any object that can be proxied (KSA module) */
|
|
29
|
+
type ProxiableModule = Record<string, unknown>;
|
|
30
|
+
|
|
31
|
+
/** Options for creating a KSA proxy */
|
|
32
|
+
export interface ProxyOptions {
|
|
33
|
+
/** Override framework config (for testing) */
|
|
34
|
+
config?: Partial<FrameworkConfig>;
|
|
35
|
+
/** Disable all behaviors (passthrough mode) */
|
|
36
|
+
disabled?: boolean;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// ============================================================================
|
|
40
|
+
// Proxy Factory
|
|
41
|
+
// ============================================================================
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Create a proxied version of a KSA module.
|
|
45
|
+
*
|
|
46
|
+
* The proxy wraps all exported functions and automatically applies
|
|
47
|
+
* before/after hooks based on the KSA's behavior configuration.
|
|
48
|
+
*
|
|
49
|
+
* @param ksaName - Name of the KSA (e.g., "file", "web")
|
|
50
|
+
* @param ksaModule - The raw KSA module
|
|
51
|
+
* @param options - Optional configuration overrides
|
|
52
|
+
* @returns Proxied module with automatic behaviors
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* // In ksa/index.ts
|
|
56
|
+
* import * as fileRaw from "./file";
|
|
57
|
+
* export const file = createKSAProxy("file", fileRaw);
|
|
58
|
+
*
|
|
59
|
+
* // Agent code (unchanged)
|
|
60
|
+
* import { file } from "./ksa";
|
|
61
|
+
* const content = await file.read("/path/to/file.txt");
|
|
62
|
+
* // Automatically tracked in local DB!
|
|
63
|
+
*/
|
|
64
|
+
export function createKSAProxy<T extends ProxiableModule>(
|
|
65
|
+
ksaName: string,
|
|
66
|
+
ksaModule: T,
|
|
67
|
+
options?: ProxyOptions
|
|
68
|
+
): T {
|
|
69
|
+
// In passthrough mode, return the raw module
|
|
70
|
+
if (options?.disabled) {
|
|
71
|
+
return ksaModule;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Get framework config for this KSA
|
|
75
|
+
const config = {
|
|
76
|
+
...getFrameworkConfigForKSA(ksaName),
|
|
77
|
+
...options?.config,
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
return new Proxy(ksaModule, {
|
|
81
|
+
get(target, prop: string | symbol) {
|
|
82
|
+
const original = target[prop as keyof T];
|
|
83
|
+
|
|
84
|
+
// Only wrap functions
|
|
85
|
+
if (typeof original !== "function") {
|
|
86
|
+
return original;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Don't wrap internal properties
|
|
90
|
+
if (typeof prop === "symbol" || prop.startsWith("_")) {
|
|
91
|
+
return original;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Return wrapped function
|
|
95
|
+
return createWrappedFunction(ksaName, prop, original as Function, config);
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Create a wrapped version of a KSA function with automatic behaviors.
|
|
102
|
+
*/
|
|
103
|
+
function createWrappedFunction(
|
|
104
|
+
ksaName: string,
|
|
105
|
+
funcName: string,
|
|
106
|
+
original: Function,
|
|
107
|
+
config: FrameworkConfig
|
|
108
|
+
): (...args: unknown[]) => Promise<unknown> {
|
|
109
|
+
return async function wrappedFunction(...args: unknown[]): Promise<unknown> {
|
|
110
|
+
const startTime = Date.now();
|
|
111
|
+
|
|
112
|
+
// Build hook context
|
|
113
|
+
const ctx: HookContext = {
|
|
114
|
+
ksaName,
|
|
115
|
+
funcName,
|
|
116
|
+
args,
|
|
117
|
+
config,
|
|
118
|
+
startTime,
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
// Get behaviors for this function
|
|
122
|
+
const { before, after } = getBehavior(ksaName, funcName);
|
|
123
|
+
|
|
124
|
+
// Execute before hook (may return cached result)
|
|
125
|
+
if (before) {
|
|
126
|
+
try {
|
|
127
|
+
const beforeResult = await before(ctx);
|
|
128
|
+
if (beforeResult && beforeResult.skipExecution) {
|
|
129
|
+
// Return cached result
|
|
130
|
+
return beforeResult.cachedResult;
|
|
131
|
+
}
|
|
132
|
+
} catch (e) {
|
|
133
|
+
// Before hook failed, continue with execution
|
|
134
|
+
console.warn(`[KSA Proxy] Before hook failed for ${ksaName}.${funcName}:`, e);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Execute original function
|
|
139
|
+
let result: unknown;
|
|
140
|
+
let error: Error | undefined;
|
|
141
|
+
|
|
142
|
+
try {
|
|
143
|
+
result = await original.apply(null, args);
|
|
144
|
+
} catch (e) {
|
|
145
|
+
error = e instanceof Error ? e : new Error(String(e));
|
|
146
|
+
throw error;
|
|
147
|
+
} finally {
|
|
148
|
+
// Execute after hook (fire-and-forget for performance)
|
|
149
|
+
if (after) {
|
|
150
|
+
try {
|
|
151
|
+
// Don't await - fire and forget
|
|
152
|
+
Promise.resolve(after(ctx, result, error)).catch((e) => {
|
|
153
|
+
console.warn(`[KSA Proxy] After hook failed for ${ksaName}.${funcName}:`, e);
|
|
154
|
+
});
|
|
155
|
+
} catch (e) {
|
|
156
|
+
console.warn(`[KSA Proxy] After hook failed for ${ksaName}.${funcName}:`, e);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return result;
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// ============================================================================
|
|
166
|
+
// Bulk Proxy Creation
|
|
167
|
+
// ============================================================================
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Create proxies for multiple KSA modules at once.
|
|
171
|
+
*
|
|
172
|
+
* @param modules - Map of KSA name to raw module
|
|
173
|
+
* @param options - Optional configuration overrides
|
|
174
|
+
* @returns Map of KSA name to proxied module
|
|
175
|
+
*
|
|
176
|
+
* @example
|
|
177
|
+
* import * as file from "./file";
|
|
178
|
+
* import * as web from "./web";
|
|
179
|
+
*
|
|
180
|
+
* const proxied = createKSAProxies({ file, web });
|
|
181
|
+
* export const { file: fileProxy, web: webProxy } = proxied;
|
|
182
|
+
*/
|
|
183
|
+
export function createKSAProxies<T extends Record<string, ProxiableModule>>(
|
|
184
|
+
modules: T,
|
|
185
|
+
options?: ProxyOptions
|
|
186
|
+
): T {
|
|
187
|
+
const result = {} as T;
|
|
188
|
+
|
|
189
|
+
for (const [name, module] of Object.entries(modules)) {
|
|
190
|
+
result[name as keyof T] = createKSAProxy(name, module, options) as T[keyof T];
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return result;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// ============================================================================
|
|
197
|
+
// Passthrough Mode
|
|
198
|
+
// ============================================================================
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Check if proxy behaviors should be disabled.
|
|
202
|
+
*
|
|
203
|
+
* Behaviors are disabled when:
|
|
204
|
+
* - LAKITU_PROXY_DISABLED=true environment variable is set
|
|
205
|
+
* - Running in test mode (NODE_ENV=test)
|
|
206
|
+
*/
|
|
207
|
+
export function isProxyDisabled(): boolean {
|
|
208
|
+
return (
|
|
209
|
+
process.env.LAKITU_PROXY_DISABLED === "true" ||
|
|
210
|
+
process.env.NODE_ENV === "test"
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Create a KSA proxy with automatic passthrough detection.
|
|
216
|
+
* Uses isProxyDisabled() to determine if behaviors should be applied.
|
|
217
|
+
*/
|
|
218
|
+
export function createKSAProxyAuto<T extends ProxiableModule>(
|
|
219
|
+
ksaName: string,
|
|
220
|
+
ksaModule: T,
|
|
221
|
+
options?: Omit<ProxyOptions, "disabled">
|
|
222
|
+
): T {
|
|
223
|
+
return createKSAProxy(ksaName, ksaModule, {
|
|
224
|
+
...options,
|
|
225
|
+
disabled: isProxyDisabled(),
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// ============================================================================
|
|
230
|
+
// Debug Utilities
|
|
231
|
+
// ============================================================================
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Get debug info about the proxy configuration for a KSA.
|
|
235
|
+
*/
|
|
236
|
+
export function getProxyDebugInfo(ksaName: string): {
|
|
237
|
+
config: FrameworkConfig;
|
|
238
|
+
isDisabled: boolean;
|
|
239
|
+
hasBehaviors: boolean;
|
|
240
|
+
} {
|
|
241
|
+
const config = getFrameworkConfigForKSA(ksaName);
|
|
242
|
+
|
|
243
|
+
return {
|
|
244
|
+
config,
|
|
245
|
+
isDisabled: isProxyDisabled(),
|
|
246
|
+
hasBehaviors: true, // All KSAs have at least default behaviors
|
|
247
|
+
};
|
|
248
|
+
}
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local DB Client - Sandbox Convex Integration
|
|
3
|
+
*
|
|
4
|
+
* Shared client for calling the local Convex backend running in the E2B sandbox.
|
|
5
|
+
* This is the foundation for automatic state tracking, caching, and session persistence.
|
|
6
|
+
*
|
|
7
|
+
* Key differences from gateway.ts:
|
|
8
|
+
* - Calls LOCAL Convex at http://localhost:3210 (not cloud)
|
|
9
|
+
* - No JWT required (sandbox is trusted)
|
|
10
|
+
* - Designed for high-frequency, low-latency operations
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* import { localDb, getSessionId } from './_shared/localDb';
|
|
14
|
+
*
|
|
15
|
+
* // Blocking query
|
|
16
|
+
* const files = await localDb.query('state/files:getByThread', { threadId });
|
|
17
|
+
*
|
|
18
|
+
* // Blocking mutation
|
|
19
|
+
* const id = await localDb.mutate('planning/beads:create', { title: 'Task' });
|
|
20
|
+
*
|
|
21
|
+
* // Fire-and-forget (non-blocking)
|
|
22
|
+
* localDb.fire('state/files:trackFileAccess', { path, operation: 'read' });
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { readFileSync, existsSync } from "fs";
|
|
26
|
+
|
|
27
|
+
// ============================================================================
|
|
28
|
+
// Environment Loading
|
|
29
|
+
// ============================================================================
|
|
30
|
+
|
|
31
|
+
function loadEnvFile(): Record<string, string> {
|
|
32
|
+
const envPath = "/home/user/.env";
|
|
33
|
+
if (!existsSync(envPath)) return {};
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
const content = readFileSync(envPath, "utf-8");
|
|
37
|
+
const envVars: Record<string, string> = {};
|
|
38
|
+
for (const line of content.split("\n")) {
|
|
39
|
+
const match = line.match(/^export\s+(\w+)="([^"]*)"/);
|
|
40
|
+
if (match) {
|
|
41
|
+
envVars[match[1]] = match[2];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return envVars;
|
|
45
|
+
} catch {
|
|
46
|
+
return {};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const envFile = loadEnvFile();
|
|
51
|
+
|
|
52
|
+
// Local Convex URL (sandbox backend, NOT cloud gateway)
|
|
53
|
+
const LOCAL_CONVEX_URL = process.env.CONVEX_URL || envFile.CONVEX_URL || "http://localhost:3210";
|
|
54
|
+
|
|
55
|
+
// Session identifiers
|
|
56
|
+
export const SESSION_ID = process.env.SESSION_ID || envFile.SESSION_ID || `session_${Date.now()}`;
|
|
57
|
+
export const THREAD_ID = process.env.THREAD_ID || envFile.THREAD_ID;
|
|
58
|
+
export const CARD_ID = process.env.CARD_ID || envFile.CARD_ID;
|
|
59
|
+
|
|
60
|
+
// ============================================================================
|
|
61
|
+
// Path Conversion
|
|
62
|
+
// ============================================================================
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Convert dot-notation path to Convex HTTP API format.
|
|
66
|
+
* "planning.beads.create" -> "planning/beads:create"
|
|
67
|
+
*/
|
|
68
|
+
function toConvexPath(dotPath: string): string {
|
|
69
|
+
const parts = dotPath.split(".");
|
|
70
|
+
const funcName = parts.pop()!;
|
|
71
|
+
const modulePath = parts.join("/");
|
|
72
|
+
return `${modulePath}:${funcName}`;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// ============================================================================
|
|
76
|
+
// Core Client Functions
|
|
77
|
+
// ============================================================================
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Execute a query on local Convex (blocking).
|
|
81
|
+
*
|
|
82
|
+
* @param path - Dot-notation path (e.g., 'state/files.getByPath')
|
|
83
|
+
* @param args - Query arguments
|
|
84
|
+
* @returns Query result
|
|
85
|
+
*/
|
|
86
|
+
async function query<T = unknown>(
|
|
87
|
+
path: string,
|
|
88
|
+
args: Record<string, unknown> = {}
|
|
89
|
+
): Promise<T> {
|
|
90
|
+
const convexPath = toConvexPath(path);
|
|
91
|
+
|
|
92
|
+
const response = await fetch(`${LOCAL_CONVEX_URL}/api/query`, {
|
|
93
|
+
method: "POST",
|
|
94
|
+
headers: { "Content-Type": "application/json" },
|
|
95
|
+
body: JSON.stringify({ path: convexPath, args, format: "json" }),
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
if (!response.ok) {
|
|
99
|
+
const text = await response.text();
|
|
100
|
+
throw new Error(`Local Convex query error (${response.status}): ${text}`);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const result = await response.json();
|
|
104
|
+
return result.value as T;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Execute a mutation on local Convex (blocking).
|
|
109
|
+
*
|
|
110
|
+
* @param path - Dot-notation path (e.g., 'state/files.trackFileAccess')
|
|
111
|
+
* @param args - Mutation arguments
|
|
112
|
+
* @returns Mutation result
|
|
113
|
+
*/
|
|
114
|
+
async function mutate<T = unknown>(
|
|
115
|
+
path: string,
|
|
116
|
+
args: Record<string, unknown> = {}
|
|
117
|
+
): Promise<T> {
|
|
118
|
+
const convexPath = toConvexPath(path);
|
|
119
|
+
|
|
120
|
+
const response = await fetch(`${LOCAL_CONVEX_URL}/api/mutation`, {
|
|
121
|
+
method: "POST",
|
|
122
|
+
headers: { "Content-Type": "application/json" },
|
|
123
|
+
body: JSON.stringify({ path: convexPath, args, format: "json" }),
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
if (!response.ok) {
|
|
127
|
+
const text = await response.text();
|
|
128
|
+
throw new Error(`Local Convex mutation error (${response.status}): ${text}`);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const result = await response.json();
|
|
132
|
+
return result.value as T;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Execute an action on local Convex (blocking).
|
|
137
|
+
*
|
|
138
|
+
* @param path - Dot-notation path
|
|
139
|
+
* @param args - Action arguments
|
|
140
|
+
* @returns Action result
|
|
141
|
+
*/
|
|
142
|
+
async function action<T = unknown>(
|
|
143
|
+
path: string,
|
|
144
|
+
args: Record<string, unknown> = {}
|
|
145
|
+
): Promise<T> {
|
|
146
|
+
const convexPath = toConvexPath(path);
|
|
147
|
+
|
|
148
|
+
const response = await fetch(`${LOCAL_CONVEX_URL}/api/action`, {
|
|
149
|
+
method: "POST",
|
|
150
|
+
headers: { "Content-Type": "application/json" },
|
|
151
|
+
body: JSON.stringify({ path: convexPath, args, format: "json" }),
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
if (!response.ok) {
|
|
155
|
+
const text = await response.text();
|
|
156
|
+
throw new Error(`Local Convex action error (${response.status}): ${text}`);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const result = await response.json();
|
|
160
|
+
return result.value as T;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Fire-and-forget mutation (non-blocking).
|
|
165
|
+
* Use for non-critical tracking operations where latency matters.
|
|
166
|
+
*
|
|
167
|
+
* @param path - Dot-notation path
|
|
168
|
+
* @param args - Mutation arguments
|
|
169
|
+
*/
|
|
170
|
+
function fire(
|
|
171
|
+
path: string,
|
|
172
|
+
args: Record<string, unknown> = {}
|
|
173
|
+
): void {
|
|
174
|
+
const convexPath = toConvexPath(path);
|
|
175
|
+
|
|
176
|
+
fetch(`${LOCAL_CONVEX_URL}/api/mutation`, {
|
|
177
|
+
method: "POST",
|
|
178
|
+
headers: { "Content-Type": "application/json" },
|
|
179
|
+
body: JSON.stringify({ path: convexPath, args, format: "json" }),
|
|
180
|
+
}).catch(() => {
|
|
181
|
+
// Intentionally ignore errors - fire and forget
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Fire-and-forget query (non-blocking).
|
|
187
|
+
* Rarely needed, but available for completeness.
|
|
188
|
+
*/
|
|
189
|
+
function fireQuery(
|
|
190
|
+
path: string,
|
|
191
|
+
args: Record<string, unknown> = {}
|
|
192
|
+
): void {
|
|
193
|
+
const convexPath = toConvexPath(path);
|
|
194
|
+
|
|
195
|
+
fetch(`${LOCAL_CONVEX_URL}/api/query`, {
|
|
196
|
+
method: "POST",
|
|
197
|
+
headers: { "Content-Type": "application/json" },
|
|
198
|
+
body: JSON.stringify({ path: convexPath, args, format: "json" }),
|
|
199
|
+
}).catch(() => {
|
|
200
|
+
// Intentionally ignore errors
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// ============================================================================
|
|
205
|
+
// Exported Client
|
|
206
|
+
// ============================================================================
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Local Convex database client for sandbox operations.
|
|
210
|
+
*
|
|
211
|
+
* Use this for all local DB operations in the KSA framework.
|
|
212
|
+
* The fire() method is optimized for high-frequency tracking calls.
|
|
213
|
+
*/
|
|
214
|
+
export const localDb = {
|
|
215
|
+
query,
|
|
216
|
+
mutate,
|
|
217
|
+
action,
|
|
218
|
+
fire,
|
|
219
|
+
fireQuery,
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
// ============================================================================
|
|
223
|
+
// Helper Functions
|
|
224
|
+
// ============================================================================
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Get the current session ID.
|
|
228
|
+
* Used for session-scoped caching and memory.
|
|
229
|
+
*/
|
|
230
|
+
export function getSessionId(): string {
|
|
231
|
+
return SESSION_ID;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Get the current thread ID (if available).
|
|
236
|
+
* Used for thread-scoped operations.
|
|
237
|
+
*/
|
|
238
|
+
export function getThreadId(): string | undefined {
|
|
239
|
+
return THREAD_ID;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Get the current card ID (if available).
|
|
244
|
+
* Used for kanban card-scoped operations.
|
|
245
|
+
*/
|
|
246
|
+
export function getCardId(): string | undefined {
|
|
247
|
+
return CARD_ID;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Check if local Convex is available.
|
|
252
|
+
* Useful for graceful degradation.
|
|
253
|
+
*/
|
|
254
|
+
export async function isLocalDbAvailable(): Promise<boolean> {
|
|
255
|
+
try {
|
|
256
|
+
const response = await fetch(`${LOCAL_CONVEX_URL}/version`, {
|
|
257
|
+
method: "GET",
|
|
258
|
+
signal: AbortSignal.timeout(1000),
|
|
259
|
+
});
|
|
260
|
+
return response.ok;
|
|
261
|
+
} catch {
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Get local Convex connection info.
|
|
268
|
+
* Useful for debugging.
|
|
269
|
+
*/
|
|
270
|
+
export function getLocalDbConfig() {
|
|
271
|
+
return {
|
|
272
|
+
url: LOCAL_CONVEX_URL,
|
|
273
|
+
sessionId: SESSION_ID,
|
|
274
|
+
threadId: THREAD_ID,
|
|
275
|
+
cardId: CARD_ID,
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// ============================================================================
|
|
280
|
+
// Cache Helpers
|
|
281
|
+
// ============================================================================
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Generate a cache key from function name and arguments.
|
|
285
|
+
*/
|
|
286
|
+
export function cacheKey(ksaName: string, funcName: string, args: unknown[]): string {
|
|
287
|
+
const argsHash = JSON.stringify(args);
|
|
288
|
+
return `${ksaName}.${funcName}:${argsHash}`;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Simple hash function for cache keys.
|
|
293
|
+
*/
|
|
294
|
+
export function simpleHash(str: string): string {
|
|
295
|
+
let hash = 0;
|
|
296
|
+
for (let i = 0; i < str.length; i++) {
|
|
297
|
+
const char = str.charCodeAt(i);
|
|
298
|
+
hash = (hash << 5) - hash + char;
|
|
299
|
+
hash = hash & hash;
|
|
300
|
+
}
|
|
301
|
+
return hash.toString(16);
|
|
302
|
+
}
|
package/ksa/index.ts
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KSA Index - Knowledge, Skills, and Abilities
|
|
3
|
+
*
|
|
4
|
+
* This module re-exports from the Lakitu SDK and definitions.
|
|
5
|
+
*
|
|
6
|
+
* ## Architecture
|
|
7
|
+
*
|
|
8
|
+
* KSAs are now defined in `convex/lakitu/definitions/` using the TypeScript SDK
|
|
9
|
+
* from `packages/lakitu/sdk/`. This file provides backward compatibility.
|
|
10
|
+
*
|
|
11
|
+
* ## Usage
|
|
12
|
+
*
|
|
13
|
+
* ```typescript
|
|
14
|
+
* // Import the SDK for defining custom KSAs
|
|
15
|
+
* import { defineKSA, fn, service, primitive } from '@lakitu/sdk';
|
|
16
|
+
*
|
|
17
|
+
* // Import KSA definitions
|
|
18
|
+
* import { fileKSA, webKSA } from 'convex/lakitu/definitions';
|
|
19
|
+
*
|
|
20
|
+
* // Execute KSA functions
|
|
21
|
+
* import { executeFunction, createKSAProxy } from '@lakitu/sdk';
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
// ============================================================================
|
|
26
|
+
// Re-export SDK
|
|
27
|
+
// ============================================================================
|
|
28
|
+
|
|
29
|
+
export {
|
|
30
|
+
// Types
|
|
31
|
+
type KSADef,
|
|
32
|
+
type KSADefinition,
|
|
33
|
+
type FunctionDef,
|
|
34
|
+
type ParamDef,
|
|
35
|
+
type ParamType,
|
|
36
|
+
type Implementation,
|
|
37
|
+
type ServiceImpl,
|
|
38
|
+
type PrimitiveImpl,
|
|
39
|
+
type CompositeImpl,
|
|
40
|
+
type ExecutionContext,
|
|
41
|
+
type ExecutionResult,
|
|
42
|
+
|
|
43
|
+
// Builders
|
|
44
|
+
defineKSA,
|
|
45
|
+
fn,
|
|
46
|
+
service,
|
|
47
|
+
primitive,
|
|
48
|
+
composite,
|
|
49
|
+
|
|
50
|
+
// Runtime
|
|
51
|
+
executeFunction,
|
|
52
|
+
createKSAProxy,
|
|
53
|
+
createKSAProxies,
|
|
54
|
+
|
|
55
|
+
// Primitives
|
|
56
|
+
file,
|
|
57
|
+
shell,
|
|
58
|
+
browser,
|
|
59
|
+
getPrimitive,
|
|
60
|
+
hasPrimitive,
|
|
61
|
+
PRIMITIVES,
|
|
62
|
+
|
|
63
|
+
// Gateway
|
|
64
|
+
callGateway,
|
|
65
|
+
callGatewayBatch,
|
|
66
|
+
fireAndForget,
|
|
67
|
+
} from "../sdk";
|
|
68
|
+
|
|
69
|
+
// ============================================================================
|
|
70
|
+
// Re-export Gateway (for backward compatibility)
|
|
71
|
+
// ============================================================================
|
|
72
|
+
|
|
73
|
+
export {
|
|
74
|
+
callGateway as callGatewayLegacy,
|
|
75
|
+
callGatewayBatch as callGatewayBatchLegacy,
|
|
76
|
+
fireAndForget as fireAndForgetLegacy,
|
|
77
|
+
THREAD_ID,
|
|
78
|
+
CARD_ID,
|
|
79
|
+
WORKSPACE_ID,
|
|
80
|
+
getGatewayConfig,
|
|
81
|
+
} from "./_shared/gateway";
|
|
82
|
+
|
|
83
|
+
// ============================================================================
|
|
84
|
+
// Re-export from Generated Registry (for backward compatibility)
|
|
85
|
+
// ============================================================================
|
|
86
|
+
|
|
87
|
+
export type { KSAInfo, KSACategory, KSAGroup } from "./_generated/registry";
|
|
88
|
+
|
|
89
|
+
export {
|
|
90
|
+
KSA_REGISTRY,
|
|
91
|
+
CORE_KSAS as CORE_KSA_NAMES,
|
|
92
|
+
getAllKSAs,
|
|
93
|
+
getKSA as getKSALegacy,
|
|
94
|
+
getKSAsByCategory as getKSAsByCategoryLegacy,
|
|
95
|
+
getKSAsByNames,
|
|
96
|
+
searchKSAs,
|
|
97
|
+
getServicePathsForKSAs,
|
|
98
|
+
isServicePathAllowed,
|
|
99
|
+
} from "./_generated/registry";
|
|
100
|
+
|
|
101
|
+
// ============================================================================
|
|
102
|
+
// Re-export Config Schemas (for backward compatibility)
|
|
103
|
+
// ============================================================================
|
|
104
|
+
|
|
105
|
+
export type { ConfigField, PresetDefinition } from "./_shared/configSchemas";
|
|
106
|
+
|
|
107
|
+
export {
|
|
108
|
+
CONFIG_SCHEMAS,
|
|
109
|
+
CONFIG_DEFAULTS,
|
|
110
|
+
KSA_PRESETS,
|
|
111
|
+
getConfigSchema,
|
|
112
|
+
getConfigDefaults,
|
|
113
|
+
getPreset,
|
|
114
|
+
getPresetsForKSA,
|
|
115
|
+
resolvePreset,
|
|
116
|
+
FRAMEWORK_CONFIG_SCHEMA,
|
|
117
|
+
FRAMEWORK_DEFAULTS,
|
|
118
|
+
getFrameworkConfig,
|
|
119
|
+
} from "./_shared/configSchemas";
|
|
120
|
+
|
|
121
|
+
export type { FrameworkConfig } from "./_shared/configSchemas";
|
|
122
|
+
|
|
123
|
+
// ============================================================================
|
|
124
|
+
// Re-export Local DB (for backward compatibility)
|
|
125
|
+
// ============================================================================
|
|
126
|
+
|
|
127
|
+
export {
|
|
128
|
+
localDb,
|
|
129
|
+
getSessionId,
|
|
130
|
+
getThreadId,
|
|
131
|
+
getCardId,
|
|
132
|
+
isLocalDbAvailable,
|
|
133
|
+
getLocalDbConfig,
|
|
134
|
+
} from "./_shared/localDb";
|