pacs-core 0.1.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/LICENSE +21 -0
- package/README.md +602 -0
- package/bin/pacs-cli.js +7 -0
- package/package.json +31 -0
- package/phase2-test.mjs +53 -0
- package/src/agent-creator.js +178 -0
- package/src/agent-registry.js +165 -0
- package/src/bootstrap.js +245 -0
- package/src/cli.js +384 -0
- package/src/crypto.js +118 -0
- package/src/index.js +74 -0
- package/src/inter-agent-bus.js +187 -0
- package/src/learn-mode.js +97 -0
- package/src/learning-loop.js +254 -0
- package/src/memory-store.js +226 -0
- package/src/openclaw-bridge.cjs +214 -0
- package/src/openclaw-bridge.js +304 -0
- package/src/routing-engine.js +221 -0
- package/src/test.js +298 -0
- package/src/trigger-parser.js +187 -0
- package/src/triggers.json +122 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 PACS Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,602 @@
|
|
|
1
|
+
# PACS Core — Personal AI Control System
|
|
2
|
+
|
|
3
|
+
**Phase 1 Foundation** | MIT License | Encrypted Storage Layer
|
|
4
|
+
|
|
5
|
+
> PACS replaces the traditional Agent/Skill MD-file system with encrypted, AI-controlled memory and routing.
|
|
6
|
+
|
|
7
|
+
## What is PACS?
|
|
8
|
+
|
|
9
|
+
PACS (Personal AI Control System) gives AI assistants persistent, encrypted memory and user-controlled routing — without relying on plaintext markdown files.
|
|
10
|
+
|
|
11
|
+
### Key Features
|
|
12
|
+
|
|
13
|
+
- **AES-256-GCM Encryption** — All sensitive data is encrypted at rest
|
|
14
|
+
- **3-Layer Architecture** — Commands (plaintext) → AI Logic (encrypted) → System Kernel (hardcoded)
|
|
15
|
+
- **Learn Mode** — AI asks before storing facts; user controls auto vs. manual learning
|
|
16
|
+
- **Trigger Commands** — Plaintext, human-editable commands in any language
|
|
17
|
+
- **Standalone or Integrated** — Works with OpenClaw or as a standalone npm package
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install pacs-core
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Or for development:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
git clone https://github.com/yourusername/pacs-core.git
|
|
29
|
+
cd pacs-core
|
|
30
|
+
npm install
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
34
|
+
|
|
35
|
+
### 1. Set your encryption key
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
export PACS_ENCRYPTION_KEY="$(openssl rand -hex 32)"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The key lives in the environment only — never in files.
|
|
42
|
+
|
|
43
|
+
### 2. Bootstrap your PACS directory
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npm run bootstrap
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
This creates `~/.openclaw/pacs/` with sample encrypted files.
|
|
50
|
+
|
|
51
|
+
### 3. Use in your code
|
|
52
|
+
|
|
53
|
+
```javascript
|
|
54
|
+
const pacs = require('pacs-core');
|
|
55
|
+
|
|
56
|
+
// Parse a trigger command
|
|
57
|
+
const parsed = pacs.triggers.parse('MERKE: Ich spreche Deutsch');
|
|
58
|
+
if (parsed) {
|
|
59
|
+
console.log(`Trigger: ${parsed.trigger.id}`);
|
|
60
|
+
console.log(`Payload: ${parsed.payload}`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Add a fact to memory
|
|
64
|
+
const memory = pacs.memory.addFact('I prefer German when writing');
|
|
65
|
+
|
|
66
|
+
// Search memory
|
|
67
|
+
const results = pacs.memory.search('German');
|
|
68
|
+
|
|
69
|
+
// Show help
|
|
70
|
+
console.log(pacs.triggers.getHelp());
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Architecture
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
┌─────────────────────────────────────────────┐
|
|
77
|
+
│ Layer 1: COMMANDS (plaintext) │
|
|
78
|
+
│ Human-editable, multi-language triggers │
|
|
79
|
+
│ MERKE:, ROUTING:, REGEL:, SUCHE:, etc. │
|
|
80
|
+
├─────────────────────────────────────────────┤
|
|
81
|
+
│ Layer 2: PERSONAL AI LOGIC (encrypted) │
|
|
82
|
+
│ AES-256-GCM — AI can reject conflicts │
|
|
83
|
+
│ Memory, routing hints, core rules │
|
|
84
|
+
├─────────────────────────────────────────────┤
|
|
85
|
+
│ Layer 3: SYSTEM KERNEL (hardcoded) │
|
|
86
|
+
│ AI's own immutable rules — never changed │
|
|
87
|
+
└─────────────────────────────────────────────┘
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Trigger Commands
|
|
91
|
+
|
|
92
|
+
| Command | Aliases | Description |
|
|
93
|
+
|---------|---------|-------------|
|
|
94
|
+
| `MERKE:` | `LEARN:` | Store a fact in encrypted memory |
|
|
95
|
+
| `PRIVAT:` | `PRIVATE:` | Mark info as private (excluded from exports) |
|
|
96
|
+
| `ROUTING:` | `ROUTE:` | Add routing hint for task delegation |
|
|
97
|
+
| `REGEL:` | `RULE:` | Add a personal AI behavior rule |
|
|
98
|
+
| `BEFEHLE:` | `COMMANDS:` | Show available commands |
|
|
99
|
+
| `WAS WEISST DU?` | `WHAT DO YOU KNOW?` | Query what AI remembers |
|
|
100
|
+
| `SUCHE:` | `SEARCH:` | Search encrypted memory |
|
|
101
|
+
| `VERGISS:` | `FORGET:` | Delete something from memory |
|
|
102
|
+
| `EXPORTIEREN:` | `EXPORT:` | Export memory (excludes private) |
|
|
103
|
+
|
|
104
|
+
## Learn Modes
|
|
105
|
+
|
|
106
|
+
Control how PACS handles learning:
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
AI: lern automatisch → Auto-learn mode (AI offers to remember)
|
|
110
|
+
AI: nur auf Befehl → Manual mode only (MERKE: required)
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Security
|
|
114
|
+
|
|
115
|
+
- **Encryption:** AES-256-GCM (Node.js built-in crypto)
|
|
116
|
+
- **Key storage:** `PACS_ENCRYPTION_KEY` env variable only
|
|
117
|
+
- **Private facts:** Excluded from all exports
|
|
118
|
+
- **AI override:** AI can reject facts that contradict its logic
|
|
119
|
+
- **No external dependencies** beyond Node.js standard library
|
|
120
|
+
|
|
121
|
+
## API Reference
|
|
122
|
+
|
|
123
|
+
### `pacs.crypto`
|
|
124
|
+
|
|
125
|
+
```javascript
|
|
126
|
+
pacs.crypto.encrypt(plaintext) // → "iv:authTag:ciphertext"
|
|
127
|
+
pacs.crypto.decrypt(encryptedData) // → plaintext
|
|
128
|
+
pacs.crypto.generateKey() // → 64-char hex string
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### `pacs.memory`
|
|
132
|
+
|
|
133
|
+
```javascript
|
|
134
|
+
pacs.memory.read() // → { facts: [], private: [], learnedAt: {} }
|
|
135
|
+
pacs.memory.addFact(fact, isPrivate) // → updated memory
|
|
136
|
+
pacs.memory.removeFact(fact) // → updated memory
|
|
137
|
+
pacs.memory.search(query) // → string[]
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### `pacs.triggers`
|
|
141
|
+
|
|
142
|
+
```javascript
|
|
143
|
+
pacs.triggers.parse(message) // → { trigger, payload } or null
|
|
144
|
+
pacs.triggers.find('MERKE') // → trigger object or null
|
|
145
|
+
pacs.triggers.contains(message) // → boolean
|
|
146
|
+
pacs.triggers.detectLearnMode(msg) // → 'auto' | 'onDemand' | null
|
|
147
|
+
pacs.triggers.getHelp() // → formatted help string
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### `pacs.routing`
|
|
151
|
+
|
|
152
|
+
```javascript
|
|
153
|
+
pacs.routing.read() // → { hints: [], agents: [] }
|
|
154
|
+
pacs.routing.addHint(hint) // → updated routing
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### `pacs.rules`
|
|
158
|
+
|
|
159
|
+
```javascript
|
|
160
|
+
pacs.rules.read() // → { rules: [] }
|
|
161
|
+
pacs.rules.addRule(rule) // → updated rules
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## File Structure
|
|
165
|
+
|
|
166
|
+
```
|
|
167
|
+
pacs-core/
|
|
168
|
+
├── package.json
|
|
169
|
+
├── README.md
|
|
170
|
+
├── LICENSE
|
|
171
|
+
└── src/
|
|
172
|
+
├── index.js # Main entry point
|
|
173
|
+
├── crypto.js # AES-256-GCM encryption
|
|
174
|
+
├── memory-store.js # Encrypted storage layer
|
|
175
|
+
├── trigger-parser.js # Command parsing
|
|
176
|
+
├── triggers.json # Trigger definitions (plaintext)
|
|
177
|
+
├── bootstrap.js # Setup script
|
|
178
|
+
└── test.js # Test suite
|
|
179
|
+
|
|
180
|
+
~/.openclaw/pacs/ # Created by bootstrap
|
|
181
|
+
├── memory.enc # Encrypted user facts
|
|
182
|
+
├── routing.enc # Encrypted routing hints
|
|
183
|
+
├── core-rules.enc # Encrypted AI rules
|
|
184
|
+
└── triggers/
|
|
185
|
+
└── triggers.json # Copy of trigger definitions
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Multi-Agent System
|
|
189
|
+
|
|
190
|
+
PACS Phase 2 adds an inter-agent communication bus and agent registry, enabling multi-agent workflows.
|
|
191
|
+
|
|
192
|
+
### Agent Registry
|
|
193
|
+
|
|
194
|
+
Manages agent definitions with encrypted persistence.
|
|
195
|
+
|
|
196
|
+
```javascript
|
|
197
|
+
const { AgentRegistry } = require('pacs-core');
|
|
198
|
+
|
|
199
|
+
// Register an agent
|
|
200
|
+
const agent = AgentRegistry.registerAgent('finance-agent', {
|
|
201
|
+
domain: 'finance',
|
|
202
|
+
capabilities: ['analysis', 'planning'],
|
|
203
|
+
description: 'Handles all financial analysis tasks'
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
// Get agent by name
|
|
207
|
+
const found = AgentRegistry.getAgent('finance-agent');
|
|
208
|
+
|
|
209
|
+
// List all agents
|
|
210
|
+
const all = AgentRegistry.listAgents();
|
|
211
|
+
const active = AgentRegistry.listAgents({ status: 'active' });
|
|
212
|
+
|
|
213
|
+
// Remove an agent
|
|
214
|
+
AgentRegistry.removeAgent('finance-agent');
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Inter-Agent Bus
|
|
218
|
+
|
|
219
|
+
Message passing between agents with encrypted message history.
|
|
220
|
+
|
|
221
|
+
```javascript
|
|
222
|
+
const { InterAgentBus } = require('pacs-core');
|
|
223
|
+
|
|
224
|
+
// Send a message to a specific agent
|
|
225
|
+
InterAgentBus.emit('orchestrator', 'finance-agent', 'Analyze Q1 expenses');
|
|
226
|
+
|
|
227
|
+
// Broadcast to all agents
|
|
228
|
+
InterAgentBus.broadcast('orchestrator', 'System update: all agents report status');
|
|
229
|
+
|
|
230
|
+
// Request-response pattern (async)
|
|
231
|
+
const response = await InterAgentBus.request('orchestrator', 'finance-agent', {
|
|
232
|
+
task: 'calculate_budget',
|
|
233
|
+
params: { quarter: 'Q2' }
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
// Respond to a request
|
|
237
|
+
InterAgentBus.respond(requestId, 'finance-agent', { result: 45000 });
|
|
238
|
+
|
|
239
|
+
// Get messages for an agent
|
|
240
|
+
const msgs = InterAgentBus.getMessages('finance-agent', { limit: 50 });
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Agent Creator
|
|
244
|
+
|
|
245
|
+
Creates agents from natural language text or markdown definitions.
|
|
246
|
+
|
|
247
|
+
```javascript
|
|
248
|
+
const { AgentCreator } = require('pacs-core');
|
|
249
|
+
|
|
250
|
+
// From natural language (German or English)
|
|
251
|
+
const agent = AgentCreator.createFromText(
|
|
252
|
+
'Erstelle einen Agenten für Finanzen, der Analysen und Planung kann'
|
|
253
|
+
);
|
|
254
|
+
|
|
255
|
+
// From markdown definition
|
|
256
|
+
const agent2 = AgentCreator.createFromMD(`
|
|
257
|
+
---
|
|
258
|
+
name: marketing-agent
|
|
259
|
+
domain: marketing
|
|
260
|
+
status: active
|
|
261
|
+
---
|
|
262
|
+
This agent handles marketing campaigns, social media, and CRM.
|
|
263
|
+
`);
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Agent Object Schema
|
|
267
|
+
|
|
268
|
+
```javascript
|
|
269
|
+
{
|
|
270
|
+
id: 'm1abc2def3', // Unique ID
|
|
271
|
+
name: 'finance-agent', // Unique name
|
|
272
|
+
domain: 'finance', // Domain category
|
|
273
|
+
capabilities: [], // List of capabilities
|
|
274
|
+
status: 'active', // 'active' | 'sleep'
|
|
275
|
+
lastActive: 'ISO8601', // Last activity timestamp
|
|
276
|
+
createdAt: 'ISO8601', // Creation timestamp
|
|
277
|
+
description: '', // Human-readable description
|
|
278
|
+
metadata: {} // Custom metadata
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Message Schema
|
|
283
|
+
|
|
284
|
+
```javascript
|
|
285
|
+
{
|
|
286
|
+
id: 'msg_id',
|
|
287
|
+
from: 'orchestrator',
|
|
288
|
+
to: 'finance-agent', // or '*' for broadcast
|
|
289
|
+
type: 'message', // 'message' | 'request' | 'response'
|
|
290
|
+
payload: '...', // string or JSON string
|
|
291
|
+
timestamp: 'ISO8601',
|
|
292
|
+
inReplyTo: 'msg_id' // only for response type
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Storage
|
|
297
|
+
|
|
298
|
+
Agent definitions are stored in `~/.openclaw/pacs/agents.enc` and messages in `messages.enc`, both AES-256-GCM encrypted.
|
|
299
|
+
|
|
300
|
+
## Routing Engine
|
|
301
|
+
|
|
302
|
+
Routes incoming user tasks to the correct agent(s) using capability matching and scoring.
|
|
303
|
+
|
|
304
|
+
```javascript
|
|
305
|
+
const { RoutingEngine } = require('pacs-core');
|
|
306
|
+
|
|
307
|
+
// Route to best matching agents
|
|
308
|
+
const result = RoutingEngine.route('Organisiere meine Finanzen');
|
|
309
|
+
// → { task: 'Organisiere meine Finanzen', plan: [{ agent: 'finance', mode: 'parallel', score: 0.85 }], confidence: 0.85 }
|
|
310
|
+
|
|
311
|
+
// Get agents for parallel execution
|
|
312
|
+
const parallel = RoutingEngine.routeParallel('Analyze Q1 AND plan marketing campaign');
|
|
313
|
+
|
|
314
|
+
// Get agents for sequential execution
|
|
315
|
+
const sequential = RoutingEngine.routeSequential('Plan my week and send emails');
|
|
316
|
+
|
|
317
|
+
// Find who handles a topic
|
|
318
|
+
const handlers = RoutingEngine.whoHandles('Steuererklärung');
|
|
319
|
+
// → ['finance']
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
**Special queries:**
|
|
323
|
+
- `"alle Agenten"` / `"alle agenten"` — returns all registered agents
|
|
324
|
+
- `"wer ist für X zuständig?"` — returns the best agent for topic X
|
|
325
|
+
|
|
326
|
+
**Scoring:** 0.0–1.0 based on domain keywords, capabilities, description match, and stored routing hints.
|
|
327
|
+
|
|
328
|
+
## Learning Loop
|
|
329
|
+
|
|
330
|
+
Handles SAFE learning mode with "Soll ich mir das merken?" confirmation flow.
|
|
331
|
+
|
|
332
|
+
```javascript
|
|
333
|
+
const { LearningLoop } = require('pacs-core');
|
|
334
|
+
|
|
335
|
+
// Check if a message should be remembered
|
|
336
|
+
const result = LearningLoop.shouldRemember('Ich spreche lieber Deutsch');
|
|
337
|
+
// → { should: true, reason: 'safe-detect', fact: 'Ich spreche lieber Deutsch' }
|
|
338
|
+
|
|
339
|
+
// Get the confirmation prompt in user's language
|
|
340
|
+
const prompt = LearningLoop.promptConfirmation('Ich spreche lieber Deutsch');
|
|
341
|
+
// → 'Soll ich mir das merken? "Ich spreche lieber Deutsch"'
|
|
342
|
+
|
|
343
|
+
// After user confirms, store the fact
|
|
344
|
+
LearningLoop.storeConfirmed('user123', 'Ich sprebe lieber Deutsch');
|
|
345
|
+
|
|
346
|
+
// If user rejects, mark as ignored
|
|
347
|
+
LearningLoop.rejectLearning('user123', 'some-fact');
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
**Supported learn modes:**
|
|
351
|
+
- `safe` — AI asks before storing ("Soll ich mir das merken?") **default**
|
|
352
|
+
- `explicit` — Only store when explicitly commanded via `MERKE:`/`LEARN:`
|
|
353
|
+
- `auto` — Auto-store and confirm after the fact
|
|
354
|
+
|
|
355
|
+
### Learn Mode Manager
|
|
356
|
+
|
|
357
|
+
```javascript
|
|
358
|
+
const { LearnMode } = require('pacs-core');
|
|
359
|
+
|
|
360
|
+
LearnMode.getMode(); // → 'safe'
|
|
361
|
+
LearnMode.setMode('auto'); // → 'auto'
|
|
362
|
+
LearnMode.getModeDescription(); // → human-readable description
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
Stored in `~/.openclaw/pacs/settings.enc`.
|
|
366
|
+
|
|
367
|
+
## Phase 2 (Planned)
|
|
368
|
+
|
|
369
|
+
- [x] Agent routing engine with match scoring
|
|
370
|
+
- [x] Learning loop with confirmation prompts
|
|
371
|
+
- [x] OpenClaw integration bridge
|
|
372
|
+
- [x] CLI tool for management
|
|
373
|
+
- Export/import functionality
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
## OpenClaw Bridge
|
|
378
|
+
|
|
379
|
+
The OpenClaw Bridge integrates PACS into the OpenClaw agent framework.
|
|
380
|
+
|
|
381
|
+
```javascript
|
|
382
|
+
const { OpenClawBridge } = require('pacs-core');
|
|
383
|
+
|
|
384
|
+
// Initialize with OpenClaw config
|
|
385
|
+
const result = OpenClawBridge.init({
|
|
386
|
+
pacs: {
|
|
387
|
+
enabled: true,
|
|
388
|
+
mode: 'integrated' // 'integrated' | 'standalone'
|
|
389
|
+
}
|
|
390
|
+
}, openClawAgentApi); // optional OpenClaw agent API for fallback
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### Modes
|
|
394
|
+
|
|
395
|
+
| Mode | Description |
|
|
396
|
+
|------|-------------|
|
|
397
|
+
| `integrated` | PACS and OpenClaw agents coexist. PACS processes messages first; falls back to OpenClaw agents if no PACS handler matches. |
|
|
398
|
+
| `standalone` | PACS runs independently. OpenClaw is used only as the UI layer. |
|
|
399
|
+
|
|
400
|
+
### API
|
|
401
|
+
|
|
402
|
+
```javascript
|
|
403
|
+
// Process a user message through PACS
|
|
404
|
+
const result = await OpenClawBridge.query(userMessage);
|
|
405
|
+
// → { response, routedTo, fallback }
|
|
406
|
+
|
|
407
|
+
// Check if a message is a PACS command
|
|
408
|
+
const isPACS = OpenClawBridge.isPACSQuery('MERKE: Ich spreche Deutsch');
|
|
409
|
+
// → true
|
|
410
|
+
|
|
411
|
+
// Check bridge status
|
|
412
|
+
const status = OpenClawBridge.status();
|
|
413
|
+
// → { initialized, mode, enabled, openClawConnected }
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
### How Routing Works
|
|
417
|
+
|
|
418
|
+
1. `isPACSQuery()` checks for PACS keywords (MERKE, SUCHE, LERNE, AGENT, ROUTING, REGELN, MEMORY) or trigger patterns
|
|
419
|
+
2. If matched: PACS handles it → routes to memory, agent registry, or learn mode
|
|
420
|
+
3. If not matched in `integrated` mode → delegates to OpenClaw agents via `fallbackToOpenClawAgents()`
|
|
421
|
+
4. If not matched in `standalone` mode → returns "no handler found" response
|
|
422
|
+
|
|
423
|
+
---
|
|
424
|
+
|
|
425
|
+
## CLI Reference
|
|
426
|
+
|
|
427
|
+
PACS includes a full command-line interface for managing agents, memory, and settings.
|
|
428
|
+
|
|
429
|
+
### Installation
|
|
430
|
+
|
|
431
|
+
```bash
|
|
432
|
+
npm install # install dependencies
|
|
433
|
+
npm link # make `pacs` command available globally
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
Or run directly:
|
|
437
|
+
```bash
|
|
438
|
+
node src/cli.js <command>
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
### Commands
|
|
442
|
+
|
|
443
|
+
#### `pacs --help`
|
|
444
|
+
Show all available commands.
|
|
445
|
+
|
|
446
|
+
#### `pacs init`
|
|
447
|
+
Initialize the PACS storage directory (`~/.openclaw/pacs/`).
|
|
448
|
+
|
|
449
|
+
```bash
|
|
450
|
+
pacs init
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
#### `pacs status`
|
|
454
|
+
Show PACS system status.
|
|
455
|
+
|
|
456
|
+
```bash
|
|
457
|
+
pacs status
|
|
458
|
+
# === PACS Status ===
|
|
459
|
+
# Bridge initialisiert : ja/nein
|
|
460
|
+
# Bridge Mode : integrated/standalone
|
|
461
|
+
# Agenten registriert : 3
|
|
462
|
+
# Memory Facts : 12
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
#### `pacs agents list`
|
|
466
|
+
List all registered agents.
|
|
467
|
+
|
|
468
|
+
```bash
|
|
469
|
+
pacs agents list
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
#### `pacs agents add <name>`
|
|
473
|
+
Register a new agent.
|
|
474
|
+
|
|
475
|
+
```bash
|
|
476
|
+
pacs agents add finbot --text "Finance and invoicing agent"
|
|
477
|
+
pacs agents add devbot --md ./agent-definition.md
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
#### `pacs agents remove <name>`
|
|
481
|
+
Remove an agent by name.
|
|
482
|
+
|
|
483
|
+
```bash
|
|
484
|
+
pacs agents remove finbot
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
#### `pacs agents get <name>`
|
|
488
|
+
Show full details for a specific agent.
|
|
489
|
+
|
|
490
|
+
```bash
|
|
491
|
+
pacs agents get finbot
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
#### `pacs memory list`
|
|
495
|
+
List all stored memory facts.
|
|
496
|
+
|
|
497
|
+
```bash
|
|
498
|
+
pacs memory list
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
#### `pacs memory search <query>`
|
|
502
|
+
Search memory facts.
|
|
503
|
+
|
|
504
|
+
```bash
|
|
505
|
+
pacs memory search "preferences"
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
#### `pacs memory add "<fact>"`
|
|
509
|
+
Add a new memory fact.
|
|
510
|
+
|
|
511
|
+
```bash
|
|
512
|
+
pacs memory add "Lech prefers German in the morning"
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
#### `pacs memory forget "<fact>"`
|
|
516
|
+
Remove a memory fact by content match.
|
|
517
|
+
|
|
518
|
+
```bash
|
|
519
|
+
pacs memory forget "Lech prefers German in the morning"
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
#### `pacs learn-mode get`
|
|
523
|
+
Show the current learn mode.
|
|
524
|
+
|
|
525
|
+
```bash
|
|
526
|
+
pacs learn-mode get
|
|
527
|
+
# Learn-Mode: safe
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
#### `pacs learn-mode set <mode>`
|
|
531
|
+
Set the learn mode.
|
|
532
|
+
|
|
533
|
+
```bash
|
|
534
|
+
pacs learn-mode set explicit
|
|
535
|
+
# Valid modes: safe | explicit | auto
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
#### `pacs messages <agent>`
|
|
539
|
+
Show message history for an agent.
|
|
540
|
+
|
|
541
|
+
```bash
|
|
542
|
+
pacs messages finbot
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
### Environment Variables
|
|
546
|
+
|
|
547
|
+
| Variable | Required | Description |
|
|
548
|
+
|----------|----------|-------------|
|
|
549
|
+
| `PACS_ENCRYPTION_KEY` | Yes | 256-bit encryption key (required for all encrypted operations) |
|
|
550
|
+
|
|
551
|
+
Generate a key:
|
|
552
|
+
```bash
|
|
553
|
+
openssl rand -hex 32
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
Set permanently (Linux/macOS):
|
|
557
|
+
```bash
|
|
558
|
+
echo 'export PACS_ENCRYPTION_KEY=$(openssl rand -hex 32)' >> ~/.bashrc
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
Set permanently (Windows PowerShell):
|
|
562
|
+
```powershell
|
|
563
|
+
[System.Environment]::SetEnvironmentVariable("PACS_ENCRYPTION_KEY", $(openssl rand -hex 32), "User")
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
### File Structure
|
|
567
|
+
|
|
568
|
+
```
|
|
569
|
+
pacs-core/
|
|
570
|
+
├── bin/
|
|
571
|
+
│ └── pacs-cli.js # CLI executable entry point
|
|
572
|
+
├── src/
|
|
573
|
+
│ ├── index.js # Main entry point + all exports
|
|
574
|
+
│ ├── cli.js # CLI implementation
|
|
575
|
+
│ ├── openclaw-bridge.cjs # OpenClaw integration
|
|
576
|
+
│ ├── agent-registry.js # Agent management
|
|
577
|
+
│ ├── memory-store.js # Encrypted storage
|
|
578
|
+
│ ├── crypto.js # AES-256-GCM
|
|
579
|
+
│ ├── trigger-parser.js # Command parsing
|
|
580
|
+
│ ├── routing-engine.js # Task routing
|
|
581
|
+
│ ├── learn-mode.js # Learn mode settings
|
|
582
|
+
│ ├── learning-loop.js # Learning confirmation flow
|
|
583
|
+
│ ├── inter-agent-bus.js # Agent messaging
|
|
584
|
+
│ └── agent-creator.js # Agent creation
|
|
585
|
+
└── package.json # "bin": { "pacs": "./bin/pacs-cli.js" }
|
|
586
|
+
|
|
587
|
+
~/.openclaw/pacs/ # Created at runtime
|
|
588
|
+
├── memory.enc # Encrypted user facts
|
|
589
|
+
├── routing.enc # Encrypted routing hints
|
|
590
|
+
├── core-rules.enc # Encrypted AI rules
|
|
591
|
+
├── agents.enc # Encrypted agent registry
|
|
592
|
+
├── settings.enc # Encrypted settings (learn mode)
|
|
593
|
+
└── messages.enc # Encrypted inter-agent messages
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
## License
|
|
597
|
+
|
|
598
|
+
MIT — see [LICENSE](LICENSE)
|
|
599
|
+
|
|
600
|
+
## Contributing
|
|
601
|
+
|
|
602
|
+
Contributions welcome. Open an issue first for major changes.
|
package/bin/pacs-cli.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "pacs-core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "PACS — Personal AI Control System. Encrypted memory, routing, and learn mode for AI assistants.",
|
|
5
|
+
|
|
6
|
+
"main": "src/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"pacs": "./bin/pacs-cli.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"bootstrap": "node src/bootstrap.js",
|
|
12
|
+
"test": "node src/test.js"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"ai",
|
|
16
|
+
"memory",
|
|
17
|
+
"encrypted",
|
|
18
|
+
"personal-ai",
|
|
19
|
+
"pacs",
|
|
20
|
+
"agent",
|
|
21
|
+
"openclaw"
|
|
22
|
+
],
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "https://github.com/yourusername/pacs-core"
|
|
27
|
+
},
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=18.0.0"
|
|
30
|
+
}
|
|
31
|
+
}
|