@goobits/sherpa 1.0.1
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/dist/chunk-3CILH2TO.js +387 -0
- package/dist/chunk-3CILH2TO.js.map +7 -0
- package/dist/chunk-5NF3BSD6.js +512 -0
- package/dist/chunk-5NF3BSD6.js.map +7 -0
- package/dist/chunk-IIU6U7TE.js +307 -0
- package/dist/chunk-IIU6U7TE.js.map +7 -0
- package/dist/chunk-LQZTKH3U.js +307 -0
- package/dist/chunk-LQZTKH3U.js.map +7 -0
- package/dist/cli.d.ts +11 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +84 -0
- package/dist/cli.js.map +7 -0
- package/dist/commands/init.d.ts +7 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +333 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/post.d.ts +20 -0
- package/dist/commands/post.d.ts.map +1 -0
- package/dist/commands/post.js +183 -0
- package/dist/commands/post.js.map +1 -0
- package/dist/commands/pre.d.ts +18 -0
- package/dist/commands/pre.d.ts.map +1 -0
- package/dist/commands/pre.js +102 -0
- package/dist/commands/pre.js.map +1 -0
- package/dist/commands/status.d.ts +5 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +48 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/daemon-V2QDZTUB.js +89 -0
- package/dist/daemon-V2QDZTUB.js.map +7 -0
- package/dist/daemon.d.ts +9 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +112 -0
- package/dist/daemon.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +36 -0
- package/dist/index.js.map +7 -0
- package/dist/parser.d.ts +21 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/parser.js +152 -0
- package/dist/parser.js.map +1 -0
- package/dist/reviewer/index.js +544 -0
- package/dist/reviewer/index.js.map +7 -0
- package/dist/rules.d.ts +21 -0
- package/dist/rules.d.ts.map +1 -0
- package/dist/rules.js +165 -0
- package/dist/rules.js.map +1 -0
- package/dist/status-Q6Z4TFJZ.js +52 -0
- package/dist/status-Q6Z4TFJZ.js.map +7 -0
- package/dist/types.d.ts +69 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +13 -0
- package/dist/types.js.map +1 -0
- package/package.json +52 -0
package/dist/rules.js
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule matching engine for guard
|
|
3
|
+
*/
|
|
4
|
+
import { isPathWithinAllowed, normalizePath } from './parser.js';
|
|
5
|
+
// Cache compiled RegExp patterns to avoid recompilation on every check
|
|
6
|
+
const regexCache = new Map();
|
|
7
|
+
function getRegex(pattern) {
|
|
8
|
+
let regex = regexCache.get(pattern);
|
|
9
|
+
if (!regex) {
|
|
10
|
+
regex = new RegExp(pattern);
|
|
11
|
+
regexCache.set(pattern, regex);
|
|
12
|
+
}
|
|
13
|
+
return regex;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Check if command matches a block rule
|
|
17
|
+
*/
|
|
18
|
+
export function matchesBlockRule(cmdInfo, rule) {
|
|
19
|
+
// Check command name
|
|
20
|
+
if (rule.cmd) {
|
|
21
|
+
const cmds = Array.isArray(rule.cmd) ? rule.cmd : [rule.cmd];
|
|
22
|
+
if (!cmds.includes(cmdInfo.cmd)) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
// Check subcommand (for git, etc.)
|
|
27
|
+
if (rule.subcommand && cmdInfo.subcommand !== rule.subcommand) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
// Check flags
|
|
31
|
+
if (rule.flags) {
|
|
32
|
+
const ruleFlags = Array.isArray(rule.flags) ? rule.flags : [rule.flags];
|
|
33
|
+
const mode = rule.flagMode || 'all';
|
|
34
|
+
if (mode === 'any') {
|
|
35
|
+
const hasAnyFlag = ruleFlags.some(f => cmdInfo.flags.includes(f));
|
|
36
|
+
if (!hasAnyFlag) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
const hasAllFlags = ruleFlags.every(f => cmdInfo.flags.includes(f));
|
|
42
|
+
if (!hasAllFlags) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// Check path patterns (using normalized paths to catch traversal)
|
|
48
|
+
if (rule.pathPatterns) {
|
|
49
|
+
const patterns = Array.isArray(rule.pathPatterns)
|
|
50
|
+
? rule.pathPatterns
|
|
51
|
+
: [rule.pathPatterns];
|
|
52
|
+
const pathsToCheck = cmdInfo.paths.length > 0 ? cmdInfo.paths : cmdInfo.args;
|
|
53
|
+
if (pathsToCheck.length === 0) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
const matchesPath = pathsToCheck.some(p => {
|
|
57
|
+
const pathInfo = normalizePath(p);
|
|
58
|
+
// Check both original AND normalized path for block rules
|
|
59
|
+
return patterns.some(pattern => {
|
|
60
|
+
const regex = getRegex(pattern);
|
|
61
|
+
return regex.test(pathInfo.original) || regex.test(pathInfo.normalized);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
if (!matchesPath) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// Check arg patterns
|
|
69
|
+
if (rule.argPatterns) {
|
|
70
|
+
const patterns = Array.isArray(rule.argPatterns)
|
|
71
|
+
? rule.argPatterns
|
|
72
|
+
: [rule.argPatterns];
|
|
73
|
+
const rawStr = cmdInfo.raw.join(' ');
|
|
74
|
+
const matchesArg = patterns.some(pattern => getRegex(pattern).test(rawStr));
|
|
75
|
+
if (!matchesArg) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Check if command matches an allow rule
|
|
83
|
+
*/
|
|
84
|
+
export function matchesAllowRule(cmdInfo, rule) {
|
|
85
|
+
if (rule.cmd) {
|
|
86
|
+
const cmds = Array.isArray(rule.cmd) ? rule.cmd : [rule.cmd];
|
|
87
|
+
if (!cmds.includes(cmdInfo.cmd)) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (rule.pathPatterns) {
|
|
92
|
+
const patterns = Array.isArray(rule.pathPatterns)
|
|
93
|
+
? rule.pathPatterns
|
|
94
|
+
: [rule.pathPatterns];
|
|
95
|
+
const pathsToCheck = cmdInfo.paths.length > 0 ? cmdInfo.paths : cmdInfo.args;
|
|
96
|
+
if (pathsToCheck.length === 0) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
const matchesPath = pathsToCheck.some(p => {
|
|
100
|
+
const pathInfo = normalizePath(p);
|
|
101
|
+
return patterns.some(pattern => isPathWithinAllowed(pathInfo, pattern));
|
|
102
|
+
});
|
|
103
|
+
if (!matchesPath) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Check pipeline for dangerous pipe patterns (curl | bash)
|
|
111
|
+
*/
|
|
112
|
+
export function checkPipeline(ast, rules) {
|
|
113
|
+
if (!ast || ast.type !== 'Script') {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
for (const cmd of ast.commands || []) {
|
|
117
|
+
if (cmd.type !== 'Pipeline') {
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
const pipeCommands = (cmd.commands || [])
|
|
121
|
+
.map(c => c.name?.text)
|
|
122
|
+
.filter((t) => Boolean(t));
|
|
123
|
+
for (const rule of rules.block || []) {
|
|
124
|
+
if (!rule.pipeTo) {
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
const cmds = Array.isArray(rule.cmd) ? rule.cmd : [rule.cmd];
|
|
128
|
+
const pipes = Array.isArray(rule.pipeTo) ? rule.pipeTo : [rule.pipeTo];
|
|
129
|
+
// Find if source command exists in pipeline
|
|
130
|
+
for (let i = 0; i < pipeCommands.length; i++) {
|
|
131
|
+
if (cmds.includes(pipeCommands[i])) {
|
|
132
|
+
// Check if ANY subsequent command is a dangerous target
|
|
133
|
+
for (let j = i + 1; j < pipeCommands.length; j++) {
|
|
134
|
+
if (pipes.includes(pipeCommands[j])) {
|
|
135
|
+
return rule;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Check a command against all rules
|
|
146
|
+
*/
|
|
147
|
+
export function checkCommand(cmdInfo, rules) {
|
|
148
|
+
// First check allow rules
|
|
149
|
+
for (const rule of rules.allow || []) {
|
|
150
|
+
if (matchesAllowRule(cmdInfo, rule)) {
|
|
151
|
+
return { blocked: false, reason: `Allowed: ${rule.name}` };
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// Then check block rules
|
|
155
|
+
for (const rule of rules.block || []) {
|
|
156
|
+
if (rule.pipeTo) {
|
|
157
|
+
continue;
|
|
158
|
+
} // Handled separately
|
|
159
|
+
if (matchesBlockRule(cmdInfo, rule)) {
|
|
160
|
+
return { blocked: true, rule };
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return { blocked: false };
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=rules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rules.js","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import {
|
|
2
|
+
checkProviderStatus,
|
|
3
|
+
getAvailableProviders
|
|
4
|
+
} from "./chunk-3CILH2TO.js";
|
|
5
|
+
|
|
6
|
+
// src/commands/status.ts
|
|
7
|
+
async function runStatus() {
|
|
8
|
+
console.log("Checking LLM providers...\n");
|
|
9
|
+
const available = getAvailableProviders();
|
|
10
|
+
if (available.length === 0) {
|
|
11
|
+
console.log("No providers configured.");
|
|
12
|
+
console.log("Set CEREBRAS_API_KEY, GROQ_API_KEY, or OPENAI_API_KEY");
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
console.log(`Configured: ${available.join(", ")}
|
|
16
|
+
`);
|
|
17
|
+
const statuses = await checkProviderStatus();
|
|
18
|
+
for (const status of statuses) {
|
|
19
|
+
const icon = status.available ? "\u2713" : "\u2717";
|
|
20
|
+
console.log(`${icon} ${status.provider.toUpperCase()}`);
|
|
21
|
+
if (status.error) {
|
|
22
|
+
console.log(` Error: ${status.error}`);
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (status.limits) {
|
|
26
|
+
const l = status.limits;
|
|
27
|
+
if (l.requestsPerMinute && l.requestsRemainingMinute) {
|
|
28
|
+
const pct = Math.round(l.requestsRemainingMinute / l.requestsPerMinute * 100);
|
|
29
|
+
console.log(` Requests/min: ${l.requestsRemainingMinute.toLocaleString()}/${l.requestsPerMinute.toLocaleString()} (${pct}%)`);
|
|
30
|
+
}
|
|
31
|
+
if (l.requestsRemainingDay) {
|
|
32
|
+
const limit = l.requestsPerDay || 14400;
|
|
33
|
+
const used = limit - l.requestsRemainingDay;
|
|
34
|
+
console.log(` Requests/day: ${l.requestsRemainingDay.toLocaleString()} remaining (${used.toLocaleString()} used)`);
|
|
35
|
+
}
|
|
36
|
+
if (l.tokensPerMinute && l.tokensRemainingMinute) {
|
|
37
|
+
const pct = Math.round(l.tokensRemainingMinute / l.tokensPerMinute * 100);
|
|
38
|
+
console.log(` Tokens/min: ${l.tokensRemainingMinute.toLocaleString()}/${l.tokensPerMinute.toLocaleString()} (${pct}%)`);
|
|
39
|
+
}
|
|
40
|
+
if (l.tokensRemainingDay) {
|
|
41
|
+
const limit = l.tokensPerDay || 1e6;
|
|
42
|
+
const used = limit - l.tokensRemainingDay;
|
|
43
|
+
console.log(` Tokens/day: ${l.tokensRemainingDay.toLocaleString()} remaining (${used.toLocaleString()} used)`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
console.log("");
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export {
|
|
50
|
+
runStatus
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=status-Q6Z4TFJZ.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/commands/status.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * sherpa status - Show LLM provider status and rate limits\n */\n\nimport { checkProviderStatus, getAvailableProviders } from '@goobits/sherpa-core'\n\nexport async function runStatus(): Promise<void> {\n\tconsole.log('Checking LLM providers...\\n')\n\n\tconst available = getAvailableProviders()\n\n\tif (available.length === 0) {\n\t\tconsole.log('No providers configured.')\n\t\tconsole.log('Set CEREBRAS_API_KEY, GROQ_API_KEY, or OPENAI_API_KEY')\n\t\treturn\n\t}\n\n\tconsole.log(`Configured: ${ available.join(', ') }\\n`)\n\n\tconst statuses = await checkProviderStatus()\n\n\tfor (const status of statuses) {\n\t\tconst icon = status.available ? '\u2713' : '\u2717'\n\t\tconsole.log(`${ icon } ${ status.provider.toUpperCase() }`)\n\n\t\tif (status.error) {\n\t\t\tconsole.log(` Error: ${ status.error }`)\n\t\t\tcontinue\n\t\t}\n\n\t\tif (status.limits) {\n\t\t\tconst l = status.limits\n\n\t\t\t// Show requests\n\t\t\tif (l.requestsPerMinute && l.requestsRemainingMinute) {\n\t\t\t\tconst pct = Math.round((l.requestsRemainingMinute / l.requestsPerMinute) * 100)\n\t\t\t\tconsole.log(` Requests/min: ${ l.requestsRemainingMinute.toLocaleString() }/${ l.requestsPerMinute.toLocaleString() } (${ pct }%)`)\n\t\t\t}\n\t\t\tif (l.requestsRemainingDay) {\n\t\t\t\tconst limit = l.requestsPerDay || 14400 // Cerebras free tier default\n\t\t\t\tconst used = limit - l.requestsRemainingDay\n\t\t\t\tconsole.log(` Requests/day: ${ l.requestsRemainingDay.toLocaleString() } remaining (${ used.toLocaleString() } used)`)\n\t\t\t}\n\n\t\t\t// Show tokens\n\t\t\tif (l.tokensPerMinute && l.tokensRemainingMinute) {\n\t\t\t\tconst pct = Math.round((l.tokensRemainingMinute / l.tokensPerMinute) * 100)\n\t\t\t\tconsole.log(` Tokens/min: ${ l.tokensRemainingMinute.toLocaleString() }/${ l.tokensPerMinute.toLocaleString() } (${ pct }%)`)\n\t\t\t}\n\t\t\tif (l.tokensRemainingDay) {\n\t\t\t\tconst limit = l.tokensPerDay || 1000000 // Cerebras free tier default\n\t\t\t\tconst used = limit - l.tokensRemainingDay\n\t\t\t\tconsole.log(` Tokens/day: ${ l.tokensRemainingDay.toLocaleString() } remaining (${ used.toLocaleString() } used)`)\n\t\t\t}\n\t\t}\n\t\tconsole.log('')\n\t}\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;AAMA,eAAsB,YAA2B;AAChD,UAAQ,IAAI,6BAA6B;AAEzC,QAAM,YAAY,sBAAsB;AAExC,MAAI,UAAU,WAAW,GAAG;AAC3B,YAAQ,IAAI,0BAA0B;AACtC,YAAQ,IAAI,uDAAuD;AACnE;AAAA,EACD;AAEA,UAAQ,IAAI,eAAgB,UAAU,KAAK,IAAI,CAAE;AAAA,CAAI;AAErD,QAAM,WAAW,MAAM,oBAAoB;AAE3C,aAAW,UAAU,UAAU;AAC9B,UAAM,OAAO,OAAO,YAAY,WAAM;AACtC,YAAQ,IAAI,GAAI,IAAK,IAAK,OAAO,SAAS,YAAY,CAAE,EAAE;AAE1D,QAAI,OAAO,OAAO;AACjB,cAAQ,IAAI,YAAa,OAAO,KAAM,EAAE;AACxC;AAAA,IACD;AAEA,QAAI,OAAO,QAAQ;AAClB,YAAM,IAAI,OAAO;AAGjB,UAAI,EAAE,qBAAqB,EAAE,yBAAyB;AACrD,cAAM,MAAM,KAAK,MAAO,EAAE,0BAA0B,EAAE,oBAAqB,GAAG;AAC9E,gBAAQ,IAAI,mBAAoB,EAAE,wBAAwB,eAAe,CAAE,IAAK,EAAE,kBAAkB,eAAe,CAAE,KAAM,GAAI,IAAI;AAAA,MACpI;AACA,UAAI,EAAE,sBAAsB;AAC3B,cAAM,QAAQ,EAAE,kBAAkB;AAClC,cAAM,OAAO,QAAQ,EAAE;AACvB,gBAAQ,IAAI,mBAAoB,EAAE,qBAAqB,eAAe,CAAE,eAAgB,KAAK,eAAe,CAAE,QAAQ;AAAA,MACvH;AAGA,UAAI,EAAE,mBAAmB,EAAE,uBAAuB;AACjD,cAAM,MAAM,KAAK,MAAO,EAAE,wBAAwB,EAAE,kBAAmB,GAAG;AAC1E,gBAAQ,IAAI,iBAAkB,EAAE,sBAAsB,eAAe,CAAE,IAAK,EAAE,gBAAgB,eAAe,CAAE,KAAM,GAAI,IAAI;AAAA,MAC9H;AACA,UAAI,EAAE,oBAAoB;AACzB,cAAM,QAAQ,EAAE,gBAAgB;AAChC,cAAM,OAAO,QAAQ,EAAE;AACvB,gBAAQ,IAAI,iBAAkB,EAAE,mBAAmB,eAAe,CAAE,eAAgB,KAAK,eAAe,CAAE,QAAQ;AAAA,MACnH;AAAA,IACD;AACA,YAAQ,IAAI,EAAE;AAAA,EACf;AACD;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for guard
|
|
3
|
+
*/
|
|
4
|
+
/** Parsed command info extracted from AST */
|
|
5
|
+
export interface CommandInfo {
|
|
6
|
+
cmd: string;
|
|
7
|
+
args: string[];
|
|
8
|
+
flags: string[];
|
|
9
|
+
paths: string[];
|
|
10
|
+
raw: string[];
|
|
11
|
+
subcommand?: string;
|
|
12
|
+
subArgs?: string[];
|
|
13
|
+
}
|
|
14
|
+
/** Normalized path info for traversal detection */
|
|
15
|
+
export interface PathInfo {
|
|
16
|
+
original: string;
|
|
17
|
+
normalized: string;
|
|
18
|
+
hasTraversal: boolean;
|
|
19
|
+
isAbsolute: boolean;
|
|
20
|
+
}
|
|
21
|
+
/** Rule definition for blocking/allowing commands */
|
|
22
|
+
export interface Rule {
|
|
23
|
+
name: string;
|
|
24
|
+
cmd?: string | string[];
|
|
25
|
+
subcommand?: string;
|
|
26
|
+
flags?: string | string[];
|
|
27
|
+
flagMode?: 'all' | 'any';
|
|
28
|
+
pathPatterns?: string | string[];
|
|
29
|
+
argPatterns?: string | string[];
|
|
30
|
+
pipeTo?: string | string[];
|
|
31
|
+
reason: string;
|
|
32
|
+
}
|
|
33
|
+
/** Rules configuration */
|
|
34
|
+
export interface RulesConfig {
|
|
35
|
+
block: Rule[];
|
|
36
|
+
allow: Rule[];
|
|
37
|
+
}
|
|
38
|
+
/** Check result */
|
|
39
|
+
export interface CheckResult {
|
|
40
|
+
blocked: boolean;
|
|
41
|
+
rule?: Rule;
|
|
42
|
+
reason?: string;
|
|
43
|
+
}
|
|
44
|
+
/** Bash parser AST node types */
|
|
45
|
+
export interface ASTNode {
|
|
46
|
+
type: string;
|
|
47
|
+
commands?: ASTNode[];
|
|
48
|
+
left?: ASTNode;
|
|
49
|
+
right?: ASTNode;
|
|
50
|
+
list?: ASTNode[];
|
|
51
|
+
name?: {
|
|
52
|
+
text: string;
|
|
53
|
+
};
|
|
54
|
+
suffix?: Array<{
|
|
55
|
+
text: string;
|
|
56
|
+
}>;
|
|
57
|
+
}
|
|
58
|
+
/** Guard configuration */
|
|
59
|
+
export interface GuardConfig {
|
|
60
|
+
maxTokens: number;
|
|
61
|
+
previewTokens: number;
|
|
62
|
+
scratchDir: string;
|
|
63
|
+
maxAgeMinutes: number;
|
|
64
|
+
maxScratchSizeMB: number;
|
|
65
|
+
socketPath: string;
|
|
66
|
+
}
|
|
67
|
+
/** Default guard configuration */
|
|
68
|
+
export declare const DEFAULT_CONFIG: GuardConfig;
|
|
69
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,6CAA6C;AAC7C,MAAM,WAAW,WAAW;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,mDAAmD;AACnD,MAAM,WAAW,QAAQ;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,OAAO,CAAC;IACtB,UAAU,EAAE,OAAO,CAAC;CACpB;AAED,qDAAqD;AACrD,MAAM,WAAW,IAAI;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC1B,QAAQ,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;CACf;AAED,0BAA0B;AAC1B,MAAM,WAAW,WAAW;IAC3B,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,KAAK,EAAE,IAAI,EAAE,CAAC;CACd;AAED,mBAAmB;AACnB,MAAM,WAAW,WAAW;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,iCAAiC;AACjC,MAAM,WAAW,OAAO;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;IACrB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC;IACjB,IAAI,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACxB,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjC;AAED,0BAA0B;AAC1B,MAAM,WAAW,WAAW;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,kCAAkC;AAClC,eAAO,MAAM,cAAc,EAAE,WAO5B,CAAA"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for guard
|
|
3
|
+
*/
|
|
4
|
+
/** Default guard configuration */
|
|
5
|
+
export const DEFAULT_CONFIG = {
|
|
6
|
+
maxTokens: 2000,
|
|
7
|
+
previewTokens: 500,
|
|
8
|
+
scratchDir: '.claude/scratch',
|
|
9
|
+
maxAgeMinutes: 60,
|
|
10
|
+
maxScratchSizeMB: 50,
|
|
11
|
+
socketPath: '/tmp/mcp-guard.sock'
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAoEH,kCAAkC;AAClC,MAAM,CAAC,MAAM,cAAc,GAAgB;IAC1C,SAAS,EAAE,IAAI;IACf,aAAa,EAAE,GAAG;IAClB,UAAU,EAAE,iBAAiB;IAC7B,aAAa,EAAE,EAAE;IACjB,gBAAgB,EAAE,EAAE;IACpB,UAAU,EAAE,qBAAqB;CACjC,CAAA"}
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@goobits/sherpa",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "CLI guard for safer AI coding - blocks dangerous bash commands and manages output context",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"sherpa": "dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "dist/index.js",
|
|
10
|
+
"types": "dist/index.d.ts",
|
|
11
|
+
"files": [
|
|
12
|
+
"dist"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc --emitDeclarationOnly && node scripts/build.mjs",
|
|
16
|
+
"dev": "tsc --watch",
|
|
17
|
+
"typecheck": "tsc --noEmit",
|
|
18
|
+
"test": "vitest run",
|
|
19
|
+
"test:watch": "vitest",
|
|
20
|
+
"prepublishOnly": "npm run build && npm run test"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"claude",
|
|
24
|
+
"claude-code",
|
|
25
|
+
"mcp",
|
|
26
|
+
"ai",
|
|
27
|
+
"coding",
|
|
28
|
+
"safety",
|
|
29
|
+
"hooks",
|
|
30
|
+
"bash",
|
|
31
|
+
"guard"
|
|
32
|
+
],
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "https://github.com/goobits/sherpa.git",
|
|
37
|
+
"directory": "packages/sherpa"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
41
|
+
"bash-parser": "^0.5.0",
|
|
42
|
+
"glob": "^10.4.0",
|
|
43
|
+
"ignore": "^5.3.0",
|
|
44
|
+
"openai": "^4.77.0",
|
|
45
|
+
"tiktoken": "^1.0.0"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@goobits/sherpa-core": "workspace:*",
|
|
49
|
+
"esbuild": "^0.23.0",
|
|
50
|
+
"vitest": "^2.0.0"
|
|
51
|
+
}
|
|
52
|
+
}
|