fabiana 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -0
- package/ascii.txt +10 -0
- package/dist/daemon/index.js +3 -1
- package/dist/loaders/context.js +18 -2
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -57,6 +57,21 @@ She's built on [Pi SDK](https://github.com/mariozechner/pi) — which means she
|
|
|
57
57
|
|
|
58
58
|
Memory is tiered — hot files load every session, warm files load when relevant, cold files sit in the archive, searchable when needed. She writes and organizes it herself. You can read any of it any time.
|
|
59
59
|
|
|
60
|
+
### Everything lives in `~/.fabiana`
|
|
61
|
+
|
|
62
|
+
Your data, config, and even her system prompt all live in one place:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
~/.fabiana/
|
|
66
|
+
├── data/memory/ ← everything she remembers about you
|
|
67
|
+
├── config/system.md ← her base personality and instructions
|
|
68
|
+
├── config/system-chat.md ← how she behaves in conversation
|
|
69
|
+
├── config/manifest.json ← what files she's allowed to touch
|
|
70
|
+
└── .env ← your API keys
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
No black boxes. Open `~/.fabiana/config/system.md` to see exactly what she's been told to do — or edit it to change how she thinks, speaks, or behaves. Want her to be more terse? More philosophical? Less likely to roast you at 1am? That's the file.
|
|
74
|
+
|
|
60
75
|
---
|
|
61
76
|
|
|
62
77
|
## Installation
|
package/ascii.txt
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
________ ____ _______ .-./`) ____ ,---. .--. ____
|
|
2
|
+
| | .' __ `. \ ____ \\ .-.') .' __ `. | \ | | .' __ `.
|
|
3
|
+
| .----'/ ' \ \| | \ |/ `-' \/ ' \ \| , \ | |/ ' \ \
|
|
4
|
+
| _|____ |___| / || |____/ / `-'`"`|___| / || |\_ \| ||___| / |
|
|
5
|
+
|_( )_ | _.-` || _ _ '. .---. _.-` || _( )_\ | _.-` |
|
|
6
|
+
(_ o._)__|.' _ || ( ' ) \| | .' _ || (_ o _) |.' _ |
|
|
7
|
+
|(_,_) | _( )_ || (_{;}_) || | | _( )_ || (_,_)\ || _( )_ |
|
|
8
|
+
| | \ (_ o _) /| (_,_) /| | \ (_ o _) /| | | |\ (_ o _) /
|
|
9
|
+
'---' '.(_,_).' /_______.' '---' '.(_,_).' '--' '--' '.(_,_).'
|
|
10
|
+
|
package/dist/daemon/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import { Logger } from '../utils/logger.js';
|
|
|
9
9
|
import { createFabianaTools } from '../tools/index.js';
|
|
10
10
|
import { loadContext, buildPrompt } from '../loaders/context.js';
|
|
11
11
|
import { loadPlugins } from '../loaders/plugins.js';
|
|
12
|
-
import { paths, PLUGINS_DIR } from '../paths.js';
|
|
12
|
+
import { paths, PLUGINS_DIR, FABIANA_HOME } from '../paths.js';
|
|
13
13
|
async function loadConfig() {
|
|
14
14
|
try {
|
|
15
15
|
const content = await fs.readFile(paths.configJson, 'utf-8');
|
|
@@ -48,6 +48,8 @@ export async function runPiSession(mode, incomingMessage, channel, incomingMsg,
|
|
|
48
48
|
let systemPromptContent = modeSystemPrompt
|
|
49
49
|
? `${baseSystemPrompt}\n\n---\n\n${modeSystemPrompt}`
|
|
50
50
|
: baseSystemPrompt;
|
|
51
|
+
// Resolve .fabiana/ references to the actual home path so Fabiana uses correct absolute paths
|
|
52
|
+
systemPromptContent = systemPromptContent.replaceAll('.fabiana/', `${FABIANA_HOME}/`);
|
|
51
53
|
// Inject owner name and conversation purpose into external system prompt
|
|
52
54
|
if (mode.startsWith('external-')) {
|
|
53
55
|
const identity = await fs.readFile(paths.memory('identity.md'), 'utf-8').catch(() => '');
|
package/dist/loaders/context.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import fs from 'fs/promises';
|
|
2
2
|
import { paths } from '../paths.js';
|
|
3
|
+
const TODAY_LOG_MAX_LINES = 80;
|
|
3
4
|
export async function loadContext(mode, incomingMessage, conversationState) {
|
|
4
5
|
const timestamp = new Date().toISOString();
|
|
6
|
+
const today = timestamp.slice(0, 10);
|
|
5
7
|
const identity = await readFile(paths.memory('identity.md'), '(No identity file yet)');
|
|
6
8
|
const core = await readFile(paths.memory('core.md'), '(No core memory yet)');
|
|
7
9
|
const recentMemory = await readFile(paths.memory('recent', 'this-week.md'), '(No recent memory yet)');
|
|
8
|
-
|
|
10
|
+
const rawLog = await readFile(paths.logs(`conversation-${today}.log`), '');
|
|
11
|
+
const todayLog = tailLines(rawLog, TODAY_LOG_MAX_LINES);
|
|
12
|
+
return { mode, identity, core, recentMemory, todayLog, incomingMessage, timestamp, conversationState };
|
|
9
13
|
}
|
|
10
14
|
async function readFile(filePath, fallback) {
|
|
11
15
|
try {
|
|
@@ -15,7 +19,19 @@ async function readFile(filePath, fallback) {
|
|
|
15
19
|
return fallback;
|
|
16
20
|
}
|
|
17
21
|
}
|
|
22
|
+
function tailLines(text, maxLines) {
|
|
23
|
+
if (!text)
|
|
24
|
+
return '';
|
|
25
|
+
const lines = text.split('\n').filter(l => l.trim());
|
|
26
|
+
if (lines.length <= maxLines)
|
|
27
|
+
return lines.join('\n');
|
|
28
|
+
const omitted = lines.length - maxLines;
|
|
29
|
+
return `(${omitted} earlier lines omitted — full log in ${paths.logs('conversation-' + new Date().toISOString().slice(0, 10) + '.log')})\n...\n` + lines.slice(-maxLines).join('\n');
|
|
30
|
+
}
|
|
18
31
|
export function buildPrompt(ctx) {
|
|
32
|
+
const todaySection = ctx.todayLog
|
|
33
|
+
? `\n\n### Today's Conversation\n${ctx.todayLog}`
|
|
34
|
+
: '';
|
|
19
35
|
const base = `# Session Start — ${ctx.timestamp}
|
|
20
36
|
**Mode**: ${ctx.mode}
|
|
21
37
|
|
|
@@ -30,7 +46,7 @@ ${ctx.identity}
|
|
|
30
46
|
${ctx.core}
|
|
31
47
|
|
|
32
48
|
### Recent (This Week)
|
|
33
|
-
${ctx.recentMemory}`;
|
|
49
|
+
${ctx.recentMemory}${todaySection}`;
|
|
34
50
|
if (ctx.mode === 'chat' && ctx.incomingMessage) {
|
|
35
51
|
return `${base}
|
|
36
52
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fabiana",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Personal AI assistant that actually feels personal",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
},
|
|
18
18
|
"files": [
|
|
19
19
|
"bin/",
|
|
20
|
-
"dist/"
|
|
20
|
+
"dist/",
|
|
21
|
+
"ascii.txt"
|
|
21
22
|
],
|
|
22
23
|
"keywords": [
|
|
23
24
|
"ai",
|