@ftarganski/omni-ai 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 (49) hide show
  1. package/dist/chunk-3RZELMF2.js +214 -0
  2. package/dist/chunk-5WELBZWN.js +70 -0
  3. package/dist/chunk-6APAA6WD.js +495 -0
  4. package/dist/chunk-6OPRALDC.js +163 -0
  5. package/dist/chunk-6YFFZMXY.js +104 -0
  6. package/dist/chunk-AG6NZIJ3.js +122 -0
  7. package/dist/chunk-AWMSN7OB.js +451 -0
  8. package/dist/chunk-JTXDF5KG.js +156 -0
  9. package/dist/chunk-M4QJF7CV.js +57 -0
  10. package/dist/chunk-PPTEJ2FH.js +102 -0
  11. package/dist/chunk-S5MK6LBH.js +136 -0
  12. package/dist/chunk-TFU437SW.js +107 -0
  13. package/dist/chunk-Y4EYGADJ.js +216 -0
  14. package/dist/cli/bin.js +2723 -0
  15. package/dist/index.d.ts +16 -0
  16. package/dist/index.js +42 -0
  17. package/dist/mcp.d.ts +1 -0
  18. package/dist/mcp.js +86 -0
  19. package/dist/memory.d.ts +1 -0
  20. package/dist/memory.js +320 -0
  21. package/dist/provider-anthropic.d.ts +1 -0
  22. package/dist/provider-anthropic.js +120 -0
  23. package/dist/provider-google.d.ts +1 -0
  24. package/dist/provider-google.js +141 -0
  25. package/dist/provider-openai.d.ts +1 -0
  26. package/dist/provider-openai.js +214 -0
  27. package/dist/skills/backend.d.ts +1 -0
  28. package/dist/skills/backend.js +12 -0
  29. package/dist/skills/code.d.ts +1 -0
  30. package/dist/skills/code.js +6 -0
  31. package/dist/skills/frontend.d.ts +1 -0
  32. package/dist/skills/frontend.js +10 -0
  33. package/dist/skills/fs.d.ts +1 -0
  34. package/dist/skills/fs.js +10 -0
  35. package/dist/skills/git.d.ts +1 -0
  36. package/dist/skills/git.js +12 -0
  37. package/dist/skills/http.d.ts +1 -0
  38. package/dist/skills/http.js +6 -0
  39. package/dist/skills/index.d.ts +1 -0
  40. package/dist/skills/index.js +60 -0
  41. package/dist/skills/multimodal.d.ts +1 -0
  42. package/dist/skills/multimodal.js +6 -0
  43. package/dist/skills/qa.d.ts +1 -0
  44. package/dist/skills/qa.js +8 -0
  45. package/dist/skills/ux.d.ts +1 -0
  46. package/dist/skills/ux.js +6 -0
  47. package/dist/src-6MUVU5ML.js +8 -0
  48. package/dist/src-ZHTGR7T6.js +8 -0
  49. package/package.json +136 -0
