mirror of
https://github.com/kolbytn/mindcraft.git
synced 2025-08-26 17:03:45 +02:00
commit
a5bcf169a6
9 changed files with 343 additions and 163 deletions
|
@ -11,7 +11,7 @@
|
||||||
"google-translate-api-x": "^10.7.1",
|
"google-translate-api-x": "^10.7.1",
|
||||||
"groq-sdk": "^0.15.0",
|
"groq-sdk": "^0.15.0",
|
||||||
"minecraft-data": "^3.78.0",
|
"minecraft-data": "^3.78.0",
|
||||||
"mineflayer": "^4.26.0",
|
"mineflayer": "^4.29.0",
|
||||||
"mineflayer-armor-manager": "^2.0.1",
|
"mineflayer-armor-manager": "^2.0.1",
|
||||||
"mineflayer-auto-eat": "^3.3.6",
|
"mineflayer-auto-eat": "^3.3.6",
|
||||||
"mineflayer-collectblock": "^1.4.1",
|
"mineflayer-collectblock": "^1.4.1",
|
||||||
|
|
|
@ -28,7 +28,7 @@ const settings = {
|
||||||
"only_chat_with": [], // users that the bots listen to and send general messages to. if empty it will chat publicly
|
"only_chat_with": [], // users that the bots listen to and send general messages to. if empty it will chat publicly
|
||||||
"speak": false, // allows all bots to speak through system text-to-speech. works on windows, mac, on linux you need to `apt install espeak`
|
"speak": false, // allows all bots to speak through system text-to-speech. works on windows, mac, on linux you need to `apt install espeak`
|
||||||
"language": "en", // translate to/from this language. Supports these language names: https://cloud.google.com/translate/docs/languages
|
"language": "en", // translate to/from this language. Supports these language names: https://cloud.google.com/translate/docs/languages
|
||||||
"render_bot_views": false, // show bot's view in browser at localhost:3000, 3001...
|
"render_bot_view": false, // show bot's view in browser at localhost:3000, 3001...
|
||||||
|
|
||||||
"allow_insecure_coding": false, // allows newAction command and model can write/run code on your computer. enable at own risk
|
"allow_insecure_coding": false, // allows newAction command and model can write/run code on your computer. enable at own risk
|
||||||
"allow_vision": false, // allows vision model to interpret screenshots as inputs
|
"allow_vision": false, // allows vision model to interpret screenshots as inputs
|
||||||
|
|
|
@ -23,10 +23,10 @@ export class Agent {
|
||||||
this.count_id = count_id;
|
this.count_id = count_id;
|
||||||
|
|
||||||
// Initialize components with more detailed error handling
|
// Initialize components with more detailed error handling
|
||||||
console.log(`Initializing agent ${this.name}...`);
|
|
||||||
this.actions = new ActionManager(this);
|
this.actions = new ActionManager(this);
|
||||||
this.prompter = new Prompter(this, settings.profile);
|
this.prompter = new Prompter(this, settings.profile);
|
||||||
this.name = this.prompter.getName();
|
this.name = this.prompter.getName();
|
||||||
|
console.log(`Initializing agent ${this.name}...`);
|
||||||
this.history = new History(this);
|
this.history = new History(this);
|
||||||
this.coder = new Coder(this);
|
this.coder = new Coder(this);
|
||||||
this.npc = new NPCContoller(this);
|
this.npc = new NPCContoller(this);
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
{
|
|
||||||
"minecraft_version": "1.21.1",
|
|
||||||
"host": "127.0.0.1",
|
|
||||||
"port": 55916,
|
|
||||||
"auth": "offline",
|
|
||||||
"base_profile": "survival",
|
|
||||||
"load_memory": false,
|
|
||||||
"init_message": "Respond with hello world and your name",
|
|
||||||
"only_chat_with": [],
|
|
||||||
"speak": false,
|
|
||||||
"language": "en",
|
|
||||||
"allow_vision": false,
|
|
||||||
"blocked_actions" : ["!checkBlueprint", "!checkBlueprintLevel", "!getBlueprint", "!getBlueprintLevel"] ,
|
|
||||||
"relevant_docs_count": 5,
|
|
||||||
"max_messages": 15,
|
|
||||||
"num_examples": 2,
|
|
||||||
"max_commands": -1,
|
|
||||||
"narrate_behavior": true,
|
|
||||||
"log_all_prompts": false,
|
|
||||||
"verbose_commands": true,
|
|
||||||
"chat_bot_messages": true,
|
|
||||||
"render_bot_view": false,
|
|
||||||
"allow_insecure_coding": false,
|
|
||||||
"code_timeout_mins": -1
|
|
||||||
}
|
|
|
@ -16,7 +16,7 @@ let io;
|
||||||
let server;
|
let server;
|
||||||
const agent_connections = {};
|
const agent_connections = {};
|
||||||
|
|
||||||
const default_settings = JSON.parse(readFileSync(path.join(__dirname, 'default_settings.json'), 'utf8'));
|
const settings_spec = JSON.parse(readFileSync(path.join(__dirname, 'public/settings_spec.json'), 'utf8'));
|
||||||
|
|
||||||
class AgentConnection {
|
class AgentConnection {
|
||||||
constructor(settings) {
|
constructor(settings) {
|
||||||
|
@ -58,7 +58,22 @@ export function createMindServer(host_public = false, port = 8080) {
|
||||||
|
|
||||||
socket.on('create-agent', (settings, callback) => {
|
socket.on('create-agent', (settings, callback) => {
|
||||||
console.log('API create agent...');
|
console.log('API create agent...');
|
||||||
settings = { ...default_settings, ...settings };
|
for (let key in settings_spec) {
|
||||||
|
if (!(key in settings)) {
|
||||||
|
if (settings_spec[key].required) {
|
||||||
|
callback({ success: false, error: `Setting ${key} is required` });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
settings[key] = settings_spec[key].default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let key in settings) {
|
||||||
|
if (!(key in settings_spec)) {
|
||||||
|
delete settings[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
if (settings.profile?.name) {
|
if (settings.profile?.name) {
|
||||||
if (settings.profile.name in agent_connections) {
|
if (settings.profile.name in agent_connections) {
|
||||||
callback({ success: false, error: 'Agent already exists' });
|
callback({ success: false, error: 'Agent already exists' });
|
||||||
|
|
|
@ -58,97 +58,229 @@
|
||||||
.status-icon.offline {
|
.status-icon.offline {
|
||||||
color: #f44336;
|
color: #f44336;
|
||||||
}
|
}
|
||||||
|
#settingsForm {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
|
||||||
|
gap: 8px;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
.setting-wrapper {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
background: #3a3a3a;
|
||||||
|
padding: 6px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
.setting-wrapper label {
|
||||||
|
flex: 0 0 50%;
|
||||||
|
font-size: 0.9em;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.setting-wrapper input[type="text"],
|
||||||
|
.setting-wrapper input[type="number"] {
|
||||||
|
flex: 1 1 0;
|
||||||
|
background: #262626;
|
||||||
|
border: 1px solid #555;
|
||||||
|
color: #e0e0e0;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 4px 6px;
|
||||||
|
max-width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
.setting-wrapper input[type="checkbox"] {
|
||||||
|
transform: scale(1.2);
|
||||||
|
}
|
||||||
|
.agent-viewer {
|
||||||
|
width: 200px;
|
||||||
|
height: 150px;
|
||||||
|
border: none;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
.start-btn:disabled {
|
||||||
|
opacity: 0.4;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
.agent-view-container {
|
||||||
|
margin-top: 6px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>Mindcraft</h1>
|
<h1>Mindcraft</h1>
|
||||||
<div id="agents"></div>
|
<div id="agents"></div>
|
||||||
|
|
||||||
<div style="margin-top: 20px;">
|
<div id="createAgentSection" style="margin-top:20px;background:#2d2d2d;padding:20px;border-radius:8px;">
|
||||||
<button id="createAgentBtn" class="start-btn">Create Agent</button>
|
<h2>Create Agent</h2>
|
||||||
<input type="file" id="agentConfigFile" accept=".json,application/json" style="display: none">
|
<div id="settingsForm"></div>
|
||||||
|
<div id="profileStatus" style="margin-top:6px;font-style:italic;color:#cccccc;">Profile: Not uploaded</div>
|
||||||
|
<div style="margin-top:10px;">
|
||||||
|
<button id="uploadProfileBtn" class="start-btn">Upload Profile</button>
|
||||||
|
<input type="file" id="profileFileInput" accept=".json,application/json" style="display:none">
|
||||||
|
<button id="submitCreateAgentBtn" class="start-btn" disabled>Create Agent</button>
|
||||||
|
</div>
|
||||||
|
<div id="createError" style="color:#f44336;margin-top:10px;"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const socket = io();
|
const socket = io();
|
||||||
const agentsDiv = document.getElementById('agents');
|
const agentsDiv = document.getElementById('agents');
|
||||||
|
let settingsSpec = {};
|
||||||
|
let profileData = null;
|
||||||
|
const agentSettings = {};
|
||||||
|
|
||||||
document.getElementById('createAgentBtn').addEventListener('click', () => {
|
fetch('/settings_spec.json')
|
||||||
document.getElementById('agentConfigFile').click();
|
.then(r => r.json())
|
||||||
|
.then(spec => {
|
||||||
|
settingsSpec = spec;
|
||||||
|
const form = document.getElementById('settingsForm');
|
||||||
|
Object.keys(spec).forEach(key => {
|
||||||
|
if (key === 'profile') return; // profile handled via upload
|
||||||
|
const cfg = spec[key];
|
||||||
|
const wrapper = document.createElement('div');
|
||||||
|
wrapper.className = 'setting-wrapper';
|
||||||
|
const label = document.createElement('label');
|
||||||
|
label.textContent = key;
|
||||||
|
label.title = cfg.description || '';
|
||||||
|
let input;
|
||||||
|
switch (cfg.type) {
|
||||||
|
case 'boolean':
|
||||||
|
input = document.createElement('input');
|
||||||
|
input.type = 'checkbox';
|
||||||
|
input.checked = cfg.default === true;
|
||||||
|
break;
|
||||||
|
case 'number':
|
||||||
|
input = document.createElement('input');
|
||||||
|
input.type = 'number';
|
||||||
|
input.value = cfg.default;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
input = document.createElement('input');
|
||||||
|
input.type = 'text';
|
||||||
|
input.value = typeof cfg.default === 'object' ? JSON.stringify(cfg.default) : cfg.default;
|
||||||
|
}
|
||||||
|
input.title = cfg.description || '';
|
||||||
|
input.id = `setting-${key}`;
|
||||||
|
wrapper.appendChild(label);
|
||||||
|
wrapper.appendChild(input);
|
||||||
|
form.appendChild(wrapper);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('uploadProfileBtn').addEventListener('click', () => {
|
||||||
|
document.getElementById('profileFileInput').click();
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('agentConfigFile').addEventListener('change', (event) => {
|
document.getElementById('profileFileInput').addEventListener('change', e => {
|
||||||
const file = event.target.files[0];
|
const file = e.target.files[0];
|
||||||
if (!file) {
|
if (!file) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
reader.onload = (e) => {
|
reader.onload = ev => {
|
||||||
try {
|
try {
|
||||||
const profile = JSON.parse(e.target.result);
|
profileData = JSON.parse(ev.target.result);
|
||||||
socket.emit('create-agent', {profile}, (response) => {
|
document.getElementById('submitCreateAgentBtn').disabled = false;
|
||||||
if (response.success) {
|
document.getElementById('profileStatus').textContent = `Profile: ${profileData.name || 'Uploaded'}`;
|
||||||
alert('Agent created successfully!');
|
document.getElementById('createError').textContent = '';
|
||||||
} else {
|
} catch (err) {
|
||||||
alert(`Error creating agent: ${response.error}`);
|
document.getElementById('createError').textContent = 'Invalid profile JSON: ' + err.message;
|
||||||
}
|
profileData = null;
|
||||||
});
|
document.getElementById('submitCreateAgentBtn').disabled = true;
|
||||||
} catch (error) {
|
document.getElementById('profileStatus').textContent = 'Profile: Not uploaded';
|
||||||
alert('Error parsing JSON file: ' + error.message);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
reader.readAsText(file);
|
reader.readAsText(file);
|
||||||
// Reset file input to allow re-uploading the same file
|
e.target.value = '';
|
||||||
event.target.value = '';
|
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('agents-update', (agents) => {
|
document.getElementById('submitCreateAgentBtn').addEventListener('click', () => {
|
||||||
agentsDiv.innerHTML = agents.length ?
|
if (!profileData) return;
|
||||||
agents.map(agent => `
|
const settings = { profile: profileData };
|
||||||
|
Object.keys(settingsSpec).forEach(key => {
|
||||||
|
if (key === 'profile') return;
|
||||||
|
const input = document.getElementById(`setting-${key}`);
|
||||||
|
if (!input) return;
|
||||||
|
const type = settingsSpec[key].type;
|
||||||
|
let val;
|
||||||
|
if (type === 'boolean') val = input.checked;
|
||||||
|
else if (type === 'number') val = Number(input.value);
|
||||||
|
else if (type === 'array' || type === 'object') {
|
||||||
|
try { val = JSON.parse(input.value); }
|
||||||
|
catch { val = input.value; }
|
||||||
|
} else val = input.value;
|
||||||
|
settings[key] = val;
|
||||||
|
});
|
||||||
|
socket.emit('create-agent', settings, res => {
|
||||||
|
if (!res.success) {
|
||||||
|
document.getElementById('createError').textContent = res.error || 'Unknown error';
|
||||||
|
} else {
|
||||||
|
// reset on success
|
||||||
|
profileData = null;
|
||||||
|
document.getElementById('submitCreateAgentBtn').disabled = true;
|
||||||
|
document.getElementById('profileStatus').textContent = 'Profile: Not uploaded';
|
||||||
|
document.getElementById('createError').textContent = '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function fetchAgentSettings(name) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
if (agentSettings[name]) { resolve(agentSettings[name]); return; }
|
||||||
|
socket.emit('get-settings', name, res => {
|
||||||
|
if (res.settings) {
|
||||||
|
agentSettings[name] = res.settings;
|
||||||
|
resolve(res.settings);
|
||||||
|
} else resolve(null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderAgents(agents) {
|
||||||
|
// fetch settings for any new agents
|
||||||
|
await Promise.all(agents.map(a => fetchAgentSettings(a.name)));
|
||||||
|
|
||||||
|
agentsDiv.innerHTML = agents.length ?
|
||||||
|
agents.map((agent, idx) => {
|
||||||
|
const cfg = agentSettings[agent.name] || {};
|
||||||
|
const showViewer = cfg.render_bot_view === true;
|
||||||
|
const viewerHTML = showViewer ? `<div class="agent-view-container"><iframe class="agent-viewer" src="http://localhost:${3000 + idx}"></iframe></div>` : '';
|
||||||
|
return `
|
||||||
<div class="agent">
|
<div class="agent">
|
||||||
<span>
|
<div style="display:flex;justify-content:space-between;align-items:center;">
|
||||||
<span class="status-icon ${agent.in_game ? 'online' : 'offline'}">●</span>
|
<span><span class="status-icon ${agent.in_game ? 'online' : 'offline'}">●</span>${agent.name}</span>
|
||||||
${agent.name}
|
<div style="display:flex;align-items:center;">
|
||||||
</span>
|
${agent.in_game ? `
|
||||||
<div>
|
<button class="stop-btn" onclick="stopAgent('${agent.name}')">Stop</button>
|
||||||
${agent.in_game ? `
|
<button class="restart-btn" onclick="restartAgent('${agent.name}')">Restart</button>
|
||||||
<button class="stop-btn" onclick="stopAgent('${agent.name}')">Stop</button>
|
<input type="text" id="messageInput-${agent.name}" placeholder="Enter message..." style="margin-left:4px;">
|
||||||
<button class="restart-btn" onclick="restartAgent('${agent.name}')">Restart</button>
|
<button class="start-btn" onclick="sendMessage('${agent.name}', document.getElementById('messageInput-${agent.name}').value)">Send</button>
|
||||||
<input type="text" id="messageInput" placeholder="Enter a message or command..."></input><button class="start-btn" onclick="sendMessage('${agent.name}', document.getElementById('messageInput').value)">Send</button>
|
` : `
|
||||||
` : `
|
<button class="start-btn" onclick="startAgent('${agent.name}')">Start</button>
|
||||||
<button class="start-btn" onclick="startAgent('${agent.name}')">Start</button>
|
`}
|
||||||
`}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
${viewerHTML}
|
||||||
`).join('') +
|
</div>`;
|
||||||
|
}).join('') +
|
||||||
`<button class="stop-btn" onclick="killAllAgents()">Stop All</button>
|
`<button class="stop-btn" onclick="killAllAgents()">Stop All</button>
|
||||||
<button class="stop-btn" onclick="shutdown()">Shutdown</button>` :
|
<button class="stop-btn" onclick="shutdown()">Shutdown</button>` :
|
||||||
'<div class="agent">No agents connected</div>';
|
'<div class="agent">No agents connected</div>';
|
||||||
});
|
|
||||||
|
|
||||||
function restartAgent(agentName) {
|
|
||||||
socket.emit('restart-agent', agentName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function startAgent(agentName) {
|
socket.on('agents-update', agents => { renderAgents(agents); });
|
||||||
socket.emit('start-agent', agentName);
|
|
||||||
}
|
|
||||||
|
|
||||||
function stopAgent(agentName) {
|
function restartAgent(n) { socket.emit('restart-agent', n); }
|
||||||
socket.emit('stop-agent', agentName);
|
function startAgent(n) { socket.emit('start-agent', n); }
|
||||||
}
|
function stopAgent(n) { socket.emit('stop-agent', n); }
|
||||||
|
function killAllAgents() { socket.emit('stop-all-agents'); }
|
||||||
function killAllAgents() {
|
function shutdown() { socket.emit('shutdown'); }
|
||||||
socket.emit('stop-all-agents');
|
function sendMessage(n, m) { socket.emit('send-message', n, m); }
|
||||||
}
|
|
||||||
|
|
||||||
function shutdown() {
|
|
||||||
socket.emit('shutdown');
|
|
||||||
}
|
|
||||||
|
|
||||||
function sendMessage(agentName, message) {
|
|
||||||
socket.emit('send-message', agentName, message)
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
127
src/mindcraft/public/settings_spec.json
Normal file
127
src/mindcraft/public/settings_spec.json
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
{
|
||||||
|
"profile": {
|
||||||
|
"type": "object",
|
||||||
|
"required": true,
|
||||||
|
"description": "The profile object to use, including name, prompts, and examples"
|
||||||
|
},
|
||||||
|
"minecraft_version": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The version of Minecraft to use",
|
||||||
|
"default": "1.21.1"
|
||||||
|
},
|
||||||
|
"host": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The minecraft server host address to connect to",
|
||||||
|
"default": "127.0.0.1"
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "The minecraft server port to connect to",
|
||||||
|
"default": 55916
|
||||||
|
},
|
||||||
|
"auth": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The authentication method to use",
|
||||||
|
"default": "offline"
|
||||||
|
},
|
||||||
|
"base_profile": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Allowed values: survival, creative, god_mode. Each has fine tuned settings for different game modes.",
|
||||||
|
"default": "survival"
|
||||||
|
},
|
||||||
|
"load_memory": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to load bot's previous memory",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"init_message": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The initial message to send to the bot",
|
||||||
|
"default": "Respond with hello world and your name"
|
||||||
|
},
|
||||||
|
"only_chat_with": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "List of agents to only chat with. If empty, the bot will chat publicly",
|
||||||
|
"default": []
|
||||||
|
},
|
||||||
|
"speak": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to enable text-to-speech reading on the host machine",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"language": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The language to automatically translate to and from using google translate",
|
||||||
|
"default": "en"
|
||||||
|
},
|
||||||
|
"allow_vision": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to allow vision capabilities",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"blocked_actions": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "List of actions that are blocked",
|
||||||
|
"default": ["!checkBlueprint", "!checkBlueprintLevel", "!getBlueprint", "!getBlueprintLevel"]
|
||||||
|
},
|
||||||
|
"relevant_docs_count": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Number of relevant function documents to include in the prompt for LLM code writing",
|
||||||
|
"default": 5
|
||||||
|
},
|
||||||
|
"max_messages": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Maximum number of recent messages to keep in context for LLM",
|
||||||
|
"default": 15
|
||||||
|
},
|
||||||
|
"num_examples": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Number of examples to select to help prompt better LLM responses",
|
||||||
|
"default": 2
|
||||||
|
},
|
||||||
|
"max_commands": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Maximum number of commands allowed in consecutive responses. -1 for no limit",
|
||||||
|
"default": -1
|
||||||
|
},
|
||||||
|
"narrate_behavior": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to openly chat automatic behavior like 'Picking up item!'",
|
||||||
|
"default": true
|
||||||
|
},
|
||||||
|
"log_all_prompts": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to log all prompts to file. Can be very verbose.",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"verbose_commands": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to show full command syntax in bot responses. If false will use a shortened syntax.",
|
||||||
|
"default": true
|
||||||
|
},
|
||||||
|
"chat_bot_messages": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to publicly chat messages to and from other bots",
|
||||||
|
"default": true
|
||||||
|
},
|
||||||
|
"render_bot_view": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to render bot view for user observation. Does not give bot vision.",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"allow_insecure_coding": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to allow newAction command that let's LLM write/run code on host computer. Despite sandboxxing, it is potentially insecure.",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"code_timeout_mins": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Number of minutes to allow code execution. -1 for no timeout",
|
||||||
|
"default": -1
|
||||||
|
},
|
||||||
|
"task": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "The task object to give the agent on start. If null, the agent will not have a task.",
|
||||||
|
"default": null
|
||||||
|
}
|
||||||
|
}
|
|
@ -55,7 +55,7 @@ export class GroqCloudAPI {
|
||||||
...(this.params || {})
|
...(this.params || {})
|
||||||
});
|
});
|
||||||
|
|
||||||
res = completion.choices[0].message;
|
res = completion.choices[0].message.content;
|
||||||
|
|
||||||
res = res.replace(/<think>[\s\S]*?<\/think>/g, '').trim();
|
res = res.replace(/<think>[\s\S]*?<\/think>/g, '').trim();
|
||||||
}
|
}
|
||||||
|
|
69
viewer.html
69
viewer.html
|
@ -1,69 +0,0 @@
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Viewer</title>
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
#container {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
width: 100%;
|
|
||||||
height: 100vh;
|
|
||||||
}
|
|
||||||
.iframe-wrapper {
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="container">
|
|
||||||
<iframe data-port="3000" src="http://localhost:3000" class="iframe-wrapper"></iframe>
|
|
||||||
<iframe data-port="3001" src="http://localhost:3001" class="iframe-wrapper"></iframe>
|
|
||||||
<iframe data-port="3002" src="http://localhost:3002" class="iframe-wrapper"></iframe>
|
|
||||||
<iframe data-port="3003" src="http://localhost:3003" class="iframe-wrapper"></iframe>
|
|
||||||
</div>
|
|
||||||
<script>
|
|
||||||
function updateLayout() {
|
|
||||||
let width = window.innerWidth;
|
|
||||||
let height = window.innerHeight;
|
|
||||||
let iframes = document.querySelectorAll('.iframe-wrapper');
|
|
||||||
if (width > height) {
|
|
||||||
iframes.forEach(function(iframe) {
|
|
||||||
iframe.style.width = '50%';
|
|
||||||
iframe.style.height = '50%';
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
iframes.forEach(function(iframe) {
|
|
||||||
iframe.style.width = '100%';
|
|
||||||
iframe.style.height = '25%';
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
window.addEventListener('resize', updateLayout);
|
|
||||||
window.addEventListener('load', updateLayout);
|
|
||||||
let iframes = document.querySelectorAll('.iframe-wrapper');
|
|
||||||
iframes.forEach(function(iframe) {
|
|
||||||
let port = iframe.getAttribute('data-port');
|
|
||||||
let loaded = false;
|
|
||||||
function checkServer() {
|
|
||||||
fetch('http://localhost:' + port, { method: 'HEAD' })
|
|
||||||
.then(function(response) {
|
|
||||||
if (response.ok && !loaded) {
|
|
||||||
iframe.src = 'http://localhost:' + port;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(function(error) {});
|
|
||||||
}
|
|
||||||
iframe.onload = function() {
|
|
||||||
loaded = true;
|
|
||||||
};
|
|
||||||
iframe.onerror = function() {
|
|
||||||
loaded = false;
|
|
||||||
};
|
|
||||||
setInterval(checkServer, 3000);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
Loading…
Add table
Reference in a new issue