This commit is contained in:
@@ -1465,6 +1465,89 @@ function bareAgentNormalizeGuestScript(code) {
|
||||
return src.trim() + '\n'
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim glued prose off a curl/wget URL (`orgBut` → `org`).
|
||||
* @param {string} cmd
|
||||
*/
|
||||
function bareAgentTrimGluedShellCommand(cmd) {
|
||||
let s = String(cmd || '').trim()
|
||||
s = s.replace(/(\.(?:org|com|net|io|dev|fyi|info|edu|co))([A-Z].*)$/i, '$1')
|
||||
s = s.replace(/(https?:\/\/[^\s]+?)(?=[A-Z][a-z])/, '$1')
|
||||
return s.trim()
|
||||
}
|
||||
|
||||
/**
|
||||
* If a run_js_script body is actually a guest CLI (curl/wget/ip), return
|
||||
* the command so dispatch can divert to run_command.
|
||||
* @param {string} code
|
||||
* @returns {string}
|
||||
*/
|
||||
function bareAgentShellCommandFromJsScript(code) {
|
||||
const s = String(code || '')
|
||||
if (!s.trim()) return ''
|
||||
const trimmed = s.trim()
|
||||
const looksShell =
|
||||
typeof bareAgentLooksLikeShellCommand === 'function'
|
||||
? bareAgentLooksLikeShellCommand(trimmed)
|
||||
: /^(curl|wget|ip|ping|ifconfig)\b/i.test(trimmed)
|
||||
if (
|
||||
looksShell &&
|
||||
!/\bfunction\b|\bclass\b|\bawait\b|\bconst\b|\blet\b|\bvar\b|\bimport\b/.test(trimmed)
|
||||
) {
|
||||
return bareAgentTrimGluedShellCommand(trimmed)
|
||||
}
|
||||
const execRe =
|
||||
/\b(?:execLine|execSync|exec|spawnSync|system)\s*\(\s*(['"`])([\s\S]*?)\1/g
|
||||
let m
|
||||
while ((m = execRe.exec(s))) {
|
||||
const cmd = String(m[2] || '').trim()
|
||||
if (/^(curl|wget|ip|ping|ifconfig)\b/i.test(cmd)) {
|
||||
return bareAgentTrimGluedShellCommand(cmd)
|
||||
}
|
||||
}
|
||||
const fetchRe = /\bfetch\s*\(\s*(['"`])(https?:\/\/[^'"`]+)\1/
|
||||
m = fetchRe.exec(s)
|
||||
if (m) return 'curl -s ' + String(m[2] || '').trim()
|
||||
const curlRe = /(?:^|[\n;])\s*((?:curl|wget)\s+https?:\/\/[^\s;'"`]+)/im
|
||||
m = curlRe.exec(s)
|
||||
if (m) return bareAgentTrimGluedShellCommand(m[1])
|
||||
return ''
|
||||
}
|
||||
|
||||
/**
|
||||
* task_complete used as a surrender after a failed tool, not a real finish.
|
||||
* @param {string} summary
|
||||
*/
|
||||
function bareAgentLooksLikeFailedTaskComplete(summary) {
|
||||
const s = String(summary || '').toLowerCase()
|
||||
if (!s.trim()) return false
|
||||
return (
|
||||
/error occurred/.test(s) ||
|
||||
/alternative method required/.test(s) ||
|
||||
(/attempted to /.test(s) && /error|fail/.test(s)) ||
|
||||
/failed due to/.test(s) ||
|
||||
/could not (run|execute|retrieve|complete|get)/.test(s) ||
|
||||
/not (able|allowed) to (run|execute|complete)/.test(s) ||
|
||||
/top-level (scope|await|module)/.test(s)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* User asked to run a guest CLI (curl / IP lookup), not write JS.
|
||||
* @param {string} text
|
||||
*/
|
||||
function bareAgentLooksLikeGuestCliRequest(text) {
|
||||
const s = String(text || '').toLowerCase()
|
||||
if (!s.trim()) return false
|
||||
return (
|
||||
/\b(run|execute|use)\b.{0,48}\b(curl|wget|ping|ifconfig|ip addr)\b/.test(s) ||
|
||||
/\b(curl|wget)\b.{0,48}\b(ip address|public ip|our ip|my ip)\b/.test(s) ||
|
||||
/\b(find|get|check|show|lookup)\b.{0,48}\b(ip address|public ip|our ip|my ip)\b/.test(
|
||||
s
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/** ~/.agent paths, config, history trim, man digest (preamble for /bin/agent). */
|
||||
|
||||
/**
|
||||
@@ -6955,7 +7038,7 @@ function bareAgentToolDefinitions() {
|
||||
function: {
|
||||
name: 'run_command',
|
||||
description:
|
||||
'Run a shell command line via ctx.execLine (same as interactive shell). Output is captured to a temp file. Set capture_exit true to append a final EXIT:<code> line.',
|
||||
'Run a guest CLI line (curl, wget, ip, ping, ls, cat, …) via ctx.execLine. Prefer this over run_js_script for any shell command. Output is captured to a temp file. Set capture_exit true to append a final EXIT:<code> line.',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
@@ -6982,7 +7065,7 @@ function bareAgentToolDefinitions() {
|
||||
function: {
|
||||
name: 'run_js_script',
|
||||
description:
|
||||
'Run custom guest JavaScript only. Do not use this to replace read_file, write_file, list_directory, or run_command. Node is not installed. Writes ~/.agent/_tmp_agent_run.mjs and runs it on the Bare kernel. ctx and argv are already injected — never declare them, never export. Body must be: async function run(ctx, argv) { const vfs = ctx.vfs; ... }',
|
||||
'Run custom guest JavaScript only. Do not use this for curl, wget, ip, ping, or any shell — call run_command. Do not use this to replace read_file, write_file, list_directory, or run_command. Node is not installed. Writes ~/.agent/_tmp_agent_run.mjs and runs it on the Bare kernel. ctx and argv are already injected — never declare them, never export. Body must be: async function run(ctx, argv) { const vfs = ctx.vfs; ... }',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
@@ -8440,7 +8523,7 @@ function bareAgentToolCatalogPrompt(tools) {
|
||||
'AVAILABLE TOOLS (' +
|
||||
cat.length +
|
||||
' callable functions — live registry)',
|
||||
'These names are the only functions you can call. Skills such as ctx-api-change, docs-contract-update, hdms, and holesail are playbooks: load them with read_skill. Guest /bin names such as ctx-baredoctor, hdms, and holepunch are commands for run_command, not tools.',
|
||||
'These names are the only functions you can call. Skills such as ctx-api-change, docs-contract-update, hdms, and holesail are playbooks: load them with read_skill. Guest /bin names such as ctx-baredoctor, hdms, curl, and holepunch are commands for run_command, not tools. curl/wget/ip are run_command — never run_js_script.',
|
||||
'When the user asks what tools you have or what you can do, list every name below. Do not invent names. Do not list skills as tools.',
|
||||
'To call a tool, emit exactly:',
|
||||
'<tool_call>{"name":"TOOL_NAME","arguments":{}}</tool_call>',
|
||||
@@ -9082,6 +9165,19 @@ async function bareAgentDispatchTool(o) {
|
||||
|
||||
if (toolName === 'task_complete') {
|
||||
const summary = typeof args.summary === 'string' ? args.summary : ''
|
||||
if (
|
||||
typeof bareAgentLooksLikeFailedTaskComplete === 'function' &&
|
||||
bareAgentLooksLikeFailedTaskComplete(summary)
|
||||
) {
|
||||
appendProgress('task_complete_rejected_failure')
|
||||
return bareAgentJsonResult({
|
||||
ok: false,
|
||||
error: 'task_not_complete',
|
||||
hint:
|
||||
'Do not call task_complete after a failed tool. Keep going. Guest CLI (curl, wget, ip, ping, ls) is run_command({command:"..."}). Never wrap curl in run_js_script. Call run_command now and report stdout.',
|
||||
summary
|
||||
})
|
||||
}
|
||||
appendProgress('task_complete: ' + summary.slice(0, 200))
|
||||
onTaskComplete(summary || '(done)')
|
||||
return bareAgentJsonResult({
|
||||
@@ -9457,6 +9553,18 @@ async function bareAgentDispatchTool(o) {
|
||||
|
||||
if (toolName === 'run_js_script') {
|
||||
const rawCode = typeof args.code === 'string' ? args.code : ''
|
||||
const diverted =
|
||||
typeof bareAgentShellCommandFromJsScript === 'function'
|
||||
? bareAgentShellCommandFromJsScript(rawCode)
|
||||
: ''
|
||||
if (diverted) {
|
||||
appendProgress('run_js_script_diverted_to_run_command ' + diverted.slice(0, 120))
|
||||
return bareAgentDispatchTool({
|
||||
...o,
|
||||
toolName: 'run_command',
|
||||
argsJson: JSON.stringify({ command: diverted, capture_exit: true })
|
||||
})
|
||||
}
|
||||
const code =
|
||||
typeof bareAgentNormalizeGuestScript === 'function'
|
||||
? bareAgentNormalizeGuestScript(rawCode)
|
||||
@@ -9485,6 +9593,20 @@ async function bareAgentDispatchTool(o) {
|
||||
stdout_stderr: text
|
||||
})
|
||||
}
|
||||
if (
|
||||
/await is only valid|top.level|cannot find module|require is not defined|node\.js|ReferenceError|SyntaxError/i.test(
|
||||
text
|
||||
) ||
|
||||
/await is only valid|top.level/i.test(String(out.error || ''))
|
||||
) {
|
||||
return bareAgentJsonResult({
|
||||
ok: false,
|
||||
error: 'guest_script_wrong_tool',
|
||||
hint:
|
||||
'Do not use run_js_script for curl/wget/ip/shell. Node is not installed. Call run_command({command:"curl -s https://api.ipify.org"}) and report stdout.',
|
||||
stdout_stderr: text
|
||||
})
|
||||
}
|
||||
return bareAgentJsonResult(
|
||||
r.ok === false ? r : { ok: true, stdout_stderr: r.stdout_stderr }
|
||||
)
|
||||
@@ -13463,7 +13585,7 @@ const BARE_AGENT_STATIC_SYSTEM = `You are the Bare OS coding agent — a senior
|
||||
|
||||
YOU RUN THE TOOLS. The user never runs your tools, commands, patches, or scripts. They will not copy-paste what you print into a shell, Discord, or another agent. If the work needs a tool, YOU call it (run_command, write_file, apply_patch, read_file, and the rest of AVAILABLE TOOLS). Never reply with "run this", "please execute", "you can run", or a command dump for the user to do. The user is not your tool runner.
|
||||
|
||||
YOU CAN EXECUTE. Never say "I cannot execute commands", "I cannot run CLI", "I can help you use available tools", or "try:". That is a failure. Guest shell is run_command({command, cwd?}). There is no bash, shell, cli, or terminal tool — those names map to run_command. Emitting a ```bash fence instead of calling run_command is a failure. If the operator says "run it yourself", call the tool immediately and return the result.
|
||||
YOU CAN EXECUTE. Never say "I cannot execute commands", "I cannot run CLI", "I can help you use available tools", or "try:". That is a failure. Guest shell is run_command({command, cwd?}). There is no bash, shell, cli, or terminal tool — those names map to run_command. Emitting a ```bash fence instead of calling run_command is a failure. If the operator says "run it yourself", call the tool immediately and return the result. curl, wget, ip, ping, ls, cat, and every other guest CLI are run_command — never wrap them in run_js_script. Do not call task_complete after a failed tool; retry with run_command until you have stdout.
|
||||
|
||||
Bare OS by Raven Scott (https://raven-scott.fyi). Repo: https://git.ssh.surf/snxraven/bare-operating-system. Booter: pear://qupw8zspk34pcxc7fqchzyeh33jtmxq1k7qze44fkosctwiid8zy
|
||||
|
||||
@@ -13480,7 +13602,7 @@ ACCESS (denylist, not allowlist). You already have full guest admin. You can cre
|
||||
- Read any absolute path, including /proc (read_proc_file, runtime_diagnostic_bundle). Use read_file offset/limit for large files.
|
||||
- Run every guest command via run_command (command_deny is empty by default). Prefer list_directory, glob_files, and file_stat over ls/find when you only need names. list_bin lists guest /bin utilities (POSIX-in-JS, not GNU). Never dump curl/ip/ls for the user — call run_command and report stdout.
|
||||
- Delete and move are enabled. Do not mutate the read-only base system: /bin /etc /boot /lib /usr /share /proc /dev /sys /run.
|
||||
- Node is not installed in the guest. Never plan or run node, npm, or npx here. Do not use run_js_script to read files, write files, or run shell — call read_file, write_file, run_command instead. Only use run_js_script for custom guest JS. The kernel already injects ctx and argv: never write const/let/var ctx, never export. Body must be only async function run(ctx, argv) { const vfs = ctx.vfs; ... }. Do not import Node builtins. Never paste a "final correct script" into the user reply — call the tool.
|
||||
- Node is not installed in the guest. Never plan or run node, npm, or npx here. Do not use run_js_script to read files, write files, or run shell — call read_file, write_file, run_command instead. curl/wget/ip/ping are run_command({command:"curl -s https://api.ipify.org"}), never run_js_script. Only use run_js_script for custom guest JS. The kernel already injects ctx and argv: never write const/let/var ctx, never export. Body must be only async function run(ctx, argv) { const vfs = ctx.vfs; ... }. Do not import Node builtins. Never paste a "final correct script" into the user reply — call the tool.
|
||||
- Live kernel: read_proc_file on /proc/bare_os/features (or features.json) and /proc/bare_os/capabilities.json. Man pages and apropos_man are documentation only — never infer what is enabled from them.
|
||||
- web_fetch uses the same host allow/deny list as wget/curl.
|
||||
- emit_host_notification and request_host_action are enabled by default. emergency_stop_mutations is the kill switch.
|
||||
@@ -13492,7 +13614,7 @@ CODING LOOP. Multi-step work: todo_write (merge=true). Large unknown surface: en
|
||||
1. Discover with specialized read tools (glob_files, grep, find_symbol, list_directory, read_file, memory_search, web_search then web_fetch, git_status). Call read_skill when a skill matches. Read before you edit. Walk-up AGENTS.md and .grok/skills from cwd are already injected when present.
|
||||
2. Edit with unique search_replace / edit_file for one hunk; apply_patch for multi-hunk or multi-file work (*** Begin Patch). Create with write_file / create_directory. State blast radius before wide edits. Match surrounding style.
|
||||
3. Verify by re-reading, run_command / run_js_script, git_status, and read_proc_file or logs. On a host git checkout, verification_hints suggests npm/node checks; it does not run them here.
|
||||
4. Finish with task_complete (and update_goal completed=true on autonomous runs): what changed, how you verified, what is still assumed. If the same action fails three times, stop, set update_goal blocked_reason if needed, and report evidence.
|
||||
4. Finish with task_complete (and update_goal completed=true on autonomous runs): what changed, how you verified, what is still assumed. Never task_complete with "error occurred" / "attempted" / "alternative method required" — that is a failure, not a finish. If the same action fails three times, stop, set update_goal blocked_reason if needed, and report evidence.
|
||||
|
||||
TOOL DISCIPLINE.
|
||||
- YOU call every tool. The user will never run them. Do not print commands, patches, or "run this" for the user.
|
||||
@@ -13800,7 +13922,9 @@ function bareAgentLooksLikeInstructionDump(text) {
|
||||
/please (run|execute|try) (this|the|it)/.test(low) ||
|
||||
/try this command/.test(low) ||
|
||||
/for .{0,60} try:/.test(low) ||
|
||||
/let me know if you need help with other commands/.test(low)
|
||||
/let me know if you need help with other commands/.test(low) ||
|
||||
/the assistant (is supposed to|should|needs to|would) (use|call|generate)/.test(low) ||
|
||||
/the correct approach is to call/.test(low)
|
||||
) {
|
||||
return true
|
||||
}
|
||||
@@ -13983,6 +14107,19 @@ function bareAgentExtractToolCallsFromText(text) {
|
||||
}
|
||||
}
|
||||
|
||||
const glued = /\b((?:curl|wget)\s+https?:\/\/[^\s]+)/gi
|
||||
while ((m = glued.exec(src))) {
|
||||
let cmd = String(m[1] || '').trim()
|
||||
if (typeof bareAgentTrimGluedShellCommand === 'function') {
|
||||
cmd = bareAgentTrimGluedShellCommand(cmd)
|
||||
} else {
|
||||
cmd = cmd.replace(/(\.(?:org|com|net|io|dev|fyi))([A-Z].*)$/i, '$1')
|
||||
}
|
||||
if (/^(curl|wget)\s+https?:\/\//i.test(cmd)) {
|
||||
push('run_command', JSON.stringify({ command: cmd }))
|
||||
}
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
@@ -15146,6 +15283,13 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
|
||||
userTask +=
|
||||
'\n\n[harness] The operator told you to execute. Call run_command / write_file / the rest of AVAILABLE TOOLS yourself. Do not print commands for them. There is no bash tool — use run_command.'
|
||||
}
|
||||
if (
|
||||
typeof bareAgentLooksLikeGuestCliRequest === 'function' &&
|
||||
bareAgentLooksLikeGuestCliRequest(userTask)
|
||||
) {
|
||||
userTask +=
|
||||
'\n\n[harness] This is a guest CLI request. Call run_command({command:"curl -s https://api.ipify.org"}) or the equivalent now. Do not use run_js_script. Do not dump the command. Do not task_complete until stdout has the result.'
|
||||
}
|
||||
if (discordReply) {
|
||||
userTask +=
|
||||
'\n\n[harness] This is Discord. Execute with tools. The operator will not run your commands. Call run_command yourself. Never dump curl/ip/bash for them to copy. Never say you cannot execute.'
|
||||
@@ -15536,6 +15680,7 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
|
||||
}
|
||||
|
||||
let assistantContent = ''
|
||||
let thinkDump = ''
|
||||
/** @type {Map<number, { id: string, name: string, args: string }>} */
|
||||
const toolAcc = new Map()
|
||||
/** @type {unknown} */
|
||||
@@ -15547,14 +15692,22 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
|
||||
if (recoveredFromText) return
|
||||
recoveredFromText = true
|
||||
if (typeof bareAgentExtractToolCallsFromText !== 'function') return
|
||||
const extracted = bareAgentExtractToolCallsFromText(assistantContent)
|
||||
const blob = assistantContent + '\n' + thinkDump
|
||||
const extracted = bareAgentExtractToolCallsFromText(blob)
|
||||
if (extracted.length) {
|
||||
if (!toolAcc.size) {
|
||||
for (const tc of extracted) bareAgentMergeToolCallDelta(toolAcc, tc)
|
||||
appendProgress(
|
||||
'recovered_tool_calls_from_text n=' + String(extracted.length)
|
||||
)
|
||||
const before = toolAcc.size
|
||||
for (const tc of extracted) {
|
||||
const shifted = {
|
||||
index: before + 1000 + (typeof tc.index === 'number' ? tc.index : 0),
|
||||
id: tc.id,
|
||||
function: tc.function
|
||||
}
|
||||
bareAgentMergeToolCallDelta(toolAcc, shifted)
|
||||
}
|
||||
appendProgress(
|
||||
(before ? 'recovered_additional_tool_calls_from_text n=' : 'recovered_tool_calls_from_text n=') +
|
||||
String(extracted.length)
|
||||
)
|
||||
assistantContent = bareAgentStripToolCallsFromText(assistantContent)
|
||||
}
|
||||
if (
|
||||
@@ -15619,6 +15772,7 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
|
||||
*/
|
||||
function feedThink(chunk) {
|
||||
if (!chunk || !String(chunk).trim()) return
|
||||
thinkDump += chunk
|
||||
if (hideThink) return
|
||||
clearStatusLine()
|
||||
if (thinkPanel) thinkPanel.append(chunk)
|
||||
@@ -15997,7 +16151,9 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
|
||||
|
||||
let toolCallsArr = bareAgentFinalizeToolCalls(toolAcc)
|
||||
if (!toolCallsArr.length && typeof bareAgentExtractToolCallsFromText === 'function') {
|
||||
const extracted = bareAgentExtractToolCallsFromText(assistantContent)
|
||||
const extracted = bareAgentExtractToolCallsFromText(
|
||||
assistantContent + '\n' + thinkDump
|
||||
)
|
||||
if (extracted.length) {
|
||||
for (const tc of extracted) bareAgentMergeToolCallDelta(toolAcc, tc)
|
||||
toolCallsArr = bareAgentFinalizeToolCalls(toolAcc)
|
||||
|
||||
Reference in New Issue
Block a user