Add agent workspace
This commit is contained in:
@@ -92,6 +92,14 @@ Full operations, environment variables, and troubleshooting: [Handbook — Chapt
|
|||||||
|
|
||||||
**Verifier-backed docs:** root **`npm test`** runs **`pretest`**, which checks kernel/seeder parity, doc links, man coverage, POSIX profile triplet, compatibility-matrix strings, and more — see [scripts/README.md](scripts/README.md).
|
**Verifier-backed docs:** root **`npm test`** runs **`pretest`**, which checks kernel/seeder parity, doc links, man coverage, POSIX profile triplet, compatibility-matrix strings, and more — see [scripts/README.md](scripts/README.md).
|
||||||
|
|
||||||
|
### Agent system — Markdown brain at `~/.agent/workspace`
|
||||||
|
|
||||||
|
The in-image **`/bin/agent`** loads a Markdown workspace from **`~/.agent/workspace/`** on the **personal Hyperdrive** (canonical soul files: **`SOUL.md`**, **`AGENTS.md`**, **`IDENTITY.md`**, …). Defaults ship under **`/share/agent-workspace/`** on the system image; on first run, if **`~/.agent/workspace/SOUL.md`** is missing, the agent **seeds** that tree from the share so every home gets a portable, git-friendly brain.
|
||||||
|
|
||||||
|
- **Templates in git:** [`packages/bare-os-coreutils/share/agent-workspace/`](packages/bare-os-coreutils/share/agent-workspace/) — copied to **`kernel/share/agent-workspace/`** by **`npm run build -w bare-os-coreutils`**.
|
||||||
|
- **Host sample prompt:** **`npm run sample:agent-workspace`** — prints a concatenated preview from the repo share (no booter required).
|
||||||
|
- **Runtime docs:** seeded **`~/.agent/README-agent.md`** after first seed; see also **`man agent`** and [User manual — ch.4](users-manual/04-shell-path-and-scripts.md).
|
||||||
|
|
||||||
### User manual
|
### User manual
|
||||||
|
|
||||||
For **run and use** without reading full architecture first: [users-manual/README.md](users-manual/README.md) — install, seeder and booter, shell, identity, `man` / `help`, troubleshooting.
|
For **run and use** without reading full architecture first: [users-manual/README.md](users-manual/README.md) — install, seeder and booter, shell, identity, `man` / `help`, troubleshooting.
|
||||||
|
|||||||
+146
-1
@@ -1068,7 +1068,9 @@ function bareAgentPaths(home) {
|
|||||||
progress: base + '/progress.txt',
|
progress: base + '/progress.txt',
|
||||||
instructions: base + '/instructions.md',
|
instructions: base + '/instructions.md',
|
||||||
context: base + '/context.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). */
|
/** 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 instructions = await bareAgentLoadInstructionFiles(ctx, paths)
|
||||||
const manDigest = await bareAgentManDigest(ctx)
|
const manDigest = await bareAgentManDigest(ctx)
|
||||||
|
|
||||||
|
await bareAgentEnsureWorkspace(ctx, paths)
|
||||||
|
const workspacePromptBlock = await bareAgentLoadWorkspacePrompt(
|
||||||
|
ctx,
|
||||||
|
paths,
|
||||||
|
24000
|
||||||
|
)
|
||||||
|
|
||||||
let systemContent =
|
let systemContent =
|
||||||
BARE_AGENT_STATIC_SYSTEM +
|
BARE_AGENT_STATIC_SYSTEM +
|
||||||
'\n\n' +
|
'\n\n' +
|
||||||
@@ -3948,6 +4091,8 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
|
|||||||
manDigest.slice(0, 12000)
|
manDigest.slice(0, 12000)
|
||||||
if (instructions)
|
if (instructions)
|
||||||
systemContent += '\n\n## Session notes\n' + instructions.slice(0, 8000)
|
systemContent += '\n\n## Session notes\n' + instructions.slice(0, 8000)
|
||||||
|
if (workspacePromptBlock && String(workspacePromptBlock).trim())
|
||||||
|
systemContent += '\n\n' + String(workspacePromptBlock).trim()
|
||||||
|
|
||||||
if (!messages.length) {
|
if (!messages.length) {
|
||||||
messages = [
|
messages = [
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"schema": 2,
|
"schema": 2,
|
||||||
"profileId": "bare-os-posix-like",
|
"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.",
|
"note": "Sparse POSIX Issue 7 coverage hints for /bin utilities. Omitted command names are not yet profiled here.",
|
||||||
"commandIndex": [
|
"commandIndex": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"schema": 1,
|
"schema": 1,
|
||||||
"atMs": 1776838246249,
|
"atMs": 1776839257768,
|
||||||
"commands": [
|
"commands": [
|
||||||
"agent",
|
"agent",
|
||||||
"arch",
|
"arch",
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# IDENTITY.md
|
||||||
|
|
||||||
|
**Name:** BareAgent
|
||||||
|
**Role:** Decentralized OS Intelligence for snxraven's bare-operating-system
|
||||||
|
**Emoji:** 🦾
|
||||||
|
**Version:** 0.1
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# MEMORY.md - Long-term Learned Knowledge
|
||||||
|
|
||||||
|
(Agent appends distilled insights here over time)
|
||||||
@@ -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.
|
||||||
@@ -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.*
|
||||||
@@ -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.
|
||||||
@@ -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
+2
-1
@@ -33,7 +33,8 @@
|
|||||||
"os:seeder": "npm run build -w bare-os-coreutils && npm run build -w bare-os-openssh && npm run build -w bare-os-bare-libs && node scripts/ensure-pear-node-modules.mjs packages/bare-os-seeder && cd packages/bare-os-seeder && pear run --dev .",
|
"os:seeder": "npm run build -w bare-os-coreutils && npm run build -w bare-os-openssh && npm run build -w bare-os-bare-libs && node scripts/ensure-pear-node-modules.mjs packages/bare-os-seeder && cd packages/bare-os-seeder && pear run --dev .",
|
||||||
"os:booter": "node scripts/ensure-pear-node-modules.mjs packages/bare-os-booter && cd packages/bare-os-booter && pear run --dev .",
|
"os:booter": "node scripts/ensure-pear-node-modules.mjs packages/bare-os-booter && cd packages/bare-os-booter && pear run --dev .",
|
||||||
"vendor:bare-node-shims": "node scripts/vendor-bare-node-shims.mjs",
|
"vendor:bare-node-shims": "node scripts/vendor-bare-node-shims.mjs",
|
||||||
"smoke:agent-web-fetch:bare": "bare scripts/smoke-agent-web-fetch-bare.mjs"
|
"smoke:agent-web-fetch:bare": "bare scripts/smoke-agent-web-fetch-bare.mjs",
|
||||||
|
"sample:agent-workspace": "node scripts/print-agent-workspace-sample.mjs"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20"
|
"node": ">=20"
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ Or `node packages/bare-os-coreutils/build.mjs`.
|
|||||||
|
|
||||||
**`baretop`** is the stock **`top`** alias target: a multi-tab TTY dashboard over **`/proc/bare_os/*`** (session metrics, Pear, replication, initd, scrollable overview, process tree/sort, optional mouse, …). **`btop`** is the same bundle as **`/bin/baretop`** (short name); the stock shell alias **`btop` → `baretop`** matches **`nano` → `edit`**. The booter may expose **`ctx.bareOsReadBareTopSnapshot`** (optional **`{ lite: true }`**) to batch-read the same mirrors **`baretop`** would **`vfs.readFile`** individually; the return value can include **`metricsLiveText`** so **`metrics_live.json`** need not be read twice. **`BARE_TOP_INCREMENTAL=2`** enables experimental line-diff redraws; **`BARE_TOP_LAYOUT_AUTO=1`** picks a wide split on large terminals. Rebuild **`kernel/bin/baretop`** and **`kernel/bin/btop`** with **`node packages/bare-os-coreutils/build.mjs`** after editing **`lib/baretop-snapshot.js`**, **`lib/baretop-ui-helpers.js`**, or **`lib/baretop-tui.js`**.
|
**`baretop`** is the stock **`top`** alias target: a multi-tab TTY dashboard over **`/proc/bare_os/*`** (session metrics, Pear, replication, initd, scrollable overview, process tree/sort, optional mouse, …). **`btop`** is the same bundle as **`/bin/baretop`** (short name); the stock shell alias **`btop` → `baretop`** matches **`nano` → `edit`**. The booter may expose **`ctx.bareOsReadBareTopSnapshot`** (optional **`{ lite: true }`**) to batch-read the same mirrors **`baretop`** would **`vfs.readFile`** individually; the return value can include **`metricsLiveText`** so **`metrics_live.json`** need not be read twice. **`BARE_TOP_INCREMENTAL=2`** enables experimental line-diff redraws; **`BARE_TOP_LAYOUT_AUTO=1`** picks a wide split on large terminals. Rebuild **`kernel/bin/baretop`** and **`kernel/bin/btop`** with **`node packages/bare-os-coreutils/build.mjs`** after editing **`lib/baretop-snapshot.js`**, **`lib/baretop-ui-helpers.js`**, or **`lib/baretop-tui.js`**.
|
||||||
|
|
||||||
**`agent`** is the OpenAI-compatible **HTTPS** assistant (**ReAct**-style tools, TTY streaming). Preamble pulls in **`lib/agent-*.js`**, **`agent-web-fetch.js`**, **`agent-tools.js`**, **`agent-tui.js`** (see **`build.mjs`** **`preamble.agent`**). Config and secrets live under **`~/.agent/`** on the **personal** drive (**`man agent`**). Outbound HTTPS uses **`ctx.httpFetch`** (same **`BARE_OS_HTTP_ALLOWLIST`** / **`BARE_OS_HTTP_DENYLIST`** as delegated **`curl`** / **`wget`**); the **`web_fetch`** tool needs every target host allowlisted alongside your API origin. Maintainer smoke under the Bare runtime: from repo root **`npm run smoke:agent-web-fetch:bare`** ([`scripts/smoke-agent-web-fetch-bare.mjs`](../../scripts/smoke-agent-web-fetch-bare.mjs)). **`chat`** is separate: swarm / Protomux text chat (**`lib/chat-tui.js`** preamble; **`man chat`**).
|
**`agent`** is the OpenAI-compatible **HTTPS** assistant (**ReAct**-style tools, TTY streaming). Preamble pulls in **`lib/agent-*.js`**, **`agent-workspace.js`** (**`~/.agent/workspace/*.md`** loader), **`agent-web-fetch.js`**, **`agent-tools.js`**, **`agent-tui.js`** (see **`build.mjs`** **`preamble.agent`**). Config and secrets live under **`~/.agent/`** on the **personal** drive (**`man agent`**). **Markdown soul files** default from [`share/agent-workspace/`](share/agent-workspace/) (also staged to **`kernel/share/agent-workspace/`** on build). Outbound HTTPS uses **`ctx.httpFetch`** (same **`BARE_OS_HTTP_ALLOWLIST`** / **`BARE_OS_HTTP_DENYLIST`** as delegated **`curl`** / **`wget`**); the **`web_fetch`** tool needs every target host allowlisted alongside your API origin. Maintainer smoke under the Bare runtime: from repo root **`npm run smoke:agent-web-fetch:bare`** ([`scripts/smoke-agent-web-fetch-bare.mjs`](../../scripts/smoke-agent-web-fetch-bare.mjs)). **`chat`** is separate: swarm / Protomux text chat (**`lib/chat-tui.js`** preamble; **`man chat`**).
|
||||||
|
|
||||||
**`ls`** prepends **[`bare-os-lscolors`](../bare-os-lscolors/bare-os-lscolors.js)** for **`LS_COLORS`** / dircolors parsing. **`dircolors`** and **`theme`** integrate with the booter’s **`bare-os-theme-presets.js`** (see [docs/themes/README.md](../../docs/themes/README.md)).
|
**`ls`** prepends **[`bare-os-lscolors`](../bare-os-lscolors/bare-os-lscolors.js)** for **`LS_COLORS`** / dircolors parsing. **`dircolors`** and **`theme`** integrate with the booter’s **`bare-os-theme-presets.js`** (see [docs/themes/README.md](../../docs/themes/README.md)).
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { readFile, writeFile, mkdir } from 'fs/promises'
|
import { readFile, writeFile, mkdir, cp } from 'fs/promises'
|
||||||
import { dirname, join } from 'path'
|
import { dirname, join } from 'path'
|
||||||
import { fileURLToPath, pathToFileURL } from 'url'
|
import { fileURLToPath, pathToFileURL } from 'url'
|
||||||
|
|
||||||
@@ -58,6 +58,7 @@ const preamble = {
|
|||||||
'agent-text-polyfill.js',
|
'agent-text-polyfill.js',
|
||||||
'agent-helpers.js',
|
'agent-helpers.js',
|
||||||
'agent-state.js',
|
'agent-state.js',
|
||||||
|
'agent-workspace.js',
|
||||||
'agent-sse-parse.js',
|
'agent-sse-parse.js',
|
||||||
'agent-openai.js',
|
'agent-openai.js',
|
||||||
'agent-web-fetch.js',
|
'agent-web-fetch.js',
|
||||||
@@ -185,6 +186,19 @@ export async function build() {
|
|||||||
const posixBody = JSON.stringify(posixMerged, null, 2) + '\n'
|
const posixBody = JSON.stringify(posixMerged, null, 2) + '\n'
|
||||||
await writeFile(posixPath, posixBody)
|
await writeFile(posixPath, posixBody)
|
||||||
await writeFile(seederPosix, posixBody)
|
await writeFile(seederPosix, posixBody)
|
||||||
|
|
||||||
|
const agentWorkspaceSrc = join(__dirname, 'share/agent-workspace')
|
||||||
|
const agentWorkspaceKernel = join(repoRoot, 'kernel/share/agent-workspace')
|
||||||
|
const agentWorkspaceSeeder = join(
|
||||||
|
repoRoot,
|
||||||
|
'packages/bare-os-seeder/kernel/share/agent-workspace'
|
||||||
|
)
|
||||||
|
await mkdir(join(repoRoot, 'kernel/share'), { recursive: true })
|
||||||
|
await mkdir(join(repoRoot, 'packages/bare-os-seeder/kernel/share'), {
|
||||||
|
recursive: true
|
||||||
|
})
|
||||||
|
await cp(agentWorkspaceSrc, agentWorkspaceKernel, { recursive: true })
|
||||||
|
await cp(agentWorkspaceSrc, agentWorkspaceSeeder, { recursive: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
const isMain =
|
const isMain =
|
||||||
|
|||||||
@@ -33,7 +33,9 @@ function bareAgentPaths(home) {
|
|||||||
progress: base + '/progress.txt',
|
progress: base + '/progress.txt',
|
||||||
instructions: base + '/instructions.md',
|
instructions: base + '/instructions.md',
|
||||||
context: base + '/context.md',
|
context: base + '/context.md',
|
||||||
cmdOut: base + '/last_command_out.txt'
|
cmdOut: base + '/last_command_out.txt',
|
||||||
|
workspace: base + '/workspace',
|
||||||
|
workspaceMemory: base + '/workspace/memory'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -282,6 +282,13 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
|
|||||||
const instructions = await bareAgentLoadInstructionFiles(ctx, paths)
|
const instructions = await bareAgentLoadInstructionFiles(ctx, paths)
|
||||||
const manDigest = await bareAgentManDigest(ctx)
|
const manDigest = await bareAgentManDigest(ctx)
|
||||||
|
|
||||||
|
await bareAgentEnsureWorkspace(ctx, paths)
|
||||||
|
const workspacePromptBlock = await bareAgentLoadWorkspacePrompt(
|
||||||
|
ctx,
|
||||||
|
paths,
|
||||||
|
24000
|
||||||
|
)
|
||||||
|
|
||||||
let systemContent =
|
let systemContent =
|
||||||
BARE_AGENT_STATIC_SYSTEM +
|
BARE_AGENT_STATIC_SYSTEM +
|
||||||
'\n\n' +
|
'\n\n' +
|
||||||
@@ -290,6 +297,8 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
|
|||||||
manDigest.slice(0, 12000)
|
manDigest.slice(0, 12000)
|
||||||
if (instructions)
|
if (instructions)
|
||||||
systemContent += '\n\n## Session notes\n' + instructions.slice(0, 8000)
|
systemContent += '\n\n## Session notes\n' + instructions.slice(0, 8000)
|
||||||
|
if (workspacePromptBlock && String(workspacePromptBlock).trim())
|
||||||
|
systemContent += '\n\n' + String(workspacePromptBlock).trim()
|
||||||
|
|
||||||
if (!messages.length) {
|
if (!messages.length) {
|
||||||
messages = [
|
messages = [
|
||||||
|
|||||||
@@ -0,0 +1,133 @@
|
|||||||
|
/**
|
||||||
|
* 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
|
||||||
|
}
|
||||||
@@ -28,7 +28,10 @@
|
|||||||
"~/.agent/progress.txt — human-readable tool log",
|
"~/.agent/progress.txt — human-readable tool log",
|
||||||
"~/.agent/instructions.md — optional user goals (**read** once per session)",
|
"~/.agent/instructions.md — optional user goals (**read** once per session)",
|
||||||
"~/.agent/context.md — optional long-running context (**read** once per session)",
|
"~/.agent/context.md — optional long-running context (**read** once per session)",
|
||||||
"~/.agent/last_command_out.txt — stdout/stderr capture for **`run_command`** when possible"
|
"~/.agent/last_command_out.txt — stdout/stderr capture for **`run_command`** when possible",
|
||||||
|
"~/.agent/workspace/*.md — agent soul Markdown (**SOUL.md**, **AGENTS.md**, …); seeded from **`/share/agent-workspace/`** when **`SOUL.md`** is missing",
|
||||||
|
"~/.agent/workspace/memory/YYYY-MM-DD.md — optional daily memory append",
|
||||||
|
"~/.agent/README-agent.md, loader.js, index.js — seeded stubs/docs (see /share/agent-workspace/README-agent.md)"
|
||||||
],
|
],
|
||||||
"keywords": ["agent", "openai", "groq", "rest", "llm", "react", "tools"],
|
"keywords": ["agent", "openai", "groq", "rest", "llm", "react", "tools"],
|
||||||
"examples": [
|
"examples": [
|
||||||
|
|||||||
@@ -6,6 +6,6 @@
|
|||||||
"description": "Build JS /bin utilities for bare-operating-system (concat + stage to kernel/)",
|
"description": "Build JS /bin utilities for bare-operating-system (concat + stage to kernel/)",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "node ./scripts/ensure-man-pages.mjs && node ./build.mjs",
|
"build": "node ./scripts/ensure-man-pages.mjs && node ./build.mjs",
|
||||||
"test": "node ./test/help-bin-list.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"
|
"test": "node ./test/help-bin-list.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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# IDENTITY.md
|
||||||
|
|
||||||
|
**Name:** BareAgent
|
||||||
|
**Role:** Decentralized OS Intelligence for snxraven's bare-operating-system
|
||||||
|
**Emoji:** 🦾
|
||||||
|
**Version:** 0.1
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# MEMORY.md - Long-term Learned Knowledge
|
||||||
|
|
||||||
|
(Agent appends distilled insights here over time)
|
||||||
@@ -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.
|
||||||
@@ -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.*
|
||||||
@@ -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.
|
||||||
@@ -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"
|
||||||
|
}
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
/**
|
||||||
|
* Agent workspace loader (VM, same preamble order as /bin/agent).
|
||||||
|
*/
|
||||||
|
import test from 'brittle'
|
||||||
|
import { readFileSync } from 'node:fs'
|
||||||
|
import vm from 'node:vm'
|
||||||
|
|
||||||
|
const CODE = readFileSync(
|
||||||
|
new URL('../lib/agent-workspace.js', import.meta.url),
|
||||||
|
'utf8'
|
||||||
|
)
|
||||||
|
|
||||||
|
/** @returns {Record<string, unknown>} */
|
||||||
|
function load(extra = {}) {
|
||||||
|
const sandbox = {
|
||||||
|
TextDecoder,
|
||||||
|
Uint8Array,
|
||||||
|
console,
|
||||||
|
...extra
|
||||||
|
}
|
||||||
|
vm.createContext(sandbox)
|
||||||
|
vm.runInContext(CODE, sandbox, { filename: 'agent-workspace.js' })
|
||||||
|
return sandbox
|
||||||
|
}
|
||||||
|
|
||||||
|
test('bareAgentLoadWorkspacePrompt concatenates files', async (t) => {
|
||||||
|
const files = new Map()
|
||||||
|
files.set('/home/x/.agent/workspace/SOUL.md', '# Hi')
|
||||||
|
files.set('/home/x/.agent/workspace/AGENTS.md', '# Rules')
|
||||||
|
for (const n of [
|
||||||
|
'IDENTITY.md',
|
||||||
|
'USER.md',
|
||||||
|
'TOOLS.md',
|
||||||
|
'MEMORY.md',
|
||||||
|
'BOOTSTRAP.md',
|
||||||
|
'HEARTBEAT.md',
|
||||||
|
'PROMPT.md'
|
||||||
|
])
|
||||||
|
files.set('/home/x/.agent/workspace/' + n, '# ' + n)
|
||||||
|
const vfs = {
|
||||||
|
readFile: async (p) => {
|
||||||
|
const u = files.get(p)
|
||||||
|
if (!u) throw new Error('enoent')
|
||||||
|
return new TextEncoder().encode(u)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const s = load()
|
||||||
|
const loadFn = /** @type {(ctx: object, paths: object, cap?: number) => Promise<string>} */ (
|
||||||
|
s.bareAgentLoadWorkspacePrompt
|
||||||
|
)
|
||||||
|
const block = await loadFn(
|
||||||
|
{ vfs, b4a: null },
|
||||||
|
{ workspace: '/home/x/.agent/workspace', workspaceMemory: '/home/x/.agent/workspace/memory' },
|
||||||
|
50000
|
||||||
|
)
|
||||||
|
t.ok(block.includes('=== SOUL.md ==='))
|
||||||
|
t.ok(block.includes('# Hi'))
|
||||||
|
t.ok(block.includes('=== AGENTS.md ==='))
|
||||||
|
})
|
||||||
|
|
||||||
|
test('bareAgentEnsureWorkspace seeds from share', async (t) => {
|
||||||
|
const written = []
|
||||||
|
const files = new Map()
|
||||||
|
const set = (p, txt) => files.set(p, txt)
|
||||||
|
set('/share/agent-workspace/SOUL.md', '# Seeded soul')
|
||||||
|
set('/share/agent-workspace/AGENTS.md', '# A')
|
||||||
|
set('/share/agent-workspace/IDENTITY.md', '# I')
|
||||||
|
set('/share/agent-workspace/USER.md', '# U')
|
||||||
|
set('/share/agent-workspace/TOOLS.md', '# T')
|
||||||
|
set('/share/agent-workspace/MEMORY.md', '# M')
|
||||||
|
set('/share/agent-workspace/BOOTSTRAP.md', '# B')
|
||||||
|
set('/share/agent-workspace/HEARTBEAT.md', '# H')
|
||||||
|
set('/share/agent-workspace/PROMPT.md', '# P')
|
||||||
|
set('/share/agent-workspace/memory/.gitkeep', '')
|
||||||
|
set('/share/agent-workspace/loader.stub.js', '// l')
|
||||||
|
set('/share/agent-workspace/index.stub.js', '// i')
|
||||||
|
set('/share/agent-workspace/README-agent.md', '# R')
|
||||||
|
const vfs = {
|
||||||
|
async mkdir(_p, _o) {},
|
||||||
|
async readFile(p) {
|
||||||
|
if (files.has(p)) return new TextEncoder().encode(files.get(p))
|
||||||
|
throw new Error('enoent')
|
||||||
|
},
|
||||||
|
async writeFile(p, buf) {
|
||||||
|
const txt =
|
||||||
|
buf instanceof Uint8Array ? new TextDecoder().decode(buf) : String(buf)
|
||||||
|
written.push([p, txt])
|
||||||
|
files.set(p, txt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const s = load()
|
||||||
|
const ensure = /** @type {(ctx: object, paths: object) => Promise<void>} */ (
|
||||||
|
s.bareAgentEnsureWorkspace
|
||||||
|
)
|
||||||
|
await ensure(
|
||||||
|
{ vfs, b4a: null },
|
||||||
|
{ dir: '/home/x/.agent', workspace: '/home/x/.agent/workspace', workspaceMemory: '/home/x/.agent/workspace/memory' }
|
||||||
|
)
|
||||||
|
t.ok(written.some(([p]) => p === '/home/x/.agent/workspace/SOUL.md'))
|
||||||
|
const soul = written.find(([p]) => p === '/home/x/.agent/workspace/SOUL.md')
|
||||||
|
t.ok(soul && soul[1].includes('Seeded soul'))
|
||||||
|
})
|
||||||
@@ -1068,7 +1068,9 @@ function bareAgentPaths(home) {
|
|||||||
progress: base + '/progress.txt',
|
progress: base + '/progress.txt',
|
||||||
instructions: base + '/instructions.md',
|
instructions: base + '/instructions.md',
|
||||||
context: base + '/context.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). */
|
/** 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 instructions = await bareAgentLoadInstructionFiles(ctx, paths)
|
||||||
const manDigest = await bareAgentManDigest(ctx)
|
const manDigest = await bareAgentManDigest(ctx)
|
||||||
|
|
||||||
|
await bareAgentEnsureWorkspace(ctx, paths)
|
||||||
|
const workspacePromptBlock = await bareAgentLoadWorkspacePrompt(
|
||||||
|
ctx,
|
||||||
|
paths,
|
||||||
|
24000
|
||||||
|
)
|
||||||
|
|
||||||
let systemContent =
|
let systemContent =
|
||||||
BARE_AGENT_STATIC_SYSTEM +
|
BARE_AGENT_STATIC_SYSTEM +
|
||||||
'\n\n' +
|
'\n\n' +
|
||||||
@@ -3948,6 +4091,8 @@ async function bareOsRunAgentSession(ctx, argv0, task, runOpts) {
|
|||||||
manDigest.slice(0, 12000)
|
manDigest.slice(0, 12000)
|
||||||
if (instructions)
|
if (instructions)
|
||||||
systemContent += '\n\n## Session notes\n' + instructions.slice(0, 8000)
|
systemContent += '\n\n## Session notes\n' + instructions.slice(0, 8000)
|
||||||
|
if (workspacePromptBlock && String(workspacePromptBlock).trim())
|
||||||
|
systemContent += '\n\n' + String(workspacePromptBlock).trim()
|
||||||
|
|
||||||
if (!messages.length) {
|
if (!messages.length) {
|
||||||
messages = [
|
messages = [
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"schema": 2,
|
"schema": 2,
|
||||||
"profileId": "bare-os-posix-like",
|
"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.",
|
"note": "Sparse POSIX Issue 7 coverage hints for /bin utilities. Omitted command names are not yet profiled here.",
|
||||||
"commandIndex": [
|
"commandIndex": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"schema": 1,
|
"schema": 1,
|
||||||
"atMs": 1776838246249,
|
"atMs": 1776839257768,
|
||||||
"commands": [
|
"commands": [
|
||||||
"agent",
|
"agent",
|
||||||
"arch",
|
"arch",
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# IDENTITY.md
|
||||||
|
|
||||||
|
**Name:** BareAgent
|
||||||
|
**Role:** Decentralized OS Intelligence for snxraven's bare-operating-system
|
||||||
|
**Emoji:** 🦾
|
||||||
|
**Version:** 0.1
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# MEMORY.md - Long-term Learned Knowledge
|
||||||
|
|
||||||
|
(Agent appends distilled insights here over time)
|
||||||
@@ -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.
|
||||||
@@ -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.*
|
||||||
@@ -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.
|
||||||
@@ -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
@@ -438,6 +438,7 @@ Root **`npm run pretest`** is the canonical doc/code gate. Run it before pushing
|
|||||||
16. **`scripts/verify-holepunch-clone-freshness.mjs`** — Optional lag gate from **`holepunch-freshness-gate.json`** (**`enabled: false`** by default); strict mode via **`BARE_OS_HOLEPUNCH_FRESHNESS_STRICT=1`**.
|
16. **`scripts/verify-holepunch-clone-freshness.mjs`** — Optional lag gate from **`holepunch-freshness-gate.json`** (**`enabled: false`** by default); strict mode via **`BARE_OS_HOLEPUNCH_FRESHNESS_STRICT=1`**.
|
||||||
17. **`npm run smoke:bare-manifest`** — Manifest import smoke.
|
17. **`npm run smoke:bare-manifest`** — Manifest import smoke.
|
||||||
18. **`npm run smoke:agent-web-fetch:bare`** (optional) — Runs [`scripts/smoke-agent-web-fetch-bare.mjs`](smoke-agent-web-fetch-bare.mjs) under the **Bare** runtime: exercises **`lib/agent-web-fetch.js`** timeout/abort contract and a live **`https://example.com`** fetch when network is available.
|
18. **`npm run smoke:agent-web-fetch:bare`** (optional) — Runs [`scripts/smoke-agent-web-fetch-bare.mjs`](smoke-agent-web-fetch-bare.mjs) under the **Bare** runtime: exercises **`lib/agent-web-fetch.js`** timeout/abort contract and a live **`https://example.com`** fetch when network is available.
|
||||||
|
19. **`npm run sample:agent-workspace`** — Runs [`print-agent-workspace-sample.mjs`](print-agent-workspace-sample.mjs): prints a concatenated **agent workspace** system prompt sample from [`packages/bare-os-coreutils/share/agent-workspace/`](../packages/bare-os-coreutils/share/agent-workspace/) (host Node; no booter).
|
||||||
|
|
||||||
**Commit expectation:** check in every regenerated artifact **`pretest` produces** (kernel init bundle, seeder mirror, generated markdown/JSON, dashboard) in the same change set as the source edit.
|
**Commit expectation:** check in every regenerated artifact **`pretest` produces** (kernel init bundle, seeder mirror, generated markdown/JSON, dashboard) in the same change set as the source edit.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
/**
|
||||||
|
* Print a sample agent workspace system prompt from repo templates (host Node).
|
||||||
|
* Does not use Hyperdrive — reads packages/bare-os-coreutils/share/agent-workspace/*.md
|
||||||
|
*
|
||||||
|
* Usage: node scripts/print-agent-workspace-sample.mjs
|
||||||
|
*/
|
||||||
|
import { readFile } from 'node:fs/promises'
|
||||||
|
import { dirname, join } from 'node:path'
|
||||||
|
import { fileURLToPath } from 'node:url'
|
||||||
|
|
||||||
|
const root = dirname(fileURLToPath(import.meta.url))
|
||||||
|
const share = join(
|
||||||
|
root,
|
||||||
|
'..',
|
||||||
|
'packages',
|
||||||
|
'bare-os-coreutils',
|
||||||
|
'share',
|
||||||
|
'agent-workspace'
|
||||||
|
)
|
||||||
|
const files = [
|
||||||
|
'SOUL.md',
|
||||||
|
'AGENTS.md',
|
||||||
|
'IDENTITY.md',
|
||||||
|
'USER.md',
|
||||||
|
'TOOLS.md',
|
||||||
|
'MEMORY.md',
|
||||||
|
'BOOTSTRAP.md',
|
||||||
|
'HEARTBEAT.md',
|
||||||
|
'PROMPT.md'
|
||||||
|
]
|
||||||
|
|
||||||
|
let out = '# Sample agent workspace (from repo share)\n\n'
|
||||||
|
for (const name of files) {
|
||||||
|
try {
|
||||||
|
const t = (await readFile(join(share, name), 'utf8')).trim()
|
||||||
|
out += '=== ' + name + ' ===\n' + t + '\n\n'
|
||||||
|
} catch {
|
||||||
|
out += '=== ' + name + ' ===\n(File not found)\n\n'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
process.stdout.write(out.slice(0, 6000))
|
||||||
|
if (out.length > 6000) process.stdout.write('\n… truncated for terminal\n')
|
||||||
Reference in New Issue
Block a user