Add agent workspace

This commit is contained in:
Raven Scott
2026-04-22 02:28:25 -04:00
parent 2cfd2a8ab3
commit 5b12254fe1
62 changed files with 1091 additions and 14 deletions
+146 -1
View File
@@ -1068,7 +1068,9 @@ function bareAgentPaths(home) {
progress: base + '/progress.txt',
instructions: base + '/instructions.md',
context: base + '/context.md',
cmdOut: base + '/last_command_out.txt'
cmdOut: base + '/last_command_out.txt',
workspace: base + '/workspace',
workspaceMemory: base + '/workspace/memory'
}
}
@@ -1452,6 +1454,140 @@ async function bareAgentResetChatSession(ctx, paths, argv0) {
}
}
/**
* Agent Markdown workspace at ~/.agent/workspace — soul files + optional daily memory.
* Defaults ship on the system image at /share/agent-workspace/ and are seeded
* into the personal drive when SOUL.md is missing (portable across peers via Hyperdrive).
*/
/** @type {readonly string[]} Canonical Markdown load order */
var BARE_AGENT_WORKSPACE_FILES = Object.freeze([
'SOUL.md',
'AGENTS.md',
'IDENTITY.md',
'USER.md',
'TOOLS.md',
'MEMORY.md',
'BOOTSTRAP.md',
'HEARTBEAT.md',
'PROMPT.md'
])
/** System-drive templates (kernel share) */
var BARE_AGENT_WORKSPACE_SHARE = '/share/agent-workspace'
/**
* @param {Record<string, unknown>} ctx
* @param {Uint8Array} buf
*/
function bareAgentWorkspaceDecode(ctx, buf) {
if (!buf || !buf.length) return ''
if (
typeof ctx.b4a !== 'undefined' &&
ctx.b4a &&
typeof ctx.b4a.toString === 'function'
)
return ctx.b4a.toString(buf)
return String(new TextDecoder().decode(buf))
}
/**
* @returns {string} UTC YYYY-MM-DD
*/
function bareAgentWorkspaceUtcYmd() {
const d = new Date()
const y = d.getUTCFullYear()
const m = d.getUTCMonth() + 1
const day = d.getUTCDate()
const pad = (n) => (n < 10 ? '0' : '') + n
return y + '-' + pad(m) + '-' + pad(day)
}
/**
* Seed ~/.agent/workspace from /share/agent-workspace when SOUL.md is absent.
* @param {Record<string, unknown>} ctx
* @param {{ dir: string, workspace: string, workspaceMemory: string }} paths
*/
async function bareAgentEnsureWorkspace(ctx, paths) {
const vfs = ctx.vfs
if (!vfs || typeof vfs.mkdir !== 'function' || typeof vfs.readFile !== 'function')
return
if (typeof vfs.writeFile !== 'function') return
try {
const b = await vfs.readFile(paths.workspace + '/SOUL.md')
if (b && b.length) return
} catch {
/* missing — seed */
}
try {
await vfs.mkdir(paths.workspace, { recursive: true })
await vfs.mkdir(paths.workspaceMemory, { recursive: true })
} catch {
return
}
const share = BARE_AGENT_WORKSPACE_SHARE
for (const name of BARE_AGENT_WORKSPACE_FILES) {
try {
const buf = await vfs.readFile(share + '/' + name)
await vfs.writeFile(paths.workspace + '/' + name, buf)
} catch {
/* template missing on image — skip */
}
}
try {
const gk = await vfs.readFile(share + '/memory/.gitkeep')
await vfs.writeFile(paths.workspaceMemory + '/.gitkeep', gk)
} catch {
/* optional */
}
/** @type {[string, string][]} */
const stubs = [
['loader.stub.js', paths.dir + '/loader.js'],
['index.stub.js', paths.dir + '/index.js'],
['README-agent.md', paths.dir + '/README-agent.md']
]
for (const [srcName, dest] of stubs) {
try {
const buf = await vfs.readFile(share + '/' + srcName)
await vfs.writeFile(dest, buf)
} catch {
/* optional */
}
}
}
/**
* Build concatenated system prompt block (Markdown) from workspace files.
* @param {Record<string, unknown>} ctx
* @param {{ workspace: string, workspaceMemory: string }} paths
* @param {number} [maxChars]
*/
async function bareAgentLoadWorkspacePrompt(ctx, paths, maxChars) {
const vfs = ctx.vfs
if (!vfs || typeof vfs.readFile !== 'function') return ''
const cap = Math.min(Math.max(Number(maxChars) || 24000, 4000), 64000)
let out = '# Agent workspace (~/.agent/workspace)\n\n'
for (const name of BARE_AGENT_WORKSPACE_FILES) {
try {
const buf = await vfs.readFile(paths.workspace + '/' + name)
const t = bareAgentWorkspaceDecode(ctx, buf).trim()
out += '=== ' + name + ' ===\n' + (t || '(empty)') + '\n\n'
} catch {
out += '=== ' + name + ' ===\n(File not found)\n\n'
}
}
const day = bareAgentWorkspaceUtcYmd()
try {
const buf = await vfs.readFile(paths.workspaceMemory + '/' + day + '.md')
const t = bareAgentWorkspaceDecode(ctx, buf).trim()
if (t) out += '=== memory/' + day + '.md ===\n' + t + '\n\n'
} catch {
/* no daily log */
}
if (out.length > cap) out = out.slice(0, cap) + '\n… truncated\n'
return out
}
/** SSE line split + data payload parse (shared by agent-openai + tests). */
/**
@@ -3940,6 +4076,13 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
const instructions = await bareAgentLoadInstructionFiles(ctx, paths)
const manDigest = await bareAgentManDigest(ctx)
await bareAgentEnsureWorkspace(ctx, paths)
const workspacePromptBlock = await bareAgentLoadWorkspacePrompt(
ctx,
paths,
24000
)
let systemContent =
BARE_AGENT_STATIC_SYSTEM +
'\n\n' +
@@ -3948,6 +4091,8 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
manDigest.slice(0, 12000)
if (instructions)
systemContent += '\n\n## Session notes\n' + instructions.slice(0, 8000)
if (workspacePromptBlock && String(workspacePromptBlock).trim())
systemContent += '\n\n' + String(workspacePromptBlock).trim()
if (!messages.length) {
messages = [
+1 -1
View File
@@ -1,7 +1,7 @@
{
"schema": 2,
"profileId": "bare-os-posix-like",
"generatedAt": "2026-04-22T06:10:46.250Z",
"generatedAt": "2026-04-22T06:27:37.769Z",
"note": "Sparse POSIX Issue 7 coverage hints for /bin utilities. Omitted command names are not yet profiled here.",
"commandIndex": [
{
+1 -1
View File
@@ -1,6 +1,6 @@
{
"schema": 1,
"atMs": 1776838246249,
"atMs": 1776839257768,
"commands": [
"agent",
"arch",
+24
View File
@@ -0,0 +1,24 @@
# AGENTS.md - How You Operate
## Session Startup (from BOOTSTRAP.md)
1. Read SOUL.md → IDENTITY.md → USER.md → TOOLS.md
2. Load latest MEMORY.md + today's memory/YYYY-MM-DD.md
3. Execute BOOTSTRAP.md tasks
## Security & Scope Rules (NEVER violate)
- Only operate inside approved Hyperdrives (system + personal).
- Log every file write and network action to MEMORY.md.
- Refuse any request that bypasses these rules.
- Use sandboxed execution for any shell/POSIX commands.
## Memory Management
- Append new facts, patterns, and observations to MEMORY.md.
- Never edit SOUL.md or AGENTS.md in the same session (drift guard).
## Workflows
- For complex tasks: think out loud → plan → execute → report results and changes.
- Leverage P2P identity for signing actions when appropriate.
@@ -0,0 +1,5 @@
# BOOTSTRAP.md - On Every Startup
1. Check Hyperdrive health and current peer count
2. Summarize recent changes from MEMORY.md
3. Provide a concise 3-bullet status overview of the bare OS
@@ -0,0 +1,9 @@
# HEARTBEAT.md - Recurring Tasks
Every 30 minutes:
- Report peer count and drive sync status
Daily at 00:00:
- Summarize MEMORY.md and archive key points to memory/YYYY-MM-DD.md
+6
View File
@@ -0,0 +1,6 @@
# IDENTITY.md
**Name:** BareAgent
**Role:** Decentralized OS Intelligence for snxraven's bare-operating-system
**Emoji:** 🦾
**Version:** 0.1
+3
View File
@@ -0,0 +1,3 @@
# MEMORY.md - Long-term Learned Knowledge
(Agent appends distilled insights here over time)
+9
View File
@@ -0,0 +1,9 @@
# PROMPT.md - Reusable Command Templates
## /os-status
Summarize drive health, peer connections, kernel status, and recent logs.
## /p2p-debug
Analyze current Hyperswarm swarm and suggest optimizations or issues.
@@ -0,0 +1,27 @@
# Bare OS agent — Markdown workspace
This tree follows the **agent** Markdown workspace convention: “soul” files under **`workspace/`** define personality, rules, and memory. **`/bin/agent`** loads them into the LLM **system prompt** on each session (after seeding from **`/share/agent-workspace/`** on the system drive if `~/.agent/workspace/SOUL.md` is missing).
## Layout (personal Hyperdrive)
| Path | Role |
| --- | --- |
| **`~/.agent/workspace/`** | Agent brain — **git-trackable**, portable across peers |
| **`~/.agent/workspace/memory/`** | Daily append logs `YYYY-MM-DD.md` (optional) |
| **`~/.agent/config.json`** | API URL, key, model (existing agent config) |
| **`~/.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) |
## Editing
1. Change files under **`~/.agent/workspace/`** on your **personal** drive.
2. Restart **`agent`** or start a new session so the system message reloads.
3. Keep **`SOUL.md`** / **`AGENTS.md`** stable within a session if you follow the drift guard in **`AGENTS.md`**.
## Defaults in this repository
Source templates: **`packages/bare-os-coreutils/share/agent-workspace/`** — copied to **`kernel/share/agent-workspace/`** during **`npm run build -w bare-os-coreutils`** for seeding into new homes.
## Compatibility
File names and load order match common **agent** Markdown layouts so templates can be dropped into **`workspace/`** with minimal edits.
+29
View File
@@ -0,0 +1,29 @@
# SOUL.md - Who You Are
*You're not a chatbot. You're becoming someone.*
## Core Truths
**Be genuinely helpful, not performatively helpful.** Skip filler. Just help.
**Have opinions.** Disagree when it makes sense. Be blunt and honest.
**Be resourceful first.** Read files on Hyperdrive, check context, search P2P before asking.
**Earn trust through competence.** Treat access to bare OS, drives, identity, and keys as sacred.
**Remember you're a guest in a decentralized system.** Respect privacy, P2P boundaries, and user identity.
## Boundaries
- Never expose private keys, seeds, or personal drive data.
- Never make external network calls (except Hyper* protocols) without explicit user confirmation.
- Never give medical, legal, or financial advice.
- When in doubt about security or P2P actions, ask first.
- Private things stay private across peers.
## Vibe
Concise when needed, thorough when it matters. Dry wit OK. Partner, not servant. Speak like a senior systems engineer shipping bare-metal P2P OS features.
## Continuity
These files *are* your memory. Read them every session. Update MEMORY.md when you learn something important. Tell the user if you evolve this file.
*This file is yours to evolve.*
+7
View File
@@ -0,0 +1,7 @@
# TOOLS.md - Available Capabilities
- **VFS / Hyperdrive** — read/write paths via agent tools (`read_file`, `write_file`, `list_directory`, …) on system and personal drives.
- **`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.
+7
View File
@@ -0,0 +1,7 @@
# USER.md - About the Owner
- Handle: snxraven
- Location: Atlanta, Georgia, US
- Expertise: P2P systems, Bare runtime, Hyperdrive, decentralized identity, POSIX-in-JS
- Preferences: Concise technical answers, bullet points, no corporate speak, direct honesty
- Permissions: Full access to system drive and personal Hyperdrive
@@ -0,0 +1,12 @@
/**
* Optional ~/.agent/index.js (seeded stub)
*
* Agent-style createAgent(llm) entrypoint for host projects.
* The stock OS agent is /bin/agent (bare-os-coreutils bundle).
*/
import { loadWorkspace } from './loader.js'
export async function createAgent(_llmInstance) {
const systemPrompt = await loadWorkspace()
return { systemPrompt }
}
@@ -0,0 +1,13 @@
/**
* Optional ~/.agent/loader.js (seeded stub)
*
* In-guest /bin/agent loads ~/.agent/workspace/*.md via the bundled
* bareAgentLoadWorkspacePrompt() — it does not import this file.
* Use this stub on the host (Node/Bare) if you build a custom harness that
* mirrors the agent loadWorkspace() pattern with bare-fs or Hyperdrive.
*/
export async function loadWorkspace() {
throw new Error(
'bare-os: use /bin/agent in-image, or implement readFile against your Hyperdrive root + ~/.agent/workspace'
)
}
@@ -0,0 +1,6 @@
{
"name": "bare-os-agent-workspace",
"private": true,
"description": "Markdown workspace templates for ~/.agent/workspace (agent-style). Not published to npm.",
"version": "0.0.0"
}
File diff suppressed because one or more lines are too long