ai-eng-system 0.0.13 → 0.0.15

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 (66) hide show
  1. package/README.md +24 -5
  2. package/dist/.claude-plugin/agents/agent-creator.md +1 -1
  3. package/dist/.claude-plugin/agents/command-creator.md +0 -1
  4. package/dist/.claude-plugin/agents/docs-writer.md +0 -1
  5. package/dist/.claude-plugin/agents/documentation_specialist.md +0 -1
  6. package/dist/.claude-plugin/agents/plugin-validator.md +0 -1
  7. package/dist/.claude-plugin/agents/subagent-orchestration.md +224 -0
  8. package/dist/.claude-plugin/analyzer.ts +447 -0
  9. package/dist/.claude-plugin/commands/create-skill.md +2 -2
  10. package/dist/.claude-plugin/commands/optimize.md +1075 -32
  11. package/dist/.claude-plugin/commands/plan.md +62 -32
  12. package/dist/.claude-plugin/commands/research.md +67 -63
  13. package/dist/.claude-plugin/commands/review.md +83 -10
  14. package/dist/.claude-plugin/commands/specify.md +54 -16
  15. package/dist/.claude-plugin/commands/work.md +57 -14
  16. package/dist/.claude-plugin/formatter.ts +274 -0
  17. package/dist/.claude-plugin/hooks/hooks.json +0 -0
  18. package/dist/.claude-plugin/hooks/prompt-optimizer-hook.py +0 -0
  19. package/dist/.claude-plugin/index.ts +54 -0
  20. package/dist/.claude-plugin/marketplace.json +3 -3
  21. package/dist/.claude-plugin/optimizer.ts +441 -0
  22. package/dist/.claude-plugin/plugin.json +9 -9
  23. package/dist/.claude-plugin/skills/plugin-dev/SKILL.md +0 -2
  24. package/dist/.claude-plugin/skills/plugin-dev/references/agent-format.md +1 -6
  25. package/dist/.claude-plugin/skills/plugin-dev/references/claude-code-plugins.md +0 -2
  26. package/dist/.claude-plugin/skills/plugin-dev/references/command-format.md +0 -3
  27. package/dist/.claude-plugin/skills/plugin-dev/references/opencode-plugins.md +7 -7
  28. package/dist/.claude-plugin/skills/plugin-dev/references/skill-format.md +1 -1
  29. package/dist/.claude-plugin/techniques.ts +230 -0
  30. package/dist/.claude-plugin/types.ts +214 -0
  31. package/dist/.opencode/agent/ai-eng/development/docs-writer.md +0 -1
  32. package/dist/.opencode/agent/ai-eng/development/documentation_specialist.md +0 -1
  33. package/dist/.opencode/agent/ai-eng/general/subagent-orchestration.md +225 -0
  34. package/dist/.opencode/agent/ai-eng/meta/agent-creator.md +1 -1
  35. package/dist/.opencode/agent/ai-eng/meta/command-creator.md +0 -1
  36. package/dist/.opencode/agent/ai-eng/quality-testing/plugin-validator.md +0 -1
  37. package/dist/.opencode/command/ai-eng/create-skill.md +2 -2
  38. package/dist/.opencode/command/ai-eng/optimize.md +1075 -32
  39. package/dist/.opencode/command/ai-eng/plan.md +62 -32
  40. package/dist/.opencode/command/ai-eng/research.md +67 -63
  41. package/dist/.opencode/command/ai-eng/review.md +83 -10
  42. package/dist/.opencode/command/ai-eng/specify.md +54 -16
  43. package/dist/.opencode/command/ai-eng/work.md +57 -14
  44. package/dist/.opencode/skill/plugin-dev/SKILL.md +0 -2
  45. package/dist/.opencode/skill/plugin-dev/references/agent-format.md +1 -6
  46. package/dist/.opencode/skill/plugin-dev/references/claude-code-plugins.md +0 -2
  47. package/dist/.opencode/skill/plugin-dev/references/command-format.md +0 -3
  48. package/dist/.opencode/skill/plugin-dev/references/opencode-plugins.md +7 -7
  49. package/dist/.opencode/skill/plugin-dev/references/skill-format.md +1 -1
  50. package/dist/.opencode/tool/prompt-optimize.ts +184 -0
  51. package/dist/index.js +13 -46
  52. package/dist/prompt-optimization/analyzer.ts +447 -0
  53. package/dist/prompt-optimization/formatter.ts +274 -0
  54. package/dist/prompt-optimization/index.ts +54 -0
  55. package/dist/prompt-optimization/optimizer.ts +441 -0
  56. package/dist/prompt-optimization/techniques.ts +230 -0
  57. package/dist/prompt-optimization/types.ts +214 -0
  58. package/dist/skills/plugin-dev/SKILL.md +0 -2
  59. package/dist/skills/plugin-dev/references/agent-format.md +1 -6
  60. package/dist/skills/plugin-dev/references/claude-code-plugins.md +0 -2
  61. package/dist/skills/plugin-dev/references/command-format.md +0 -3
  62. package/dist/skills/plugin-dev/references/opencode-plugins.md +7 -7
  63. package/dist/skills/plugin-dev/references/skill-format.md +1 -1
  64. package/package.json +5 -3
  65. package/scripts/install.js +333 -47
  66. package/dist/.claude-plugin/hooks.json +0 -17
