@trikhub/linter 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/LICENSE +21 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +57 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/linter.d.ts +70 -0
- package/dist/linter.d.ts.map +1 -0
- package/dist/linter.js +275 -0
- package/dist/linter.js.map +1 -0
- package/dist/rules.d.ts +87 -0
- package/dist/rules.d.ts.map +1 -0
- package/dist/rules.js +397 -0
- package/dist/rules.js.map +1 -0
- package/package.json +57 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Muffles
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { TrikLinter } from './linter.js';
|
|
4
|
+
async function main() {
|
|
5
|
+
const args = process.argv.slice(2);
|
|
6
|
+
if (args.length === 0 || args.includes('--help') || args.includes('-h')) {
|
|
7
|
+
console.log(`
|
|
8
|
+
Usage: trik-lint <trik-path> [options]
|
|
9
|
+
|
|
10
|
+
Arguments:
|
|
11
|
+
trik-path Path to the trik directory containing manifest.json
|
|
12
|
+
|
|
13
|
+
Options:
|
|
14
|
+
--warnings-as-errors Treat warnings as errors
|
|
15
|
+
--skip <rule> Skip a specific rule (can be used multiple times)
|
|
16
|
+
--help, -h Show this help message
|
|
17
|
+
|
|
18
|
+
Rules:
|
|
19
|
+
valid-manifest Manifest must be valid JSON and match schema
|
|
20
|
+
manifest-completeness Check for recommended manifest fields
|
|
21
|
+
has-source-files Trik must have TypeScript source files
|
|
22
|
+
entry-point-exists Entry point in manifest must exist
|
|
23
|
+
no-forbidden-imports Block dangerous Node.js modules
|
|
24
|
+
no-dynamic-code Block eval() and Function constructor
|
|
25
|
+
undeclared-tool Tools used must be declared in manifest
|
|
26
|
+
no-process-env Warn on process.env access
|
|
27
|
+
`);
|
|
28
|
+
process.exit(0);
|
|
29
|
+
}
|
|
30
|
+
const trikPath = resolve(args[0]);
|
|
31
|
+
const warningsAsErrors = args.includes('--warnings-as-errors');
|
|
32
|
+
const skipRules = [];
|
|
33
|
+
for (let i = 0; i < args.length; i++) {
|
|
34
|
+
if (args[i] === '--skip' && args[i + 1]) {
|
|
35
|
+
skipRules.push(args[i + 1]);
|
|
36
|
+
i++;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const linter = new TrikLinter({
|
|
40
|
+
warningsAsErrors,
|
|
41
|
+
skipRules,
|
|
42
|
+
});
|
|
43
|
+
console.log(`Linting trik at: ${trikPath}\n`);
|
|
44
|
+
try {
|
|
45
|
+
const results = await linter.lint(trikPath);
|
|
46
|
+
console.log(linter.formatResults(results));
|
|
47
|
+
if (linter.hasErrors(results)) {
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
console.error('Error:', error instanceof Error ? error.message : error);
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
main();
|
|
57
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAEnC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACxE,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;CAoBf,CAAC,CAAC;QACC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAClC,MAAM,gBAAgB,GAAG,IAAI,CAAC,QAAQ,CAAC,sBAAsB,CAAC,CAAC;IAC/D,MAAM,SAAS,GAAa,EAAE,CAAC;IAE/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YACxC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YAC5B,CAAC,EAAE,CAAC;QACN,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC;QAC5B,gBAAgB;QAChB,SAAS;KACV,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,oBAAoB,QAAQ,IAAI,CAAC,CAAC;IAE9C,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC5C,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC;QAE3C,IAAI,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { TrikLinter, type LinterConfig } from './linter.js';
|
|
2
|
+
export { type LintResult, type LintSeverity, FORBIDDEN_IMPORTS, FORBIDDEN_CALLS, getImports, checkForbiddenImports, checkDynamicCodeExecution, checkUndeclaredTools, checkProcessEnvAccess, findToolUsage, ALLOWED_AGENT_STRING_FORMATS, schemaHasNoUnconstrainedStrings, checkNoFreeStringsInAgentData, extractTemplatePlaceholders, getSchemaFieldNames, checkTemplateFieldsExist, checkHasResponseTemplates, checkDefaultTemplateRecommended, } from './rules.js';
|
|
3
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EACL,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,iBAAiB,EACjB,eAAe,EACf,UAAU,EACV,qBAAqB,EACrB,yBAAyB,EACzB,oBAAoB,EACpB,qBAAqB,EACrB,aAAa,EAEb,4BAA4B,EAC5B,+BAA+B,EAC/B,6BAA6B,EAC7B,2BAA2B,EAC3B,mBAAmB,EACnB,wBAAwB,EACxB,yBAAyB,EACzB,+BAA+B,GAChC,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { TrikLinter } from './linter.js';
|
|
2
|
+
export { FORBIDDEN_IMPORTS, FORBIDDEN_CALLS, getImports, checkForbiddenImports, checkDynamicCodeExecution, checkUndeclaredTools, checkProcessEnvAccess, findToolUsage,
|
|
3
|
+
// V2 rules
|
|
4
|
+
ALLOWED_AGENT_STRING_FORMATS, schemaHasNoUnconstrainedStrings, checkNoFreeStringsInAgentData, extractTemplatePlaceholders, getSchemaFieldNames, checkTemplateFieldsExist, checkHasResponseTemplates, checkDefaultTemplateRecommended, } from './rules.js';
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAqB,MAAM,aAAa,CAAC;AAC5D,OAAO,EAGL,iBAAiB,EACjB,eAAe,EACf,UAAU,EACV,qBAAqB,EACrB,yBAAyB,EACzB,oBAAoB,EACpB,qBAAqB,EACrB,aAAa;AACb,WAAW;AACX,4BAA4B,EAC5B,+BAA+B,EAC/B,6BAA6B,EAC7B,2BAA2B,EAC3B,mBAAmB,EACnB,wBAAwB,EACxB,yBAAyB,EACzB,+BAA+B,GAChC,MAAM,YAAY,CAAC"}
|
package/dist/linter.d.ts
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { type LintResult } from './rules.js';
|
|
2
|
+
/**
|
|
3
|
+
* Linter configuration
|
|
4
|
+
*/
|
|
5
|
+
export interface LinterConfig {
|
|
6
|
+
/** Additional forbidden imports */
|
|
7
|
+
forbiddenImports?: string[];
|
|
8
|
+
/** Skip certain rules */
|
|
9
|
+
skipRules?: string[];
|
|
10
|
+
/** Treat warnings as errors */
|
|
11
|
+
warningsAsErrors?: boolean;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Linter for trik validation
|
|
15
|
+
*/
|
|
16
|
+
export declare class TrikLinter {
|
|
17
|
+
private config;
|
|
18
|
+
constructor(config?: LinterConfig);
|
|
19
|
+
/**
|
|
20
|
+
* Parse a TypeScript file into a source file
|
|
21
|
+
*/
|
|
22
|
+
private parseTypeScript;
|
|
23
|
+
/**
|
|
24
|
+
* Load and parse the manifest
|
|
25
|
+
*/
|
|
26
|
+
private loadManifest;
|
|
27
|
+
/**
|
|
28
|
+
* Find all TypeScript files in the trik directory
|
|
29
|
+
*/
|
|
30
|
+
private findSourceFiles;
|
|
31
|
+
/**
|
|
32
|
+
* Check if a rule should be skipped
|
|
33
|
+
*/
|
|
34
|
+
private shouldSkipRule;
|
|
35
|
+
/**
|
|
36
|
+
* Lint only the manifest (for downloaded/compiled triks without TypeScript source)
|
|
37
|
+
*
|
|
38
|
+
* This validates:
|
|
39
|
+
* - Manifest structure and required fields
|
|
40
|
+
* - Privilege separation rules (no free strings in agentData)
|
|
41
|
+
* - Template field existence
|
|
42
|
+
* - Response templates presence
|
|
43
|
+
*
|
|
44
|
+
* This does NOT validate:
|
|
45
|
+
* - Source code (forbidden imports, eval, etc.)
|
|
46
|
+
* - Entry point existence as TypeScript
|
|
47
|
+
*/
|
|
48
|
+
lintManifestOnly(trikPath: string): Promise<LintResult[]>;
|
|
49
|
+
/**
|
|
50
|
+
* Lint a trik
|
|
51
|
+
*/
|
|
52
|
+
lint(trikPath: string): Promise<LintResult[]>;
|
|
53
|
+
/**
|
|
54
|
+
* Lint manifest with privilege separation rules
|
|
55
|
+
*/
|
|
56
|
+
private lintManifest;
|
|
57
|
+
/**
|
|
58
|
+
* Check manifest has all recommended fields
|
|
59
|
+
*/
|
|
60
|
+
private checkManifestCompleteness;
|
|
61
|
+
/**
|
|
62
|
+
* Format lint results for console output
|
|
63
|
+
*/
|
|
64
|
+
formatResults(results: LintResult[]): string;
|
|
65
|
+
/**
|
|
66
|
+
* Check if lint results have any errors
|
|
67
|
+
*/
|
|
68
|
+
hasErrors(results: LintResult[]): boolean;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=linter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linter.d.ts","sourceRoot":"","sources":["../src/linter.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,KAAK,UAAU,EAUhB,MAAM,YAAY,CAAC;AAEpB;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,mCAAmC;IACnC,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,yBAAyB;IACzB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,+BAA+B;IAC/B,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;GAEG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAe;gBAEjB,MAAM,GAAE,YAAiB;IAIrC;;OAEG;IACH,OAAO,CAAC,eAAe;IAIvB;;OAEG;YACW,YAAY;IAa1B;;OAEG;YACW,eAAe;IAiB7B;;OAEG;IACH,OAAO,CAAC,cAAc;IAItB;;;;;;;;;;;;OAYG;IACG,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAsC/D;;OAEG;IACG,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAwFnD;;OAEG;IACH,OAAO,CAAC,YAAY;IA0BpB;;OAEG;IACH,OAAO,CAAC,yBAAyB;IA2CjC;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM;IAyB5C;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,OAAO;CAG1C"}
|
package/dist/linter.js
ADDED
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import ts from 'typescript';
|
|
4
|
+
import { validateManifest, } from '@trikhub/manifest';
|
|
5
|
+
import { checkForbiddenImports, checkDynamicCodeExecution, checkUndeclaredTools, checkProcessEnvAccess,
|
|
6
|
+
// Privilege separation rules
|
|
7
|
+
checkNoFreeStringsInAgentData, checkTemplateFieldsExist, checkHasResponseTemplates, checkDefaultTemplateRecommended, } from './rules.js';
|
|
8
|
+
/**
|
|
9
|
+
* Linter for trik validation
|
|
10
|
+
*/
|
|
11
|
+
export class TrikLinter {
|
|
12
|
+
config;
|
|
13
|
+
constructor(config = {}) {
|
|
14
|
+
this.config = config;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Parse a TypeScript file into a source file
|
|
18
|
+
*/
|
|
19
|
+
parseTypeScript(filePath, content) {
|
|
20
|
+
return ts.createSourceFile(filePath, content, ts.ScriptTarget.ESNext, true, ts.ScriptKind.TS);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Load and parse the manifest
|
|
24
|
+
*/
|
|
25
|
+
async loadManifest(trikPath) {
|
|
26
|
+
const manifestPath = join(trikPath, 'manifest.json');
|
|
27
|
+
const content = await readFile(manifestPath, 'utf-8');
|
|
28
|
+
const data = JSON.parse(content);
|
|
29
|
+
const validation = validateManifest(data);
|
|
30
|
+
if (!validation.valid) {
|
|
31
|
+
throw new Error(`Invalid manifest: ${validation.errors?.join(', ')}`);
|
|
32
|
+
}
|
|
33
|
+
return data;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Find all TypeScript files in the trik directory
|
|
37
|
+
*/
|
|
38
|
+
async findSourceFiles(trikPath) {
|
|
39
|
+
const fs = await import('node:fs/promises');
|
|
40
|
+
const entries = await fs.readdir(trikPath, { withFileTypes: true });
|
|
41
|
+
const tsFiles = [];
|
|
42
|
+
for (const entry of entries) {
|
|
43
|
+
if (entry.isFile() && (entry.name.endsWith('.ts') || entry.name.endsWith('.tsx'))) {
|
|
44
|
+
// Skip test files and declaration files
|
|
45
|
+
if (!entry.name.includes('.test.') && !entry.name.includes('.spec.') && !entry.name.endsWith('.d.ts')) {
|
|
46
|
+
tsFiles.push(join(trikPath, entry.name));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return tsFiles;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Check if a rule should be skipped
|
|
54
|
+
*/
|
|
55
|
+
shouldSkipRule(ruleName) {
|
|
56
|
+
return this.config.skipRules?.includes(ruleName) ?? false;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Lint only the manifest (for downloaded/compiled triks without TypeScript source)
|
|
60
|
+
*
|
|
61
|
+
* This validates:
|
|
62
|
+
* - Manifest structure and required fields
|
|
63
|
+
* - Privilege separation rules (no free strings in agentData)
|
|
64
|
+
* - Template field existence
|
|
65
|
+
* - Response templates presence
|
|
66
|
+
*
|
|
67
|
+
* This does NOT validate:
|
|
68
|
+
* - Source code (forbidden imports, eval, etc.)
|
|
69
|
+
* - Entry point existence as TypeScript
|
|
70
|
+
*/
|
|
71
|
+
async lintManifestOnly(trikPath) {
|
|
72
|
+
const results = [];
|
|
73
|
+
const manifestPath = join(trikPath, 'manifest.json');
|
|
74
|
+
// 1. Load and validate manifest
|
|
75
|
+
let manifest;
|
|
76
|
+
try {
|
|
77
|
+
manifest = await this.loadManifest(trikPath);
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
results.push({
|
|
81
|
+
rule: 'valid-manifest',
|
|
82
|
+
severity: 'error',
|
|
83
|
+
message: error instanceof Error ? error.message : 'Failed to load manifest',
|
|
84
|
+
file: manifestPath,
|
|
85
|
+
});
|
|
86
|
+
return results;
|
|
87
|
+
}
|
|
88
|
+
// 2. Apply manifest-specific rules (privilege separation)
|
|
89
|
+
results.push(...this.lintManifest(manifest, manifestPath));
|
|
90
|
+
// 3. Check manifest completeness
|
|
91
|
+
if (!this.shouldSkipRule('manifest-completeness')) {
|
|
92
|
+
results.push(...this.checkManifestCompleteness(manifest, trikPath));
|
|
93
|
+
}
|
|
94
|
+
// Apply warningsAsErrors if configured
|
|
95
|
+
if (this.config.warningsAsErrors) {
|
|
96
|
+
for (const result of results) {
|
|
97
|
+
if (result.severity === 'warning') {
|
|
98
|
+
result.severity = 'error';
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return results;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Lint a trik
|
|
106
|
+
*/
|
|
107
|
+
async lint(trikPath) {
|
|
108
|
+
const results = [];
|
|
109
|
+
const manifestPath = join(trikPath, 'manifest.json');
|
|
110
|
+
// 1. Load and validate manifest
|
|
111
|
+
let manifest;
|
|
112
|
+
try {
|
|
113
|
+
manifest = await this.loadManifest(trikPath);
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
results.push({
|
|
117
|
+
rule: 'valid-manifest',
|
|
118
|
+
severity: 'error',
|
|
119
|
+
message: error instanceof Error ? error.message : 'Failed to load manifest',
|
|
120
|
+
file: manifestPath,
|
|
121
|
+
});
|
|
122
|
+
return results;
|
|
123
|
+
}
|
|
124
|
+
// 2. Apply manifest-specific rules (privilege separation)
|
|
125
|
+
results.push(...this.lintManifest(manifest, manifestPath));
|
|
126
|
+
// 3. Check manifest completeness
|
|
127
|
+
if (!this.shouldSkipRule('manifest-completeness')) {
|
|
128
|
+
results.push(...this.checkManifestCompleteness(manifest, trikPath));
|
|
129
|
+
}
|
|
130
|
+
// 4. Find and analyze source files
|
|
131
|
+
const sourceFiles = await this.findSourceFiles(trikPath);
|
|
132
|
+
if (sourceFiles.length === 0) {
|
|
133
|
+
results.push({
|
|
134
|
+
rule: 'has-source-files',
|
|
135
|
+
severity: 'error',
|
|
136
|
+
message: 'No TypeScript source files found in trik directory',
|
|
137
|
+
file: trikPath,
|
|
138
|
+
});
|
|
139
|
+
return results;
|
|
140
|
+
}
|
|
141
|
+
// 5. Check entry point exists
|
|
142
|
+
const entryPath = join(trikPath, manifest.entry.module.replace('.js', '.ts'));
|
|
143
|
+
if (!sourceFiles.some((f) => f.endsWith(entryPath.split('/').pop().replace('.js', '.ts')))) {
|
|
144
|
+
results.push({
|
|
145
|
+
rule: 'entry-point-exists',
|
|
146
|
+
severity: 'warning',
|
|
147
|
+
message: `Entry point "${manifest.entry.module}" not found as TypeScript source`,
|
|
148
|
+
file: trikPath,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
// 6. Analyze each source file
|
|
152
|
+
for (const filePath of sourceFiles) {
|
|
153
|
+
const content = await readFile(filePath, 'utf-8');
|
|
154
|
+
const sourceFile = this.parseTypeScript(filePath, content);
|
|
155
|
+
// Check forbidden imports
|
|
156
|
+
if (!this.shouldSkipRule('no-forbidden-imports')) {
|
|
157
|
+
results.push(...checkForbiddenImports(sourceFile, this.config.forbiddenImports));
|
|
158
|
+
}
|
|
159
|
+
// Check dynamic code execution
|
|
160
|
+
if (!this.shouldSkipRule('no-dynamic-code')) {
|
|
161
|
+
results.push(...checkDynamicCodeExecution(sourceFile));
|
|
162
|
+
}
|
|
163
|
+
// Check undeclared tools
|
|
164
|
+
if (!this.shouldSkipRule('undeclared-tool')) {
|
|
165
|
+
results.push(...checkUndeclaredTools(sourceFile, manifest.capabilities.tools));
|
|
166
|
+
}
|
|
167
|
+
// Check process.env access
|
|
168
|
+
if (!this.shouldSkipRule('no-process-env')) {
|
|
169
|
+
results.push(...checkProcessEnvAccess(sourceFile));
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
// Apply warningsAsErrors if configured
|
|
173
|
+
if (this.config.warningsAsErrors) {
|
|
174
|
+
for (const result of results) {
|
|
175
|
+
if (result.severity === 'warning') {
|
|
176
|
+
result.severity = 'error';
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return results;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Lint manifest with privilege separation rules
|
|
184
|
+
*/
|
|
185
|
+
lintManifest(manifest, manifestPath) {
|
|
186
|
+
const results = [];
|
|
187
|
+
// Core security rule: no free-form strings in agentDataSchema
|
|
188
|
+
if (!this.shouldSkipRule('no-free-strings-in-agent-data')) {
|
|
189
|
+
results.push(...checkNoFreeStringsInAgentData(manifest, manifestPath));
|
|
190
|
+
}
|
|
191
|
+
// Validate template placeholders reference real fields
|
|
192
|
+
if (!this.shouldSkipRule('template-fields-exist')) {
|
|
193
|
+
results.push(...checkTemplateFieldsExist(manifest, manifestPath));
|
|
194
|
+
}
|
|
195
|
+
// Ensure actions have response templates
|
|
196
|
+
if (!this.shouldSkipRule('has-response-templates')) {
|
|
197
|
+
results.push(...checkHasResponseTemplates(manifest, manifestPath));
|
|
198
|
+
}
|
|
199
|
+
// Recommend having a default/success template
|
|
200
|
+
if (!this.shouldSkipRule('default-template-recommended')) {
|
|
201
|
+
results.push(...checkDefaultTemplateRecommended(manifest, manifestPath));
|
|
202
|
+
}
|
|
203
|
+
return results;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Check manifest has all recommended fields
|
|
207
|
+
*/
|
|
208
|
+
checkManifestCompleteness(manifest, trikPath) {
|
|
209
|
+
const results = [];
|
|
210
|
+
const manifestPath = join(trikPath, 'manifest.json');
|
|
211
|
+
if (!manifest.author) {
|
|
212
|
+
results.push({
|
|
213
|
+
rule: 'manifest-completeness',
|
|
214
|
+
severity: 'info',
|
|
215
|
+
message: 'Manifest is missing optional "author" field',
|
|
216
|
+
file: manifestPath,
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
if (!manifest.repository) {
|
|
220
|
+
results.push({
|
|
221
|
+
rule: 'manifest-completeness',
|
|
222
|
+
severity: 'info',
|
|
223
|
+
message: 'Manifest is missing optional "repository" field',
|
|
224
|
+
file: manifestPath,
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
if (!manifest.license) {
|
|
228
|
+
results.push({
|
|
229
|
+
rule: 'manifest-completeness',
|
|
230
|
+
severity: 'info',
|
|
231
|
+
message: 'Manifest is missing optional "license" field',
|
|
232
|
+
file: manifestPath,
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
if (manifest.limits.maxExecutionTimeMs > 60000) {
|
|
236
|
+
results.push({
|
|
237
|
+
rule: 'manifest-completeness',
|
|
238
|
+
severity: 'warning',
|
|
239
|
+
message: 'maxExecutionTimeMs is very high (>60s) - consider reducing',
|
|
240
|
+
file: manifestPath,
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
return results;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Format lint results for console output
|
|
247
|
+
*/
|
|
248
|
+
formatResults(results) {
|
|
249
|
+
if (results.length === 0) {
|
|
250
|
+
return '✓ No issues found';
|
|
251
|
+
}
|
|
252
|
+
const lines = [];
|
|
253
|
+
const errors = results.filter((r) => r.severity === 'error');
|
|
254
|
+
const warnings = results.filter((r) => r.severity === 'warning');
|
|
255
|
+
const infos = results.filter((r) => r.severity === 'info');
|
|
256
|
+
for (const result of results) {
|
|
257
|
+
const icon = result.severity === 'error' ? '✗' : result.severity === 'warning' ? '⚠' : 'ℹ';
|
|
258
|
+
const location = result.line ? `${result.file}:${result.line}:${result.column}` : result.file;
|
|
259
|
+
lines.push(`${icon} [${result.rule}] ${result.message}`);
|
|
260
|
+
if (location) {
|
|
261
|
+
lines.push(` at ${location}`);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
lines.push('');
|
|
265
|
+
lines.push(`${errors.length} error(s), ${warnings.length} warning(s), ${infos.length} info`);
|
|
266
|
+
return lines.join('\n');
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Check if lint results have any errors
|
|
270
|
+
*/
|
|
271
|
+
hasErrors(results) {
|
|
272
|
+
return results.some((r) => r.severity === 'error');
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
//# sourceMappingURL=linter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linter.js","sourceRoot":"","sources":["../src/linter.ts"],"names":[],"mappings":"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"}
|
package/dist/rules.d.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
/**
|
|
3
|
+
* Lint result severity
|
|
4
|
+
*/
|
|
5
|
+
export type LintSeverity = 'error' | 'warning' | 'info';
|
|
6
|
+
/**
|
|
7
|
+
* A single lint result
|
|
8
|
+
*/
|
|
9
|
+
export interface LintResult {
|
|
10
|
+
rule: string;
|
|
11
|
+
severity: LintSeverity;
|
|
12
|
+
message: string;
|
|
13
|
+
file?: string;
|
|
14
|
+
line?: number;
|
|
15
|
+
column?: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* List of forbidden Node.js core modules
|
|
19
|
+
*/
|
|
20
|
+
export declare const FORBIDDEN_IMPORTS: string[];
|
|
21
|
+
/**
|
|
22
|
+
* List of forbidden global function calls
|
|
23
|
+
*/
|
|
24
|
+
export declare const FORBIDDEN_CALLS: string[];
|
|
25
|
+
/**
|
|
26
|
+
* Extract all import specifiers from a source file
|
|
27
|
+
*/
|
|
28
|
+
export declare function getImports(sourceFile: ts.SourceFile): string[];
|
|
29
|
+
/**
|
|
30
|
+
* Check for forbidden imports
|
|
31
|
+
*/
|
|
32
|
+
export declare function checkForbiddenImports(sourceFile: ts.SourceFile, forbiddenList?: string[]): LintResult[];
|
|
33
|
+
/**
|
|
34
|
+
* Check for dynamic code execution (eval, Function constructor)
|
|
35
|
+
*/
|
|
36
|
+
export declare function checkDynamicCodeExecution(sourceFile: ts.SourceFile): LintResult[];
|
|
37
|
+
/**
|
|
38
|
+
* Find tool usages in the source file
|
|
39
|
+
* This is a heuristic - looks for common LangGraph tool patterns
|
|
40
|
+
*/
|
|
41
|
+
export declare function findToolUsage(sourceFile: ts.SourceFile): string[];
|
|
42
|
+
/**
|
|
43
|
+
* Check that all tools used are declared in manifest
|
|
44
|
+
*/
|
|
45
|
+
export declare function checkUndeclaredTools(sourceFile: ts.SourceFile, declaredTools: string[]): LintResult[];
|
|
46
|
+
/**
|
|
47
|
+
* Check for process.env access (potential secret leakage)
|
|
48
|
+
*/
|
|
49
|
+
export declare function checkProcessEnvAccess(sourceFile: ts.SourceFile): LintResult[];
|
|
50
|
+
import type { JSONSchema, TrikManifest } from '@trikhub/manifest';
|
|
51
|
+
/**
|
|
52
|
+
* Allowed string formats in agentDataSchema.
|
|
53
|
+
* These are safe because they have constrained, predictable values.
|
|
54
|
+
*/
|
|
55
|
+
export declare const ALLOWED_AGENT_STRING_FORMATS: string[];
|
|
56
|
+
/**
|
|
57
|
+
* Recursively check if a schema contains unconstrained strings.
|
|
58
|
+
* Returns array of paths where unconstrained strings are found.
|
|
59
|
+
*/
|
|
60
|
+
export declare function schemaHasNoUnconstrainedStrings(schema: JSONSchema, path?: string): string[];
|
|
61
|
+
/**
|
|
62
|
+
* Check that agentDataSchema contains no free-form strings.
|
|
63
|
+
* This is the core security rule for type-directed privilege separation.
|
|
64
|
+
*/
|
|
65
|
+
export declare function checkNoFreeStringsInAgentData(manifest: TrikManifest, manifestPath: string): LintResult[];
|
|
66
|
+
/**
|
|
67
|
+
* Extract placeholder names from template text.
|
|
68
|
+
* Placeholders use {{fieldName}} syntax.
|
|
69
|
+
*/
|
|
70
|
+
export declare function extractTemplatePlaceholders(templateText: string): string[];
|
|
71
|
+
/**
|
|
72
|
+
* Get all top-level field names from a schema
|
|
73
|
+
*/
|
|
74
|
+
export declare function getSchemaFieldNames(schema: JSONSchema): string[];
|
|
75
|
+
/**
|
|
76
|
+
* Check that all template placeholders reference fields in agentDataSchema.
|
|
77
|
+
*/
|
|
78
|
+
export declare function checkTemplateFieldsExist(manifest: TrikManifest, manifestPath: string): LintResult[];
|
|
79
|
+
/**
|
|
80
|
+
* Check that template mode V2 actions have at least one response template.
|
|
81
|
+
*/
|
|
82
|
+
export declare function checkHasResponseTemplates(manifest: TrikManifest, manifestPath: string): LintResult[];
|
|
83
|
+
/**
|
|
84
|
+
* Check that template mode V2 actions have a "default" or commonly expected template.
|
|
85
|
+
*/
|
|
86
|
+
export declare function checkDefaultTemplateRecommended(manifest: TrikManifest, manifestPath: string): LintResult[];
|
|
87
|
+
//# sourceMappingURL=rules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAExD;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,YAAY,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,eAAO,MAAM,iBAAiB,UAc7B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,UAAuB,CAAC;AAEpD;;GAEG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,GAAG,MAAM,EAAE,CAwB9D;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,EAAE,CAAC,UAAU,EACzB,aAAa,GAAE,MAAM,EAAsB,GAC1C,UAAU,EAAE,CAmBd;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,GAAG,UAAU,EAAE,CAyCjF;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,GAAG,MAAM,EAAE,CA8CjE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,EAAE,CAAC,UAAU,EACzB,aAAa,EAAE,MAAM,EAAE,GACtB,UAAU,EAAE,CAgBd;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,GAAG,UAAU,EAAE,CA8B7E;AAMD,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAElE;;;GAGG;AACH,eAAO,MAAM,4BAA4B,UAAsD,CAAC;AAEhG;;;GAGG;AACH,wBAAgB,+BAA+B,CAC7C,MAAM,EAAE,UAAU,EAClB,IAAI,GAAE,MAAe,GACpB,MAAM,EAAE,CA6CV;AA6BD;;;GAGG;AACH,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,YAAY,EACtB,YAAY,EAAE,MAAM,GACnB,UAAU,EAAE,CAwBd;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,EAAE,CAU1E;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,EAAE,CAQhE;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,YAAY,EACtB,YAAY,EAAE,MAAM,GACnB,UAAU,EAAE,CA6Bd;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,YAAY,EACtB,YAAY,EAAE,MAAM,GACnB,UAAU,EAAE,CAuBd;AAED;;GAEG;AACH,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,YAAY,EACtB,YAAY,EAAE,MAAM,GACnB,UAAU,EAAE,CAyBd"}
|
package/dist/rules.js
ADDED
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
/**
|
|
3
|
+
* List of forbidden Node.js core modules
|
|
4
|
+
*/
|
|
5
|
+
export const FORBIDDEN_IMPORTS = [
|
|
6
|
+
'fs',
|
|
7
|
+
'fs/promises',
|
|
8
|
+
'child_process',
|
|
9
|
+
'net',
|
|
10
|
+
'http',
|
|
11
|
+
'https',
|
|
12
|
+
'dgram',
|
|
13
|
+
'dns',
|
|
14
|
+
'tls',
|
|
15
|
+
'cluster',
|
|
16
|
+
'worker_threads',
|
|
17
|
+
'vm',
|
|
18
|
+
'process',
|
|
19
|
+
];
|
|
20
|
+
/**
|
|
21
|
+
* List of forbidden global function calls
|
|
22
|
+
*/
|
|
23
|
+
export const FORBIDDEN_CALLS = ['eval', 'Function'];
|
|
24
|
+
/**
|
|
25
|
+
* Extract all import specifiers from a source file
|
|
26
|
+
*/
|
|
27
|
+
export function getImports(sourceFile) {
|
|
28
|
+
const imports = [];
|
|
29
|
+
function visit(node) {
|
|
30
|
+
if (ts.isImportDeclaration(node)) {
|
|
31
|
+
const moduleSpecifier = node.moduleSpecifier;
|
|
32
|
+
if (ts.isStringLiteral(moduleSpecifier)) {
|
|
33
|
+
imports.push(moduleSpecifier.text);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// Also check for dynamic imports
|
|
37
|
+
if (ts.isCallExpression(node)) {
|
|
38
|
+
if (node.expression.kind === ts.SyntaxKind.ImportKeyword) {
|
|
39
|
+
const arg = node.arguments[0];
|
|
40
|
+
if (arg && ts.isStringLiteral(arg)) {
|
|
41
|
+
imports.push(arg.text);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
ts.forEachChild(node, visit);
|
|
46
|
+
}
|
|
47
|
+
visit(sourceFile);
|
|
48
|
+
return imports;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Check for forbidden imports
|
|
52
|
+
*/
|
|
53
|
+
export function checkForbiddenImports(sourceFile, forbiddenList = FORBIDDEN_IMPORTS) {
|
|
54
|
+
const results = [];
|
|
55
|
+
const imports = getImports(sourceFile);
|
|
56
|
+
for (const imp of imports) {
|
|
57
|
+
// Check direct matches and node: prefix
|
|
58
|
+
const normalizedImport = imp.startsWith('node:') ? imp.slice(5) : imp;
|
|
59
|
+
if (forbiddenList.includes(normalizedImport)) {
|
|
60
|
+
results.push({
|
|
61
|
+
rule: 'no-forbidden-imports',
|
|
62
|
+
severity: 'error',
|
|
63
|
+
message: `Forbidden import: "${imp}" - triks cannot use this module`,
|
|
64
|
+
file: sourceFile.fileName,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return results;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Check for dynamic code execution (eval, Function constructor)
|
|
72
|
+
*/
|
|
73
|
+
export function checkDynamicCodeExecution(sourceFile) {
|
|
74
|
+
const results = [];
|
|
75
|
+
function visit(node) {
|
|
76
|
+
// Check for eval()
|
|
77
|
+
if (ts.isCallExpression(node)) {
|
|
78
|
+
const callee = node.expression;
|
|
79
|
+
if (ts.isIdentifier(callee) && callee.text === 'eval') {
|
|
80
|
+
const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
|
81
|
+
results.push({
|
|
82
|
+
rule: 'no-dynamic-code',
|
|
83
|
+
severity: 'error',
|
|
84
|
+
message: 'Use of eval() is forbidden in triks',
|
|
85
|
+
file: sourceFile.fileName,
|
|
86
|
+
line: line + 1,
|
|
87
|
+
column: character + 1,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// Check for new Function()
|
|
92
|
+
if (ts.isNewExpression(node)) {
|
|
93
|
+
const expression = node.expression;
|
|
94
|
+
if (ts.isIdentifier(expression) && expression.text === 'Function') {
|
|
95
|
+
const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
|
96
|
+
results.push({
|
|
97
|
+
rule: 'no-dynamic-code',
|
|
98
|
+
severity: 'error',
|
|
99
|
+
message: 'Use of Function constructor is forbidden in triks',
|
|
100
|
+
file: sourceFile.fileName,
|
|
101
|
+
line: line + 1,
|
|
102
|
+
column: character + 1,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
ts.forEachChild(node, visit);
|
|
107
|
+
}
|
|
108
|
+
visit(sourceFile);
|
|
109
|
+
return results;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Find tool usages in the source file
|
|
113
|
+
* This is a heuristic - looks for common LangGraph tool patterns
|
|
114
|
+
*/
|
|
115
|
+
export function findToolUsage(sourceFile) {
|
|
116
|
+
const tools = [];
|
|
117
|
+
function visit(node) {
|
|
118
|
+
// Look for @tool decorator or tool() calls
|
|
119
|
+
if (ts.isCallExpression(node)) {
|
|
120
|
+
const callee = node.expression;
|
|
121
|
+
if (ts.isIdentifier(callee) && callee.text === 'tool') {
|
|
122
|
+
// tool("name", ...) pattern
|
|
123
|
+
const firstArg = node.arguments[0];
|
|
124
|
+
if (firstArg && ts.isStringLiteral(firstArg)) {
|
|
125
|
+
tools.push(firstArg.text);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// Look for StructuredTool class definitions
|
|
130
|
+
if (ts.isClassDeclaration(node)) {
|
|
131
|
+
const heritage = node.heritageClauses;
|
|
132
|
+
if (heritage) {
|
|
133
|
+
for (const clause of heritage) {
|
|
134
|
+
for (const type of clause.types) {
|
|
135
|
+
if (ts.isIdentifier(type.expression) && type.expression.text === 'StructuredTool') {
|
|
136
|
+
// Get the name property
|
|
137
|
+
for (const member of node.members) {
|
|
138
|
+
if (ts.isPropertyDeclaration(member)) {
|
|
139
|
+
const name = member.name;
|
|
140
|
+
if (ts.isIdentifier(name) && name.text === 'name') {
|
|
141
|
+
const initializer = member.initializer;
|
|
142
|
+
if (initializer && ts.isStringLiteral(initializer)) {
|
|
143
|
+
tools.push(initializer.text);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
ts.forEachChild(node, visit);
|
|
154
|
+
}
|
|
155
|
+
visit(sourceFile);
|
|
156
|
+
return tools;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Check that all tools used are declared in manifest
|
|
160
|
+
*/
|
|
161
|
+
export function checkUndeclaredTools(sourceFile, declaredTools) {
|
|
162
|
+
const results = [];
|
|
163
|
+
const usedTools = findToolUsage(sourceFile);
|
|
164
|
+
for (const tool of usedTools) {
|
|
165
|
+
if (!declaredTools.includes(tool)) {
|
|
166
|
+
results.push({
|
|
167
|
+
rule: 'undeclared-tool',
|
|
168
|
+
severity: 'error',
|
|
169
|
+
message: `Tool "${tool}" is used but not declared in manifest.capabilities.tools`,
|
|
170
|
+
file: sourceFile.fileName,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return results;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Check for process.env access (potential secret leakage)
|
|
178
|
+
*/
|
|
179
|
+
export function checkProcessEnvAccess(sourceFile) {
|
|
180
|
+
const results = [];
|
|
181
|
+
function visit(node) {
|
|
182
|
+
if (ts.isPropertyAccessExpression(node)) {
|
|
183
|
+
// Check for process.env
|
|
184
|
+
if (ts.isPropertyAccessExpression(node.expression) &&
|
|
185
|
+
ts.isIdentifier(node.expression.expression) &&
|
|
186
|
+
node.expression.expression.text === 'process' &&
|
|
187
|
+
ts.isIdentifier(node.expression.name) &&
|
|
188
|
+
node.expression.name.text === 'env') {
|
|
189
|
+
const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
|
190
|
+
results.push({
|
|
191
|
+
rule: 'no-process-env',
|
|
192
|
+
severity: 'warning',
|
|
193
|
+
message: 'Accessing process.env - ensure no secrets are leaked in trik output',
|
|
194
|
+
file: sourceFile.fileName,
|
|
195
|
+
line: line + 1,
|
|
196
|
+
column: character + 1,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
ts.forEachChild(node, visit);
|
|
201
|
+
}
|
|
202
|
+
visit(sourceFile);
|
|
203
|
+
return results;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Allowed string formats in agentDataSchema.
|
|
207
|
+
* These are safe because they have constrained, predictable values.
|
|
208
|
+
*/
|
|
209
|
+
export const ALLOWED_AGENT_STRING_FORMATS = ['id', 'date', 'date-time', 'uuid', 'email', 'url'];
|
|
210
|
+
/**
|
|
211
|
+
* Recursively check if a schema contains unconstrained strings.
|
|
212
|
+
* Returns array of paths where unconstrained strings are found.
|
|
213
|
+
*/
|
|
214
|
+
export function schemaHasNoUnconstrainedStrings(schema, path = 'root') {
|
|
215
|
+
const violations = [];
|
|
216
|
+
// Handle array type
|
|
217
|
+
if (Array.isArray(schema.type)) {
|
|
218
|
+
if (schema.type.includes('string')) {
|
|
219
|
+
// String is one of the allowed types - check if constrained
|
|
220
|
+
if (!isConstrainedString(schema)) {
|
|
221
|
+
violations.push(path);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
else if (schema.type === 'string') {
|
|
226
|
+
// Direct string type - must be constrained
|
|
227
|
+
if (!isConstrainedString(schema)) {
|
|
228
|
+
violations.push(path);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
// Recursively check properties
|
|
232
|
+
if (schema.properties) {
|
|
233
|
+
for (const [key, propSchema] of Object.entries(schema.properties)) {
|
|
234
|
+
violations.push(...schemaHasNoUnconstrainedStrings(propSchema, `${path}.${key}`));
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
// Recursively check array items
|
|
238
|
+
if (schema.items) {
|
|
239
|
+
violations.push(...schemaHasNoUnconstrainedStrings(schema.items, `${path}[]`));
|
|
240
|
+
}
|
|
241
|
+
// Check additionalProperties if it's a schema
|
|
242
|
+
if (schema.additionalProperties && typeof schema.additionalProperties === 'object') {
|
|
243
|
+
violations.push(...schemaHasNoUnconstrainedStrings(schema.additionalProperties, `${path}[additionalProperties]`));
|
|
244
|
+
}
|
|
245
|
+
// Check $defs
|
|
246
|
+
if (schema.$defs) {
|
|
247
|
+
for (const [key, defSchema] of Object.entries(schema.$defs)) {
|
|
248
|
+
violations.push(...schemaHasNoUnconstrainedStrings(defSchema, `${path}.$defs.${key}`));
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return violations;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Check if a string schema is properly constrained
|
|
255
|
+
*/
|
|
256
|
+
function isConstrainedString(schema) {
|
|
257
|
+
// Has enum constraint
|
|
258
|
+
if (schema.enum && Array.isArray(schema.enum) && schema.enum.length > 0) {
|
|
259
|
+
return true;
|
|
260
|
+
}
|
|
261
|
+
// Has const constraint
|
|
262
|
+
if (schema.const !== undefined) {
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
// Has pattern constraint
|
|
266
|
+
if (schema.pattern && typeof schema.pattern === 'string') {
|
|
267
|
+
return true;
|
|
268
|
+
}
|
|
269
|
+
// Has allowed format constraint
|
|
270
|
+
if (schema.format && ALLOWED_AGENT_STRING_FORMATS.includes(schema.format)) {
|
|
271
|
+
return true;
|
|
272
|
+
}
|
|
273
|
+
return false;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Check that agentDataSchema contains no free-form strings.
|
|
277
|
+
* This is the core security rule for type-directed privilege separation.
|
|
278
|
+
*/
|
|
279
|
+
export function checkNoFreeStringsInAgentData(manifest, manifestPath) {
|
|
280
|
+
const results = [];
|
|
281
|
+
for (const [actionName, action] of Object.entries(manifest.actions)) {
|
|
282
|
+
// Only check agentDataSchema for template mode actions
|
|
283
|
+
if (action.responseMode === 'template' && action.agentDataSchema) {
|
|
284
|
+
const violations = schemaHasNoUnconstrainedStrings(action.agentDataSchema, `actions.${actionName}.agentDataSchema`);
|
|
285
|
+
for (const violationPath of violations) {
|
|
286
|
+
results.push({
|
|
287
|
+
rule: 'no-free-strings-in-agent-data',
|
|
288
|
+
severity: 'error',
|
|
289
|
+
message: `Unconstrained string found at ${violationPath}. ` +
|
|
290
|
+
`Strings in agentDataSchema must have: enum, const, pattern, or format (${ALLOWED_AGENT_STRING_FORMATS.join(', ')})`,
|
|
291
|
+
file: manifestPath,
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return results;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Extract placeholder names from template text.
|
|
300
|
+
* Placeholders use {{fieldName}} syntax.
|
|
301
|
+
*/
|
|
302
|
+
export function extractTemplatePlaceholders(templateText) {
|
|
303
|
+
const regex = /\{\{(\w+)\}\}/g;
|
|
304
|
+
const placeholders = [];
|
|
305
|
+
let match;
|
|
306
|
+
while ((match = regex.exec(templateText)) !== null) {
|
|
307
|
+
placeholders.push(match[1]);
|
|
308
|
+
}
|
|
309
|
+
return placeholders;
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Get all top-level field names from a schema
|
|
313
|
+
*/
|
|
314
|
+
export function getSchemaFieldNames(schema) {
|
|
315
|
+
const fields = [];
|
|
316
|
+
if (schema.properties) {
|
|
317
|
+
fields.push(...Object.keys(schema.properties));
|
|
318
|
+
}
|
|
319
|
+
return fields;
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Check that all template placeholders reference fields in agentDataSchema.
|
|
323
|
+
*/
|
|
324
|
+
export function checkTemplateFieldsExist(manifest, manifestPath) {
|
|
325
|
+
const results = [];
|
|
326
|
+
for (const [actionName, action] of Object.entries(manifest.actions)) {
|
|
327
|
+
// Only check template fields for template mode actions with schemas and templates
|
|
328
|
+
if (action.responseMode !== 'template' || !action.agentDataSchema || !action.responseTemplates) {
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
const schemaFields = getSchemaFieldNames(action.agentDataSchema);
|
|
332
|
+
for (const [templateId, template] of Object.entries(action.responseTemplates)) {
|
|
333
|
+
const placeholders = extractTemplatePlaceholders(template.text);
|
|
334
|
+
for (const placeholder of placeholders) {
|
|
335
|
+
if (!schemaFields.includes(placeholder)) {
|
|
336
|
+
results.push({
|
|
337
|
+
rule: 'template-fields-exist',
|
|
338
|
+
severity: 'error',
|
|
339
|
+
message: `Template "${templateId}" in action "${actionName}" references field "{{${placeholder}}}" ` +
|
|
340
|
+
`which does not exist in agentDataSchema. Available fields: ${schemaFields.join(', ') || 'none'}`,
|
|
341
|
+
file: manifestPath,
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
return results;
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Check that template mode V2 actions have at least one response template.
|
|
351
|
+
*/
|
|
352
|
+
export function checkHasResponseTemplates(manifest, manifestPath) {
|
|
353
|
+
const results = [];
|
|
354
|
+
for (const [actionName, action] of Object.entries(manifest.actions)) {
|
|
355
|
+
// Only check template mode actions
|
|
356
|
+
if (action.responseMode !== 'template') {
|
|
357
|
+
continue;
|
|
358
|
+
}
|
|
359
|
+
const templateCount = action.responseTemplates ? Object.keys(action.responseTemplates).length : 0;
|
|
360
|
+
if (templateCount === 0) {
|
|
361
|
+
results.push({
|
|
362
|
+
rule: 'has-response-templates',
|
|
363
|
+
severity: 'error',
|
|
364
|
+
message: `Template mode action "${actionName}" has no response templates. ` +
|
|
365
|
+
`Template mode actions must define at least one response template.`,
|
|
366
|
+
file: manifestPath,
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
return results;
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Check that template mode V2 actions have a "default" or commonly expected template.
|
|
374
|
+
*/
|
|
375
|
+
export function checkDefaultTemplateRecommended(manifest, manifestPath) {
|
|
376
|
+
const results = [];
|
|
377
|
+
const commonTemplates = ['default', 'success', 'result'];
|
|
378
|
+
for (const [actionName, action] of Object.entries(manifest.actions)) {
|
|
379
|
+
// Only check template mode actions with templates
|
|
380
|
+
if (action.responseMode !== 'template' || !action.responseTemplates) {
|
|
381
|
+
continue;
|
|
382
|
+
}
|
|
383
|
+
const templateIds = Object.keys(action.responseTemplates);
|
|
384
|
+
const hasCommon = templateIds.some((id) => commonTemplates.includes(id));
|
|
385
|
+
if (!hasCommon && templateIds.length > 0) {
|
|
386
|
+
results.push({
|
|
387
|
+
rule: 'default-template-recommended',
|
|
388
|
+
severity: 'warning',
|
|
389
|
+
message: `Action "${actionName}" has no common template (${commonTemplates.join(', ')}). ` +
|
|
390
|
+
`Consider adding a "success" or "default" template for clarity.`,
|
|
391
|
+
file: manifestPath,
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
return results;
|
|
396
|
+
}
|
|
397
|
+
//# sourceMappingURL=rules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rules.js","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@trikhub/linter",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Linter and validator for trik manifests and handlers",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"trik-lint": "./dist/cli.js"
|
|
10
|
+
},
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"import": "./dist/index.js",
|
|
14
|
+
"types": "./dist/index.d.ts"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"README.md",
|
|
20
|
+
"LICENSE"
|
|
21
|
+
],
|
|
22
|
+
"keywords": [
|
|
23
|
+
"ai",
|
|
24
|
+
"agent",
|
|
25
|
+
"trik",
|
|
26
|
+
"linter",
|
|
27
|
+
"validator",
|
|
28
|
+
"cli",
|
|
29
|
+
"typescript",
|
|
30
|
+
"trikhub"
|
|
31
|
+
],
|
|
32
|
+
"author": "Muffles",
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "git+https://github.com/Muffles/trikhub.git",
|
|
37
|
+
"directory": "packages/trik-linter"
|
|
38
|
+
},
|
|
39
|
+
"bugs": {
|
|
40
|
+
"url": "https://github.com/Muffles/trikhub/issues"
|
|
41
|
+
},
|
|
42
|
+
"homepage": "https://github.com/Muffles/trikhub/tree/main/packages/trik-linter#readme",
|
|
43
|
+
"publishConfig": {
|
|
44
|
+
"access": "public"
|
|
45
|
+
},
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": ">=18.0.0"
|
|
48
|
+
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"typescript": "^5.5.0",
|
|
51
|
+
"@trikhub/manifest": "0.1.0"
|
|
52
|
+
},
|
|
53
|
+
"scripts": {
|
|
54
|
+
"build": "tsc",
|
|
55
|
+
"clean": "rm -rf dist *.tsbuildinfo"
|
|
56
|
+
}
|
|
57
|
+
}
|