@@ -0,0 +1,214 @@
1
+ // ../skills/src/backend/analyze-dynamo-schema.ts
2
+ import { readFile } from "fs/promises";
3
+ import { resolve } from "path";
4
+ import { z } from "zod";
5
+ var InputSchema = z.object({
6
+ path: z.string().describe("Path to the *.model.ts file containing the OneTable schema")
7
+ });
8
+ function extractSchemaName(source) {
9
+ const match = /export\s+const\s+(\w+Schema)\s*=/.exec(source);
10
+ return match?.[1] ?? "UnknownSchema";
11
+ }
12
+ function extractEntityType(source) {
13
+ const match = /export\s+type\s+(\w+)\s*=\s*Entity</.exec(source);
14
+ return match?.[1] ?? "UnknownEntity";
15
+ }
16
+ function extractFields(source) {
17
+ const fieldsKeyIdx = source.indexOf("fields:");
18
+ if (fieldsKeyIdx === -1) return [];
19
+ const braceOpen = source.indexOf("{", fieldsKeyIdx);
20
+ if (braceOpen === -1) return [];
21
+ let depth = 0;
22
+ let fieldsEnd = -1;
23
+ for (let i = braceOpen; i < source.length; i++) {
24
+ if (source[i] === "{") depth++;
25
+ else if (source[i] === "}") {
26
+ depth--;
27
+ if (depth === 0) {
28
+ fieldsEnd = i;
29
+ break;
30
+ }
31
+ }
32
+ }
33
+ if (fieldsEnd === -1) return [];
34
+ const fieldsBlock = source.slice(braceOpen + 1, fieldsEnd);
35
+ const fields = [];
36
+ for (const m of fieldsBlock.matchAll(/(\w+)\s*:\s*\{([^}]*)\}/g)) {
37
+ const body = m[2];
38
+ const typeMatch = /type\s*:\s*['"]?(\w+)['"]?/.exec(body);
39
+ const requiredMatch = /required\s*:\s*(true|false)/.exec(body);
40
+ fields.push({
41
+ name: m[1],
42
+ type: typeMatch?.[1] ?? "unknown",
43
+ required: requiredMatch?.[1] === "true",
44
+ isEnum: /enum\s*:\s*\w+/.test(body)
45
+ });
46
+ }
47
+ return fields;
48
+ }
49
+ function extractEnums(source) {
50
+ const enums = [];
51
+ for (const m of source.matchAll(/export\s+(?:const\s+)?enum\s+(\w+)\s*\{([^}]*)\}/g)) {
52
+ const values = m[2].split(",").map((v) => v.trim().split("=")[0].trim()).filter(Boolean);
53
+ enums.push({ name: m[1], values });
54
+ }
55
+ return enums;
56
+ }
57
+ function extractTypenames(source) {
58
+ const matches = source.match(/Typenames\.\w+/g) ?? [];
59
+ return [...new Set(matches)];
60
+ }
61
+ var analyzeDynamoSchemaSkill = {
62
+ name: "analyze-dynamo-schema",
63
+ description: "Parse a OneTable *.model.ts file and extract the schema name, entity type, fields (with types and required flags), enums, and Typenames references. Use this before generating a service to understand the exact entity shape.",
64
+ async execute(input) {
65
+ const { path } = InputSchema.parse(input);
66
+ const source = await readFile(resolve(path), "utf-8");
67
+ return {
68
+ schemaName: extractSchemaName(source),
69
+ entityType: extractEntityType(source),
70
+ fields: extractFields(source),
71
+ enums: extractEnums(source),
72
+ typenames: extractTypenames(source)
73
+ };
74
+ }
75
+ };
76
+
77
+ // ../skills/src/backend/analyze-graphql-schema.ts
78
+ import { readFile as readFile2 } from "fs/promises";
79
+ import { resolve as resolve2 } from "path";
80
+ import { z as z2 } from "zod";
81
+ var InputSchema2 = z2.object({
82
+ path: z2.string().describe("Path to the *.schema.graphql file")
83
+ });
84
+ function extractOperations(source, section) {
85
+ const sectionRe = new RegExp(`extend\\s+type\\s+${section}\\s*\\{([^}]*)\\}`, "s");
86
+ const match = sectionRe.exec(source);
87
+ if (!match) return [];
88
+ const ops = [];
89
+ for (const m of match[1].matchAll(/(\w+)\s*(\([^)]*\))?\s*:\s*([^\n@#]+)((?:\s*@\w+[^\n]*)*)/g)) {
90
+ const directives = m[4].trim().split(/\s*@/).filter(Boolean).map((d) => `@${d.trim()}`);
91
+ ops.push({
92
+ name: m[1],
93
+ args: (m[2] ?? "").trim(),
94
+ returns: m[3].trim(),
95
+ directives
96
+ });
97
+ }
98
+ return ops;
99
+ }
100
+ function extractTypes(source) {
101
+ const types = [];
102
+ for (const m of source.matchAll(/(?:^|\n)\s*(?:extend\s+)?type\s+(\w+)\s*(?:implements[^{]*)?\{/g)) {
103
+ if (!["Query", "Mutation", "Subscription"].includes(m[1])) types.push(m[1]);
104
+ }
105
+ return [...new Set(types)];
106
+ }
107
+ function extractInputs(source) {
108
+ return [...source.matchAll(/input\s+(\w+)\s*\{/g)].map((m) => m[1]);
109
+ }
110
+ function extractEnums2(source) {
111
+ return [...source.matchAll(/(?:extend\s+)?enum\s+(\w+)\s*\{/g)].map((m) => m[1]);
112
+ }
113
+ var analyzeGraphqlSchemaSkill = {
114
+ name: "analyze-graphql-schema",
115
+ description: "Parse a GraphQL SDL file and extract types, queries, mutations, inputs and enums. Use this before generating a resolver to understand what operations already exist and what the correct return types are.",
116
+ async execute(input) {
117
+ const { path } = InputSchema2.parse(input);
118
+ const source = await readFile2(resolve2(path), "utf-8");
119
+ return {
120
+ types: extractTypes(source),
121
+ queries: extractOperations(source, "Query"),
122
+ mutations: extractOperations(source, "Mutation"),
123
+ inputs: extractInputs(source),
124
+ enums: extractEnums2(source)
125
+ };
126
+ }
127
+ };
128
+
129
+ // ../skills/src/backend/analyze-nestjs-module.ts
130
+ import { readFile as readFile3 } from "fs/promises";
131
+ import { resolve as resolve3 } from "path";
132
+ import { z as z3 } from "zod";
133
+ var InputSchema3 = z3.object({
134
+ path: z3.string().describe("Path to the *.module.ts file")
135
+ });
136
+ function extractArrayItems(source, key) {
137
+ const re = new RegExp(`${key}\\s*:\\s*\\[([^\\]]*?)\\]`, "s");
138
+ const match = re.exec(source);
139
+ if (!match) return [];
140
+ return match[1].split(",").map(
141
+ (s) => s.trim().replace(/\/\/.*$/m, "").trim()
142
+ ).filter(Boolean);
143
+ }
144
+ function extractModuleName(source) {
145
+ const match = /export\s+class\s+(\w+Module)/.exec(source);
146
+ return match?.[1] ?? "UnknownModule";
147
+ }
148
+ var analyzeNestjsModuleSkill = {
149
+ name: "analyze-nestjs-module",
150
+ description: "Parse a NestJS *.module.ts file and extract its imports, providers, exports and controllers. Use this to understand what a module exposes before adding new providers or resolving injection dependencies.",
151
+ async execute(input) {
152
+ const { path } = InputSchema3.parse(input);
153
+ const source = await readFile3(resolve3(path), "utf-8");
154
+ return {
155
+ moduleName: extractModuleName(source),
156
+ imports: extractArrayItems(source, "imports"),
157
+ providers: extractArrayItems(source, "providers"),
158
+ exports: extractArrayItems(source, "exports"),
159
+ controllers: extractArrayItems(source, "controllers")
160
+ };
161
+ }
162
+ };
163
+
164
+ // ../skills/src/backend/find-code-pattern.ts
165
+ import { readdir, readFile as readFile4 } from "fs/promises";
166
+ import { join } from "path";
167
+ import { z as z4 } from "zod";
168
+ var patternSuffixes = {
169
+ service: [".service.ts"],
170
+ resolver: [".resolver.ts"],
171
+ listener: [".listener.ts"],
172
+ model: [".model.ts"],
173
+ test: [".spec.ts"],
174
+ schema: [".schema.graphql"]
175
+ };
176
+ var InputSchema4 = z4.object({
177
+ patternType: z4.enum(["service", "resolver", "listener", "model", "test", "schema"]).describe("Type of NestJS pattern to find examples of"),
178
+ directory: z4.string().describe("Root directory to search in"),
179
+ maxExamples: z4.number().int().positive().default(3).describe("Maximum number of examples to return")
180
+ });
181
+ async function walkForPattern(dir, suffixes, results, max) {
182
+ if (results.length >= max) return;
183
+ const entries = await readdir(dir, { withFileTypes: true }).catch(() => null);
184
+ if (!entries) return;
185
+ for (const entry of entries) {
186
+ if (results.length >= max) break;
187
+ if (entry.name === "node_modules" || entry.name === "dist" || entry.name === ".git") continue;
188
+ const fullPath = join(dir, entry.name);
189
+ if (entry.isDirectory()) {
190
+ await walkForPattern(fullPath, suffixes, results, max);
191
+ } else if (entry.isFile() && suffixes.some((s) => entry.name.endsWith(s))) {
192
+ const content = await readFile4(fullPath, "utf-8");
193
+ results.push({ file: fullPath, content });
194
+ }
195
+ }
196
+ }
197
+ var findCodePatternSkill = {
198
+ name: "find-code-pattern",
199
+ description: "Find real examples of NestJS patterns (service, resolver, listener, model, test, schema) from the codebase. Use this before generating new code to understand the exact conventions and patterns already in use.",
200
+ async execute(input) {
201
+ const { patternType, directory, maxExamples } = InputSchema4.parse(input);
202
+ const suffixes = patternSuffixes[patternType];
203
+ const results = [];
204
+ await walkForPattern(directory, suffixes, results, maxExamples);
205
+ return results;
206
+ }
207
+ };
208
+
209
+ export {
210
+ analyzeDynamoSchemaSkill,
211
+ analyzeGraphqlSchemaSkill,
212
+ analyzeNestjsModuleSkill,
213
+ findCodePatternSkill
214
+ };
@@ -0,0 +1,70 @@
1
+ // ../skills/src/multimodal/analyze-image.ts
2
+ import { readFile } from "fs/promises";
3
+ import { extname } from "path";
4
+ import { z } from "zod";
5
+ var SUPPORTED_MIME = ["image/jpeg", "image/png", "image/gif", "image/webp"];
6
+ var InputSchema = z.object({
7
+ prompt: z.string().describe("Question or instruction for the vision model, e.g. 'Describe this screenshot'"),
8
+ imagePath: z.string().optional().describe("Absolute or relative path to an image file on disk"),
9
+ imageUrl: z.string().url().optional().describe("Public URL of an image to fetch and analyse"),
10
+ imageBase64: z.string().optional().describe("Base64-encoded image data (without data-URL prefix)"),
11
+ mimeType: z.enum(SUPPORTED_MIME).optional().describe("MIME type \u2014 required when using imageBase64, inferred from extension otherwise")
12
+ }).refine((d) => d.imagePath ?? d.imageUrl ?? d.imageBase64, {
13
+ message: "Provide exactly one of: imagePath, imageUrl, or imageBase64"
14
+ });
15
+ var EXT_TO_MIME = {
16
+ ".jpg": "image/jpeg",
17
+ ".jpeg": "image/jpeg",
18
+ ".png": "image/png",
19
+ ".gif": "image/gif",
20
+ ".webp": "image/webp"
21
+ };
22
+ async function loadImage(input) {
23
+ if (input.imagePath) {
24
+ const ext = extname(input.imagePath).toLowerCase();
25
+ const mimeType2 = input.mimeType ?? EXT_TO_MIME[ext];
26
+ if (!mimeType2) throw new Error(`Unsupported image extension "${ext}". Use: ${Object.keys(EXT_TO_MIME).join(", ")}`);
27
+ const data = (await readFile(input.imagePath)).toString("base64");
28
+ return { data, mimeType: mimeType2 };
29
+ }
30
+ if (input.imageUrl) {
31
+ const res = await fetch(input.imageUrl);
32
+ if (!res.ok) throw new Error(`Failed to fetch image: ${res.status} ${res.statusText}`);
33
+ const contentType = res.headers.get("content-type") ?? "";
34
+ const mimeType2 = input.mimeType ?? SUPPORTED_MIME.find((m) => contentType.startsWith(m));
35
+ if (!mimeType2) throw new Error(`Unsupported content-type "${contentType}"`);
36
+ const buffer = await res.arrayBuffer();
37
+ return { data: Buffer.from(buffer).toString("base64"), mimeType: mimeType2 };
38
+ }
39
+ const mimeType = input.mimeType;
40
+ if (!mimeType) throw new Error("mimeType is required when supplying imageBase64");
41
+ return { data: input.imageBase64, mimeType };
42
+ }
43
+ var analyzeImageSkill = {
44
+ name: "analyze-image",
45
+ description: "Analyse an image (screenshot, diagram, mockup, photo) using the configured vision-capable LLM provider. Accepts a file path, public URL, or raw base64 data. Returns a natural-language description or answer to your prompt.",
46
+ async execute(input, ctx) {
47
+ const parsed = InputSchema.parse(input);
48
+ if (!ctx.provider.capabilities.vision) {
49
+ throw new Error(
50
+ `Provider "${ctx.provider.name}" does not support vision. Configure a vision-capable provider (e.g. Anthropic claude-3, OpenAI gpt-4o).`
51
+ );
52
+ }
53
+ const { data, mimeType } = await loadImage(parsed);
54
+ const imagePart = { type: "image", mimeType, data };
55
+ const response = await ctx.provider.complete({
56
+ messages: [
57
+ {
58
+ role: "user",
59
+ content: [imagePart, { type: "text", text: parsed.prompt }]
60
+ }
61
+ ],
62
+ temperature: 0.2
63
+ });
64
+ return { analysis: response.content };
65
+ }
66
+ };
67
+
68
+ export {
69
+ analyzeImageSkill
70
+ };