@@ -0,0 +1,447 @@
1
+ /**
2
+ * Prompt Analyzer
3
+ *
4
+ * Analyzes user prompts to determine complexity, domain,
5
+ * and missing context. Uses a combination of word count,
6
+ * keyword detection, and pattern matching.
7
+ */
8
+
9
+ import type { AnalysisResult, Complexity, Domain, TechniqueId } from "./types";
10
+
11
+ /**
12
+ * Keywords for complexity detection
13
+ */
14
+ const COMPLEXITY_KEYWORDS = {
15
+ debug: ["debug", "fix", "error", "bug", "issue", "problem", "troubleshoot"],
16
+ design: [
17
+ "design",
18
+ "architecture",
19
+ "architect",
20
+ "structure",
21
+ "pattern",
22
+ "approach",
23
+ ],
24
+ optimize: [
25
+ "optimize",
26
+ "improve",
27
+ "performance",
28
+ "efficient",
29
+ "fast",
30
+ "scale",
31
+ ],
32
+ implement: ["implement", "build", "create", "develop", "write", "code"],
33
+ complex: ["complex", "challenge", "difficult", "advanced", "sophisticated"],
34
+ };
35
+
36
+ /**
37
+ * Domain-specific keywords
38
+ */
39
+ const DOMAIN_KEYWORDS: Record<Domain, string[]> = {
40
+ security: [
41
+ "auth",
42
+ "authentication",
43
+ "jwt",
44
+ "oauth",
45
+ "password",
46
+ "encrypt",
47
+ "decrypt",
48
+ "security",
49
+ "token",
50
+ "session",
51
+ "csrf",
52
+ "xss",
53
+ "injection",
54
+ "vulnerability",
55
+ "hack",
56
+ "attack",
57
+ ],
58
+ frontend: [
59
+ "react",
60
+ "vue",
61
+ "angular",
62
+ "component",
63
+ "css",
64
+ "html",
65
+ "ui",
66
+ "ux",
67
+ "render",
68
+ "state",
69
+ "hook",
70
+ "props",
71
+ "dom",
72
+ "frontend",
73
+ "client",
74
+ ],
75
+ backend: [
76
+ "api",
77
+ "server",
78
+ "endpoint",
79
+ "database",
80
+ "query",
81
+ "backend",
82
+ "service",
83
+ "microservice",
84
+ "rest",
85
+ "graphql",
86
+ "http",
87
+ "request",
88
+ "response",
89
+ ],
90
+ database: [
91
+ "sql",
92
+ "postgresql",
93
+ "mysql",
94
+ "mongodb",
95
+ "redis",
96
+ "query",
97
+ "index",
98
+ "schema",
99
+ "migration",
100
+ "database",
101
+ "db",
102
+ "join",
103
+ "transaction",
104
+ "orm",
105
+ ],
106
+ devops: [
107
+ "deploy",
108
+ "ci/cd",
109
+ "docker",
110
+ "kubernetes",
111
+ "k8s",
112
+ "pipeline",
113
+ "infrastructure",
114
+ "aws",
115
+ "gcp",
116
+ "azure",
117
+ "terraform",
118
+ "ansible",
119
+ "jenkins",
120
+ "devops",
121
+ "ops",
122
+ ],
123
+ architecture: [
124
+ "architecture",
125
+ "design",
126
+ "pattern",
127
+ "microservices",
128
+ "monolith",
129
+ "scalability",
130
+ "system",
131
+ "distributed",
132
+ "architect",
133
+ "high-level",
134
+ ],
135
+ testing: [
136
+ "test",
137
+ "spec",
138
+ "unit test",
139
+ "integration test",
140
+ "e2e",
141
+ "jest",
142
+ "cypress",
143
+ "playwright",
144
+ "testing",
145
+ "tdd",
146
+ "coverage",
147
+ "mock",
148
+ "stub",
149
+ ],
150
+ general: [], // Fallback domain
151
+ };
152
+
153
+ /**
154
+ * Simple prompt patterns (greetings, simple questions)
155
+ */
156
+ const SIMPLE_PATTERNS = [
157
+ /^(hello|hi|hey|greetings|good morning|good evening)/i,
158
+ /^(thanks|thank you|thx)/i,
159
+ /^(yes|no|ok|sure|alright)/i,
160
+ /^(what|how|why|when|where|who|which)\s+\w+\??$/i, // Simple single questions
161
+ /^(help|assist)\s*$/i,
162
+ ];
163
+
164
+ /**
165
+ * Calculate complexity score for a prompt
166
+ */
167
+ function calculateComplexityScore(prompt: string): number {
168
+ const words = prompt.split(/\s+/);
169
+ const wordCount = words.length;
170
+
171
+ let score = 0;
172
+
173
+ // Word count contribution (0-10 points)
174
+ if (wordCount < 5) score += 0;
175
+ else if (wordCount < 10) score += 3;
176
+ else if (wordCount < 20) score += 6;
177
+ else score += 10;
178
+
179
+ // Keyword contribution (0-10 points)
180
+ const lowerPrompt = prompt.toLowerCase();
181
+ for (const category of Object.values(COMPLEXITY_KEYWORDS)) {
182
+ for (const keyword of category) {
183
+ if (lowerPrompt.includes(keyword)) {
184
+ score += 2;
185
+ break; // One keyword per category
186
+ }
187
+ }
188
+ }
189
+
190
+ // Question marks reduce complexity (asking for info is simpler)
191
+ const questionMarks = (prompt.match(/\?/g) || []).length;
192
+ score -= Math.min(questionMarks * 2, 5);
193
+
194
+ // Technical terms increase complexity
195
+ const techTerms = words.filter((word) => {
196
+ const lower = word.toLowerCase();
197
+ return (
198
+ /\w{4,}/.test(word) &&
199
+ !["this", "that", "with", "from", "into"].includes(lower)
200
+ );
201
+ });
202
+ score += Math.min(techTerms.length * 0.5, 5);
203
+
204
+ return Math.max(0, Math.min(20, score));
205
+ }
206
+
207
+ /**
208
+ * Determine complexity from score
209
+ */
210
+ function scoreToComplexity(score: number): Complexity {
211
+ if (score < 5) return "simple";
212
+ if (score < 12) return "medium";
213
+ return "complex";
214
+ }
215
+
216
+ /**
217
+ * Check if prompt matches simple patterns
218
+ */
219
+ function isSimplePrompt(prompt: string): boolean {
220
+ for (const pattern of SIMPLE_PATTERNS) {
221
+ if (pattern.test(prompt.trim())) {
222
+ return true;
223
+ }
224
+ }
225
+ return false;
226
+ }
227
+
228
+ /**
229
+ * Detect domain from prompt keywords
230
+ */
231
+ function detectDomain(prompt: string): Domain {
232
+ const lowerPrompt = prompt.toLowerCase();
233
+
234
+ // Count keyword matches per domain
235
+ const scores: Record<Domain, number> = {
236
+ security: 0,
237
+ frontend: 0,
238
+ backend: 0,
239
+ database: 0,
240
+ devops: 0,
241
+ architecture: 0,
242
+ testing: 0,
243
+ general: 0,
244
+ };
245
+
246
+ for (const [domain, keywords] of Object.entries(DOMAIN_KEYWORDS)) {
247
+ for (const keyword of keywords) {
248
+ if (lowerPrompt.includes(keyword)) {
249
+ scores[domain as Domain]++;
250
+ }
251
+ }
252
+ }
253
+
254
+ // Find domain with highest score
255
+ let bestDomain: Domain = "general";
256
+ let bestScore = 0;
257
+
258
+ for (const [domain, score] of Object.entries(scores)) {
259
+ if (score > bestScore) {
260
+ bestScore = score;
261
+ bestDomain = domain as Domain;
262
+ }
263
+ }
264
+
265
+ return bestDomain;
266
+ }
267
+
268
+ /**
269
+ * Extract keywords from prompt
270
+ */
271
+ function extractKeywords(prompt: string): string[] {
272
+ const keywords: string[] = [];
273
+ const lowerPrompt = prompt.toLowerCase();
274
+
275
+ // Extract from complexity keywords
276
+ for (const [category, terms] of Object.entries(COMPLEXITY_KEYWORDS)) {
277
+ for (const term of terms) {
278
+ if (lowerPrompt.includes(term) && !keywords.includes(term)) {
279
+ keywords.push(term);
280
+ }
281
+ }
282
+ }
283
+
284
+ // Extract from domain keywords
285
+ for (const [domain, terms] of Object.entries(DOMAIN_KEYWORDS)) {
286
+ for (const term of terms) {
287
+ if (lowerPrompt.includes(term) && !keywords.includes(term)) {
288
+ keywords.push(term);
289
+ }
290
+ }
291
+ }
292
+
293
+ return keywords;
294
+ }
295
+
296
+ /**
297
+ * Identify missing context based on prompt content
298
+ */
299
+ function identifyMissingContext(prompt: string, domain: Domain): string[] {
300
+ const missing: string[] = [];
301
+ const lowerPrompt = prompt.toLowerCase();
302
+
303
+ // Check for debug/fix requests
304
+ if (
305
+ lowerPrompt.includes("fix") ||
306
+ lowerPrompt.includes("debug") ||
307
+ lowerPrompt.includes("error")
308
+ ) {
309
+ if (
310
+ !lowerPrompt.includes("error") &&
311
+ !lowerPrompt.includes("exception")
312
+ ) {
313
+ missing.push("error message or stack trace");
314
+ }
315
+ if (!/\.(js|ts|py|go|java|rb|php)/i.test(prompt)) {
316
+ missing.push("file or code location");
317
+ }
318
+ }
319
+
320
+ // Check for tech stack
321
+ const techKeywords = [
322
+ "javascript",
323
+ "typescript",
324
+ "python",
325
+ "go",
326
+ "java",
327
+ "rust",
328
+ "react",
329
+ "vue",
330
+ "angular",
331
+ "node",
332
+ "express",
333
+ "django",
334
+ "flask",
335
+ ];
336
+ const hasTech = techKeywords.some((tech) => lowerPrompt.includes(tech));
337
+ if (!hasTech && !/\.(js|ts|py|go|java|rb|php)/i.test(prompt)) {
338
+ missing.push("technology stack");
339
+ }
340
+
341
+ // Domain-specific missing context
342
+ if (domain === "security") {
343
+ if (
344
+ !lowerPrompt.includes("jwt") &&
345
+ !lowerPrompt.includes("oauth") &&
346
+ !lowerPrompt.includes("session")
347
+ ) {
348
+ missing.push("authentication method (JWT, OAuth, session, etc.)");
349
+ }
350
+ }
351
+
352
+ if (domain === "database") {
353
+ if (
354
+ !lowerPrompt.includes("sql") &&
355
+ !lowerPrompt.includes("mysql") &&
356
+ !lowerPrompt.includes("postgresql") &&
357
+ !lowerPrompt.includes("mongodb")
358
+ ) {
359
+ missing.push("database type");
360
+ }
361
+ if (!lowerPrompt.includes("index")) {
362
+ missing.push("index information");
363
+ }
364
+ }
365
+
366
+ return missing;
367
+ }
368
+
369
+ /**
370
+ * Suggest techniques based on analysis
371
+ */
372
+ function suggestTechniques(
373
+ complexity: Complexity,
374
+ domain: Domain,
375
+ ): TechniqueId[] {
376
+ const techniques: TechniqueId[] = [];
377
+
378
+ // Always start with analysis
379
+ techniques.push("analysis");
380
+
381
+ // Expert persona for medium and complex
382
+ if (complexity === "medium" || complexity === "complex") {
383
+ techniques.push("expert_persona");
384
+ }
385
+
386
+ // Reasoning chain for medium and complex
387
+ if (complexity === "medium" || complexity === "complex") {
388
+ techniques.push("reasoning_chain");
389
+ }
390
+
391
+ // Stakes language for medium and complex
392
+ if (complexity === "medium" || complexity === "complex") {
393
+ techniques.push("stakes_language");
394
+ }
395
+
396
+ // Challenge framing only for complex
397
+ if (complexity === "complex") {
398
+ techniques.push("challenge_framing");
399
+ }
400
+
401
+ // Self-evaluation for medium and complex
402
+ if (complexity === "medium" || complexity === "complex") {
403
+ techniques.push("self_evaluation");
404
+ }
405
+
406
+ return techniques;
407
+ }
408
+
409
+ /**
410
+ * Main analysis function
411
+ */
412
+ export function analyzePrompt(prompt: string): AnalysisResult {
413
+ // Check for simple patterns first
414
+ if (isSimplePrompt(prompt)) {
415
+ return {
416
+ complexity: "simple",
417
+ domain: "general",
418
+ keywords: [],
419
+ missingContext: [],
420
+ suggestedTechniques: ["analysis"],
421
+ };
422
+ }
423
+
424
+ // Calculate complexity
425
+ const complexityScore = calculateComplexityScore(prompt);
426
+ const complexity = scoreToComplexity(complexityScore);
427
+
428
+ // Detect domain
429
+ const domain = detectDomain(prompt);
430
+
431
+ // Extract keywords
432
+ const keywords = extractKeywords(prompt);
433
+
434
+ // Identify missing context
435
+ const missingContext = identifyMissingContext(prompt, domain);
436
+
437
+ // Suggest techniques
438
+ const suggestedTechniques = suggestTechniques(complexity, domain);
439
+
440
+ return {
441
+ complexity,
442
+ domain,
443
+ keywords,
444
+ missingContext,
445
+ suggestedTechniques,
446
+ };
447
+ }
@@ -24,8 +24,8 @@ Create a new OpenCode skill using AI assistance.
24
24
  ## Output Location
25
25
 
26
26
  Skill will be saved to:
27
- - Project-local: `.opencode/skills/[skill-name]/SKILL.md`
28
- - Global: `~/.config/opencode/skills/[skill-name]/SKILL.md`
27
+ - Project-local: `.opencode/skill/[skill-name]/SKILL.md`
28
+ - Global: `~/.config/opencode/skill/[skill-name]/SKILL.md`
29
29
  - Ferg content: `content/skills/[skill-name]/SKILL.md`
30
30
 
31
31
  ## Examples