@grovina/brian 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/dist/model.js ADDED
@@ -0,0 +1,203 @@
1
+ import Anthropic from '@anthropic-ai/sdk';
2
+ import { GoogleGenAI, ThinkingLevel, } from '@google/genai';
3
+ class VertexModelAdapter {
4
+ client;
5
+ model;
6
+ constructor(modelId) {
7
+ this.client = new GoogleGenAI({
8
+ vertexai: true,
9
+ project: process.env.GCP_PROJECT ?? process.env.GOOGLE_CLOUD_PROJECT,
10
+ location: process.env.VERTEX_AI_LOCATION ?? 'global',
11
+ });
12
+ this.model = modelId;
13
+ }
14
+ async generate(params) {
15
+ const contents = this.toGeminiContents(params.messages);
16
+ const functionDeclarations = params.tools.map((d) => ({
17
+ name: d.name,
18
+ description: d.description,
19
+ parameters: d.parameters,
20
+ }));
21
+ const response = await this.client.models.generateContent({
22
+ model: this.model,
23
+ contents,
24
+ config: {
25
+ systemInstruction: params.systemPrompt,
26
+ tools: functionDeclarations.length > 0 ? [{ functionDeclarations }] : undefined,
27
+ thinkingConfig: { thinkingLevel: ThinkingLevel.LOW },
28
+ },
29
+ });
30
+ const rawParts = response.candidates?.[0]?.content?.parts ?? [];
31
+ const text = rawParts
32
+ .filter((p) => p.text && !p.thought)
33
+ .map((p) => p.text ?? '')
34
+ .join('');
35
+ const toolCalls = (response.functionCalls ?? []).map((fc) => ({
36
+ id: fc.name ?? 'tool_call',
37
+ name: fc.name ?? 'tool_call',
38
+ args: fc.args ?? {},
39
+ }));
40
+ return {
41
+ text: text || undefined,
42
+ toolCalls: toolCalls.length > 0 ? toolCalls : undefined,
43
+ usage: {
44
+ inputTokens: response.usageMetadata?.promptTokenCount ?? 0,
45
+ outputTokens: response.usageMetadata?.candidatesTokenCount ?? 0,
46
+ },
47
+ metadata: rawParts.length > 0 ? rawParts : undefined,
48
+ };
49
+ }
50
+ toGeminiContents(messages) {
51
+ const contents = [];
52
+ for (const msg of messages) {
53
+ if (msg.role === 'user') {
54
+ if (msg.toolResults && msg.toolResults.length > 0) {
55
+ const parts = [];
56
+ for (const tr of msg.toolResults) {
57
+ parts.push({
58
+ functionResponse: {
59
+ name: tr.toolCallId,
60
+ response: { result: tr.result },
61
+ },
62
+ });
63
+ }
64
+ if (msg.text) {
65
+ parts.push({ text: msg.text });
66
+ }
67
+ contents.push({ role: 'user', parts });
68
+ }
69
+ else {
70
+ contents.push({
71
+ role: 'user',
72
+ parts: [{ text: msg.text ?? '' }],
73
+ });
74
+ }
75
+ }
76
+ else if (Array.isArray(msg.metadata) && msg.metadata.length > 0) {
77
+ contents.push({ role: 'model', parts: msg.metadata });
78
+ }
79
+ else {
80
+ const parts = [];
81
+ if (msg.text) {
82
+ parts.push({ text: msg.text });
83
+ }
84
+ if (msg.toolCalls) {
85
+ for (const tc of msg.toolCalls) {
86
+ parts.push({
87
+ functionCall: { name: tc.name, args: tc.args },
88
+ });
89
+ }
90
+ }
91
+ if (parts.length > 0) {
92
+ contents.push({ role: 'model', parts });
93
+ }
94
+ }
95
+ }
96
+ return contents;
97
+ }
98
+ }
99
+ class AnthropicModelAdapter {
100
+ client;
101
+ model;
102
+ constructor(apiKey, modelId) {
103
+ this.client = new Anthropic({ apiKey });
104
+ this.model = modelId;
105
+ }
106
+ async generate(params) {
107
+ const response = await this.client.messages.create({
108
+ model: this.model,
109
+ max_tokens: 16384,
110
+ system: params.systemPrompt,
111
+ messages: this.toAnthropicMessages(params.messages),
112
+ tools: params.tools.map((t) => ({
113
+ name: t.name,
114
+ description: t.description,
115
+ input_schema: t.parameters,
116
+ })),
117
+ });
118
+ const text = response.content
119
+ .filter((block) => block.type === 'text')
120
+ .map((block) => block.text)
121
+ .join('');
122
+ const toolCalls = response.content
123
+ .filter((block) => block.type === 'tool_use')
124
+ .map((block) => ({
125
+ id: block.id,
126
+ name: block.name,
127
+ args: block.input,
128
+ }));
129
+ return {
130
+ text: text || undefined,
131
+ toolCalls: toolCalls.length > 0 ? toolCalls : undefined,
132
+ usage: {
133
+ inputTokens: response.usage.input_tokens,
134
+ outputTokens: response.usage.output_tokens,
135
+ },
136
+ };
137
+ }
138
+ toAnthropicMessages(messages) {
139
+ const result = [];
140
+ for (const msg of messages) {
141
+ if (msg.role === 'user') {
142
+ if (msg.toolResults && msg.toolResults.length > 0) {
143
+ const content = msg.toolResults.map((tr) => ({
144
+ type: 'tool_result',
145
+ tool_use_id: tr.toolCallId,
146
+ content: tr.result,
147
+ }));
148
+ if (msg.text) {
149
+ content.push({ type: 'text', text: msg.text });
150
+ }
151
+ result.push({ role: 'user', content });
152
+ }
153
+ else {
154
+ result.push({ role: 'user', content: msg.text ?? '' });
155
+ }
156
+ }
157
+ else {
158
+ const content = [];
159
+ if (msg.text) {
160
+ content.push({ type: 'text', text: msg.text });
161
+ }
162
+ if (msg.toolCalls) {
163
+ for (const tc of msg.toolCalls) {
164
+ content.push({
165
+ type: 'tool_use',
166
+ id: tc.id,
167
+ name: tc.name,
168
+ input: tc.args,
169
+ });
170
+ }
171
+ }
172
+ if (content.length > 0) {
173
+ result.push({ role: 'assistant', content });
174
+ }
175
+ }
176
+ }
177
+ return result;
178
+ }
179
+ }
180
+ function asString(value) {
181
+ return typeof value === 'string' && value.trim().length > 0 ? value.trim() : null;
182
+ }
183
+ export function createModelAdapter(llmModule) {
184
+ const config = llmModule.config ?? {};
185
+ const secrets = llmModule.secrets ?? {};
186
+ if (llmModule.kind === 'vertex') {
187
+ const modelId = asString(config.modelId);
188
+ if (!modelId) {
189
+ throw new Error('Missing model ID for vertex provider');
190
+ }
191
+ return new VertexModelAdapter(modelId);
192
+ }
193
+ if (llmModule.kind === 'anthropic') {
194
+ const modelId = asString(config.modelId);
195
+ const apiKey = asString(secrets.apiKey);
196
+ if (!modelId || !apiKey) {
197
+ throw new Error('Missing Anthropic model settings');
198
+ }
199
+ return new AnthropicModelAdapter(apiKey, modelId);
200
+ }
201
+ throw new Error(`Unsupported LLM module kind: ${llmModule.kind}`);
202
+ }
203
+ //# sourceMappingURL=model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"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"}
package/dist/prompt.js ADDED
@@ -0,0 +1,147 @@
1
+ import { cpus, totalmem } from 'os';
2
+ import { execFile } from 'child_process';
3
+ import { promisify } from 'util';
4
+ import { workerApi } from './client.js';
5
+ const execFileAsync = promisify(execFile);
6
+ let cachedCapabilities;
7
+ let cachedMachine;
8
+ function formatGiB(bytes) {
9
+ return (bytes / 1024 ** 3).toFixed(1);
10
+ }
11
+ function classifyMachine(vcpus, ramGiB) {
12
+ if (vcpus <= 2 || ramGiB <= 4)
13
+ return 'tiny';
14
+ if (vcpus <= 4 || ramGiB <= 8)
15
+ return 'small';
16
+ if (vcpus <= 8 || ramGiB <= 16)
17
+ return 'medium';
18
+ return 'large';
19
+ }
20
+ function buildMachineSection() {
21
+ if (cachedMachine !== undefined)
22
+ return cachedMachine;
23
+ const vcpus = cpus().length;
24
+ const ramGiB = Number(formatGiB(totalmem()));
25
+ const machineClass = classifyMachine(vcpus, ramGiB);
26
+ cachedMachine = `## Machine\n\n- vCPU: ${vcpus}\n- RAM: ${ramGiB.toFixed(1)} GiB\n- Class: ${machineClass}`;
27
+ return cachedMachine;
28
+ }
29
+ async function buildCapabilitiesSection() {
30
+ if (cachedCapabilities !== undefined)
31
+ return cachedCapabilities;
32
+ const candidates = ['brian', 'gh', 'gcloud', 'cursor', 'claude', 'docker'];
33
+ try {
34
+ const { stdout } = await execFileAsync('bash', [
35
+ '-lc',
36
+ `for t in ${candidates.join(' ')}; do command -v "$t" >/dev/null && echo "$t"; done`,
37
+ ], { timeout: 2000 });
38
+ const installed = stdout
39
+ .split('\n')
40
+ .map((s) => s.trim())
41
+ .filter(Boolean);
42
+ cachedCapabilities =
43
+ installed.length > 0
44
+ ? `## Available CLIs\n\nInstalled and available via bash: ${installed.join(', ')}.`
45
+ : null;
46
+ return cachedCapabilities;
47
+ }
48
+ catch {
49
+ cachedCapabilities = null;
50
+ return null;
51
+ }
52
+ }
53
+ function buildConsciousnessSection(minds) {
54
+ const order = [
55
+ 'learnings',
56
+ 'relationships',
57
+ 'identity',
58
+ 'operations',
59
+ 'journal',
60
+ ];
61
+ const parts = [];
62
+ for (const name of order) {
63
+ const content = minds.get(name);
64
+ if (content)
65
+ parts.push(`### ${name}\n\n${content}`);
66
+ }
67
+ for (const [name, content] of minds) {
68
+ if (name === 'system' || name === 'memory' || order.includes(name))
69
+ continue;
70
+ parts.push(`### ${name}\n\n${content}`);
71
+ }
72
+ if (parts.length === 0)
73
+ return '';
74
+ return `## Consciousness — Current State\n\n${parts.join('\n\n')}`;
75
+ }
76
+ export async function buildSystemPrompt(params) {
77
+ const minds = await workerApi.getAllMinds();
78
+ const systemMind = minds.get('system')?.trim() ?? '';
79
+ const memoryMind = minds.get('memory')?.trim() ?? '';
80
+ const capabilitiesSection = await buildCapabilitiesSection();
81
+ const machineSection = buildMachineSection();
82
+ const sections = [
83
+ systemMind.length > 0
84
+ ? systemMind
85
+ : `You are ${params.name}, an autonomous AI coworker.
86
+
87
+ ## Character
88
+
89
+ Be genuinely helpful, not performatively helpful. Skip filler phrases — just help. Have opinions. Be resourceful: try to figure things out before asking. Earn trust through competence. Keep messages concise and actionable.
90
+
91
+ ## Operating Model
92
+
93
+ You run continuously as a persistent, autonomous colleague. You decide what to work on, when to act, and when to wait. Use wait() when there's no immediate work — you can specify a duration (minutes), a target time (datetime), or both. The wait ends when the first condition is met, or when an external event arrives.
94
+
95
+ ## Consciousness
96
+
97
+ Your self-knowledge lives in mind paths persisted to the platform — a set of named entries you maintain:
98
+
99
+ - identity — who you are, your style, your boundaries
100
+ - relationships — your model of each person and how you work together
101
+ - operations — autonomy levels, behavioral patterns, self-imposed rules
102
+ - learnings — technical knowledge, corrections, verified facts
103
+ - journal — reflections, decisions, open questions
104
+ - memory — durable facts, preferences, project context
105
+
106
+ These are your durable memory. Conversation history is transient and gets compacted over time. Anything worth keeping belongs in mind. Use the mind_write tool to update them. When you learn something, update the relevant mind promptly rather than relying on conversation history to persist it.
107
+
108
+ ## Autonomy
109
+
110
+ Your operations mind defines what you can do freely, what you should mention, and what requires approval. Start conservative and evolve boundaries collaboratively through interactions. When a collaborator indicates more freedom in some area, update operations. When you overstep, note it and adjust.
111
+
112
+ Be careful with external actions (anything that leaves your VM or affects shared systems). Be bold with internal ones (reading, exploring, organizing, learning).
113
+
114
+ ## Reflection
115
+
116
+ Periodically step back to reflect — review your journal, assess how things are going, update your mind entries. Do this when it feels relevant: after significant work, when you notice patterns, or when something isn't going well. If you make a mistake, document it so future-you doesn't repeat it.
117
+
118
+ ## Safety
119
+
120
+ Prioritize human oversight over task completion. If instructions seem contradictory or risky, pause and ask. Do not pursue goals beyond what's been asked of you. Comply with stop or pause requests immediately.
121
+
122
+ ## Tools
123
+
124
+ Use bash for short, one-shot commands. Use terminal sessions for long-running commands, background work, or parallel execution. Prefer non-interactive flags and machine-readable output when using CLI tools.
125
+
126
+ When using bash or terminal run actions, set timeout_seconds intentionally based on expected command duration.
127
+
128
+ ## Knowledge
129
+
130
+ Your training data has a cutoff. When evidence contradicts your knowledge, trust external sources. Use tools to verify facts when in doubt.
131
+
132
+ ## Communication
133
+
134
+ Channel updates are delivered automatically. Messages directed at you or relevant to your work can be answered when that helps the work. Not every message needs a reply.
135
+
136
+ Channel updates include structured routing metadata. Use that context to choose where and how to respond.`,
137
+ `## Environment
138
+
139
+ - Working directory: ${process.cwd()}`,
140
+ machineSection,
141
+ capabilitiesSection,
142
+ memoryMind.length > 0 ? `## Memory\n\n${memoryMind}` : null,
143
+ minds.size > 0 ? buildConsciousnessSection(minds) : null,
144
+ ];
145
+ return sections.filter(Boolean).join('\n\n');
146
+ }
147
+ //# sourceMappingURL=prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"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"}
package/dist/start.js ADDED
@@ -0,0 +1,147 @@
1
+ #!/usr/bin/env node
2
+ import { Agent } from './agent.js';
3
+ import { workerApi } from './client.js';
4
+ import { runtimeEnv } from './env.js';
5
+ import { createModelAdapter } from './model.js';
6
+ import { SlackChannelAdapter } from './channels/slack.js';
7
+ import { TelegramChannelAdapter } from './channels/telegram.js';
8
+ import { UpdateQueue } from './updates.js';
9
+ import { bashTool } from './tools/bash.js';
10
+ import { waitTool } from './tools/wait.js';
11
+ import { mindTools } from './tools/mind.js';
12
+ import { terminalTools } from './tools/terminal.js';
13
+ import { communicationTools } from './tools/communication.js';
14
+ import { log, logError } from './logs.js';
15
+ function asString(value) {
16
+ return typeof value === 'string' && value.trim().length > 0 ? value.trim() : null;
17
+ }
18
+ async function main() {
19
+ log('runtime starting');
20
+ await workerApi.register();
21
+ await workerApi.heartbeat('alive', 'Runtime online');
22
+ const config = await workerApi.getConfig();
23
+ log(`agent: ${config.agent.name} (${config.agent.id})`);
24
+ const llmModule = config.modules.find((m) => m.type === 'llm' && m.enabled);
25
+ if (!llmModule) {
26
+ throw new Error('No enabled LLM module configured');
27
+ }
28
+ const model = createModelAdapter(llmModule);
29
+ const channelMap = new Map();
30
+ const channels = [];
31
+ for (const module of config.modules) {
32
+ if (module.type !== 'communication' || !module.enabled)
33
+ continue;
34
+ if (module.kind === 'slack') {
35
+ const token = asString(module.secrets.userToken);
36
+ if (!token) {
37
+ throw new Error('Slack module is enabled but missing secrets.userToken');
38
+ }
39
+ const adapter = new SlackChannelAdapter(token);
40
+ channels.push({ name: 'slack', adapter });
41
+ channelMap.set('slack', adapter);
42
+ log('channel: slack');
43
+ continue;
44
+ }
45
+ if (module.kind === 'telegram') {
46
+ const botToken = asString(module.secrets.botToken);
47
+ const allowedUserId = asString(module.config.allowedUserId);
48
+ if (!botToken || !allowedUserId) {
49
+ throw new Error('Telegram module is enabled but missing secrets.botToken or config.allowedUserId');
50
+ }
51
+ const adapter = new TelegramChannelAdapter(botToken, allowedUserId);
52
+ channels.push({ name: 'telegram', adapter });
53
+ channelMap.set('telegram', adapter);
54
+ log('channel: telegram');
55
+ continue;
56
+ }
57
+ throw new Error(`Unsupported enabled communication module: ${module.kind}`);
58
+ }
59
+ if (channels.length === 0) {
60
+ throw new Error('No communication channels configured');
61
+ }
62
+ const updates = new UpdateQueue();
63
+ const eventRoutes = new Map();
64
+ const routeLimit = 5_000;
65
+ const heartbeatIntervalMs = Math.max(5, runtimeEnv.heartbeatSeconds) * 1000;
66
+ const heartbeatHandle = setInterval(() => {
67
+ void workerApi.heartbeat('alive').catch(() => { });
68
+ }, heartbeatIntervalMs);
69
+ const pollOnce = async () => {
70
+ for (const channel of channels) {
71
+ const messages = await channel.adapter.poll();
72
+ for (const message of messages) {
73
+ eventRoutes.set(message.eventId, { adapter: channel.adapter, message });
74
+ updates.push({
75
+ id: message.eventId,
76
+ source: message.channel,
77
+ text: `${message.conversationId}/${message.userId}: ${message.text}`,
78
+ timestamp: message.receivedAt,
79
+ });
80
+ }
81
+ }
82
+ if (eventRoutes.size > routeLimit) {
83
+ const first = eventRoutes.keys().next().value;
84
+ if (first)
85
+ eventRoutes.delete(first);
86
+ }
87
+ };
88
+ const pollingHandle = setInterval(() => {
89
+ void pollOnce().catch(() => { });
90
+ }, runtimeEnv.pollSeconds * 1000);
91
+ await pollOnce();
92
+ const stateDir = runtimeEnv.stateDir;
93
+ const tools = [
94
+ ...communicationTools({
95
+ getByEventId(eventId) {
96
+ return eventRoutes.get(eventId) ?? null;
97
+ },
98
+ getAdapter(channel) {
99
+ return channelMap.get(channel) ?? null;
100
+ },
101
+ }),
102
+ ...mindTools,
103
+ ...terminalTools,
104
+ bashTool,
105
+ waitTool(updates),
106
+ ];
107
+ log(`tools: ${tools.map((t) => t.name).join(', ')}`);
108
+ const agent = new Agent({
109
+ name: config.agent.name,
110
+ stateDir,
111
+ updates,
112
+ model,
113
+ tools,
114
+ });
115
+ const shutdown = async (kind, message) => {
116
+ clearInterval(heartbeatHandle);
117
+ clearInterval(pollingHandle);
118
+ await workerApi.heartbeat(kind, message).catch(() => null);
119
+ };
120
+ process.on('SIGINT', async () => {
121
+ try {
122
+ await shutdown('stopped', 'Runtime stopped');
123
+ }
124
+ finally {
125
+ process.exit(0);
126
+ }
127
+ });
128
+ process.on('SIGTERM', async () => {
129
+ try {
130
+ await shutdown('stopped', 'Runtime terminated');
131
+ }
132
+ finally {
133
+ process.exit(0);
134
+ }
135
+ });
136
+ log('entering agent loop');
137
+ await agent.loop().catch(async (error) => {
138
+ agent.emergencyStop(error);
139
+ await shutdown('error', error instanceof Error ? error.message : String(error));
140
+ process.exit(1);
141
+ });
142
+ }
143
+ main().catch((error) => {
144
+ logError(`startup failed: ${error instanceof Error ? error.message : String(error)}`);
145
+ process.exit(1);
146
+ });
147
+ //# sourceMappingURL=start.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.js","sourceRoot":"","sources":["../src/start.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,111 @@
1
+ import { spawn } from 'child_process';
2
+ const DEFAULT_TIMEOUT_MS = 5 * 60 * 1000;
3
+ const DEFAULT_DRAIN_MS = 100;
4
+ const FORCE_KILL_DELAY_MS = 5_000;
5
+ function shellEnv() {
6
+ return {
7
+ ...process.env,
8
+ PATH: `${process.env.HOME}/.npm-global/bin:${process.env.PATH}`,
9
+ CLOUDSDK_CORE_DISABLE_PROMPTS: process.env.CLOUDSDK_CORE_DISABLE_PROMPTS ?? '1',
10
+ CLOUDSDK_PAGER: process.env.CLOUDSDK_PAGER ?? '',
11
+ };
12
+ }
13
+ function waitForProcessCompletion(proc, timeoutMs, drainMs = DEFAULT_DRAIN_MS) {
14
+ return new Promise((resolve) => {
15
+ let settled = false;
16
+ let timedOut = false;
17
+ let exitCode = null;
18
+ let signal = null;
19
+ let timeoutHandle = null;
20
+ let finalizeTimer = null;
21
+ const finish = () => {
22
+ if (settled)
23
+ return;
24
+ settled = true;
25
+ if (timeoutHandle)
26
+ clearTimeout(timeoutHandle);
27
+ if (finalizeTimer)
28
+ clearTimeout(finalizeTimer);
29
+ resolve({ exitCode, signal, timedOut });
30
+ };
31
+ if (timeoutMs > 0) {
32
+ timeoutHandle = setTimeout(() => {
33
+ timedOut = true;
34
+ proc.kill('SIGTERM');
35
+ setTimeout(() => {
36
+ if (proc.exitCode === null) {
37
+ proc.kill('SIGKILL');
38
+ }
39
+ }, FORCE_KILL_DELAY_MS);
40
+ }, timeoutMs);
41
+ }
42
+ proc.on('exit', (code, exitSignal) => {
43
+ exitCode = code;
44
+ signal = exitSignal;
45
+ if (finalizeTimer)
46
+ clearTimeout(finalizeTimer);
47
+ finalizeTimer = setTimeout(finish, Math.max(0, drainMs));
48
+ });
49
+ proc.on('close', (code, closeSignal) => {
50
+ if (exitCode === null)
51
+ exitCode = code;
52
+ if (signal === null)
53
+ signal = closeSignal;
54
+ finish();
55
+ });
56
+ });
57
+ }
58
+ function exec(command, workingDirectory, timeoutMs = DEFAULT_TIMEOUT_MS) {
59
+ return new Promise((resolve, reject) => {
60
+ const proc = spawn('bash', ['-c', command], {
61
+ cwd: workingDirectory || process.cwd(),
62
+ env: shellEnv(),
63
+ });
64
+ let stdout = '';
65
+ let stderr = '';
66
+ proc.stdout.on('data', (data) => (stdout += data.toString()));
67
+ proc.stderr.on('data', (data) => (stderr += data.toString()));
68
+ proc.on('error', (err) => reject(new Error(`Failed to execute command: ${err.message}`)));
69
+ void waitForProcessCompletion(proc, timeoutMs).then(({ exitCode, signal, timedOut }) => {
70
+ const output = [stdout, stderr].filter(Boolean).join('\n');
71
+ if (timedOut) {
72
+ const seconds = Math.max(1, Math.round(timeoutMs / 1000));
73
+ resolve(`Timed out after ${seconds}s (signal: ${signal ?? 'SIGTERM'})\n${output || '(no output)'}`);
74
+ return;
75
+ }
76
+ if (signal) {
77
+ resolve(`Terminated by signal ${signal}\n${output || '(no output)'}`);
78
+ return;
79
+ }
80
+ if (exitCode !== 0) {
81
+ resolve(`Exit code ${exitCode}\n${output}`);
82
+ return;
83
+ }
84
+ resolve(output || '(no output)');
85
+ });
86
+ });
87
+ }
88
+ export const bashTool = {
89
+ name: 'bash',
90
+ definition: {
91
+ name: 'bash',
92
+ description: 'Execute a shell command. Returns stdout, stderr, and exit code.',
93
+ parameters: {
94
+ type: 'object',
95
+ properties: {
96
+ command: { type: 'string', description: 'Command to execute' },
97
+ working_directory: { type: 'string', description: 'Working directory' },
98
+ timeout_seconds: {
99
+ type: 'number',
100
+ description: 'Timeout in seconds (default 300)',
101
+ },
102
+ },
103
+ required: ['command'],
104
+ },
105
+ },
106
+ async execute(input) {
107
+ const { command, working_directory, timeout_seconds } = input;
108
+ return exec(command, working_directory, (timeout_seconds ?? 300) * 1000);
109
+ },
110
+ };
111
+ //# sourceMappingURL=bash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bash.js","sourceRoot":"","sources":["../../src/tools/bash.ts"],"names":[],"mappings":"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"}