This commit is contained in:
@@ -1601,6 +1601,78 @@ function bareAgentLooksLikeGuestCliRequest(text) {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* User asked for a mutating/action job, not a definition.
|
||||
* @param {string} text
|
||||
*/
|
||||
function bareAgentLooksLikeActionRequest(text) {
|
||||
const s = String(text || '').toLowerCase()
|
||||
if (!s.trim()) return false
|
||||
return (
|
||||
/\b(create|write|make|add|put|place|move|rename|copy|delete|remove|fix|implement|build|install|edit|patch|run)\b/.test(
|
||||
s
|
||||
) ||
|
||||
/\b(director(y|ies)|files?|scripts?|bin utils?)\b/.test(s)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Assistant is asking the operator to choose instead of finishing.
|
||||
* @param {string} text
|
||||
*/
|
||||
function bareAgentLooksLikeQuestionDump(text) {
|
||||
const s = String(text || '')
|
||||
if (!s.trim()) return false
|
||||
const low = s.toLowerCase()
|
||||
if (
|
||||
/would you like( me)? to/.test(low) ||
|
||||
/do you want me to/.test(low) ||
|
||||
/should i (create|move|rename|run|write|add|make)/.test(low) ||
|
||||
/you('d| would) need to:/.test(low) ||
|
||||
/the user might need to/.test(low) ||
|
||||
/let me know if you want/.test(low) ||
|
||||
/shall i /.test(low)
|
||||
) {
|
||||
return true
|
||||
}
|
||||
if (
|
||||
/would you like/.test(low) &&
|
||||
/\n\s*1[\).:]/.test(s) &&
|
||||
/\n\s*2[\).:]/.test(s)
|
||||
) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Claimed a file exists / was named without a verifying tool result.
|
||||
* @param {string} text
|
||||
*/
|
||||
function bareAgentLooksLikeUnverifiedFileClaim(text) {
|
||||
const s = String(text || '').toLowerCase()
|
||||
if (!s.trim()) return false
|
||||
return (
|
||||
/has been (created|placed|moved|renamed|written|copied) (successfully )?(in|to|at|into)/.test(
|
||||
s
|
||||
) ||
|
||||
/the file will be named/.test(s) ||
|
||||
/is now in the (correct |right )?location/.test(s) ||
|
||||
/scripts? (are|is) now in/.test(s)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Permission-style ask_user_question payload (create/move/rename).
|
||||
* @param {unknown} questions
|
||||
*/
|
||||
function bareAgentLooksLikePermissionQuestions(questions) {
|
||||
const blob = JSON.stringify(questions || '').toLowerCase()
|
||||
return /would you like|do you want me to|should i |create a script|move the|rename the|add additional/.test(
|
||||
blob
|
||||
)
|
||||
}
|
||||
|
||||
/** ~/.agent paths, config, history trim, man digest (preamble for /bin/agent). */
|
||||
|
||||
/**
|
||||
@@ -7121,11 +7193,16 @@ function bareAgentToolDefinitions() {
|
||||
function: {
|
||||
name: 'run_js_script',
|
||||
description:
|
||||
'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; ... }',
|
||||
'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. Without path=, this ONLY writes a throwaway ~/.agent/_tmp_agent_run.mjs — that is not a user file. Pass path=~/test/name.js (or call write_file) to persist. Node is not installed. 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: {
|
||||
code: { type: 'string', description: 'Full ESM/CommonJS script body' }
|
||||
code: { type: 'string', description: 'Full ESM/CommonJS script body' },
|
||||
path: {
|
||||
type: 'string',
|
||||
description:
|
||||
'If set, persist the script here (absolute or ~/...) then run it. Use this when the user asked you to create a file.'
|
||||
}
|
||||
},
|
||||
required: ['code']
|
||||
}
|
||||
@@ -8663,7 +8740,8 @@ async function bareAgentDispatchTool(o) {
|
||||
'destination',
|
||||
'target',
|
||||
'old_path',
|
||||
'new_path'
|
||||
'new_path',
|
||||
'save_as'
|
||||
]
|
||||
let cwdForExpand = resolvedHome
|
||||
if (paths && paths.lastCwd && typeof bareAgentReadTextFile === 'function') {
|
||||
@@ -9197,6 +9275,18 @@ async function bareAgentDispatchTool(o) {
|
||||
}
|
||||
|
||||
if (toolName === 'ask_user_question') {
|
||||
const previewQs = args.questions
|
||||
if (
|
||||
typeof bareAgentLooksLikePermissionQuestions === 'function' &&
|
||||
bareAgentLooksLikePermissionQuestions(previewQs)
|
||||
) {
|
||||
return bareAgentJsonResult({
|
||||
ok: false,
|
||||
error: 'execute_instead',
|
||||
hint:
|
||||
'Do not ask the operator whether to create/move/rename/run. Call write_file, move_path, list_directory now. Keep going until the files exist.'
|
||||
})
|
||||
}
|
||||
const rows = Array.isArray(args.questions) ? args.questions : []
|
||||
if (!rows.length) {
|
||||
return bareAgentJsonResult({ ok: false, error: 'questions_required' })
|
||||
@@ -9282,6 +9372,19 @@ async function bareAgentDispatchTool(o) {
|
||||
summary
|
||||
})
|
||||
}
|
||||
if (
|
||||
typeof bareAgentLooksLikeQuestionDump === 'function' &&
|
||||
bareAgentLooksLikeQuestionDump(summary)
|
||||
) {
|
||||
appendProgress('task_complete_rejected_questions')
|
||||
return bareAgentJsonResult({
|
||||
ok: false,
|
||||
error: 'task_not_complete',
|
||||
hint:
|
||||
'That is a question for the operator, not a finish. Call write_file / move_path / list_directory and finish the goal. If blocked, return a BLOCKED REPORT (paths, tool errors, what exists, what is missing).',
|
||||
summary
|
||||
})
|
||||
}
|
||||
appendProgress('task_complete: ' + summary.slice(0, 200))
|
||||
onTaskComplete(summary || '(done)')
|
||||
return bareAgentJsonResult({
|
||||
@@ -9751,16 +9854,44 @@ async function bareAgentDispatchTool(o) {
|
||||
typeof bareAgentNormalizeGuestScript === 'function'
|
||||
? bareAgentNormalizeGuestScript(rawCode)
|
||||
: rawCode
|
||||
const scriptPath = paths.dir + '/_tmp_agent_run.mjs'
|
||||
const persistPath =
|
||||
(typeof args.path === 'string' && args.path.trim()) ||
|
||||
(typeof args.file_path === 'string' && args.file_path.trim()) ||
|
||||
(typeof args.save_as === 'string' && args.save_as.trim()) ||
|
||||
''
|
||||
const tempPath = paths.dir + '/_tmp_agent_run.mjs'
|
||||
let scriptPath = tempPath
|
||||
if (
|
||||
persistPath &&
|
||||
persistPath !== tempPath &&
|
||||
persistPath.startsWith('/') &&
|
||||
!persistPath.includes('..')
|
||||
) {
|
||||
const persist = await bareAgentDispatchTool({
|
||||
...o,
|
||||
toolName: 'write_file',
|
||||
argsJson: JSON.stringify({ path: persistPath, content: code })
|
||||
})
|
||||
let persistOk = false
|
||||
try {
|
||||
const pj = JSON.parse(persist)
|
||||
persistOk = Boolean(pj && pj.ok)
|
||||
} catch {
|
||||
persistOk = false
|
||||
}
|
||||
if (persistOk) scriptPath = persistPath
|
||||
}
|
||||
if (!vfs?.writeFile || !execLine) {
|
||||
return bareAgentJsonResult({ ok: false, error: 'vfs or execLine' })
|
||||
}
|
||||
appendProgress('run_js_script (' + code.length + ' chars)')
|
||||
const body =
|
||||
typeof ctx.b4a !== 'undefined' && ctx.b4a && typeof ctx.b4a.from === 'function'
|
||||
? ctx.b4a.from(code)
|
||||
: new TextEncoder().encode(code)
|
||||
await vfs.writeFile(scriptPath, body)
|
||||
appendProgress('run_js_script (' + code.length + ' chars) path=' + scriptPath)
|
||||
if (scriptPath === tempPath) {
|
||||
const body =
|
||||
typeof ctx.b4a !== 'undefined' && ctx.b4a && typeof ctx.b4a.from === 'function'
|
||||
? ctx.b4a.from(code)
|
||||
: new TextEncoder().encode(code)
|
||||
await vfs.writeFile(scriptPath, body)
|
||||
}
|
||||
/** Absolute path → kernel-runner runs .mjs like `./script.mjs` (no host `node` binary). captureExec adds stdout redirect. */
|
||||
const cmd = bareAgentShellQuote(scriptPath)
|
||||
const r = await captureExec(cmd, 60000)
|
||||
@@ -9789,8 +9920,29 @@ async function bareAgentDispatchTool(o) {
|
||||
stdout_stderr: text
|
||||
})
|
||||
}
|
||||
const persisted = scriptPath !== tempPath
|
||||
const persistHint = persisted
|
||||
? 'Script persisted and executed at ' + scriptPath
|
||||
: 'run_js_script only ran a throwaway temp file at ' +
|
||||
tempPath +
|
||||
'. That is NOT a user file. To create a lasting script call write_file({path, content}) then list_directory the destination.'
|
||||
return bareAgentJsonResult(
|
||||
r.ok === false ? r : { ok: true, stdout_stderr: r.stdout_stderr }
|
||||
r.ok === false
|
||||
? {
|
||||
ok: false,
|
||||
error: out.error || 'run_js_script_failed',
|
||||
stdout_stderr: text,
|
||||
ran_from: scriptPath,
|
||||
persisted_to: persisted ? scriptPath : null,
|
||||
hint: persistHint
|
||||
}
|
||||
: {
|
||||
ok: true,
|
||||
stdout_stderr: r.stdout_stderr,
|
||||
ran_from: scriptPath,
|
||||
persisted_to: persisted ? scriptPath : null,
|
||||
hint: persistHint
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -10014,26 +10166,118 @@ async function bareAgentDispatchTool(o) {
|
||||
}
|
||||
|
||||
if (toolName === 'move_path') {
|
||||
const from = typeof args.from_path === 'string' ? args.from_path : ''
|
||||
const to = typeof args.to_path === 'string' ? args.to_path : ''
|
||||
let from =
|
||||
(typeof args.from_path === 'string' && args.from_path.trim()) ||
|
||||
(typeof args.from === 'string' && args.from.trim()) ||
|
||||
(typeof args.src === 'string' && args.src.trim()) ||
|
||||
(typeof args.source === 'string' && args.source.trim()) ||
|
||||
(typeof args.old_path === 'string' && args.old_path.trim()) ||
|
||||
''
|
||||
let to =
|
||||
(typeof args.to_path === 'string' && args.to_path.trim()) ||
|
||||
(typeof args.to === 'string' && args.to.trim()) ||
|
||||
(typeof args.dest === 'string' && args.dest.trim()) ||
|
||||
(typeof args.destination === 'string' && args.destination.trim()) ||
|
||||
(typeof args.new_path === 'string' && args.new_path.trim()) ||
|
||||
''
|
||||
if (!from && paths.dir) {
|
||||
const tmp = paths.dir + '/_tmp_agent_run.mjs'
|
||||
try {
|
||||
if (vfs && typeof vfs.readFile === 'function') {
|
||||
const buf = await vfs.readFile(tmp)
|
||||
if (buf) from = tmp
|
||||
}
|
||||
} catch {
|
||||
/* no temp */
|
||||
}
|
||||
}
|
||||
if (!from || !to) {
|
||||
return bareAgentJsonResult({
|
||||
ok: false,
|
||||
error: 'from_and_to_required',
|
||||
hint: 'move_path needs from_path and to_path (absolute or ~/...). To rename the throwaway script, from_path=~/.agent/_tmp_agent_run.mjs to_path=~/test/bareos-cli.js'
|
||||
})
|
||||
}
|
||||
if (
|
||||
!bareAgentPathAllowedMutate(from, mutateDenyPrefixes) ||
|
||||
!bareAgentPathAllowedMutate(to, mutateDenyPrefixes) ||
|
||||
from.includes('..') ||
|
||||
to.includes('..')
|
||||
) {
|
||||
return bareAgentJsonResult({ ok: false, error: 'path_not_allowed' })
|
||||
return bareAgentJsonResult({ ok: false, error: 'path_not_allowed', from, to })
|
||||
}
|
||||
let finalTo = to
|
||||
try {
|
||||
const st =
|
||||
vfs && typeof vfs.lstat === 'function'
|
||||
? await vfs.lstat(to)
|
||||
: vfs && typeof vfs.stat === 'function'
|
||||
? await vfs.stat(to)
|
||||
: null
|
||||
const isDir =
|
||||
st &&
|
||||
((typeof st.isDirectory === 'function' && st.isDirectory()) ||
|
||||
(st && st.kind === 'dir'))
|
||||
if (isDir) {
|
||||
let base = from.split('/').filter(Boolean).pop() || 'file'
|
||||
if (base === '_tmp_agent_run.mjs') {
|
||||
const named =
|
||||
(typeof args.filename === 'string' && args.filename.trim()) ||
|
||||
(typeof args.name === 'string' && args.name.trim()) ||
|
||||
'cli.js'
|
||||
base = named.replace(/^.*\//, '')
|
||||
}
|
||||
finalTo = to.replace(/\/+$/, '') + '/' + base
|
||||
}
|
||||
} catch {
|
||||
/* dest does not exist yet — treat as file path */
|
||||
}
|
||||
if (!execLine) {
|
||||
return bareAgentJsonResult({ ok: false, error: 'execLine unavailable' })
|
||||
}
|
||||
appendProgress('move_path')
|
||||
appendProgress('move_path ' + from + ' -> ' + finalTo)
|
||||
const parent = finalTo.replace(/\/[^/]+$/, '')
|
||||
if (parent && parent !== finalTo && vfs && typeof vfs.mkdir === 'function') {
|
||||
try {
|
||||
await vfs.mkdir(parent, { recursive: true })
|
||||
} catch {
|
||||
/* optional */
|
||||
}
|
||||
}
|
||||
const cmd =
|
||||
'mv -- ' + bareAgentShellQuote(from) + ' ' + bareAgentShellQuote(to)
|
||||
'mv -- ' + bareAgentShellQuote(from) + ' ' + bareAgentShellQuote(finalTo)
|
||||
const r = await captureExec(cmd, 120000)
|
||||
return bareAgentJsonResult(
|
||||
r.ok === false ? r : { ok: true, stdout_stderr: r.stdout_stderr }
|
||||
)
|
||||
if (r && r.ok === false) {
|
||||
return bareAgentJsonResult({ ...r, from, to: finalTo })
|
||||
}
|
||||
let verified = false
|
||||
try {
|
||||
if (vfs && typeof vfs.lstat === 'function') verified = Boolean(await vfs.lstat(finalTo))
|
||||
else if (vfs && typeof vfs.stat === 'function') verified = Boolean(await vfs.stat(finalTo))
|
||||
else if (vfs && typeof vfs.readFile === 'function') {
|
||||
const got = await vfs.readFile(finalTo)
|
||||
verified = got != null
|
||||
}
|
||||
} catch {
|
||||
verified = false
|
||||
}
|
||||
if (!verified) {
|
||||
return bareAgentJsonResult({
|
||||
ok: false,
|
||||
error: 'move_not_visible',
|
||||
from,
|
||||
to: finalTo,
|
||||
stdout_stderr: r && r.stdout_stderr,
|
||||
hint: 'mv ran but destination is not visible. Retry with absolute paths and list_directory the target folder.'
|
||||
})
|
||||
}
|
||||
return bareAgentJsonResult({
|
||||
ok: true,
|
||||
from,
|
||||
to: finalTo,
|
||||
verified: true,
|
||||
stdout_stderr: r && r.stdout_stderr
|
||||
})
|
||||
}
|
||||
|
||||
if (toolName === 'delete_path') {
|
||||
@@ -13777,7 +14021,7 @@ Bare OS by Raven Scott (https://raven-scott.fyi). Repo: https://git.ssh.surf/snx
|
||||
WORK POLICY.
|
||||
- Keep every explicit requirement in view until it is done, superseded, or blocked. If blocked, say so plainly.
|
||||
- Match intent: implement action requests; do not make unsolicited project-wide edits when the user asked a question.
|
||||
- For clear, reversible local work, do it now. NEVER ASK for permission.
|
||||
- For clear, reversible local work, do it now. NEVER ASK for permission. Never ask "would you like me to". Pick a reasonable name and do it. Keep calling tools until the original request is verified (list_directory / file_stat / stdout). If you cannot finish, call task_complete with a BLOCKED REPORT: goal, every path tried, verbatim tool errors, what exists now, what is missing. Do not stop to ask questions.
|
||||
- Claim done, fixed, or tested only when a tool result supports it. Otherwise say what you did not verify.
|
||||
- Scope to what was asked. Comments are short and factual. No placeholders. Comments must not substitute for a fix.
|
||||
|
||||
@@ -13787,13 +14031,13 @@ 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. 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.
|
||||
- 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. run_js_script always writes a throwaway ~/.agent/_tmp_agent_run.mjs — that is NOT a user file. To create a lasting script in ~/test, call write_file({path:"~/test/name.js", content}) (or pass path= to run_js_script to persist). Then list_directory that folder. 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.
|
||||
- DISCORD CHANNEL: You have a Direct Message channel with the operator. Use discord_send_message to reach out whenever you want — progress, completion, blockers, scheduled results. Do not wait for them to message first. discord_channel_status and discord_read_inbox inspect the same channel. Only whitelisted users receive DMs.
|
||||
- Never print ~/.agent/config.json, API keys, seeds, or vault material.
|
||||
- ask_user_question is only for a real product choice the user must make. Never use it (or chat) to request permission.
|
||||
- ask_user_question is only for a real product choice the user must make. Never use it (or chat) to request permission. Never offer numbered menus ("Would you like me to: 1. …"). Execute.
|
||||
|
||||
CODING LOOP. Multi-step work: todo_write (merge=true). Large unknown surface: enter_plan_mode, write ~/.agent/plan.md, exit_plan_mode, then implement. Plan mode is read-only except that plan file. Do not stop after a plan-only reply — keep calling tools until verified.
|
||||
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.
|
||||
@@ -14152,6 +14396,18 @@ function bareAgentRefusalNudge() {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Bounce a question-menu / unverified file claim back into the tool loop.
|
||||
*/
|
||||
function bareAgentGoalDriveNudge(kind) {
|
||||
const k = String(kind || 'continue')
|
||||
return (
|
||||
'[harness] Do not ask the operator questions. Do not stop. kind=' +
|
||||
k +
|
||||
'. run_js_script is throwaway (~/.agent/_tmp_agent_run.mjs) — that is not a user file. Create lasting files with write_file({path, content}). Move/rename with move_path({from_path, to_path}). Then list_directory the destination and only then claim done. If blocked, task_complete with a BLOCKED REPORT: goal, paths tried, verbatim tool errors, what list_directory shows, what is missing. Call the next tool now.'
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Recover tool calls the provider streamed as plain text (Hermes / Qwen XML,
|
||||
* ```bash fences, Grok/Claude `bash` dumps) instead of `delta_tool_calls`.
|
||||
@@ -15638,6 +15894,13 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
|
||||
const maxIterBase = Number(configRef.current.max_iterations) || 64
|
||||
let iter = 0
|
||||
let instructionDumpNudges = 0
|
||||
let goalDriveNudges = 0
|
||||
let sawFileMutation = false
|
||||
let sawFileVerify = false
|
||||
const driveGoal =
|
||||
typeof bareAgentLooksLikeActionRequest === 'function'
|
||||
? bareAgentLooksLikeActionRequest(task)
|
||||
: true
|
||||
|
||||
for (;;) {
|
||||
if (masterAbort.signal.aborted) {
|
||||
@@ -16422,6 +16685,42 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
|
||||
await bareAgentSaveHistory(ctx, paths.history, messages)
|
||||
continue
|
||||
}
|
||||
const questionDump =
|
||||
typeof bareAgentLooksLikeQuestionDump === 'function' &&
|
||||
bareAgentLooksLikeQuestionDump(assistantContent)
|
||||
const unverifiedClaim =
|
||||
typeof bareAgentLooksLikeUnverifiedFileClaim === 'function' &&
|
||||
bareAgentLooksLikeUnverifiedFileClaim(assistantContent)
|
||||
const needsVerify = sawFileMutation && !sawFileVerify
|
||||
const neverStarted = driveGoal && !sawFileMutation && !sawFileVerify
|
||||
const shouldDrive =
|
||||
questionDump ||
|
||||
needsVerify ||
|
||||
(unverifiedClaim && !sawFileVerify) ||
|
||||
neverStarted
|
||||
if (goalDriveNudges < 5 && shouldDrive) {
|
||||
goalDriveNudges += 1
|
||||
const kind =
|
||||
goalDriveNudges >= 5
|
||||
? 'last_chance_report'
|
||||
: questionDump
|
||||
? 'questions'
|
||||
: needsVerify
|
||||
? 'need_list_directory'
|
||||
: unverifiedClaim
|
||||
? 'unverified_claim'
|
||||
: 'continue'
|
||||
messages.push({
|
||||
role: 'user',
|
||||
content:
|
||||
typeof bareAgentGoalDriveNudge === 'function'
|
||||
? bareAgentGoalDriveNudge(kind)
|
||||
: '[harness] Keep going. Call write_file / move_path / list_directory. Do not ask questions.'
|
||||
})
|
||||
appendProgress('goal_drive_nudge n=' + String(goalDriveNudges) + ' kind=' + kind)
|
||||
await bareAgentSaveHistory(ctx, paths.history, messages)
|
||||
continue
|
||||
}
|
||||
if (
|
||||
bareAgentAutonomousShouldContinue(configRef.current, {
|
||||
completed: completed,
|
||||
@@ -16520,6 +16819,35 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
|
||||
bareAgentWriteOut(ctx, stdout, spinner + '\r')
|
||||
statusLineActive = true
|
||||
|
||||
if (
|
||||
name === 'write_file' ||
|
||||
name === 'create_directory' ||
|
||||
name === 'move_path' ||
|
||||
name === 'copy_path' ||
|
||||
name === 'delete_path' ||
|
||||
name === 'edit_file' ||
|
||||
name === 'search_replace' ||
|
||||
name === 'apply_patch'
|
||||
) {
|
||||
sawFileMutation = true
|
||||
}
|
||||
if (name === 'run_js_script') {
|
||||
try {
|
||||
const a = JSON.parse(argsStr || '{}')
|
||||
if (a && (a.path || a.file_path || a.save_as)) sawFileMutation = true
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
if (
|
||||
name === 'list_directory' ||
|
||||
name === 'file_stat' ||
|
||||
name === 'read_file' ||
|
||||
name === 'glob_files'
|
||||
) {
|
||||
sawFileVerify = true
|
||||
}
|
||||
|
||||
let resultStr = await bareAgentDispatchTool({
|
||||
ctx,
|
||||
toolName: name,
|
||||
@@ -16532,6 +16860,23 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
|
||||
manCacheRef,
|
||||
onTaskComplete
|
||||
})
|
||||
if (name === 'task_complete') {
|
||||
let parsedTc = null
|
||||
try {
|
||||
parsedTc = JSON.parse(resultStr)
|
||||
} catch {
|
||||
parsedTc = null
|
||||
}
|
||||
if (parsedTc && parsedTc.ok && sawFileMutation && !sawFileVerify) {
|
||||
completed = false
|
||||
resultStr = JSON.stringify({
|
||||
ok: false,
|
||||
error: 'not_verified',
|
||||
hint:
|
||||
'You created or moved files but never listed them. Call list_directory on the destination, then task_complete with what it shows. If blocked, return a BLOCKED REPORT.'
|
||||
})
|
||||
}
|
||||
}
|
||||
if (typeof bareAgentRunHooks === 'function' && paths.hooks) {
|
||||
try {
|
||||
let parsedArgs = {}
|
||||
|
||||
Reference in New Issue
Block a user