@openweave/weave-skills 1.0.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/LICENSE +21 -0
- package/README.md +154 -0
- package/dist/config-loader.d.ts +52 -0
- package/dist/config-loader.d.ts.map +1 -0
- package/dist/config-loader.js +123 -0
- package/dist/config-loader.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/skill-registry.d.ts +96 -0
- package/dist/skill-registry.d.ts.map +1 -0
- package/dist/skill-registry.js +218 -0
- package/dist/skill-registry.js.map +1 -0
- package/dist/skills/auto-fix.d.ts +35 -0
- package/dist/skills/auto-fix.d.ts.map +1 -0
- package/dist/skills/auto-fix.js +121 -0
- package/dist/skills/auto-fix.js.map +1 -0
- package/dist/skills/cli-interactive.d.ts +60 -0
- package/dist/skills/cli-interactive.d.ts.map +1 -0
- package/dist/skills/cli-interactive.js +264 -0
- package/dist/skills/cli-interactive.js.map +1 -0
- package/dist/skills/code-review.d.ts +39 -0
- package/dist/skills/code-review.d.ts.map +1 -0
- package/dist/skills/code-review.js +204 -0
- package/dist/skills/code-review.js.map +1 -0
- package/dist/skills/commit-composer.d.ts +51 -0
- package/dist/skills/commit-composer.d.ts.map +1 -0
- package/dist/skills/commit-composer.js +223 -0
- package/dist/skills/commit-composer.js.map +1 -0
- package/dist/skills/container-advisor.d.ts +43 -0
- package/dist/skills/container-advisor.d.ts.map +1 -0
- package/dist/skills/container-advisor.js +274 -0
- package/dist/skills/container-advisor.js.map +1 -0
- package/dist/skills/context-memory.d.ts +44 -0
- package/dist/skills/context-memory.d.ts.map +1 -0
- package/dist/skills/context-memory.js +160 -0
- package/dist/skills/context-memory.js.map +1 -0
- package/dist/skills/dep-audit.d.ts +55 -0
- package/dist/skills/dep-audit.d.ts.map +1 -0
- package/dist/skills/dep-audit.js +248 -0
- package/dist/skills/dep-audit.js.map +1 -0
- package/dist/skills/deploy-provision.d.ts +47 -0
- package/dist/skills/deploy-provision.d.ts.map +1 -0
- package/dist/skills/deploy-provision.js +270 -0
- package/dist/skills/deploy-provision.js.map +1 -0
- package/dist/skills/docs-gen.d.ts +36 -0
- package/dist/skills/docs-gen.d.ts.map +1 -0
- package/dist/skills/docs-gen.js +187 -0
- package/dist/skills/docs-gen.js.map +1 -0
- package/dist/skills/index.d.ts +19 -0
- package/dist/skills/index.d.ts.map +1 -0
- package/dist/skills/index.js +55 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/skills/multi-repo.d.ts +50 -0
- package/dist/skills/multi-repo.d.ts.map +1 -0
- package/dist/skills/multi-repo.js +175 -0
- package/dist/skills/multi-repo.js.map +1 -0
- package/dist/skills/onboarding.d.ts +48 -0
- package/dist/skills/onboarding.d.ts.map +1 -0
- package/dist/skills/onboarding.js +245 -0
- package/dist/skills/onboarding.js.map +1 -0
- package/dist/skills/perf-profile.d.ts +36 -0
- package/dist/skills/perf-profile.d.ts.map +1 -0
- package/dist/skills/perf-profile.js +179 -0
- package/dist/skills/perf-profile.js.map +1 -0
- package/dist/skills/pipeline-aware.d.ts +33 -0
- package/dist/skills/pipeline-aware.d.ts.map +1 -0
- package/dist/skills/pipeline-aware.js +226 -0
- package/dist/skills/pipeline-aware.js.map +1 -0
- package/dist/skills/refactor.d.ts +33 -0
- package/dist/skills/refactor.d.ts.map +1 -0
- package/dist/skills/refactor.js +210 -0
- package/dist/skills/refactor.js.map +1 -0
- package/dist/skills/test-gen.d.ts +36 -0
- package/dist/skills/test-gen.d.ts.map +1 -0
- package/dist/skills/test-gen.js +154 -0
- package/dist/skills/test-gen.js.map +1 -0
- package/dist/types.d.ts +133 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/package.json +39 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill: perf-profile
|
|
3
|
+
*
|
|
4
|
+
* Analyses build, test and bundle timing data and produces a prioritised
|
|
5
|
+
* table of bottlenecks with actionable suggestions.
|
|
6
|
+
*
|
|
7
|
+
* Input options (ctx.graph):
|
|
8
|
+
* - `timings` {TimingEntry[]} â inject timing data directly (tests / CI JSON)
|
|
9
|
+
* - `ciLog` {string} â parse timing information from a raw CI log
|
|
10
|
+
* - `threshold` {number} â ms threshold to flag a step as slow (default: 10_000)
|
|
11
|
+
*/
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
// Suggestions by category
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
const SUGGESTIONS = {
|
|
16
|
+
build: 'Enable incremental TypeScript builds (`incremental: true` in tsconfig). Consider `isolatedModules`.',
|
|
17
|
+
test: 'Use `--reporter=dot` or run only changed files with `--changed`. Parallelise across workers.',
|
|
18
|
+
bundle: 'Enable Vite/esbuild caching. Code-split large entry points. Analyse bundle with `rollup-plugin-visualizer`.',
|
|
19
|
+
lint: 'Use `lint-staged` to lint only staged files. Enable ESLint caching (`--cache`).',
|
|
20
|
+
install: 'Use `pnpm install --frozen-lockfile`. Cache `~/.pnpm-store` in CI. Audit dep count.',
|
|
21
|
+
other: 'Profile the step further to identify sub-task bottlenecks.',
|
|
22
|
+
};
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// Log-based timing extraction
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
const TIMING_PATTERNS = [
|
|
27
|
+
// GitHub Actions step duration: "##[group]Run pnpm build (3m 12s)"
|
|
28
|
+
{
|
|
29
|
+
pattern: /##\[group\](.+?)\s+\((\d+)m\s+(\d+)s\)/i,
|
|
30
|
+
label: (m) => m[1].trim(),
|
|
31
|
+
category: 'build',
|
|
32
|
+
},
|
|
33
|
+
// Generic "Step X completed in Ns" or "done in Ns"
|
|
34
|
+
{
|
|
35
|
+
pattern: /(?:completed in|done in|finished in)\s+(\d+(?:\.\d+)?)\s*s(?:ec(?:onds?)?)?/i,
|
|
36
|
+
label: (_m, line) => (line ?? 'step').trim().slice(0, 50),
|
|
37
|
+
category: 'other',
|
|
38
|
+
},
|
|
39
|
+
// Vitest / Jest duration: "Duration 12.34 s"
|
|
40
|
+
{
|
|
41
|
+
pattern: /Duration\s+(\d+(?:\.\d+)?)\s*s\b/i,
|
|
42
|
+
label: () => 'Test suite',
|
|
43
|
+
category: 'test',
|
|
44
|
+
},
|
|
45
|
+
// npm/pnpm install: "added N packages in Xs"
|
|
46
|
+
{
|
|
47
|
+
pattern: /added\s+\d+\s+packages?\s+in\s+(\d+(?:\.\d+)?)\s*s/i,
|
|
48
|
+
label: () => 'Package install',
|
|
49
|
+
category: 'install',
|
|
50
|
+
},
|
|
51
|
+
// tsc timing
|
|
52
|
+
{
|
|
53
|
+
pattern: /tsc\s+.*?(\d+(?:\.\d+)?)\s*s(?:ec)?/i,
|
|
54
|
+
label: () => 'TypeScript compile',
|
|
55
|
+
category: 'build',
|
|
56
|
+
},
|
|
57
|
+
];
|
|
58
|
+
export function extractTimingsFromLog(log) {
|
|
59
|
+
const lines = log.split('\n');
|
|
60
|
+
const entries = [];
|
|
61
|
+
for (const line of lines) {
|
|
62
|
+
for (const rule of TIMING_PATTERNS) {
|
|
63
|
+
const m = rule.pattern.exec(line);
|
|
64
|
+
if (!m)
|
|
65
|
+
continue;
|
|
66
|
+
// Try to parse duration
|
|
67
|
+
let durationMs = 0;
|
|
68
|
+
if (rule.pattern.source.includes('(\\d+)m')) {
|
|
69
|
+
// "Xm Ys" format
|
|
70
|
+
const mins = parseInt(m[2], 10);
|
|
71
|
+
const secs = parseInt(m[3], 10);
|
|
72
|
+
durationMs = (mins * 60 + secs) * 1000;
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
// seconds as float
|
|
76
|
+
const secIdx = m.findIndex((v, i) => i > 0 && /^\d+(\.\d+)?$/.test(v ?? ''));
|
|
77
|
+
if (secIdx > 0) {
|
|
78
|
+
durationMs = Math.round(parseFloat(m[secIdx]) * 1000);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (durationMs > 0) {
|
|
82
|
+
entries.push({
|
|
83
|
+
label: rule.label(m, line),
|
|
84
|
+
durationMs,
|
|
85
|
+
category: rule.category,
|
|
86
|
+
});
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return entries;
|
|
92
|
+
}
|
|
93
|
+
// ---------------------------------------------------------------------------
|
|
94
|
+
// Analysis
|
|
95
|
+
// ---------------------------------------------------------------------------
|
|
96
|
+
export function analyseTimings(entries, threshold = 10_000) {
|
|
97
|
+
if (entries.length === 0) {
|
|
98
|
+
return {
|
|
99
|
+
entries: [],
|
|
100
|
+
bottlenecks: [],
|
|
101
|
+
totalMs: 0,
|
|
102
|
+
slowestStep: null,
|
|
103
|
+
summary: 'No timing data available',
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
const sorted = [...entries].sort((a, b) => b.durationMs - a.durationMs);
|
|
107
|
+
const slowest = sorted[0];
|
|
108
|
+
const totalMs = entries.reduce((sum, e) => sum + e.durationMs, 0);
|
|
109
|
+
const bottlenecks = sorted
|
|
110
|
+
.filter((e) => e.durationMs >= threshold / 2) // surface anything âĨ half the threshold
|
|
111
|
+
.map((e) => {
|
|
112
|
+
let severity = 'info';
|
|
113
|
+
if (e.durationMs >= threshold)
|
|
114
|
+
severity = 'critical';
|
|
115
|
+
else if (e.durationMs >= threshold * 0.6)
|
|
116
|
+
severity = 'warning';
|
|
117
|
+
return {
|
|
118
|
+
label: e.label,
|
|
119
|
+
durationMs: e.durationMs,
|
|
120
|
+
category: e.category,
|
|
121
|
+
severity,
|
|
122
|
+
suggestion: SUGGESTIONS[e.category],
|
|
123
|
+
};
|
|
124
|
+
});
|
|
125
|
+
const criticals = bottlenecks.filter((b) => b.severity === 'critical').length;
|
|
126
|
+
const summary = criticals > 0
|
|
127
|
+
? `â ${criticals} step(s) exceed ${threshold / 1000}s threshold â total pipeline: ${(totalMs / 1000).toFixed(1)}s`
|
|
128
|
+
: `â
All steps within threshold â total: ${(totalMs / 1000).toFixed(1)}s`;
|
|
129
|
+
return { entries, bottlenecks, totalMs, slowestStep: slowest, summary };
|
|
130
|
+
}
|
|
131
|
+
// ---------------------------------------------------------------------------
|
|
132
|
+
// Skill
|
|
133
|
+
// ---------------------------------------------------------------------------
|
|
134
|
+
export const perfProfileSkill = {
|
|
135
|
+
id: 'perf-profile',
|
|
136
|
+
name: 'Perf Profiler',
|
|
137
|
+
description: 'Analyses build/test/bundle timing data and surfaces bottlenecks with optimisation suggestions',
|
|
138
|
+
version: '1.0.0',
|
|
139
|
+
enabled: false,
|
|
140
|
+
tags: ['devops', 'performance'],
|
|
141
|
+
async execute(ctx) {
|
|
142
|
+
const opts = ctx.graph ?? {};
|
|
143
|
+
const threshold = typeof opts['threshold'] === 'number' ? opts['threshold'] : 10_000;
|
|
144
|
+
let entries = [];
|
|
145
|
+
if (Array.isArray(opts['timings'])) {
|
|
146
|
+
entries = opts['timings'];
|
|
147
|
+
}
|
|
148
|
+
else if (typeof opts['ciLog'] === 'string') {
|
|
149
|
+
entries = extractTimingsFromLog(opts['ciLog']);
|
|
150
|
+
}
|
|
151
|
+
const report = analyseTimings(entries, threshold);
|
|
152
|
+
const lines = [
|
|
153
|
+
`âą Perf Profiler â ${report.entries.length} timing entries`,
|
|
154
|
+
` ${report.summary}`,
|
|
155
|
+
'',
|
|
156
|
+
];
|
|
157
|
+
if (report.bottlenecks.length > 0) {
|
|
158
|
+
lines.push(' BOTTLENECKS (slowest first):');
|
|
159
|
+
for (const b of report.bottlenecks) {
|
|
160
|
+
const icon = b.severity === 'critical' ? 'â' : b.severity === 'warning' ? 'â ī¸ ' : 'âšī¸ ';
|
|
161
|
+
const dur = b.durationMs >= 60_000
|
|
162
|
+
? `${(b.durationMs / 60_000).toFixed(1)}m`
|
|
163
|
+
: `${(b.durationMs / 1000).toFixed(1)}s`;
|
|
164
|
+
lines.push(` ${icon} ${b.label} [${b.category}] â ${dur}`);
|
|
165
|
+
lines.push(` đĄ ${b.suggestion}`);
|
|
166
|
+
lines.push('');
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
lines.push(' â
No bottlenecks detected.');
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
success: report.bottlenecks.filter((b) => b.severity === 'critical').length === 0,
|
|
174
|
+
output: lines.join('\n'),
|
|
175
|
+
data: report,
|
|
176
|
+
};
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
//# sourceMappingURL=perf-profile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"perf-profile.js","sourceRoot":"","sources":["../../src/skills/perf-profile.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill: pipeline-aware
|
|
3
|
+
*
|
|
4
|
+
* Parses CI/CD log output (GitHub Actions, GitLab CI, generic) and produces a
|
|
5
|
+
* structured diagnosis: root cause, failing step, and a suggested remediation.
|
|
6
|
+
*
|
|
7
|
+
* Input options (ctx.graph):
|
|
8
|
+
* - `log` {string} â inject raw log content directly (for tests / piping)
|
|
9
|
+
* - `logFile` {string} â absolute path to a log file to read
|
|
10
|
+
* - `platform` {'github'|'gitlab'|'auto'} â hint for parser (default: 'auto')
|
|
11
|
+
*/
|
|
12
|
+
import type { SkillModule } from '../types.js';
|
|
13
|
+
export type CIPlatform = 'github' | 'gitlab' | 'generic';
|
|
14
|
+
export type FailureCategory = 'test-failure' | 'build-error' | 'lint-error' | 'permission-error' | 'network-error' | 'config-error' | 'timeout' | 'unknown';
|
|
15
|
+
export interface CIFailure {
|
|
16
|
+
step: string;
|
|
17
|
+
category: FailureCategory;
|
|
18
|
+
severity: 'critical' | 'high' | 'medium';
|
|
19
|
+
message: string;
|
|
20
|
+
context: string;
|
|
21
|
+
suggestion: string;
|
|
22
|
+
}
|
|
23
|
+
export interface PipelineReport {
|
|
24
|
+
platform: CIPlatform;
|
|
25
|
+
status: 'passed' | 'failed' | 'unknown';
|
|
26
|
+
failures: CIFailure[];
|
|
27
|
+
totalLines: number;
|
|
28
|
+
summary: string;
|
|
29
|
+
}
|
|
30
|
+
export declare function detectPlatform(log: string): CIPlatform;
|
|
31
|
+
export declare function parsePipelineLog(log: string, platform?: CIPlatform): PipelineReport;
|
|
32
|
+
export declare const pipelineAwareSkill: SkillModule;
|
|
33
|
+
//# sourceMappingURL=pipeline-aware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline-aware.d.ts","sourceRoot":"","sources":["../../src/skills/pipeline-aware.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,WAAW,EAA6B,MAAM,aAAa,CAAC;AAM1E,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEzD,MAAM,MAAM,eAAe,GACvB,cAAc,GACd,aAAa,GACb,YAAY,GACZ,kBAAkB,GAClB,eAAe,GACf,cAAc,GACd,SAAS,GACT,SAAS,CAAC;AAEd,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,eAAe,CAAC;IAC1B,QAAQ,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,CAAC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,UAAU,CAAC;IACrB,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;IACxC,QAAQ,EAAE,SAAS,EAAE,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAMD,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAItD;AAgID,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,UAAU,GAAG,cAAc,CAwCnF;AAMD,eAAO,MAAM,kBAAkB,EAAE,WAyDhC,CAAC"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill: pipeline-aware
|
|
3
|
+
*
|
|
4
|
+
* Parses CI/CD log output (GitHub Actions, GitLab CI, generic) and produces a
|
|
5
|
+
* structured diagnosis: root cause, failing step, and a suggested remediation.
|
|
6
|
+
*
|
|
7
|
+
* Input options (ctx.graph):
|
|
8
|
+
* - `log` {string} â inject raw log content directly (for tests / piping)
|
|
9
|
+
* - `logFile` {string} â absolute path to a log file to read
|
|
10
|
+
* - `platform` {'github'|'gitlab'|'auto'} â hint for parser (default: 'auto')
|
|
11
|
+
*/
|
|
12
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
13
|
+
import { join } from 'node:path';
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// Platform detection
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
export function detectPlatform(log) {
|
|
18
|
+
if (/##\[group\]|##\[error\]|##\[warning\]|::(?:error|warning|notice|debug)(?:::|[ ,])/i.test(log))
|
|
19
|
+
return 'github';
|
|
20
|
+
if (/Running with gitlab-runner|CI_JOB_ID|GITLAB_CI/i.test(log))
|
|
21
|
+
return 'gitlab';
|
|
22
|
+
return 'generic';
|
|
23
|
+
}
|
|
24
|
+
const PATTERNS = [
|
|
25
|
+
// GitHub Actions step failure
|
|
26
|
+
{
|
|
27
|
+
pattern: /##\[error\](.+)/i,
|
|
28
|
+
category: 'build-error',
|
|
29
|
+
severity: 'critical',
|
|
30
|
+
step: (_m, line) => line,
|
|
31
|
+
suggestion: 'Check the full Actions log for the step that emitted ##[error]. Expand collapsed groups.',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
pattern: /::error (?:file=([^,]+),)?[^:]*::(.+)/i,
|
|
35
|
+
category: 'build-error',
|
|
36
|
+
severity: 'critical',
|
|
37
|
+
step: (m) => m[1] ?? 'unknown file',
|
|
38
|
+
suggestion: 'Fix the reported error in the specified file and re-run the workflow.',
|
|
39
|
+
},
|
|
40
|
+
// Test failures
|
|
41
|
+
{
|
|
42
|
+
pattern: /\b(\d+)\s+(?:test(?:s)?|spec(?:s)?)\s+failed\b/i,
|
|
43
|
+
category: 'test-failure',
|
|
44
|
+
severity: 'critical',
|
|
45
|
+
step: (_m, line) => line.trim().slice(0, 60),
|
|
46
|
+
suggestion: 'Run the test suite locally with the same Node/Python version to reproduce and fix failures.',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
pattern: /FAIL\s+([\w/.-]+\.(?:test|spec)\.[jt]sx?)/i,
|
|
50
|
+
category: 'test-failure',
|
|
51
|
+
severity: 'critical',
|
|
52
|
+
step: (m) => m[1],
|
|
53
|
+
suggestion: `Run \`npx vitest run ${'{file}'}\` locally to reproduce the test failure.`,
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
pattern: /AssertionError|expect\(.+\)\.to(?:Be|Equal|Throw)|FAILED|â/,
|
|
57
|
+
category: 'test-failure',
|
|
58
|
+
severity: 'high',
|
|
59
|
+
step: (_m, line) => line.trim().slice(0, 60),
|
|
60
|
+
suggestion: 'Inspect the failed assertion â check mocks, fixtures and async handling.',
|
|
61
|
+
},
|
|
62
|
+
// TypeScript / build errors
|
|
63
|
+
{
|
|
64
|
+
pattern: /error TS(\d+):\s*(.+)/i,
|
|
65
|
+
category: 'build-error',
|
|
66
|
+
severity: 'critical',
|
|
67
|
+
step: (m) => `TS${m[1]}`,
|
|
68
|
+
suggestion: 'Fix the TypeScript compilation error. Run `tsc --noEmit` locally for the full list.',
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
pattern: /Cannot find module '([^']+)'/i,
|
|
72
|
+
category: 'build-error',
|
|
73
|
+
severity: 'critical',
|
|
74
|
+
step: (m) => m[1],
|
|
75
|
+
suggestion: 'Run `pnpm install` or add the missing package to package.json dependencies.',
|
|
76
|
+
},
|
|
77
|
+
// Lint errors
|
|
78
|
+
{
|
|
79
|
+
pattern: /ESLint: (\d+) error/i,
|
|
80
|
+
category: 'lint-error',
|
|
81
|
+
severity: 'high',
|
|
82
|
+
step: (_m, line) => line.trim().slice(0, 60),
|
|
83
|
+
suggestion: 'Run `pnpm lint --fix` locally to auto-fix lint errors before pushing.',
|
|
84
|
+
},
|
|
85
|
+
// Permission / auth errors
|
|
86
|
+
{
|
|
87
|
+
pattern: /permission denied|EACCES|403 Forbidden|401 Unauthorized/i,
|
|
88
|
+
category: 'permission-error',
|
|
89
|
+
severity: 'critical',
|
|
90
|
+
step: (_m, line) => line.trim().slice(0, 60),
|
|
91
|
+
suggestion: 'Check repository secrets and Action permissions (Settings â Actions â Workflow permissions).',
|
|
92
|
+
},
|
|
93
|
+
// Network errors
|
|
94
|
+
{
|
|
95
|
+
pattern: /ECONNREFUSED|ETIMEDOUT|getaddrinfo ENOTFOUND|npm ERR! network/i,
|
|
96
|
+
category: 'network-error',
|
|
97
|
+
severity: 'high',
|
|
98
|
+
step: (_m, line) => line.trim().slice(0, 60),
|
|
99
|
+
suggestion: 'Transient network failure â retry the job. If persistent, check npm registry or VPN settings.',
|
|
100
|
+
},
|
|
101
|
+
// Timeout
|
|
102
|
+
{
|
|
103
|
+
pattern: /exceeded the timeout|timed out after|##\[warning\]Approaching timeout/i,
|
|
104
|
+
category: 'timeout',
|
|
105
|
+
severity: 'high',
|
|
106
|
+
step: (_m, line) => line.trim().slice(0, 60),
|
|
107
|
+
suggestion: 'Increase `timeout-minutes` in the job definition or optimise the slow step.',
|
|
108
|
+
},
|
|
109
|
+
// Exit code
|
|
110
|
+
{
|
|
111
|
+
pattern: /Process completed with exit code (\d+)/i,
|
|
112
|
+
category: 'unknown',
|
|
113
|
+
severity: 'critical',
|
|
114
|
+
step: (m) => `exit code ${m[1]}`,
|
|
115
|
+
suggestion: 'Non-zero exit code from process. Scroll up in the log to find the originating error.',
|
|
116
|
+
},
|
|
117
|
+
// GitLab-style
|
|
118
|
+
{
|
|
119
|
+
pattern: /ERROR:\s+(.+)/,
|
|
120
|
+
category: 'build-error',
|
|
121
|
+
severity: 'high',
|
|
122
|
+
step: (m) => m[1].slice(0, 60),
|
|
123
|
+
suggestion: 'Investigate the ERROR line above for the root cause.',
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
pattern: /Job failed: (.+)/i,
|
|
127
|
+
category: 'unknown',
|
|
128
|
+
severity: 'critical',
|
|
129
|
+
step: (m) => m[1].slice(0, 60),
|
|
130
|
+
suggestion: 'Check the GitLab job trace for the step that triggered the failure.',
|
|
131
|
+
},
|
|
132
|
+
];
|
|
133
|
+
// ---------------------------------------------------------------------------
|
|
134
|
+
// Core parser
|
|
135
|
+
// ---------------------------------------------------------------------------
|
|
136
|
+
export function parsePipelineLog(log, platform) {
|
|
137
|
+
const lines = log.split('\n');
|
|
138
|
+
const resolvedPlatform = platform ?? detectPlatform(log);
|
|
139
|
+
const failures = [];
|
|
140
|
+
for (let i = 0; i < lines.length; i++) {
|
|
141
|
+
const line = lines[i];
|
|
142
|
+
for (const rule of PATTERNS) {
|
|
143
|
+
const m = rule.pattern.exec(line);
|
|
144
|
+
if (!m)
|
|
145
|
+
continue;
|
|
146
|
+
// Gather surrounding context (up to 3 lines before/after)
|
|
147
|
+
const ctxStart = Math.max(0, i - 2);
|
|
148
|
+
const ctxEnd = Math.min(lines.length - 1, i + 2);
|
|
149
|
+
const context = lines.slice(ctxStart, ctxEnd + 1).join('\n');
|
|
150
|
+
const suggestion = rule.suggestion.replace('{file}', m[1] ?? 'file');
|
|
151
|
+
failures.push({
|
|
152
|
+
step: rule.step(m, line),
|
|
153
|
+
category: rule.category,
|
|
154
|
+
severity: rule.severity,
|
|
155
|
+
message: line.trim().slice(0, 120),
|
|
156
|
+
context,
|
|
157
|
+
suggestion,
|
|
158
|
+
});
|
|
159
|
+
break; // one rule match per line
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
const status = failures.length === 0 ? 'passed' : 'failed';
|
|
163
|
+
const criticals = failures.filter((f) => f.severity === 'critical').length;
|
|
164
|
+
const highs = failures.filter((f) => f.severity === 'high').length;
|
|
165
|
+
const summary = status === 'passed'
|
|
166
|
+
? 'â
No failure patterns detected'
|
|
167
|
+
: `â ${criticals} critical, ${highs} high-severity failure(s) detected`;
|
|
168
|
+
return { platform: resolvedPlatform, status, failures, totalLines: lines.length, summary };
|
|
169
|
+
}
|
|
170
|
+
// ---------------------------------------------------------------------------
|
|
171
|
+
// Skill
|
|
172
|
+
// ---------------------------------------------------------------------------
|
|
173
|
+
export const pipelineAwareSkill = {
|
|
174
|
+
id: 'pipeline-aware',
|
|
175
|
+
name: 'Pipeline Aware',
|
|
176
|
+
description: 'Parses CI/CD logs (GitHub Actions, GitLab) and produces structured failure diagnosis with root-cause suggestions',
|
|
177
|
+
version: '1.0.0',
|
|
178
|
+
enabled: false,
|
|
179
|
+
tags: ['devops', 'ci'],
|
|
180
|
+
async execute(ctx) {
|
|
181
|
+
const opts = ctx.graph ?? {};
|
|
182
|
+
let log = '';
|
|
183
|
+
if (typeof opts['log'] === 'string') {
|
|
184
|
+
log = opts['log'];
|
|
185
|
+
}
|
|
186
|
+
else if (typeof opts['logFile'] === 'string') {
|
|
187
|
+
const absPath = opts['logFile'].startsWith('/')
|
|
188
|
+
? opts['logFile']
|
|
189
|
+
: join(ctx.projectRoot, opts['logFile']);
|
|
190
|
+
if (!existsSync(absPath)) {
|
|
191
|
+
return { success: false, output: `â Log file not found: ${absPath}`, error: 'log file not found' };
|
|
192
|
+
}
|
|
193
|
+
log = readFileSync(absPath, 'utf-8');
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
return { success: false, output: 'â Provide `log` (string) or `logFile` (path) via ctx.graph', error: 'no log input' };
|
|
197
|
+
}
|
|
198
|
+
const platform = typeof opts['platform'] === 'string'
|
|
199
|
+
? opts['platform']
|
|
200
|
+
: undefined;
|
|
201
|
+
const report = parsePipelineLog(log, platform);
|
|
202
|
+
const lines = [
|
|
203
|
+
`đ Pipeline Aware â ${report.platform.toUpperCase()} (${report.totalLines} lines)`,
|
|
204
|
+
` ${report.summary}`,
|
|
205
|
+
'',
|
|
206
|
+
];
|
|
207
|
+
if (report.failures.length > 0) {
|
|
208
|
+
for (const f of report.failures.slice(0, 10)) {
|
|
209
|
+
const icon = f.severity === 'critical' ? 'â' : f.severity === 'high' ? 'â ī¸ ' : 'âšī¸ ';
|
|
210
|
+
lines.push(` ${icon} [${f.category}] ${f.step}`);
|
|
211
|
+
lines.push(` ${f.message.slice(0, 80)}`);
|
|
212
|
+
lines.push(` đĄ ${f.suggestion}`);
|
|
213
|
+
lines.push('');
|
|
214
|
+
}
|
|
215
|
+
if (report.failures.length > 10) {
|
|
216
|
+
lines.push(` âĻ and ${report.failures.length - 10} more failure(s)`);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return {
|
|
220
|
+
success: report.status !== 'failed',
|
|
221
|
+
output: lines.join('\n'),
|
|
222
|
+
data: report,
|
|
223
|
+
};
|
|
224
|
+
},
|
|
225
|
+
};
|
|
226
|
+
//# sourceMappingURL=pipeline-aware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline-aware.js","sourceRoot":"","sources":["../../src/skills/pipeline-aware.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill: refactor
|
|
3
|
+
*
|
|
4
|
+
* Detects common code smells in TypeScript source files and produces a prioritised
|
|
5
|
+
* list of refactoring suggestions. Purely static / heuristic â no AST required.
|
|
6
|
+
*
|
|
7
|
+
* Detects:
|
|
8
|
+
* - Long functions (> LONG_FUNCTION_LINES lines between opening { and matching })
|
|
9
|
+
* - Large files (> LARGE_FILE_LINES total lines)
|
|
10
|
+
* - Magic numbers (numeric literals that are not 0, 1, -1, 2, 100)
|
|
11
|
+
* - Deep nesting (indentation depth > MAX_NESTING spaces / 2)
|
|
12
|
+
* - Long parameter lists (> MAX_PARAMS parameters in a function signature)
|
|
13
|
+
* - TODO / FIXME / HACK comments
|
|
14
|
+
* - Duplicate imports (same module imported more than once)
|
|
15
|
+
*/
|
|
16
|
+
import type { SkillModule } from '../types.js';
|
|
17
|
+
export type SmellKind = 'long-function' | 'large-file' | 'magic-number' | 'deep-nesting' | 'long-param-list' | 'todo-comment' | 'duplicate-import';
|
|
18
|
+
export interface RefactorSmell {
|
|
19
|
+
file: string;
|
|
20
|
+
line: number;
|
|
21
|
+
kind: SmellKind;
|
|
22
|
+
severity: 'error' | 'warning' | 'info';
|
|
23
|
+
message: string;
|
|
24
|
+
detail?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface RefactorResult {
|
|
27
|
+
smells: RefactorSmell[];
|
|
28
|
+
filesAnalyzed: number;
|
|
29
|
+
summary: Record<SmellKind, number>;
|
|
30
|
+
}
|
|
31
|
+
export declare function detectSmells(source: string, filePath: string): RefactorSmell[];
|
|
32
|
+
export declare const refactorSkill: SkillModule;
|
|
33
|
+
//# sourceMappingURL=refactor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refactor.d.ts","sourceRoot":"","sources":["../../src/skills/refactor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EAAE,WAAW,EAA6B,MAAM,aAAa,CAAC;AAe1E,MAAM,MAAM,SAAS,GACjB,eAAe,GACf,YAAY,GACZ,cAAc,GACd,cAAc,GACd,iBAAiB,GACjB,cAAc,GACd,kBAAkB,CAAC;AAEvB,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;CACpC;AAMD,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,aAAa,EAAE,CAwI9E;AAMD,eAAO,MAAM,aAAa,EAAE,WA0D3B,CAAC"}
|