feat(agent): add configurable reasoning stream and in-OS ops tools

Add configurable reasoning/process visibility to /bin/agent via ~/.agent/config.json and setup wizard prompts, including bounded output and optional tool trace display. Expand agent capabilities with operational tools for service/timer inspection, cron/audit log reads, boot policy and kernel extension resolution, plus a new seeded agent-ops skill and updated workspace docs/tests to support the new automation workflow.
This commit is contained in:
Raven Scott
2026-04-26 03:06:53 -04:00
parent 993c9a4387
commit 78dbe3e588
32 changed files with 2484 additions and 536 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"schemaVersion": 1,
"generatedAt": "2026-04-26T02:43:51.281Z",
"generatedAt": "2026-04-26T07:05:46.949Z",
"normativeManifest": "packages/bare-os-booter/lib/bare-module-manifest.json",
"buildTool": "packages/bare-os-bare-libs/build.mjs",
"bundles": [
@@ -0,0 +1,41 @@
# Agent OS Automation Next Slices
## `bare-agentd` initd service
- Add a long-lived `bare-agentd` unit with queue polling from `~/.agent/queue/`.
- Emit run reports to `~/.agent/reports/` and status snapshots to `/run/bare-os/agentd.json`.
- Support wake triggers from timer drop-ins and optional IPC events.
## Autonomy policy file
- Introduce `~/.agent/autonomy.json` with explicit allow/deny sections:
- shell mutation
- network egress
- host bridge routes
- destructive file ops
- Add policy-aware throttle controls (`maxActionsPerHour`, quiet windows, escalation mode).
## Provider reasoning adapters
- Normalize provider-specific reasoning fields into one internal event stream:
- OpenAI-compatible deltas
- Anthropic thinking summaries (when available)
- local model metadata adapters
- Keep hidden reasoning private when provider policy does not expose it.
- Preserve `reasoning_mode` semantics (`off`, `summary`, `trace`) across adapters.
## Host bridge route expansion
- Add audited `hrpc` route set for:
- desktop notifications
- local editor/file opener
- approved host command execution with allowlisted templates
- snapshot/export helpers for personal drive workflows
- Require route-level schemas and default-deny allowlists.
## Rollout checkpoints
1. Ship behind config flags (`show_reasoning`, route toggles, autonomy policy enabled=false).
2. Record audit logs for all bridge and mutation actions.
3. Add simulation tests for policy-denied and policy-allowed flows.
4. Promote to defaults only after operator feedback from staged environments.
+570 -8
View File
@@ -1092,7 +1092,11 @@ function bareAgentDefaultConfig() {
allow_delete: false,
require_confirm_token: '',
owner_name: '',
agent_label: ''
agent_label: '',
show_reasoning: false,
reasoning_mode: 'off',
reasoning_max_chars: 4000,
reasoning_include_tools: true
}
}
@@ -1126,7 +1130,11 @@ function bareAgentMergeConfig(defaults, src) {
'allow_delete',
'require_confirm_token',
'owner_name',
'agent_label'
'agent_label',
'show_reasoning',
'reasoning_mode',
'reasoning_max_chars',
'reasoning_include_tools'
])
for (const k of Object.keys(src)) {
if (k.startsWith('x-')) continue
@@ -1147,18 +1155,30 @@ function bareAgentMergeConfig(defaults, src) {
out[k] = String(val ?? '')
continue
}
if (k === 'reasoning_mode') {
const mode = String(val ?? '').trim().toLowerCase()
out.reasoning_mode =
mode === 'summary' || mode === 'trace' ? mode : 'off'
continue
}
if (
k === 'max_tokens' ||
k === 'temperature' ||
k === 'max_iterations' ||
k === 'tool_parallelism' ||
k === 'request_timeout_ms'
k === 'request_timeout_ms' ||
k === 'reasoning_max_chars'
) {
const n = Number(val)
out[k] = Number.isFinite(n) ? n : defaults[k]
continue
}
if (k === 'stream' || k === 'allow_delete') {
if (
k === 'stream' ||
k === 'allow_delete' ||
k === 'show_reasoning' ||
k === 'reasoning_include_tools'
) {
out[k] = Boolean(val)
continue
}
@@ -1192,7 +1212,11 @@ function bareAgentValidateConfigShape(raw) {
'allow_delete',
'require_confirm_token',
'owner_name',
'agent_label'
'agent_label',
'show_reasoning',
'reasoning_mode',
'reasoning_max_chars',
'reasoning_include_tools'
]
if (!known.includes(k)) {
throw new Error('unknown config key: ' + k)
@@ -1492,6 +1516,7 @@ var BARE_AGENT_SKILL_SEED_REL = Object.freeze([
'skills/p2p-os-status/SKILL.md',
'skills/bare-os-kernel-proc/SKILL.md',
'skills/bare-os-super-developer/SKILL.md',
'skills/agent-ops/SKILL.md',
'skills/holesail/SKILL.md',
'skills/hdms/SKILL.md'
])
@@ -2091,6 +2116,37 @@ async function bareAgentStreamChatCompletions(opts) {
type: 'delta_tool_calls',
tool_calls: toolCalls
})
const rc = delta.reasoning_content
if (typeof rc === 'string' && rc.length) {
onEvent({
type: 'delta_reasoning',
reasoning: rc
})
}
const r = delta.reasoning
if (typeof r === 'string' && r.length) {
onEvent({
type: 'delta_reasoning',
reasoning: r
})
} else if (Array.isArray(r)) {
for (const chunk of r) {
if (!chunk || typeof chunk !== 'object') continue
const ro = /** @type {Record<string, unknown>} */ (chunk)
const tx =
typeof ro.text === 'string'
? ro.text
: typeof ro.content === 'string'
? ro.content
: ''
if (tx) {
onEvent({
type: 'delta_reasoning',
reasoning: tx
})
}
}
}
}
if (finishReason)
@@ -3272,6 +3328,134 @@ function bareAgentToolDefinitions() {
}
}
},
{
type: 'function',
function: {
name: 'list_services',
description:
'List initd service definitions and current runtime phases from /proc/bare_os/initd_readiness.json when available.',
parameters: {
type: 'object',
properties: {}
}
}
},
{
type: 'function',
function: {
name: 'service_status',
description:
'Read one initd unit status by name from /proc/bare_os/initd_readiness.json and include journal hint paths when present.',
parameters: {
type: 'object',
properties: {
name: { type: 'string', description: 'Unit name, e.g. bare-cron' }
},
required: ['name']
}
}
},
{
type: 'function',
function: {
name: 'list_timers',
description:
'List user timer drop-ins from ~/.config/bare-os/timers and optionally include short file previews.',
parameters: {
type: 'object',
properties: {
include_preview: {
type: 'boolean',
description: 'Include bounded timer file text previews (default false)'
},
max_entries: {
type: 'integer',
description: 'Maximum timer files to return (default 128, max 512)'
}
}
}
}
},
{
type: 'function',
function: {
name: 'read_cron_log',
description:
'Read /var/log/bare-os/cron.log with bounded output and optional tail mode.',
parameters: {
type: 'object',
properties: {
max_chars: {
type: 'integer',
description: 'Maximum returned characters (default 12000)'
},
tail_only: {
type: 'boolean',
description: 'When true, return only the trailing max_chars slice'
}
}
}
}
},
{
type: 'function',
function: {
name: 'read_audit_log',
description:
'Read /var/log/bare-os/audit.log with bounded output and best-effort secret redaction.',
parameters: {
type: 'object',
properties: {
max_chars: {
type: 'integer',
description: 'Maximum returned characters (default 12000)'
},
tail_only: {
type: 'boolean',
description: 'When true, return only the trailing max_chars slice'
},
redact: {
type: 'boolean',
description: 'Apply lightweight token redaction (default true)'
}
}
}
}
},
{
type: 'function',
function: {
name: 'read_boot_policy',
description:
'Read /etc/bare-os/boot.policy.json and return text plus parsed JSON when available.',
parameters: {
type: 'object',
properties: {
max_chars: {
type: 'integer',
description: 'Maximum returned characters (default 20000)'
}
}
}
}
},
{
type: 'function',
function: {
name: 'read_kernel_extension_resolution',
description:
'Read /run/bare-os/kernel-ext-resolution.json for extension ordering, conflicts, and pin outcomes.',
parameters: {
type: 'object',
properties: {
max_chars: {
type: 'integer',
description: 'Maximum returned characters (default 20000)'
}
}
}
}
},
{
type: 'function',
function: {
@@ -4032,6 +4216,246 @@ async function bareAgentDispatchTool(o) {
}
}
if (toolName === 'list_services') {
appendProgress('list_services')
if (!vfs || typeof vfs.readFile !== 'function') {
return bareAgentJsonResult({ ok: false, error: 'vfs unavailable' })
}
let readinessText = ''
/** @type {Record<string, unknown> | null} */
let readinessJson = null
try {
const b = await vfs.readFile('/proc/bare_os/initd_readiness.json')
if (b && b.length) {
readinessText =
typeof ctx.b4a !== 'undefined' && ctx.b4a && typeof ctx.b4a.toString === 'function'
? ctx.b4a.toString(b)
: String(new TextDecoder().decode(b))
try {
const parsed = JSON.parse(readinessText)
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed))
readinessJson = /** @type {Record<string, unknown>} */ (parsed)
} catch {
/* ignore */
}
}
} catch {
/* ignore */
}
const units = Array.isArray(readinessJson?.units)
? /** @type {unknown[]} */ (readinessJson.units)
: []
const rows = units
.filter((u) => u && typeof u === 'object')
.map((u) => {
const o = /** @type {Record<string, unknown>} */ (u)
return {
name: String(o.name || ''),
phase: String(o.phase || ''),
startedAtMs:
typeof o.startedAtMs === 'number' ? o.startedAtMs : undefined,
error: typeof o.error === 'string' ? o.error : undefined
}
})
.filter((r) => r.name)
return bareAgentJsonResult({
ok: true,
source: '/proc/bare_os/initd_readiness.json',
count: rows.length,
units: rows,
note:
rows.length > 0
? 'Runtime units from initd readiness snapshot.'
: 'No parsed readiness units available.'
})
}
if (toolName === 'service_status') {
const name = typeof args.name === 'string' ? args.name.trim() : ''
if (!name) return bareAgentJsonResult({ ok: false, error: 'name_required' })
appendProgress('service_status ' + name)
if (!vfs || typeof vfs.readFile !== 'function') {
return bareAgentJsonResult({ ok: false, error: 'vfs unavailable' })
}
try {
const b = await vfs.readFile('/proc/bare_os/initd_readiness.json')
const t =
b && b.length
? typeof ctx.b4a !== 'undefined' &&
ctx.b4a &&
typeof ctx.b4a.toString === 'function'
? ctx.b4a.toString(b)
: String(new TextDecoder().decode(b))
: ''
const parsed = JSON.parse(t)
const units = Array.isArray(parsed?.units) ? parsed.units : []
const hit =
units.find((u) => u && typeof u === 'object' && String(u.name || '') === name) ||
null
if (!hit) {
return bareAgentJsonResult({
ok: false,
error: 'not_found',
source: '/proc/bare_os/initd_readiness.json'
})
}
const o = /** @type {Record<string, unknown>} */ (hit)
return bareAgentJsonResult({
ok: true,
status: {
name: String(o.name || ''),
phase: String(o.phase || ''),
startedAtMs:
typeof o.startedAtMs === 'number' ? o.startedAtMs : undefined,
error: typeof o.error === 'string' ? o.error : undefined
},
journal_hint: '/run/bare-os/unit-journal/' + name + '.ndjson'
})
} catch (e) {
const msg =
e && typeof e === 'object' && 'message' in e ? String(e.message) : String(e)
return bareAgentJsonResult({ ok: false, error: msg })
}
}
if (toolName === 'list_timers') {
const includePreview = Boolean(args.include_preview)
const maxEntries =
typeof args.max_entries === 'number' && Number.isFinite(args.max_entries)
? Math.min(Math.max(Math.floor(args.max_entries), 1), 512)
: 128
appendProgress('list_timers')
if (!vfs || typeof vfs.readdir !== 'function' || typeof vfs.readFile !== 'function') {
return bareAgentJsonResult({ ok: false, error: 'vfs unavailable' })
}
const dir = home + '/.config/bare-os/timers'
let names = []
try {
names = await vfs.readdir(dir)
} catch (e) {
const msg =
e && typeof e === 'object' && 'message' in e ? String(e.message) : String(e)
return bareAgentJsonResult({ ok: false, error: msg, path: dir })
}
const timerNames = names
.filter((n) => typeof n === 'string' && n.endsWith('.timer'))
.sort()
.slice(0, maxEntries)
/** @type {unknown[]} */
const timers = []
for (const name of timerNames) {
const path = dir + '/' + name
/** @type {Record<string, unknown>} */
const row = { name, path }
if (includePreview) {
try {
const b = await vfs.readFile(path)
const txt =
b && b.length
? typeof ctx.b4a !== 'undefined' &&
ctx.b4a &&
typeof ctx.b4a.toString === 'function'
? ctx.b4a.toString(b)
: String(new TextDecoder().decode(b))
: ''
row.preview = bareAgentTruncateChars(txt, 1200)
} catch (e) {
row.preview_error =
e && typeof e === 'object' && 'message' in e ? String(e.message) : String(e)
}
}
timers.push(row)
}
return bareAgentJsonResult({
ok: true,
path: dir,
count: timers.length,
timers
})
}
if (toolName === 'read_cron_log' || toolName === 'read_audit_log') {
const maxChars =
typeof args.max_chars === 'number' && Number.isFinite(args.max_chars)
? Math.min(Math.max(Math.floor(args.max_chars), 200), 80_000)
: 12_000
const tailOnly = Boolean(args.tail_only)
const redact = toolName === 'read_audit_log' ? args.redact !== false : false
const path =
toolName === 'read_audit_log'
? '/var/log/bare-os/audit.log'
: '/var/log/bare-os/cron.log'
appendProgress(toolName + ' ' + path)
if (!vfs || typeof vfs.readFile !== 'function') {
return bareAgentJsonResult({ ok: false, error: 'vfs unavailable' })
}
try {
const b = await vfs.readFile(path)
if (!b || !b.length) return bareAgentJsonResult({ ok: false, error: 'empty_or_missing' })
let t =
typeof ctx.b4a !== 'undefined' && ctx.b4a && typeof ctx.b4a.toString === 'function'
? ctx.b4a.toString(b)
: String(new TextDecoder().decode(b))
if (redact) {
t = t
.replace(/\bBearer\s+\S+/gi, 'Bearer <redacted>')
.replace(/\bsk-[a-zA-Z0-9]{16,}\b/g, '<redacted_sk>')
.replace(/\b([A-Z0-9_]*(KEY|TOKEN|SECRET|PASS)[A-Z0-9_]*)\s*=\s*([^\s]+)/gi, '$1=<redacted>')
}
const out = tailOnly ? t.slice(-maxChars) : bareAgentTruncateChars(t, maxChars)
return bareAgentJsonResult({
ok: true,
path,
text: out,
truncated: t.length > out.length
})
} catch (e) {
const msg =
e && typeof e === 'object' && 'message' in e ? String(e.message) : String(e)
return bareAgentJsonResult({ ok: false, error: msg })
}
}
if (toolName === 'read_boot_policy' || toolName === 'read_kernel_extension_resolution') {
const maxChars =
typeof args.max_chars === 'number' && Number.isFinite(args.max_chars)
? Math.min(Math.max(Math.floor(args.max_chars), 200), 120_000)
: 20_000
const path =
toolName === 'read_boot_policy'
? '/etc/bare-os/boot.policy.json'
: '/run/bare-os/kernel-ext-resolution.json'
appendProgress(toolName + ' ' + path)
if (!vfs || typeof vfs.readFile !== 'function') {
return bareAgentJsonResult({ ok: false, error: 'vfs unavailable' })
}
try {
const b = await vfs.readFile(path)
if (!b || !b.length) return bareAgentJsonResult({ ok: false, error: 'empty_or_missing' })
const t =
typeof ctx.b4a !== 'undefined' && ctx.b4a && typeof ctx.b4a.toString === 'function'
? ctx.b4a.toString(b)
: String(new TextDecoder().decode(b))
/** @type {unknown} */
let json = null
try {
json = JSON.parse(t)
} catch {
json = null
}
return bareAgentJsonResult({
ok: true,
path,
text: bareAgentTruncateChars(t, maxChars),
json
})
} catch (e) {
const msg =
e && typeof e === 'object' && 'message' in e ? String(e.message) : String(e)
return bareAgentJsonResult({ ok: false, error: msg })
}
}
if (toolName === 'get_swarm_peers') {
appendProgress('get_swarm_peers')
if (!vfs || typeof vfs.readFile !== 'function') {
@@ -4174,14 +4598,19 @@ function bareAgentMergeConfigPatch(base, patch) {
'allow_delete',
'require_confirm_token',
'owner_name',
'agent_label'
'agent_label',
'show_reasoning',
'reasoning_mode',
'reasoning_max_chars',
'reasoning_include_tools'
]
const numKeys = new Set([
'max_tokens',
'temperature',
'max_iterations',
'tool_parallelism',
'request_timeout_ms'
'request_timeout_ms',
'reasoning_max_chars'
])
for (const k of keys) {
if (Object.prototype.hasOwnProperty.call(patch, k)) {
@@ -4190,8 +4619,16 @@ function bareAgentMergeConfigPatch(base, patch) {
if (numKeys.has(k)) {
const n = Number(v)
if (Number.isFinite(n)) out[k] = n
} else if (k === 'stream' || k === 'allow_delete') {
} else if (
k === 'stream' ||
k === 'allow_delete' ||
k === 'show_reasoning' ||
k === 'reasoning_include_tools'
) {
out[k] = Boolean(v)
} else if (k === 'reasoning_mode') {
const mode = String(v ?? '').trim().toLowerCase()
out[k] = mode === 'summary' || mode === 'trace' ? mode : 'off'
} else if (k === 'require_confirm_token') {
out[k] = String(v ?? '')
} else {
@@ -4485,6 +4922,21 @@ function bareAgentFinalizeToolCalls(acc) {
return arr
}
/**
* @param {Record<string, unknown>} cfg
*/
function bareAgentReasoningSettings(cfg) {
const modeRaw = String(cfg.reasoning_mode || '').trim().toLowerCase()
const mode = modeRaw === 'summary' || modeRaw === 'trace' ? modeRaw : 'off'
const enabled = Boolean(cfg.show_reasoning) && mode !== 'off'
const maxChars =
typeof cfg.reasoning_max_chars === 'number' && Number.isFinite(cfg.reasoning_max_chars)
? Math.min(Math.max(Math.floor(cfg.reasoning_max_chars), 200), 80_000)
: 4000
const includeTools = cfg.reasoning_include_tools !== false
return { enabled, mode, maxChars, includeTools }
}
/**
* @param {Record<string, unknown>} ctx
* @param {string} argv0
@@ -4555,6 +5007,52 @@ async function bareAgentInteractiveSetup(ctx, argv0, paths, config, opts) {
'Provider label [' + String(config.provider || '') + ']: '
)) || ''
if (provRaw.trim()) config.provider = provRaw.trim()
const showReasoningRaw =
(await bareAgentPromptSetupLine(
ctx,
'Show thinking/process output? (y/N) [' +
(config.show_reasoning ? 'y' : 'n') +
']: '
)) || ''
{
const v = showReasoningRaw.trim().toLowerCase()
if (v === 'y' || v === 'yes' || v === '1' || v === 'true') config.show_reasoning = true
else if (v === 'n' || v === 'no' || v === '0' || v === 'false') config.show_reasoning = false
}
const modeRaw =
(await bareAgentPromptSetupLine(
ctx,
'Reasoning mode off|summary|trace [' +
String(config.reasoning_mode || 'off') +
']: '
)) || ''
if (modeRaw.trim()) {
const m = modeRaw.trim().toLowerCase()
if (m === 'off' || m === 'summary' || m === 'trace') config.reasoning_mode = m
}
const maxCharsRaw =
(await bareAgentPromptSetupLine(
ctx,
'Reasoning max chars [default ' +
String(config.reasoning_max_chars || 4000) +
']: '
)) || ''
if (maxCharsRaw.trim()) {
const n = Number(maxCharsRaw)
if (Number.isFinite(n) && n >= 200) config.reasoning_max_chars = Math.floor(n)
}
const includeToolsRaw =
(await bareAgentPromptSetupLine(
ctx,
'Include tool traces in process output? (Y/n) [' +
(config.reasoning_include_tools === false ? 'n' : 'y') +
']: '
)) || ''
{
const v = includeToolsRaw.trim().toLowerCase()
if (v === 'y' || v === 'yes' || v === '1' || v === 'true') config.reasoning_include_tools = true
else if (v === 'n' || v === 'no' || v === '0' || v === 'false') config.reasoning_include_tools = false
}
} catch (e) {
const msg =
e && typeof e === 'object' && 'message' in e ? String(e.message) : String(e)
@@ -4770,6 +5268,8 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
bareAgentNormalizeBaseUrl(String(configRef.current.rest_base_url || '')) +
'/chat/completions'
const tools = bareAgentToolDefinitions()
let reasoningSettings = bareAgentReasoningSettings(configRef.current)
let reasoningCharCount = 0
let suspended = replSuspendedForSetup
try {
@@ -4804,6 +5304,7 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
let iter = 0
for (;;) {
reasoningSettings = bareAgentReasoningSettings(configRef.current)
if (completed) break
iter++
if (iter > maxIter) {
@@ -4861,6 +5362,25 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
if (Array.isArray(arr)) {
for (const tc of arr) bareAgentMergeToolCallDelta(toolAcc, tc)
}
} else if (e.type === 'delta_reasoning' && reasoningSettings.enabled) {
const chunk = typeof e.reasoning === 'string' ? e.reasoning : ''
if (chunk && reasoningCharCount < reasoningSettings.maxChars) {
const remain = reasoningSettings.maxChars - reasoningCharCount
const out = chunk.slice(0, remain)
reasoningCharCount += out.length
if (out.length) {
bareAgentWriteOut(
ctx,
stdout,
'\n' +
bareEditSgr('dim', useColor) +
'[thinking] ' +
out +
EDIT_ANSI_RESET +
'\n'
)
}
}
} else if (e.type === 'usage') {
usageOut = e.usage
} else if (e.type === 'finish_reason') {
@@ -4923,6 +5443,19 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
/** @type {{ function?: { name?: string } }} */ (x).function?.name
).join(',')
)
if (reasoningSettings.enabled && reasoningSettings.mode === 'trace') {
bareAgentWriteOut(
ctx,
stdout,
bareEditSgr('dim', useColor) +
'\n[process] iteration ' +
String(iter) +
' finish_reason=' +
(finishReason || 'unknown') +
EDIT_ANSI_RESET +
'\n'
)
}
for (const tc of toolCallsArr) {
const fn = /** @type {{ id?: string, function?: { name?: string, arguments?: string } }} */ (
@@ -4931,6 +5464,20 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
const id = /** @type {{ id?: string }} */ (tc).id || ''
const name = fn?.name || ''
const argsStr = fn?.arguments || '{}'
if (reasoningSettings.enabled && reasoningSettings.mode === 'trace' && reasoningSettings.includeTools) {
const argsPreview = argsStr.length > 280 ? argsStr.slice(0, 280) + '…' : argsStr
bareAgentWriteOut(
ctx,
stdout,
bareEditSgr('dim', useColor) +
'[process] tool_call ' +
name +
' args=' +
argsPreview +
EDIT_ANSI_RESET +
'\n'
)
}
bareAgentWriteOut(
ctx,
stdout,
@@ -4965,6 +5512,21 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
tool_call_id: id,
content: resultStr
})
if (reasoningSettings.enabled && reasoningSettings.mode === 'trace' && reasoningSettings.includeTools) {
const resPreview =
resultStr.length > 360 ? resultStr.slice(0, 360) + '…' : resultStr
bareAgentWriteOut(
ctx,
stdout,
bareEditSgr('dim', useColor) +
'[process] tool_result ' +
name +
' ' +
resPreview +
EDIT_ANSI_RESET +
'\n'
)
}
if (completed) break
}
+1 -1
View File
@@ -1,7 +1,7 @@
{
"schema": 2,
"profileId": "bare-os-posix-like",
"generatedAt": "2026-04-26T02:43:49.731Z",
"generatedAt": "2026-04-26T07:05:45.727Z",
"note": "Sparse POSIX Issue 7 coverage hints for /bin utilities. Omitted command names are not yet profiled here.",
"commandIndex": [
{
+226 -226
View File
@@ -25,36 +25,36 @@
"compactEncoding"
]
},
{
"path": "/lib/bare/bundles/protomux.js",
"keys": [
"protomux"
]
},
{
"path": "/lib/bare/bundles/bareUrl.js",
"keys": [
"bareUrl"
]
},
{
"path": "/lib/bare/bundles/protomux.js",
"keys": [
"protomux"
]
},
{
"path": "/lib/bare/bundles/barePath.js",
"keys": [
"barePath"
]
},
{
"path": "/lib/bare/bundles/bareEvents.js",
"keys": [
"bareEvents"
]
},
{
"path": "/lib/bare/bundles/bareEncoding.js",
"keys": [
"bareEncoding"
]
},
{
"path": "/lib/bare/bundles/bareEvents.js",
"keys": [
"bareEvents"
]
},
{
"path": "/lib/bare/bundles/bareAbort.js",
"keys": [
@@ -67,18 +67,18 @@
"bareAbortController"
]
},
{
"path": "/lib/bare/bundles/bareAnsiEscapes.js",
"keys": [
"bareAnsiEscapes"
]
},
{
"path": "/lib/bare/bundles/bareAddonResolve.js",
"keys": [
"bareAddonResolve"
]
},
{
"path": "/lib/bare/bundles/bareAnsiEscapes.js",
"keys": [
"bareAnsiEscapes"
]
},
{
"path": "/lib/bare/bundles/bareReadline.js",
"keys": [
@@ -97,6 +97,12 @@
"bareAppKit"
]
},
{
"path": "/lib/bare/bundles/bareAsyncHooks.js",
"keys": [
"bareAsyncHooks"
]
},
{
"path": "/lib/bare/bundles/bareAssert.js",
"keys": [
@@ -109,48 +115,42 @@
"bareAtomics"
]
},
{
"path": "/lib/bare/bundles/bareAsyncHooks.js",
"keys": [
"bareAsyncHooks"
]
},
{
"path": "/lib/bare/bundles/fetch.js",
"keys": [
"fetch"
]
},
{
"path": "/lib/bare/bundles/bareBmp.js",
"keys": [
"bareBmp"
]
},
{
"path": "/lib/bare/bundles/bareBundle.js",
"keys": [
"bareBundle"
]
},
{
"path": "/lib/bare/bundles/bareApk.js",
"keys": [
"bareApk"
]
},
{
"path": "/lib/bare/bundles/bareBuffer.js",
"keys": [
"bareBuffer"
]
},
{
"path": "/lib/bare/bundles/bareBundleCompile.js",
"keys": [
"bareBundleCompile"
]
},
{
"path": "/lib/bare/bundles/bareBundle.js",
"keys": [
"bareBundle"
]
},
{
"path": "/lib/bare/bundles/bareBmp.js",
"keys": [
"bareBmp"
]
},
{
"path": "/lib/bare/bundles/bareBuffer.js",
"keys": [
"bareBuffer"
]
},
{
"path": "/lib/bare/bundles/bareBluetoothApple.js",
"keys": [
@@ -169,12 +169,6 @@
"bareChannel"
]
},
{
"path": "/lib/bare/bundles/bareBoot.js",
"keys": [
"bareBoot"
]
},
{
"path": "/lib/bare/bundles/bareBundleEvaluate.js",
"keys": [
@@ -182,9 +176,9 @@
]
},
{
"path": "/lib/bare/bundles/bareBundleId.js",
"path": "/lib/bare/bundles/bareBoot.js",
"keys": [
"bareBundleId"
"bareBoot"
]
},
{
@@ -193,12 +187,6 @@
"bareDebugLog"
]
},
{
"path": "/lib/bare/bundles/bareDaemon.js",
"keys": [
"bareDaemon"
]
},
{
"path": "/lib/bare/bundles/bareDelta.js",
"keys": [
@@ -206,9 +194,9 @@
]
},
{
"path": "/lib/bare/bundles/bareCov.js",
"path": "/lib/bare/bundles/bareBundleId.js",
"keys": [
"bareCov"
"bareBundleId"
]
},
{
@@ -218,15 +206,21 @@
]
},
{
"path": "/lib/bare/bundles/bareDns.js",
"path": "/lib/bare/bundles/bareCov.js",
"keys": [
"bareDns"
"bareCov"
]
},
{
"path": "/lib/bare/bundles/bareEnv.js",
"path": "/lib/bare/bundles/bareDaemon.js",
"keys": [
"bareEnv"
"bareDaemon"
]
},
{
"path": "/lib/bare/bundles/bareDns.js",
"keys": [
"bareDns"
]
},
{
@@ -236,21 +230,9 @@
]
},
{
"path": "/lib/bare/bundles/bareDgram.js",
"path": "/lib/bare/bundles/bareEnv.js",
"keys": [
"bareDgram"
]
},
{
"path": "/lib/bare/bundles/bareFormData.js",
"keys": [
"bareFormData"
]
},
{
"path": "/lib/bare/bundles/bareFfmpegEncodings.js",
"keys": [
"bareFfmpegEncodings"
"bareEnv"
]
},
{
@@ -260,21 +242,15 @@
]
},
{
"path": "/lib/bare/bundles/bareFileLogger.js",
"path": "/lib/bare/bundles/bareFfmpegEncodings.js",
"keys": [
"bareFileLogger"
"bareFfmpegEncodings"
]
},
{
"path": "/lib/bare/bundles/bareFormat.js",
"path": "/lib/bare/bundles/bareDgram.js",
"keys": [
"bareFormat"
]
},
{
"path": "/lib/bare/bundles/bareHrtime.js",
"keys": [
"bareHrtime"
"bareDgram"
]
},
{
@@ -284,9 +260,21 @@
]
},
{
"path": "/lib/bare/bundles/bareGtk.js",
"path": "/lib/bare/bundles/bareFormat.js",
"keys": [
"bareGtk"
"bareFormat"
]
},
{
"path": "/lib/bare/bundles/bareFormData.js",
"keys": [
"bareFormData"
]
},
{
"path": "/lib/bare/bundles/bareHrtime.js",
"keys": [
"bareHrtime"
]
},
{
@@ -296,15 +284,15 @@
]
},
{
"path": "/lib/bare/bundles/bareHttpParser.js",
"path": "/lib/bare/bundles/bareGtk.js",
"keys": [
"bareHttpParser"
"bareGtk"
]
},
{
"path": "/lib/bare/bundles/bareIco.js",
"path": "/lib/bare/bundles/bareFileLogger.js",
"keys": [
"bareIco"
"bareFileLogger"
]
},
{
@@ -314,9 +302,9 @@
]
},
{
"path": "/lib/bare/bundles/bareHttp1.js",
"path": "/lib/bare/bundles/bareIco.js",
"keys": [
"bareHttp1"
"bareIco"
]
},
{
@@ -326,9 +314,15 @@
]
},
{
"path": "/lib/bare/bundles/bareInspect.js",
"path": "/lib/bare/bundles/bareHttpParser.js",
"keys": [
"bareInspect"
"bareHttpParser"
]
},
{
"path": "/lib/bare/bundles/bareHttp1.js",
"keys": [
"bareHttp1"
]
},
{
@@ -337,24 +331,30 @@
"bareHttps"
]
},
{
"path": "/lib/bare/bundles/bareInspect.js",
"keys": [
"bareInspect"
]
},
{
"path": "/lib/bare/bundles/bareJpeg.js",
"keys": [
"bareJpeg"
]
},
{
"path": "/lib/bare/bundles/bareIntl.js",
"keys": [
"bareIntl"
]
},
{
"path": "/lib/bare/bundles/bareIpc.js",
"keys": [
"bareIpc"
]
},
{
"path": "/lib/bare/bundles/bareIntl.js",
"keys": [
"bareIntl"
]
},
{
"path": "/lib/bare/bundles/bareLogger.js",
"keys": [
@@ -368,9 +368,9 @@
]
},
{
"path": "/lib/bare/bundles/bareMake.js",
"path": "/lib/bare/bundles/bareLink.js",
"keys": [
"bareMake"
"bareLink"
]
},
{
@@ -380,9 +380,9 @@
]
},
{
"path": "/lib/bare/bundles/bareLink.js",
"path": "/lib/bare/bundles/bareMake.js",
"keys": [
"bareLink"
"bareMake"
]
},
{
@@ -391,12 +391,6 @@
"bareModuleResolve"
]
},
{
"path": "/lib/bare/bundles/bareModuleLexer.js",
"keys": [
"bareModuleLexer"
]
},
{
"path": "/lib/bare/bundles/bareModule.js",
"keys": [
@@ -410,21 +404,9 @@
]
},
{
"path": "/lib/bare/bundles/bareNative.js",
"path": "/lib/bare/bundles/bareModuleLexer.js",
"keys": [
"bareNative"
]
},
{
"path": "/lib/bare/bundles/bareModuleTraverse.js",
"keys": [
"bareModuleTraverse"
]
},
{
"path": "/lib/bare/bundles/bareNdk.js",
"keys": [
"bareNdk"
"bareModuleLexer"
]
},
{
@@ -434,15 +416,27 @@
]
},
{
"path": "/lib/bare/bundles/bareNet.js",
"path": "/lib/bare/bundles/bareModuleTraverse.js",
"keys": [
"bareNet"
"bareModuleTraverse"
]
},
{
"path": "/lib/bare/bundles/bareOs.js",
"path": "/lib/bare/bundles/bareNative.js",
"keys": [
"bareOs"
"bareNative"
]
},
{
"path": "/lib/bare/bundles/bareNdk.js",
"keys": [
"bareNdk"
]
},
{
"path": "/lib/bare/bundles/bareNet.js",
"keys": [
"bareNet"
]
},
{
@@ -452,15 +446,15 @@
]
},
{
"path": "/lib/bare/bundles/barePerformance.js",
"path": "/lib/bare/bundles/bareOs.js",
"keys": [
"barePerformance"
"bareOs"
]
},
{
"path": "/lib/bare/bundles/barePipe.js",
"path": "/lib/bare/bundles/barePerformance.js",
"keys": [
"barePipe"
"barePerformance"
]
},
{
@@ -476,9 +470,9 @@
]
},
{
"path": "/lib/bare/bundles/bareNodeRuntime.js",
"path": "/lib/bare/bundles/bareDev.js",
"keys": [
"bareNodeRuntime"
"bareDev"
]
},
{
@@ -488,9 +482,9 @@
]
},
{
"path": "/lib/bare/bundles/barePunycode.js",
"path": "/lib/bare/bundles/barePipe.js",
"keys": [
"barePunycode"
"barePipe"
]
},
{
@@ -500,15 +494,21 @@
]
},
{
"path": "/lib/bare/bundles/bareQueueMicrotask.js",
"path": "/lib/bare/bundles/barePunycode.js",
"keys": [
"bareQueueMicrotask"
"barePunycode"
]
},
{
"path": "/lib/bare/bundles/bareProcess.js",
"path": "/lib/bare/bundles/bareNodeRuntime.js",
"keys": [
"bareProcess"
"bareNodeRuntime"
]
},
{
"path": "/lib/bare/bundles/bareQueueMicrotask.js",
"keys": [
"bareQueueMicrotask"
]
},
{
@@ -523,24 +523,18 @@
"barePrebuild"
]
},
{
"path": "/lib/bare/bundles/bareProcess.js",
"keys": [
"bareProcess"
]
},
{
"path": "/lib/bare/bundles/bareRuntime.js",
"keys": [
"bareRuntime"
]
},
{
"path": "/lib/bare/bundles/bareRpc.js",
"keys": [
"bareRpc"
]
},
{
"path": "/lib/bare/bundles/bareDev.js",
"keys": [
"bareDev"
]
},
{
"path": "/lib/bare/bundles/bareSdl.js",
"keys": [
@@ -554,15 +548,15 @@
]
},
{
"path": "/lib/bare/bundles/barePromClient.js",
"path": "/lib/bare/bundles/bareRpc.js",
"keys": [
"barePromClient"
"bareRpc"
]
},
{
"path": "/lib/bare/bundles/bareSignals.js",
"path": "/lib/bare/bundles/barePromClient.js",
"keys": [
"bareSignals"
"barePromClient"
]
},
{
@@ -578,15 +572,21 @@
]
},
{
"path": "/lib/bare/bundles/bareSidecar.js",
"path": "/lib/bare/bundles/bareSignals.js",
"keys": [
"bareSidecar"
"bareSignals"
]
},
{
"path": "/lib/bare/bundles/bareStorage.js",
"path": "/lib/bare/bundles/bareStringDecoder.js",
"keys": [
"bareStorage"
"bareStringDecoder"
]
},
{
"path": "/lib/bare/bundles/bareSidecar.js",
"keys": [
"bareSidecar"
]
},
{
@@ -595,12 +595,6 @@
"bareStream"
]
},
{
"path": "/lib/bare/bundles/bareStdio.js",
"keys": [
"bareStdio"
]
},
{
"path": "/lib/bare/bundles/bareSvg.js",
"keys": [
@@ -608,9 +602,21 @@
]
},
{
"path": "/lib/bare/bundles/bareStringDecoder.js",
"path": "/lib/bare/bundles/bareStdio.js",
"keys": [
"bareStringDecoder"
"bareStdio"
]
},
{
"path": "/lib/bare/bundles/bareStorage.js",
"keys": [
"bareStorage"
]
},
{
"path": "/lib/bare/bundles/bareStructuredClone.js",
"keys": [
"bareStructuredClone"
]
},
{
@@ -625,30 +631,12 @@
"bareSystemLogger"
]
},
{
"path": "/lib/bare/bundles/bareStructuredClone.js",
"keys": [
"bareStructuredClone"
]
},
{
"path": "/lib/bare/bundles/bareTiff.js",
"keys": [
"bareTiff"
]
},
{
"path": "/lib/bare/bundles/bareTimers.js",
"keys": [
"bareTimers"
]
},
{
"path": "/lib/bare/bundles/bareTpl.js",
"keys": [
"bareTpl"
]
},
{
"path": "/lib/bare/bundles/bareSubprocess.js",
"keys": [
@@ -661,48 +649,54 @@
"bareTcp"
]
},
{
"path": "/lib/bare/bundles/bareTimers.js",
"keys": [
"bareTimers"
]
},
{
"path": "/lib/bare/bundles/bareTpl.js",
"keys": [
"bareTpl"
]
},
{
"path": "/lib/bare/bundles/bareType.js",
"keys": [
"bareType"
]
},
{
"path": "/lib/bare/bundles/bareUiKit.js",
"keys": [
"bareUiKit"
]
},
{
"path": "/lib/bare/bundles/bareTty.js",
"keys": [
"bareTty"
]
},
{
"path": "/lib/bare/bundles/bareThread.js",
"keys": [
"bareThread"
]
},
{
"path": "/lib/bare/bundles/bareUiKit.js",
"keys": [
"bareUiKit"
]
},
{
"path": "/lib/bare/bundles/bareTls.js",
"keys": [
"bareTls"
]
},
{
"path": "/lib/bare/bundles/bareTty.js",
"keys": [
"bareTty"
]
},
{
"path": "/lib/bare/bundles/bareUnpack.js",
"keys": [
"bareUnpack"
]
},
{
"path": "/lib/bare/bundles/bareV8.js",
"keys": [
"bareV8"
]
},
{
"path": "/lib/bare/bundles/bareVm.js",
"keys": [
@@ -710,9 +704,9 @@
]
},
{
"path": "/lib/bare/bundles/bareUnionBundle.js",
"path": "/lib/bare/bundles/bareV8.js",
"keys": [
"bareUnionBundle"
"bareV8"
]
},
{
@@ -733,30 +727,30 @@
"bareWebKitGtk"
]
},
{
"path": "/lib/bare/bundles/bareUtils.js",
"keys": [
"bareUtils"
]
},
{
"path": "/lib/bare/bundles/bareWebp.js",
"keys": [
"bareWebp"
]
},
{
"path": "/lib/bare/bundles/bareV8ToIstanbul.js",
"keys": [
"bareV8ToIstanbul"
]
},
{
"path": "/lib/bare/bundles/bareWinUi.js",
"keys": [
"bareWinUi"
]
},
{
"path": "/lib/bare/bundles/bareUnionBundle.js",
"keys": [
"bareUnionBundle"
]
},
{
"path": "/lib/bare/bundles/bareUtils.js",
"keys": [
"bareUtils"
]
},
{
"path": "/lib/bare/bundles/bareXdiff.js",
"keys": [
@@ -764,15 +758,15 @@
]
},
{
"path": "/lib/bare/bundles/bareWhich.js",
"path": "/lib/bare/bundles/bareV8ToIstanbul.js",
"keys": [
"bareWhich"
"bareV8ToIstanbul"
]
},
{
"path": "/lib/bare/bundles/bareZlib.js",
"path": "/lib/bare/bundles/bareWhich.js",
"keys": [
"bareZlib"
"bareWhich"
]
},
{
@@ -787,6 +781,12 @@
"bareWorker"
]
},
{
"path": "/lib/bare/bundles/bareZlib.js",
"keys": [
"bareZlib"
]
},
{
"path": "/lib/bare/bundles/bareZmq.js",
"keys": [
@@ -1607,8 +1607,8 @@
],
"bundleProvenance": {
"schemaVersion": 1,
"generatedAt": "2026-04-26T02:43:51.268Z",
"gitCommit": "51b3b97bc027b9ff4744789bd661bc22f00695dd",
"generatedAt": "2026-04-26T07:05:46.937Z",
"gitCommit": "993c9a438772334e016ef8d822c5272a86bfbe13",
"nodeVersion": "v20.20.2",
"bundleTier": "all",
"normativeManifest": "packages/bare-os-booter/lib/bare-module-manifest.json",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"schema": 1,
"atMs": 1777171429730,
"atMs": 1777187145726,
"commands": [
"agent",
"arch",
+12
View File
@@ -7,3 +7,15 @@ Summarize drive health, peer connections, kernel status, and recent logs.
## /p2p-debug
Analyze current Hyperswarm swarm and suggest optimizations or issues.
## /ops-diagnose
Inspect initd unit phases, timer drop-ins, cron/audit logs, boot policy, and kernel extension resolution; summarize root causes and safe next actions.
## /reasoning-on
Enable process visibility with `edit_agent_config` (`show_reasoning=true`, `reasoning_mode=trace`) and keep output bounded.
## /reasoning-off
Disable reasoning/process output with `edit_agent_config` (`show_reasoning=false`, `reasoning_mode=off`).
+9 -2
View File
@@ -10,7 +10,7 @@ This tree follows the **agent** Markdown workspace convention: “soul” files
| **`~/.agent/workspace/skills/`** | Modular **skills** — one folder per skill, each with **`SKILL.md`** (optional YAML frontmatter) |
| **`~/.agent/workspace/memory/`** | Daily append logs `YYYY-MM-DD.md` (optional) |
| **`~/.agent/skills/`** | Optional **global** skills (lower precedence than `workspace/skills/` when names collide) |
| **`~/.agent/config.json`** | API URL, key, model (existing agent config) |
| **`~/.agent/config.json`** | API URL, key, model, and reasoning/process visibility controls |
| **`~/.agent/skill-loader.js`** | Host stub for `discoverSkills` / `loadSkill` (in-image agent uses bundled discovery + **`read_skill`** tool) |
| **`~/.agent/loader.js`** | Stub / hook for **host-side** experimentation (not used by `/bin/agent` bundle) |
| **`~/.agent/index.js`** | Stub factory reference (in-image agent uses built-in loader) |
@@ -22,10 +22,17 @@ This tree follows the **agent** Markdown workspace convention: “soul” files
3. During a session, the model loads the full document with the **`read_skill`** tool (do not paste huge skills into the user channel unless asked).
4. Shared skills can live under **`~/.agent/skills/`**; keep **`workspace/skills/`** for machine-local or repo-specific behavior.
Seeded examples in this repo (under **`skills/`**): **`p2p-os-status`**, **`bare-os-kernel-proc`**, **`bare-os-super-developer`**, **`holesail`** (managed **`state.json`**, **`seed`**/**`key`**, stock **`bare-www-*`** / **`bare-ssh-*`**), and **`hdms`** (Hyperdrive mounts and invite/pair).
Seeded examples in this repo (under **`skills/`**): **`p2p-os-status`**, **`bare-os-kernel-proc`**, **`bare-os-super-developer`**, **`agent-ops`**, **`holesail`** (managed **`state.json`**, **`seed`**/**`key`**, stock **`bare-www-*`** / **`bare-ssh-*`**), and **`hdms`** (Hyperdrive mounts and invite/pair).
After **`agent --config`** / **`--setup`** (or changing **`owner_name`** / **`agent_label`** via **`edit_agent_config`**), **`IDENTITY.md`** and **`USER.md`** are regenerated from **`config.json`** so the workspace matches the operator and agent label.
Reasoning/process visibility is configurable in `config.json`:
- `show_reasoning` — master toggle
- `reasoning_mode``off` / `summary` / `trace`
- `reasoning_max_chars` — bounded reasoning output
- `reasoning_include_tools` — include tool traces in process stream
## Editing
1. Change files under **`~/.agent/workspace/`** on your **personal** drive.
+11
View File
@@ -3,11 +3,22 @@
## Core OS tools
- **VFS / Hyperdrive** — read/write paths via agent tools (`read_file`, `write_file`, `list_directory`, …) on system and personal drives.
- **Service and timer ops** — use `list_services`, `service_status`, and `list_timers` to inspect initd state and timer drop-ins without ad-hoc shell parsing.
- **Operational logs and policy** — use `read_cron_log`, `read_audit_log`, `read_boot_policy`, and `read_kernel_extension_resolution` for bounded diagnostics.
- **`web_fetch`** — live `http(s)` fetches **only** when the operator allows them (`ctx.httpFetch`, `BARE_OS_HTTP_ALLOWLIST` / denylist). Same policy as delegated `curl` / `wget`.
- **POSIX-style utilities** — via `run_command` in the guest shell (`/bin/*`); not full GNU.
- **Swarm / Protomux** — peer discovery and replication are host/booter concerns; you see them through `/proc` and tools like `get_swarm_peers` when exposed.
- **Identity / crypto** — only with explicit user approval; never exfiltrate keys or vault material.
## Reasoning / process visibility
- Runtime process visibility can be configured in `~/.agent/config.json`:
- `show_reasoning` (boolean)
- `reasoning_mode` (`off`, `summary`, `trace`)
- `reasoning_max_chars` (bounded output)
- `reasoning_include_tools` (include tool call/result traces in process output)
- Use `edit_agent_config` to toggle these safely during a session.
## Skills system
The agent has access to modular **skills** under `~/.agent/workspace/skills/` (and optionally shared skills under `~/.agent/skills/`).
@@ -0,0 +1,31 @@
---
name: agent-ops
version: 1.0.0
description: Diagnose Bare OS runtime state using agent operations tools for services, timers, logs, boot policy, and extension resolution.
tags: [bare-os, operations, initd, cron, audit, diagnostics]
requires: [list_services, service_status, list_timers, read_cron_log, read_audit_log, read_boot_policy, read_kernel_extension_resolution]
---
# agent-ops
Use this skill for operational diagnostics and health checks inside Bare OS.
## Workflow
1. Start with service state:
- `list_services`
- `service_status` for any unit in failed/inactive phase.
2. Inspect scheduling:
- `list_timers` for `~/.config/bare-os/timers/*.timer`
- `read_cron_log` for runtime scheduler failures.
3. Check security/provenance controls:
- `read_boot_policy`
- `read_kernel_extension_resolution`
4. If behavior looks suspicious, read `read_audit_log` (bounded + redacted).
## Output Contract
- Report observed state first (services, timers, policies, extension resolution).
- Separate confirmed facts from hypotheses.
- Suggest safe next actions with minimal blast radius.
- Avoid destructive recommendations unless explicitly requested.
File diff suppressed because one or more lines are too long
@@ -133,6 +133,37 @@ async function bareAgentStreamChatCompletions(opts) {
type: 'delta_tool_calls',
tool_calls: toolCalls
})
const rc = delta.reasoning_content
if (typeof rc === 'string' && rc.length) {
onEvent({
type: 'delta_reasoning',
reasoning: rc
})
}
const r = delta.reasoning
if (typeof r === 'string' && r.length) {
onEvent({
type: 'delta_reasoning',
reasoning: r
})
} else if (Array.isArray(r)) {
for (const chunk of r) {
if (!chunk || typeof chunk !== 'object') continue
const ro = /** @type {Record<string, unknown>} */ (chunk)
const tx =
typeof ro.text === 'string'
? ro.text
: typeof ro.content === 'string'
? ro.content
: ''
if (tx) {
onEvent({
type: 'delta_reasoning',
reasoning: tx
})
}
}
}
}
if (finishReason)
+29 -5
View File
@@ -57,7 +57,11 @@ function bareAgentDefaultConfig() {
allow_delete: false,
require_confirm_token: '',
owner_name: '',
agent_label: ''
agent_label: '',
show_reasoning: false,
reasoning_mode: 'off',
reasoning_max_chars: 4000,
reasoning_include_tools: true
}
}
@@ -91,7 +95,11 @@ function bareAgentMergeConfig(defaults, src) {
'allow_delete',
'require_confirm_token',
'owner_name',
'agent_label'
'agent_label',
'show_reasoning',
'reasoning_mode',
'reasoning_max_chars',
'reasoning_include_tools'
])
for (const k of Object.keys(src)) {
if (k.startsWith('x-')) continue
@@ -112,18 +120,30 @@ function bareAgentMergeConfig(defaults, src) {
out[k] = String(val ?? '')
continue
}
if (k === 'reasoning_mode') {
const mode = String(val ?? '').trim().toLowerCase()
out.reasoning_mode =
mode === 'summary' || mode === 'trace' ? mode : 'off'
continue
}
if (
k === 'max_tokens' ||
k === 'temperature' ||
k === 'max_iterations' ||
k === 'tool_parallelism' ||
k === 'request_timeout_ms'
k === 'request_timeout_ms' ||
k === 'reasoning_max_chars'
) {
const n = Number(val)
out[k] = Number.isFinite(n) ? n : defaults[k]
continue
}
if (k === 'stream' || k === 'allow_delete') {
if (
k === 'stream' ||
k === 'allow_delete' ||
k === 'show_reasoning' ||
k === 'reasoning_include_tools'
) {
out[k] = Boolean(val)
continue
}
@@ -157,7 +177,11 @@ function bareAgentValidateConfigShape(raw) {
'allow_delete',
'require_confirm_token',
'owner_name',
'agent_label'
'agent_label',
'show_reasoning',
'reasoning_mode',
'reasoning_max_chars',
'reasoning_include_tools'
]
if (!known.includes(k)) {
throw new Error('unknown config key: ' + k)
+384 -3
View File
@@ -453,6 +453,134 @@ function bareAgentToolDefinitions() {
}
}
},
{
type: 'function',
function: {
name: 'list_services',
description:
'List initd service definitions and current runtime phases from /proc/bare_os/initd_readiness.json when available.',
parameters: {
type: 'object',
properties: {}
}
}
},
{
type: 'function',
function: {
name: 'service_status',
description:
'Read one initd unit status by name from /proc/bare_os/initd_readiness.json and include journal hint paths when present.',
parameters: {
type: 'object',
properties: {
name: { type: 'string', description: 'Unit name, e.g. bare-cron' }
},
required: ['name']
}
}
},
{
type: 'function',
function: {
name: 'list_timers',
description:
'List user timer drop-ins from ~/.config/bare-os/timers and optionally include short file previews.',
parameters: {
type: 'object',
properties: {
include_preview: {
type: 'boolean',
description: 'Include bounded timer file text previews (default false)'
},
max_entries: {
type: 'integer',
description: 'Maximum timer files to return (default 128, max 512)'
}
}
}
}
},
{
type: 'function',
function: {
name: 'read_cron_log',
description:
'Read /var/log/bare-os/cron.log with bounded output and optional tail mode.',
parameters: {
type: 'object',
properties: {
max_chars: {
type: 'integer',
description: 'Maximum returned characters (default 12000)'
},
tail_only: {
type: 'boolean',
description: 'When true, return only the trailing max_chars slice'
}
}
}
}
},
{
type: 'function',
function: {
name: 'read_audit_log',
description:
'Read /var/log/bare-os/audit.log with bounded output and best-effort secret redaction.',
parameters: {
type: 'object',
properties: {
max_chars: {
type: 'integer',
description: 'Maximum returned characters (default 12000)'
},
tail_only: {
type: 'boolean',
description: 'When true, return only the trailing max_chars slice'
},
redact: {
type: 'boolean',
description: 'Apply lightweight token redaction (default true)'
}
}
}
}
},
{
type: 'function',
function: {
name: 'read_boot_policy',
description:
'Read /etc/bare-os/boot.policy.json and return text plus parsed JSON when available.',
parameters: {
type: 'object',
properties: {
max_chars: {
type: 'integer',
description: 'Maximum returned characters (default 20000)'
}
}
}
}
},
{
type: 'function',
function: {
name: 'read_kernel_extension_resolution',
description:
'Read /run/bare-os/kernel-ext-resolution.json for extension ordering, conflicts, and pin outcomes.',
parameters: {
type: 'object',
properties: {
max_chars: {
type: 'integer',
description: 'Maximum returned characters (default 20000)'
}
}
}
}
},
{
type: 'function',
function: {
@@ -1213,6 +1341,246 @@ async function bareAgentDispatchTool(o) {
}
}
if (toolName === 'list_services') {
appendProgress('list_services')
if (!vfs || typeof vfs.readFile !== 'function') {
return bareAgentJsonResult({ ok: false, error: 'vfs unavailable' })
}
let readinessText = ''
/** @type {Record<string, unknown> | null} */
let readinessJson = null
try {
const b = await vfs.readFile('/proc/bare_os/initd_readiness.json')
if (b && b.length) {
readinessText =
typeof ctx.b4a !== 'undefined' && ctx.b4a && typeof ctx.b4a.toString === 'function'
? ctx.b4a.toString(b)
: String(new TextDecoder().decode(b))
try {
const parsed = JSON.parse(readinessText)
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed))
readinessJson = /** @type {Record<string, unknown>} */ (parsed)
} catch {
/* ignore */
}
}
} catch {
/* ignore */
}
const units = Array.isArray(readinessJson?.units)
? /** @type {unknown[]} */ (readinessJson.units)
: []
const rows = units
.filter((u) => u && typeof u === 'object')
.map((u) => {
const o = /** @type {Record<string, unknown>} */ (u)
return {
name: String(o.name || ''),
phase: String(o.phase || ''),
startedAtMs:
typeof o.startedAtMs === 'number' ? o.startedAtMs : undefined,
error: typeof o.error === 'string' ? o.error : undefined
}
})
.filter((r) => r.name)
return bareAgentJsonResult({
ok: true,
source: '/proc/bare_os/initd_readiness.json',
count: rows.length,
units: rows,
note:
rows.length > 0
? 'Runtime units from initd readiness snapshot.'
: 'No parsed readiness units available.'
})
}
if (toolName === 'service_status') {
const name = typeof args.name === 'string' ? args.name.trim() : ''
if (!name) return bareAgentJsonResult({ ok: false, error: 'name_required' })
appendProgress('service_status ' + name)
if (!vfs || typeof vfs.readFile !== 'function') {
return bareAgentJsonResult({ ok: false, error: 'vfs unavailable' })
}
try {
const b = await vfs.readFile('/proc/bare_os/initd_readiness.json')
const t =
b && b.length
? typeof ctx.b4a !== 'undefined' &&
ctx.b4a &&
typeof ctx.b4a.toString === 'function'
? ctx.b4a.toString(b)
: String(new TextDecoder().decode(b))
: ''
const parsed = JSON.parse(t)
const units = Array.isArray(parsed?.units) ? parsed.units : []
const hit =
units.find((u) => u && typeof u === 'object' && String(u.name || '') === name) ||
null
if (!hit) {
return bareAgentJsonResult({
ok: false,
error: 'not_found',
source: '/proc/bare_os/initd_readiness.json'
})
}
const o = /** @type {Record<string, unknown>} */ (hit)
return bareAgentJsonResult({
ok: true,
status: {
name: String(o.name || ''),
phase: String(o.phase || ''),
startedAtMs:
typeof o.startedAtMs === 'number' ? o.startedAtMs : undefined,
error: typeof o.error === 'string' ? o.error : undefined
},
journal_hint: '/run/bare-os/unit-journal/' + name + '.ndjson'
})
} catch (e) {
const msg =
e && typeof e === 'object' && 'message' in e ? String(e.message) : String(e)
return bareAgentJsonResult({ ok: false, error: msg })
}
}
if (toolName === 'list_timers') {
const includePreview = Boolean(args.include_preview)
const maxEntries =
typeof args.max_entries === 'number' && Number.isFinite(args.max_entries)
? Math.min(Math.max(Math.floor(args.max_entries), 1), 512)
: 128
appendProgress('list_timers')
if (!vfs || typeof vfs.readdir !== 'function' || typeof vfs.readFile !== 'function') {
return bareAgentJsonResult({ ok: false, error: 'vfs unavailable' })
}
const dir = home + '/.config/bare-os/timers'
let names = []
try {
names = await vfs.readdir(dir)
} catch (e) {
const msg =
e && typeof e === 'object' && 'message' in e ? String(e.message) : String(e)
return bareAgentJsonResult({ ok: false, error: msg, path: dir })
}
const timerNames = names
.filter((n) => typeof n === 'string' && n.endsWith('.timer'))
.sort()
.slice(0, maxEntries)
/** @type {unknown[]} */
const timers = []
for (const name of timerNames) {
const path = dir + '/' + name
/** @type {Record<string, unknown>} */
const row = { name, path }
if (includePreview) {
try {
const b = await vfs.readFile(path)
const txt =
b && b.length
? typeof ctx.b4a !== 'undefined' &&
ctx.b4a &&
typeof ctx.b4a.toString === 'function'
? ctx.b4a.toString(b)
: String(new TextDecoder().decode(b))
: ''
row.preview = bareAgentTruncateChars(txt, 1200)
} catch (e) {
row.preview_error =
e && typeof e === 'object' && 'message' in e ? String(e.message) : String(e)
}
}
timers.push(row)
}
return bareAgentJsonResult({
ok: true,
path: dir,
count: timers.length,
timers
})
}
if (toolName === 'read_cron_log' || toolName === 'read_audit_log') {
const maxChars =
typeof args.max_chars === 'number' && Number.isFinite(args.max_chars)
? Math.min(Math.max(Math.floor(args.max_chars), 200), 80_000)
: 12_000
const tailOnly = Boolean(args.tail_only)
const redact = toolName === 'read_audit_log' ? args.redact !== false : false
const path =
toolName === 'read_audit_log'
? '/var/log/bare-os/audit.log'
: '/var/log/bare-os/cron.log'
appendProgress(toolName + ' ' + path)
if (!vfs || typeof vfs.readFile !== 'function') {
return bareAgentJsonResult({ ok: false, error: 'vfs unavailable' })
}
try {
const b = await vfs.readFile(path)
if (!b || !b.length) return bareAgentJsonResult({ ok: false, error: 'empty_or_missing' })
let t =
typeof ctx.b4a !== 'undefined' && ctx.b4a && typeof ctx.b4a.toString === 'function'
? ctx.b4a.toString(b)
: String(new TextDecoder().decode(b))
if (redact) {
t = t
.replace(/\bBearer\s+\S+/gi, 'Bearer <redacted>')
.replace(/\bsk-[a-zA-Z0-9]{16,}\b/g, '<redacted_sk>')
.replace(/\b([A-Z0-9_]*(KEY|TOKEN|SECRET|PASS)[A-Z0-9_]*)\s*=\s*([^\s]+)/gi, '$1=<redacted>')
}
const out = tailOnly ? t.slice(-maxChars) : bareAgentTruncateChars(t, maxChars)
return bareAgentJsonResult({
ok: true,
path,
text: out,
truncated: t.length > out.length
})
} catch (e) {
const msg =
e && typeof e === 'object' && 'message' in e ? String(e.message) : String(e)
return bareAgentJsonResult({ ok: false, error: msg })
}
}
if (toolName === 'read_boot_policy' || toolName === 'read_kernel_extension_resolution') {
const maxChars =
typeof args.max_chars === 'number' && Number.isFinite(args.max_chars)
? Math.min(Math.max(Math.floor(args.max_chars), 200), 120_000)
: 20_000
const path =
toolName === 'read_boot_policy'
? '/etc/bare-os/boot.policy.json'
: '/run/bare-os/kernel-ext-resolution.json'
appendProgress(toolName + ' ' + path)
if (!vfs || typeof vfs.readFile !== 'function') {
return bareAgentJsonResult({ ok: false, error: 'vfs unavailable' })
}
try {
const b = await vfs.readFile(path)
if (!b || !b.length) return bareAgentJsonResult({ ok: false, error: 'empty_or_missing' })
const t =
typeof ctx.b4a !== 'undefined' && ctx.b4a && typeof ctx.b4a.toString === 'function'
? ctx.b4a.toString(b)
: String(new TextDecoder().decode(b))
/** @type {unknown} */
let json = null
try {
json = JSON.parse(t)
} catch {
json = null
}
return bareAgentJsonResult({
ok: true,
path,
text: bareAgentTruncateChars(t, maxChars),
json
})
} catch (e) {
const msg =
e && typeof e === 'object' && 'message' in e ? String(e.message) : String(e)
return bareAgentJsonResult({ ok: false, error: msg })
}
}
if (toolName === 'get_swarm_peers') {
appendProgress('get_swarm_peers')
if (!vfs || typeof vfs.readFile !== 'function') {
@@ -1355,14 +1723,19 @@ function bareAgentMergeConfigPatch(base, patch) {
'allow_delete',
'require_confirm_token',
'owner_name',
'agent_label'
'agent_label',
'show_reasoning',
'reasoning_mode',
'reasoning_max_chars',
'reasoning_include_tools'
]
const numKeys = new Set([
'max_tokens',
'temperature',
'max_iterations',
'tool_parallelism',
'request_timeout_ms'
'request_timeout_ms',
'reasoning_max_chars'
])
for (const k of keys) {
if (Object.prototype.hasOwnProperty.call(patch, k)) {
@@ -1371,8 +1744,16 @@ function bareAgentMergeConfigPatch(base, patch) {
if (numKeys.has(k)) {
const n = Number(v)
if (Number.isFinite(n)) out[k] = n
} else if (k === 'stream' || k === 'allow_delete') {
} else if (
k === 'stream' ||
k === 'allow_delete' ||
k === 'show_reasoning' ||
k === 'reasoning_include_tools'
) {
out[k] = Boolean(v)
} else if (k === 'reasoning_mode') {
const mode = String(v ?? '').trim().toLowerCase()
out[k] = mode === 'summary' || mode === 'trace' ? mode : 'off'
} else if (k === 'require_confirm_token') {
out[k] = String(v ?? '')
} else {
+125
View File
@@ -258,6 +258,21 @@ function bareAgentFinalizeToolCalls(acc) {
return arr
}
/**
* @param {Record<string, unknown>} cfg
*/
function bareAgentReasoningSettings(cfg) {
const modeRaw = String(cfg.reasoning_mode || '').trim().toLowerCase()
const mode = modeRaw === 'summary' || modeRaw === 'trace' ? modeRaw : 'off'
const enabled = Boolean(cfg.show_reasoning) && mode !== 'off'
const maxChars =
typeof cfg.reasoning_max_chars === 'number' && Number.isFinite(cfg.reasoning_max_chars)
? Math.min(Math.max(Math.floor(cfg.reasoning_max_chars), 200), 80_000)
: 4000
const includeTools = cfg.reasoning_include_tools !== false
return { enabled, mode, maxChars, includeTools }
}
/**
* @param {Record<string, unknown>} ctx
* @param {string} argv0
@@ -328,6 +343,52 @@ async function bareAgentInteractiveSetup(ctx, argv0, paths, config, opts) {
'Provider label [' + String(config.provider || '') + ']: '
)) || ''
if (provRaw.trim()) config.provider = provRaw.trim()
const showReasoningRaw =
(await bareAgentPromptSetupLine(
ctx,
'Show thinking/process output? (y/N) [' +
(config.show_reasoning ? 'y' : 'n') +
']: '
)) || ''
{
const v = showReasoningRaw.trim().toLowerCase()
if (v === 'y' || v === 'yes' || v === '1' || v === 'true') config.show_reasoning = true
else if (v === 'n' || v === 'no' || v === '0' || v === 'false') config.show_reasoning = false
}
const modeRaw =
(await bareAgentPromptSetupLine(
ctx,
'Reasoning mode off|summary|trace [' +
String(config.reasoning_mode || 'off') +
']: '
)) || ''
if (modeRaw.trim()) {
const m = modeRaw.trim().toLowerCase()
if (m === 'off' || m === 'summary' || m === 'trace') config.reasoning_mode = m
}
const maxCharsRaw =
(await bareAgentPromptSetupLine(
ctx,
'Reasoning max chars [default ' +
String(config.reasoning_max_chars || 4000) +
']: '
)) || ''
if (maxCharsRaw.trim()) {
const n = Number(maxCharsRaw)
if (Number.isFinite(n) && n >= 200) config.reasoning_max_chars = Math.floor(n)
}
const includeToolsRaw =
(await bareAgentPromptSetupLine(
ctx,
'Include tool traces in process output? (Y/n) [' +
(config.reasoning_include_tools === false ? 'n' : 'y') +
']: '
)) || ''
{
const v = includeToolsRaw.trim().toLowerCase()
if (v === 'y' || v === 'yes' || v === '1' || v === 'true') config.reasoning_include_tools = true
else if (v === 'n' || v === 'no' || v === '0' || v === 'false') config.reasoning_include_tools = false
}
} catch (e) {
const msg =
e && typeof e === 'object' && 'message' in e ? String(e.message) : String(e)
@@ -543,6 +604,8 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
bareAgentNormalizeBaseUrl(String(configRef.current.rest_base_url || '')) +
'/chat/completions'
const tools = bareAgentToolDefinitions()
let reasoningSettings = bareAgentReasoningSettings(configRef.current)
let reasoningCharCount = 0
let suspended = replSuspendedForSetup
try {
@@ -577,6 +640,7 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
let iter = 0
for (;;) {
reasoningSettings = bareAgentReasoningSettings(configRef.current)
if (completed) break
iter++
if (iter > maxIter) {
@@ -634,6 +698,25 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
if (Array.isArray(arr)) {
for (const tc of arr) bareAgentMergeToolCallDelta(toolAcc, tc)
}
} else if (e.type === 'delta_reasoning' && reasoningSettings.enabled) {
const chunk = typeof e.reasoning === 'string' ? e.reasoning : ''
if (chunk && reasoningCharCount < reasoningSettings.maxChars) {
const remain = reasoningSettings.maxChars - reasoningCharCount
const out = chunk.slice(0, remain)
reasoningCharCount += out.length
if (out.length) {
bareAgentWriteOut(
ctx,
stdout,
'\n' +
bareEditSgr('dim', useColor) +
'[thinking] ' +
out +
EDIT_ANSI_RESET +
'\n'
)
}
}
} else if (e.type === 'usage') {
usageOut = e.usage
} else if (e.type === 'finish_reason') {
@@ -696,6 +779,19 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
/** @type {{ function?: { name?: string } }} */ (x).function?.name
).join(',')
)
if (reasoningSettings.enabled && reasoningSettings.mode === 'trace') {
bareAgentWriteOut(
ctx,
stdout,
bareEditSgr('dim', useColor) +
'\n[process] iteration ' +
String(iter) +
' finish_reason=' +
(finishReason || 'unknown') +
EDIT_ANSI_RESET +
'\n'
)
}
for (const tc of toolCallsArr) {
const fn = /** @type {{ id?: string, function?: { name?: string, arguments?: string } }} */ (
@@ -704,6 +800,20 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
const id = /** @type {{ id?: string }} */ (tc).id || ''
const name = fn?.name || ''
const argsStr = fn?.arguments || '{}'
if (reasoningSettings.enabled && reasoningSettings.mode === 'trace' && reasoningSettings.includeTools) {
const argsPreview = argsStr.length > 280 ? argsStr.slice(0, 280) + '…' : argsStr
bareAgentWriteOut(
ctx,
stdout,
bareEditSgr('dim', useColor) +
'[process] tool_call ' +
name +
' args=' +
argsPreview +
EDIT_ANSI_RESET +
'\n'
)
}
bareAgentWriteOut(
ctx,
stdout,
@@ -738,6 +848,21 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
tool_call_id: id,
content: resultStr
})
if (reasoningSettings.enabled && reasoningSettings.mode === 'trace' && reasoningSettings.includeTools) {
const resPreview =
resultStr.length > 360 ? resultStr.slice(0, 360) + '…' : resultStr
bareAgentWriteOut(
ctx,
stdout,
bareEditSgr('dim', useColor) +
'[process] tool_result ' +
name +
' ' +
resPreview +
EDIT_ANSI_RESET +
'\n'
)
}
if (completed) break
}
@@ -26,6 +26,7 @@ var BARE_AGENT_SKILL_SEED_REL = Object.freeze([
'skills/p2p-os-status/SKILL.md',
'skills/bare-os-kernel-proc/SKILL.md',
'skills/bare-os-super-developer/SKILL.md',
'skills/agent-ops/SKILL.md',
'skills/holesail/SKILL.md',
'skills/hdms/SKILL.md'
])
+1 -1
View File
@@ -6,6 +6,6 @@
"description": "Build JS /bin utilities for bare-operating-system (concat + stage to kernel/)",
"scripts": {
"build": "node ./scripts/ensure-man-pages.mjs && node ./build.mjs",
"test": "node ./test/clear-sequence.test.mjs && node ./test/help-bin-list.test.mjs && node ./test/whois-rdap.test.mjs && node ./test/edit-key-parse.test.mjs && node ./test/edit-teardown.test.mjs && node ./test/baresay-say-bundle.test.mjs && node ./test/baretop-bundle.test.mjs && node ./test/baretop-fixture.test.mjs && node ./test/baretop-compose.test.mjs && node ./test/baretop-incremental.test.mjs && node ./test/baretop-ui-helpers.test.mjs && node ./test/posix-test-int-compare.test.mjs && node ./test/posix-utils-edge.test.mjs && node ./test/posix-golden-issue7.test.mjs && node ./test/getconf-pathconf-union-mirror.test.mjs && node ./test/getconf-posix-shm.test.mjs && node ./test/awk-sed-posix-smoke.test.mjs && node ./test/xattr-acl-utils.test.mjs && node ./test/xcu-issue7-sweep.test.mjs && node ./test/expand-tab-stops.test.mjs && node ./test/pkg-swarm-index-pathcap.test.mjs && node ./test/sha224-sha384-sum.test.mjs && node ./test/agent-sse-parse.test.mjs && node ./test/agent-web-fetch.test.mjs && node ./test/agent-helpers.test.mjs && node ./test/agent-workspace.test.mjs && node ./test/agent-skills.test.mjs"
"test": "node ./test/clear-sequence.test.mjs && node ./test/help-bin-list.test.mjs && node ./test/whois-rdap.test.mjs && node ./test/edit-key-parse.test.mjs && node ./test/edit-teardown.test.mjs && node ./test/baresay-say-bundle.test.mjs && node ./test/baretop-bundle.test.mjs && node ./test/baretop-fixture.test.mjs && node ./test/baretop-compose.test.mjs && node ./test/baretop-incremental.test.mjs && node ./test/baretop-ui-helpers.test.mjs && node ./test/posix-test-int-compare.test.mjs && node ./test/posix-utils-edge.test.mjs && node ./test/posix-golden-issue7.test.mjs && node ./test/getconf-pathconf-union-mirror.test.mjs && node ./test/getconf-posix-shm.test.mjs && node ./test/awk-sed-posix-smoke.test.mjs && node ./test/xattr-acl-utils.test.mjs && node ./test/xcu-issue7-sweep.test.mjs && node ./test/expand-tab-stops.test.mjs && node ./test/pkg-swarm-index-pathcap.test.mjs && node ./test/sha224-sha384-sum.test.mjs && node ./test/agent-sse-parse.test.mjs && node ./test/agent-web-fetch.test.mjs && node ./test/agent-helpers.test.mjs && node ./test/agent-workspace.test.mjs && node ./test/agent-skills.test.mjs && node ./test/agent-config-surface.test.mjs"
}
}
@@ -7,3 +7,15 @@ Summarize drive health, peer connections, kernel status, and recent logs.
## /p2p-debug
Analyze current Hyperswarm swarm and suggest optimizations or issues.
## /ops-diagnose
Inspect initd unit phases, timer drop-ins, cron/audit logs, boot policy, and kernel extension resolution; summarize root causes and safe next actions.
## /reasoning-on
Enable process visibility with `edit_agent_config` (`show_reasoning=true`, `reasoning_mode=trace`) and keep output bounded.
## /reasoning-off
Disable reasoning/process output with `edit_agent_config` (`show_reasoning=false`, `reasoning_mode=off`).
@@ -10,7 +10,7 @@ This tree follows the **agent** Markdown workspace convention: “soul” files
| **`~/.agent/workspace/skills/`** | Modular **skills** — one folder per skill, each with **`SKILL.md`** (optional YAML frontmatter) |
| **`~/.agent/workspace/memory/`** | Daily append logs `YYYY-MM-DD.md` (optional) |
| **`~/.agent/skills/`** | Optional **global** skills (lower precedence than `workspace/skills/` when names collide) |
| **`~/.agent/config.json`** | API URL, key, model (existing agent config) |
| **`~/.agent/config.json`** | API URL, key, model, and reasoning/process visibility controls |
| **`~/.agent/skill-loader.js`** | Host stub for `discoverSkills` / `loadSkill` (in-image agent uses bundled discovery + **`read_skill`** tool) |
| **`~/.agent/loader.js`** | Stub / hook for **host-side** experimentation (not used by `/bin/agent` bundle) |
| **`~/.agent/index.js`** | Stub factory reference (in-image agent uses built-in loader) |
@@ -22,10 +22,17 @@ This tree follows the **agent** Markdown workspace convention: “soul” files
3. During a session, the model loads the full document with the **`read_skill`** tool (do not paste huge skills into the user channel unless asked).
4. Shared skills can live under **`~/.agent/skills/`**; keep **`workspace/skills/`** for machine-local or repo-specific behavior.
Seeded examples in this repo (under **`skills/`**): **`p2p-os-status`**, **`bare-os-kernel-proc`**, **`bare-os-super-developer`**, **`holesail`** (managed **`state.json`**, **`seed`**/**`key`**, stock **`bare-www-*`** / **`bare-ssh-*`**), and **`hdms`** (Hyperdrive mounts and invite/pair).
Seeded examples in this repo (under **`skills/`**): **`p2p-os-status`**, **`bare-os-kernel-proc`**, **`bare-os-super-developer`**, **`agent-ops`**, **`holesail`** (managed **`state.json`**, **`seed`**/**`key`**, stock **`bare-www-*`** / **`bare-ssh-*`**), and **`hdms`** (Hyperdrive mounts and invite/pair).
After **`agent --config`** / **`--setup`** (or changing **`owner_name`** / **`agent_label`** via **`edit_agent_config`**), **`IDENTITY.md`** and **`USER.md`** are regenerated from **`config.json`** so the workspace matches the operator and agent label.
Reasoning/process visibility is configurable in `config.json`:
- `show_reasoning` — master toggle
- `reasoning_mode``off` / `summary` / `trace`
- `reasoning_max_chars` — bounded reasoning output
- `reasoning_include_tools` — include tool traces in process stream
## Editing
1. Change files under **`~/.agent/workspace/`** on your **personal** drive.
@@ -3,11 +3,22 @@
## Core OS tools
- **VFS / Hyperdrive** — read/write paths via agent tools (`read_file`, `write_file`, `list_directory`, …) on system and personal drives.
- **Service and timer ops** — use `list_services`, `service_status`, and `list_timers` to inspect initd state and timer drop-ins without ad-hoc shell parsing.
- **Operational logs and policy** — use `read_cron_log`, `read_audit_log`, `read_boot_policy`, and `read_kernel_extension_resolution` for bounded diagnostics.
- **`web_fetch`** — live `http(s)` fetches **only** when the operator allows them (`ctx.httpFetch`, `BARE_OS_HTTP_ALLOWLIST` / denylist). Same policy as delegated `curl` / `wget`.
- **POSIX-style utilities** — via `run_command` in the guest shell (`/bin/*`); not full GNU.
- **Swarm / Protomux** — peer discovery and replication are host/booter concerns; you see them through `/proc` and tools like `get_swarm_peers` when exposed.
- **Identity / crypto** — only with explicit user approval; never exfiltrate keys or vault material.
## Reasoning / process visibility
- Runtime process visibility can be configured in `~/.agent/config.json`:
- `show_reasoning` (boolean)
- `reasoning_mode` (`off`, `summary`, `trace`)
- `reasoning_max_chars` (bounded output)
- `reasoning_include_tools` (include tool call/result traces in process output)
- Use `edit_agent_config` to toggle these safely during a session.
## Skills system
The agent has access to modular **skills** under `~/.agent/workspace/skills/` (and optionally shared skills under `~/.agent/skills/`).
@@ -0,0 +1,31 @@
---
name: agent-ops
version: 1.0.0
description: Diagnose Bare OS runtime state using agent operations tools for services, timers, logs, boot policy, and extension resolution.
tags: [bare-os, operations, initd, cron, audit, diagnostics]
requires: [list_services, service_status, list_timers, read_cron_log, read_audit_log, read_boot_policy, read_kernel_extension_resolution]
---
# agent-ops
Use this skill for operational diagnostics and health checks inside Bare OS.
## Workflow
1. Start with service state:
- `list_services`
- `service_status` for any unit in failed/inactive phase.
2. Inspect scheduling:
- `list_timers` for `~/.config/bare-os/timers/*.timer`
- `read_cron_log` for runtime scheduler failures.
3. Check security/provenance controls:
- `read_boot_policy`
- `read_kernel_extension_resolution`
4. If behavior looks suspicious, read `read_audit_log` (bounded + redacted).
## Output Contract
- Report observed state first (services, timers, policies, extension resolution).
- Separate confirmed facts from hypotheses.
- Suggest safe next actions with minimal blast radius.
- Avoid destructive recommendations unless explicitly requested.
@@ -0,0 +1,36 @@
import test from 'brittle'
import { readFileSync } from 'node:fs'
const STATE = readFileSync(new URL('../lib/agent-state.js', import.meta.url), 'utf8')
const TOOLS = readFileSync(new URL('../lib/agent-tools.js', import.meta.url), 'utf8')
const OPENAI = readFileSync(new URL('../lib/agent-openai.js', import.meta.url), 'utf8')
test('agent-state exposes reasoning config keys', async (t) => {
for (const key of [
'show_reasoning',
'reasoning_mode',
'reasoning_max_chars',
'reasoning_include_tools'
]) {
t.ok(STATE.includes(key), 'missing key in agent-state.js: ' + key)
}
})
test('agent-tools exposes agent ops tools', async (t) => {
for (const toolName of [
'list_services',
'service_status',
'list_timers',
'read_cron_log',
'read_audit_log',
'read_boot_policy',
'read_kernel_extension_resolution'
]) {
t.ok(TOOLS.includes("name: '" + toolName + "'"), 'missing tool definition: ' + toolName)
}
})
test('agent-openai parses reasoning deltas when present', async (t) => {
t.ok(OPENAI.includes('delta_reasoning'))
t.ok(OPENAI.includes('reasoning_content'))
})
@@ -117,6 +117,7 @@ test('bareAgentEnsureSkillTemplates copies skill seeds when missing', async (t)
set('/share/agent-workspace/skills/p2p-os-status/SKILL.md', '# Skill')
set('/share/agent-workspace/skills/bare-os-kernel-proc/SKILL.md', '# Proc skill')
set('/share/agent-workspace/skills/bare-os-super-developer/SKILL.md', '# Dev skill')
set('/share/agent-workspace/skills/agent-ops/SKILL.md', '# Ops skill')
set('/share/agent-workspace/skills/holesail/SKILL.md', '# Holesail skill')
set('/share/agent-workspace/skills/hdms/SKILL.md', '# Hdms skill')
set('/share/agent-workspace/skill-loader.stub.js', '// stub')
@@ -148,6 +149,7 @@ test('bareAgentEnsureSkillTemplates copies skill seeds when missing', async (t)
t.ok(written.some(([p]) => p === '/home/x/.agent/workspace/skills/p2p-os-status/SKILL.md'))
t.ok(written.some(([p]) => p === '/home/x/.agent/workspace/skills/bare-os-kernel-proc/SKILL.md'))
t.ok(written.some(([p]) => p === '/home/x/.agent/workspace/skills/bare-os-super-developer/SKILL.md'))
t.ok(written.some(([p]) => p === '/home/x/.agent/workspace/skills/agent-ops/SKILL.md'))
t.ok(written.some(([p]) => p === '/home/x/.agent/workspace/skills/holesail/SKILL.md'))
t.ok(written.some(([p]) => p === '/home/x/.agent/workspace/skills/hdms/SKILL.md'))
t.ok(written.some(([p]) => p === '/home/x/.agent/skill-loader.js'))
+570 -8
View File
@@ -1092,7 +1092,11 @@ function bareAgentDefaultConfig() {
allow_delete: false,
require_confirm_token: '',
owner_name: '',
agent_label: ''
agent_label: '',
show_reasoning: false,
reasoning_mode: 'off',
reasoning_max_chars: 4000,
reasoning_include_tools: true
}
}
@@ -1126,7 +1130,11 @@ function bareAgentMergeConfig(defaults, src) {
'allow_delete',
'require_confirm_token',
'owner_name',
'agent_label'
'agent_label',
'show_reasoning',
'reasoning_mode',
'reasoning_max_chars',
'reasoning_include_tools'
])
for (const k of Object.keys(src)) {
if (k.startsWith('x-')) continue
@@ -1147,18 +1155,30 @@ function bareAgentMergeConfig(defaults, src) {
out[k] = String(val ?? '')
continue
}
if (k === 'reasoning_mode') {
const mode = String(val ?? '').trim().toLowerCase()
out.reasoning_mode =
mode === 'summary' || mode === 'trace' ? mode : 'off'
continue
}
if (
k === 'max_tokens' ||
k === 'temperature' ||
k === 'max_iterations' ||
k === 'tool_parallelism' ||
k === 'request_timeout_ms'
k === 'request_timeout_ms' ||
k === 'reasoning_max_chars'
) {
const n = Number(val)
out[k] = Number.isFinite(n) ? n : defaults[k]
continue
}
if (k === 'stream' || k === 'allow_delete') {
if (
k === 'stream' ||
k === 'allow_delete' ||
k === 'show_reasoning' ||
k === 'reasoning_include_tools'
) {
out[k] = Boolean(val)
continue
}
@@ -1192,7 +1212,11 @@ function bareAgentValidateConfigShape(raw) {
'allow_delete',
'require_confirm_token',
'owner_name',
'agent_label'
'agent_label',
'show_reasoning',
'reasoning_mode',
'reasoning_max_chars',
'reasoning_include_tools'
]
if (!known.includes(k)) {
throw new Error('unknown config key: ' + k)
@@ -1492,6 +1516,7 @@ var BARE_AGENT_SKILL_SEED_REL = Object.freeze([
'skills/p2p-os-status/SKILL.md',
'skills/bare-os-kernel-proc/SKILL.md',
'skills/bare-os-super-developer/SKILL.md',
'skills/agent-ops/SKILL.md',
'skills/holesail/SKILL.md',
'skills/hdms/SKILL.md'
])
@@ -2091,6 +2116,37 @@ async function bareAgentStreamChatCompletions(opts) {
type: 'delta_tool_calls',
tool_calls: toolCalls
})
const rc = delta.reasoning_content
if (typeof rc === 'string' && rc.length) {
onEvent({
type: 'delta_reasoning',
reasoning: rc
})
}
const r = delta.reasoning
if (typeof r === 'string' && r.length) {
onEvent({
type: 'delta_reasoning',
reasoning: r
})
} else if (Array.isArray(r)) {
for (const chunk of r) {
if (!chunk || typeof chunk !== 'object') continue
const ro = /** @type {Record<string, unknown>} */ (chunk)
const tx =
typeof ro.text === 'string'
? ro.text
: typeof ro.content === 'string'
? ro.content
: ''
if (tx) {
onEvent({
type: 'delta_reasoning',
reasoning: tx
})
}
}
}
}
if (finishReason)
@@ -3272,6 +3328,134 @@ function bareAgentToolDefinitions() {
}
}
},
{
type: 'function',
function: {
name: 'list_services',
description:
'List initd service definitions and current runtime phases from /proc/bare_os/initd_readiness.json when available.',
parameters: {
type: 'object',
properties: {}
}
}
},
{
type: 'function',
function: {
name: 'service_status',
description:
'Read one initd unit status by name from /proc/bare_os/initd_readiness.json and include journal hint paths when present.',
parameters: {
type: 'object',
properties: {
name: { type: 'string', description: 'Unit name, e.g. bare-cron' }
},
required: ['name']
}
}
},
{
type: 'function',
function: {
name: 'list_timers',
description:
'List user timer drop-ins from ~/.config/bare-os/timers and optionally include short file previews.',
parameters: {
type: 'object',
properties: {
include_preview: {
type: 'boolean',
description: 'Include bounded timer file text previews (default false)'
},
max_entries: {
type: 'integer',
description: 'Maximum timer files to return (default 128, max 512)'
}
}
}
}
},
{
type: 'function',
function: {
name: 'read_cron_log',
description:
'Read /var/log/bare-os/cron.log with bounded output and optional tail mode.',
parameters: {
type: 'object',
properties: {
max_chars: {
type: 'integer',
description: 'Maximum returned characters (default 12000)'
},
tail_only: {
type: 'boolean',
description: 'When true, return only the trailing max_chars slice'
}
}
}
}
},
{
type: 'function',
function: {
name: 'read_audit_log',
description:
'Read /var/log/bare-os/audit.log with bounded output and best-effort secret redaction.',
parameters: {
type: 'object',
properties: {
max_chars: {
type: 'integer',
description: 'Maximum returned characters (default 12000)'
},
tail_only: {
type: 'boolean',
description: 'When true, return only the trailing max_chars slice'
},
redact: {
type: 'boolean',
description: 'Apply lightweight token redaction (default true)'
}
}
}
}
},
{
type: 'function',
function: {
name: 'read_boot_policy',
description:
'Read /etc/bare-os/boot.policy.json and return text plus parsed JSON when available.',
parameters: {
type: 'object',
properties: {
max_chars: {
type: 'integer',
description: 'Maximum returned characters (default 20000)'
}
}
}
}
},
{
type: 'function',
function: {
name: 'read_kernel_extension_resolution',
description:
'Read /run/bare-os/kernel-ext-resolution.json for extension ordering, conflicts, and pin outcomes.',
parameters: {
type: 'object',
properties: {
max_chars: {
type: 'integer',
description: 'Maximum returned characters (default 20000)'
}
}
}
}
},
{
type: 'function',
function: {
@@ -4032,6 +4216,246 @@ async function bareAgentDispatchTool(o) {
}
}
if (toolName === 'list_services') {
appendProgress('list_services')
if (!vfs || typeof vfs.readFile !== 'function') {
return bareAgentJsonResult({ ok: false, error: 'vfs unavailable' })
}
let readinessText = ''
/** @type {Record<string, unknown> | null} */
let readinessJson = null
try {
const b = await vfs.readFile('/proc/bare_os/initd_readiness.json')
if (b && b.length) {
readinessText =
typeof ctx.b4a !== 'undefined' && ctx.b4a && typeof ctx.b4a.toString === 'function'
? ctx.b4a.toString(b)
: String(new TextDecoder().decode(b))
try {
const parsed = JSON.parse(readinessText)
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed))
readinessJson = /** @type {Record<string, unknown>} */ (parsed)
} catch {
/* ignore */
}
}
} catch {
/* ignore */
}
const units = Array.isArray(readinessJson?.units)
? /** @type {unknown[]} */ (readinessJson.units)
: []
const rows = units
.filter((u) => u && typeof u === 'object')
.map((u) => {
const o = /** @type {Record<string, unknown>} */ (u)
return {
name: String(o.name || ''),
phase: String(o.phase || ''),
startedAtMs:
typeof o.startedAtMs === 'number' ? o.startedAtMs : undefined,
error: typeof o.error === 'string' ? o.error : undefined
}
})
.filter((r) => r.name)
return bareAgentJsonResult({
ok: true,
source: '/proc/bare_os/initd_readiness.json',
count: rows.length,
units: rows,
note:
rows.length > 0
? 'Runtime units from initd readiness snapshot.'
: 'No parsed readiness units available.'
})
}
if (toolName === 'service_status') {
const name = typeof args.name === 'string' ? args.name.trim() : ''
if (!name) return bareAgentJsonResult({ ok: false, error: 'name_required' })
appendProgress('service_status ' + name)
if (!vfs || typeof vfs.readFile !== 'function') {
return bareAgentJsonResult({ ok: false, error: 'vfs unavailable' })
}
try {
const b = await vfs.readFile('/proc/bare_os/initd_readiness.json')
const t =
b && b.length
? typeof ctx.b4a !== 'undefined' &&
ctx.b4a &&
typeof ctx.b4a.toString === 'function'
? ctx.b4a.toString(b)
: String(new TextDecoder().decode(b))
: ''
const parsed = JSON.parse(t)
const units = Array.isArray(parsed?.units) ? parsed.units : []
const hit =
units.find((u) => u && typeof u === 'object' && String(u.name || '') === name) ||
null
if (!hit) {
return bareAgentJsonResult({
ok: false,
error: 'not_found',
source: '/proc/bare_os/initd_readiness.json'
})
}
const o = /** @type {Record<string, unknown>} */ (hit)
return bareAgentJsonResult({
ok: true,
status: {
name: String(o.name || ''),
phase: String(o.phase || ''),
startedAtMs:
typeof o.startedAtMs === 'number' ? o.startedAtMs : undefined,
error: typeof o.error === 'string' ? o.error : undefined
},
journal_hint: '/run/bare-os/unit-journal/' + name + '.ndjson'
})
} catch (e) {
const msg =
e && typeof e === 'object' && 'message' in e ? String(e.message) : String(e)
return bareAgentJsonResult({ ok: false, error: msg })
}
}
if (toolName === 'list_timers') {
const includePreview = Boolean(args.include_preview)
const maxEntries =
typeof args.max_entries === 'number' && Number.isFinite(args.max_entries)
? Math.min(Math.max(Math.floor(args.max_entries), 1), 512)
: 128
appendProgress('list_timers')
if (!vfs || typeof vfs.readdir !== 'function' || typeof vfs.readFile !== 'function') {
return bareAgentJsonResult({ ok: false, error: 'vfs unavailable' })
}
const dir = home + '/.config/bare-os/timers'
let names = []
try {
names = await vfs.readdir(dir)
} catch (e) {
const msg =
e && typeof e === 'object' && 'message' in e ? String(e.message) : String(e)
return bareAgentJsonResult({ ok: false, error: msg, path: dir })
}
const timerNames = names
.filter((n) => typeof n === 'string' && n.endsWith('.timer'))
.sort()
.slice(0, maxEntries)
/** @type {unknown[]} */
const timers = []
for (const name of timerNames) {
const path = dir + '/' + name
/** @type {Record<string, unknown>} */
const row = { name, path }
if (includePreview) {
try {
const b = await vfs.readFile(path)
const txt =
b && b.length
? typeof ctx.b4a !== 'undefined' &&
ctx.b4a &&
typeof ctx.b4a.toString === 'function'
? ctx.b4a.toString(b)
: String(new TextDecoder().decode(b))
: ''
row.preview = bareAgentTruncateChars(txt, 1200)
} catch (e) {
row.preview_error =
e && typeof e === 'object' && 'message' in e ? String(e.message) : String(e)
}
}
timers.push(row)
}
return bareAgentJsonResult({
ok: true,
path: dir,
count: timers.length,
timers
})
}
if (toolName === 'read_cron_log' || toolName === 'read_audit_log') {
const maxChars =
typeof args.max_chars === 'number' && Number.isFinite(args.max_chars)
? Math.min(Math.max(Math.floor(args.max_chars), 200), 80_000)
: 12_000
const tailOnly = Boolean(args.tail_only)
const redact = toolName === 'read_audit_log' ? args.redact !== false : false
const path =
toolName === 'read_audit_log'
? '/var/log/bare-os/audit.log'
: '/var/log/bare-os/cron.log'
appendProgress(toolName + ' ' + path)
if (!vfs || typeof vfs.readFile !== 'function') {
return bareAgentJsonResult({ ok: false, error: 'vfs unavailable' })
}
try {
const b = await vfs.readFile(path)
if (!b || !b.length) return bareAgentJsonResult({ ok: false, error: 'empty_or_missing' })
let t =
typeof ctx.b4a !== 'undefined' && ctx.b4a && typeof ctx.b4a.toString === 'function'
? ctx.b4a.toString(b)
: String(new TextDecoder().decode(b))
if (redact) {
t = t
.replace(/\bBearer\s+\S+/gi, 'Bearer <redacted>')
.replace(/\bsk-[a-zA-Z0-9]{16,}\b/g, '<redacted_sk>')
.replace(/\b([A-Z0-9_]*(KEY|TOKEN|SECRET|PASS)[A-Z0-9_]*)\s*=\s*([^\s]+)/gi, '$1=<redacted>')
}
const out = tailOnly ? t.slice(-maxChars) : bareAgentTruncateChars(t, maxChars)
return bareAgentJsonResult({
ok: true,
path,
text: out,
truncated: t.length > out.length
})
} catch (e) {
const msg =
e && typeof e === 'object' && 'message' in e ? String(e.message) : String(e)
return bareAgentJsonResult({ ok: false, error: msg })
}
}
if (toolName === 'read_boot_policy' || toolName === 'read_kernel_extension_resolution') {
const maxChars =
typeof args.max_chars === 'number' && Number.isFinite(args.max_chars)
? Math.min(Math.max(Math.floor(args.max_chars), 200), 120_000)
: 20_000
const path =
toolName === 'read_boot_policy'
? '/etc/bare-os/boot.policy.json'
: '/run/bare-os/kernel-ext-resolution.json'
appendProgress(toolName + ' ' + path)
if (!vfs || typeof vfs.readFile !== 'function') {
return bareAgentJsonResult({ ok: false, error: 'vfs unavailable' })
}
try {
const b = await vfs.readFile(path)
if (!b || !b.length) return bareAgentJsonResult({ ok: false, error: 'empty_or_missing' })
const t =
typeof ctx.b4a !== 'undefined' && ctx.b4a && typeof ctx.b4a.toString === 'function'
? ctx.b4a.toString(b)
: String(new TextDecoder().decode(b))
/** @type {unknown} */
let json = null
try {
json = JSON.parse(t)
} catch {
json = null
}
return bareAgentJsonResult({
ok: true,
path,
text: bareAgentTruncateChars(t, maxChars),
json
})
} catch (e) {
const msg =
e && typeof e === 'object' && 'message' in e ? String(e.message) : String(e)
return bareAgentJsonResult({ ok: false, error: msg })
}
}
if (toolName === 'get_swarm_peers') {
appendProgress('get_swarm_peers')
if (!vfs || typeof vfs.readFile !== 'function') {
@@ -4174,14 +4598,19 @@ function bareAgentMergeConfigPatch(base, patch) {
'allow_delete',
'require_confirm_token',
'owner_name',
'agent_label'
'agent_label',
'show_reasoning',
'reasoning_mode',
'reasoning_max_chars',
'reasoning_include_tools'
]
const numKeys = new Set([
'max_tokens',
'temperature',
'max_iterations',
'tool_parallelism',
'request_timeout_ms'
'request_timeout_ms',
'reasoning_max_chars'
])
for (const k of keys) {
if (Object.prototype.hasOwnProperty.call(patch, k)) {
@@ -4190,8 +4619,16 @@ function bareAgentMergeConfigPatch(base, patch) {
if (numKeys.has(k)) {
const n = Number(v)
if (Number.isFinite(n)) out[k] = n
} else if (k === 'stream' || k === 'allow_delete') {
} else if (
k === 'stream' ||
k === 'allow_delete' ||
k === 'show_reasoning' ||
k === 'reasoning_include_tools'
) {
out[k] = Boolean(v)
} else if (k === 'reasoning_mode') {
const mode = String(v ?? '').trim().toLowerCase()
out[k] = mode === 'summary' || mode === 'trace' ? mode : 'off'
} else if (k === 'require_confirm_token') {
out[k] = String(v ?? '')
} else {
@@ -4485,6 +4922,21 @@ function bareAgentFinalizeToolCalls(acc) {
return arr
}
/**
* @param {Record<string, unknown>} cfg
*/
function bareAgentReasoningSettings(cfg) {
const modeRaw = String(cfg.reasoning_mode || '').trim().toLowerCase()
const mode = modeRaw === 'summary' || modeRaw === 'trace' ? modeRaw : 'off'
const enabled = Boolean(cfg.show_reasoning) && mode !== 'off'
const maxChars =
typeof cfg.reasoning_max_chars === 'number' && Number.isFinite(cfg.reasoning_max_chars)
? Math.min(Math.max(Math.floor(cfg.reasoning_max_chars), 200), 80_000)
: 4000
const includeTools = cfg.reasoning_include_tools !== false
return { enabled, mode, maxChars, includeTools }
}
/**
* @param {Record<string, unknown>} ctx
* @param {string} argv0
@@ -4555,6 +5007,52 @@ async function bareAgentInteractiveSetup(ctx, argv0, paths, config, opts) {
'Provider label [' + String(config.provider || '') + ']: '
)) || ''
if (provRaw.trim()) config.provider = provRaw.trim()
const showReasoningRaw =
(await bareAgentPromptSetupLine(
ctx,
'Show thinking/process output? (y/N) [' +
(config.show_reasoning ? 'y' : 'n') +
']: '
)) || ''
{
const v = showReasoningRaw.trim().toLowerCase()
if (v === 'y' || v === 'yes' || v === '1' || v === 'true') config.show_reasoning = true
else if (v === 'n' || v === 'no' || v === '0' || v === 'false') config.show_reasoning = false
}
const modeRaw =
(await bareAgentPromptSetupLine(
ctx,
'Reasoning mode off|summary|trace [' +
String(config.reasoning_mode || 'off') +
']: '
)) || ''
if (modeRaw.trim()) {
const m = modeRaw.trim().toLowerCase()
if (m === 'off' || m === 'summary' || m === 'trace') config.reasoning_mode = m
}
const maxCharsRaw =
(await bareAgentPromptSetupLine(
ctx,
'Reasoning max chars [default ' +
String(config.reasoning_max_chars || 4000) +
']: '
)) || ''
if (maxCharsRaw.trim()) {
const n = Number(maxCharsRaw)
if (Number.isFinite(n) && n >= 200) config.reasoning_max_chars = Math.floor(n)
}
const includeToolsRaw =
(await bareAgentPromptSetupLine(
ctx,
'Include tool traces in process output? (Y/n) [' +
(config.reasoning_include_tools === false ? 'n' : 'y') +
']: '
)) || ''
{
const v = includeToolsRaw.trim().toLowerCase()
if (v === 'y' || v === 'yes' || v === '1' || v === 'true') config.reasoning_include_tools = true
else if (v === 'n' || v === 'no' || v === '0' || v === 'false') config.reasoning_include_tools = false
}
} catch (e) {
const msg =
e && typeof e === 'object' && 'message' in e ? String(e.message) : String(e)
@@ -4770,6 +5268,8 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
bareAgentNormalizeBaseUrl(String(configRef.current.rest_base_url || '')) +
'/chat/completions'
const tools = bareAgentToolDefinitions()
let reasoningSettings = bareAgentReasoningSettings(configRef.current)
let reasoningCharCount = 0
let suspended = replSuspendedForSetup
try {
@@ -4804,6 +5304,7 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
let iter = 0
for (;;) {
reasoningSettings = bareAgentReasoningSettings(configRef.current)
if (completed) break
iter++
if (iter > maxIter) {
@@ -4861,6 +5362,25 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
if (Array.isArray(arr)) {
for (const tc of arr) bareAgentMergeToolCallDelta(toolAcc, tc)
}
} else if (e.type === 'delta_reasoning' && reasoningSettings.enabled) {
const chunk = typeof e.reasoning === 'string' ? e.reasoning : ''
if (chunk && reasoningCharCount < reasoningSettings.maxChars) {
const remain = reasoningSettings.maxChars - reasoningCharCount
const out = chunk.slice(0, remain)
reasoningCharCount += out.length
if (out.length) {
bareAgentWriteOut(
ctx,
stdout,
'\n' +
bareEditSgr('dim', useColor) +
'[thinking] ' +
out +
EDIT_ANSI_RESET +
'\n'
)
}
}
} else if (e.type === 'usage') {
usageOut = e.usage
} else if (e.type === 'finish_reason') {
@@ -4923,6 +5443,19 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
/** @type {{ function?: { name?: string } }} */ (x).function?.name
).join(',')
)
if (reasoningSettings.enabled && reasoningSettings.mode === 'trace') {
bareAgentWriteOut(
ctx,
stdout,
bareEditSgr('dim', useColor) +
'\n[process] iteration ' +
String(iter) +
' finish_reason=' +
(finishReason || 'unknown') +
EDIT_ANSI_RESET +
'\n'
)
}
for (const tc of toolCallsArr) {
const fn = /** @type {{ id?: string, function?: { name?: string, arguments?: string } }} */ (
@@ -4931,6 +5464,20 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
const id = /** @type {{ id?: string }} */ (tc).id || ''
const name = fn?.name || ''
const argsStr = fn?.arguments || '{}'
if (reasoningSettings.enabled && reasoningSettings.mode === 'trace' && reasoningSettings.includeTools) {
const argsPreview = argsStr.length > 280 ? argsStr.slice(0, 280) + '…' : argsStr
bareAgentWriteOut(
ctx,
stdout,
bareEditSgr('dim', useColor) +
'[process] tool_call ' +
name +
' args=' +
argsPreview +
EDIT_ANSI_RESET +
'\n'
)
}
bareAgentWriteOut(
ctx,
stdout,
@@ -4965,6 +5512,21 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
tool_call_id: id,
content: resultStr
})
if (reasoningSettings.enabled && reasoningSettings.mode === 'trace' && reasoningSettings.includeTools) {
const resPreview =
resultStr.length > 360 ? resultStr.slice(0, 360) + '…' : resultStr
bareAgentWriteOut(
ctx,
stdout,
bareEditSgr('dim', useColor) +
'[process] tool_result ' +
name +
' ' +
resPreview +
EDIT_ANSI_RESET +
'\n'
)
}
if (completed) break
}
@@ -1,7 +1,7 @@
{
"schema": 2,
"profileId": "bare-os-posix-like",
"generatedAt": "2026-04-26T02:43:49.731Z",
"generatedAt": "2026-04-26T07:05:45.727Z",
"note": "Sparse POSIX Issue 7 coverage hints for /bin utilities. Omitted command names are not yet profiled here.",
"commandIndex": [
{
@@ -25,36 +25,36 @@
"compactEncoding"
]
},
{
"path": "/lib/bare/bundles/protomux.js",
"keys": [
"protomux"
]
},
{
"path": "/lib/bare/bundles/bareUrl.js",
"keys": [
"bareUrl"
]
},
{
"path": "/lib/bare/bundles/protomux.js",
"keys": [
"protomux"
]
},
{
"path": "/lib/bare/bundles/barePath.js",
"keys": [
"barePath"
]
},
{
"path": "/lib/bare/bundles/bareEvents.js",
"keys": [
"bareEvents"
]
},
{
"path": "/lib/bare/bundles/bareEncoding.js",
"keys": [
"bareEncoding"
]
},
{
"path": "/lib/bare/bundles/bareEvents.js",
"keys": [
"bareEvents"
]
},
{
"path": "/lib/bare/bundles/bareAbort.js",
"keys": [
@@ -67,18 +67,18 @@
"bareAbortController"
]
},
{
"path": "/lib/bare/bundles/bareAnsiEscapes.js",
"keys": [
"bareAnsiEscapes"
]
},
{
"path": "/lib/bare/bundles/bareAddonResolve.js",
"keys": [
"bareAddonResolve"
]
},
{
"path": "/lib/bare/bundles/bareAnsiEscapes.js",
"keys": [
"bareAnsiEscapes"
]
},
{
"path": "/lib/bare/bundles/bareReadline.js",
"keys": [
@@ -97,6 +97,12 @@
"bareAppKit"
]
},
{
"path": "/lib/bare/bundles/bareAsyncHooks.js",
"keys": [
"bareAsyncHooks"
]
},
{
"path": "/lib/bare/bundles/bareAssert.js",
"keys": [
@@ -109,48 +115,42 @@
"bareAtomics"
]
},
{
"path": "/lib/bare/bundles/bareAsyncHooks.js",
"keys": [
"bareAsyncHooks"
]
},
{
"path": "/lib/bare/bundles/fetch.js",
"keys": [
"fetch"
]
},
{
"path": "/lib/bare/bundles/bareBmp.js",
"keys": [
"bareBmp"
]
},
{
"path": "/lib/bare/bundles/bareBundle.js",
"keys": [
"bareBundle"
]
},
{
"path": "/lib/bare/bundles/bareApk.js",
"keys": [
"bareApk"
]
},
{
"path": "/lib/bare/bundles/bareBuffer.js",
"keys": [
"bareBuffer"
]
},
{
"path": "/lib/bare/bundles/bareBundleCompile.js",
"keys": [
"bareBundleCompile"
]
},
{
"path": "/lib/bare/bundles/bareBundle.js",
"keys": [
"bareBundle"
]
},
{
"path": "/lib/bare/bundles/bareBmp.js",
"keys": [
"bareBmp"
]
},
{
"path": "/lib/bare/bundles/bareBuffer.js",
"keys": [
"bareBuffer"
]
},
{
"path": "/lib/bare/bundles/bareBluetoothApple.js",
"keys": [
@@ -169,12 +169,6 @@
"bareChannel"
]
},
{
"path": "/lib/bare/bundles/bareBoot.js",
"keys": [
"bareBoot"
]
},
{
"path": "/lib/bare/bundles/bareBundleEvaluate.js",
"keys": [
@@ -182,9 +176,9 @@
]
},
{
"path": "/lib/bare/bundles/bareBundleId.js",
"path": "/lib/bare/bundles/bareBoot.js",
"keys": [
"bareBundleId"
"bareBoot"
]
},
{
@@ -193,12 +187,6 @@
"bareDebugLog"
]
},
{
"path": "/lib/bare/bundles/bareDaemon.js",
"keys": [
"bareDaemon"
]
},
{
"path": "/lib/bare/bundles/bareDelta.js",
"keys": [
@@ -206,9 +194,9 @@
]
},
{
"path": "/lib/bare/bundles/bareCov.js",
"path": "/lib/bare/bundles/bareBundleId.js",
"keys": [
"bareCov"
"bareBundleId"
]
},
{
@@ -218,15 +206,21 @@
]
},
{
"path": "/lib/bare/bundles/bareDns.js",
"path": "/lib/bare/bundles/bareCov.js",
"keys": [
"bareDns"
"bareCov"
]
},
{
"path": "/lib/bare/bundles/bareEnv.js",
"path": "/lib/bare/bundles/bareDaemon.js",
"keys": [
"bareEnv"
"bareDaemon"
]
},
{
"path": "/lib/bare/bundles/bareDns.js",
"keys": [
"bareDns"
]
},
{
@@ -236,21 +230,9 @@
]
},
{
"path": "/lib/bare/bundles/bareDgram.js",
"path": "/lib/bare/bundles/bareEnv.js",
"keys": [
"bareDgram"
]
},
{
"path": "/lib/bare/bundles/bareFormData.js",
"keys": [
"bareFormData"
]
},
{
"path": "/lib/bare/bundles/bareFfmpegEncodings.js",
"keys": [
"bareFfmpegEncodings"
"bareEnv"
]
},
{
@@ -260,21 +242,15 @@
]
},
{
"path": "/lib/bare/bundles/bareFileLogger.js",
"path": "/lib/bare/bundles/bareFfmpegEncodings.js",
"keys": [
"bareFileLogger"
"bareFfmpegEncodings"
]
},
{
"path": "/lib/bare/bundles/bareFormat.js",
"path": "/lib/bare/bundles/bareDgram.js",
"keys": [
"bareFormat"
]
},
{
"path": "/lib/bare/bundles/bareHrtime.js",
"keys": [
"bareHrtime"
"bareDgram"
]
},
{
@@ -284,9 +260,21 @@
]
},
{
"path": "/lib/bare/bundles/bareGtk.js",
"path": "/lib/bare/bundles/bareFormat.js",
"keys": [
"bareGtk"
"bareFormat"
]
},
{
"path": "/lib/bare/bundles/bareFormData.js",
"keys": [
"bareFormData"
]
},
{
"path": "/lib/bare/bundles/bareHrtime.js",
"keys": [
"bareHrtime"
]
},
{
@@ -296,15 +284,15 @@
]
},
{
"path": "/lib/bare/bundles/bareHttpParser.js",
"path": "/lib/bare/bundles/bareGtk.js",
"keys": [
"bareHttpParser"
"bareGtk"
]
},
{
"path": "/lib/bare/bundles/bareIco.js",
"path": "/lib/bare/bundles/bareFileLogger.js",
"keys": [
"bareIco"
"bareFileLogger"
]
},
{
@@ -314,9 +302,9 @@
]
},
{
"path": "/lib/bare/bundles/bareHttp1.js",
"path": "/lib/bare/bundles/bareIco.js",
"keys": [
"bareHttp1"
"bareIco"
]
},
{
@@ -326,9 +314,15 @@
]
},
{
"path": "/lib/bare/bundles/bareInspect.js",
"path": "/lib/bare/bundles/bareHttpParser.js",
"keys": [
"bareInspect"
"bareHttpParser"
]
},
{
"path": "/lib/bare/bundles/bareHttp1.js",
"keys": [
"bareHttp1"
]
},
{
@@ -337,24 +331,30 @@
"bareHttps"
]
},
{
"path": "/lib/bare/bundles/bareInspect.js",
"keys": [
"bareInspect"
]
},
{
"path": "/lib/bare/bundles/bareJpeg.js",
"keys": [
"bareJpeg"
]
},
{
"path": "/lib/bare/bundles/bareIntl.js",
"keys": [
"bareIntl"
]
},
{
"path": "/lib/bare/bundles/bareIpc.js",
"keys": [
"bareIpc"
]
},
{
"path": "/lib/bare/bundles/bareIntl.js",
"keys": [
"bareIntl"
]
},
{
"path": "/lib/bare/bundles/bareLogger.js",
"keys": [
@@ -368,9 +368,9 @@
]
},
{
"path": "/lib/bare/bundles/bareMake.js",
"path": "/lib/bare/bundles/bareLink.js",
"keys": [
"bareMake"
"bareLink"
]
},
{
@@ -380,9 +380,9 @@
]
},
{
"path": "/lib/bare/bundles/bareLink.js",
"path": "/lib/bare/bundles/bareMake.js",
"keys": [
"bareLink"
"bareMake"
]
},
{
@@ -391,12 +391,6 @@
"bareModuleResolve"
]
},
{
"path": "/lib/bare/bundles/bareModuleLexer.js",
"keys": [
"bareModuleLexer"
]
},
{
"path": "/lib/bare/bundles/bareModule.js",
"keys": [
@@ -410,21 +404,9 @@
]
},
{
"path": "/lib/bare/bundles/bareNative.js",
"path": "/lib/bare/bundles/bareModuleLexer.js",
"keys": [
"bareNative"
]
},
{
"path": "/lib/bare/bundles/bareModuleTraverse.js",
"keys": [
"bareModuleTraverse"
]
},
{
"path": "/lib/bare/bundles/bareNdk.js",
"keys": [
"bareNdk"
"bareModuleLexer"
]
},
{
@@ -434,15 +416,27 @@
]
},
{
"path": "/lib/bare/bundles/bareNet.js",
"path": "/lib/bare/bundles/bareModuleTraverse.js",
"keys": [
"bareNet"
"bareModuleTraverse"
]
},
{
"path": "/lib/bare/bundles/bareOs.js",
"path": "/lib/bare/bundles/bareNative.js",
"keys": [
"bareOs"
"bareNative"
]
},
{
"path": "/lib/bare/bundles/bareNdk.js",
"keys": [
"bareNdk"
]
},
{
"path": "/lib/bare/bundles/bareNet.js",
"keys": [
"bareNet"
]
},
{
@@ -452,15 +446,15 @@
]
},
{
"path": "/lib/bare/bundles/barePerformance.js",
"path": "/lib/bare/bundles/bareOs.js",
"keys": [
"barePerformance"
"bareOs"
]
},
{
"path": "/lib/bare/bundles/barePipe.js",
"path": "/lib/bare/bundles/barePerformance.js",
"keys": [
"barePipe"
"barePerformance"
]
},
{
@@ -476,9 +470,9 @@
]
},
{
"path": "/lib/bare/bundles/bareNodeRuntime.js",
"path": "/lib/bare/bundles/bareDev.js",
"keys": [
"bareNodeRuntime"
"bareDev"
]
},
{
@@ -488,9 +482,9 @@
]
},
{
"path": "/lib/bare/bundles/barePunycode.js",
"path": "/lib/bare/bundles/barePipe.js",
"keys": [
"barePunycode"
"barePipe"
]
},
{
@@ -500,15 +494,21 @@
]
},
{
"path": "/lib/bare/bundles/bareQueueMicrotask.js",
"path": "/lib/bare/bundles/barePunycode.js",
"keys": [
"bareQueueMicrotask"
"barePunycode"
]
},
{
"path": "/lib/bare/bundles/bareProcess.js",
"path": "/lib/bare/bundles/bareNodeRuntime.js",
"keys": [
"bareProcess"
"bareNodeRuntime"
]
},
{
"path": "/lib/bare/bundles/bareQueueMicrotask.js",
"keys": [
"bareQueueMicrotask"
]
},
{
@@ -523,24 +523,18 @@
"barePrebuild"
]
},
{
"path": "/lib/bare/bundles/bareProcess.js",
"keys": [
"bareProcess"
]
},
{
"path": "/lib/bare/bundles/bareRuntime.js",
"keys": [
"bareRuntime"
]
},
{
"path": "/lib/bare/bundles/bareRpc.js",
"keys": [
"bareRpc"
]
},
{
"path": "/lib/bare/bundles/bareDev.js",
"keys": [
"bareDev"
]
},
{
"path": "/lib/bare/bundles/bareSdl.js",
"keys": [
@@ -554,15 +548,15 @@
]
},
{
"path": "/lib/bare/bundles/barePromClient.js",
"path": "/lib/bare/bundles/bareRpc.js",
"keys": [
"barePromClient"
"bareRpc"
]
},
{
"path": "/lib/bare/bundles/bareSignals.js",
"path": "/lib/bare/bundles/barePromClient.js",
"keys": [
"bareSignals"
"barePromClient"
]
},
{
@@ -578,15 +572,21 @@
]
},
{
"path": "/lib/bare/bundles/bareSidecar.js",
"path": "/lib/bare/bundles/bareSignals.js",
"keys": [
"bareSidecar"
"bareSignals"
]
},
{
"path": "/lib/bare/bundles/bareStorage.js",
"path": "/lib/bare/bundles/bareStringDecoder.js",
"keys": [
"bareStorage"
"bareStringDecoder"
]
},
{
"path": "/lib/bare/bundles/bareSidecar.js",
"keys": [
"bareSidecar"
]
},
{
@@ -595,12 +595,6 @@
"bareStream"
]
},
{
"path": "/lib/bare/bundles/bareStdio.js",
"keys": [
"bareStdio"
]
},
{
"path": "/lib/bare/bundles/bareSvg.js",
"keys": [
@@ -608,9 +602,21 @@
]
},
{
"path": "/lib/bare/bundles/bareStringDecoder.js",
"path": "/lib/bare/bundles/bareStdio.js",
"keys": [
"bareStringDecoder"
"bareStdio"
]
},
{
"path": "/lib/bare/bundles/bareStorage.js",
"keys": [
"bareStorage"
]
},
{
"path": "/lib/bare/bundles/bareStructuredClone.js",
"keys": [
"bareStructuredClone"
]
},
{
@@ -625,30 +631,12 @@
"bareSystemLogger"
]
},
{
"path": "/lib/bare/bundles/bareStructuredClone.js",
"keys": [
"bareStructuredClone"
]
},
{
"path": "/lib/bare/bundles/bareTiff.js",
"keys": [
"bareTiff"
]
},
{
"path": "/lib/bare/bundles/bareTimers.js",
"keys": [
"bareTimers"
]
},
{
"path": "/lib/bare/bundles/bareTpl.js",
"keys": [
"bareTpl"
]
},
{
"path": "/lib/bare/bundles/bareSubprocess.js",
"keys": [
@@ -661,48 +649,54 @@
"bareTcp"
]
},
{
"path": "/lib/bare/bundles/bareTimers.js",
"keys": [
"bareTimers"
]
},
{
"path": "/lib/bare/bundles/bareTpl.js",
"keys": [
"bareTpl"
]
},
{
"path": "/lib/bare/bundles/bareType.js",
"keys": [
"bareType"
]
},
{
"path": "/lib/bare/bundles/bareUiKit.js",
"keys": [
"bareUiKit"
]
},
{
"path": "/lib/bare/bundles/bareTty.js",
"keys": [
"bareTty"
]
},
{
"path": "/lib/bare/bundles/bareThread.js",
"keys": [
"bareThread"
]
},
{
"path": "/lib/bare/bundles/bareUiKit.js",
"keys": [
"bareUiKit"
]
},
{
"path": "/lib/bare/bundles/bareTls.js",
"keys": [
"bareTls"
]
},
{
"path": "/lib/bare/bundles/bareTty.js",
"keys": [
"bareTty"
]
},
{
"path": "/lib/bare/bundles/bareUnpack.js",
"keys": [
"bareUnpack"
]
},
{
"path": "/lib/bare/bundles/bareV8.js",
"keys": [
"bareV8"
]
},
{
"path": "/lib/bare/bundles/bareVm.js",
"keys": [
@@ -710,9 +704,9 @@
]
},
{
"path": "/lib/bare/bundles/bareUnionBundle.js",
"path": "/lib/bare/bundles/bareV8.js",
"keys": [
"bareUnionBundle"
"bareV8"
]
},
{
@@ -733,30 +727,30 @@
"bareWebKitGtk"
]
},
{
"path": "/lib/bare/bundles/bareUtils.js",
"keys": [
"bareUtils"
]
},
{
"path": "/lib/bare/bundles/bareWebp.js",
"keys": [
"bareWebp"
]
},
{
"path": "/lib/bare/bundles/bareV8ToIstanbul.js",
"keys": [
"bareV8ToIstanbul"
]
},
{
"path": "/lib/bare/bundles/bareWinUi.js",
"keys": [
"bareWinUi"
]
},
{
"path": "/lib/bare/bundles/bareUnionBundle.js",
"keys": [
"bareUnionBundle"
]
},
{
"path": "/lib/bare/bundles/bareUtils.js",
"keys": [
"bareUtils"
]
},
{
"path": "/lib/bare/bundles/bareXdiff.js",
"keys": [
@@ -764,15 +758,15 @@
]
},
{
"path": "/lib/bare/bundles/bareWhich.js",
"path": "/lib/bare/bundles/bareV8ToIstanbul.js",
"keys": [
"bareWhich"
"bareV8ToIstanbul"
]
},
{
"path": "/lib/bare/bundles/bareZlib.js",
"path": "/lib/bare/bundles/bareWhich.js",
"keys": [
"bareZlib"
"bareWhich"
]
},
{
@@ -787,6 +781,12 @@
"bareWorker"
]
},
{
"path": "/lib/bare/bundles/bareZlib.js",
"keys": [
"bareZlib"
]
},
{
"path": "/lib/bare/bundles/bareZmq.js",
"keys": [
@@ -1607,8 +1607,8 @@
],
"bundleProvenance": {
"schemaVersion": 1,
"generatedAt": "2026-04-26T02:43:51.268Z",
"gitCommit": "51b3b97bc027b9ff4744789bd661bc22f00695dd",
"generatedAt": "2026-04-26T07:05:46.937Z",
"gitCommit": "993c9a438772334e016ef8d822c5272a86bfbe13",
"nodeVersion": "v20.20.2",
"bundleTier": "all",
"normativeManifest": "packages/bare-os-booter/lib/bare-module-manifest.json",
@@ -1,6 +1,6 @@
{
"schema": 1,
"atMs": 1777171429730,
"atMs": 1777187145726,
"commands": [
"agent",
"arch",
@@ -7,3 +7,15 @@ Summarize drive health, peer connections, kernel status, and recent logs.
## /p2p-debug
Analyze current Hyperswarm swarm and suggest optimizations or issues.
## /ops-diagnose
Inspect initd unit phases, timer drop-ins, cron/audit logs, boot policy, and kernel extension resolution; summarize root causes and safe next actions.
## /reasoning-on
Enable process visibility with `edit_agent_config` (`show_reasoning=true`, `reasoning_mode=trace`) and keep output bounded.
## /reasoning-off
Disable reasoning/process output with `edit_agent_config` (`show_reasoning=false`, `reasoning_mode=off`).
@@ -10,7 +10,7 @@ This tree follows the **agent** Markdown workspace convention: “soul” files
| **`~/.agent/workspace/skills/`** | Modular **skills** — one folder per skill, each with **`SKILL.md`** (optional YAML frontmatter) |
| **`~/.agent/workspace/memory/`** | Daily append logs `YYYY-MM-DD.md` (optional) |
| **`~/.agent/skills/`** | Optional **global** skills (lower precedence than `workspace/skills/` when names collide) |
| **`~/.agent/config.json`** | API URL, key, model (existing agent config) |
| **`~/.agent/config.json`** | API URL, key, model, and reasoning/process visibility controls |
| **`~/.agent/skill-loader.js`** | Host stub for `discoverSkills` / `loadSkill` (in-image agent uses bundled discovery + **`read_skill`** tool) |
| **`~/.agent/loader.js`** | Stub / hook for **host-side** experimentation (not used by `/bin/agent` bundle) |
| **`~/.agent/index.js`** | Stub factory reference (in-image agent uses built-in loader) |
@@ -22,10 +22,17 @@ This tree follows the **agent** Markdown workspace convention: “soul” files
3. During a session, the model loads the full document with the **`read_skill`** tool (do not paste huge skills into the user channel unless asked).
4. Shared skills can live under **`~/.agent/skills/`**; keep **`workspace/skills/`** for machine-local or repo-specific behavior.
Seeded examples in this repo (under **`skills/`**): **`p2p-os-status`**, **`bare-os-kernel-proc`**, **`bare-os-super-developer`**, **`holesail`** (managed **`state.json`**, **`seed`**/**`key`**, stock **`bare-www-*`** / **`bare-ssh-*`**), and **`hdms`** (Hyperdrive mounts and invite/pair).
Seeded examples in this repo (under **`skills/`**): **`p2p-os-status`**, **`bare-os-kernel-proc`**, **`bare-os-super-developer`**, **`agent-ops`**, **`holesail`** (managed **`state.json`**, **`seed`**/**`key`**, stock **`bare-www-*`** / **`bare-ssh-*`**), and **`hdms`** (Hyperdrive mounts and invite/pair).
After **`agent --config`** / **`--setup`** (or changing **`owner_name`** / **`agent_label`** via **`edit_agent_config`**), **`IDENTITY.md`** and **`USER.md`** are regenerated from **`config.json`** so the workspace matches the operator and agent label.
Reasoning/process visibility is configurable in `config.json`:
- `show_reasoning` — master toggle
- `reasoning_mode``off` / `summary` / `trace`
- `reasoning_max_chars` — bounded reasoning output
- `reasoning_include_tools` — include tool traces in process stream
## Editing
1. Change files under **`~/.agent/workspace/`** on your **personal** drive.
@@ -3,11 +3,22 @@
## Core OS tools
- **VFS / Hyperdrive** — read/write paths via agent tools (`read_file`, `write_file`, `list_directory`, …) on system and personal drives.
- **Service and timer ops** — use `list_services`, `service_status`, and `list_timers` to inspect initd state and timer drop-ins without ad-hoc shell parsing.
- **Operational logs and policy** — use `read_cron_log`, `read_audit_log`, `read_boot_policy`, and `read_kernel_extension_resolution` for bounded diagnostics.
- **`web_fetch`** — live `http(s)` fetches **only** when the operator allows them (`ctx.httpFetch`, `BARE_OS_HTTP_ALLOWLIST` / denylist). Same policy as delegated `curl` / `wget`.
- **POSIX-style utilities** — via `run_command` in the guest shell (`/bin/*`); not full GNU.
- **Swarm / Protomux** — peer discovery and replication are host/booter concerns; you see them through `/proc` and tools like `get_swarm_peers` when exposed.
- **Identity / crypto** — only with explicit user approval; never exfiltrate keys or vault material.
## Reasoning / process visibility
- Runtime process visibility can be configured in `~/.agent/config.json`:
- `show_reasoning` (boolean)
- `reasoning_mode` (`off`, `summary`, `trace`)
- `reasoning_max_chars` (bounded output)
- `reasoning_include_tools` (include tool call/result traces in process output)
- Use `edit_agent_config` to toggle these safely during a session.
## Skills system
The agent has access to modular **skills** under `~/.agent/workspace/skills/` (and optionally shared skills under `~/.agent/skills/`).
@@ -0,0 +1,31 @@
---
name: agent-ops
version: 1.0.0
description: Diagnose Bare OS runtime state using agent operations tools for services, timers, logs, boot policy, and extension resolution.
tags: [bare-os, operations, initd, cron, audit, diagnostics]
requires: [list_services, service_status, list_timers, read_cron_log, read_audit_log, read_boot_policy, read_kernel_extension_resolution]
---
# agent-ops
Use this skill for operational diagnostics and health checks inside Bare OS.
## Workflow
1. Start with service state:
- `list_services`
- `service_status` for any unit in failed/inactive phase.
2. Inspect scheduling:
- `list_timers` for `~/.config/bare-os/timers/*.timer`
- `read_cron_log` for runtime scheduler failures.
3. Check security/provenance controls:
- `read_boot_policy`
- `read_kernel_extension_resolution`
4. If behavior looks suspicious, read `read_audit_log` (bounded + redacted).
## Output Contract
- Report observed state first (services, timers, policies, extension resolution).
- Separate confirmed facts from hypotheses.
- Suggest safe next actions with minimal blast radius.
- Avoid destructive recommendations unless explicitly requested.
File diff suppressed because one or more lines are too long