@cereworker/cerebrum 0.3.0 → 0.5.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/dist/context.d.ts +6 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +19 -0
- package/dist/context.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/provider.d.ts +10 -5
- package/dist/provider.d.ts.map +1 -1
- package/dist/provider.js +75 -34
- package/dist/provider.js.map +1 -1
- package/dist/retry.d.ts +8 -0
- package/dist/retry.d.ts.map +1 -0
- package/dist/retry.js +69 -0
- package/dist/retry.js.map +1 -0
- package/dist/tools/exec-policy.d.ts +17 -0
- package/dist/tools/exec-policy.d.ts.map +1 -0
- package/dist/tools/exec-policy.js +93 -0
- package/dist/tools/exec-policy.js.map +1 -0
- package/dist/tools/shell.d.ts +3 -0
- package/dist/tools/shell.d.ts.map +1 -1
- package/dist/tools/shell.js +19 -0
- package/dist/tools/shell.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAEhD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CAejE"}
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build the prompt for the compaction LLM call.
|
|
3
|
+
*/
|
|
4
|
+
export function buildCompactionPrompt(messages) {
|
|
5
|
+
const formatted = messages
|
|
6
|
+
.map((m) => `[${m.role}]: ${m.content}`)
|
|
7
|
+
.join('\n\n');
|
|
8
|
+
return `Summarize the following conversation, preserving:
|
|
9
|
+
- Active tasks and their current status
|
|
10
|
+
- Key decisions made
|
|
11
|
+
- Important context and facts established
|
|
12
|
+
- Any pending questions or action items
|
|
13
|
+
|
|
14
|
+
Be concise but thorough. Do not lose critical details.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
${formatted}`;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAAmB;IACvD,MAAM,SAAS,GAAG,QAAQ;SACvB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,OAAO,EAAE,CAAC;SACvC,IAAI,CAAC,MAAM,CAAC,CAAC;IAEhB,OAAO;;;;;;;;;EASP,SAAS,EAAE,CAAC;AACd,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export { CerebrumProvider } from './provider.js';
|
|
2
2
|
export type { CerebrumConfig, ProviderConfig, CerebrumRequest, StreamCallbacks } from './types.js';
|
|
3
3
|
export { createBuiltinTools, type BuiltinTools, type BuiltinToolName } from './tools/index.js';
|
|
4
|
+
export { withRetry, type RetryOptions } from './retry.js';
|
|
5
|
+
export { buildCompactionPrompt } from './context.js';
|
|
6
|
+
export { evaluateCommand, extractBinary, isSafeBinary, type ExecDecision } from './tools/exec-policy.js';
|
|
4
7
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACnG,OAAO,EAAE,kBAAkB,EAAE,KAAK,YAAY,EAAE,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACnG,OAAO,EAAE,kBAAkB,EAAE,KAAK,YAAY,EAAE,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAC/F,OAAO,EAAE,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,wBAAwB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
1
|
export { CerebrumProvider } from './provider.js';
|
|
2
2
|
export { createBuiltinTools } from './tools/index.js';
|
|
3
|
+
export { withRetry } from './retry.js';
|
|
4
|
+
export { buildCompactionPrompt } from './context.js';
|
|
5
|
+
export { evaluateCommand, extractBinary, isSafeBinary } from './tools/exec-policy.js';
|
|
3
6
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAE,kBAAkB,EAA2C,MAAM,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAE,kBAAkB,EAA2C,MAAM,kBAAkB,CAAC;AAC/F,OAAO,EAAE,SAAS,EAAqB,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,YAAY,EAAqB,MAAM,wBAAwB,CAAC"}
|
package/dist/provider.d.ts
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import type { Message } from '@cereworker/core';
|
|
2
2
|
import type { CerebrumConfig, StreamCallbacks } from './types.js';
|
|
3
|
+
import { type RetryOptions } from './retry.js';
|
|
3
4
|
export declare class CerebrumProvider {
|
|
4
5
|
private config;
|
|
5
6
|
private builtinTools;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
timeout?: number;
|
|
9
|
-
maxOutputSize?: number;
|
|
10
|
-
});
|
|
7
|
+
private retryOptions;
|
|
8
|
+
constructor(config: CerebrumConfig, shellConfig?: Partial<import('./tools/shell.js').ShellToolConfig>, retryOptions?: RetryOptions);
|
|
11
9
|
private getModel;
|
|
12
10
|
private convertMessages;
|
|
13
11
|
stream(messages: Message[], callbacks: StreamCallbacks, options?: {
|
|
@@ -18,5 +16,12 @@ export declare class CerebrumProvider {
|
|
|
18
16
|
}): Promise<void>;
|
|
19
17
|
getDefaultProvider(): string;
|
|
20
18
|
getDefaultModel(): string;
|
|
19
|
+
setProvider(provider: string): void;
|
|
20
|
+
setModel(model: string): void;
|
|
21
|
+
/**
|
|
22
|
+
* Summarize a list of messages into a concise summary via a single LLM call.
|
|
23
|
+
* Used for context window compaction.
|
|
24
|
+
*/
|
|
25
|
+
summarize(messages: Message[]): Promise<string>;
|
|
21
26
|
}
|
|
22
27
|
//# sourceMappingURL=provider.d.ts.map
|
package/dist/provider.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,KAAK,EAAE,cAAc,EAAkB,eAAe,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,KAAK,EAAE,cAAc,EAAkB,eAAe,EAAE,MAAM,YAAY,CAAC;AAElF,OAAO,EAAa,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAG1D,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,YAAY,CAAe;gBAGjC,MAAM,EAAE,cAAc,EACtB,WAAW,CAAC,EAAE,OAAO,CAAC,OAAO,kBAAkB,EAAE,eAAe,CAAC,EACjE,YAAY,CAAC,EAAE,YAAY;IAO7B,OAAO,CAAC,QAAQ;IAwChB,OAAO,CAAC,eAAe;IA2BjB,MAAM,CACV,QAAQ,EAAE,OAAO,EAAE,EACnB,SAAS,EAAE,eAAe,EAC1B,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GACxF,OAAO,CAAC,IAAI,CAAC;IA0DhB,kBAAkB,IAAI,MAAM;IAI5B,eAAe,IAAI,MAAM;IAIzB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAInC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI7B;;;OAGG;IACG,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;CAetD"}
|
package/dist/provider.js
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
|
-
import { streamText } from 'ai';
|
|
1
|
+
import { streamText, generateText } from 'ai';
|
|
2
2
|
import { createAnthropic } from '@ai-sdk/anthropic';
|
|
3
3
|
import { createOpenAI } from '@ai-sdk/openai';
|
|
4
4
|
import { createGoogleGenerativeAI } from '@ai-sdk/google';
|
|
5
5
|
import { createBuiltinTools } from './tools/index.js';
|
|
6
|
+
import { withRetry } from './retry.js';
|
|
7
|
+
import { buildCompactionPrompt } from './context.js';
|
|
6
8
|
export class CerebrumProvider {
|
|
7
9
|
config;
|
|
8
10
|
builtinTools;
|
|
9
|
-
|
|
11
|
+
retryOptions;
|
|
12
|
+
constructor(config, shellConfig, retryOptions) {
|
|
10
13
|
this.config = config;
|
|
11
14
|
this.builtinTools = createBuiltinTools(shellConfig);
|
|
15
|
+
this.retryOptions = retryOptions ?? {};
|
|
12
16
|
}
|
|
13
17
|
getModel(provider, model) {
|
|
14
18
|
const providerName = provider ?? this.config.defaultProvider;
|
|
@@ -75,41 +79,55 @@ export class CerebrumProvider {
|
|
|
75
79
|
});
|
|
76
80
|
}
|
|
77
81
|
async stream(messages, callbacks, options) {
|
|
82
|
+
// Extract system messages from the messages array for system prompt
|
|
83
|
+
const systemMessages = messages.filter((m) => m.role === 'system');
|
|
84
|
+
const nonSystemMessages = messages.filter((m) => m.role !== 'system');
|
|
78
85
|
const model = this.getModel(options?.provider, options?.model);
|
|
79
|
-
const coreMessages = this.convertMessages(
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
86
|
+
const coreMessages = this.convertMessages(nonSystemMessages);
|
|
87
|
+
// Build system prompt from explicit option + system messages
|
|
88
|
+
const systemParts = [];
|
|
89
|
+
if (options?.systemPrompt)
|
|
90
|
+
systemParts.push(options.systemPrompt);
|
|
91
|
+
for (const sm of systemMessages) {
|
|
92
|
+
systemParts.push(sm.content);
|
|
93
|
+
}
|
|
94
|
+
const systemPrompt = systemParts.length > 0 ? systemParts.join('\n\n') : undefined;
|
|
95
|
+
await withRetry(async () => {
|
|
96
|
+
try {
|
|
97
|
+
const result = streamText({
|
|
98
|
+
model,
|
|
99
|
+
messages: coreMessages,
|
|
100
|
+
tools: this.builtinTools,
|
|
101
|
+
maxSteps: options?.maxSteps ?? this.config.maxSteps,
|
|
102
|
+
temperature: this.config.temperature,
|
|
103
|
+
...(systemPrompt ? { system: systemPrompt } : {}),
|
|
104
|
+
});
|
|
105
|
+
let fullContent = '';
|
|
106
|
+
for await (const part of result.fullStream) {
|
|
107
|
+
switch (part.type) {
|
|
108
|
+
case 'text-delta':
|
|
109
|
+
fullContent += part.textDelta;
|
|
110
|
+
callbacks.onChunk(part.textDelta);
|
|
111
|
+
break;
|
|
112
|
+
case 'tool-call':
|
|
113
|
+
await callbacks.onToolCall({
|
|
114
|
+
id: part.toolCallId,
|
|
115
|
+
name: part.toolName,
|
|
116
|
+
args: part.args,
|
|
117
|
+
});
|
|
118
|
+
break;
|
|
119
|
+
case 'error':
|
|
120
|
+
callbacks.onError(part.error instanceof Error ? part.error : new Error(String(part.error)));
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
106
123
|
}
|
|
124
|
+
callbacks.onFinish(fullContent);
|
|
107
125
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
callbacks.onError(error instanceof Error ? error : new Error(String(error)));
|
|
128
|
+
throw error; // Re-throw so withRetry can catch it
|
|
129
|
+
}
|
|
130
|
+
}, this.retryOptions);
|
|
113
131
|
}
|
|
114
132
|
getDefaultProvider() {
|
|
115
133
|
return this.config.defaultProvider;
|
|
@@ -117,5 +135,28 @@ export class CerebrumProvider {
|
|
|
117
135
|
getDefaultModel() {
|
|
118
136
|
return this.config.defaultModel;
|
|
119
137
|
}
|
|
138
|
+
setProvider(provider) {
|
|
139
|
+
this.config.defaultProvider = provider;
|
|
140
|
+
}
|
|
141
|
+
setModel(model) {
|
|
142
|
+
this.config.defaultModel = model;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Summarize a list of messages into a concise summary via a single LLM call.
|
|
146
|
+
* Used for context window compaction.
|
|
147
|
+
*/
|
|
148
|
+
async summarize(messages) {
|
|
149
|
+
const model = this.getModel();
|
|
150
|
+
const prompt = buildCompactionPrompt(messages);
|
|
151
|
+
const result = await withRetry(async () => {
|
|
152
|
+
const { text } = await generateText({
|
|
153
|
+
model,
|
|
154
|
+
prompt,
|
|
155
|
+
temperature: 0.3, // Lower temperature for factual summarization
|
|
156
|
+
});
|
|
157
|
+
return text;
|
|
158
|
+
}, this.retryOptions);
|
|
159
|
+
return result;
|
|
160
|
+
}
|
|
120
161
|
}
|
|
121
162
|
//# sourceMappingURL=provider.js.map
|
package/dist/provider.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAwC,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"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"}
|
package/dist/retry.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAiDD,wBAAsB,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,CAAC,CAAC,CAmB3F"}
|
package/dist/retry.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
const DEFAULTS = {
|
|
2
|
+
maxAttempts: 3,
|
|
3
|
+
baseDelayMs: 1000,
|
|
4
|
+
maxDelayMs: 30_000,
|
|
5
|
+
jitter: true,
|
|
6
|
+
};
|
|
7
|
+
function isRetryable(error) {
|
|
8
|
+
if (!(error instanceof Error))
|
|
9
|
+
return false;
|
|
10
|
+
const msg = error.message.toLowerCase();
|
|
11
|
+
// Don't retry auth errors or bad requests
|
|
12
|
+
if (msg.includes('401') || msg.includes('unauthorized'))
|
|
13
|
+
return false;
|
|
14
|
+
if (msg.includes('400') || msg.includes('bad request'))
|
|
15
|
+
return false;
|
|
16
|
+
if (msg.includes('context length') || msg.includes('too many tokens'))
|
|
17
|
+
return false;
|
|
18
|
+
if (msg.includes('invalid_api_key') || msg.includes('authentication'))
|
|
19
|
+
return false;
|
|
20
|
+
// Retry rate limits
|
|
21
|
+
if (msg.includes('429') || msg.includes('rate limit') || msg.includes('too many requests'))
|
|
22
|
+
return true;
|
|
23
|
+
// Retry server errors
|
|
24
|
+
if (msg.includes('500') || msg.includes('502') || msg.includes('503') || msg.includes('504'))
|
|
25
|
+
return true;
|
|
26
|
+
if (msg.includes('internal server error') || msg.includes('service unavailable'))
|
|
27
|
+
return true;
|
|
28
|
+
if (msg.includes('bad gateway') || msg.includes('gateway timeout'))
|
|
29
|
+
return true;
|
|
30
|
+
// Retry network errors
|
|
31
|
+
if (msg.includes('econnreset') || msg.includes('econnrefused') || msg.includes('etimedout'))
|
|
32
|
+
return true;
|
|
33
|
+
if (msg.includes('fetch failed') || msg.includes('network') || msg.includes('socket'))
|
|
34
|
+
return true;
|
|
35
|
+
if (msg.includes('overloaded'))
|
|
36
|
+
return true;
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
function computeDelay(attempt, opts) {
|
|
40
|
+
const exponentialDelay = opts.baseDelayMs * Math.pow(2, attempt);
|
|
41
|
+
const capped = Math.min(exponentialDelay, opts.maxDelayMs);
|
|
42
|
+
if (opts.jitter) {
|
|
43
|
+
return capped * (0.5 + Math.random() * 0.5);
|
|
44
|
+
}
|
|
45
|
+
return capped;
|
|
46
|
+
}
|
|
47
|
+
function sleep(ms) {
|
|
48
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
49
|
+
}
|
|
50
|
+
export async function withRetry(fn, options) {
|
|
51
|
+
const opts = { ...DEFAULTS, ...options };
|
|
52
|
+
let lastError;
|
|
53
|
+
for (let attempt = 0; attempt < opts.maxAttempts; attempt++) {
|
|
54
|
+
try {
|
|
55
|
+
return await fn();
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
lastError = error;
|
|
59
|
+
if (attempt === opts.maxAttempts - 1)
|
|
60
|
+
break;
|
|
61
|
+
if (!isRetryable(error))
|
|
62
|
+
break;
|
|
63
|
+
const delay = computeDelay(attempt, opts);
|
|
64
|
+
await sleep(delay);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
throw lastError;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type ExecDecision = 'allow' | 'ask' | 'block';
|
|
2
|
+
/**
|
|
3
|
+
* Extract the first binary/command from a shell command string.
|
|
4
|
+
* Handles env vars, sudo, leading whitespace, pipes.
|
|
5
|
+
*/
|
|
6
|
+
export declare function extractBinary(command: string): string;
|
|
7
|
+
/**
|
|
8
|
+
* Evaluate a command and return the exec decision.
|
|
9
|
+
*
|
|
10
|
+
* - Supervised mode (autoMode=false): safe binary → allow, hard-block → block, destructive → block, else → ask
|
|
11
|
+
* - Full-auto mode (autoMode=true): safe binary → allow, hard-block → block, else → allow
|
|
12
|
+
* (Cerebellum pre-screening happens at a higher level for full-auto)
|
|
13
|
+
*/
|
|
14
|
+
export declare function evaluateCommand(command: string, autoMode: boolean): ExecDecision;
|
|
15
|
+
/** Check if a binary is in the safe list */
|
|
16
|
+
export declare function isSafeBinary(binary: string): boolean;
|
|
17
|
+
//# sourceMappingURL=exec-policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exec-policy.d.ts","sourceRoot":"","sources":["../../src/tools/exec-policy.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,KAAK,GAAG,OAAO,CAAC;AAgCrD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CA0BrD;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,YAAY,CA2BhF;AAED,4CAA4C;AAC5C,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEpD"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/** Read-only / safe binaries that auto-execute in both modes */
|
|
2
|
+
const SAFE_BINARIES = new Set([
|
|
3
|
+
'ls', 'cat', 'head', 'tail', 'grep', 'rg', 'find',
|
|
4
|
+
'wc', 'echo', 'pwd', 'whoami', 'date', 'which', 'file', 'stat', 'du', 'df',
|
|
5
|
+
'env', 'printenv', 'uname', 'hostname', 'tree', 'less', 'more', 'sort',
|
|
6
|
+
'uniq', 'diff', 'tr', 'cut', 'sed', 'awk', 'jq', 'curl', 'wget',
|
|
7
|
+
'git', 'node', 'python', 'python3', 'npm', 'pnpm', 'yarn', 'bun',
|
|
8
|
+
'tsc', 'npx', 'cargo', 'go', 'make', 'cmake',
|
|
9
|
+
]);
|
|
10
|
+
/** Hard-block patterns — blocked in ALL modes, including full-auto */
|
|
11
|
+
const HARD_BLOCK_PATTERNS = [
|
|
12
|
+
/rm\s+-[a-zA-Z]*r[a-zA-Z]*f[a-zA-Z]*\s+\/\s*$/, // rm -rf /
|
|
13
|
+
/rm\s+-[a-zA-Z]*f[a-zA-Z]*r[a-zA-Z]*\s+\/\s*$/, // rm -fr /
|
|
14
|
+
/mkfs\b/,
|
|
15
|
+
/dd\s+if=.*of=\/dev/,
|
|
16
|
+
/:()\s*\{\s*:\|:&\s*\}\s*;/, // fork bomb
|
|
17
|
+
];
|
|
18
|
+
/** Destructive patterns — blocked in supervised, Cerebellum-screened in full-auto */
|
|
19
|
+
const DESTRUCTIVE_PATTERNS = [
|
|
20
|
+
/rm\s+(-[a-zA-Z]*r|-[a-zA-Z]*f|--recursive|--force)/,
|
|
21
|
+
/chmod\s+(777|a\+[rwx])/,
|
|
22
|
+
/>\s*\/dev\/sd/,
|
|
23
|
+
/curl\b.*\|\s*(bash|sh)\b/,
|
|
24
|
+
/wget\b.*\|\s*(bash|sh)\b/,
|
|
25
|
+
/\bgit\s+push\s+.*--force\b/,
|
|
26
|
+
/\bgit\s+reset\s+--hard\b/,
|
|
27
|
+
];
|
|
28
|
+
/**
|
|
29
|
+
* Extract the first binary/command from a shell command string.
|
|
30
|
+
* Handles env vars, sudo, leading whitespace, pipes.
|
|
31
|
+
*/
|
|
32
|
+
export function extractBinary(command) {
|
|
33
|
+
const trimmed = command.trim();
|
|
34
|
+
// Handle environment variable prefixes (e.g. "FOO=bar cmd")
|
|
35
|
+
let rest = trimmed;
|
|
36
|
+
while (/^\w+=\S*\s+/.test(rest)) {
|
|
37
|
+
rest = rest.replace(/^\w+=\S*\s+/, '');
|
|
38
|
+
}
|
|
39
|
+
// Skip sudo/env/nohup prefixes
|
|
40
|
+
const prefixes = ['sudo', 'env', 'nohup', 'nice', 'time'];
|
|
41
|
+
for (const prefix of prefixes) {
|
|
42
|
+
const pattern = new RegExp(`^${prefix}\\s+`);
|
|
43
|
+
if (pattern.test(rest)) {
|
|
44
|
+
rest = rest.replace(pattern, '');
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// Extract the binary name (first word, stripping path)
|
|
48
|
+
const match = rest.match(/^(\S+)/);
|
|
49
|
+
if (!match)
|
|
50
|
+
return '';
|
|
51
|
+
const fullPath = match[1];
|
|
52
|
+
// Strip path component (e.g. /usr/bin/ls -> ls)
|
|
53
|
+
const parts = fullPath.split('/');
|
|
54
|
+
return parts[parts.length - 1];
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Evaluate a command and return the exec decision.
|
|
58
|
+
*
|
|
59
|
+
* - Supervised mode (autoMode=false): safe binary → allow, hard-block → block, destructive → block, else → ask
|
|
60
|
+
* - Full-auto mode (autoMode=true): safe binary → allow, hard-block → block, else → allow
|
|
61
|
+
* (Cerebellum pre-screening happens at a higher level for full-auto)
|
|
62
|
+
*/
|
|
63
|
+
export function evaluateCommand(command, autoMode) {
|
|
64
|
+
// Hard-block patterns are always blocked
|
|
65
|
+
for (const pattern of HARD_BLOCK_PATTERNS) {
|
|
66
|
+
if (pattern.test(command))
|
|
67
|
+
return 'block';
|
|
68
|
+
}
|
|
69
|
+
// In supervised mode, check destructive patterns before safe binary check
|
|
70
|
+
// (a safe binary like curl can still be used destructively: curl | bash)
|
|
71
|
+
if (!autoMode) {
|
|
72
|
+
for (const pattern of DESTRUCTIVE_PATTERNS) {
|
|
73
|
+
if (pattern.test(command))
|
|
74
|
+
return 'block';
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const binary = extractBinary(command);
|
|
78
|
+
// Safe binaries are allowed
|
|
79
|
+
if (SAFE_BINARIES.has(binary))
|
|
80
|
+
return 'allow';
|
|
81
|
+
if (autoMode) {
|
|
82
|
+
// Full-auto: everything not hard-blocked is allowed
|
|
83
|
+
// (Cerebellum pre-screening is handled by the caller)
|
|
84
|
+
return 'allow';
|
|
85
|
+
}
|
|
86
|
+
// Unknown command in supervised mode → ask user
|
|
87
|
+
return 'ask';
|
|
88
|
+
}
|
|
89
|
+
/** Check if a binary is in the safe list */
|
|
90
|
+
export function isSafeBinary(binary) {
|
|
91
|
+
return SAFE_BINARIES.has(binary);
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=exec-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exec-policy.js","sourceRoot":"","sources":["../../src/tools/exec-policy.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/shell.d.ts
CHANGED
|
@@ -18,6 +18,9 @@ export interface ShellToolConfig {
|
|
|
18
18
|
denyList: string[];
|
|
19
19
|
timeout: number;
|
|
20
20
|
maxOutputSize: number;
|
|
21
|
+
autoMode: boolean;
|
|
22
|
+
onApprovalRequired?: (command: string) => Promise<boolean>;
|
|
23
|
+
onBlocked?: (command: string, reason: string) => void;
|
|
21
24
|
}
|
|
22
25
|
export declare function createShellExecutor(config?: Partial<ShellToolConfig>): (args: ShellToolArgs) => Promise<string>;
|
|
23
26
|
//# sourceMappingURL=shell.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../src/tools/shell.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../src/tools/shell.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,mBAAmB;;;;;;;;;;;;EAI9B,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC;IAClB,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3D,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACvD;AAUD,wBAAgB,mBAAmB,CAAC,MAAM,GAAE,OAAO,CAAC,eAAe,CAAM,IAGpC,MAAM,aAAa,KAAG,OAAO,CAAC,MAAM,CAAC,CA2DzE"}
|
package/dist/tools/shell.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { execFile } from 'node:child_process';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
+
import { evaluateCommand } from './exec-policy.js';
|
|
3
4
|
export const shellToolParameters = z.object({
|
|
4
5
|
command: z.string().describe('The shell command to execute'),
|
|
5
6
|
cwd: z.string().optional().describe('Working directory for the command'),
|
|
@@ -10,6 +11,7 @@ const DEFAULT_CONFIG = {
|
|
|
10
11
|
denyList: ['rm -rf /'],
|
|
11
12
|
timeout: 30000,
|
|
12
13
|
maxOutputSize: 102400,
|
|
14
|
+
autoMode: false,
|
|
13
15
|
};
|
|
14
16
|
export function createShellExecutor(config = {}) {
|
|
15
17
|
const cfg = { ...DEFAULT_CONFIG, ...config };
|
|
@@ -18,11 +20,28 @@ export function createShellExecutor(config = {}) {
|
|
|
18
20
|
return 'Shell execution is disabled';
|
|
19
21
|
}
|
|
20
22
|
const { command, cwd, timeout } = args;
|
|
23
|
+
// Legacy deny list check (still active as fallback)
|
|
21
24
|
for (const denied of cfg.denyList) {
|
|
22
25
|
if (command.includes(denied)) {
|
|
26
|
+
cfg.onBlocked?.(command, `matches deny list entry "${denied}"`);
|
|
23
27
|
return `Command denied: matches deny list entry "${denied}"`;
|
|
24
28
|
}
|
|
25
29
|
}
|
|
30
|
+
// Exec policy evaluation
|
|
31
|
+
const decision = evaluateCommand(command, cfg.autoMode);
|
|
32
|
+
if (decision === 'block') {
|
|
33
|
+
const reason = cfg.autoMode
|
|
34
|
+
? 'hard-blocked for safety'
|
|
35
|
+
: 'blocked by exec policy (destructive or dangerous pattern)';
|
|
36
|
+
cfg.onBlocked?.(command, reason);
|
|
37
|
+
return `Command blocked: ${reason}`;
|
|
38
|
+
}
|
|
39
|
+
if (decision === 'ask' && cfg.onApprovalRequired) {
|
|
40
|
+
const approved = await cfg.onApprovalRequired(command);
|
|
41
|
+
if (!approved) {
|
|
42
|
+
return 'Command denied by user';
|
|
43
|
+
}
|
|
44
|
+
}
|
|
26
45
|
return new Promise((resolve) => {
|
|
27
46
|
execFile('bash', ['-c', command], {
|
|
28
47
|
cwd: cwd ?? process.cwd(),
|
package/dist/tools/shell.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shell.js","sourceRoot":"","sources":["../../src/tools/shell.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"shell.js","sourceRoot":"","sources":["../../src/tools/shell.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cereworker/cerebrum",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
"@ai-sdk/openai": "^1.2.0",
|
|
22
22
|
"@ai-sdk/google": "^1.2.0",
|
|
23
23
|
"zod": "^3.24.0",
|
|
24
|
-
"@cereworker/core": "0.
|
|
25
|
-
"@cereworker/config": "0.
|
|
24
|
+
"@cereworker/core": "0.5.0",
|
|
25
|
+
"@cereworker/config": "0.5.0"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"typescript": "^5.7.3"
|